Download commands: Add JGit archive
Since JGit 3.1 archive command was implemented. Add it to download drop down as new line. The following libraries are introduced in this change: * jgit-archive (Apache 2) * commons-compress (Apache 2) * tukaani-xz (Public domain) Change-Id: I5f61aac8c434414c73585a9320e84f4430dd111d
This commit is contained in:
		
				
					committed by
					
						
						David Ostrovsky
					
				
			
			
				
	
			
			
			
						parent
						
							b6af30e13c
						
					
				
				
					commit
					fbf6b7dabd
				
			@@ -40,9 +40,13 @@ import com.google.gwt.user.client.ui.VerticalPanel;
 | 
			
		||||
import com.google.gwt.user.client.ui.Widget;
 | 
			
		||||
import com.google.gwtexpui.clippy.client.CopyableLabel;
 | 
			
		||||
 | 
			
		||||
import java.util.ArrayList;
 | 
			
		||||
import java.util.EnumSet;
 | 
			
		||||
import java.util.Iterator;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
 | 
			
		||||
class DownloadBox extends VerticalPanel {
 | 
			
		||||
  private final static String ARCHIVE[] = {"tar", "tbz2", "tgz", "txz"};
 | 
			
		||||
  private final ChangeInfo change;
 | 
			
		||||
  private final String revision;
 | 
			
		||||
  private final PatchSet.Id psId;
 | 
			
