diff options
author | Robin Rosenberg <robin.rosenberg@dewire.com> | 2012-08-21 17:34:45 -0400 |
---|---|---|
committer | Gerrit Code Review @ Eclipse.org <gerrit@eclipse.org> | 2012-08-21 17:34:45 -0400 |
commit | 5e21a8916cd823979613c0b3e49b4b3d0995c0e3 (patch) | |
tree | 81879d4379d46f336fc5972d8038d606d3687134 /org.eclipse.jgit/src | |
parent | 1c1fc6814c44ec0af43b1788451339462821088d (diff) | |
parent | c010c93694eb76e90f60de01b5a6b946c2472e9d (diff) | |
download | jgit-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.java | 179 |
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) |