summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKevin Sawicki <kevin@github.com>2011-12-16 17:05:42 -0800
committerKevin Sawicki <kevin@github.com>2011-12-16 17:05:47 -0800
commitdc4c06e7acba79044fc3850a61971fec615632e5 (patch)
tree932854c1dd67fbd6060e6ba0c182cf8c1382814d
parent29fc8fffc19f3a8e92c795294ee59d24052c3443 (diff)
downloadjgit-dc4c06e7acba79044fc3850a61971fec615632e5.tar.gz
jgit-dc4c06e7acba79044fc3850a61971fec615632e5.zip
Support resolving integer-based reflog revisions
Revision strings such as 'master@{0}' can now be resolved by Repository.resolve by reading the reflog for the ref and returning the commit for the entry number specified. This still throws an exception for cases not supported such as 'master@{yesterday}'. Change-Id: I6162777d6510e083565a77cac4545cda5a9aefb3
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/ReflogResolveTest.java123
-rw-r--r--org.eclipse.jgit/resources/org/eclipse/jgit/JGitText.properties3
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/JGitText.java3
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/lib/Repository.java40
4 files changed, 162 insertions, 7 deletions
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/ReflogResolveTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/ReflogResolveTest.java
new file mode 100644
index 0000000000..c3de79b6c4
--- /dev/null
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/ReflogResolveTest.java
@@ -0,0 +1,123 @@
+/*
+ * Copyright (C) 2011, GitHub 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.lib;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.fail;
+
+import org.eclipse.jgit.api.Git;
+import org.eclipse.jgit.errors.RevisionSyntaxException;
+import org.eclipse.jgit.revwalk.RevCommit;
+import org.junit.Test;
+
+/**
+ * Unit tests for resolving reflog-based revisions
+ */
+public class ReflogResolveTest extends RepositoryTestCase {
+
+ @Test
+ public void resolveMasterCommits() throws Exception {
+ Git git = new Git(db);
+ writeTrashFile("file.txt", "content");
+ git.add().addFilepattern("file.txt").call();
+ RevCommit c1 = git.commit().setMessage("create file").call();
+ writeTrashFile("file.txt", "content2");
+ git.add().addFilepattern("file.txt").call();
+ RevCommit c2 = git.commit().setMessage("edit file").call();
+
+ assertEquals(c2, db.resolve("master@{0}"));
+ assertEquals(c1, db.resolve("master@{1}"));
+ }
+
+ @Test
+ public void resolveReflogParent() throws Exception {
+ Git git = new Git(db);
+ writeTrashFile("file.txt", "content");
+ git.add().addFilepattern("file.txt").call();
+ RevCommit c1 = git.commit().setMessage("create file").call();
+ writeTrashFile("file.txt", "content2");
+ git.add().addFilepattern("file.txt").call();
+ git.commit().setMessage("edit file").call();
+
+ assertEquals(c1, db.resolve("master@{0}~1"));
+ }
+
+ @Test
+ public void resolveNonExistingBranch() throws Exception {
+ Git git = new Git(db);
+ writeTrashFile("file.txt", "content");
+ git.add().addFilepattern("file.txt").call();
+ git.commit().setMessage("create file").call();
+ assertNull(db.resolve("notabranch@{7}"));
+ }
+
+ @Test
+ public void resolveNegativeEntryNumber() throws Exception {
+ Git git = new Git(db);
+ writeTrashFile("file.txt", "content");
+ git.add().addFilepattern("file.txt").call();
+ git.commit().setMessage("create file").call();
+ try {
+ db.resolve("master@{-12}");
+ fail("Exception not thrown");
+ } catch (RevisionSyntaxException e) {
+ assertNotNull(e);
+ }
+ }
+
+ @Test
+ public void resolveDate() throws Exception {
+ Git git = new Git(db);
+ writeTrashFile("file.txt", "content");
+ git.add().addFilepattern("file.txt").call();
+ git.commit().setMessage("create file").call();
+ try {
+ db.resolve("master@{yesterday}");
+ fail("Exception not thrown");
+ } catch (RevisionSyntaxException e) {
+ assertNotNull(e);
+ }
+ }
+} \ No newline at end of file
diff --git a/org.eclipse.jgit/resources/org/eclipse/jgit/JGitText.properties b/org.eclipse.jgit/resources/org/eclipse/jgit/JGitText.properties
index fc32069999..5bb2800db0 100644
--- a/org.eclipse.jgit/resources/org/eclipse/jgit/JGitText.properties
+++ b/org.eclipse.jgit/resources/org/eclipse/jgit/JGitText.properties
@@ -249,6 +249,7 @@ invalidObject=Invalid {0} {1}:{2}
invalidOldIdSent=invalid old id sent
invalidPacketLineHeader=Invalid packet line header: {0}
invalidPath=Invalid path: {0}
+invalidReflogRevision=Invalid reflog revision: {0}
invalidRefName=Invalid ref name: {0}
invalidRemote=Invalid remote: {0}
invalidStageForPath=Invalid stage {0} for path {1}
@@ -366,7 +367,7 @@ receivingObjects=Receiving objects
refAlreadyExists=Ref {0} already exists
refNotResolved=Ref {0} can not be resolved
refUpdateReturnCodeWas=RefUpdate return code was: {0}
-reflogsNotYetSupportedByRevisionParser=reflogs not yet supported by revision parser
+reflogEntryNotFound=Entry {0} not found in reflog for ''{1}'', only {2} entries exist
remoteConfigHasNoURIAssociated=Remote config "{0}" has no URIs associated
remoteDoesNotHaveSpec=Remote does not have {0} available for fetch.
remoteDoesNotSupportSmartHTTPPush=remote does not support smart HTTP push
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/JGitText.java b/org.eclipse.jgit/src/org/eclipse/jgit/JGitText.java
index 4dabe07412..c57f77ec1d 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/JGitText.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/JGitText.java
@@ -310,6 +310,7 @@ public class JGitText extends TranslationBundle {
/***/ public String invalidPacketLineHeader;
/***/ public String invalidPath;
/***/ public String invalidRemote;
+ /***/ public String invalidReflogRevision;
/***/ public String invalidRefName;
/***/ public String invalidStageForPath;
/***/ public String invalidTagOption;
@@ -426,7 +427,7 @@ public class JGitText extends TranslationBundle {
/***/ public String refAlreadyExists;
/***/ public String refNotResolved;
/***/ public String refUpdateReturnCodeWas;
- /***/ public String reflogsNotYetSupportedByRevisionParser;
+ /***/ public String reflogEntryNotFound;
/***/ public String remoteConfigHasNoURIAssociated;
/***/ public String remoteDoesNotHaveSpec;
/***/ public String remoteDoesNotSupportSmartHTTPPush;
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/Repository.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/Repository.java
index 85f82955ea..afbde589c3 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/Repository.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/Repository.java
@@ -51,6 +51,7 @@ import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
+import java.text.MessageFormat;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
@@ -78,6 +79,7 @@ import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevObject;
import org.eclipse.jgit.revwalk.RevTree;
import org.eclipse.jgit.revwalk.RevWalk;
+import org.eclipse.jgit.storage.file.ReflogEntry;
import org.eclipse.jgit.storage.file.ReflogReader;
import org.eclipse.jgit.treewalk.TreeWalk;
import org.eclipse.jgit.util.FS;
@@ -524,11 +526,15 @@ public abstract class Repository {
break;
}
}
- if (time != null)
- throw new RevisionSyntaxException(
- JGitText.get().reflogsNotYetSupportedByRevisionParser,
- revstr);
- i = m - 1;
+ if (time != null) {
+ String refName = new String(rev, 0, i);
+ Ref resolved = getRefDatabase().getRef(refName);
+ if (resolved == null)
+ return null;
+ ref = resolveReflog(rw, resolved, time);
+ i = m;
+ } else
+ i = m - 1;
break;
case ':': {
RevTree tree;
@@ -610,6 +616,30 @@ public abstract class Repository {
return null;
}
+ private RevCommit resolveReflog(RevWalk rw, Ref ref, String time)
+ throws IOException {
+ int number;
+ try {
+ number = Integer.parseInt(time);
+ } catch (NumberFormatException nfe) {
+ throw new RevisionSyntaxException(MessageFormat.format(
+ JGitText.get().invalidReflogRevision, time));
+ }
+ if (number < 0)
+ throw new RevisionSyntaxException(MessageFormat.format(
+ JGitText.get().invalidReflogRevision, time));
+
+ ReflogReader reader = new ReflogReader(this, ref.getName());
+ List<ReflogEntry> entries = reader.getReverseEntries(number + 1);
+ if (number >= entries.size())
+ throw new RevisionSyntaxException(MessageFormat.format(
+ JGitText.get().reflogEntryNotFound,
+ Integer.valueOf(number), ref.getName(),
+ Integer.valueOf(entries.size())));
+
+ return rw.parseCommit(entries.get(number).getNewId());
+ }
+
private ObjectId resolveAbbreviation(final String revstr) throws IOException,
AmbiguousObjectException {
AbbreviatedObjectId id = AbbreviatedObjectId.fromString(revstr);