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