summaryrefslogtreecommitdiffstats
path: root/org.eclipse.jgit
diff options
context:
space:
mode:
authorRobin Rosenberg <robin.rosenberg@dewire.com>2012-07-12 08:04:35 +0200
committerRobin Rosenberg <robin.rosenberg@dewire.com>2012-07-20 08:20:48 +0200
commit2a2362fbb399582bf0f1be9f0f55101ac9daa201 (patch)
tree4e32249877407510dc5a9e664389993bda9f6e2c /org.eclipse.jgit
parentf82d1cb5c0ee593eb7a68b2d9ea539399f9204ba (diff)
downloadjgit-2a2362fbb399582bf0f1be9f0f55101ac9daa201.tar.gz
jgit-2a2362fbb399582bf0f1be9f0f55101ac9daa201.zip
Support parsing previous checkout as a revision expresion.
Repository.resolve can only return an ObjectId and will continue to do so, but another method, simplify(), will be able to return a branch name for some cases. Previous checkouts can be specified as @{-n}, where n is an integer speifying the n:th previous branch. The result is the branch name, unless the checkout was a detached head, in which case the object id is returned. Since the result is a branch it may be followed by a references to the reflog, such as @{-1}@{1} if necessary. A simple expression like "master" is resolved to master in simplify, but anything starting with refs gets resolved to its object id, even if it is a branch. A symbolic ref is resolved to its leaf ref, e.g. "HEAD" might be resolved to "master". Change-Id: Ifb815a1247ba2a3e2d9c46249c09be9d47f2b693
Diffstat (limited to 'org.eclipse.jgit')
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/lib/Repository.java142
1 files changed, 102 insertions, 40 deletions
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 2916c29b64..db030952a0 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/Repository.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/Repository.java
@@ -79,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.CheckoutEntry;
import org.eclipse.jgit.storage.file.ReflogEntry;
import org.eclipse.jgit.storage.file.ReflogReader;
import org.eclipse.jgit.treewalk.TreeWalk;
@@ -376,20 +377,58 @@ public abstract class Repository {
throws AmbiguousObjectException, IOException {
RevWalk rw = new RevWalk(this);
try {
- return resolve(rw, revstr);
+ Object resolved = resolve(rw, revstr);
+ if (resolved instanceof String) {
+ return getRef((String) resolved).getLeaf().getObjectId();
+ } else {
+ return (ObjectId) resolved;
+ }
} finally {
rw.release();
}
}
- private ObjectId resolve(final RevWalk rw, final String revstr) throws IOException {
+ /**
+ * Simplify an expression, but unlike {@link #resolve(String)} it will not
+ * resolve a branch passed or resulting from the expression, such as @{-}.
+ * Thus this method can be used to process an expression to a method that
+ * expects a branch or revision id.
+ *
+ * @param revstr
+ * @return object id or ref name from resolved expression
+ * @throws AmbiguousObjectException
+ * @throws IOException
+ */
+ public String simplify(final String revstr)
+ throws AmbiguousObjectException, IOException {
+ RevWalk rw = new RevWalk(this);
+ try {
+ Object resolved = resolve(rw, revstr);
+ if (resolved != null)
+ if (resolved instanceof String)
+ return (String) resolved;
+ else
+ return ((AnyObjectId) resolved).getName();
+ return null;
+ } finally {
+ rw.release();
+ }
+ }
+
+ private Object resolve(final RevWalk rw, final String revstr)
+ throws IOException {
char[] revChars = revstr.toCharArray();
RevObject rev = null;
+ String name = null;
+ int done = 0;
for (int i = 0; i < revChars.length; ++i) {
switch (revChars[i]) {
case '^':
if (rev == null) {
- rev = parseSimple(rw, new String(revChars, 0, i));
+ if (name == null)
+ name = new String(revChars, done, i);
+ rev = parseSimple(rw, name);
+ name = null;
if (rev == null)
return null;
}
@@ -429,6 +468,7 @@ public abstract class Repository {
rev = commit.getParent(pnum - 1);
}
i = j - 1;
+ done = i;
break;
case '{':
int k;
@@ -456,6 +496,7 @@ public abstract class Repository {
throw new RevisionSyntaxException(revstr);
else
throw new RevisionSyntaxException(revstr);
+ done = k;
break;
default:
rev = rw.parseAny(rev);
@@ -485,7 +526,9 @@ public abstract class Repository {
break;
case '~':
if (rev == null) {
- rev = parseSimple(rw, new String(revChars, 0, i));
+ if (name == null)
+ name = new String(revChars, done, i);
+ rev = parseSimple(rw, name);
if (rev == null)
return null;
}
@@ -523,6 +566,8 @@ public abstract class Repository {
i = l - 1;
break;
case '@':
+ if (rev != null)
+ throw new RevisionSyntaxException(revstr);
int m;
String time = null;
for (m = i + 2; m < revChars.length; ++m) {
@@ -532,47 +577,48 @@ public abstract class Repository {
}
}
if (time != null) {
- String refName = new String(revChars, 0, i);
- Ref ref;
- if (refName.equals("")) {
- // Currently checked out branch, HEAD if
- // detached
- ref = getRef(Constants.HEAD);
+ if (time.matches("^-\\d+$")) {
+ if (name != null)
+ throw new RevisionSyntaxException(revstr);
+ else {
+ String previousCheckout = resolveReflogCheckout(-Integer
+ .parseInt(time));
+ if (ObjectId.isId(previousCheckout))
+ rev = parseSimple(rw, previousCheckout);
+ else
+ name = previousCheckout;
+ }
+ } else {
+ if (name == null)
+ name = new String(revChars, done, i);
+ if (name.equals(""))
+ name = Constants.HEAD;
+ Ref ref = getRef(name);
if (ref == null)
return null;
+ // @{n} means current branch, not HEAD@{1} unless
+ // detached
if (ref.isSymbolic())
ref = ref.getLeaf();
- if (ref.getObjectId() == null)
- return null;
- } else
- ref = getRef(refName);
- if (ref == null)
- return null;
- rev = resolveReflog(rw, ref, time);
+ rev = resolveReflog(rw, ref, time);
+ name = null;
+ }
i = m;
} else
- i = m - 1;
+ throw new RevisionSyntaxException(revstr);
break;
case ':': {
RevTree tree;
if (rev == null) {
- // We might not yet have parsed the left hand side.
- ObjectId id;
- try {
- if (i == 0)
- id = resolve(rw, Constants.HEAD);
- else
- id = resolve(rw, new String(revChars, 0, i));
- } catch (RevisionSyntaxException badSyntax) {
- throw new RevisionSyntaxException(revstr);
- }
- if (id == null)
- return null;
- tree = rw.parseTree(id);
- } else {
- tree = rw.parseTree(rev);
+ if (name == null)
+ name = new String(revChars, done, i);
+ if (name.equals(""))
+ name = Constants.HEAD;
+ rev = parseSimple(rw, name);
}
-
+ if (rev == null)
+ return null;
+ tree = rw.parseTree(rev);
if (i == revChars.length - 1)
return tree.copy();
@@ -581,13 +627,19 @@ public abstract class Repository {
tree);
return tw != null ? tw.getObjectId(0) : null;
}
-
default:
if (rev != null)
throw new RevisionSyntaxException(revstr);
}
}
- return rev != null ? rev.copy() : resolveSimple(revstr);
+ if (rev != null)
+ return rev.copy();
+ if (name != null)
+ return name;
+ name = revstr.substring(done);
+ if (getRef(name) != null)
+ return name;
+ return resolveSimple(name);
}
private static boolean isHex(char c) {
@@ -634,6 +686,19 @@ public abstract class Repository {
return null;
}
+ private String resolveReflogCheckout(int checkoutNo)
+ throws IOException {
+ List<ReflogEntry> reflogEntries = new ReflogReader(this, Constants.HEAD)
+ .getReverseEntries();
+ for (ReflogEntry entry : reflogEntries) {
+ CheckoutEntry checkout = entry.parseCheckout();
+ if (checkout != null)
+ if (checkoutNo-- == 1)
+ return checkout.getFromBranch();
+ }
+ return null;
+ }
+
private RevCommit resolveReflog(RevWalk rw, Ref ref, String time)
throws IOException {
int number;
@@ -643,10 +708,7 @@ public abstract class Repository {
throw new RevisionSyntaxException(MessageFormat.format(
JGitText.get().invalidReflogRevision, time));
}
- if (number < 0)
- throw new RevisionSyntaxException(MessageFormat.format(
- JGitText.get().invalidReflogRevision, time));
-
+ assert number >= 0;
ReflogReader reader = new ReflogReader(this, ref.getName());
ReflogEntry entry = reader.getReverseEntry(number);
if (entry == null)