1. /*
  2. * Copyright 2002-2004 The Apache Software Foundation
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. *
  16. */
  17. package org.apache.tools.ant.taskdefs.optional.starteam;
  18. import com.starbase.starteam.Folder;
  19. import com.starbase.starteam.Item;
  20. import com.starbase.starteam.Status;
  21. import com.starbase.starteam.View;
  22. import com.starbase.starteam.ViewConfiguration;
  23. import java.io.IOException;
  24. import java.util.Enumeration;
  25. import org.apache.tools.ant.BuildException;
  26. /**
  27. * Checks files into a StarTeam project.
  28. * Optionally adds files and in the local tree that
  29. * are not managed by the repository to its control.
  30. * Created: Sat Dec 15 20:26:07 2001
  31. *
  32. * @version 1.0
  33. *
  34. * @ant.task name="stcheckin" category="scm" product="Starteam"
  35. */
  36. public class StarTeamCheckin extends TreeBasedTask {
  37. public StarTeamCheckin() {
  38. // we want this to have a false default, unlike for Checkin.
  39. setRecursive(false);
  40. }
  41. private boolean createFolders = true;
  42. /**
  43. * The comment which will be stored with the checkin.
  44. */
  45. private String comment = null;
  46. /**
  47. * holder for the add Uncontrolled attribute. If true, all
  48. * local files not in StarTeam will be added to the repository.
  49. */
  50. private boolean addUncontrolled = false;
  51. /**
  52. * Sets the value of createFolders
  53. *
  54. * @param argCreateFolders Value to assign to this.createFolders
  55. */
  56. public void setCreateFolders(boolean argCreateFolders) {
  57. this.createFolders = argCreateFolders;
  58. }
  59. /**
  60. * Get the comment attribute for this operation
  61. * @return value of comment.
  62. */
  63. public String getComment() {
  64. return this.comment;
  65. }
  66. /**
  67. * Optional checkin comment to be saved with the file.
  68. * @param comment Value to assign to comment.
  69. */
  70. public void setComment(String comment) {
  71. this.comment = comment;
  72. }
  73. /**
  74. * Get the value of addUncontrolled.
  75. * @return value of addUncontrolled.
  76. */
  77. public boolean isAddUncontrolled() {
  78. return this.addUncontrolled;
  79. }
  80. /**
  81. * if true, any files or folders NOT in StarTeam will be
  82. * added to the repository. Defaults to "false".
  83. * @param addUncontrolled Value to assign to addUncontrolled.
  84. */
  85. public void setAddUncontrolled(boolean addUncontrolled) {
  86. this.addUncontrolled = addUncontrolled;
  87. }
  88. /**
  89. * This attribute tells whether unlocked files on checkin (so that
  90. * other users may access them) checkout or to leave the checkout status
  91. * alone (default).
  92. * @see #setUnlocked(boolean)
  93. */
  94. private int lockStatus = Item.LockType.UNCHANGED;
  95. /**
  96. * Set to do an unlocked checkout; optional, default is false;
  97. * If true, file will be unlocked so that other users may
  98. * change it. If false, lock status will not change.
  99. * @param v true means do an unlocked checkout
  100. * false means leave status alone.
  101. */
  102. public void setUnlocked(boolean v) {
  103. if (v) {
  104. this.lockStatus = Item.LockType.UNLOCKED;
  105. } else {
  106. this.lockStatus = Item.LockType.UNCHANGED;
  107. }
  108. }
  109. /**
  110. * Override of base-class abstract function creates an
  111. * appropriately configured view. For checkins this is
  112. * always the current or "tip" view.
  113. *
  114. * @param raw the unconfigured <code>View</code>
  115. * @return the snapshot <code>View</code> appropriately configured.
  116. */
  117. protected View createSnapshotView(View raw) {
  118. return new View(raw, ViewConfiguration.createTip());
  119. }
  120. /**
  121. * Implements base-class abstract function to define tests for
  122. * any preconditons required by the task.
  123. *
  124. * @exception BuildException thrown if both rootLocalFolder
  125. * and viewRootLocalFolder are defined
  126. */
  127. protected void testPreconditions() throws BuildException {
  128. }
  129. /**
  130. * Implements base-class abstract function to emit to the log an
  131. * entry describing the parameters that will be used by this operation.
  132. *
  133. * @param starteamrootFolder
  134. * root folder in StarTeam for the operation
  135. * @param targetrootFolder
  136. * root local folder for the operation
  137. * (whether specified by the user or not).
  138. */
  139. protected void logOperationDescription(
  140. Folder starteamrootFolder, java.io.File targetrootFolder) {
  141. log((this.isRecursive() ? "Recursive" : "Non-recursive")
  142. + " Checkin from"
  143. + (null == getRootLocalFolder() ? " (default): " : ": ")
  144. + targetrootFolder.getAbsolutePath());
  145. log("Checking in to: " + starteamrootFolder.getFolderHierarchy());
  146. logIncludes();
  147. logExcludes();
  148. if (this.lockStatus == Item.LockType.UNLOCKED) {
  149. log(" Items will be checked in unlocked.");
  150. } else {
  151. log(" Items will be checked in with no change in lock status.");
  152. }
  153. if (this.isForced()) {
  154. log(" Items will be checked in in accordance with repository "
  155. + "status and regardless of lock status.");
  156. } else {
  157. log(" Items will be checked in regardless of repository status "
  158. + "only if locked.");
  159. }
  160. }
  161. /**
  162. * Implements base-class abstract function to perform the checkout
  163. * operation on the files in each folder of the tree.
  164. *
  165. * @param starteamFolder the StarTeam folder to which files
  166. * will be checked in
  167. * @param targetFolder local folder from which files will be checked in
  168. * @exception BuildException if any error occurs
  169. */
  170. protected void visit(Folder starteamFolder, java.io.File targetFolder)
  171. throws BuildException {
  172. try {
  173. if (null != getRootLocalFolder()) {
  174. starteamFolder.setAlternatePathFragment(
  175. targetFolder.getAbsolutePath());
  176. }
  177. Folder[] foldersList = starteamFolder.getSubFolders();
  178. Item[] stFiles = starteamFolder.getItems(getTypeNames().FILE);
  179. // note, it's important to scan the items BEFORE we make the
  180. // UnmatchedFileMap because that creates a bunch of NEW
  181. // folders and files (unattached to repository) and we
  182. // don't want to include those in our traversal.
  183. UnmatchedFileMap ufm =
  184. new CheckinMap().init(
  185. targetFolder.getAbsoluteFile(), starteamFolder);
  186. for (int i = 0, size = foldersList.length; i < size; i++) {
  187. Folder stFolder = foldersList[i];
  188. java.io.File subfolder =
  189. new java.io.File(targetFolder, stFolder.getName());
  190. ufm.removeControlledItem(subfolder);
  191. if (isRecursive()) {
  192. visit(stFolder, subfolder);
  193. }
  194. }
  195. for (int i = 0, size = stFiles.length; i < size; i++) {
  196. com.starbase.starteam.File stFile =
  197. (com.starbase.starteam.File) stFiles[i];
  198. processFile(stFile);
  199. ufm.removeControlledItem(
  200. new java.io.File(targetFolder, stFile.getName()));
  201. }
  202. if (this.addUncontrolled) {
  203. ufm.processUncontrolledItems();
  204. }
  205. } catch (IOException e) {
  206. throw new BuildException(e);
  207. }
  208. }
  209. /**
  210. * provides a string showing from and to full paths for logging
  211. *
  212. * @param remotefile the Star Team file being processed.
  213. *
  214. * @return a string showing from and to full paths
  215. */
  216. private String describeCheckin(com.starbase.starteam.File remotefile) {
  217. StringBuffer sb = new StringBuffer();
  218. sb.append(remotefile.getFullName())
  219. .append(" --> ")
  220. .append(getFullRepositoryPath(remotefile));
  221. return sb.toString();
  222. }
  223. /**
  224. * Processes (checks-out) <code>stFiles</code>files from StarTeam folder.
  225. *
  226. * @param eachFile repository file to process
  227. * @param targetFolder a java.io.File (Folder) to work
  228. * @throws IOException when StarTeam API fails to work with files
  229. */
  230. private void processFile(com.starbase.starteam.File eachFile)
  231. throws IOException {
  232. String filename = eachFile.getName();
  233. // If the file doesn't pass the include/exclude tests, skip it.
  234. if (!shouldProcess(filename)) {
  235. log("Excluding " + getFullRepositoryPath(eachFile));
  236. return;
  237. }
  238. boolean checkin = true;
  239. int fileStatus = (eachFile.getStatus());
  240. // We try to update the status once to give StarTeam
  241. // another chance.
  242. if (fileStatus == Status.MERGE || fileStatus == Status.UNKNOWN) {
  243. eachFile.updateStatus(true, true);
  244. fileStatus = (eachFile.getStatus());
  245. }
  246. if (fileStatus == Status.MODIFIED) {
  247. log("Checking in: " + describeCheckin(eachFile));
  248. } else if (fileStatus == Status.MISSING) {
  249. log("Local file missing: " + describeCheckin(eachFile));
  250. checkin = false;
  251. } else {
  252. if (isForced()) {
  253. log("Forced checkin of " + describeCheckin(eachFile)
  254. + " over status " + Status.name(fileStatus));
  255. } else {
  256. log("Skipping: " + getFullRepositoryPath(eachFile)
  257. + " - status: " + Status.name(fileStatus));
  258. checkin = false;
  259. }
  260. }
  261. if (checkin) {
  262. eachFile.checkin(this.comment, this.lockStatus,
  263. this.isForced(), true, true);
  264. }
  265. }
  266. /**
  267. * handles the deletion of uncontrolled items
  268. */
  269. private class CheckinMap extends UnmatchedFileMap {
  270. protected boolean isActive() {
  271. return StarTeamCheckin.this.addUncontrolled;
  272. }
  273. /**
  274. * This override adds all its members to the repository. It is assumed
  275. * that this method will not be called until all the items in the
  276. * corresponding folder have been processed, and that the internal map
  277. * will contain only uncontrolled items.
  278. */
  279. void processUncontrolledItems() throws BuildException {
  280. if (this.isActive()) {
  281. Enumeration e = this.keys();
  282. while (e.hasMoreElements()) {
  283. java.io.File local = (java.io.File) e.nextElement();
  284. Item remoteItem = (Item) this.get(local);
  285. remoteItem.update();
  286. // once we find a folder that isn't in the repository,
  287. // we know we can add it.
  288. if (local.isDirectory()) {
  289. Folder folder = (Folder) remoteItem;
  290. log("Added uncontrolled folder "
  291. + folder.getFolderHierarchy()
  292. + " from " + local.getAbsoluteFile());
  293. if (isRecursive()) {
  294. UnmatchedFileMap submap =
  295. new CheckinMap().init(local, folder);
  296. submap.processUncontrolledItems();
  297. }
  298. } else {
  299. com.starbase.starteam.File remoteFile =
  300. (com.starbase.starteam.File) remoteItem;
  301. log("Added uncontrolled file "
  302. + TreeBasedTask.getFullRepositoryPath(remoteFile)
  303. + " from " + local.getAbsoluteFile());
  304. }
  305. }
  306. }
  307. }
  308. }
  309. }