James Moger
2012-03-28 1aa6e081ffe319ff3ddfa246783cb65dc1c71b3b
src/com/gitblit/utils/JGitUtils.java
@@ -36,8 +36,6 @@
import org.eclipse.jgit.api.CloneCommand;
import org.eclipse.jgit.api.FetchCommand;
import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.api.ResetCommand;
import org.eclipse.jgit.api.ResetCommand.ResetType;
import org.eclipse.jgit.diff.DiffEntry;
import org.eclipse.jgit.diff.DiffEntry.ChangeType;
import org.eclipse.jgit.diff.DiffFormatter;
@@ -253,27 +251,6 @@
   }
   /**
    * Reset HEAD to the latest remote tracking commit.
    *
    * @param repository
    * @param remoteRef
    *            the remote tracking reference (e.g. origin/master)
    * @return Ref
    * @throws Exception
    */
   public static Ref resetHEAD(Repository repository, String remoteRef) throws Exception {
      if (!remoteRef.startsWith(Constants.R_REMOTES)) {
         remoteRef = Constants.R_REMOTES + remoteRef;
      }
      Git git = new Git(repository);
      ResetCommand reset = git.reset();
      reset.setMode(ResetType.SOFT);
      reset.setRef(remoteRef);
      Ref result = reset.call();
      return result;
   }
   /**
    * Creates a bare repository.
    * 
    * @param repositoriesFolder
@@ -289,21 +266,21 @@
    * Returns a list of repository names in the specified folder.
    * 
    * @param repositoriesFolder
    * @param exportAll
    *            if true, all repositories are listed. If false only the
    *            repositories with a "git-daemon-export-ok" file are included
    * @param onlyBare
    *            if true, only bare repositories repositories are listed. If
    *            false all repositories are included.
    * @param searchSubfolders
    *            recurse into subfolders to find grouped repositories
    * @return list of repository names
    */
   public static List<String> getRepositoryList(File repositoriesFolder, boolean exportAll,
   public static List<String> getRepositoryList(File repositoriesFolder, boolean onlyBare,
         boolean searchSubfolders) {
      List<String> list = new ArrayList<String>();
      if (repositoriesFolder == null || !repositoriesFolder.exists()) {
         return list;
      }
      list.addAll(getRepositoryList(repositoriesFolder.getAbsolutePath(), repositoriesFolder,
            exportAll, searchSubfolders));
            onlyBare, searchSubfolders));
      StringUtils.sortRepositorynames(list);
      return list;
   }
