dependency layer refactoring

classic Classic list List threaded Threaded
16 messages Options
Reply | Threaded
Open this post in threaded view
|

dependency layer refactoring

Adam Murdoch-2
Hi,

I'd like to provide some feedback on the changes to DependencyManager,
in particular the changes for mapping configuration <-> task.

I don't think method names such as linkConfWithTask(), getConfs4Task(),
and so on, really convey the meaning of what is being modelled.  There
are 2 types of task - configuration relationships:  One is the
relationship between a configuration and a task that consumes it, the
other is the relationship between a configuration and a task which
*produces* it.  The current method names don't really describe which of
these relationships they refer to. I think it would be nice to model
both types of relationships more explicitly.

There are a number of methods on DependencyManager which take a
configuration name as their first parameter, or return a map indexed by
configuration name. This suggests a missing domain object, which would
represent a configuration and which could be used to configure, query,
resolve and publish the configuration (I'm not referring to ivy's
Configuration object here, though we would end up converting each
configuration to one of these).  I think it would be good to have a
strong domain model for the things which the build produces, not just
how it produces them.


Adam


---------------------------------------------------------------------
To unsubscribe from this list, please visit:

    http://xircles.codehaus.org/manage_email


Reply | Threaded
Open this post in threaded view
|

Re: dependency layer refactoring

hans_d
Administrator
Hi Adam,

On Jul 30, 2008, at 5:17 AM, Adam Murdoch wrote:

> Hi,
>
> I'd like to provide some feedback on the changes to  
> DependencyManager, in particular the changes for mapping  
> configuration <-> task.
>
> I don't think method names such as linkConfWithTask(), getConfs4Task
> (), and so on, really convey the meaning of what is being  
> modelled.  There are 2 types of task - configuration  
> relationships:  One is the relationship between a configuration and  
> a task that consumes it,

Right. Before the last changes a task could only "consume" one  
configuration. No it can consume multiple ones. The compile task for  
a War project for example can now consume the 'compile' and  
'provided' configuration.

> the other is the relationship between a configuration and a task  
> which *produces* it.

I don't see a use case relationship. Any examples?

> The current method names don't really describe which of these  
> relationships they refer to. I think it would be nice to model both  
> types of relationships more explicitly.
>
> There are a number of methods on DependencyManager which take a  
> configuration name as their first parameter, or return a map  
> indexed by configuration name. This suggests a missing domain  
> object, which would represent a configuration and which could be  
> used to configure, query, resolve and publish the configuration  
> (I'm not referring to ivy's Configuration object here, though we  
> would end up converting each configuration to one of these).  I  
> think it would be good to have a strong domain model for the things  
> which the build produces, not just how it produces them.

I completely agree with the objectives. For example the fact that  
there are n:n relationships between tasks and configurations is not  
expressed clearly by the model but just 'implemented' with two maps  
and some methods within another class. Adding a configuration object  
as you have proposed looks like a good idea. I have field a Jira:  
http://jira.codehaus.org/browse/GRADLE-171

One reason why things are as they are, is that the script has been  
driving the model.

I'd love to do continuous peer reviews particularly on domain driven  
design aspects. Unfortunately Codehaus does not offer Atlassians  
Crucible.

- Hans

--
Hans Dockter
Gradle Project lead
http://www.gradle.org





---------------------------------------------------------------------
To unsubscribe from this list, please visit:

    http://xircles.codehaus.org/manage_email


Reply | Threaded
Open this post in threaded view
|

Re: dependency layer refactoring

Adam Murdoch-2


Hans Dockter wrote:
> Hi Adam,
>
> On Jul 30, 2008, at 5:17 AM, Adam Murdoch wrote:
>
>> the other is the relationship between a configuration and a task
>> which *produces* it.
>
> I don't see a use case relationship. Any examples?
>
One example is a project which uses the artifacts of another project in
a multi-project build. Currently we use
DependencyManager.artifactProductionTaskName to model this, which
ProjectDependency uses to add a task dependency from the consuming
project to the producing task of the project. This is fine when all
public configurations of a project are produced by a single task and are
cheap to build. A problem I ran into porting a multi-project ant build
to gradle is that some configurations were very expensive to build and
were not needed by most of the other projects. However, in order to use
any of them in another project, I was forced to build all of them
whether required or not.

I also think some consistency between modelling the consumers of a
configuration and the producers of a configuration would help
understandability.

>
> I'd love to do continuous peer reviews particularly on domain driven
> design aspects. Unfortunately Codehaus does not offer Atlassians
> Crucible.
>

I've not really seen anything other than the 'check it in and let the
other develpers comment on it' approach for open source projects. I
guess it works reasonably well. It's predicated on sufficient developer
bandwidth to review stuff, and probably some upfront discussion on the
mailing list (the why, the what, and the roughly how).


Adam


---------------------------------------------------------------------
To unsubscribe from this list, please visit:

    http://xircles.codehaus.org/manage_email


Reply | Threaded
Open this post in threaded view
|

Re: dependency layer refactoring

hans_d
Administrator

On Jul 30, 2008, at 12:08 PM, Adam Murdoch wrote:

>
>
> Hans Dockter wrote:
>> Hi Adam,
>>
>> On Jul 30, 2008, at 5:17 AM, Adam Murdoch wrote:
>>
>>> the other is the relationship between a configuration and a task  
>>> which *produces* it.
>>
>> I don't see a use case relationship. Any examples?
>>
> One example is a project which uses the artifacts of another  
> project in a multi-project build. Currently we use  
> DependencyManager.artifactProductionTaskName to model this, which  
> ProjectDependency uses to add a task dependency from the consuming  
> project to the producing task of the project. This is fine when all  
> public configurations of a project are produced by a single task  
> and are cheap to build. A problem I ran into porting a multi-
> project ant build to gradle is that some configurations were very  
> expensive to build and were not needed by most of the other  
> projects. However, in order to use any of them in another project,  
> I was forced to build all of them whether required or not.

I'm not sure if I understand the example above correctly. As I  
understand it, 'configuration project dependencies' as described at  
the end of section 14.6 in the UG might help (e.g. new  
ProjectDependency(project(':api'), 'spi')).

>
> I also think some consistency between modelling the consumers of a  
> configuration and the producers of a configuration would help  
> understandability.
>

Configurations in Ivy have two aspects. One is internal for a  
project, like compile, testCompile, etc which are needed for building  
the project. The other aspect is an external one. You use  
configurations to bundle artifacts produced by a project (like 'spi'  
in the example above). When you talk about a producer of  
configurations, is this equivalent to a producer of artifacts?

- Hans

--
Hans Dockter
Gradle Project lead
http://www.gradle.org





---------------------------------------------------------------------
To unsubscribe from this list, please visit:

    http://xircles.codehaus.org/manage_email


Reply | Threaded
Open this post in threaded view
|

Re: dependency layer refactoring

Adam Murdoch-2


Hans Dockter wrote:

>
> On Jul 30, 2008, at 12:08 PM, Adam Murdoch wrote:
>
>>
>>
>> Hans Dockter wrote:
>>> Hi Adam,
>>>
>>> On Jul 30, 2008, at 5:17 AM, Adam Murdoch wrote:
>>>
>>>> the other is the relationship between a configuration and a task
>>>> which *produces* it.
>>>
>>> I don't see a use case relationship. Any examples?
>>>
>> One example is a project which uses the artifacts of another project
>> in a multi-project build. Currently we use
>> DependencyManager.artifactProductionTaskName to model this, which
>> ProjectDependency uses to add a task dependency from the consuming
>> project to the producing task of the project. This is fine when all
>> public configurations of a project are produced by a single task and
>> are cheap to build. A problem I ran into porting a multi-project ant
>> build to gradle is that some configurations were very expensive to
>> build and were not needed by most of the other projects. However, in
>> order to use any of them in another project, I was forced to build
>> all of them whether required or not.
>
> I'm not sure if I understand the example above correctly. As I
> understand it, 'configuration project dependencies' as described at
> the end of section 14.6 in the UG might help (e.g. new
> ProjectDependency(project(':api'), 'spi')).
>
Say I have a multi-project build (not neccessarily using the java
plugin), where each project has 2 tasks: a 'libs' task, which assembles
some jars for the project, and a 'dists' task, which assembles the
project into some kind of distribution. The 'libs' task publishes a
'libs' configuration, and depends on the 'libs' configuration of other
projects. Similarly, the 'dists' task publishes a 'dists' configuration,
and depends on the 'dists' configuration of other projects.  Say that
the 'dists' task is really slow, so that we don't want to execute it if
we're only building the jars for a project.

The ProjectDependency lets me declare that the 'libs' task for a project
depends on the 'libs' config for some other project, and that the
'dists' task depends on the 'dists' config. This is good.  What I can't
do is declare that the 'libs' task publishes the 'libs' config and that
the 'dists' task publishes the 'dists' config.  All I can do is set
DependencyManager.artifactProductionTaskName, which I would have to set
to 'dists' in this case. Which means that when I only want to build the
jars for a project, I have to build the jars and dists for all the
projects which the project depends on, whereas I only really want to
build the jars for the other projects.

Given that we have a way to tell DependencyManager that a given task
uses a given config, it would be good to also tell DependencyManager
that a given task produces a given config.  That is, rename
linkConfWithTask() to something like taskUsesConf(task, conf) and add
something like taskPublishesConf(task, conf)

