PR: 21144 Obtained from: Alexey Solofnenko git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@274834 13f79535-47bb-0310-9956-ffa450edef68master
| @@ -95,6 +95,8 @@ Options: | |||||
| -file <file> '' | -file <file> '' | ||||
| -f <file> '' | -f <file> '' | ||||
| -D<property>=<value> use value for given property | -D<property>=<value> use value for given property | ||||
| -keep-going, -k execute all targets that do not depend | |||||
| on failed target(s) | |||||
| -propertyfile <name> load all properties from file with -D | -propertyfile <name> load all properties from file with -D | ||||
| properties taking precedence | properties taking precedence | ||||
| -inputhandler <class> the class which will handle input requests | -inputhandler <class> the class which will handle input requests | ||||
| @@ -113,6 +113,9 @@ public class Main implements AntMain { | |||||
| /** Indicates whether this build is to support interactive input */ | /** Indicates whether this build is to support interactive input */ | ||||
| private boolean allowInput = true; | private boolean allowInput = true; | ||||
| /** keep going mode */ | |||||
| private boolean keepGoingMode = false; | |||||
| /** | /** | ||||
| * The Ant logger class. There may be only one logger. It will have | * The Ant logger class. There may be only one logger. It will have | ||||
| * the right to use the 'out' PrintStream. The class must implements the | * the right to use the 'out' PrintStream. The class must implements the | ||||
| @@ -422,6 +425,8 @@ public class Main implements AntMain { | |||||
| "using the -propertyfile argument"; | "using the -propertyfile argument"; | ||||
| throw new BuildException(msg); | throw new BuildException(msg); | ||||
| } | } | ||||
| } else if (arg.equals("-k") || arg.equals("-keep-going")) { | |||||
| keepGoingMode = true; | |||||
| } else if (arg.startsWith("-")) { | } else if (arg.startsWith("-")) { | ||||
| // we don't have any more args to recognize! | // we don't have any more args to recognize! | ||||
| String msg = "Unknown argument: " + arg; | String msg = "Unknown argument: " + arg; | ||||
| @@ -634,6 +639,8 @@ public class Main implements AntMain { | |||||
| project.setUserProperty("ant.file", | project.setUserProperty("ant.file", | ||||
| buildFile.getAbsolutePath()); | buildFile.getAbsolutePath()); | ||||
| project.setKeepGoingMode(keepGoingMode); | |||||
| ProjectHelper.configureProject(project, buildFile); | ProjectHelper.configureProject(project, buildFile); | ||||
| if (projectHelp) { | if (projectHelp) { | ||||
| @@ -800,6 +807,8 @@ public class Main implements AntMain { | |||||
| msg.append(" -file <file> ''" + lSep); | msg.append(" -file <file> ''" + lSep); | ||||
| msg.append(" -f <file> ''" + lSep); | msg.append(" -f <file> ''" + lSep); | ||||
| msg.append(" -D<property>=<value> use value for given property" + lSep); | msg.append(" -D<property>=<value> use value for given property" + lSep); | ||||
| msg.append(" -keep-going, -k execute all targets that do not depend" + lSep); | |||||
| msg.append(" on failed target(s)" + lSep); | |||||
| msg.append(" -propertyfile <name> load all properties from file with -D" + lSep); | msg.append(" -propertyfile <name> load all properties from file with -D" + lSep); | ||||
| msg.append(" properties taking precedence" + lSep); | msg.append(" properties taking precedence" + lSep); | ||||
| msg.append(" -inputhandler <class> the class which will handle input requests" + lSep); | msg.append(" -inputhandler <class> the class which will handle input requests" + lSep); | ||||
| @@ -65,6 +65,8 @@ import java.util.Hashtable; | |||||
| import java.util.Properties; | import java.util.Properties; | ||||
| import java.util.Stack; | import java.util.Stack; | ||||
| import java.util.Vector; | import java.util.Vector; | ||||
| import java.util.Set; | |||||
| import java.util.HashSet; | |||||
| import org.apache.tools.ant.input.DefaultInputHandler; | import org.apache.tools.ant.input.DefaultInputHandler; | ||||
| import org.apache.tools.ant.input.InputHandler; | import org.apache.tools.ant.input.InputHandler; | ||||
| import org.apache.tools.ant.types.FilterSet; | import org.apache.tools.ant.types.FilterSet; | ||||
| @@ -207,6 +209,11 @@ public class Project { | |||||
| */ | */ | ||||
| private InputStream defaultInputStream = null; | private InputStream defaultInputStream = null; | ||||
| /** | |||||
| * Keep going flag | |||||
| */ | |||||
| private boolean keepGoingMode = false; | |||||
| /** | /** | ||||
| * Sets the input handler | * Sets the input handler | ||||
| * | * | ||||
| @@ -272,6 +279,7 @@ public class Project { | |||||
| public void initSubProject(Project subProject) { | public void initSubProject(Project subProject) { | ||||
| ComponentHelper.getComponentHelper(subProject) | ComponentHelper.getComponentHelper(subProject) | ||||
| .initSubProject(ComponentHelper.getComponentHelper(this)); | .initSubProject(ComponentHelper.getComponentHelper(this)); | ||||
| subProject.setKeepGoingMode(this.isKeepGoingMode()); | |||||
| } | } | ||||
| /** | /** | ||||
| @@ -778,6 +786,26 @@ public class Project { | |||||
| return baseDir; | return baseDir; | ||||
| } | } | ||||
| /** | |||||
| * Sets "keep-going" mode. In this mode ANT will try to execute | |||||
| * as many targets as possible. All targets that do not depend | |||||
| * on failed target(s) will be executed. | |||||
| * @param keepGoingMode "keep-going" mode | |||||
| * @since Ant 1.6 | |||||
| */ | |||||
| public void setKeepGoingMode(boolean keepGoingMode) { | |||||
| this.keepGoingMode = keepGoingMode; | |||||
| } | |||||
| /** | |||||
| * Returns the keep-going mode. | |||||
| * @return "keep-going" mode | |||||
| * @since Ant 1.6 | |||||
| */ | |||||
| public boolean isKeepGoingMode() { | |||||
| return this.keepGoingMode; | |||||
| } | |||||
| /** | /** | ||||
| * Returns the version of Java this class is running under. | * Returns the version of Java this class is running under. | ||||
| * @return the version of Java as a String, e.g. "1.1" | * @return the version of Java as a String, e.g. "1.1" | ||||
| @@ -1174,13 +1202,70 @@ public class Project { | |||||
| // graph. | // graph. | ||||
| Vector sortedTargets = topoSort(targetName, targets); | Vector sortedTargets = topoSort(targetName, targets); | ||||
| int curidx = 0; | |||||
| Target curtarget; | |||||
| do { | |||||
| curtarget = (Target) sortedTargets.elementAt(curidx++); | |||||
| curtarget.performTasks(); | |||||
| } while (!curtarget.getName().equals(targetName)); | |||||
| Set succeededTargets = new HashSet(); | |||||
| BuildException buildException = null; // first build exception | |||||
| for (Enumeration iter = sortedTargets.elements(); | |||||
| iter.hasMoreElements();) { | |||||
| Target curtarget = (Target) iter.nextElement(); | |||||
| boolean canExecute = true; | |||||
| for (Enumeration depIter = curtarget.getDependencies(); | |||||
| depIter.hasMoreElements();) { | |||||
| String dependencyName = ((String) depIter.nextElement()); | |||||
| if (!succeededTargets.contains(dependencyName)) { | |||||
| canExecute = false; | |||||
| log(curtarget, | |||||
| "Cannot execute '" + curtarget.getName() + "' - '" | |||||
| + dependencyName + "' failed or was not executed.", | |||||
| MSG_ERR); | |||||
| break; | |||||
| } | |||||
| } | |||||
| if (canExecute) { | |||||
| Throwable thrownException = null; | |||||
| try { | |||||
| curtarget.performTasks(); | |||||
| succeededTargets.add(curtarget.getName()); | |||||
| } catch (RuntimeException ex) { | |||||
| if (!(keepGoingMode)) { | |||||
| throw ex; // throw further | |||||
| } | |||||
| thrownException = ex; | |||||
| } catch (Throwable ex) { | |||||
| if (!(keepGoingMode)) { | |||||
| throw new BuildException(ex); | |||||
| } | |||||
| thrownException = ex; | |||||
| } | |||||
| if (thrownException != null) { | |||||
| if (thrownException instanceof BuildException) { | |||||
| log(curtarget, | |||||
| "Target '" + curtarget.getName() | |||||
| + "' failed with message '" | |||||
| + thrownException.getMessage() + "'.", MSG_ERR); | |||||
| // only the first build exception is reported | |||||
| if (buildException == null) { | |||||
| buildException = (BuildException) thrownException; | |||||
| } | |||||
| } else { | |||||
| log(curtarget, | |||||
| "Target '" + curtarget.getName() | |||||
| + "' failed with message '" | |||||
| + thrownException.getMessage() + "'.", MSG_ERR); | |||||
| thrownException.printStackTrace(System.err); | |||||
| if (buildException == null) { | |||||
| buildException = | |||||
| new BuildException(thrownException); | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| if (curtarget.getName().equals(targetName)) { // old exit condition | |||||
| break; | |||||
| } | |||||
| } | |||||
| if (buildException != null) { | |||||
| throw buildException; | |||||
| } | |||||
| } | } | ||||
| /** | /** | ||||
| @@ -134,18 +134,57 @@ public class SubAnt | |||||
| target = getOwningTarget().getName(); | target = getOwningTarget().getName(); | ||||
| } | } | ||||
| */ | */ | ||||
| BuildException buildException = null; | |||||
| for (int i = 0; i < count; ++i) { | for (int i = 0; i < count; ++i) { | ||||
| File directory = null; | |||||
| File file = new File(filenames[i]); | |||||
| if (file.isDirectory()) { | |||||
| if (genericantfile != null) { | |||||
| directory = file; | |||||
| file = genericantfile; | |||||
| File file = null; | |||||
| Throwable thrownException = null; | |||||
| try { | |||||
| File directory = null; | |||||
| file = new File(filenames[i]); | |||||
| if (file.isDirectory()) { | |||||
| if (genericantfile != null) { | |||||
| directory = file; | |||||
| file = genericantfile; | |||||
| } else { | |||||
| file = new File(file, antfile); | |||||
| } | |||||
| } | |||||
| execute(file, directory); | |||||
| } catch (RuntimeException ex) { | |||||
| if (!(getProject().isKeepGoingMode())) { | |||||
| throw ex; // throw further | |||||
| } | |||||
| thrownException = ex; | |||||
| } catch (Throwable ex) { | |||||
| if (!(getProject().isKeepGoingMode())) { | |||||
| throw new BuildException(ex); | |||||
| } | |||||
| thrownException = ex; | |||||
| } | |||||
| if (thrownException != null) { | |||||
| if (thrownException instanceof BuildException) { | |||||
| log("File '" + file | |||||
| + "' failed with message '" | |||||
| + thrownException.getMessage() + "'.", Project.MSG_ERR); | |||||
| // only the first build exception is reported | |||||
| if (buildException == null) { | |||||
| buildException = (BuildException) thrownException; | |||||
| } | |||||
| } else { | } else { | ||||
| file = new File(file, antfile); | |||||
| log("Target '" + file | |||||
| + "' failed with message '" | |||||
| + thrownException.getMessage() + "'.", Project.MSG_ERR); | |||||
| thrownException.printStackTrace(System.err); | |||||
| if (buildException == null) { | |||||
| buildException = | |||||
| new BuildException(thrownException); | |||||
| } | |||||
| } | } | ||||
| } | } | ||||
| execute(file, directory); | |||||
| } | |||||
| // check if one of the builds failed in keep going mode | |||||
| if (buildException != null) { | |||||
| throw buildException; | |||||
| } | } | ||||
| } | } | ||||