1 package org.apache.maven.scm.provider.git.gitexe.command.checkin;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import java.io.File;
23 import java.io.IOException;
24 import java.net.URI;
25 import java.util.ArrayList;
26 import java.util.Collections;
27 import java.util.List;
28 import java.util.Map;
29
30 import org.apache.commons.io.FilenameUtils;
31 import org.apache.maven.scm.ScmException;
32 import org.apache.maven.scm.ScmFile;
33 import org.apache.maven.scm.ScmFileSet;
34 import org.apache.maven.scm.ScmFileStatus;
35 import org.apache.maven.scm.ScmVersion;
36 import org.apache.maven.scm.command.checkin.AbstractCheckInCommand;
37 import org.apache.maven.scm.command.checkin.CheckInScmResult;
38 import org.apache.maven.scm.provider.ScmProviderRepository;
39 import org.apache.maven.scm.provider.git.command.GitCommand;
40 import org.apache.maven.scm.provider.git.gitexe.command.GitCommandLineUtils;
41 import org.apache.maven.scm.provider.git.gitexe.command.add.GitAddCommand;
42 import org.apache.maven.scm.provider.git.gitexe.command.branch.GitBranchCommand;
43 import org.apache.maven.scm.provider.git.gitexe.command.status.GitStatusCommand;
44 import org.apache.maven.scm.provider.git.gitexe.command.status.GitStatusConsumer;
45 import org.apache.maven.scm.provider.git.repository.GitScmProviderRepository;
46 import org.apache.maven.scm.provider.git.util.GitUtil;
47 import org.codehaus.plexus.util.FileUtils;
48 import org.codehaus.plexus.util.Os;
49 import org.codehaus.plexus.util.cli.CommandLineUtils;
50 import org.codehaus.plexus.util.cli.Commandline;
51
52
53
54
55
56
57 public class GitCheckInCommand
58 extends AbstractCheckInCommand
59 implements GitCommand
60 {
61 private final Map<String, String> environmentVariables;
62
63 public GitCheckInCommand( Map<String, String> environmentVariables )
64 {
65 super();
66 this.environmentVariables = environmentVariables;
67 }
68
69
70 protected CheckInScmResult executeCheckInCommand( ScmProviderRepository repo, ScmFileSet fileSet, String message,
71 ScmVersion version )
72 throws ScmException
73 {
74 GitScmProviderRepository repository = (GitScmProviderRepository) repo;
75
76 CommandLineUtils.StringStreamConsumer stderr = new CommandLineUtils.StringStreamConsumer();
77 CommandLineUtils.StringStreamConsumer stdout = new CommandLineUtils.StringStreamConsumer();
78
79 int exitCode = -1;
80
81 File messageFile = FileUtils.createTempFile( "maven-scm-", ".commit", null );
82 try
83 {
84 FileUtils.fileWrite( messageFile.getAbsolutePath(), "UTF-8", message );
85 }
86 catch ( IOException ex )
87 {
88 return new CheckInScmResult( null, "Error while making a temporary file for the commit message: "
89 + ex.getMessage(), null, false );
90 }
91
92 try
93 {
94 if ( !fileSet.getFileList().isEmpty() )
95 {
96
97
98
99 Commandline clAdd = null;
100
101
102 if ( Os.isFamily( Os.FAMILY_WINDOWS ) )
103 {
104 for ( File file: fileSet.getFileList() )
105 {
106 clAdd = GitAddCommand.createCommandLine( fileSet.getBasedir(),
107 Collections.singletonList( file ) );
108 exitCode = GitCommandLineUtils.execute( clAdd, stdout, stderr );
109
110 if ( exitCode != 0 )
111 {
112 break;
113 }
114 }
115 }
116 else
117 {
118 clAdd = GitAddCommand.createCommandLine( fileSet.getBasedir(), fileSet.getFileList() );
119 exitCode = GitCommandLineUtils.execute( clAdd, stdout, stderr );
120 }
121
122 if ( exitCode != 0 )
123 {
124 return new CheckInScmResult( clAdd.toString(), "The git-add command failed.",
125 stderr.getOutput(), false );
126 }
127
128 }
129
130
131
132 URI relativeRepositoryPath = GitStatusCommand.getRelativeCWD( logger, fileSet );
133
134
135
136
137 Commandline clStatus = GitStatusCommand.createCommandLine( repository, fileSet );
138
139 GitStatusConsumer statusConsumer =
140 new GitStatusConsumer( fileSet.getBasedir(), relativeRepositoryPath, fileSet );
141 exitCode = GitCommandLineUtils.execute( clStatus, statusConsumer, stderr );
142 if ( exitCode != 0 )
143 {
144
145 if ( logger.isInfoEnabled() )
146 {
147 logger.info( "nothing added to commit but untracked files present (use \"git add\" to "
148 + "track)" );
149 }
150 }
151
152 if ( statusConsumer.getChangedFiles().isEmpty() )
153 {
154 return new CheckInScmResult( null, statusConsumer.getChangedFiles() );
155 }
156
157 Commandline clCommit = createCommitCommandLine( repository, fileSet, messageFile, environmentVariables );
158
159 exitCode = GitCommandLineUtils.execute( clCommit, stdout, stderr );
160 if ( exitCode != 0 )
161 {
162 return new CheckInScmResult( clCommit.toString(), "The git-commit command failed.", stderr.getOutput(),
163 false );
164 }
165
166 if ( repo.isPushChanges() )
167 {
168 Commandline cl = createPushCommandLine( repository, fileSet, version );
169
170 exitCode = GitCommandLineUtils.execute( cl, stdout, stderr );
171 if ( exitCode != 0 )
172 {
173 return new CheckInScmResult( cl.toString(), "The git-push command failed.", stderr.getOutput(),
174 false );
175 }
176 }
177
178 List<ScmFile> checkedInFiles = new ArrayList<>( statusConsumer.getChangedFiles().size() );
179
180
181 for ( ScmFile changedFile : statusConsumer.getChangedFiles() )
182 {
183 ScmFile scmfile = new ScmFile( changedFile.getPath(), ScmFileStatus.CHECKED_IN );
184
185 if ( fileSet.getFileList().isEmpty() )
186 {
187 checkedInFiles.add( scmfile );
188 }
189 else
190 {
191
192 for ( File f : fileSet.getFileList() )
193 {
194 if ( FilenameUtils.separatorsToUnix( f.getPath() ).equals( scmfile.getPath() ) )
195 {
196 checkedInFiles.add( scmfile );
197 }
198
199 }
200 }
201 }
202
203 return new CheckInScmResult( clCommit.toString(), checkedInFiles );
204 }
205 finally
206 {
207 try
208 {
209 FileUtils.forceDelete( messageFile );
210 }
211 catch ( IOException ex )
212 {
213
214 }
215 }
216
217 }
218
219
220
221
222
223 public Commandline createPushCommandLine( GitScmProviderRepository repository,
224 ScmFileSet fileSet, ScmVersion version )
225 throws ScmException
226 {
227 Commandline cl = GitCommandLineUtils.getBaseGitCommandLine( fileSet.getBasedir(), "push", repository,
228 environmentVariables );
229
230 String branch = GitBranchCommand.getCurrentBranch( repository, fileSet );
231
232 if ( branch == null || branch.length() == 0 )
233 {
234 throw new ScmException( "Could not detect the current branch. Don't know where I should push to!" );
235 }
236
237 cl.createArg().setValue( repository.getPushUrl() );
238
239 cl.createArg().setValue( "refs/heads/" + branch + ":" + "refs/heads/" + branch );
240
241 return cl;
242 }
243
244 public static Commandline createCommitCommandLine( GitScmProviderRepository repository, ScmFileSet fileSet,
245 File messageFile )
246 throws ScmException
247 {
248 return createCommitCommandLine( repository, fileSet, messageFile, Collections.emptyMap() );
249 }
250
251 public static Commandline createCommitCommandLine( GitScmProviderRepository repository, ScmFileSet fileSet,
252 File messageFile, Map<String, String> environmentVariables )
253 throws ScmException
254 {
255 Commandline cl = GitCommandLineUtils.getBaseGitCommandLine( fileSet.getBasedir(), "commit" );
256
257 cl.createArg().setValue( "--verbose" );
258
259 cl.createArg().setValue( "-F" );
260
261 cl.createArg().setValue( messageFile.getAbsolutePath() );
262
263 if ( fileSet.getFileList().isEmpty() )
264 {
265
266 cl.createArg().setValue( "-a" );
267 }
268
269 if ( GitUtil.getSettings().isCommitNoVerify() )
270 {
271 cl.createArg().setValue( "--no-verify" );
272 }
273
274 return cl;
275 }
276
277 }