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>
final RevCommit... parents) throws Exception {
tick(secDelta);
- final Commit c = new Commit(db);
+ final Commit c = new Commit();
c.setTreeId(tree);
c.setParentIds(parents);
c.setAuthor(new PersonIdent(author, new Date(now)));
if (self == null) {
TestRepository.this.tick(tick);
- final Commit c = new Commit(db);
- c.setParentIds(parents.toArray(new RevCommit[parents.size()]));
+ final Commit c = new Commit();
+ c.setParentIds(parents);
c.setAuthor(new PersonIdent(author, new Date(now)));
c.setCommitter(new PersonIdent(committer, new Date(now)));
c.setMessage(message);
import java.util.Collections;
import java.util.List;
-import org.kohsuke.args4j.Argument;
-import org.kohsuke.args4j.Option;
+import org.eclipse.jgit.errors.IncorrectObjectTypeException;
+import org.eclipse.jgit.errors.MissingObjectException;
import org.eclipse.jgit.errors.NotSupportedException;
import org.eclipse.jgit.errors.TransportException;
-import org.eclipse.jgit.lib.Commit;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.GitIndex;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.TextProgressMonitor;
import org.eclipse.jgit.lib.Tree;
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.transport.FetchResult;
import org.eclipse.jgit.transport.RefSpec;
import org.eclipse.jgit.transport.RemoteConfig;
import org.eclipse.jgit.transport.Transport;
import org.eclipse.jgit.transport.URIish;
+import org.kohsuke.args4j.Argument;
+import org.kohsuke.args4j.Option;
@Command(common = true, usage = "usage_cloneRepositoryIntoNewDir")
class Clone extends AbstractFetchCommand {
u.link(branch.getName());
}
- final Commit commit = db.mapCommit(branch.getObjectId());
+ final RevCommit commit = parseCommit(branch);
final RefUpdate u = db.updateRef(Constants.HEAD);
- u.setNewObjectId(commit.getCommitId());
+ u.setNewObjectId(commit);
u.forceUpdate();
final GitIndex index = new GitIndex(db);
- final Tree tree = commit.getTree();
+ final Tree tree = db.mapTree(commit.getTree());
final WorkDirCheckout co;
co = new WorkDirCheckout(db, db.getWorkTree(), index, tree);
co.checkout();
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;
+ }
}
\ No newline at end of file
import java.util.ListIterator;
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.ObjectWritingException;
import org.eclipse.jgit.lib.Commit;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.ObjectId;
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.ProgressMonitor;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.RefUpdate;
import org.eclipse.jgit.lib.RefWriter;
import org.eclipse.jgit.lib.TextProgressMonitor;
-import org.eclipse.jgit.lib.Tree;
import org.eclipse.jgit.pgm.CLIText;
import org.eclipse.jgit.pgm.TextBuiltin;
import org.eclipse.jgit.revwalk.RevWalk;
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.
}
pm.beginTask("Rewriting commits", queue.size());
- final ObjectWriter ow = new ObjectWriter(db);
- final ObjectId emptyTree = ow.writeTree(new Tree(db));
+ final ObjectInserter oi = db.newObjectInserter();
+ final ObjectId emptyTree = oi.insert(Constants.OBJ_TREE, new byte[] {});
final PersonIdent me = new PersonIdent("jgit rebuild-commitgraph",
"rebuild-commitgraph@localhost");
while (!queue.isEmpty()) {
}
}
- final Commit newc = new Commit(db);
+ final Commit newc = new Commit();
newc.setTreeId(emptyTree);
newc.setAuthor(new PersonIdent(me, new Date(t.commitTime)));
newc.setCommitter(newc.getAuthor());
newc.setParentIds(newParents);
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);
pm.update(1);
}
}
+ oi.flush();
+ oi.release();
pm.endTask();
}
File workDir = db.getWorkTree();
if (workDir != null) {
WorkDirCheckout workDirCheckout = new WorkDirCheckout(db,
- workDir, db.mapCommit(Constants.HEAD).getTree(),
- db.getIndex(), db.mapCommit(branchName).getTree());
+ workDir, db.mapTree(Constants.HEAD),
+ db.getIndex(), db.mapTree(branchName));
workDirCheckout.setFailOnConflict(true);
try {
workDirCheckout.checkout();
private void commit(final Tree t, String commitMsg, PersonIdent author,
PersonIdent committer) throws IOException {
- final Commit commit = new Commit(db);
+ final Commit commit = new Commit();
commit.setAuthor(author);
commit.setCommitter(committer);
commit.setMessage(commitMsg);
- commit.setTree(t);
+ commit.setTreeId(t.getTreeId());
ObjectWriter writer = new ObjectWriter(db);
commit.setCommitId(writer.writeCommit(commit));
private ObjectId commit(final ObjectInserter odi, final DirCache treeB,
final ObjectId[] parentIds) throws Exception {
- final Commit c = new Commit(db);
+ final Commit c = new Commit();
c.setTreeId(treeB.writeTree(odi));
c.setAuthor(new PersonIdent("A U Thor", "a.u.thor", 1L, 0));
c.setCommitter(c.getAuthor());
private ObjectId commit(final ObjectInserter odi, final DirCache treeB,
final ObjectId[] parentIds) throws Exception {
- final Commit c = new Commit(db);
+ final Commit c = new Commit();
c.setTreeId(treeB.writeTree(odi));
c.setAuthor(new PersonIdent("A U Thor", "a.u.thor", 1L, 0));
c.setCommitter(c.getAuthor());
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
+import java.io.UnsupportedEncodingException;
import org.eclipse.jgit.JGitText;
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.Config;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.FileTreeEntry;
import org.eclipse.jgit.lib.ObjectDatabase;
import org.eclipse.jgit.lib.ObjectId;
+import org.eclipse.jgit.lib.ObjectInserter;
import org.eclipse.jgit.lib.ObjectWriter;
import org.eclipse.jgit.lib.PersonIdent;
import org.eclipse.jgit.lib.RefUpdate;
import org.eclipse.jgit.lib.Tree;
import org.eclipse.jgit.lib.TreeEntry;
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 void test001_Initalize() {
assertEqualsPath(theDir.getParentFile(), r.getWorkTree());
assertEqualsPath(indexFile, r.getIndexFile());
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
// locked via the alternate object directories on Windows.
r.close();
assertEquals(ObjectId.fromString("00b1f73724f493096d1ffa0b0f1f1482dbb8c936"),
t.getTreeId());
- final Commit c = new Commit(db);
+ final Commit c = new Commit();
c.setAuthor(new PersonIdent(author, 1154236443000L, -4 * 60));
c.setCommitter(new PersonIdent(committer, 1154236443000L, -4 * 60));
c.setMessage("A Commit\n");
- c.setTree(t);
+ c.setTreeId(t.getTreeId());
assertEquals(t.getTreeId(), c.getTreeId());
- c.commit();
+
+ insertCommit(c);
+
final ObjectId cmtid = ObjectId.fromString(
"803aec4aba175e8ab1d666873c984c0308179099");
assertEquals(cmtid, c.getCommitId());
}
// Verify we can read it.
- final Commit c2 = db.mapCommit(cmtid);
+ RevCommit c2 = parseCommit(c.getCommitId());
assertNotNull(c2);
- assertEquals(c.getMessage(), c2.getMessage());
- assertEquals(c.getTreeId(), c2.getTreeId());
- assertEquals(c.getAuthor(), c2.getAuthor());
- assertEquals(c.getCommitter(), c2.getCommitter());
+ assertEquals(c.getMessage(), c2.getFullMessage());
+ assertEquals(c.getTreeId(), c2.getTree());
+ assertEquals(c.getAuthor(), c2.getAuthorIdent());
+ assertEquals(c.getCommitter(), c2.getCommitterIdent());
}
public void test012_SubtreeExternalSorting() throws IOException {
final Tree almostEmptyTree = new Tree(db);
almostEmptyTree.addEntry(new FileTreeEntry(almostEmptyTree, emptyId, "empty".getBytes(), false));
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.setCommitter(new PersonIdent(author, 1154236443000L, -2 * 60));
almostEmptyCommit.setMessage("test022\n");
almostEmptyCommit.setTreeId(almostEmptyTreeId);
- ObjectId almostEmptyCommitId = new ObjectWriter(db).writeCommit(almostEmptyCommit);
+ ObjectId almostEmptyCommitId = insertCommit(almostEmptyCommit);
final Tag t = new Tag(db);
t.setObjId(almostEmptyCommitId);
t.setType("commit");
final Tree almostEmptyTree = new Tree(db);
almostEmptyTree.addEntry(new FileTreeEntry(almostEmptyTree, emptyId, "empty".getBytes(), false));
final ObjectId almostEmptyTreeId = new ObjectWriter(db).writeTree(almostEmptyTree);
- Commit commit = new Commit(db);
+ Commit commit = new Commit();
commit.setTreeId(almostEmptyTreeId);
commit.setAuthor(new PersonIdent("Joe H\u00e4cker","joe@example.com",4294967295000L,60));
commit.setCommitter(new PersonIdent("Joe Hacker","joe2@example.com",4294967295000L,60));
commit.setEncoding("UTF-8");
commit.setMessage("\u00dcbergeeks");
- ObjectId cid = new ObjectWriter(db).writeCommit(commit);
+ ObjectId cid = insertCommit(commit);
assertEquals("4680908112778718f37e686cbebcc912730b3154", cid.name());
- Commit loadedCommit = db.mapCommit(cid);
- assertNotSame(loadedCommit, commit);
- assertEquals(commit.getMessage(), loadedCommit.getMessage());
+
+ RevCommit loadedCommit = parseCommit(cid);
+ assertEquals(commit.getMessage(), loadedCommit.getFullMessage());
}
public void test024_createCommitNonAscii() throws IOException {
final Tree almostEmptyTree = new Tree(db);
almostEmptyTree.addEntry(new FileTreeEntry(almostEmptyTree, emptyId, "empty".getBytes(), false));
final ObjectId almostEmptyTreeId = new ObjectWriter(db).writeTree(almostEmptyTree);
- Commit commit = new Commit(db);
+ Commit commit = new Commit();
commit.setTreeId(almostEmptyTreeId);
commit.setAuthor(new PersonIdent("Joe H\u00e4cker","joe@example.com",4294967295000L,60));
commit.setCommitter(new PersonIdent("Joe Hacker","joe2@example.com",4294967295000L,60));
commit.setEncoding("ISO-8859-1");
commit.setMessage("\u00dcbergeeks");
- ObjectId cid = new ObjectWriter(db).writeCommit(commit);
+ ObjectId cid = insertCommit(commit);
assertEquals("2979b39d385014b33287054b87f77bcb3ecb5ebf", cid.name());
}
assertEquals(ObjectId.fromString("00b1f73724f493096d1ffa0b0f1f1482dbb8c936"),
t.getTreeId());
- final Commit c1 = new Commit(db);
+ final Commit c1 = new Commit();
c1.setAuthor(new PersonIdent(author, 1154236443000L, -4 * 60));
c1.setCommitter(new PersonIdent(committer, 1154236443000L, -4 * 60));
c1.setMessage("A Commit\n");
- c1.setTree(t);
+ c1.setTreeId(t.getTreeId());
assertEquals(t.getTreeId(), c1.getTreeId());
- c1.commit();
+ insertCommit(c1);
final ObjectId cmtid1 = ObjectId.fromString(
"803aec4aba175e8ab1d666873c984c0308179099");
assertEquals(cmtid1, c1.getCommitId());
- final Commit c2 = new Commit(db);
+ final Commit c2 = new Commit();
c2.setAuthor(new PersonIdent(author, 1154236443000L, -4 * 60));
c2.setCommitter(new PersonIdent(committer, 1154236443000L, -4 * 60));
c2.setMessage("A Commit 2\n");
- c2.setTree(t);
+ c2.setTreeId(t.getTreeId());
assertEquals(t.getTreeId(), c2.getTreeId());
- c2.setParentIds(new ObjectId[] { c1.getCommitId() } );
- c2.commit();
+ c2.setParentIds(c1.getCommitId());
+ insertCommit(c2);
final ObjectId cmtid2 = ObjectId.fromString(
"95d068687c91c5c044fb8c77c5154d5247901553");
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
- assertEquals(c2.getAuthor(), rm2.getAuthor());
- assertEquals(c2.getCommitId(), rm2.getCommitId());
- assertEquals(c2.getMessage(), rm2.getMessage());
- assertEquals(c2.getTree().getTreeId(), rm2.getTree().getTreeId());
- assertEquals(1, rm2.getParentIds().length);
- assertEquals(c1.getCommitId(), rm2.getParentIds()[0]);
-
- final Commit c3 = new Commit(db);
+ assertEquals(c2.getAuthor(), rm2.getAuthorIdent());
+ assertEquals(c2.getCommitId(), rm2.getId());
+ assertEquals(c2.getMessage(), rm2.getFullMessage());
+ assertEquals(c2.getTreeId(), rm2.getTree().getId());
+ assertEquals(1, rm2.getParentCount());
+ assertEquals(c1.getCommitId(), rm2.getParent(0));
+
+ final Commit c3 = new Commit();
c3.setAuthor(new PersonIdent(author, 1154236443000L, -4 * 60));
c3.setCommitter(new PersonIdent(committer, 1154236443000L, -4 * 60));
c3.setMessage("A Commit 3\n");
- c3.setTree(t);
+ c3.setTreeId(t.getTreeId());
assertEquals(t.getTreeId(), c3.getTreeId());
- c3.setParentIds(new ObjectId[] { c1.getCommitId(), c2.getCommitId() });
- c3.commit();
+ c3.setParentIds(c1.getCommitId(), c2.getCommitId());
+ insertCommit(c3);
final ObjectId cmtid3 = ObjectId.fromString(
"ce6e1ce48fbeeb15a83f628dc8dc2debefa066f4");
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
- assertEquals(c3.getAuthor(), rm3.getAuthor());
- assertEquals(c3.getCommitId(), rm3.getCommitId());
- assertEquals(c3.getMessage(), rm3.getMessage());
- assertEquals(c3.getTree().getTreeId(), rm3.getTree().getTreeId());
- assertEquals(2, rm3.getParentIds().length);
- assertEquals(c1.getCommitId(), rm3.getParentIds()[0]);
- assertEquals(c2.getCommitId(), rm3.getParentIds()[1]);
-
- final Commit c4 = new Commit(db);
+ assertEquals(c3.getAuthor(), rm3.getAuthorIdent());
+ assertEquals(c3.getCommitId(), rm3.getId());
+ assertEquals(c3.getMessage(), rm3.getFullMessage());
+ assertEquals(c3.getTreeId(), rm3.getTree().getId());
+ assertEquals(2, rm3.getParentCount());
+ assertEquals(c1.getCommitId(), rm3.getParent(0));
+ assertEquals(c2.getCommitId(), rm3.getParent(1));
+
+ final Commit c4 = new Commit();
c4.setAuthor(new PersonIdent(author, 1154236443000L, -4 * 60));
c4.setCommitter(new PersonIdent(committer, 1154236443000L, -4 * 60));
c4.setMessage("A Commit 4\n");
- c4.setTree(t);
+ c4.setTreeId(t.getTreeId());
assertEquals(t.getTreeId(), c3.getTreeId());
- c4.setParentIds(new ObjectId[] { c1.getCommitId(), c2.getCommitId(), c3.getCommitId() });
- c4.commit();
+ c4.setParentIds(c1.getCommitId(), c2.getCommitId(), c3.getCommitId());
+ insertCommit(c4);
final ObjectId cmtid4 = ObjectId.fromString(
"d1fca9fe3fef54e5212eb67902c8ed3e79736e27");
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
- assertEquals(c4.getAuthor(), rm4.getAuthor());
- assertEquals(c4.getCommitId(), rm4.getCommitId());
- assertEquals(c4.getMessage(), rm4.getMessage());
- assertEquals(c4.getTree().getTreeId(), rm4.getTree().getTreeId());
- assertEquals(3, rm4.getParentIds().length);
- assertEquals(c1.getCommitId(), rm4.getParentIds()[0]);
- assertEquals(c2.getCommitId(), rm4.getParentIds()[1]);
- assertEquals(c3.getCommitId(), rm4.getParentIds()[2]);
+ assertEquals(c4.getAuthor(), rm4.getAuthorIdent());
+ assertEquals(c4.getCommitId(), rm4.getId());
+ assertEquals(c4.getMessage(), rm4.getFullMessage());
+ assertEquals(c4.getTreeId(), rm4.getTree().getId());
+ assertEquals(3, rm4.getParentCount());
+ assertEquals(c1.getCommitId(), rm4.getParent(0));
+ assertEquals(c2.getCommitId(), rm4.getParent(1));
+ assertEquals(c3.getCommitId(), rm4.getParent(2));
}
public void test027_UnpackedRefHigherPriorityThanPacked() throws IOException {
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() {
File relCwd = new File(".");
File absCwd = relCwd.getAbsoluteFile();
}
+ 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.
* <p>
ObjectId indexTreeId = index.writeTree(odi);
// Create a Commit object, populate it and write it
- Commit commit = new Commit(repo);
+ Commit commit = new Commit();
commit.setCommitter(committer);
commit.setAuthor(author);
commit.setMessage(message);
- commit.setParentIds(parents.toArray(new ObjectId[] {}));
+ commit.setParentIds(parents);
commit.setTreeId(indexTreeId);
ObjectId commitId = odi.insert(Constants.OBJ_COMMIT, odi
.format(commit));
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.ObjectIdRef;
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.Result;
import org.eclipse.jgit.lib.Repository;
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.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevWalk;
File workDir = repo.getWorkTree();
if (workDir != null) {
WorkDirCheckout workDirCheckout = new WorkDirCheckout(repo,
- workDir, headCommit.asCommit(revWalk).getTree(), index,
- newHeadCommit.asCommit(revWalk).getTree());
+ workDir, repo.mapTree(headCommit.getTree()), index,
+ repo.mapTree(newHeadCommit.getTree()));
workDirCheckout.setFailOnConflict(true);
try {
workDirCheckout.checkout();
import org.eclipse.jgit.JGitText;
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.util.IO;
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 {
/**
- * The constructor from a byte array
+ * Parse a configuration from a byte array.
*
* @param base
* the base configuration file
}
/**
- * The constructor from object identifier
+ * Load a configuration file from a blob.
*
* @param base
* the base configuration file
- * @param r
+ * @param db
* the repository
* @param objectId
* the object identifier
* @throws ConfigInvalidException
* the blob is not a valid configuration format.
*/
- public BlobBasedConfig(Config base, final Repository r,
- final ObjectId objectId) throws IOException, ConfigInvalidException {
- super(base);
- ObjectLoader loader = r.open(objectId, Constants.OBJ_BLOB);
- fromText(RawParseUtils.decode(loader.getCachedBytes()));
+ public BlobBasedConfig(Config base, Repository db, AnyObjectId objectId)
+ throws IOException, ConfigInvalidException {
+ this(base, read(db, objectId));
+ }
+
+ 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
* the base configuration file
- * @param commit
- * the commit that contains the object
+ * @param db
+ * the repository containing the objects.
+ * @param treeish
+ * the tree (or commit) that contains the object
* @param path
- * the path within the tree of the commit
+ * the path within the tree
* @throws FileNotFoundException
* the path does not exist in the commit's tree.
* @throws IOException
* @throws ConfigInvalidException
* the blob is not a valid configuration format.
*/
- public BlobBasedConfig(Config base, final Commit commit, final String path)
- throws FileNotFoundException, IOException, ConfigInvalidException {
- super(base);
- final ObjectId treeId = commit.getTreeId();
- final Repository r = commit.getRepository();
- final TreeWalk tree = TreeWalk.forPath(r, path, treeId);
- if (tree == null)
- throw new FileNotFoundException(MessageFormat.format(JGitText.get().entryNotFoundByPath, path));
- final ObjectId blobId = tree.getObjectId(0);
- ObjectLoader loader = r.open(blobId,Constants.OBJ_BLOB);
- fromText(RawParseUtils.decode(loader.getCachedBytes()));
+ public BlobBasedConfig(Config base, Repository db, AnyObjectId treeish,
+ String path) throws FileNotFoundException, IOException,
+ ConfigInvalidException {
+ this(base, read(db, treeish, path));
+ }
+
+ 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)
+ throw new FileNotFoundException(MessageFormat.format(JGitText
+ .get().entryNotFoundByPath, path));
+ return read(or, tree.getObjectId(0));
+ } 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();
}
}
package org.eclipse.jgit.lib;
-import java.io.ByteArrayInputStream;
-import java.io.DataInputStream;
-import java.io.IOException;
import java.nio.charset.Charset;
-import java.text.MessageFormat;
-
-import org.eclipse.jgit.JGitText;
-import org.eclipse.jgit.errors.CorruptObjectException;
-import org.eclipse.jgit.errors.MissingObjectException;
+import java.util.List;
/**
- * Instances of this class represent a Commit object. It represents a snapshot
- * in a Git repository, who created it and when.
+ * Mutable builder to construct a commit recording the state of a project.
+ *
+ * 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 final Repository objdb;
-
private ObjectId commitId;
private ObjectId treeId;
private String message;
- private Tree treeObj;
-
- private byte[] raw;
-
private Charset encoding;
- /**
- * Create an empty commit object. More information must be fed to this
- * object to make it useful.
- *
- * @param db
- * The repository with which to associate it.
- */
- public Commit(final Repository db) {
- objdb = db;
+ /** Initialize an empty commit. */
+ public Commit() {
parentIds = EMPTY_OBJECTID_LIST;
+ encoding = Constants.CHARSET;
}
- /**
- * 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;
- this.raw = raw;
- }
-
- /**
- * @return get repository for the commit
- */
- public Repository getRepository() {
- return objdb;
- }
-
- /**
- * @return The commit object id
- */
+ /** @return this commit's object id. */
public ObjectId getCommitId() {
return commitId;
}
/**
- * Set the id of this object.
+ * Set the id of this commit object.
*
* @param id
* the id that we calculated for this object.
commitId = id;
}
+ /** @return id of the root tree listing this commit's snapshot. */
public ObjectId getTreeId() {
return treeId;
}
* Set the tree id for this commit object
*
* @param id
+ * the tree identity.
*/
- public void setTreeId(final ObjectId id) {
- if (treeId==null || !treeId.equals(id)) {
- treeObj = 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;
+ public void setTreeId(AnyObjectId id) {
+ treeId = id.copy();
+ commitId = null;
}
- /**
- * @return the author and authoring time for this commit
- */
+ /** @return the author of this commit (who wrote it). */
public PersonIdent getAuthor() {
- decode();
return author;
}
/**
- * Set the author and authoring time for this commit
- * @param a
+ * Set the author (name, email address, and date) of who wrote the commit.
+ *
+ * @param newAuthor
+ * the new author. Should not be null.
*/
- public void setAuthor(final PersonIdent a) {
- author = a;
+ public void setAuthor(PersonIdent newAuthor) {
+ 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() {
- decode();
return committer;
}
/**
* 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) {
- committer = c;
+ public void setCommitter(PersonIdent newCommitter) {
+ committer = newCommitter;
+ commitId = null;
}
- /**
- * @return the object ids of this commit
- */
+ /** @return the ancestors of this commit. Never null. */
public ObjectId[] getParentIds() {
return parentIds;
}
/**
- * @return the commit message
+ * Set the parent of this commit.
+ *
+ * @param newParent
+ * the single parent for the commit.
*/
- public String getMessage() {
- decode();
- return message;
+ public void setParentId(AnyObjectId newParent) {
+ parentIds = new ObjectId[] { newParent.copy() };
+ commitId = null;
}
/**
- * Set the parents of this commit
- * @param parentIds
+ * Set the parents of this commit.
+ *
+ * @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) {
- this.parentIds = new ObjectId[parentIds.length];
- for (int i=0; i<parentIds.length; ++i)
- this.parentIds[i] = parentIds[i];
+ public void setParentIds(AnyObjectId parent1, AnyObjectId parent2) {
+ parentIds = new ObjectId[] { parent1.copy(), parent2.copy() };
+ commitId = null;
}
- private void decode() {
- // FIXME: handle I/O errors
- if (raw != null) {
- try {
- DataInputStream br = new DataInputStream(new ByteArrayInputStream(raw));
- String n = br.readLine();
- if (n == null || !n.startsWith("tree ")) {
- throw new CorruptObjectException(commitId, JGitText.get().corruptObjectNotree);
- }
- while ((n = br.readLine()) != null && n.startsWith("parent ")) {
- // empty body
- }
- 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 parents of this commit.
+ *
+ * @param newParents
+ * the entire list of parents for this commit.
+ */
+ public void setParentIds(ObjectId... newParents) {
+ parentIds = new ObjectId[newParents.length];
+ for (int i = 0; i < newParents.length; i++)
+ parentIds[i] = newParents[i].copy();
+ commitId = 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) {
- message = m;
+ public void setParentIds(List<? extends AnyObjectId> newParents) {
+ 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 {
- if (getCommitId() != null)
- throw new IllegalStateException(MessageFormat.format(JGitText.get().commitAlreadyExists, getCommitId()));
- ObjectInserter odi = objdb.newObjectInserter();
- try {
- ObjectId id = odi.insert(Constants.OBJ_COMMIT, odi.format(this));
- odi.flush();
- setCommitId(id);
- } finally {
- odi.release();
+ public void addParentId(AnyObjectId additionalParent) {
+ if (parentIds.length == 0) {
+ setParentId(additionalParent);
+ } else {
+ ObjectId[] newParents = new ObjectId[parentIds.length + 1];
+ for (int i = 0; i < parentIds.length; i++)
+ newParents[i] = parentIds[i];
+ newParents[parentIds.length] = additionalParent.copy();
+ parentIds = newParents;
+ commitId = null;
}
}
- public String toString() {
- return "Commit[" + ObjectId.toString(getCommitId()) + " " + getAuthor() + "]"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ /** @return the complete commit message. */
+ public String getMessage() {
+ return message;
}
/**
- * State the encoding for the commit information
+ * Set the commit message.
*
- * @param e
- * the encoding. See {@link Charset}
+ * @param newMessage
+ * the commit message. Should not be null.
*/
- public void setEncoding(String e) {
- encoding = Charset.forName(e);
+ public void setMessage(final String newMessage) {
+ message = newMessage;
}
/**
- * State the encoding for the commit information
+ * Set the encoding for the commit information
*
- * @param e
- * the encoding. See {@link Charset}
+ * @param encodingName
+ * the encoding name. See {@link Charset#forName(String)}.
*/
- public void setEncoding(Charset e) {
- encoding = e;
+ public void setEncoding(String encodingName) {
+ 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() {
- if (encoding != null)
- return encoding.name();
- else
- return null;
+ public void setEncoding(Charset enc) {
+ encoding = enc;
+ }
+
+ /** @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();
}
}
import java.io.InputStream;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
+import java.nio.charset.Charset;
import java.security.MessageDigest;
import java.text.MessageFormat;
*/
public final byte[] format(Commit commit)
throws UnsupportedEncodingException {
- String encoding = commit.getEncoding();
- if (encoding == null)
- encoding = Constants.CHARACTER_ENCODING;
-
+ Charset encoding = commit.getEncoding();
ByteArrayOutputStream os = new ByteArrayOutputStream();
OutputStreamWriter w = new OutputStreamWriter(os, encoding);
try {
commit.getTreeId().copyTo(os);
os.write('\n');
- ObjectId[] ps = commit.getParentIds();
- for (int i = 0; i < ps.length; ++i) {
+ for (ObjectId p : commit.getParentIds()) {
os.write(hparent);
os.write(' ');
- ps[i].copyTo(os);
+ p.copyTo(os);
os.write('\n');
}
w.flush();
os.write('\n');
- if (!encoding.equals(Constants.CHARACTER_ENCODING)) {
+ if (encoding != Constants.CHARSET) {
os.write(hencoding);
os.write(' ');
- os.write(Constants.encodeASCII(encoding));
+ os.write(Constants.encodeASCII(encoding.name()));
os.write('\n');
}
os.write('\n');
- w.write(commit.getMessage());
- w.flush();
+
+ if (commit.getMessage() != null) {
+ w.write(commit.getMessage());
+ w.flush();
+ }
} catch (IOException err) {
// This should never occur, the only way to get it above is
// for the ByteArrayOutputStream to throw, but it doesn't.
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
* be a SHA-1 or ref in combination with a number of symbols translating
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.Constants;
import org.eclipse.jgit.lib.MutableObjectId;
import org.eclipse.jgit.lib.PersonIdent;
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.
*