/*
* Copyright 2017 ThoughtWorks, Inc.
*
* 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.thoughtworks.go.domain.materials.git;
import com.thoughtworks.go.config.materials.git.GitMaterial;
import com.thoughtworks.go.config.materials.git.GitMaterialConfig;
import com.thoughtworks.go.domain.materials.Material;
import com.thoughtworks.go.domain.materials.Modification;
import com.thoughtworks.go.domain.materials.TestSubprocessExecutionContext;
import com.thoughtworks.go.domain.materials.mercurial.StringRevision;
import com.thoughtworks.go.helper.TestRepo;
import com.thoughtworks.go.util.FileUtil;
import com.thoughtworks.go.util.TestFileUtil;
import com.thoughtworks.go.util.command.CommandLine;
import com.thoughtworks.go.util.command.InMemoryStreamConsumer;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import static com.thoughtworks.go.util.command.CommandLine.createCommandLine;
import static com.thoughtworks.go.util.command.ProcessOutputStreamConsumer.inMemoryConsumer;
public class GitTestRepo extends TestRepo {
private static final String GIT_3_REVISIONS_BUNDLE = "../common/test-resources/unit/data/git/git-3-revisions.git";
public static final String GIT_FOO_BRANCH_BUNDLE = "../common/test-resources/unit/data/git/foo-branch.git";
public static final String GIT_SUBMODULE_REF_BUNDLE = "../common/test-resources/unit/data/git/referenced-submodule.git";
public static final StringRevision REVISION_0 = new StringRevision("55502a724dd8574f1e4bcf19b605a1f4f182e892");
public static final StringRevision REVISION_1 = new StringRevision("b613aee673d96e967100306222246aa9decbc53c");
public static final StringRevision REVISION_2 = new StringRevision("4ab7833f55024c975cf5b918af640954c108825e");
public static final StringRevision REVISION_3 = new StringRevision("ab9ff2cee965ae4d0778dbcda1fadffbbc202e85");
public static final StringRevision REVISION_4 = new StringRevision("5def073a425dfe239aabd4bf8039ffe3b0e8856b");
public static final StringRevision NON_EXISTENT_REVISION = new StringRevision("4ffef3cb33d98b28858743a53b6ee77bfe9d21bb");
private File gitRepo;
public GitTestRepo(String path) throws IOException {
this(new File(path));
}
public static GitTestRepo testRepoAtBranch(String gitBundleFilePath, String branch) throws IOException {
GitTestRepo testRepo = new GitTestRepo(gitBundleFilePath);
testRepo.checkoutRemoteBranchToLocal(branch);
return testRepo;
}
public GitTestRepo() throws IOException {
this(GIT_3_REVISIONS_BUNDLE);
}
public GitMaterial createMaterial(String dest) {
GitMaterial gitMaterial = new GitMaterial(this.projectRepositoryUrl());
gitMaterial.setFolder(dest);
return gitMaterial;
}
public GitTestRepo(File gitBundleFile) {
gitRepo = new File(TestFileUtil.createUniqueTempFolder("GitTestRepo"), "repo");
cloneBundleToFolder(gitBundleFile, gitRepo);
tmpFolders.add(gitRepo);
}
public String projectRepositoryUrl() {
return FileUtil.toFileURI(gitRepo);
}
@Override public List<Modification> checkInOneFile(String fileName, String comment) throws IOException {
return addFileAndPush(fileName ,comment);
}
@Override public List<Modification> latestModification() {
return git(gitRepo).latestModification();
}
@Override public Material material() {
return createMaterial();
}
public File gitRepository() {
return gitRepo;
}
private void cloneBundleToFolder(File from, File workingDir) {
GitCommand git = git(workingDir);
InMemoryStreamConsumer outputStreamConsumer = inMemoryConsumer();
int returnValue = git.clone(outputStreamConsumer, from.getAbsolutePath());
if (returnValue != 0) {
throw new RuntimeException(String.format("[ERROR] Failed to clone. URL [%s] exit value [%d] output [%s]", from.getAbsolutePath(), returnValue, outputStreamConsumer.getAllOutput()));
}
createCommandLine("git").withEncoding("UTF-8").withWorkingDir(workingDir).withArgs("config", "user.name", "go_test").runOrBomb(true, "git_config");
createCommandLine("git").withEncoding("UTF-8").withWorkingDir(workingDir).withArgs("config", "user.email", "go_test@go_test.me").runOrBomb(true, "git_config");
git.fetchAndResetToHead(outputStreamConsumer);
}
private GitCommand git(File workingDir) {
return new GitCommand(null, workingDir, GitMaterialConfig.DEFAULT_BRANCH, false, new HashMap<>(), null);
}
public GitMaterial createMaterial() {
return new GitMaterial(this.projectRepositoryUrl());
}
public List<Modification> latestModifications() {
return latestModification();
}
private void checkoutRemoteBranchToLocal(String branch) {
new GitCommand(null, gitRepo, branch, false, new HashMap<>(), null).checkoutRemoteBranchToLocal();
}
public List<Modification> addFileAndPush(String fileName, String message) throws IOException {
File newFile = new File(gitRepo, fileName);
newFile.createNewFile();
new GitCommand(null, gitRepo, GitMaterialConfig.DEFAULT_BRANCH, false, new HashMap<>(), null).add(newFile);
new GitCommand(null, gitRepo, GitMaterialConfig.DEFAULT_BRANCH, false, new HashMap<>(), null).commit(message);
return createMaterial().latestModification(TestFileUtil.createUniqueTempFolder("working-dir-"), new TestSubprocessExecutionContext());
}
public List<Modification> addFileAndAmend(String fileName, String message) throws IOException {
File newFile = new File(gitRepo, fileName);
newFile.createNewFile();
new GitCommand(null, gitRepo, GitMaterialConfig.DEFAULT_BRANCH, false, new HashMap<>(), null).add(newFile);
new GitCommandWithAmend(null, gitRepo, GitMaterialConfig.DEFAULT_BRANCH, false, new HashMap<>()).commitWithAmend(message, gitRepo);
return createMaterial().latestModification(TestFileUtil.createUniqueTempFolder("working-dir-"), new TestSubprocessExecutionContext());
}
private static class GitCommandWithAmend extends GitCommand {
public GitCommandWithAmend(String materialFingerprint, File workingDir, String branch, boolean isSubmodule, Map<String, String> environment) {
super(materialFingerprint, workingDir, branch, isSubmodule, environment, null);
}
public void commitWithAmend(String message, File gitRepo) {
String[] args = new String[]{"commit", "--amend", "-m", message};
CommandLine gitCommit = CommandLine.createCommandLine("git").withEncoding("UTF-8").withArgs(args).withWorkingDir(gitRepo);
runOrBomb(gitCommit);
}
}
}