Support alternate compressed download formats (issue-174)
3 files added
9 files modified
| | |
| | | # SINCE 0.5.0
|
| | | web.allowZipDownloads = true
|
| | |
|
| | | # If *web.allowZipDownloads=true* the following formats will be displayed for
|
| | | # download compressed archive links:
|
| | | #
|
| | | # zip = standard .zip
|
| | | # tar = standard tar format (preserves *nix permissions and symlinks)
|
| | | # gz = gz-compressed tar
|
| | | # xz = xz-compressed tar
|
| | | # bzip2 = bzip2-compressed tar
|
| | | #
|
| | | # SPACE-DELIMITED
|
| | | # SINCE 1.2.0
|
| | | web.compressedDownloads = zip gz
|
| | |
|
| | | # Allow optional Lucene integration. Lucene indexing is an opt-in feature.
|
| | | # A repository may specify branches to index with Lucene instead of using Git
|
| | | # commit traversal. There are scenarios where you may want to completely disable
|
| | |
| | | - Added Gitblit Certificate Authority, an X509 certificate generation tool for Gitblit GO to encourage use of client certificate authentication.
|
| | | - Added setting to control length of shortened commit ids
|
| | | **New:** *web.shortCommitIdLength=8*
|
| | | - Added alternate compressed download formats: tar.gz, tar.xz, tar.bzip2 (issue 174) |
| | | **New:** *web.compressedDownloads = zip gz*
|
| | | - Added simple project pages. A project is a subfolder off the *git.repositoriesFolder*.
|
| | | - Added support for X-Forwarded-Context for Apache subdomain proxy configurations (issue 135)
|
| | | - Delete branch feature (issue 121, Github/ajermakovics)
|
| | |
| | |
|
| | | #### changes
|
| | |
|
| | | - Access restricted servlets (e.g. DownloadZip, RSS, etc) will try to authenticate any Gitblit cookie found in the request before resorting to BASIC authentication.
|
| | | - Added *groovy* and *scala* to *web.prettyPrintExtensions*
|
| | | - Added short commit id column to log and history tables (issue 168)
|
| | | - Teams can now specify the *admin*, *create*, and *fork* roles to simplify user administration
|
| | |
| | | import org.slf4j.Logger;
|
| | | import org.slf4j.LoggerFactory;
|
| | |
|
| | | import com.gitblit.utils.CompressionUtils;
|
| | | import com.gitblit.utils.JGitUtils;
|
| | | import com.gitblit.utils.MarkdownUtils;
|
| | | import com.gitblit.utils.StringUtils;
|
| | |
| | |
|
| | | private transient Logger logger = LoggerFactory.getLogger(DownloadZipServlet.class);
|
| | |
|
| | | public static enum Format {
|
| | | zip(".zip"), tar(".tar"), gz(".tar.gz"), xz(".tar.xz"), bzip2(".tar.bzip2");
|
| | | |
| | | public final String extension;
|
| | | |
| | | Format(String ext) {
|
| | | this.extension = ext;
|
| | | }
|
| | | |
| | | public static Format fromName(String name) {
|
| | | for (Format format : values()) {
|
| | | if (format.name().equalsIgnoreCase(name)) {
|
| | | return format;
|
| | | }
|
| | | }
|
| | | return zip;
|
| | | }
|
| | | }
|
| | |
|
| | | public DownloadZipServlet() {
|
| | | super();
|
| | | }
|
| | |
| | | * @param repository
|
| | | * @param objectId
|
| | | * @param path
|
| | | * @param format
|
| | | * @return an url
|
| | | */
|
| | | public static String asLink(String baseURL, String repository, String objectId, String path) {
|
| | | public static String asLink(String baseURL, String repository, String objectId, String path, Format format) {
|
| | | if (baseURL.length() > 0 && baseURL.charAt(baseURL.length() - 1) == '/') {
|
| | | baseURL = baseURL.substring(0, baseURL.length() - 1);
|
| | | }
|
| | | return baseURL + Constants.ZIP_PATH + "?r=" + repository
|
| | | + (path == null ? "" : ("&p=" + path))
|
| | | + (objectId == null ? "" : ("&h=" + objectId));
|
| | | + (objectId == null ? "" : ("&h=" + objectId))
|
| | | + (format == null ? "" : ("&format=" + format.name()));
|
| | | }
|
| | |
|
| | | /**
|
| | |
| | | return;
|
| | | }
|
| | |
|
| | | Format format = Format.zip;
|
| | | String repository = request.getParameter("r");
|
| | | String basePath = request.getParameter("p");
|
| | | String objectId = request.getParameter("h");
|
| | | String f = request.getParameter("format");
|
| | | if (!StringUtils.isEmpty(f)) {
|
| | | format = Format.fromName(f);
|
| | | }
|
| | |
|
| | | try {
|
| | | String name = repository;
|
| | | if (name.indexOf('/') > -1) {
|
| | | name = name.substring(name.lastIndexOf('/') + 1);
|
| | | }
|
| | | name = StringUtils.stripDotGit(name);
|
| | |
|
| | | if (!StringUtils.isEmpty(basePath)) {
|
| | | name += "-" + basePath.replace('/', '_');
|
| | |
| | |
|
| | | String contentType = "application/octet-stream";
|
| | | response.setContentType(contentType + "; charset=" + response.getCharacterEncoding());
|
| | | response.setHeader("Content-Disposition", "attachment; filename=\"" + name + ".zip"
|
| | | + "\"");
|
| | | response.setHeader("Content-Disposition", "attachment; filename=\"" + name + format.extension + "\"");
|
| | | response.setDateHeader("Last-Modified", date.getTime());
|
| | | response.setHeader("Cache-Control", "no-cache");
|
| | | response.setHeader("Pragma", "no-cache");
|
| | | response.setDateHeader("Expires", 0);
|
| | |
|
| | | try {
|
| | | JGitUtils.zip(r, basePath, objectId, response.getOutputStream());
|
| | | switch (format) {
|
| | | case zip:
|
| | | CompressionUtils.zip(r, basePath, objectId, response.getOutputStream());
|
| | | break;
|
| | | case tar:
|
| | | CompressionUtils.tar(r, basePath, objectId, response.getOutputStream());
|
| | | break;
|
| | | case gz:
|
| | | CompressionUtils.gz(r, basePath, objectId, response.getOutputStream());
|
| | | break;
|
| | | case xz:
|
| | | CompressionUtils.xz(r, basePath, objectId, response.getOutputStream());
|
| | | break;
|
| | | case bzip2:
|
| | | CompressionUtils.bzip2(r, basePath, objectId, response.getOutputStream());
|
| | | break;
|
| | | }
|
| | | |
| | | response.flushBuffer();
|
| | | } catch (Throwable t) {
|
| | | logger.error("Failed to write attachment to client", t);
|
New file |
| | |
| | | /*
|
| | | * 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.InputStream;
|
| | | import java.io.OutputStream;
|
| | | import java.text.MessageFormat;
|
| | | import java.util.ArrayList;
|
| | | import java.util.List;
|
| | | import java.util.zip.ZipEntry;
|
| | | import java.util.zip.ZipOutputStream;
|
| | |
|
| | | import org.apache.commons.compress.archivers.tar.TarArchiveEntry;
|
| | | import org.apache.commons.compress.archivers.tar.TarArchiveOutputStream;
|
| | | import org.apache.commons.compress.compressors.CompressorException;
|
| | | import org.apache.commons.compress.compressors.CompressorStreamFactory;
|
| | | import org.apache.commons.compress.utils.IOUtils;
|
| | | import org.eclipse.jgit.lib.Constants;
|
| | | import org.eclipse.jgit.lib.FileMode;
|
| | | import org.eclipse.jgit.lib.ObjectId;
|
| | | import org.eclipse.jgit.lib.ObjectLoader;
|
| | | import org.eclipse.jgit.lib.Repository;
|
| | | import org.eclipse.jgit.revwalk.RevBlob;
|
| | | 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.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()) {
|
| | | if (tw.getFileMode(0) == FileMode.GITLINK) {
|
| | | continue;
|
| | | }
|
| | | 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;
|
| | | }
|
| | | |
| | | /**
|
| | | * 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.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);
|
| | | while (tw.next()) {
|
| | | FileMode mode = tw.getFileMode(0);
|
| | | if (mode == FileMode.GITLINK) {
|
| | | continue;
|
| | | }
|
| | | ObjectId id = tw.getObjectId(0);
|
| | | |
| | | // new entry
|
| | | TarArchiveEntry entry = new TarArchiveEntry(tw.getPathString());
|
| | | entry.setSize(tw.getObjectReader().getObjectSize(id, Constants.OBJ_BLOB));
|
| | | |
| | | if (FileMode.SYMLINK.equals(mode)) {
|
| | | // symlink
|
| | | entry.setMode(mode.getBits());
|
| | | |
| | | // read the symlink target
|
| | | ByteArrayOutputStream bs = new ByteArrayOutputStream();
|
| | | RevBlob blob = (RevBlob) rw.lookupAny(id, mode.getObjectType());
|
| | | rw.parseBody(blob); |
| | | ObjectLoader ldr = repository.open(blob.getId(), Constants.OBJ_BLOB);
|
| | | IOUtils.copy(ldr.openStream(), bs);
|
| | | entry.setLinkName(bs.toString("UTF-8"));
|
| | | } else {
|
| | | // regular file or executable file
|
| | | entry.setMode(mode.getBits());
|
| | | } |
| | | entry.setModTime(commit.getAuthorIdent().getWhen());
|
| | |
|
| | | tos.putArchiveEntry(entry);
|
| | | |
| | | if (!FileMode.SYMLINK.equals(mode)) {
|
| | | // write the blob
|
| | | RevBlob blob = (RevBlob) rw.lookupAny(id, mode.getObjectType());
|
| | | rw.parseBody(blob); |
| | | ObjectLoader ldr = repository.open(blob.getId(), Constants.OBJ_BLOB);
|
| | | IOUtils.copy(ldr.openStream(), tos);
|
| | | }
|
| | | |
| | | // close entry
|
| | | 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;
|
| | | }
|
| | | }
|
| | |
| | | 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.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;
|
| | |
| | | }
|
| | | } catch (Throwable t) {
|
| | | error(t, repository, "Failed to create orphan branch {1} in repository {0}", branchName);
|
| | | }
|
| | | return success;
|
| | | }
|
| | |
|
| | | /**
|
| | | * 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()) {
|
| | | if (tw.getFileMode(0) == FileMode.GITLINK) {
|
| | | continue;
|
| | | }
|
| | | 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;
|
| | | }
|
| | |
| | | <tr class="hidden-phone"><th><wicket:message key="gb.tree">tree</wicket:message></th>
|
| | | <td><span class="sha1" wicket:id="commitTree">[commit tree]</span>
|
| | | <span class="link">
|
| | | <a wicket:id="treeLink"><wicket:message key="gb.tree"></wicket:message></a> | <a wicket:id="zipLink"><wicket:message key="gb.zip"></wicket:message></a>
|
| | | <a wicket:id="treeLink"><wicket:message key="gb.tree"></wicket:message></a> | <span wicket:id="compressedLinks"></span>
|
| | | </span>
|
| | | </td></tr>
|
| | | <tr class="hidden-phone"><th valign="top"><wicket:message key="gb.parent">parent</wicket:message></th>
|
| | |
| | | import org.apache.wicket.PageParameters;
|
| | | import org.apache.wicket.markup.html.basic.Label;
|
| | | import org.apache.wicket.markup.html.link.BookmarkablePageLink;
|
| | | import org.apache.wicket.markup.html.link.ExternalLink;
|
| | | import org.apache.wicket.markup.repeater.Item;
|
| | | import org.apache.wicket.markup.repeater.data.DataView;
|
| | | import org.apache.wicket.markup.repeater.data.ListDataProvider;
|
| | |
| | | import org.eclipse.jgit.revwalk.RevCommit;
|
| | |
|
| | | import com.gitblit.Constants;
|
| | | import com.gitblit.DownloadZipServlet;
|
| | | import com.gitblit.GitBlit;
|
| | | import com.gitblit.Keys;
|
| | | import com.gitblit.models.GitNote;
|
| | | import com.gitblit.models.SubmoduleModel;
|
| | | import com.gitblit.models.PathModel.PathChangeModel;
|
| | | import com.gitblit.models.SubmoduleModel;
|
| | | import com.gitblit.utils.JGitUtils;
|
| | | import com.gitblit.wicket.WicketUtils;
|
| | | import com.gitblit.wicket.panels.CommitHeaderPanel;
|
| | | import com.gitblit.wicket.panels.CommitLegendPanel;
|
| | | import com.gitblit.wicket.panels.CompressedDownloadsPanel;
|
| | | import com.gitblit.wicket.panels.GravatarImage;
|
| | | import com.gitblit.wicket.panels.LinkPanel;
|
| | | import com.gitblit.wicket.panels.RefsPanel;
|
| | |
| | | newCommitParameter()));
|
| | | add(new BookmarkablePageLink<Void>("treeLink", TreePage.class, newCommitParameter()));
|
| | | final String baseUrl = WicketUtils.getGitblitURL(getRequest());
|
| | | add(new ExternalLink("zipLink", DownloadZipServlet.asLink(baseUrl, repositoryName,
|
| | | objectId, null)).setVisible(GitBlit.getBoolean(Keys.web.allowZipDownloads, true)));
|
| | | |
| | | add(new CompressedDownloadsPanel("compressedLinks", baseUrl, repositoryName, objectId, null));
|
| | |
|
| | | // Parent Commits
|
| | | ListDataProvider<String> parentsDp = new ListDataProvider<String>(parents);
|
| | |
| | |
|
| | | <!-- blob nav links -->
|
| | | <div class="page_nav2">
|
| | | <a wicket:id="historyLink"><wicket:message key="gb.history"></wicket:message></a> | <a wicket:id="headLink"><wicket:message key="gb.head"></wicket:message></a> | <a wicket:id="zipLink"><wicket:message key="gb.zip"></wicket:message></a>
|
| | | <a wicket:id="historyLink"><wicket:message key="gb.history"></wicket:message></a> | <a wicket:id="headLink"><wicket:message key="gb.head"></wicket:message></a> | <span wicket:id="compressedLinks"></span>
|
| | | </div>
|
| | |
|
| | | <!-- commit header -->
|
| | |
| | | <!-- submodule links -->
|
| | | <wicket:fragment wicket:id="submoduleLinks">
|
| | | <span class="link">
|
| | | <a wicket:id="view"><wicket:message key="gb.view"></wicket:message></a> | <span class="hidden-phone"><a wicket:id="tree"><wicket:message key="gb.tree"></wicket:message></a> | </span><a wicket:id="history"><wicket:message key="gb.history"></wicket:message></a> | <a wicket:id="zip"><wicket:message key="gb.zip"></wicket:message></a>
|
| | | <a wicket:id="view"><wicket:message key="gb.view"></wicket:message></a> | <span class="hidden-phone"><a wicket:id="tree"><wicket:message key="gb.tree"></wicket:message></a> | </span><a wicket:id="history"><wicket:message key="gb.history"></wicket:message></a> | <span wicket:id="compressedLinks"></span>
|
| | | </span>
|
| | | </wicket:fragment>
|
| | |
|
| | | <!-- tree links -->
|
| | | <wicket:fragment wicket:id="treeLinks">
|
| | | <span class="link">
|
| | | <span class="hidden-phone"><a wicket:id="tree"><wicket:message key="gb.tree"></wicket:message></a> | </span><a wicket:id="history"><wicket:message key="gb.history"></wicket:message></a> | <a wicket:id="zip"><wicket:message key="gb.zip"></wicket:message></a>
|
| | | <span class="hidden-phone"><a wicket:id="tree"><wicket:message key="gb.tree"></wicket:message></a> | </span><a wicket:id="history"><wicket:message key="gb.history"></wicket:message></a> | <span wicket:id="compressedLinks"></span>
|
| | | </span>
|
| | | </wicket:fragment>
|
| | |
|
| | |
| | | import org.apache.wicket.PageParameters;
|
| | | import org.apache.wicket.markup.html.basic.Label;
|
| | | import org.apache.wicket.markup.html.link.BookmarkablePageLink;
|
| | | import org.apache.wicket.markup.html.link.ExternalLink;
|
| | | import org.apache.wicket.markup.html.panel.Fragment;
|
| | | import org.apache.wicket.markup.repeater.Item;
|
| | | import org.apache.wicket.markup.repeater.data.DataView;
|
| | |
| | | import org.eclipse.jgit.lib.Repository;
|
| | | import org.eclipse.jgit.revwalk.RevCommit;
|
| | |
|
| | | import com.gitblit.DownloadZipServlet;
|
| | | import com.gitblit.GitBlit;
|
| | | import com.gitblit.Keys;
|
| | | import com.gitblit.models.PathModel;
|
| | | import com.gitblit.models.SubmoduleModel;
|
| | | import com.gitblit.utils.ByteFormat;
|
| | | import com.gitblit.utils.JGitUtils;
|
| | | import com.gitblit.wicket.WicketUtils;
|
| | | import com.gitblit.wicket.panels.CommitHeaderPanel;
|
| | | import com.gitblit.wicket.panels.CompressedDownloadsPanel;
|
| | | import com.gitblit.wicket.panels.LinkPanel;
|
| | | import com.gitblit.wicket.panels.PathBreadcrumbsPanel;
|
| | |
|
| | |
| | | WicketUtils.newPathParameter(repositoryName, objectId, path)));
|
| | | add(new BookmarkablePageLink<Void>("headLink", TreePage.class,
|
| | | WicketUtils.newPathParameter(repositoryName, Constants.HEAD, path)));
|
| | | add(new ExternalLink("zipLink", DownloadZipServlet.asLink(getRequest()
|
| | | .getRelativePathPrefixToContextRoot(), repositoryName, objectId, path))
|
| | | .setVisible(GitBlit.getBoolean(Keys.web.allowZipDownloads, true)));
|
| | | add(new CompressedDownloadsPanel("compressedLinks", getRequest()
|
| | | .getRelativePathPrefixToContextRoot(), repositoryName, objectId, path));
|
| | |
|
| | | add(new CommitHeaderPanel("commitHeader", repositoryName, commit));
|
| | |
|
| | |
| | | links.add(new BookmarkablePageLink<Void>("history", HistoryPage.class,
|
| | | WicketUtils.newPathParameter(repositoryName, entry.commitId,
|
| | | entry.path)));
|
| | | links.add(new ExternalLink("zip", DownloadZipServlet.asLink(baseUrl,
|
| | | repositoryName, objectId, entry.path)).setVisible(GitBlit
|
| | | .getBoolean(Keys.web.allowZipDownloads, true)));
|
| | | links.add(new CompressedDownloadsPanel("compressedLinks", baseUrl,
|
| | | repositoryName, objectId, entry.path));
|
| | |
|
| | | item.add(links);
|
| | | } else if (entry.isSubmodule()) {
|
| | | // submodule
|
| | |
| | | links.add(new BookmarkablePageLink<Void>("history", HistoryPage.class,
|
| | | WicketUtils.newPathParameter(submodulePath, submoduleId,
|
| | | "")).setEnabled(hasSubmodule));
|
| | | links.add(new ExternalLink("zip", DownloadZipServlet.asLink(baseUrl,
|
| | | submodulePath, submoduleId, "")).setVisible(GitBlit
|
| | | .getBoolean(Keys.web.allowZipDownloads, true)).setEnabled(hasSubmodule));
|
| | | links.add(new CompressedDownloadsPanel("compressedLinks", baseUrl,
|
| | | submodulePath, submoduleId, "").setEnabled(hasSubmodule));
|
| | | item.add(links);
|
| | | } else {
|
| | | // blob link
|
New file |
| | |
| | | <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
| | | <html xmlns="http://www.w3.org/1999/xhtml" |
| | | xmlns:wicket="http://wicket.apache.org/dtds.data/wicket-xhtml1.3-strict.dtd" |
| | | xml:lang="en" |
| | | lang="en"> |
| | |
|
| | | <wicket:panel>
|
| | | <span wicket:id="compressedLinks">
|
| | | <span wicket:id="linkSep">|</span><span wicket:id="compressedLink">ref</span>
|
| | | </span> |
| | | </wicket:panel>
|
| | | </html> |
New file |
| | |
| | | /*
|
| | | * 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.wicket.panels;
|
| | |
|
| | | import java.util.List;
|
| | |
|
| | | import org.apache.wicket.Component;
|
| | | import org.apache.wicket.markup.html.basic.Label;
|
| | | import org.apache.wicket.markup.html.panel.Panel;
|
| | | import org.apache.wicket.markup.repeater.Item;
|
| | | import org.apache.wicket.markup.repeater.data.DataView;
|
| | | import org.apache.wicket.markup.repeater.data.ListDataProvider;
|
| | |
|
| | | import com.gitblit.DownloadZipServlet;
|
| | | import com.gitblit.DownloadZipServlet.Format;
|
| | | import com.gitblit.GitBlit;
|
| | | import com.gitblit.Keys;
|
| | |
|
| | | public class CompressedDownloadsPanel extends Panel {
|
| | |
|
| | | private static final long serialVersionUID = 1L;
|
| | |
|
| | | public CompressedDownloadsPanel(String id, final String baseUrl, final String repositoryName, final String objectId, final String path) {
|
| | | super(id);
|
| | | |
| | | List<String> types = GitBlit.getStrings(Keys.web.compressedDownloads);
|
| | | if (types.isEmpty()) {
|
| | | types.add(Format.zip.name());
|
| | | types.add(Format.gz.name());
|
| | | }
|
| | | |
| | | ListDataProvider<String> refsDp = new ListDataProvider<String>(types);
|
| | | DataView<String> refsView = new DataView<String>("compressedLinks", refsDp) {
|
| | | private static final long serialVersionUID = 1L;
|
| | | int counter;
|
| | |
|
| | | @Override
|
| | | protected void onBeforeRender() {
|
| | | super.onBeforeRender();
|
| | | counter = 0;
|
| | | }
|
| | | |
| | | @Override
|
| | | public void populateItem(final Item<String> item) {
|
| | | String compressionType = item.getModelObject();
|
| | | Format format = Format.fromName(compressionType);
|
| | | |
| | | String href = DownloadZipServlet.asLink(baseUrl, repositoryName,
|
| | | objectId, path, format);
|
| | | Component c = new LinkPanel("compressedLink", null, format.name(), href);
|
| | | item.add(c);
|
| | | Label lb = new Label("linkSep", "|");
|
| | | lb.setVisible(counter > 0);
|
| | | lb.setRenderBodyOnly(true);
|
| | | item.add(lb.setEscapeModelStrings(false));
|
| | | item.setRenderBodyOnly(true);
|
| | | counter++;
|
| | | }
|
| | | };
|
| | | add(refsView);
|
| | | |
| | | setVisible(GitBlit.getBoolean(Keys.web.allowZipDownloads, true));
|
| | | }
|
| | | } |
| | |
| | | import com.gitblit.models.PathModel;
|
| | | import com.gitblit.models.PathModel.PathChangeModel;
|
| | | import com.gitblit.models.RefModel;
|
| | | import com.gitblit.utils.CompressionUtils;
|
| | | import com.gitblit.utils.JGitUtils;
|
| | | import com.gitblit.utils.StringUtils;
|
| | |
|
| | |
| | |
|
| | | @Test
|
| | | public void testZip() throws Exception {
|
| | | assertFalse(JGitUtils.zip(null, null, null, null));
|
| | | assertFalse(CompressionUtils.zip(null, null, null, null));
|
| | | Repository repository = GitBlitSuite.getHelloworldRepository();
|
| | | File zipFileA = new File(GitBlitSuite.REPOSITORIES, "helloworld.zip");
|
| | | FileOutputStream fosA = new FileOutputStream(zipFileA);
|
| | | boolean successA = JGitUtils.zip(repository, null, Constants.HEAD, fosA);
|
| | | boolean successA = CompressionUtils.zip(repository, null, Constants.HEAD, fosA);
|
| | | fosA.close();
|
| | |
|
| | | File zipFileB = new File(GitBlitSuite.REPOSITORIES, "helloworld-java.zip");
|
| | | FileOutputStream fosB = new FileOutputStream(zipFileB);
|
| | | boolean successB = JGitUtils.zip(repository, "java.java", Constants.HEAD, fosB);
|
| | | boolean successB = CompressionUtils.zip(repository, "java.java", Constants.HEAD, fosB);
|
| | | fosB.close();
|
| | |
|
| | | repository.close();
|