Failed Conditions
Push — develop ( bf7046...18e86d )
by Maxime
18:38
created

Git::checkout()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 16
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 11
CRAP Score 2

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 16
ccs 11
cts 11
cp 1
rs 9.4285
cc 2
eloc 9
nc 2
nop 1
crap 2
1
<?php
2
3
/*
4
 * This file is part of Rocketeer
5
 *
6
 * (c) Maxime Fabre <[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
 */
12
13
namespace Rocketeer\Binaries\Vcs;
14
15
use Rocketeer\Binaries\AbstractBinary;
16
17
/**
18
 * The Git implementation of the VcsInterface.
19
 */
20
class Git extends AbstractBinary implements VcsInterface
21
{
22
    /**
23
     * The core binary.
24
     *
25
     * @var string
26
     */
27
    protected $binary = 'git';
28
29
    ////////////////////////////////////////////////////////////////////
30
    ///////////////////////////// INFORMATIONS /////////////////////////
31
    ////////////////////////////////////////////////////////////////////
32
33
    /**
34
     * Check if the VCS is available.
35
     *
36
     * @return string
37
     */
38 7
    public function check()
39
    {
40 7
        return $this->getCommand('--version');
41
    }
42
43
    /**
44
     * Get the current state.
45
     *
46
     * @return string
47
     */
48 3
    public function currentState()
49
    {
50 3
        return $this->revParse('HEAD');
0 ignored issues
show
Documentation Bug introduced by Maxime Fabre
The method revParse does not exist on object<Rocketeer\Binaries\Vcs\Git>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
51
    }
52
53
    /**
54
     * Get the current branch.
55
     *
56
     * @return string
57
     */
58 1
    public function currentBranch()
59
    {
60 1
        return $this->revParse('--abbrev-ref HEAD');
0 ignored issues
show
Documentation Bug introduced by Maxime Fabre
The method revParse does not exist on object<Rocketeer\Binaries\Vcs\Git>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
61
    }
62
63
    /**
64
     * @return string
65
     */
66 5
    public function currentEndpoint()
67
    {
68 5
        return $this->getCommand('remote get-url origin');
69
    }
70
71
    ////////////////////////////////////////////////////////////////////
72
    /////////////////////////////// ACTIONS ////////////////////////////
73
    ////////////////////////////////////////////////////////////////////
74
75
    /**
76
     * Clone a repository.
77
     *
78
     * @param string $destination
79
     *
80
     * @return string
81
     */
82 22
    public function checkout($destination)
83
    {
84 22
        $repository = $this->credentials->getCurrentRepository();
85 22
        $arguments = array_map([$this, 'quote'], [
86 22
            $repository->repository,
87 22
            $destination,
88 22
        ]);
89
90
        // Build flags
91 22
        $flags = ['--branch' => $repository->branch];
92 22
        if ($this->config->getContextually('vcs.shallow')) {
0 ignored issues
show
Bug introduced by Maxime Fabre
It seems like you code against a concrete implementation and not the interface Rocketeer\Services\Config\ConfigurationInterface as the method getContextually() does only exist in the following implementations of said interface: Rocketeer\Services\Config\ContextualConfiguration, Rocketeer\Services\Config\ContextualConfiguration.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
93 20
            $flags['--depth'] = 1;
94 20
        }
95
96 22
        return $this->clone($arguments, $flags);
0 ignored issues
show
Documentation Bug introduced by Maxime Fabre
The method clone does not exist on object<Rocketeer\Binaries\Vcs\Git>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
97
    }
98
99
    /**
100
     * Resets the repository.
101
     *
102
     * @return string
103
     */
104 7
    public function reset()
105
    {
106 7
        return $this->getCommand('reset', [], ['--hard']);
107
    }
108
109
    /**
110
     * Updates the repository.
111
     *
112
     * @return string
113
     */
114 7
    public function update()
115
    {
116 7
        return $this->pull(null, ['--recurse-submodules']);
0 ignored issues
show
Documentation Bug introduced by Maxime Fabre
The method pull does not exist on object<Rocketeer\Binaries\Vcs\Git>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
117
    }
118
119
    /**
120
     * Checkout the repository's submodules.
121
     *
122
     * @return string
123
     */
124 12
    public function submodules()
125
    {
126 12
        return $this->submodule('update', ['--init', '--recursive']);
127
    }
128
}
129