mirror of https://github.com/apache/maven.git
implement snapshot policies: default is to only check once a day (after crossing midnight), or if --update-snapshots (-U) is specified on the command line
git-svn-id: https://svn.apache.org/repos/asf/maven/components/trunk@163711 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
b03435f9e1
commit
eabafcc093
|
@ -52,6 +52,8 @@ public class SnapshotArtifactMetadata
|
|||
|
||||
private static final String UTC_TIMESTAMP_PATTERN = "yyyyMMdd.HHmmss";
|
||||
|
||||
private long lastModified = 0;
|
||||
|
||||
public SnapshotArtifactMetadata( Artifact artifact )
|
||||
{
|
||||
super( artifact, artifact.getArtifactId() + "-" + artifact.getBaseVersion() + "." + SNAPSHOT_VERSION_FILE );
|
||||
|
@ -81,6 +83,7 @@ public class SnapshotArtifactMetadata
|
|||
}
|
||||
String path = getLocalRepositoryLocation( localRepository ).getPath();
|
||||
FileUtils.fileWrite( path, constructVersion() );
|
||||
lastModified = new File( path ).lastModified();
|
||||
}
|
||||
catch ( IOException e )
|
||||
{
|
||||
|
@ -101,7 +104,7 @@ public class SnapshotArtifactMetadata
|
|||
public String constructVersion()
|
||||
{
|
||||
String version = artifact.getBaseVersion();
|
||||
if ( timestamp != null )
|
||||
if ( timestamp != null && buildNumber > 0 )
|
||||
{
|
||||
String newVersion = timestamp + "-" + buildNumber;
|
||||
if ( version != null )
|
||||
|
@ -157,15 +160,23 @@ public class SnapshotArtifactMetadata
|
|||
return snapshotMetadata;
|
||||
}
|
||||
|
||||
private void readFromFile( File destination )
|
||||
private void readFromFile( File file )
|
||||
throws IOException
|
||||
{
|
||||
String version = FileUtils.fileRead( destination );
|
||||
String version = FileUtils.fileRead( file );
|
||||
lastModified = file.lastModified();
|
||||
|
||||
if ( version.indexOf( "SNAPSHOT" ) >= 0 )
|
||||
{
|
||||
timestamp = null;
|
||||
buildNumber = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
int index = version.lastIndexOf( "-" );
|
||||
timestamp = version.substring( 0, index );
|
||||
buildNumber = Integer.valueOf( version.substring( index + 1 ) ).intValue();
|
||||
index = version.indexOf( "-" );
|
||||
index = timestamp.lastIndexOf( "-" );
|
||||
if ( index >= 0 )
|
||||
{
|
||||
// ignore starting version part, will be prepended later
|
||||
|
@ -196,6 +207,9 @@ public class SnapshotArtifactMetadata
|
|||
{
|
||||
SnapshotArtifactMetadata metadata = (SnapshotArtifactMetadata) o;
|
||||
|
||||
// TODO: probably shouldn't test timestamp - except that it may be used do differentiate for a build number of 0
|
||||
// in the local repository. check, then remove from here and just compare the build numbers
|
||||
|
||||
if ( buildNumber > metadata.buildNumber )
|
||||
{
|
||||
return 1;
|
||||
|
@ -209,4 +223,9 @@ public class SnapshotArtifactMetadata
|
|||
return timestamp.compareTo( metadata.timestamp );
|
||||
}
|
||||
}
|
||||
|
||||
public long getLastModified()
|
||||
{
|
||||
return lastModified;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -33,21 +33,46 @@ import org.apache.maven.wagon.repository.Repository;
|
|||
public class ArtifactRepository
|
||||
extends Repository
|
||||
{
|
||||
private final String snapshotPolicy;
|
||||
|
||||
private final ArtifactRepositoryLayout layout;
|
||||
|
||||
public static final String SNAPSHOT_POLICY_NEVER = "never";
|
||||
|
||||
public static final String SNAPSHOT_POLICY_ALWAYS = "always";
|
||||
|
||||
public static final String SNAPSHOT_POLICY_DAILY = "daily";
|
||||
|
||||
public static final String SNAPSHOT_POLICY_INTERVAL = "interval";
|
||||
|
||||
public ArtifactRepository( String id, String url, ArtifactRepositoryLayout layout )
|
||||
{
|
||||
this( id, url, layout, null );
|
||||
}
|
||||
|
||||
public ArtifactRepository( String id, String url, AuthenticationInfo authenticationInfo,
|
||||
ArtifactRepositoryLayout layout )
|
||||
{
|
||||
this( id, url, authenticationInfo, layout, null );
|
||||
}
|
||||
|
||||
public ArtifactRepository( String id, String url, ArtifactRepositoryLayout layout, String snapshotPolicy )
|
||||
{
|
||||
super( id, url );
|
||||
|
||||
this.layout = layout;
|
||||
|
||||
this.snapshotPolicy = snapshotPolicy;
|
||||
}
|
||||
|
||||
public ArtifactRepository( String id, String url, AuthenticationInfo authInfo, ArtifactRepositoryLayout layout )
|
||||
public ArtifactRepository( String id, String url, AuthenticationInfo authInfo, ArtifactRepositoryLayout layout,
|
||||
String snapshotPolicy )
|
||||
{
|
||||
super( id, url, authInfo );
|
||||
|
||||
this.layout = layout;
|
||||
|
||||
this.snapshotPolicy = snapshotPolicy;
|
||||
}
|
||||
|
||||
public String pathOf( Artifact artifact )
|
||||
|
@ -62,4 +87,8 @@ public class ArtifactRepository
|
|||
return layout.pathOfMetadata( artifactMetadata );
|
||||
}
|
||||
|
||||
public String getSnapshotPolicy()
|
||||
{
|
||||
return snapshotPolicy;
|
||||
}
|
||||
}
|
|
@ -25,6 +25,8 @@ import org.apache.maven.artifact.repository.layout.ArtifactPathFormatException;
|
|||
import org.codehaus.plexus.logging.AbstractLogEnabled;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
@ -50,9 +52,7 @@ public class SnapshotTransformation
|
|||
public void transformForResolve( Artifact artifact, List remoteRepositories, ArtifactRepository localRepository )
|
||||
throws ArtifactMetadataRetrievalException
|
||||
{
|
||||
// TODO: remove hack
|
||||
if ( isSnapshot( artifact ) &&
|
||||
!Boolean.valueOf( System.getProperty( "maven.debug.snapshot.disabled", "true" ) ).booleanValue() )
|
||||
if ( isSnapshot( artifact ) )
|
||||
{
|
||||
// TODO: this mostly works, however...
|
||||
// - we definitely need the manual/daily check as this is quite slow given the large number of snapshots inside m2 presently
|
||||
|
@ -72,31 +72,65 @@ public class SnapshotTransformation
|
|||
}
|
||||
|
||||
String version = localMetadata.constructVersion();
|
||||
if ( !alreadyResolved( artifact ) )
|
||||
// TODO: remove hack
|
||||
if ( !alreadyResolved( artifact ) &&
|
||||
!Boolean.valueOf( System.getProperty( "maven.debug.snapshot.disabled", "false" ) ).booleanValue() )
|
||||
{
|
||||
boolean foundRemote = false;
|
||||
boolean checkedUpdates = false;
|
||||
for ( Iterator i = remoteRepositories.iterator(); i.hasNext(); )
|
||||
{
|
||||
ArtifactRepository remoteRepository = (ArtifactRepository) i.next();
|
||||
|
||||
getLogger().info(
|
||||
artifact.getArtifactId() + ": checking for updates from " + remoteRepository.getId() );
|
||||
|
||||
SnapshotArtifactMetadata remoteMetadata = SnapshotArtifactMetadata.retrieveFromRemoteRepository(
|
||||
artifact, remoteRepository, wagonManager );
|
||||
|
||||
if ( remoteMetadata.compareTo( localMetadata ) > 0 )
|
||||
String snapshotPolicy = remoteRepository.getSnapshotPolicy();
|
||||
// TODO: should be able to calculate this less often
|
||||
boolean checkForUpdates = false;
|
||||
if ( ArtifactRepository.SNAPSHOT_POLICY_ALWAYS.equals( snapshotPolicy ) )
|
||||
{
|
||||
artifact.setRepository( remoteRepository );
|
||||
checkForUpdates = true;
|
||||
}
|
||||
else if ( ArtifactRepository.SNAPSHOT_POLICY_DAILY.equals( snapshotPolicy ) )
|
||||
{
|
||||
// Note that if last modified is 0, it didn't exist, so this will be true
|
||||
if ( getMidnightBoundary().after( new Date( localMetadata.getLastModified() ) ) )
|
||||
{
|
||||
checkForUpdates = true;
|
||||
}
|
||||
}
|
||||
else if ( snapshotPolicy.startsWith( ArtifactRepository.SNAPSHOT_POLICY_INTERVAL ) )
|
||||
{
|
||||
String s = snapshotPolicy.substring( ArtifactRepository.SNAPSHOT_POLICY_INTERVAL.length() + 1 );
|
||||
int minutes = Integer.valueOf( s ).intValue();
|
||||
Calendar cal = Calendar.getInstance();
|
||||
cal.add( Calendar.MINUTE, -minutes );
|
||||
// Note that if last modified is 0, it didn't exist, so this will be true
|
||||
if ( cal.getTime().after( new Date( localMetadata.getLastModified() ) ) )
|
||||
{
|
||||
checkForUpdates = true;
|
||||
}
|
||||
}
|
||||
// else assume "never"
|
||||
|
||||
localMetadata = remoteMetadata;
|
||||
foundRemote = true;
|
||||
if ( checkForUpdates )
|
||||
{
|
||||
getLogger().info(
|
||||
artifact.getArtifactId() + ": checking for updates from " + remoteRepository.getId() );
|
||||
|
||||
SnapshotArtifactMetadata remoteMetadata = SnapshotArtifactMetadata.retrieveFromRemoteRepository(
|
||||
artifact, remoteRepository, wagonManager );
|
||||
|
||||
if ( remoteMetadata.compareTo( localMetadata ) > 0 )
|
||||
{
|
||||
artifact.setRepository( remoteRepository );
|
||||
|
||||
localMetadata = remoteMetadata;
|
||||
}
|
||||
checkedUpdates = true;
|
||||
}
|
||||
}
|
||||
|
||||
if ( foundRemote )
|
||||
if ( checkedUpdates )
|
||||
{
|
||||
artifact.addMetadata( localMetadata );
|
||||
localMetadata.storeInLocalRepository( localRepository );
|
||||
}
|
||||
|
||||
if ( getLogger().isInfoEnabled() )
|
||||
|
@ -104,7 +138,7 @@ public class SnapshotTransformation
|
|||
if ( !version.equals( artifact.getBaseVersion() ) )
|
||||
{
|
||||
String message = artifact.getArtifactId() + ": resolved to version " + version;
|
||||
if ( foundRemote )
|
||||
if ( artifact.getRepository() != null )
|
||||
{
|
||||
message += " from repository " + artifact.getRepository().getId();
|
||||
}
|
||||
|
@ -122,6 +156,16 @@ public class SnapshotTransformation
|
|||
}
|
||||
}
|
||||
|
||||
private Date getMidnightBoundary()
|
||||
{
|
||||
Calendar cal = Calendar.getInstance();
|
||||
cal.set( Calendar.HOUR_OF_DAY, 0 );
|
||||
cal.set( Calendar.MINUTE, 0 );
|
||||
cal.set( Calendar.SECOND, 0 );
|
||||
cal.set( Calendar.MILLISECOND, 0 );
|
||||
return cal.getTime();
|
||||
}
|
||||
|
||||
private boolean alreadyResolved( Artifact artifact )
|
||||
{
|
||||
return resolvedArtifactCache.contains( getCacheKey( artifact ) );
|
||||
|
|
|
@ -31,4 +31,5 @@ public interface ArtifactRepositoryFactory
|
|||
public ArtifactRepository createArtifactRepository( Repository modelRepository, MavenSettings settings,
|
||||
ArtifactRepositoryLayout repositoryLayout );
|
||||
|
||||
void setGlobalSnapshotPolicy( String snapshotPolicy );
|
||||
}
|
|
@ -31,6 +31,7 @@ public class DefaultArtifactRepositoryFactory
|
|||
extends AbstractLogEnabled
|
||||
implements ArtifactRepositoryFactory
|
||||
{
|
||||
private String globalSnapshotPolicy = null;
|
||||
|
||||
public ArtifactRepository createArtifactRepository( Repository modelRepository, MavenSettings settings,
|
||||
ArtifactRepositoryLayout repositoryLayout )
|
||||
|
@ -55,6 +56,12 @@ public class DefaultArtifactRepositoryFactory
|
|||
|
||||
ArtifactRepository repo = null;
|
||||
|
||||
String snapshotPolicy = globalSnapshotPolicy;
|
||||
if ( snapshotPolicy == null )
|
||||
{
|
||||
snapshotPolicy = modelRepository.getSnapshotPolicy();
|
||||
}
|
||||
|
||||
if ( repoProfile != null )
|
||||
{
|
||||
AuthenticationInfo authInfo = new AuthenticationInfo();
|
||||
|
@ -68,14 +75,20 @@ public class DefaultArtifactRepositoryFactory
|
|||
authInfo.setPassphrase( repoProfile.getPassphrase() );
|
||||
|
||||
repo = new ArtifactRepository( modelRepository.getId(), modelRepository.getUrl(), authInfo,
|
||||
repositoryLayout );
|
||||
repositoryLayout, snapshotPolicy );
|
||||
}
|
||||
else
|
||||
{
|
||||
repo = new ArtifactRepository( modelRepository.getId(), modelRepository.getUrl(), repositoryLayout );
|
||||
repo = new ArtifactRepository( modelRepository.getId(), modelRepository.getUrl(), repositoryLayout,
|
||||
snapshotPolicy );
|
||||
}
|
||||
|
||||
return repo;
|
||||
}
|
||||
|
||||
public void setGlobalSnapshotPolicy( String snapshotPolicy )
|
||||
{
|
||||
this.globalSnapshotPolicy = snapshotPolicy;
|
||||
}
|
||||
|
||||
}
|
|
@ -67,7 +67,8 @@ public class MavenCli
|
|||
|
||||
public static File userDir = new File( System.getProperty( "user.dir" ) );
|
||||
|
||||
public static int main( String[] args, ClassWorld classWorld ) throws Exception
|
||||
public static int main( String[] args, ClassWorld classWorld )
|
||||
throws Exception
|
||||
{
|
||||
// ----------------------------------------------------------------------
|
||||
// Setup the command line parser
|
||||
|
@ -135,8 +136,13 @@ public class MavenCli
|
|||
|
||||
MavenSettings settings = settingsBuilder.buildSettings();
|
||||
|
||||
ArtifactRepositoryFactory artifactRepositoryFactory = (ArtifactRepositoryFactory) embedder
|
||||
.lookup( ArtifactRepositoryFactory.ROLE );
|
||||
ArtifactRepositoryFactory artifactRepositoryFactory = (ArtifactRepositoryFactory) embedder.lookup(
|
||||
ArtifactRepositoryFactory.ROLE );
|
||||
|
||||
if ( commandLine.hasOption( CLIManager.UPDATE_SNAPSHOTS ) )
|
||||
{
|
||||
artifactRepositoryFactory.setGlobalSnapshotPolicy( ArtifactRepository.SNAPSHOT_POLICY_ALWAYS );
|
||||
}
|
||||
|
||||
// TODO: Switch the default repository layout id to "default" when the
|
||||
// conversion is done.
|
||||
|
@ -152,10 +158,8 @@ public class MavenCli
|
|||
repoLayoutId = "default";
|
||||
}
|
||||
|
||||
ArtifactRepositoryLayout repositoryLayout = (ArtifactRepositoryLayout) embedder
|
||||
.lookup(
|
||||
ArtifactRepositoryLayout.ROLE,
|
||||
repoLayoutId );
|
||||
ArtifactRepositoryLayout repositoryLayout = (ArtifactRepositoryLayout) embedder.lookup(
|
||||
ArtifactRepositoryLayout.ROLE, repoLayoutId );
|
||||
|
||||
ArtifactRepository localRepository = getLocalRepository( settings, artifactRepositoryFactory, repositoryLayout );
|
||||
|
||||
|
@ -302,43 +306,42 @@ public class MavenCli
|
|||
// TODO: this is a hack until we can get the main repo converted...
|
||||
public static final char VERSION_2_REPO = 'a';
|
||||
|
||||
public static final char UPDATE_SNAPSHOTS = 'U';
|
||||
|
||||
public CLIManager()
|
||||
{
|
||||
options = new Options();
|
||||
options.addOption( OptionBuilder.withLongOpt( "nobanner" ).withDescription( "Suppress logo banner" )
|
||||
.create( NO_BANNER ) );
|
||||
options
|
||||
.addOption( OptionBuilder.withLongOpt( "define" ).hasArg()
|
||||
.withDescription( "Define a system property" ).create( SET_SYSTEM_PROPERTY ) );
|
||||
options.addOption( OptionBuilder.withLongOpt( "offline" ).hasArg().withDescription( "Work offline" )
|
||||
.create( WORK_OFFLINE ) );
|
||||
options
|
||||
.addOption( OptionBuilder.withLongOpt( "mojoDescriptors" )
|
||||
.withDescription( "Display available mojoDescriptors" ).create( LIST_GOALS ) );
|
||||
options.addOption( OptionBuilder.withLongOpt( "help" ).withDescription( "Display help information" )
|
||||
.create( HELP ) );
|
||||
options.addOption( OptionBuilder.withLongOpt( "offline" ).withDescription( "Build is happening offline" )
|
||||
.create( WORK_OFFLINE ) );
|
||||
options.addOption( OptionBuilder.withLongOpt( "version" ).withDescription( "Display version information" )
|
||||
.create( VERSION ) );
|
||||
options.addOption( OptionBuilder.withLongOpt( "debug" ).withDescription( "Produce execution debug output" )
|
||||
.create( DEBUG ) );
|
||||
options.addOption( OptionBuilder.withLongOpt( "reactor" )
|
||||
.withDescription( "Execute goals for project found in the reactor" )
|
||||
.create( REACTOR ) );
|
||||
options.addOption( OptionBuilder.withLongOpt( "non-recursive" )
|
||||
.withDescription( "Do not recurse into sub-projects" )
|
||||
.create( NON_RECURSIVE ) );
|
||||
options.addOption( OptionBuilder.withLongOpt( "v1-local-repository" )
|
||||
.withDescription( "Use legacy layout for local artifact repository" )
|
||||
.create( VERSION_1_REPO ) );
|
||||
options.addOption( OptionBuilder.withLongOpt( "nobanner" ).withDescription( "Suppress logo banner" ).create(
|
||||
NO_BANNER ) );
|
||||
options.addOption( OptionBuilder.withLongOpt( "define" ).hasArg().withDescription(
|
||||
"Define a system property" ).create( SET_SYSTEM_PROPERTY ) );
|
||||
options.addOption( OptionBuilder.withLongOpt( "offline" ).hasArg().withDescription( "Work offline" ).create(
|
||||
WORK_OFFLINE ) );
|
||||
options.addOption( OptionBuilder.withLongOpt( "mojoDescriptors" ).withDescription(
|
||||
"Display available mojoDescriptors" ).create( LIST_GOALS ) );
|
||||
options.addOption( OptionBuilder.withLongOpt( "help" ).withDescription( "Display help information" ).create(
|
||||
HELP ) );
|
||||
options.addOption( OptionBuilder.withLongOpt( "offline" ).withDescription( "Build is happening offline" ).create(
|
||||
WORK_OFFLINE ) );
|
||||
options.addOption( OptionBuilder.withLongOpt( "version" ).withDescription( "Display version information" ).create(
|
||||
VERSION ) );
|
||||
options.addOption( OptionBuilder.withLongOpt( "debug" ).withDescription( "Produce execution debug output" ).create(
|
||||
DEBUG ) );
|
||||
options.addOption( OptionBuilder.withLongOpt( "reactor" ).withDescription(
|
||||
"Execute goals for project found in the reactor" ).create( REACTOR ) );
|
||||
options.addOption( OptionBuilder.withLongOpt( "non-recursive" ).withDescription(
|
||||
"Do not recurse into sub-projects" ).create( NON_RECURSIVE ) );
|
||||
options.addOption( OptionBuilder.withLongOpt( "v1-local-repository" ).withDescription(
|
||||
"Use legacy layout for local artifact repository" ).create( VERSION_1_REPO ) );
|
||||
|
||||
options.addOption( OptionBuilder.withLongOpt( "v2-local-repository" )
|
||||
.withDescription( "Use new layout for local artifact repository" )
|
||||
.create( VERSION_2_REPO ) );
|
||||
options.addOption( OptionBuilder.withLongOpt( "v2-local-repository" ).withDescription(
|
||||
"Use new layout for local artifact repository" ).create( VERSION_2_REPO ) );
|
||||
options.addOption( OptionBuilder.withLongOpt( "update-snapshots" ).withDescription(
|
||||
"Update all snapshots regardless of repository policies" ).create( UPDATE_SNAPSHOTS ) );
|
||||
}
|
||||
|
||||
public CommandLine parse( String[] args ) throws ParseException
|
||||
public CommandLine parse( String[] args )
|
||||
throws ParseException
|
||||
{
|
||||
CommandLineParser parser = new PosixParser();
|
||||
return parser.parse( options, args );
|
||||
|
@ -384,8 +387,9 @@ public class MavenCli
|
|||
}
|
||||
|
||||
protected static ArtifactRepository getLocalRepository( MavenSettings settings,
|
||||
ArtifactRepositoryFactory repoFactory,
|
||||
ArtifactRepositoryLayout repositoryLayout ) throws Exception
|
||||
ArtifactRepositoryFactory repoFactory,
|
||||
ArtifactRepositoryLayout repositoryLayout )
|
||||
throws Exception
|
||||
{
|
||||
Profile profile = settings.getActiveProfile();
|
||||
|
||||
|
@ -398,7 +402,8 @@ public class MavenCli
|
|||
if ( localRepository == null )
|
||||
{
|
||||
String userConfigurationDirectory = System.getProperty( "user.home" ) + "/.m2";
|
||||
localRepository = new File( userConfigurationDirectory, MavenConstants.MAVEN_REPOSITORY ).getAbsolutePath();
|
||||
localRepository =
|
||||
new File( userConfigurationDirectory, MavenConstants.MAVEN_REPOSITORY ).getAbsolutePath();
|
||||
}
|
||||
|
||||
// TODO [BP]: this should not be necessary - grep for and remove
|
||||
|
|
|
@ -1850,6 +1850,16 @@
|
|||
]]></description>
|
||||
<type>String</type>
|
||||
</field>
|
||||
<field>
|
||||
<name>snapshotPolicy</name>
|
||||
<version>4.0.0</version>
|
||||
<description>
|
||||
The policy for downloading snapshots - can be "always", "daily" (default), "interval:XXX" (in minutes) or
|
||||
"never".
|
||||
</description>
|
||||
<type>String</type>
|
||||
<defaultValue>daily</defaultValue>
|
||||
</field>
|
||||
</fields>
|
||||
<codeSegments>
|
||||
<codeSegment>
|
||||
|
|
Loading…
Reference in New Issue