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.gwt.user.client.ui.Widget;
|
||||||
import com.google.gwtexpui.clippy.client.CopyableLabel;
|
import com.google.gwtexpui.clippy.client.CopyableLabel;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.EnumSet;
|
import java.util.EnumSet;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
class DownloadBox extends VerticalPanel {
|
class DownloadBox extends VerticalPanel {
|
||||||
|
private final static String ARCHIVE[] = {"tar", "tbz2", "tgz", "txz"};
|
||||||
private final ChangeInfo change;
|
private final ChangeInfo change;
|
||||||
private final String revision;
|
private final String revision;
|
||||||
private final PatchSet.Id psId;
|
private final PatchSet.Id psId;
|
||||||
@@ -109,6 +113,7 @@ class DownloadBox extends VerticalPanel {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
insertPatch();
|
insertPatch();
|
||||||
|
insertArchive();
|
||||||
insertCommand(null, scheme);
|
insertCommand(null, scheme);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -141,6 +146,34 @@ class DownloadBox extends VerticalPanel {
|
|||||||
insertCommand("Patch-File", p);
|
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) {
|
private void insertCommand(String commandName, Widget w) {
|
||||||
int row = commandTable.getRowCount();
|
int row = commandTable.getRowCount();
|
||||||
commandTable.insertRow(row);
|
commandTable.insertRow(row);
|
||||||
|
@@ -57,6 +57,7 @@ java_library2(
|
|||||||
'//lib/guice:guice-assistedinject',
|
'//lib/guice:guice-assistedinject',
|
||||||
'//lib/guice:guice-servlet',
|
'//lib/guice:guice-servlet',
|
||||||
'//lib/jgit:jgit',
|
'//lib/jgit:jgit',
|
||||||
|
'//lib/jgit:jgit-archive',
|
||||||
'//lib/joda:joda-time',
|
'//lib/joda:joda-time',
|
||||||
'//lib/log:api',
|
'//lib/log:api',
|
||||||
'//lib/prolog:prolog-cafe',
|
'//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);
|
get(REVISION_KIND, "submit_type").to(TestSubmitType.Get.class);
|
||||||
post(REVISION_KIND, "test.submit_rule").to(TestSubmitRule.class);
|
post(REVISION_KIND, "test.submit_rule").to(TestSubmitRule.class);
|
||||||
post(REVISION_KIND, "test.submit_type").to(TestSubmitType.class);
|
post(REVISION_KIND, "test.submit_type").to(TestSubmitType.class);
|
||||||
|
get(REVISION_KIND, "archive").to(GetArchive.class);
|
||||||
|
|
||||||
child(REVISION_KIND, "drafts").to(Drafts.class);
|
child(REVISION_KIND, "drafts").to(Drafts.class);
|
||||||
put(REVISION_KIND, "drafts").to(CreateDraft.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 = 'prologcafe')
|
||||||
define_license(name = 'protobuf')
|
define_license(name = 'protobuf')
|
||||||
define_license(name = 'slf4j')
|
define_license(name = 'slf4j')
|
||||||
|
define_license(name = 'xz')
|
||||||
define_license(name = 'DO_NOT_DISTRIBUTE')
|
define_license(name = 'DO_NOT_DISTRIBUTE')
|
||||||
|
|
||||||
maven_jar(
|
maven_jar(
|
||||||
@@ -248,3 +249,12 @@ maven_jar(
|
|||||||
visibility = ['//lib:easymock'],
|
visibility = ['//lib:easymock'],
|
||||||
attach_source = False,
|
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(
|
maven_jar(
|
||||||
name = 'dbcp',
|
name = 'dbcp',
|
||||||
id = 'commons-dbcp:commons-dbcp:1.4',
|
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(
|
maven_jar(
|
||||||
name = 'junit',
|
name = 'junit',
|
||||||
id = 'org.eclipse.jgit:org.eclipse.jgit.junit:' + VERS,
|
id = 'org.eclipse.jgit:org.eclipse.jgit.junit:' + VERS,
|
||||||
|
Reference in New Issue
Block a user