View Javadoc
1   package org.apache.maven.scm.provider.svn.svnexe.command.changelog;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   * http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  import org.apache.maven.scm.ScmBranch;
23  import org.apache.maven.scm.ScmException;
24  import org.apache.maven.scm.ScmFileSet;
25  import org.apache.maven.scm.ScmTag;
26  import org.apache.maven.scm.ScmVersion;
27  import org.apache.maven.scm.command.changelog.AbstractChangeLogCommand;
28  import org.apache.maven.scm.command.changelog.ChangeLogScmRequest;
29  import org.apache.maven.scm.command.changelog.ChangeLogScmResult;
30  import org.apache.maven.scm.command.changelog.ChangeLogSet;
31  import org.apache.maven.scm.provider.ScmProviderRepository;
32  import org.apache.maven.scm.provider.svn.SvnTagBranchUtils;
33  import org.apache.maven.scm.provider.svn.command.SvnCommand;
34  import org.apache.maven.scm.provider.svn.repository.SvnScmProviderRepository;
35  import org.apache.maven.scm.provider.svn.svnexe.command.SvnCommandLineUtils;
36  import org.codehaus.plexus.util.Os;
37  import org.codehaus.plexus.util.StringUtils;
38  import org.codehaus.plexus.util.cli.CommandLineException;
39  import org.codehaus.plexus.util.cli.CommandLineUtils;
40  import org.codehaus.plexus.util.cli.Commandline;
41  
42  import java.io.File;
43  import java.text.SimpleDateFormat;
44  import java.util.Date;
45  import java.util.Objects;
46  import java.util.TimeZone;
47  import org.apache.maven.scm.CommandParameter;
48  import org.apache.maven.scm.CommandParameters;
49  import org.apache.maven.scm.ScmResult;
50  
51  /**
52   * @author <a href="mailto:evenisse@apache.org">Emmanuel Venisse</a>
53   * @author Olivier Lamy
54   *
55   */
56  public class SvnChangeLogCommand
57      extends AbstractChangeLogCommand
58      implements SvnCommand
59  {
60      private static final String DATE_FORMAT = "yyyy-MM-dd HH:mm:ss Z";
61  
62      @Override
63      public ScmResult executeCommand( ScmProviderRepository repository, ScmFileSet fileSet,
64                                       CommandParameters parameters )
65          throws ScmException
66      {
67          return executeChangeLogCommand( repository, fileSet,
68                  parameters.getDate( CommandParameter.START_DATE, null ),
69                  parameters.getDate( CommandParameter.END_DATE, null ),
70                  (ScmBranch) parameters.getScmVersion( CommandParameter.BRANCH, null ),
71                  parameters.getString( CommandParameter.CHANGELOG_DATE_PATTERN, null ),
72                  parameters.getScmVersion( CommandParameter.START_SCM_VERSION, null ),
73                  parameters.getScmVersion( CommandParameter.END_SCM_VERSION, null ),
74                  parameters.getInt( CommandParameter.LIMIT, -1 ) );
75      }
76  
77      /** {@inheritDoc} */
78      @Deprecated
79      @Override
80      protected ChangeLogScmResult executeChangeLogCommand( ScmProviderRepository repo, ScmFileSet fileSet,
81                                                            ScmVersion startVersion, ScmVersion endVersion,
82                                                            String datePattern )
83          throws ScmException
84      {
85          return executeChangeLogCommand( repo, fileSet, null, null, null, datePattern, startVersion, endVersion, null );
86      }
87  
88      /** {@inheritDoc} */
89      @Deprecated
90      @Override
91      protected ChangeLogScmResult executeChangeLogCommand( ScmProviderRepository repo, ScmFileSet fileSet,
92                                                            Date startDate, Date endDate, ScmBranch branch,
93                                                            String datePattern )
94          throws ScmException
95      {
96          return executeChangeLogCommand( repo, fileSet, startDate, endDate, branch, datePattern, null, null, null );
97      }
98  
99      @Override
100     protected ChangeLogScmResult executeChangeLogCommand( ChangeLogScmRequest request )
101         throws ScmException
102     {
103         final ScmVersion startVersion = request.getStartRevision();
104         final ScmVersion endVersion = request.getEndRevision();
105         final ScmFileSet fileSet = request.getScmFileSet();
106         final String datePattern = request.getDatePattern();
107         return executeChangeLogCommand( request.getScmRepository().getProviderRepository(), fileSet,
108             request.getStartDate(), request.getEndDate(), request.getScmBranch(), datePattern, startVersion,
109                 endVersion, request.getLimit() );
110     }
111 
112     private ChangeLogScmResult executeChangeLogCommand( ScmProviderRepository repo, ScmFileSet fileSet,
113                                                           Date startDate, Date endDate, ScmBranch branch,
114                                                           String datePattern, ScmVersion startVersion,
115                                                           ScmVersion endVersion, Integer limit )
116         throws ScmException
117     {
118         Commandline cl = createCommandLine( (SvnScmProviderRepository) repo, fileSet.getBasedir(), branch, startDate,
119                                             endDate, startVersion, endVersion, limit );
120 
121         SvnChangeLogConsumer consumer = new SvnChangeLogConsumer( getLogger(), datePattern );
122 
123         CommandLineUtils.StringStreamConsumer stderr = new CommandLineUtils.StringStreamConsumer();
124 
125         if ( getLogger().isInfoEnabled() )
126         {
127             getLogger().info( "Executing: " + SvnCommandLineUtils.cryptPassword( cl ) );
128 
129             if ( Os.isFamily( Os.FAMILY_WINDOWS ) )
130             {
131                 getLogger().info( "Working directory: " + cl.getWorkingDirectory().getAbsolutePath() );
132             }
133         }
134 
135         int exitCode;
136 
137         try
138         {
139             exitCode = SvnCommandLineUtils.execute( cl, consumer, stderr, getLogger() );
140         }
141         catch ( CommandLineException ex )
142         {
143             throw new ScmException( "Error while executing svn command.", ex );
144         }
145 
146         if ( exitCode != 0 )
147         {
148             return new ChangeLogScmResult( cl.toString(), "The svn command failed.", stderr.getOutput(), false );
149         }
150         ChangeLogSet changeLogSet = new ChangeLogSet( consumer.getModifications(), startDate, endDate );
151         changeLogSet.setStartVersion( startVersion );
152         changeLogSet.setEndVersion( endVersion );
153 
154         return new ChangeLogScmResult( cl.toString(), changeLogSet );
155     }
156 
157     // ----------------------------------------------------------------------
158     //
159     // ----------------------------------------------------------------------
160 
161     public static Commandline createCommandLine( SvnScmProviderRepository repository, File workingDirectory,
162                                                  ScmBranch branch, Date startDate, Date endDate,
163                                                  ScmVersion startVersion, ScmVersion endVersion )
164     {
165         return createCommandLine( repository, workingDirectory, branch, startDate, endDate, startVersion, endVersion,
166                                   null );
167     }
168 
169     public static Commandline createCommandLine( SvnScmProviderRepository repository, File workingDirectory,
170                                                  ScmBranch branch, Date startDate, Date endDate,
171                                                  ScmVersion startVersion, ScmVersion endVersion, Integer limit )
172     {
173         SimpleDateFormat dateFormat = new SimpleDateFormat( DATE_FORMAT );
174 
175         dateFormat.setTimeZone( TimeZone.getTimeZone( "GMT" ) );
176 
177         Commandline cl = SvnCommandLineUtils.getBaseSvnCommandLine( workingDirectory, repository );
178 
179         cl.createArg().setValue( "log" );
180 
181         cl.createArg().setValue( "-v" );
182 
183         // TODO: May want to add some kind of support for --stop-on-copy and --limit NUM
184 
185         if ( limit != null && limit > 0 )
186         {
187             cl.createArg().setValue( "--limit" );
188             cl.createArg().setValue( Integer.toString( limit ) );
189         }
190 
191         if ( startDate != null )
192         {
193             cl.createArg().setValue( "-r" );
194 
195             if ( endDate != null )
196             {
197                 cl.createArg().setValue(
198                     "{" + dateFormat.format( startDate ) + "}" + ":" + "{" + dateFormat.format( endDate ) + "}" );
199             }
200             else
201             {
202                 cl.createArg().setValue( "{" + dateFormat.format( startDate ) + "}:HEAD" );
203             }
204         }
205 
206         if ( startVersion != null )
207         {
208             cl.createArg().setValue( "-r" );
209 
210             if ( endVersion != null )
211             {
212                 if ( startVersion.getName().equals( endVersion.getName() ) )
213                 {
214                     cl.createArg().setValue( startVersion.getName() );
215                 }
216                 else
217                 {
218                     cl.createArg().setValue( startVersion.getName() + ":" + endVersion.getName() );
219                 }
220             }
221             else
222             {
223                 cl.createArg().setValue( startVersion.getName() + ":HEAD" );
224             }
225         }
226 
227         if ( branch != null && StringUtils.isNotEmpty( branch.getName() ) )
228         {
229             // By specifying a branch and this repository url below, subversion should show
230             // the changelog of that branch, but limit it to paths that also occur in this repository.
231             if ( branch instanceof ScmTag )
232             {
233                 String tagUrl = SvnTagBranchUtils.resolveTagUrl( repository, (ScmTag) branch );
234                 cl.createArg().setValue( tagUrl + "@" );
235             }
236             else
237             {
238                 String branchUrl = SvnTagBranchUtils.resolveBranchUrl( repository, branch );
239                 cl.createArg().setValue( branchUrl + "@" );
240             }
241         }
242 
243         if ( endVersion == null || !Objects.equals( "BASE", endVersion.getName() ) )
244         {
245             cl.createArg().setValue( repository.getUrl() + "@" );
246         }
247 
248         return cl;
249     }
250 }