Package com.gitblit.utils

Source Code of com.gitblit.utils.CompressionUtils

/*
* Copyright 2012 gitblit.com.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*     http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.gitblit.utils;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.List;

import org.apache.commons.compress.archivers.tar.TarArchiveEntry;
import org.apache.commons.compress.archivers.tar.TarArchiveOutputStream;
import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
import org.apache.commons.compress.archivers.zip.ZipArchiveOutputStream;
import org.apache.commons.compress.compressors.CompressorException;
import org.apache.commons.compress.compressors.CompressorStreamFactory;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.FileMode;
import org.eclipse.jgit.lib.MutableObjectId;
import org.eclipse.jgit.lib.ObjectLoader;
import org.eclipse.jgit.lib.ObjectReader;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevWalk;
import org.eclipse.jgit.treewalk.TreeWalk;
import org.eclipse.jgit.treewalk.filter.PathFilter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
* Collection of static methods for retrieving information from a repository.
*
* @author James Moger
*
*/
public class CompressionUtils {

  static final Logger LOGGER = LoggerFactory.getLogger(CompressionUtils.class);

  /**
   * Log an error message and exception.
   *
   * @param t
   * @param repository
   *            if repository is not null it MUST be the {0} parameter in the
   *            pattern.
   * @param pattern
   * @param objects
   */
  private static void error(Throwable t, Repository repository, String pattern, Object... objects) {
    List<Object> parameters = new ArrayList<Object>();
    if (objects != null && objects.length > 0) {
      for (Object o : objects) {
        parameters.add(o);
      }
    }
    if (repository != null) {
      parameters.add(0, repository.getDirectory().getAbsolutePath());
    }
    LOGGER.error(MessageFormat.format(pattern, parameters.toArray()), t);
  }

  /**
   * 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 = JGitUtils.getCommit(repository, objectId);
    if (commit == null) {
      return false;
    }
    boolean success = false;
    RevWalk rw = new RevWalk(repository);
    TreeWalk tw = new TreeWalk(repository);
    try {
      tw.reset();
      tw.addTree(commit.getTree());
      ZipArchiveOutputStream zos = new ZipArchiveOutputStream(os);
      zos.setComment("Generated by Gitblit");
      if (!StringUtils.isEmpty(basePath)) {
        PathFilter f = PathFilter.create(basePath);
        tw.setFilter(f);
      }
      tw.setRecursive(true);
      MutableObjectId id = new MutableObjectId();
      ObjectReader reader = tw.getObjectReader();
      long modified = commit.getAuthorIdent().getWhen().getTime();
      while (tw.next()) {
        FileMode mode = tw.getFileMode(0);
        if (mode == FileMode.GITLINK || mode == FileMode.TREE) {
          continue;
        }
        tw.getObjectId(id, 0);

        ZipArchiveEntry entry = new ZipArchiveEntry(tw.getPathString());
        entry.setSize(reader.getObjectSize(id, Constants.OBJ_BLOB));
        entry.setComment(commit.getName());
        entry.setUnixMode(mode.getBits());
        entry.setTime(modified);
        zos.putArchiveEntry(entry);

        ObjectLoader ldr = repository.open(id);
        ldr.copyTo(zos);
        zos.closeArchiveEntry();
      }
      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;
  }

  /**
   * tar 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 tar(Repository repository, String basePath, String objectId,
      OutputStream os) {
    return tar(null, repository, basePath, objectId, os);
  }

  /**
   * tar.gz 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 gz(Repository repository, String basePath, String objectId,
      OutputStream os) {
    return tar(CompressorStreamFactory.GZIP, repository, basePath, objectId, os);
  }

  /**
   * tar.xz 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 xz(Repository repository, String basePath, String objectId,
      OutputStream os) {
    return tar(CompressorStreamFactory.XZ, repository, basePath, objectId, os);
  }

  /**
   * tar.bzip2 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 bzip2(Repository repository, String basePath, String objectId,
      OutputStream os) {

    return tar(CompressorStreamFactory.BZIP2, repository, basePath, objectId, os);
  }

  /**
   * Compresses/archives the contents of the tree at the (optionally)
   * specified revision and the (optionally) specified basepath to the
   * supplied outputstream.
   *
   * @param algorithm
   *            compression algorithm for tar (optional)
   * @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
   */
  private static boolean tar(String algorithm, Repository repository, String basePath, String objectId,
      OutputStream os) {
    RevCommit commit = JGitUtils.getCommit(repository, objectId);
    if (commit == null) {
      return false;
    }

    OutputStream cos = os;
    if (!StringUtils.isEmpty(algorithm)) {
      try {
        cos = new CompressorStreamFactory().createCompressorOutputStream(algorithm, os);
      } catch (CompressorException e1) {
        error(e1, repository, "{0} failed to open {1} stream", algorithm);
      }
    }
    boolean success = false;
    RevWalk rw = new RevWalk(repository);
    TreeWalk tw = new TreeWalk(repository);
    try {
      tw.reset();
      tw.addTree(commit.getTree());
      TarArchiveOutputStream tos = new TarArchiveOutputStream(cos);
      tos.setAddPaxHeadersForNonAsciiNames(true);
      tos.setLongFileMode(TarArchiveOutputStream.LONGFILE_POSIX);
      if (!StringUtils.isEmpty(basePath)) {
        PathFilter f = PathFilter.create(basePath);
        tw.setFilter(f);
      }
      tw.setRecursive(true);
      MutableObjectId id = new MutableObjectId();
      long modified = commit.getAuthorIdent().getWhen().getTime();
      while (tw.next()) {
        FileMode mode = tw.getFileMode(0);
        if (mode == FileMode.GITLINK || mode == FileMode.TREE) {
          continue;
        }
        tw.getObjectId(id, 0);

        ObjectLoader loader = repository.open(id);
        if (FileMode.SYMLINK == mode) {
          TarArchiveEntry entry = new TarArchiveEntry(tw.getPathString(),TarArchiveEntry.LF_SYMLINK);
          ByteArrayOutputStream bos = new ByteArrayOutputStream();
          loader.copyTo(bos);
          entry.setLinkName(bos.toString());
          entry.setModTime(modified);
          tos.putArchiveEntry(entry);
          tos.closeArchiveEntry();
        } else {
          TarArchiveEntry entry = new TarArchiveEntry(tw.getPathString());
          entry.setMode(mode.getBits());
          entry.setModTime(modified);
          entry.setSize(loader.getSize());
          tos.putArchiveEntry(entry);
          loader.copyTo(tos);
          tos.closeArchiveEntry();
        }
      }
      tos.finish();
      tos.close();
      cos.close();
      success = true;
    } catch (IOException e) {
      error(e, repository, "{0} failed to {1} stream files from commit {2}", algorithm, commit.getName());
    } finally {
      tw.release();
      rw.dispose();
    }
    return success;
  }
}
TOP

Related Classes of com.gitblit.utils.CompressionUtils

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.