saheba
2013-03-25 2a8a74bedafdb56b7e7edcb42642dc1eb5e54fff
src/com/gitblit/utils/JGitUtils.java
@@ -19,23 +19,22 @@
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.regex.Pattern;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
import org.eclipse.jgit.api.CloneCommand;
import org.eclipse.jgit.api.FetchCommand;
import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.api.TagCommand;
import org.eclipse.jgit.api.errors.GitAPIException;
import org.eclipse.jgit.diff.DiffEntry;
import org.eclipse.jgit.diff.DiffEntry.ChangeType;
@@ -83,6 +82,8 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.gitblit.GitBlit;
import com.gitblit.Keys;
import com.gitblit.models.GitNote;
import com.gitblit.models.PathModel;
import com.gitblit.models.PathModel.PathChangeModel;
@@ -97,6 +98,7 @@
 */
public class JGitUtils {
   private static final String REVISION_TAG_PREFIX = "rev_";
   static final Logger LOGGER = LoggerFactory.getLogger(JGitUtils.class);
   /**
@@ -210,11 +212,10 @@
         if (credentialsProvider != null) {
            clone.setCredentialsProvider(credentialsProvider);
         }
         clone.call();
         Repository repository = clone.call().getRepository();
         // Now we have to fetch because CloneCommand doesn't fetch
         // refs/notes nor does it allow manual RefSpec.
         File gitDir = FileKey.resolve(new File(repositoriesFolder, name), FS.DETECTED);
         FileRepository repository = new FileRepository(gitDir);
         result.createdRepository = true;
         result.fetchResult = fetchRepository(credentialsProvider, repository);
         repository.close();
@@ -541,7 +542,7 @@
    * @param path
    * @return content as a byte []
    */
   public static byte[] getByteContent(Repository repository, RevTree tree, final String path) {
   public static byte[] getByteContent(Repository repository, RevTree tree, final String path, boolean throwError) {
      RevWalk rw = new RevWalk(repository);
      TreeWalk tw = new TreeWalk(repository);
      tw.setFilter(PathFilterGroup.createFromStrings(Collections.singleton(path)));
@@ -576,7 +577,9 @@
            }
         }
      } catch (Throwable t) {
         error(t, repository, "{0} can't find {1} in tree {2}", path, tree.name());
         if (throwError) {
            error(t, repository, "{0} can't find {1} in tree {2}", path, tree.name());
         }
      } finally {
         rw.dispose();
         tw.release();
@@ -595,7 +598,7 @@
    * @return UTF-8 string content
    */
   public static String getStringContent(Repository repository, RevTree tree, String blobPath, String... charsets) {
      byte[] content = getByteContent(repository, tree, blobPath);
      byte[] content = getByteContent(repository, tree, blobPath, true);
      if (content == null) {
         return null;
      }
@@ -745,11 +748,7 @@
            df.setDetectRenames(true);
            List<DiffEntry> diffs = df.scan(parent.getTree(), commit.getTree());
            for (DiffEntry diff : diffs) {
               String objectId = null;
               if (FileMode.GITLINK.equals(diff.getNewMode())) {
                  objectId = diff.getNewId().name();
               }
               String objectId = diff.getNewId().name();
               if (diff.getChangeType().equals(ChangeType.DELETE)) {
                  list.add(new PathChangeModel(diff.getOldPath(), diff.getOldPath(), 0, diff
                        .getNewMode().getBits(), objectId, commit.getId().getName(), diff
@@ -1461,6 +1460,20 @@
         int maxCount) {
      return getRefs(repository, Constants.R_NOTES, fullName, maxCount);
   }
   /**
    * Returns the list of refs in the specified base ref. If repository does
    * not exist or is empty, an empty list is returned.
    *
    * @param repository
    * @param fullName
    *            if true, /refs/yadayadayada is returned. If false,
    *            yadayadayada is returned.
    * @return list of refs
    */
   public static List<RefModel> getRefs(Repository repository, String baseRef) {
      return getRefs(repository, baseRef, true, -1);
   }
   /**
    * Returns a list of references in the repository matching "refs". If the
@@ -1532,7 +1545,7 @@
      try {
         // search for the branch in local heads
         for (RefModel ref : JGitUtils.getLocalBranches(repository, false, -1)) {
            if (ref.displayName.endsWith(name)) {
            if (ref.reference.getName().endsWith(name)) {
               branch = ref;
               break;
            }
@@ -1541,7 +1554,7 @@
         // search for the branch in remote heads
         if (branch == null) {
            for (RefModel ref : JGitUtils.getRemoteBranches(repository, false, -1)) {
               if (ref.displayName.endsWith(name)) {
               if (ref.reference.getName().endsWith(name)) {
                  branch = ref;
                  break;
               }
@@ -1574,7 +1587,7 @@
    */
   public static List<SubmoduleModel> getSubmodules(Repository repository, RevTree tree) {
      List<SubmoduleModel> list = new ArrayList<SubmoduleModel>();
      byte [] blob = getByteContent(repository, tree, ".gitmodules");
      byte [] blob = getByteContent(repository, tree, ".gitmodules", false);
      if (blob == null) {
         return list;
      }
@@ -1607,6 +1620,32 @@
         }
      }
      return null;
   }
   public static String getSubmoduleCommitId(Repository repository, String path, RevCommit commit) {
      String commitId = null;
      RevWalk rw = new RevWalk(repository);
      TreeWalk tw = new TreeWalk(repository);
      tw.setFilter(PathFilterGroup.createFromStrings(Collections.singleton(path)));
      try {
         tw.reset(commit.getTree());
         while (tw.next()) {
            if (tw.isSubtree() && !path.equals(tw.getPathString())) {
               tw.enterSubtree();
               continue;
            }
            if (FileMode.GITLINK == tw.getFileMode(0)) {
               commitId = tw.getObjectId(0).getName();
               break;
            }
         }
      } catch (Throwable t) {
         error(t, repository, "{0} can't find {1} in commit {2}", path, commit.name());
      } finally {
         rw.dispose();
         tw.release();
      }
      return commitId;
   }
   /**
@@ -1653,7 +1692,72 @@
      }
      return list;
   }
   /**
    * this method creates an incremental revision number as a tag according to
    * the amount of already existing tags, which start with a defined prefix {@link REVISION_TAG_PREFIX}
    *
    * @param repository
    * @param objectId
    * @return true if operation was successful, otherwise false
    */
   public static boolean createIncrementalRevisionTag(Repository repository, String objectId) {
      boolean result = false;
      Iterator<Entry<String, Ref>> iterator = repository.getTags().entrySet().iterator();
      long revisionNumber = 1;
      while (iterator.hasNext()) {
         Entry<String, Ref> entry = iterator.next();
         if (entry.getKey().startsWith(REVISION_TAG_PREFIX)) {
            revisionNumber++;
         }
      }
      result = createTag(repository,REVISION_TAG_PREFIX+revisionNumber,objectId);
      return result;
   }
   /**
    * creates a tag in a repository referring to the current head
    *
    * @param repository
    * @param tag, the string label
    * @return boolean, true if operation was successful, otherwise false
    */
   public static boolean createTag(Repository repository, String tag) {
      return createTag(repository, tag, null);
   }
   /**
    * creates a tag in a repository
    *
    * @param repository
    * @param tag, the string label
    * @param objectId, the ref the tag points towards
    * @return boolean, true if operation was successful, otherwise false
    */
   public static boolean createTag(Repository repository, String tag,
         String objectId) {
      try {
         PersonIdent author = new PersonIdent("GitblitAutoTagPush",
               "gitblit@localhost");
         LOGGER.debug("createTag in repo: "+repository.getDirectory().getAbsolutePath());
         Git gitClient = Git.open(repository.getDirectory());
         TagCommand tagCommand = gitClient.tag();
         tagCommand.setTagger(author);
         tagCommand.setMessage("autotag");
         if (objectId != null) {
            RevObject revObj = getCommit(repository, objectId);
            tagCommand.setObjectId(revObj);
         }
         tagCommand.setName(tag);
         Ref call = tagCommand.call();
         return call != null ? true : false;
      } catch (Exception e) {
         e.printStackTrace();
      }
      return false;
   }
   /**
    * Create an orphaned branch in a repository.
    * 
@@ -1724,67 +1828,18 @@
      }
      return success;
   }
   /**
    * Zips the contents of the tree at the (optionally) specified revision and
    * the (optionally) specified basepath to the supplied outputstream.
    * Reads the sparkleshare id, if present, from the repository.
    * 
    * @param repository
    * @param basePath
    *            if unspecified, entire repository is assumed.
    * @param objectId
    *            if unspecified, HEAD is assumed.
    * @param os
    * @return true if repository was successfully zipped to supplied output
    *         stream
    * @return an id or null
    */
   public static boolean zip(Repository repository, String basePath, String objectId,
         OutputStream os) {
      RevCommit commit = getCommit(repository, objectId);
      if (commit == null) {
         return false;
   public static String getSparkleshareId(Repository repository) {
      byte[] content = getByteContent(repository, null, ".sparkleshare", false);
      if (content == null) {
         return null;
      }
      boolean success = false;
      RevWalk rw = new RevWalk(repository);
      TreeWalk tw = new TreeWalk(repository);
      try {
         tw.addTree(commit.getTree());
         ZipOutputStream zos = new ZipOutputStream(os);
         zos.setComment("Generated by Gitblit");
         if (!StringUtils.isEmpty(basePath)) {
            PathFilter f = PathFilter.create(basePath);
            tw.setFilter(f);
         }
         tw.setRecursive(true);
         while (tw.next()) {
            ZipEntry entry = new ZipEntry(tw.getPathString());
            entry.setSize(tw.getObjectReader().getObjectSize(tw.getObjectId(0),
                  Constants.OBJ_BLOB));
            entry.setComment(commit.getName());
            zos.putNextEntry(entry);
            ObjectId entid = tw.getObjectId(0);
            FileMode entmode = tw.getFileMode(0);
            RevBlob blob = (RevBlob) rw.lookupAny(entid, entmode.getObjectType());
            rw.parseBody(blob);
            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) {
               zos.write(tmp, 0, n);
            }
            in.close();
         }
         zos.finish();
         success = true;
      } catch (IOException e) {
         error(e, repository, "{0} failed to zip files from commit {1}", commit.getName());
      } finally {
         tw.release();
         rw.dispose();
      }
      return success;
      return StringUtils.decodeString(content);
   }
}