Exemple #1
0
  /**
   * Update any smudged entries with information from the working tree.
   *
   * @throws IOException
   */
  private void updateSmudgedEntries() throws IOException {
    TreeWalk walk = new TreeWalk(repository);
    List<String> paths = new ArrayList<String>(128);
    try {
      for (int i = 0; i < entryCnt; i++)
        if (sortedEntries[i].isSmudged()) paths.add(sortedEntries[i].getPathString());
      if (paths.isEmpty()) return;
      walk.setFilter(PathFilterGroup.createFromStrings(paths));

      DirCacheIterator iIter = new DirCacheIterator(this);
      FileTreeIterator fIter = new FileTreeIterator(repository);
      walk.addTree(iIter);
      walk.addTree(fIter);
      walk.setRecursive(true);
      while (walk.next()) {
        iIter = walk.getTree(0, DirCacheIterator.class);
        if (iIter == null) continue;
        fIter = walk.getTree(1, FileTreeIterator.class);
        if (fIter == null) continue;
        DirCacheEntry entry = iIter.getDirCacheEntry();
        if (entry.isSmudged() && iIter.idEqual(fIter)) {
          entry.setLength(fIter.getEntryLength());
          entry.setLastModified(fIter.getEntryLastModified());
        }
      }
    } finally {
      walk.release();
    }
  }
Exemple #2
0
  /**
   * Compute the current projects that will be missing after the given branch is checked out
   *
   * @param branch
   * @param currentProjects
   * @return non-null but possibly empty array of missing projects
   */
  private IProject[] getMissingProjects(String branch, IProject[] currentProjects) {
    if (delete || currentProjects.length == 0) return new IProject[0];

    ObjectId targetTreeId;
    ObjectId currentTreeId;
    try {
      targetTreeId = repository.resolve(branch + "^{tree}"); // $NON-NLS-1$
      currentTreeId = repository.resolve(Constants.HEAD + "^{tree}"); // $NON-NLS-1$
    } catch (IOException e) {
      return new IProject[0];
    }
    if (targetTreeId == null || currentTreeId == null) return new IProject[0];

    Map<File, IProject> locations = new HashMap<File, IProject>();
    for (IProject project : currentProjects) {
      IPath location = project.getLocation();
      if (location == null) continue;
      location = location.append(IProjectDescription.DESCRIPTION_FILE_NAME);
      locations.put(location.toFile(), project);
    }

    List<IProject> toBeClosed = new ArrayList<IProject>();
    File root = repository.getWorkTree();
    TreeWalk walk = new TreeWalk(repository);
    try {
      walk.addTree(targetTreeId);
      walk.addTree(currentTreeId);
      walk.addTree(new FileTreeIterator(repository));
      walk.setRecursive(true);
      walk.setFilter(
          AndTreeFilter.create(
              PathSuffixFilter.create(IProjectDescription.DESCRIPTION_FILE_NAME),
              TreeFilter.ANY_DIFF));
      while (walk.next()) {
        AbstractTreeIterator targetIter = walk.getTree(0, AbstractTreeIterator.class);
        if (targetIter != null) continue;

        AbstractTreeIterator currentIter = walk.getTree(1, AbstractTreeIterator.class);
        AbstractTreeIterator workingIter = walk.getTree(2, AbstractTreeIterator.class);
        if (currentIter == null || workingIter == null) continue;

        IProject project = locations.get(new File(root, walk.getPathString()));
        if (project != null) toBeClosed.add(project);
      }
    } catch (IOException e) {
      return new IProject[0];
    } finally {
      walk.release();
    }
    return toBeClosed.toArray(new IProject[toBeClosed.size()]);
  }
  /**
   * Returns all tree entries that do not match the ignore paths.
   *
   * @param db
   * @param ignorePaths
   * @param dcBuilder
   * @throws IOException
   */
  private List<DirCacheEntry> getTreeEntries(Repository db, Collection<String> ignorePaths)
      throws IOException {
    List<DirCacheEntry> list = new ArrayList<DirCacheEntry>();
    ObjectId treeId = db.resolve(BRANCH + "^{tree}");
    if (treeId == null) {
      // branch does not exist yet, could be migrating tickets
      return list;
    }
    try (TreeWalk tw = new TreeWalk(db)) {
      int hIdx = tw.addTree(treeId);
      tw.setRecursive(true);

      while (tw.next()) {
        String path = tw.getPathString();
        CanonicalTreeParser hTree = null;
        if (hIdx != -1) {
          hTree = tw.getTree(hIdx, CanonicalTreeParser.class);
        }
        if (!ignorePaths.contains(path)) {
          // add all other tree entries
          if (hTree != null) {
            final DirCacheEntry entry = new DirCacheEntry(path);
            entry.setObjectId(hTree.getEntryObjectId());
            entry.setFileMode(hTree.getEntryFileMode());
            list.add(entry);
          }
        }
      }
    }
    return list;
  }
 public static List<File> getNotIgnoredFilesOfRepo(File directory) throws GitException {
   Git git = openRepository(directory);
   Repository repo = null;
   repo = git.getRepository();
   List<File> foundFiles = new ArrayList<>();
   TreeWalk treeWalk = null;
   try {
     treeWalk = new TreeWalk(repo);
     FileTreeIterator tree = new FileTreeIterator(repo);
     treeWalk.addTree(tree);
     treeWalk.setRecursive(false);
     while (treeWalk.next()) {
       WorkingTreeIterator iterator = treeWalk.getTree(0, WorkingTreeIterator.class);
       if (!iterator.isEntryIgnored())
         if (treeWalk.isSubtree()) {
           treeWalk.enterSubtree();
         } else {
           File file = new File(directory, treeWalk.getPathString());
           foundFiles.add(file);
         }
     }
   } catch (IOException e) {
     throw new GitException("Listing of non-ignored files in " + directory + " failed", e);
   } finally {
     if (treeWalk != null) treeWalk.close();
   }
   return foundFiles;
 }
