001/* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, 013 * software distributed under the License is distributed on an 014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 015 * KIND, either express or implied. See the License for the 016 * specific language governing permissions and limitations 017 * under the License. 018 */ 019package org.apache.maven.scm.provider.git.command.checkin; 020 021import java.io.File; 022import java.io.IOException; 023import java.io.InputStream; 024import java.nio.file.Files; 025import java.nio.file.Path; 026import java.nio.file.StandardCopyOption; 027 028import org.apache.maven.scm.CommandParameter; 029import org.apache.maven.scm.CommandParameters; 030import org.apache.maven.scm.PlexusJUnit4TestCase; 031import org.apache.maven.scm.ScmException; 032import org.apache.maven.scm.ScmFileSet; 033import org.apache.maven.scm.command.checkin.CheckInScmResult; 034import org.apache.maven.scm.command.checkout.CheckOutScmResult; 035import org.apache.maven.scm.provider.git.GitScmTestUtils; 036import org.apache.maven.scm.provider.git.util.GitUtil; 037import org.apache.maven.scm.repository.ScmRepository; 038import org.apache.maven.scm.tck.command.checkin.CheckInCommandTckTest; 039import org.codehaus.plexus.util.FileUtils; 040import org.junit.Test; 041 042import static org.junit.Assert.assertFalse; 043 044/** 045 * @author <a href="mailto:struberg@yahoo.de">Mark Struberg</a> 046 */ 047public abstract class GitCheckInCommandTckTest extends CheckInCommandTckTest { 048 049 /** 050 * {@inheritDoc} 051 */ 052 public void initRepo() throws Exception { 053 GitScmTestUtils.initRepo("src/test/resources/repository/", getRepositoryRoot(), getWorkingDirectory()); 054 } 055 056 @Override 057 protected CheckOutScmResult checkOut(File workingDirectory, ScmRepository repository) throws Exception { 058 try { 059 return super.checkOut(workingDirectory, repository); 060 } finally { 061 GitScmTestUtils.setDefaultGitConfig(workingDirectory); 062 } 063 } 064 065 @Test 066 public void testUpToDatePush() throws Exception { 067 File checkedOutRepo = getWorkingCopy(); 068 069 ScmRepository scmRepository = getScmManager().makeScmRepository(getScmUrl()); 070 checkoutRepoInto(checkedOutRepo, scmRepository); 071 072 // Add a default user to the config 073 GitScmTestUtils.setDefaultGitConfig(checkedOutRepo); 074 075 CheckInScmResult result = 076 getScmManager().checkIn(scmRepository, new ScmFileSet(checkedOutRepo), "No change commit message"); 077 078 assertResultIsSuccess(result); 079 } 080 081 @Test 082 public void testRejectedNonFastForwardPush() throws Exception { 083 File blockingRepo = PlexusJUnit4TestCase.getTestFile("target/scm-test/blocking-repo"); 084 File rejectedRepo = PlexusJUnit4TestCase.getTestFile("target/scm-test/rejected-repo"); 085 086 ScmRepository scmRepository = getScmManager().makeScmRepository(getScmUrl()); 087 checkoutRepoInto(rejectedRepo, scmRepository); 088 checkoutRepoInto(blockingRepo, scmRepository); 089 090 // Add a default user to the config 091 GitScmTestUtils.setDefaultGitConfig(rejectedRepo); 092 GitScmTestUtils.setDefaultGitConfig(blockingRepo); 093 094 ScmFileSet blockingFileSet = createWorkspaceChange(rejectedRepo); 095 096 CommandParameters commandParameters = new CommandParameters(); 097 commandParameters.setString(CommandParameter.MESSAGE, "Blocking commit"); 098 099 CheckInScmResult blockingResult = getScmManager().checkIn(scmRepository, blockingFileSet, commandParameters); 100 assertResultIsSuccess(blockingResult); 101 102 ScmFileSet rejectedFileSet = createWorkspaceChange(blockingRepo); 103 104 commandParameters = new CommandParameters(); 105 commandParameters.setString(CommandParameter.MESSAGE, "Rejected commit"); 106 107 CheckInScmResult checkInScmResult = getScmManager().checkIn(scmRepository, rejectedFileSet, commandParameters); 108 assertFalse( 109 "check-in should have been rejected since fast forward was not possible", checkInScmResult.isSuccess()); 110 } 111 112 @Test 113 public void testCommitWithRejectingPreCommitHook() throws Exception { 114 GitScmTestUtils.setupRejectAllCommitsPreCommitHook(getWorkingCopy()); 115 GitScmTestUtils.setDefaultGitConfig(getWorkingCopy()); 116 ScmFileSet addedFile = createWorkspaceChange(getWorkingCopy()); 117 try { 118 CheckInScmResult result = 119 getScmManager().checkIn(getScmRepository(), addedFile, "Commit with pre-commit hook"); 120 assertFalse( 121 "check-in should have been rejected since pre-push hook rejects all commits", result.isSuccess()); 122 } catch (ScmException e) { 123 // some providers may use an exception to indicate a failed commit 124 125 } 126 } 127 128 @Test 129 public void testCommitNoVerify() throws Exception { 130 GitScmTestUtils.setupRejectAllCommitsPreCommitHook(getWorkingCopy()); 131 GitScmTestUtils.setDefaultGitConfig(getWorkingCopy()); 132 ScmFileSet addedFile = createWorkspaceChange(getWorkingCopy()); 133 Path gitSettingsFile = 134 createTempFileFromClasspathResource("/git-settings-no-verify.xml", GitUtil.GIT_SETTINGS_FILENAME); 135 GitUtil.setSettingsDirectory( 136 gitSettingsFile.getParent().toFile()); // ensure that the settings are read from the .git directory 137 try { 138 CheckInScmResult result = 139 getScmManager().checkIn(getScmRepository(), addedFile, "Commit with pre-commit hook"); 140 assertResultIsSuccess(result); 141 } finally { 142 GitUtil.setSettingsDirectory(GitUtil.DEFAULT_SETTINGS_DIRECTORY); // reset to default settings directory 143 Files.delete(gitSettingsFile); // delete the temporary settings file 144 Files.delete(gitSettingsFile.getParent()); // delete the temporary settings directory 145 } 146 } 147 148 private CheckOutScmResult checkoutRepoInto(File workingCopy, ScmRepository scmRepository) throws Exception { 149 FileUtils.deleteDirectory(workingCopy); 150 workingCopy.mkdir(); 151 152 CheckOutScmResult result = getScmManager().checkOut(scmRepository, new ScmFileSet(workingCopy), null); 153 154 assertResultIsSuccess(result); 155 return result; 156 } 157 158 private ScmFileSet createWorkspaceChange(File repo) throws IOException { 159 File beerFile = new File(repo.getAbsolutePath(), "beer.xml"); 160 FileUtils.fileWrite(beerFile.getAbsolutePath(), "1 litre"); 161 return new ScmFileSet(repo, beerFile.getName()); 162 } 163 164 /** 165 * Creates a new file below a new temporary directory and copies the content of a classpath resource into it. 166 * The caller is responsible for deleting the temporary directory afterwards. 167 * 168 * @param resourceName from where to populate the file (relative to {@code clazz}) 169 * @param fileName the file name to create below 170 * @return the newly created file 171 * @throws IOException in case of an error creating the file or copying the resource 172 */ 173 private static Path createTempFileFromClasspathResource(String resourceName, String fileName) throws IOException { 174 Path tmpDirectory = Files.createTempDirectory("maven-scm-git-test-"); 175 Path tmpFile = tmpDirectory.resolve(fileName); 176 try (InputStream inputStream = GitCheckInCommandTckTest.class.getResourceAsStream(resourceName)) { 177 if (inputStream == null) { 178 throw new IOException("Resource not found: " + resourceName); 179 } 180 Files.copy(inputStream, tmpFile, StandardCopyOption.REPLACE_EXISTING); 181 } 182 return tmpFile; 183 } 184}