View Javadoc
1   package org.apache.maven.scm.provider.local.command.update;
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.ScmException;
23  import org.apache.maven.scm.ScmFile;
24  import org.apache.maven.scm.ScmFileSet;
25  import org.apache.maven.scm.ScmFileStatus;
26  import org.apache.maven.scm.ScmVersion;
27  import org.apache.maven.scm.command.changelog.ChangeLogCommand;
28  import org.apache.maven.scm.command.update.AbstractUpdateCommand;
29  import org.apache.maven.scm.command.update.UpdateScmResult;
30  import org.apache.maven.scm.provider.ScmProviderRepository;
31  import org.apache.maven.scm.provider.local.command.LocalCommand;
32  import org.apache.maven.scm.provider.local.command.changelog.LocalChangeLogCommand;
33  import org.apache.maven.scm.provider.local.metadata.LocalScmMetadata;
34  import org.apache.maven.scm.provider.local.metadata.LocalScmMetadataUtils;
35  import org.apache.maven.scm.provider.local.repository.LocalScmProviderRepository;
36  import org.codehaus.plexus.util.FileUtils;
37  
38  import java.io.File;
39  import java.io.IOException;
40  import java.util.ArrayList;
41  import java.util.Iterator;
42  import java.util.List;
43  
44  /**
45   * @author <a href="mailto:trygvis@inamo.no">Trygve Laugst&oslash;l</a>
46   * @author Olivier Lamy
47   *
48   */
49  public class LocalUpdateCommand
50      extends AbstractUpdateCommand
51      implements LocalCommand
52  {
53      /** {@inheritDoc} */
54      protected UpdateScmResult executeUpdateCommand( ScmProviderRepository repo, ScmFileSet fileSet, ScmVersion version )
55          throws ScmException
56      {
57          LocalScmProviderRepository repository = (LocalScmProviderRepository) repo;
58  
59          if ( version != null )
60          {
61              throw new ScmException( "The local scm doesn't support tags." );
62          }
63  
64          File root = new File( repository.getRoot() );
65  
66          String module = repository.getModule();
67  
68          File source = new File( root, module );
69  
70          File baseDestination = fileSet.getBasedir();
71  
72          if ( !baseDestination.exists() )
73          {
74              throw new ScmException(
75                  "The working directory doesn't exist (" + baseDestination.getAbsolutePath() + ")." );
76          }
77  
78          if ( !root.exists() )
79          {
80              throw new ScmException( "The base directory doesn't exist (" + root.getAbsolutePath() + ")." );
81          }
82  
83          if ( !source.exists() )
84          {
85              throw new ScmException( "The module directory doesn't exist (" + source.getAbsolutePath() + ")." );
86          }
87  
88          if ( !baseDestination.exists() && !baseDestination.isDirectory() )
89          {
90              throw new ScmException( "The destination directory isn't a directory or doesn't exist ("
91                  + baseDestination.getAbsolutePath() + ")." );
92          }
93  
94          List<ScmFile> updatedFiles;
95  
96          try
97          {
98              if ( getLogger().isInfoEnabled() )
99              {
100                 getLogger().info(
101                                   "Updating '" + baseDestination.getAbsolutePath() + "' from '"
102                                       + source.getAbsolutePath() + "'." );
103             }
104 
105             @SuppressWarnings( "unchecked" )
106             List<File> fileList = FileUtils.getFiles( source.getAbsoluteFile(), "**", null );
107             updatedFiles = update( source, baseDestination, fileList );
108 
109             // process deletions in repository
110             LocalScmMetadataUtils metadataUtils = new LocalScmMetadataUtils( getLogger() );
111             LocalScmMetadata originalMetadata = metadataUtils.readMetadata( baseDestination );
112             if ( originalMetadata != null )
113             {
114                 LocalScmMetadata newMetadata = metadataUtils.buildMetadata( source );
115                 for ( Iterator<String> it = originalMetadata.getRepositoryFileNames().iterator(); it.hasNext(); )
116                 {
117                     String filename = it.next();
118                     if ( !newMetadata.getRepositoryFileNames().contains( filename ) )
119                     {
120                         File localFile = new File( baseDestination, filename );
121                         if ( localFile.exists() )
122                         {
123                             localFile.delete();
124                             updatedFiles.add( new ScmFile( "/" + filename, ScmFileStatus.UPDATED ) );
125                         }
126                     }
127                 }
128             }
129 
130             // rewrite metadata file
131             metadataUtils.writeMetadata( baseDestination, metadataUtils.buildMetadata( source ) );
132 
133         }
134         catch ( IOException ex )
135         {
136             throw new ScmException( "Error while checking out the files.", ex );
137         }
138 
139         return new LocalUpdateScmResult( null, updatedFiles );
140     }
141 
142     private List<ScmFile> update( File source, File baseDestination, List<File> files )
143         throws ScmException, IOException
144     {
145         String sourcePath = source.getAbsolutePath();
146 
147         List<ScmFile> updatedFiles = new ArrayList<ScmFile>();
148 
149         for ( Iterator<File> i = files.iterator(); i.hasNext(); )
150         {
151             File repositoryFile = i.next();
152 
153             File repositoryDirectory = repositoryFile.getParentFile();
154 
155             // TODO: Add more excludes here
156             if ( repositoryDirectory != null && repositoryDirectory.getName().equals( "CVS" ) )
157             {
158                 continue;
159             }
160 
161             String dest = repositoryFile.getAbsolutePath().substring( sourcePath.length() + 1 );
162 
163             File destinationFile = new File( baseDestination, dest );
164 
165             String repositoryFileContents = FileUtils.fileRead( repositoryFile );
166 
167             if ( destinationFile.exists() )
168             {
169                 String destionationFileContents = FileUtils.fileRead( destinationFile );
170 
171                 if ( repositoryFileContents.equals( destionationFileContents ) )
172                 {
173                     continue;
174                 }
175             }
176 
177             File destinationDirectory = destinationFile.getParentFile();
178 
179             if ( !destinationDirectory.exists() && !destinationDirectory.mkdirs() )
180             {
181                 throw new ScmException(
182                     "Could not create destination directory '" + destinationDirectory.getAbsolutePath() + "'." );
183             }
184 
185             ScmFileStatus status;
186 
187             if ( destinationFile.exists() )
188             {
189                 status = ScmFileStatus.UPDATED;
190             }
191             else
192             {
193                 status = ScmFileStatus.ADDED;
194             }
195 
196             FileUtils.copyFileToDirectory( repositoryFile, destinationDirectory );
197 
198             int chop = baseDestination.getAbsolutePath().length();
199 
200             String fileName = "/" + destinationFile.getAbsolutePath().substring( chop + 1 );
201 
202             updatedFiles.add( new ScmFile( fileName, status ) );
203         }
204 
205         return updatedFiles;
206     }
207 
208     /** {@inheritDoc} */
209     protected ChangeLogCommand getChangeLogCommand()
210     {
211         return new LocalChangeLogCommand();
212     }
213 }