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
- application/pgp-signature attachment: stored
 
Received on Mon Feb 27 20:08:00 2006