1
<?php
2
/**
3
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
4
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
5
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
6
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
7
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
8
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
9
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
10
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
11
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
12
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
13
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
14
 *
15
 * This software consists of voluntary contributions made by many individuals
16
 * and is licensed under the LGPL. For more information please see
17
 * <http://phing.info>.
18
 */
19

20
/**
21
 * VersionTask
22
 *
23
 * Increments a three-part version number from a given file
24
 * and writes it back to the file.
25
 * Incrementing is based on given releasetype, which can be one
26
 * of Major, Minor and Bugfix.
27
 * Resulting version number is also published under supplied property.
28
 *
29
 * @author  Mike Wittje <mw@mike.wittje.de>
30
 * @package phing.tasks.ext
31
 */
32
class VersionTask extends Task
33
{
34

35
    /**
36
     * The name of the property in which the build number is stored.
37
     */
38
    public const DEFAULT_PROPERTY_NAME = "build.version";
39

40
    /**
41
     * The default filename to use if no file specified.
42
     */
43
    public const DEFAULT_FILENAME = self::DEFAULT_PROPERTY_NAME;
44

45
    private $startingVersion = '0.0.0';
46

47
    /**
48
     * Property for Releasetype
49
     *
50
     * @var string $releasetype
51
     */
52
    private $releasetype;
53

54
    /**
55
     * Property for File
56
     *
57
     * @var PhingFile file
58
     */
59
    private $file;
60

61
    /**
62
     * Property to be set
63
     *
64
     * @var string $property
65
     */
66
    private $property;
67

68
    /* Allowed Releastypes */
69
    public const RELEASETYPE_MAJOR = 'MAJOR';
70
    public const RELEASETYPE_MINOR = 'MINOR';
71
    public const RELEASETYPE_BUGFIX = 'BUGFIX';
72

73
    private $propFile = false;
74

75
    /**
76
     * @param string $startingVersion
77
     */
78 1
    public function setStartingVersion($startingVersion)
79
    {
80 1
        $this->startingVersion = $startingVersion;
81
    }
82

83
    /**
84
     * Set Property for Releasetype (Minor, Major, Bugfix)
85
     *
86
     * @param string $releasetype
87
     */
88 1
    public function setReleasetype($releasetype)
89
    {
90 1
        $this->releasetype = strtoupper($releasetype);
91
    }
92

93
    /**
94
     * Set Property for File containing versioninformation
95
     *
96
     * @param PhingFile $file
97
     */
98 1
    public function setFile(PhingFile $file)
99
    {
100 1
        $this->file = $file;
101
    }
102

103
    /**
104
     * Set name of property to be set
105
     *
106
     * @param  $property
107
     * @return void
108
     */
109 1
    public function setProperty($property)
110
    {
111 1
        $this->property = $property;
112
    }
113

114
    /**
115
     * @param bool $isPropFile
116
     */
117 1
    public function setPropFile($isPropFile)
118
    {
119 1
        $this->propFile = $isPropFile;
120
    }
121

122
    /**
123
     * Main-Method for the Task
124
     *
125
     * @return void
126
     * @throws BuildException
127
     */
128 1
    public function main()
129
    {
130
        // check supplied attributes
131 1
        $this->checkReleasetype();
132 1
        $this->checkFile();
133 1
        $this->checkProperty();
134

135
        // read file (or use fallback value if file is empty)
136
        try {
137 1
            if ($this->propFile) {
138 1
                $properties = $this->loadProperties();
139 1
                $content = $properties->getProperty($this->property);
140
            } else {
141 1
                $content = trim($this->file->contents());
142
            }
143 1
            if (empty($content)) {
144 1
                $content = $this->startingVersion;
145
            }
146 0
        } catch (Exception $e) {
147 0
            throw new BuildException($e);
148
        }
149

150
        // get new version
151 1
        $this->log("Old version: $content", Project::MSG_INFO);
152 1
        $newVersion = $this->getVersion($content);
153 1
        $this->log("New version: $newVersion", Project::MSG_INFO);
154

155 1
        if ($this->propFile) {
156 1
            $properties->put($this->property, $newVersion);
157
            try {
158 1
                $header = "Build Number for PHING. Do not edit!";
159 1
                $properties->store($this->file, $header);
160 0
            } catch (IOException $ioe) {
161 0
                $message = "Error while writing " . $this->file;
162 0
                throw new BuildException($message, $ioe);
163
            }
164
        } else {
165
            // write new Version to file
166 1
            file_put_contents($this->file, $newVersion . $this->getProject()->getProperty('line.separator'));
167
        }
168

169
        //Finally set the property
170 1
        $this->getProject()->setNewProperty($this->property, $newVersion);
171
    }
172

173
    /**
174
     * Utility method to load properties from file.
175
     *
176
     * @return Properties the loaded properties
177
     * @throws BuildException
178
     */
179 1
    private function loadProperties()
180
    {
181
        try {
182 1
            $properties = new Properties();
183 1
            $properties->load($this->file);
184 0
        } catch (IOException $ioe) {
185 0
            throw new BuildException($ioe);
186
        }
187 1
        return $properties;
188
    }
189

190
    /**
191
     * Returns new version number corresponding to Release type
192
     *
193
     * @param  string $oldVersion
194
     * @return string
195
     */
196 1
    private function getVersion($oldVersion)
197
    {
198 1
        preg_match('#^(?<PREFIX>v)?(?<MAJOR>\d+)?(?:\.(?<MINOR>\d+))?(?:\.(?<BUGFIX>\d+))?#', $oldVersion, $version);
199

200
        // Setting values if not captured
201 1
        $version['PREFIX'] = $version['PREFIX'] ?? '';
202 1
        $version[self::RELEASETYPE_MAJOR] = $version[self::RELEASETYPE_MAJOR] ?? '0';
203 1
        $version[self::RELEASETYPE_MINOR] = $version[self::RELEASETYPE_MINOR] ?? '0';
204 1
        $version[self::RELEASETYPE_BUGFIX] = $version[self::RELEASETYPE_BUGFIX] ?? '0';
205

206
        // Resetting Minor and/or Bugfix number according to release type
207 1
        switch ($this->releasetype) {
208
            case self::RELEASETYPE_MAJOR:
209 1
                $version[self::RELEASETYPE_MINOR] = '0';
210
            // no break
211
            case self::RELEASETYPE_MINOR:
212 1
                $version[self::RELEASETYPE_BUGFIX] = '0';
213 1
                break;
214
        }
215

216 1
        $version[$this->releasetype]++;
217

218 1
        return sprintf(
219 1
            '%s%u.%u.%u',
220 1
            $version['PREFIX'],
221 1
            $version[self::RELEASETYPE_MAJOR],
222 1
            $version[self::RELEASETYPE_MINOR],
223 1
            $version[self::RELEASETYPE_BUGFIX]
224
        );
225
    }
226

227
    /**
228
     * checks releasetype attribute
229
     *
230
     * @return void
231
     * @throws BuildException
232
     */
233 1
    private function checkReleasetype()
234
    {
235
        // check Releasetype
236 1
        if (null === $this->releasetype) {
237 0
            throw new BuildException('releasetype attribute is required', $this->getLocation());
238
        }
239
        // known releasetypes
240
        $releaseTypes = [
241 1
            self::RELEASETYPE_MAJOR,
242
            self::RELEASETYPE_MINOR,
243
            self::RELEASETYPE_BUGFIX
244
        ];
245

246 1
        if (!in_array($this->releasetype, $releaseTypes)) {
247 0
            throw new BuildException(
248 0
                sprintf(
249 0
                    'Unknown Releasetype %s..Must be one of Major, Minor or Bugfix',
250 0
                    $this->releasetype
251
                ),
252 0
                $this->getLocation()
253
            );
254
        }
255
    }
256

257
    /**
258
     * checks file attribute
259
     *
260
     * @return void
261
     * @throws BuildException
262
     */
263 1
    private function checkFile()
264
    {
265 1
        $fileUtils = new FileUtils();
266
        // check File
267
        try {
268 1
            if (null === $this->file) {
269 1
                $this->file = $fileUtils->resolveFile($this->getProject()->getBasedir(), self::DEFAULT_FILENAME);
270
            }
271 1
            if (!$this->file->exists()) {
272 1
                $this->file->createNewFile();
273 1
                $this->log(
274 1
                    'Creating file "' . $this->file->getName() . '" since it was not present',
275 1
                    Project::MSG_INFO
276
                );
277
            }
278 0
        } catch (IOException $ioe) {
279 0
            $message = $this->file . " doesn't exist and new file can't be created.";
280 0
            throw new BuildException($message, $ioe);
281
        }
282

283 1
        if (!$this->file->canRead()) {
284 0
            $message = "Unable to read from " . $this->file . ".";
285 0
            throw new BuildException($message);
286
        }
287 1
        if (!$this->file->canWrite()) {
288 0
            $message = "Unable to write to " . $this->file . ".";
289 0
            throw new BuildException($message);
290
        }
291
    }
292

293 1
    private function checkProperty()
294
    {
295 1
        if ($this->property === null) {
296 1
            $this->property = self::DEFAULT_PROPERTY_NAME;
297
        }
298
    }
299
}

Read our documentation on viewing source code .

Loading