Result parse()

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;
    }
  }