@Test
  public void testAddUnstagedChanges()
      throws IOException, NoHeadException, NoMessageException, ConcurrentRefUpdateException,
          JGitInternalException, WrongRepositoryStateException, NoFilepatternException {
    File file = new File(db.getWorkTree(), "a.txt");
    FileUtils.createNewFile(file);
    PrintWriter writer = new PrintWriter(file);
    writer.print("content");
    writer.close();

    Git git = new Git(db);
    git.add().addFilepattern("a.txt").call();
    RevCommit commit = git.commit().setMessage("initial commit").call();
    TreeWalk tw = TreeWalk.forPath(db, "a.txt", commit.getTree());
    assertEquals("6b584e8ece562ebffc15d38808cd6b98fc3d97ea", tw.getObjectId(0).getName());

    writer = new PrintWriter(file);
    writer.print("content2");
    writer.close();
    commit = git.commit().setMessage("second commit").call();
    tw = TreeWalk.forPath(db, "a.txt", commit.getTree());
    assertEquals("6b584e8ece562ebffc15d38808cd6b98fc3d97ea", tw.getObjectId(0).getName());

    commit = git.commit().setAll(true).setMessage("third commit").setAll(true).call();
    tw = TreeWalk.forPath(db, "a.txt", commit.getTree());
    assertEquals("db00fd65b218578127ea51f3dffac701f12f486a", tw.getObjectId(0).getName());
  }
예제 #2
0
  @Nullable
  private static MarkdownFile findFile(RevWalk rw, RevTree root, String path) throws IOException {
    if (Strings.isNullOrEmpty(path)) {
      path = INDEX_MD;
    }

    ObjectReader reader = rw.getObjectReader();
    try (TreeWalk tw = TreeWalk.forPath(reader, path, root)) {
      if (tw == null) {
        return null;
      }
      if ((tw.getRawMode(0) & TYPE_MASK) == TYPE_TREE) {
        if (findIndexFile(tw)) {
          path = tw.getPathString();
        } else {
          return null;
        }
      }
      if ((tw.getRawMode(0) & TYPE_MASK) == TYPE_FILE) {
        if (!path.endsWith(".md")) {
          return null;
        }
        return new MarkdownFile(path, tw.getObjectId(0));
      }
      return null;
    }
  }
예제 #3
0
 private boolean find(RevCommit commit, PathFilter path) throws IOException {
   treeWalk.setFilter(path);
   treeWalk.reset(commit.getTree());
   if (treeWalk.next() && isFile(treeWalk.getRawMode(0))) {
     treeWalk.getObjectId(idBuf, 0);
     return true;
   }
   return false;
 }
예제 #4
0
  private String getRepositoryContent(Repository repository, RevCommit revCommit, String fileName)
      throws IOException {
    TreeWalk treewalk = TreeWalk.forPath(repository, fileName, revCommit.getTree());

    if (treewalk != null) {
      return new String(repository.open(treewalk.getObjectId(0)).getBytes());
    } else {
      return null;
    }
  }
예제 #5
0
 private static byte[] read(Repository db, AnyObjectId treeish, String path)
     throws MissingObjectException, IncorrectObjectTypeException, IOException {
   try (ObjectReader or = db.newObjectReader()) {
     TreeWalk tree = TreeWalk.forPath(or, path, asTree(or, treeish));
     if (tree == null)
       throw new FileNotFoundException(
           MessageFormat.format(JGitText.get().entryNotFoundByPath, path));
     return read(or, tree.getObjectId(0));
   }
 }
예제 #6
0
  protected ObjectId getObjectId(String fileName) throws IOException {
    if (revision == null) {
      return null;
    }

    TreeWalk tw = TreeWalk.forPath(reader, fileName, revision.getTree());
    if (tw != null) {
      return tw.getObjectId(0);
    }

    return null;
  }
예제 #7
0
  protected byte[] readFile(String fileName) throws IOException {
    if (revision == null) {
      return new byte[] {};
    }

    TreeWalk tw = TreeWalk.forPath(reader, fileName, revision.getTree());
    if (tw != null) {
      ObjectLoader obj = reader.open(tw.getObjectId(0), Constants.OBJ_BLOB);
      return obj.getCachedBytes(Integer.MAX_VALUE);

    } else {
      return new byte[] {};
    }
  }
예제 #8
0
 /**
  * Lookup an entry stored in a tree, failing if not present.
  *
  * @param tree the tree to search.
  * @param path the path to find the entry of.
  * @return the parsed object entry at this path, never null.
  * @throws Exception
  */
 public RevObject get(final RevTree tree, final String path) throws Exception {
   final TreeWalk tw = new TreeWalk(pool.getObjectReader());
   tw.setFilter(PathFilterGroup.createFromStrings(Collections.singleton(path)));
   tw.reset(tree);
   while (tw.next()) {
     if (tw.isSubtree() && !path.equals(tw.getPathString())) {
       tw.enterSubtree();
       continue;
     }
     final ObjectId entid = tw.getObjectId(0);
     final FileMode entmode = tw.getFileMode(0);
     return pool.lookupAny(entid, entmode.getObjectType());
   }
   fail("Can't find " + path + " in tree " + tree.name());
   return null; // never reached.
 }
예제 #9
0
  @Override
  public byte[] getData(String commitName, String filePath) {

    try {

      RevCommit revCommit = revWalk.parseCommit(ObjectId.fromString(commitName));
      RevTree tree = revCommit.getTree();
      TreeWalk treeWalk = TreeWalk.forPath(reader, filePath, tree);

      if (treeWalk == null) return null;
      else return reader.open(treeWalk.getObjectId(0)).getBytes();

    } catch (IOException e) {
      throw new VisMinerAPIException(e.getMessage(), e);
    }
  }
