in java/com/google/gitiles/RevisionParser.java [117:232]
Result parse(String path) throws IOException {
if (path.startsWith("/")) {
path = path.substring(1);
}
if (Strings.isNullOrEmpty(path)) {
return null;
}
try (RevWalk walk = new RevWalk(repo)) {
walk.setRetainBody(false);
Revision oldRevision = null;
Revision oldRevisionRedirected = null;
StringBuilder b = new StringBuilder();
boolean first = true;
for (String part : PathUtil.SPLITTER.split(path)) {
if (part.isEmpty()) {
return null; // No valid revision contains empty segments.
}
if (!first) {
b.append('/');
}
if (oldRevision == null) {
int dots = part.indexOf("..");
int firstParent = part.indexOf("^!");
if (dots == 0 || firstParent == 0) {
return null;
} else if (dots > 0) {
b.append(part, 0, dots);
String oldName = b.toString();
String oldNameRedirect = getRedirectFor(oldName);
if (!isValidRevision(oldNameRedirect)) {
return null;
}
RevObject old = resolve(oldNameRedirect, walk);
if (old == null) {
return null;
}
/*
* Retain oldRevision with the old name (non-redirected-path) since it is used in
* determining the Revision path (start index of the path from the name).
* For example: For a master -> main redirect,
* original path: /master/index.c is updated to /main/index.c
* To parse the ref/path to build Revision object we look at the original path.
*/
oldRevision = Revision.peel(oldName, old, walk);
oldRevisionRedirected = Revision.peel(oldNameRedirect, old, walk);
part = part.substring(dots + 2);
b = new StringBuilder();
} else if (firstParent > 0) {
if (firstParent != part.length() - 2) {
return null;
}
b.append(part, 0, part.length() - 2);
String name = b.toString();
if (!isValidRevision(name)) {
return null;
}
String nameRedirected = getRedirectFor(name);
RevObject obj = resolve(nameRedirected, walk);
if (obj == null) {
return null;
}
while (obj instanceof RevTag) {
obj = ((RevTag) obj).getObject();
walk.parseHeaders(obj);
}
if (!(obj instanceof RevCommit)) {
return null; // Not a commit, ^! is invalid.
}
RevCommit c = (RevCommit) obj;
if (c.getParentCount() > 0) {
oldRevisionRedirected = Revision.peeled(nameRedirected + "^", c.getParent(0));
} else {
oldRevisionRedirected = Revision.NULL;
}
Result result =
new Result(
Revision.peeled(nameRedirected, c),
oldRevisionRedirected,
path.substring(name.length() + 2));
return isVisible(walk, result) ? result : null;
}
}
b.append(part);
String name = b.toString();
if (!isValidRevision(name)) {
return null;
}
String nameRedirected = getRedirectFor(name);
RevObject obj = resolve(nameRedirected, walk);
if (obj != null) {
int pathStart;
if (oldRevision == null) {
pathStart = name.length(); // foo
} else {
// foo..bar (foo may be empty)
pathStart = oldRevision.getName().length() + 2 + name.length();
}
Result result =
new Result(
Revision.peel(nameRedirected, obj, walk),
oldRevisionRedirected,
path.substring(pathStart));
return isVisible(walk, result) ? result : null;
}
first = false;
}
return null;
}
}