Summary: | want to remember a value set within a task next time the task is called | ||
---|---|---|---|
Product: | Ant | Reporter: | Ben Temko <benjamin> |
Component: | Core | Assignee: | Ant Notifications List <notifications> |
Status: | NEW --- | ||
Severity: | enhancement | ||
Priority: | P3 | ||
Version: | 1.6.2 | ||
Target Milestone: | --- | ||
Hardware: | All | ||
OS: | All |
Description
Ben Temko
2004-11-03 15:45:50 UTC
It is very easy to write a new task using <scriptdef> to store a property into a file. There is also <loadfile> and <property file=""> tasks for loading properties. We dont do mutability because it turns out to work very well for overriding things in bigger and more complex build process. I'd be leery about adding any kind of mutability, especially as you probably want persistence of the information. Save the input to a file, instead. I must admit to a very deep dissatisfaction to touching the filesystem outside of the actual compilation process. I thought of this solution early on but discarded it as impractical for various reasons (also, it doesn't "feel" right). One of those reasons is that we have a common build base file which defines many tasks. If multiple users are building various projects (especially if multiple users are working on several branches of the same project) it can be a pain to manage the files to which I am trying to maintain user session data. Sure, you can always write to the user's home directory, but if I have builds going in parallel this gets messy as well. It makes much more sense to me to have a thread-safe session like object where I can store data generated throughout the build process, and refer to this data as needed during my large, anastomotic builds. Ant does everything else so well, and is so enormously useful, this seems like a next-logical-step, especially under the context of user-input-driven builds with the "input" task - that's a pandora's box you can't close back. Why not use build.xml.properties file for storing persistent data - it is local for the build. There is also an API to store user settings in registry (or user home on Unix), you can use it. Are you talking about within the life of a single (capital-P) Project? If so you could simply use ant-contrib's <var> task for that. If you mean within a JVM that could reference multiple Project instances, you could still write a custom task to set a system property (I think), which should then be copied into later-instantiated Project properties collections. Otherwise I am at a loss to understand what you expect of Ant. Let me try to show you what I mean. Here's a simplified example: ====================== [basebuild.xml] ... <property name="default_rhost" value="192.168.1.1"/> ... <target name="remote_deploy"> <input message="Enter remote server [${default_rhost}]: " addproperty="rd_rhost" defaultvalue="${default_rhost}"/> <property name="default_rhost" value="${rd_rhost}"> <scp task here using user-supplied hostname in "rd_host"> </target> ====================== ====================== [projectbuild.xml] <import file="basebuild.xml"/> <target name="remote_deploy" description="scp files"> <antcall target="basebuild.remote_deploy"> <params to specify first set of files fo here> </antcall> <antcall target="basebuild.remote_deploy"> <params to specify next set of files go here> </antcall> <ant call and so on> </target> ====================== OK, from the top : I have basebuild, which is included in projectbuild. The basebuild file defines the remote_deploy task which projectbuild uses to deploy several different sets of files remotely, possible to one or more servers, possibly not, it is not known until I'm ready for deployment. 1) default_rhost gets set to 192.168.1.1 2) antcall to basebuild.remote_deploy occurs, the user is asked for input 3) user gives 192.168.23.24 4) I set the "default_rhost" variable to the user supplied value, which works as long as this Target is active. 5) first set of files is deployed to 192.168.23.24 6) basebuild.remote_deploy Target ends, *** "default_rhost" resets to "192.168.1.1" *** 7) second antcall to remote_deploy occurs, the user is asked for input, but the "default_rhost" variable doesn't remember what the user put in last time, even though I attempted to set its value within the Target. I've tried this in several different ways and its always the same. Changing the value of a property in the scope of a single Target execution works fine with ant-contrib's Variable, but once the Target has completed, it ** does not remember ** the last value it had. If I call that Target again and attempt to access either an ant-contrib Variable or a Property which only has scope within that Target (i.e. it has no <property> task outside of the Target to which it is assigned a value), it is empty. There is no memory of its last value. Why is this useful? In our case, because we want to be able to have the user re-use a given value several times in a row, rather then potentially mis-typing an ip address and having files get deployed to the wrong place. The user gives a value once (or, in our case, picks a value from a list), and then can re-use it until he needs to give a different value. In the interim, *** between Target calls*, and remembers the last thing the user gave as input. I hope this is clearer? Please avoid using <antcall>&Co tasks. Please use <macrodef> to define <remote_deploy> task and specify different parameters to it. To elaborate on Alexey's response, the reason your <var> is "scoped" is due to the fact that you are using <antcall>. If you use <macrodef> (which is a really great task) you may really be glad you did. It looks like when using <macrodef> I lose the ability to inherit "depends" Targets, since <macrodef> is only defining Tasks, not Targets? I want my project's Target to have its own list of dependancies in it which are checked before my project's Target is run, and then to have the <rdeploy> Target I'm executing via <antcall> have ITS own set of dependancies, which are project independant, checked before it runs. I suppose I could simply add the dependancy Targets, in the proper order, to the list in <sequential> to happen before my actual desired action takes place to simulate it, but that's mixing my modes - I would have to convert every dependancy to a <macrodef>'d Task in this case? Out of curiosity, why not use <antcall>? Is it being phased out? <ant>, <subant> and <antcall> are to be used when you do NOT want to keep the results of the target invocations. This is because they clone the Project instance instead of acting upon the current Project. If you need an <antcall> that will return properties your simplest option is to look at some of the alternatives ant-contrib has to offer such as <antfetch> and <antcallback>. I also now remember why I had to use <antcall> - if I want to call the Target (or even the Task, <macrodef>'d or otherwise defined) multiple times, and still get user input, I have to use <antcall>, otherwise, once the property is set, it's set, and that's the end of it, no more user input, as the "addproperty" portion of the Task sort of kills the fun. I'm tinkering with using various combinations of antcontrib's <var> and the <macrodef> Task to do what I need, but I'm not optimistic yet... I hope I'm wrong! You can use <var unset="true" /> while you're using ant-contrib stuff... anyway... |