예제 #10
0
 /**
  * Returns a path model of the current file in the treewalk.
  *
  * @param tw
  * @param basePath
  * @param commit
  * @return a path model of the current file in the treewalk
  */
 private static PathModel getPathModel(TreeWalk tw, String basePath, RevCommit commit) {
   String name;
   long size = 0;
   if (basePath == null) {
     name = tw.getPathString();
   } else {
     name = tw.getPathString().substring(basePath.length() + 1);
   }
   try {
     if (!tw.isSubtree()) {
       size = tw.getObjectReader().getObjectSize(tw.getObjectId(0), Constants.OBJ_BLOB);
     }
   } catch (Throwable t) {
     // error(t, null, "failed to retrieve blob size for " + tw.getPathString());
     Logger.error(t, t.getMessage());
   }
   return new PathModel(
       name, tw.getPathString(), size, tw.getFileMode(0).getBits(), commit.getName());
 }
예제 #11
0
 public static JSONArray getListEntries(
     TreeWalk treeWalk, Repository repo, Git git, Ref head, String filePath, String projectName)
     throws MissingObjectException, IncorrectObjectTypeException, CorruptObjectException,
         IOException {
   JSONArray contents = new JSONArray();
   do {
     if (treeWalk.isSubtree()) {
       String test = new String(treeWalk.getRawPath());
       if (test.length() /*treeWalk.getPathLength()*/ > filePath.length()) {
         listEntry(
             treeWalk.getNameString(),
             "dir",
             "0",
             treeWalk.getPathString(),
             projectName,
             head.getName(),
             git,
             contents);
       }
       if (test.length() /*treeWalk.getPathLength()*/ <= filePath.length()) {
         treeWalk.enterSubtree();
       }
     } else {
       ObjectId objId = treeWalk.getObjectId(0);
       ObjectLoader loader = repo.open(objId);
       long size = loader.getSize();
       listEntry(
           treeWalk.getNameString(),
           "file",
           Long.toString(size),
           treeWalk.getPathString(),
           projectName,
           head.getName(),
           git,
           contents);
     }
   } while (treeWalk.next());
   return contents;
 }
예제 #12
0
  private void buildMaps(
      Repository repository,
      RevCommit baseCommit,
      RevCommit compareCommit,
      IProgressMonitor monitor)
      throws InterruptedException, IOException {
    monitor.beginTask(UIText.CompareTreeView_AnalyzingRepositoryTaskText, IProgressMonitor.UNKNOWN);
    boolean useIndex = compareVersion.equals(INDEX_VERSION);
    deletedPaths.clear();
    equalContentPaths.clear();
    baseVersionMap.clear();
    compareVersionMap.clear();
    compareVersionPathsWithChildren.clear();
    addedPaths.clear();
    baseVersionPathsWithChildren.clear();
    boolean checkIgnored = false;
    TreeWalk tw = new TreeWalk(repository);
    try {
      int baseTreeIndex;
      if (baseCommit == null) {
        checkIgnored = true;
        baseTreeIndex =
            tw.addTree(
                new AdaptableFileTreeIterator(
                    repository, ResourcesPlugin.getWorkspace().getRoot()));
      } else
        baseTreeIndex =
            tw.addTree(
                new CanonicalTreeParser(null, repository.newObjectReader(), baseCommit.getTree()));
      int compareTreeIndex;
      if (!useIndex)
        compareTreeIndex =
            tw.addTree(
                new CanonicalTreeParser(
                    null, repository.newObjectReader(), compareCommit.getTree()));
      else compareTreeIndex = tw.addTree(new DirCacheIterator(repository.readDirCache()));

      if (input instanceof IResource[]) {
        IResource[] resources = (IResource[]) input;
        List<TreeFilter> orFilters = new ArrayList<TreeFilter>(resources.length);

        for (IResource resource : resources) {
          String relPath = repositoryMapping.getRepoRelativePath(resource);
          if (relPath.length() > 0) orFilters.add(PathFilter.create(relPath));
        }
        if (orFilters.size() > 1) tw.setFilter(OrTreeFilter.create(orFilters));
        else if (orFilters.size() == 1) tw.setFilter(orFilters.get(0));
      }

      tw.setRecursive(true);

      if (monitor.isCanceled()) throw new InterruptedException();
      while (tw.next()) {
        if (monitor.isCanceled()) throw new InterruptedException();
        AbstractTreeIterator compareVersionIterator =
            tw.getTree(compareTreeIndex, AbstractTreeIterator.class);
        AbstractTreeIterator baseVersionIterator =
            tw.getTree(baseTreeIndex, AbstractTreeIterator.class);
        if (checkIgnored
            && baseVersionIterator != null
            && ((WorkingTreeIterator) baseVersionIterator).isEntryIgnored()) continue;
        if (compareVersionIterator != null && baseVersionIterator != null) {
          monitor.setTaskName(baseVersionIterator.getEntryPathString());
          IPath currentPath = new Path(baseVersionIterator.getEntryPathString());
          if (!useIndex)
            compareVersionMap.put(
                currentPath,
                GitFileRevision.inCommit(
                    repository,
                    compareCommit,
                    baseVersionIterator.getEntryPathString(),
                    tw.getObjectId(compareTreeIndex)));
          else
            compareVersionMap.put(
                currentPath,
                GitFileRevision.inIndex(repository, baseVersionIterator.getEntryPathString()));
          if (baseCommit != null)
            baseVersionMap.put(
                currentPath,
                GitFileRevision.inCommit(
                    repository,
                    baseCommit,
                    baseVersionIterator.getEntryPathString(),
                    tw.getObjectId(baseTreeIndex)));
          boolean equalContent =
              compareVersionIterator
                  .getEntryObjectId()
                  .equals(baseVersionIterator.getEntryObjectId());
          if (equalContent) equalContentPaths.add(currentPath);

          if (equalContent && !showEquals) continue;

          while (currentPath.segmentCount() > 0) {
            currentPath = currentPath.removeLastSegments(1);
            if (!baseVersionPathsWithChildren.add(currentPath)) break;
          }

        } else if (baseVersionIterator != null && compareVersionIterator == null) {
          monitor.setTaskName(baseVersionIterator.getEntryPathString());
          // only on base side
          IPath currentPath = new Path(baseVersionIterator.getEntryPathString());
          addedPaths.add(currentPath);
          if (baseCommit != null)
            baseVersionMap.put(
                currentPath,
                GitFileRevision.inCommit(
                    repository,
                    baseCommit,
                    baseVersionIterator.getEntryPathString(),
                    tw.getObjectId(baseTreeIndex)));
          while (currentPath.segmentCount() > 0) {
            currentPath = currentPath.removeLastSegments(1);
            if (!baseVersionPathsWithChildren.add(currentPath)) break;
          }

        } else if (compareVersionIterator != null && baseVersionIterator == null) {
          monitor.setTaskName(compareVersionIterator.getEntryPathString());
          // only on compare side
          IPath currentPath = new Path(compareVersionIterator.getEntryPathString());
          deletedPaths.add(currentPath);
          List<PathNodeAdapter> children =
              compareVersionPathsWithChildren.get(currentPath.removeLastSegments(1));
          if (children == null) {
            children = new ArrayList<PathNodeAdapter>(1);
            compareVersionPathsWithChildren.put(currentPath.removeLastSegments(1), children);
          }
          children.add(new PathNodeAdapter(new PathNode(currentPath, Type.FILE_DELETED)));

          if (!useIndex)
            compareVersionMap.put(
                currentPath,
                GitFileRevision.inCommit(
                    repository,
                    compareCommit,
                    compareVersionIterator.getEntryPathString(),
                    tw.getObjectId(compareTreeIndex)));
          else
            compareVersionMap.put(
                currentPath,
                GitFileRevision.inIndex(repository, compareVersionIterator.getEntryPathString()));
        }
      }
    } finally {
      tw.release();
      monitor.done();
    }
  }
