Subversion-Projekte lars-tiefland.php_share

Revision

Details | Letzte Änderung | Log anzeigen | RSS feed

Revision Autor Zeilennr. Zeile
1 lars 1
<?php
2
/*
3
 *  $Id: CvsTask.php 227 2007-08-28 02:17:00Z hans $
4
 *
5
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
6
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
7
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
8
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
9
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
10
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
11
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
12
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
13
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
14
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
15
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
16
 *
17
 * This software consists of voluntary contributions made by many individuals
18
 * and is licensed under the LGPL. For more information please see
19
 * <http://phing.info>.
20
 */
21
 
22
require_once 'phing/Task.php';
23
include_once 'phing/tasks/system/ExecTask.php';
24
include_once 'phing/types/Commandline.php';
25
 
26
/**
27
 * Task for performing CVS operations.
28
 *
29
 *  NOTE: This implementation has been moved here from Cvs.java with
30
 *  the addition of some accessors for extensibility.  Another task
31
 *  can extend this with some customized output processing.
32
 *
33
 * @author Hans Lellelid <hans@xmpl.org> (Phing)
34
 * @author costin@dnt.ro (Ant)
35
 * @author stefano@apache.org (Ant)
36
 * @author Wolfgang Werner <wwerner@picturesafe.de> (Ant)
37
 * @author Kevin Ross <kevin.ross@bredex.com> (Ant)
38
 * @version $Revision: 1.14 $
39
 * @package phing.tasks.system
40
 */
