123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888 |
- /*
- * Copyright (C) 2009-2010, Google Inc.
- * and other copyright owners as documented in the project's IP log.
- *
- * This program and the accompanying materials are made available
- * under the terms of the Eclipse Distribution License v1.0 which
- * accompanies this distribution, is reproduced below, and is
- * available at http://www.eclipse.org/org/documents/edl-v10.php
- *
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or
- * without modification, are permitted provided that the following
- * conditions are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * - Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials provided
- * with the distribution.
- *
- * - Neither the name of the Eclipse Foundation, Inc. nor the
- * names of its contributors may be used to endorse or promote
- * products derived from this software without specific prior
- * written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
- * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
- * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
- package org.eclipse.jgit.junit;
-
- import static org.junit.Assert.assertEquals;
- import static org.junit.Assert.fail;
-
- import java.io.File;
- import java.io.FileOutputStream;
- import java.io.IOException;
- import java.io.OutputStream;
- import java.security.MessageDigest;
- import java.util.ArrayList;
- import java.util.Collections;
- import java.util.Date;
- import java.util.HashSet;
- import java.util.List;
- import java.util.Set;
-
- import org.eclipse.jgit.dircache.DirCache;
- import org.eclipse.jgit.dircache.DirCacheBuilder;
- import org.eclipse.jgit.dircache.DirCacheEditor;
- import org.eclipse.jgit.dircache.DirCacheEditor.DeletePath;
- import org.eclipse.jgit.dircache.DirCacheEditor.DeleteTree;
- import org.eclipse.jgit.dircache.DirCacheEditor.PathEdit;
- import org.eclipse.jgit.dircache.DirCacheEntry;
- import org.eclipse.jgit.errors.IncorrectObjectTypeException;
- import org.eclipse.jgit.errors.MissingObjectException;
- import org.eclipse.jgit.errors.ObjectWritingException;
- import org.eclipse.jgit.lib.AnyObjectId;
- import org.eclipse.jgit.lib.Constants;
- import org.eclipse.jgit.lib.FileMode;
- import org.eclipse.jgit.lib.NullProgressMonitor;
- import org.eclipse.jgit.lib.ObjectChecker;
- import org.eclipse.jgit.lib.ObjectId;
- import org.eclipse.jgit.lib.ObjectInserter;
- import org.eclipse.jgit.lib.PersonIdent;
- import org.eclipse.jgit.lib.Ref;
- import org.eclipse.jgit.lib.RefUpdate;
- import org.eclipse.jgit.lib.RefWriter;
- import org.eclipse.jgit.lib.Repository;
- import org.eclipse.jgit.lib.TagBuilder;
- import org.eclipse.jgit.revwalk.ObjectWalk;
- import org.eclipse.jgit.revwalk.RevBlob;
- import org.eclipse.jgit.revwalk.RevCommit;
- import org.eclipse.jgit.revwalk.RevObject;
- import org.eclipse.jgit.revwalk.RevTag;
- import org.eclipse.jgit.revwalk.RevTree;
- import org.eclipse.jgit.revwalk.RevWalk;
- import org.eclipse.jgit.storage.file.FileRepository;
- import org.eclipse.jgit.storage.file.LockFile;
- import org.eclipse.jgit.storage.file.ObjectDirectory;
- import org.eclipse.jgit.storage.file.PackFile;
- import org.eclipse.jgit.storage.file.PackIndex.MutableEntry;
- import org.eclipse.jgit.storage.pack.PackWriter;
- import org.eclipse.jgit.treewalk.TreeWalk;
- import org.eclipse.jgit.treewalk.filter.PathFilterGroup;
- import org.eclipse.jgit.util.FileUtils;
- import org.eclipse.jgit.util.io.SafeBufferedOutputStream;
-
- /**
- * Wrapper to make creating test data easier.
- *
- * @param <R>
- * type of Repository the test data is stored on.
- */
- public class TestRepository<R extends Repository> {
- private static final PersonIdent author;
-
- private static final PersonIdent committer;
-
- static {
- final MockSystemReader m = new MockSystemReader();
- final long now = m.getCurrentTime();
- final int tz = m.getTimezone(now);
-
- final String an = "J. Author";
- final String ae = "jauthor@example.com";
- author = new PersonIdent(an, ae, now, tz);
-
- final String cn = "J. Committer";
- final String ce = "jcommitter@example.com";
- committer = new PersonIdent(cn, ce, now, tz);
- }
-
- private final R db;
-
- private final RevWalk pool;
-
- private final ObjectInserter inserter;
-
- private long now;
-
- /**
- * Wrap a repository with test building tools.
- *
- * @param db
- * the test repository to write into.
- * @throws IOException
- */
- public TestRepository(R db) throws IOException {
- this(db, new RevWalk(db));
- }
-
- /**
- * Wrap a repository with test building tools.
- *
- * @param db
- * the test repository to write into.
- * @param rw
- * the RevObject pool to use for object lookup.
- * @throws IOException
- */
- public TestRepository(R db, RevWalk rw) throws IOException {
- this.db = db;
- this.pool = rw;
- this.inserter = db.newObjectInserter();
- this.now = 1236977987000L;
- }
-
- /** @return the repository this helper class operates against. */
- public R getRepository() {
- return db;
- }
-
- /** @return get the RevWalk pool all objects are allocated through. */
- public RevWalk getRevWalk() {
- return pool;
- }
-
- /** @return current time adjusted by {@link #tick(int)}. */
- public Date getClock() {
- return new Date(now);
- }
-
- /**
- * Adjust the current time that will used by the next commit.
- *
- * @param secDelta
- * number of seconds to add to the current time.
- */
- public void tick(final int secDelta) {
- now += secDelta * 1000L;
- }
-
- /**
- * Set the author and committer using {@link #getClock()}.
- *
- * @param c
- * the commit builder to store.
- */
- public void setAuthorAndCommitter(org.eclipse.jgit.lib.CommitBuilder c) {
- c.setAuthor(new PersonIdent(author, new Date(now)));
- c.setCommitter(new PersonIdent(committer, new Date(now)));
- }
-
- /**
- * Create a new blob object in the repository.
- *
- * @param content
- * file content, will be UTF-8 encoded.
- * @return reference to the blob.
- * @throws Exception
- */
- public RevBlob blob(final String content) throws Exception {
- return blob(content.getBytes("UTF-8"));
- }
-
- /**
- * Create a new blob object in the repository.
- *
- * @param content
- * binary file content.
- * @return reference to the blob.
- * @throws Exception
- */
- public RevBlob blob(final byte[] content) throws Exception {
- ObjectId id;
- try {
- id = inserter.insert(Constants.OBJ_BLOB, content);
- inserter.flush();
- } finally {
- inserter.release();
- }
- return pool.lookupBlob(id);
- }
-
- /**
- * Construct a regular file mode tree entry.
- *
- * @param path
- * path of the file.
- * @param blob
- * a blob, previously constructed in the repository.
- * @return the entry.
- * @throws Exception
- */
- public DirCacheEntry file(final String path, final RevBlob blob)
- throws Exception {
- final DirCacheEntry e = new DirCacheEntry(path);
- e.setFileMode(FileMode.REGULAR_FILE);
- e.setObjectId(blob);
- return e;
- }
-
- /**
- * Construct a tree from a specific listing of file entries.
- *
- * @param entries
- * the files to include in the tree. The collection does not need
- * to be sorted properly and may be empty.
- * @return reference to the tree specified by the entry list.
- * @throws Exception
- */
- public RevTree tree(final DirCacheEntry... entries) throws Exception {
- final DirCache dc = DirCache.newInCore();
- final DirCacheBuilder b = dc.builder();
- for (final DirCacheEntry e : entries)
- b.add(e);
- b.finish();
- ObjectId root;
- try {
- root = dc.writeTree(inserter);
- inserter.flush();
- } finally {
- inserter.release();
- }
- return pool.lookupTree(root);
- }
-
- /**
- * Lookup an entry stored in a tree, failing if not present.
- *
- * @param tree
- * the tree to search.
- * @param path
- * the path to find the entry of.
- * @return the parsed object entry at this path, never null.
- * @throws Exception
- */
- public RevObject get(final RevTree tree, final String path)
- throws Exception {
- final TreeWalk tw = new TreeWalk(pool.getObjectReader());
- tw.setFilter(PathFilterGroup.createFromStrings(Collections
- .singleton(path)));
- tw.reset(tree);
- while (tw.next()) {
- if (tw.isSubtree() && !path.equals(tw.getPathString())) {
- tw.enterSubtree();
- continue;
- }
- final ObjectId entid = tw.getObjectId(0);
- final FileMode entmode = tw.getFileMode(0);
- return pool.lookupAny(entid, entmode.getObjectType());
- }
- fail("Can't find " + path + " in tree " + tree.name());
- return null; // never reached.
- }
-
- /**
- * Create a new commit.
- * <p>
- * See {@link #commit(int, RevTree, RevCommit...)}. The tree is the empty
- * tree (no files or subdirectories).
- *
- * @param parents
- * zero or more parents of the commit.
- * @return the new commit.
- * @throws Exception
- */
- public RevCommit commit(final RevCommit... parents) throws Exception {
- return commit(1, tree(), parents);
- }
-
- /**
- * Create a new commit.
- * <p>
- * See {@link #commit(int, RevTree, RevCommit...)}.
- *
- * @param tree
- * the root tree for the commit.
- * @param parents
- * zero or more parents of the commit.
- * @return the new commit.
- * @throws Exception
- */
- public RevCommit commit(final RevTree tree, final RevCommit... parents)
- throws Exception {
- return commit(1, tree, parents);
- }
-
- /**
- * Create a new commit.
- * <p>
- * See {@link #commit(int, RevTree, RevCommit...)}. The tree is the empty
- * tree (no files or subdirectories).
- *
- * @param secDelta
- * number of seconds to advance {@link #tick(int)} by.
- * @param parents
- * zero or more parents of the commit.
- * @return the new commit.
- * @throws Exception
- */
- public RevCommit commit(final int secDelta, final RevCommit... parents)
- throws Exception {
- return commit(secDelta, tree(), parents);
- }
-
- /**
- * Create a new commit.
- * <p>
- * The author and committer identities are stored using the current
- * timestamp, after being incremented by {@code secDelta}. The message body
- * is empty.
- *
- * @param secDelta
- * number of seconds to advance {@link #tick(int)} by.
- * @param tree
- * the root tree for the commit.
- * @param parents
- * zero or more parents of the commit.
- * @return the new commit.
- * @throws Exception
- */
- public RevCommit commit(final int secDelta, final RevTree tree,
- final RevCommit... parents) throws Exception {
- tick(secDelta);
-
- final org.eclipse.jgit.lib.CommitBuilder c;
-
- c = new org.eclipse.jgit.lib.CommitBuilder();
- c.setTreeId(tree);
- c.setParentIds(parents);
- c.setAuthor(new PersonIdent(author, new Date(now)));
- c.setCommitter(new PersonIdent(committer, new Date(now)));
- c.setMessage("");
- ObjectId id;
- try {
- id = inserter.insert(c);
- inserter.flush();
- } finally {
- inserter.release();
- }
- return pool.lookupCommit(id);
- }
-
- /** @return a new commit builder. */
- public CommitBuilder commit() {
- return new CommitBuilder();
- }
-
- /**
- * Construct an annotated tag object pointing at another object.
- * <p>
- * The tagger is the committer identity, at the current time as specified by
- * {@link #tick(int)}. The time is not increased.
- * <p>
- * The tag message is empty.
- *
- * @param name
- * name of the tag. Traditionally a tag name should not start
- * with {@code refs/tags/}.
- * @param dst
- * object the tag should be pointed at.
- * @return the annotated tag object.
- * @throws Exception
- */
- public RevTag tag(final String name, final RevObject dst) throws Exception {
- final TagBuilder t = new TagBuilder();
- t.setObjectId(dst);
- t.setTag(name);
- t.setTagger(new PersonIdent(committer, new Date(now)));
- t.setMessage("");
- ObjectId id;
- try {
- id = inserter.insert(t);
- inserter.flush();
- } finally {
- inserter.release();
- }
- return (RevTag) pool.lookupAny(id, Constants.OBJ_TAG);
- }
-
- /**
- * Update a reference to point to an object.
- *
- * @param ref
- * the name of the reference to update to. If {@code ref} does
- * not start with {@code refs/} and is not the magic names
- * {@code HEAD} {@code FETCH_HEAD} or {@code MERGE_HEAD}, then
- * {@code refs/heads/} will be prefixed in front of the given
- * name, thereby assuming it is a branch.
- * @param to
- * the target object.
- * @return the target object.
- * @throws Exception
- */
- public RevCommit update(String ref, CommitBuilder to) throws Exception {
- return update(ref, to.create());
- }
-
- /**
- * Update a reference to point to an object.
- *
- * @param <T>
- * type of the target object.
- * @param ref
- * the name of the reference to update to. If {@code ref} does
- * not start with {@code refs/} and is not the magic names
- * {@code HEAD} {@code FETCH_HEAD} or {@code MERGE_HEAD}, then
- * {@code refs/heads/} will be prefixed in front of the given
- * name, thereby assuming it is a branch.
- * @param obj
- * the target object.
- * @return the target object.
- * @throws Exception
- */
- public <T extends AnyObjectId> T update(String ref, T obj) throws Exception {
- if (Constants.HEAD.equals(ref)) {
- // nothing
- } else if ("FETCH_HEAD".equals(ref)) {
- // nothing
- } else if ("MERGE_HEAD".equals(ref)) {
- // nothing
- } else if (ref.startsWith(Constants.R_REFS)) {
- // nothing
- } else
- ref = Constants.R_HEADS + ref;
-
- RefUpdate u = db.updateRef(ref);
- u.setNewObjectId(obj);
- switch (u.forceUpdate()) {
- case FAST_FORWARD:
- case FORCED:
- case NEW:
- case NO_CHANGE:
- updateServerInfo();
- return obj;
-
- default:
- throw new IOException("Cannot write " + ref + " " + u.getResult());
- }
- }
-
- /**
- * Update the dumb client server info files.
- *
- * @throws Exception
- */
- public void updateServerInfo() throws Exception {
- if (db instanceof FileRepository) {
- final FileRepository fr = (FileRepository) db;
- RefWriter rw = new RefWriter(fr.getAllRefs().values()) {
- @Override
- protected void writeFile(final String name, final byte[] bin)
- throws IOException {
- File path = new File(fr.getDirectory(), name);
- TestRepository.this.writeFile(path, bin);
- }
- };
- rw.writePackedRefs();
- rw.writeInfoRefs();
-
- final StringBuilder w = new StringBuilder();
- for (PackFile p : fr.getObjectDatabase().getPacks()) {
- w.append("P ");
- w.append(p.getPackFile().getName());
- w.append('\n');
- }
- writeFile(new File(new File(fr.getObjectDatabase().getDirectory(),
- "info"), "packs"), Constants.encodeASCII(w.toString()));
- }
- }
-
- /**
- * Ensure the body of the given object has been parsed.
- *
- * @param <T>
- * type of object, e.g. {@link RevTag} or {@link RevCommit}.
- * @param object
- * reference to the (possibly unparsed) object to force body
- * parsing of.
- * @return {@code object}
- * @throws Exception
- */
- public <T extends RevObject> T parseBody(final T object) throws Exception {
- pool.parseBody(object);
- return object;
- }
-
- /**
- * Create a new branch builder for this repository.
- *
- * @param ref
- * name of the branch to be constructed. If {@code ref} does not
- * start with {@code refs/} the prefix {@code refs/heads/} will
- * be added.
- * @return builder for the named branch.
- */
- public BranchBuilder branch(String ref) {
- if (Constants.HEAD.equals(ref)) {
- // nothing
- } else if (ref.startsWith(Constants.R_REFS)) {
- // nothing
- } else
- ref = Constants.R_HEADS + ref;
- return new BranchBuilder(ref);
- }
-
- /**
- * Tag an object using a lightweight tag.
- *
- * @param name
- * the tag name. The /refs/tags/ prefix will be added if the name
- * doesn't start with it
- * @param obj
- * the object to tag
- * @return the tagged object
- * @throws Exception
- */
- public ObjectId lightweightTag(String name, ObjectId obj) throws Exception {
- if (!name.startsWith(Constants.R_TAGS))
- name = Constants.R_TAGS + name;
- return update(name, obj);
- }
-
- /**
- * Run consistency checks against the object database.
- * <p>
- * This method completes silently if the checks pass. A temporary revision
- * pool is constructed during the checking.
- *
- * @param tips
- * the tips to start checking from; if not supplied the refs of
- * the repository are used instead.
- * @throws MissingObjectException
- * @throws IncorrectObjectTypeException
- * @throws IOException
- */
- public void fsck(RevObject... tips) throws MissingObjectException,
- IncorrectObjectTypeException, IOException {
- ObjectWalk ow = new ObjectWalk(db);
- if (tips.length != 0) {
- for (RevObject o : tips)
- ow.markStart(ow.parseAny(o));
- } else {
- for (Ref r : db.getAllRefs().values())
- ow.markStart(ow.parseAny(r.getObjectId()));
- }
-
- ObjectChecker oc = new ObjectChecker();
- for (;;) {
- final RevCommit o = ow.next();
- if (o == null)
- break;
-
- final byte[] bin = db.open(o, o.getType()).getCachedBytes();
- oc.checkCommit(bin);
- assertHash(o, bin);
- }
-
- for (;;) {
- final RevObject o = ow.nextObject();
- if (o == null)
- break;
-
- final byte[] bin = db.open(o, o.getType()).getCachedBytes();
- oc.check(o.getType(), bin);
- assertHash(o, bin);
- }
- }
-
- private static void assertHash(RevObject id, byte[] bin) {
- MessageDigest md = Constants.newMessageDigest();
- md.update(Constants.encodedTypeString(id.getType()));
- md.update((byte) ' ');
- md.update(Constants.encodeASCII(bin.length));
- md.update((byte) 0);
- md.update(bin);
- assertEquals(id, ObjectId.fromRaw(md.digest()));
- }
-
- /**
- * Pack all reachable objects in the repository into a single pack file.
- * <p>
- * All loose objects are automatically pruned. Existing packs however are
- * not removed.
- *
- * @throws Exception
- */
- public void packAndPrune() throws Exception {
- if (db.getObjectDatabase() instanceof ObjectDirectory) {
- ObjectDirectory odb = (ObjectDirectory) db.getObjectDatabase();
- NullProgressMonitor m = NullProgressMonitor.INSTANCE;
-
- final File pack, idx;
- PackWriter pw = new PackWriter(db);
- try {
- Set<ObjectId> all = new HashSet<ObjectId>();
- for (Ref r : db.getAllRefs().values())
- all.add(r.getObjectId());
- pw.preparePack(m, all, Collections.<ObjectId> emptySet());
-
- final ObjectId name = pw.computeName();
- OutputStream out;
-
- pack = nameFor(odb, name, ".pack");
- out = new SafeBufferedOutputStream(new FileOutputStream(pack));
- try {
- pw.writePack(m, m, out);
- } finally {
- out.close();
- }
- pack.setReadOnly();
-
- idx = nameFor(odb, name, ".idx");
- out = new SafeBufferedOutputStream(new FileOutputStream(idx));
- try {
- pw.writeIndex(out);
- } finally {
- out.close();
- }
- idx.setReadOnly();
- } finally {
- pw.release();
- }
-
- odb.openPack(pack, idx);
- updateServerInfo();
- prunePacked(odb);
- }
- }
-
- private void prunePacked(ObjectDirectory odb) throws IOException {
- for (PackFile p : odb.getPacks()) {
- for (MutableEntry e : p)
- FileUtils.delete(odb.fileFor(e.toObjectId()));
- }
- }
-
- private static File nameFor(ObjectDirectory odb, ObjectId name, String t) {
- File packdir = new File(odb.getDirectory(), "pack");
- return new File(packdir, "pack-" + name.name() + t);
- }
-
- private void writeFile(final File p, final byte[] bin) throws IOException,
- ObjectWritingException {
- final LockFile lck = new LockFile(p, db.getFS());
- if (!lck.lock())
- throw new ObjectWritingException("Can't write " + p);
- try {
- lck.write(bin);
- } catch (IOException ioe) {
- throw new ObjectWritingException("Can't write " + p);
- }
- if (!lck.commit())
- throw new ObjectWritingException("Can't write " + p);
- }
-
- /** Helper to build a branch with one or more commits */
- public class BranchBuilder {
- private final String ref;
-
- BranchBuilder(final String ref) {
- this.ref = ref;
- }
-
- /**
- * @return construct a new commit builder that updates this branch. If
- * the branch already exists, the commit builder will have its
- * first parent as the current commit and its tree will be
- * initialized to the current files.
- * @throws Exception
- * the commit builder can't read the current branch state
- */
- public CommitBuilder commit() throws Exception {
- return new CommitBuilder(this);
- }
-
- /**
- * Forcefully update this branch to a particular commit.
- *
- * @param to
- * the commit to update to.
- * @return {@code to}.
- * @throws Exception
- */
- public RevCommit update(CommitBuilder to) throws Exception {
- return update(to.create());
- }
-
- /**
- * Forcefully update this branch to a particular commit.
- *
- * @param to
- * the commit to update to.
- * @return {@code to}.
- * @throws Exception
- */
- public RevCommit update(RevCommit to) throws Exception {
- return TestRepository.this.update(ref, to);
- }
- }
-
- /** Helper to generate a commit. */
- public class CommitBuilder {
- private final BranchBuilder branch;
-
- private final DirCache tree = DirCache.newInCore();
-
- private ObjectId topLevelTree;
-
- private final List<RevCommit> parents = new ArrayList<RevCommit>(2);
-
- private int tick = 1;
-
- private String message = "";
-
- private RevCommit self;
-
- CommitBuilder() {
- branch = null;
- }
-
- CommitBuilder(BranchBuilder b) throws Exception {
- branch = b;
-
- Ref ref = db.getRef(branch.ref);
- if (ref != null) {
- parent(pool.parseCommit(ref.getObjectId()));
- }
- }
-
- CommitBuilder(CommitBuilder prior) throws Exception {
- branch = prior.branch;
-
- DirCacheBuilder b = tree.builder();
- for (int i = 0; i < prior.tree.getEntryCount(); i++)
- b.add(prior.tree.getEntry(i));
- b.finish();
-
- parents.add(prior.create());
- }
-
- public CommitBuilder parent(RevCommit p) throws Exception {
- if (parents.isEmpty()) {
- DirCacheBuilder b = tree.builder();
- parseBody(p);
- b.addTree(new byte[0], DirCacheEntry.STAGE_0, pool
- .getObjectReader(), p.getTree());
- b.finish();
- }
- parents.add(p);
- return this;
- }
-
- public CommitBuilder noParents() {
- parents.clear();
- return this;
- }
-
- public CommitBuilder noFiles() {
- tree.clear();
- return this;
- }
-
- public CommitBuilder setTopLevelTree(ObjectId treeId) {
- topLevelTree = treeId;
- return this;
- }
-
- public CommitBuilder add(String path, String content) throws Exception {
- return add(path, blob(content));
- }
-
- public CommitBuilder add(String path, final RevBlob id)
- throws Exception {
- return edit(new PathEdit(path) {
- @Override
- public void apply(DirCacheEntry ent) {
- ent.setFileMode(FileMode.REGULAR_FILE);
- ent.setObjectId(id);
- }
- });
- }
-
- public CommitBuilder edit(PathEdit edit) {
- DirCacheEditor e = tree.editor();
- e.add(edit);
- e.finish();
- return this;
- }
-
- public CommitBuilder rm(String path) {
- DirCacheEditor e = tree.editor();
- e.add(new DeletePath(path));
- e.add(new DeleteTree(path));
- e.finish();
- return this;
- }
-
- public CommitBuilder message(String m) {
- message = m;
- return this;
- }
-
- public CommitBuilder tick(int secs) {
- tick = secs;
- return this;
- }
-
- public RevCommit create() throws Exception {
- if (self == null) {
- TestRepository.this.tick(tick);
-
- final org.eclipse.jgit.lib.CommitBuilder c;
-
- c = new org.eclipse.jgit.lib.CommitBuilder();
- c.setParentIds(parents);
- setAuthorAndCommitter(c);
- c.setMessage(message);
-
- ObjectId commitId;
- try {
- if (topLevelTree != null)
- c.setTreeId(topLevelTree);
- else
- c.setTreeId(tree.writeTree(inserter));
- commitId = inserter.insert(c);
- inserter.flush();
- } finally {
- inserter.release();
- }
- self = pool.lookupCommit(commitId);
-
- if (branch != null)
- branch.update(self);
- }
- return self;
- }
-
- public CommitBuilder child() throws Exception {
- return new CommitBuilder(this);
- }
- }
- }
|