예제 #13
0
  public HistoryPanel(
      String wicketId,
      final String repositoryName,
      final String objectId,
      final String path,
      Repository r,
      int limit,
      int pageOffset,
      boolean showRemoteRefs) {
    super(wicketId);
    boolean pageResults = limit <= 0;
    int itemsPerPage = GitBlit.getInteger(Keys.web.itemsPerPage, 50);
    if (itemsPerPage <= 1) {
      itemsPerPage = 50;
    }

    RevCommit commit = JGitUtils.getCommit(r, objectId);
    List<PathChangeModel> paths = JGitUtils.getFilesInCommit(r, commit);

    Map<String, SubmoduleModel> submodules = new HashMap<String, SubmoduleModel>();
    for (SubmoduleModel model : JGitUtils.getSubmodules(r, commit.getTree())) {
      submodules.put(model.path, model);
    }

    PathModel matchingPath = null;
    for (PathModel p : paths) {
      if (p.path.equals(path)) {
        matchingPath = p;
        break;
      }
    }
    if (matchingPath == null) {
      // path not in commit
      // manually locate path in tree
      TreeWalk tw = new TreeWalk(r);
      tw.reset();
      tw.setRecursive(true);
      try {
        tw.addTree(commit.getTree());
        tw.setFilter(PathFilterGroup.createFromStrings(Collections.singleton(path)));
        while (tw.next()) {
          if (tw.getPathString().equals(path)) {
            matchingPath =
                new PathChangeModel(
                    tw.getPathString(),
                    tw.getPathString(),
                    0,
                    tw.getRawMode(0),
                    tw.getObjectId(0).getName(),
                    commit.getId().getName(),
                    ChangeType.MODIFY);
          }
        }
      } catch (Exception e) {
      } finally {
        tw.release();
      }
    }

    final boolean isTree = matchingPath == null ? true : matchingPath.isTree();
    final boolean isSubmodule = matchingPath == null ? true : matchingPath.isSubmodule();

    // submodule
    SubmoduleModel submodule = getSubmodule(submodules, repositoryName, matchingPath.path);
    final String submodulePath;
    final boolean hasSubmodule;
    if (submodule != null) {
      submodulePath = submodule.gitblitPath;
      hasSubmodule = submodule.hasSubmodule;
    } else {
      submodulePath = "";
      hasSubmodule = false;
    }

    final Map<ObjectId, List<RefModel>> allRefs = JGitUtils.getAllRefs(r, showRemoteRefs);
    List<RevCommit> commits;
    if (pageResults) {
      // Paging result set
      commits = JGitUtils.getRevLog(r, objectId, path, pageOffset * itemsPerPage, itemsPerPage);
    } else {
      // Fixed size result set
      commits = JGitUtils.getRevLog(r, objectId, path, 0, limit);
    }

    // inaccurate way to determine if there are more commits.
    // works unless commits.size() represents the exact end.
    hasMore = commits.size() >= itemsPerPage;

    add(new CommitHeaderPanel("commitHeader", repositoryName, commit));

    // breadcrumbs
    add(new PathBreadcrumbsPanel("breadcrumbs", repositoryName, path, objectId));

    final int hashLen = GitBlit.getInteger(Keys.web.shortCommitIdLength, 6);
    ListDataProvider<RevCommit> dp = new ListDataProvider<RevCommit>(commits);
    DataView<RevCommit> logView =
        new DataView<RevCommit>("commit", dp) {
          private static final long serialVersionUID = 1L;
          int counter;

          public void populateItem(final Item<RevCommit> item) {
            final RevCommit entry = item.getModelObject();
            final Date date = JGitUtils.getCommitDate(entry);

            item.add(
                WicketUtils.createDateLabel("commitDate", date, getTimeZone(), getTimeUtils()));

            // author search link
            String author = entry.getAuthorIdent().getName();
            LinkPanel authorLink =
                new LinkPanel(
                    "commitAuthor",
                    "list",
                    author,
                    GitSearchPage.class,
                    WicketUtils.newSearchParameter(
                        repositoryName, objectId, author, Constants.SearchType.AUTHOR));
            setPersonSearchTooltip(authorLink, author, Constants.SearchType.AUTHOR);
            item.add(authorLink);

            // merge icon
            if (entry.getParentCount() > 1) {
              item.add(WicketUtils.newImage("commitIcon", "commit_merge_16x16.png"));
            } else {
              item.add(WicketUtils.newBlankImage("commitIcon"));
            }

            String shortMessage = entry.getShortMessage();
            String trimmedMessage = shortMessage;
            if (allRefs.containsKey(entry.getId())) {
              trimmedMessage = StringUtils.trimString(shortMessage, Constants.LEN_SHORTLOG_REFS);
            } else {
              trimmedMessage = StringUtils.trimString(shortMessage, Constants.LEN_SHORTLOG);
            }
            LinkPanel shortlog =
                new LinkPanel(
                    "commitShortMessage",
                    "list subject",
                    trimmedMessage,
                    CommitPage.class,
                    WicketUtils.newObjectParameter(repositoryName, entry.getName()));
            if (!shortMessage.equals(trimmedMessage)) {
              WicketUtils.setHtmlTooltip(shortlog, shortMessage);
            }
            item.add(shortlog);

            item.add(new RefsPanel("commitRefs", repositoryName, entry, allRefs));

            if (isTree) {
              // tree
              item.add(new Label("hashLabel", getString("gb.tree") + "@"));
              LinkPanel commitHash =
                  new LinkPanel(
                      "hashLink",
                      null,
                      entry.getName().substring(0, hashLen),
                      TreePage.class,
                      WicketUtils.newObjectParameter(repositoryName, entry.getName()));
              WicketUtils.setCssClass(commitHash, "shortsha1");
              WicketUtils.setHtmlTooltip(commitHash, entry.getName());
              item.add(commitHash);

              Fragment links = new Fragment("historyLinks", "treeLinks", this);
              links.add(
                  new BookmarkablePageLink<Void>(
                      "commitdiff",
                      CommitDiffPage.class,
                      WicketUtils.newObjectParameter(repositoryName, entry.getName())));
              item.add(links);
            } else if (isSubmodule) {
              // submodule
              item.add(new Label("hashLabel", submodulePath + "@"));
              Repository repository = GitBlit.self().getRepository(repositoryName);
              String submoduleId = JGitUtils.getSubmoduleCommitId(repository, path, entry);
              repository.close();
              LinkPanel commitHash =
                  new LinkPanel(
                      "hashLink",
                      null,
                      submoduleId.substring(0, hashLen),
                      TreePage.class,
                      WicketUtils.newObjectParameter(submodulePath, submoduleId));
              WicketUtils.setCssClass(commitHash, "shortsha1");
              WicketUtils.setHtmlTooltip(commitHash, submoduleId);
              item.add(commitHash.setEnabled(hasSubmodule));

              Fragment links = new Fragment("historyLinks", "treeLinks", this);
              links.add(
                  new BookmarkablePageLink<Void>(
                      "commitdiff",
                      CommitDiffPage.class,
                      WicketUtils.newObjectParameter(repositoryName, entry.getName())));
              item.add(links);
            } else {
              // commit
              item.add(new Label("hashLabel", getString("gb.blob") + "@"));
              LinkPanel commitHash =
                  new LinkPanel(
                      "hashLink",
                      null,
                      entry.getName().substring(0, hashLen),
                      BlobPage.class,
                      WicketUtils.newPathParameter(repositoryName, entry.getName(), path));
              WicketUtils.setCssClass(commitHash, "sha1");
              WicketUtils.setHtmlTooltip(commitHash, entry.getName());
              item.add(commitHash);

              Fragment links = new Fragment("historyLinks", "blobLinks", this);
              links.add(
                  new BookmarkablePageLink<Void>(
                      "commitdiff",
                      CommitDiffPage.class,
                      WicketUtils.newObjectParameter(repositoryName, entry.getName())));
              links.add(
                  new BookmarkablePageLink<Void>(
                          "difftocurrent",
                          BlobDiffPage.class,
                          WicketUtils.newBlobDiffParameter(
                              repositoryName, entry.getName(), objectId, path))
                      .setEnabled(counter > 0));
              item.add(links);
            }

            WicketUtils.setAlternatingBackground(item, counter);
            counter++;
          }
        };
    add(logView);

    // determine to show pager, more, or neither
    if (limit <= 0) {
      // no display limit
      add(new Label("moreHistory", "").setVisible(false));
    } else {
      if (pageResults) {
        // paging
        add(new Label("moreHistory", "").setVisible(false));
      } else {
        // more
        if (commits.size() == limit) {
          // show more
          add(
              new LinkPanel(
                  "moreHistory",
                  "link",
                  new StringResourceModel("gb.moreHistory", this, null),
                  HistoryPage.class,
                  WicketUtils.newPathParameter(repositoryName, objectId, path)));
        } else {
          // no more
          add(new Label("moreHistory", "").setVisible(false));
        }
      }
    }
  }