		||||
@@ -109,6 +113,7 @@ class DownloadBox extends VerticalPanel {
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    insertPatch();
 | 
			
		||||
    insertArchive();
 | 
			
		||||
    insertCommand(null, scheme);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
@@ -141,6 +146,34 @@ class DownloadBox extends VerticalPanel {
 | 
			
		||||
    insertCommand("Patch-File", p);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private void insertArchive() {
 | 
			
		||||
    List<Anchor> formats = new ArrayList<>(ARCHIVE.length);
 | 
			
		||||
    for (String f : ARCHIVE) {
 | 
			
		||||
      Anchor archive = new Anchor(f);
 | 
			
		||||
      archive.setHref(new RestApi("/changes/")
 | 
			
		||||
          .id(psId.getParentKey().get())
 | 
			
		||||
          .view("revisions")
 | 
			
		||||
          .id(revision)
 | 
			
		||||
          .view("archive")
 | 
			
		||||
          .addParameter("format", f)
 | 
			
		||||
          .url());
 | 
			
		||||
      formats.add(archive);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    HorizontalPanel p = new HorizontalPanel();
 | 
			
		||||
    Iterator<Anchor> it = formats.iterator();
 | 
			
		||||
    while (it.hasNext()) {
 | 
			
		||||
      Anchor a = it.next();
 | 
			
		||||
      p.add(a);
 | 
			
		||||
      if (it.hasNext()) {
 | 
			
		||||
        InlineLabel spacer = new InlineLabel("|");
 | 
			
		||||
        spacer.setStyleName(Gerrit.RESOURCES.css().downloadBoxSpacer());
 | 
			
		||||
        p.add(spacer);
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    insertCommand("Archive", p);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private void insertCommand(String commandName, Widget w) {
 | 
			
		||||
    int row = commandTable.getRowCount();
 | 
			
		||||
    commandTable.insertRow(row);
 | 
			
		||||
 
 | 
			
		||||
@@ -57,6 +57,7 @@ java_library2(
 | 
			
		||||
    '//lib/guice:guice-assistedinject',
 | 
			
		||||
    '//lib/guice:guice-servlet',
 | 
			
		||||
    '//lib/jgit:jgit',
 | 
			
		||||
    '//lib/jgit:jgit-archive',
 | 
			
		||||
    '//lib/joda:joda-time',
 | 
			
		||||
    '//lib/log:api',
 | 
			
		||||
    '//lib/prolog:prolog-cafe',
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,84 @@
 | 
			
		||||
// Copyright 2013 Google Inc. All Rights Reserved.
 | 
			
		||||
//
 | 
			
		||||
// 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.google.gerrit.server.change;
 | 
			
		||||
 | 
			
		||||
import com.google.common.collect.Maps;
 | 
			
		||||
 | 
			
		||||
import org.eclipse.jgit.api.ArchiveCommand;
 | 
			
		||||
import org.eclipse.jgit.archive.TarFormat;
 | 
			
		||||
import org.eclipse.jgit.archive.Tbz2Format;
 | 
			
		||||
import org.eclipse.jgit.archive.TgzFormat;
 | 
			
		||||
import org.eclipse.jgit.archive.TxzFormat;
 | 
			
		||||
import org.slf4j.Logger;
 | 
			
		||||
import org.slf4j.LoggerFactory;
 | 
			
		||||
 | 
			
		||||
import java.util.Collections;
 | 
			
		||||
import java.util.Map;
 | 
			
		||||
 | 
			
		||||
enum ArchiveFormat {
 | 
			
		||||
  TGZ("application/x-gzip", new TgzFormat()),
 | 
			
		||||
  TAR("application/x-tar", new TarFormat()),
 | 
			
		||||
  TBZ2("application/x-bzip2", new Tbz2Format()),
 | 
			
		||||
  TXZ("application/x-xz", new TxzFormat());
 | 
			
		||||
  // Zip is not supported because it may be interpreted by a Java plugin as a
 | 
			
		||||
  // valid JAR file, whose code would have access to cookies on the domain.
 | 
			
		||||
 | 
			
		||||
  static final Logger log = LoggerFactory.getLogger(ArchiveFormat.class);
 | 
			
		||||
 | 
			
		||||
  private final ArchiveCommand.Format<?> format;
 | 
			
		||||
  private final String mimeType;
 | 
			
		||||
 | 
			
		||||
  private ArchiveFormat(String mimeType, ArchiveCommand.Format<?> format) {
 | 
			
		||||
    this.format = format;
 | 
			
		||||
    this.mimeType = mimeType;
 | 
			
		||||
    ArchiveCommand.registerFormat(name(), format);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  String getShortName() {
 | 
			
		||||
    return name().toLowerCase();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  String getMimeType() {
 | 
			
		||||
    return mimeType;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  String getDefaultSuffix() {
 | 
			
		||||
    return getSuffixes().iterator().next();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  Iterable<String> getSuffixes() {
 | 
			
		||||
    return format.suffixes();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  static Map<String, ArchiveFormat> init() {
 | 
			
		||||
    String[] formats = new String[values().length];
 | 
			
		||||
    for (int i = 0; i < values().length; i++) {
 | 
			
		||||
      formats[i] = values()[i].name();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    Map<String, ArchiveFormat> exts = Maps.newLinkedHashMap();
 | 
			
		||||
    for (String name : formats) {
 | 
			
		||||
      try {
 | 
			
		||||
        ArchiveFormat format = valueOf(name.toUpperCase());
 | 
			
		||||
        for (String ext : format.getSuffixes()) {
 | 
			
		||||
          exts.put(ext, format);
 | 
			
		||||
        }
 | 
			
		||||
      } catch (IllegalArgumentException e) {
 | 
			
		||||
        log.warn("Invalid archive.format {}", name);
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    return Collections.unmodifiableMap(exts);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,111 @@
 | 
			
		||||
// Copyright (C) 2014 The Android Open Source Project
 | 
			
		||||
//
 | 
			
		||||
// 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.google.gerrit.server.change;
 | 
			
		||||
 | 
			
		||||
import com.google.common.base.Strings;
 | 
			
		||||
import com.google.gerrit.extensions.restapi.BadRequestException;
 | 
			
		||||
import com.google.gerrit.extensions.restapi.BinaryResult;
 | 
			
		||||
import com.google.gerrit.extensions.restapi.RestReadView;
 | 
			
		||||
import com.google.gerrit.server.git.GitRepositoryManager;
 | 
			
		||||
import com.google.inject.Inject;
 | 
			
		||||
 | 
			
		||||
import org.eclipse.jgit.api.ArchiveCommand;
 | 
			
		||||
import org.eclipse.jgit.api.errors.GitAPIException;
 | 
			
		||||
import org.eclipse.jgit.lib.ObjectId;
 | 
			
		||||
import org.eclipse.jgit.lib.Repository;
 | 
			
		||||
import org.eclipse.jgit.revwalk.RevCommit;
 | 
			
		||||
import org.eclipse.jgit.revwalk.RevWalk;
 | 
			
		||||
import org.kohsuke.args4j.Option;
 | 
			
		||||
 | 
			
		||||
import java.io.IOException;
 | 
			
		||||
import java.io.OutputStream;
 | 
			
		||||
import java.util.Map;
 | 
			
		||||
 | 
			
		||||
class GetArchive implements RestReadView<RevisionResource> {
 | 
			
		||||
  private static final Map<String, ArchiveFormat> formats = ArchiveFormat.init();
 | 
			
		||||
  private final GitRepositoryManager repoManager;
 | 
			
		||||
 | 
			
		||||
  @Option(name = "--format")
 | 
			
		||||
  private String format;
 | 
			
		||||
 | 
			
		||||
  @Inject
 | 
			
		||||
  GetArchive(GitRepositoryManager repoManager) {
 | 
			
		||||
    this.repoManager = repoManager;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @Override
 | 
			
		||||
  public BinaryResult apply(RevisionResource rsrc)
 | 
			
		||||
      throws BadRequestException, IOException {
 | 
			
		||||
    if (Strings.isNullOrEmpty(format)) {
 | 
			
		||||
      throw new BadRequestException("format is not specified");
 | 
			
		||||
    }
 | 
			
		||||
    final ArchiveFormat f = formats.get("." + format);
 | 
			
		||||
    if (f == null) {
 | 
			
		||||
      throw new BadRequestException("unknown archive format");
 | 
			
		||||
    }
 | 
			
		||||
    boolean close = true;
 | 
			
		||||
    final Repository repo = repoManager
 | 
			
		||||
        .openRepository(rsrc.getControl().getProject().getNameKey());
 | 
			
		||||
    try {
 | 
			
		||||
      final RevWalk rw = new RevWalk(repo);
 | 
			
		||||
      try {
 | 
			
		||||
        final RevCommit commit =
 | 
			
		||||
            rw.parseCommit(ObjectId.fromString(rsrc.getPatchSet()
 | 
			
		||||
                .getRevision().get()));
 | 
			
		||||
        BinaryResult bin = new BinaryResult() {
 | 
			
		||||
          @Override
 | 
			
		||||
          public void writeTo(OutputStream out) throws IOException {
 | 
			
		||||
            try {
 | 
			
		||||
              new ArchiveCommand(repo)
 | 
			
		||||
                  .setFormat(f.name())
 | 
			
		||||
                  .setTree(commit.getTree())
 | 
			
		||||
                  .setOutputStream(out).call();
 | 
			
		||||
            } catch (GitAPIException e) {
 | 
			
		||||
              throw new IOException(e);
 | 
			
		||||
            }
 | 
			
		||||
          }
 | 
			
		||||
 | 
			
		||||
          @Override
 | 
			
		||||
          public void close() throws IOException {
 | 
			
		||||
            rw.release();
 | 
			
		||||
            repo.close();
 | 
			
		||||
          }
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        bin.disableGzip()
 | 
			
		||||
            .setContentType(f.getMimeType())
 | 
			
		||||
            .setAttachmentName(name(f, rw, commit));
 | 
			
		||||
 | 
			
		||||
        close = false;
 | 
			
		||||
        return bin;
 | 
			
		||||
      } finally {
 | 
			
		||||
        if (close) {
 | 
			
		||||
          rw.release();
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    } finally {
 | 
			
		||||
      if (close) {
 | 
			
		||||
        repo.close();
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private static String name(ArchiveFormat format, RevWalk rw, RevCommit commit)
 | 
			
		||||
      throws IOException {
 | 
			
		||||
    return String.format("%s%s",
 | 
			
		||||
        rw.getObjectReader().abbreviate(commit,7).name(),
 | 
			
		||||
        format.getDefaultSuffix());
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -82,6 +82,7 @@ public class Module extends RestApiModule {
 | 
			
		||||
    get(REVISION_KIND, "submit_type").to(TestSubmitType.Get.class);
 | 
			
		||||
    post(REVISION_KIND, "test.submit_rule").to(TestSubmitRule.class);
 | 
			
		||||
    post(REVISION_KIND, "test.submit_type").to(TestSubmitType.class);
 | 
			
		||||
    get(REVISION_KIND, "archive").to(GetArchive.class);
 | 
			
		||||
 | 
			
		||||
    child(REVISION_KIND, "drafts").to(Drafts.class);
 | 
			
		||||
    put(REVISION_KIND, "drafts").to(CreateDraft.class);
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										10
									
								
								lib/BUCK
									
									
									
									
									
								
							
							
						
						
									
										10
									
								
								lib/BUCK
									
									
									
									
									
								
							@@ -20,6 +20,7 @@ define_license(name = 'postgresql')
 | 
			
		||||
define_license(name = 'prologcafe')
 | 
			
		||||
define_license(name = 'protobuf')
 | 
			
		||||
define_license(name = 'slf4j')
 | 
			
		||||
define_license(name = 'xz')
 | 
			
		||||
define_license(name = 'DO_NOT_DISTRIBUTE')
 | 
			
		||||
 | 
			
		||||
maven_jar(
 | 
			
		||||
@@ -248,3 +249,12 @@ maven_jar(
 | 
			
		||||
  visibility = ['//lib:easymock'],
 | 
			
		||||
  attach_source = False,
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
maven_jar(
 | 
			
		||||
  name = 'tukaani-xz',
 | 
			
		||||
  id = 'org.tukaani:xz:1.4',
 | 
			
		||||
  sha1 = '18a9a2ce6abf32ea1b5fd31dae5210ad93f4e5e3',
 | 
			
		||||
  license = 'xz',
 | 
			
		||||
  attach_source = False,
 | 
			
		||||
  visibility = ['//lib/jgit:jgit-archive'],
 | 
			
		||||
)
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										4
									
								
								lib/LICENSE-xz
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								lib/LICENSE-xz
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,4 @@
 | 
			
		||||
All the files in this package have been written by Lasse Collin
 | 
			
		||||
and/or Igor Pavlov. All these files have been put into the
 | 
			
		||||
public domain. You can do whatever you want with these files.
 | 
			
		||||
This software is provided "as is", without any warranty.
 | 
			
		||||
@@ -21,6 +21,15 @@ maven_jar(
 | 
			
		||||
  ],
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
maven_jar(
 | 
			
		||||
  name = 'compress',
 | 
			
		||||
  id = 'org.apache.commons:commons-compress:1.7',
 | 
			
		||||
  sha1 = 'ab365c96ee9bc88adcc6fa40d185c8e15a31410d',
 | 
			
		||||
  license = 'Apache2.0',
 | 
			
		||||
  exclude = ['META-INF/LICENSE.txt', 'META-INF/NOTICE.txt'],
 | 
			
		||||
  visibility = ['//lib/jgit:jgit-archive'],
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
maven_jar(
 | 
			
		||||
  name = 'dbcp',
 | 
			
		||||
  id = 'commons-dbcp:commons-dbcp:1.4',
 | 
			
		||||
 
 | 
			
		||||
@@ -33,6 +33,23 @@ maven_jar(
 | 
			
		||||
  ],
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
maven_jar(
 | 
			
		||||
  name = 'jgit-archive',
 | 
			
		||||
  id = 'org.eclipse.jgit:org.eclipse.jgit.archive:' + VERS,
 | 
			
		||||
  sha1 = 'c645b284344ec9791404f6fd0e04f6dbedb58b7d',
 | 
			
		||||
  license = 'jgit',
 | 
			
		||||
  repository = REPO,
 | 
			
		||||
  deps = [':jgit',
 | 
			
		||||
    '//lib/commons:compress',
 | 
			
		||||
    '//lib:tukaani-xz',
 | 
			
		||||
  ],
 | 
			
		||||
  unsign = True,
 | 
			
		||||
  exclude = [
 | 
			
		||||
    'about.html',
 | 
			
		||||
    'plugin.properties',
 | 
			
		||||
  ],
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
maven_jar(
 | 
			
		||||
  name = 'junit',
 | 
			
		||||
  id = 'org.eclipse.jgit:org.eclipse.jgit.junit:' + VERS,
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user