As the implementation of CopySpec has been changed, the behavior has changed in
ways that seem inconsistent to me. Several of these seem to be bugs, but some
may just may reflect a different intention than what I was trying to originally
achieve. I would like some consensus on how it should behave before I try to
correct some of these issues.
For discussion purposes, here is a brief summary of how it originally worked.
CopySpecs can be nested hierarchically. A CopyAction initially had a single
root CopySpec that the Copy task delegated to. The versions of the from and
into methods that took a closure created a child CopySpec and the closure
configured it. Properties of the CopySpec that were collections (like include,
exclude, filter) would inherit values from the parent spec. Scalar properties
(ones with a single value), like into, would override the value of their
parent. Only leaf specs were actually used for a copy. All the CopySpec
methods returned a CopySpec so it could be used in a fluent style.
How it is different now:
1) All CopySpecs in the hierarchy are used in the copy, not just the leaf ones.
The hierarchy was originally intended to allow common properties to be defined
just once, at the top. The following will no longer work:
copy {
exclude('**/*.bak')
from('src1') {
into 'dst1'
}
from('src1') {
into 'dst2'
}
}
The root spec doesn't have a destination. As originally envisioned, non-leaf
specs were just containers to specify common properties, not something to
actually copy.
2) The form of the into method without a closure is now treated specially in
the root spec. FileCopyActionImpl overrides the into method and does not set
the value on the contained CopySpec. This has several implications:
a) Into with a closure now doesn't work at the root level. The following fails
with 'No copy destination specified':
copy {
from 'src'
into('dest') { }
}
The following, does work, however:
copy {
into 'dest'
from('src') { }
}
b) The order of operation now matters for the fluent style:
copy { into('dest').from('src') } // this works
copy { from('src').into('dest') } // this fails with 'No copy destination
specified'
3) Into in a child spec is now interpreted relative to the destination of it's
parent spec. There must be an into with no closure at the root spec.
copy {
into 'dest'
from('src') {
into 'other'
}
}
This copies the contents of src/ to src/other/. Originally, into 'other'
would override the into specified at the root level. Other scalar properties
(like fileMode) override the value in their parent. This use of into no longer
matches the javadoc for the into method (which says it works like
Project.file). Actually, if you give it a file with an absolute path, it
doesn't handle it well.
copy {
into 'dest'
from('src') {
into file 'other'
}
}
For me, the above sample copied to dest/Users/sappling/temp/samples/cpy/other
I like the ability to build up the destination with relative paths in child
specs, but I think the different ways that CopySpec properties interact with a
parent CopySpec may be a little confusing. If you are trying to nest CopySpecs
to build up an output path, then inheriting collection properties like excludes
or filters is probably not what you want. The original intent for the CopySpec
nesting was to share common configuration in an efficient way, not to describe
the structure of the output.
Currently most scalar properties override the value in their parent. Most
collection properties aggregate their value and all their ancestor's values.
The destination (a scalar specified with into) is used to build up a relative
path. Sources (a collection specified with from) do not get any values from a
parent. Is this inconsistency confusing or what you would expect?
Several of the behaviors I have described seemed like real bugs that should be
fixed before 0.9. I'm willing to work on these, but wanted to get some general
agreement on a direction.
Is the original design intent (just use CopySpecs to inherit common properties)
now dead? I assume so.
If nested CopySpecs are used to build up the structure of your output, should
we stop inheriting all the collection properties: includes, exclude, filters
and other actions? Is this inheritance the expected behavior?
If CopySpecs with no into or from delegated to their parent, we might have some
of the original properties sharing capabilities. I don't know if that is
desired or not.
I don't have a real proposal right now, but I wanted to point out that I think
there are some issues that should be addressed before 0.9. I'll try to pull
together a suggestion over the weekend.
--
Steve Appling
Automated Logic Research Team
---------------------------------------------------------------------
To unsubscribe from this list, please visit:
http://xircles.codehaus.org/manage_email