예제 #14
0
 protected PathInfo(TreeWalk tw) {
   fileMode = tw.getFileMode(0);
   path = tw.getPathString();
   objectId = tw.getObjectId(0);
 }
예제 #15
0
  @Override
  public List<CommitInfo> history(
      String objectId,
      String path,
      int limit,
      int pageOffset,
      boolean showRemoteRefs,
      int itemsPerPage) {
    try {
      if (itemsPerPage <= 1) {
        itemsPerPage = 50;
      }
      boolean pageResults = limit <= 0;
      Repository r = git.getRepository();

      // TODO not sure if this is the right String we should use for the sub module stuff...
      String repositoryName = getConfigDirectory().getPath();

      objectId = defaultObjectId(objectId);
      RevCommit commit = JGitUtils.getCommit(r, objectId);
      List<PathModel.PathChangeModel> paths = JGitUtils.getFilesInCommit(r, commit);

      Map<String, SubmoduleModel> submodules = new HashMap<String, SubmoduleModel>();
      for (SubmoduleModel model : JGitUtils.getSubmodules(r, commit.getTree())) {
        submodules.put(model.path, model);
      }

      PathModel matchingPath = null;
      for (PathModel p : paths) {
        if (p.path.equals(path)) {
          matchingPath = p;
          break;
        }
      }
      if (matchingPath == null) {
        // path not in commit
        // manually locate path in tree
        TreeWalk tw = new TreeWalk(r);
        tw.reset();
        tw.setRecursive(true);
        try {
          tw.addTree(commit.getTree());
          tw.setFilter(PathFilterGroup.createFromStrings(Collections.singleton(path)));
          while (tw.next()) {
            if (tw.getPathString().equals(path)) {
              matchingPath =
                  new PathModel.PathChangeModel(
                      tw.getPathString(),
                      tw.getPathString(),
                      0,
                      tw.getRawMode(0),
                      tw.getObjectId(0).getName(),
                      commit.getId().getName(),
                      ChangeType.MODIFY);
            }
          }
        } catch (Exception e) {
        } finally {
          tw.release();
        }
      }

      final boolean isTree = matchingPath == null ? true : matchingPath.isTree();
      final boolean isSubmodule = matchingPath == null ? true : matchingPath.isSubmodule();

      // submodule
      SubmoduleModel submodule = null;
      if (matchingPath != null) {
        submodule = getSubmodule(submodules, repositoryName, matchingPath.path);
      }
      final String submodulePath;
      final boolean hasSubmodule;
      if (submodule != null) {
        submodulePath = submodule.gitblitPath;
        hasSubmodule = submodule.hasSubmodule;
      } else {
        submodulePath = "";
        hasSubmodule = false;
      }

      final Map<ObjectId, List<RefModel>> allRefs = JGitUtils.getAllRefs(r, showRemoteRefs);
      List<RevCommit> commits;
      if (pageResults) {
        // Paging result set
        commits = JGitUtils.getRevLog(r, objectId, path, pageOffset * itemsPerPage, itemsPerPage);
      } else {
        // Fixed size result set
        commits = JGitUtils.getRevLog(r, objectId, path, 0, limit);
      }

      // inaccurate way to determine if there are more commits.
      // works unless commits.size() represents the exact end.
      boolean hasMore = commits.size() >= itemsPerPage;

      List<CommitInfo> results = new ArrayList<CommitInfo>();
      for (RevCommit entry : commits) {
        final Date date = JGitUtils.getCommitDate(entry);
        String author = entry.getAuthorIdent().getName();
        boolean merge = entry.getParentCount() > 1;

        String shortMessage = entry.getShortMessage();
        String trimmedMessage = shortMessage;
        if (allRefs.containsKey(entry.getId())) {
          trimmedMessage = StringUtils.trimString(shortMessage, Constants.LEN_SHORTLOG_REFS);
        } else {
          trimmedMessage = StringUtils.trimString(shortMessage, Constants.LEN_SHORTLOG);
        }
        String name = entry.getName();
        String commitHashText = getShortCommitHash(name);

        String kind;
        if (isTree) {
          kind = "tree";
        } else if (isSubmodule) {
          kind = "submodule";
        } else kind = "file";

        results.add(
            new CommitInfo(
                commitHashText, name, kind, author, date, merge, trimmedMessage, shortMessage));
      }
      return results;
    } catch (Exception e) {
      throw new RuntimeIOException(e);
    }
  }
