1<?php
2/*
3 *  $Id: b87593e0f31239277d8aee7440f0dfb7c5b89d30 $
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
22require_once 'phing/Task.php';
23require_once 'phing/tasks/ext/git/GitBaseTask.php';
24
25/**
26 * Wrapper aroung git-pull
27 *
28 * @author Victor Farazdagi <simple.square@gmail.com>
29 * @version $Id: b87593e0f31239277d8aee7440f0dfb7c5b89d30 $
30 * @package phing.tasks.ext.git
31 * @see VersionControl_Git
32 * @since 2.4.3
33 */
34class GitPullTask extends GitBaseTask
35{
36    /**
37     * <repository> argument to git-pull
38     * @var string
39     */
40    private $source = 'origin';
41
42    /**
43     * <refspec> argument to git-pull
44     * @var string
45     */
46    private $refspec;
47
48    /**
49     * --rebase key to git-pull
50     * @var boolean
51     */
52    private $rebase = false;
53
54    /**
55     * --no-rebase key to git-pull
56     * Allow to override --rebase (if set to default true in configuration)
57     * @var boolean
58     */
59    private $noRebase = false;
60
61    /**
62     * Merge strategy. See -s <strategy> of git-pull
63     * @var string
64     */
65    private $strategy;
66
67    /**
68     * -X or --strategy-option of git-pull
69     * @var string
70     */
71    private $strategyOption;
72
73    /**
74     * Fetch all remotes
75     * --all key to git-pull
76     * @var boolean
77     */
78    private $allRemotes = false;
79
80    /**
81     * --append key to git-pull
82     * @var boolean
83     */
84    private $append = false;
85
86    /**
87     * Keep downloaded pack
88     * --keep key to git-pull
89     * @var boolean
90     */
91    private $keepFiles = false;
92
93    /**
94     * Disable/enable automatic tag following
95     * --no-tags key to git-pull
96     * @var boolean
97     */
98    private $noTags = false;
99
100    /**
101     * Fetch all tags (even not reachable from branch heads)
102     * --tags key to git-pull
103     * @var boolean
104     */
105    private $tags = false;
106
107    /**
108     * --quiet, -q key to git-pull
109     * @var boolean
110     */
111    private $quiet = true;
112
113    /**
114     * --force, -f key to git-pull
115     * @var boolean
116     */
117    private $force = false;
118
119    /**
120     * Valid merge strategies
121     * @var array
122     */
123    private $validStrategies = array(
124        'octopus', 'ours', 'recursive', 'resolve', 'subtree');
125
126    /**
127     * The main entry point for the task
128     */
129    public function main()
130    {
131        if (null === $this->getRepository()) {
132            throw new BuildException('"repository" is required parameter');
133        }
134
135        $client = $this->getGitClient(false, $this->getRepository());
136        $command = $client->getCommand('pull');
137        $command
138            ->setOption('rebase', $this->isRebase());
139
140        if (!$this->isRebase()) {
141            $command->setOption('no-rebase', $this->isNoRebase());
142        }
143
144        $strategy = $this->getStrategy();
145        if ($strategy) {
146            // check if strategy is valid
147            if (false === in_array($strategy, $this->validStrategies)) {
148                throw new BuildException(
149                    "Could not find merge strategy '" . $strategy . "'\n".
150                    "Available strategies are: " . implode(', ', $this->validStrategies));
151            }
152            $command->setOption('strategy', $strategy);
153            if ($this->getStrategyOption()) {
154                $command->setOption(
155                    'strategy-option', $this->getStrategyOption());
156            }
157        }
158
159        // order of arguments is important
160        $command
161            ->setOption('tags', $this->isTags())
162            ->setOption('no-tags', $this->isNoTags())
163            ->setOption('keep', $this->isKeepFiles())
164            ->setOption('append', $this->isAppend())
165            ->setOption('q', $this->isQuiet())
166            ->setOption('force', $this->isForce());
167
168        // set operation target
169        if ($this->isAllRemotes()) {            // --all
170            $command->setOption('all', true);
171            $this->log('git-pull: fetching from all remotes', Project::MSG_INFO);
172        } elseif ($this->getSource()) {         // <repository> [<refspec>]
173            $command->addArgument($this->getSource());
174            if ($this->getRefspec()) {
175                $command->addArgument($this->getRefspec());
176            }
177            $this->log(
178                sprintf('git-pull: pulling from %s %s',
179                    $this->getSource(), $this->getRefspec()),
180                Project::MSG_INFO);
181        } else {
182            throw new BuildException('No source repository specified');
183        }
184
185        $this->log('git-pull command: ' . $command->createCommandString(), Project::MSG_INFO);
186
187        try {
188            $output = $command->execute();
189        } catch (Exception $e) {
190            throw new BuildException('Task execution failed.', $e);
191        }
192
193        $this->log('git-pull: complete', Project::MSG_INFO);
194        $this->log('git-pull output: ' . trim($output), Project::MSG_INFO);
195
196    }
197
198    public function setStrategy($strategy)
199    {
200        $this->strategy = $strategy;
201    }
202
203    public function getStrategy()
204    {
205        return $this->strategy;
206    }
207
208    public function setStrategyOption($strategyOption)
209    {
210        $this->strategyOption = $strategyOption;
211    }
212
213    public function getStrategyOption()
214    {
215        return $this->strategyOption;
216    }
217
218    public function setSource($source)
219    {
220        $this->source = $source;
221    }
222
223    public function getSource()
224    {
225        return $this->source;
226    }
227
228    public function setRefspec($spec)
229    {
230        $this->refspec = $spec;
231    }
232
233    public function getRefspec()
234    {
235        return $this->refspec;
236    }
237
238    public function setAll($flag)
239    {
240        $this->allRemotes = $flag;
241    }
242
243    public function getAll()
244    {
245        return $this->allRemotes;
246    }
247
248    public function isAllRemotes()
249    {
250        return $this->getAll();
251    }
252
253    public function setAppend($flag)
254    {
255        $this->append = (boolean)$flag;
256    }
257
258    public function getAppend()
259    {
260        return $this->append;
261    }
262
263    public function isAppend()
264    {
265        return $this->getAppend();
266    }
267
268    public function setKeep($flag)
269    {
270        $this->keepFiles = $flag;
271    }
272
273    public function getKeep()
274    {
275        return $this->keepFiles;
276    }
277
278    public function isKeepFiles()
279    {
280        return $this->getKeep();
281    }
282
283    public function setNoTags($flag)
284    {
285        $this->noTags = $flag;
286    }
287
288    public function getNoTags()
289    {
290        return $this->noTags;
291    }
292
293    public function isNoTags()
294    {
295        return $this->getNoTags();
296    }
297
298    public function setTags($flag)
299    {
300        $this->tags = $flag;
301    }
302
303    public function getTags()
304    {
305        return $this->tags;
306    }
307
308    public function isTags()
309    {
310        return $this->getTags();
311    }
312
313    public function setQuiet($flag)
314    {
315        $this->quiet = $flag;
316    }
317
318    public function getQuiet()
319    {
320        return $this->quiet;
321    }
322
323    public function isQuiet()
324    {
325        return $this->getQuiet();
326    }
327
328    public function setRebase($flag)
329    {
330        $this->rebase = (boolean)$flag;
331    }
332
333    public function getRebase()
334    {
335        return $this->rebase;
336    }
337
338    public function isRebase()
339    {
340        return $this->getRebase();
341    }
342
343    public function setNoRebase($flag)
344    {
345        $this->noRebase = (boolean)$flag;
346    }
347
348    public function getNoRebase()
349    {
350        return $this->noRebase;
351    }
352
353    public function isNoRebase()
354    {
355        return $this->getNoRebase();
356    }
357
358    public function setForce($flag)
359    {
360        $this->force = $flag;
361    }
362
363    public function getForce()
364    {
365        return $this->force;
366    }
367
368    public function isForce()
369    {
370        return $this->getForce();
371    }
372
373}
374