Ticket #448: PatchTask.4.php

File PatchTask.4.php, 5.4 KB (added by Merkas <mk@…>, 2 years ago)

Fixed "haltOnFailure"

Line 
1<?php
2/**
3 *  Patches a file by applying a 'diff' file to it
4 *
5 *  Requires "patch" to be on the execution path.
6 *
7 *  Based on Apache Ant PatchTask:
8 *
9 *  Licensed to the Apache Software Foundation (ASF) under one or more
10 *  contributor license agreements.  See the NOTICE file distributed with
11 *  this work for additional information regarding copyright ownership.
12 *  The ASF licenses this file to You under the Apache License, Version 2.0
13 *  (the "License"); you may not use this file except in compliance with
14 *  the License.  You may obtain a copy of the License at
15 *
16 *      http://www.apache.org/licenses/LICENSE-2.0
17 *
18 *  Unless required by applicable law or agreed to in writing, software
19 *  distributed under the License is distributed on an "AS IS" BASIS,
20 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
21 *  See the License for the specific language governing permissions and
22 *  limitations under the License.
23 *
24 * @author Mikhail Krasilnikov <mk@3wstyle>
25 * @version 0.01
26 * @package phing.tasks.ext
27 */
28require_once 'phing/Task.php';
29
30/**
31 * Patches a file by applying a 'diff' file to it
32 *
33 * Requires "patch" to be on the execution path.
34 *
35 * @package phing.tasks.ext
36 */
37class PatchTask extends Task
38{
39    /**
40     * Base command to be executed
41     * @var string
42     */
43    const CMD = 'patch --batch ';
44
45    /**
46     * File to be patched
47     * @var string
48     */
49    private $originalFile;
50
51    /**
52     * Patch file
53     *
54     * @var string
55     */
56    private $patchFile;
57
58    /**
59     * Value for a "-p" option
60     * @var int
61     */
62    private $strip;
63
64    /**
65     * Command line arguments for patch binary
66     * @var array
67     */
68    private $cmdArgs = array();
69
70    /**
71     * Halt on error return value from patch invocation.
72     * @var bool
73     */
74    private $haltOnFailure = false;
75
76    /**
77     * The file containing the diff output
78     *
79     * Required.
80     *
81     * @param string $file  File containing the diff output
82     * @return void
83     * @throws BuildException if $file not exists
84     */
85    public function setPatchFile($file)
86    {
87        if (!is_file($file))
88            throw new BuildException(sprintf('Patchfile %s doesn\'t exist', $file));
89
90    $this->patchFile = $file;
91    }
92
93    /**
94     * The file to patch
95     *
96     * Optional if it can be inferred from the diff file.
97     *
98     * @param string $file  File to patch
99     * @return void
100     */
101    public function setOriginalFile($file)
102    {
103        $this->originalFile = $file;
104    }
105
106    /**
107     * The name of a file to send the output to, instead of patching
108     * the file(s) in place
109     *
110     * Optional.
111     *
112     * @param string $file   File to send the output to
113     * @return void
114     */
115    public function setDestFile($file)
116    {
117        if ($file !== null)
118            $this->cmdArgs []= "--output=$file";
119    }
120
121    /**
122     * Flag to create backups
123     *
124     * Optional, default - false
125     *
126     * @param bool $backups  If true create backups
127     * @return void
128     */
129    public function setBackups($backups)
130    {
131        if ($backups)
132            $this->cmdArgs []= '--backup';
133    }
134
135    /**
136     * Flag to ignore whitespace differences;
137     *
138     * Default - false
139     *
140     * @param bool $ignore  If true ignore whitespace differences
141     * @return void
142     */
143    public function setIgnoreWhiteSpace($ignore)
144    {
145        if ($ignore)
146            $this->cmdArgs []= '--ignore-whitespace';
147    }
148
149    /**
150     * Strip the smallest prefix containing <i>num</i> leading slashes
151     * from filenames.
152     *
153     * patch's <i>--strip</i> option.
154     *
155     * @param int $num number of lines to strip
156     * @return void
157     * @throws BuildException if num is < 0, or other errors
158     */
159    public function setStrip($num)
160    {
161        if ($num < 0)
162            throw new BuildException('strip has to be >= 0');
163
164        $this->strip = $num;
165    }
166
167    /**
168     * Work silently unless an error occurs
169     *
170     * Optional, default - false
171     * @param bool $flag  If true suppress set the -s option on the patch command
172     * @return void
173     */
174    public function setQuiet($flag)
175    {
176        if ($flag)
177            $this->cmdArgs []= '--silent';
178    }
179
180    /**
181     * Assume patch was created with old and new files swapped
182     *
183     * Optional, default - false
184     *
185     * @param bool $flag  If true set the -R option on the patch command
186     * @return void
187     */
188    public function setReverse($flag)
189    {
190        if ($flag)
191            $this->cmdArgs []= '--reverse';
192    }
193
194    /**
195     * The directory to run the patch command in
196     *
197     * Defaults to the project's base directory.
198     *
199     * @param string $directory  Directory to run the patch command in
200     * @return void
201     */
202    public function setDir($directory)
203    {
204        $this->cmdArgs []= "--directory=$directory";
205    }
206
207    /**
208     * If true, stop the build process if the patch command
209     * exits with an error status.
210     *
211     * The default is "false"
212     *
213     * @param bool $value  "true" if it should halt, otherwise "false"
214     * @return void
215     */
216    public function setHaltOnFailure($value)
217    {
218        $this->haltOnFailure = $value;
219    }
220
221    /**
222     * Main task method
223     *
224     * @return void
225     * @throws BuildException when it all goes a bit pear shaped
226     */
227    public function main()
228    {
229        if ($this->patchFile == null)
230            throw new BuildException('patchfile argument is required');
231
232        // Define patch file
233        $this->cmdArgs []= '-i ' . $this->patchFile;
234        // Define strip factor
235        if ($this->strip != null)
236            $this->cmdArgs []= '--strip=' . $this->strip;
237        // Define original file if specified
238        if ($this->originalFile != null)
239            $this->cmdArgs []= $this->originalFile;
240
241        $cmd = self::CMD . implode(' ', $this->cmdArgs);
242
243        $this->log('Applying patch: ' . $this->patchFile);
244
245        exec($cmd, $output, $exitCode);
246
247        foreach ($output as $line)
248            $this->log($line, Project::MSG_VERBOSE);
249
250        if ($exitCode != 0 && $this->haltOnFailure)
251            throw new BuildException( "Task exited with code $exitCode" );
252
253    }
254}