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.jgit.command.checkin;
20
21 import java.io.File;
22 import java.net.InetAddress;
23 import java.net.UnknownHostException;
24 import java.util.Collections;
25 import java.util.List;
26 import java.util.Set;
27
28 import org.apache.commons.lang3.StringUtils;
29 import org.apache.maven.scm.ScmException;
30 import org.apache.maven.scm.ScmFile;
31 import org.apache.maven.scm.ScmFileSet;
32 import org.apache.maven.scm.ScmVersion;
33 import org.apache.maven.scm.command.checkin.AbstractCheckInCommand;
34 import org.apache.maven.scm.command.checkin.CheckInScmResult;
35 import org.apache.maven.scm.provider.ScmProviderRepository;
36 import org.apache.maven.scm.provider.git.command.GitCommand;
37 import org.apache.maven.scm.provider.git.jgit.command.JGitUtils;
38 import org.apache.maven.scm.provider.git.repository.GitScmProviderRepository;
39 import org.eclipse.jgit.api.AddCommand;
40 import org.eclipse.jgit.api.CommitCommand;
41 import org.eclipse.jgit.api.Git;
42 import org.eclipse.jgit.api.Status;
43 import org.eclipse.jgit.lib.Constants;
44 import org.eclipse.jgit.lib.UserConfig;
45 import org.eclipse.jgit.revwalk.RevCommit;
46 import org.eclipse.jgit.transport.PushResult;
47 import org.eclipse.jgit.transport.RefSpec;
48 import org.eclipse.jgit.transport.RemoteRefUpdate;
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67 public class JGitCheckInCommand extends AbstractCheckInCommand implements GitCommand {
68
69 protected static final String GIT_MAVEN_SECTION = "maven-scm";
70
71 protected static final String GIT_MAILDOMAIN = "maildomain";
72
73 protected static final String GIT_FORCE = "forceUsername";
74
75
76
77
78 protected CheckInScmResult executeCheckInCommand(
79 ScmProviderRepository repo, ScmFileSet fileSet, String message, ScmVersion version) throws ScmException {
80
81 Git git = null;
82 try {
83 File basedir = fileSet.getBasedir();
84 git = JGitUtils.openRepo(basedir);
85
86 boolean doCommit = false;
87
88 if (!fileSet.getFileList().isEmpty()) {
89
90 doCommit = JGitUtils.addAllFiles(git, fileSet).size() > 0;
91 if (!doCommit) {
92 doCommit = git.status().call().hasUncommittedChanges();
93 }
94 } else {
95
96 Status status = git.status().call();
97 Set<String> changeds = git.status().call().getModified();
98 if (changeds.isEmpty()) {
99 if (!status.hasUncommittedChanges()) {
100
101 logger.warn("There are neither files to be added nor any uncommitted changes");
102 doCommit = false;
103 } else {
104 logger.debug("There are uncommitted changes in the git index");
105 doCommit = true;
106 }
107 } else {
108
109 AddCommand add = git.add();
110 for (String changed : changeds) {
111 logger.debug("Add manually: {}", changed);
112 add.addFilepattern(changed);
113 doCommit = true;
114 }
115 add.call();
116 }
117 }
118
119 List<ScmFile> checkedInFiles = Collections.emptyList();
120 if (doCommit) {
121 UserInfo author = getAuthor(repo, git);
122 UserInfo committer = getCommitter(repo, git);
123
124 CommitCommand command = git.commit().setMessage(message).setAuthor(author.name, author.email);
125 command.setCommitter(committer.name, committer.email);
126 RevCommit commitRev = command.call();
127
128 logger.info("commit done: " + commitRev.getShortMessage());
129 checkedInFiles = JGitUtils.getFilesInCommit(git.getRepository(), commitRev, fileSet.getBasedir());
130 if (logger.isDebugEnabled()) {
131 for (ScmFile scmFile : checkedInFiles) {
132 logger.debug("in commit: " + scmFile);
133 }
134 }
135 }
136
137 if (repo.isPushChanges()) {
138 String branch = version != null ? version.getName() : null;
139 if (StringUtils.isBlank(branch)) {
140 branch = git.getRepository().getBranch();
141 }
142 RefSpec refSpec = new RefSpec(Constants.R_HEADS + branch + ":" + Constants.R_HEADS + branch);
143 logger.info("push changes to remote... " + refSpec);
144 Iterable<PushResult> pushResultList = JGitUtils.push(git, (GitScmProviderRepository) repo, refSpec);
145
146 for (PushResult pushResult : pushResultList) {
147 for (RemoteRefUpdate remoteRefUpdate : pushResult.getRemoteUpdates()) {
148 if (!isSuccessStatus(remoteRefUpdate.getStatus())) {
149 return new CheckInScmResult(
150 "JGit checkin",
151 "The git-push command failed, with status: " + remoteRefUpdate.getStatus(),
152 remoteRefUpdate.getMessage(),
153 false);
154 }
155 }
156 }
157 }
158
159 return new CheckInScmResult("JGit checkin", checkedInFiles);
160 } catch (Exception e) {
161 throw new ScmException("JGit checkin failure!", e);
162 } finally {
163 JGitUtils.closeRepo(git);
164 }
165 }
166
167 private boolean isSuccessStatus(RemoteRefUpdate.Status remoteRefUpdateStatus) {
168 return remoteRefUpdateStatus == RemoteRefUpdate.Status.OK
169 || remoteRefUpdateStatus == RemoteRefUpdate.Status.UP_TO_DATE;
170 }
171
172 private static final class UserInfo {
173
174 final String name;
175
176 final String email;
177
178 UserInfo(String name, String email) {
179 this.name = name;
180 this.email = email;
181 }
182 }
183
184 private UserInfo getCommitter(ScmProviderRepository repo, Git git) {
185 boolean forceMvnUser = git.getRepository().getConfig().getBoolean(GIT_MAVEN_SECTION, GIT_FORCE, false);
186
187
188 UserConfig user = git.getRepository().getConfig().get(UserConfig.KEY);
189 String committerName = null;
190 if (!forceMvnUser && !user.isCommitterNameImplicit()) {
191 committerName = user.getCommitterName();
192 }
193
194
195 if (StringUtils.isBlank(committerName)) {
196 committerName = repo.getUser();
197 }
198
199
200 if (StringUtils.isBlank(committerName)) {
201 committerName = user.getCommitterName();
202 }
203
204
205 String committerMail = null;
206 if (!user.isCommitterEmailImplicit()) {
207 committerMail = user.getCommitterEmail();
208 }
209
210 if (StringUtils.isBlank(committerMail)) {
211 String defaultDomain = git.getRepository().getConfig().getString(GIT_MAVEN_SECTION, null, GIT_MAILDOMAIN);
212 defaultDomain = StringUtils.isNotBlank(defaultDomain) ? defaultDomain : getHostname();
213
214
215 committerMail = StringUtils.isNotBlank(repo.getUser())
216 ? repo.getUser() + "@" + defaultDomain
217 : user.getCommitterEmail();
218 }
219
220 return new UserInfo(committerName, committerMail);
221 }
222
223 private UserInfo getAuthor(ScmProviderRepository repo, Git git) {
224 boolean forceMvnUser = git.getRepository().getConfig().getBoolean(GIT_MAVEN_SECTION, GIT_FORCE, false);
225
226
227 UserConfig user = git.getRepository().getConfig().get(UserConfig.KEY);
228 String authorName = null;
229 if (!forceMvnUser && !user.isAuthorNameImplicit()) {
230 authorName = user.getAuthorName();
231 }
232
233
234 if (StringUtils.isBlank(authorName)) {
235 authorName = repo.getUser();
236 }
237
238
239 if (StringUtils.isBlank(authorName)) {
240 authorName = user.getAuthorName();
241 }
242
243
244 String authorMail = null;
245 if (!user.isAuthorEmailImplicit()) {
246 authorMail = user.getAuthorEmail();
247 }
248
249 if (StringUtils.isBlank(authorMail)) {
250 String defaultDomain = git.getRepository().getConfig().getString(GIT_MAVEN_SECTION, null, GIT_MAILDOMAIN);
251 defaultDomain = StringUtils.isNotBlank(defaultDomain) ? defaultDomain : getHostname();
252
253
254 authorMail = StringUtils.isNotBlank(repo.getUser())
255 ? repo.getUser() + "@" + defaultDomain
256 : user.getAuthorEmail();
257 }
258
259 return new UserInfo(authorName, authorMail);
260 }
261
262 private String getHostname() {
263 String hostname;
264 try {
265 InetAddress localhost = java.net.InetAddress.getLocalHost();
266 hostname = localhost.getHostName();
267 } catch (UnknownHostException e) {
268 logger.warn(
269 "failed to resolve hostname to create mail address, " + "defaulting to 'maven-scm-provider-jgit'");
270 hostname = "maven-scm-provider-jgit";
271 }
272 return hostname;
273 }
274 }