Esempio n. 1
0
  private boolean processOne(Candidate n) throws IOException {
    RevCommit parent = n.getParent(0);
    if (parent == null) return split(n.getNextCandidate(0), n);
    revPool.parseHeaders(parent);

    if (find(parent, n.sourcePath)) {
      if (idBuf.equals(n.sourceBlob)) return blameEntireRegionOnParent(n, parent);
      return splitBlameWithParent(n, parent);
    }

    if (n.sourceCommit == null) return result(n);

    DiffEntry r = findRename(parent, n.sourceCommit, n.sourcePath);
    if (r == null) return result(n);

    if (0 == r.getOldId().prefixCompare(n.sourceBlob)) {
      // A 100% rename without any content change can also
      // skip directly to the parent.
      n.sourceCommit = parent;
      n.sourcePath = PathFilter.create(r.getOldPath());
      push(n);
      return false;
    }

    Candidate next = n.create(parent, PathFilter.create(r.getOldPath()));
    next.sourceBlob = r.getOldId().toObjectId();
    next.renameScore = r.getScore();
    next.loadText(reader);
    return split(next, n);
  }
  protected boolean hasIgnoreFile(Repository repository, RevCommit revCommit, String relativePath)
      throws Exception {

    if (_ignoreFileName == null) {
      return false;
    }

    try (TreeWalk treeWalk = new TreeWalk(repository)) {
      treeWalk.addTree(revCommit.getTree());

      if (revCommit.getParentCount() > 0) {
        RevCommit parentRevCommit = revCommit.getParent(0);

        treeWalk.addTree(parentRevCommit.getTree());
      }

      treeWalk.setRecursive(true);

      treeWalk.setFilter(
          AndTreeFilter.create(
              PathFilter.create(relativePath + "/" + _ignoreFileName), TreeFilter.ANY_DIFF));

      return treeWalk.next();
    }
  }
Esempio n. 3
0
  /**
   * Create a blame generator for the repository and path (relative to repository)
   *
   * @param repository repository to access revision data from.
   * @param path initial path of the file to start scanning (relative to the repository).
   */
  public BlameGenerator(Repository repository, String path) {
    this.repository = repository;
    this.resultPath = PathFilter.create(path);

    idBuf = new MutableObjectId();
    setFollowFileRenames(true);
    initRevPool(false);

    remaining = -1;
  }
Esempio n. 4
0
 @SuppressWarnings("nls")
 @Override
 public String toString() {
   return "(FOLLOW("
       + path.toString()
       + ")" //
       + " AND " //
       + ANY_DIFF.toString()
       + ")";
 }
Esempio n. 5
0
  private DiffEntry findRename(RevCommit parent, RevCommit commit, PathFilter path)
      throws IOException {
    if (renameDetector == null) return null;

    treeWalk.setFilter(TreeFilter.ANY_DIFF);
    treeWalk.reset(parent.getTree(), commit.getTree());
    renameDetector.reset();
    renameDetector.addAll(DiffEntry.scan(treeWalk));
    for (DiffEntry ent : renameDetector.compute()) {
      if (isRename(ent) && ent.getNewPath().equals(path.getPath())) return ent;
    }
    return null;
  }