@@ -315,33 +292,30 @@
    *            basePath is stripped from the repository name as repositories
    *            are relative to this path
    * @param searchFolder
    * @param exportAll
    *            if true all repositories are listed. If false only the
    *            repositories with a "git-daemon-export-ok" file are included
    * @param onlyBare
    *            if true only bare repositories will be listed. if false all
    *            repositories are included.
    * @param searchSubfolders
    *            recurse into subfolders to find grouped repositories
    * @return
    */
   private static List<String> getRepositoryList(String basePath, File searchFolder,
         boolean exportAll, boolean searchSubfolders) {
         boolean onlyBare, boolean searchSubfolders) {
      File baseFile = new File(basePath);
      List<String> list = new ArrayList<String>();
      for (File file : searchFolder.listFiles()) {
         if (file.isDirectory()) {
            File gitDir = FileKey.resolve(new File(searchFolder, file.getName()), FS.DETECTED);
            if (gitDir != null) {
               boolean exportRepository = exportAll
                     || new File(gitDir, "git-daemon-export-ok").exists();
               if (!exportRepository) {
               if (onlyBare && gitDir.getName().equals(".git")) {
                  continue;
               }
               // determine repository name relative to base path
               String repository = StringUtils.getRelativePath(basePath,
                     file.getAbsolutePath());
               String repository = FileUtils.getRelativePath(baseFile, file);
               list.add(repository);
            } else if (searchSubfolders) {
            } else if (searchSubfolders && file.canRead()) {
               // look for repositories in subfolders
               list.addAll(getRepositoryList(basePath, file, exportAll, searchSubfolders));
               list.addAll(getRepositoryList(basePath, file, onlyBare, searchSubfolders));
            }
         }
      }
@@ -426,11 +400,9 @@
    * last modified date of the repository folder is returned.
    * 
    * @param repository
    * @param branch
    *            if unspecified, all branches are checked.
    * @return
    */
   public static Date getLastChange(Repository repository, String branch) {
   public static Date getLastChange(Repository repository) {
      if (!hasCommits(repository)) {
         // null repository
         if (repository == null) {
@@ -439,26 +411,21 @@
         // fresh repository
         return new Date(repository.getDirectory().lastModified());
      }
      if (StringUtils.isEmpty(branch)) {
         List<RefModel> branchModels = getLocalBranches(repository, true, -1);
         if (branchModels.size() > 0) {
            // find most recent branch update
            Date lastChange = new Date(0);
            for (RefModel branchModel : branchModels) {
               if (branchModel.getDate().after(lastChange)) {
                  lastChange = branchModel.getDate();
               }
            }
            return lastChange;
         } else {
            // try to find head
            branch = Constants.HEAD;
         }
      }
      // lookup specified branch
      RevCommit commit = getCommit(repository, branch);
      return getCommitDate(commit);
      List<RefModel> branchModels = getLocalBranches(repository, true, -1);
      if (branchModels.size() > 0) {
         // find most recent branch update
         Date lastChange = new Date(0);
         for (RefModel branchModel : branchModels) {
            if (branchModel.getDate().after(lastChange)) {
               lastChange = branchModel.getDate();
            }
         }
         return lastChange;
      }
      // default to the repository folder modification date
      return new Date(repository.getDirectory().lastModified());
   }
   /**
@@ -731,6 +698,10 @@
                  list.add(new PathChangeModel(diff.getOldPath(), diff.getOldPath(), 0, diff
                        .getNewMode().getBits(), commit.getId().getName(), diff
                        .getChangeType()));
               } else if (diff.getChangeType().equals(ChangeType.RENAME)) {
                  list.add(new PathChangeModel(diff.getOldPath(), diff.getNewPath(), 0, diff
                        .getNewMode().getBits(), commit.getId().getName(), diff
                        .getChangeType()));
               } else {
                  list.add(new PathChangeModel(diff.getNewPath(), diff.getNewPath(), 0, diff
                        .getNewMode().getBits(), commit.getId().getName(), diff
@@ -965,6 +936,9 @@
         } else {
            branchObject = repository.resolve(objectId);
         }
         if (branchObject == null) {
            return list;
         }
         RevWalk rw = new RevWalk(repository);
         rw.markStart(rw.parseCommit(branchObject));
@@ -1175,6 +1149,98 @@
   }
   /**
    * Returns the target of the symbolic HEAD reference for a repository.
    * Normally returns a branch reference name, but when HEAD is detached,
    * the commit is matched against the known tags. The most recent matching
    * tag ref name will be returned if it references the HEAD commit. If
    * no match is found, the SHA1 is returned.
    *
    * @param repository
    * @return the ref name or the SHA1 for a detached HEAD
    */
   public static String getHEADRef(Repository repository) {
      String target = null;
      try {
         target = repository.getFullBranch();
         if (!target.startsWith(Constants.R_HEADS)) {
            // refers to an actual commit, probably a tag
            // find latest tag that matches the commit, if any
            List<RefModel> tagModels = getTags(repository, true, -1);
            if (tagModels.size() > 0) {
               RefModel tag = null;
               Date lastDate = new Date(0);
               for (RefModel tagModel : tagModels) {
                  if (tagModel.getReferencedObjectId().getName().equals(target) &&
                        tagModel.getDate().after(lastDate)) {
                     tag = tagModel;
                     lastDate = tag.getDate();
                  }
               }
               target = tag.getName();
            }
         }
      } catch (Throwable t) {
         error(t, repository, "{0} failed to get symbolic HEAD target");
      }
      return target;
   }
   /**
    * Sets the symbolic ref HEAD to the specified target ref. The
    * HEAD will be detached if the target ref is not a branch.
    *
    * @param repository
    * @param targetRef
    * @return true if successful
    */
   public static boolean setHEADtoRef(Repository repository, String targetRef) {
      try {
          // detach HEAD if target ref is not a branch
         boolean detach = !targetRef.startsWith(Constants.R_HEADS);
         RefUpdate.Result result;
         RefUpdate head = repository.updateRef(Constants.HEAD, detach);
         if (detach) { // Tag
            RevCommit commit = getCommit(repository, targetRef);
            head.setNewObjectId(commit.getId());
            result = head.forceUpdate();
         } else {
            result = head.link(targetRef);
         }
         switch (result) {
         case NEW:
         case FORCED:
         case NO_CHANGE:
         case FAST_FORWARD:
            return true;
         default:
            LOGGER.error(MessageFormat.format("{0} HEAD update to {1} returned result {2}",
                  repository.getDirectory().getAbsolutePath(), targetRef, result));
         }
      } catch (Throwable t) {
         error(t, repository, "{0} failed to set HEAD to {1}", targetRef);
      }
      return false;
   }
   /**
    * Get the full branch and tag ref names for any potential HEAD targets.
    *
    * @param repository
    * @return a list of ref names
    */
   public static List<String> getAvailableHeadTargets(Repository repository) {
      List<String> targets = new ArrayList<String>();
      for (RefModel branchModel : JGitUtils.getLocalBranches(repository, true, -1)) {
         targets.add(branchModel.getName());
      }
      for (RefModel tagModel : JGitUtils.getTags(repository, true, -1)) {
         targets.add(tagModel.getName());
      }
      return targets;
   }
   /**
    * Returns all refs grouped by their associated object id.
    * 
    * @param repository
@@ -1368,10 +1434,23 @@
      List<RefModel> noteBranches = getNoteBranches(repository, true, -1);
      for (RefModel notesRef : noteBranches) {
         RevTree notesTree = JGitUtils.getCommit(repository, notesRef.getName()).getTree();
         // flat notes list
         String notePath = commit.getName();
         String text = getStringContent(repository, notesTree, notePath);
         if (!StringUtils.isEmpty(text)) {
            List<RevCommit> history = getRevLog(repository, notesRef.getName(), notePath, 0, -1);
            RefModel noteRef = new RefModel(notesRef.displayName, null, history.get(history
                  .size() - 1));
            GitNote gitNote = new GitNote(noteRef, text);
            list.add(gitNote);
            continue;
         }
         // folder structure
         StringBuilder sb = new StringBuilder(commit.getName());
         sb.insert(2, '/');
         String notePath = sb.toString();
         String text = getStringContent(repository, notesTree, notePath);
         notePath = sb.toString();
         text = getStringContent(repository, notesTree, notePath);
         if (!StringUtils.isEmpty(text)) {
            List<RevCommit> history = getRevLog(repository, notesRef.getName(), notePath, 0, -1);
            RefModel noteRef = new RefModel(notesRef.displayName, null, history.get(history
@@ -1408,7 +1487,7 @@
            // Create a tree object to reference from a commit
            TreeFormatter tree = new TreeFormatter();
            tree.append("NEWBRANCH", FileMode.REGULAR_FILE, blobId);
            tree.append(".branch", FileMode.REGULAR_FILE, blobId);
            ObjectId treeId = odi.insert(tree);
            // Create a commit object