>>
>> I also think some consistency between modelling the consumers of a
>> configuration and the producers of a configuration would help
>> understandability.
>>
>
> Configurations in Ivy have two aspects. One is internal for a project,
> like compile, testCompile, etc which are needed for building the
> project. The other aspect is an external one. You use configurations
> to bundle artifacts produced by a project (like 'spi' in the example
> above). When you talk about a producer of configurations, is this
> equivalent to a producer of artifacts?
>
Good question. I'm talking about the task which publishes the artifacts
for the configuration.  I guess this isn't strictly the same as the
task(s) that produce the artifacts themselves.


Adam


---------------------------------------------------------------------
To unsubscribe from this list, please visit:

    http://xircles.codehaus.org/manage_email


Reply | Threaded
Open this post in threaded view
|

Re: dependency layer refactoring

hans_d
Administrator
In reply to this post by Adam Murdoch-2
Converted from Rich Text
Hi Adam,
 
this mail is written from my mobile. I hope the formatting is OK.
 
Finally I get your point. I like the idea of a conf producing task. An alternative would be to pass to a project dependency a specific artifactProductionTask. But I prefer your proposal, as it removes the smell of 'inappropriate intimacy' between projects.
Right now we have two use cases for a n:n mapping between conf and tasks. We have a taskUsesConf use case. For example the compile task may use a couple of configurations to get its classpath from. We have also a confIsAssociatedWithTask use case. When we establish a project dependency right now we create a task dependency between the tasks associated with the conf and the artifactProductionTask of the other projects. In fact this use case was the very reason why we have introduced task-conf mappings. Without project dependencies we would not need such a mapping. Instead we could add an additional confs property to the respective tasks (e.g. compile). But as we needed such a mapping anyway I thought it is less redundant to let the tasks use this mapping as well to get its dependencies.
 
To implement your proposal we could modify the confIsAssociatedWithTask behavior. Instead of linking the tasks with an artifactProductionTask we could link the tasks with something like otherProject.dependencies.publishTaskForConf('someconf').
 
Just to point it out. An alternative approach would be not to use the task-conf mapping as described above. Instead we would execute at build execution time the publishTaskForConf when the resolve takes place. The advantage would be that it is easier and more flexible. For example if you say in an init action: dependencies.resolve('compile'). Let's say also the compile conf has a project dependency. The jars of the project dependency wouldn't be available as only the execution of the compile task triggers the generation of the artifacts of the other project. The disadvantage is that the graph of tasks to be executed wouldn't be complete after configuration time.
 
One more point we need to think about. If we do a partial build of project A which has a project dependency on project B. Let's say we execute 'gradle clean libs'. Project A is cleaned before its libs are created, not so project B. Only the publish task is executed. We could declare an additional dependsOn('projectB') in project A. Such a dependsOn establishes task dependencies between tasks with similar names of both projects. Now the clean is done for both projects but also the libs task is executed for project B which would neutralize our effort to become more fine-grained regarding project dependencies artifacts.
 
- Hans
 
____________ Ursprüngliche Mitteilung ____________
Betreff: Re: [gradle-dev] dependency layer refactoring
Autor: "Adam Murdoch" <[hidden email]>
Datum: 3. August 2008 12.27.53
 


Hans Dockter wrote:

>
> On Jul 30, 2008, at 12:08 PM, Adam Murdoch wrote:
>
>>
>>
>> Hans Dockter wrote:
>>> Hi Adam,
>>>
>>> On Jul 30, 2008, at 5:17 AM, Adam Murdoch wrote:
>>>
>>>> the other is the relationship between a configuration and a task
>>>> which *produces* it.
>>>
>>> I don't see a use case relationship. Any examples?
>>>
>> One example is a project which uses the artifacts of another project
>> in a multi-project build. Currently we use
>> DependencyManager.artifactProductionTaskName to model this, which
>> ProjectDependency uses to add a task dependency from the consuming
>> project to the producing task of the project. This is fine when all
>> public configurations of a project are produced by a single task and
>> are cheap to build. A problem I ran into porting a multi-project ant
>> build to gradle is that some configurations were very expensive to
>> build and were not needed by most of the other projects. However, in
>> order to use any of them in another project, I was forced to build
>> all of them whether required or not.
>
> I'm not sure if I understand the example above correctly. As I
> understand it, 'configuration project dependencies' as described at
> the end of section 14.6 in the UG might help (e.g. new
> ProjectDependency(project(':api'), 'spi')).
>
Say I have a multi-project build (not neccessarily using the java
plugin), where each project has 2 tasks: a 'libs' task, which assembles
some jars for the project, and a 'dists' task, which assembles the
project into some kind of distribution. The 'libs' task publishes a
'libs' configuration, and depends on the 'libs' configuration of other
projects. Similarly, the 'dists' task publishes a 'dists' configuration,
and depends on the 'dists' configuration of other projects. Say that
the 'dists' task is really slow, so that we don't want to execute it if
we're only building the jars for a project.

The ProjectDependency lets me declare that the 'libs' task for a project
depends on the 'libs' config for some other project, and that the
'dists' task depends on the 'dists' config. This is good. What I can't
do is declare that the 'libs' task publishes the 'libs' config and that
the 'dists' task publishes the 'dists' config. All I can do is set
DependencyManager.artifactProductionTaskName, which I would have to set
to 'dists' in this case. Which means that when I only want to build the
jars for a project, I have to build the jars and dists for all the
projects which the project depends on, whereas I only really want to
build the jars for the other projects.

Given that we have a way to tell DependencyManager that a given task
uses a given config, it would be good to also tell DependencyManager
that a given task produces a given config. That is, rename
linkConfWithTask() to something like taskUsesConf(task, conf) and add
something like taskPublishesConf(task, conf)

>>
>> I also think some consistency between modelling the consumers of a
>> configuration and the producers of a configuration would help
>> understandability.
>>
>
> Configurations in Ivy have two aspects. One is internal for a project,
> like compile, testCompile, etc which are needed for building the
> project. The other aspect is an external one. You use configurations
> to bundle artifacts produced by a project (like 'spi' in the example
> above). When you talk about a producer of configurations, is this
> equivalent to a producer of artifacts?
>
Good question. I'm talking about the task which publishes the artifacts
for the configuration. I guess this isn't strictly the same as the
task(s) that produce the artifacts themselves.

Adam


---------------------------------------------------------------------
To unsubscribe from this list, please visit:

http://xircles.codehaus.org/manage_email


Reply | Threaded
Open this post in threaded view
|

Re: dependency layer refactoring

hans_d
Administrator
In reply to this post by Adam Murdoch-2
Converted from Rich Text
What about doing things differently?
 
We could introduce a Configuration class which implements Task. One can add dependencies to a configuration. Executing such a task means resolving its dependencies. Such a task would offer also methods to get a path, list of files, etc ... The compile task for example would depends on its configuration task(s). A project dependency would establish a depends relation between the configuration it belongs to and the configuration of the other project. The artifact producing configuration of the other project would depend on the corresponding artifact task(s).
 
This would remove unnecessary elements from our API. It decreases the learning curve and simplifies the design. Last but not least we have finally our Configuration object to express this important domain concept.
 
- Hans
____________ Ursprüngliche Mitteilung ____________
Betreff: Re: [gradle-dev] dependency layer refactoring
Autor: "Hans Dockter" <[hidden email]>
Datum: 5. August 2008 10.56.47
 
Hi Adam,

this mail is written from my mobile. I hope the formatting is OK.

Finally I get your point. I like the idea of a conf producing task. An alternative would be to pass to a project dependency a specific artifactProductionTask. But I prefer your proposal, as it removes the smell of 'inappropriate intimacy' between projects.
Right now we have two use cases for a n:n mapping between conf and tasks. We have a taskUsesConf use case. For example the compile task may use a couple of configurations to get its classpath from. We have also a confIsAssociatedWithTask use case. When we establish a project dependency right now we create a task dependency between the tasks associated with the conf and the artifactProductionTask of the other projects. In fact this use case was the very reason why we have introduced task-conf mappings. Without project dependencies we would not need such a mapping. Instead we could add an additional confs property to the respective tasks (e.g. compile). But as we needed such a mapping anyway I thought it is less redundant to let the tasks use this mapping as well to get its dependencies.

To implement your proposal we could modify the confIsAssociatedWithTask behavior. Instead of linking the tasks with an artifactProductionTask we could link the tasks with something like otherProject.dependencies.publishTaskForConf('someconf').

Just to point it out. An alternative approach would be not to use the task-conf mapping as described above. Instead we would execute at build execution time the publishTaskForConf when the resolve takes place. The advantage would be that it is easier and more flexible. For example if you say in an init action: dependencies.resolve('compile'). Let's say also the compile conf has a project dependency. The jars of the project dependency wouldn't be available as only the execution of the compile task triggers the generation of the artifacts of the other project. The disadvantage is that the graph of tasks to be executed wouldn't be complete after configuration time.

One more point we need to think about. If we do a partial build of project A which has a project dependency on project B. Let's say we execute 'gradle clean libs'. Project A is cleaned before its libs are created, not so project B. Only the publish task is executed. We could declare an additional dependsOn('projectB') in project A. Such a dependsOn establishes task dependencies between tasks with similar names of both projects. Now the clean is done for both projects but also the libs task is executed for project B which would neutralize our effort to become more fine-grained regarding project dependencies artifacts.

- Hans

____________ Ursprüngliche Mitteilung ____________
Betreff: Re: [gradle-dev] dependency layer refactoring
Autor: "Adam Murdoch" <[hidden email]>
Datum: 3. August 2008 12.27.53


Hans Dockter wrote:

>
> On Jul 30, 2008, at 12:08 PM, Adam Murdoch wrote:
>
>>
>>
>> Hans Dockter wrote:
>>> Hi Adam,
>>>
>>> On Jul 30, 2008, at 5:17 AM, Adam Murdoch wrote:
>>>
>>>> the other is the relationship between a configuration and a task
>>>> which *produces* it.
>>>
>>> I don't see a use case relationship. Any examples?
>>>
>> One example is a project which uses the artifacts of another project
>> in a multi-project build. Currently we use
>> DependencyManager.artifactProductionTaskName to model this, which
>> ProjectDependency uses to add a task dependency from the consuming
>> project to the producing task of the project. This is fine when all
>> public configurations of a project are produced by a single task and
>> are cheap to build. A problem I ran into porting a multi-project ant
>> build to gradle is that some configurations were very expensive to
>> build and were not needed by most of the other projects. However, in
>> order to use any of them in another project, I was forced to build
>> all of them whether required or not.
>
> I'm not sure if I understand the example above correctly. As I
> understand it, 'configuration project dependencies' as described at
> the end of section 14.6 in the UG might help (e.g. new
> ProjectDependency(project(':api'), 'spi')).
>
Say I have a multi-project build (not neccessarily using the java
plugin), where each project has 2 tasks: a 'libs' task, which assembles
some jars for the project, and a 'dists' task, which assembles the
project into some kind of distribution. The 'libs' task publishes a
'libs' configuration, and depends on the 'libs' configuration of other
projects. Similarly, the 'dists' task publishes a 'dists' configuration,
and depends on the 'dists' configuration of other projects. Say that
the 'dists' task is really slow, so that we don't want to execute it if
we're only building the jars for a project.

The ProjectDependency lets me declare that the 'libs' task for a project
depends on the 'libs' config for some other project, and that the
'dists' task depends on the 'dists' config. This is good. What I can't
do is declare that the 'libs' task publishes the 'libs' config and that
the 'dists' task publishes the 'dists' config. All I can do is set
DependencyManager.artifactProductionTaskName, which I would have to set
to 'dists' in this case. Which means that when I only want to build the
jars for a project, I have to build the jars and dists for all the
projects which the project depends on, whereas I only really want to
build the jars for the other projects.

Given that we have a way to tell DependencyManager that a given task
uses a given config, it would be good to also tell DependencyManager
that a given task produces a given config. That is, rename
linkConfWithTask() to something like taskUsesConf(task, conf) and add
something like taskPublishesConf(task, conf)

>>
>> I also think some consistency between modelling the consumers of a
>> configuration and the producers of a configuration would help
>> understandability.
>>
>
> Configurations in Ivy have two aspects. One is internal for a project,
> like compile, testCompile, etc which are needed for building the
> project. The other aspect is an external one. You use configurations
> to bundle artifacts produced by a project (like 'spi' in the example
> above). When you talk about a producer of configurations, is this
> equivalent to a producer of artifacts?
>
Good question. I'm talking about the task which publishes the artifacts
for the configuration. I guess this isn't strictly the same as the
task(s) that produce the artifacts themselves.

Adam


---------------------------------------------------------------------
To unsubscribe from this list, please visit:

http://xircles.codehaus.org/manage_email

Reply | Threaded
Open this post in threaded view
|

Re: dependency layer refactoring

Adam Murdoch-2


Hans Dockter wrote:
Converted from Rich Text
What about doing things differently?
 
We could introduce a Configuration class which implements Task. One can add dependencies to a configuration. Executing such a task means resolving its dependencies. Such a task would offer also methods to get a path, list of files, etc ... The compile task for example would depends on its configuration task(s). A project dependency would establish a depends relation between the configuration it belongs to and the configuration of the other project. The artifact producing configuration of the other project would depend on the corresponding artifact task(s).
 
This would remove unnecessary elements from our API. It decreases the learning curve and simplifies the design. Last but not least we have finally our Configuration object to express this important domain concept.

I think this is an excellent idea. We already do something similar (conceptually) for bundles: A task is added to the project for each bundle produced by the project, and I can ask that a bundle be built from the command-line, add dependencies on it, query it for its location, etc. We could probably come up with a common approach for configurations and bundles.  This approach would extend nicely to other types of artifacts a build could produce (eg reports, releases, etc) and maybe even more generally into other types of build domain concepts, such as app servers (eg I need this app server to be running in order to deploy to it).

I'm not sure if Configuration should implement Task, or whether adding a Configuration would trigger the adding of a Task that resolves it.  The problem with implementing Task is that there are (at least) 2 interpretations of 'executing' a configuration: resolving it, and producing/publishing it. By adding a task instead, we have the option of adding both a resolve task and a publish task for a configuration. I guess another option would be to have 2 types of Configuration: one for incoming dependencies and one for produced artifacts.


Adam

--------------------------------------------------------------------- To unsubscribe from this list, please visit: http://xircles.codehaus.org/manage_email
Reply | Threaded
Open this post in threaded view
|

Re: dependency layer refactoring

hans_d
Administrator

On Aug 6, 2008, at 12:12 PM, Adam Murdoch wrote:

>
>
> Hans Dockter wrote:
>>
>> What about doing things differently?
>>
>> We could introduce a Configuration class which implements Task.  
>> One can add dependencies to a configuration. Executing such a task  
>> means resolving its dependencies. Such a task would offer also  
>> methods to get a path, list of files, etc ... The compile task for  
>> example would depends on its configuration task(s). A project  
>> dependency would establish a depends relation between the  
>> configuration it belongs to and the configuration of the other  
>> project. The artifact producing configuration of the other project  
>> would depend on the corresponding artifact task(s).
>>
>> This would remove unnecessary elements from our API. It decreases  
>> the learning curve and simplifies the design. Last but not least  
>> we have finally our Configuration object to express this important  
>> domain concept.
>
> I think this is an excellent idea. We already do something similar  
> (conceptually) for bundles: A task is added to the project for each  
> bundle produced by the project, and I can ask that a bundle be  
> built from the command-line, add dependencies on it, query it for  
> its location, etc. We could probably come up with a common approach  
> for configurations and bundles.

A bundle is a task and at the same time a container for archive tasks  
on which it depends. Your analogy is that a configuration is a  
container for dependencies, right? But the dependencies are no tasks  
yet and I'm not sure if it makes sense to transform them into tasks.

> This approach would extend nicely to other types of artifacts a  
> build could produce (eg reports, releases, etc) and maybe even more  
> generally into other types of build domain concepts, such as app  
> servers (eg I need this app server to be running in order to deploy  
> to it).

We might create an abstraction for such a task container.

>
>
> I'm not sure if Configuration should implement Task, or whether  
> adding a Configuration would trigger the adding of a Task that  
> resolves it.  The problem with implementing Task is that there are  
> (at least) 2 interpretations of 'executing' a configuration:  
> resolving it, and producing/publishing it. By adding a task  
> instead, we have the option of adding both a resolve task and a  
> publish task for a configuration. I guess another option would be  
> to have 2 types of Configuration: one for incoming dependencies and  
> one for produced artifacts.
>

In Ivy itself all configurations are equals. They may contain only  
external dependencies or only artifacts produced by the project or  
both (e.g. a configuration that exposes the artifacts of a projects  
plus its external dependencies). I'm not sure if Ivy misses to model  
an important concept.

Our configurations could take the same approach as Ivy. The fact that  
a configuration contains artifacts to be produced by the project can  
be expressed by the fact that this configuration depends on the  
respective archive task. A resolve could be simply defined by calling  
an Ivy resolve for the underlying Ivy ocnfiguration.

- Hans

--
Hans Dockter
Gradle Project lead
http://www.gradle.org





---------------------------------------------------------------------
To unsubscribe from this list, please visit:

    http://xircles.codehaus.org/manage_email


Reply | Threaded
Open this post in threaded view
|

Re: dependency layer refactoring

Adam Murdoch-2


Hans Dockter wrote:

>
> On Aug 6, 2008, at 12:12 PM, Adam Murdoch wrote:
>
>>
>>
>> Hans Dockter wrote:
>>>
>>> What about doing things differently?
>>>
>>> We could introduce a Configuration class which implements Task. One
>>> can add dependencies to a configuration. Executing such a task means
>>> resolving its dependencies. Such a task would offer also methods to
>>> get a path, list of files, etc ... The compile task for example
>>> would depends on its configuration task(s). A project dependency
>>> would establish a depends relation between the configuration it
>>> belongs to and the configuration of the other project. The artifact
>>> producing configuration of the other project would depend on the
>>> corresponding artifact task(s).
>>>
>>> This would remove unnecessary elements from our API. It decreases
>>> the learning curve and simplifies the design. Last but not least we
>>> have finally our Configuration object to express this important
>>> domain concept.
>>
>> I think this is an excellent idea. We already do something similar
>> (conceptually) for bundles: A task is added to the project for each
>> bundle produced by the project, and I can ask that a bundle be built
>> from the command-line, add dependencies on it, query it for its
>> location, etc. We could probably come up with a common approach for
>> configurations and bundles.
>
> A bundle is a task and at the same time a container for archive tasks
> on which it depends. Your analogy is that a configuration is a
> container for dependencies, right?
Sorry, I meant to say archives instead of bundles, ie we do something
similar for archives (make them available as tasks which other tasks can
depend on).  Hopefully that makes more sense.

