Index: C:/java/maven-src/maven-scm/maven-scm-providers/maven-scm-provider-local/src/test/java/org/apache/maven/scm/provider/local/command/update/LocalUpdateCommandTckTest.java =================================================================== --- C:/java/maven-src/maven-scm/maven-scm-providers/maven-scm-provider-local/src/test/java/org/apache/maven/scm/provider/local/command/update/LocalUpdateCommandTckTest.java (revision 446890) +++ C:/java/maven-src/maven-scm/maven-scm-providers/maven-scm-provider-local/src/test/java/org/apache/maven/scm/provider/local/command/update/LocalUpdateCommandTckTest.java (working copy) @@ -16,10 +16,27 @@ * limitations under the License. */ +import java.io.File; +import java.io.FileReader; +import java.io.Reader; +import java.util.Date; +import java.util.Iterator; +import java.util.List; +import java.util.TreeSet; + +import org.apache.maven.scm.ChangeSet; +import org.apache.maven.scm.ScmFile; +import org.apache.maven.scm.ScmFileSet; +import org.apache.maven.scm.ScmTestCase; +import org.apache.maven.scm.command.update.UpdateScmResult; +import org.apache.maven.scm.manager.ScmManager; +import org.apache.maven.scm.providers.local.metadata.LocalScmMetadata; +import org.apache.maven.scm.providers.local.metadata.io.xpp3.LocalScmMetadataXpp3Reader; +import org.apache.maven.scm.repository.ScmRepository; import org.apache.maven.scm.tck.command.update.UpdateCommandTckTest; +import org.codehaus.plexus.util.FileUtils; +import org.codehaus.plexus.util.IOUtil; -import java.io.File; - /** * @author Trygve Laugstøl * @version $Id$ @@ -41,6 +58,96 @@ makeRepo( getRepositoryRoot() ); } + /** + * Tests that a file that has been deleted from repository after checkout will be removed by scm-local. Local + * additions must not be deleted. + */ + public void testDeletion() throws Exception + { + FileUtils.deleteDirectory( getUpdatingCopy() ); + + ScmRepository repository = makeScmRepository( getScmUrl() ); + + checkOut( getUpdatingCopy(), repository ); + + // Check preconditions + File readmeFileLocal = new File( getUpdatingCopy(), "readme.txt" ); + assertTrue( readmeFileLocal.exists() ); + File newFileLocal = new File( getUpdatingCopy(), "newfile.xml" ); + assertTrue( !newFileLocal.exists() ); + + // Delete readme.txt from repository + File readmeFileRepo = new File( getRepositoryRoot(), moduleName + "/readme.txt" ); + assertTrue( readmeFileRepo.exists() ); + assertTrue( "Could not delete", readmeFileRepo.delete() ); + assertFalse( readmeFileRepo.exists() ); + + // Make local addition to updating copy - this one must not be touched + ScmTestCase.makeFile( getUpdatingCopy(), "newfile.xml", "added newfile.xml locally" ); + assertTrue( newFileLocal.exists() ); + + // ---------------------------------------------------------------------- + // Update the project + // ---------------------------------------------------------------------- + + ScmManager scmManager = getScmManager(); + Date lastUpdate = new Date( System.currentTimeMillis() ); + Thread.sleep( 1000 ); + UpdateScmResult result = + scmManager.getProviderByUrl( getScmUrl() ).update( repository, new ScmFileSet( getUpdatingCopy() ), null, + lastUpdate ); + + assertNotNull( "The command returned a null result.", result ); + + assertResultIsSuccess( result ); + + List updatedFiles = result.getUpdatedFiles(); + + assertEquals( "Expected 1 files in the updated files list " + updatedFiles, 1, updatedFiles.size() ); + + // ---------------------------------------------------------------------- + // Assert the files in the updated files list + // ---------------------------------------------------------------------- + + Iterator files = new TreeSet( updatedFiles ).iterator(); + + // readme.txt + ScmFile file = (ScmFile) files.next(); + assertPath( "/readme.txt", file.getPath() ); + assertTrue( file.getStatus().isUpdate() ); + + // ---------------------------------------------------------------------- + // Assert working directory contents + // ---------------------------------------------------------------------- + + // readme.txt + assertTrue( "Expected local copy of readme.txt to be deleted", !readmeFileLocal.exists() ); + + // newfile.xml + assertTrue( "Expected local copy of newfile.xml NOT to be deleted", newFileLocal.exists() ); + + // ---------------------------------------------------------------------- + // Assert metadata file + // ---------------------------------------------------------------------- + File metadataFile = new File( getUpdatingCopy(), ".maven-scm-local" ); + assertTrue( "Expected metadata file .maven-scm-local does not exist", metadataFile.exists() ); + Reader reader = new FileReader( metadataFile ); + LocalScmMetadata metadata; + try + { + metadata = new LocalScmMetadataXpp3Reader().read( reader ); + } + finally + { + IOUtil.close( reader ); + } + File root = new File( getRepositoryRoot() + "/" + moduleName ); + List fileNames = FileUtils.getFileNames( root, "**", null, false ); + assertEquals( fileNames, metadata.getRepositoryFileNames() ); + + } + + private void makeRepo( File workingDirectory ) throws Exception { Index: C:/java/maven-src/maven-scm/maven-scm-providers/maven-scm-provider-local/src/test/java/org/apache/maven/scm/provider/local/command/checkout/LocalCheckOutCommandTckTest.java =================================================================== --- C:/java/maven-src/maven-scm/maven-scm-providers/maven-scm-provider-local/src/test/java/org/apache/maven/scm/provider/local/command/checkout/LocalCheckOutCommandTckTest.java (revision 446890) +++ C:/java/maven-src/maven-scm/maven-scm-providers/maven-scm-provider-local/src/test/java/org/apache/maven/scm/provider/local/command/checkout/LocalCheckOutCommandTckTest.java (working copy) @@ -16,10 +16,18 @@ * limitations under the License. */ +import java.io.File; +import java.io.FileReader; +import java.io.Reader; +import java.util.List; + +import org.apache.maven.scm.command.checkout.CheckOutScmResult; +import org.apache.maven.scm.providers.local.metadata.LocalScmMetadata; +import org.apache.maven.scm.providers.local.metadata.io.xpp3.LocalScmMetadataXpp3Reader; import org.apache.maven.scm.tck.command.checkout.CheckOutCommandTckTest; +import org.codehaus.plexus.util.FileUtils; +import org.codehaus.plexus.util.IOUtil; -import java.io.File; - /** * @author Emmanuel Venisse * @version $Id$ @@ -50,4 +58,39 @@ makeDirectory( root, "/src/test/resources" ); } + + /** + * Tests that the metadata file .maven-scm-local is written correctly + */ + public void testMetadata() throws Exception + { + FileUtils.deleteDirectory( getWorkingCopy() ); + + CheckOutScmResult result = checkOut( getWorkingCopy(), getScmRepository() ); + + assertResultIsSuccess( result ); + + List checkedOutFiles = result.getCheckedOutFiles(); + + assertEquals( 4, checkedOutFiles.size() ); + + // ---------------------------------------------------------------------- + // Assert metadata file + // ---------------------------------------------------------------------- + File metadataFile = new File( getWorkingCopy(), ".maven-scm-local" ); + assertTrue( "Expected metadata file .maven-scm-local does not exist", metadataFile.exists() ); + Reader reader = new FileReader( metadataFile ); + LocalScmMetadata metadata; + try + { + metadata = new LocalScmMetadataXpp3Reader().read( reader ); + } + finally + { + IOUtil.close( reader ); + } + File root = new File( getRepositoryRoot() + "/" + module ); + List fileNames = FileUtils.getFileNames( root, "**", null, false ); + assertEquals( fileNames, metadata.getRepositoryFileNames() ); + } } Index: C:/java/maven-src/maven-scm/maven-scm-providers/maven-scm-provider-local/src/main/mdo/maven-scm-local-metadata.mdo =================================================================== --- C:/java/maven-src/maven-scm/maven-scm-providers/maven-scm-provider-local/src/main/mdo/maven-scm-local-metadata.mdo (revision 0) +++ C:/java/maven-src/maven-scm/maven-scm-providers/maven-scm-provider-local/src/main/mdo/maven-scm-local-metadata.mdo (revision 0) @@ -0,0 +1,29 @@ + + maven-scm-local-metadata + LocalScmMetadata + Metadata for Maven SCM Local provider + + + package + org.apache.maven.scm.providers.local.metadata + + + + + + LocalScmMetadata + 1.0.0+ + + + repositoryFileNames + 1.0.0+ + + String + * + + The list of filenames contained in the repository during last checkout or update operation. + + + + + Index: C:/java/maven-src/maven-scm/maven-scm-providers/maven-scm-provider-local/src/main/java/org/apache/maven/scm/provider/local/metadata/LocalScmMetadataUtils.java =================================================================== --- C:/java/maven-src/maven-scm/maven-scm-providers/maven-scm-provider-local/src/main/java/org/apache/maven/scm/provider/local/metadata/LocalScmMetadataUtils.java (revision 0) +++ C:/java/maven-src/maven-scm/maven-scm-providers/maven-scm-provider-local/src/main/java/org/apache/maven/scm/provider/local/metadata/LocalScmMetadataUtils.java (revision 0) @@ -0,0 +1,103 @@ +package org.apache.maven.scm.provider.local.metadata; + +import java.io.File; +import java.io.FileReader; +import java.io.FileWriter; +import java.io.IOException; +import java.io.Reader; +import java.io.Writer; +import java.util.List; + +import org.apache.maven.scm.log.ScmLogger; +import org.apache.maven.scm.providers.local.metadata.LocalScmMetadata; +import org.apache.maven.scm.providers.local.metadata.io.xpp3.LocalScmMetadataXpp3Reader; +import org.apache.maven.scm.providers.local.metadata.io.xpp3.LocalScmMetadataXpp3Writer; +import org.codehaus.plexus.util.FileUtils; +import org.codehaus.plexus.util.IOUtil; +import org.codehaus.plexus.util.xml.pull.XmlPullParserException; + +/** + * Utils for dealing with LocalScmMetadata + * + * @author Arne Degenring + * @version $Id: $ + */ +public class LocalScmMetadataUtils +{ + /** The name of the metadata file */ + public static final String FILENMAE = ".maven-scm-local"; + + protected final ScmLogger logger; + + public LocalScmMetadataUtils( ScmLogger logger ) + { + this.logger = logger; + } + + /** + * Builds LocalScmMetadata based on contents of repository + */ + public LocalScmMetadata buildMetadata( File repository ) throws IOException + { + List repoFilenames = FileUtils.getFileNames( repository.getAbsoluteFile(), "**", null, false ); + LocalScmMetadata metadata = new LocalScmMetadata(); + metadata.setRepositoryFileNames( repoFilenames ); + return metadata; + } + + /** + * Writes metadata file + */ + public void writeMetadata( File destinationDir, LocalScmMetadata metadata ) throws IOException + { + File metadataFile = new File( destinationDir, FILENMAE ); + metadataFile.createNewFile(); + Writer writer = new FileWriter( metadataFile ); + try + { + new LocalScmMetadataXpp3Writer().write( writer, metadata ); + } + finally + { + IOUtil.close( writer ); + } + } + + /** + * Reads metadata file from given directory. + * + * @param dir + * The directory that should contain the metadata file + * @return LocalScmMetadata or null in case of problems + */ + public LocalScmMetadata readMetadata( File dir ) + { + File metadataFile = new File( dir, FILENMAE ); + if ( !metadataFile.exists() ) + { + return null; + } + LocalScmMetadata result = null; + Reader reader = null; + try + { + reader = new FileReader( metadataFile ); + result = new LocalScmMetadataXpp3Reader().read( reader ); + } + catch ( XmlPullParserException e ) + { + logger.warn( "Could not interpret .maven-scm-local - ignoring", e ); + return null; + } + catch ( IOException e ) + { + logger.warn( "Could not Read .maven-scm-local - ignoring", e ); + } + finally + { + IOUtil.close( reader ); + } + return result; + } + +} Index: C:/java/maven-src/maven-scm/maven-scm-providers/maven-scm-provider-local/src/main/java/org/apache/maven/scm/provider/local/command/update/LocalUpdateCommand.java =================================================================== --- C:/java/maven-src/maven-scm/maven-scm-providers/maven-scm-provider-local/src/main/java/org/apache/maven/scm/provider/local/command/update/LocalUpdateCommand.java (revision 446890) +++ C:/java/maven-src/maven-scm/maven-scm-providers/maven-scm-provider-local/src/main/java/org/apache/maven/scm/provider/local/command/update/LocalUpdateCommand.java (working copy) @@ -16,6 +16,12 @@ * limitations under the License. */ +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + import org.apache.maven.scm.ScmException; import org.apache.maven.scm.ScmFile; import org.apache.maven.scm.ScmFileSet; @@ -26,16 +32,12 @@ import org.apache.maven.scm.provider.ScmProviderRepository; import org.apache.maven.scm.provider.local.command.LocalCommand; import org.apache.maven.scm.provider.local.command.changelog.LocalChangeLogCommand; +import org.apache.maven.scm.provider.local.metadata.LocalScmMetadataUtils; import org.apache.maven.scm.provider.local.repository.LocalScmProviderRepository; +import org.apache.maven.scm.providers.local.metadata.LocalScmMetadata; import org.codehaus.plexus.util.FileUtils; import org.codehaus.plexus.util.StringUtils; -import java.io.File; -import java.io.IOException; -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; - /** * @author Trygve Laugstøl * @version $Id$ @@ -94,6 +96,31 @@ List fileList = FileUtils.getFiles( source.getAbsoluteFile(), "**", null ); updatedFiles = update( source, baseDestination, fileList ); + + // process deletions in repository + LocalScmMetadataUtils metadataUtils = new LocalScmMetadataUtils( getLogger() ); + LocalScmMetadata originalMetadata = metadataUtils.readMetadata( baseDestination ); + if ( originalMetadata != null ) + { + LocalScmMetadata newMetadata = metadataUtils.buildMetadata( source ); + for ( Iterator it = originalMetadata.getRepositoryFileNames().iterator(); it.hasNext(); ) + { + String filename = (String) it.next(); + if ( !newMetadata.getRepositoryFileNames().contains( filename ) ) + { + File localFile = new File( baseDestination, filename ); + if ( localFile.exists() ) + { + localFile.delete(); + updatedFiles.add( new ScmFile( "/" + filename, ScmFileStatus.UPDATED ) ); + } + } + } + } + + // rewrite metadata file + metadataUtils.writeMetadata( baseDestination, metadataUtils.buildMetadata( source ) ); + } catch ( IOException ex ) { Index: C:/java/maven-src/maven-scm/maven-scm-providers/maven-scm-provider-local/src/main/java/org/apache/maven/scm/provider/local/command/checkout/LocalCheckOutCommand.java =================================================================== --- C:/java/maven-src/maven-scm/maven-scm-providers/maven-scm-provider-local/src/main/java/org/apache/maven/scm/provider/local/command/checkout/LocalCheckOutCommand.java (revision 446890) +++ C:/java/maven-src/maven-scm/maven-scm-providers/maven-scm-provider-local/src/main/java/org/apache/maven/scm/provider/local/command/checkout/LocalCheckOutCommand.java (working copy) @@ -16,6 +16,15 @@ * limitations under the License. */ +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.io.Writer; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Iterator; +import java.util.List; + import org.apache.maven.scm.ScmException; import org.apache.maven.scm.ScmFile; import org.apache.maven.scm.ScmFileSet; @@ -24,17 +33,14 @@ import org.apache.maven.scm.command.checkout.CheckOutScmResult; import org.apache.maven.scm.provider.ScmProviderRepository; import org.apache.maven.scm.provider.local.command.LocalCommand; +import org.apache.maven.scm.provider.local.metadata.LocalScmMetadataUtils; import org.apache.maven.scm.provider.local.repository.LocalScmProviderRepository; +import org.apache.maven.scm.providers.local.metadata.LocalScmMetadata; +import org.apache.maven.scm.providers.local.metadata.io.xpp3.LocalScmMetadataXpp3Writer; import org.codehaus.plexus.util.FileUtils; +import org.codehaus.plexus.util.IOUtil; import org.codehaus.plexus.util.StringUtils; -import java.io.File; -import java.io.IOException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Iterator; -import java.util.List; - /** * @author Trygve Laugstøl * @version $Id$ @@ -101,6 +107,10 @@ } checkedOutFiles = checkOut( source, baseDestination, fileList, repository.getModule() ); + + // write metadata file + LocalScmMetadataUtils metadataUtils = new LocalScmMetadataUtils( getLogger() ); + metadataUtils.writeMetadata( baseDestination, metadataUtils.buildMetadata( source ) ); } catch ( IOException ex ) { @@ -152,4 +162,6 @@ return checkedOutFiles; } + + } Index: C:/java/maven-src/maven-scm/maven-scm-providers/maven-scm-provider-local/pom.xml =================================================================== --- C:/java/maven-src/maven-scm/maven-scm-providers/maven-scm-provider-local/pom.xml (revision 446890) +++ C:/java/maven-src/maven-scm/maven-scm-providers/maven-scm-provider-local/pom.xml (working copy) @@ -8,4 +8,27 @@ maven-scm-provider-local Maven SCM Local Provider 1.0-SNAPSHOT + + + + org.codehaus.modello + modello-maven-plugin + 1.0-alpha-6 + + + + java + xpp3-reader + xpp3-writer + xsd + + + + + 1.0.0 + src/main/mdo/maven-scm-local-metadata.mdo + + + + \ No newline at end of file