You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@ant.apache.org by ma...@apache.org on 2018/09/16 21:45:47 UTC
ant-ivy git commit: NEW: The buildlist task can now have `root` and
`leaf` subelements to specify the organisation (and other attributes) of the
root and leaf modules
Repository: ant-ivy
Updated Branches:
refs/heads/master 0712acabd -> b3f7c8596
NEW: The buildlist task can now have `root` and `leaf` subelements to specify the organisation (and other attributes) of the root and leaf modules
Project: http://git-wip-us.apache.org/repos/asf/ant-ivy/repo
Commit: http://git-wip-us.apache.org/repos/asf/ant-ivy/commit/b3f7c859
Tree: http://git-wip-us.apache.org/repos/asf/ant-ivy/tree/b3f7c859
Diff: http://git-wip-us.apache.org/repos/asf/ant-ivy/diff/b3f7c859
Branch: refs/heads/master
Commit: b3f7c8596957c87934f7d90e5e5cb94877df7d1a
Parents: 0712aca
Author: Maarten Coene <ma...@apache.org>
Authored: Sun Sep 16 23:43:30 2018 +0200
Committer: Maarten Coene <ma...@apache.org>
Committed: Sun Sep 16 23:43:30 2018 +0200
----------------------------------------------------------------------
asciidoc/release-notes.adoc | 1 +
asciidoc/use/buildlist.adoc | 51 ++++-
src/java/org/apache/ivy/ant/IvyBuildList.java | 217 ++++++++++++++++-----
3 files changed, 217 insertions(+), 52 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/ant-ivy/blob/b3f7c859/asciidoc/release-notes.adoc
----------------------------------------------------------------------
diff --git a/asciidoc/release-notes.adoc b/asciidoc/release-notes.adoc
index efa7057..dbae920 100644
--- a/asciidoc/release-notes.adoc
+++ b/asciidoc/release-notes.adoc
@@ -101,6 +101,7 @@ For details about the following changes, check our JIRA install at link:https://
- NEW: Add ivy.maven.lookup.sources and ivy.maven.lookup.javadoc variables to control the lookup of the additional artifacts. Defaults to true, for backward compatibility (jira:IVY-1529[])
- NEW: Add (conditional) support for SHA-256, SHA-512 and SHA-384 checksum algorithms (jira:IVY-1554[]) (Thanks to Jaikiran Pai)
- NEW: The standalone Ivy jar can now be used to generate a pom file for the resolved module, using the `makepom` option (Thanks to link:https://github.com/aanno[Thomas Pasch])
+- NEW: The buildlist task can now have `root` and `leaf` subelements to specify the organisation (and other attributes) of the root and leaf modules (jira:/IVY-1242[]) and (jira:IVY-1293[])
////
http://git-wip-us.apache.org/repos/asf/ant-ivy/blob/b3f7c859/asciidoc/use/buildlist.adoc
----------------------------------------------------------------------
diff --git a/asciidoc/use/buildlist.adoc b/asciidoc/use/buildlist.adoc
index 4d827eb..120757e 100644
--- a/asciidoc/use/buildlist.adoc
+++ b/asciidoc/use/buildlist.adoc
@@ -32,9 +32,9 @@ When the `ivy.xml` of the modules that you want to order contains link:../ivyfil
(*__since 1.4__*) The `ivy.sorted.modules` property is set in Ant project at the end of the task with a comma separated list of ordered modules. This can be useful for debug or information purpose.
-[*__since 2.0__*]
+(*__since 2.0__*) The `root` and `leaf` attributes can be a delimited list of modules to use as roots. These modules, and all their dependencies will be included in the build list.
-The `root` and `leaf` attributes can be a delimited list of modules to use as roots. These modules, and all their dependencies will be included in the build list.
+(*__since 2.5__*) The root and leaf modules can also be specified as nested `root` and `leaf` elements. This way, not only the module name can be specified, but also the organisation, revision and branch of the root/leaf.
By default, all the modules included in a circular dependency are grouped together so that any dependency of any module in the loop will appear before the modules in the loop. This guarantees that if there is a dependency path between a module A and a module B (but no dependency path from B to A), B will always appear before A even if A is included in a loop in the provided set of modules to sort.
Note that a circular dependency can also trigger a failure depending on the value configured in the `circularDependencyStrategy` of your link:../settings/conf{outfilesuffix}#circularDependencyStrategy[settings]
@@ -76,6 +76,29 @@ This field is ignored when neither root nor leaf is filled.|No. Defaults to no `
|settingsRef|(*__since 2.0__*) A reference to Ivy settings that must be used by this task|No, `ivy.instance` is taken by default.
|=======
+== Child elements
+
+[options="header",cols="15%,50%,35%"]
+|=======
+|Element|Description|Cardinality
+|root|(*__since 2.5__*) Declares a root module.
+
+This element takes the following attributes: +
+* `organisation`: the organisation of the root module (defaults to *) +
+* `module`: the name of the root module (defaults to *) +
+* `revision`: the revision of the root module (defaults to *) +
+* `branch`: the branch of the root module (default to *)
+* `file`: a specific ivy.xml file to use as root module|0..n
+|leaf|(*__since 2.5__*) Declares a leaf module.
+
+This element takes the following attributes: +
+* `organisation`: the organisation of the leaf module (defaults to *) +
+* `module`: the name of the leaf module (defaults to *) +
+* `revision`: the revision of the leaf module (defaults to *) +
+* `branch`: the branch of the leaf module (default to *)
+* `file`: a specific ivy.xml file to use as leaf module|0..n
+|=======
+
== Parameters specified as nested elements
=== fileset
@@ -132,3 +155,27 @@ Builds a list of `build.xml` files sorted according to the `ivy.xml` files found
----
Builds a list of `build.xml` files sorted according to the `ivy.xml` files found in an Ivy directory relative to those build files. Only `build.xml` files of modules which have dependencies (direct or transitive) on `mymodule` are put in the result list.
+
+'''
+
+[source,xml]
+----
+ <ivy:buildlist reference="build-path" ivyfilepath="ivy/ivy.xml">
+ <root organisation="myorg" module="myapp" />
+ <fileset dir="projects" includes="**/build.xml"/>
+ </ivy:buildlist>
+----
+
+Builds a list of `build.xml` files sorted according to the `ivy.xml` files found in an Ivy directory relative to those build files. Only `build.xml` files of modules which are dependencies of `myorg#myapp` (either direct or transitive) are put in the result list.
+
+'''
+
+[source,xml]
+----
+ <ivy:buildlist reference="build-path" ivyfilepath="ivy/ivy.xml">
+ <root file="/path/to/myapp-ivy.xml" />
+ <fileset dir="projects" includes="**/build.xml"/>
+ </ivy:buildlist>
+----
+
+Builds a list of `build.xml` files sorted according to the `ivy.xml` files found in an Ivy directory relative to those build files. Only `build.xml` files of modules which are dependencies defined in `/path/to/myapp-ivy.xml` (either direct or transitive) are put in the result list.
http://git-wip-us.apache.org/repos/asf/ant-ivy/blob/b3f7c859/src/java/org/apache/ivy/ant/IvyBuildList.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/ivy/ant/IvyBuildList.java b/src/java/org/apache/ivy/ant/IvyBuildList.java
index 8340065..87c7054 100644
--- a/src/java/org/apache/ivy/ant/IvyBuildList.java
+++ b/src/java/org/apache/ivy/ant/IvyBuildList.java
@@ -30,11 +30,14 @@ import java.util.Set;
import java.util.StringTokenizer;
import org.apache.ivy.Ivy;
+import org.apache.ivy.core.IvyPatternHelper;
import org.apache.ivy.core.module.descriptor.DependencyDescriptor;
import org.apache.ivy.core.module.descriptor.ModuleDescriptor;
import org.apache.ivy.core.module.id.ModuleId;
import org.apache.ivy.core.settings.IvySettings;
import org.apache.ivy.core.sort.SortOptions;
+import org.apache.ivy.plugins.matcher.MapMatcher;
+import org.apache.ivy.plugins.matcher.PatternMatcher;
import org.apache.ivy.plugins.parser.ModuleDescriptorParserRegistry;
import org.apache.ivy.util.Message;
import org.apache.tools.ant.BuildException;
@@ -62,6 +65,60 @@ public class IvyBuildList extends IvyTask {
}
}
+ public static final class BuildListModule {
+
+ private String organisation;
+
+ private String module;
+
+ private String revision;
+
+ private String branch;
+
+ private File file;
+
+ public String getOrganisation() {
+ return organisation;
+ }
+
+ public void setOrganisation(String organisation) {
+ this.organisation = organisation;
+ }
+
+ public String getModule() {
+ return module;
+ }
+
+ public void setModule(String module) {
+ this.module = module;
+ }
+
+ public String getRevision() {
+ return revision;
+ }
+
+ public void setRevision(String revision) {
+ this.revision = revision;
+ }
+
+ public String getBranch() {
+ return branch;
+ }
+
+ public void setBranch(String branch) {
+ this.branch = branch;
+ }
+
+ public File getFile() {
+ return file;
+ }
+
+ public void setFile(File file) {
+ this.file = file;
+ }
+
+ }
+
public static final String DESCRIPTOR_REQUIRED = "required";
private List<FileSet> buildFileSets = new ArrayList<>();
@@ -78,10 +135,14 @@ public class IvyBuildList extends IvyTask {
private String root = "*";
+ private List<BuildListModule> roots = new ArrayList<>();
+
private boolean excludeRoot = false;
private String leaf = "*";
+ private List<BuildListModule> leafs = new ArrayList<>();
+
private String delimiter = ",";
private boolean excludeLeaf = false;
@@ -110,6 +171,12 @@ public class IvyBuildList extends IvyTask {
this.root = root;
}
+ public BuildListModule createRoot() {
+ BuildListModule root = new BuildListModule();
+ roots.add(root);
+ return root;
+ }
+
public boolean isExcludeRoot() {
return excludeRoot;
}
@@ -126,6 +193,12 @@ public class IvyBuildList extends IvyTask {
this.leaf = leaf;
}
+ public BuildListModule createLeaf() {
+ BuildListModule leaf = new BuildListModule();
+ leafs.add(leaf);
+ return leaf;
+ }
+
public boolean isExcludeLeaf() {
return excludeLeaf;
}
@@ -172,28 +245,9 @@ public class IvyBuildList extends IvyTask {
List<File> noDescriptor = new ArrayList<>();
Collection<ModuleDescriptor> mds = new ArrayList<>();
- Set<String> rootModuleNames = new LinkedHashSet<>();
- if (!"*".equals(root)) {
- StringTokenizer st = new StringTokenizer(root, delimiter);
- while (st.hasMoreTokens()) {
- rootModuleNames.add(st.nextToken());
- }
- }
-
- Set<String> leafModuleNames = new LinkedHashSet<>();
- if (!"*".equals(leaf)) {
- StringTokenizer st = new StringTokenizer(leaf, delimiter);
- while (st.hasMoreTokens()) {
- leafModuleNames.add(st.nextToken());
- }
- }
-
- Set<String> restartFromModuleNames = new LinkedHashSet<>();
- if (!"*".equals(restartFrom)) {
- StringTokenizer st = new StringTokenizer(restartFrom, delimiter);
- // Only accept one (first) module
- restartFromModuleNames.add(st.nextToken());
- }
+ Set<MapMatcher> rootModules = convert(roots, root, settings);
+ Set<MapMatcher> leafModules = convert(leafs, leaf, settings);
+ Set<MapMatcher> restartFromModules = convert(Collections.<BuildListModule>emptyList(), restartFrom, settings);
for (FileSet fs : buildFileSets) {
DirectoryScanner ds = fs.getDirectoryScanner(getProject());
@@ -225,19 +279,19 @@ public class IvyBuildList extends IvyTask {
}
}
- List<ModuleDescriptor> leafModuleDescriptors = convertModuleNamesToModuleDescriptors(mds,
- leafModuleNames, "leaf");
- List<ModuleDescriptor> rootModuleDescriptors = convertModuleNamesToModuleDescriptors(mds,
- rootModuleNames, "root");
- List<ModuleDescriptor> restartFromModuleDescriptors = convertModuleNamesToModuleDescriptors(
- mds, restartFromModuleNames, "restartFrom");
+ List<ModuleDescriptor> leafModuleDescriptors =
+ findModuleDescriptors(mds, leafModules, "leaf");
+ List<ModuleDescriptor> rootModuleDescriptors =
+ findModuleDescriptors(mds, rootModules, "root");
+ List<ModuleDescriptor> restartFromModuleDescriptors =
+ findModuleDescriptors(mds, restartFromModules, "restartFrom");
if (!rootModuleDescriptors.isEmpty()) {
- Message.info("Filtering modules based on roots " + rootModuleNames);
+ Message.info("Filtering modules based on roots [" + extractModuleNames(rootModules) + "]");
mds = filterModulesFromRoot(mds, rootModuleDescriptors);
}
if (!leafModuleDescriptors.isEmpty()) {
- Message.info("Filtering modules based on leafs " + leafModuleNames);
+ Message.info("Filtering modules based on leafs [" + extractModuleNames(leafModules) + "]");
mds = filterModulesFromLeaf(mds, leafModuleDescriptors);
}
@@ -260,6 +314,7 @@ public class IvyBuildList extends IvyTask {
if (!restartFromModuleDescriptors.isEmpty()) {
boolean foundRestartFrom = false;
List<ModuleDescriptor> keptModules = new ArrayList<>();
+ // Only accept one (first) module
ModuleDescriptor restartFromModuleDescriptor = restartFromModuleDescriptors.get(0);
for (ModuleDescriptor md : sortedModules) {
if (md.equals(restartFromModuleDescriptor)) {
@@ -289,6 +344,54 @@ public class IvyBuildList extends IvyTask {
getProject().setProperty("ivy.sorted.modules", order.toString());
}
+ private Set<MapMatcher> convert(List<BuildListModule> modulesList, String modulesString, IvySettings settings) {
+ Set<MapMatcher> result = new LinkedHashSet<>();
+
+ for (BuildListModule module : modulesList) {
+ File ivyFile = module.getFile();
+ if (ivyFile == null) {
+ String org = module.getOrganisation();
+ String name = module.getModule();
+ String rev = module.getRevision();
+ String branch = module.getBranch();
+
+ Map<String, String> attributes = new HashMap<>();
+ attributes.put(IvyPatternHelper.ORGANISATION_KEY, org == null ? PatternMatcher.ANY_EXPRESSION : org);
+ attributes.put(IvyPatternHelper.MODULE_KEY, name == null ? PatternMatcher.ANY_EXPRESSION : name);
+ attributes.put(IvyPatternHelper.MODULE_KEY, rev == null ? PatternMatcher.ANY_EXPRESSION : rev);
+ attributes.put(IvyPatternHelper.MODULE_KEY, branch == null ? PatternMatcher.ANY_EXPRESSION : branch);
+
+ result.add(new MapMatcher(attributes, settings.getMatcher(PatternMatcher.EXACT)));
+ } else {
+ try {
+ ModuleDescriptor md = ModuleDescriptorParserRegistry.getInstance()
+ .parseDescriptor(settings, ivyFile.toURI().toURL(),
+ doValidate(settings));
+
+ Map<String, String> attributes = new HashMap<>();
+ attributes.putAll(md.getModuleRevisionId().getAttributes());
+ attributes.put("resource", md.getResource().getName());
+
+ result.add(new MapMatcher(attributes, settings.getMatcher(PatternMatcher.EXACT)));
+ } catch (Exception e) {
+ throw new BuildException(e);
+ }
+ }
+ }
+
+ if (!"*".equals(modulesString)) {
+ StringTokenizer st = new StringTokenizer(modulesString, getDelimiter());
+ while (st.hasMoreTokens()) {
+ Map<String, String> attributes = new HashMap<>();
+ attributes.put(IvyPatternHelper.MODULE_KEY, st.nextToken());
+
+ result.add(new MapMatcher(attributes, settings.getMatcher(PatternMatcher.EXACT)));
+ }
+ }
+
+ return result;
+ }
+
private void onMissingDescriptor(File buildFile, File ivyFile, List<File> noDescriptor) {
switch (onMissingDescriptor) {
case OnMissingDescriptor.FAIL:
@@ -312,38 +415,52 @@ public class IvyBuildList extends IvyTask {
}
}
- private List<ModuleDescriptor> convertModuleNamesToModuleDescriptors(
- Collection<ModuleDescriptor> mds, Set<String> moduleNames, String kind) {
+ private List<ModuleDescriptor> findModuleDescriptors(
+ Collection<ModuleDescriptor> mds, Set<MapMatcher> matchers, String kind) {
List<ModuleDescriptor> result = new ArrayList<>();
- Set<String> foundModuleNames = new HashSet<>();
+ Set<MapMatcher> missingMatchers = new HashSet<>(matchers);
for (ModuleDescriptor md : mds) {
- String name = md.getModuleRevisionId().getModuleId().getName();
- if (moduleNames.contains(name)) {
- foundModuleNames.add(name);
- result.add(md);
+ Map<String, String> attributes = new HashMap<>();
+ attributes.putAll(md.getAttributes());
+ attributes.put("resource", md.getResource().getName());
+
+ for (MapMatcher matcher : matchers) {
+ if (matcher.matches(attributes)) {
+ missingMatchers.remove(matcher);
+ result.add(md);
+ }
}
}
- if (foundModuleNames.size() < moduleNames.size()) {
- Set<String> missingModules = new HashSet<>(moduleNames);
- missingModules.removeAll(foundModuleNames);
-
- StringBuilder missingNames = new StringBuilder();
- String sep = "";
- for (String name : missingModules) {
- missingNames.append(sep);
- missingNames.append(name);
- sep = ", ";
- }
-
+ if (!missingMatchers.isEmpty()) {
throw new BuildException("unable to find " + kind + " module(s) "
- + missingNames.toString() + " in build fileset");
+ + extractModuleNames(missingMatchers) + " in build fileset");
}
return result;
}
+ private String extractModuleNames(Set<MapMatcher> matchers) {
+ StringBuilder result = new StringBuilder();
+
+ String sep = "";
+ for (MapMatcher matcher : matchers) {
+ result.append(sep);
+
+ Map<String, String> attributes = matcher.getAttributes();
+ String organisation = attributes.get(IvyPatternHelper.ORGANISATION_KEY);
+ if (organisation != null && !PatternMatcher.ANY_EXPRESSION.equals(organisation)) {
+ result.append(organisation);
+ result.append('#');
+ }
+ result.append(attributes.get(IvyPatternHelper.MODULE_KEY));
+ sep = ", ";
+ }
+
+ return result.toString();
+ }
+
/**
* Returns a collection of ModuleDescriptors that are contained in the input collection of
* ModuleDescriptors and upon which the root module depends