{"thread":{"id":"17526","subject":"[JGIT] help needed to create a siimple commit","startedAt":"2009-02-03T11:07:33Z","lastAt":"2009-02-04T17:07:29Z","messageCount":4,"participants":["Yann Simon","Shawn O. Pearce"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"102951","messageId":"551f769b0902030307s2a9204cch7967df17c1f2c8a6@mail.gmail.com","threadId":"17526","inReplyTo":null,"subject":"[JGIT] help needed to create a siimple commit","fromName":"Yann Simon","fromEmail":"yann.simon.fr@gmail.com","sentAt":"2009-02-03T11:07:33Z","receivedAt":"2009-02-03T11:07:33Z","isPatch":false,"sender":{"key":"yann.simon.fr@gmail.com","avatar":"https://gravatar.com/avatar/2d926895d27ac988c5c8e591887e5a6a4c7036390403c74fce92519119b887a0?d=mp&s=160"},"body":"Hi,\n\nI wrote the following unit test to learn how to make a commit with JGIT:\n\npackage org.spearce.jgit.lib;\n\nimport java.io.File;\nimport java.io.IOException;\n\npublic class CommitTest extends RepositoryTestCase {\n\n\tpublic void testASimpleCommit() throws IOException {\n\t\t\n\t\tGitIndex index = new GitIndex(db);\n\t\tindex.filemode = Boolean.TRUE;\n\t\t\n\t\tFile file;\n\t\tfile = writeTrashFile(\"file1\", \"file1\");\n\t\t\n\t\tindex.add(trash, file);\n\t\tindex.write();\n\t\tObjectId objectId = index.writeTree();\n\t\tTree tree = db.mapTree(objectId);\n\t\ttree.accept(new WriteTree(trash, db), TreeEntry.MODIFIED_ONLY);\n\t\t\n\t\tfinal Commit c1 = new Commit(db);\n\t\tc1.setAuthor(new PersonIdent(jauthor, 1154236443000L, -4 * 60));\n\t\tc1.setCommitter(new PersonIdent(jcommitter, 1154236443000L, -4 * 60));\n\t\tc1.setMessage(\"A Commit\\n\");\n\t\tc1.setTree(tree);\n\t\tassertEquals(tree.getTreeId(), c1.getTreeId());\n\t\tc1.commit();\n\t\t\n\t}\n}\n\nBut the result is not brillant.\nIn the trash workspace, git log does not show me my commit.\ngit diff --cached shows me that my file is in the index but not committed...\n\nThank for the help.\n\nYann\n"},{"id":"102976","messageId":"20090203155107.GU26880@spearce.org","threadId":"17526","inReplyTo":"551f769b0902030307s2a9204cch7967df17c1f2c8a6@mail.gmail.com","subject":"Re: [JGIT] help needed to create a siimple commit","fromName":"Shawn O. Pearce","fromEmail":"spearce@spearce.org","sentAt":"2009-02-03T15:51:07Z","receivedAt":"2009-02-03T15:51:07Z","isPatch":false,"sender":{"key":"spearce@spearce.org","avatar":"https://avatars.githubusercontent.com/u/34844?v=4"},"body":"Yann Simon <yann.simon.fr@gmail.com> wrote:\n> I wrote the following unit test to learn how to make a commit\n> with JGIT:\n> \n> \tpublic void testASimpleCommit() throws IOException {\n> \t\t\n> \t\tGitIndex index = new GitIndex(db);\n> \t\tindex.filemode = Boolean.TRUE;\n> \t\t\n> \t\tFile file;\n> \t\tfile = writeTrashFile(\"file1\", \"file1\");\n> \t\t\n> \t\tindex.add(trash, file);\n> \t\tindex.write();\n> \t\tObjectId objectId = index.writeTree();\n> \t\tTree tree = db.mapTree(objectId);\n> \t\ttree.accept(new WriteTree(trash, db), TreeEntry.MODIFIED_ONLY);\n> \t\t\n> \t\tfinal Commit c1 = new Commit(db);\n> \t\tc1.setAuthor(new PersonIdent(jauthor, 1154236443000L, -4 * 60));\n> \t\tc1.setCommitter(new PersonIdent(jcommitter, 1154236443000L, -4 * 60));\n> \t\tc1.setMessage(\"A Commit\\n\");\n> \t\tc1.setTree(tree);\n> \t\tassertEquals(tree.getTreeId(), c1.getTreeId());\n> \t\tc1.commit();\n\nYou are missing the final step of updating the HEAD ref with the\ncommit.  Calling commit() on the Commit object only writes it to\nthe object database, this is similar to git-commit-tree.\n\nTry adding on the end:\n\n\tRefUpdate ru = db.updateRef(Constants.HEAD);\n\tru.setRefLogMessage(\"commit\");\n\tru.setNewObjectId(c1.getCommitId());\n\tassertSame(RefUpdate.Result.NEW, ru.update());\n\nIf your commit had parents, you might want to do instead:\n\n\tru.setExpectedOldObjectId(oldHEAD);\n\tassertSame(RefUpdate.Result.FAST_FORWARD, ru.update());\n\nwhere oldHEAD is the value of HEAD you read and used as the first\nparent of the commit.  This ensures that the update method fails\nif someone else has updated HEAD since you last read it.\n\nThe update method returns a number of different states, usually we\ncheck its result with a switch statement as a number of states are\nsometimes permissible in a context.  Sometimes though, you know it\nhas to be exactly one state, and everything else is a failure.\n\n-- \nShawn.\n"},{"id":"103160","messageId":"551f769b0902040810o6b45008fgcc1ef70108b3d90@mail.gmail.com","threadId":"17526","inReplyTo":"20090203155107.GU26880@spearce.org","subject":"Re: [JGIT] help needed to create a siimple commit","fromName":"Yann Simon","fromEmail":"yann.simon.fr@gmail.com","sentAt":"2009-02-04T16:10:48Z","receivedAt":"2009-02-04T16:10:48Z","isPatch":false,"sender":{"key":"yann.simon.fr@gmail.com","avatar":"https://gravatar.com/avatar/2d926895d27ac988c5c8e591887e5a6a4c7036390403c74fce92519119b887a0?d=mp&s=160"},"body":"2009/2/3 Shawn O. Pearce <spearce@spearce.org>:\n> You are missing the final step of updating the HEAD ref with the\n> commit.  Calling commit() on the Commit object only writes it to\n> the object database, this is similar to git-commit-tree.\n>\n> Try adding on the end:\n>\n>        RefUpdate ru = db.updateRef(Constants.HEAD);\n>        ru.setRefLogMessage(\"commit\");\n>        ru.setNewObjectId(c1.getCommitId());\n>        assertSame(RefUpdate.Result.NEW, ru.update());\n>\n> If your commit had parents, you might want to do instead:\n>\n>        ru.setExpectedOldObjectId(oldHEAD);\n>        assertSame(RefUpdate.Result.FAST_FORWARD, ru.update());\n>\n> where oldHEAD is the value of HEAD you read and used as the first\n> parent of the commit.  This ensures that the update method fails\n> if someone else has updated HEAD since you last read it.\n>\n> The update method returns a number of different states, usually we\n> check its result with a switch statement as a number of states are\n> sometimes permissible in a context.  Sometimes though, you know it\n> has to be exactly one state, and everything else is a failure.\n>\nI updated my simple test like this:\n\npackage org.spearce.jgit.lib;\n\nimport java.io.File;\nimport java.io.IOException;\n\npublic class CommitTest extends RepositoryTestCase {\n\n\tpublic void testASimpleCommit() throws IOException {\n\t\t\n\t\trecursiveDelete(trash_git, false, null, true);\n\t\tdb = new Repository(trash_git);\n\t\tdb.create();\n\n\t\tGitIndex index = new GitIndex(db);\n\t\tindex.filemode = Boolean.TRUE;\n\t\t\n\t\tcommitIndex(index, \"commit 1\");\n\n\t\tFile file1 = writeTrashFile(\"file1\", \"file1\");\n\t\tindex.add(trash, file1);\n\t\t\n\t\tcommitIndex(index, \"commit 2\");\n\n\t}\n\t\n\tprivate void commitIndex(GitIndex index, String commitMessage) throws\nIOException {\n\t\tindex.write();\n\t\tObjectId objectId = index.writeTree();\n\t\tTree tree = db.mapTree(objectId);\n\t\tfinal Commit commit = new Commit(db);\n\t\tcommit.setAuthor(new PersonIdent(jauthor, 1154236443000L, -4 * 60));\n\t\tcommit.setCommitter(new PersonIdent(jcommitter, 1154236443000L, -4 * 60));\n\t\tcommit.setMessage(commitMessage);\n\t\tcommit.setTree(tree);\n\t\tassertEquals(tree.getTreeId(), commit.getTreeId());\n\t\tcommit.commit();\n\t\t\n\t\tObjectWriter writer = new ObjectWriter(db);\n\t\tcommit.setCommitId(writer.writeCommit(commit));\n\n\t\tRef oldHEAD = db.getAllRefs().get(Constants.HEAD);\n\t\tfinal RefUpdate ru = db.updateRef(Constants.HEAD);\n\t\tru.setNewObjectId(commit.getCommitId());\n\t\tru.setRefLogMessage(commitMessage, false);\n\n\t\tif (oldHEAD != null) {\n\t\t\t// commit has parents\n\t\t\tru.setExpectedOldObjectId(oldHEAD.getObjectId());\n\t\t\tassertSame(RefUpdate.Result.FAST_FORWARD, ru.update());\n\t\t} else {\n\t\t\t// commit has no parents\n\t\t\tassertSame(RefUpdate.Result.NEW, ru.update());\n\t\t}\n\t\t\n\n\t}\n}\n\nThe first commit \"with an empty workspace\" is ok. I can see the commit\nin the log.\nThe second commit fails, with ru.update() = REJECTED.\n\nI tried different combination, without success.\n\nIf someone could tell me, what I am doing wrong...\n\nYann\n"},{"id":"103166","messageId":"20090204170729.GB26880@spearce.org","threadId":"17526","inReplyTo":"551f769b0902040810o6b45008fgcc1ef70108b3d90@mail.gmail.com","subject":"Re: [JGIT] help needed to create a siimple commit","fromName":"Shawn O. Pearce","fromEmail":"spearce@spearce.org","sentAt":"2009-02-04T17:07:29Z","receivedAt":"2009-02-04T17:07:29Z","isPatch":false,"sender":{"key":"spearce@spearce.org","avatar":"https://avatars.githubusercontent.com/u/34844?v=4"},"body":"Yann Simon <yann.simon.fr@gmail.com> wrote:\n> \t\tfinal Commit commit = new Commit(db);\n> \t\tcommit.setAuthor(new PersonIdent(jauthor, 1154236443000L, -4 * 60));\n> \t\tcommit.setCommitter(new PersonIdent(jcommitter, 1154236443000L, -4 * 60));\n> \t\tcommit.setMessage(commitMessage);\n> \t\tcommit.setTree(tree);\n\nFWIW, its faster to use setTreeId().  Then you don't need to use\nmapTree to read the tree object into memory.  This is an older area\nof the Commit class API, before we understood how important it was\nto avoid processing unnecessary data.  :-)\n\n> \t\tassertEquals(tree.getTreeId(), commit.getTreeId());\n> \t\tcommit.commit();\n> \t\t\n> \t\tObjectWriter writer = new ObjectWriter(db);\n> \t\tcommit.setCommitId(writer.writeCommit(commit));\n\nUh, commit.commit() is doing the same work as the above two lines,\nso these above two lines are a no-op as the object already exists\nin the object database.\n \n> \t\tRef oldHEAD = db.getAllRefs().get(Constants.HEAD);\n> \t\tfinal RefUpdate ru = db.updateRef(Constants.HEAD);\n> \t\tru.setNewObjectId(commit.getCommitId());\n> \t\tru.setRefLogMessage(commitMessage, false);\n> \n> \t\tif (oldHEAD != null) {\n> \t\t\t// commit has parents\n> \t\t\tru.setExpectedOldObjectId(oldHEAD.getObjectId());\n> \t\t\tassertSame(RefUpdate.Result.FAST_FORWARD, ru.update());\n\nThis fails because the commit has no parents, but you asked\nfor a fast-forward update.  Since HEAD already has a commit,\nand the new commit isn't a super-set of the existing HEAD, and\nRefUpdate.isForceUpdate() is false, the update is being rejected.\n\nIf you really mean to replace the commit, e.g. commit --amend,\nyou need to ru.setForceUpdate(true).\n\nIf you really mean to fast-forward the commit, e.g. just make\na new commit on top of the existing commits, you need to do\nthe read to get oldHEAD *before* you call commit.commit()\nabove, and use:\n\n  commit.setParents(new Object[]{ oldHEAD.getObjectId() })\n\nto set the current commit as the first parent of the new commit,\nso the new commit is really a superset of the old one.\n\nAgain, back to the basic DAG in Git... JGit is just a library with\nthe building blocks necessary to manipulate the DAG.  Its up to\nthe appliction to create the new nodes correctly for its needs,\nand to make the right requests to RefUpdate.  The RefUpdate API is\ndesigned to help the application enforce CAS semantics, to avoid\nrace conditions and other ugly surprises.\n\n-- \nShawn.\n"}]}