Browse Source

Make Commit class only for writing

The Commit class now only supports the creation of a commit object.
To read a commit, applictions should use RevCommit.  This permits
us to have exactly one implementation, and RevCommit's is faster
and more bug-free.

Change-Id: Ib573f7e15f36855112815269385c21dea532e2cf
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
stable-0.9
Shawn O. Pearce 14 years ago
parent
commit
b46b635c03
  1. 6
      org.eclipse.jgit.junit/src/org/eclipse/jgit/junit/TestRepository.java
  2. 28
      org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Clone.java
  3. 17
      org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/debug/RebuildCommitGraph.java
  4. 4
      org.eclipse.jgit.test/tst/org/eclipse/jgit/api/MergeCommandTest.java
  5. 4
      org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/ReflogConfigTest.java
  6. 2
      org.eclipse.jgit.test/tst/org/eclipse/jgit/merge/CherryPickTest.java
  7. 2
      org.eclipse.jgit.test/tst/org/eclipse/jgit/merge/SimpleMergeTest.java
  8. 159
      org.eclipse.jgit.test/tst/org/eclipse/jgit/storage/file/T0003_Basic.java
  9. 4
      org.eclipse.jgit/src/org/eclipse/jgit/api/CommitCommand.java
  10. 8
      org.eclipse.jgit/src/org/eclipse/jgit/api/MergeCommand.java
  11. 104
      org.eclipse.jgit/src/org/eclipse/jgit/lib/BlobBasedConfig.java
  12. 379
      org.eclipse.jgit/src/org/eclipse/jgit/lib/Commit.java
  13. 18
      org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectInserter.java
  14. 78
      org.eclipse.jgit/src/org/eclipse/jgit/lib/Repository.java
  15. 13
      org.eclipse.jgit/src/org/eclipse/jgit/revwalk/RevCommit.java

6
org.eclipse.jgit.junit/src/org/eclipse/jgit/junit/TestRepository.java

