On Mon, 27 Feb 2006, Jeremy Whitlock wrote:
> Daniel,
> I never thought of allowing the use of multiple info targets in one
> info tag.
Given that you can nest multiple <info> commands inside a single <svn>
tag, this seems reasonable enough to me too. However, it is rather
different than how the <list verbose="true" ... /> command Dan Price
wrote seems to work. Dan used a separator character, rather than a
series of prefixed properties (which I believe came from his
pre-verbose version of the patch). Jeremy, I rather like the way your
<info> command works, but do you guys have any thoughts on how the UI
for these tasks could be made a little more consistent?
> The reason I allowed for the specifying of the prefix was in case
> you wanted to run info on multiple files/dirs but not overwrite the original
> Ant properties set by the previous info calls. So you could do:
>
> <!-- svn.info.* properties -->
> <info file="${basedir}" />
>
> that would use the defaults for setting the properties of the base and then
> using:
>
> <!-- svn.core.* properties -->
> <info file="${basedir}/modules/core" rootPrefix="svn.core." />
>
> and get properties that apply only for the core. I hope this makes sense.
Yup (though, propPrefix="..."). The test cases in Dan Prince's second
version of a patch adding a <list> command demonstate how several of
the same commands can be used inside invocation of a single <svn>
task.
> That being said, I think the info support is documented well but maybe I
> should add more use case examples like why you'd use the rootPrefix
> attribute and how to run info against multiple files/dirs. Since this was
> never really spec'd out, I just came up with my own approach and implemented
> it. Obviously the community will drive this but as it is implemented, it
> does address your questions just in different ways. What do you think?
I agree. Some additional documentation outlining the multi-target
case would certainly come in handy for anyone just starting out with
SvnAnt. I think this documentation be written specific to the <info>
command (to highlight how to use multiple property prefixes), but do
we have similar or generic documentation for other commands? If we
don't, pointing to this new <info> documentation would be a good
start.
- Dan
> On 2/27/06, Daniel Rall <dlr@collab.net> wrote:
> >
> > Hello Jeremy, and thanks for your patience, and great start on the
> > <info> command. I've committed a command based on your code in r2125.
> > Please take a look at the commit, give it a whirl, and let me know
> > whether everything still looks kosher.
> >
> > I modified a lot of the code, most notably adding support for running
> > the <info> command against URIs, and refactoring the test suite. I
> > didn't add any ra_dav or ra_svn tests for that functionality, but I
> > think the test framework may provide a way to do this.
> >
> > Notably still missing is the ability to provide multiple targets to
> > the <info> command. Were you thinking that the use of multiple <info>
> > commands within a single <svn> task with different prefixes (e.g. for
> > "foo.c", provide a "foo.c-" prefix or something)? I think this should
> > be documented, or perhaps have much better support built right into
> > the task. Any feedback (or more patches ;) ?
> >
> > - Dan
> >
> >
> > On Tue, 14 Feb 2006, Jeremy Whitlock wrote:
> >
> > > Hey all,
> > > There has been a lot of talk about this in recent months so I have
> > gone
> > > ahead and implemented "svn info" for the SvnAnt Ant tasks. This support
> > is
> > > fully unit tested and documented as if it were written by the
> > maintainers of
> > > SvnAnt. It takes advantage of svnClientAdapter so access to javahl and
> > > command line adapters are available. There is one caveat where it does
> > not
> > > support the checksum feature since ISVNInfo doesn't expose a method to
> > > obtaining it. I will research this and submit a patch at a later time.
> > > Please review the attached patch and let me know if there is anything I
> > can
> > > do to fix an existing related issue.
> > >
> > > Take care,
> > >
> > > Jeremy
> >
> > > Index: C:/dev/java/svnant/test/svn/build.xml
> > > ===================================================================
> > > --- C:/dev/java/svnant/test/svn/build.xml (revision 2094)
> > > +++ C:/dev/java/svnant/test/svn/build.xml (working copy)
> > > @@ -1008,6 +1008,36 @@
> > > <fileset refid="svnFileSetPatternSet"/>
> > > </copy>
> > > </target>
> > > +
> > > + <target name="testInfoNoAttributes" depends="init">
> > > + <svn javahl="${javahl}" javasvn="${javasvn}">
> > > + <info />
> > > + </svn>
> > > + </target>
> > > +
> > > + <target name="testInfoDirectory" depends="init">
> > > + <svn javahl="${javahl}" javasvn="${javasvn}">
> > > + <info file="${basedir}"/>
> > > + </svn>
> > > + </target>
> > > +
> > > + <target name="testInfoFile" depends="init">
> > > + <svn javahl="${javahl}" javasvn="${javasvn}">
> > > + <info file="${basedir}/build.xml"/>
> > > + </svn>
> > > + </target>
> > > +
> > > + <target name="testInfoBadFile" depends="init">
> > > + <svn javahl="${javahl}" javasvn="${javasvn}">
> > > + <info file="${basedir}/nullfile.txt"/>
> > > + </svn>
> > > + </target>
> > > +
> > > + <target name="testInfoCustomPrefix" depends="init">
> > > + <svn javahl="${javahl}" javasvn="${javasvn}">
> > > + <info file="${basedir}" propPrefix="wc.info" />
> > > + </svn>
> > > + </target>
> > >
> > > <target name="all" depends="init">
> > > </target>
> > > Index: C:/dev/java/svnant/doc/svn.html
> > > ===================================================================
> > > --- C:/dev/java/svnant/doc/svn.html (revision 2094)
> > > +++ C:/dev/java/svnant/doc/svn.html (working copy)
> > > @@ -123,36 +123,36 @@
> > > <td>createRepository</td>
> > > <td>import</td>
> > > <td>move</td>
> > > - <td>status</td>
> > > + <td>revert</td>
> > > </tr>
> > > <tr>
> > > <td>cat</td>
> > > <td>delete</td>
> > > + <td>info</td>
> > > + <td>mkdir</td>
> > > + <td>status</td>
> > > + </tr>
> > > + <tr>
> > > + <td>checkout</td>
> > > + <td>diff</td>
> > > <td>keywordsset</td>
> > > <td>propdel</td>
> > > <td>switch</td>
> > > </tr>
> > > <tr>
> > > - <td>checkout</td>
> > > - <td>diff</td>
> > > + <td>commit</td>
> > > + <td>export</td>
> > > <td>keywordsadd</td>
> > > <td>propget</td>
> > > <td>update</td>
> > > </tr>
> > > <tr>
> > > - <td>commit</td>
> > > - <td>export</td>
> > > + <td>copy</td>
> > > + <td>ignore</td>
> > > <td>keywordsremove</td>
> > > <td>propset</td>
> > > <td></td>
> > > </tr>
> > > - <tr>
> > > - <td>copy</td>
> > > - <td>ignore</td>
> > > - <td>mkdir</td>
> > > - <td>revert</td>
> > > - <td></td>
> > > - </tr>
> > > </table>
> > > <p> </p>
> > >
> > > @@ -620,6 +620,33 @@
> > > </tr>
> > > </table>
> > >
> > > +<H3><a name="info">info</a></H3>
> > > +<p>
> > > +Gets the information from the repo for a file or directory and sets the
> > values to Ant properties.<BR>
> > > +</p>
> > > +<table>
> > > + <tr>
> > > + <td>Attribute</td>
> > > + <td>Description</td>
> > > + <td>Required</td>
> > > + </tr>
> > > + <tr>
> > > + <td>file</td>
> > > + <td>Directory or file to gather the information
> > about.</td>
> > > + <td>Yes</td>
> > > + </tr>
> > > + <tr>
> > > + <td>propPrefix</td>
> > > + <td>Prefix to use for the Ant properties. Default is
> > "svn.info.".</td>
> > > + <td>False</td>
> > > + </tr>
> > > + <tr>
> > > + <td>verbose</td>
> > > + <td>Turns on verbosity for this Ant task. Default is
> > "false".</td>
> > > + <td>False</td>
> > > + </tr>
> > > +</table>
> > > +
> > > <H3><a name="keywordsset">keywordsset</a></H3>
> > > <p>Keywordsset controls which keywords will be substituted on the
> > > given files. Valid keywords are:
> > > Index:
> > C:/dev/java/svnant/src/main/org/tigris/subversion/svnant/SvnTask.java
> > > ===================================================================
> > > ---
> > C:/dev/java/svnant/src/main/org/tigris/subversion/svnant/SvnTask.java
> > (revision 2094)
> > > +++
> > C:/dev/java/svnant/src/main/org/tigris/subversion/svnant/SvnTask.java
> > (working copy)
> > > @@ -208,6 +208,10 @@
> > > commands.add(a);
> > > }
> > >
> > > + public void addInfo(Info a) {
> > > + commands.add(a);
> > > + }
> > > +
> > > public void addNotifyListener(ISVNNotifyListener notifyListener) {
> > > notifyListeners.add(notifyListener);
> > > }
> > > Index:
> > C:/dev/java/svnant/src/main/org/tigris/subversion/svnant/Info.java
> > > ===================================================================
> > > ---
> > C:/dev/java/svnant/src/main/org/tigris/subversion/svnant/Info.java (revision
> > 0)
> > > +++
> > C:/dev/java/svnant/src/main/org/tigris/subversion/svnant/Info.java (revision
> > 0)
> > > @@ -0,0 +1,181 @@
> > > +package org.tigris.subversion.svnant;
> > > +
> > > +import java.io.File;
> > > +
> > > +import org.apache.tools.ant.BuildException;
> > > +import org.apache.tools.ant.Project;
> > > +import org.tigris.subversion.svnclientadapter.ISVNClientAdapter;
> > > +import org.tigris.subversion.svnclientadapter.ISVNInfo;
> > > +
> > > +/**
> > > + * svn info
> > > + * @author Jeremy Whitlock
> > > + * <a href="mailto:jwhitlock@collab.net">jwhitlock@collab.net</a>
> > > + */
> > > +public class Info extends SvnCommand {
> > > +
> > > + /** Path to the file to get properties from **/
> > > + private String file = null;
> > > +
> > > + /** Whether or not to print the properties **/
> > > + private boolean verbose = false;
> > > +
> > > + /** String prepended to new property names **/
> > > + private String propPrefix = "svn.info.";
> > > +
> > > + /** Project reference **/
> > > + private Project project = null;
> > > +
> > > + /** Subversion info **/
> > > + private ISVNInfo info = null;
> > > +
> > > + /** Available directory properties **/
> > > + private String[] dirProps = new String[] {
> > > + "path",
> > > + "url",
> > > + "repouuid",
> > > + "rev",
> > > + "nodekind",
> > > + "schedule",
> > > + "author",
> > > + "lastRev",
> > > + "lastDate"
> > > + };
> > > +
> > > + /** Available file properties **/
> > > + private String[] fileProps = new String[] {
> > > + "path",
> > > + "name",
> > > + "url",
> > > + "repouuid",
> > > + "rev",
> > > + "nodekind",
> > > + "schedule",
> > > + "author",
> > > + "lastRev",
> > > + "lastDate",
> > > + "lastTextUpdate",
> > > + "lastPropUpdate",
> > > + "checksum"
> > > + };
> > > +
> > > + /**
> > > + * @see org.tigris.subversion.svnant.SvnCommand#execute(
> > org.tigris.subversion.svnclientadapter.ISVNClientAdapter)
> > > + */
> > > + public void execute(ISVNClientAdapter svnClient) throws
> > BuildException {
> > > + validateAttributes();
> > > +
> > > + if (verbose) {
> > > + log("Svn: Info");
> > > + }
> > > +
> > > + project = getProject();
> > > +
> > > + File wc = new File(file);
> > > +
> > > + if (wc.exists()) {
> > > + try {
> > > + info = svnClient.getInfo(wc);
> > > + String[] props = null;
> > > +
> > > + if (wc.isDirectory()) {
> > > + props = dirProps;
> > > + } else {
> > > + props = fileProps;
> > > + }
> > > +
> > > + for (int i = 0; i < props.length; i++) {
> > > + String value = getValue(props[i]);
> > > +
> > > + project.setProperty(propPrefix +
> > props[i], value);
> > > +
> > > + if (verbose) {
> > > + log(" " + propPrefix +
> > props[i] + ": " + value, Project.MSG_INFO);
> > > + }
> > > + }
> > > + } catch (Exception e) {
> > > + throw new BuildException(e);
> > > + }
> > > + } else {
> > > + throw new BuildException("Dir must be set to an
> > existing file/directory in your working copy.");
> > > + }
> > > + }
> > > +
> > > + /**
> > > + * Gets the proper info property
> > > + * @param prop String representation of the property
> > > + * @return String value of the property
> > > + */
> > > + public String getValue(String prop) {
> > > + String value = null;
> > > +
> > > + if (prop.equals(fileProps[0])) {
> > > + value = info.getFile().getAbsolutePath();
> > > + } else if (prop.equals(fileProps[1])) {
> > > + value = info.getFile().getName();
> > > + } else if (prop.equals(fileProps[2])) {
> > > + value = info.getUrl().toString();
> > > + } else if (prop.equals(fileProps[3])) {
> > > + value = info.getUuid();
> > > + } else if (prop.equals(fileProps[4])) {
> > > + value = info.getRevision().toString();
> > > + } else if (prop.equals(fileProps[5])) {
> > > + value = info.getNodeKind().toString();
> > > + } else if (prop.equals(fileProps[6])) {
> > > + value = info.getSchedule().toString();
> > > + } else if (prop.equals(fileProps[7])) {
> > > + value = info.getLastCommitAuthor();
> > > + } else if (prop.equals(fileProps[8])) {
> > > + value = info.getLastChangedRevision().toString();
> > > + } else if (prop.equals(fileProps[9])) {
> > > + value = info.getLastChangedDate().toString();
> > > + } else if (prop.equals(fileProps[10])) {
> > > + value = info.getLastDateTextUpdate().toString();
> > > + } else if (prop.equals(fileProps[11])) {
> > > + value = info.getLastDatePropsUpdate().toString();
> > > + } else if (prop.equals(fileProps[12])) {
> > > + value = "Checksum is not implemented!";
> > > + } else {
> > > + value = prop + " is an invalid property!";
> > > + }
> > > +
> > > + return value;
> > > + }
> > > +
> > > + /**
> > > + * Validates the call to svn info
> > > + */
> > > + public void validateAttributes() {
> > > + if (file == null) {
> > > + throw new BuildException("File must be set to a
> > file/directory of your local working copy.");
> > > + }
> > > + }
> > > +
> > > + /**
> > > + * Set the path to the file/dir
> > > + * @param file
> > > + */
> > > + public void setFile(String file) {
> > > + this.file = Project.translatePath(file);
> > > + }
> > > +
> > > + /**
> > > + * Sets whether or not we output the properties we set
> > > + * @param verbose
> > > + */
> > > + public void setVerbose(boolean verbose) {
> > > + this.verbose = verbose;
> > > + }
> > > +
> > > + /**
> > > + * Sets the Ant property prefix
> > > + * @param propPrefix
> > > + */
> > > + public void setPropPrefix(String propPrefix) {
> > > + if (propPrefix.endsWith(".")) {
> > > + this.propPrefix = propPrefix;
> > > + } else {
> > > + this.propPrefix = propPrefix + ".";
> > > + }
> > > + }
> > > +}
> > > Index:
> > C:/dev/java/svnant/src/testcases/org/tigris/subversion/svnant/SvnTest.java
> > > ===================================================================
> > > ---
> > C:/dev/java/svnant/src/testcases/org/tigris/subversion/svnant/SvnTest.java (revision
> > 2094)
> > > +++
> > C:/dev/java/svnant/src/testcases/org/tigris/subversion/svnant/SvnTest.java (working
> > copy)
> > > @@ -815,8 +815,53 @@
> > > assertEquals(1, dir.listFiles().length);
> > > assertTrue( (new File(dir, "file3.xml")).exists() );
> > > }
> > > -
> > >
> > > + public void testSvnInfo() throws Exception {
> > > + // Here only for debugging the test
> > > + try {
> > > + expectBuildException("testInfoNoAttributes", "Dir
> > or file must be set.");
> > > + expectBuildException("testInfoBadFile", "
> > fakefile.txt: (Not a versioned resource)");
> > > +
> > > + executeTarget("testInfoFile");
> > > +
> > > + assertNotNull("Property should be set!",
> > project.getProperty("svn.info.path"));
> > > + assertNotNull("Property should be set!",
> > project.getProperty("svn.info.name"));
> > > + assertNotNull("Property should be set!",
> > project.getProperty("svn.info.url"));
> > > + assertNotNull("Property should be set!",
> > project.getProperty("svn.info.repouuid"));
> > > + assertNotNull("Property should be set!",
> > project.getProperty("svn.info.rev"));
> > > + assertNotNull("Property should be set!",
> > project.getProperty("svn.info.nodekind"));
> > > + assertNotNull("Property should be set!",
> > project.getProperty("svn.info.schedule"));
> > > + assertNotNull("Property should be set!",
> > project.getProperty("svn.info.author"));
> > > + assertNotNull("Property should be set!",
> > project.getProperty("svn.info.lastRev"));
> > > + assertNotNull("Property should be set!",
> > project.getProperty("svn.info.lastDate"));
> > > + assertNotNull("Property should be set!",
> > project.getProperty("svn.info.lastTextUpdate"));
> > > + assertNotNull("Property should be set!",
> > project.getProperty("svn.info.lastPropUpdate"));
> > > + assertNotNull("Property should be set!",
> > project.getProperty("svn.info.checksum"));
> > > +
> > > + executeTarget("testInfoDir");
> > > +
> > > + assertNotNull("Property should be set!",
> > project.getProperty("svn.info.path"));
> > > + assertNull("Property should be null!",
> > project.getProperty("svn.info.name"));
> > > + assertNotNull("Property should be set!",
> > project.getProperty("svn.info.url"));
> > > + assertNotNull("Property should be set!",
> > project.getProperty("svn.info.repouuid"));
> > > + assertNotNull("Property should be set!",
> > project.getProperty("svn.info.rev"));
> > > + assertNotNull("Property should be set!",
> > project.getProperty("svn.info.nodekind"));
> > > + assertNotNull("Property should be set!",
> > project.getProperty("svn.info.schedule"));
> > > + assertNotNull("Property should be set!",
> > project.getProperty("svn.info.author"));
> > > + assertNotNull("Property should be set!",
> > project.getProperty("svn.info.lastRev"));
> > > + assertNotNull("Property should be set!",
> > project.getProperty("svn.info.lastDate"));
> > > + assertNull("Property should be null!",
> > project.getProperty("svn.info.lastTextUpdate"));
> > > + assertNull("Property should be null!",
> > project.getProperty("svn.info.lastPropUpdate"));
> > > + assertNull("Property should be null!",
> > project.getProperty("svn.info.checksum"));
> > > +
> > > + executeTarget("testInfoCustomPrefix");
> > > +
> > > + assertNotNull("Property should not be null!",
> > project.getProperty("wc.info.path"));
> > > + } catch (Exception e) {
> > > + e.printStackTrace();
> > > + }
> > > + }
> > > +
> > > /**
> > > * This is not actually a test case, but a hook to assure that
> > > * cleanup is handled after all test cases have run (rather than
> >
> >
> > --
> >
> > Daniel Rall
> >
> >
> >
--
Daniel Rall
- application/pgp-signature attachment: stored
Received on Tue Feb 28 10:06:47 2006