Esempio n. 6
0
 private boolean isModified(String path) throws CorruptObjectException, IOException {
   NameConflictTreeWalk tw = new NameConflictTreeWalk(repo);
   tw.addTree(new DirCacheIterator(dc));
   tw.addTree(new FileTreeIterator(repo));
   tw.setRecursive(true);
   tw.setFilter(PathFilter.create(path));
   DirCacheIterator dcIt;
   WorkingTreeIterator wtIt;
   while (tw.next()) {
     dcIt = tw.getTree(0, DirCacheIterator.class);
     wtIt = tw.getTree(1, WorkingTreeIterator.class);
     if (dcIt == null || wtIt == null) return true;
     if (wtIt.isModified(dcIt.getDirCacheEntry(), true)) {
       return true;
     }
   }
   return false;
 }
 /**
  * Returns the list of files in the specified folder at the specified commit. If the repository
  * does not exist or is empty, an empty list is returned.
  *
  * @param repository
  * @param path if unspecified, root folder is assumed.
  * @param commit if null, HEAD is assumed.
  * @return list of files in specified path
  */
 public static List<PathModel> getFilesInPath(
     Repository repository, String path, RevCommit commit) {
   List<PathModel> list = new ArrayList<PathModel>();
   if (!hasCommits(repository)) {
     return list;
   }
   if (commit == null) {
     commit = getCommit(repository, null);
   }
   final TreeWalk tw = new TreeWalk(repository);
   try {
     tw.addTree(commit.getTree());
     if (!(path == null)) {
       PathFilter f = PathFilter.create(path);
       tw.setFilter(f);
       tw.setRecursive(false);
       boolean foundFolder = false;
       while (tw.next()) {
         if (!foundFolder && tw.isSubtree()) {
           tw.enterSubtree();
         }
         if (tw.getPathString().equals(path)) {
           foundFolder = true;
           continue;
         }
         if (foundFolder) {
           list.add(getPathModel(tw, path, commit));
         }
       }
     } else {
       tw.setRecursive(false);
       while (tw.next()) {
         list.add(getPathModel(tw, null, commit));
       }
     }
   } catch (IOException e) {
     // error(e, repository, "{0} failed to get files for commit {1}", commit.getName());
     Logger.error(e, e.getMessage());
   } finally {
     tw.release();
   }
   Collections.sort(list);
   return list;
 }
Esempio n. 8
0
  /**
   * Determine the differences between two trees.
   *
   * <p>No output is created, instead only the file paths that are different are returned. Callers
   * may choose to format these paths themselves, or convert them into {@link FileHeader} instances
   * with a complete edit list by calling {@link #toFileHeader(DiffEntry)}.
   *
   * @param a the old (or previous) side.
   * @param b the new (or updated) side.
   * @return the paths that are different.
   * @throws IOException trees cannot be read or file contents cannot be read.
   */
  public List<DiffEntry> scan(AbstractTreeIterator a, AbstractTreeIterator b) throws IOException {
    assertHaveRepository();

    TreeWalk walk = new TreeWalk(reader);
    walk.addTree(a);
    walk.addTree(b);
    walk.setRecursive(true);

    TreeFilter filter = getDiffTreeFilterFor(a, b);
    if (pathFilter instanceof FollowFilter) {
      walk.setFilter(
          AndTreeFilter.create(PathFilter.create(((FollowFilter) pathFilter).getPath()), filter));
    } else {
      walk.setFilter(AndTreeFilter.create(pathFilter, filter));
    }

    source = new ContentSource.Pair(source(a), source(b));

    List<DiffEntry> files = DiffEntry.scan(walk);
    if (pathFilter instanceof FollowFilter && isAdd(files)) {
      // The file we are following was added here, find where it
      // came from so we can properly show the rename or copy,
      // then continue digging backwards.
      //
      a.reset();
      b.reset();
      walk.reset();
      walk.addTree(a);
      walk.addTree(b);
      walk.setFilter(filter);

      if (renameDetector == null) setDetectRenames(true);
      files = updateFollowFilter(detectRenames(DiffEntry.scan(walk)));

    } else if (renameDetector != null) files = detectRenames(files);

    return files;
  }
Esempio n. 9
0
 /** @return the path this filter matches. */
 public String getPath() {
   return path.getPath();
 }
