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.gitexe.command.changelog; 020 021import java.io.File; 022import java.text.SimpleDateFormat; 023import java.util.Date; 024import java.util.TimeZone; 025 026import org.apache.commons.text.StringEscapeUtils; 027import org.apache.maven.scm.CommandParameter; 028import org.apache.maven.scm.CommandParameters; 029import org.apache.maven.scm.ScmBranch; 030import org.apache.maven.scm.ScmException; 031import org.apache.maven.scm.ScmFileSet; 032import org.apache.maven.scm.ScmResult; 033import org.apache.maven.scm.ScmVersion; 034import org.apache.maven.scm.command.changelog.AbstractChangeLogCommand; 035import org.apache.maven.scm.command.changelog.ChangeLogScmRequest; 036import org.apache.maven.scm.command.changelog.ChangeLogScmResult; 037import org.apache.maven.scm.command.changelog.ChangeLogSet; 038import org.apache.maven.scm.provider.ScmProviderRepository; 039import org.apache.maven.scm.provider.git.command.GitCommand; 040import org.apache.maven.scm.provider.git.gitexe.command.GitCommandLineUtils; 041import org.apache.maven.scm.provider.git.repository.GitScmProviderRepository; 042import org.codehaus.plexus.util.cli.CommandLineUtils; 043import org.codehaus.plexus.util.cli.Commandline; 044 045/** 046 * @author <a href="mailto:evenisse@apache.org">Emmanuel Venisse</a> 047 * @author Olivier Lamy 048 * 049 */ 050public class GitChangeLogCommand extends AbstractChangeLogCommand implements GitCommand { 051 private static final String DATE_FORMAT = "yyyy-MM-dd HH:mm:ss Z"; 052 053 @Override 054 public ScmResult executeCommand(ScmProviderRepository repository, ScmFileSet fileSet, CommandParameters parameters) 055 throws ScmException { 056 return executeChangeLogCommand( 057 repository, 058 fileSet, 059 parameters.getDate(CommandParameter.START_DATE, null), 060 parameters.getDate(CommandParameter.END_DATE, null), 061 (ScmBranch) parameters.getScmVersion(CommandParameter.BRANCH, null), 062 parameters.getString(CommandParameter.CHANGELOG_DATE_PATTERN, null), 063 parameters.getScmVersion(CommandParameter.START_SCM_VERSION, null), 064 parameters.getScmVersion(CommandParameter.END_SCM_VERSION, null), 065 parameters.getInt(CommandParameter.LIMIT, -1), 066 parameters.getScmVersion(CommandParameter.SCM_VERSION, null)); 067 } 068 069 /** {@inheritDoc} */ 070 @Override 071 protected ChangeLogScmResult executeChangeLogCommand( 072 ScmProviderRepository repo, 073 ScmFileSet fileSet, 074 ScmVersion startVersion, 075 ScmVersion endVersion, 076 String datePattern) 077 throws ScmException { 078 return executeChangeLogCommand(repo, fileSet, null, null, null, datePattern, startVersion, endVersion); 079 } 080 081 /** {@inheritDoc} */ 082 @Override 083 protected ChangeLogScmResult executeChangeLogCommand( 084 ScmProviderRepository repo, 085 ScmFileSet fileSet, 086 Date startDate, 087 Date endDate, 088 ScmBranch branch, 089 String datePattern) 090 throws ScmException { 091 return executeChangeLogCommand(repo, fileSet, startDate, endDate, branch, datePattern, null, null); 092 } 093 094 @Override 095 protected ChangeLogScmResult executeChangeLogCommand( 096 ScmProviderRepository repository, ScmFileSet fileSet, ScmVersion version, String datePattern) 097 throws ScmException { 098 return executeChangeLogCommand(repository, fileSet, null, null, null, datePattern, null, null, null, version); 099 } 100 101 protected ChangeLogScmResult executeChangeLogCommand( 102 ScmProviderRepository repo, 103 ScmFileSet fileSet, 104 Date startDate, 105 Date endDate, 106 ScmBranch branch, 107 String datePattern, 108 ScmVersion startVersion, 109 ScmVersion endVersion) 110 throws ScmException { 111 return executeChangeLogCommand( 112 repo, fileSet, startDate, endDate, branch, datePattern, startVersion, endVersion, null, null); 113 } 114 115 @Override 116 protected ChangeLogScmResult executeChangeLogCommand(ChangeLogScmRequest request) throws ScmException { 117 final ScmVersion startVersion = request.getStartRevision(); 118 final ScmVersion endVersion = request.getEndRevision(); 119 final ScmVersion revision = request.getRevision(); 120 final ScmFileSet fileSet = request.getScmFileSet(); 121 final String datePattern = request.getDatePattern(); 122 final ScmProviderRepository providerRepository = 123 request.getScmRepository().getProviderRepository(); 124 final Date startDate = request.getStartDate(); 125 final Date endDate = request.getEndDate(); 126 final ScmBranch branch = request.getScmBranch(); 127 final Integer limit = request.getLimit(); 128 129 return executeChangeLogCommand( 130 providerRepository, 131 fileSet, 132 startDate, 133 endDate, 134 branch, 135 datePattern, 136 startVersion, 137 endVersion, 138 limit, 139 revision); 140 } 141 142 protected ChangeLogScmResult executeChangeLogCommand( 143 ScmProviderRepository repo, 144 ScmFileSet fileSet, 145 Date startDate, 146 Date endDate, 147 ScmBranch branch, 148 String datePattern, 149 ScmVersion startVersion, 150 ScmVersion endVersion, 151 Integer limit) 152 throws ScmException { 153 return executeChangeLogCommand( 154 repo, fileSet, startDate, endDate, branch, datePattern, startVersion, endVersion, limit, null); 155 } 156 157 protected ChangeLogScmResult executeChangeLogCommand( 158 ScmProviderRepository repo, 159 ScmFileSet fileSet, 160 Date startDate, 161 Date endDate, 162 ScmBranch branch, 163 String datePattern, 164 ScmVersion startVersion, 165 ScmVersion endVersion, 166 Integer limit, 167 ScmVersion version) 168 throws ScmException { 169 Commandline cl = createCommandLine( 170 (GitScmProviderRepository) repo, 171 fileSet.getBasedir(), 172 branch, 173 startDate, 174 endDate, 175 startVersion, 176 endVersion, 177 limit, 178 version); 179 180 GitChangeLogConsumer consumer = new GitChangeLogConsumer(datePattern); 181 182 CommandLineUtils.StringStreamConsumer stderr = new CommandLineUtils.StringStreamConsumer(); 183 184 int exitCode; 185 186 exitCode = GitCommandLineUtils.execute(cl, consumer, stderr); 187 if (exitCode != 0) { 188 return new ChangeLogScmResult(cl.toString(), "The git-log command failed.", stderr.getOutput(), false); 189 } 190 ChangeLogSet changeLogSet = new ChangeLogSet(consumer.getModifications(), startDate, endDate); 191 changeLogSet.setStartVersion(startVersion); 192 changeLogSet.setEndVersion(endVersion); 193 194 return new ChangeLogScmResult(cl.toString(), changeLogSet); 195 } 196 197 // ---------------------------------------------------------------------- 198 // 199 // ---------------------------------------------------------------------- 200 201 /** 202 * This method creates the commandline for the git-whatchanged command. 203 * <p> 204 * Since it uses --since and --until for the start and end date, the branch 205 * and version parameters can be used simultanously. 206 * 207 * @param repository Provider repositry to use. 208 * @param workingDirectory Working copy directory. 209 * @param branch Branch to run command on. 210 * @param startDate Start date of log entries. 211 * @param endDate End date of log entries. 212 * @param startVersion Start version of log entries. 213 * @param endVersion End version of log entries. 214 * @return Command line. 215 */ 216 public static Commandline createCommandLine( 217 GitScmProviderRepository repository, 218 File workingDirectory, 219 ScmBranch branch, 220 Date startDate, 221 Date endDate, 222 ScmVersion startVersion, 223 ScmVersion endVersion) { 224 return createCommandLine( 225 repository, workingDirectory, branch, startDate, endDate, startVersion, endVersion, null); 226 } 227 228 static Commandline createCommandLine( 229 GitScmProviderRepository repository, 230 File workingDirectory, 231 ScmBranch branch, 232 Date startDate, 233 Date endDate, 234 ScmVersion startVersion, 235 ScmVersion endVersion, 236 Integer limit) { 237 return createCommandLine( 238 repository, workingDirectory, branch, startDate, endDate, startVersion, endVersion, limit, null); 239 } 240 241 static Commandline createCommandLine( 242 GitScmProviderRepository repository, 243 File workingDirectory, 244 ScmBranch branch, 245 Date startDate, 246 Date endDate, 247 ScmVersion startVersion, 248 ScmVersion endVersion, 249 Integer limit, 250 ScmVersion version) { 251 SimpleDateFormat dateFormat = new SimpleDateFormat(DATE_FORMAT); 252 dateFormat.setTimeZone(TimeZone.getTimeZone("GMT")); 253 254 Commandline cl = GitCommandLineUtils.getBaseGitCommandLine(workingDirectory, "whatchanged"); 255 cl.createArg().setValue("--format=medium"); 256 cl.createArg().setValue("--decorate=short"); 257 cl.createArg().setValue("--raw"); 258 cl.createArg().setValue("--no-merges"); 259 260 if (startDate != null || endDate != null) { 261 if (startDate != null) { 262 cl.createArg().setValue("--since=" + StringEscapeUtils.escapeJava(dateFormat.format(startDate))); 263 } 264 265 if (endDate != null) { 266 cl.createArg().setValue("--until=" + StringEscapeUtils.escapeJava(dateFormat.format(endDate))); 267 } 268 } 269 270 // since this parameter is also used for the output formatting, we need it also if no start nor end date is 271 // given 272 cl.createArg().setValue("--date=iso"); 273 274 if (startVersion != null || endVersion != null) { 275 StringBuilder versionRange = new StringBuilder(); 276 277 if (startVersion != null) { 278 versionRange.append(StringEscapeUtils.escapeJava(startVersion.getName())); 279 } 280 281 versionRange.append(".."); 282 283 if (endVersion != null) { 284 versionRange.append(StringEscapeUtils.escapeJava(endVersion.getName())); 285 } 286 287 cl.createArg().setValue(versionRange.toString()); 288 289 } else if (version != null) { 290 cl.createArg().setValue(StringEscapeUtils.escapeJava(version.getName())); 291 } 292 293 if (limit != null && limit > 0) { 294 cl.createArg().setValue("--max-count=" + limit); 295 } 296 297 if (branch != null && branch.getName() != null && branch.getName().length() > 0) { 298 cl.createArg().setValue(branch.getName()); 299 } 300 301 // Insert a separator to make sure that files aren't interpreted as part of the version spec 302 cl.createArg().setValue("--"); 303 304 // We have to report only the changes of the current project. 305 // This is needed for child projects, otherwise we would get the changelog of the 306 // whole parent-project including all childs. 307 cl.createArg().setValue("."); 308 309 return cl; 310 } 311}