001    package org.apache.maven.scm.provider.local.command.update;
002    
003    /*
004     * Licensed to the Apache Software Foundation (ASF) under one
005     * or more contributor license agreements.  See the NOTICE file
006     * distributed with this work for additional information
007     * regarding copyright ownership.  The ASF licenses this file
008     * to you under the Apache License, Version 2.0 (the
009     * "License"); you may not use this file except in compliance
010     * with the License.  You may obtain a copy of the License at
011     *
012     * http://www.apache.org/licenses/LICENSE-2.0
013     *
014     * Unless required by applicable law or agreed to in writing,
015     * software distributed under the License is distributed on an
016     * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
017     * KIND, either express or implied.  See the License for the
018     * specific language governing permissions and limitations
019     * under the License.
020     */
021    
022    import org.apache.maven.scm.ScmException;
023    import org.apache.maven.scm.ScmFile;
024    import org.apache.maven.scm.ScmFileSet;
025    import org.apache.maven.scm.ScmFileStatus;
026    import org.apache.maven.scm.ScmVersion;
027    import org.apache.maven.scm.command.changelog.ChangeLogCommand;
028    import org.apache.maven.scm.command.update.AbstractUpdateCommand;
029    import org.apache.maven.scm.command.update.UpdateScmResult;
030    import org.apache.maven.scm.provider.ScmProviderRepository;
031    import org.apache.maven.scm.provider.local.command.LocalCommand;
032    import org.apache.maven.scm.provider.local.command.changelog.LocalChangeLogCommand;
033    import org.apache.maven.scm.provider.local.metadata.LocalScmMetadata;
034    import org.apache.maven.scm.provider.local.metadata.LocalScmMetadataUtils;
035    import org.apache.maven.scm.provider.local.repository.LocalScmProviderRepository;
036    import org.codehaus.plexus.util.FileUtils;
037    
038    import java.io.File;
039    import java.io.IOException;
040    import java.util.ArrayList;
041    import java.util.Iterator;
042    import java.util.List;
043    
044    /**
045     * @author <a href="mailto:trygvis@inamo.no">Trygve Laugst&oslash;l</a>
046     * @author Olivier Lamy
047     * @version $Id: LocalUpdateCommand.java 1056980 2011-01-09 17:23:55Z olamy $
048     */
049    public class LocalUpdateCommand
050        extends AbstractUpdateCommand
051        implements LocalCommand
052    {
053        /** {@inheritDoc} */
054        protected UpdateScmResult executeUpdateCommand( ScmProviderRepository repo, ScmFileSet fileSet, ScmVersion version )
055            throws ScmException
056        {
057            LocalScmProviderRepository repository = (LocalScmProviderRepository) repo;
058    
059            if ( version != null )
060            {
061                throw new ScmException( "The local scm doesn't support tags." );
062            }
063    
064            File root = new File( repository.getRoot() );
065    
066            String module = repository.getModule();
067    
068            File source = new File( root, module );
069    
070            File baseDestination = fileSet.getBasedir();
071    
072            if ( !baseDestination.exists() )
073            {
074                throw new ScmException(
075                    "The working directory doesn't exist (" + baseDestination.getAbsolutePath() + ")." );
076            }
077    
078            if ( !root.exists() )
079            {
080                throw new ScmException( "The base directory doesn't exist (" + root.getAbsolutePath() + ")." );
081            }
082    
083            if ( !source.exists() )
084            {
085                throw new ScmException( "The module directory doesn't exist (" + source.getAbsolutePath() + ")." );
086            }
087    
088            if ( !baseDestination.exists() && !baseDestination.isDirectory() )
089            {
090                throw new ScmException( "The destination directory isn't a directory or doesn't exist ("
091                    + baseDestination.getAbsolutePath() + ")." );
092            }
093    
094            List<ScmFile> updatedFiles;
095    
096            try
097            {
098                if ( getLogger().isInfoEnabled() )
099                {
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                List<File> list = fileList;
108                updatedFiles = update( source, baseDestination, list );
109    
110                // process deletions in repository
111                LocalScmMetadataUtils metadataUtils = new LocalScmMetadataUtils( getLogger() );
112                LocalScmMetadata originalMetadata = metadataUtils.readMetadata( baseDestination );
113                if ( originalMetadata != null )
114                {
115                    LocalScmMetadata newMetadata = metadataUtils.buildMetadata( source );
116                    for ( Iterator<String> it = originalMetadata.getRepositoryFileNames().iterator(); it.hasNext(); )
117                    {
118                        String filename = it.next();
119                        if ( !newMetadata.getRepositoryFileNames().contains( filename ) )
120                        {
121                            File localFile = new File( baseDestination, filename );
122                            if ( localFile.exists() )
123                            {
124                                localFile.delete();
125                                updatedFiles.add( new ScmFile( "/" + filename, ScmFileStatus.UPDATED ) );
126                            }
127                        }
128                    }
129                }
130    
131                // rewrite metadata file
132                metadataUtils.writeMetadata( baseDestination, metadataUtils.buildMetadata( source ) );
133    
134            }
135            catch ( IOException ex )
136            {
137                throw new ScmException( "Error while checking out the files.", ex );
138            }
139    
140            return new LocalUpdateScmResult( null, updatedFiles );
141        }
142    
143        private List<ScmFile> update( File source, File baseDestination, List<File> files )
144            throws ScmException, IOException
145        {
146            String sourcePath = source.getAbsolutePath();
147    
148            List<ScmFile> updatedFiles = new ArrayList<ScmFile>();
149    
150            for ( Iterator<File> i = files.iterator(); i.hasNext(); )
151            {
152                File repositoryFile = i.next();
153    
154                File repositoryDirectory = repositoryFile.getParentFile();
155    
156                // TODO: Add more excludes here
157                if ( repositoryDirectory != null && repositoryDirectory.getName().equals( "CVS" ) )
158                {
159                    continue;
160                }
161    
162                String dest = repositoryFile.getAbsolutePath().substring( sourcePath.length() + 1 );
163    
164                File destinationFile = new File( baseDestination, dest );
165    
166                String repositoryFileContents = FileUtils.fileRead( repositoryFile );
167    
168                if ( destinationFile.exists() )
169                {
170                    String destionationFileContents = FileUtils.fileRead( destinationFile );
171    
172                    if ( repositoryFileContents.equals( destionationFileContents ) )
173                    {
174                        continue;
175                    }
176                }
177    
178                File destinationDirectory = destinationFile.getParentFile();
179    
180                if ( !destinationDirectory.exists() && !destinationDirectory.mkdirs() )
181                {
182                    throw new ScmException(
183                        "Could not create destination directory '" + destinationDirectory.getAbsolutePath() + "'." );
184                }
185    
186                ScmFileStatus status;
187    
188                if ( destinationFile.exists() )
189                {
190                    status = ScmFileStatus.UPDATED;
191                }
192                else
193                {
194                    status = ScmFileStatus.ADDED;
195                }
196    
197                FileUtils.copyFileToDirectory( repositoryFile, destinationDirectory );
198    
199                int chop = baseDestination.getAbsolutePath().length();
200    
201                String fileName = "/" + destinationFile.getAbsolutePath().substring( chop + 1 );
202    
203                updatedFiles.add( new ScmFile( fileName, status ) );
204            }
205    
206            return updatedFiles;
207        }
208    
209        /** {@inheritDoc} */
210        protected ChangeLogCommand getChangeLogCommand()
211        {
212            return new LocalChangeLogCommand();
213        }
214    }