Completed
Push — develop ( 29df12...700ecb )
by Matteo
03:39
created

RepositoryTest   C

Complexity

Total Complexity 64

Size/Duplication

Total Lines 981
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 10

Importance

Changes 15
Bugs 3 Features 1
Metric Value
wmc 64
c 15
b 3
f 1
lcom 1
cbo 10
dl 0
loc 981
rs 5

45 Methods

Rating   Name   Duplication   Size   Complexity  
A testInit() 0 15 3
B testGetBranches() 0 37 1
A testGetLog_for_a_branch() 0 16 2
A testCheckoutTag() 0 17 1
A testMove() 0 10 1
A testRemove() 0 10 1
A testFetch() 0 21 1
A testRevParse() 0 11 1
A testIsBare() 0 15 1
A testGlobalConfigs() 0 21 3
A testGlobalOptions() 0 21 3
A testGlobalCommandArguments() 0 21 3
A setUp() 0 4 1
A testConstruct() 0 10 1
A testName() 0 5 1
A testStage() 0 13 3
A testUnstage() 0 15 1
B testCommit() 0 25 5
A testGetStatus() 0 11 1
A testCreateBranch() 0 8 1
A testGetMainBranch() 0 7 1
A testGetBranch() 0 8 1
A testTags() 0 13 1
A testGetLastTag() 0 19 1
A testGetCommit() 0 7 1
A testGetBranchOrTag() 0 11 1
B testGetObjectLog() 0 35 1
B testGetObjectLogFolders() 0 35 3
B testGetObjectLogBranches() 0 36 1
A testGetLog() 0 13 2
A testCheckout() 0 10 1
A testGetTree() 0 54 1
A testGetDiff() 0 15 1
A testCloneFrom() 0 14 1
A testOutputContent() 0 11 1
A testCountCommits() 0 18 1
A testHumanishName() 0 5 1
A testCreateFromRemote() 0 22 1
A testRemote() 0 12 1
A testPull() 0 15 1
B testPush() 0 24 1
A testResetHard() 0 18 1
A testResetSoft() 0 18 1
A testDeleteBranch() 0 16 1
B testMerge() 0 42 2

How to fix   Complexity   

Complex Class

Complex classes like RepositoryTest often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use RepositoryTest, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
/**
4
 * This file is part of the GitElephant package.
5
 *
6
 * (c) Matteo Giachino <[email protected]>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 *
11
 * Just for fun...
12
 */
13
14
namespace GitElephant;
15
16
use GitElephant\Command\ResetCommand;
17
use \GitElephant\Objects\Branch;
18
use \GitElephant\Objects\Object;
19
use \GitElephant\Objects\Tag;
20
21
/**
22
 * RepositoryTest
23
 *
24
 * Repository Test Class
25
 *
26
 * @author Matteo Giachino <[email protected]>
27
 */