>>
>>
>> I'm not sure if Configuration should implement Task, or whether
>> adding a Configuration would trigger the adding of a Task that
>> resolves it.  The problem with implementing Task is that there are
>> (at least) 2 interpretations of 'executing' a configuration:
>> resolving it, and producing/publishing it. By adding a task instead,
>> we have the option of adding both a resolve task and a publish task
>> for a configuration. I guess another option would be to have 2 types
>> of Configuration: one for incoming dependencies and one for produced
>> artifacts.
>>
>
> In Ivy itself all configurations are equals. They may contain only
> external dependencies or only artifacts produced by the project or
> both (e.g. a configuration that exposes the artifacts of a projects
> plus its external dependencies). I'm not sure if Ivy misses to model
> an important concept.
>
> Our configurations could take the same approach as Ivy. The fact that
> a configuration contains artifacts to be produced by the project can
> be expressed by the fact that this configuration depends on the
> respective archive task. A resolve could be simply defined by calling
> an Ivy resolve for the underlying Ivy ocnfiguration.
>
This makes sense. So, for example, if I have a project that produces an
artifact and includes it in a configuration, I add an Archive (task) to
produce the artifact, then add a Configuration (task) with a dependency
on the archive task. Adding this dependency declares that the archive is
a publication included in the configuration.

If I want to use the configuration in my project, I add another task
with a dependency on the configuration task.  Adding this dependency
declares that the task uses the configuration. Before my task is
executes, the archive is built, the configuration is resolved, and my
task can query the Configuration object for the files that make up the
configuration.

If I want to include artifacts from another project, I can add a
dependency from the configuration task to a configuration task in the
other project. I can add more artifacts to the configuration by adding
more dependencies on archive tasks (or any file producing task, really).
I can add external dependencies (log4j, say) by adding them directly to
the configuration task.

Where do you think publishing would happen in all this?


Adam


---------------------------------------------------------------------
To unsubscribe from this list, please visit:

    http://xircles.codehaus.org/manage_email


Reply | Threaded
Open this post in threaded view
|

Re: dependency layer refactoring

hans_d
Administrator

On Aug 7, 2008, at 1:22 PM, Adam Murdoch wrote:

>
>
> Hans Dockter wrote:
>>
>> On Aug 6, 2008, at 12:12 PM, Adam Murdoch wrote:
>>
>>>
>>>
>>> Hans Dockter wrote:
>>>>
>>>> What about doing things differently?
>>>>
>>>> We could introduce a Configuration class which implements Task.  
>>>> One can add dependencies to a configuration. Executing such a  
>>>> task means resolving its dependencies. Such a task would offer  
>>>> also methods to get a path, list of files, etc ... The compile  
>>>> task for example would depends on its configuration task(s). A  
>>>> project dependency would establish a depends relation between  
>>>> the configuration it belongs to and the configuration of the  
>>>> other project. The artifact producing configuration of the other  
>>>> project would depend on the corresponding artifact task(s).
>>>>
>>>> This would remove unnecessary elements from our API. It  
>>>> decreases the learning curve and simplifies the design. Last but  
>>>> not least we have finally our Configuration object to express  
>>>> this important domain concept.
>>>
>>> I think this is an excellent idea. We already do something  
>>> similar (conceptually) for bundles: A task is added to the  
>>> project for each bundle produced by the project, and I can ask  
>>> that a bundle be built from the command-line, add dependencies on  
>>> it, query it for its location, etc. We could probably come up  
>>> with a common approach for configurations and bundles.
>>
>> A bundle is a task and at the same time a container for archive  
>> tasks on which it depends. Your analogy is that a configuration is  
>> a container for dependencies, right?
> Sorry, I meant to say archives instead of bundles, ie we do  
> something similar for archives (make them available as tasks which  
> other tasks can depend on).  Hopefully that makes more sense.
>
>>>
>>>
>>> I'm not sure if Configuration should implement Task, or whether  
>>> adding a Configuration would trigger the adding of a Task that  
>>> resolves it.  The problem with implementing Task is that there  
>>> are (at least) 2 interpretations of 'executing' a configuration:  
>>> resolving it, and producing/publishing it. By adding a task  
>>> instead, we have the option of adding both a resolve task and a  
>>> publish task for a configuration. I guess another option would be  
>>> to have 2 types of Configuration: one for incoming dependencies  
>>> and one for produced artifacts.
>>>
>>
>> In Ivy itself all configurations are equals. They may contain only  
>> external dependencies or only artifacts produced by the project or  
>> both (e.g. a configuration that exposes the artifacts of a  
>> projects plus its external dependencies). I'm not sure if Ivy  
>> misses to model an important concept.
>>
>> Our configurations could take the same approach as Ivy. The fact  
>> that a configuration contains artifacts to be produced by the  
>> project can be expressed by the fact that this configuration  
>> depends on the respective archive task. A resolve could be simply  
>> defined by calling an Ivy resolve for the underlying Ivy  
>> ocnfiguration.
>>
> This makes sense. So, for example, if I have a project that  
> produces an artifact and includes it in a configuration, I add an  
> Archive (task) to produce the artifact, then add a Configuration  
> (task) with a dependency on the archive task. Adding this  
> dependency declares that the archive is a publication included in  
> the configuration.
>
> If I want to use the configuration in my project, I add another  
> task with a dependency on the configuration task.  Adding this  
> dependency declares that the task uses the configuration. Before my  
> task is executes, the archive is built, the configuration is  
> resolved, and my task can query the Configuration object for the  
> files that make up the configuration.
>
> If I want to include artifacts from another project, I can add a  
> dependency from the configuration task to a configuration task in  
> the other project.

Right. With the current design we would use an intermediary for doing  
this. A project dependency would establish the dependency between the  
two configurations of the respective projects. The project dependency  
has the additional job to translate this dependency into ivy language.

> I can add more artifacts to the configuration by adding more  
> dependencies on archive tasks (or any file producing task, really).  
> I can add external dependencies (log4j, say) by adding them  
> directly to the configuration task.
>
> Where do you think publishing would happen in all this?

Publishing in the sense of adding an artifact to a repository happens  
in the uploadLibs and uploadDists tasks. I'm not sure if it was a  
good idea to introduce a new term 'upload' for this instead of using  
the term 'publish'.

The remaining open issue is how to deal with cleaning. Building a  
dependency without cleaning is not that reliable.  This is a  
(modified) quote from one of my earlier emails:

> One more point we need to think about. If we do a partial build of  
> project A which has a project dependency on project B. Let's say we  
> execute 'gradle clean libs'. Project A is cleaned before its libs  
> are created, not so project B. Only the artifact producing task is  
> executed. We could declare an additional dependsOn('projectB') in  
> project A. Such a dependsOn establishes task dependencies between  
> tasks with similar names of both projects. Now the clean is done  
> for both projects but also the libs task is executed for project B  
> which would neutralize our effort to become more fine-grained  
> regarding project dependencies artifacts.


- Hans

--
Hans Dockter
Gradle Project lead
http://www.gradle.org





---------------------------------------------------------------------
To unsubscribe from this list, please visit:

    http://xircles.codehaus.org/manage_email


Reply | Threaded
Open this post in threaded view
|

Re: dependency layer refactoring

Adam Murdoch-2


Hans Dockter wrote:

>
> On Aug 7, 2008, at 1:22 PM, Adam Murdoch wrote:
>
>>
>>
>> Hans Dockter wrote:
>>>
>>> On Aug 6, 2008, at 12:12 PM, Adam Murdoch wrote:
>>>
>>>>
>>>>
>>>> Hans Dockter wrote:
>>>>>
>>>>> What about doing things differently?
>>>>>
>>>>> We could introduce a Configuration class which implements Task.
>>>>> One can add dependencies to a configuration. Executing such a task
>>>>> means resolving its dependencies. Such a task would offer also
>>>>> methods to get a path, list of files, etc ... The compile task for
>>>>> example would depends on its configuration task(s). A project
>>>>> dependency would establish a depends relation between the
>>>>> configuration it belongs to and the configuration of the other
>>>>> project. The artifact producing configuration of the other project
>>>>> would depend on the corresponding artifact task(s).
>>>>>
>>>>> This would remove unnecessary elements from our API. It decreases
>>>>> the learning curve and simplifies the design. Last but not least
>>>>> we have finally our Configuration object to express this important
>>>>> domain concept.
>>>>
>>>> I think this is an excellent idea. We already do something similar
>>>> (conceptually) for bundles: A task is added to the project for each
>>>> bundle produced by the project, and I can ask that a bundle be
>>>> built from the command-line, add dependencies on it, query it for
>>>> its location, etc. We could probably come up with a common approach
>>>> for configurations and bundles.
>>>
>>> A bundle is a task and at the same time a container for archive
>>> tasks on which it depends. Your analogy is that a configuration is a
>>> container for dependencies, right?
>> Sorry, I meant to say archives instead of bundles, ie we do something
>> similar for archives (make them available as tasks which other tasks
>> can depend on).  Hopefully that makes more sense.
>>
>>>>
>>>>
>>>> I'm not sure if Configuration should implement Task, or whether
>>>> adding a Configuration would trigger the adding of a Task that
>>>> resolves it.  The problem with implementing Task is that there are
>>>> (at least) 2 interpretations of 'executing' a configuration:
>>>> resolving it, and producing/publishing it. By adding a task
>>>> instead, we have the option of adding both a resolve task and a
>>>> publish task for a configuration. I guess another option would be
>>>> to have 2 types of Configuration: one for incoming dependencies and
>>>> one for produced artifacts.
>>>>
>>>
>>> In Ivy itself all configurations are equals. They may contain only
>>> external dependencies or only artifacts produced by the project or
>>> both (e.g. a configuration that exposes the artifacts of a projects
>>> plus its external dependencies). I'm not sure if Ivy misses to model
>>> an important concept.
>>>
>>> Our configurations could take the same approach as Ivy. The fact
>>> that a configuration contains artifacts to be produced by the
>>> project can be expressed by the fact that this configuration depends
>>> on the respective archive task. A resolve could be simply defined by
>>> calling an Ivy resolve for the underlying Ivy ocnfiguration.
>>>
>> This makes sense. So, for example, if I have a project that produces
>> an artifact and includes it in a configuration, I add an Archive
>> (task) to produce the artifact, then add a Configuration (task) with
>> a dependency on the archive task. Adding this dependency declares
>> that the archive is a publication included in the configuration.
>>
>> If I want to use the configuration in my project, I add another task
>> with a dependency on the configuration task.  Adding this dependency
>> declares that the task uses the configuration. Before my task is
>> executes, the archive is built, the configuration is resolved, and my
>> task can query the Configuration object for the files that make up
>> the configuration.
>>
>> If I want to include artifacts from another project, I can add a
>> dependency from the configuration task to a configuration task in the
>> other project.
>
> Right. With the current design we would use an intermediary for doing
> this. A project dependency would establish the dependency between the
> two configurations of the respective projects. The project dependency
> has the additional job to translate this dependency into ivy language.
>
>> I can add more artifacts to the configuration by adding more
>> dependencies on archive tasks (or any file producing task, really). I
>> can add external dependencies (log4j, say) by adding them directly to
>> the configuration task.
>>
>> Where do you think publishing would happen in all this?
>
> Publishing in the sense of adding an artifact to a repository happens
> in the uploadLibs and uploadDists tasks.
I'm interested in how this happens generically, so assume I'm not using
the java plugin. In my example above, then, I would add an upload task
which depends on the configuration it uploads.  Adding the dependency
declares that the upload task publishes the config to a repository. So,
the dependency graph ends up like: upload -> config -> archive. The
upload task could potentially be automatically added when the
configuration is added to the project.

