From b50fd138f8b9c08dc04ff70319e953d2450780a6 Mon Sep 17 00:00:00 2001 From: Conor MacNeill Date: Sun, 9 Feb 2003 12:59:13 +0000 Subject: [PATCH] VSS Task refactor PR: 16910 Submitted by: Jesse Stockall git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@274025 13f79535-47bb-0310-9956-ffa450edef68 --- build.xml | 2 + .../testcases/taskdefs/optional/vss/vss.xml | 46 ++ .../ant/taskdefs/optional/vss/MSVSS.java | 467 +++++++++++++----- .../ant/taskdefs/optional/vss/MSVSSADD.java | 139 ++---- .../taskdefs/optional/vss/MSVSSCHECKIN.java | 150 ++---- .../taskdefs/optional/vss/MSVSSCHECKOUT.java | 167 ++----- .../ant/taskdefs/optional/vss/MSVSSCP.java | 63 +-- .../taskdefs/optional/vss/MSVSSCREATE.java | 126 ++--- .../taskdefs/optional/vss/MSVSSConstants.java | 115 +++++ .../ant/taskdefs/optional/vss/MSVSSGET.java | 228 ++------- .../taskdefs/optional/vss/MSVSSHISTORY.java | 287 +++-------- .../ant/taskdefs/optional/vss/MSVSSLABEL.java | 170 ++----- .../ant/taskdefs/optional/vss/MSVSSTest.java | 458 +++++++++++++++++ 13 files changed, 1268 insertions(+), 1150 deletions(-) create mode 100644 src/etc/testcases/taskdefs/optional/vss/vss.xml create mode 100644 src/main/org/apache/tools/ant/taskdefs/optional/vss/MSVSSConstants.java create mode 100644 src/testcases/org/apache/tools/ant/taskdefs/optional/vss/MSVSSTest.java diff --git a/build.xml b/build.xml index a2554fefc..c9230f985 100644 --- a/build.xml +++ b/build.xml @@ -1600,6 +1600,8 @@ unless="tests.and.ant.share.classloader"/> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/vss/MSVSS.java b/src/main/org/apache/tools/ant/taskdefs/optional/vss/MSVSS.java index e1c5e5655..eb5e54669 100644 --- a/src/main/org/apache/tools/ant/taskdefs/optional/vss/MSVSS.java +++ b/src/main/org/apache/tools/ant/taskdefs/optional/vss/MSVSS.java @@ -1,7 +1,7 @@ /* * The Apache Software License, Version 1.1 * - * Copyright (c) 2000-2002 The Apache Software Foundation. All rights + * Copyright (c) 2000-2003 The Apache Software Foundation. All rights * reserved. * * Redistribution and use in source and binary forms, with or without @@ -54,7 +54,13 @@ package org.apache.tools.ant.taskdefs.optional.vss; - +import java.io.File; +import java.io.IOException; +import java.text.DateFormat; +import java.text.ParseException; +import java.util.Calendar; +import java.util.Date; +import java.util.GregorianCalendar; import org.apache.tools.ant.BuildException; import org.apache.tools.ant.Project; @@ -77,36 +83,72 @@ import org.apache.tools.ant.types.Commandline; * * @author Craig Cottingham * @author Andrew Everitt + * @author Jesse Stockall */ -public abstract class MSVSS extends Task { +public abstract class MSVSS extends Task implements MSVSSConstants { - private String m_SSDir = ""; + private String m_SSDir = null; private String m_vssLogin = null; private String m_vssPath = null; private String m_serverPath = null; + /** Version */ + protected String m_Version = null; + /** Date */ + protected String m_Date = null; + /** Label */ + protected String m_Label = null; + /** Auto response */ + protected String m_AutoResponse = null; + /** Local path */ + protected String m_LocalPath = null; + /** Comment */ + protected String m_Comment = null; + /** From label */ + protected String m_FromLabel = null; + /** To label */ + protected String m_ToLabel = null; + /** Output file name */ + protected String m_OutputFileName = null; + /** User */ + protected String m_User = null; + /** From date */ + protected String m_FromDate = null; + /** To date */ + protected String m_ToDate = null; + /** History style */ + protected String m_Style = null; + /** Quiet defaults to false */ + protected boolean m_Quiet = false; + /** Recursive defaults to false */ + protected boolean m_Recursive = false; + /** Writable defaults to false */ + protected boolean m_Writable = false; + /** Fail on error defaults to true */ + protected boolean m_FailOnError = true; + /** Number of days offset for History */ + protected int m_NumDays = Integer.MIN_VALUE; + /** Date format for History */ + protected DateFormat m_DateFormat = DateFormat.getDateInstance(DateFormat.SHORT); + + /** + * Each sub-class must implemnt this method and return the constructed + * command line to be executed. It is up to the sub-task to determine the + * required attrubutes and their order. + * + * @return The Constructed command line. + */ + abstract Commandline buildCmdLine(); + /** - * directory where ss.exe resides; optional. + * Directory where ss.exe resides; optional. * By default the task expects it to be in the PATH. * - * @param dir the directory containing ss.exe + * @param dir The directory containing ss.exe. */ public final void setSsdir(String dir) { m_SSDir = Project.translatePath(dir); } - - /** - * Builds and returns the command string to execute ss.exe - */ - public final String getSSCommand() { - String toReturn = m_SSDir; - if (!toReturn.equals("") && !toReturn.endsWith("\\")) { - toReturn += "\\"; - } - toReturn += SS_EXE; - - return toReturn; - } /** * The login to use when accessing VSS, formatted as "username,password"; @@ -115,32 +157,20 @@ public abstract class MSVSS extends Task { * You can omit the password if your database is not password protected. * if you have a password and omit it, Ant/VSS will hang. * - * @param login the login string to use + * @param login The login string to use. */ public final void setLogin(String login) { m_vssLogin = login; } /** - * the appropriate login command if the 'login' attribute was specified, otherwise an empty string - */ - public void getLoginCommand(Commandline cmd) { - if (m_vssLogin == null) { - return; - } else { - cmd.createArgument().setValue(FLAG_LOGIN + m_vssLogin); - } - } - - /** - * SourceSafe path which specifies the project/file(s) you wish to - * perform the action on; required. You should not specify the leading dollar-sign - - * it is prepended by Ant automatically. - *

- * Ant can't cope with a '$' sign in an attribute so we have to add it here. - * Also we strip off any 'vss://' prefix which is an XMS special and should probably be removed! - * @todo dont add a $ prefix if it has one - * @param vssPath + * SourceSafe path which specifies the project/file(s) you wish to perform + * the action on; required.

+ * + * Also we strip off any 'vss://' prefix which is an XMS special and should + * probably be removed! + * + * @param vssPath The VSS project path. */ public final void setVsspath(String vssPath) { String projectPath; @@ -158,117 +188,314 @@ public abstract class MSVSS extends Task { } /** - * @return m_vssPath + * Set the directory where srssafe.ini resides; optional. + * + * @param serverPath The path to the VSS server. + */ + public final void setServerpath(String serverPath) { + m_serverPath = serverPath; + } + + /** + * Executes the task.
+ * Builds a command line to execute ss.exe and then calls Exec's run method + * to execute the command line. + * @throws BuildException + */ + public void execute() + throws BuildException { + int result = 0; + Commandline commandLine = buildCmdLine(); + result = run(commandLine); + if (result != 0 && getFailOnError()) { + String msg = "Failed executing: " + commandLine.toString() + + " With a return code of " + result; + throw new BuildException(msg, getLocation()); + } + } + + /** + * Gets the sscommand string. "ss" or "c:\path\to\ss" + * + * @return The path to ss.exe or just ss if sscommand is not set. + */ + public String getSSCommand() { + if (m_SSDir == null) { + return SS_EXE; + } + return m_SSDir.endsWith(File.separator) ? m_SSDir + SS_EXE : m_SSDir + + File.separator + SS_EXE; + } + + /** + * Gets the vssserverpath string. + * + * @return null if vssserverpath is not set. */ - public String getVsspath() { + protected String getVsspath() { return m_vssPath; } /** - * Set the directory where srssafe.ini resides; optional. - * @param serverPath + * Gets the quiet string. -O- + * + * @return An empty string if quiet is not set or is false. */ - public final void setServerpath(String serverPath) { - m_serverPath = serverPath; + protected String getQuiet() { + return m_Quiet ? FLAG_QUIET : ""; } - protected int run(Commandline cmd) { - try { - Execute exe = new Execute(new LogStreamHandler(this, - Project.MSG_INFO, - Project.MSG_WARN)); + /** + * Gets the recursive string. "-R" + * + * @return An empty string if recursive is not set or is false. + */ + protected String getRecursive() { + return m_Recursive ? FLAG_RECURSION : ""; + } - // If location of ss.ini is specified we need to set the - // environment-variable SSDIR to this value - if (m_serverPath != null) { - String[] env = exe.getEnvironment(); - if (env == null) { - env = new String[0]; - } - String[] newEnv = new String[env.length + 1]; - for (int i = 0; i < env.length ; i++) { - newEnv[i] = env[i]; - } - newEnv[env.length] = "SSDIR=" + m_serverPath; + /** + * Gets the writable string. "-W" + * + * @return An empty string if writable is not set or is false. + */ + protected String getWritable() { + return m_Writable ? FLAG_WRITABLE : ""; + } - exe.setEnvironment(newEnv); + /** + * Gets the label string. "-Lbuild1" + * + * @return An empty string if label is not set. + */ + protected String getLabel() { + return m_Label != null ? FLAG_LABEL + m_Label : ""; + } + + /** + * Gets the style string. "-Lbuild1" + * + * @return An empty string if label is not set. + */ + protected String getStyle() { + return m_Style != null ? m_Style : ""; + } + + /** + * Gets the version string. Returns the first specified of version "-V1.0", + * date "-Vd01.01.01", label "-Vlbuild1". + * + * @return An empty string if a version is not set. + */ + protected String getVersion() { + if (m_Version != null) { + return FLAG_VERSION + m_Version; + } else if (m_Date != null) { + return FLAG_VERSION_DATE + m_Date; + } else if (m_Label != null) { + return FLAG_VERSION_LABEL + m_Label; + } else { + return ""; + } + } + + /** + * Gets the localpath string. "-GLc:\source"

+ * + * The localpath is created if it didn't exist. + * + * @return An empty string if localpath is not set. + */ + protected String getLocalpath() { + if (m_LocalPath == null) { + return ""; + } else { + // make sure m_LocalDir exists, create it if it doesn't + File dir = getProject().resolveFile(m_LocalPath); + if (! dir.exists()) { + boolean done = dir.mkdirs(); + if (! done) { + String msg = "Directory " + m_LocalPath + " creation was not " + + "successful for an unknown reason"; + throw new BuildException(msg, getLocation()); + } + getProject().log("Created dir: " + dir.getAbsolutePath()); } - - exe.setAntRun(getProject()); - exe.setWorkingDirectory(getProject().getBaseDir()); - exe.setCommandline(cmd.getCommandline()); - return exe.execute(); - } catch (java.io.IOException e) { - throw new BuildException(e, getLocation()); + return FLAG_OVERRIDE_WORKING_DIR + m_LocalPath; } } /** - * Constant for the thing to execute + * Gets the comment string. "-Ccomment text" + * + * @return A comment of "-" if comment is not set. + */ + protected String getComment() { + return m_Comment != null ? FLAG_COMMENT + m_Comment : FLAG_COMMENT + "-"; + } + + /** + * Gets the auto response string. This can be Y "-I-Y" or N "-I-N". + * + * @return The default value "-I-" if autoresponse is not set. */ - private static final String SS_EXE = "ss"; - /** */ - public static final String PROJECT_PREFIX = "$"; + protected String getAutoresponse() { + if (m_AutoResponse == null) { + return FLAG_AUTORESPONSE_DEF; + } else if (m_AutoResponse.equalsIgnoreCase("Y")) { + return FLAG_AUTORESPONSE_YES; + } else if (m_AutoResponse.equalsIgnoreCase("N")) { + return FLAG_AUTORESPONSE_NO; + } else { + return FLAG_AUTORESPONSE_DEF; + } + } /** - * The 'CP' command + * Gets the login string. This can be user and password, "-Yuser,password" + * or just user "-Yuser". + * + * @return An empty string if login is not set. */ - public static final String COMMAND_CP = "CP"; + protected String getLogin() { + return m_vssLogin != null ? FLAG_LOGIN + m_vssLogin : ""; + } + /** - * The 'Add' command + * Gets the output file string. "-Ooutput.file" + * + * @return An empty string if user is not set. */ - public static final String COMMAND_ADD = "Add"; + protected String getOutput() { + return m_OutputFileName != null ? FLAG_OUTPUT + m_OutputFileName : ""; + } + /** - * The 'Get' command + * Gets the user string. "-Uusername" + * + * @return An empty string if user is not set. */ - public static final String COMMAND_GET = "Get"; + protected String getUser() { + return m_User != null ? FLAG_USER + m_User : ""; + } + /** - * The 'Checkout' command + * Gets the version string. This can be to-from "-VLbuild2~Lbuild1", from + * "~Lbuild1" or to "-VLbuild2". + * + * @return An empty string if neither tolabel or fromlabel are set. */ - public static final String COMMAND_CHECKOUT = "Checkout"; + protected String getVersionLabel() { + if (m_FromLabel == null && m_ToLabel == null) { + return ""; + } + if (m_FromLabel != null && m_ToLabel != null) { + return FLAG_VERSION_LABEL + m_ToLabel + VALUE_FROMLABEL + m_FromLabel; + } else if (m_FromLabel != null) { + return FLAG_VERSION + VALUE_FROMLABEL + m_FromLabel; + } else { + return FLAG_VERSION_LABEL + m_ToLabel; + } + } + /** - * The 'Checkin' command + * Gets the Version date string. + * @return An empty string is neither Todate or from date are set. + * @throws BuildException */ - public static final String COMMAND_CHECKIN = "Checkin"; + protected String getVersionDate() throws BuildException { + if (m_FromDate == null && m_ToDate == null + && m_NumDays == Integer.MIN_VALUE) { + return ""; + } + if (m_FromDate != null && m_ToDate != null) { + return FLAG_VERSION_DATE + m_ToDate + VALUE_FROMDATE + m_FromDate; + } else if (m_ToDate != null && m_NumDays != Integer.MIN_VALUE) { + try { + return FLAG_VERSION_DATE + m_ToDate + VALUE_FROMDATE + + calcDate(m_ToDate, m_NumDays); + } catch (ParseException ex) { + String msg = "Error parsing date: " + m_ToDate; + throw new BuildException(msg, getLocation()); + } + } else if (m_FromDate != null && m_NumDays != Integer.MIN_VALUE) { + try { + return FLAG_VERSION_DATE + calcDate(m_FromDate, m_NumDays) + + VALUE_FROMDATE + m_FromDate; + } catch (ParseException ex) { + String msg = "Error parsing date: " + m_FromDate; + throw new BuildException(msg, getLocation()); + } + } else { + return m_FromDate != null ? FLAG_VERSION + VALUE_FROMDATE + + m_FromDate : FLAG_VERSION_DATE + m_ToDate; + } + } + /** - * The 'Label' command + * Gets the value of the fail on error flag. This is only used by execute + * when checking the return code. + * + * @return True if the FailOnError flag has been set. */ - public static final String COMMAND_LABEL = "Label"; + private boolean getFailOnError() { + return m_FailOnError; + } + /** - * The 'History' command + * Sets up the required environment and executes the command line. + * + * @param cmd The command line to execute. + * @return The return code from the exec'd process. */ - public static final String COMMAND_HISTORY = "History"; - /** - * The 'Create' command + private int run(Commandline cmd) { + try { + Execute exe = new Execute(new LogStreamHandler(this, + Project.MSG_INFO, + Project.MSG_WARN)); + + // If location of ss.ini is specified we need to set the + // environment-variable SSDIR to this value + if (m_serverPath != null) { + String[] env = exe.getEnvironment(); + if (env == null) { + env = new String[0]; + } + String[] newEnv = new String[env.length + 1]; + for (int i = 0; i < env.length; i++) { + newEnv[i] = env[i]; + } + newEnv[env.length] = "SSDIR=" + m_serverPath; + + exe.setEnvironment(newEnv); + } + + exe.setAntRun(getProject()); + exe.setWorkingDirectory(getProject().getBaseDir()); + exe.setCommandline(cmd.getCommandline()); + return exe.execute(); + } catch (IOException e) { + throw new BuildException(e, getLocation()); + } + } + + /** + * Calculates the start date for version comparison. + *

+ * Calculates the date numDay days earlier than startdate. + * @param fromDate The start date. + * @param numDays The number of days to add. + * @return The calculated date. + * @throws ParseException */ - public static final String COMMAND_CREATE = "Create"; - - - /** */ - public static final String FLAG_LOGIN = "-Y"; - /** */ - public static final String FLAG_OVERRIDE_WORKING_DIR = "-GL"; - /** */ - public static final String FLAG_AUTORESPONSE_DEF = "-I-"; - /** */ - public static final String FLAG_AUTORESPONSE_YES = "-I-Y"; - /** */ - public static final String FLAG_AUTORESPONSE_NO = "-I-N"; - /** */ - public static final String FLAG_RECURSION = "-R"; - /** */ - public static final String FLAG_VERSION = "-V"; - /** */ - public static final String FLAG_VERSION_DATE = "-Vd"; - /** */ - public static final String FLAG_VERSION_LABEL = "-VL"; - /** */ - public static final String FLAG_WRITABLE = "-W"; - /** */ - public static final String VALUE_NO = "-N"; - /** */ - public static final String VALUE_YES = "-Y"; - /** */ - public static final String FLAG_QUIET = "-O-"; + private String calcDate(String fromDate, int numDays) throws ParseException { + String toDate = null; + Date currdate = new Date(); + Calendar calend = new GregorianCalendar(); + currdate = m_DateFormat.parse(fromDate); + calend.setTime(currdate); + calend.add(Calendar.DATE, numDays); + toDate = m_DateFormat.format(calend.getTime()); + return toDate; + } } - diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/vss/MSVSSADD.java b/src/main/org/apache/tools/ant/taskdefs/optional/vss/MSVSSADD.java index 5eebc788b..9836df003 100644 --- a/src/main/org/apache/tools/ant/taskdefs/optional/vss/MSVSSADD.java +++ b/src/main/org/apache/tools/ant/taskdefs/optional/vss/MSVSSADD.java @@ -1,7 +1,7 @@ /* * The Apache Software License, Version 1.1 * - * Copyright (c) 2002 The Apache Software Foundation. All rights + * Copyright (c) 2002-2003 The Apache Software Foundation. All rights * reserved. * * Redistribution and use in source and binary forms, with or without @@ -63,34 +63,25 @@ import org.apache.tools.ant.types.Path; * Based on the VSS Checkin code by Martin Poeschl * * @author Nigel Magnay + * @author Jesse Stockall + * * @ant.task name="vssadd" category="scm" */ public class MSVSSADD extends MSVSS { - private String m_LocalPath = null; - private boolean m_Recursive = false; - private boolean m_Writable = false; - private String m_AutoResponse = null; - private String m_Comment = "-"; - /** - * Executes the task. - *

- * Builds a command line to execute ss and then calls Exec's run method - * to execute the command line. + * Builds a command line to execute ss. + * @return The constructed commandline. */ - public void execute() throws BuildException { + protected Commandline buildCmdLine() { Commandline commandLine = new Commandline(); - int result = 0; - // first off, make sure that we've got a command and a localPath ... - if (getLocalPath() == null) { + // first off, make sure that we've got a command and a localPath ... + if (getLocalpath() == null) { String msg = "localPath attribute must be set!"; throw new BuildException(msg, getLocation()); } - // now look for illegal combinations of things ... - // build the command line from what we got the format is // ss Add VSS items [-B] [-C] [-D-] [-H] [-I-] [-K] [-N] [-O] [-R] [-W] [-Y] [-?] // as specified in the SS.EXE help @@ -98,126 +89,76 @@ public class MSVSSADD extends MSVSS { commandLine.createArgument().setValue(COMMAND_ADD); // VSS items - commandLine.createArgument().setValue(getLocalPath()); + commandLine.createArgument().setValue(getLocalpath()); // -I- or -I-Y or -I-N - getAutoresponse(commandLine); + commandLine.createArgument().setValue(getAutoresponse()); // -R - getRecursiveCommand(commandLine); + commandLine.createArgument().setValue(getRecursive()); // -W - getWritableCommand(commandLine); + commandLine.createArgument().setValue(getWritable()); // -Y - getLoginCommand(commandLine); + commandLine.createArgument().setValue(getLogin()); // -C - commandLine.createArgument().setValue("-C" + getComment()); + commandLine.createArgument().setValue(getComment()); - result = run(commandLine); - if (result != 0) { - String msg = "Failed executing: " + commandLine.toString(); - throw new BuildException(msg, getLocation()); - } + return commandLine; } /** - * Set behaviour recursive or non-recursive + * Returns the local path without the flag.; required + * @todo See why this returns the local path without the flag. + * @return The local path value. */ - public void setRecursive(boolean recursive) { - m_Recursive = recursive; + protected String getLocalpath() { + return m_LocalPath; } /** - * @return the 'recursive' command if the attribute was 'true', otherwise an empty string + * Flag to tell the task to recurse down the tree; + * optional, default false. + * @param recursive The boolean value for recursive. */ - public void getRecursiveCommand(Commandline cmd) { - if (!m_Recursive) { - return; - } else { - cmd.createArgument().setValue(FLAG_RECURSION); - } + public void setRecursive(boolean recursive) { + m_Recursive = recursive; } /** - * Whether or not to leave added files writable. - * Default is false. + * Leave checked in files writable? Default: false. + * @param argWritable The boolean value for writable. */ public final void setWritable(boolean argWritable) { m_Writable = argWritable; } /** - * The 'make writable' command if the attribute was true, - * otherwise an empty string. + * Set the autoresponce behaviour; optional. + *

+ * Valid options are Y and N. + * @param response The auto response value. */ - public void getWritableCommand(Commandline cmd) { - if (!m_Writable) { - return; - } else { - cmd.createArgument().setValue(FLAG_WRITABLE); - } - } - - /** - * What to respond with (sets the -I option). By default, -I- is - * used; values of Y or N will be appended to this. - */ public void setAutoresponse(String response){ - if (response.equals("") || response.equals("null")) { - m_AutoResponse = null; - } else { - m_AutoResponse = response; - } + m_AutoResponse = response; } /** - * Checks the value set for the autoResponse. - * if it equals "Y" then we return -I-Y - * if it equals "N" then we return -I-N - * otherwise we return -I - */ - public void getAutoresponse(Commandline cmd) { - - if (m_AutoResponse == null) { - cmd.createArgument().setValue(FLAG_AUTORESPONSE_DEF); - } else if (m_AutoResponse.equalsIgnoreCase("Y")) { - cmd.createArgument().setValue(FLAG_AUTORESPONSE_YES); - - } else if (m_AutoResponse.equalsIgnoreCase("N")) { - cmd.createArgument().setValue(FLAG_AUTORESPONSE_NO); - } else { - cmd.createArgument().setValue(FLAG_AUTORESPONSE_DEF); - } // end of else - - } - - /** - * Sets the comment to apply; optional. + * Set the comment to apply; optional. *

* If this is null or empty, it will be replaced with "-" which * is what SourceSafe uses for an empty comment. + * @param comment The comment to apply in SourceSafe */ public void setComment(String comment) { - if (comment.equals("") || comment.equals("null")) { - m_Comment = "-"; - } else { - m_Comment = comment; - } + m_Comment = comment; } /** - * Gets the comment to be applied. - * @return the comment to be applied. - */ - public String getComment() { - return m_Comment; - } - - /** - * Set the local path. + * Set the local path; optional. + *

+ * This is the path to override the project + * working directory. + * @param localPath The path on disk. */ public void setLocalpath(Path localPath) { m_LocalPath = localPath.toString(); } - - public String getLocalPath() { - return m_LocalPath; - } } diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/vss/MSVSSCHECKIN.java b/src/main/org/apache/tools/ant/taskdefs/optional/vss/MSVSSCHECKIN.java index 14fbc0c4e..7d0bb2d13 100644 --- a/src/main/org/apache/tools/ant/taskdefs/optional/vss/MSVSSCHECKIN.java +++ b/src/main/org/apache/tools/ant/taskdefs/optional/vss/MSVSSCHECKIN.java @@ -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 @@ -54,7 +54,6 @@ package org.apache.tools.ant.taskdefs.optional.vss; -import java.io.File; import org.apache.tools.ant.BuildException; import org.apache.tools.ant.types.Commandline; import org.apache.tools.ant.types.Path; @@ -63,26 +62,18 @@ import org.apache.tools.ant.types.Path; * Performs CheckIn commands to Microsoft Visual SourceSafe. * * @author Martin Poeschl + * @author Jesse Stockall * * @ant.task name="vsscheckin" category="scm" */ public class MSVSSCHECKIN extends MSVSS { - private String m_LocalPath = null; - private boolean m_Recursive = false; - private boolean m_Writable = false; - private String m_AutoResponse = null; - private String m_Comment = "-"; - /** - * Executes the task. - *

- * Builds a command line to execute ss and then calls Exec's run method - * to execute the command line. + * Builds a command line to execute ss. + * @return The constructed commandline. */ - public void execute() throws BuildException { + protected Commandline buildCmdLine() { Commandline commandLine = new Commandline(); - int result = 0; // first off, make sure that we've got a command and a vssdir ... if (getVsspath() == null) { @@ -90,8 +81,6 @@ public class MSVSSCHECKIN extends MSVSS { throw new BuildException(msg, getLocation()); } - // now look for illegal combinations of things ... - // build the command line from what we got the format is // ss Checkin VSS items [-H] [-C] [-I-] [-N] [-O] [-R] [-W] [-Y] [-?] // as specified in the SS.EXE help @@ -101,150 +90,67 @@ public class MSVSSCHECKIN extends MSVSS { // VSS items commandLine.createArgument().setValue(getVsspath()); // -GL - getLocalpathCommand(commandLine); + commandLine.createArgument().setValue(getLocalpath()); // -I- or -I-Y or -I-N - getAutoresponse(commandLine); + commandLine.createArgument().setValue(getAutoresponse()); // -R - getRecursiveCommand(commandLine); + commandLine.createArgument().setValue(getRecursive()); // -W - getWritableCommand(commandLine); + commandLine.createArgument().setValue(getWritable()); // -Y - getLoginCommand(commandLine); + commandLine.createArgument().setValue(getLogin()); // -C - commandLine.createArgument().setValue("-C" + getComment()); + commandLine.createArgument().setValue(getComment()); - result = run(commandLine); - if (result != 0) { - String msg = "Failed executing: " + commandLine.toString(); - throw new BuildException(msg, getLocation()); - } + return commandLine; } /** - * Set the local path. + * Set the local path; optional. + *

+ * This is the path to override the project + * working directory. + * @param localPath The path on disk. */ public void setLocalpath(Path localPath) { m_LocalPath = localPath.toString(); } - /** - * Builds and returns the -GL flag command if required. - *

- * The localpath is created if it didn't exist - */ - public void getLocalpathCommand(Commandline cmd) { - if (m_LocalPath == null) { - return; - } else { - // make sure m_LocalDir exists, create it if it doesn't - File dir = getProject().resolveFile(m_LocalPath); - if (!dir.exists()) { - boolean done = dir.mkdirs(); - if (!done) { - String msg = "Directory " + m_LocalPath - + " creation was not " - + "succesful for an unknown reason"; - throw new BuildException(msg, getLocation()); - } - getProject().log("Created dir: " + dir.getAbsolutePath()); - } - - cmd.createArgument().setValue(FLAG_OVERRIDE_WORKING_DIR - + m_LocalPath); - } - } - /** * Flag to tell the task to recurse down the tree; * optional, default false. + * @param recursive The boolean value for recursive. */ public void setRecursive(boolean recursive) { m_Recursive = recursive; } /** - * the 'recursive' command if the attribute was 'true', otherwise an empty string - */ - public void getRecursiveCommand(Commandline cmd) { - if (!m_Recursive) { - return; - } else { - cmd.createArgument().setValue(FLAG_RECURSION); - } - } - - /** - * Whether or not to leave checked in files writable. - * Default is false. + * Sets behaviour, unset the READ-ONLY flag on files checkedin to VSS.; optional + * @param argWritable The boolean value for writable. */ public final void setWritable(boolean argWritable) { m_Writable = argWritable; } /** - * The 'make writable' command if the attribute was true, - * otherwise an empty string. + * Sets the autoresponce behaviour.; optional. + *

+ * Valid options are Y and N. + * @param response The auto response value. */ - public void getWritableCommand(Commandline cmd) { - if (!m_Writable) { - return; - } else { - cmd.createArgument().setValue(FLAG_WRITABLE); - } - } - - /** - * What to respond with (sets the -I option). By default, -I- is - * used; values of Y or N will be appended to this. - */ public void setAutoresponse(String response){ - if (response.equals("") || response.equals("null")) { - m_AutoResponse = null; - } else { - m_AutoResponse = response; - } - } - - /** - * Checks the value set for the autoResponse. - * if it equals "Y" then we return -I-Y - * if it equals "N" then we return -I-N - * otherwise we return -I - */ - public void getAutoresponse(Commandline cmd) { - - if (m_AutoResponse == null) { - cmd.createArgument().setValue(FLAG_AUTORESPONSE_DEF); - } else if (m_AutoResponse.equalsIgnoreCase("Y")) { - cmd.createArgument().setValue(FLAG_AUTORESPONSE_YES); - - } else if (m_AutoResponse.equalsIgnoreCase("N")) { - cmd.createArgument().setValue(FLAG_AUTORESPONSE_NO); - } else { - cmd.createArgument().setValue(FLAG_AUTORESPONSE_DEF); - } // end of else - + m_AutoResponse = response; } /** - * Set the comment to apply; optional. + * Sets the comment to apply in SourceSafe.; optional. *

* If this is null or empty, it will be replaced with "-" which * is what SourceSafe uses for an empty comment. + * @param comment The comment to apply in SourceSafe */ public void setComment(String comment) { - if (comment.equals("") || comment.equals("null")) { - m_Comment = "-"; - } else { - m_Comment = comment; - } - } - - /** - * Gets the comment to be applied. - * @return the comment to be applied. - */ - public String getComment() { - return m_Comment; + m_Comment = comment; } } diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/vss/MSVSSCHECKOUT.java b/src/main/org/apache/tools/ant/taskdefs/optional/vss/MSVSSCHECKOUT.java index f4415137e..ab9573aec 100644 --- a/src/main/org/apache/tools/ant/taskdefs/optional/vss/MSVSSCHECKOUT.java +++ b/src/main/org/apache/tools/ant/taskdefs/optional/vss/MSVSSCHECKOUT.java @@ -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 @@ -54,37 +54,28 @@ package org.apache.tools.ant.taskdefs.optional.vss; -import java.io.File; import org.apache.tools.ant.BuildException; import org.apache.tools.ant.types.Commandline; import org.apache.tools.ant.types.Path; /** * Performs CheckOut commands to Microsoft Visual SourceSafe. - *

If you specify two or more attributes from version, date and + *

If you specify two or more attributes from version, date and * label only one will be used in the order version, date, label.

+ * * @author Martin Poeschl + * @author Jesse Stockall * * @ant.task name="vsscheckout" category="scm" */ public class MSVSSCHECKOUT extends MSVSS { - private String m_LocalPath = null; - private boolean m_Recursive = false; - private String m_Version = null; - private String m_Date = null; - private String m_Label = null; - private String m_AutoResponse = null; - /** - * Executes the task. - *

- * Builds a command line to execute ss and then calls Exec's run method - * to execute the command line. + * Builds a command line to execute ss. + * @return The constructed commandline. */ - public void execute() throws BuildException { + protected Commandline buildCmdLine() { Commandline commandLine = new Commandline(); - int result = 0; // first off, make sure that we've got a command and a vssdir ... if (getVsspath() == null) { @@ -92,8 +83,6 @@ public class MSVSSCHECKOUT extends MSVSS { throw new BuildException(msg, getLocation()); } - // now look for illegal combinations of things ... - // build the command line from what we got the format is // ss Checkout VSS items [-G] [-C] [-H] [-I-] [-N] [-O] [-R] [-V] [-Y] [-?] // as specified in the SS.EXE help @@ -103,160 +92,70 @@ public class MSVSSCHECKOUT extends MSVSS { // VSS items commandLine.createArgument().setValue(getVsspath()); // -GL - getLocalpathCommand(commandLine); + commandLine.createArgument().setValue(getLocalpath()); // -I- or -I-Y or -I-N - getAutoresponse(commandLine); + commandLine.createArgument().setValue(getAutoresponse()); // -R - getRecursiveCommand(commandLine); + commandLine.createArgument().setValue(getRecursive()); // -V - getVersionCommand(commandLine); + commandLine.createArgument().setValue(getVersion()); // -Y - getLoginCommand(commandLine); + commandLine.createArgument().setValue(getLogin()); - result = run(commandLine); - if (result != 0) { - String msg = "Failed executing: " + commandLine.toString(); - throw new BuildException(msg, getLocation()); - } + return commandLine; } /** - * Set the local path. + * Set the local path; optional. + *

+ * This is the path to override the project + * working directory. + * @param localPath The path on disk. */ public void setLocalpath(Path localPath) { m_LocalPath = localPath.toString(); } - /** - * Builds and returns the -GL flag command if required. - *

- * The localpath is created if it didn't exist - */ - public void getLocalpathCommand(Commandline cmd) { - if (m_LocalPath == null) { - return; - } else { - // make sure m_LocalDir exists, create it if it doesn't - File dir = getProject().resolveFile(m_LocalPath); - if (!dir.exists()) { - boolean done = dir.mkdirs(); - if (!done) { - String msg = "Directory " + m_LocalPath + " creation was not " + - "succesful for an unknown reason"; - throw new BuildException(msg, getLocation()); - } - getProject().log("Created dir: " + dir.getAbsolutePath()); - } - - cmd.createArgument().setValue(FLAG_OVERRIDE_WORKING_DIR + m_LocalPath); - } - } - /** * Flag to tell the task to recurse down the tree; * optional, default false. + * @param recursive The boolean value for recursive. */ public void setRecursive(boolean recursive) { m_Recursive = recursive; } /** - * the 'recursive' command if the attribute was 'true', otherwise an empty string - */ - public void getRecursiveCommand(Commandline cmd) { - if (!m_Recursive) { - return; - } else { - cmd.createArgument().setValue(FLAG_RECURSION); - } - } - - /** - * Set the version to get; - * optional, only one of version, label, or date - * allowed. + * Sets the stored version string.; optional. + * @param version The version to checkout. */ public void setVersion(String version) { - if (version.equals("") || version.equals("null")) { - m_Version = null; - } else { - m_Version = version; - } + m_Version = version; } /** - * Set the date to get; - * optional, only one of version, label, or date - * allowed. + * Sets the stored date string.; optional. + * @param date The date to checkout. */ public void setDate(String date) { - if (date.equals("") || date.equals("null")) { - m_Date = null; - } else { - m_Date = date; - } + m_Date = date; } /** - * Set the label to get; - * optional, only one of version, label, or date - * allowed. + * Sets the label to apply in SourceSafe.; optional. + * @param label The label to apply. */ public void setLabel(String label) { - if (label.equals("") || label.equals("null")) { - m_Label = null; - } else { - m_Label = label; - } + m_Label = label; } /** - * Simple order of priority. Returns the first specified of version, date, label - * If none of these was specified returns "" + * Sets the autoresponce behaviour.; optional. + *

+ * Valid options are Y and N. + * @param response The auto response value. */ - public void getVersionCommand(Commandline cmd) { - - if (m_Version != null) { - cmd.createArgument().setValue(FLAG_VERSION + m_Version); - } else if (m_Date != null) { - cmd.createArgument().setValue(FLAG_VERSION_DATE + m_Date); - } else if (m_Label != null) { - cmd.createArgument().setValue(FLAG_VERSION_LABEL + m_Label); - } - } - - /** - * What to respond with (sets the -I option). By default, -I- is - * used; values of Y or N will be appended to this. - */ public void setAutoresponse(String response){ - if (response.equals("") || response.equals("null")) { - m_AutoResponse = null; - } else { - m_AutoResponse = response; - } + m_AutoResponse = response; } - - /** - * Checks the value set for the autoResponse. - * if it equals "Y" then we return -I-Y - * if it equals "N" then we return -I-N - * otherwise we return -I - */ - public void getAutoresponse(Commandline cmd) { - - if (m_AutoResponse == null) { - cmd.createArgument().setValue(FLAG_AUTORESPONSE_DEF); - } else if (m_AutoResponse.equalsIgnoreCase("Y")) { - cmd.createArgument().setValue(FLAG_AUTORESPONSE_YES); - - } else if (m_AutoResponse.equalsIgnoreCase("N")) { - cmd.createArgument().setValue(FLAG_AUTORESPONSE_NO); - } else { - cmd.createArgument().setValue(FLAG_AUTORESPONSE_DEF); - } // end of else - - } - } - diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/vss/MSVSSCP.java b/src/main/org/apache/tools/ant/taskdefs/optional/vss/MSVSSCP.java index b0546e8eb..3b9c5fb94 100644 --- a/src/main/org/apache/tools/ant/taskdefs/optional/vss/MSVSSCP.java +++ b/src/main/org/apache/tools/ant/taskdefs/optional/vss/MSVSSCP.java @@ -1,7 +1,7 @@ /* * The Apache Software License, Version 1.1 * - * Copyright (c) 2002 The Apache Software Foundation. All rights + * Copyright (c) 2002-2003 The Apache Software Foundation. All rights * reserved. * * Redistribution and use in source and binary forms, with or without @@ -63,22 +63,18 @@ import org.apache.tools.ant.types.Commandline; * Based on the VSS Checkin code by Martin Poeschl * * @author Nigel Magnay + * @author Jesse Stockall * * @ant.task name="vsscp" category="scm" */ public class MSVSSCP extends MSVSS { - private String m_AutoResponse = null; - /** - * Executes the task. - *

- * Builds a command line to execute ss and then calls Exec's run method - * to execute the command line. + * Builds a command line to execute ss. + * @return The constructed commandline. */ - public void execute() throws BuildException { + protected Commandline buildCmdLine() { Commandline commandLine = new Commandline(); - int result = 0; // first off, make sure that we've got a command and a vssdir ... if (getVsspath() == null) { @@ -86,8 +82,6 @@ public class MSVSSCP extends MSVSS { throw new BuildException(msg, getLocation()); } - // now look for illegal combinations of things ... - // build the command line from what we got the format is // ss CP VSS items [-H] [-I-] [-Y] [-?] // as specified in the SS.EXE help @@ -95,49 +89,22 @@ public class MSVSSCP extends MSVSS { commandLine.createArgument().setValue(COMMAND_CP); // VSS items - commandLine.createArgument().setValue(getVsspath()); + commandLine.createArgument().setValue(getVsspath()); // -I- or -I-Y or -I-N - getAutoresponse(commandLine); + commandLine.createArgument().setValue(getAutoresponse()); // -Y - getLoginCommand(commandLine); - - result = run(commandLine); - if (result != 0) { - String msg = "Failed executing: " + commandLine.toString(); - throw new BuildException(msg, getLocation()); - } - } + commandLine.createArgument().setValue(getLogin()); - /** - * What to respond with (sets the -I option). By default, -I- is - * used; values of Y or N will be appended to this. - */ - public void setAutoresponse(String response) { - if (response.equals("") || response.equals("null")) { - m_AutoResponse = null; - } else { - m_AutoResponse = response; - } + return commandLine; } /** - * Checks the value set for the autoResponse. - * if it equals "Y" then we return -I-Y - * if it equals "N" then we return -I-N - * otherwise we return -I + * Sets the autoresponce behaviour.; optional. + *

+ * Valid options are Y and N. + * @param response The auto response value. */ - public void getAutoresponse(Commandline cmd) { - - if (m_AutoResponse == null) { - cmd.createArgument().setValue(FLAG_AUTORESPONSE_DEF); - } else if (m_AutoResponse.equalsIgnoreCase("Y")) { - cmd.createArgument().setValue(FLAG_AUTORESPONSE_YES); - - } else if (m_AutoResponse.equalsIgnoreCase("N")) { - cmd.createArgument().setValue(FLAG_AUTORESPONSE_NO); - } else { - cmd.createArgument().setValue(FLAG_AUTORESPONSE_DEF); - } // end of else - + public void setAutoresponse(String response) { + m_AutoResponse = response; } } diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/vss/MSVSSCREATE.java b/src/main/org/apache/tools/ant/taskdefs/optional/vss/MSVSSCREATE.java index 5e2d05a15..636a5ca8e 100644 --- a/src/main/org/apache/tools/ant/taskdefs/optional/vss/MSVSSCREATE.java +++ b/src/main/org/apache/tools/ant/taskdefs/optional/vss/MSVSSCREATE.java @@ -1,7 +1,7 @@ /* * The Apache Software License, Version 1.1 * - * Copyright (c) 2002 The Apache Software Foundation. All rights + * Copyright (c) 2002-2003 The Apache Software Foundation. All rights * reserved. * * Redistribution and use in source and binary forms, with or without @@ -92,7 +92,7 @@ import org.apache.tools.ant.types.Commandline; * failOnError * fail if there is an error creating the project (true by default) * No - * + * * * autoresponse * What to respond with (sets the -I option). By default, -I- is @@ -104,34 +104,22 @@ import org.apache.tools.ant.types.Commandline; * The comment to use for this label. Empty or '-' for no comment. * No * - * + * * * * @author Gary S. Weaver + * @author Jesse Stockall + * * @ant.task name="vsscreate" category="scm" */ public class MSVSSCREATE extends MSVSS { - private String m_AutoResponse = null; - private String m_Comment = "-"; - private boolean m_Quiet = false; - - /** - * True by default since most of the time we won't be trying to create a - * project with the same name more than once. - */ - private boolean m_FailOnError = true; - /** - * Executes the task. - *

- * Builds a command line to execute ss and then calls Exec's run method - * to execute the command line. - * @throws BuildException if the task fails. + * Builds a command line to execute ss. + * @return The constructed commandline. */ - public void execute() throws BuildException { + Commandline buildCmdLine() { Commandline commandLine = new Commandline(); - int result = 0; // first off, make sure that we've got a command and a vssdir... if (getVsspath() == null) { @@ -139,9 +127,8 @@ public class MSVSSCREATE extends MSVSS { throw new BuildException(msg, getLocation()); } - // now look for illegal combinations of things ... - - // build the command line from what we got the format is + // build the command line from what we got + // the format is: // ss Create VSS items [-C] [-H] [-I-] [-N] [-O] [-S] [-Y] [-?] // as specified in the SS.EXE help commandLine.setExecutable(getSSCommand()); @@ -149,108 +136,53 @@ public class MSVSSCREATE extends MSVSS { // VSS items commandLine.createArgument().setValue(getVsspath()); - // -C - commandLine.createArgument().setValue("-C" + getComment()); - + commandLine.createArgument().setValue(getComment()); // -I- or -I-Y or -I-N - getAutoresponse(commandLine); - + commandLine.createArgument().setValue(getAutoresponse()); // -O- - getQuietCommand(commandLine); - + commandLine.createArgument().setValue(getQuiet()); // -Y - getLoginCommand(commandLine); - - result = run(commandLine); - if (result != 0 && m_FailOnError) { - String msg = "Failed executing: " + commandLine.toString(); - throw new BuildException(msg, getLocation()); - } + commandLine.createArgument().setValue(getLogin()); + return commandLine; } /** - * Sets the comment to apply in SourceSafe. + * Sets the comment to apply in SourceSafe.; optional. *

* If this is null or empty, it will be replaced with "-" which * is what SourceSafe uses for an empty comment. - * @param comment the comment to apply in SourceSafe + * @param comment The comment to apply in SourceSafe */ public void setComment(String comment) { - if (comment.equals("") || comment.equals("null")) { - m_Comment = "-"; - } else { - m_Comment = comment; - } - } - - /** - * Gets the comment to be applied. - * @return the comment to be applied. - */ - public String getComment() { - return m_Comment; + m_Comment = comment; } /** * Sets/clears quiet mode; optional, default false. - * @param quiet whether or not command should be run in "quiet mode". + * @param quiet The boolean value for quiet. */ public final void setQuiet (boolean quiet) { - this.m_Quiet = quiet; - } - - /** - * Modify the commandline to add the quiet argument. - * @param cmd the commandline to modify. - */ - public void getQuietCommand (Commandline cmd) { - if (m_Quiet) { - cmd.createArgument().setValue (FLAG_QUIET); - } + m_Quiet = quiet; } /** - * Sets whether task should fail if there is an error creating the project; - * optional, default true. - * @param failOnError true if task should fail if there is an error creating - * the project. + * Sets behaviour, whether task should fail if there is an error creating + * the project.; optional. + * @param failOnError True if task should fail on any error. */ public final void setFailOnError (boolean failOnError) { - this.m_FailOnError = failOnError; + m_FailOnError = failOnError; } /** - * What to respond with (sets the -I option). By default, -I- is - * used; values of Y or N will be appended to this. - * @param response the response. + * Sets the autoresponce behaviour.; optional. + *

+ * Valid options are Y and N. + * @param response The auto response value. */ public void setAutoresponse(String response) { - if (response.equals("") || response.equals("null")) { - m_AutoResponse = null; - } else { - m_AutoResponse = response; - } - } - - /** - * Checks the value set for the autoResponse. - * if it equals "Y" then we return -I-Y - * if it equals "N" then we return -I-N - * otherwise we return -I - * @param cmd the commandline to modify with the autoresponse. - */ - public void getAutoresponse(Commandline cmd) { - if (m_AutoResponse == null) { - cmd.createArgument().setValue(FLAG_AUTORESPONSE_DEF); - } else if (m_AutoResponse.equalsIgnoreCase("Y")) { - cmd.createArgument().setValue(FLAG_AUTORESPONSE_YES); - - } else if (m_AutoResponse.equalsIgnoreCase("N")) { - cmd.createArgument().setValue(FLAG_AUTORESPONSE_NO); - } else { - cmd.createArgument().setValue(FLAG_AUTORESPONSE_DEF); - } // end of else + m_AutoResponse = response; } } diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/vss/MSVSSConstants.java b/src/main/org/apache/tools/ant/taskdefs/optional/vss/MSVSSConstants.java new file mode 100644 index 000000000..801152288 --- /dev/null +++ b/src/main/org/apache/tools/ant/taskdefs/optional/vss/MSVSSConstants.java @@ -0,0 +1,115 @@ +/* + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2003 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "The Jakarta Project", "Ant", and "Apache Software + * Foundation" must not be used to endorse or promote products derived + * from this software without prior written permission. For written + * permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ +package org.apache.tools.ant.taskdefs.optional.vss; + +/** + * Holds all the constants for the VSS tasks. + * + * @author Jesse Stockall + */ +public interface MSVSSConstants { + /** Constant for the thing to execute */ + String SS_EXE = "ss"; + /** Dollar Sigh to prefix the project path */ + String PROJECT_PREFIX = "$"; + + /** The 'CP' command */ + String COMMAND_CP = "CP"; + /** The 'Add' command */ + String COMMAND_ADD = "Add"; + /** The 'Get' command */ + String COMMAND_GET = "Get"; + /** The 'Checkout' command */ + String COMMAND_CHECKOUT = "Checkout"; + /** The 'Checkin' command */ + String COMMAND_CHECKIN = "Checkin"; + /** The 'Label' command */ + String COMMAND_LABEL = "Label"; + /** The 'History' command */ + String COMMAND_HISTORY = "History"; + /** The 'Create' command */ + String COMMAND_CREATE = "Create"; + + /** The brief style flag */ + String STYLE_BRIEF = "brief"; + /** The codediff style flag */ + String STYLE_CODEDIFF = "codediff"; + /** The nofile style flag */ + String STYLE_NOFILE = "nofile"; + /** The default style flag */ + String STYLE_DEFAULT = "default"; + + String FLAG_LOGIN = "-Y"; + String FLAG_OVERRIDE_WORKING_DIR = "-GL"; + String FLAG_AUTORESPONSE_DEF = "-I-"; + String FLAG_AUTORESPONSE_YES = "-I-Y"; + String FLAG_AUTORESPONSE_NO = "-I-N"; + String FLAG_RECURSION = "-R"; + String FLAG_VERSION = "-V"; + String FLAG_VERSION_DATE = "-Vd"; + String FLAG_VERSION_LABEL = "-VL"; + String FLAG_WRITABLE = "-W"; + String VALUE_NO = "-N"; + String VALUE_YES = "-Y"; + String FLAG_QUIET = "-O-"; + String FLAG_COMMENT = "-C"; + String FLAG_LABEL = "-L"; + String VALUE_FROMDATE = "~d"; + String VALUE_FROMLABEL = "~L"; + String FLAG_OUTPUT = "-O"; + String FLAG_USER = "-U"; + String FLAG_NO_FILE = "-F-"; + String FLAG_BRIEF = "-B"; + String FLAG_CODEDIFF = "-D"; +} diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/vss/MSVSSGET.java b/src/main/org/apache/tools/ant/taskdefs/optional/vss/MSVSSGET.java index ef30925dc..65266290b 100644 --- a/src/main/org/apache/tools/ant/taskdefs/optional/vss/MSVSSGET.java +++ b/src/main/org/apache/tools/ant/taskdefs/optional/vss/MSVSSGET.java @@ -1,7 +1,7 @@ /* * The Apache Software License, Version 1.1 * - * Copyright (c) 2000-2002 The Apache Software Foundation. All rights + * Copyright (c) 2000-2003 The Apache Software Foundation. All rights * reserved. * * Redistribution and use in source and binary forms, with or without @@ -125,37 +125,18 @@ import org.apache.tools.ant.types.Path; * * @author Craig Cottingham * @author Andrew Everitt + * @author Jesse Stockall * * @ant.task name="vssget" category="scm" */ public class MSVSSGET extends MSVSS { - private String m_LocalPath = null; - private boolean m_Recursive = false; - private boolean m_Writable = false; - private String m_Version = null; - private String m_Date = null; - private String m_Label = null; - private String m_AutoResponse = null; - private boolean m_Quiet = false; - /** - * Executes the task. - *

- * Builds a command line to execute ss and then calls Exec's run method - * to execute the command line. + * Builds a command line to execute ss. + * @return The constructed commandline. */ - public void execute() throws BuildException { + Commandline buildCmdLine() { Commandline commandLine = new Commandline(); - int result = 0; - - // first off, make sure that we've got a command and a vssdir ... - if (getVsspath() == null) { - String msg = "vsspath attribute must be set!"; - throw new BuildException(msg, getLocation()); - } - - // now look for illegal combinations of things ... // build the command line from what we got the format is // ss Get VSS items [-G] [-H] [-I-] [-N] [-O] [-R] [-V] [-W] [-Y] [-?] @@ -163,217 +144,96 @@ public class MSVSSGET extends MSVSS { commandLine.setExecutable(getSSCommand()); commandLine.createArgument().setValue(COMMAND_GET); - // VSS items + if (getVsspath() == null) { + throw new BuildException("vsspath attribute must be set!", getLocation()); + } commandLine.createArgument().setValue(getVsspath()); + // -GL - getLocalpathCommand(commandLine); + commandLine.createArgument().setValue(getLocalpath()); // -I- or -I-Y or -I-N - getAutoresponse(commandLine); + commandLine.createArgument().setValue(getAutoresponse()); // -O- - getQuietCommand(commandLine); + commandLine.createArgument().setValue(getQuiet()); // -R - getRecursiveCommand(commandLine); + commandLine.createArgument().setValue(getRecursive()); // -V - getVersionCommand(commandLine); + commandLine.createArgument().setValue(getVersion()); // -W - getWritableCommand(commandLine); + commandLine.createArgument().setValue(getWritable()); // -Y - getLoginCommand(commandLine); + commandLine.createArgument().setValue(getLogin()); - result = run(commandLine); - if (result != 0) { - String msg = "Failed executing: " + commandLine.toString(); - throw new BuildException(msg, getLocation()); - } + return commandLine; } /** - * Override the working directory and get to the specified path; optional. + * Set the local path; optional. + *

+ * This is the path to override the project + * working directory. + * @param localPath The path on disk. */ public void setLocalpath(Path localPath) { m_LocalPath = localPath.toString(); } - /** - * Builds and returns the -GL flag command if required. - *

- * The localpath is created if it didn't exist - */ - public void getLocalpathCommand(Commandline cmd) { - if (m_LocalPath == null) { - return; - } else { - // make sure m_LocalDir exists, create it if it doesn't - File dir = getProject().resolveFile(m_LocalPath); - if (!dir.exists()) { - boolean done = dir.mkdirs(); - if (!done) { - String msg = "Directory " + m_LocalPath + " creation was not " + - "successful for an unknown reason"; - throw new BuildException(msg, getLocation()); - } - getProject().log("Created dir: " + dir.getAbsolutePath()); - } - - cmd.createArgument().setValue(FLAG_OVERRIDE_WORKING_DIR + m_LocalPath); - } - } - /** * Flag to tell the task to recurse down the tree; * optional, default false. + * @param recursive The boolean value for recursive. */ - public void setRecursive(boolean recursive) { + public final void setRecursive(boolean recursive) { m_Recursive = recursive; } /** - * the 'recursive' command if the attribute was 'true', otherwise an empty string - */ - public void getRecursiveCommand(Commandline cmd) { - if (!m_Recursive) { - return; - } else { - cmd.createArgument().setValue(FLAG_RECURSION); - } - } - - /** - * Flag to suppress output when true ; false by default. + * Sets/clears quiet mode; optional, default false. + * @param quiet The boolean value for quiet. */ public final void setQuiet (boolean quiet) { - this.m_Quiet = quiet; - } - - public void getQuietCommand (Commandline cmd) { - if (m_Quiet) { - cmd.createArgument().setValue (FLAG_QUIET); - } + m_Quiet = quiet; } - + /** - * make fetched files writable; optional, default false. + * Sets behaviour, unset the READ-ONLY flag on files retrieved from VSS.; optional + * @param argWritable The boolean value for writable. */ public final void setWritable(boolean argWritable) { m_Writable = argWritable; } /** - * the 'make writable' command if the attribute was 'true', otherwise an empty string - */ - public void getWritableCommand(Commandline cmd) { - if (!m_Writable) { - return; - } else { - cmd.createArgument().setValue(FLAG_WRITABLE); - } - } - - /** - * Set a version number to get; - * optional, only one of version, label, or date - * allowed. - *

- * ORIGINAL COMMENT THAT DOES NOT SEEM AT ALL VALID: - * Note we assume that if the supplied string has the value "null" that something - * went wrong and that the string value got populated from a null object. This - * happens if a ant variable is used e.g. version="${ver_server}" when ver_server - * has not been defined to ant! - * NO, in this case the version string is "${ver_server}". - * @todo fix this + * Sets the stored version string.; optional. + * @param version The version to get. */ public void setVersion(String version) { - if (version.equals("") || version.equals("null")) { - m_Version = null; - } else { - m_Version = version; - } + m_Version = version; } /** - * Set the date to get; - * optional, only one of version, label, or date - * allowed. - *

- * ORIGINAL COMMENT THAT DOES NOT SEEM AT ALL VALID: - * Note we assume that if the supplied string has the value "null" that something - * went wrong and that the string value got populated from a null object. This - * happens if a ant variable is used e.g. date="${date}" when date - * has not been defined to ant! - * @todo fix this + * Sets the stored date string.; optional. + * @param date The date to checkout. */ public void setDate(String date) { - if (date.equals("") || date.equals("null")) { - m_Date = null; - } else { - m_Date = date; - } + m_Date = date; } /** - * Set the label to get; - * optional, only one of version, label, or date - * allowed. - *

- * Note we assume that if the supplied string has the value "null" that something - * went wrong and that the string value got populated from a null object. This - * happens if a ant variable is used e.g. label="${label_server}" when label_server - * has not been defined to ant! + * Sets the label to apply in SourceSafe.; optional. + * @param label The label to apply. */ public void setLabel(String label) { - if (label.equals("") || label.equals("null")) { - m_Label = null; - } else { - m_Label = label; - } + m_Label = label; } /** - * Simple order of priority. Returns the first specified of version, date, label. - * If none of these was specified returns "" - */ - public void getVersionCommand(Commandline cmd) { - - if (m_Version != null) { - cmd.createArgument().setValue(FLAG_VERSION + m_Version); - } else if (m_Date != null) { - cmd.createArgument().setValue(FLAG_VERSION_DATE + m_Date); - } else if (m_Label != null) { - cmd.createArgument().setValue(FLAG_VERSION_LABEL + m_Label); - } - } - - /** - * What to respond with (sets the -I option). By default, -I- is - * used; values of Y or N will be appended to this. + * Sets the autoresponce behaviour.; optional. + *

+ * Valid options are Y and N. + * @param response The auto response value. */ public void setAutoresponse(String response){ - if (response.equals("") || response.equals("null")) { - m_AutoResponse = null; - } else { - m_AutoResponse = response; - } - } - - /** - * Checks the value set for the autoResponse. - * if it equals "Y" then we return -I-Y - * if it equals "N" then we return -I-N - * otherwise we return -I - */ - public void getAutoresponse(Commandline cmd) { - - if (m_AutoResponse == null) { - cmd.createArgument().setValue(FLAG_AUTORESPONSE_DEF); - } else if (m_AutoResponse.equalsIgnoreCase("Y")) { - cmd.createArgument().setValue(FLAG_AUTORESPONSE_YES); - - } else if (m_AutoResponse.equalsIgnoreCase("N")) { - cmd.createArgument().setValue(FLAG_AUTORESPONSE_NO); - } else { - cmd.createArgument().setValue(FLAG_AUTORESPONSE_DEF); - } // end of else - + m_AutoResponse = response; } } - diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/vss/MSVSSHISTORY.java b/src/main/org/apache/tools/ant/taskdefs/optional/vss/MSVSSHISTORY.java index 964e48b38..41089899d 100644 --- a/src/main/org/apache/tools/ant/taskdefs/optional/vss/MSVSSHISTORY.java +++ b/src/main/org/apache/tools/ant/taskdefs/optional/vss/MSVSSHISTORY.java @@ -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 @@ -69,40 +69,18 @@ import org.apache.tools.ant.types.EnumeratedAttribute; * * @author Balazs Fejes 2 * @author Glenn_Twiggs@bmc.com + * @author Jesse Stockall * * @ant.task name="vsshistory" category="scm" */ - public class MSVSSHISTORY extends MSVSS { - private String m_FromDate = null; - private String m_ToDate = null; - private DateFormat m_DateFormat = - DateFormat.getDateInstance(DateFormat.SHORT); - - private String m_FromLabel = null; - private String m_ToLabel = null; - private String m_OutputFileName = null; - private String m_User = null; - private int m_NumDays = Integer.MIN_VALUE; - private String m_Style = ""; - private boolean m_Recursive = false; - - public static final String VALUE_FROMDATE = "~d"; - public static final String VALUE_FROMLABEL = "~L"; - - public static final String FLAG_OUTPUT = "-O"; - public static final String FLAG_USER = "-U"; - /** - * Executes the task. - *

- * Builds a command line to execute ss and then calls Exec's run method - * to execute the command line. + * Builds a command line to execute ss. + * @return The constructed commandline. */ - public void execute() throws BuildException { + Commandline buildCmdLine() { Commandline commandLine = new Commandline(); - int result = 0; // first off, make sure that we've got a command and a vssdir and a label ... if (getVsspath() == null) { @@ -110,8 +88,6 @@ public class MSVSSHISTORY extends MSVSS { throw new BuildException(msg, getLocation()); } - // now look for illegal combinations of things ... - // build the command line from what we got the format is // ss History elements [-H] [-L] [-N] [-O] [-V] [-Y] [-#] [-?] // as specified in the SS.EXE help @@ -120,97 +96,88 @@ public class MSVSSHISTORY extends MSVSS { // VSS items commandLine.createArgument().setValue(getVsspath()); - // -I- - commandLine.createArgument().setValue("-I-"); // ignore all errors - - // -V - // Label an existing file or project version - getVersionDateCommand(commandLine); - getVersionLabelCommand(commandLine); - - // -R - if (m_Recursive) { - commandLine.createArgument().setValue(FLAG_RECURSION); - } - + commandLine.createArgument().setValue(FLAG_AUTORESPONSE_DEF); // ignore all errors + // -Vd + commandLine.createArgument().setValue(getVersionDate()); + // -VL + commandLine.createArgument().setValue(getVersionLabel()); + // -R + commandLine.createArgument().setValue(getRecursive()); // -B / -D / -F- - if (m_Style.length() > 0) { - commandLine.createArgument().setValue(m_Style); - } - + commandLine.createArgument().setValue(getStyle()); // -Y - getLoginCommand(commandLine); - + commandLine.createArgument().setValue(getLogin()); // -O - getOutputCommand(commandLine); - - System.out.println("***: " + commandLine); - - result = run(commandLine); - if (result != 0) { - String msg = "Failed executing: " + commandLine.toString(); - throw new BuildException(msg, getLocation()); - } + commandLine.createArgument().setValue(getOutput()); + return commandLine; } /** - * Set the Start Date for the Comparison of two versions; optional. + * Flag to tell the task to recurse down the tree; + * optional, default false. + * @param recursive The boolean value for recursive. */ - public void setFromDate(String fromDate) { - if (fromDate.equals("") || fromDate == null) { - m_FromDate = null; - } else { - m_FromDate = fromDate; - } + public void setRecursive(boolean recursive) { + m_Recursive = recursive; } /** - * Set the Start Label; optional + * Sets the username of the user whose changes we would like to see.; optional + * @param user The username. */ - public void setFromLabel(String fromLabel) { - if (fromLabel.equals("") || fromLabel == null) { - m_FromLabel = null; - } else { - m_FromLabel = fromLabel; - } + public void setUser(String user) { + m_User = user; } /** - * Set the End Label ; optional + * Set the Start Date for the comparison of two versions in SourceSafe + * history.; optional + * @param fromDate The start date. */ - public void setToLabel(String toLabel) { - if (toLabel.equals("") || toLabel == null) { - m_ToLabel = null; - } else { - m_ToLabel = toLabel; - } + public void setFromDate(String fromDate) { + m_FromDate = fromDate; } /** * Set the End Date for the Comparison of two versions; optional. + * @param toDate The end date. */ public void setToDate(String toDate) { - if (toDate.equals("") || toDate == null) { - m_ToDate = null; - } else { - m_ToDate = toDate; - } + m_ToDate = toDate; } /** - * Set the number of days for comparison; + * Set the Start Label; optional. + * @param fromLabel The start label. + */ + public void setFromLabel(String fromLabel) { + m_FromLabel = fromLabel; + } + + /** + * Set the End label; optional. + * @param toLabel The end label. + */ + public void setToLabel(String toLabel) { + m_ToLabel = toLabel; + } + + /** + * Set the number of days for comparison; * optional. *

* The default value is 2 days. (maybe) + * @param numd The number of days. */ public void setNumdays(int numd) { m_NumDays = numd; } - + /** * Set the output file name for the history; optional. + * @param outfile The output file name. */ public void setOutput(File outfile) { if (outfile == null) { @@ -222,146 +189,52 @@ public class MSVSSHISTORY extends MSVSS { /** * Format of dates in fromDate and toDate; optional. - * Used when calculating dates with - * the numdays attribute. - * This string uses the formatting rules of SimpleDateFormat. + * Used when calculating dates with + * the numdays attribute. + * This string uses the formatting rules of SimpleDateFormat. * Defaults to DateFormat.SHORT. + * @param dateFormat The date format. */ public void setDateFormat(String dateFormat) { - if (!(dateFormat.equals("") || dateFormat == null)) { - m_DateFormat = new SimpleDateFormat(dateFormat); - } - } - - /** - * Builds the version date command. - * @param cmd the commandline the command is to be added to - */ - private void getVersionDateCommand(Commandline cmd) throws BuildException { - if (m_FromDate == null && m_ToDate == null - && m_NumDays == Integer.MIN_VALUE) { - return; - } - - if (m_FromDate != null && m_ToDate != null) { - cmd.createArgument().setValue(FLAG_VERSION_DATE + m_ToDate - + VALUE_FROMDATE + m_FromDate); - } else if (m_ToDate != null && m_NumDays != Integer.MIN_VALUE) { - String startDate = null; - try { - startDate = calcDate(m_ToDate, m_NumDays); - } catch (ParseException ex) { - String msg = "Error parsing date: " + m_ToDate; - throw new BuildException(msg, getLocation()); - } - cmd.createArgument().setValue(FLAG_VERSION_DATE + m_ToDate + VALUE_FROMDATE + startDate); - } else if (m_FromDate != null && m_NumDays != Integer.MIN_VALUE) { - String endDate = null; - try { - endDate = calcDate(m_FromDate, m_NumDays); - } catch (ParseException ex) { - String msg = "Error parsing date: " + m_FromDate; - throw new BuildException(msg, getLocation()); - } - cmd.createArgument().setValue(FLAG_VERSION_DATE + endDate + VALUE_FROMDATE + m_FromDate); - } else { - if (m_FromDate != null) { - cmd.createArgument().setValue(FLAG_VERSION + VALUE_FROMDATE + m_FromDate); - } else { - cmd.createArgument().setValue(FLAG_VERSION_DATE + m_ToDate); - } - } - } - - /** - * Builds the version date command. - * @param cmd the commandline the command is to be added to - */ - private void getVersionLabelCommand(Commandline cmd) throws BuildException { - if (m_FromLabel == null && m_ToLabel == null) { - return; - } - - if (m_FromLabel != null && m_ToLabel != null) { - cmd.createArgument().setValue(FLAG_VERSION_LABEL + m_ToLabel + VALUE_FROMLABEL + m_FromLabel); - } else if (m_FromLabel != null) { - cmd.createArgument().setValue(FLAG_VERSION + VALUE_FROMLABEL + m_FromLabel); - } else { - cmd.createArgument().setValue(FLAG_VERSION_LABEL + m_ToLabel); - } - } - - /** - * Builds the version date command. - * @param cmd the commandline the command is to be added to - */ - private void getOutputCommand(Commandline cmd) { - if (m_OutputFileName != null) { - cmd.createArgument().setValue(FLAG_OUTPUT + m_OutputFileName); - } + m_DateFormat = new SimpleDateFormat(dateFormat); } - /** - * Calculates the start date for version comparison. - *

- * Calculates the date numDay days earlier than startdate. - */ - private String calcDate(String fromDate, int numDays) throws ParseException { - String toDate = null; - Date currdate = new Date(); - Calendar calend = new GregorianCalendar(); - currdate = m_DateFormat.parse(fromDate); - calend.setTime(currdate); - calend.add(Calendar.DATE, numDays); - toDate = m_DateFormat.format(calend.getTime()); - return toDate; - } - - /** - * Flag to tell the task to recurse down the tree; - * optional, default false. - */ - - public void setRecursive(boolean recursive) { - m_Recursive = recursive; - } - - /** - * Name the user whose changes we would like to see; optional - */ - public void setUser(String user) { - m_User = user; - } - - /** + /** * Specify the output style; optional. * - * @param option valid values: + * @param attr valid values: *

    - *
  • brief: -B Display a brief history. - *
  • codediff: -D Display line-by-line file changes. - *
  • nofile: -F- Do not display individual file updates in the project history. + *
  • brief: -B Display a brief history. + *
  • codediff: -D Display line-by-line file changes. + *
  • nofile: -F- Do not display individual file updates in the project history. *
  • default: No option specified. Display in Source Safe's default format. *
*/ public void setStyle(BriefCodediffNofile attr) { String option = attr.getValue(); - if (option.equals("brief")) { - m_Style = "-B"; - } else if (option.equals("codediff")) { - m_Style = "-D"; - } else if (option.equals("default")) { + if (option.equals(STYLE_BRIEF)) { + m_Style = FLAG_BRIEF; + } else if (option.equals(STYLE_CODEDIFF)) { + m_Style = FLAG_CODEDIFF; + } else if (option.equals(STYLE_DEFAULT)) { m_Style = ""; - } else if (option.equals("nofile")) { - m_Style = "-F-"; + } else if (option.equals(STYLE_NOFILE)) { + m_Style = FLAG_NO_FILE; } else { throw new BuildException("Style " + attr + " unknown."); } } + /** + * Extention of EnumeratedAttribute to hold the values for style. + */ public static class BriefCodediffNofile extends EnumeratedAttribute { - public String[] getValues() { - return new String[] {"brief", "codediff", "nofile", "default"}; - } - } + /** + * Gets the list of allowable values. + * @return The values. + */ + public String[] getValues() { + return new String[] {STYLE_BRIEF, STYLE_CODEDIFF, STYLE_NOFILE, STYLE_DEFAULT}; + } + } } diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/vss/MSVSSLABEL.java b/src/main/org/apache/tools/ant/taskdefs/optional/vss/MSVSSLABEL.java index 2f2a5b616..ea2c744d8 100644 --- a/src/main/org/apache/tools/ant/taskdefs/optional/vss/MSVSSLABEL.java +++ b/src/main/org/apache/tools/ant/taskdefs/optional/vss/MSVSSLABEL.java @@ -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 @@ -105,194 +105,86 @@ import org.apache.tools.ant.types.Commandline; * The comment to use for this label. Empty or '-' for no comment. * No * - * + * * * * @author Phillip Wells + * @author Jesse Stockall * * @ant.task name="vsslabel" category="scm" */ public class MSVSSLABEL extends MSVSS { - private String m_AutoResponse = null; - private String m_Label = null; - private String m_Version = null; - private String m_Comment = "-"; - - public static final String FLAG_LABEL = "-L"; /** - * Executes the task. - *

- * Builds a command line to execute ss and then calls Exec's run method - * to execute the command line. + * Builds a command line to execute ss. + * @return The constructed commandline. */ - public void execute() throws BuildException { + Commandline buildCmdLine() { Commandline commandLine = new Commandline(); - int result = 0; // first off, make sure that we've got a command and a vssdir and a label ... if (getVsspath() == null) { - String msg = "vsspath attribute must be set!"; - throw new BuildException(msg, getLocation()); + throw new BuildException("vsspath attribute must be set!", getLocation()); } - if (getLabel() == null) { + if (getLabel() == "") { String msg = "label attribute must be set!"; throw new BuildException(msg, getLocation()); } - // now look for illegal combinations of things ... - // build the command line from what we got the format is - // ss Label VSS items [-C] [-H] [-I-] [-Llabel] [-N] [-O] [-V] [-Y] [-?] + // ss Label VSS items [-C] [-H] [-I-] [-Llabel] [-N] [-O] [-V] [-Y] [-?] // as specified in the SS.EXE help commandLine.setExecutable(getSSCommand()); commandLine.createArgument().setValue(COMMAND_LABEL); // VSS items commandLine.createArgument().setValue(getVsspath()); - // -C - commandLine.createArgument().setValue("-C" + getComment()); - + commandLine.createArgument().setValue(getComment()); // -I- or -I-Y or -I-N - getAutoresponse(commandLine); - - // -L - // Specify the new label on the command line (instead of being prompted) - getLabelCommand(commandLine); - - // -V - // Label an existing file or project version - getVersionCommand(commandLine); - + commandLine.createArgument().setValue(getAutoresponse()); + // -L Specify the new label on the command line (instead of being prompted) + commandLine.createArgument().setValue(getLabel()); + // -V Label an existing file or project version + commandLine.createArgument().setValue(getVersion()); // -Y - getLoginCommand(commandLine); - - result = run(commandLine); - if (result != 0) { - String msg = "Failed executing: " + commandLine.toString(); - throw new BuildException(msg, getLocation()); - } + commandLine.createArgument().setValue(getLogin()); + return commandLine; } /** - * Set the label to apply; required. - *

- * Note we assume that if the supplied string has the value "null" that something - * went wrong and that the string value got populated from a null object. This - * happens if a ant variable is used e.g. label="${label_server}" when label_server - * has not been defined to ant! - * @todo correct. + * Set the label to apply in SourceSafe.; required. + * @param label The label to apply. */ public void setLabel(String label) { - if (label.equals("") || label.equals("null")) { - m_Label = null; - } else { - m_Label = label; - } - } - - /** - * Builds the version command. - * @param cmd the commandline the command is to be added to - */ - public void getVersionCommand(Commandline cmd) { - if (m_Version != null) { - cmd.createArgument().setValue(FLAG_VERSION + m_Version); - } + m_Label = label; } /** - * Builds the label command. - * @param cmd the commandline the command is to be added to - */ - public void getLabelCommand(Commandline cmd) { - if (m_Label != null) { - cmd.createArgument().setValue(FLAG_LABEL + m_Label); - } - } - - /** - * Name an existing file or project version to label; optional. - * By default the current version is labelled. - *

- * Note we assume that if the supplied string has the value "null" that something - * went wrong and that the string value got populated from a null object. This - * happens if a ant variable is used e.g. version="${ver_server}" when ver_server - * has not been defined to ant! - * @todo fix + * Set the stored version string.; optional. + * @param version The version to label. */ public void setVersion(String version) { - if (version.equals("") || version.equals("null")) { - m_Version = null; - } else { - m_Version = version; - } - } - - /** - * Gets the label to be applied. - * @return the label to be applied. - */ - public String getLabel() { - return m_Label; + m_Version = version; } /** - * The comment to use for this label; optional. + * The comment to use for this label.; optional. * Empty or '-' for no comment. - *

- * If this is null or empty, it will be replaced with "-" which - * is what SourceSafe uses for an empty comment. - *@todo correct + * @param comment The comment to apply in SourceSafe */ public void setComment(String comment) { - if (comment.equals("") || comment.equals("null")) { - m_Comment = "-"; - } else { - m_Comment = comment; - } + m_Comment = comment; } /** - * Gets the comment to be applied. - * @return the comment to be applied. - */ - public String getComment() { - return m_Comment; - } - - /** - * What to respond with (sets the -I option). By default, -I- is - * used; values of Y or N will be appended to this. + * Sets the autoresponce behaviour.; optional. + *

+ * Valid options are Y and N. + * @param response The auto response value. */ - public void setAutoresponse(String response){ - if (response.equals("") || response.equals("null")) { - m_AutoResponse = null; - } else { - m_AutoResponse = response; - } - } - - /** - * Checks the value set for the autoResponse. - * if it equals "Y" then we return -I-Y - * if it equals "N" then we return -I-N - * otherwise we return -I - */ - public void getAutoresponse(Commandline cmd) { - - if (m_AutoResponse == null) { - cmd.createArgument().setValue(FLAG_AUTORESPONSE_DEF); - } else if (m_AutoResponse.equalsIgnoreCase("Y")) { - cmd.createArgument().setValue(FLAG_AUTORESPONSE_YES); - - } else if (m_AutoResponse.equalsIgnoreCase("N")) { - cmd.createArgument().setValue(FLAG_AUTORESPONSE_NO); - } else { - cmd.createArgument().setValue(FLAG_AUTORESPONSE_DEF); - } // end of else + m_AutoResponse = response; } } diff --git a/src/testcases/org/apache/tools/ant/taskdefs/optional/vss/MSVSSTest.java b/src/testcases/org/apache/tools/ant/taskdefs/optional/vss/MSVSSTest.java new file mode 100644 index 000000000..f97032f74 --- /dev/null +++ b/src/testcases/org/apache/tools/ant/taskdefs/optional/vss/MSVSSTest.java @@ -0,0 +1,458 @@ +/* + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2003 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "The Jakarta Project", "Ant", and "Apache Software + * Foundation" must not be used to endorse or promote products derived + * from this software without prior written permission. For written + * permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ +package org.apache.tools.ant.taskdefs.optional.vss; + +import java.io.File; +import java.text.SimpleDateFormat; +import java.util.Calendar; +import java.util.Date; +import java.util.TimeZone; + +import org.apache.tools.ant.BuildFileTest; +import org.apache.tools.ant.Location; +import org.apache.tools.ant.Project; +import org.apache.tools.ant.taskdefs.Tstamp; +import org.apache.tools.ant.types.Commandline; +import org.apache.tools.ant.types.Path; + +/** + * Testcase to ensure that command line generation and required attributes are correct. + * + * @author Jesse Stockall + */ +public class MSVSSTest extends BuildFileTest { + + private Project project; + private Commandline commandline; + + private static final String VSS_SERVER_PATH = "\\\\server\\vss\\srcsafe.ini"; + private static final String VSS_PROJECT_PATH = "/SourceRoot/Project"; + private static final String DS_VSS_PROJECT_PATH = "$/SourceRoot/Project"; + private static final String VSS_USERNAME = "ant"; + private static final String VSS_PASSWORD = "rocks"; + private static final String LOCAL_PATH = "testdir"; + private static final String SRC_FILE = "Class1.java"; + private static final String SRC_LABEL = "label1"; + private static final String SRC_COMMENT = "I fixed a bug"; + private static final String VERSION = "007"; + private static final String DATE = "00-00-00"; + private static final String DATE2 = "01-01-01"; + private static final String OUTPUT = "output.log"; + private static final String SS_DIR = "c:/winnt"; + + /** + * Constructor for the MSVSSTest object + * + * @param s Test name + */ + public MSVSSTest(String s) { + super(s); + } + + /** + * The JUnit setup method + * + * @throws Exception + */ + protected void setUp() + throws Exception { + ; + project = new Project(); + project.setBasedir("."); + } + + /** + * The teardown method for JUnit + * + * @throws Exception + */ + protected void tearDown() + throws Exception { + File file = new File(project.getBaseDir(), LOCAL_PATH); + if (file.exists()) { + file.delete(); + } + } + + /** Tests VSSGet commandline generation. */ + public void testGetCommandLine() { + String[] sTestCmdLine = {MSVSS.SS_EXE, MSVSS.COMMAND_GET, DS_VSS_PROJECT_PATH, + MSVSS.FLAG_OVERRIDE_WORKING_DIR + project.getBaseDir().getAbsolutePath() + + File.separator + LOCAL_PATH, MSVSS.FLAG_AUTORESPONSE_DEF, + MSVSS.FLAG_RECURSION, MSVSS.FLAG_VERSION + VERSION, MSVSS.FLAG_LOGIN + + VSS_USERNAME + "," + VSS_PASSWORD}; + + // Set up a VSSGet task + MSVSSGET vssGet = new MSVSSGET(); + vssGet.setProject(project); + vssGet.setRecursive(true); + vssGet.setLocalpath(new Path(project, LOCAL_PATH)); + vssGet.setLogin(VSS_USERNAME + "," + VSS_PASSWORD); + vssGet.setVersion(VERSION); + vssGet.setQuiet(false); + vssGet.setDate(DATE); + vssGet.setLabel(SRC_LABEL); + vssGet.setVsspath(VSS_PROJECT_PATH); + + commandline = vssGet.buildCmdLine(); + + checkCommandLines(sTestCmdLine, commandline.getCommandline()); + } + + /** Tests VSSGet required attributes. */ + public void testGetExceptions() { + configureProject("src/etc/testcases/taskdefs/optional/vss/vss.xml"); + expectSpecificBuildException("vssget.1", "some cause", "vsspath attribute must be set!"); + } + + /** Tests Label commandline generation. */ + public void testLabelCommandLine() { + String[] sTestCmdLine = {MSVSS.SS_EXE, MSVSS.COMMAND_LABEL, DS_VSS_PROJECT_PATH, + MSVSS.FLAG_COMMENT + SRC_COMMENT, MSVSS.FLAG_AUTORESPONSE_YES, + MSVSS.FLAG_LABEL + SRC_LABEL, MSVSS.FLAG_VERSION + VERSION, MSVSS.FLAG_LOGIN + + VSS_USERNAME + "," + VSS_PASSWORD}; + + // Set up a VSSLabel task + MSVSSLABEL vssLabel = new MSVSSLABEL(); + vssLabel.setProject(project); + vssLabel.setComment(SRC_COMMENT); + vssLabel.setLogin(VSS_USERNAME + "," + VSS_PASSWORD); + vssLabel.setVersion(VERSION); + vssLabel.setAutoresponse("Y"); + vssLabel.setLabel(SRC_LABEL); + vssLabel.setVsspath(VSS_PROJECT_PATH); + + commandline = vssLabel.buildCmdLine(); + + checkCommandLines(sTestCmdLine, commandline.getCommandline()); + } + + /** + * Test VSSLabel required attributes. + */ + public void testLabelExceptions() { + configureProject("src/etc/testcases/taskdefs/optional/vss/vss.xml"); + expectSpecificBuildException("vsslabel.1", "some cause", "vsspath attribute must be set!"); + expectSpecificBuildException("vsslabel.2", "some cause", "label attribute must be set!"); + } + + /** Tests VSSHistory commandline generation with from label. */ + public void testHistoryCommandLine1() { + String[] sTestCmdLine = {MSVSS.SS_EXE, MSVSS.COMMAND_HISTORY, DS_VSS_PROJECT_PATH, + MSVSS.FLAG_AUTORESPONSE_DEF, MSVSS.FLAG_VERSION_LABEL + SRC_LABEL + + MSVSS.VALUE_FROMLABEL + SRC_LABEL, MSVSS.FLAG_LOGIN + VSS_USERNAME + + "," + VSS_PASSWORD, MSVSS.FLAG_OUTPUT + project.getBaseDir().getAbsolutePath() + + File.separator + OUTPUT}; + + // Set up a VSSHistory task + MSVSSHISTORY vssHistory = new MSVSSHISTORY(); + vssHistory.setProject(project); + + vssHistory.setLogin(VSS_USERNAME + "," + VSS_PASSWORD); + + vssHistory.setFromLabel(SRC_LABEL); + vssHistory.setToLabel(SRC_LABEL); + vssHistory.setVsspath(VSS_PROJECT_PATH); + vssHistory.setRecursive(false); + vssHistory.setOutput(new File(project.getBaseDir().getAbsolutePath(), OUTPUT)); + + commandline = vssHistory.buildCmdLine(); + + checkCommandLines(sTestCmdLine, commandline.getCommandline()); + } + + /** Tests VSSHistory commandline generation with from date. */ + public void testHistoryCommandLine2() { + String[] sTestCmdLine = {MSVSS.SS_EXE, MSVSS.COMMAND_HISTORY, DS_VSS_PROJECT_PATH, + MSVSS.FLAG_AUTORESPONSE_DEF, MSVSS.FLAG_VERSION_DATE + DATE + MSVSS.VALUE_FROMDATE + + DATE2, MSVSS.FLAG_RECURSION, MSVSS.FLAG_LOGIN + VSS_USERNAME + "," + VSS_PASSWORD}; + + // Set up a VSSHistory task + MSVSSHISTORY vssHistory = new MSVSSHISTORY(); + vssHistory.setProject(project); + vssHistory.setLogin(VSS_USERNAME + "," + VSS_PASSWORD); + vssHistory.setFromDate(DATE2); + vssHistory.setToDate(DATE); + vssHistory.setVsspath(VSS_PROJECT_PATH); + vssHistory.setRecursive(true); + + commandline = vssHistory.buildCmdLine(); + + checkCommandLines(sTestCmdLine, commandline.getCommandline()); + } + + /** Tests VSSHistory commandline generation with date calculation. */ + public void testHistoryCommandLine3() { + // Set up a Timestamp + Tstamp tstamp = new Tstamp(); + Location location = new Location("src/etc/testcases/taskdefs/optional/vss/vss.xml"); + tstamp.setLocation(location); + tstamp.setProject(project); + Tstamp.CustomFormat format = tstamp.createFormat(); + format.setProperty("today"); + format.setPattern("HH:mm:ss z"); + format.setTimezone("GMT"); + Date date = Calendar.getInstance().getTime(); + format.execute(project, date, location); + String today = project.getProperty("today"); + + // Get today's date + SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss z"); + sdf.setTimeZone( TimeZone.getTimeZone("GMT") ); + String expected = sdf.format(date); + + // Set up a VSSHistory task + MSVSSHISTORY vssHistory = new MSVSSHISTORY(); + vssHistory.setProject(project); + vssHistory.setLogin(VSS_USERNAME); + vssHistory.setToDate(today); + vssHistory.setVsspath(VSS_PROJECT_PATH); + + String[] sTestCmdLine = {MSVSS.SS_EXE, MSVSS.COMMAND_HISTORY, DS_VSS_PROJECT_PATH, + MSVSS.FLAG_AUTORESPONSE_DEF, MSVSS.FLAG_VERSION_DATE + expected, MSVSS.FLAG_LOGIN + VSS_USERNAME}; + + commandline = vssHistory.buildCmdLine(); + + checkCommandLines(sTestCmdLine, commandline.getCommandline()); + } + + /** + * Tests VSSHistory required attributes. + */ + public void testHistoryExceptions() { + configureProject("src/etc/testcases/taskdefs/optional/vss/vss.xml"); + expectSpecificBuildException("vsshistory.1", "some cause", "vsspath attribute must be set!"); + } + + /** Tests CheckIn commandline generation. */ + public void testCheckinCommandLine() { + String[] sTestCmdLine = {MSVSS.SS_EXE, MSVSS.COMMAND_CHECKIN, DS_VSS_PROJECT_PATH, + MSVSS.FLAG_AUTORESPONSE_NO, MSVSS.FLAG_WRITABLE, MSVSS.FLAG_LOGIN + VSS_USERNAME, + MSVSS.FLAG_COMMENT + SRC_COMMENT}; + + // Set up a VSSCheckIn task + MSVSSCHECKIN vssCheckin = new MSVSSCHECKIN(); + vssCheckin.setProject(project); + vssCheckin.setComment(SRC_COMMENT); + vssCheckin.setLogin(VSS_USERNAME); + vssCheckin.setAutoresponse("N"); + vssCheckin.setVsspath(VSS_PROJECT_PATH); + vssCheckin.setWritable(true); + + commandline = vssCheckin.buildCmdLine(); + + checkCommandLines(sTestCmdLine, commandline.getCommandline()); + } + + /** + * Test VSSCheckIn required attributes. + */ + public void testCheckinExceptions() { + configureProject("src/etc/testcases/taskdefs/optional/vss/vss.xml"); + expectSpecificBuildException("vsscheckin.1", "some cause", "vsspath attribute must be set!"); + } + + /** Tests CheckOut commandline generation. */ + public void testCheckoutCommandLine() { + String[] sTestCmdLine = {SS_DIR + File.separator + MSVSS.SS_EXE, MSVSS.COMMAND_CHECKOUT, + DS_VSS_PROJECT_PATH, MSVSS.FLAG_AUTORESPONSE_DEF, MSVSS.FLAG_RECURSION, + MSVSS.FLAG_VERSION_DATE + DATE, MSVSS.FLAG_LOGIN + VSS_USERNAME}; + + // Set up a VSSCheckOut task + MSVSSCHECKOUT vssCheckout = new MSVSSCHECKOUT(); + vssCheckout.setProject(project); + vssCheckout.setLogin(VSS_USERNAME); + vssCheckout.setVsspath(DS_VSS_PROJECT_PATH); + vssCheckout.setRecursive(true); + vssCheckout.setDate(DATE); + vssCheckout.setSsdir(SS_DIR); + + commandline = vssCheckout.buildCmdLine(); + + checkCommandLines(sTestCmdLine, commandline.getCommandline()); + } + + /** + * Test VSSCheckout required attributes. + */ + public void testCheckoutExceptions() { + configureProject("src/etc/testcases/taskdefs/optional/vss/vss.xml"); + expectSpecificBuildException("vsscheckout.1", "some cause", "vsspath attribute must be set!"); + } + + /** Tests Add commandline generation. */ + public void testAddCommandLine() { + String[] sTestCmdLine = {SS_DIR + File.separator + MSVSS.SS_EXE, MSVSS.COMMAND_ADD, + project.getBaseDir().getAbsolutePath() + File.separator + LOCAL_PATH, + MSVSS.FLAG_AUTORESPONSE_DEF, MSVSS.FLAG_RECURSION, + MSVSS.FLAG_LOGIN + VSS_USERNAME + "," + VSS_PASSWORD, MSVSS.FLAG_COMMENT + "-"}; + + // Set up a VSSAdd task + MSVSSADD vssAdd = new MSVSSADD(); + vssAdd.setProject(project); + vssAdd.setLogin(VSS_USERNAME + "," + VSS_PASSWORD); + vssAdd.setVsspath(DS_VSS_PROJECT_PATH); + vssAdd.setRecursive(true); + vssAdd.setSsdir(SS_DIR); + vssAdd.setWritable(false); + vssAdd.setLocalpath(new Path(project, LOCAL_PATH)); + + commandline = vssAdd.buildCmdLine(); + + checkCommandLines(sTestCmdLine, commandline.getCommandline()); + } + + /** + * Test VSSAdd required attributes. + */ + public void testAddExceptions() { + configureProject("src/etc/testcases/taskdefs/optional/vss/vss.xml"); + expectSpecificBuildException("vssadd.1", "some cause", "localPath attribute must be set!"); + } + + /** Tests CP commandline generation. */ + public void testCpCommandLine() { + String[] sTestCmdLine = {MSVSS.SS_EXE, MSVSS.COMMAND_CP, + DS_VSS_PROJECT_PATH, MSVSS.FLAG_AUTORESPONSE_DEF, MSVSS.FLAG_LOGIN + + VSS_USERNAME}; + + // Set up a VSSCp task + MSVSSCP vssCp = new MSVSSCP(); + vssCp.setProject(project); + vssCp.setLogin(VSS_USERNAME); + vssCp.setVsspath(DS_VSS_PROJECT_PATH); + + commandline = vssCp.buildCmdLine(); + + checkCommandLines(sTestCmdLine, commandline.getCommandline()); + } + + /** + * Test VSSCP required attributes. + */ + public void testCpExceptions() { + configureProject("src/etc/testcases/taskdefs/optional/vss/vss.xml"); + expectSpecificBuildException("vsscp.1", "some cause", "vsspath attribute must be set!"); + } + + /** Tests Create commandline generation. */ + public void testCreateCommandLine() { + String[] sTestCmdLine = { MSVSS.SS_EXE, MSVSS.COMMAND_CREATE, + DS_VSS_PROJECT_PATH, MSVSS.FLAG_COMMENT + SRC_COMMENT, MSVSS.FLAG_AUTORESPONSE_NO, + MSVSS.FLAG_QUIET, MSVSS.FLAG_LOGIN + VSS_USERNAME}; + + // Set up a VSSCreate task + MSVSSCREATE vssCreate = new MSVSSCREATE(); + vssCreate.setProject(project); + vssCreate.setComment(SRC_COMMENT); + vssCreate.setLogin(VSS_USERNAME); + vssCreate.setVsspath(DS_VSS_PROJECT_PATH); + vssCreate.setFailOnError(true); + vssCreate.setAutoresponse("N"); + vssCreate.setQuiet(true); + + commandline = vssCreate.buildCmdLine(); + + checkCommandLines(sTestCmdLine, commandline.getCommandline()); + } + + /** + * Test VSSCreate required attributes. + */ + public void testCreateExceptions() { + configureProject("src/etc/testcases/taskdefs/optional/vss/vss.xml"); + expectSpecificBuildException("vsscreate.1", "some cause", "vsspath attribute must be set!"); + } + + /** + * Iterate through the generated command line comparing it to reference one. + * @param sTestCmdLine The reference command line; + * @param sGeneratedCmdLine The generated command line; + */ + private void checkCommandLines(String[] sTestCmdLine, String[] sGeneratedCmdLine) { + int testLength = sTestCmdLine.length; + int genLength = sGeneratedCmdLine.length; + + int genIndex = 0; + int testIndex = 0; + + while (testIndex < testLength) { + try { + if (sGeneratedCmdLine[genIndex] == "") { + genIndex++; + continue; + } + assertEquals("arg # " + testIndex, + sTestCmdLine[testIndex], + sGeneratedCmdLine[genIndex]); + testIndex++; + genIndex++; + } catch (ArrayIndexOutOfBoundsException aioob) { + fail("missing arg " + sTestCmdLine[testIndex]); + } + } + + // Count the number of empty strings + int cnt = 0; + for (int i = 0; i < genLength; i++) { + if (sGeneratedCmdLine[i] == "") { + cnt++; + } + } + if (genLength - cnt > sTestCmdLine.length) { + // We have extra elements + fail("extra args"); + } + } +}