/* * 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.helper; import com.thoughtworks.go.config.materials.git.GitMaterial; import com.thoughtworks.go.config.materials.git.GitMaterialConfig; import com.thoughtworks.go.domain.materials.Modification; import com.thoughtworks.go.domain.materials.TestSubprocessExecutionContext; import com.thoughtworks.go.domain.materials.git.GitCommand; import com.thoughtworks.go.domain.materials.mercurial.StringRevision; import com.thoughtworks.go.util.FileUtil; import com.thoughtworks.go.util.TestFileUtil; import org.apache.commons.io.FileUtils; import java.io.File; import java.io.IOException; import java.util.HashMap; import java.util.List; import static com.thoughtworks.go.util.ArrayUtil.asList; import static com.thoughtworks.go.util.command.CommandLine.createCommandLine; import static com.thoughtworks.go.util.command.ProcessOutputStreamConsumer.inMemoryConsumer; public class GitSubmoduleRepos extends TestRepo { private final File temporaryFolder; private File remoteRepoDir; public static final String NAME = "with-submodules"; public GitSubmoduleRepos() throws Exception { temporaryFolder = TestFileUtil.createTempFolder("gitRepos-" + System.currentTimeMillis()); tmpFolders.add(temporaryFolder); remoteRepoDir = createRepo(NAME); } public File addSubmodule(String repoName, String folderName) throws Exception { return addSubmodule(repoName, folderName, folderName); } public File addSubmodule(String repoName, String submoduleNameToPutInGitSubmodules, String folderName) throws Exception { File submodule = createRepo(repoName); git(remoteRepoDir).submoduleAdd(submodule.getAbsolutePath(), submoduleNameToPutInGitSubmodules, folderName); git(remoteRepoDir).commit("Added submodule " + folderName); return submodule; } public void removeSubmodule(String folderName) throws Exception { git(remoteRepoDir).updateSubmoduleWithInit(inMemoryConsumer()); git(remoteRepoDir).submoduleRemove(folderName); git(remoteRepoDir).commit("Removed submodule " + folderName); } public String currentRevision(String repoFolder) { return git(workingCopy(repoFolder)).currentRevision(); } private File workingCopy(String repoFolder) { return new File(temporaryFolder, repoFolder); } public List<File> files(String repoFolder) { return asList(workingCopy(repoFolder).listFiles()); } private File createRepo(String repoName) throws Exception { File withSubmodules = TestFileUtil.createTestFolder(temporaryFolder, repoName); git(withSubmodules).init(); createCommandLine("git").withEncoding("UTF-8").withWorkingDir(withSubmodules).withArgs("config", "user.name", "go_test").runOrBomb(true, "git_config"); createCommandLine("git").withEncoding("UTF-8").withWorkingDir(withSubmodules).withArgs("config", "user.email", "go_test@go_test.me").runOrBomb(true, "git_config"); String fileName = "file-" + System.currentTimeMillis(); addAndCommitNewFile(withSubmodules, fileName, "Added " + fileName); return withSubmodules; } private void addAndCommitNewFile(File repoFolder, String fileName, String comments) throws Exception { File testFile = TestFileUtil.createTestFile(repoFolder, fileName); checkInOneFile(repoFolder, testFile, comments); } private void checkInOneFile(File repoFolder, File testFile, String comments) { git(repoFolder).add(testFile); git(repoFolder).commit(comments); } private GitCommand git(File workingDir) { return new GitCommand(null, workingDir, GitMaterialConfig.DEFAULT_BRANCH, false, new HashMap<>(), null); } public GitMaterial mainRepo() { return material(); } public String projectRepositoryUrl() { return FileUtil.toFileURI(remoteRepoDir.getAbsoluteFile()); } public List<Modification> checkInOneFile(String fileName, String comment) throws Exception { addAndCommitNewFile(remoteRepoDir, fileName, comment); return latestModification(); } public List<Modification> modifyOneFileInSubmoduleAndUpdateMainRepo(File remoteSubmoduleRepoLocation, String submoduleNameInRepo, String fileName, String newContentOfFile) throws Exception { String comment = "Changed file: " + fileName + " in submodule: " + remoteSubmoduleRepoLocation; changeFile(remoteSubmoduleRepoLocation, fileName, newContentOfFile); checkInOneFile(remoteSubmoduleRepoLocation, new File(fileName), comment); git(new File(remoteRepoDir, submoduleNameInRepo)).pull(); checkInOneFile(remoteRepoDir, new File(submoduleNameInRepo), comment); return latestModification(); } private void changeFile(File parentDir, String fileName, String newFileContent) throws IOException { File fileToChange = new File(parentDir, fileName); FileUtils.writeStringToFile(fileToChange, newFileContent); } public List<Modification> latestModification() { File dir = workingCopy("local-working-copy"); return mainRepo().latestModification(dir, new TestSubprocessExecutionContext()); } @Override public GitMaterial material() { return new GitMaterial(remoteRepoDir.getAbsolutePath()); } public void changeSubmoduleUrl(String submoduleName) throws Exception { File newSubmodule = createRepo("new-submodule"); addAndCommitNewFile(newSubmodule, "new", "make a commit"); git(remoteRepoDir).changeSubmoduleUrl(submoduleName, newSubmodule.getAbsolutePath()); git(remoteRepoDir).submoduleSync(); git(new File(remoteRepoDir, "local-submodule")).fetch(inMemoryConsumer()); git(new File(remoteRepoDir, "local-submodule")).resetHard(inMemoryConsumer(), new StringRevision("origin/master")); git(remoteRepoDir).add(new File(".gitmodules")); git(remoteRepoDir).add(new File("local-submodule")); git(remoteRepoDir).commit("change submodule url"); } }