001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: *
017: */
018:
019: package org.apache.tools.ant.taskdefs;
020:
021: import java.io.File;
022: import java.io.IOException;
023: import org.apache.tools.ant.BuildException;
024: import org.apache.tools.ant.Project;
025: import org.apache.tools.ant.Task;
026: import org.apache.tools.ant.types.Commandline;
027:
028: /**
029: * Patches a file by applying a 'diff' file to it; requires "patch" to be
030: * on the execution path.
031: *
032: * @since Ant 1.1
033: *
034: * @ant.task category="utility"
035: */
036: public class Patch extends Task {
037:
038: private File originalFile;
039: private File directory;
040: private boolean havePatchfile = false;
041: private Commandline cmd = new Commandline();
042:
043: /**
044: * The file to patch; optional if it can be inferred from
045: * the diff file
046: * @param file the file to patch
047: */
048: public void setOriginalfile(File file) {
049: originalFile = file;
050: }
051:
052: /**
053: * The name of a file to send the output to, instead of patching
054: * the file(s) in place; optional.
055: * @param file the file to send the output to
056: * @since Ant 1.6
057: */
058: public void setDestfile(File file) {
059: if (file != null) {
060: cmd.createArgument().setValue("-o");
061: cmd.createArgument().setFile(file);
062: }
063: }
064:
065: /**
066: * The file containing the diff output; required.
067: * @param file the file containing the diff output
068: */
069: public void setPatchfile(File file) {
070: if (!file.exists()) {
071: throw new BuildException("patchfile " + file
072: + " doesn\'t exist", getLocation());
073: }
074: cmd.createArgument().setValue("-i");
075: cmd.createArgument().setFile(file);
076: havePatchfile = true;
077: }
078:
079: /**
080: * flag to create backups; optional, default=false
081: * @param backups if true create backups
082: */
083: public void setBackups(boolean backups) {
084: if (backups) {
085: cmd.createArgument().setValue("-b");
086: }
087: }
088:
089: /**
090: * flag to ignore whitespace differences; default=false
091: * @param ignore if true ignore whitespace differences
092: */
093: public void setIgnorewhitespace(boolean ignore) {
094: if (ignore) {
095: cmd.createArgument().setValue("-l");
096: }
097: }
098:
099: /**
100: * Strip the smallest prefix containing <i>num</i> leading slashes
101: * from filenames.
102: *
103: * <p>patch's <i>-p</i> option.
104: * @param num number of lines to strip
105: * @exception BuildException if num is < 0, or other errors
106: */
107: public void setStrip(int num) throws BuildException {
108: if (num < 0) {
109: throw new BuildException("strip has to be >= 0",
110: getLocation());
111: }
112: cmd.createArgument().setValue("-p" + num);
113: }
114:
115: /**
116: * Work silently unless an error occurs; optional, default=false
117: * @param q if true suppress set the -s option on the patch command
118: */
119: public void setQuiet(boolean q) {
120: if (q) {
121: cmd.createArgument().setValue("-s");
122: }
123: }
124:
125: /**
126: * Assume patch was created with old and new files swapped; optional,
127: * default=false
128: * @param r if true set the -R option on the patch command
129: */
130: public void setReverse(boolean r) {
131: if (r) {
132: cmd.createArgument().setValue("-R");
133: }
134: }
135:
136: /**
137: * The directory to run the patch command in, defaults to the
138: * project's base directory.
139: * @param directory the directory to run the patch command in
140: * @since Ant 1.5
141: */
142: public void setDir(File directory) {
143: this .directory = directory;
144: }
145:
146: /**
147: * execute patch
148: * @throws BuildException when it all goes a bit pear shaped
149: */
150: public void execute() throws BuildException {
151: if (!havePatchfile) {
152: throw new BuildException("patchfile argument is required",
153: getLocation());
154: }
155: Commandline toExecute = (Commandline) cmd.clone();
156: toExecute.setExecutable("patch");
157:
158: if (originalFile != null) {
159: toExecute.createArgument().setFile(originalFile);
160: }
161:
162: Execute exe = new Execute(new LogStreamHandler(this ,
163: Project.MSG_INFO, Project.MSG_WARN), null);
164: exe.setCommandline(toExecute.getCommandline());
165:
166: if (directory != null) {
167: if (directory.exists() && directory.isDirectory()) {
168: exe.setWorkingDirectory(directory);
169: } else if (!directory.isDirectory()) {
170: throw new BuildException(directory
171: + " is not a directory.", getLocation());
172: } else {
173: throw new BuildException("directory " + directory
174: + " doesn\'t exist", getLocation());
175: }
176: } else {
177: exe.setWorkingDirectory(getProject().getBaseDir());
178: }
179:
180: log(toExecute.describeCommand(), Project.MSG_VERBOSE);
181: try {
182: exe.execute();
183: } catch (IOException e) {
184: throw new BuildException(e, getLocation());
185: }
186: }
187: }
|