If I want to use the config from another project in the same
multi-project build, I really want to depend on the config rather than
the upload task (ie I want to depend on the thing I use, rather than the
step that happens to produce it). So, then ideally I have a dependency
graph like a:task -> a:config -> b:config -> b:archive.  Would we do an
implicit publish when b:config is executed, or would a:config reach in
to project b and resolve the archive from there?

> I'm not sure if it was a good idea to introduce a new term 'upload'
> for this instead of using the term 'publish'.
>
> The remaining open issue is how to deal with cleaning. Building a
> dependency without cleaning is not that reliable.  This is a
> (modified) quote from one of my earlier emails:
>> One more point we need to think about. If we do a partial build of
>> project A which has a project dependency on project B. Let's say we
>> execute 'gradle clean libs'. Project A is cleaned before its libs are
>> created, not so project B. Only the artifact producing task is
>> executed. We could declare an additional dependsOn('projectB') in
>> project A. Such a dependsOn establishes task dependencies between
>> tasks with similar names of both projects. Now the clean is done for
>> both projects but also the libs task is executed for project B which
>> would neutralize our effort to become more fine-grained regarding
>> project dependencies artifacts.
Not sure yet.  When you execute 'gradle clean libs', you're really
saying 'rebuild the libs and its dependencies', so I think a good
solution is going to allow me to 1. ask gradle to do this from the
command-line, and 2. declare in the build scripts how to do this.

Given that cleaning and rebuilding are concepts that pretty much every
build has, it is tempting to bake this concept into the build tool's
domain model. Something like (I haven't thought this through, its just
an example), a project can declare which task should be run before doing
a rebuild of its artifacts (eg a Clean task). Then, using the
configuration dependencies, gradle can decorate the dependency graph to
add in the clean tasks if a rebuild is being done.


Adam


---------------------------------------------------------------------
To unsubscribe from this list, please visit:

    http://xircles.codehaus.org/manage_email


Reply | Threaded
Open this post in threaded view
|

Re: dependency layer refactoring

hans_d
Administrator
Hi Adam,

I gonna respond to this when I'm back next week.

- Hans

On Aug 9, 2008, at 12:20 PM, Adam Murdoch wrote:

>
>
> Hans Dockter wrote:
>>
>> On Aug 7, 2008, at 1:22 PM, Adam Murdoch wrote:
>>
>>>
>>>
>>> Hans Dockter wrote:
>>>>
>>>> On Aug 6, 2008, at 12:12 PM, Adam Murdoch wrote:
>>>>
>>>>>
>>>>>
>>>>> Hans Dockter wrote:
>>>>>>
>>>>>> What about doing things differently?
>>>>>>
>>>>>> We could introduce a Configuration class which implements  
>>>>>> Task. One can add dependencies to a configuration. Executing  
>>>>>> such a task means resolving its dependencies. Such a task  
>>>>>> would offer also methods to get a path, list of files, etc ...  
>>>>>> The compile task for example would depends on its  
>>>>>> configuration task(s). A project dependency would establish a  
>>>>>> depends relation between the configuration it belongs to and  
>>>>>> the configuration of the other project. The artifact producing  
>>>>>> configuration of the other project would depend on the  
>>>>>> corresponding artifact task(s).
>>>>>>
>>>>>> This would remove unnecessary elements from our API. It  
>>>>>> decreases the learning curve and simplifies the design. Last  
>>>>>> but not least we have finally our Configuration object to  
>>>>>> express this important domain concept.
>>>>>
>>>>> I think this is an excellent idea. We already do something  
>>>>> similar (conceptually) for bundles: A task is added to the  
>>>>> project for each bundle produced by the project, and I can ask  
>>>>> that a bundle be built from the command-line, add dependencies  
>>>>> on it, query it for its location, etc. We could probably come  
>>>>> up with a common approach for configurations and bundles.
>>>>
>>>> A bundle is a task and at the same time a container for archive  
>>>> tasks on which it depends. Your analogy is that a configuration  
>>>> is a container for dependencies, right?
>>> Sorry, I meant to say archives instead of bundles, ie we do  
>>> something similar for archives (make them available as tasks  
>>> which other tasks can depend on).  Hopefully that makes more sense.
>>>
>>>>>
>>>>>
>>>>> I'm not sure if Configuration should implement Task, or whether  
>>>>> adding a Configuration would trigger the adding of a Task that  
>>>>> resolves it.  The problem with implementing Task is that there  
>>>>> are (at least) 2 interpretations of 'executing' a  
>>>>> configuration: resolving it, and producing/publishing it. By  
>>>>> adding a task instead, we have the option of adding both a  
>>>>> resolve task and a publish task for a configuration. I guess  
>>>>> another option would be to have 2 types of Configuration: one  
>>>>> for incoming dependencies and one for produced artifacts.
>>>>>
>>>>
>>>> In Ivy itself all configurations are equals. They may contain  
>>>> only external dependencies or only artifacts produced by the  
>>>> project or both (e.g. a configuration that exposes the artifacts  
>>>> of a projects plus its external dependencies). I'm not sure if  
>>>> Ivy misses to model an important concept.
>>>>
>>>> Our configurations could take the same approach as Ivy. The fact  
>>>> that a configuration contains artifacts to be produced by the  
>>>> project can be expressed by the fact that this configuration  
>>>> depends on the respective archive task. A resolve could be  
>>>> simply defined by calling an Ivy resolve for the underlying Ivy  
>>>> ocnfiguration.
>>>>
>>> This makes sense. So, for example, if I have a project that  
>>> produces an artifact and includes it in a configuration, I add an  
>>> Archive (task) to produce the artifact, then add a Configuration  
>>> (task) with a dependency on the archive task. Adding this  
>>> dependency declares that the archive is a publication included in  
>>> the configuration.
>>>
>>> If I want to use the configuration in my project, I add another  
>>> task with a dependency on the configuration task.  Adding this  
>>> dependency declares that the task uses the configuration. Before  
>>> my task is executes, the archive is built, the configuration is  
>>> resolved, and my task can query the Configuration object for the  
>>> files that make up the configuration.
>>>
>>> If I want to include artifacts from another project, I can add a  
>>> dependency from the configuration task to a configuration task in  
>>> the other project.
>>
>> Right. With the current design we would use an intermediary for  
>> doing this. A project dependency would establish the dependency  
>> between the two configurations of the respective projects. The  
>> project dependency has the additional job to translate this  
>> dependency into ivy language.
>>
>>> I can add more artifacts to the configuration by adding more  
>>> dependencies on archive tasks (or any file producing task,  
>>> really). I can add external dependencies (log4j, say) by adding  
>>> them directly to the configuration task.
>>>
>>> Where do you think publishing would happen in all this?
>>
>> Publishing in the sense of adding an artifact to a repository  
>> happens in the uploadLibs and uploadDists tasks.
> I'm interested in how this happens generically, so assume I'm not  
> using the java plugin. In my example above, then, I would add an  
> upload task which depends on the configuration it uploads.  Adding  
> the dependency declares that the upload task publishes the config  
> to a repository. So, the dependency graph ends up like: upload ->  
> config -> archive. The upload task could potentially be  
> automatically added when the configuration is added to the project.
>
> If I want to use the config from another project in the same multi-
> project build, I really want to depend on the config rather than  
> the upload task (ie I want to depend on the thing I use, rather  
> than the step that happens to produce it). So, then ideally I have  
> a dependency graph like a:task -> a:config -> b:config ->  
> b:archive.  Would we do an implicit publish when b:config is  
> executed, or would a:config reach in to project b and resolve the  
> archive from there?
>
>> I'm not sure if it was a good idea to introduce a new term  
>> 'upload' for this instead of using the term 'publish'.
>>
>> The remaining open issue is how to deal with cleaning. Building a  
>> dependency without cleaning is not that reliable.  This is a  
>> (modified) quote from one of my earlier emails:
>>> One more point we need to think about. If we do a partial build  
>>> of project A which has a project dependency on project B. Let's  
>>> say we execute 'gradle clean libs'. Project A is cleaned before  
>>> its libs are created, not so project B. Only the artifact  
>>> producing task is executed. We could declare an additional  
>>> dependsOn('projectB') in project A. Such a dependsOn establishes  
>>> task dependencies between tasks with similar names of both  
>>> projects. Now the clean is done for both projects but also the  
>>> libs task is executed for project B which would neutralize our  
>>> effort to become more fine-grained regarding project dependencies  
>>> artifacts.
> Not sure yet.  When you execute 'gradle clean libs', you're really  
> saying 'rebuild the libs and its dependencies', so I think a good  
> solution is going to allow me to 1. ask gradle to do this from the  
> command-line, and 2. declare in the build scripts how to do this.
>
> Given that cleaning and rebuilding are concepts that pretty much  
> every build has, it is tempting to bake this concept into the build  
> tool's domain model. Something like (I haven't thought this  
> through, its just an example), a project can declare which task  
> should be run before doing a rebuild of its artifacts (eg a Clean  
> task). Then, using the configuration dependencies, gradle can  
> decorate the dependency graph to add in the clean tasks if a  
> rebuild is being done.
>
>
> Adam
>
>
> ---------------------------------------------------------------------
> To unsubscribe from this list, please visit:
>
>    http://xircles.codehaus.org/manage_email
>
>