예제 #16
0
  @Override
  protected void doGet(final HttpServletRequest req, final HttpServletResponse rsp)
      throws IOException {
    String keyStr = req.getPathInfo();

    // We shouldn't have to do this extra decode pass, but somehow we
    // are now receiving our "^1" suffix as "%5E1", which confuses us
    // downstream. Other times we get our embedded "," as "%2C", which
    // is equally bad. And yet when these happen a "%2F" is left as-is,
    // rather than escaped as "%252F", which makes me feel really really
    // uncomfortable with a blind decode right here.
    //
    keyStr = URLDecoder.decode(keyStr, "UTF-8");

    if (!keyStr.startsWith("/")) {
      rsp.sendError(HttpServletResponse.SC_NOT_FOUND);
      return;
    }
    keyStr = keyStr.substring(1);

    final Patch.Key patchKey;
    final int side;
    {
      final int c = keyStr.lastIndexOf('^');
      if (c == 0) {
        rsp.sendError(HttpServletResponse.SC_NOT_FOUND);
        return;
      }

      if (c < 0) {
        side = 0;

      } else {
        try {
          side = Integer.parseInt(keyStr.substring(c + 1));
          keyStr = keyStr.substring(0, c);
        } catch (NumberFormatException e) {
          rsp.sendError(HttpServletResponse.SC_NOT_FOUND);
          return;
        }
      }

      try {
        patchKey = Patch.Key.parse(keyStr);
      } catch (NumberFormatException e) {
        rsp.sendError(HttpServletResponse.SC_NOT_FOUND);
        return;
      }
    }

    final Change.Id changeId = patchKey.getParentKey().getParentKey();
    final Project project;
    final PatchSet patchSet;
    try {
      final ReviewDb db = requestDb.get();
      final ChangeControl control = changeControl.validateFor(changeId);

      project = control.getProject();
      patchSet = db.patchSets().get(patchKey.getParentKey());
      if (patchSet == null) {
        rsp.sendError(HttpServletResponse.SC_NOT_FOUND);
        return;
      }
    } catch (NoSuchChangeException e) {
      rsp.sendError(HttpServletResponse.SC_NOT_FOUND);
      return;
    } catch (OrmException e) {
      getServletContext().log("Cannot query database", e);
      rsp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
      return;
    }

    final Repository repo;
    try {
      repo = repoManager.openRepository(project.getNameKey());
    } catch (RepositoryNotFoundException e) {
      getServletContext().log("Cannot open repository", e);
      rsp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
      return;
    }

    final ObjectLoader blobLoader;
    final RevCommit fromCommit;
    final String suffix;
    final String path = patchKey.getFileName();
    try {
      final ObjectReader reader = repo.newObjectReader();
      try {
        final RevWalk rw = new RevWalk(reader);
        final RevCommit c;
        final TreeWalk tw;

        c = rw.parseCommit(ObjectId.fromString(patchSet.getRevision().get()));
        if (side == 0) {
          fromCommit = c;
          suffix = "new";

        } else if (1 <= side && side - 1 < c.getParentCount()) {
          fromCommit = rw.parseCommit(c.getParent(side - 1));
          if (c.getParentCount() == 1) {
            suffix = "old";
          } else {
            suffix = "old" + side;
          }

        } else {
          rsp.sendError(HttpServletResponse.SC_NOT_FOUND);
          return;
        }

        tw = TreeWalk.forPath(reader, path, fromCommit.getTree());
        if (tw == null) {
          rsp.sendError(HttpServletResponse.SC_NOT_FOUND);
          return;
        }

        if (tw.getFileMode(0).getObjectType() == Constants.OBJ_BLOB) {
          blobLoader = reader.open(tw.getObjectId(0), Constants.OBJ_BLOB);

        } else {
          rsp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
          return;
        }
      } finally {
        reader.release();
      }
    } catch (IOException e) {
      getServletContext().log("Cannot read repository", e);
      rsp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
      return;
    } catch (RuntimeException e) {
      getServletContext().log("Cannot read repository", e);
      rsp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
      return;
    } finally {
      repo.close();
    }

    final byte[] raw = blobLoader.isLarge() ? null : blobLoader.getCachedBytes();
    final long when = fromCommit.getCommitTime() * 1000L;

    rsp.setDateHeader("Last-Modified", when);
    rsp.setDateHeader("Expires", 0L);
    rsp.setHeader("Pragma", "no-cache");
    rsp.setHeader("Cache-Control", "no-cache, must-revalidate");

    OutputStream out;
    ZipOutputStream zo;

    final MimeType contentType = registry.getMimeType(path, raw);
    if (!registry.isSafeInline(contentType)) {
      // The content may not be safe to transmit inline, as a browser might
      // interpret it as HTML or JavaScript hosted by this site. Such code
      // might then run in the site's security domain, and may be able to use
      // the user's cookies to perform unauthorized actions.
      //
      // Usually, wrapping the content into a ZIP file forces the browser to
      // save the content to the local system instead.
      //

      rsp.setContentType(ZIP.toString());
      rsp.setHeader(
          "Content-Disposition",
          "attachment; filename=\"" + safeFileName(path, suffix) + ".zip" + "\"");

      zo = new ZipOutputStream(rsp.getOutputStream());

      final ZipEntry e = new ZipEntry(safeFileName(path, rand(req, suffix)));
      e.setComment(fromCommit.name() + ":" + path);
      e.setSize(blobLoader.getSize());
      e.setTime(when);
      zo.putNextEntry(e);
      out = zo;

    } else {
      rsp.setContentType(contentType.toString());
      rsp.setHeader("Content-Length", "" + blobLoader.getSize());

      out = rsp.getOutputStream();
      zo = null;
    }

    if (raw != null) {
      out.write(raw);
    } else {
      blobLoader.copyTo(out);
    }

    if (zo != null) {
      zo.closeEntry();
    }
    out.close();
  }
  private IDiffContainer buildDiffContainer(
      RevCommit baseCommit, RevCommit compareCommit, IProgressMonitor monitor)
      throws IOException, InterruptedException {
    boolean useIndex = compareVersion.equals(CompareTreeView.INDEX_VERSION);
    boolean checkIgnored = false;

    IDiffContainer result = new DiffNode(Differencer.CONFLICTING);

    try (TreeWalk tw = new TreeWalk(repository)) {

      // filter by selected resources
      if (filterPathStrings.size() > 1) {
        List<TreeFilter> suffixFilters = new ArrayList<TreeFilter>();
        for (String filterPath : filterPathStrings)
          suffixFilters.add(PathFilter.create(filterPath));
        TreeFilter otf = OrTreeFilter.create(suffixFilters);
        tw.setFilter(otf);
      } else if (filterPathStrings.size() > 0) {
        String path = filterPathStrings.get(0);
        if (path.length() != 0) tw.setFilter(PathFilter.create(path));
      }

      tw.setRecursive(true);

      int baseTreeIndex;
      if (baseCommit == null) {
        // compare workspace with something
        checkIgnored = true;
        baseTreeIndex = tw.addTree(new FileTreeIterator(repository));
      } else
        baseTreeIndex =
            tw.addTree(
                new CanonicalTreeParser(null, repository.newObjectReader(), baseCommit.getTree()));
      int compareTreeIndex;
      if (!useIndex)
        compareTreeIndex =
            tw.addTree(
                new CanonicalTreeParser(
                    null, repository.newObjectReader(), compareCommit.getTree()));
      else
        // compare something with the index
        compareTreeIndex = tw.addTree(new DirCacheIterator(repository.readDirCache()));

      while (tw.next()) {
        if (monitor.isCanceled()) throw new InterruptedException();
        AbstractTreeIterator compareVersionIterator =
            tw.getTree(compareTreeIndex, AbstractTreeIterator.class);
        AbstractTreeIterator baseVersionIterator =
            tw.getTree(baseTreeIndex, AbstractTreeIterator.class);
        if (checkIgnored
            && baseVersionIterator != null
            && ((WorkingTreeIterator) baseVersionIterator).isEntryIgnored()) continue;

        if (compareVersionIterator != null && baseVersionIterator != null) {
          boolean equalContent =
              compareVersionIterator
                  .getEntryObjectId()
                  .equals(baseVersionIterator.getEntryObjectId());
          if (equalContent) continue;
        }

        String encoding = null;

        GitFileRevision compareRev = null;
        if (compareVersionIterator != null) {
          String entryPath = compareVersionIterator.getEntryPathString();
          encoding = CompareCoreUtils.getResourceEncoding(repository, entryPath);
          if (!useIndex)
            compareRev =
                GitFileRevision.inCommit(
                    repository, compareCommit, entryPath, tw.getObjectId(compareTreeIndex));
          else compareRev = GitFileRevision.inIndex(repository, entryPath);
        }

        GitFileRevision baseRev = null;
        if (baseVersionIterator != null) {
          String entryPath = baseVersionIterator.getEntryPathString();
          if (encoding == null) {
            encoding = CompareCoreUtils.getResourceEncoding(repository, entryPath);
          }
          baseRev =
              GitFileRevision.inCommit(
                  repository, baseCommit, entryPath, tw.getObjectId(baseTreeIndex));
        }

        if (compareVersionIterator != null && baseVersionIterator != null) {
          monitor.setTaskName(baseVersionIterator.getEntryPathString());
          // content exists on both sides
          add(
              result,
              baseVersionIterator.getEntryPathString(),
              new DiffNode(
                  new FileRevisionTypedElement(compareRev, encoding),
                  new FileRevisionTypedElement(baseRev, encoding)));
        } else if (baseVersionIterator != null && compareVersionIterator == null) {
          monitor.setTaskName(baseVersionIterator.getEntryPathString());
          // only on base side
          add(
              result,
              baseVersionIterator.getEntryPathString(),
              new DiffNode(
                  Differencer.DELETION | Differencer.RIGHT,
                  null,
                  null,
                  new FileRevisionTypedElement(baseRev, encoding)));
        } else if (compareVersionIterator != null && baseVersionIterator == null) {
          monitor.setTaskName(compareVersionIterator.getEntryPathString());
          // only on compare side
          add(
              result,
              compareVersionIterator.getEntryPathString(),
              new DiffNode(
                  Differencer.ADDITION | Differencer.RIGHT,
                  null,
                  new FileRevisionTypedElement(compareRev, encoding),
                  null));
        }

        if (monitor.isCanceled()) throw new InterruptedException();
      }
      return result;
    }
  }