Esempio n. 10
0
 /**
  * Is the configured already a submodule in the index?
  *
  * @return true if submodule exists in index, false otherwise
  * @throws IOException
  */
 protected boolean submoduleExists() throws IOException {
   TreeFilter filter = PathFilter.create(path);
   return SubmoduleWalk.forIndex(repo).setFilter(filter).next();
 }
  @Override
  public void execute() throws BuildException {
    if (_property == null) {
      throw new BuildException("Property attribute is required", getLocation());
    }

    if (_path == null) {
      throw new BuildException("Path attribute is required", getLocation());
    }

    File gitDir = PathUtil.getGitDir(_gitDir, getProject(), getLocation());

    String relativePath = PathUtil.toRelativePath(gitDir, _path);

    if (_useCache) {
      String hash = _hashes.get(relativePath);

      if (hash != null) {
        Project currentProject = getProject();

        currentProject.setNewProperty(_property, hash);

        return;
      }
    }

    try (Repository repository = RepositoryCache.open(FileKey.exact(gitDir, FS.DETECTED))) {

      RevWalk revWalk = new RevWalk(repository);

      revWalk.setRetainBody(false);

      revWalk.markStart(revWalk.parseCommit(repository.resolve(Constants.HEAD)));

      if (_ignoreFileName == null) {
        revWalk.setRevFilter(MaxCountRevFilter.create(1));
      } else {
        revWalk.setRevFilter(MaxCountRevFilter.create(2));
      }

      revWalk.setTreeFilter(
          AndTreeFilter.create(PathFilter.create(relativePath), TreeFilter.ANY_DIFF));

      RevCommit revCommit = revWalk.next();

      if (revCommit == null) {
        throw new IllegalStateException("Unable to find any commit under " + _path);
      }

      if (hasIgnoreFile(repository, revCommit, relativePath)) {
        RevCommit secondRevCommit = revWalk.next();

        if (secondRevCommit != null) {
          revCommit = secondRevCommit;
        }
      }

      Project currentProject = getProject();

      String hash = revCommit.name();

      currentProject.setNewProperty(_property, hash);

      if (_useCache) {
        _hashes.put(relativePath, hash);
      }

      revWalk.dispose();
    } catch (Exception e) {
      throw new BuildException("Unable to get head hash for path " + _path, e);
    }
  }
Esempio n. 12
0
  private boolean processMerge(Candidate n) throws IOException {
    int pCnt = n.getParentCount();

    // If any single parent exactly matches the merge, follow only
    // that one parent through history.
    ObjectId[] ids = null;
    for (int pIdx = 0; pIdx < pCnt; pIdx++) {
      RevCommit parent = n.getParent(pIdx);
      revPool.parseHeaders(parent);
      if (!find(parent, n.sourcePath)) continue;
      if (!(n instanceof ReverseCandidate) && idBuf.equals(n.sourceBlob))
        return blameEntireRegionOnParent(n, parent);
      if (ids == null) ids = new ObjectId[pCnt];
      ids[pIdx] = idBuf.toObjectId();
    }

    // If rename detection is enabled, search for any relevant names.
    DiffEntry[] renames = null;
    if (renameDetector != null) {
      renames = new DiffEntry[pCnt];
      for (int pIdx = 0; pIdx < pCnt; pIdx++) {
        RevCommit parent = n.getParent(pIdx);
        if (ids != null && ids[pIdx] != null) continue;

        DiffEntry r = findRename(parent, n.sourceCommit, n.sourcePath);
        if (r == null) continue;

        if (n instanceof ReverseCandidate) {
          if (ids == null) ids = new ObjectId[pCnt];
          ids[pCnt] = r.getOldId().toObjectId();
        } else if (0 == r.getOldId().prefixCompare(n.sourceBlob)) {
          // A 100% rename without any content change can also
          // skip directly to the parent. Note this bypasses an
          // earlier parent that had the path (above) but did not
          // have an exact content match. For performance reasons
          // we choose to follow the one parent over trying to do
          // possibly both parents.
          n.sourcePath = PathFilter.create(r.getOldPath());
          return blameEntireRegionOnParent(n, parent);
        }

        renames[pIdx] = r;
      }
    }

    // Construct the candidate for each parent.
    Candidate[] parents = new Candidate[pCnt];
    for (int pIdx = 0; pIdx < pCnt; pIdx++) {
      RevCommit parent = n.getParent(pIdx);

      Candidate p;
      if (renames != null && renames[pIdx] != null) {
        p = n.create(parent, PathFilter.create(renames[pIdx].getOldPath()));
        p.renameScore = renames[pIdx].getScore();
        p.sourceBlob = renames[pIdx].getOldId().toObjectId();
      } else if (ids != null && ids[pIdx] != null) {
        p = n.create(parent, n.sourcePath);
        p.sourceBlob = ids[pIdx];
      } else {
        continue;
      }

      EditList editList;
      if (n instanceof ReverseCandidate && p.sourceBlob.equals(n.sourceBlob)) {
        // This special case happens on ReverseCandidate forks.
        p.sourceText = n.sourceText;
        editList = new EditList(0);
      } else {
        p.loadText(reader);
        editList = diffAlgorithm.diff(textComparator, p.sourceText, n.sourceText);
      }

      if (editList.isEmpty()) {
        // Ignoring whitespace (or some other special comparator) can
        // cause non-identical blobs to have an empty edit list. In
        // a case like this push the parent alone.
        if (n instanceof ReverseCandidate) {
          parents[pIdx] = p;
          continue;
        }

        p.regionList = n.regionList;
        n.regionList = null;
        parents[pIdx] = p;
        break;
      }

      p.takeBlame(editList, n);

      // Only remember this parent candidate if there is at least
      // one region that was blamed on the parent.
      if (p.regionList != null) {
        // Reverse blame requires inverting the regions. This puts
        // the regions the parent deleted from us into the parent,
        // and retains the common regions to look at other parents
        // for deletions.
        if (n instanceof ReverseCandidate) {
          Region r = p.regionList;
          p.regionList = n.regionList;
          n.regionList = r;
        }

        parents[pIdx] = p;
      }
    }

    if (n instanceof ReverseCandidate) {
      // On a reverse blame report all deletions found in the children,
      // and pass on to them a copy of our region list.
      Candidate resultHead = null;
      Candidate resultTail = null;

      for (int pIdx = 0; pIdx < pCnt; pIdx++) {
        Candidate p = parents[pIdx];
        if (p == null) continue;

        if (p.regionList != null) {
          Candidate r = p.copy(p.sourceCommit);
          if (resultTail != null) {
            resultTail.queueNext = r;
            resultTail = r;
          } else {
            resultHead = r;
            resultTail = r;
          }
        }

        if (n.regionList != null) {
          p.regionList = n.regionList.deepCopy();
          push(p);
        }
      }

      if (resultHead != null) return result(resultHead);
      return false;
    }

    // Push any parents that are still candidates.
    for (int pIdx = 0; pIdx < pCnt; pIdx++) {
      if (parents[pIdx] != null) push(parents[pIdx]);
    }

    if (n.regionList != null) return result(n);
    return false;
  }
  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;
    }
  }
