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;
20
21 import java.io.File;
22 import java.io.IOException;
23 import java.util.HashMap;
24 import java.util.List;
25 import java.util.Map;
26
27 import org.apache.commons.io.FilenameUtils;
28 import org.apache.commons.lang3.StringUtils;
29 import org.apache.maven.scm.ScmException;
30 import org.apache.maven.scm.provider.git.repository.GitScmProviderRepository;
31 import org.apache.maven.scm.provider.git.util.GitUtil;
32 import org.apache.maven.scm.providers.gitlib.settings.Settings;
33 import org.codehaus.plexus.util.cli.CommandLineException;
34 import org.codehaus.plexus.util.cli.CommandLineUtils;
35 import org.codehaus.plexus.util.cli.Commandline;
36 import org.codehaus.plexus.util.cli.StreamConsumer;
37 import org.slf4j.Logger;
38 import org.slf4j.LoggerFactory;
39
40
41
42
43
44
45
46 public final class GitCommandLineUtils {
47 private static final Logger LOGGER = LoggerFactory.getLogger(GitCommandLineUtils.class);
48
49
50 public static final String VARIABLE_GIT_SSH_COMMAND = "GIT_SSH_COMMAND";
51
52 private GitCommandLineUtils() {}
53
54 public static void addTarget(Commandline commandLine, List<File> files) {
55 if (files == null || files.isEmpty()) {
56 return;
57 }
58 final File workingDirectory = commandLine.getWorkingDirectory();
59 try {
60 final String canonicalWorkingDirectory = workingDirectory.getCanonicalPath();
61 for (File file : files) {
62 String relativeFile = file.getPath();
63
64 final String canonicalFile = file.getCanonicalPath();
65 if (canonicalFile.startsWith(canonicalWorkingDirectory)) {
66
67 relativeFile = canonicalFile.substring(canonicalWorkingDirectory.length());
68
69 if (relativeFile.startsWith(File.separator)) {
70 relativeFile = relativeFile.substring(File.separator.length());
71 }
72 }
73
74
75 commandLine.createArg().setValue(FilenameUtils.separatorsToUnix(relativeFile));
76 }
77 } catch (IOException ex) {
78 throw new IllegalArgumentException(
79 "Could not get canonical paths for workingDirectory = " + workingDirectory + " or files=" + files,
80 ex);
81 }
82 }
83
84
85
86
87 public static Commandline getBaseGitCommandLine(File workingDirectory, String command) {
88 return getBaseGitCommandLine(workingDirectory, command, null, null);
89 }
90
91
92
93
94 public static Commandline getBaseGitCommandLine(
95 File workingDirectory,
96 String command,
97 GitScmProviderRepository repository,
98 Map<String, String> environment) {
99 Commandline commandLine = getAnonymousBaseGitCommandLine(workingDirectory, command);
100 if (repository != null) {
101 prepareEnvVariablesForRepository(repository, environment).forEach(commandLine::addEnvironment);
102 } else if (environment != null) {
103 environment.forEach(commandLine::addEnvironment);
104 }
105 return commandLine;
106 }
107
108
109
110
111
112
113
114
115
116 private static Commandline getAnonymousBaseGitCommandLine(File workingDirectory, String command) {
117 if (command == null || command.isEmpty()) {
118 return null;
119 }
120
121 Commandline commandLine = new AnonymousCommandLine();
122
123 composeCommand(workingDirectory, command, commandLine);
124
125 return commandLine;
126 }
127
128 private static void composeCommand(File workingDirectory, String command, Commandline commandLine) {
129 Settings settings = GitUtil.getSettings();
130
131 commandLine.setExecutable(settings.getGitCommand());
132
133 commandLine.createArg().setValue(command);
134
135 if (workingDirectory != null) {
136 commandLine.setWorkingDirectory(workingDirectory.getAbsolutePath());
137 }
138 }
139
140 public static int execute(
141 Commandline commandline, StreamConsumer consumer, CommandLineUtils.StringStreamConsumer stderr)
142 throws ScmException {
143 if (LOGGER.isDebugEnabled()) {
144 LOGGER.debug("Executing: " + commandline);
145 LOGGER.debug(
146 "Working directory: " + commandline.getWorkingDirectory().getAbsolutePath());
147 }
148
149 int exitCode;
150 try {
151 exitCode = CommandLineUtils.executeCommandLine(commandline, consumer, stderr);
152 } catch (CommandLineException ex) {
153 throw new ScmException("Error while executing command.", ex);
154 }
155
156 return exitCode;
157 }
158
159 public static int execute(
160 Commandline commandLine,
161 CommandLineUtils.StringStreamConsumer stdout,
162 CommandLineUtils.StringStreamConsumer stderr)
163 throws ScmException {
164 if (LOGGER.isDebugEnabled()) {
165 LOGGER.debug("Executing: " + commandLine);
166 LOGGER.debug(
167 "Working directory: " + commandLine.getWorkingDirectory().getAbsolutePath());
168 }
169
170 int exitCode;
171 try {
172 exitCode = CommandLineUtils.executeCommandLine(commandLine, stdout, stderr);
173 } catch (CommandLineException ex) {
174 throw new ScmException("Error while executing command.", ex);
175 }
176
177 return exitCode;
178 }
179
180 static Map<String, String> prepareEnvVariablesForRepository(
181 GitScmProviderRepository repository, Map<String, String> environmentVariables) {
182 Map<String, String> effectiveEnvironmentVariables = new HashMap<>();
183 if (environmentVariables != null) {
184 effectiveEnvironmentVariables.putAll(environmentVariables);
185 }
186 if (StringUtils.isNotBlank(repository.getPrivateKey())) {
187 if (effectiveEnvironmentVariables.putIfAbsent(
188 VARIABLE_GIT_SSH_COMMAND,
189 "ssh -o IdentitiesOnly=yes -i "
190 + FilenameUtils.separatorsToUnix(repository.getPrivateKey()))
191 != null) {
192 LOGGER.warn(
193 "Ignore GitScmProviderRepository.privateKey as environment variable {} is already set",
194 VARIABLE_GIT_SSH_COMMAND);
195 }
196 }
197 if (StringUtils.isNotBlank(repository.getPassphrase())) {
198 LOGGER.warn("GitScmProviderRepository.passphrase currently not supported by provider 'git'");
199 }
200 return effectiveEnvironmentVariables;
201 }
202 }