Browse Source

Rewrite resolve in terms of RevWalk

We want to eventually get rid of the mapCommit, mapTree APIs on
Repository and force everyone into the faster parsers that exist
in RevWalk.  Rewriting resolve in terms of the faster parsers is
a good first step.

It actually simplifies the code a bit, as we no longer need to
keep track of an ObjectId and an Object (the parsed form), since
all RevObjects implicitly have their ObjectId readily available.

Change-Id: I4d234630195616e2c263e7e70038b55a1be4e7a3
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
stable-0.9
Shawn O. Pearce 15 years ago
parent
commit
b6ba9739d5
  1. 202
      org.eclipse.jgit/src/org/eclipse/jgit/lib/Repository.java

202
org.eclipse.jgit/src/org/eclipse/jgit/lib/Repository.java

@ -67,6 +67,10 @@ import org.eclipse.jgit.dircache.DirCache;
import org.eclipse.jgit.errors.ConfigInvalidException; import org.eclipse.jgit.errors.ConfigInvalidException;
import org.eclipse.jgit.errors.IncorrectObjectTypeException; import org.eclipse.jgit.errors.IncorrectObjectTypeException;
import org.eclipse.jgit.errors.RevisionSyntaxException; import org.eclipse.jgit.errors.RevisionSyntaxException;
import org.eclipse.jgit.revwalk.RevBlob;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevObject;
import org.eclipse.jgit.revwalk.RevWalk;
import org.eclipse.jgit.util.FS; import org.eclipse.jgit.util.FS;
import org.eclipse.jgit.util.IO; import org.eclipse.jgit.util.IO;
import org.eclipse.jgit.util.RawParseUtils; import org.eclipse.jgit.util.RawParseUtils;
@ -745,36 +749,37 @@ public class Repository {
* *
* Currently supported is combinations of these. * Currently supported is combinations of these.
* <ul> * <ul>
* <li>SHA-1 - a SHA-1</li> * <li>SHA-1 - a SHA-1</li>
* <li>refs/... - a ref name</li> * <li>refs/... - a ref name</li>
* <li>ref^n - nth parent reference</li> * <li>ref^n - nth parent reference</li>
* <li>ref~n - distance via parent reference</li> * <li>ref~n - distance via parent reference</li>
* <li>ref@{n} - nth version of ref</li> * <li>ref@{n} - nth version of ref</li>
* <li>ref^{tree} - tree references by ref</li> * <li>ref^{tree} - tree references by ref</li>
* <li>ref^{commit} - commit references by ref</li> * <li>ref^{commit} - commit references by ref</li>
* </ul> * </ul>
* *
* Not supported is * Not supported is:
* <ul> * <ul>
* <li>timestamps in reflogs, ref@{full or relative timestamp}</li> * <li>timestamps in reflogs, ref@{full or relative timestamp}</li>
* <li>abbreviated SHA-1's</li> * <li>abbreviated SHA-1's</li>
* </ul> * </ul>
* *
* @param revstr A git object references expression * @param revstr
* A git object references expression
* @return an ObjectId or null if revstr can't be resolved to any ObjectId * @return an ObjectId or null if revstr can't be resolved to any ObjectId
* @throws IOException on serious errors * @throws IOException
* on serious errors
*/ */
public ObjectId resolve(final String revstr) throws IOException { public ObjectId resolve(final String revstr) throws IOException {
char[] rev = revstr.toCharArray(); char[] rev = revstr.toCharArray();
Object ref = null; RevObject ref = null;
ObjectId refId = null; RevWalk rw = new RevWalk(this);
for (int i = 0; i < rev.length; ++i) { for (int i = 0; i < rev.length; ++i) {
switch (rev[i]) { switch (rev[i]) {
case '^': case '^':
if (refId == null) { if (ref == null) {
String refstr = new String(rev,0,i); ref = parseSimple(rw, new String(rev, 0, i));
refId = resolveSimple(refstr); if (ref == null)
if (refId == null)
return null; return null;
} }
if (i + 1 < rev.length) { if (i + 1 < rev.length) {
@ -790,19 +795,12 @@ public class Repository {
case '8': case '8':
case '9': case '9':
int j; int j;
ref = mapObject(refId, null); ref = rw.parseCommit(ref);
while (ref instanceof Tag) { for (j = i + 1; j < rev.length; ++j) {
Tag tag = (Tag)ref;
refId = tag.getObjId();
ref = mapObject(refId, null);
}
if (!(ref instanceof Commit))
throw new IncorrectObjectTypeException(refId, Constants.TYPE_COMMIT);
for (j=i+1; j<rev.length; ++j) {
if (!Character.isDigit(rev[j])) if (!Character.isDigit(rev[j]))
break; break;
} }
String parentnum = new String(rev, i+1, j-i-1); String parentnum = new String(rev, i + 1, j - i - 1);
int pnum; int pnum;
try { try {
pnum = Integer.parseInt(parentnum); pnum = Integer.parseInt(parentnum);
@ -812,123 +810,83 @@ public class Repository {
revstr); revstr);
} }
if (pnum != 0) { if (pnum != 0) {
final ObjectId parents[] = ((Commit) ref) RevCommit commit = (RevCommit) ref;
.getParentIds(); if (pnum > commit.getParentCount())
if (pnum > parents.length) ref = null;
refId = null;
else else
refId = parents[pnum - 1]; ref = commit.getParent(pnum - 1);
} }
i = j - 1; i = j - 1;
break; break;
case '{': case '{':
int k; int k;
String item = null; String item = null;
for (k=i+2; k<rev.length; ++k) { for (k = i + 2; k < rev.length; ++k) {
if (rev[k] == '}') { if (rev[k] == '}') {
item = new String(rev, i+2, k-i-2); item = new String(rev, i + 2, k - i - 2);
break; break;
} }
} }
i = k; i = k;
if (item != null) if (item != null)
if (item.equals("tree")) { if (item.equals("tree")) {
ref = mapObject(refId, null); ref = rw.parseTree(ref);
while (ref instanceof Tag) { } else if (item.equals("commit")) {
Tag t = (Tag)ref; ref = rw.parseCommit(ref);
refId = t.getObjId(); } else if (item.equals("blob")) {
ref = mapObject(refId, null); ref = rw.peel(ref);
} if (!(ref instanceof RevBlob))
if (ref instanceof Treeish) throw new IncorrectObjectTypeException(ref,
refId = ((Treeish)ref).getTreeId(); Constants.TYPE_BLOB);
else } else if (item.equals("")) {
throw new IncorrectObjectTypeException(refId, Constants.TYPE_TREE); ref = rw.peel(ref);
} } else
else if (item.equals("commit")) {
ref = mapObject(refId, null);
while (ref instanceof Tag) {
Tag t = (Tag)ref;
refId = t.getObjId();
ref = mapObject(refId, null);
}
if (!(ref instanceof Commit))
throw new IncorrectObjectTypeException(refId, Constants.TYPE_COMMIT);
}
else if (item.equals("blob")) {
ref = mapObject(refId, null);
while (ref instanceof Tag) {
Tag t = (Tag)ref;
refId = t.getObjId();
ref = mapObject(refId, null);
}
if (!(ref instanceof byte[]))
throw new IncorrectObjectTypeException(refId, Constants.TYPE_BLOB);
}
else if (item.equals("")) {
ref = mapObject(refId, null);
while (ref instanceof Tag) {
Tag t = (Tag)ref;
refId = t.getObjId();
ref = mapObject(refId, null);
}
}
else
throw new RevisionSyntaxException(revstr); throw new RevisionSyntaxException(revstr);
else else
throw new RevisionSyntaxException(revstr); throw new RevisionSyntaxException(revstr);
break; break;
default: default:
ref = mapObject(refId, null); ref = rw.parseAny(ref);
if (ref instanceof Commit) { if (ref instanceof RevCommit) {
final ObjectId parents[] = ((Commit) ref) RevCommit commit = ((RevCommit) ref);
.getParentIds(); if (commit.getParentCount() == 0)
if (parents.length == 0) ref = null;
refId = null;
else else
refId = parents[0]; ref = commit.getParent(0);
} else } else
throw new IncorrectObjectTypeException(refId, Constants.TYPE_COMMIT); throw new IncorrectObjectTypeException(ref,
Constants.TYPE_COMMIT);
} }
} else { } else {
ref = mapObject(refId, null); ref = rw.peel(ref);
while (ref instanceof Tag) { if (ref instanceof RevCommit) {
Tag tag = (Tag)ref; RevCommit commit = ((RevCommit) ref);
refId = tag.getObjId(); if (commit.getParentCount() == 0)
ref = mapObject(refId, null); ref = null;
}
if (ref instanceof Commit) {
final ObjectId parents[] = ((Commit) ref)
.getParentIds();
if (parents.length == 0)
refId = null;
else else
refId = parents[0]; ref = commit.getParent(0);
} else } else
throw new IncorrectObjectTypeException(refId, Constants.TYPE_COMMIT); throw new IncorrectObjectTypeException(ref,
Constants.TYPE_COMMIT);
} }
break; break;
case '~': case '~':
if (ref == null) { if (ref == null) {
String refstr = new String(rev,0,i); ref = parseSimple(rw, new String(rev, 0, i));
refId = resolveSimple(refstr); if (ref == null)
if (refId == null)
return null; return null;
ref = mapObject(refId, null);
}
while (ref instanceof Tag) {
Tag tag = (Tag)ref;
refId = tag.getObjId();
ref = mapObject(refId, null);
} }
if (!(ref instanceof Commit)) ref = rw.peel(ref);
throw new IncorrectObjectTypeException(refId, Constants.TYPE_COMMIT); if (!(ref instanceof RevCommit))
throw new IncorrectObjectTypeException(ref,
Constants.TYPE_COMMIT);
int l; int l;
for (l = i + 1; l < rev.length; ++l) { for (l = i + 1; l < rev.length; ++l) {
if (!Character.isDigit(rev[l])) if (!Character.isDigit(rev[l]))
break; break;
} }
String distnum = new String(rev, i+1, l-i-1); String distnum = new String(rev, i + 1, l - i - 1);
int dist; int dist;
try { try {
dist = Integer.parseInt(distnum); dist = Integer.parseInt(distnum);
@ -937,13 +895,14 @@ public class Repository {
JGitText.get().invalidAncestryLength, revstr); JGitText.get().invalidAncestryLength, revstr);
} }
while (dist > 0) { while (dist > 0) {
final ObjectId[] parents = ((Commit) ref).getParentIds(); RevCommit commit = (RevCommit) ref;
if (parents.length == 0) { if (commit.getParentCount() == 0) {
refId = null; ref = null;
break; break;
} }
refId = parents[0]; commit = commit.getParent(0);
ref = mapCommit(refId); rw.parseHeaders(commit);
ref = commit;
--dist; --dist;
} }
i = l - 1; i = l - 1;
@ -951,30 +910,35 @@ public class Repository {
case '@': case '@':
int m; int m;
String time = null; String time = null;
for (m=i+2; m<rev.length; ++m) { for (m = i + 2; m < rev.length; ++m) {
if (rev[m] == '}') { if (rev[m] == '}') {
time = new String(rev, i+2, m-i-2); time = new String(rev, i + 2, m - i - 2);
break; break;
} }
} }
if (time != null) if (time != null)
throw new RevisionSyntaxException(JGitText.get().reflogsNotYetSupportedByRevisionParser, revstr); throw new RevisionSyntaxException(
JGitText.get().reflogsNotYetSupportedByRevisionParser,
revstr);
i = m - 1; i = m - 1;
break; break;
default: default:
if (refId != null) if (ref != null)
throw new RevisionSyntaxException(revstr); throw new RevisionSyntaxException(revstr);
} }
} }
if (refId == null) return ref != null ? ref.copy() : resolveSimple(revstr);
refId = resolveSimple(revstr); }
return refId;
private RevObject parseSimple(RevWalk rw, String revstr) throws IOException {
ObjectId id = resolveSimple(revstr);
return id != null ? rw.parseAny(id) : null;
} }
private ObjectId resolveSimple(final String revstr) throws IOException { private ObjectId resolveSimple(final String revstr) throws IOException {
if (ObjectId.isId(revstr)) if (ObjectId.isId(revstr))
return ObjectId.fromString(revstr); return ObjectId.fromString(revstr);
final Ref r = refs.getRef(revstr); final Ref r = getRefDatabase().getRef(revstr);
return r != null ? r.getObjectId() : null; return r != null ? r.getObjectId() : null;
} }

Loading…
Cancel
Save