Esempio n. 14
0
 /** @return path file path being processed. */
 public String getResultPath() {
   return resultPath.getPath();
 }
Esempio n. 15
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();
    }
  }
Esempio n. 16
0
 @Override
 public boolean shouldBeRecursive() {
   return path.shouldBeRecursive() || ANY_DIFF.shouldBeRecursive();
 }
Esempio n. 17
0
  @Override
  protected void doGet(HttpServletRequest req, HttpServletResponse resp)
      throws ServletException, IOException {
    handleAuth(req);
    resp.setCharacterEncoding("UTF-8");
    final PrintWriter out = resp.getWriter();
    try {
      String pathInfo = req.getPathInfo();
      Pattern pattern = Pattern.compile("/([^/]*)(?:/([^/]*)(?:/(.*))?)?");
      Matcher matcher = pattern.matcher(pathInfo);
      matcher.matches();
      String projectName = null;
      String refName = null;
      String filePath = null;
      if (matcher.groupCount() > 0) {
        projectName = matcher.group(1);
        refName = matcher.group(2);
        filePath = matcher.group(3);
        if (projectName == null || projectName.equals("")) {
          projectName = null;
        } else {
          projectName = java.net.URLDecoder.decode(projectName, "UTF-8");
        }
        if (refName == null || refName.equals("")) {
          refName = null;
        } else {
          refName = java.net.URLDecoder.decode(refName, "UTF-8");
        }
        if (filePath == null || filePath.equals("")) {
          filePath = null;
        } else {
          filePath = java.net.URLDecoder.decode(filePath, "UTF-8");
        }
      }
      if (projectName != null) {
        if (filePath == null) filePath = "";
        NameKey projName = NameKey.parse(projectName);

        ProjectControl control;
        try {
          control = projControlFactory.controlFor(projName);
          if (!control.isVisible()) {
            log.debug("Project not visible!");
            resp.sendError(
                HttpServletResponse.SC_UNAUTHORIZED,
                "You need to be logged in to see private projects");
            return;
          }
        } catch (NoSuchProjectException e1) {
        }
        Repository repo = repoManager.openRepository(projName);
        if (refName == null) {
          JSONArray contents = new JSONArray();
          List<Ref> call;
          try {
            call = new Git(repo).branchList().call();
            Git git = new Git(repo);
            for (Ref ref : call) {
              JSONObject jsonObject = new JSONObject();
              try {
                jsonObject.put("name", ref.getName());
                jsonObject.put("type", "ref");
                jsonObject.put("size", "0");
                jsonObject.put("path", "");
                jsonObject.put("project", projectName);
                jsonObject.put("ref", ref.getName());
                lastCommit(git, null, ref.getObjectId(), jsonObject);
              } catch (JSONException e) {
              }
              contents.put(jsonObject);
            }
            String response = contents.toString();
            resp.setContentType("application/json");
            resp.setHeader("Cache-Control", "no-cache");
            resp.setHeader("ETag", "W/\"" + response.length() + "-" + response.hashCode() + "\"");
            log.debug(response);
            out.write(response);
          } catch (GitAPIException e) {
          }
        } else {
          Ref head = repo.getRef(refName);
          if (head == null) {
            JSONArray contents = new JSONArray();
            String response = contents.toString();
            resp.setContentType("application/json");
            resp.setHeader("Cache-Control", "no-cache");
            resp.setHeader("ETag", "W/\"" + response.length() + "-" + response.hashCode() + "\"");
            log.debug(response);
            out.write(response);
            return;
          }
          RevWalk walk = new RevWalk(repo);
          // add try catch to catch failures
          Git git = new Git(repo);
          RevCommit commit = walk.parseCommit(head.getObjectId());
          RevTree tree = commit.getTree();
          TreeWalk treeWalk = new TreeWalk(repo);
          treeWalk.addTree(tree);
          treeWalk.setRecursive(false);
          if (!filePath.equals("")) {
            PathFilter pathFilter = PathFilter.create(filePath);
            treeWalk.setFilter(pathFilter);
          }
          if (!treeWalk.next()) {
            CanonicalTreeParser canonicalTreeParser =
                treeWalk.getTree(0, CanonicalTreeParser.class);
            JSONArray contents = new JSONArray();
            if (canonicalTreeParser != null) {
              while (!canonicalTreeParser.eof()) {
                String path = canonicalTreeParser.getEntryPathString();
                FileMode mode = canonicalTreeParser.getEntryFileMode();
                listEntry(
                    path,
                    mode.equals(FileMode.TREE) ? "dir" : "file",
                    "0",
                    path,
                    projectName,
                    head.getName(),
                    git,
                    contents);
                canonicalTreeParser.next();
              }
            }
            String response = contents.toString();
            resp.setContentType("application/json");
            resp.setHeader("Cache-Control", "no-cache");
            resp.setHeader("ETag", "\"" + tree.getId().getName() + "\"");
            log.debug(response);
            out.write(response);
          } else {
            // if (treeWalk.isSubtree()) {
            // treeWalk.enterSubtree();
            // }

            JSONArray contents = getListEntries(treeWalk, repo, git, head, filePath, projectName);
            String response = contents.toString();

            resp.setContentType("application/json");
            resp.setHeader("Cache-Control", "no-cache");
            resp.setHeader("ETag", "\"" + tree.getId().getName() + "\"");
            log.debug(response);
            out.write(response);
          }
          walk.release();
          treeWalk.release();
        }
      }
    } catch (RepositoryNotFoundException e) {
      handleException(resp, e, 400);
    } catch (MissingObjectException e) {
      // example "Missing unknown 7035305927ca125757ecd8407e608f6dcf0bd8a5"
      // usually indicative of being unable to locate a commit from a submodule
      log.error(e.getMessage(), e);
      String msg =
          e.getMessage()
              + ".  This exception could have been caused by the use of a git submodule, "
              + "which is currently not supported by the repository browser.";
      handleException(resp, new Exception(msg), 501);
    } catch (IOException e) {
      handleException(resp, e, 500);
    } finally {
      out.close();
    }
  }
  private boolean handleGetDiff(
      HttpServletRequest request,
      HttpServletResponse response,
      Repository db,
      String scope,
      String pattern,
      OutputStream out)
      throws Exception {
    Git git = new Git(db);
    DiffCommand diff = git.diff();
    diff.setOutputStream(new BufferedOutputStream(out));
    AbstractTreeIterator oldTree;
    AbstractTreeIterator newTree = new FileTreeIterator(db);
    if (scope.contains("..")) { // $NON-NLS-1$
      String[] commits = scope.split("\\.\\."); // $NON-NLS-1$
      if (commits.length != 2) {
        String msg = NLS.bind("Failed to generate diff for {0}", scope);
        return statusHandler.handleRequest(
            request,
            response,
            new ServerStatus(IStatus.ERROR, HttpServletResponse.SC_BAD_REQUEST, msg, null));
      }
      oldTree = getTreeIterator(db, commits[0]);
      newTree = getTreeIterator(db, commits[1]);
    } else if (scope.equals(GitConstants.KEY_DIFF_CACHED)) {
      ObjectId head = db.resolve(Constants.HEAD + "^{tree}"); // $NON-NLS-1$
      if (head == null) {
        String msg = NLS.bind("Failed to generate diff for {0}, no HEAD", scope);
        return statusHandler.handleRequest(
            request,
            response,
            new ServerStatus(IStatus.ERROR, HttpServletResponse.SC_BAD_REQUEST, msg, null));
      }
      CanonicalTreeParser p = new CanonicalTreeParser();
      ObjectReader reader = db.newObjectReader();
      try {
        p.reset(reader, head);
      } finally {
        reader.release();
      }
      oldTree = p;
      newTree = new DirCacheIterator(db.readDirCache());
    } else if (scope.equals(GitConstants.KEY_DIFF_DEFAULT)) {
      oldTree = new DirCacheIterator(db.readDirCache());
    } else {
      oldTree = getTreeIterator(db, scope);
    }

    String[] paths = request.getParameterValues(ProtocolConstants.KEY_PATH);
    TreeFilter filter = null;
    TreeFilter pathFilter = null;
    if (paths != null) {
      if (paths.length > 1) {
        Set<TreeFilter> pathFilters = new HashSet<TreeFilter>(paths.length);
        for (String path : paths) {
          pathFilters.add(PathFilter.create(path));
        }
        pathFilter = OrTreeFilter.create(pathFilters);
      } else if (paths.length == 1) {
        pathFilter = PathFilter.create(paths[0]);
      }
    }
    if (pattern != null) {
      PathFilter patternFilter = PathFilter.create(pattern);
      if (pathFilter != null) filter = AndTreeFilter.create(patternFilter, pathFilter);
      else filter = patternFilter;
    } else {
      filter = pathFilter;
    }
    if (filter != null) diff.setPathFilter(filter);

    diff.setOldTree(oldTree);
    diff.setNewTree(newTree);
    diff.call();
    return true;
  }
Esempio n. 19
0
 /**
  * Create a new tree filter for a user supplied path.
  *
  * <p>Path strings are relative to the root of the repository. If the user's input should be
  * assumed relative to a subdirectory of the repository the caller must prepend the subdirectory's
  * path prior to creating the filter.
  *
  * <p>Path strings use '/' to delimit directories on all platforms.
  *
  * @param path the path to filter on. Must not be the empty string. All trailing '/' characters
  *     will be trimmed before string's length is checked or is used as part of the constructed
  *     filter.
  * @return a new filter for the requested path.
  * @throws IllegalArgumentException the path supplied was the empty string.
  */
 public static FollowFilter create(String path) {
   return new FollowFilter(PathFilter.create(path));
 }
Esempio n. 20
0
 @Override
 public TreeFilter clone() {
   return new FollowFilter(path.clone());
 }
Esempio n. 21
0
 @Override
 public boolean include(final TreeWalk walker)
     throws MissingObjectException, IncorrectObjectTypeException, IOException {
   return path.include(walker) && ANY_DIFF.include(walker);
 }
Esempio n. 22
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);
        }
      }
    }
  }