Completed
Push — develop ( 4961cb...5f7df1 )
by Matteo
03:22
created

MainCommand::add()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 9
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 1
Metric Value
c 1
b 0
f 1
dl 0
loc 9
ccs 6
cts 6
cp 1
rs 9.6666
cc 1
eloc 6
nc 1
nop 1
crap 1
1
<?php
2
/**
3
 * GitElephant - An abstraction layer for git written in PHP
4
 * Copyright (C) 2013  Matteo Giachino
5
 *
6
 * This program is free software: you can redistribute it and/or modify
7
 * it under the terms of the GNU General Public License as published by
8
 * the Free Software Foundation, either version 3 of the License, or
9
 * (at your option) any later version.
10
 *
11
 * This program is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 * GNU General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU General Public License
17
 * along with this program.  If not, see [http://www.gnu.org/licenses/].
18
 */
19
20
namespace GitElephant\Command;
21
22
use \GitElephant\Objects\Author;
23
use \GitElephant\Objects\Branch;
24
use \GitElephant\Objects\TreeishInterface;
25
use \GitElephant\Repository;
26
27
/**
28
 * Main command generator (init, status, add, commit, checkout)
29
 *
30
 * @author Matteo Giachino <[email protected]>
31
 */
32
class MainCommand extends BaseCommand
33
{
34
    const GIT_INIT     = 'init';
35
    const GIT_STATUS   = 'status';
36
    const GIT_ADD      = 'add';
37
    const GIT_COMMIT   = 'commit';
38
    const GIT_CHECKOUT = 'checkout';
39
    const GIT_MOVE     = 'mv';
40
    const GIT_REMOVE   = 'rm';
41
    const GIT_RESET    = 'reset';
42
43
    /**
44
     * constructor
45
     *
46
     * @param \GitElephant\Repository $repo The repository object this command 
47
     *                                      will interact with
48
     */
49 103
    public function __construct(Repository $repo = null)
50
    {
51 103
        parent::__construct($repo);
52 103
    }
53
54
    /**
55
     * Init the repository
56
     *
57
     * @param bool $bare
58
     *
59
     * @throws \RuntimeException
60
     * @return MainCommand
61
     */
62 97
    public function init($bare = false)
63
    {
64 97
        $this->clearAll();
65 97
        if ($bare) {
66 5
            $this->addCommandArgument('--bare');
67 5
        }
68 97
        $this->addCommandName(self::GIT_INIT);
69
70 97
        return $this->getCommand();
71
    }
72
73
    /**
74
     * Get the repository status
75
     *
76
     * @param bool $porcelain
77
     *
78
     * @throws \RuntimeException
79
     * @return string
80
     */
81 12
    public function status($porcelain = false)
82
    {
83 12
        $this->clearAll();
84 12
        $this->addCommandName(self::GIT_STATUS);
85 12
        if ($porcelain) {
86 9
            $this->addCommandArgument('--porcelain');
87 9
        } else {
88 3
            $this->addConfigs(array('color.status' => 'false'));
89
        }
90
91 12
        return $this->getCommand();
92
    }
93
94
    /**
95
     * Add a node to the stage
96
     *
97
     * @param string $what what should be added to the repository
98
     *
99
     * @throws \RuntimeException
100
     * @return string
101
     */
102 92
    public function add($what = '.')
103
    {
104 92
        $this->clearAll();
105 92
        $this->addCommandName(self::GIT_ADD);
106 92
        $this->addCommandArgument('--all');
107 92
        $this->addCommandSubject($what);
108
109 92
        return $this->getCommand();
110
    }
111
112
    /**
113
     * Remove a node from the stage and put in the working tree
114
     *
115
     * @param string $what what should be removed from the stage
116
     *
117
     * @throws \RuntimeException
118
     * @return string
119
     */
120 2
    public function unstage($what)
121
    {
122 2
        $this->clearAll();
123 2
        $this->addCommandName(self::GIT_RESET);
124 2
        $this->addCommandArgument('HEAD');
125 2
        $this->addPath($what);
126
127 2
        return $this->getCommand();
128
    }
129
130
    /**
131
     * Commit
132
     *
133
     * @param string        $message  the commit message
134
     * @param bool          $stageAll commit all changes
135
     * @param string|Author $author   override the author for this commit
136
     *
137
     * @throws \RuntimeException
138
     * @throws \InvalidArgumentException
139
     * @return string
140
     */
141 92
    public function commit($message, $stageAll = false, $author = null, $allowEmpty = false)
142
    {
143 92
        $this->clearAll();
144 92
        if (trim($message) === '' || is_null($message)) {
145
            throw new \InvalidArgumentException(sprintf('You can\'t commit without message'));
146
        }
147 92
        $this->addCommandName(self::GIT_COMMIT);
148
149 92
        if ($stageAll) {
150 86
            $this->addCommandArgument('-a');
151 86
        }
152
153 92
        if ($author !== null) {
154 1
            $this->addCommandArgument('--author');
155 1
            $this->addCommandArgument($author);
0 ignored issues
show
Bug introduced by
It seems like $author defined by parameter $author on line 141 can also be of type object<GitElephant\Objects\Author>; however, GitElephant\Command\Base...d::addCommandArgument() does only seem to accept string, maybe add an additional type check?

This check looks at variables that have been passed in as parameters and are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
156 1
        }
157
158 92
        if ($allowEmpty) {
159 1
            $this->addCommandArgument('--allow-empty');
160 1
        }
161
162 92
        $this->addCommandArgument('-m');
163 92
        $this->addCommandSubject($message);
164
165 92
        return $this->getCommand();
166
    }
167
168
    /**
169
     * Checkout a treeish reference
170
     *
171
     * @param string|Branch $ref the reference to checkout
172
     *
173
     * @throws \RuntimeException
174
     * @return string
175
     */
176 23
    public function checkout($ref)
177
    {
178 23
        $this->clearAll();
179
180 23
        $what = $ref;
181 23
        if ($ref instanceof Branch) {
182 2
            $what = $ref->getName();
183 23
        } elseif ($ref instanceof TreeishInterface) {
184
            $what = $ref->getSha();
185
        }
186
187 23
        $this->addCommandName(self::GIT_CHECKOUT);
188 23
        $this->addCommandArgument('-q');
189 23
        $this->addCommandSubject($what);
190
191 23
        return $this->getCommand();
192
    }
193
194
    /**
195
     * Move a file/directory
196
     *
197
     * @param string|Object $from source path
198
     * @param string|Object $to   destination path
199
     *
200
     * @throws \RuntimeException
201
     * @throws \InvalidArgumentException
202
     * @return string
203
     */
204 1
    public function move($from, $to)
205
    {
206 1
        $this->clearAll();
207
208 1
        $from = trim($from);
209 1
        if (!$this->validatePath($from)) {
210
            throw new \InvalidArgumentException('Invalid source path');
211
        }
212
213 1
        $to = trim($to);
214 1
        if (!$this->validatePath($to)) {
215
            throw new \InvalidArgumentException('Invalid destination path');
216
        }
217
218 1
        $this->addCommandName(self::GIT_MOVE);
219 1
        $this->addCommandSubject($from);
220 1
        $this->addCommandSubject2($to);
221
222 1
        return $this->getCommand();
223
    }
224
225
    /**
226
     * Remove a file/directory
227
     *
228
     * @param string|Object $path      the path to remove
229
     * @param bool          $recursive recurse
230
     * @param bool          $force     force
231
     *
232
     * @throws \RuntimeException
233
     * @throws \InvalidArgumentException
234
     * @return string
235
     */
236 1
    public function remove($path, $recursive, $force)
237
    {
238 1
        $this->clearAll();
239
240 1
        $path = trim($path);
241 1
        if (!$this->validatePath($path)) {
242
            throw new \InvalidArgumentException('Invalid path');
243
        }
244
245 1
        $this->addCommandName(self::GIT_REMOVE);
246
247 1
        if ($recursive) {
248
            $this->addCommandArgument('-r');
249
        }
250
251 1
        if ($force) {
252
            $this->addCommandArgument('-f');
253
        }
254
255 1
        $this->addPath($path);
256
257 1
        return $this->getCommand();
258
    }
259
260
    /**
261
     * Validates a path
262
     *
263
     * @param string $path path
264
     *
265
     * @return bool
266
     */
267 2
    protected function validatePath($path)
268
    {
269 2
        if (empty($path)) {
270
            return false;
271
        }
272
273
        // we are always operating from root directory
274
        // so forbid relative paths
275 2
        if (false !== strpos($path, '..')) {
276
            return false;
277
        }
278
279 2
        return true;
280
    }
281
}
282