summaryrefslogtreecommitdiffstats
path: root/org.eclipse.jgit/src
diff options
context:
space:
mode:
authorRobin Rosenberg <robin.rosenberg@dewire.com>2012-08-21 17:34:45 -0400
committerGerrit Code Review @ Eclipse.org <gerrit@eclipse.org>2012-08-21 17:34:45 -0400
commit5e21a8916cd823979613c0b3e49b4b3d0995c0e3 (patch)
tree81879d4379d46f336fc5972d8038d606d3687134 /org.eclipse.jgit/src
parent1c1fc6814c44ec0af43b1788451339462821088d (diff)
parentc010c93694eb76e90f60de01b5a6b946c2472e9d (diff)
downloadjgit-5e21a8916cd823979613c0b3e49b4b3d0995c0e3.tar.gz
jgit-5e21a8916cd823979613c0b3e49b4b3d0995c0e3.zip
Merge changes I98df46ce,Ifb815a12,I051a1724
* changes: Support [<ref>]@{upstream} revision syntax Support parsing previous checkout as a revision expresion. Allow a @ without branch in revision syntax
Diffstat (limited to 'org.eclipse.jgit/src')
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/lib/Repository.java179
1 files changed, 147 insertions, 32 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 1f9286871f..82394dd757 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.net.URISyntaxException;
import java.text.MessageFormat;
import java.util.Collection;
import java.util.Collections;
@@ -79,8 +80,11 @@ 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.transport.RefSpec;
+import org.eclipse.jgit.transport.RemoteConfig;
import org.eclipse.jgit.treewalk.TreeWalk;
import org.eclipse.jgit.util.FS;
import org.eclipse.jgit.util.FileUtils;
@@ -376,20 +380,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();
+ }
+ }
+
+ /**
+ * 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 ObjectId resolve(final RevWalk rw, final String revstr) throws IOException {
+ 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 +471,7 @@ public abstract class Repository {
rev = commit.getParent(pnum - 1);
}
i = j - 1;
+ done = i;
break;
case '{':
int k;
@@ -456,6 +499,7 @@ public abstract class Repository {
throw new RevisionSyntaxException(revstr);
else
throw new RevisionSyntaxException(revstr);
+ done = k;
break;
default:
rev = rw.parseAny(rev);
@@ -485,7 +529,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 +569,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,35 +580,86 @@ public abstract class Repository {
}
}
if (time != null) {
- String refName = new String(revChars, 0, i);
- Ref resolved = getRefDatabase().getRef(refName);
- if (resolved == null)
- return null;
- rev = resolveReflog(rw, resolved, time);
+ if (time.equals("upstream")) {
+ if (name == null)
+ name = new String(revChars, done, i);
+ if (name.equals(""))
+ // Currently checked out branch, HEAD if
+ // detached
+ name = Constants.HEAD;
+ Ref ref = getRef(name);
+ if (ref == null)
+ return null;
+ if (ref.isSymbolic())
+ ref = ref.getLeaf();
+ name = ref.getName();
+
+ RemoteConfig remoteConfig;
+ try {
+ remoteConfig = new RemoteConfig(getConfig(),
+ "origin");
+ } catch (URISyntaxException e) {
+ throw new RevisionSyntaxException(revstr);
+ }
+ String remoteBranchName = getConfig()
+ .getString(
+ ConfigConstants.CONFIG_BRANCH_SECTION,
+ Repository.shortenRefName(ref.getName()),
+ ConfigConstants.CONFIG_KEY_MERGE);
+ List<RefSpec> fetchRefSpecs = remoteConfig
+ .getFetchRefSpecs();
+ for (RefSpec refSpec : fetchRefSpecs) {
+ if (refSpec.matchSource(remoteBranchName)) {
+ RefSpec expandFromSource = refSpec
+ .expandFromSource(remoteBranchName);
+ name = expandFromSource.getDestination();
+ break;
+ }
+ }
+ if (name == null)
+ throw new RevisionSyntaxException(revstr);
+ } else 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();
+ 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();
@@ -569,13 +668,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) {
@@ -622,6 +727,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;
@@ -631,10 +749,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)