You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@ant.apache.org by co...@apache.org on 2003/02/13 14:59:53 UTC
cvs commit: ant/src/main/org/apache/tools/ant/taskdefs/optional/starteam StarTeamCheckin.java StarTeamCheckout.java StarTeamLabel.java StarTeamList.java StarTeamTask.java TreeBasedTask.java
conor 2003/02/13 05:59:53
Modified: src/main/org/apache/tools/ant/taskdefs/optional/starteam
Tag: ANT_15_BRANCH StarTeamCheckin.java
StarTeamCheckout.java StarTeamLabel.java
StarTeamList.java StarTeamTask.java
TreeBasedTask.java
Log:
Merge of StarTeam fixes
Revision Changes Path
No revision
No revision
1.5.2.3 +190 -113 ant/src/main/org/apache/tools/ant/taskdefs/optional/starteam/StarTeamCheckin.java
Index: StarTeamCheckin.java
===================================================================
RCS file: /home/cvs/ant/src/main/org/apache/tools/ant/taskdefs/optional/starteam/StarTeamCheckin.java,v
retrieving revision 1.5.2.2
retrieving revision 1.5.2.3
diff -u -w -u -r1.5.2.2 -r1.5.2.3
--- StarTeamCheckin.java 10 Feb 2003 14:25:20 -0000 1.5.2.2
+++ StarTeamCheckin.java 13 Feb 2003 13:59:53 -0000 1.5.2.3
@@ -53,18 +53,17 @@
*/
package org.apache.tools.ant.taskdefs.optional.starteam;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.util.Enumeration;
-import java.util.Hashtable;
-
import com.starbase.starteam.File;
import com.starbase.starteam.Folder;
import com.starbase.starteam.Item;
import com.starbase.starteam.Status;
+import com.starbase.starteam.TypeNames;
import com.starbase.starteam.View;
import com.starbase.starteam.ViewConfiguration;
-
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.util.Enumeration;
+import java.util.Hashtable;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.Project;
@@ -72,8 +71,6 @@
* Checks files into a StarTeam project.
* Optionally adds files and in the local tree that
* are not managed by the repository to its control.
- *
- *
* Created: Sat Dec 15 20:26:07 2001
*
* @author <a href="mailto:scohen@localhost.localdomain">Steve Cohen</a>
@@ -181,15 +178,50 @@
/**
* Implements base-class abstract function to define tests for
- * any preconditons required by the task
+ * any preconditons required by the task.
*
- * @exception BuildException not thrown in this implementation
+ * @exception BuildException thrown if both rootLocalFolder
+ * and viewRootLocalFolder are defined
*/
protected void testPreconditions() throws BuildException {
- if (null != getRootLocalFolder() && !isForced()) {
- log("Warning: rootLocalFolder specified, but forcing off.",
- Project.MSG_WARN);
}
+ /**
+ * Implements base-class abstract function to emit to the log an
+ * entry describing the parameters that will be used by this operation.
+ *
+ * @param starteamrootFolder
+ * root folder in StarTeam for the operation
+ * @param targetrootFolder
+ * root local folder for the operation
+ * (whether specified by the user or not).
+ */
+ protected void logOperationDescription(
+ Folder starteamrootFolder, java.io.File targetrootFolder)
+ {
+ log((this.isRecursive() ? "Recursive" : "Non-recursive")
+ +" Checkin from"
+ + (null == getRootLocalFolder() ? " (default): " : ": ")
+ + targetrootFolder.getAbsolutePath());
+
+ log("Checking in to: " + starteamrootFolder.getFolderHierarchy());
+ logIncludes();
+ logExcludes();
+
+ if (this.lockStatus == Item.LockType.UNLOCKED) {
+ log(" Items will be checked in unlocked.");
+ }
+ else {
+ log(" Items will be checked in with no change in lock status.");
+ }
+
+ if (this.isForced()) {
+ log(" Items will be checked in in accordance with repository status and regardless of lock status.");
+ }
+ else {
+ log(" Items will be checked in regardless of repository status only if locked." );
+ }
+
+
}
/**
@@ -202,129 +234,174 @@
* @exception BuildException if any error occurs
*/
protected void visit(Folder starteamFolder, java.io.File targetFolder)
- throws BuildException {
+ throws BuildException
+ {
try {
- Hashtable localFiles = listLocalFiles(targetFolder);
+ if (null != getRootLocalFolder()) {
+ starteamFolder.setAlternatePathFragment(
+ targetFolder.getAbsolutePath());
+ }
- // If we have been told to create the working folders
- // 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);
+ Folder[] foldersList = starteamFolder.getSubFolders();
+ Item[] stFiles = starteamFolder.getItems(getTypeNames().FILE);
- delistLocalFile(localFiles, localFile);
+ // note, it's important to scan the items BEFORE we make the
+ // UnmatchedFileMap because that creates a bunch of NEW
+ // folders and files (unattached to repository) and we
+ // don't want to include those in our traversal.
- // If the file doesn't pass the include/exclude tests, skip it.
- if (!shouldProcess(filename)) {
- log("Skipping " + eachFile.toString(), Project.MSG_INFO);
- continue;
- }
+ UnmatchedFileMap ufm =
+ new CheckinMap().init(
+ targetFolder.getAbsoluteFile(), starteamFolder);
- // 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.
+ for (int i = 0, size = foldersList.length; i < size; i++) {
+ Folder stFolder = foldersList[i];
+ java.io.File subfolder =
+ new java.io.File(targetFolder, stFolder.getName());
- if (!isForced()) {
- int fileStatus = (eachFile.getStatus());
+ ufm.removeControlledItem(subfolder);
- // 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;
+ if (isRecursive()) {
+ visit(stFolder, subfolder);
}
}
- // Check in anything else.
- log("Checking In: " + (localFile.toString()), Project.MSG_INFO);
- eachFile.checkinFrom(localFile, this.comment,
- this.lockStatus,
- true, true, true);
- }
+ for (int i = 0, size = stFiles.length; i < size; i++) {
+ com.starbase.starteam.File stFile =
+ (com.starbase.starteam.File) stFiles[i];
+ processFile(stFile);
- // 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(localFiles, targetSubfolder);
-
- if (isRecursive()) {
- visit(subFolders[i], targetSubfolder);
- }
+ ufm.removeControlledItem(
+ new java.io.File(targetFolder, stFile.getName()));
}
+
if (this.addUncontrolled) {
- addUncontrolledItems(localFiles, starteamFolder);
+ ufm.processUncontrolledItems();
}
-
} catch (IOException e) {
throw new BuildException(e);
}
+
}
/**
- * Adds to the StarTeam repository everything on the local machine that
- * is not currently in the repository.
- * @param folder - StarTeam folder to which these items are to be added.
+ * provides a string showing from and to full paths for logging
+ *
+ * @param remotefile the Star Team file being processed.
+ *
+ * @return a string showing from and to full paths
+ */
+ private String describeCheckin(com.starbase.starteam.File remotefile)
+ {
+ StringBuffer sb = new StringBuffer();
+ sb.append(remotefile.getFullName())
+ .append(" --> ")
+ .append(getFullRepositoryPath(remotefile));
+ return sb.toString();
+ }
+
+ /**
+ * Processes (checks-out) <code>stFiles</code>files from StarTeam folder.
+ *
+ * @param eachFile repository file to process
+ * @param targetFolder a java.io.File (Folder) to work
+ * @throws IOException when StarTeam API fails to work with files
*/
- private void addUncontrolledItems(Hashtable localFiles, Folder folder)
+ private void processFile(com.starbase.starteam.File eachFile)
throws IOException {
- try {
- Enumeration e = localFiles.keys();
- while (e.hasMoreElements()) {
- java.io.File file =
- new java.io.File(e.nextElement().toString());
- add(folder, file);
+ String filename = eachFile.getName();
+
+ // If the file doesn't pass the include/exclude tests, skip it.
+ if (!shouldProcess(filename)) {
+ log("Excluding " + getFullRepositoryPath(eachFile));
+ return;
}
- } catch (SecurityException e) {
- log("Error adding file: " + e, Project.MSG_ERR);
+
+ boolean checkin = true;
+ 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.MODIFIED) {
+ log("Checking in: " + describeCheckin(eachFile));
+ }
+ else if (fileStatus == Status.MISSING) {
+ log("Local file missing: " + describeCheckin(eachFile));
+ checkin = false;
+ }
+ else {
+ if (isForced()) {
+ log("Forced checkin of " + describeCheckin(eachFile) +
+ " over status " + Status.name(fileStatus));
+ } else {
+ log("Skipping: " + getFullRepositoryPath(eachFile) +
+ " - status: " + Status.name(fileStatus));
+ checkin = false;
+ }
+ }
+ if (checkin) {
+ eachFile.checkin(this.comment, this.lockStatus,
+ this.isForced(), true, true);
}
}
/**
- * Deletes the file from the local drive.
- * @param file the file or directory to delete.
- * @return true if the file was successfully deleted otherwise false.
+ * handles the deletion of uncontrolled items
*/
- private void add(Folder parentFolder, java.io.File file)
- throws IOException {
- // If the current file is a Directory, we need to process all
- // of its children as well.
- if (file.isDirectory()) {
- log("Adding new folder to repository: " + file.getAbsolutePath(),
- Project.MSG_INFO);
- Folder newFolder = new Folder(parentFolder);
- newFolder.setName(file.getName());
- newFolder.update();
+ private class CheckinMap extends UnmatchedFileMap {
+ protected boolean isActive() {
+ return StarTeamCheckin.this.addUncontrolled;
+ }
- // now visit this new folder to take care of adding any files
- // or subfolders within it.
+
+ /**
+ * This override adds all its members to the repository. It is assumed
+ * that this method will not be called until all the items in the
+ * corresponding folder have been processed, and that the internal map
+ * will contain only uncontrolled items.
+ */
+ void processUncontrolledItems() throws BuildException {
+ if (this.isActive()) {
+ Enumeration e = this.keys();
+ while (e.hasMoreElements()) {
+ java.io.File local = (java.io.File) e.nextElement();
+ Item remoteItem = (Item) this.get(local);
+ remoteItem.update();
+
+ // once we find a folder that isn't in the repository,
+ // we know we can add it.
+ if (local.isDirectory()) {
+ Folder folder = (Folder) remoteItem;
+ log("Added uncontrolled folder "
+ + folder.getFolderHierarchy()
+ + " from " + local.getAbsoluteFile());
if (isRecursive()) {
- visit(newFolder, file);
+ UnmatchedFileMap submap =
+ new CheckinMap().init(local, folder);
+ submap.processUncontrolledItems();
}
} else {
- log("Adding new file to repository: " + file.getAbsolutePath(),
- Project.MSG_INFO);
- File newFile = new File(parentFolder);
- newFile.addFromStream(new FileInputStream(file),
- file.getName(),
- null, this.comment, 3, true);
+ com.starbase.starteam.File remoteFile =
+ (com.starbase.starteam.File) remoteItem;
+ log("Added uncontrolled file "
+ + TreeBasedTask.getFullRepositoryPath(remoteFile)
+ + " from " + local.getAbsoluteFile());
+
+ }
+ }
}
}
}
+
+}
+
+
1.9.2.4 +379 -127 ant/src/main/org/apache/tools/ant/taskdefs/optional/starteam/StarTeamCheckout.java
Index: StarTeamCheckout.java
===================================================================
RCS file: /home/cvs/ant/src/main/org/apache/tools/ant/taskdefs/optional/starteam/StarTeamCheckout.java,v
retrieving revision 1.9.2.3
retrieving revision 1.9.2.4
diff -u -w -u -r1.9.2.3 -r1.9.2.4
--- StarTeamCheckout.java 10 Feb 2003 14:25:20 -0000 1.9.2.3
+++ StarTeamCheckout.java 13 Feb 2003 13:59:53 -0000 1.9.2.4
@@ -1,7 +1,7 @@
/*
* The Apache Software License, Version 1.1
*
- * Copyright (c) 2001-2002 The Apache Software Foundation. All rights
+ * Copyright (c) 2001-2003 The Apache Software Foundation. All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -53,17 +53,16 @@
*/
package org.apache.tools.ant.taskdefs.optional.starteam;
-import java.io.IOException;
-import java.util.Enumeration;
-import java.util.Hashtable;
-
import com.starbase.starteam.File;
import com.starbase.starteam.Folder;
import com.starbase.starteam.Item;
import com.starbase.starteam.Status;
+import com.starbase.starteam.TypeNames;
import com.starbase.starteam.View;
import com.starbase.starteam.ViewConfiguration;
-
+import java.io.IOException;
+import java.util.Enumeration;
+import java.util.Hashtable;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.Project;
@@ -112,8 +111,8 @@
}
/**
- * Should all all local files <i>not<i> in StarTeam be deleted?
- * Optional, defaults to "true".
+ * Whether or not all local files <i>not<i> in StarTeam should be deleted.
+ * Optional, defaults to <code>true</code>.
* @param value the value to set the attribute to.
*/
public void setDeleteUncontrolled(boolean value) {
@@ -174,40 +173,132 @@
}
/**
+ * should checked out files get the timestamp from the repository
+ * or the time they are checked out. True means use the repository
+ * timestamp.
+ */
+ private boolean useRepositoryTimeStamp = false;
+
+ /**
+ * sets the useRepositoryTimestmp member.
+ *
+ * @param useRepositoryTimeStamp
+ * true means checked out files will get the repository timestamp.
+ * false means the checked out files will be timestamped at the time
+ * of checkout.
+ */
+ public void setUseRepositoryTimeStamp(boolean useRepositoryTimeStamp)
+ {
+ this.useRepositoryTimeStamp = useRepositoryTimeStamp;
+ }
+
+ /**
+ * returns the value of the useRepositoryTimestamp member
+ *
+ * @return the value of the useRepositoryTimestamp member
+ */
+ public boolean getUseRepositoryTimeStamp() {
+ return this.useRepositoryTimeStamp;
+ }
+ /**
* Override of base-class abstract function creates an
* appropriately configured view for checkouts - either
- * the current view or a view from this.label.
+ * the current view or a view from this.label or the raw
+ * view itself in the case of a revision label.
*
* @param raw the unconfigured <code>View</code>
+ *
* @return the snapshot <code>View</code> appropriately configured.
+ * @exception BuildException
*/
- protected View createSnapshotView(View raw) {
+ protected View createSnapshotView(View raw)
+ throws BuildException
+ {
int labelID = getLabelID(raw);
- // if a label has been supplied, use it to configure the view
- // otherwise use current view
- if (labelID >= 0) {
+ // if a label has been supplied and it is a view label, use it
+ // to configure the view
+ if (this.isUsingViewLabel()) {
return new View(raw, ViewConfiguration.createFromLabel(labelID));
- } else {
+ }
+ // if a label has been supplied and it is a revision label, use the raw
+ // the view as the snapshot
+ else if (this.isUsingRevisionLabel()) {
+ return raw;
+ }
+ // otherwise, use this view configured as the tip.
+ else {
return new View(raw, ViewConfiguration.createTip());
}
}
/**
* Implements base-class abstract function to define tests for
- * any preconditons required by the task
+ * any preconditons required by the task.
*
- * @exception BuildException not thrown in this implementation
+ * @exception BuildException thrown if both rootLocalFolder
+ * and viewRootLocalFolder are defined
*/
protected void testPreconditions() throws BuildException {
- if (null != getRootLocalFolder() && !isForced()) {
- log("Warning: rootLocalFolder specified, but forcing off.",
+ if (this.isUsingRevisionLabel() && this.createDirs) {
+ log("Ignoring createworkingdirs while using a revision label." +
+ " Folders will be created only as needed.",
Project.MSG_WARN);
+ this.createDirs=false;
}
}
/**
+ * extenders should emit to the log an entry describing the parameters
+ * that will be used by this operation.
+ *
+ * @param starteamrootFolder
+ * root folder in StarTeam for the operation
+ * @param targetrootFolder
+ * root local folder for the operation (whether specified
+ * by the user or not.
+ */
+
+ protected void logOperationDescription(
+ Folder starteamrootFolder, java.io.File targetrootFolder)
+ {
+ log((this.isRecursive() ? "Recursive" : "Non-recursive") +
+ " Checkout from: " + starteamrootFolder.getFolderHierarchy());
+
+ log(" Checking out to"
+ + (null == getRootLocalFolder() ? "(default): " : ": ")
+ + targetrootFolder.getAbsolutePath());
+
+
+ logLabel();
+ logIncludes();
+ logExcludes();
+
+ if (this.lockStatus == Item.LockType.EXCLUSIVE) {
+ log(" Items will be checked out with Exclusive locks.");
+ }
+ else if (this.lockStatus == Item.LockType.UNLOCKED) {
+ log(" Items will be checked out unlocked (even if presently locked).");
+ }
+ else {
+ log(" Items will be checked out with no change in lock status.");
+ }
+ log(" Items will be checked out with " +
+ (this.useRepositoryTimeStamp ? "repository timestamps."
+ : "the current timestamp."));
+ log(" Items will be checked out " +
+ (this.isForced() ? "regardless of" : "in accordance with") +
+ " repository status.");
+ if (this.deleteUncontrolled) {
+ log(" Local items not found in the repository will be deleted.");
+ }
+ log(" Directories will be created"+
+ (this.createDirs ? " wherever they exist in the repository, even if empty."
+ : " only where needed to check out files."));
+
+ }
+ /**
* Implements base-class abstract function to perform the checkout
* operation on the files in each folder of the tree.
*
@@ -217,59 +308,166 @@
* @exception BuildException if any error occurs
*/
protected void visit(Folder starteamFolder, java.io.File targetFolder)
- throws BuildException {
+ throws BuildException
+ {
try {
- Hashtable localFiles = listLocalFiles(targetFolder);
- // If we have been told to create the working folders
- if (createDirs) {
- // Create if it doesn't exist
+
+ if (null != getRootLocalFolder()) {
+ starteamFolder.setAlternatePathFragment(
+ targetFolder.getAbsolutePath());
+ }
+
if (!targetFolder.exists()) {
- targetFolder.mkdir();
+ if (!this.isUsingRevisionLabel()) {
+ if (this.createDirs) {
+ if (targetFolder.mkdirs()) {
+ log("Creating folder: " + targetFolder);
+ } else {
+ throw new BuildException(
+ "Failed to create local folder " + targetFolder);
+ }
+ }
}
}
- // 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(localFiles, localFile);
+ Folder[] foldersList = starteamFolder.getSubFolders();
+ Item[] filesList = starteamFolder.getItems(getTypeNames().FILE);
- // If the file doesn't pass the include/exclude tests, skip it.
- if (!shouldProcess(filename)) {
- log("Skipping " + eachFile.toString(), Project.MSG_INFO);
- continue;
+ if (this.isUsingRevisionLabel()) {
+
+ // prune away any files not belonging to the revision label
+ // this is one ugly API from Starteam SDK
+
+ Hashtable labelItems = new Hashtable(filesList.length);
+ int s = filesList.length;
+ int[] ids = new int[s];
+ for (int i=0; i < s; i++) {
+ ids[i]=filesList[i].getItemID();
+ labelItems.put(new Integer(ids[i]), new Integer(i));
+ }
+ int[] foundIds = getLabelInUse().getLabeledItemIDs(ids);
+ s = foundIds.length;
+ Item[] labeledFiles = new Item[s];
+ for (int i=0; i < s; i++) {
+ Integer ID = new Integer(foundIds[i]);
+ labeledFiles[i] =
+ filesList[((Integer) labelItems.get(ID)).intValue()];
+ }
+ filesList = labeledFiles;
}
- // 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.
+ // note, it's important to scan the items BEFORE we make the
+ // Unmatched file map because that creates a bunch of NEW
+ // folders and files (unattached to repository) and we
+ // don't want to include those in our traversal.
- if (!isForced()) {
- int fileStatus = (eachFile.getStatus());
+ UnmatchedFileMap ufm =
+ new CheckoutMap().
+ init(targetFolder.getAbsoluteFile(), starteamFolder);
- // 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());
+
+
+ for (int i = 0; i < foldersList.length; i++) {
+ Folder stFolder = foldersList[i];
+
+ java.io.File subfolder =
+ new java.io.File(targetFolder, stFolder.getName());
+
+ ufm.removeControlledItem(subfolder);
+
+ if (isRecursive()) {
+ visit(stFolder, subfolder);
}
- if (fileStatus == Status.CURRENT) {
- log("Not processing " + eachFile.toString()
- + " as it is current.",
- Project.MSG_INFO);
- continue;
+ }
+
+ for (int i = 0; i < filesList.length; i++) {
+ com.starbase.starteam.File stFile =
+ (com.starbase.starteam.File) filesList[i];
+ processFile( stFile, targetFolder);
+
+ ufm.removeControlledItem(
+ new java.io.File(targetFolder, stFile.getName()));
+ }
+ if (this.deleteUncontrolled) {
+ ufm.processUncontrolledItems();
+ }
+ } catch (IOException e) {
+ throw new BuildException(e);
}
}
- // Check out anything else.
+ /**
+ * provides a string showing from and to full paths for logging
+ *
+ * @param remotefile the Star Team file being processed.
+ *
+ * @return a string showing from and to full paths
+ */
+ private String describeCheckout(com.starbase.starteam.File remotefile,
+ java.io.File localFile)
+ {
+ StringBuffer sb = new StringBuffer();
+ sb.append(getFullRepositoryPath(remotefile))
+ .append(" --> ");
+ if (null == localFile) {
+ sb.append(remotefile.getFullName());
+ } else {
+ sb.append(localFile);
+ }
+ return sb.toString();
+ }
+ private String describeCheckout(com.starbase.starteam.File remotefile) {
+ return describeCheckout(remotefile,null);
+ }
+ /**
+ * Processes (checks out) <code>stFiles</code>files from StarTeam folder.
+ *
+ * @param eachFile repository file to process
+ * @param targetFolder a java.io.File (Folder) to work
+ * @throws IOException when StarTeam API fails to work with files
+ */
+ private void processFile(com.starbase.starteam.File eachFile,
+ java.io.File targetFolder )
+ throws IOException
+ {
+ String filename = eachFile.getName();
+
+ java.io.File localFile = new java.io.File(targetFolder, filename);
+
+ // If the file doesn't pass the include/exclude tests, skip it.
+ if (!shouldProcess(filename)) {
+ log("Excluding " + getFullRepositoryPath(eachFile),
+ Project.MSG_INFO);
+ return;
+ }
+
+ if (this.isUsingRevisionLabel()) {
+ if (!targetFolder.exists()) {
+ if (targetFolder.mkdirs()) {
+ log("Creating folder: " + targetFolder);
+ } else {
+ throw new BuildException(
+ "Failed to create local folder " + targetFolder);
+ }
+ }
+ boolean success = eachFile.checkoutByLabelID(
+ localFile,
+ getIDofLabelInUse(),
+ this.lockStatus,
+ !this.useRepositoryTimeStamp,
+ true,
+ false);
+ if (success) {
+ log("Checked out " + describeCheckout(eachFile, localFile));
+ }
+ }
+ else {
+ boolean checkout = true;
+
// 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
@@ -281,79 +479,133 @@
// we can just check out everything here without worrying
// about losing anything.
- log("Checking Out: " + (localFile.toString()), Project.MSG_INFO);
- eachFile.checkoutTo(localFile, this.lockStatus,
- true, true, true);
+ 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());
}
- // 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(localFiles, targetSubfolder);
- if (isRecursive()) {
- visit(subFolders[i], targetSubfolder);
+ log(eachFile.toString() + " has status of " +
+ Status.name(fileStatus), Project.MSG_DEBUG);
+
+
+ switch (fileStatus) {
+ case Status.OUTOFDATE:
+ case Status.MISSING:
+ log("Checking out: " + describeCheckout(eachFile));
+ break;
+ default:
+ if (isForced()) {
+ log("Forced checkout of "
+ + describeCheckout(eachFile)
+ + " over status " + Status.name(fileStatus));
+ } else {
+ log("Skipping: " + getFullRepositoryPath(eachFile) +
+ " - status: " + Status.name(fileStatus));
+ checkout = false;
}
}
- if (this.deleteUncontrolled) {
- deleteUncontrolledItems(localFiles);
+ if (checkout) {
+ if (!targetFolder.exists()) {
+ if (targetFolder.mkdirs()) {
+ log("Creating folder: " + targetFolder);
+ } else {
+ throw new BuildException(
+ "Failed to create local folder " + targetFolder);
+ }
+ }
+ eachFile.checkout(this.lockStatus,
+ !this.useRepositoryTimeStamp, true, true);
+ }
+ }
+ }
+ /**
+ * handles the deletion of uncontrolled items
+ */
+ private class CheckoutMap extends UnmatchedFileMap {
+ protected boolean isActive() {
+ return StarTeamCheckout.this.deleteUncontrolled;
}
- } catch (IOException e) {
- throw new BuildException(e);
+ /**
+ * override of the base class init. It can be much simpler, since
+ * the action to be taken is simply to delete the local files. No
+ * further interaction with the repository is necessary.
+ *
+ * @param localFolder
+ * the local folder from which the mappings will be made.
+ * @param remoteFolder
+ * not used in this implementation
+ */
+ UnmatchedFileMap init(java.io.File localFolder, Folder remoteFolder) {
+ if (!localFolder.exists()) {
+ return this;
+ }
+
+ String[] localFiles = localFolder.list();
+
+ for (int i=0; i < localFiles.length; i++) {
+ java.io.File localFile =
+ new java.io.File(localFolder, localFiles[i]).getAbsoluteFile();
+
+ log("adding " + localFile + " to UnmatchedFileMap",
+ Project.MSG_DEBUG);
+
+ if (localFile.isDirectory()) {
+ this.put(localFile, "");
+ }
+ else {
+ this.put(localFile, "");
}
}
+ return this;
+ }
+
/**
- * Deletes everything on the local machine that is not in the repository.
- *
- * @param localFiles the list of filenames whose elements are to be deleted
+ * deletes uncontrolled items from the local tree. It is assumed
+ * that this method will not be called until all the items in the
+ * corresponding folder have been processed, and that the internal map
+ * will contain only uncontrolled items.
*/
- private void deleteUncontrolledItems(Hashtable localFiles) {
- try {
- Enumeration e = localFiles.keys();
+ void processUncontrolledItems() throws BuildException {
+ if (this.isActive()) {
+ Enumeration e = this.keys();
while (e.hasMoreElements()) {
- java.io.File file =
- new java.io.File(e.nextElement().toString());
- delete(file);
+ java.io.File local = (java.io.File) e.nextElement();
+ delete(local);
}
- } catch (SecurityException e) {
- log("Error deleting file: " + e, Project.MSG_ERR);
}
}
/**
- * Deletes the file from the local drive.
- * @param file the file or directory to delete.
- * @return true if the file was successfully deleted otherwise false.
+ * deletes all files and if the file is a folder recursively deletes
+ * everything in it.
+ *
+ * @param local The local file or folder to be deleted.
*/
- private boolean delete(java.io.File file) {
- // 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++) {
- delete(children[i]);
+ void delete(java.io.File local) {
+ // once we find a folder that isn't in the repository,
+ // anything below it can be deleted.
+ if (local.isDirectory() && isRecursive()) {
+ String[] contents = local.list();
+ for (int i=0; i< contents.length; i++) {
+ java.io.File file = new java.io.File(local, contents[i]);
+ delete(file);
}
}
-
- log("Deleting: " + file.getAbsolutePath(), Project.MSG_INFO);
- return file.delete();
+ local.delete();
+ log("Deleted uncontrolled item " + local.getAbsolutePath());
}
-
-
}
-
-
-
-
-
-
-
-
+}
1.9.2.4 +72 -8 ant/src/main/org/apache/tools/ant/taskdefs/optional/starteam/StarTeamLabel.java
Index: StarTeamLabel.java
===================================================================
RCS file: /home/cvs/ant/src/main/org/apache/tools/ant/taskdefs/optional/starteam/StarTeamLabel.java,v
retrieving revision 1.9.2.3
retrieving revision 1.9.2.4
diff -u -w -u -r1.9.2.3 -r1.9.2.4
--- StarTeamLabel.java 10 Feb 2003 14:25:20 -0000 1.9.2.3
+++ StarTeamLabel.java 13 Feb 2003 13:59:53 -0000 1.9.2.4
@@ -53,15 +53,13 @@
*/
package org.apache.tools.ant.taskdefs.optional.starteam;
-import java.text.ParseException;
-import java.text.SimpleDateFormat;
-import java.util.Date;
-
import com.starbase.starteam.Label;
import com.starbase.starteam.View;
import com.starbase.starteam.ViewConfiguration;
import com.starbase.util.OLEDate;
-
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
import org.apache.tools.ant.BuildException;
/**
@@ -96,6 +94,19 @@
private String description;
/**
+ * If true, this will be a build label. If false, it will be a build
+ * label. The default is false. Has no effect if revision label is
+ * true.
+ */
+ private boolean buildlabel = false;
+
+ /**
+ * If true, this will be a revision label. If false, it will be a build
+ * label. The default is false.
+ */
+ private boolean revisionlabel = false;
+
+ /**
* The time of the last successful. The new label will be a snapshot of the
* repository at this time. String should be formatted as "yyyyMMddHHmmss"
*/
@@ -120,6 +131,30 @@
}
/**
+ * set the type of label based on the supplied value - if true, this
+ * label will be a revision label, if false, a build label.
+ *
+ * @param revision If true this will be a revision label; if false,
+ * a build label
+ */
+ public void setBuildLabel( boolean buildlabel ) {
+ this.buildlabel = buildlabel;
+ }
+
+ /**
+ * set the type of label based on the supplied value - if true, this
+ * label will be a revision label, if false, a build label.
+ *
+ * @param revision If true this will be a revision label; if false,
+ * a build label
+ */
+ public void setRevisionLabel( boolean revisionlabel ) {
+ this.revisionlabel = revisionlabel;
+ }
+
+
+
+ /**
* The timestamp of the build that will be stored with the label; required.
* Must be formatted <code>yyyyMMddHHmmss</code>
*/
@@ -128,7 +163,8 @@
Date lastBuildTime = DATE_FORMAT.parse(lastbuild);
this.lastBuild = new OLEDate(lastBuildTime);
} catch (ParseException e) {
- throw new BuildException("Unable to parse the date '" + lastbuild + "'", e);
+ throw new BuildException("Unable to parse the date '" +
+ lastbuild + "'", e);
}
}
@@ -139,11 +175,33 @@
*/
public void execute() throws BuildException {
+ if (this.revisionlabel && this.buildlabel) {
+ throw new BuildException(
+ "'revisionlabel' and 'buildlabel' both specified. " +
+ "A revision label cannot be a build label.");
+ }
+
View snapshot = openView();
// Create the new label and update the repository
- new Label(snapshot, labelName, description, this.lastBuild, true).update();
- log("Created Label " + labelName);
+
+ if (this.revisionlabel) {
+ new Label(snapshot, this.labelName, this.description).update();
+ log("Created Revision Label " + this.labelName);
+ }
+ else if (null != lastBuild){
+ new Label(snapshot, this.labelName, this.description,this.lastBuild,
+ this.buildlabel).update();
+ log("Created View Label ("
+ +(this.buildlabel ? "" : "non-") + "build) " + this.labelName
+ +" as of " + this.lastBuild.toString());
+ }
+ else {
+ new Label(snapshot, this.labelName, this.description,
+ this.buildlabel).update();
+ log("Created View Label ("
+ +(this.buildlabel ? "" : "non-") + "build) " + this.labelName);
+ }
}
/**
@@ -155,7 +213,13 @@
* @return the snapshot <code>View</code> appropriately configured.
*/
protected View createSnapshotView(View raw) {
+ /*
+ if (this.revisionlabel) {
+ return raw;
+ }
return new View(raw, ViewConfiguration.createFromTime(this.lastBuild));
+ */
+ return raw;
}
}
1.6.2.4 +125 -21 ant/src/main/org/apache/tools/ant/taskdefs/optional/starteam/StarTeamList.java
Index: StarTeamList.java
===================================================================
RCS file: /home/cvs/ant/src/main/org/apache/tools/ant/taskdefs/optional/starteam/StarTeamList.java,v
retrieving revision 1.6.2.3
retrieving revision 1.6.2.4
diff -u -w -u -r1.6.2.3 -r1.6.2.4
--- StarTeamList.java 10 Feb 2003 14:25:20 -0000 1.6.2.3
+++ StarTeamList.java 13 Feb 2003 13:59:53 -0000 1.6.2.4
@@ -53,17 +53,18 @@
*/
package org.apache.tools.ant.taskdefs.optional.starteam;
-import java.io.IOException;
-import java.util.Hashtable;
-
import com.starbase.starteam.File;
import com.starbase.starteam.Folder;
import com.starbase.starteam.Item;
import com.starbase.starteam.Status;
import com.starbase.starteam.View;
import com.starbase.starteam.ViewConfiguration;
-
+import java.io.IOException;
+import java.text.SimpleDateFormat;
+import java.util.Enumeration;
+import java.util.Hashtable;
import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.Project;
/**
* Produces a listing of the contents of the StarTeam repository
@@ -78,6 +79,7 @@
*/
public class StarTeamList extends TreeBasedTask {
+ private boolean listUncontrolled = true;
/**
* List files, dates, and statuses as of this label; optional.
* The label must exist in starteam or an exception will be thrown.
@@ -120,6 +122,29 @@
}
/**
+ * extenders should emit to the log an entry describing the parameters
+ * that will be used by this operation.
+ *
+ * @param starteamrootFolder
+ * root folder in StarTeam for the operation
+ * @param targetrootFolder
+ * root local folder for the operation (whether specified by the user or not.
+ */
+ protected void logOperationDescription(Folder starteamrootFolder, java.io.File targetrootFolder) {
+ log((this.isRecursive() ? "Recursive" : "Non-recursive") +
+ " Listing of: " + starteamrootFolder.getFolderHierarchy());
+
+ log("Listing against local folder"
+ + (null == getRootLocalFolder() ? " (default): " : ": ")
+ + targetrootFolder.getAbsolutePath(),
+ Project.MSG_INFO);
+ logLabel();
+ logIncludes();
+ logExcludes();
+
+
+ }
+ /**
* Implements base-class abstract function to perform the checkout
* operation on the files in each folder of the tree.
*
@@ -130,26 +155,35 @@
protected void visit(Folder starteamFolder, java.io.File targetFolder)
throws BuildException {
try {
- if (null == getRootLocalFolder()) {
- log("Folder: " + starteamFolder.getName() + " (Default folder: " + targetFolder + ")");
- } else {
- log("Folder: " + starteamFolder.getName() + " (Local folder: " + targetFolder + ")");
+ if (null != getRootLocalFolder()) {
+ starteamFolder.setAlternatePathFragment(
+ targetFolder.getAbsolutePath());
+
}
- Hashtable localFiles = listLocalFiles(targetFolder);
+ Folder[] subFolders = starteamFolder.getSubFolders();
+ Item[] files = starteamFolder.getItems(getTypeNames().FILE);
+
+ UnmatchedFileMap ufm =
+ new UnmatchedListingMap().init(
+ targetFolder.getAbsoluteFile(), starteamFolder);
+
+ log("");
+ log("Listing StarTeam folder " +
+ starteamFolder.getFolderHierarchy());
+ log(" against local folder " +
+ targetFolder.getAbsolutePath());
+
// 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(localFiles, localFile);
-
-
+ ufm.removeControlledItem(localFile);
// If the file doesn't pass the include/exclude tests, skip it.
if (!shouldProcess(filename)) {
@@ -162,32 +196,40 @@
// 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(localFiles, targetSubfolder);
+ ufm.removeControlledItem(targetSubfolder);
if (isRecursive()) {
visit(subFolders[i], targetSubfolder);
}
}
+ if (this.listUncontrolled) {
+ ufm.processUncontrolledItems();
+ }
} catch (IOException e) {
throw new BuildException(e);
}
}
+ private static final SimpleDateFormat SDF =
+ new SimpleDateFormat("yyyy-MM-dd hh:mm:ss zzz");
+
protected void list(File reposFile, java.io.File localFile)
throws IOException {
StringBuffer b = new StringBuffer();
- if (null == getRootLocalFolder()) {
- // status is irrelevant to us if we have specified a
- // root local folder.
- b.append(pad(Status.name(reposFile.getStatus()), 12)).append(' ');
+ int status = reposFile.getStatus();
+ java.util.Date displayDate = null;
+ if (status==Status.NEW) {
+ displayDate = new java.util.Date(localFile.lastModified());
+ } else {
+ displayDate = reposFile.getModifiedTime().createDate();
}
+ b.append(pad(Status.name(status), 12)).append(' ');
b.append(pad(getUserName(reposFile.getLocker()), 20))
.append(' ')
- .append(reposFile.getModifiedTime().toString())
+ .append(SDF.format(displayDate))
.append(rpad(String.valueOf(reposFile.getSize()), 9))
.append(' ')
.append(reposFile.getName());
@@ -212,6 +254,68 @@
protected static String rpad(String s, int padlen) {
s = blankstr + s;
return s.substring(s.length() - padlen);
+ }
+
+ /**
+ * handles the list of uncontrolled items
+ */
+ private class UnmatchedListingMap extends UnmatchedFileMap {
+
+ protected boolean isActive() {
+ return StarTeamList.this.listUncontrolled;
+ }
+
+ /**
+ * lists uncontrolled items from the local tree. It is assumed
+ * that this method will not be called until all the items in the
+ * corresponding folder have been processed, and that the internal map
+ * will contain only uncontrolled items.
+ */
+ void processUncontrolledItems() throws BuildException{
+ if (this.isActive()) {
+ Enumeration e = this.keys();
+
+ // handle the files so they appear first
+ while (e.hasMoreElements()) {
+ java.io.File local = (java.io.File) e.nextElement();
+ Item remoteItem = (Item) this.get(local);
+
+ // once we find a folder that isn't in the repository,
+ // we know we can add it.
+ if (local.isFile()) {
+ com.starbase.starteam.File remoteFile =
+ (com.starbase.starteam.File) remoteItem;
+ try {
+ list(remoteFile, local);
+ } catch (IOException ie) {
+ throw new BuildException("IOError in stlist",ie);
+ }
+ }
+ }
+ // now do it again for the directories so they appear last.
+ e = this.keys();
+ while (e.hasMoreElements()) {
+ java.io.File local = (java.io.File) e.nextElement();
+ Item remoteItem = (Item) this.get(local);
+
+ // once we find a folder that isn't in the repository,
+ // we know we can add it.
+ if (local.isDirectory()) {
+ Folder folder = (Folder) remoteItem;
+ if (isRecursive()) {
+ log("Listing uncontrolled folder "
+ + folder.getFolderHierarchy()
+ + " from " + local.getAbsoluteFile());
+ UnmatchedFileMap submap =
+ new UnmatchedListingMap().init(local, folder);
+ submap.processUncontrolledItems();
+ }
+ }
+ }
+ }
+ }
+
+
}
1.6.2.3 +54 -24 ant/src/main/org/apache/tools/ant/taskdefs/optional/starteam/StarTeamTask.java
Index: StarTeamTask.java
===================================================================
RCS file: /home/cvs/ant/src/main/org/apache/tools/ant/taskdefs/optional/starteam/StarTeamTask.java,v
retrieving revision 1.6.2.2
retrieving revision 1.6.2.3
diff -u -w -u -r1.6.2.2 -r1.6.2.3
--- StarTeamTask.java 10 Feb 2003 14:25:20 -0000 1.6.2.2
+++ StarTeamTask.java 13 Feb 2003 13:59:53 -0000 1.6.2.3
@@ -53,14 +53,15 @@
*/
package org.apache.tools.ant.taskdefs.optional.starteam;
-import java.util.StringTokenizer;
-
+import com.starbase.starteam.BuildNumber;
import com.starbase.starteam.Server;
import com.starbase.starteam.StarTeamFinder;
+import com.starbase.starteam.TypeNames;
import com.starbase.starteam.User;
import com.starbase.starteam.View;
-
+import java.util.StringTokenizer;
import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.Project;
import org.apache.tools.ant.Task;
/**
@@ -114,6 +115,12 @@
*/
private Server server = null;
+ private void logStarteamVersion() {
+ log("StarTeam version: "+
+ BuildNumber.getDisplayString(), Project.MSG_DEBUG);
+ }
+
+
/////////////////////////////////////////////////////////
// GET/SET methods.
// Setters, of course are where ant user passes in values.
@@ -125,7 +132,7 @@
* @param servername a <code>String</code> value
* @see #setURL(String)
*/
- public void setServername(String servername) {
+ public final void setServername(String servername) {
this.servername = servername;
}
@@ -135,7 +142,7 @@
* @return the name of the StarTeam server
* @see #getURL()
*/
- public String getServername() {
+ public final String getServername() {
return this.servername;
}
@@ -145,7 +152,7 @@
* @param serverport port number to be set
* @see #setURL(String)
*/
- public void setServerport(String serverport) {
+ public final void setServerport(String serverport) {
this.serverport = serverport;
}
@@ -155,7 +162,7 @@
* @return the port number of the StarTeam connection
* @see #getURL()
*/
- public String getServerport() {
+ public final String getServerport() {
return this.serverport;
}
@@ -166,7 +173,7 @@
* @param projectname the name of the StarTeam project to be acted on
* @see #setURL(String)
*/
- public void setProjectname(String projectname) {
+ public final void setProjectname(String projectname) {
this.projectname = projectname;
}
@@ -176,7 +183,7 @@
* @return the name of the StarTeam project to be acted on
* @see #getURL()
*/
- public String getProjectname() {
+ public final String getProjectname() {
return this.projectname;
}
@@ -187,7 +194,7 @@
* @param projectname the name of the StarTeam view to be acted on
* @see #setURL(String)
*/
- public void setViewname(String viewname) {
+ public final void setViewname(String viewname) {
this.viewname = viewname;
}
@@ -197,7 +204,7 @@
* @return the name of the StarTeam view to be acted on
* @see #getURL()
*/
- public String getViewname() {
+ public final String getViewname() {
return this.viewname;
}
@@ -214,7 +221,7 @@
* @see #setProjectname(String)
* @see #setViewname(String)
*/
- public void setURL(String url) {
+ public final void setURL(String url) {
StringTokenizer t = new StringTokenizer(url, "/");
if (t.hasMoreTokens()) {
String unpw = t.nextToken();
@@ -248,7 +255,7 @@
* @see #getProjectname()
* @see #getViewname()
*/
- public String getURL() {
+ public final String getURL() {
return
this.servername + ":" +
this.serverport + "/" +
@@ -257,11 +264,20 @@
}
/**
+ * returns an URL string useful for interacting with many StarTeamFinder
+ * methods.
+ *
+ * @return the URL string for this task.
+ */
+ protected final String getViewURL() {
+ return getUserName() + ":" + getPassword() + "@" + getURL();
+ }
+ /**
* set the name of the StarTeam user, needed for the connection
*
* @param userName name of the user to be logged in
*/
- public void setUserName(String userName) {
+ public final void setUserName(String userName) {
this.userName = userName;
}
@@ -270,7 +286,7 @@
*
* @return the name of the StarTeam user
*/
- public String getUserName() {
+ public final String getUserName() {
return this.userName;
}
@@ -279,7 +295,7 @@
*
* @param password the password to be used for login
*/
- public void setPassword(String password) {
+ public final void setPassword(String password) {
this.password = password;
}
@@ -288,7 +304,7 @@
*
* @return the password used for login
*/
- public String getPassword() {
+ public final String getPassword() {
return this.password;
}
@@ -298,18 +314,27 @@
*
* @return a reference to the server
*/
- protected Server getServer() {
+ protected final Server getServer() {
return this.server;
}
/**
+ * returns a list of TypeNames known to the server.
+ *
+ * @return a reference to the server's TypeNames
+ */
+ protected final TypeNames getTypeNames() {
+ return this.server.getTypeNames();
+ }
+ /**
* Derived classes must override <code>createSnapshotView</code>
* defining the kind of configured view appropriate to its task.
*
* @param rawview the unconfigured <code>View</code>
* @return the snapshot <code>View</code> appropriately configured.
*/
- protected abstract View createSnapshotView(View rawview);
+ protected abstract View createSnapshotView(View rawview)
+ throws BuildException;
/**
* All subclasses will call on this method to open the view needed for
@@ -322,10 +347,15 @@
* @see #getServer()
*/
protected View openView() throws BuildException {
- View view =
- StarTeamFinder.openView(getUserName() + ":"
- + getPassword()
- + "@" + getURL());
+
+ logStarteamVersion();
+ View view = null;
+ try {
+ view = StarTeamFinder.openView(getViewURL());
+ } catch (Exception e) {
+ throw new BuildException(
+ "Failed to connect to " + getURL(), e);
+ }
if (null == view) {
throw new BuildException("Cannot find view" + getURL() +
@@ -344,7 +374,7 @@
* @param userID a user's ID
* @return the name of the user with ID userID
*/
- protected String getUserName(int userID) {
+ protected final String getUserName(int userID) {
User u = this.server.getUser(userID);
if (null == u) {
return "";
1.8.2.3 +330 -82 ant/src/main/org/apache/tools/ant/taskdefs/optional/starteam/TreeBasedTask.java
Index: TreeBasedTask.java
===================================================================
RCS file: /home/cvs/ant/src/main/org/apache/tools/ant/taskdefs/optional/starteam/TreeBasedTask.java,v
retrieving revision 1.8.2.2
retrieving revision 1.8.2.3
diff -u -w -u -r1.8.2.2 -r1.8.2.3
--- TreeBasedTask.java 10 Feb 2003 14:25:20 -0000 1.8.2.2
+++ TreeBasedTask.java 13 Feb 2003 13:59:53 -0000 1.8.2.3
@@ -1,7 +1,7 @@
/*
* The Apache Software License, Version 1.1
*
- * Copyright (c) 2001-2002 The Apache Software Foundation. All rights
+ * Copyright (c) 2001-2003 The Apache Software Foundation. All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -53,16 +53,18 @@
*/
package org.apache.tools.ant.taskdefs.optional.starteam;
-import java.util.Hashtable;
-import java.util.StringTokenizer;
-
import com.starbase.starteam.Folder;
+import com.starbase.starteam.Item;
import com.starbase.starteam.Label;
import com.starbase.starteam.StarTeamFinder;
import com.starbase.starteam.View;
-
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.StringTokenizer;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.DirectoryScanner;
+import org.apache.tools.ant.Project;
+import org.apache.tools.ant.ProjectComponent;
/**
* FileBasedTask.java
@@ -116,7 +118,7 @@
/**
* The local folder corresponding to starteamFolder. If not specified
- * the Star Team defalt folder will be used.
+ * the Star Team default folder will be used.
*/
private String rootLocalFolder = null;
@@ -150,6 +152,7 @@
*/
private boolean forced = false;
+ private Label labelInUse = null;
///////////////////////////////////////////////////////////////
// GET/SET methods.
@@ -179,23 +182,32 @@
* to which files are checked out; optional.
* If this is not supplied, then the StarTeam "default folder"
* associated with <tt>rootstarteamfolder</tt> is used.
- * @param rootLocalFolder the local folder that will mirror
+ *
+ * @param rootLocalFolder
+ * the local folder that will mirror
* this.rootStarteamFolder
+ *
+ * @see rootLocalFolder
*/
public void setRootLocalFolder(String rootLocalFolder) {
this.rootLocalFolder = rootLocalFolder;
}
+
+
/**
* Returns the local folder specified by the user,
- * corresponding to the starteam folder for this operation.
- * or null if not specified
+ * corresponding to the starteam folder for this operation
+ * or null if not specified.
+ *
* @return the local folder that mirrors this.rootStarteamFolder
+ * @see rootLocalFolder
*/
public String getRootLocalFolder() {
return this.rootLocalFolder;
}
+
/**
* Declare files to include using standard <tt>includes</tt> patterns; optional.
* @param includes A string of filter patterns to include. Separate the
@@ -223,6 +235,15 @@
}
/**
+ * if excludes have been specified, emit the list to the log
+ */
+ protected void logIncludes() {
+ if (this.DEFAULT_INCLUDESETTING != this.includes) {
+ log(" Includes specified: "+ this.includes);
+ }
+ }
+
+ /**
* Declare files to exclude using standard <tt>excludes</tt> patterns; optional.
* When filtering files, AntStarTeamCheckOut
* uses an unmodified version of <CODE>DirectoryScanner</CODE>'s
@@ -275,6 +296,16 @@
}
/**
+ * if excludes have been specified, emit the list to the log
+ */
+ protected void logExcludes() {
+ if (this.DEFAULT_EXCLUDESETTING != this.excludes) {
+ log(" Excludes specified: "+ this.excludes);
+ }
+ }
+
+
+ /**
* protected function to allow subclasses to set the label (or not).
* sets the StarTeam label
*
@@ -289,6 +320,10 @@
}
}
+ protected String getLabel() {
+ return this.label;
+ }
+
/**
* Get the value of recursive.
* @return value of recursive.
@@ -326,6 +361,49 @@
this.forced = v;
}
+ /**
+ * returns true if a label has been specified and it is a view label.
+ *
+ * @return true if a label has been specified and it is a view label
+ */
+ protected boolean isUsingViewLabel() {
+ return null != this.labelInUse &&
+ this.labelInUse.isViewLabel();
+ }
+ /**
+ * returns true if a label has been specified and it is a revision label.
+ *
+ * @return true if a label has been specified and it is a revision label
+ */
+ protected boolean isUsingRevisionLabel() {
+ return null != this.labelInUse &&
+ this.labelInUse.isRevisionLabel();
+ }
+
+ /**
+ * returns the label being used
+ *
+ * @return
+ */
+ protected Label getLabelInUse() {
+ return this.labelInUse;
+ }
+
+ /**
+ * show the label in the log and its type.
+ */
+ protected void logLabel() {
+ if (this.isUsingViewLabel()) {
+ log(" Using view label " + getLabel());
+ }
+ else if (this.isUsingRevisionLabel()) {
+ log(" Using revision label " + getLabel());
+ }
+ }
+
+
+
+
///////////////////////////////////////////////////////////////
// INCLUDE-EXCLUDE processing
///////////////////////////////////////////////////////////////
@@ -334,8 +412,10 @@
* Look if the file should be processed by the task.
* Don't process it if it fits no include filters or if
* it fits an exclude filter.
+ *
* @param pName the item name to look for being included.
- * @return whether the file should be checked out or not.
+ *
+ * @return whether the file should be processed or not.
*/
protected boolean shouldProcess(String pName) {
boolean includeIt = matchPatterns(getIncludes(), pName);
@@ -364,49 +444,144 @@
}
/**
- * This method does the work of opening the supplied Starteam view and
- * calling the <code>visit()</code> method to perform the task.
+ * Finds and opens the root starteam folder of the operation specified
+ * by this task. This will be one of the following cases:
*
- * @exception BuildException if any error occurs in the processing
- * @see <code>visit()</code>
- */
-
- public void execute() throws BuildException {
+ * @return Starteam's root folder for the operation.
+ * @exception BuildException
+ * if the root folder cannot be found in the repository
+ */
+ private final Folder configureRootStarteamFolder()
+ throws BuildException
+ {
+ Folder starteamrootfolder = null;
try {
- testPreconditions();
-
+ // no root local mapping has been specified.
View snapshot = openView();
// find the starteam folder specified to be the root of the
// operation. Throw if it can't be found.
- Folder starteamrootfolder =
+
+ starteamrootfolder =
StarTeamFinder.findFolder(snapshot.getRootFolder(),
this.rootStarteamFolder);
+ }
+ catch (BuildException e) {
+ throw e;
+ }
+ catch (Exception e) {
+ throw new BuildException(
+ "Unable to find root folder " + this.rootStarteamFolder +
+ " in repository at " + getURL(), e);
+
+ }
+
if (null == starteamrootfolder) {
throw new BuildException(
- "Unable to find root folder in repository.");
+ "Unable to find root folder " + this.rootStarteamFolder +
+ " in repository at " + getURL());
}
+ return starteamrootfolder;
+ }
+
+ /**
+ * Returns the local folder mapped to the given StarTeam root folder
+ * of the operation. There are two cases here, depending on whether
+ * <code>rootLocalFolder</code> is defined.
+ * If <code>rootLocalFolder</code> is defined, it will be used to
+ * establish a root mapping. Otherwise, the repository's default root
+ * folder will be used.
+ *
+ * @param starteamrootfolder
+ * root Starteam folder initialized for the operation
+ *
+ * @return the local folder corresponding to the root Starteam folder.
+ * @see findRootStarteamFolder
+ */
+ private final java.io.File getLocalRootMapping(Folder starteamrootfolder) {
// 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);
+ String localrootfolder;
+ if (null != this.rootLocalFolder) {
+ localrootfolder = rootLocalFolder;
+ }
+ else {
+ // either use default path or root local mapping,
+ // which is now embedded in the root folder
+ localrootfolder = starteamrootfolder.getPathFragment();
}
+ return new java.io.File(localrootfolder);
+
+ }
+
+ /**
+ * extenders should emit to the log an entry describing the parameters
+ * that will be used by this operation.
+ *
+ * @param starteamrootFolder
+ * root folder in StarTeam for the operation
+ * @param targetrootFolder
+ * root local folder for the operation (whether specified by the user or not.
+ */
+ protected abstract void logOperationDescription(
+ Folder starteamrootFolder, java.io.File targetrootFolder);
+
+ /**
+ * This method does the work of opening the supplied Starteam view and
+ * calling the <code>visit()</code> method to perform the task.
+ * Derived classes can customize the called methods
+ * <code>testPreconditions()</code> and <code>visit()</code>.
+ *
+ * @exception BuildException if any error occurs in the processing
+ * @see <code>testPreconditions()</code>
+ * @see <code>visit()</code>
+ */
+
+ public final void execute() throws BuildException {
+ try {
+
+ Folder starteamrootfolder = configureRootStarteamFolder();
+
+ // set the local folder.
+ java.io.File localrootfolder =
+ getLocalRootMapping(starteamrootfolder);
+
+ testPreconditions();
+
+ // Tell user what he is doing
+ logOperationDescription(starteamrootfolder, localrootfolder);
+
// Inspect everything in the root folder and then recursively
visit(starteamrootfolder, localrootfolder);
+
} catch (Exception e) {
throw new BuildException(e);
}
}
+ private void findLabel(View v) throws BuildException {
+ Label[] allLabels = v.getLabels();
+ for (int i = 0; i < allLabels.length; i++) {
+ Label stLabel = allLabels[i];
+ log("checking label " + stLabel.getName(), Project.MSG_DEBUG);
+ if (stLabel.getName().equals(this.label)) {
+ if (!stLabel.isRevisionLabel() && !stLabel.isViewLabel()) {
+ throw new BuildException("Unexpected label type.");
+ }
+ log("using label " + stLabel.getName(), Project.MSG_DEBUG);
+ this.labelInUse = stLabel;
+ return;
+ }
+ }
+ throw new BuildException("Error: label "
+ + this.label
+ + " does not exist in view "
+ + v.getFullName());
+
+ }
+
/**
* Helper method calls on the StarTeam API to retrieve an ID number
* for the specified view, corresponding to this.label.
@@ -418,32 +593,37 @@
*/
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();
+ findLabel(v);
+ return this.labelInUse.getID();
}
+ return -1;
}
- throw new BuildException("Error: label "
- + this.label
- + " does not exist in view");
+
+ protected int getIDofLabelInUse() {
+ if (null != this.labelInUse) {
+ return this.labelInUse.getID();
}
return -1;
}
-
/**
* 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
+ * @param rootStarteamFolder
+ * the StarTeam folderto be visited
+ * @param rootLocalFolder
+ * the local mapping of rootStarteamFolder
+ *
+ * @exception BuildException
*/
protected abstract void visit(Folder rootStarteamFolder,
java.io.File rootLocalFolder)
throws BuildException;
+
+
/**
* Derived classes must override this method to define tests for
* any preconditons required by the task. This method is called at
@@ -456,46 +636,114 @@
*/
protected abstract void testPreconditions() throws BuildException;
+
+ /**
+ * Return the full repository path name of a file. Surprisingly there's
+ * no method in com.starbase.starteam.File to provide this.
+ *
+ * @param remotefile the Star Team file whose path is to be returned
+ *
+ * @return the full repository path name of a file.
+ */
+ public static String getFullRepositoryPath(
+ com.starbase.starteam.File remotefile)
+ {
+ StringBuffer sb = new StringBuffer();
+ sb.append(remotefile.getParentFolderHierarchy())
+ .append(remotefile.getName());
+ return sb.toString();
+ }
+
/**
- * 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
- * @return an "identity" hashtable whose keys each represent a file or
- * directory in localFolder.
- */
- protected static Hashtable listLocalFiles(java.io.File localFolder) {
-
- Hashtable localFileList = new Hashtable();
- // 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 "").
+ * This class implements a map of existing local files to possibly
+ * existing repository files. The map is created by a TreeBasedTask
+ * upon recursing into a directory. Each local item is mapped to an
+ * unattached StarTeam object of the proper type, File->File and
+ * Directory->Folder.
+ *
+ * As the TreeBased does its work, it deletes from the map all items
+ * it has processed.
+ *
+ * When the TreeBased task processes all the items from the repository,
+ * whatever items left in the UnmatchedFileMap are uncontrolled items
+ * and can be processed as appropriate to the task. In the case of
+ * Checkouts, they can be optionally deleted from the local tree. In the
+ * case of Checkins they can optionally be added to the resository.
+ */
+ protected abstract class UnmatchedFileMap extends Hashtable {
+
+ /**
+ * initializes the UnmatchedFileMap with entries from the local folder
+ * These will be mapped to the corresponding StarTeam entry even though
+ * it will not, in fact, exist in the repository. But through it, it
+ * can be added, listed, etc.
+ *
+ * @param localFolder
+ * the local folder from which the mappings will be made.
+ * @param remoteFolder
+ * the corresponding StarTeam folder which will be processed.
+ */
+ UnmatchedFileMap init(java.io.File localFolder, Folder remoteFolder) {
+ if (!localFolder.exists()) {
+ return this;
+ }
- if (localFolder.exists()) {
String[] localFiles = localFolder.list();
+
for (int i = 0; i < localFiles.length; i++) {
- localFileList.put(localFolder.toString() +
- java.io.File.separatorChar + localFiles[i], "");
+ String fn = localFiles[i];
+ java.io.File localFile =
+ new java.io.File(localFolder, localFiles[i]).getAbsoluteFile();
+
+ log("adding " + localFile + " to UnmatchedFileMap",
+ Project.MSG_DEBUG);
+
+ if (localFile.isDirectory()) {
+ this.put(localFile, new Folder( remoteFolder, fn, fn));
}
+ else {
+ com.starbase.starteam.File remoteFile =
+ new com.starbase.starteam.File(remoteFolder);
+ remoteFile.setName(fn);
+ this.put(localFile, remoteFile);
}
- return localFileList;
+ }
+ return this;
}
/**
- * 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 localFiles a <code>Hashtable</code> value
- * @param thisfile file to remove from list.
- * @return true if file was removed, false if it wasn't found.
+ * remove an item found to be controlled from the map.
+ *
+ * @param localFile the local item found to be controlled.
*/
- protected boolean delistLocalFile(Hashtable localFiles, java.io.File thisfile) {
- return null != localFiles.remove(thisfile.toString());
+ void removeControlledItem(java.io.File localFile) {
+ if (isActive()) {
+ log("removing processed " + localFile.getAbsoluteFile() +
+ " from UnmatchedFileMap", Project.MSG_DEBUG);
+ this.remove(localFile.getAbsoluteFile());
}
}
+ /**
+ * override will perform the action appropriate for its task to perform
+ * on items which are on the local tree but not in StarTeam. It is
+ * assumed that this method will not be called until all the items in
+ * the corresponding folder have been processed, and that the internal
+ * map * will contain only uncontrolled items.
+ */
+ abstract void processUncontrolledItems() throws BuildException;
+
+ /**
+ * overrides must define this to declare how this method knows if it
+ * is active. This presents extra clock cycles when the functionality
+ * is not called for.
+ *
+ * @return True if this object is to perform its functionality.
+ */
+ abstract protected boolean isActive();
+ }
+}