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: MoveTask.php 325 2007-12-20 15:44:58Z 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/tasks/system/CopyTask.php';
23
include_once 'phing/system/io/PhingFile.php';
24
include_once 'phing/system/io/IOException.php';
25
 
26
/**
27
 * Moves a file or directory to a new file or directory.
28
 *
29
 * By default, the destination file is overwritten if it
30
 * already exists.  When overwrite is turned off, then files
31
 * are only moved if the source file is newer than the
32
 * destination file, or when the destination file does not
33
 * exist.
34
 *
35
 * Source files and directories are only deleted when the file or
36
 * directory has been copied to the destination successfully.
37
 *
38
 * @version $Revision: 1.8 $
39
 * @package phing.tasks.system
40
 */
41
class MoveTask extends CopyTask {
42
 
43
    function __construct() {
44
        parent::__construct();
45
        $this->forceOverwrite = true;
46
    }
47
 
48
    /**
49
     * Validates attributes coming in from XML
50
     *
51
     * @access  private
52
     * @return  void
53
     * @throws  BuildException
54
     */
55
    protected function validateAttributes() {
56
        if ($this->file !== null && $this->file->isDirectory()) {
57
			if (($this->destFile !== null && $this->destDir !== null)
58
				|| ($this->destFile === null && $this->destDir === null)) {
59
					throw new BuildException("One and only one of tofile and todir must be set.");
60
			}
61
 
62
            if ($this->destFile === null)
63
            {
64
				$this->destFile = new PhingFile($this->destDir, $this->file->getName());
65
			}
66
 
67
            if ($this->destDir === null)
68
            {
69
				$this->destDir = $this->destFile->getParentFile();
70
			}
71
 
72
			$this->completeDirMap[$this->file->getAbsolutePath()] = $this->destFile->getAbsolutePath();
73
 
74
			$this->file = null;
75
		} else {
76
			parent::validateAttributes();
77
		}
78
    }
79
 
80
    protected function doWork() {
81
		if (count($this->completeDirMap) > 0)
82
		{
83
			foreach ($this->completeDirMap as $from => $to)
84
			{
85
                $f = new PhingFile($from);
86
                $d = new PhingFile($to);
87
 
88
                $moved = false;
89
                try { // try to rename
90
                    $this->log("Attempting to rename $from to $to", $this->verbosity);
91
                    $this->renameFile($f, $d, $this->forceOverwrite);
92
                    $moved = true;
93
                } catch (IOException $ioe) {
94
                    $moved = false;
95
                    $this->log("Failed to rename $from to $to: " . $ioe->getMessage(), $this->verbosity);
96
                }
97
			}
98
		}
99
 
100
        $copyMapSize = count($this->fileCopyMap);
101
        if ($copyMapSize > 0) {
102
            // files to move
103
            $this->log("Moving $copyMapSize files to " . $this->destDir->getAbsolutePath());
104
 
105
            foreach($this->fileCopyMap as $from => $to) {
106
                if ($from == $to) {
107
                    $this->log("Skipping self-move of $from", $this->verbosity);
108
                    continue;
109
                }
110
 
111
                $moved = false;
112
                $f = new PhingFile($from);
113
                $d = new PhingFile($to);
114
 
115
                $moved = false;
116
                try { // try to rename
117
                    $this->log("Attempting to rename $from to $to", $this->verbosity);
118
                    $this->renameFile($f, $d, $this->forceOverwrite);
119
                    $moved = true;
120
                } catch (IOException $ioe) {
121
                    $moved = false;
122
                    $this->log("Failed to rename $from to $to: " . $ioe->getMessage(), $this->verbosity);
123
                }
124
 
125
                if (!$moved) {
126
                    try { // try to move
127
                        $this->log("Moving $from to $to", $this->verbosity);
128
 
129
                        $this->fileUtils->copyFile($f, $d, $this->forceOverwrite, $this->preserveLMT, $this->filterChains, $this->getProject());
130
 
131
                        $f = new PhingFile($fromFile);
132
                        $f->delete();
133
                    } catch (IOException $ioe) {
134
                        $msg = "Failed to move $from to $to: " . $ioe->getMessage();
135
                        throw new BuildException($msg, $this->location);
136
                    }
137
                } // if !moved
138
            } // foreach fileCopyMap
139
        } // if copyMapSize
140
 
141
        // handle empty dirs if appropriate
142
        if ($this->includeEmpty) {
143
            $e = array_keys($this->dirCopyMap);
144
            $count = 0;
145
            foreach ($e as $dir) {
146
                $d = new PhingFile((string) $dir);
147
                if (!$d->exists()) {
148
                    if (!$d->mkdirs()) {
149
                        $this->log("Unable to create directory " . $d->getAbsolutePath(), Project::MSG_ERR);
150
                    } else {
151
                        $count++;
152
                    }
153
                }
154
            }
155
            if ($count > 0) {
156
                $this->log("moved $count empty director" . ($count == 1 ? "y" : "ies") . " to " . $this->destDir->getAbsolutePath());
157
            }
158
        }
159
 
160
        if (count($this->filesets) > 0) {
161
            // process filesets
162
            foreach($this->filesets as $fs) {
163
                $dir = $fs->getDir($this->project);
164
                if ($this->okToDelete($dir)) {
165
                    $this->deleteDir($dir);
166
                }
167
            }
168
        }
169
    }
170
 
171
    /** Its only ok to delete a dir tree if there are no files in it. */
172
    private function okToDelete($d) {
173
        $list = $d->listDir();
174
        if ($list === null) {
175
            return false;     // maybe io error?
176
        }
177
 
178
        foreach($list as $s) {
179
            $f = new PhingFile($d, $s);
180
            if ($f->isDirectory()) {
181
                if (!$this->okToDelete($f)) {
182
                    return false;
183
                }
184
            } else {
185
                // found a file
186
                return false;
187
            }
188
        }
189
        return true;
190
    }
191
 
192
    /** Go and delete the directory tree. */
193
    private function deleteDir($d) {
194
 
195
        $list = $d->listDir();
196
        if ($list === null) {
197
            return;      // on an io error list() can return null
198
        }
199
 
200
        foreach($list as $fname) {
201
            $f = new PhingFile($d, $fname);
202
            if ($f->isDirectory()) {
203
                $this->deleteDir($f);
204
            } else {
205
                throw new BuildException("UNEXPECTED ERROR - The file " . $f->getAbsolutePath() . " should not exist!");
206
            }
207
        }
208
 
209
        $this->log("Deleting directory " . $d->getPath(), $this->verbosity);
210
        try {
211
            $d->delete();
212
        } catch (Exception $e) {
213
            throw new BuildException("Unable to delete directory " . $d->__toString() . ": " . $e->getMessage());
214
        }
215
    }
216
 
217
    /**
218
     * Attempts to rename a file from a source to a destination.
219
     * If overwrite is set to true, this method overwrites existing file
220
     * even if the destination file is newer.
221
     * Otherwise, the source f
222
     * ile is renamed only if the destination file #
223
     * is older than it.
224
     */
225
    private function renameFile(PhingFile $sourceFile, PhingFile $destFile, $overwrite) {
226
        $renamed = true;
227
 
228
        // ensure that parent dir of dest file exists!
229
        $parent = $destFile->getParentFile();
230
        if ($parent !== null) {
231
            if (!$parent->exists()) {
232
                $parent->mkdirs();
233
            }
234
        }
235
        if ($destFile->exists()) {
236
            try {
237
                $destFile->delete();
238
            } catch (Exception $e) {
239
                throw new BuildException("Unable to remove existing file " . $destFile->__toString() . ": " . $e->getMessage());
240
            }
241
        }
242
        $renamed = $sourceFile->renameTo($destFile);
243
 
244
        return $renamed;
245
    }
246
}
247