28
29
class RepositoryTest extends TestCase
30
{
31
    /**
32
     * setUp
33
     */
34
    public function setUp()
35
    {
36
        $this->initRepository();
37
    }
38
39
    /**
40
     * @covers GitElephant\Repository::__construct
41
     * @covers GitElephant\Repository::getPath
42
     */
43
    public function testConstruct()
44
    {
45
        $this->assertEquals($this->getRepository()->getPath(), $this->path);
46
47
        $this->setExpectedException('GitElephant\Exception\InvalidRepositoryPathException');
48
        $repo = new Repository('non-existent-path');
0 ignored issues
show
Unused Code introduced by
$repo is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
49
50
        $repo = Repository::open($this->path);
51
        $this->assertInstanceOf('GitElephant\Repository', $repo);
52
    }
53
54
    /**
55
     * @covers GitElephant\Repository::init
56
     */
57
    public function testInit()
58
    {
59
        $this->getRepository()->init();
60
        $match = false;
61
62
        // Force US/EN locale
63
        putenv('LANG=en_US.UTF-8');
64
65
        foreach ($this->getRepository()->getStatusOutput() as $line) {
66
            if (preg_match('/nothing to commit?(.*)/', $line)) {
67
                $match = true;
68
            }
69
        }
70
        $this->assertTrue($match, 'init problem, git status on an empty repo should give nothing to commit');
71
    }
72
73
    /**
74
     * testName
75
     */
76
    public function testName()
77
    {
78
        $this->getRepository()->setName('test-repo');
79
        $this->assertEquals('test-repo', $this->getRepository()->getName());
80
    }
81
82
    /**
83
     * @covers GitElephant\Repository::stage
84
     */
85
    public function testStage()
86
    {
87
        $this->getRepository()->init();
88
        $this->addFile('test');
89
        $this->getRepository()->stage();
90
        $match = false;
91
        foreach ($this->getRepository()->getStatusOutput() as $line) {
92
            if (preg_match('/(.*)Changes to be committed(.*)/', $line)) {
93
                $match = true;
94
            }
95
        }
96
        $this->assertTrue($match, 'stageAll error, git status should give Changes to be committed');
97
    }
98
99
    /**
100
     * @covers GitElephant\Repository::unstage
101
     */
102
    public function testUnstage()
103
    {
104
        $this->getRepository()->init();
105
        $this->addFile('test');
106
        $this->getRepository()->commit('first commit', true);
107
        $this->addFile('test2');
108
        $this->assertCount(1, $this->getRepository()->getStatus()->untracked());
109
        $this->assertCount(0, $this->getRepository()->getStatus()->added());
110
        $this->getRepository()->stage('test2');
111
        $this->assertCount(0, $this->getRepository()->getStatus()->untracked());
112
        $this->assertCount(1, $this->getRepository()->getStatus()->added());
113
        $this->getRepository()->unstage('test2');
114
        $this->assertCount(1, $this->getRepository()->getStatus()->untracked());
115
        $this->assertCount(0, $this->getRepository()->getStatus()->added());
116
    }
117
118
    /**
119
     * @covers GitElephant\Repository::commit
120
     * @covers GitElephant\Repository::getStatusOutput
121
     */
122
    public function testCommit()
123
    {
124
        $this->getRepository()->init();
125
        $this->addFile('test');
126
        $this->getRepository()->stage();
127
        $this->getRepository()->commit('initial import');
128
        $match = false;
129
        foreach ($this->getRepository()->getStatusOutput() as $line) {
130
            if (preg_match('/nothing to commit?(.*)/', $line)) {
131
                $match = true;
132
            }
133
        }
134
        $this->assertTrue($match, 'commit error, git status should give nothing to commit');
135
136
        $this->getRepository()->createBranch('develop', $this->getRepository()->getCommit());
137
        $this->addFile('test2');
138
        $this->getRepository()->commit('commit 2', true, 'develop');
139
        $match = false;
140
        foreach ($this->getRepository()->getStatusOutput() as $line) {
141
            if (preg_match('/nothing to commit?(.*)/', $line)) {
142
                $match = true;
143
            }
144
        }
145
        $this->assertTrue($match, 'commit error, git status should give nothing to commit');
146
    }
147
148
    /**
149
     * @covers GitElephant\Repository::getStatusOutput
150
     */
151
    public function testGetStatus()
152
    {
153
        $this->getRepository()->init();
154
        $this->addFile('test');
155
        $this->getRepository()->commit('test commit', true);
156
        $output = $this->getRepository()->getStatusOutput();
157
        $this->assertStringEndsWith('master', $output[0]);
158
        $this->addFile('file2');
159
        $output = $this->getRepository()->getStatusOutput();
160
        $this->assertStringEndsWith('file2', $output[4]);
161
    }
162
163
    /**
164
     * @covers GitElephant\Repository::createBranch
165
     */
166
    public function testCreateBranch()
167
    {
168
        $this->getRepository()->init();
169
        $this->addFile('test');
170
        $this->getRepository()->commit('foo', true);
171
        $this->getRepository()->createBranch('test-branch');
172
        $this->assertEquals(2, count($this->getRepository()->getBranches()));
173
    }
174
175
    /**
176
     * @covers GitElephant\Repository::deleteBranch
177
     */
178
    public function testDeleteBranch()
179
    {
180
        $this->getRepository()->init();
181
        $this->addFile('test-file');
182
        $this->getRepository()->commit('test', true);
183
        $this->getRepository()->createBranch('branch2');
184
        $this->assertEquals(2, count($this->getRepository()->getBranches(true)));
185
        $this->getRepository()->deleteBranch('branch2');
186
        $this->assertEquals(1, count($this->getRepository()->getBranches(true)));
187
        $this->addFile('test-file2');
188
        $this->getRepository()->commit('test2', true);
189
        $this->getRepository()->createBranch('branch3');
190
        $this->assertEquals(2, count($this->getRepository()->getBranches(true)));
191
        $this->getRepository()->deleteBranch('branch3', true);
192
        $this->assertEquals(1, count($this->getRepository()->getBranches(true)));
193
    }
194
195
    /**
196
     * @covers GitElephant\Repository::getBranches
197
     */
198
    public function testGetBranches()
199
    {
200
        $this->getRepository()->init();
201
        $this->addFile('test');
202
        $this->getRepository()->stage();
203
        $this->getRepository()->commit('initial import', true);
204
        $this->assertCount(
205
            1,
206
            $this->getRepository()->getBranches(),
207
            'an initialized repository should have only one branch'
208
        );
209
        $this->getRepository()->createBranch('test-branch');
210
        $this->assertCount(2, $this->getRepository()->getBranches(), 'two branches expected');
211
        $branches = $this->getRepository()->getBranches();
212
        $this->assertEquals('master', $branches[0]->getName());
213
        $this->getRepository()->deleteBranch('test-branch');
214
        $this->assertCount(1, $this->getRepository()->getBranches(), 'one branch expected');
215
        $mainBranch = $this->getRepository()->getMainBranch();
0 ignored issues
show
Unused Code introduced by
$mainBranch is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
216
        $this->assertInstanceOf(
217
            'GitElephant\Objects\Branch',
218
            $this->getRepository()->getMainBranch(),
219
            'main branch should be an instance of Branch'
220
        );
221
        $this->assertTrue(
222
            $this->getRepository()->getMainBranch()->getCurrent(),
223
            'getCurrent on main branch should be true'
224
        );
225
        $this->assertEquals(
226
            'master',
227
            $this->getRepository()->getMainBranch()->getName(),
228
            'main branch should be named "master"'
229
        );
230
        $this->assertEquals(array('master'), $this->getRepository()->getBranches(true));
231
        $this->getRepository()->createBranch('develop');
232
        $this->assertContains('master', $this->getRepository()->getBranches(true));
233
        $this->assertContains('develop', $this->getRepository()->getBranches(true));
234
    }
235
236
    /**
237
     * @covers GitElephant\Repository::getMainBranch
238
     */
239
    public function testGetMainBranch()
240
    {
241
        $this->getRepository()->init();
242
        $this->addFile('test-file');
243
        $this->getRepository()->commit('test', true);
244
        $this->assertEquals('master', $this->getRepository()->getMainBranch()->getName());
245
    }
246
247
    /**
248
     * @covers GitElephant\Repository::getBranch
249
     */
250
    public function testGetBranch()
251
    {
252
        $this->getRepository()->init();
253
        $this->addFile('test-file');
254
        $this->getRepository()->commit('test', true);
255
        $this->assertInstanceOf('GitElephant\Objects\Branch', $this->getRepository()->getBranch('master'));
256
        $this->assertNull($this->getRepository()->getBranch('a-branch-that-do-not-exists'));
257
    }
258
259
    /**
260
     * @covers GitElephant\Repository::merge
261
     */
262
    public function testMerge()
263
    {
264
        $this->getRepository()->init();
265
        $this->addFile('test-file');
266
        $this->getRepository()->commit('test', true);
267
        $this->assertEquals(1, count($this->getRepository()->getTree()));
268
        $this->getRepository()->createBranch('branch2');
269
        $this->getRepository()->checkout('branch2');
270
        $this->addFile('file2');
271
        $this->getRepository()->commit('test2', true);
272
        $this->assertEquals(2, count($this->getRepository()->getTree()));
273
        $this->getRepository()->checkout('master');
274
        $this->assertEquals(1, count($this->getRepository()->getTree()));
275
        $this->getRepository()->merge($this->getRepository()->getBranch('branch2'));
0 ignored issues
show
Bug introduced by
It seems like $this->getRepository()->getBranch('branch2') can be null; however, merge() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
276
        $this->assertEquals(2, count($this->getRepository()->getTree()));
277
278
        // attempt to merge a different branch by forcing a 3-way merge and verify the merge commit message
279
        $this->getRepository()->createBranch('branch3');
280
        $this->getRepository()->checkout('branch3');
281
        $this->addFile('file3');
282
        $this->getRepository()->commit('test3', true);
283
        $this->assertEquals(3, count($this->getRepository()->getTree()));
284
        $this->getRepository()->checkout('master');
285
        $this->assertEquals(2, count($this->getRepository()->getTree()));
286
        $this->getRepository()->merge($this->getRepository()->getBranch('branch3'), 'test msg', 'no-ff');
0 ignored issues
show
Bug introduced by
It seems like $this->getRepository()->getBranch('branch3') can be null; however, merge() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
287
        $this->assertEquals(3, count($this->getRepository()->getTree()));
288
        $this->assertEquals('test msg', $this->getRepository()->getCommit()->getMessage()->getFullMessage());
289
290
        // attempt a fast forward merge where a 3-way is necessary and trap the resulting exception
291
        $this->getRepository()->checkout('branch2');
292
        $this->addFile('file4');
293
        $this->getRepository()->commit('test4', true);
294
        $this->assertEquals(3, count($this->getRepository()->getTree()));
295
        $this->getRepository()->checkout('master');
296
        $this->assertEquals(3, count($this->getRepository()->getTree()));
297
        try {
298
            $this->getRepository()->merge($this->getRepository()->getBranch('branch2'), '', 'ff-only');
0 ignored issues
show
Bug introduced by
It seems like $this->getRepository()->getBranch('branch2') can be null; however, merge() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
299
        } catch (\RuntimeException $e) {
300
            return;
301
        }
302
        $this->fail("Merge should have produced a runtime exception.");
303
    }
304
305
    /**
306
     * @covers GitElephant\Repository::getTags
307
     * @covers GitElephant\Repository::getTag
308
     * @covers GitElephant\Repository::createTag
309
     * @covers GitElephant\Repository::deleteTag
310
     */
311
    public function testTags()
312
    {
313
        $this->getRepository()->init();
314
        $this->addFile('test-file');
315
        $this->getRepository()->commit('test', true);
316
        $this->assertEquals(0, count($this->getRepository()->getTags()));
317
        $this->getRepository()->createTag('test-tag');
318
        $this->assertEquals(1, count($this->getRepository()->getTags()));
319
        $this->assertInstanceOf('GitElephant\Objects\Tag', $this->getRepository()->getTag('test-tag'));
320
        $this->getRepository()->deleteTag('test-tag');
321
        $this->assertEquals(0, count($this->getRepository()->getTags()));
322
        $this->assertNull($this->getRepository()->getTag('a-tag-that-do-not-exists'));
323
    }
324
325
    /**
326
     * test getLastTag
327
     */
328
    public function testGetLastTag()
329
    {
330
        $this->getRepository()->init();
331
        $this->addFile('test-file');
332
        $this->getRepository()->commit('test', true);
333
        $this->getRepository()->createTag('0.0.2');
334
        sleep(1);
335
        $this->getRepository()->createTag('0.0.4');
336
        sleep(1);
337
        $this->getRepository()->createTag('0.0.3');
338
        sleep(1);
339
        $this->getRepository()->createTag('0.0.1');
340
        sleep(1);
341
        $this->assertEquals(Tag::pick($this->getRepository(), '0.0.1'), $this->getRepository()->getLastTag());
342
        $this->getRepository()->createTag('0.0.05');
343
        $this->assertEquals(Tag::pick($this->getRepository(), '0.0.05'), $this->getRepository()->getLastTag());
344
        $this->getRepository()->deleteTag(Tag::pick($this->getRepository(), '0.0.05'));
345
        $this->assertEquals(Tag::pick($this->getRepository(), '0.0.1'), $this->getRepository()->getLastTag());
346
    }
347
348
    /**
349
     * @covers GitElephant\Repository::getCommit
350
     */
351
    public function testGetCommit()
352
    {
353
        $this->getRepository()->init();
354
        $this->addFile('test-file');
355
        $this->getRepository()->commit('test', true);
356
        $this->assertInstanceOf('GitElephant\Objects\Commit', $this->getRepository()->getCommit());
357
    }
358
359
    public function testGetBranchOrTag()
360
    {
361
        $this->getRepository()->init();
362
        $this->addFile('test-file');
363
        $this->getRepository()->commit('test', true);
364
        $this->getRepository()->createBranch('branch2');
365
        $this->getRepository()->createTag('tag1');
366
        $this->assertInstanceOf('\GitElephant\Objects\Branch', $this->getRepository()->getBranchOrTag('branch2'));
367
        $this->assertInstanceOf('\GitElephant\Objects\Tag', $this->getRepository()->getBranchOrTag('tag1'));
368
        $this->assertNull($this->getRepository()->getBranchOrTag('not-exists'));
369
    }
370
371
    /**
372
     * @covers GitElephant\Repository::getObjectLog
373
     */
374
    public function testGetObjectLog()
375
    {
376
        $repo = $this->getRepository();
377
        $repo->init();
378
379
        $this->addFolder('test');
380
381
        $this->addFile('A.txt', 'test');
382
        $repo->commit('added A.txt', true);
383
384
        $this->addFile('B.txt', 'test');
385
        $repo->commit('added B.txt', true);
386
387
        $this->addFile('C.txt', 'test');
388
        $repo->commit('added C.txt', true);
389
390
        $this->addFile('D.txt', 'test');
391
        $repo->commit('added D.txt', true);
392
393
        $this->addFile('E.txt', 'test');
394
        $repo->commit('added E.txt', true);
395
396
        $tree = $repo->getTree();
397
        $obj = $tree[0];
398
399
        $log = $this->getRepository()->getObjectLog($obj);
400
        $this->assertInstanceOf('GitElephant\Objects\Log', $log);
401
        $this->assertEquals(1, $log->count());
402
403
        $log = $this->getRepository()->getObjectLog($obj, null, null, null);
404
        $this->assertEquals(5, $log->count());
405
406
        $this->assertEquals('added E.txt', $log->first()->getMessage()->toString());
407
        $this->assertEquals('added A.txt', $log->last()->getMessage()->toString());
408
    }
409
410
    /**
411
     * Test logs on different tree objects
412
     *
413
     * @covers GitElephant\Repository::getObjectLog
414
     */
415
    public function testGetObjectLogFolders()
416
    {
417
        $repo = $this->getRepository();
418
        $repo->init();
419
420
        $this->addFolder('A');
421
        $this->addFile('A1.txt', 'A');
422
        $repo->commit('A/A1', true);
423
424
        $this->addFile('A2.txt', 'A');
425
        $repo->commit('A/A2', true);
426
427
        $this->addFolder('B');
428
        $this->addFile('B1.txt', 'B');
429
        $repo->commit('B/B1', true);
430
431
        $this->addFile('B2.txt', 'B');
432
        $repo->commit('B/B2', true);
433
434
        $tree = $repo->getTree();
435
436
        /* @var $treeObj Object */
437
        foreach ($tree as $treeObj) {
438
            $name = $treeObj->getName();
439
            $log = $repo->getObjectLog($treeObj, null, null, null);
440
441
            $this->assertEquals(2, $log->count());
442
443
            $i = 2;
444
            foreach ($log as $commit) {
445
                $this->assertEquals($name . '/' . $name . $i, $commit->getMessage()->toString());
446
                --$i;
447
            }
448
        }
449
    }
450
451
    /**
452
     * Test logs on different branches
453
     *
454
     * @covers GitElephant\Repository::getObjectLog
455
     */
456
    public function testGetObjectLogBranches()
457
    {
458
        $repo = $this->getRepository();
459
        $repo->init();
460
461
        $this->addFolder('A');
462
        $this->addFile('A1.txt', 'A');
463
        $repo->commit('A/A1', true);
464
465
        $this->addFile('A2.txt', 'A');
466
        $repo->commit('A/A2', true);
467
468
        $repo->createBranch('test-branch');
469
        $repo->checkout('test-branch');
470
471
        $this->addFile('A3.txt', 'A');
472
        $repo->commit('A/A3', true);
473
474
        // master branch
475
        $repo->checkout('master');
476
        $tree = $repo->getTree();
477
        $dir = $tree[0];
478
        $log = $repo->getObjectLog($dir, null, null, null);
479
480
        $this->assertEquals(2, $log->count());
481
        $this->assertEquals('A/A2', $log->first()->getMessage()->toString());
482
483
        // test branch
484
        $repo->checkout('test-branch');
485
        $tree = $repo->getTree();
486
        $dir = $tree[0];
487
        $log = $repo->getObjectLog($dir, null, null, null);
488
489
        $this->assertEquals(3, $log->count());
490
        $this->assertEquals('A/A3', $log->first()->getMessage()->toString());
491
    }
492
493
    /**
494
     * @covers GitElephant\Repository::getLog
495
     */
496
    public function testGetLog()
497
    {
498
        $this->getRepository()->init();
499
500
        for ($i = 0; $i < 50; $i++) {
501
            $this->addFile('test file ' . $i);
502
            $this->getRepository()->commit('test commit ' . $i, true);
503
        }
504
505
        $log = $this->getRepository()->getLog();
506
        $this->assertInstanceOf('GitElephant\Objects\Log', $this->getRepository()->getLog());
507
        $this->assertGreaterThan(0, $log->count());
508
    }
509
510
    /**
511
     * @covers GitElephant\Repository::getLog
512
     */
513
    public function testGetLog_for_a_branch()
514
    {
515
        $this->getRepository()->init();
516
        $this->addFile('test file 0');
517
        $this->getRepository()->commit('first commit', true);
518
        $this->getRepository()->checkout('test-branch', true);
519
520
        for ($i = 1; $i <= 2; $i++) {
521
            $this->addFile('test file ' . $i);
522
            $this->getRepository()->commit('test commit ' . $i, true);
523
        }
524
525
        $log = $this->getRepository()->getLog(array('test-branch', '^master'));
526
        $this->assertInstanceOf('GitElephant\Objects\Log', $this->getRepository()->getLog());
527
        $this->assertEquals(2, $log->count());
528
    }
529
530
    /**
531
     * @covers GitElephant\Repository::checkout
532
     */
533
    public function testCheckout()
534
    {
535
        $this->getRepository()->init();
536
        $this->addFile('test-file');
537
        $this->getRepository()->commit('test', true);
538
        $this->assertEquals('master', $this->getRepository()->getMainBranch()->getName());
539
        $this->getRepository()->createBranch('branch2');
540
        $this->getRepository()->checkout('branch2');
541
        $this->assertEquals('branch2', $this->getRepository()->getMainBranch()->getName());
542
    }
543
544
    /**
545
     * @covers GitElephant\Repository::checkout
546
     */
547
    public function testCheckoutTag()
548
    {
549
        $this->getRepository()->init();
550
        $this->addFile('test-file');
551
        $this->getRepository()->commit('test', true);
552
        $this->getRepository()->createTag('v0.0.1');
553
        $this->addFile('test-file2');
554
        $this->getRepository()->commit('test2', true);
555
        $tag = $this->getRepository()->getTag('v0.0.1');
556
        $this->assertInstanceOf('GitElephant\Objects\Tag', $tag);
557
        $lastCommit = $this->getRepository()->getCommit();
558
        $this->assertNotContains('detached', implode(' ', $this->getRepository()->getStatusOutput()));
559
        $this->getRepository()->checkout($tag);
0 ignored issues
show
Bug introduced by
It seems like $tag defined by $this->getRepository()->getTag('v0.0.1') on line 555 can be null; however, GitElephant\Repository::checkout() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
560
        $newCommit = $this->getRepository()->getCommit();
561
        $this->assertNotEquals($newCommit->getSha(), $lastCommit->getSha());
562
        $this->assertContains('detached', implode(' ', $this->getRepository()->getStatusOutput()));
563
    }
564
565
    /**
566
     * @covers GitElephant\Repository::getTree
567
     * @covers GitElephant\Objects\Tree
568
     */
569
    public function testGetTree()
570
    {
571
        $this->getRepository()->init();
572
        $this->addFile('test');
573
        $this->addFolder('test-folder');
574
        $this->addFile('test2', 'test-folder');
575
576
        $this->getRepository()->stage();
577
        $this->getRepository()->commit('initial import');
578
579
        $tree = $this->getRepository()->getTree();
580
        $this->assertFalse($tree->isBlob());
581
        $this->assertTrue($this->getRepository()->getTree($this->getRepository()->getCommit(), 'test')->isBlob());
582
        $this->assertCount(2, $tree, 'One file in the repository');
583
        $firstNode = $tree[0];
584
        $this->assertInstanceOf(
585
            'GitElephant\Objects\Object',
586
            $firstNode,
587
            'array access on tree should give always a node type'
588
        );
589
        $this->assertEquals(
590
            'test-folder',
591
            $firstNode->getName(),
592
            'First repository file should be named "test"'
593
        );
594
        $secondNode = $tree[1];
595
        $this->assertInstanceOf(
596
            'GitElephant\Objects\Object',
597
            $secondNode,
598
            'array access on tree should give always a node type'
599
        );
600
        $this->assertEquals(
601
            Object::TYPE_BLOB,
602
            $secondNode->getType(),
603
            'second node should be of type tree'
604
        );
605
        $subtree = $this->getRepository()->getTree('master', 'test-folder');
606
        $subnode = $subtree[0];
607
        $this->assertInstanceOf(
608
            'GitElephant\Objects\Object',
609
            $subnode,
610
            'array access on tree should give always a node type'
611
        );
612
        $this->assertEquals(
613
            Object::TYPE_BLOB,
614
            $subnode->getType(),
615
            'subnode should be of type blob'
616
        );
617
        $this->assertEquals(
618
            'test2',
619
            $subnode->getName(),
620
            'subnode should be named "test2"'
621
        );
622
    }
623
624
    /**
625
     * @covers GitElephant\Repository::getDiff
626
     */
627
    public function testGetDiff()
628
    {
629
        $this->getRepository()->init();
630
        $this->addFile('test-file');
631
        $this->getRepository()->commit('commit 1', true);
632
        $commit1 = $this->getRepository()->getCommit();
633
        $this->assertInstanceOf('GitElephant\Objects\Diff\Diff', $this->getRepository()->getDiff($commit1));
634
        $this->addFile('test-file2');
635
        $this->getRepository()->commit('commit 2', true);
636
        $commit2 = $this->getRepository()->getCommit();
637
        $this->assertInstanceOf('GitElephant\Objects\Diff\Diff', $this->getRepository()->getDiff($commit2));
638
        $this->assertInstanceOf('GitElephant\Objects\Diff\Diff', $this->getRepository()->getDiff($commit2, $commit1));
639
        $shaHead = $this->getRepository()->getCommit();
640
        $this->assertInstanceOf('GitElephant\Objects\Diff\Diff', $diff = $this->getRepository()->getDiff($shaHead));
641
    }
642
643
    /**
644
     * testCloneFrom
645
     */
646
    public function testCloneFrom()
647
    {
648
        $this->initRepository(null, 0);
649
        $this->initRepository(null, 1);
650
        $remote = $this->getRepository(0);
651
        $remote->init();
652
        $this->addFile('test', null, null, $remote);
653
        $remote->commit('test', true);
654
        $local = $this->getRepository(1);
655
        $local->cloneFrom($remote->getPath(), '.');
656
        $commit = $local->getCommit();
657
        $this->assertEquals($remote->getCommit()->getSha(), $commit->getSha());
658
        $this->assertEquals($remote->getCommit()->getMessage(), $commit->getMessage());
659
    }
660
661
    /**
662
     * testOutputContent
663
     */
664
    public function testOutputContent()
665
    {
666
        $this->initRepository();
667
        $this->getRepository()->init();
668
        $this->addFile('file1', null, 'file content');
669
        $this->getRepository()->commit('first commit', true);
670
        $branch = $this->getRepository()->getBranch('master');
671
        $tree = $this->getRepository()->getTree($branch, 'file1');
0 ignored issues
show
Bug introduced by
It seems like $branch defined by $this->getRepository()->getBranch('master') on line 670 can be null; however, GitElephant\Repository::getTree() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
672
        $treeObject = $tree->getBlob();
673
        $this->assertEquals(array('file content'), $this->getRepository()->outputContent($treeObject, $branch));
0 ignored issues
show
Bug introduced by
It seems like $branch defined by $this->getRepository()->getBranch('master') on line 670 can be null; however, GitElephant\Repository::outputContent() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
674
    }
675
676
    /**
677
     * testMove
678
     */
679
    public function testMove()
680
    {
681
        $this->getRepository()->init();
682
        $this->addFile('foo');
683
        $this->getRepository()->commit('commit 1', true);
684
        $this->getRepository()->move('foo', 'bar');
685
        $status = $this->getRepository()->getStatusOutput();
686
687
        $this->assertRegExp('/(.*):    foo -> bar/', $status[4]);
688
    }
689
690
    /**
691
     * testRemove
692
     */
693
    public function testRemove()
694
    {
695
        $this->getRepository()->init();
696
        $this->addFile('foo');
697
        $this->getRepository()->commit('commit 1', true);
698
        $this->getRepository()->remove('foo');
699
        $status = $this->getRepository()->getStatusOutput();
700
701
        $this->assertRegExp('/(.*):    foo/', $status[4]);
702
    }
703
704
    /**
705
     * testCountCommits
706
     */
707
    public function testCountCommits()
708
    {
709
        $this->getRepository()->init();
710
        $this->addFile('foo');
711
        $this->getRepository()->commit('commit 1', true);
712
        $this->assertEquals(1, $this->getRepository()->countCommits());
713
        $this->addFile('foo2');
714
        $this->getRepository()->commit('commit 2', true);
715
        $this->assertEquals(2, $this->getRepository()->countCommits());
716
        $this->getRepository()->createBranch('new-branch');
717
        $this->getRepository()->checkout('new-branch');
718
        $this->assertEquals(2, $this->getRepository()->countCommits());
719
        $this->addFile('bar');
720
        $this->getRepository()->commit('commit 3', true);
721
        $this->assertEquals(3, $this->getRepository()->countCommits());
722
        $this->getRepository()->checkout('master');
723
        $this->assertEquals(2, $this->getRepository()->countCommits());
724
    }
725
726
    /**
727
     * testHumanishName
728
     */
729
    public function testHumanishName()
730
    {
731
        $this->initRepository('test-dir');
732
        $this->assertEquals('test-dir', $this->getRepository()->getHumanishName());
733
    }
734
735
    /**
736
     * testCreateFromRemote
737
     *
738
     * @return null
739
     */
740
    public function testCreateFromRemote()
741
    {
742
        $this->initRepository(null, 0);
743
        $remote = $this->getRepository(0);
744
        $remote->init();
745
        $this->addFile('test', null, null, $remote);
746
        $remote->commit('test', true);
747
        $remote->createBranch('develop');
748
749
        $repo = Repository::createFromRemote($remote->getPath());
750
        $this->assertInstanceOf('GitElephant\Repository', $repo);
751
        $this->assertGreaterThanOrEqual(2, $repo->getBranches());
752
        $branches = $repo->getBranches();
753
        $branchesName = array_map(
754
            function (Branch $b) {
755
                return $b->getName();
756
            },
757
            $branches
758
        );
759
        $this->assertContains('master', $branchesName);
760
        $this->assertContains('develop', $branchesName);
761
    }
762
763
    /**
764
     * testAddRemote
765
     */
766
    public function testRemote()
767
    {
768
        $this->initRepository(null, 0);
769
        $remote = $this->getRepository(0);
770
        $remote->init(true);
771
        $this->initRepository();
772
        $this->repository->init();
773
        $this->repository->addRemote('github', $remote->getPath());
774
        $this->assertInstanceOf('GitElephant\Objects\Remote', $this->repository->getRemote('github'));
775
        $this->repository->addRemote('github2', $remote->getPath());
776
        $this->assertCount(2, $this->repository->getRemotes());
777
    }
778
779
    /**
780
     * testFetch, git branch -a should find the branch
781
     */
782
    public function testFetch()
783
    {
784
        $this->initRepository(null, 0);
785
        $this->initRepository(null, 1);
786
        $r1 = $this->getRepository(0);
787
        $r1->init();
788
        $this->addFile('test1', null, null, $r1);
789
        $r1->commit('test commit', true);
790
        $r1->createBranch('tag-test');
791
        $this->addFile('test2', null, null, $r1);
792
        $r1->commit('another test commit', true);
793
        $r1->createTag('test-tag');
794
        $r2 = $this->getRepository(1);
795
        $r2->init();
796
        $r2->addRemote('origin', $r1->getPath());
797
        $this->assertEmpty($r2->getBranches(true, true));
798
        $r2->fetch();
799
        $this->assertNotEmpty($r2->getBranches(true, true));
800
        $r2->fetch(null, null, true);
801
        $this->assertNotNull($r2->getTag('test-tag'));
802
    }
803
804
    /**
805
     * test pull
806
     */
807
    public function testPull()
808
    {
809
        $this->initRepository(null, 0);
810
        $this->initRepository(null, 1);
811
        $r1 = $this->getRepository(0);
812
        $r1->init();
813
        $this->addFile('test1', null, null, $r1);
814
        $r1->commit('test commit', true);
815
        $r2 = $this->getRepository(1);
816
        $r2->init();
817
        $r2->addRemote('origin', $r1->getPath());
818
        $r2->pull('origin', 'master');
819
        $this->assertEquals('test commit', $r2->getLog()->last()->getMessage());
820
        $this->assertEquals($r1->getMainBranch()->getSha(), $r2->getLog()->last()->getSha());
821
    }
822
823
    /**
824
     * test pull
825
     */
826
    public function testPush()
827
    {
828
        $this->initRepository(null, 0);
829
        $this->initRepository(null, 1);
830
        $this->initRepository(null, 2);
831
        // commit on r1
832
        $r1 = $this->getRepository(0);
833
        $r1->init();
834
        $this->addFile('test1', null, null, $r1);
835
        $r1->commit('test commit', true);
836
        // push from r1 to r2
837
        $r2 = $this->getRepository(1);
838
        $r2->init(true);
839
        $r1->addRemote('origin', $r2->getPath());
840
        $r1->push('origin', 'master');
841
        // pull from r2 to r3 should get the same result
842
        $r3 = $this->getRepository(2);
843
        $r3->init();
844
        $r3->addRemote('origin', $r2->getPath());
845
        $r3->pull('origin', 'master');
846
847
        $this->assertEquals('test commit', $r3->getLog()->last()->getMessage());
848
        $this->assertEquals($r1->getMainBranch()->getSha(), $r3->getLog()->last()->getSha());
849
    }
850
851
    public function testRevParse()
852
    {
853
        $this->initRepository(null, 0);
854
        $r = $this->getRepository(0);
855
        $r->init();
856
        $this->addFile('test1', null, null, $r);
857
        $r->commit('test commit', true);
858
        $master = $r->getBranch('master');
859
        $revParse = $r->revParse($master, array());
860
        $this->assertEquals($master->getSha(), $revParse[0]);
861
    }
862
863
    public function testIsBare()
864
    {
865
        $this->initRepository(null, 0);
866
        $r = $this->getRepository(0);
867
        $r->init();
868
869
        $this->assertEquals(false, $r->isBare());
870
871
        $this->initRepository(null, 1);
872
        $r = $this->getRepository(1);
873
        $r->init(true);
874
875
        $this->assertEquals(true, $r->isBare());
876
877
    }
878
879
    /**
880
     * test add, remove and get global configs
881
     *
882
     * @covers GitElephant\Repository::addGlobalConfig
883
     * @covers GitElephant\Repository::getGlobalConfigs
884
     * @covers GitElephant\Repository::removeGlobalConfig
885
     */
886
    public function testGlobalConfigs()
887
    {
888
        $repo = $this->getRepository();
889
890
        $configs = array(
891
            'test1' => true,
892
            'test2' => 1,
893
            'test3' => 'value',
894
        );
895
        $this->assertEmpty($repo->getGlobalConfigs());
896
897
        foreach ($configs as $configName => $configValue) {
898
            $repo->addGlobalConfig($configName, $configValue);
899
        }
900
        $this->assertSame($configs, $repo->getGlobalConfigs());
901
902
        foreach ($configs as $configName => $configValue) {
903
            $repo->removeGlobalConfig($configName, $configValue);
0 ignored issues
show
Unused Code introduced by
The call to Repository::removeGlobalConfig() has too many arguments starting with $configValue.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
904
        }
905
        $this->assertEmpty($repo->getGlobalConfigs());
906
    }
907
908
    /**
909
     * test reset
910
     */
911
    public function testResetHard()
912
    {
913
        $this->initRepository();
914
        $repo=$this->getRepository();
915
        $repo->init();
916
        $this->addFile('file1');
917
        $repo->stage();
918
        $repo->commit('message1');
919
        $headCommit=$repo->getCommit();
920
        $this->addFile('file2');
921
        $repo->stage();
922
        $repo->commit('message2');
923
924
        $this->assertEquals(2,$repo->countCommits());
925
        $repo->reset($headCommit,array(ResetCommand::OPTION_HARD));
926
        $this->assertEquals(1,$repo->countCommits());
927
        $this->assertEmpty($repo->getIndexStatus()->added());
928
    }
929
930
    /**
931
     * test reset
932
     */
933
    public function testResetSoft()
934
    {
935
        $this->initRepository();
936
        $repo=$this->getRepository();
937
        $repo->init();
938
        $this->addFile('file1');
939
        $repo->stage();
940
        $repo->commit('message1');
941
        $headCommit=$repo->getCommit();
942
        $this->addFile('file2');
943
        $repo->stage();
944
        $repo->commit('message2');
945
946
        $this->assertEquals(2,$repo->countCommits());
947
        $repo->reset($headCommit,array(ResetCommand::OPTION_SOFT));
948
        $this->assertEquals(1,$repo->countCommits());
949
        $this->assertNotEmpty($repo->getIndexStatus()->added());
950
    }
951
952
    /**
953
     * test add, remove and get global options
954
     *
955
     * @covers GitElephant\Repository::addGlobalOption
956
     * @covers GitElephant\Repository::getGlobalOptions
957
     * @covers GitElephant\Repository::removeGlobalOption
958
     */
959
    public function testGlobalOptions()
960
    {
961
        $repo = $this->getRepository();
962
963
        $options = array(
964
            'test1' => true,
965
            'test2' => 1,
966
            'test3' => 'value',
967
        );
968
        $this->assertEmpty($repo->getGlobalOptions());
969
970
        foreach ($options as $configName => $configValue) {
971
            $repo->addGlobalOption($configName, $configValue);
972
        }
973
        $this->assertSame($options, $repo->getGlobalOptions());
974
975
        foreach ($options as $configName => $configValue) {
976
            $repo->removeGlobalOption($configName, $configValue);
0 ignored issues
show
Unused Code introduced by
The call to Repository::removeGlobalOption() has too many arguments starting with $configValue.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
977
        }
978
        $this->assertEmpty($repo->getGlobalOptions());
979
    }
980
981
    /**
982
     * test add, remove and get global command arguments
983
     *
984
     * @covers GitElephant\Repository::addGlobalCommandArgument
985
     * @covers GitElephant\Repository::getGlobalCommandArguments
986
     * @covers GitElephant\Repository::removeGlobalCommandArgument
987
     */
988
    public function testGlobalCommandArguments()
989
    {
990
        $repo = $this->getRepository();
991
992
        $args = array(
993
            true,
994
            1,
995
            'value',
996
        );
997
        $this->assertEmpty($repo->getGlobalCommandArguments());
998
999
        foreach ($args as $configValue) {
1000
            $repo->addGlobalCommandArgument($configValue);
1001
        }
1002
        $this->assertSame($args, $repo->getGlobalCommandArguments());
1003
1004
        foreach ($args as $configValue) {
1005
            $repo->removeGlobalCommandArgument($configValue);
1006
        }
1007
        $this->assertEmpty($repo->getGlobalCommandArguments());
1008
    }
1009
}
1010