Exemple #5
0
 /**
  * Process the given TreeWalk's entries.
  *
  * @param treeWalk The walk to iterate over.
  * @param ignoreConflicts see {@link ResolveMerger#mergeTrees(AbstractTreeIterator, RevTree,
  *     RevTree, boolean)}
  * @return Whether the trees merged cleanly.
  * @throws IOException
  * @since 3.5
  */
 protected boolean mergeTreeWalk(TreeWalk treeWalk, boolean ignoreConflicts) throws IOException {
   boolean hasWorkingTreeIterator = tw.getTreeCount() > T_FILE;
   while (treeWalk.next()) {
     if (!processEntry(
         treeWalk.getTree(T_BASE, CanonicalTreeParser.class),
         treeWalk.getTree(T_OURS, CanonicalTreeParser.class),
         treeWalk.getTree(T_THEIRS, CanonicalTreeParser.class),
         treeWalk.getTree(T_INDEX, DirCacheBuildIterator.class),
         hasWorkingTreeIterator ? treeWalk.getTree(T_FILE, WorkingTreeIterator.class) : null,
         ignoreConflicts)) {
       cleanUp();
       return false;
     }
     if (treeWalk.isSubtree() && enterSubtree) treeWalk.enterSubtree();
   }
   return true;
 }
Exemple #6
0
  private void assertEntry(FileMode type, boolean entryIgnored, String pathName)
      throws IOException {
    assertTrue("walk has entry", walk.next());
    assertEquals(pathName, walk.getPathString());
    assertEquals(type, walk.getFileMode(0));

    WorkingTreeIterator itr = walk.getTree(0, WorkingTreeIterator.class);
    assertNotNull("has tree", itr);
    assertEquals("is ignored", entryIgnored, itr.isEntryIgnored());
    if (D.equals(type)) walk.enterSubtree();
  }
  private void assertIteration(FileMode type, String pathName, List<Attribute> nodeAttrs)
      throws IOException {
    assertTrue("walk has entry", walk.next());
    assertEquals(pathName, walk.getPathString());
    assertEquals(type, walk.getFileMode(0));
    DirCacheIterator itr = walk.getTree(0, DirCacheIterator.class);
    assertNotNull("has tree", itr);

    AttributesNode attributesNode = itr.getEntryAttributesNode(db.newObjectReader());
    assertAttributesNode(pathName, attributesNode, nodeAttrs);

    if (D.equals(type)) walk.enterSubtree();
  }
  @Test
  public void testTreeWalk_LsFiles() throws Exception {
    final Repository db = createBareRepository();
    final Map<String, CGitIndexRecord> ls = readLsFiles();
    final DirCache dc = new DirCache(index, db.getFS());
    assertEquals(0, dc.getEntryCount());
    dc.read();
    assertEquals(ls.size(), dc.getEntryCount());
    {
      final Iterator<CGitIndexRecord> rItr = ls.values().iterator();
      final TreeWalk tw = new TreeWalk(db);
      tw.setRecursive(true);
      tw.addTree(new DirCacheIterator(dc));
      while (rItr.hasNext()) {
        final DirCacheIterator dcItr;

        assertTrue(tw.next());
        dcItr = tw.getTree(0, DirCacheIterator.class);
        assertNotNull(dcItr);

        assertEqual(rItr.next(), dcItr.getDirCacheEntry());
      }
    }
  }
 private AbstractTreeIterator getSingleTreeIterator(TreeWalk treeWalk, String commitMessage) {
   AbstractTreeIterator result = null;
   int treeCount = treeWalk.getTreeCount();
   for (int i = 0; i < treeCount; i++) {
     AbstractTreeIterator it = treeWalk.getTree(i, AbstractTreeIterator.class);
     if (it != null) {
       if (result != null) {
         String msg =
             "Trees of repositories overlap in path '"
                 + it.getEntryPathString()
                 + "'. "
                 + "We can only merge non-overlapping trees, "
                 + "so make sure the repositories have been prepared for that. "
                 + "One possible way is to process each repository to move the root to a subdirectory first.\n"
                 + "Current commit:\n"
                 + commitMessage;
         throw new IllegalStateException(msg);
       } else {
         result = it;
       }
     }
   }
   return result;
 }