41
class CvsTask extends Task {
42
 
43
    /**
44
     * Default compression level to use, if compression is enabled via
45
     * setCompression( true ).
46
     */
47
    const DEFAULT_COMPRESSION_LEVEL = 3;
48
 
49
    private $cmd;
50
 
51
    /**
52
     * List of Commandline children
53
     * @var array Commandline[]
54
     */
55
    private $commandlines = array();
56
 
57
    /**
58
     * the CVSROOT variable.
59
     */
60
    private $cvsRoot;
61
 
62
    /**
63
     * the CVS_RSH variable.
64
     */
65
    private $cvsRsh;
66
 
67
    /**
68
     * the package/module to check out.
69
     */
70
    private $cvsModule;
71
 
72
    /**
73
     * the default command.
74
     */
75
    private static $default_command = "checkout";
76
 
77
    /**
78
     * the CVS command to execute.
79
     */
80
    private $command = null;
81
 
82
    /**
83
     * suppress information messages.
84
     */
85
    private $quiet = false;
86
 
87
    /**
88
     * compression level to use.
89
     */
90
    private $compression = 0;
91
 
92
    /**
93
     * report only, don't change any files.
94
     */
95
    private $noexec = false;
96
 
97
    /**
98
     * CVS port
99
     */
100
    private $port = 0;
101
 
102
    /**
103
     * CVS password file
104
     * @var File
105
     */
106
    private $passFile = null;
107
 
108
    /**
109
     * the directory where the checked out files should be placed.
110
     * @var File
111
     */
112
    private $dest;
113
 
114
    private $error;
115
 
116
    private $output;
117
 
118
    /**
119
     * If true it will stop the build if cvs exits with error.
120
     * Default is false. (Iulian)
121
     * @var boolean
122
     */
123
    private $failOnError = false;
124
 
125
    public function init() {
126
        $this->cmd = new Commandline();
127
    }
128
 
129
    /**
130
     * Sets up the environment for toExecute and then runs it.
131
     * @param Commandline $toExecute
132
     * @throws BuildException
133
     */
134
    protected function runCommand(Commandline $toExecute) {
135
 
136
        // We are putting variables into the script's environment
137
        // and not removing them (!)  This should be fine, but is
138
        // worth remembering and testing.
139
 
140
        if ($this->port > 0) {
141
            putenv("CVS_CLIENT_PORT=".$this->port);
142
        }
143
 
144
         // Need a better cross platform integration with <cvspass>, so
145
         // use the same filename.
146
 
147
        if ($this->passFile === null) {
148
            $defaultPassFile = new PhingFile(Phing::getProperty("cygwin.user.home", Phing::getProperty("user.home"))
149
                . DIRECTORY_SEPARATOR . ".cvspass");
150
            if($defaultPassFile->exists()) {
151
                $this->setPassfile($defaultPassFile);
152
            }
153
        }
154
 
155
        if ($this->passFile !== null) {
156
            if ($this->passFile->isFile() && $this->passFile->canRead()) {
157
                putenv("CVS_PASSFILE=" . $this->passFile->__toString());
158
                $this->log("Using cvs passfile: " . $this->passFile->__toString(), Project::MSG_INFO);
159
            } elseif (!$this->passFile->canRead()) {
160
                $this->log("cvs passfile: " . $this->passFile->__toString()
161
                    . " ignored as it is not readable", Project::MSG_WARN);
162
            } else {
163
                $this->log("cvs passfile: " . $this->passFile->__toString()
164
                    . " ignored as it is not a file",
165
                    Project::MSG_WARN);
166
            }
167
        }
168
 
169
        if ($this->cvsRsh !== null) {
170
            putenv("CVS_RSH=".$this->cvsRsh);
171
        }
172
 
173
        // Use the ExecTask to handle execution of the command
174
        $exe = new ExecTask($this->project);
175
        $exe->setProject($this->project);
176
 
177
        //exe.setAntRun(project);
178
        if ($this->dest === null) {
179
            $this->dest = $this->project->getBaseDir();
180
        }
181
 
182
        if (!$this->dest->exists()) {
183
            $this->dest->mkdirs();
184
        }
185
 
186
        if ($this->output !== null) {
187
            $exe->setOutput($this->output);
188
        }
189
 
190
        if ($this->error !== null) {
191
            $exe->setError($this->error);
192
        }
193
 
194
        $exe->setDir($this->dest);
195
 
196
        if (is_object($toExecute)) {
197
            $toExecuteStr = $toExecute->__toString(); // unfortunately no more automagic for initial 5.0.0 release :(
198
        }
199
 
200
        $exe->setCommand($toExecuteStr);
201
 
202
        try {
203
            $actualCommandLine = $toExecuteStr; // we converted to string above
204
            $this->log($actualCommandLine, Project::MSG_INFO);
205
            $retCode = $exe->execute();
206
            $this->log("retCode=" . $retCode, Project::MSG_DEBUG);
207
            /*Throw an exception if cvs exited with error. (Iulian)*/
208
            if ($this->failOnError && $retCode !== 0) {
209
                throw new BuildException("cvs exited with error code "
210
                                         . $retCode
211
                                         . PHP_EOL
212
                                         . "Command line was ["
213
                                         . $toExecute->describeCommand() . "]", $this->getLocation());
214
            }
215
        } catch (IOException $e) {
216
            if ($this->failOnError) {
217
                throw new BuildException($e, $this->getLocation());
218
            } else {
219
                $this->log("Caught exception: " . $e, Project::MSG_WARN);
220
            }
221
        } catch (BuildException $e) {
222
            if ($this->failOnError) {
223
                throw $e;
224
            } else {
225
                $t = $e->getCause();
226
                if ($t === null) {
227
                    $t = $e;
228
                }
229
                $this->log("Caught exception: " . $t, Project::MSG_WARN);
230
            }
231
        } catch (Exception $e) {
232
            if ($this->failOnError) {
233
                throw new BuildException($e, $this->getLocation());
234
            } else {
235
                $this->log("Caught exception: " . $e, Project::MSG_WARN);
236
            }
237
        }
238
    }
239
 
240
    /**
241
     *
242
     * @return void
243
     * @throws BuildException
244
     */
245
    public function main() {
246
 
247
        $savedCommand = $this->getCommand();
248
 
249
        if ($this->getCommand() === null && empty($this->commandlines)) {
250
            // re-implement legacy behaviour:
251
            $this->setCommand(self::$default_command);
252
        }
253
 
254
        $c = $this->getCommand();
255
        $cloned = null;
256
        if ($c !== null) {
257
            $cloned = $this->cmd->__copy();
258
            $cloned->createArgument(true)->setLine($c);
259
            $this->addConfiguredCommandline($cloned, true);
260
        }
261
 
262
        try {
263
            for ($i = 0, $vecsize=count($this->commandlines); $i < $vecsize; $i++) {
264
                $this->runCommand($this->commandlines[$i]);
265
            }
266
 
267
            // finally    {
268
            if ($cloned !== null) {
269
                $this->removeCommandline($cloned);
270
            }
271
            $this->setCommand($savedCommand);
272
 
273
        } catch (Exception $e) {
274
            // finally {
275
            if ($cloned !== null) {
276
                $this->removeCommandline($cloned);
277
            }
278
            $this->setCommand($savedCommand);
279
            throw $e;
280
        }
281
    }
282
 
283
    /**
284
     * The CVSROOT variable.
285
     *
286
     * @param string $root
287
     */
288
    public function setCvsRoot($root) {
289
 
290
        // Check if not real cvsroot => set it to null
291
        if ($root !== null) {
292
            if (trim($root) == "") {
293
                $root = null;
294
            }
295
        }
296
 
297
        $this->cvsRoot = $root;
298
    }
299
 
300
    public function getCvsRoot() {
301
        return $this->cvsRoot;
302
    }
303
 
304
    /**
305
     * The CVS_RSH variable.
306
     *
307
     * @param rsh
308
     */
309
    public function setCvsRsh($rsh) {
310
        // Check if not real cvsrsh => set it to null
311
        if ($rsh !== null) {
312
            if (trim($rsh) == "") {
313
                $rsh = null;
314
            }
315
        }
316
 
317
        $this->cvsRsh = $rsh;
318
    }
319
 
320
    public function getCvsRsh() {
321
        return $this->cvsRsh;
322
    }
323
 
324
    /**
325
     * Port used by CVS to communicate with the server.
326
     *
327
     * @param int $port
328
     */
329
    public function setPort($port){
330
        $this->port = $port;
331
    }
332
 
333
    /**
334
     * @return int
335
     */
336
    public function getPort() {
337
        return $this->port;
338
    }
339
 
340
    /**
341
     * Password file to read passwords from.
342
     *
343
     * @param passFile
344
     */
345
    public function setPassfile(PhingFile $passFile) {
346
        $this->passFile = $passFile;
347
    }
348
 
349
    /**
350
     * @return File
351
     */
352
    public function getPassFile() {
353
        return $this->passFile;
354
    }
355
 
356
    /**
357
     * The directory where the checked out files should be placed.
358
     *
359
     * @param PhingFile $dest
360
     */
361
    public function setDest(PhingFile $dest) {
362
        $this->dest = $dest;
363
    }
364
 
365
    public function getDest() {
366
        return $this->dest;
367
    }
368
 
369
    /**
370
     * The package/module to operate upon.
371
     *
372
     * @param string $p
373
     */
374
    public function setModule($m) {
375
        $this->cvsModule = $m;
376
    }
377
 
378
    public function getModule(){
379
        return $this->cvsModule;
380
    }
381
 
382
    /**
383
     * The tag of the package/module to operate upon.
384
     * @param string $p
385
     */
386
    public function setTag($p) {
387
        // Check if not real tag => set it to null
388
        if ($p !== null && trim($p) !== "") {
389
            $this->appendCommandArgument("-r");
390
            $this->appendCommandArgument($p);
391
        }
392
    }
393
 
394
    /**
395
     * This needs to be public to allow configuration
396
     *      of commands externally.
397
     */
398
    public function appendCommandArgument($arg) {
399
        $this->cmd->createArgument()->setValue($arg);
400
    }
401
 
402
    /**
403
     * Use the most recent revision no later than the given date.
404
     * @param p
405
     */
406
    public function setDate($p) {
407
        if ($p !== null && trim($p) !== "") {
408
            $this->appendCommandArgument("-D");
409
            $this->appendCommandArgument($p);
410
        }
411
    }
412
 
413
    /**
414
     * The CVS command to execute.
415
     * @param string $c
416
     */
417
    public function setCommand($c) {
418
        $this->command = $c;
419
    }
420
 
421
    public function getCommand() {
422
        return $this->command;
423
    }
424
 
425
    /**
426
     * If true, suppress informational messages.
427
     * @param boolean $q
428
     */
429
    public function setQuiet($q) {
430
        $this->quiet = $q;
431
    }
432
 
433
    /**
434
     * If true, report only and don't change any files.
435
     *
436
     * @param boolean $ne
437
     */
438
    public function setNoexec($ne) {
439
        $this->noexec = (boolean) $ne;
440
    }
441
 
442
    /**
443
     * Stop the build process if the command exits with
444
     * a return code other than 0.
445
     * Defaults to false.
446
     * @param boolean $failOnError
447
     */
448
    public function setFailOnError($failOnError) {
449
        $this->failOnError = (boolean) $failOnError;
450
    }
451
 
452
    /**
453
     * Configure a commandline element for things like cvsRoot, quiet, etc.
454
     * @return string
455
     */
456
    protected function configureCommandline($c) {
457
        if ($c === null) {
458
            return;
459
        }
460
        $c->setExecutable("cvs");
461
 
462
        if ($this->cvsModule !== null) {
463
            $c->createArgument()->setLine($this->cvsModule);
464
        }
465
        if ($this->compression > 0 && $this->compression < 10) {
466
            $c->createArgument(true)->setValue("-z" . $this->compression);
467
        }
468
        if ($this->quiet) {
469
            $c->createArgument(true)->setValue("-q");
470
        }
471
        if ($this->noexec) {
472
            $c->createArgument(true)->setValue("-n");
473
        }
474
        if ($this->cvsRoot !== null) {
475
            $c->createArgument(true)->setLine("-d" . $this->cvsRoot);
476
        }
477
    }
478
 
479
    protected function removeCommandline(Commandline $c) {
480
        $idx = array_search($c, $this->commandlines, true);
481
        if ($idx === false) {
482
            return false;
483
        }
484
        $this->commandlines = array_splice($this->commandlines, $idx, 1);
485
        return true;
486
    }
487
 
488
    /**
489
    * Configures and adds the given Commandline.
490
    * @param insertAtStart If true, c is
491
    */
492
    public function addConfiguredCommandline(Commandline $c, $insertAtStart = false) {
493
        if ($c === null) {
494
            return;
495
        }
496
        $this->configureCommandline($c);
497
        if ($insertAtStart) {
498
            array_unshift($this->commandlines, $c);
499
        } else {
500
            array_push($this->commandlines, $c);
501
        }
502
    }
503
 
504
    /**
505
    * If set to a value 1-9 it adds -zN to the cvs command line, else
506
    * it disables compression.
507
    * @param int $level
508
    */
509
    public function setCompressionLevel($level) {
510
        $this->compression = $level;
511
    }
512
 
513
    /**
514
     * If true, this is the same as compressionlevel="3".
515
     *
516
     * @param boolean $usecomp If true, turns on compression using default
517
     * level, AbstractCvsTask.DEFAULT_COMPRESSION_LEVEL.
518
     */
519
    public function setCompression($usecomp) {
520
        $this->setCompressionLevel($usecomp ?
521
                            self::DEFAULT_COMPRESSION_LEVEL : 0);
522
    }
523
 
524
    /**
525
     * File to which output should be written.
526
     * @param PhingFile $output
527
     */
528
    function setOutput(PhingFile $f) {
529
        $this->output = $f;
530
    }
531
 
532
    /**
533
     * File to which error output should be written.
534
     * @param PhingFile $output
535
     */
536
    function setError(PhingFile $f) {
537
        $this->error = $f;
538
    }
539
 
540
}