blob: 332697906485d2c5260397da1770ae5132a0b01c [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package org.apache.tools.ant.taskdefs.optional.starteam;
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.util.Enumeration;
import org.apache.tools.ant.BuildException;
/**
* 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
*
* @version 1.0
*
* @ant.task name="stcheckin" category="scm" product="Starteam"
*/
public class StarTeamCheckin extends TreeBasedTask {
/**
* Constructor for StarTeamCheckin.
*/
public StarTeamCheckin() {
// we want this to have a false default, unlike for Checkin.
setRecursive(false);
}
private boolean createFolders = true;
/**
* The comment which will be stored with the checkin.
*/
private String comment = null;
/**
* holder for the add Uncontrolled attribute. If true, all
* local files not in StarTeam will be added to the repository.
*/
private boolean addUncontrolled = false;
/**
* Sets the value of createFolders
*
* @param argCreateFolders Value to assign to this.createFolders
*/
public void setCreateFolders(boolean argCreateFolders) {
this.createFolders = argCreateFolders;
}
/**
* Get the comment attribute for this operation
* @return value of comment.
*/
public String getComment() {
return this.comment;
}
/**
* Optional checkin comment to be saved with the file.
* @param comment Value to assign to comment.
*/
public void setComment(String comment) {
this.comment = comment;
}
/**
* Get the value of addUncontrolled.
* @return value of addUncontrolled.
*/
public boolean isAddUncontrolled() {
return this.addUncontrolled;
}
/**
* if true, any files or folders NOT in StarTeam will be
* added to the repository. Defaults to "false".
* @param addUncontrolled Value to assign to addUncontrolled.
*/
public void setAddUncontrolled(boolean addUncontrolled) {
this.addUncontrolled = addUncontrolled;
}
/**
* This attribute tells whether unlocked files on checkin (so that
* other users may access them) checkout or to leave the checkout status
* alone (default).
* @see #setUnlocked(boolean)
*/
private int lockStatus = Item.LockType.UNCHANGED;
/**
* Set to do an unlocked checkout; optional, default is false;
* If true, file will be unlocked so that other users may
* change it. If false, lock status will not change.
* @param v true means do an unlocked checkout
* false means leave status alone.
*/
public void setUnlocked(boolean v) {
if (v) {
this.lockStatus = Item.LockType.UNLOCKED;
} else {
this.lockStatus = Item.LockType.UNCHANGED;
}
}
/**
* Override of base-class abstract function creates an
* appropriately configured view. For checkins this is
* always the current or "tip" view.
*
* @param raw the unconfigured <code>View</code>
* @return the snapshot <code>View</code> appropriately configured.
*/
protected View createSnapshotView(View raw) {
return new View(raw, ViewConfiguration.createTip());
}
/**
* Implements base-class abstract function to define tests for
* any preconditons required by the task.
*
* @exception BuildException thrown if both rootLocalFolder
* and viewRootLocalFolder are defined
*/
protected void testPreconditions() throws BuildException {
}
/**
* 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.");
}
}
/**
* Implements base-class abstract function to perform the checkout
* operation on the files in each folder of the tree.
*
* @param starteamFolder the StarTeam folder to which files
* will be checked in
* @param targetFolder local folder from which files will be checked in
* @exception BuildException if any error occurs
*/
protected void visit(Folder starteamFolder, java.io.File targetFolder)
throws BuildException {
try {
if (null != getRootLocalFolder()) {
starteamFolder.setAlternatePathFragment(
targetFolder.getAbsolutePath());
}
Folder[] foldersList = starteamFolder.getSubFolders();
Item[] stFiles = starteamFolder.getItems(getTypeNames().FILE);
// 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.
UnmatchedFileMap ufm =
new CheckinMap().init(
targetFolder.getAbsoluteFile(), starteamFolder);
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());
ufm.removeControlledItem(subfolder);
if (isRecursive()) {
visit(stFolder, subfolder);
}
}
for (int i = 0, size = stFiles.length; i < size; i++) {
com.starbase.starteam.File stFile =
(com.starbase.starteam.File) stFiles[i];
processFile(stFile);
ufm.removeControlledItem(
new java.io.File(targetFolder, stFile.getName()));
}
if (this.addUncontrolled) {
ufm.processUncontrolledItems();
}
} catch (IOException e) {
throw new BuildException(e);
}
}
/**
* 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 processFile(com.starbase.starteam.File eachFile)
throws IOException {
String filename = eachFile.getName();
// If the file doesn't pass the include/exclude tests, skip it.
if (!shouldProcess(filename)) {
log("Excluding " + getFullRepositoryPath(eachFile));
return;
}
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);
}
}
/**
* handles the deletion of uncontrolled items
*/
private class CheckinMap extends UnmatchedFileMap {
protected boolean isActive() {
return StarTeamCheckin.this.addUncontrolled;
}
/**
* 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()) {
UnmatchedFileMap submap =
new CheckinMap().init(local, folder);
submap.processUncontrolledItems();
}
} else {
com.starbase.starteam.File remoteFile =
(com.starbase.starteam.File) remoteItem;
log("Added uncontrolled file "
+ TreeBasedTask.getFullRepositoryPath(remoteFile)
+ " from " + local.getAbsoluteFile());
}
}
}
}
}
}