--
Hans Dockter
Gradle Project lead
http://www.gradle.org





---------------------------------------------------------------------
To unsubscribe from this list, please visit:

    http://xircles.codehaus.org/manage_email


Reply | Threaded
Open this post in threaded view
|

Re: dependency layer refactoring

Adam Murdoch-2
In reply to this post by Adam Murdoch-2


Adam Murdoch wrote:

>
>
> Hans Dockter wrote:
>>
>> On Aug 7, 2008, at 1:22 PM, Adam Murdoch wrote:
>>
>>>
>>>
>>> Hans Dockter wrote:
>>>>
>>>> On Aug 6, 2008, at 12:12 PM, Adam Murdoch wrote:
>>>>
>>>>>
>>>>>
>>>>> Hans Dockter wrote:
>>>>>>
>>>>>> What about doing things differently?
>>>>>>
>>>>>> We could introduce a Configuration class which implements Task.
>>>>>> One can add dependencies to a configuration. Executing such a
>>>>>> task means resolving its dependencies. Such a task would offer
>>>>>> also methods to get a path, list of files, etc ... The compile
>>>>>> task for example would depends on its configuration task(s). A
>>>>>> project dependency would establish a depends relation between the
>>>>>> configuration it belongs to and the configuration of the other
>>>>>> project. The artifact producing configuration of the other
>>>>>> project would depend on the corresponding artifact task(s).
>>>>>>
>>>>>> This would remove unnecessary elements from our API. It decreases
>>>>>> the learning curve and simplifies the design. Last but not least
>>>>>> we have finally our Configuration object to express this
>>>>>> important domain concept.
>>>>>
>>>>> I think this is an excellent idea. We already do something similar
>>>>> (conceptually) for bundles: A task is added to the project for
>>>>> each bundle produced by the project, and I can ask that a bundle
>>>>> be built from the command-line, add dependencies on it, query it
>>>>> for its location, etc. We could probably come up with a common
>>>>> approach for configurations and bundles.
>>>>
>>>> A bundle is a task and at the same time a container for archive
>>>> tasks on which it depends. Your analogy is that a configuration is
>>>> a container for dependencies, right?
>>> Sorry, I meant to say archives instead of bundles, ie we do
>>> something similar for archives (make them available as tasks which
>>> other tasks can depend on).  Hopefully that makes more sense.
>>>
>>>>>
>>>>>
>>>>> I'm not sure if Configuration should implement Task, or whether
>>>>> adding a Configuration would trigger the adding of a Task that
>>>>> resolves it.  The problem with implementing Task is that there are
>>>>> (at least) 2 interpretations of 'executing' a configuration:
>>>>> resolving it, and producing/publishing it. By adding a task
>>>>> instead, we have the option of adding both a resolve task and a
>>>>> publish task for a configuration. I guess another option would be
>>>>> to have 2 types of Configuration: one for incoming dependencies
>>>>> and one for produced artifacts.
>>>>>
>>>>
>>>> In Ivy itself all configurations are equals. They may contain only
>>>> external dependencies or only artifacts produced by the project or
>>>> both (e.g. a configuration that exposes the artifacts of a projects
>>>> plus its external dependencies). I'm not sure if Ivy misses to
>>>> model an important concept.
>>>>
>>>> Our configurations could take the same approach as Ivy. The fact
>>>> that a configuration contains artifacts to be produced by the
>>>> project can be expressed by the fact that this configuration
>>>> depends on the respective archive task. A resolve could be simply
>>>> defined by calling an Ivy resolve for the underlying Ivy
>>>> ocnfiguration.
>>>>
>>> This makes sense. So, for example, if I have a project that produces
>>> an artifact and includes it in a configuration, I add an Archive
>>> (task) to produce the artifact, then add a Configuration (task) with
>>> a dependency on the archive task. Adding this dependency declares
>>> that the archive is a publication included in the configuration.
>>>
>>> If I want to use the configuration in my project, I add another task
>>> with a dependency on the configuration task.  Adding this dependency
>>> declares that the task uses the configuration. Before my task is
>>> executes, the archive is built, the configuration is resolved, and
>>> my task can query the Configuration object for the files that make
>>> up the configuration.
>>>
>>> If I want to include artifacts from another project, I can add a
>>> dependency from the configuration task to a configuration task in
>>> the other project.
>>
>> Right. With the current design we would use an intermediary for doing
>> this. A project dependency would establish the dependency between the
>> two configurations of the respective projects. The project dependency
>> has the additional job to translate this dependency into ivy language.
>>
>>> I can add more artifacts to the configuration by adding more
>>> dependencies on archive tasks (or any file producing task, really).
>>> I can add external dependencies (log4j, say) by adding them directly
>>> to the configuration task.
>>>
>>> Where do you think publishing would happen in all this?
>>
>> Publishing in the sense of adding an artifact to a repository happens
>> in the uploadLibs and uploadDists tasks.
> I'm interested in how this happens generically, so assume I'm not
> using the java plugin. In my example above, then, I would add an
> upload task which depends on the configuration it uploads.  Adding the
> dependency declares that the upload task publishes the config to a
> repository. So, the dependency graph ends up like: upload -> config ->
> archive. The upload task could potentially be automatically added when
> the configuration is added to the project.
>
> If I want to use the config from another project in the same
> multi-project build, I really want to depend on the config rather than
> the upload task (ie I want to depend on the thing I use, rather than
> the step that happens to produce it). So, then ideally I have a
> dependency graph like a:task -> a:config -> b:config -> b:archive.  
> Would we do an implicit publish when b:config is executed, or would
> a:config reach in to project b and resolve the archive from there?
>
>> I'm not sure if it was a good idea to introduce a new term 'upload'
>> for this instead of using the term 'publish'.
>>
>> The remaining open issue is how to deal with cleaning. Building a
>> dependency without cleaning is not that reliable.  This is a
>> (modified) quote from one of my earlier emails:
>>> One more point we need to think about. If we do a partial build of
>>> project A which has a project dependency on project B. Let's say we
>>> execute 'gradle clean libs'. Project A is cleaned before its libs
>>> are created, not so project B. Only the artifact producing task is
>>> executed. We could declare an additional dependsOn('projectB') in
>>> project A. Such a dependsOn establishes task dependencies between
>>> tasks with similar names of both projects. Now the clean is done for
>>> both projects but also the libs task is executed for project B which
>>> would neutralize our effort to become more fine-grained regarding
>>> project dependencies artifacts.
> Not sure yet.  When you execute 'gradle clean libs', you're really
> saying 'rebuild the libs and its dependencies', so I think a good
> solution is going to allow me to 1. ask gradle to do this from the
> command-line, and 2. declare in the build scripts how to do this.
>

Thinking about it, there are a two things you might want gradle to do
when you execute 'gradle clean libs':
- rebuild the libs and all their dependencies
- rebuild this lib only.

It would be good to handle both these cases.

> Given that cleaning and rebuilding are concepts that pretty much every
> build has, it is tempting to bake this concept into the build tool's
> domain model. Something like (I haven't thought this through, its just
> an example), a project can declare which task should be run before
> doing a rebuild of its artifacts (eg a Clean task). Then, using the
> configuration dependencies, gradle can decorate the dependency graph
> to add in the clean tasks if a rebuild is being done.
>

Some other options:

- We add some way to specify a dependency like: "this task depends on
the 'clean' task of each project which this project uses artifacts
from". You can then attach such a dependency to your project's 'clean'
task. Or 'rebuild' task.

- We change the Clean task so that it automatically has such a
dependency, so that you just use the Clean task in your project and it
figures it all out. Alternatively we could add a Rebuild task which does
this.

- We add a command-line option (--rebuild, say) which executes the
'clean' task for all projects whose artifacts are going to be used
during the build.


Adam


---------------------------------------------------------------------
To unsubscribe from this list, please visit:

    http://xircles.codehaus.org/manage_email


Reply | Threaded
Open this post in threaded view
|

Re: dependency layer refactoring

hans_d
Administrator

On Aug 26, 2008, at 12:47 PM, Adam Murdoch wrote:

