James Moger
2014-02-28 131da2786c1bf275c07ba628af4254a40d1dc42f
src/main/java/com/gitblit/utils/JGitUtils.java
@@ -15,10 +15,8 @@
 */
package com.gitblit.utils;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.text.DecimalFormat;
import java.text.MessageFormat;
import java.util.ArrayList;
@@ -706,6 +704,7 @@
         return null;
      }
      RevCommit commit = null;
      RevWalk walk = null;
      try {
         // resolve object id
         ObjectId branchObject;
@@ -714,12 +713,18 @@
         } else {
            branchObject = repository.resolve(objectId);
         }
         RevWalk walk = new RevWalk(repository);
         if (branchObject == null) {
            return null;
         }
         walk = new RevWalk(repository);
         RevCommit rev = walk.parseCommit(branchObject);
         commit = rev;
         walk.dispose();
      } catch (Throwable t) {
         error(t, repository, "{0} failed to get commit {1}", objectId);
      } finally {
         if (walk != null) {
            walk.dispose();
         }
      }
      return commit;
   }
@@ -755,18 +760,8 @@
            ObjectId entid = tw.getObjectId(0);
            FileMode entmode = tw.getFileMode(0);
            if (entmode != FileMode.GITLINK) {
               RevObject ro = rw.lookupAny(entid, entmode.getObjectType());
               rw.parseBody(ro);
               ByteArrayOutputStream os = new ByteArrayOutputStream();
               ObjectLoader ldr = repository.open(ro.getId(), Constants.OBJ_BLOB);
               byte[] tmp = new byte[4096];
               InputStream in = ldr.openStream();
               int n;
               while ((n = in.read(tmp)) > 0) {
                  os.write(tmp, 0, n);
               }
               in.close();
               content = os.toByteArray();
               ObjectLoader ldr = repository.open(entid, Constants.OBJ_BLOB);
               content = ldr.getCachedBytes();
            }
         }
      } catch (Throwable t) {
@@ -810,17 +805,8 @@
      byte[] content = null;
      try {
         RevBlob blob = rw.lookupBlob(ObjectId.fromString(objectId));
         rw.parseBody(blob);
         ByteArrayOutputStream os = new ByteArrayOutputStream();
         ObjectLoader ldr = repository.open(blob.getId(), Constants.OBJ_BLOB);
         byte[] tmp = new byte[4096];
         InputStream in = ldr.openStream();
         int n;
         while ((n = in.read(tmp)) > 0) {
            os.write(tmp, 0, n);
         }
         in.close();
         content = os.toByteArray();
         content = ldr.getCachedBytes();
      } catch (Throwable t) {
         error(t, repository, "{0} can't find blob {1}", objectId);
      } finally {
@@ -990,6 +976,36 @@
    *            most recent commit. if null, HEAD is assumed.
    * @return list of files changed in a commit range
    */
   public static List<PathChangeModel> getFilesInRange(Repository repository, String startCommit, String endCommit) {
      List<PathChangeModel> list = new ArrayList<PathChangeModel>();
      if (!hasCommits(repository)) {
         return list;
      }
      try {
         ObjectId startRange = repository.resolve(startCommit);
         ObjectId endRange = repository.resolve(endCommit);
         RevWalk rw = new RevWalk(repository);
         RevCommit start = rw.parseCommit(startRange);
         RevCommit end = rw.parseCommit(endRange);
         list.addAll(getFilesInRange(repository, start, end));
         rw.release();
      } catch (Throwable t) {
         error(t, repository, "{0} failed to determine files in range {1}..{2}!", startCommit, endCommit);
      }
      return list;
   }
   /**
    * Returns the list of files changed in a specified commit. If the
    * repository does not exist or is empty, an empty list is returned.
    *
    * @param repository
    * @param startCommit
    *            earliest commit
    * @param endCommit
    *            most recent commit. if null, HEAD is assumed.
    * @return list of files changed in a commit range
    */
   public static List<PathChangeModel> getFilesInRange(Repository repository, RevCommit startCommit, RevCommit endCommit) {
      List<PathChangeModel> list = new ArrayList<PathChangeModel>();
      if (!hasCommits(repository)) {
@@ -1003,7 +1019,7 @@
         List<DiffEntry> diffEntries = df.scan(startCommit.getTree(), endCommit.getTree());
         for (DiffEntry diff : diffEntries) {
            PathChangeModel pcm = PathChangeModel.from(diff,  null);
            PathChangeModel pcm = PathChangeModel.from(diff,  endCommit.getName());
            list.add(pcm);
         }
         Collections.sort(list);
@@ -1049,10 +1065,10 @@
            List<TreeFilter> suffixFilters = new ArrayList<TreeFilter>();
            for (String extension : extensions) {
               if (extension.charAt(0) == '.') {
                  suffixFilters.add(PathSuffixFilter.create("\\" + extension));
                  suffixFilters.add(PathSuffixFilter.create(extension));
               } else {
                  // escape the . since this is a regexp filter
                  suffixFilters.add(PathSuffixFilter.create("\\." + extension));
                  suffixFilters.add(PathSuffixFilter.create("." + extension));
               }
            }
            TreeFilter filter;
@@ -1470,23 +1486,6 @@
      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");
      }
@@ -1540,7 +1539,7 @@
    */
   public static boolean setBranchRef(Repository repository, String branch, String commitId) {
      String branchName = branch;
      if (!branchName.startsWith(Constants.R_HEADS)) {
      if (!branchName.startsWith(Constants.R_REFS)) {
         branchName = Constants.R_HEADS + branch;
      }
@@ -2096,4 +2095,54 @@
      }
      return StringUtils.decodeString(content);
   }
   /**
    * Automatic repair of (some) invalid refspecs.  These are the result of a
    * bug in JGit cloning where a double forward-slash was injected.  :(
    *
    * @param repository
    * @return true, if the refspecs were repaired
    */
   public static boolean repairFetchSpecs(Repository repository) {
      StoredConfig rc = repository.getConfig();
      // auto-repair broken fetch ref specs
      for (String name : rc.getSubsections("remote")) {
         int invalidSpecs = 0;
         int repairedSpecs = 0;
         List<String> specs = new ArrayList<String>();
         for (String spec : rc.getStringList("remote", name, "fetch")) {
            try {
               RefSpec rs = new RefSpec(spec);
               // valid spec
               specs.add(spec);
            } catch (IllegalArgumentException e) {
               // invalid spec
               invalidSpecs++;
               if (spec.contains("//")) {
                  // auto-repair this known spec bug
                  spec = spec.replace("//", "/");
                  specs.add(spec);
                  repairedSpecs++;
               }
            }
         }
         if (invalidSpecs == repairedSpecs && repairedSpecs > 0) {
            // the fetch specs were automatically repaired
            rc.setStringList("remote", name, "fetch", specs);
            try {
               rc.save();
               rc.load();
               LOGGER.debug("repaired {} invalid fetch refspecs for {}", repairedSpecs, repository.getDirectory());
               return true;
            } catch (Exception e) {
               LOGGER.error(null, e);
            }
         } else if (invalidSpecs > 0) {
            LOGGER.error("mirror executor found {} invalid fetch refspecs for {}", invalidSpecs, repository.getDirectory());
         }
      }
      return false;
   }
}