Line data Source code
1 : // Copyright (C) 2014 The Android Open Source Project 2 : // 3 : // Licensed under the Apache License, Version 2.0 (the "License"); 4 : // you may not use this file except in compliance with the License. 5 : // You may obtain a copy of the License at 6 : // 7 : // http://www.apache.org/licenses/LICENSE-2.0 8 : // 9 : // Unless required by applicable law or agreed to in writing, software 10 : // distributed under the License is distributed on an "AS IS" BASIS, 11 : // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 : // See the License for the specific language governing permissions and 13 : // limitations under the License. 14 : 15 : package com.google.gerrit.server.restapi.change; 16 : 17 : import static com.google.gerrit.git.ObjectIds.abbreviateName; 18 : 19 : import com.google.common.base.Strings; 20 : import com.google.gerrit.common.Nullable; 21 : import com.google.gerrit.extensions.restapi.BadRequestException; 22 : import com.google.gerrit.extensions.restapi.BinaryResult; 23 : import com.google.gerrit.extensions.restapi.MethodNotAllowedException; 24 : import com.google.gerrit.extensions.restapi.Response; 25 : import com.google.gerrit.extensions.restapi.RestReadView; 26 : import com.google.gerrit.server.change.ArchiveFormatInternal; 27 : import com.google.gerrit.server.change.RevisionResource; 28 : import com.google.gerrit.server.git.GitRepositoryManager; 29 : import com.google.inject.Inject; 30 : import java.io.IOException; 31 : import java.io.OutputStream; 32 : import org.eclipse.jgit.api.ArchiveCommand; 33 : import org.eclipse.jgit.api.errors.GitAPIException; 34 : import org.eclipse.jgit.lib.Repository; 35 : import org.eclipse.jgit.revwalk.RevCommit; 36 : import org.eclipse.jgit.revwalk.RevWalk; 37 : import org.kohsuke.args4j.Option; 38 : 39 : public class GetArchive implements RestReadView<RevisionResource> { 40 : private final GitRepositoryManager repoManager; 41 : private final AllowedFormats allowedFormats; 42 : @Nullable private String format; 43 : 44 : @Option(name = "--format") 45 : public void setFormat(String format) { 46 1 : this.format = format; 47 1 : } 48 : 49 : @Inject 50 57 : GetArchive(GitRepositoryManager repoManager, AllowedFormats allowedFormats) { 51 57 : this.repoManager = repoManager; 52 57 : this.allowedFormats = allowedFormats; 53 57 : } 54 : 55 : @Override 56 : public Response<BinaryResult> apply(RevisionResource rsrc) 57 : throws BadRequestException, IOException, MethodNotAllowedException { 58 2 : if (Strings.isNullOrEmpty(format)) { 59 2 : throw new BadRequestException("format is not specified"); 60 : } 61 1 : ArchiveFormatInternal f = allowedFormats.extensions.get("." + format); 62 1 : if (f == null) { 63 1 : throw new BadRequestException("unknown archive format"); 64 : } 65 1 : if (f == ArchiveFormatInternal.ZIP) { 66 1 : throw new MethodNotAllowedException("zip format is disabled"); 67 : } 68 1 : boolean close = true; 69 1 : Repository repo = repoManager.openRepository(rsrc.getProject()); 70 : try { 71 : RevCommit commit; 72 : String name; 73 1 : try (RevWalk rw = new RevWalk(repo)) { 74 1 : commit = rw.parseCommit(rsrc.getPatchSet().commitId()); 75 1 : name = name(f, rw, commit); 76 : } 77 : 78 1 : BinaryResult bin = 79 1 : new BinaryResult() { 80 : @Override 81 : public void writeTo(OutputStream out) throws IOException { 82 : try { 83 1 : new ArchiveCommand(repo) 84 1 : .setFormat(f.name()) 85 1 : .setTree(commit.getTree()) 86 1 : .setOutputStream(out) 87 1 : .call(); 88 0 : } catch (GitAPIException e) { 89 0 : throw new IOException(e); 90 1 : } 91 1 : } 92 : 93 : @Override 94 : public void close() throws IOException { 95 1 : repo.close(); 96 1 : } 97 : }; 98 : 99 1 : bin.disableGzip().setContentType(f.getMimeType()).setAttachmentName(name); 100 : 101 1 : close = false; 102 1 : return Response.ok(bin); 103 : } finally { 104 1 : if (close) { 105 0 : repo.close(); 106 : } 107 : } 108 : } 109 : 110 : private static String name(ArchiveFormatInternal format, RevWalk rw, RevCommit commit) 111 : throws IOException { 112 1 : return String.format( 113 1 : "%s%s", abbreviateName(commit, rw.getObjectReader()), format.getDefaultSuffix()); 114 : } 115 : }