>
>
> Adam Murdoch wrote:
>>
>>
>> Hans Dockter wrote:
>>>
>>> On Aug 7, 2008, at 1:22 PM, Adam Murdoch wrote:
>>>
>>>>
>>>>
>>>> Hans Dockter wrote:
>>>>>
>>>>> On Aug 6, 2008, at 12:12 PM, Adam Murdoch wrote:
>>>>>
>>>>>>
>>>>>>
>>>>>> Hans Dockter wrote:
>>>>>>>
>>>>>>> What about doing things differently?
>>>>>>>
>>>>>>> We could introduce a Configuration class which implements  
>>>>>>> Task. One can add dependencies to a configuration. Executing  
>>>>>>> such a task means resolving its dependencies. Such a task  
>>>>>>> would offer also methods to get a path, list of files,  
>>>>>>> etc ... The compile task for example would depends on its  
>>>>>>> configuration task(s). A project dependency would establish a  
>>>>>>> depends relation between the configuration it belongs to and  
>>>>>>> the configuration of the other project. The artifact  
>>>>>>> producing configuration of the other project would depend on  
>>>>>>> the corresponding artifact task(s).
>>>>>>>
>>>>>>> This would remove unnecessary elements from our API. It  
>>>>>>> decreases the learning curve and simplifies the design. Last  
>>>>>>> but not least we have finally our Configuration object to  
>>>>>>> express this important domain concept.
>>>>>>
>>>>>> I think this is an excellent idea. We already do something  
>>>>>> similar (conceptually) for bundles: A task is added to the  
>>>>>> project for each bundle produced by the project, and I can ask  
>>>>>> that a bundle be built from the command-line, add dependencies  
>>>>>> on it, query it for its location, etc. We could probably come  
>>>>>> up with a common approach for configurations and bundles.
>>>>>
>>>>> A bundle is a task and at the same time a container for archive  
>>>>> tasks on which it depends. Your analogy is that a configuration  
>>>>> is a container for dependencies, right?
>>>> Sorry, I meant to say archives instead of bundles, ie we do  
>>>> something similar for archives (make them available as tasks  
>>>> which other tasks can depend on).  Hopefully that makes more sense.
>>>>
>>>>>>
>>>>>>
>>>>>> I'm not sure if Configuration should implement Task, or  
>>>>>> whether adding a Configuration would trigger the adding of a  
>>>>>> Task that resolves it.  The problem with implementing Task is  
>>>>>> that there are (at least) 2 interpretations of 'executing' a  
>>>>>> configuration: resolving it, and producing/publishing it. By  
>>>>>> adding a task instead, we have the option of adding both a  
>>>>>> resolve task and a publish task for a configuration. I guess  
>>>>>> another option would be to have 2 types of Configuration: one  
>>>>>> for incoming dependencies and one for produced artifacts.
>>>>>>
>>>>>
>>>>> In Ivy itself all configurations are equals. They may contain  
>>>>> only external dependencies or only artifacts produced by the  
>>>>> project or both (e.g. a configuration that exposes the  
>>>>> artifacts of a projects plus its external dependencies). I'm  
>>>>> not sure if Ivy misses to model an important concept.
>>>>>
>>>>> Our configurations could take the same approach as Ivy. The  
>>>>> fact that a configuration contains artifacts to be produced by  
>>>>> the project can be expressed by the fact that this  
>>>>> configuration depends on the respective archive task. A resolve  
>>>>> could be simply defined by calling an Ivy resolve for the  
>>>>> underlying Ivy ocnfiguration.
>>>>>
>>>> This makes sense. So, for example, if I have a project that  
>>>> produces an artifact and includes it in a configuration, I add  
>>>> an Archive (task) to produce the artifact, then add a  
>>>> Configuration (task) with a dependency on the archive task.  
>>>> Adding this dependency declares that the archive is a  
>>>> publication included in the configuration.
>>>>
>>>> If I want to use the configuration in my project, I add another  
>>>> task with a dependency on the configuration task.  Adding this  
>>>> dependency declares that the task uses the configuration. Before  
>>>> my task is executes, the archive is built, the configuration is  
>>>> resolved, and my task can query the Configuration object for the  
>>>> files that make up the configuration.
>>>>
>>>> If I want to include artifacts from another project, I can add a  
>>>> dependency from the configuration task to a configuration task  
>>>> in the other project.
>>>
>>> Right. With the current design we would use an intermediary for  
>>> doing this. A project dependency would establish the dependency  
>>> between the two configurations of the respective projects. The  
>>> project dependency has the additional job to translate this  
>>> dependency into ivy language.
>>>
>>>> I can add more artifacts to the configuration by adding more  
>>>> dependencies on archive tasks (or any file producing task,  
>>>> really). I can add external dependencies (log4j, say) by adding  
>>>> them directly to the configuration task.
>>>>
>>>> Where do you think publishing would happen in all this?
>>>
>>> Publishing in the sense of adding an artifact to a repository  
>>> happens in the uploadLibs and uploadDists tasks.
>> I'm interested in how this happens generically, so assume I'm not  
>> using the java plugin. In my example above, then, I would add an  
>> upload task which depends on the configuration it uploads.  Adding  
>> the dependency declares that the upload task publishes the config  
>> to a repository. So, the dependency graph ends up like: upload ->  
>> config -> archive. The upload task could potentially be  
>> automatically added when the configuration is added to the project.
>>
>> If I want to use the config from another project in the same multi-
>> project build, I really want to depend on the config rather than  
>> the upload task (ie I want to depend on the thing I use, rather  
>> than the step that happens to produce it). So, then ideally I have  
>> a dependency graph like a:task -> a:config -> b:config ->  
>> b:archive.  Would we do an implicit publish when b:config is  
>> executed, or would a:config reach in to project b and resolve the  
>> archive from there?
>>
>>> I'm not sure if it was a good idea to introduce a new term  
>>> 'upload' for this instead of using the term 'publish'.
>>>
>>> The remaining open issue is how to deal with cleaning. Building a  
>>> dependency without cleaning is not that reliable.  This is a  
>>> (modified) quote from one of my earlier emails:
>>>> One more point we need to think about. If we do a partial build  
>>>> of project A which has a project dependency on project B. Let's  
>>>> say we execute 'gradle clean libs'. Project A is cleaned before  
>>>> its libs are created, not so project B. Only the artifact  
>>>> producing task is executed. We could declare an additional  
>>>> dependsOn('projectB') in project A. Such a dependsOn establishes  
>>>> task dependencies between tasks with similar names of both  
>>>> projects. Now the clean is done for both projects but also the  
>>>> libs task is executed for project B which would neutralize our  
>>>> effort to become more fine-grained regarding project  
>>>> dependencies artifacts.
>> Not sure yet.  When you execute 'gradle clean libs', you're really  
>> saying 'rebuild the libs and its dependencies', so I think a good  
>> solution is going to allow me to 1. ask gradle to do this from the  
>> command-line, and 2. declare in the build scripts how to do this.
>>
>
> Thinking about it, there are a two things you might want gradle to  
> do when you execute 'gradle clean libs':
> - rebuild the libs and all their dependencies
> - rebuild this lib only.
>
> It would be good to handle both these cases.

Definitely. Specially in large builds people want to be able to say:  
I know the project dependencies haven't change. So please rebuild  
this project only to save time.

Right now the jars of the project dependencies are copied to  
the .gradle/build-resolver dir, which is always removed before and  
after a build execution. To make the above work I guess we must not  
remove this directory and think about whether this can lead to  
problems with stale jar's.

>
>> Given that cleaning and rebuilding are concepts that pretty much  
>> every build has, it is tempting to bake this concept into the  
>> build tool's domain model. Something like (I haven't thought this  
>> through, its just an example), a project can declare which task  
>> should be run before doing a rebuild of its artifacts (eg a Clean  
>> task). Then, using the configuration dependencies, gradle can  
>> decorate the dependency graph to add in the clean tasks if a  
>> rebuild is being done.
>>
>
> Some other options:
>
> - We add some way to specify a dependency like: "this task depends  
> on the 'clean' task of each project which this project uses  
> artifacts from". You can then attach such a dependency to your  
> project's 'clean' task. Or 'rebuild' task.
>
> - We change the Clean task so that it automatically has such a  
> dependency, so that you just use the Clean task in your project and  
> it figures it all out. Alternatively we could add a Rebuild task  
> which does this.
>
> - We add a command-line option (--rebuild, say) which executes the  
> 'clean' task for all projects whose artifacts are going to be used  
> during the build.

Yet another approach would be to add a property to the  
dependencyManager, let's call it cleanTask. The default behavior of a  
ProjectDependency would be to create a dependency from the  
configuration (future implementation!) to the cleanTask of the  
dependencyProject's dependency manager. This approach would confine  
the notion of cleaning a dependency project to the domain model of  
dependency management.

- Hans

--
Hans Dockter
Gradle Project lead
http://www.gradle.org





---------------------------------------------------------------------
To unsubscribe from this list, please visit:

    http://xircles.codehaus.org/manage_email


Reply | Threaded
Open this post in threaded view
|

Re: dependency layer refactoring

Russel Winder-2
Top posting as I just wanted to say:  Can people do more editing of the
quoted parts of emails.  There are 4 pages of previous material here
before getting to anything new and almost all of the quoted material has
been seen before about seven times.

Thanks.

On Wed, 2008-08-27 at 08:44 +0200, Hans Dockter wrote:

