| | |
| | | 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;
|
| | |
| | | import org.eclipse.jgit.errors.IncorrectObjectTypeException;
|
| | | import org.eclipse.jgit.errors.MissingObjectException;
|
| | | import org.eclipse.jgit.errors.StopWalkException;
|
| | | import org.eclipse.jgit.lib.BlobBasedConfig;
|
| | | import org.eclipse.jgit.lib.CommitBuilder;
|
| | | import org.eclipse.jgit.lib.Constants;
|
| | | import org.eclipse.jgit.lib.FileMode;
|
| | |
| | | import org.eclipse.jgit.lib.RefUpdate.Result;
|
| | | import org.eclipse.jgit.lib.Repository;
|
| | | import org.eclipse.jgit.lib.RepositoryCache.FileKey;
|
| | | import org.eclipse.jgit.lib.StoredConfig;
|
| | | import org.eclipse.jgit.lib.TreeFormatter;
|
| | | import org.eclipse.jgit.revwalk.RevBlob;
|
| | | import org.eclipse.jgit.revwalk.RevCommit;
|
| | |
| | | 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;
|
| | | import com.gitblit.models.RefModel;
|
| | | import com.gitblit.models.SubmoduleModel;
|
| | |
|
| | | /**
|
| | | * Collection of static methods for retrieving information from a repository.
|
| | |
| | | */
|
| | | public class JGitUtils {
|
| | |
|
| | | private static final String REVISION_TAG_PREFIX = "rev_";
|
| | | static final Logger LOGGER = LoggerFactory.getLogger(JGitUtils.class);
|
| | |
|
| | | /**
|
| | |
| | | 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();
|
| | |
| | | if (repositoriesFolder == null || !repositoriesFolder.exists()) {
|
| | | return list;
|
| | | }
|
| | | List<Pattern> patterns = new ArrayList<Pattern>();
|
| | | if (!ArrayUtils.isEmpty(exclusions)) {
|
| | | for (String regex : exclusions) {
|
| | | patterns.add(Pattern.compile(regex));
|
| | | }
|
| | | }
|
| | | list.addAll(getRepositoryList(repositoriesFolder.getAbsolutePath(), repositoriesFolder,
|
| | | onlyBare, searchSubfolders, depth, exclusions));
|
| | | onlyBare, searchSubfolders, depth, patterns));
|
| | | StringUtils.sortRepositorynames(list);
|
| | | return list;
|
| | | }
|
| | |
| | | * recurse into subfolders to find grouped repositories
|
| | | * @param depth
|
| | | * recursion depth, -1 = infinite recursion
|
| | | * @param exclusions
|
| | | * list of regex exclusions for matching to folder names
|
| | | * @param patterns
|
| | | * list of regex patterns for matching to folder names
|
| | | * @return
|
| | | */
|
| | | private static List<String> getRepositoryList(String basePath, File searchFolder,
|
| | | boolean onlyBare, boolean searchSubfolders, int depth, List<String> exclusions) {
|
| | | boolean onlyBare, boolean searchSubfolders, int depth, List<Pattern> patterns) {
|
| | | File baseFile = new File(basePath);
|
| | | List<String> list = new ArrayList<String>();
|
| | | if (depth == 0) {
|
| | | return list;
|
| | | }
|
| | | List<Pattern> patterns = new ArrayList<Pattern>();
|
| | | if (!ArrayUtils.isEmpty(exclusions)) {
|
| | | for (String regex : exclusions) {
|
| | | patterns.add(Pattern.compile(regex));
|
| | | }
|
| | | }
|
| | |
|
| | | int nextDepth = (depth == -1) ? -1 : depth - 1;
|
| | |
| | | boolean exclude = false;
|
| | | for (Pattern pattern : patterns) {
|
| | | String path = FileUtils.getRelativePath(baseFile, file).replace('\\', '/');
|
| | | if (pattern.matcher(path).find()) {
|
| | | if (pattern.matcher(path).matches()) {
|
| | | LOGGER.debug(MessageFormat.format("excluding {0} because of rule {1}", path, pattern.pattern()));
|
| | | exclude = true;
|
| | | break;
|
| | |
| | | } else if (searchSubfolders && file.canRead()) {
|
| | | // look for repositories in subfolders
|
| | | list.addAll(getRepositoryList(basePath, file, onlyBare, searchSubfolders,
|
| | | nextDepth, exclusions));
|
| | | nextDepth, patterns));
|
| | | }
|
| | | } else if (searchSubfolders && file.canRead()) {
|
| | | // look for repositories in subfolders
|
| | | list.addAll(getRepositoryList(basePath, file, onlyBare, searchSubfolders,
|
| | | nextDepth, exclusions));
|
| | | nextDepth, patterns));
|
| | | }
|
| | | }
|
| | | }
|
| | |
| | | * @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)));
|
| | |
| | | }
|
| | | ObjectId entid = tw.getObjectId(0);
|
| | | FileMode entmode = tw.getFileMode(0);
|
| | | 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);
|
| | | 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();
|
| | | }
|
| | | in.close();
|
| | | content = os.toByteArray();
|
| | | }
|
| | | } 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();
|
| | |
| | | * @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;
|
| | | }
|
| | |
| | | tw.addTree(commit.getTree());
|
| | | while (tw.next()) {
|
| | | list.add(new PathChangeModel(tw.getPathString(), tw.getPathString(), 0, tw
|
| | | .getRawMode(0), commit.getId().getName(), ChangeType.ADD));
|
| | | .getRawMode(0), tw.getObjectId(0).getName(), commit.getId().getName(),
|
| | | ChangeType.ADD));
|
| | | }
|
| | | tw.release();
|
| | | } else {
|
| | |
| | | df.setDetectRenames(true);
|
| | | List<DiffEntry> diffs = df.scan(parent.getTree(), commit.getTree());
|
| | | for (DiffEntry diff : diffs) {
|
| | | String objectId = diff.getNewId().name();
|
| | | if (diff.getChangeType().equals(ChangeType.DELETE)) {
|
| | | list.add(new PathChangeModel(diff.getOldPath(), diff.getOldPath(), 0, diff
|
| | | .getNewMode().getBits(), commit.getId().getName(), diff
|
| | | .getNewMode().getBits(), objectId, 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
|
| | | .getNewMode().getBits(), objectId, commit.getId().getName(), diff
|
| | | .getChangeType()));
|
| | | } else {
|
| | | list.add(new PathChangeModel(diff.getNewPath(), diff.getNewPath(), 0, diff
|
| | | .getNewMode().getBits(), commit.getId().getName(), diff
|
| | | .getNewMode().getBits(), objectId, commit.getId().getName(), diff
|
| | | .getChangeType()));
|
| | | }
|
| | | }
|
| | |
| | | } else {
|
| | | name = tw.getPathString().substring(basePath.length() + 1);
|
| | | }
|
| | | ObjectId objectId = tw.getObjectId(0);
|
| | | try {
|
| | | if (!tw.isSubtree()) {
|
| | | size = tw.getObjectReader().getObjectSize(tw.getObjectId(0), Constants.OBJ_BLOB);
|
| | | if (!tw.isSubtree() && (tw.getFileMode(0) != FileMode.GITLINK)) {
|
| | | size = tw.getObjectReader().getObjectSize(objectId, Constants.OBJ_BLOB);
|
| | | }
|
| | | } catch (Throwable t) {
|
| | | error(t, null, "failed to retrieve blob size for " + tw.getPathString());
|
| | | }
|
| | | return new PathModel(name, tw.getPathString(), size, tw.getFileMode(0).getBits(),
|
| | | commit.getName());
|
| | | objectId.getName(), commit.getName());
|
| | | }
|
| | |
|
| | | /**
|
| | |
| | | } else if (FileMode.EXECUTABLE_FILE.equals(mode)) {
|
| | | return "-rwxr-xr-x";
|
| | | } else if (FileMode.SYMLINK.equals(mode)) {
|
| | | // FIXME symlink permissions
|
| | | return "symlink";
|
| | | } else if (FileMode.GITLINK.equals(mode)) {
|
| | | // FIXME gitlink permissions
|
| | | return "gitlink";
|
| | | return "submodule";
|
| | | }
|
| | | // FIXME missing permissions
|
| | | return "missing";
|
| | | }
|
| | |
|
| | |
| | | * @return all refs grouped by their referenced object id
|
| | | */
|
| | | public static Map<ObjectId, List<RefModel>> getAllRefs(Repository repository) {
|
| | | return getAllRefs(repository, true);
|
| | | }
|
| | | |
| | | /**
|
| | | * Returns all refs grouped by their associated object id.
|
| | | * |
| | | * @param repository
|
| | | * @param includeRemoteRefs
|
| | | * @return all refs grouped by their referenced object id
|
| | | */
|
| | | public static Map<ObjectId, List<RefModel>> getAllRefs(Repository repository, boolean includeRemoteRefs) {
|
| | | List<RefModel> list = getRefs(repository, org.eclipse.jgit.lib.RefDatabase.ALL, true, -1);
|
| | | Map<ObjectId, List<RefModel>> refs = new HashMap<ObjectId, List<RefModel>>();
|
| | | for (RefModel ref : list) {
|
| | | if (!includeRemoteRefs && ref.getName().startsWith(Constants.R_REMOTES)) {
|
| | | continue;
|
| | | }
|
| | | ObjectId objectid = ref.getReferencedObjectId();
|
| | | if (!refs.containsKey(objectid)) {
|
| | | refs.put(objectid, new ArrayList<RefModel>());
|
| | |
| | | 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
|
| | |
| | | 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;
|
| | | }
|
| | |
| | | // 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;
|
| | | }
|
| | |
| | | LOGGER.error(MessageFormat.format("Failed to find {0} branch!", name), t);
|
| | | }
|
| | | return branch;
|
| | | }
|
| | | |
| | | /**
|
| | | * Returns the list of submodules for this repository.
|
| | | * |
| | | * @param repository
|
| | | * @param commit
|
| | | * @return list of submodules
|
| | | */
|
| | | public static List<SubmoduleModel> getSubmodules(Repository repository, String commitId) {
|
| | | RevCommit commit = getCommit(repository, commitId);
|
| | | return getSubmodules(repository, commit.getTree());
|
| | | }
|
| | | |
| | | /**
|
| | | * Returns the list of submodules for this repository.
|
| | | * |
| | | * @param repository
|
| | | * @param commit
|
| | | * @return list of submodules
|
| | | */
|
| | | public static List<SubmoduleModel> getSubmodules(Repository repository, RevTree tree) {
|
| | | List<SubmoduleModel> list = new ArrayList<SubmoduleModel>();
|
| | | byte [] blob = getByteContent(repository, tree, ".gitmodules", false);
|
| | | if (blob == null) {
|
| | | return list;
|
| | | }
|
| | | try {
|
| | | BlobBasedConfig config = new BlobBasedConfig(repository.getConfig(), blob);
|
| | | for (String module : config.getSubsections("submodule")) {
|
| | | String path = config.getString("submodule", module, "path");
|
| | | String url = config.getString("submodule", module, "url");
|
| | | list.add(new SubmoduleModel(module, path, url));
|
| | | }
|
| | | } catch (ConfigInvalidException e) {
|
| | | LOGGER.error("Failed to load .gitmodules file for " + repository.getDirectory(), e);
|
| | | }
|
| | | return list;
|
| | | }
|
| | | |
| | | /**
|
| | | * Returns the submodule definition for the specified path at the specified
|
| | | * commit. If no module is defined for the path, null is returned.
|
| | | * |
| | | * @param repository
|
| | | * @param commit
|
| | | * @param path
|
| | | * @return a submodule definition or null if there is no submodule
|
| | | */
|
| | | public static SubmoduleModel getSubmoduleModel(Repository repository, String commitId, String path) {
|
| | | for (SubmoduleModel model : getSubmodules(repository, commitId)) {
|
| | | if (model.path.equals(path)) {
|
| | | return model;
|
| | | }
|
| | | }
|
| | | 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;
|
| | | }
|
| | |
|
| | | /**
|
| | |
| | | }
|
| | | 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.
|
| | | *
|
| | |
| | | }
|
| | | return success;
|
| | | }
|
| | |
|
| | | |
| | | /**
|
| | | * Returns a StoredConfig object for the repository.
|
| | | * Reads the sparkleshare id, if present, from the repository.
|
| | | *
|
| | | * @param repository
|
| | | * @return the StoredConfig of the repository
|
| | | * @return an id or null
|
| | | */
|
| | | public static StoredConfig readConfig(Repository repository) {
|
| | | StoredConfig c = repository.getConfig();
|
| | | try {
|
| | | c.load();
|
| | | } catch (ConfigInvalidException cex) {
|
| | | error(cex, repository, "{0} configuration is invalid!");
|
| | | } catch (IOException cex) {
|
| | | error(cex, repository, "Could not open configuration for {0}!");
|
| | | public static String getSparkleshareId(Repository repository) {
|
| | | byte[] content = getByteContent(repository, null, ".sparkleshare", false);
|
| | | if (content == null) {
|
| | | return null;
|
| | | }
|
| | | return c;
|
| | | }
|
| | |
|
| | | /**
|
| | | * Zips the contents of the tree at the (optionally) specified revision and
|
| | | * the (optionally) specified basepath to the supplied outputstream.
|
| | | * |
| | | * @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
|
| | | */
|
| | | public static boolean zip(Repository repository, String basePath, String objectId,
|
| | | OutputStream os) {
|
| | | RevCommit commit = getCommit(repository, objectId);
|
| | | if (commit == null) {
|
| | | return false;
|
| | | }
|
| | | 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);
|
| | | }
|
| | | }
|