Exemple #10
0
  private DirCache createTemporaryIndex(ObjectId headId, DirCache index, RevWalk rw)
      throws IOException {
    ObjectInserter inserter = null;

    // get DirCacheBuilder for existing index
    DirCacheBuilder existingBuilder = index.builder();

    // get DirCacheBuilder for newly created in-core index to build a
    // temporary index for this commit
    DirCache inCoreIndex = DirCache.newInCore();
    DirCacheBuilder tempBuilder = inCoreIndex.builder();

    onlyProcessed = new boolean[only.size()];
    boolean emptyCommit = true;

    try (TreeWalk treeWalk = new TreeWalk(repo)) {
      treeWalk.setOperationType(OperationType.CHECKIN_OP);
      int dcIdx = treeWalk.addTree(new DirCacheBuildIterator(existingBuilder));
      FileTreeIterator fti = new FileTreeIterator(repo);
      fti.setDirCacheIterator(treeWalk, 0);
      int fIdx = treeWalk.addTree(fti);
      int hIdx = -1;
      if (headId != null) hIdx = treeWalk.addTree(rw.parseTree(headId));
      treeWalk.setRecursive(true);

      String lastAddedFile = null;
      while (treeWalk.next()) {
        String path = treeWalk.getPathString();
        // check if current entry's path matches a specified path
        int pos = lookupOnly(path);

        CanonicalTreeParser hTree = null;
        if (hIdx != -1) hTree = treeWalk.getTree(hIdx, CanonicalTreeParser.class);

        DirCacheIterator dcTree = treeWalk.getTree(dcIdx, DirCacheIterator.class);

        if (pos >= 0) {
          // include entry in commit

          FileTreeIterator fTree = treeWalk.getTree(fIdx, FileTreeIterator.class);

          // check if entry refers to a tracked file
          boolean tracked = dcTree != null || hTree != null;
          if (!tracked) continue;

          // for an unmerged path, DirCacheBuildIterator will yield 3
          // entries, we only want to add one
          if (path.equals(lastAddedFile)) continue;

          lastAddedFile = path;

          if (fTree != null) {
            // create a new DirCacheEntry with data retrieved from
            // disk
            final DirCacheEntry dcEntry = new DirCacheEntry(path);
            long entryLength = fTree.getEntryLength();
            dcEntry.setLength(entryLength);
            dcEntry.setLastModified(fTree.getEntryLastModified());
            dcEntry.setFileMode(fTree.getIndexFileMode(dcTree));

            boolean objectExists =
                (dcTree != null && fTree.idEqual(dcTree))
                    || (hTree != null && fTree.idEqual(hTree));
            if (objectExists) {
              dcEntry.setObjectId(fTree.getEntryObjectId());
            } else {
              if (FileMode.GITLINK.equals(dcEntry.getFileMode()))
                dcEntry.setObjectId(fTree.getEntryObjectId());
              else {
                // insert object
                if (inserter == null) inserter = repo.newObjectInserter();
                long contentLength = fTree.getEntryContentLength();
                InputStream inputStream = fTree.openEntryStream();
                try {
                  dcEntry.setObjectId(
                      inserter.insert(Constants.OBJ_BLOB, contentLength, inputStream));
                } finally {
                  inputStream.close();
                }
              }
            }

            // add to existing index
            existingBuilder.add(dcEntry);
            // add to temporary in-core index
            tempBuilder.add(dcEntry);

            if (emptyCommit
                && (hTree == null
                    || !hTree.idEqual(fTree)
                    || hTree.getEntryRawMode() != fTree.getEntryRawMode()))
              // this is a change
              emptyCommit = false;
          } else {
            // if no file exists on disk, neither add it to
            // index nor to temporary in-core index

            if (emptyCommit && hTree != null)
              // this is a change
              emptyCommit = false;
          }

          // keep track of processed path
          onlyProcessed[pos] = true;
        } else {
          // add entries from HEAD for all other paths
          if (hTree != null) {
            // create a new DirCacheEntry with data retrieved from
            // HEAD
            final DirCacheEntry dcEntry = new DirCacheEntry(path);
            dcEntry.setObjectId(hTree.getEntryObjectId());
            dcEntry.setFileMode(hTree.getEntryFileMode());

            // add to temporary in-core index
            tempBuilder.add(dcEntry);
          }

          // preserve existing entry in index
          if (dcTree != null) existingBuilder.add(dcTree.getDirCacheEntry());
        }
      }
    }

    // there must be no unprocessed paths left at this point; otherwise an
    // untracked or unknown path has been specified
    for (int i = 0; i < onlyProcessed.length; i++)
      if (!onlyProcessed[i])
        throw new JGitInternalException(
            MessageFormat.format(JGitText.get().entryNotFoundByPath, only.get(i)));

    // there must be at least one change
    if (emptyCommit) throw new JGitInternalException(JGitText.get().emptyCommit);

    // update index
    existingBuilder.commit();
    // finish temporary in-core index used for this commit
    tempBuilder.finish();
    return inCoreIndex;
  }
  /**
   * Deletes a ticket from the repository.
   *
   * @param ticket
   * @return true if successful
   */
  @Override
  protected synchronized boolean deleteTicketImpl(
      RepositoryModel repository, TicketModel ticket, String deletedBy) {
    if (ticket == null) {
      throw new RuntimeException("must specify a ticket!");
    }

    boolean success = false;
    Repository db = repositoryManager.getRepository(ticket.repository);
    try {
      RefModel ticketsBranch = getTicketsBranch(db);

      if (ticketsBranch == null) {
        throw new RuntimeException(BRANCH + " does not exist!");
      }
      String ticketPath = toTicketPath(ticket.number);

      try {
        ObjectId treeId = db.resolve(BRANCH + "^{tree}");

        // Create the in-memory index of the new/updated ticket
        DirCache index = DirCache.newInCore();
        DirCacheBuilder builder = index.builder();

        // Traverse HEAD to add all other paths
        try (TreeWalk treeWalk = new TreeWalk(db)) {
          int hIdx = -1;
          if (treeId != null) {
            hIdx = treeWalk.addTree(treeId);
          }
          treeWalk.setRecursive(true);
          while (treeWalk.next()) {
            String path = treeWalk.getPathString();
            CanonicalTreeParser hTree = null;
            if (hIdx != -1) {
              hTree = treeWalk.getTree(hIdx, CanonicalTreeParser.class);
            }
            if (!path.startsWith(ticketPath)) {
              // add entries from HEAD for all other paths
              if (hTree != null) {
                final DirCacheEntry entry = new DirCacheEntry(path);
                entry.setObjectId(hTree.getEntryObjectId());
                entry.setFileMode(hTree.getEntryFileMode());

                // add to temporary in-core index
                builder.add(entry);
              }
            }
          }
        }

        // finish temporary in-core index used for this commit
        builder.finish();

        success = commitIndex(db, index, deletedBy, "- " + ticket.number);

      } catch (Throwable t) {
        log.error(
            MessageFormat.format(
                "Failed to delete ticket {0,number,0} from {1}", ticket.number, db.getDirectory()),
            t);
      }
    } finally {
      db.close();
    }
    return success;
  }
Exemple #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();
    }
  }
  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;
    }
  }
  @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();
    }
  }