diff --git a/docs/manual/OptionalTasks/starteam.html b/docs/manual/OptionalTasks/starteam.html index 2d7bcdc8a..2bdf247b2 100644 --- a/docs/manual/OptionalTasks/starteam.html +++ b/docs/manual/OptionalTasks/starteam.html @@ -48,7 +48,7 @@ other tasks in Ant. Inclusion/exclusion by folder is NOT supported.
"servername:portnum/project/view
+ servername:portnum/project/view
which enables user to set all of these elements in one string. <stcheckout URL="STARTEAM:49201/Aproject/AView" @@ -155,15 +179,28 @@ end in .bak or .old. rootlocalfolder="C:\dev\buildtest\co" includes="*.htm,*.html" excludes="index.*" + force="true" />- - + This is an example of overlapping includes and excludes attributes. Because excludes takes precedence over includes, files named
index.html
will
not be checked out by this command.
++ <stcheckout URL="STARTEAM:49201/Aproject/AView" + username="auser" + password="secret" + rootlocalfolder="C:\dev\buildtest\co" + includes="*.htm,*.html" + excludes="index.*" + force="true" + recursive="false" + /> ++This example is like the previous one, but will only check out files in +C:\dev\buildtest\co, because of the turning off of the recursive attribute.
<stcheckout URL="STARTEAM:49201/Aproject/AView" @@ -171,6 +208,7 @@ not be checked out by this command. password="secret" rootstarteamfolder="src/java" rootlocalfolder="C:\dev\buildtest\co" + force="true" />
View
+ * @return the snapshot View
appropriately configured.
*/
+ protected View createSnapshotView(View raw) {
+
+ int labelID = getLabelID(raw);
+
+ // if a label has been supplied, use it to configure the view
+ // otherwise use current view
+ if (labelID >= 0) {
+ return new View(raw, ViewConfiguration.createFromLabel(labelID));
+ } else {
+ return new View(raw, ViewConfiguration.createTip());
+ }
+ }
+
/**
- * Deletes everything on the local machine that is not in Starteam.
+ * Implements base-class abstract function to perform the checkout
+ * operation on the files in each folder of the tree.
*
- * @param files an "identity" Hashtable
which we use only because
- * of ant's requirement to be JDK 1.1 compatible. Otherwise, we
- * could use a set. We are only interested in the keys,
- * not the associated values in this Hashtable. Each of its keys
- * represents the name of a local file to be deleted.
+ * @param starteamFolder the StarTeam folder from which files to be
+ * checked out
+ * @param targetFolder the local mapping of rootStarteamFolder
*/
- private void delete(Hashtable files) {
+ protected void visit(Folder starteamFolder, java.io.File targetFolder)
+ throws BuildException {
try {
+ listLocalFiles(targetFolder);
+
+ // If we have been told to create the working folders
+ if (createDirs) {
+ // Create if it doesn't exist
+ if (!targetFolder.exists()) {
+ targetFolder.mkdir();
+ }
+ }
+ // For all Files in this folder, we need to check
+ // if there have been modifications.
+
+ Item[] files = starteamFolder.getItems("File");
+ for (int i = 0; i < files.length; i++) {
+ File eachFile = (File) files[i];
+ String filename = eachFile.getName();
+ java.io.File localFile =
+ new java.io.File(targetFolder, filename);
+
+ delistLocalFile(localFile);
+
+ // If the file doesn't pass the include/exclude tests, skip it.
+ if (!shouldProcess(filename)) {
+ log("Skipping " + eachFile.toString(), Project.MSG_INFO);
+ continue;
+ }
+
+
+ // If forced is not set then we may save ourselves some work by
+ // looking at the status flag.
+ // Otherwise, we care nothing about these statuses.
+
+ if (!isForced()) {
+ int fileStatus = (eachFile.getStatus());
+
+ // We try to update the status once to give StarTeam
+ // another chance.
+ if (fileStatus == Status.MERGE || fileStatus == Status.UNKNOWN) {
+ eachFile.updateStatus(true, true);
+ fileStatus = (eachFile.getStatus());
+ }
+ if (fileStatus == Status.CURRENT) {
+ log("Not processing " + eachFile.toString()
+ + " as it is current.",
+ Project.MSG_INFO);
+ continue;
+ }
+ }
+
+
+ // Check out anything else.
+ // Just a note: StarTeam has a status for NEW which implies
+ // that there is an item on your local machine that is not
+ // in the repository. These are the items that show up as
+ // NOT IN VIEW in the Starteam GUI.
+ // One would think that we would want to perhaps checkin the
+ // NEW items (not in all cases! - Steve Cohen 15 Dec 2001)
+ // Unfortunately, the sdk doesn't really work, and we can't
+ // actually see anything with a status of NEW. That is why
+ // we can just check out everything here without worrying
+ // about losing anything.
+
+ log("Checking Out: " + (localFile.toString()), Project.MSG_INFO);
+ eachFile.checkoutTo(localFile, Item.LockType.UNCHANGED,
+ true, true, true);
+ }
+
+ // Now we recursively call this method on all sub folders in this
+ // folder unless recursive attribute is off.
+ Folder[] subFolders = starteamFolder.getSubFolders();
+ for (int i = 0; i < subFolders.length; i++) {
+ java.io.File targetSubfolder =
+ new java.io.File(targetFolder, subFolders[i].getName());
+ delistLocalFile(targetSubfolder);
+ if (isRecursive()) {
+ visit(subFolders[i], targetSubfolder);
+ }
+ }
- Enumeration e = files.keys();
+ if (this.deleteUncontrolled) {
+ deleteUncontrolledItems();
+ }
+
+ } catch (IOException e) {
+ throw new BuildException(e);
+ }
+ }
+
+
+ /**
+ * Deletes everything on the local machine that is not in the repository.
+ */
+ private void deleteUncontrolledItems() {
+ try {
+ Enumeration e = getLocalFiles().keys();
while (e.hasMoreElements()) {
- java.io.File file = new java.io.File(e.nextElement().toString());
+ java.io.File file =
+ new java.io.File(e.nextElement().toString());
delete(file);
}
-
} catch (SecurityException e) {
log("Error deleting file: " + e, Project.MSG_ERR);
}
@@ -214,7 +269,8 @@ public class StarTeamCheckout extends TreeBasedTask {
* @return true if the file was successfully deleted otherwise false.
*/
private boolean delete(java.io.File file) {
- // If the current file is a Directory, we need to delete all its children as well.
+ // If the current file is a Directory, we need to delete all
+ // of its children as well.
if (file.isDirectory()) {
java.io.File[] children = file.listFiles();
for (int i = 0; i < children.length; i++) {
@@ -226,31 +282,7 @@ public class StarTeamCheckout extends TreeBasedTask {
return file.delete();
}
- /**
- * Gets the collection of the local file names in the current directory We
- * need to check this collection against what we find in Starteam to
- * understand what we need to delete in order to synch with the repos.
- *
- * @param folder
- * @return
- */
- private static Hashtable getLocalFiles(java.io.File localFolder) {
-
- // we can't use java 2 collections so we will use an identity Hashtable to
- // hold the file names. We only care about the keys, not the values
- // (which will all be "").
-
- Hashtable results = new Hashtable();
- if (localFolder.exists()) {
- String[] localFiles = localFolder.list();
- for (int i = 0; i < localFiles.length; i++) {
- results.put( localFolder.toString() +
- java.io.File.separatorChar + localFiles[i], "");
- }
- }
- return results;
- }
}
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/starteam/TreeBasedTask.java b/src/main/org/apache/tools/ant/taskdefs/optional/starteam/TreeBasedTask.java
index b742b2fe1..84b6db0dd 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/starteam/TreeBasedTask.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/starteam/TreeBasedTask.java
@@ -54,44 +54,42 @@
*/
package org.apache.tools.ant.taskdefs.optional.starteam;
-import org.apache.tools.ant.DirectoryScanner;
-import org.apache.tools.ant.BuildException;
-
+import java.util.Hashtable;
import java.util.StringTokenizer;
-import java.io.IOException;
-import com.starbase.starteam.File;
import com.starbase.starteam.Folder;
-import com.starbase.starteam.View;
-import com.starbase.starteam.ViewConfiguration;
-import com.starbase.util.OLEDate;
+import com.starbase.starteam.Label;
import com.starbase.starteam.StarTeamFinder;
+import com.starbase.starteam.View;
+
+import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.DirectoryScanner;
+import org.apache.tools.ant.Project;
/**
* FileBasedTask.java
* This abstract class is the base for any tasks that are tree-based, that
* is, for tasks which iterate over a tree of folders in StarTeam which
- * is reflected in a tree of folder the local machine.
+ * is reflected in a tree of folder the local machine.
*
* This class provides the tree-iteration functionality. Derived classes
* will implement their specific task functionality by the visitor pattern,
- * specifically by implementing the method
+ * specifically by implementing the method
* visit(Folder rootStarteamFolder, java.io.File rootLocalFolder)
*
* Created: Sat Dec 15 16:55:19 2001
*
* @author Steve Cohen
* @version 1.0
- * @see StarBase Web Site
+ * @see StarBase Web Site
*/
public abstract class TreeBasedTask extends StarTeamTask {
-
///////////////////////////////////////////////////////////////
// default values for attributes.
- ///////////////////////////////////////////////////////////////
+ ///////////////////////////////////////////////////////////////
/**
* This constant sets the filter to include all files. This default has
* the same result as setIncludes("*")
.
@@ -134,8 +132,30 @@ public abstract class TreeBasedTask extends StarTeamTask {
*/
private String excludes = DEFAULT_EXCLUDESETTING;
+ /**
+ * StarTeam label on which to perform task.
+ */
+ private String label = null;
+
+ /**
+ * Set recursion to false to check out files in only the given folder
+ * and not in its subfolders.
+ */
+ private boolean recursive = true;
+
+ /**
+ * If forced set to true, files in the target directory will
+ * be processed regardless of status in the repository.
+ * Usually this should be true if rootlocalfolder is set
+ * because status will be relative to the default folder, not
+ * to the one being processed.
+ */
+ private boolean forced = false;
+
+ private Hashtable localFiles = new Hashtable();
+
///////////////////////////////////////////////////////////////
- // GET/SET methods.
+ // GET/SET methods.
// Setters, of course are where ant user passes in values.
///////////////////////////////////////////////////////////////
@@ -147,7 +167,7 @@ public abstract class TreeBasedTask extends StarTeamTask {
}
/**
- * returns the root folder in the Starteam repository
+ * returns the root folder in the Starteam repository
* used for this operation
*/
public String getRootStarteamFolder() {
@@ -155,16 +175,17 @@ public abstract class TreeBasedTask extends StarTeamTask {
}
/**
- * Set the local folder corresponding to the
+ * Set the local folder corresponding to the
* starteam folder for this operation.
- * If not specified, the StarTeam default will be used
+ * If not specified, the StarTeam default will be used
* the default is used.
*/
public void setRootLocalFolder(String rootLocalFolder) {
this.rootLocalFolder = rootLocalFolder;
}
+
/**
- * Returns the local folder specified by the user,
+ * Returns the local folder specified by the user,
* corresponding to the starteam folder for this operation.
* or null if not specified
*/
@@ -173,7 +194,7 @@ public abstract class TreeBasedTask extends StarTeamTask {
}
/**
- * sets the pattern of files to be included. See setExcludes() for a
+ * sets the pattern of files to be included. See setExcludes() for a
* description
* @param includes A string of filter patterns to include. Separate the
* patterns by spaces.
@@ -189,7 +210,7 @@ public abstract class TreeBasedTask extends StarTeamTask {
* Gets the patterns from the include filter. Rather that duplicate the
* details of AntStarTeanCheckOut's filtering here, refer to these
* links:
- *
+ *
* @return A string of filter patterns separated by spaces.
* @see #setIncludes(String includes)
* @see #setExcludes(String excludes)
@@ -225,7 +246,7 @@ public abstract class TreeBasedTask extends StarTeamTask {
* filter, as well.
* createSnapshotView
+ * defining the kind of configured view appropriate to its task.
+ *
+ * @param rawview the unconfigured View
+ * @return the snapshot View
appropriately configured.
+ */
+ protected abstract View createSnapshotView(View rawview);
+
+ /**
+ * This method does the work of opening the supplied Starteam view and
+ * calling the visit()
method to perform the task.
*
* @exception BuildException if any error occurs in the processing
+ * @see visit()
*/
-
- public void execute() throws BuildException {
- // Get view as of the current time?
- View view = StarTeamFinder.openView(getUserName() + ":" + getPassword()
- + "@" + getURL());
- View snapshot = new View(view, ViewConfiguration.createFromTime(
- new OLEDate()));
- Folder starteamrootfolder =
- StarTeamFinder.findFolder(snapshot.getRootFolder(), this.rootStarteamFolder);
-
- if ( null == starteamrootfolder) {
- throw new BuildException("Unable to find root folderin repository.");
- }
- java.io.File localrootfolder;
+ public void execute() throws BuildException {
+ try {
+ if (null != this.rootLocalFolder && !this.forced) {
+ log("Warning: rootLocalFolder specified, but forcing off.",
+ Project.MSG_WARN);
+ }
+ // Open the view
+ View view =
+ StarTeamFinder.openView(getUserName() + ":"
+ + getPassword()
+ + "@" + getURL());
+
+ if (null == view) {
+ throw new BuildException("Cannot find view" + getURL() +
+ " in repository()");
+ }
+
+ View snapshot = createSnapshotView(view);
+
+ // find the starteam folder specified to be the root of the
+ // operation. Throw if it can't be found.
+ Folder starteamrootfolder =
+ StarTeamFinder.findFolder(snapshot.getRootFolder(),
+ this.rootStarteamFolder);
+
+ if (null == starteamrootfolder) {
+ throw new BuildException(
+ "Unable to find root folder in repository.");
+ }
+
+ // set the local folder.
+ java.io.File localrootfolder;
+ if (null == this.rootLocalFolder) {
+ // use Star Team's default
+ localrootfolder =
+ new java.io.File(starteamrootfolder.getPath());
+ } else {
+ // force StarTeam to use our folder
+ localrootfolder = new java.io.File(getRootLocalFolder());
+ log("overriding local folder to " + localrootfolder);
+ }
- if (null == this.rootLocalFolder) {
- // use Star Team's default
- localrootfolder = new java.io.File(starteamrootfolder.getPath());
- } else {
- // force StarTeam to use our folder
- localrootfolder = new java.io.File(getRootLocalFolder());
- log("overriding local folder to " + localrootfolder);
- }
+ // Inspect everything in the root folder and then recursively
+ visit(starteamrootfolder, localrootfolder);
+ } catch (Exception e) {
+ throw new BuildException(e);
+ }
+ }
- // Inspect everything in the root folder and then recursively
- visit(starteamrootfolder, localrootfolder);
+ /**
+ * Helper method calls on the StarTeam API to retrieve an ID number
+ * for the specified view, corresponding to this.label.
+ * @param v the View
in which to search for this.label
+ * @return the ID number corresponding to this.label
or -1 if
+ * no label was provided.
+ * @exception BuildException if this.label
does not correspond
+ * to any label in the supplied view
+ */
+ protected int getLabelID(View v) throws BuildException {
+ if (null != this.label) {
+ Label[] allLabels = v.getLabels();
+ for (int i = 0; i < allLabels.length; i++) {
+ if (allLabels[i].getName().equals(this.label))
+ return allLabels[i].getID();
+ }
+ throw new BuildException("Error: label "
+ + this.label
+ + " does not exist in view");
+ }
+ return -1;
}
+
/**
- * Derived classes must override this class to define the actual processing
- * to performed on each folder in the tree defined for the task
+ * Derived classes must override this class to define actual processing
+ * to be performed on each folder in the tree defined for the task
*
* @param rootStarteamFolder the StarTeam folderto be visited
* @param rootLocalFolder the local mapping of rootStarteamFolder
*/
- protected abstract void visit(Folder rootStarteamFolder, java.io.File rootLocalFolder)
- throws BuildException;
+ protected abstract void visit(Folder rootStarteamFolder,
+ java.io.File rootLocalFolder)
+ throws BuildException;
+
+
+ protected Hashtable getLocalFiles() {
+ return this.localFiles;
+ }
+
+ /**
+ * Gets the collection of the local file names in the supplied directory.
+ * We need to check this collection against what we find in Starteam to
+ * understand what we need to do in order to synch with the repository.
+ *
+ * @param localFolder - the local folder to scan
+ */
+ protected void listLocalFiles(java.io.File localFolder) {
+
+ this.localFiles.clear();
+ // we can't use java 2 collections so we will use an identity
+ // Hashtable to hold the file names. We only care about the keys,
+ // not the values (which will all be "").
+
+ if (localFolder.exists()) {
+ String[] localFiles = localFolder.list();
+ for (int i = 0; i < localFiles.length; i++) {
+ this.localFiles.put(localFolder.toString() +
+ java.io.File.separatorChar + localFiles[i], "");
+ }
+ }
+ }
+ /**
+ * Removes from the collection of the local file names
+ * the supplied name of a processed file. When we are done, only
+ * files not in StarTeam will remain in localFiles.
+ *
+ * @param thisfile - file to remove from list.
+ * @return - true if file was removed, false if it wasn't found.
+ */
+ protected boolean delistLocalFile(java.io.File thisfile) {
+ return null != this.localFiles.remove(thisfile.toString());
+ }
}
+