> On Aug 26, 2008, at 12:47 PM, Adam Murdoch wrote:
>
> >
> >
> > Adam Murdoch wrote:
> >>
> >>
> >> Hans Dockter wrote:
> >>>
> >>> On Aug 7, 2008, at 1:22 PM, Adam Murdoch wrote:
> >>>
> >>>>
> >>>>
> >>>> Hans Dockter wrote:
> >>>>>
> >>>>> On Aug 6, 2008, at 12:12 PM, Adam Murdoch wrote:
> >>>>>
> >>>>>>
> >>>>>>
> >>>>>> Hans Dockter wrote:
> >>>>>>>
> >>>>>>> What about doing things differently?
> >>>>>>>
> >>>>>>> We could introduce a Configuration class which implements  
> >>>>>>> Task. One can add dependencies to a configuration. Executing  
> >>>>>>> such a task means resolving its dependencies. Such a task  
> >>>>>>> would offer also methods to get a path, list of files,  
> >>>>>>> etc ... The compile task for example would depends on its  
> >>>>>>> configuration task(s). A project dependency would establish a  
> >>>>>>> depends relation between the configuration it belongs to and  
> >>>>>>> the configuration of the other project. The artifact  
> >>>>>>> producing configuration of the other project would depend on  
> >>>>>>> the corresponding artifact task(s).
> >>>>>>>
> >>>>>>> This would remove unnecessary elements from our API. It  
> >>>>>>> decreases the learning curve and simplifies the design. Last  
> >>>>>>> but not least we have finally our Configuration object to  
> >>>>>>> express this important domain concept.
> >>>>>>
> >>>>>> I think this is an excellent idea. We already do something  
> >>>>>> similar (conceptually) for bundles: A task is added to the  
> >>>>>> project for each bundle produced by the project, and I can ask  
> >>>>>> that a bundle be built from the command-line, add dependencies  
> >>>>>> on it, query it for its location, etc. We could probably come  
> >>>>>> up with a common approach for configurations and bundles.
> >>>>>
> >>>>> A bundle is a task and at the same time a container for archive  
> >>>>> tasks on which it depends. Your analogy is that a configuration  
> >>>>> is a container for dependencies, right?
> >>>> Sorry, I meant to say archives instead of bundles, ie we do  
> >>>> something similar for archives (make them available as tasks  
> >>>> which other tasks can depend on).  Hopefully that makes more sense.
> >>>>
> >>>>>>
> >>>>>>
> >>>>>> I'm not sure if Configuration should implement Task, or  
> >>>>>> whether adding a Configuration would trigger the adding of a  
> >>>>>> Task that resolves it.  The problem with implementing Task is  
> >>>>>> that there are (at least) 2 interpretations of 'executing' a  
> >>>>>> configuration: resolving it, and producing/publishing it. By  
> >>>>>> adding a task instead, we have the option of adding both a  
> >>>>>> resolve task and a publish task for a configuration. I guess  
> >>>>>> another option would be to have 2 types of Configuration: one  
> >>>>>> for incoming dependencies and one for produced artifacts.
> >>>>>>
> >>>>>
> >>>>> In Ivy itself all configurations are equals. They may contain  
> >>>>> only external dependencies or only artifacts produced by the  
> >>>>> project or both (e.g. a configuration that exposes the  
> >>>>> artifacts of a projects plus its external dependencies). I'm  
> >>>>> not sure if Ivy misses to model an important concept.
> >>>>>
> >>>>> Our configurations could take the same approach as Ivy. The  
> >>>>> fact that a configuration contains artifacts to be produced by  
> >>>>> the project can be expressed by the fact that this  
> >>>>> configuration depends on the respective archive task. A resolve  
> >>>>> could be simply defined by calling an Ivy resolve for the  
> >>>>> underlying Ivy ocnfiguration.
> >>>>>
> >>>> This makes sense. So, for example, if I have a project that  
> >>>> produces an artifact and includes it in a configuration, I add  
> >>>> an Archive (task) to produce the artifact, then add a  
> >>>> Configuration (task) with a dependency on the archive task.  
> >>>> Adding this dependency declares that the archive is a  
> >>>> publication included in the configuration.
> >>>>
> >>>> If I want to use the configuration in my project, I add another  
> >>>> task with a dependency on the configuration task.  Adding this  
> >>>> dependency declares that the task uses the configuration. Before  
> >>>> my task is executes, the archive is built, the configuration is  
> >>>> resolved, and my task can query the Configuration object for the  
> >>>> files that make up the configuration.
> >>>>
> >>>> If I want to include artifacts from another project, I can add a  
> >>>> dependency from the configuration task to a configuration task  
> >>>> in the other project.
> >>>
> >>> Right. With the current design we would use an intermediary for  
> >>> doing this. A project dependency would establish the dependency  
> >>> between the two configurations of the respective projects. The  
> >>> project dependency has the additional job to translate this  
> >>> dependency into ivy language.
> >>>
> >>>> I can add more artifacts to the configuration by adding more  
> >>>> dependencies on archive tasks (or any file producing task,  
> >>>> really). I can add external dependencies (log4j, say) by adding  
> >>>> them directly to the configuration task.
> >>>>
> >>>> Where do you think publishing would happen in all this?
> >>>
> >>> Publishing in the sense of adding an artifact to a repository  
> >>> happens in the uploadLibs and uploadDists tasks.
> >> I'm interested in how this happens generically, so assume I'm not  
> >> using the java plugin. In my example above, then, I would add an  
> >> upload task which depends on the configuration it uploads.  Adding  
> >> the dependency declares that the upload task publishes the config  
> >> to a repository. So, the dependency graph ends up like: upload ->  
> >> config -> archive. The upload task could potentially be  
> >> automatically added when the configuration is added to the project.
> >>
> >> If I want to use the config from another project in the same multi-
> >> project build, I really want to depend on the config rather than  
> >> the upload task (ie I want to depend on the thing I use, rather  
> >> than the step that happens to produce it). So, then ideally I have  
> >> a dependency graph like a:task -> a:config -> b:config ->  
> >> b:archive.  Would we do an implicit publish when b:config is  
> >> executed, or would a:config reach in to project b and resolve the  
> >> archive from there?
> >>
> >>> I'm not sure if it was a good idea to introduce a new term  
> >>> 'upload' for this instead of using the term 'publish'.
> >>>
> >>> The remaining open issue is how to deal with cleaning. Building a  
> >>> dependency without cleaning is not that reliable.  This is a  
> >>> (modified) quote from one of my earlier emails:
> >>>> One more point we need to think about. If we do a partial build  
> >>>> of project A which has a project dependency on project B. Let's  
> >>>> say we execute 'gradle clean libs'. Project A is cleaned before  
> >>>> its libs are created, not so project B. Only the artifact  
> >>>> producing task is executed. We could declare an additional  
> >>>> dependsOn('projectB') in project A. Such a dependsOn establishes  
> >>>> task dependencies between tasks with similar names of both  
> >>>> projects. Now the clean is done for both projects but also the  
> >>>> libs task is executed for project B which would neutralize our  
> >>>> effort to become more fine-grained regarding project  
> >>>> dependencies artifacts.
> >> Not sure yet.  When you execute 'gradle clean libs', you're really  
> >> saying 'rebuild the libs and its dependencies', so I think a good  
> >> solution is going to allow me to 1. ask gradle to do this from the  
> >> command-line, and 2. declare in the build scripts how to do this.
> >>
> >
> > Thinking about it, there are a two things you might want gradle to  
> > do when you execute 'gradle clean libs':
> > - rebuild the libs and all their dependencies
> > - rebuild this lib only.
> >
> > It would be good to handle both these cases.
>
> Definitely. Specially in large builds people want to be able to say:  
> I know the project dependencies haven't change. So please rebuild  
> this project only to save time.
>
> Right now the jars of the project dependencies are copied to  
> the .gradle/build-resolver dir, which is always removed before and  
> after a build execution. To make the above work I guess we must not  
> remove this directory and think about whether this can lead to  
> problems with stale jar's.
>
> >
> >> Given that cleaning and rebuilding are concepts that pretty much  
> >> every build has, it is tempting to bake this concept into the  
> >> build tool's domain model. Something like (I haven't thought this  
> >> through, its just an example), a project can declare which task  
> >> should be run before doing a rebuild of its artifacts (eg a Clean  
> >> task). Then, using the configuration dependencies, gradle can  
> >> decorate the dependency graph to add in the clean tasks if a  
> >> rebuild is being done.
> >>
> >
> > Some other options:
> >
> > - We add some way to specify a dependency like: "this task depends  
> > on the 'clean' task of each project which this project uses  
> > artifacts from". You can then attach such a dependency to your  
> > project's 'clean' task. Or 'rebuild' task.
> >
> > - We change the Clean task so that it automatically has such a  
> > dependency, so that you just use the Clean task in your project and  
> > it figures it all out. Alternatively we could add a Rebuild task  
> > which does this.
> >
> > - We add a command-line option (--rebuild, say) which executes the  
> > 'clean' task for all projects whose artifacts are going to be used  
> > during the build.
>
> Yet another approach would be to add a property to the  
> dependencyManager, let's call it cleanTask. The default behavior of a  
> ProjectDependency would be to create a dependency from the  
> configuration (future implementation!) to the cleanTask of the  
> dependencyProject's dependency manager. This approach would confine  
> the notion of cleaning a dependency project to the domain model of  
> dependency management.
>
> - Hans
>
> --
> Hans Dockter
> Gradle Project lead
> http://www.gradle.org
>
>
>
>
>
> ---------------------------------------------------------------------
> To unsubscribe from this list, please visit:
>
>     http://xircles.codehaus.org/manage_email
>
>
--
Russel.
====================================================
Dr Russel Winder                 Partner

Concertant LLP                   t: +44 20 7585 2200, +44 20 7193 9203
41 Buckmaster Road,              f: +44 8700 516 084
London SW11 1EN, UK.             m: +44 7770 465 077

signature.asc (196 bytes) Download Attachment