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


Reply via email to