예제 #18
0
  public Map<String, Object> toSoyData(ObjectId treeId, TreeWalk tw)
      throws MissingObjectException, IOException {
    ReadmeHelper readme =
        new ReadmeHelper(reader, view, MarkdownConfig.get(cfg), rootTree, requestUri);
    List<Object> entries = Lists.newArrayList();
    GitilesView.Builder urlBuilder = GitilesView.path().copyFrom(view);
    while (tw.next()) {
      FileType type = FileType.forEntry(tw);
      String name = tw.getNameString();

      GitilesView.Type viewType = view.getType();
      if (viewType == GitilesView.Type.PATH) {
        urlBuilder.setPathPart(view.getPathPart() + "/" + name);
      } else if (viewType == GitilesView.Type.REVISION) {
        // Got here from a tag pointing at a tree.
        urlBuilder.setPathPart(name);
      } else {
        throw new IllegalStateException(
            String.format("Cannot render TreeSoyData from %s view", viewType));
      }

      String url = urlBuilder.toUrl();
      if (type == FileType.TREE) {
        name += "/";
        url += "/";
      }
      Map<String, String> entry = Maps.newHashMapWithExpectedSize(4);
      entry.put("type", type.toString());
      entry.put("name", name);
      entry.put("url", url);
      if (type == FileType.SYMLINK) {
        String target = new String(reader.open(tw.getObjectId(0)).getCachedBytes(), UTF_8);
        entry.put("targetName", getTargetDisplayName(target));
        String targetUrl = resolveTargetUrl(view, target);
        if (targetUrl != null) {
          entry.put("targetUrl", targetUrl);
        }
      } else {
        readme.considerEntry(tw);
      }
      entries.add(entry);
    }

    Map<String, Object> data = Maps.newHashMapWithExpectedSize(3);
    data.put("sha", treeId.name());
    data.put("entries", entries);

    if (view.getType() == GitilesView.Type.PATH
        && view.getRevision().getPeeledType() == OBJ_COMMIT) {
      data.put("logUrl", GitilesView.log().copyFrom(view).toUrl());
      data.put(
          "archiveUrl",
          GitilesView.archive()
              .copyFrom(view)
              .setPathPart(Strings.emptyToNull(view.getPathPart()))
              .setExtension(archiveFormat.getDefaultSuffix())
              .toUrl());
      data.put("archiveType", archiveFormat.getShortName());
    }

    if (readme.isPresent()) {
      data.put("readmePath", readme.getPath());
      data.put("readmeHtml", readme.render());
    }

    return data;
  }