@ -359,7 +359,7 @@ public class TestRepository<R extends Repository> {
final RevCommit... parents) throws Exception { final RevCommit... parents) throws Exception {
tick(secDelta); tick(secDelta);
final Commit c = new Commit(db); final Commit c = new Commit();
c.setTreeId(tree); c.setTreeId(tree);
c.setParentIds(parents); c.setParentIds(parents);
c.setAuthor(new PersonIdent(author, new Date(now))); c.setAuthor(new PersonIdent(author, new Date(now)));
@ -811,8 +811,8 @@ public class TestRepository<R extends Repository> {
if (self == null) { if (self == null) {
TestRepository.this.tick(tick); TestRepository.this.tick(tick);
final Commit c = new Commit(db); final Commit c = new Commit();
c.setParentIds(parents.toArray(new RevCommit[parents.size()])); c.setParentIds(parents);
c.setAuthor(new PersonIdent(author, new Date(now))); c.setAuthor(new PersonIdent(author, new Date(now)));
c.setCommitter(new PersonIdent(committer, new Date(now))); c.setCommitter(new PersonIdent(committer, new Date(now)));
c.setMessage(message); c.setMessage(message);

28
org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Clone.java

@ -51,11 +51,10 @@ import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import org.kohsuke.args4j.Argument; import org.eclipse.jgit.errors.IncorrectObjectTypeException;
import org.kohsuke.args4j.Option; import org.eclipse.jgit.errors.MissingObjectException;
import org.eclipse.jgit.errors.NotSupportedException; import org.eclipse.jgit.errors.NotSupportedException;
import org.eclipse.jgit.errors.TransportException; import org.eclipse.jgit.errors.TransportException;
import org.eclipse.jgit.lib.Commit;
import org.eclipse.jgit.lib.Constants; import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.GitIndex; import org.eclipse.jgit.lib.GitIndex;
import org.eclipse.jgit.lib.Ref; import org.eclipse.jgit.lib.Ref;
@ -64,12 +63,16 @@ import org.eclipse.jgit.lib.RefUpdate;
import org.eclipse.jgit.lib.TextProgressMonitor; import org.eclipse.jgit.lib.TextProgressMonitor;
import org.eclipse.jgit.lib.Tree; import org.eclipse.jgit.lib.Tree;
import org.eclipse.jgit.lib.WorkDirCheckout; import org.eclipse.jgit.lib.WorkDirCheckout;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevWalk;
import org.eclipse.jgit.storage.file.FileRepository; import org.eclipse.jgit.storage.file.FileRepository;
import org.eclipse.jgit.transport.FetchResult; import org.eclipse.jgit.transport.FetchResult;
import org.eclipse.jgit.transport.RefSpec; import org.eclipse.jgit.transport.RefSpec;
import org.eclipse.jgit.transport.RemoteConfig; import org.eclipse.jgit.transport.RemoteConfig;
import org.eclipse.jgit.transport.Transport; import org.eclipse.jgit.transport.Transport;
import org.eclipse.jgit.transport.URIish; import org.eclipse.jgit.transport.URIish;
import org.kohsuke.args4j.Argument;
import org.kohsuke.args4j.Option;
@Command(common = true, usage = "usage_cloneRepositoryIntoNewDir") @Command(common = true, usage = "usage_cloneRepositoryIntoNewDir")
class Clone extends AbstractFetchCommand { class Clone extends AbstractFetchCommand {
@ -174,17 +177,30 @@ class Clone extends AbstractFetchCommand {
u.link(branch.getName()); u.link(branch.getName());
} }
final Commit commit = db.mapCommit(branch.getObjectId()); final RevCommit commit = parseCommit(branch);
final RefUpdate u = db.updateRef(Constants.HEAD); final RefUpdate u = db.updateRef(Constants.HEAD);
u.setNewObjectId(commit.getCommitId()); u.setNewObjectId(commit);
u.forceUpdate(); u.forceUpdate();
final GitIndex index = new GitIndex(db); final GitIndex index = new GitIndex(db);
final Tree tree = commit.getTree(); final Tree tree = db.mapTree(commit.getTree());
final WorkDirCheckout co; final WorkDirCheckout co;
co = new WorkDirCheckout(db, db.getWorkTree(), index, tree); co = new WorkDirCheckout(db, db.getWorkTree(), index, tree);
co.checkout(); co.checkout();
index.write(); index.write();
} }
private RevCommit parseCommit(final Ref branch)
throws MissingObjectException, IncorrectObjectTypeException,
IOException {
final RevWalk rw = new RevWalk(db);
final RevCommit commit;
try {
commit = rw.parseCommit(branch.getObjectId());
} finally {
rw.release();
}
return commit;
}
} }

17
org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/debug/RebuildCommitGraph.java

@ -56,26 +56,25 @@ import java.util.List;
import java.util.ListIterator; import java.util.ListIterator;
import java.util.Map; import java.util.Map;
import org.kohsuke.args4j.Argument;
import org.kohsuke.args4j.Option;
import org.eclipse.jgit.errors.MissingObjectException; import org.eclipse.jgit.errors.MissingObjectException;
import org.eclipse.jgit.errors.ObjectWritingException; import org.eclipse.jgit.errors.ObjectWritingException;
import org.eclipse.jgit.lib.Commit; import org.eclipse.jgit.lib.Commit;
import org.eclipse.jgit.lib.Constants; import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.ObjectId; import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.ObjectIdRef; import org.eclipse.jgit.lib.ObjectIdRef;
import org.eclipse.jgit.lib.ObjectWriter; import org.eclipse.jgit.lib.ObjectInserter;
import org.eclipse.jgit.lib.PersonIdent; import org.eclipse.jgit.lib.PersonIdent;
import org.eclipse.jgit.lib.ProgressMonitor; import org.eclipse.jgit.lib.ProgressMonitor;
import org.eclipse.jgit.lib.Ref; import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.RefUpdate; import org.eclipse.jgit.lib.RefUpdate;
import org.eclipse.jgit.lib.RefWriter; import org.eclipse.jgit.lib.RefWriter;
import org.eclipse.jgit.lib.TextProgressMonitor; import org.eclipse.jgit.lib.TextProgressMonitor;
import org.eclipse.jgit.lib.Tree;
import org.eclipse.jgit.pgm.CLIText; import org.eclipse.jgit.pgm.CLIText;
import org.eclipse.jgit.pgm.TextBuiltin; import org.eclipse.jgit.pgm.TextBuiltin;
import org.eclipse.jgit.revwalk.RevWalk; import org.eclipse.jgit.revwalk.RevWalk;
import org.eclipse.jgit.storage.file.LockFile; import org.eclipse.jgit.storage.file.LockFile;
import org.kohsuke.args4j.Argument;
import org.kohsuke.args4j.Option;
/** /**
* Recreates a repository from another one's commit graph. * Recreates a repository from another one's commit graph.
@ -164,8 +163,8 @@ class RebuildCommitGraph extends TextBuiltin {
} }
pm.beginTask("Rewriting commits", queue.size()); pm.beginTask("Rewriting commits", queue.size());
final ObjectWriter ow = new ObjectWriter(db); final ObjectInserter oi = db.newObjectInserter();
final ObjectId emptyTree = ow.writeTree(new Tree(db)); final ObjectId emptyTree = oi.insert(Constants.OBJ_TREE, new byte[] {});
final PersonIdent me = new PersonIdent("jgit rebuild-commitgraph", final PersonIdent me = new PersonIdent("jgit rebuild-commitgraph",
"rebuild-commitgraph@localhost"); "rebuild-commitgraph@localhost");
while (!queue.isEmpty()) { while (!queue.isEmpty()) {
@ -192,17 +191,19 @@ class RebuildCommitGraph extends TextBuiltin {
} }
} }
final Commit newc = new Commit(db); final Commit newc = new Commit();
newc.setTreeId(emptyTree); newc.setTreeId(emptyTree);
newc.setAuthor(new PersonIdent(me, new Date(t.commitTime))); newc.setAuthor(new PersonIdent(me, new Date(t.commitTime)));
newc.setCommitter(newc.getAuthor()); newc.setCommitter(newc.getAuthor());
newc.setParentIds(newParents); newc.setParentIds(newParents);
newc.setMessage("ORIGINAL " + t.oldId.name() + "\n"); newc.setMessage("ORIGINAL " + t.oldId.name() + "\n");
t.newId = ow.writeCommit(newc); t.newId = oi.insert(Constants.OBJ_COMMIT,oi.format(newc));
rewrites.put(t.oldId, t.newId); rewrites.put(t.oldId, t.newId);
pm.update(1); pm.update(1);
} }
} }
oi.flush();
oi.release();
pm.endTask(); pm.endTask();
} }

4
org.eclipse.jgit.test/tst/org/eclipse/jgit/api/MergeCommandTest.java

@ -155,8 +155,8 @@ public class MergeCommandTest extends RepositoryTestCase {
File workDir = db.getWorkTree(); File workDir = db.getWorkTree();
if (workDir != null) { if (workDir != null) {
WorkDirCheckout workDirCheckout = new WorkDirCheckout(db, WorkDirCheckout workDirCheckout = new WorkDirCheckout(db,
workDir, db.mapCommit(Constants.HEAD).getTree(), workDir, db.mapTree(Constants.HEAD),
db.getIndex(), db.mapCommit(branchName).getTree()); db.getIndex(), db.mapTree(branchName));
workDirCheckout.setFailOnConflict(true); workDirCheckout.setFailOnConflict(true);
try { try {
workDirCheckout.checkout(); workDirCheckout.checkout();

4
org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/ReflogConfigTest.java

@ -104,11 +104,11 @@ public class ReflogConfigTest extends RepositoryTestCase {
private void commit(final Tree t, String commitMsg, PersonIdent author, private void commit(final Tree t, String commitMsg, PersonIdent author,
PersonIdent committer) throws IOException { PersonIdent committer) throws IOException {
final Commit commit = new Commit(db); final Commit commit = new Commit();
commit.setAuthor(author); commit.setAuthor(author);
commit.setCommitter(committer); commit.setCommitter(committer);
commit.setMessage(commitMsg); commit.setMessage(commitMsg);
commit.setTree(t); commit.setTreeId(t.getTreeId());
ObjectWriter writer = new ObjectWriter(db); ObjectWriter writer = new ObjectWriter(db);
commit.setCommitId(writer.writeCommit(commit)); commit.setCommitId(writer.writeCommit(commit));

2
org.eclipse.jgit.test/tst/org/eclipse/jgit/merge/CherryPickTest.java

@ -131,7 +131,7 @@ public class CherryPickTest extends RepositoryTestCase {
private ObjectId commit(final ObjectInserter odi, final DirCache treeB, private ObjectId commit(final ObjectInserter odi, final DirCache treeB,
final ObjectId[] parentIds) throws Exception { final ObjectId[] parentIds) throws Exception {
final Commit c = new Commit(db); final Commit c = new Commit();
c.setTreeId(treeB.writeTree(odi)); c.setTreeId(treeB.writeTree(odi));
c.setAuthor(new PersonIdent("A U Thor", "a.u.thor", 1L, 0)); c.setAuthor(new PersonIdent("A U Thor", "a.u.thor", 1L, 0));
c.setCommitter(c.getAuthor()); c.setCommitter(c.getAuthor());

2
org.eclipse.jgit.test/tst/org/eclipse/jgit/merge/SimpleMergeTest.java

@ -367,7 +367,7 @@ public class SimpleMergeTest extends SampleDataRepositoryTestCase {
private ObjectId commit(final ObjectInserter odi, final DirCache treeB, private ObjectId commit(final ObjectInserter odi, final DirCache treeB,
final ObjectId[] parentIds) throws Exception { final ObjectId[] parentIds) throws Exception {
final Commit c = new Commit(db); final Commit c = new Commit();
c.setTreeId(treeB.writeTree(odi)); c.setTreeId(treeB.writeTree(odi));
c.setAuthor(new PersonIdent("A U Thor", "a.u.thor", 1L, 0)); c.setAuthor(new PersonIdent("A U Thor", "a.u.thor", 1L, 0));
c.setCommitter(c.getAuthor()); c.setCommitter(c.getAuthor());

159
org.eclipse.jgit.test/tst/org/eclipse/jgit/storage/file/T0003_Basic.java

@ -53,15 +53,20 @@ import java.io.FileReader;
import java.io.FileWriter; import java.io.FileWriter;
import java.io.IOException; import java.io.IOException;
import java.io.PrintWriter; import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import org.eclipse.jgit.JGitText; import org.eclipse.jgit.JGitText;
import org.eclipse.jgit.errors.ConfigInvalidException; import org.eclipse.jgit.errors.ConfigInvalidException;
import org.eclipse.jgit.errors.IncorrectObjectTypeException;
import org.eclipse.jgit.errors.MissingObjectException;
import org.eclipse.jgit.lib.AnyObjectId;
import org.eclipse.jgit.lib.Commit; import org.eclipse.jgit.lib.Commit;
import org.eclipse.jgit.lib.Config; import org.eclipse.jgit.lib.Config;
import org.eclipse.jgit.lib.Constants; import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.FileTreeEntry; import org.eclipse.jgit.lib.FileTreeEntry;
import org.eclipse.jgit.lib.ObjectDatabase; import org.eclipse.jgit.lib.ObjectDatabase;
import org.eclipse.jgit.lib.ObjectId; import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.ObjectInserter;
import org.eclipse.jgit.lib.ObjectWriter; import org.eclipse.jgit.lib.ObjectWriter;
import org.eclipse.jgit.lib.PersonIdent; import org.eclipse.jgit.lib.PersonIdent;
import org.eclipse.jgit.lib.RefUpdate; import org.eclipse.jgit.lib.RefUpdate;
@ -71,6 +76,8 @@ import org.eclipse.jgit.lib.Tag;
import org.eclipse.jgit.lib.Tree; import org.eclipse.jgit.lib.Tree;
import org.eclipse.jgit.lib.TreeEntry; import org.eclipse.jgit.lib.TreeEntry;
import org.eclipse.jgit.lib.WriteTree; import org.eclipse.jgit.lib.WriteTree;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevWalk;
public class T0003_Basic extends SampleDataRepositoryTestCase { public class T0003_Basic extends SampleDataRepositoryTestCase {
public void test001_Initalize() { public void test001_Initalize() {
@ -243,7 +250,8 @@ public class T0003_Basic extends SampleDataRepositoryTestCase {
assertEqualsPath(theDir.getParentFile(), r.getWorkTree()); assertEqualsPath(theDir.getParentFile(), r.getWorkTree());
assertEqualsPath(indexFile, r.getIndexFile()); assertEqualsPath(indexFile, r.getIndexFile());
assertEqualsPath(objDir, r.getObjectDatabase().getDirectory()); assertEqualsPath(objDir, r.getObjectDatabase().getDirectory());
assertNotNull(r.mapCommit("6db9c2ebf75590eef973081736730a9ea169a0c4")); assertNotNull(r.open(ObjectId
.fromString("6db9c2ebf75590eef973081736730a9ea169a0c4")));
// Must close or the default repo pack files created by this test gets // Must close or the default repo pack files created by this test gets
// locked via the alternate object directories on Windows. // locked via the alternate object directories on Windows.
r.close(); r.close();
@ -374,13 +382,15 @@ public class T0003_Basic extends SampleDataRepositoryTestCase {
assertEquals(ObjectId.fromString("00b1f73724f493096d1ffa0b0f1f1482dbb8c936"), assertEquals(ObjectId.fromString("00b1f73724f493096d1ffa0b0f1f1482dbb8c936"),
t.getTreeId()); t.getTreeId());
final Commit c = new Commit(db); final Commit c = new Commit();
c.setAuthor(new PersonIdent(author, 1154236443000L, -4 * 60)); c.setAuthor(new PersonIdent(author, 1154236443000L, -4 * 60));
c.setCommitter(new PersonIdent(committer, 1154236443000L, -4 * 60)); c.setCommitter(new PersonIdent(committer, 1154236443000L, -4 * 60));
c.setMessage("A Commit\n"); c.setMessage("A Commit\n");
c.setTree(t); c.setTreeId(t.getTreeId());
assertEquals(t.getTreeId(), c.getTreeId()); assertEquals(t.getTreeId(), c.getTreeId());
c.commit();
insertCommit(c);
final ObjectId cmtid = ObjectId.fromString( final ObjectId cmtid = ObjectId.fromString(
"803aec4aba175e8ab1d666873c984c0308179099"); "803aec4aba175e8ab1d666873c984c0308179099");
assertEquals(cmtid, c.getCommitId()); assertEquals(cmtid, c.getCommitId());
@ -399,12 +409,12 @@ public class T0003_Basic extends SampleDataRepositoryTestCase {
} }
// Verify we can read it. // Verify we can read it.
final Commit c2 = db.mapCommit(cmtid); RevCommit c2 = parseCommit(c.getCommitId());
assertNotNull(c2); assertNotNull(c2);
assertEquals(c.getMessage(), c2.getMessage()); assertEquals(c.getMessage(), c2.getFullMessage());
assertEquals(c.getTreeId(), c2.getTreeId()); assertEquals(c.getTreeId(), c2.getTree());
assertEquals(c.getAuthor(), c2.getAuthor()); assertEquals(c.getAuthor(), c2.getAuthorIdent());
assertEquals(c.getCommitter(), c2.getCommitter()); assertEquals(c.getCommitter(), c2.getCommitterIdent());
} }
public void test012_SubtreeExternalSorting() throws IOException { public void test012_SubtreeExternalSorting() throws IOException {
@ -484,12 +494,12 @@ public class T0003_Basic extends SampleDataRepositoryTestCase {
final Tree almostEmptyTree = new Tree(db); final Tree almostEmptyTree = new Tree(db);
almostEmptyTree.addEntry(new FileTreeEntry(almostEmptyTree, emptyId, "empty".getBytes(), false)); almostEmptyTree.addEntry(new FileTreeEntry(almostEmptyTree, emptyId, "empty".getBytes(), false));
final ObjectId almostEmptyTreeId = new ObjectWriter(db).writeTree(almostEmptyTree); final ObjectId almostEmptyTreeId = new ObjectWriter(db).writeTree(almostEmptyTree);
final Commit almostEmptyCommit = new Commit(db); final Commit almostEmptyCommit = new Commit();
almostEmptyCommit.setAuthor(new PersonIdent(author, 1154236443000L, -2 * 60)); // not exactly the same almostEmptyCommit.setAuthor(new PersonIdent(author, 1154236443000L, -2 * 60)); // not exactly the same
almostEmptyCommit.setCommitter(new PersonIdent(author, 1154236443000L, -2 * 60)); almostEmptyCommit.setCommitter(new PersonIdent(author, 1154236443000L, -2 * 60));
almostEmptyCommit.setMessage("test022\n"); almostEmptyCommit.setMessage("test022\n");
almostEmptyCommit.setTreeId(almostEmptyTreeId); almostEmptyCommit.setTreeId(almostEmptyTreeId);
ObjectId almostEmptyCommitId = new ObjectWriter(db).writeCommit(almostEmptyCommit); ObjectId almostEmptyCommitId = insertCommit(almostEmptyCommit);
final Tag t = new Tag(db); final Tag t = new Tag(db);
t.setObjId(almostEmptyCommitId); t.setObjId(almostEmptyCommitId);
t.setType("commit"); t.setType("commit");
@ -511,17 +521,17 @@ public class T0003_Basic extends SampleDataRepositoryTestCase {
final Tree almostEmptyTree = new Tree(db); final Tree almostEmptyTree = new Tree(db);
almostEmptyTree.addEntry(new FileTreeEntry(almostEmptyTree, emptyId, "empty".getBytes(), false)); almostEmptyTree.addEntry(new FileTreeEntry(almostEmptyTree, emptyId, "empty".getBytes(), false));
final ObjectId almostEmptyTreeId = new ObjectWriter(db).writeTree(almostEmptyTree); final ObjectId almostEmptyTreeId = new ObjectWriter(db).writeTree(almostEmptyTree);
Commit commit = new Commit(db); Commit commit = new Commit();
commit.setTreeId(almostEmptyTreeId); commit.setTreeId(almostEmptyTreeId);
commit.setAuthor(new PersonIdent("Joe H\u00e4cker","joe@example.com",4294967295000L,60)); commit.setAuthor(new PersonIdent("Joe H\u00e4cker","joe@example.com",4294967295000L,60));
commit.setCommitter(new PersonIdent("Joe Hacker","joe2@example.com",4294967295000L,60)); commit.setCommitter(new PersonIdent("Joe Hacker","joe2@example.com",4294967295000L,60));
commit.setEncoding("UTF-8"); commit.setEncoding("UTF-8");
commit.setMessage("\u00dcbergeeks"); commit.setMessage("\u00dcbergeeks");
ObjectId cid = new ObjectWriter(db).writeCommit(commit); ObjectId cid = insertCommit(commit);
assertEquals("4680908112778718f37e686cbebcc912730b3154", cid.name()); assertEquals("4680908112778718f37e686cbebcc912730b3154", cid.name());
Commit loadedCommit = db.mapCommit(cid);
assertNotSame(loadedCommit, commit); RevCommit loadedCommit = parseCommit(cid);
assertEquals(commit.getMessage(), loadedCommit.getMessage()); assertEquals(commit.getMessage(), loadedCommit.getFullMessage());
} }
public void test024_createCommitNonAscii() throws IOException { public void test024_createCommitNonAscii() throws IOException {
@ -529,13 +539,13 @@ public class T0003_Basic extends SampleDataRepositoryTestCase {
final Tree almostEmptyTree = new Tree(db); final Tree almostEmptyTree = new Tree(db);
almostEmptyTree.addEntry(new FileTreeEntry(almostEmptyTree, emptyId, "empty".getBytes(), false)); almostEmptyTree.addEntry(new FileTreeEntry(almostEmptyTree, emptyId, "empty".getBytes(), false));
final ObjectId almostEmptyTreeId = new ObjectWriter(db).writeTree(almostEmptyTree); final ObjectId almostEmptyTreeId = new ObjectWriter(db).writeTree(almostEmptyTree);
Commit commit = new Commit(db); Commit commit = new Commit();
commit.setTreeId(almostEmptyTreeId); commit.setTreeId(almostEmptyTreeId);
commit.setAuthor(new PersonIdent("Joe H\u00e4cker","joe@example.com",4294967295000L,60)); commit.setAuthor(new PersonIdent("Joe H\u00e4cker","joe@example.com",4294967295000L,60));
commit.setCommitter(new PersonIdent("Joe Hacker","joe2@example.com",4294967295000L,60)); commit.setCommitter(new PersonIdent("Joe Hacker","joe2@example.com",4294967295000L,60));
commit.setEncoding("ISO-8859-1"); commit.setEncoding("ISO-8859-1");
commit.setMessage("\u00dcbergeeks"); commit.setMessage("\u00dcbergeeks");
ObjectId cid = new ObjectWriter(db).writeCommit(commit); ObjectId cid = insertCommit(commit);
assertEquals("2979b39d385014b33287054b87f77bcb3ecb5ebf", cid.name()); assertEquals("2979b39d385014b33287054b87f77bcb3ecb5ebf", cid.name());
} }
@ -601,82 +611,82 @@ public class T0003_Basic extends SampleDataRepositoryTestCase {
assertEquals(ObjectId.fromString("00b1f73724f493096d1ffa0b0f1f1482dbb8c936"), assertEquals(ObjectId.fromString("00b1f73724f493096d1ffa0b0f1f1482dbb8c936"),
t.getTreeId()); t.getTreeId());
final Commit c1 = new Commit(db); final Commit c1 = new Commit();
c1.setAuthor(new PersonIdent(author, 1154236443000L, -4 * 60)); c1.setAuthor(new PersonIdent(author, 1154236443000L, -4 * 60));
c1.setCommitter(new PersonIdent(committer, 1154236443000L, -4 * 60)); c1.setCommitter(new PersonIdent(committer, 1154236443000L, -4 * 60));
c1.setMessage("A Commit\n"); c1.setMessage("A Commit\n");
c1.setTree(t); c1.setTreeId(t.getTreeId());
assertEquals(t.getTreeId(), c1.getTreeId()); assertEquals(t.getTreeId(), c1.getTreeId());
c1.commit(); insertCommit(c1);
final ObjectId cmtid1 = ObjectId.fromString( final ObjectId cmtid1 = ObjectId.fromString(
"803aec4aba175e8ab1d666873c984c0308179099"); "803aec4aba175e8ab1d666873c984c0308179099");
assertEquals(cmtid1, c1.getCommitId()); assertEquals(cmtid1, c1.getCommitId());
final Commit c2 = new Commit(db); final Commit c2 = new Commit();
c2.setAuthor(new PersonIdent(author, 1154236443000L, -4 * 60)); c2.setAuthor(new PersonIdent(author, 1154236443000L, -4 * 60));
c2.setCommitter(new PersonIdent(committer, 1154236443000L, -4 * 60)); c2.setCommitter(new PersonIdent(committer, 1154236443000L, -4 * 60));
c2.setMessage("A Commit 2\n"); c2.setMessage("A Commit 2\n");
c2.setTree(t); c2.setTreeId(t.getTreeId());
assertEquals(t.getTreeId(), c2.getTreeId()); assertEquals(t.getTreeId(), c2.getTreeId());
c2.setParentIds(new ObjectId[] { c1.getCommitId() } ); c2.setParentIds(c1.getCommitId());
c2.commit(); insertCommit(c2);
final ObjectId cmtid2 = ObjectId.fromString( final ObjectId cmtid2 = ObjectId.fromString(
"95d068687c91c5c044fb8c77c5154d5247901553"); "95d068687c91c5c044fb8c77c5154d5247901553");
assertEquals(cmtid2, c2.getCommitId()); assertEquals(cmtid2, c2.getCommitId());
Commit rm2 = db.mapCommit(cmtid2); RevCommit rm2 = parseCommit(cmtid2);
assertNotSame(c2, rm2); // assert the parsed objects is not from the cache assertNotSame(c2, rm2); // assert the parsed objects is not from the cache
assertEquals(c2.getAuthor(), rm2.getAuthor()); assertEquals(c2.getAuthor(), rm2.getAuthorIdent());
assertEquals(c2.getCommitId(), rm2.getCommitId()); assertEquals(c2.getCommitId(), rm2.getId());
assertEquals(c2.getMessage(), rm2.getMessage()); assertEquals(c2.getMessage(), rm2.getFullMessage());
assertEquals(c2.getTree().getTreeId(), rm2.getTree().getTreeId()); assertEquals(c2.getTreeId(), rm2.getTree().getId());
assertEquals(1, rm2.getParentIds().length); assertEquals(1, rm2.getParentCount());
assertEquals(c1.getCommitId(), rm2.getParentIds()[0]); assertEquals(c1.getCommitId(), rm2.getParent(0));
final Commit c3 = new Commit(db); final Commit c3 = new Commit();
c3.setAuthor(new PersonIdent(author, 1154236443000L, -4 * 60)); c3.setAuthor(new PersonIdent(author, 1154236443000L, -4 * 60));
c3.setCommitter(new PersonIdent(committer, 1154236443000L, -4 * 60)); c3.setCommitter(new PersonIdent(committer, 1154236443000L, -4 * 60));
c3.setMessage("A Commit 3\n"); c3.setMessage("A Commit 3\n");
c3.setTree(t); c3.setTreeId(t.getTreeId());
assertEquals(t.getTreeId(), c3.getTreeId()); assertEquals(t.getTreeId(), c3.getTreeId());
c3.setParentIds(new ObjectId[] { c1.getCommitId(), c2.getCommitId() }); c3.setParentIds(c1.getCommitId(), c2.getCommitId());
c3.commit(); insertCommit(c3);
final ObjectId cmtid3 = ObjectId.fromString( final ObjectId cmtid3 = ObjectId.fromString(
"ce6e1ce48fbeeb15a83f628dc8dc2debefa066f4"); "ce6e1ce48fbeeb15a83f628dc8dc2debefa066f4");
assertEquals(cmtid3, c3.getCommitId()); assertEquals(cmtid3, c3.getCommitId());
Commit rm3 = db.mapCommit(cmtid3); RevCommit rm3 = parseCommit(cmtid3);
assertNotSame(c3, rm3); // assert the parsed objects is not from the cache assertNotSame(c3, rm3); // assert the parsed objects is not from the cache
assertEquals(c3.getAuthor(), rm3.getAuthor()); assertEquals(c3.getAuthor(), rm3.getAuthorIdent());
assertEquals(c3.getCommitId(), rm3.getCommitId()); assertEquals(c3.getCommitId(), rm3.getId());
assertEquals(c3.getMessage(), rm3.getMessage()); assertEquals(c3.getMessage(), rm3.getFullMessage());
assertEquals(c3.getTree().getTreeId(), rm3.getTree().getTreeId()); assertEquals(c3.getTreeId(), rm3.getTree().getId());
assertEquals(2, rm3.getParentIds().length); assertEquals(2, rm3.getParentCount());
assertEquals(c1.getCommitId(), rm3.getParentIds()[0]); assertEquals(c1.getCommitId(), rm3.getParent(0));
assertEquals(c2.getCommitId(), rm3.getParentIds()[1]); assertEquals(c2.getCommitId(), rm3.getParent(1));
final Commit c4 = new Commit(db); final Commit c4 = new Commit();
c4.setAuthor(new PersonIdent(author, 1154236443000L, -4 * 60)); c4.setAuthor(new PersonIdent(author, 1154236443000L, -4 * 60));
c4.setCommitter(new PersonIdent(committer, 1154236443000L, -4 * 60)); c4.setCommitter(new PersonIdent(committer, 1154236443000L, -4 * 60));
c4.setMessage("A Commit 4\n"); c4.setMessage("A Commit 4\n");
c4.setTree(t); c4.setTreeId(t.getTreeId());
assertEquals(t.getTreeId(), c3.getTreeId()); assertEquals(t.getTreeId(), c3.getTreeId());
c4.setParentIds(new ObjectId[] { c1.getCommitId(), c2.getCommitId(), c3.getCommitId() }); c4.setParentIds(c1.getCommitId(), c2.getCommitId(), c3.getCommitId());
c4.commit(); insertCommit(c4);
final ObjectId cmtid4 = ObjectId.fromString( final ObjectId cmtid4 = ObjectId.fromString(
"d1fca9fe3fef54e5212eb67902c8ed3e79736e27"); "d1fca9fe3fef54e5212eb67902c8ed3e79736e27");
assertEquals(cmtid4, c4.getCommitId()); assertEquals(cmtid4, c4.getCommitId());
Commit rm4 = db.mapCommit(cmtid4); RevCommit rm4 = parseCommit(cmtid4);
assertNotSame(c4, rm3); // assert the parsed objects is not from the cache assertNotSame(c4, rm3); // assert the parsed objects is not from the cache
assertEquals(c4.getAuthor(), rm4.getAuthor()); assertEquals(c4.getAuthor(), rm4.getAuthorIdent());
assertEquals(c4.getCommitId(), rm4.getCommitId()); assertEquals(c4.getCommitId(), rm4.getId());
assertEquals(c4.getMessage(), rm4.getMessage()); assertEquals(c4.getMessage(), rm4.getFullMessage());
assertEquals(c4.getTree().getTreeId(), rm4.getTree().getTreeId()); assertEquals(c4.getTreeId(), rm4.getTree().getId());
assertEquals(3, rm4.getParentIds().length); assertEquals(3, rm4.getParentCount());
assertEquals(c1.getCommitId(), rm4.getParentIds()[0]); assertEquals(c1.getCommitId(), rm4.getParent(0));
assertEquals(c2.getCommitId(), rm4.getParentIds()[1]); assertEquals(c2.getCommitId(), rm4.getParent(1));
assertEquals(c3.getCommitId(), rm4.getParentIds()[2]); assertEquals(c3.getCommitId(), rm4.getParent(2));
} }
public void test027_UnpackedRefHigherPriorityThanPacked() throws IOException { public void test027_UnpackedRefHigherPriorityThanPacked() throws IOException {
@ -717,13 +727,6 @@ public class T0003_Basic extends SampleDataRepositoryTestCase {
assertEquals(newId2, db.resolve("refs/heads/foobar")); assertEquals(newId2, db.resolve("refs/heads/foobar"));
} }
public void test029_mapObject() throws IOException {
assertEquals(new byte[0].getClass(), db.mapObject(ObjectId.fromString("5b6e7c66c276e7610d4a73c70ec1a1f7c1003259"), null).getClass());
assertEquals(Commit.class, db.mapObject(ObjectId.fromString("540a36d136cf413e4b064c2b0e0a4db60f77feab"), null).getClass());
assertEquals(Tree.class, db.mapObject(ObjectId.fromString("aabf2ffaec9b497f0950352b3e582d73035c2035"), null).getClass());
assertEquals(Tag.class, db.mapObject(ObjectId.fromString("17768080a2318cd89bba4c8b87834401e2095703"), null).getClass());
}
public void test30_stripWorkDir() { public void test30_stripWorkDir() {
File relCwd = new File("."); File relCwd = new File(".");
File absCwd = relCwd.getAbsoluteFile(); File absCwd = relCwd.getAbsoluteFile();
@ -750,6 +753,30 @@ public class T0003_Basic extends SampleDataRepositoryTestCase {
} }
private ObjectId insertCommit(final Commit commit) throws IOException,
UnsupportedEncodingException {
ObjectInserter oi = db.newObjectInserter();
try {
ObjectId id = oi.insert(Constants.OBJ_COMMIT, oi.format(commit));
oi.flush();
commit.setCommitId(id);
return id;
} finally {
oi.release();
}
}
private RevCommit parseCommit(AnyObjectId id)
throws MissingObjectException, IncorrectObjectTypeException,
IOException {
RevWalk rw = new RevWalk(db);
try {
return rw.parseCommit(id);
} finally {
rw.release();
}
}
/** /**
* Kick the timestamp of a local file. * Kick the timestamp of a local file.
* <p> * <p>

4
org.eclipse.jgit/src/org/eclipse/jgit/api/CommitCommand.java

@ -162,12 +162,12 @@ public class CommitCommand extends GitCommand<RevCommit> {
ObjectId indexTreeId = index.writeTree(odi); ObjectId indexTreeId = index.writeTree(odi);
// Create a Commit object, populate it and write it // Create a Commit object, populate it and write it
Commit commit = new Commit(repo); Commit commit = new Commit();
commit.setCommitter(committer); commit.setCommitter(committer);
commit.setAuthor(author); commit.setAuthor(author);
commit.setMessage(message); commit.setMessage(message);
commit.setParentIds(parents.toArray(new ObjectId[] {})); commit.setParentIds(parents);
commit.setTreeId(indexTreeId); commit.setTreeId(indexTreeId);
ObjectId commitId = odi.insert(Constants.OBJ_COMMIT, odi ObjectId commitId = odi.insert(Constants.OBJ_COMMIT, odi
.format(commit)); .format(commit));

8
org.eclipse.jgit/src/org/eclipse/jgit/api/MergeCommand.java

@ -57,11 +57,11 @@ import org.eclipse.jgit.lib.GitIndex;
import org.eclipse.jgit.lib.ObjectId; import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.ObjectIdRef; import org.eclipse.jgit.lib.ObjectIdRef;
import org.eclipse.jgit.lib.Ref; import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.Ref.Storage;
import org.eclipse.jgit.lib.RefUpdate; import org.eclipse.jgit.lib.RefUpdate;
import org.eclipse.jgit.lib.RefUpdate.Result;
import org.eclipse.jgit.lib.Repository; import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.lib.WorkDirCheckout; import org.eclipse.jgit.lib.WorkDirCheckout;
import org.eclipse.jgit.lib.Ref.Storage;
import org.eclipse.jgit.lib.RefUpdate.Result;
import org.eclipse.jgit.merge.MergeStrategy; import org.eclipse.jgit.merge.MergeStrategy;
import org.eclipse.jgit.revwalk.RevCommit; import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevWalk; import org.eclipse.jgit.revwalk.RevWalk;
@ -176,8 +176,8 @@ public class MergeCommand extends GitCommand<MergeResult> {
File workDir = repo.getWorkTree(); File workDir = repo.getWorkTree();
if (workDir != null) { if (workDir != null) {
WorkDirCheckout workDirCheckout = new WorkDirCheckout(repo, WorkDirCheckout workDirCheckout = new WorkDirCheckout(repo,
workDir, headCommit.asCommit(revWalk).getTree(), index, workDir, repo.mapTree(headCommit.getTree()), index,
newHeadCommit.asCommit(revWalk).getTree()); repo.mapTree(newHeadCommit.getTree()));
workDirCheckout.setFailOnConflict(true); workDirCheckout.setFailOnConflict(true);
try { try {
workDirCheckout.checkout(); workDirCheckout.checkout();

104
org.eclipse.jgit/src/org/eclipse/jgit/lib/BlobBasedConfig.java

@ -51,15 +51,24 @@ import java.text.MessageFormat;
import org.eclipse.jgit.JGitText; import org.eclipse.jgit.JGitText;
import org.eclipse.jgit.errors.ConfigInvalidException; import org.eclipse.jgit.errors.ConfigInvalidException;
import org.eclipse.jgit.errors.IncorrectObjectTypeException;
import org.eclipse.jgit.errors.MissingObjectException;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevTree;
import org.eclipse.jgit.revwalk.RevWalk;
import org.eclipse.jgit.treewalk.TreeWalk; import org.eclipse.jgit.treewalk.TreeWalk;
import org.eclipse.jgit.util.IO;
import org.eclipse.jgit.util.RawParseUtils; import org.eclipse.jgit.util.RawParseUtils;
/** /**
* The configuration file based on the blobs stored in the repository * Configuration file based on the blobs stored in the repository.
*
* This implementation currently only provides reading support, and is primarily
* useful for supporting the {@code .gitmodules} file.
*/ */
public class BlobBasedConfig extends Config { public class BlobBasedConfig extends Config {
/** /**
* The constructor from a byte array * Parse a configuration from a byte array.
* *
* @param base * @param base
* the base configuration file * the base configuration file
@ -75,11 +84,11 @@ public class BlobBasedConfig extends Config {
} }
/** /**
* The constructor from object identifier * Load a configuration file from a blob.
* *
* @param base * @param base
* the base configuration file * the base configuration file
* @param r * @param db
* the repository * the repository
* @param objectId * @param objectId
* the object identifier * the object identifier
@ -88,22 +97,50 @@ public class BlobBasedConfig extends Config {
* @throws ConfigInvalidException * @throws ConfigInvalidException
* the blob is not a valid configuration format. * the blob is not a valid configuration format.
*/ */
public BlobBasedConfig(Config base, final Repository r, public BlobBasedConfig(Config base, Repository db, AnyObjectId objectId)
final ObjectId objectId) throws IOException, ConfigInvalidException { throws IOException, ConfigInvalidException {
super(base); this(base, read(db, objectId));
ObjectLoader loader = r.open(objectId, Constants.OBJ_BLOB); }
fromText(RawParseUtils.decode(loader.getCachedBytes()));
private static byte[] read(Repository db, AnyObjectId blobId)
throws MissingObjectException, IncorrectObjectTypeException,
IOException {
ObjectReader or = db.newObjectReader();
try {
return read(or, blobId);
} finally {
or.release();
}
}
private static byte[] read(ObjectReader or, AnyObjectId blobId)
throws MissingObjectException, IncorrectObjectTypeException,
IOException {
ObjectLoader loader = or.open(blobId, Constants.OBJ_BLOB);
if (loader.isLarge()) {
ObjectStream in = loader.openStream();
try {
byte[] buf = new byte[(int) in.getSize()];
IO.readFully(in, buf, 0, buf.length);
return buf;
} finally {
in.close();
}
}
return loader.getCachedBytes();
} }
/** /**
* The constructor from commit and path * Load a configuration file from a blob stored in a specific commit.
* *
* @param base * @param base
* the base configuration file * the base configuration file
* @param commit * @param db
* the commit that contains the object * the repository containing the objects.
* @param treeish
* the tree (or commit) that contains the object
* @param path * @param path
* the path within the tree of the commit * the path within the tree
* @throws FileNotFoundException * @throws FileNotFoundException
* the path does not exist in the commit's tree. * the path does not exist in the commit's tree.
* @throws IOException * @throws IOException
@ -111,16 +148,37 @@ public class BlobBasedConfig extends Config {
* @throws ConfigInvalidException * @throws ConfigInvalidException
* the blob is not a valid configuration format. * the blob is not a valid configuration format.
*/ */
public BlobBasedConfig(Config base, final Commit commit, final String path) public BlobBasedConfig(Config base, Repository db, AnyObjectId treeish,
throws FileNotFoundException, IOException, ConfigInvalidException { String path) throws FileNotFoundException, IOException,
super(base); ConfigInvalidException {
final ObjectId treeId = commit.getTreeId(); this(base, read(db, treeish, path));
final Repository r = commit.getRepository(); }
final TreeWalk tree = TreeWalk.forPath(r, path, treeId);
private static byte[] read(Repository db, AnyObjectId treeish, String path)
throws MissingObjectException, IncorrectObjectTypeException,
IOException {
ObjectReader or = db.newObjectReader();
try {
TreeWalk tree = TreeWalk.forPath(or, path, asTree(or, treeish));
if (tree == null) if (tree == null)
throw new FileNotFoundException(MessageFormat.format(JGitText.get().entryNotFoundByPath, path)); throw new FileNotFoundException(MessageFormat.format(JGitText
final ObjectId blobId = tree.getObjectId(0); .get().entryNotFoundByPath, path));
ObjectLoader loader = r.open(blobId,Constants.OBJ_BLOB); return read(or, tree.getObjectId(0));
fromText(RawParseUtils.decode(loader.getCachedBytes())); } finally {
or.release();
}
}
private static AnyObjectId asTree(ObjectReader or, AnyObjectId treeish)
throws MissingObjectException, IncorrectObjectTypeException,
IOException {
if (treeish instanceof RevTree)
return treeish;
if (treeish instanceof RevCommit
&& ((RevCommit) treeish).getTree() != null)
return ((RevCommit) treeish).getTree();
return new RevWalk(or).parseTree(treeish).getId();
} }
} }

379
org.eclipse.jgit/src/org/eclipse/jgit/lib/Commit.java

@ -45,25 +45,19 @@
package org.eclipse.jgit.lib; package org.eclipse.jgit.lib;
import java.io.ByteArrayInputStream;
import java.io.DataInputStream;
import java.io.IOException;
import java.nio.charset.Charset; import java.nio.charset.Charset;
import java.text.MessageFormat; import java.util.List;
import org.eclipse.jgit.JGitText;
import org.eclipse.jgit.errors.CorruptObjectException;
import org.eclipse.jgit.errors.MissingObjectException;
/** /**
* Instances of this class represent a Commit object. It represents a snapshot * Mutable builder to construct a commit recording the state of a project.
* in a Git repository, who created it and when. *
* Applications should use this object when they need to manually construct a
* commit and want precise control over its fields. For a higher level interface
* see {@link org.eclipse.jgit.api.CommitCommand}.
*/ */
public class Commit implements Treeish { public class Commit {
private static final ObjectId[] EMPTY_OBJECTID_LIST = new ObjectId[0]; private static final ObjectId[] EMPTY_OBJECTID_LIST = new ObjectId[0];
private final Repository objdb;
private ObjectId commitId; private ObjectId commitId;
private ObjectId treeId; private ObjectId treeId;
@ -76,102 +70,21 @@ public class Commit implements Treeish {
private String message; private String message;
private Tree treeObj;
private byte[] raw;
private Charset encoding; private Charset encoding;
/** /** Initialize an empty commit. */
* Create an empty commit object. More information must be fed to this public Commit() {
* object to make it useful.
*
* @param db
* The repository with which to associate it.
*/
public Commit(final Repository db) {
objdb = db;
parentIds = EMPTY_OBJECTID_LIST;
}
/**
* Create a commit associated with these parents and associate it with a
* repository.
*
* @param db
* The repository to which this commit object belongs
* @param parentIds
* Id's of the parent(s)
*/
public Commit(final Repository db, final ObjectId[] parentIds) {
objdb = db;
this.parentIds = parentIds;
}
/**
* Create a commit object with the specified id and data from and existing
* commit object in a repository.
*
* @param db
* The repository to which this commit object belongs
* @param id
* Commit id
* @param raw
* Raw commit object data
*/
public Commit(final Repository db, final ObjectId id, final byte[] raw) {
objdb = db;
commitId = id;
treeId = ObjectId.fromString(raw, 5);
parentIds = new ObjectId[1];
int np=0;
int rawPtr = 46;
for (;;) {
if (raw[rawPtr] != 'p')
break;
if (np == 0) {
parentIds[np++] = ObjectId.fromString(raw, rawPtr + 7);
} else if (np == 1) {
parentIds = new ObjectId[] { parentIds[0], ObjectId.fromString(raw, rawPtr + 7) };
np++;
} else {
if (parentIds.length <= np) {
ObjectId[] old = parentIds;
parentIds = new ObjectId[parentIds.length+32];
for (int i=0; i<np; ++i)
parentIds[i] = old[i];
}
parentIds[np++] = ObjectId.fromString(raw, rawPtr + 7);
}
rawPtr += 48;
}
if (np != parentIds.length) {
ObjectId[] old = parentIds;
parentIds = new ObjectId[np];
for (int i=0; i<np; ++i)
parentIds[i] = old[i];
} else
if (np == 0)
parentIds = EMPTY_OBJECTID_LIST; parentIds = EMPTY_OBJECTID_LIST;
this.raw = raw; encoding = Constants.CHARSET;
} }
/** /** @return this commit's object id. */
* @return get repository for the commit
*/
public Repository getRepository() {
return objdb;
}
/**
* @return The commit object id
*/
public ObjectId getCommitId() { public ObjectId getCommitId() {
return commitId; return commitId;
} }
/** /**
* Set the id of this object. * Set the id of this commit object.
* *
* @param id * @param id
* the id that we calculated for this object. * the id that we calculated for this object.
@ -180,6 +93,7 @@ public class Commit implements Treeish {
commitId = id; commitId = id;
} }
/** @return id of the root tree listing this commit's snapshot. */
public ObjectId getTreeId() { public ObjectId getTreeId() {
return treeId; return treeId;
} }
@ -188,198 +102,197 @@ public class Commit implements Treeish {
* Set the tree id for this commit object * Set the tree id for this commit object
* *
* @param id * @param id
* the tree identity.
*/ */
public void setTreeId(final ObjectId id) { public void setTreeId(AnyObjectId id) {
if (treeId==null || !treeId.equals(id)) { treeId = id.copy();
treeObj = null; commitId = null;
}
treeId = id;
}
public Tree getTree() throws IOException {
if (treeObj == null) {
treeObj = objdb.mapTree(getTreeId());
if (treeObj == null) {
throw new MissingObjectException(getTreeId(),
Constants.TYPE_TREE);
}
}
return treeObj;
}
/**
* Set the tree object for this commit
* @see #setTreeId
* @param t the Tree object
*/
public void setTree(final Tree t) {
treeId = t.getTreeId();
treeObj = t;
} }
/** /** @return the author of this commit (who wrote it). */
* @return the author and authoring time for this commit
*/
public PersonIdent getAuthor() { public PersonIdent getAuthor() {
decode();
return author; return author;
} }
/** /**
* Set the author and authoring time for this commit * Set the author (name, email address, and date) of who wrote the commit.
* @param a *
* @param newAuthor
* the new author. Should not be null.
*/ */
public void setAuthor(final PersonIdent a) { public void setAuthor(PersonIdent newAuthor) {
author = a; author = newAuthor;
commitId = null;
} }
/** /** @return the committer and commit time for this object. */
* @return the committer and commit time for this object
*/
public PersonIdent getCommitter() { public PersonIdent getCommitter() {
decode();
return committer; return committer;
} }
/** /**
* Set the committer and commit time for this object * Set the committer and commit time for this object
* @param c the committer information *
* @param newCommitter
* the committer information. Should not be null.
*/ */
public void setCommitter(final PersonIdent c) { public void setCommitter(PersonIdent newCommitter) {
committer = c; committer = newCommitter;
commitId = null;
} }
/** /** @return the ancestors of this commit. Never null. */
* @return the object ids of this commit
*/
public ObjectId[] getParentIds() { public ObjectId[] getParentIds() {
return parentIds; return parentIds;
} }
/** /**
* @return the commit message * Set the parent of this commit.
*
* @param newParent
* the single parent for the commit.
*/ */
public String getMessage() { public void setParentId(AnyObjectId newParent) {
decode(); parentIds = new ObjectId[] { newParent.copy() };
return message; commitId = null;
} }
/** /**
* Set the parents of this commit * Set the parents of this commit.
* @param parentIds *
* @param parent1
* the first parent of this commit. Typically this is the current
* value of the {@code HEAD} reference and is thus the current
* branch's position in history.
* @param parent2
* the second parent of this merge commit. Usually this is the
* branch being merged into the current branch.
*/ */
public void setParentIds(ObjectId[] parentIds) { public void setParentIds(AnyObjectId parent1, AnyObjectId parent2) {
this.parentIds = new ObjectId[parentIds.length]; parentIds = new ObjectId[] { parent1.copy(), parent2.copy() };
for (int i=0; i<parentIds.length; ++i) commitId = null;
this.parentIds[i] = parentIds[i];
} }
private void decode() { /**
// FIXME: handle I/O errors * Set the parents of this commit.
if (raw != null) { *
try { * @param newParents
DataInputStream br = new DataInputStream(new ByteArrayInputStream(raw)); * the entire list of parents for this commit.
String n = br.readLine(); */
if (n == null || !n.startsWith("tree ")) { public void setParentIds(ObjectId... newParents) {
throw new CorruptObjectException(commitId, JGitText.get().corruptObjectNotree); parentIds = new ObjectId[newParents.length];
} for (int i = 0; i < newParents.length; i++)
while ((n = br.readLine()) != null && n.startsWith("parent ")) { parentIds[i] = newParents[i].copy();
// empty body commitId = null;
}
if (n == null || !n.startsWith("author ")) {
throw new CorruptObjectException(commitId, JGitText.get().corruptObjectNoAuthor);
}
String rawAuthor = n.substring("author ".length());
n = br.readLine();
if (n == null || !n.startsWith("committer ")) {
throw new CorruptObjectException(commitId, JGitText.get().corruptObjectNoCommitter);
}
String rawCommitter = n.substring("committer ".length());
n = br.readLine();
if (n != null && n.startsWith( "encoding"))
encoding = Charset.forName(n.substring("encoding ".length()));
else
if (n == null || !n.equals("")) {
throw new CorruptObjectException(commitId, MessageFormat.format(
JGitText.get().corruptObjectMalformedHeader, n));
}
byte[] readBuf = new byte[br.available()]; // in-memory stream so this is all bytes left
br.read(readBuf);
int msgstart = readBuf.length != 0 ? ( readBuf[0] == '\n' ? 1 : 0 ) : 0;
// If encoding is not specified, the default for commit is UTF-8
if (encoding == null) encoding = Constants.CHARSET;
// TODO: this isn't reliable so we need to guess the encoding from the actual content
author = new PersonIdent(new String(rawAuthor.getBytes(),encoding.name()));
committer = new PersonIdent(new String(rawCommitter.getBytes(),encoding.name()));
message = new String(readBuf,msgstart, readBuf.length-msgstart, encoding.name());
} catch (IOException e) {
e.printStackTrace();
} finally {
raw = null;
}
}
} }
/** /**
* Set the commit message * Set the parents of this commit.
* *
* @param m the commit message * @param newParents
* the entire list of parents for this commit.
*/ */
public void setMessage(final String m) { public void setParentIds(List<? extends AnyObjectId> newParents) {
message = m; parentIds = new ObjectId[newParents.size()];
for (int i = 0; i < newParents.size(); i++)
parentIds[i] = newParents.get(i).copy();
commitId = null;
} }
/** /**
* Persist this commit object * Add a parent onto the end of the parent list.
* *
* @throws IOException * @param additionalParent
* new parent to add onto the end of the current parent list.
*/ */
public void commit() throws IOException { public void addParentId(AnyObjectId additionalParent) {
if (getCommitId() != null) if (parentIds.length == 0) {
throw new IllegalStateException(MessageFormat.format(JGitText.get().commitAlreadyExists, getCommitId())); setParentId(additionalParent);
ObjectInserter odi = objdb.newObjectInserter(); } else {
try { ObjectId[] newParents = new ObjectId[parentIds.length + 1];
ObjectId id = odi.insert(Constants.OBJ_COMMIT, odi.format(this)); for (int i = 0; i < parentIds.length; i++)
odi.flush(); newParents[i] = parentIds[i];
setCommitId(id); newParents[parentIds.length] = additionalParent.copy();
} finally { parentIds = newParents;
odi.release(); commitId = null;
} }
} }
public String toString() { /** @return the complete commit message. */
return "Commit[" + ObjectId.toString(getCommitId()) + " " + getAuthor() + "]"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ public String getMessage() {
return message;
} }
/** /**
* State the encoding for the commit information * Set the commit message.
* *
* @param e * @param newMessage
* the encoding. See {@link Charset} * the commit message. Should not be null.
*/ */
public void setEncoding(String e) { public void setMessage(final String newMessage) {
encoding = Charset.forName(e); message = newMessage;
} }
/** /**
* State the encoding for the commit information * Set the encoding for the commit information
* *
* @param e * @param encodingName
* the encoding. See {@link Charset} * the encoding name. See {@link Charset#forName(String)}.
*/ */
public void setEncoding(Charset e) { public void setEncoding(String encodingName) {
encoding = e; encoding = Charset.forName(encodingName);
} }
/** /**
* @return the encoding used. See {@link Charset} * Set the encoding for the commit information
*
* @param enc
* the encoding to use.
*/ */
public String getEncoding() { public void setEncoding(Charset enc) {
if (encoding != null) encoding = enc;
return encoding.name(); }
else
return null; /** @return the encoding that should be used for the commit message text. */
public Charset getEncoding() {
return encoding;
}
@Override
public String toString() {
StringBuilder r = new StringBuilder();
r.append("Commit");
if (commitId != null)
r.append("[" + commitId.name() + "]");
r.append("={\n");
r.append("tree ");
r.append(treeId != null ? treeId.name() : "NOT_SET");
r.append("\n");
for (ObjectId p : parentIds) {
r.append("parent ");
r.append(p.name());
r.append("\n");
}
r.append("author ");
r.append(author != null ? author.toString() : "NOT_SET");
r.append("\n");
r.append("committer ");
r.append(committer != null ? committer.toString() : "NOT_SET");
r.append("\n");
if (encoding != null && encoding != Constants.CHARSET) {
r.append("encoding ");
r.append(encoding.name());
r.append("\n");
}
r.append("\n");
r.append(message != null ? message : "");
r.append("}");
return r.toString();
} }
} }

18
org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectInserter.java

@ -53,6 +53,7 @@ import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.OutputStreamWriter; import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException; import java.io.UnsupportedEncodingException;
import java.nio.charset.Charset;
import java.security.MessageDigest; import java.security.MessageDigest;
import java.text.MessageFormat; import java.text.MessageFormat;
@ -304,10 +305,7 @@ public abstract class ObjectInserter {
*/ */
public final byte[] format(Commit commit) public final byte[] format(Commit commit)
throws UnsupportedEncodingException { throws UnsupportedEncodingException {
String encoding = commit.getEncoding(); Charset encoding = commit.getEncoding();
if (encoding == null)
encoding = Constants.CHARACTER_ENCODING;
ByteArrayOutputStream os = new ByteArrayOutputStream(); ByteArrayOutputStream os = new ByteArrayOutputStream();
OutputStreamWriter w = new OutputStreamWriter(os, encoding); OutputStreamWriter w = new OutputStreamWriter(os, encoding);
try { try {
@ -316,11 +314,10 @@ public abstract class ObjectInserter {
commit.getTreeId().copyTo(os); commit.getTreeId().copyTo(os);
os.write('\n'); os.write('\n');
ObjectId[] ps = commit.getParentIds(); for (ObjectId p : commit.getParentIds()) {
for (int i = 0; i < ps.length; ++i) {
os.write(hparent); os.write(hparent);
os.write(' '); os.write(' ');
ps[i].copyTo(os); p.copyTo(os);
os.write('\n'); os.write('\n');
} }
@ -336,16 +333,19 @@ public abstract class ObjectInserter {
w.flush(); w.flush();
os.write('\n'); os.write('\n');
if (!encoding.equals(Constants.CHARACTER_ENCODING)) { if (encoding != Constants.CHARSET) {
os.write(hencoding); os.write(hencoding);
os.write(' '); os.write(' ');
os.write(Constants.encodeASCII(encoding)); os.write(Constants.encodeASCII(encoding.name()));
os.write('\n'); os.write('\n');
} }
os.write('\n'); os.write('\n');
if (commit.getMessage() != null) {
w.write(commit.getMessage()); w.write(commit.getMessage());
w.flush(); w.flush();
}
} catch (IOException err) { } catch (IOException err) {
// This should never occur, the only way to get it above is // This should never occur, the only way to get it above is
// for the ByteArrayOutputStream to throw, but it doesn't. // for the ByteArrayOutputStream to throw, but it doesn't.

78
org.eclipse.jgit/src/org/eclipse/jgit/lib/Repository.java

@ -270,84 +270,6 @@ public abstract class Repository {
return getObjectDatabase().open(objectId, typeHint); return getObjectDatabase().open(objectId, typeHint);
} }
/**
* Access a Commit object using a symbolic reference. This reference may
* be a SHA-1 or ref in combination with a number of symbols translating
* from one ref or SHA1-1 to another, such as HEAD^ etc.
*
* @param revstr a reference to a git commit object
* @return a Commit named by the specified string
* @throws IOException for I/O error or unexpected object type.
*
* @see #resolve(String)
* @deprecated Use {@link #resolve(String)} and pass its return value to
* {@link org.eclipse.jgit.revwalk.RevWalk#parseCommit(AnyObjectId)}.
*/
@Deprecated
public Commit mapCommit(final String revstr) throws IOException {
final ObjectId id = resolve(revstr);
return id != null ? mapCommit(id) : null;
}
/**
* Access any type of Git object by id and
*
* @param id
* SHA-1 of object to read
* @param refName optional, only relevant for simple tags
* @return The Git object if found or null
* @throws IOException
* @deprecated Use {@link org.eclipse.jgit.revwalk.RevWalk#parseCommit(AnyObjectId)},
* or {@link org.eclipse.jgit.revwalk.RevWalk#parseTag(AnyObjectId)}.
* To read a tree, use {@link org.eclipse.jgit.treewalk.TreeWalk#addTree(AnyObjectId)}.
* To read a blob, open it with {@link #open(AnyObjectId)}.
*/
@Deprecated
public Object mapObject(final ObjectId id, final String refName) throws IOException {
final ObjectLoader or;
try {
or = open(id);
} catch (MissingObjectException notFound) {
return null;
}
final byte[] raw = or.getCachedBytes();
switch (or.getType()) {
case Constants.OBJ_TREE:
return new Tree(this, id, raw);
case Constants.OBJ_COMMIT:
return new Commit(this, id, raw);
case Constants.OBJ_TAG:
return new Tag(this, id, refName, raw);
case Constants.OBJ_BLOB:
return raw;
default:
throw new IncorrectObjectTypeException(id,
JGitText.get().incorrectObjectType_COMMITnorTREEnorBLOBnorTAG);
}
}
/**
* Access a Commit by SHA'1 id.
* @param id
* @return Commit or null
* @throws IOException for I/O error or unexpected object type.
* @deprecated Use {@link org.eclipse.jgit.revwalk.RevWalk#parseCommit(AnyObjectId)}.
*/
@Deprecated
public Commit mapCommit(final ObjectId id) throws IOException {
final ObjectLoader or;
try {
or = open(id, Constants.OBJ_COMMIT);
} catch (MissingObjectException notFound) {
return null;
}
return new Commit(this, id, or.getCachedBytes());
}
/** /**
* Access a Tree object using a symbolic reference. This reference may * Access a Tree object using a symbolic reference. This reference may
* be a SHA-1 or ref in combination with a number of symbols translating * be a SHA-1 or ref in combination with a number of symbols translating

13
org.eclipse.jgit/src/org/eclipse/jgit/revwalk/RevCommit.java

@ -53,7 +53,6 @@ import java.util.List;
import org.eclipse.jgit.errors.IncorrectObjectTypeException; import org.eclipse.jgit.errors.IncorrectObjectTypeException;
import org.eclipse.jgit.errors.MissingObjectException; import org.eclipse.jgit.errors.MissingObjectException;
import org.eclipse.jgit.lib.AnyObjectId; import org.eclipse.jgit.lib.AnyObjectId;
import org.eclipse.jgit.lib.Commit;
import org.eclipse.jgit.lib.Constants; import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.MutableObjectId; import org.eclipse.jgit.lib.MutableObjectId;
import org.eclipse.jgit.lib.PersonIdent; import org.eclipse.jgit.lib.PersonIdent;
@ -206,18 +205,6 @@ public class RevCommit extends RevObject {
return commitTime; return commitTime;
} }
/**
* Parse this commit buffer for display.
*
* @param walk
* revision walker owning this reference.
* @return parsed commit.
*/
public final Commit asCommit(final RevWalk walk) {
// TODO(spearce) Remove repository when this method dies.
return new Commit(walk.repository, this, buffer);
}
/** /**
* Get a reference to this commit's tree. * Get a reference to this commit's tree.
* *

Loading…
Cancel
Save