/* * Copyright (c) 2016 OBiBa. All rights reserved. * * This program and the accompanying materials * are made available under the terms of the GNU Public License v3.0. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package org.obiba.git.command; import java.io.ByteArrayInputStream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import javax.annotation.Nullable; import javax.validation.constraints.NotNull; import org.eclipse.jgit.api.Git; import org.eclipse.jgit.lib.ObjectId; import org.eclipse.jgit.lib.ObjectReader; import org.eclipse.jgit.lib.Ref; import org.eclipse.jgit.lib.Repository; import org.eclipse.jgit.revwalk.RevTree; import org.eclipse.jgit.revwalk.RevWalk; import org.eclipse.jgit.treewalk.TreeWalk; import org.obiba.git.GitException; import org.obiba.git.NoSuchGitRepositoryException; import static com.google.common.base.Strings.isNullOrEmpty; public class ReadFileCommand extends AbstractGitCommand<InputStream> { private final String path; private String commitId; private String tag; private ReadFileCommand(@NotNull File repositoryPath, @Nullable File workPath, String path) { super(repositoryPath, workPath); this.path = path; } @Override public InputStream execute(Git git) { try { Repository repository = git.getRepository(); if(!isNullOrEmpty(tag)) { return readTag(repository); } if(!isNullOrEmpty(commitId)) { return readCommit(repository); } // read current revision return new FileInputStream(new File(repository.getWorkTree(), path)); } catch(IOException e) { throw new GitException(e); } } private InputStream readTag(Repository repository) throws IOException { Ref ref = repository.getTags().get(tag); ObjectId objectId = repository.resolve(ref.getObjectId().getName()); if(objectId == null) { throw new GitException(String.format("No commit with id '%s' for tag '%s'", ref.getObjectId(), tag)); } return read(repository, objectId); } private InputStream readCommit(Repository repository) throws IOException { ObjectId objectId = repository.resolve(commitId); if(objectId == null) { throw new GitException(String.format("No commit with id '%s'", commitId)); } return read(repository, objectId); } private InputStream read(Repository repository, @NotNull ObjectId objectId) throws IOException { ObjectReader reader = repository.newObjectReader(); RevTree tree = new RevWalk(reader).parseCommit(objectId).getTree(); TreeWalk treeWalk = TreeWalk.forPath(reader, path, tree); if(treeWalk == null) { throw new GitException(String.format("Path '%s' was not found in commit '%s'", path, objectId)); } return new ByteArrayInputStream(reader.open(treeWalk.getObjectId(0)).getBytes()); } @SuppressWarnings("ParameterHidesMemberVariable") public static class Builder { private final ReadFileCommand command; public Builder(@NotNull File repositoryPath, String path) { this(repositoryPath, null, path); } public Builder(@NotNull File repositoryPath, @Nullable File workPath, String path) { if(!repositoryPath.exists() || !repositoryPath.isDirectory()) { throw new NoSuchGitRepositoryException(path); } command = new ReadFileCommand(repositoryPath, workPath, path); } public Builder commitId(String commitId) { command.commitId = commitId; return this; } public Builder tag(String tag) { command.tag = tag; return this; } public ReadFileCommand build() { if(!isNullOrEmpty(command.tag) && !isNullOrEmpty(command.commitId)) { throw new IllegalArgumentException("Choose between tag or commitId but don't specify both"); } return command; } } }