예제 #19
0
  protected void addInformationForPath(
      Repository repository,
      Git git,
      DocumentWriter writer,
      RevCommit commit,
      String path,
      CallSpecification spec,
      Values values)
      throws GitAPIException, IOException {
    // Make sure the path is in the canonical form we need ...
    if (path.startsWith("/")) {
      if (path.length() == 1) path = "";
      else path = path.substring(1);
    }

    // Now see if we're actually referring to the "jcr:content" node ...
    boolean isContentNode = false;
    if (path.endsWith(JCR_CONTENT_SUFFIX)) {
      isContentNode = true;
      path = path.substring(0, path.length() - JCR_CONTENT_SUFFIX.length());
    }

    // Create the TreeWalk that we'll use to navigate the files/directories ...
    final TreeWalk tw = new TreeWalk(repository);
    tw.addTree(commit.getTree());
    if ("".equals(path)) {
      // This is the top-level directory, so we don't need to pre-walk to find anything ...
      tw.setRecursive(false);
      while (tw.next()) {
        String childName = tw.getNameString();
        String childId = spec.childId(childName);
        writer.addChild(childId, childName);
      }
    } else {
      // We need to first find our path *before* we can walk the children ...
      PathFilter filter = PathFilter.create(path);
      tw.setFilter(filter);
      while (tw.next()) {
        if (filter.isDone(tw)) {
          break;
        } else if (tw.isSubtree()) {
          tw.enterSubtree();
        }
      }
      // Now that the TreeWalk is the in right location given by the 'path', we can get the
      if (tw.isSubtree()) {
        // The object at the 'path' is a directory, so go into it ...
        tw.enterSubtree();

        // Find the commit in which this folder was last modified ...
        // This may not be terribly efficient, but it seems to work faster on subsequent runs ...
        RevCommit folderCommit = git.log().addPath(path).call().iterator().next();

        // Add folder-related properties ...
        String committer = folderCommit.getCommitterIdent().getName();
        String author = folderCommit.getAuthorIdent().getName();
        DateTime committed = values.dateFrom(folderCommit.getCommitTime());
        writer.setPrimaryType(GitLexicon.FOLDER);
        writer.addProperty(JcrLexicon.CREATED, committed);
        writer.addProperty(JcrLexicon.CREATED_BY, committer);
        writer.addProperty(GitLexicon.OBJECT_ID, folderCommit.getId().name());
        writer.addProperty(GitLexicon.AUTHOR, author);
        writer.addProperty(GitLexicon.COMMITTER, committer);
        writer.addProperty(GitLexicon.COMMITTED, committed);
        writer.addProperty(GitLexicon.TITLE, folderCommit.getShortMessage());

        // And now walk the contents of the directory ...
        while (tw.next()) {
          String childName = tw.getNameString();
          String childId = spec.childId(childName);
          writer.addChild(childId, childName);
        }
      } else {
        // The path specifies a file (or a content node) ...

        // Find the commit in which this folder was last modified ...
        // This may not be terribly efficient, but it seems to work faster on subsequent runs ...
        RevCommit fileCommit = git.log().addPath(path).call().iterator().next();

        // Add file-related properties ...
        String committer = fileCommit.getCommitterIdent().getName();
        String author = fileCommit.getAuthorIdent().getName();
        DateTime committed = values.dateFrom(fileCommit.getCommitTime());
        if (isContentNode) {
          writer.setPrimaryType(GitLexicon.RESOURCE);
          writer.addProperty(JcrLexicon.LAST_MODIFIED, committed);
          writer.addProperty(JcrLexicon.LAST_MODIFIED_BY, committer);
          writer.addProperty(GitLexicon.OBJECT_ID, fileCommit.getId().name());
          writer.addProperty(GitLexicon.AUTHOR, author);
          writer.addProperty(GitLexicon.COMMITTER, committer);
          writer.addProperty(GitLexicon.COMMITTED, committed);
          writer.addProperty(GitLexicon.TITLE, fileCommit.getShortMessage());
          // Create the BinaryValue ...
          ObjectId fileObjectId = tw.getObjectId(0);
          ObjectLoader fileLoader = repository.open(fileObjectId);
          BinaryKey key = new BinaryKey(fileObjectId.getName());
          BinaryValue value = values.binaryFor(key, fileLoader.getSize());
          if (value == null) {
            // It wasn't found in the binary store ...
            if (fileLoader.isLarge()) {
              // Too large to hold in memory, so use the binary store (which reads the file
              // immediately) ...
              value = values.binaryFrom(fileLoader.openStream());
            } else {
              // This is small enough to fit into a byte[], but it still may be pretty big ...
              value =
                  new GitBinaryValue(
                      fileObjectId,
                      fileLoader,
                      connector.getSourceName(),
                      name,
                      connector.getMimeTypeDetector());
            }
          }
          writer.addProperty(JcrLexicon.DATA, value);
          if (connector.includeMimeType()) {
            try {
              String filename =
                  spec.parameter(spec.parameterCount() - 1); // the last is 'jcr:content'
              String mimeType = value.getMimeType(filename);
              if (mimeType != null) writer.addProperty(JcrLexicon.MIMETYPE, mimeType);
            } catch (RepositoryException e) {
              // do nothing
            } catch (IOException e) {
              // do nothing
            }
          }
        } else {
          writer.setPrimaryType(GitLexicon.FILE);
          writer.addProperty(JcrLexicon.CREATED, committed);
          writer.addProperty(JcrLexicon.CREATED_BY, committer);
          writer.addProperty(GitLexicon.OBJECT_ID, fileCommit.getId().name());
          writer.addProperty(GitLexicon.AUTHOR, author);
          writer.addProperty(GitLexicon.COMMITTER, committer);
          writer.addProperty(GitLexicon.COMMITTED, committed);
          writer.addProperty(GitLexicon.TITLE, fileCommit.getShortMessage());

          // Add the "jcr:content" child node ...
          String childId = spec.childId(JCR_CONTENT);
          writer.addChild(childId, JCR_CONTENT);
        }
      }
    }
  }