diff --git a/CHANGES.txt b/CHANGES.txt
index 155c024c..1441dafa 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -1,3 +1,6 @@
+- new changing attribute on dependencies indicate that the dependency artifacts
+ may change even without revision change, but with only a new ivy file with new
+ publication date
- new useRemoteConfig on conf tag in ivyconf.xml, tells to use remote configuration file
for repository config
- new type filtering in cachepath task
diff --git a/src/java/fr/jayasoft/ivy/DefaultDependencyDescriptor.java b/src/java/fr/jayasoft/ivy/DefaultDependencyDescriptor.java
index 55aeef19..535a49e7 100644
--- a/src/java/fr/jayasoft/ivy/DefaultDependencyDescriptor.java
+++ b/src/java/fr/jayasoft/ivy/DefaultDependencyDescriptor.java
@@ -35,17 +35,27 @@ public class DefaultDependencyDescriptor implements DependencyDescriptor {
* of conflicts manager
*/
private boolean _force;
- private ModuleRevisionId _parentId;
+ /**
+ * Used to indicate that the dependency is a changing one, i.e. that ivy should not rely on the version to know if it can trust artifacts in cache
+ */
+ private boolean _changing;
+ private ModuleRevisionId _parentId;
- public DefaultDependencyDescriptor(ModuleDescriptor md, ModuleRevisionId mrid, boolean force) {
+ public DefaultDependencyDescriptor(ModuleDescriptor md, ModuleRevisionId mrid, boolean force, boolean changing) {
_parentId = md.getModuleRevisionId();
_revId = mrid;
_force = force;
+ _changing = changing;
}
public DefaultDependencyDescriptor(ModuleRevisionId mrid, boolean force) {
+ this(mrid, force, false);
+ }
+
+ public DefaultDependencyDescriptor(ModuleRevisionId mrid, boolean force, boolean changing) {
_revId = mrid;
_force = force;
+ _changing = changing;
}
public ModuleId getDependencyId() {
@@ -188,5 +198,9 @@ public class DefaultDependencyDescriptor implements DependencyDescriptor {
public ModuleRevisionId getParentRevisionId() {
return _parentId;
}
-
+
+ public boolean isChanging() {
+ return _changing;
+ }
+
}
diff --git a/src/java/fr/jayasoft/ivy/DependencyDescriptor.java b/src/java/fr/jayasoft/ivy/DependencyDescriptor.java
index 37f88891..4eaacad7 100644
--- a/src/java/fr/jayasoft/ivy/DependencyDescriptor.java
+++ b/src/java/fr/jayasoft/ivy/DependencyDescriptor.java
@@ -19,6 +19,15 @@ public interface DependencyDescriptor {
* can do its work.
*/
boolean isForce();
+ /**
+ * Used to indicate that this dependency is a changing one.
+ * A changing dependency in ivy means that the revision may have its artifacts modified
+ * without revision change. When new artifacts are published a new ivy file should also
+ * be published with a new publication date to indicate to ivy that artifacts have changed and that they
+ * should be downloaded again.
+ * @return true if this dependency is a changing one
+ */
+ boolean isChanging();
ModuleRevisionId getParentRevisionId();
ModuleRevisionId getDependencyRevisionId();
String[] getModuleConfigurations();
diff --git a/src/java/fr/jayasoft/ivy/resolver/BasicResolver.java b/src/java/fr/jayasoft/ivy/resolver/BasicResolver.java
index 8178a172..5e52876d 100644
--- a/src/java/fr/jayasoft/ivy/resolver/BasicResolver.java
+++ b/src/java/fr/jayasoft/ivy/resolver/BasicResolver.java
@@ -146,6 +146,7 @@ public abstract class BasicResolver extends AbstractResolver {
_ivyattempts.clear();
boolean downloaded = false;
boolean searched = false;
+ Date cachedPublicationDate = null;
ModuleRevisionId mrid = dd.getDependencyRevisionId();
// check revision
int index = mrid.getRevision().indexOf("@");
@@ -159,9 +160,9 @@ public abstract class BasicResolver extends AbstractResolver {
return null;
}
- // if we do not have to check modified and if the revision is exact, we first
- // search for it in cache
- if (mrid.isExactRevision() && !isCheckmodified()) {
+ // if we do not have to check modified and if the revision is exact and not changing,
+ // we first search for it in cache
+ if (mrid.isExactRevision() && !isCheckmodified() && !dd.isChanging()) {
ResolvedModuleRevision rmr = data.getIvy().findModuleInCache(mrid, data.getCache(), doValidate(data));
if (rmr != null) {
Message.verbose("\t"+getName()+": revision in cache: "+mrid);
@@ -214,17 +215,22 @@ public abstract class BasicResolver extends AbstractResolver {
// now let's see if we can find it in cache and if it is up to date
ResolvedModuleRevision rmr = data.getIvy().findModuleInCache(resolvedMrid, data.getCache(), doValidate(data));
if (rmr != null) {
- if (!isCheckmodified()) {
+ if (!isCheckmodified() && !dd.isChanging()) {
Message.verbose("\t"+getName()+": revision in cache: "+resolvedMrid);
return searchedRmr(rmr);
}
long repLastModified = ivyRef.getLastModified();
long cacheLastModified = rmr.getDescriptor().getLastModified();
- if (rmr.getDescriptor().isDefault() || repLastModified <= cacheLastModified) {
+ if (repLastModified <= cacheLastModified) {
Message.verbose("\t"+getName()+": revision in cache (not updated): "+resolvedMrid);
return searchedRmr(rmr);
} else {
Message.verbose("\t"+getName()+": revision in cache is not up to date: "+resolvedMrid);
+ if (dd.isChanging()) {
+ // ivy file has been updated, we should see if it has a new publication date
+ // to see if a new download is required (in case the dependency is a changing one)
+ cachedPublicationDate = rmr.getDescriptor().getResolvedPublicationDate();
+ }
}
}
@@ -261,6 +267,25 @@ public abstract class BasicResolver extends AbstractResolver {
!ivyRef.getRevision().equals(md.getModuleRevisionId().getRevision())) {
throw new IllegalStateException("bad revision found in "+ivyRef.getResource()+": expected="+ivyRef.getRevision()+" found="+md.getModuleRevisionId().getRevision());
}
+
+ // check if publication date has changed
+ if (cachedPublicationDate != null && !cachedPublicationDate.equals(md.getResolvedPublicationDate())) {
+ // artifacts have changed, they should be downloaded again
+ Message.verbose("dependency "+dd+" has changed: deleting old artifacts");
+ String[] confs = rmr.getDescriptor().getConfigurationsNames();
+ for (int i = 0; i < confs.length; i++) {
+ Artifact[] arts = rmr.getDescriptor().getArtifacts(confs[i]);
+ for (int j = 0; j < arts.length; j++) {
+ File artFile = data.getIvy().getArchiveFileInCache(data.getCache(), arts[j]);
+ if (artFile.exists()) {
+ Message.debug("deleting "+artFile);
+ artFile.delete();
+ }
+ }
+ }
+ } else if (dd.isChanging()){
+ Message.verbose("dependency "+dd+" is changing, but has not changed: will trust cached artifacts if any");
+ }
} catch (IOException ex) {
Message.warn("io problem while parsing ivy file: "+ivyRef.getResource()+": "+ex.getMessage());
return null;
diff --git a/src/java/fr/jayasoft/ivy/xml/XmlModuleDescriptorParser.java b/src/java/fr/jayasoft/ivy/xml/XmlModuleDescriptorParser.java
index 6f4dd566..28fe38a4 100644
--- a/src/java/fr/jayasoft/ivy/xml/XmlModuleDescriptorParser.java
+++ b/src/java/fr/jayasoft/ivy/xml/XmlModuleDescriptorParser.java
@@ -50,7 +50,7 @@ import fr.jayasoft.ivy.util.XMLHelper;
*
*/
public class XmlModuleDescriptorParser extends DefaultHandler {
- private static final Collection ALLOWED_VERSIONS = Arrays.asList(new String[] {"1.0", "1.1"});
+ private static final Collection ALLOWED_VERSIONS = Arrays.asList(new String[] {"1.0", "1.1", "1.2"});
private DefaultModuleDescriptor _md;
private DefaultDependencyDescriptor _dd;
@@ -229,9 +229,10 @@ public class XmlModuleDescriptorParser extends DefaultHandler {
org = _md.getModuleRevisionId().getOrganisation();
}
boolean force = Boolean.valueOf(attributes.getValue("force")).booleanValue();
+ boolean changing = Boolean.valueOf(attributes.getValue("changing")).booleanValue();
String name = _ivy.substitute(attributes.getValue("name"));
String rev = _ivy.substitute(attributes.getValue("rev"));
- _dd = new DefaultDependencyDescriptor(_md, ModuleRevisionId.newInstance(org, name, rev), force);
+ _dd = new DefaultDependencyDescriptor(_md, ModuleRevisionId.newInstance(org, name, rev), force, changing);
_md.addDependency(_dd);
String confs = attributes.getValue("conf");
if (confs != null && confs.length() > 0) {
diff --git a/src/java/fr/jayasoft/ivy/xml/ivy.xsd b/src/java/fr/jayasoft/ivy/xml/ivy.xsd
index 4cb65b2d..5925096f 100644
--- a/src/java/fr/jayasoft/ivy/xml/ivy.xsd
+++ b/src/java/fr/jayasoft/ivy/xml/ivy.xsd
@@ -159,6 +159,7 @@
+
diff --git a/test/java/fr/jayasoft/ivy/resolver/FileSystemResolverTest.java b/test/java/fr/jayasoft/ivy/resolver/FileSystemResolverTest.java
index d138a775..30b53299 100644
--- a/test/java/fr/jayasoft/ivy/resolver/FileSystemResolverTest.java
+++ b/test/java/fr/jayasoft/ivy/resolver/FileSystemResolverTest.java
@@ -5,7 +5,10 @@
*/
package fr.jayasoft.ivy.resolver;
+import java.io.BufferedReader;
import java.io.File;
+import java.io.FileReader;
+import java.io.Reader;
import java.util.Date;
import java.util.GregorianCalendar;
@@ -155,6 +158,76 @@ public class FileSystemResolverTest extends TestCase {
assertEquals(pubdate, rmr.getPublicationDate());
}
+ public void testChanging() throws Exception {
+ FileSystemResolver resolver = new FileSystemResolver();
+ resolver.setName("test");
+ resolver.setIvy(_ivy);
+ _ivy.addResolver(resolver);
+ assertEquals("test", resolver.getName());
+
+ resolver.addIvyPattern("test"+FS+"repositories"+FS+"checkmodified"+FS+"ivy-[revision].xml");
+ resolver.addArtifactPattern("test"+FS+"repositories"+FS+"checkmodified"+FS+"[artifact]-[revision].[ext]");
+ File modify = new File("test/repositories/checkmodified/ivy-1.0.xml");
+ File artifact = new File("test/repositories/checkmodified/mod1.1-1.0.jar");
+
+ // 'publish' 'before' version
+ FileUtil.copy(new File("test/repositories/checkmodified/ivy-1.0-before.xml"), modify, null);
+ FileUtil.copy(new File("test/repositories/checkmodified/mod1.1-1.0-before.jar"), artifact, null);
+ Date pubdate = new GregorianCalendar(2004, 10, 1, 11, 0, 0).getTime();
+ modify.setLastModified(pubdate.getTime());
+
+ ModuleRevisionId mrid = ModuleRevisionId.newInstance("org1", "mod1.1", "1.0");
+ ResolvedModuleRevision rmr = resolver.getDependency(new DefaultDependencyDescriptor(mrid, false), _data);
+ assertNotNull(rmr);
+
+ assertEquals(mrid, rmr.getId());
+ assertEquals(pubdate, rmr.getPublicationDate());
+
+ Artifact[] artifacts = rmr.getDescriptor().getArtifacts("default");
+ resolver.download(artifacts, _ivy, _cache);
+ File archiveFileInCache = _ivy.getArchiveFileInCache(_cache, artifacts[0]);
+ assertTrue(archiveFileInCache.exists());
+ BufferedReader r = new BufferedReader(new FileReader(archiveFileInCache));
+ assertEquals("before", r.readLine());
+ r.close();
+
+ // updates ivy file and artifact in repository
+ FileUtil.copy(new File("test/repositories/checkmodified/ivy-1.0-after.xml"), modify, null);
+ FileUtil.copy(new File("test/repositories/checkmodified/mod1.1-1.0-after.jar"), artifact, null);
+ pubdate = new GregorianCalendar(2005, 4, 1, 11, 0, 0).getTime();
+ modify.setLastModified(pubdate.getTime());
+ // no need to update new artifact timestamp cause it isn't used
+
+ // should not get the new version: checkmodified is false and edpendency is not told to be a changing one
+ resolver.setCheckmodified(false);
+ rmr = resolver.getDependency(new DefaultDependencyDescriptor(mrid, false), _data);
+ assertNotNull(rmr);
+
+ assertEquals(mrid, rmr.getId());
+ assertEquals(new GregorianCalendar(2004, 10, 1, 11, 0, 0).getTime(), rmr.getPublicationDate());
+
+ assertTrue(archiveFileInCache.exists());
+ r = new BufferedReader(new FileReader(archiveFileInCache));
+ assertEquals("before", r.readLine());
+ r.close();
+
+ // should now get the new version cause we say it's a changing one
+ rmr = resolver.getDependency(new DefaultDependencyDescriptor(mrid, false, true), _data);
+ assertNotNull(rmr);
+
+ assertEquals(mrid, rmr.getId());
+ assertEquals(pubdate, rmr.getPublicationDate());
+
+ assertFalse(archiveFileInCache.exists());
+
+ artifacts = rmr.getDescriptor().getArtifacts("default");
+ resolver.download(artifacts, _ivy, _cache);
+ assertTrue(archiveFileInCache.exists());
+ r = new BufferedReader(new FileReader(archiveFileInCache));
+ assertEquals("after", r.readLine());
+ r.close();
+}
+
public void testLatestTime() throws Exception {
FileSystemResolver resolver = new FileSystemResolver();
resolver.setName("test");
diff --git a/test/repositories/checkmodified/mod1.1-1.0-after.jar b/test/repositories/checkmodified/mod1.1-1.0-after.jar
new file mode 100644
index 00000000..5c80f32d
--- /dev/null
+++ b/test/repositories/checkmodified/mod1.1-1.0-after.jar
@@ -0,0 +1 @@
+after
\ No newline at end of file
diff --git a/test/repositories/checkmodified/mod1.1-1.0-before.jar b/test/repositories/checkmodified/mod1.1-1.0-before.jar
new file mode 100644
index 00000000..ee2363a4
--- /dev/null
+++ b/test/repositories/checkmodified/mod1.1-1.0-before.jar
@@ -0,0 +1 @@
+before
\ No newline at end of file