Completed
Push — master ( 127bad...31a673 )
by Matthias
02:19
created

All::setBranch()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 4
rs 10
cc 1
eloc 2
nc 1
nop 1
1
<?php
2
3
namespace Cauditor\Runners;
4
5
use Cauditor\Analyzers\AnalyzerInterface;
6
use Cauditor\Api;
7
use Cauditor\Config;
8
use Cauditor\Exception;
9
use MatthiasMullie\CI\Factory as CIFactory;
10
11
/**
12
 * @author Matthias Mullie <[email protected]>
13
 * @copyright Copyright (c) 2016, Matthias Mullie. All rights reserved.
14
 * @license LICENSE MIT
15
 */
16
class All implements RunnerInterface
17
{
18
    /**
19
     * @var Config
20
     */
21
    protected $config;
22
23
    /**
24
     * @var Api
25
     */
26
    protected $api;
27
28
    /**
29
     * @var AnalyzerInterface
30
     */
31
    protected $analyzer;
32
33
    /**
34
     * @var bool
35
     */
36
    protected $stashed;
37
38
    /**
39
     * @var string
40
     */
41
    protected $branch;
42
43
    /**
44
     * @param Config            $config
45
     * @param Api               $api
46
     * @param AnalyzerInterface $analyzer
47
     */
48
    public function __construct(Config $config, Api $api, AnalyzerInterface $analyzer)
49
    {
50
        $this->config = $config;
51
        $this->api = $api;
52
        $this->analyzer = $analyzer;
53
54
        // lets make sure the code we're testing is this specific commit,
55
        // without lingering uncommitted bits
56
        $output = exec('git stash');
57
        $this->stashed = $output === 'No local changes to save';
58
59
        // store current branch
60
        $environment = $this->getEnvironment();
61
        $this->branch = $environment['branch'];
62
63
        // move to default branch, which is likely the one we want to analyze
64
        $this->setBranch($this->getDefaultBranch());
65
    }
66
67
    /**
68
     * Restores the original environment after analyzing.
69
     */
70
    public function __destruct()
71
    {
72
        exec("git checkout $this->branch");
73
        if ($this->stashed) {
74
            exec('git stash pop');
75
        }
76
    }
77
78
    /**
79
     * @param string $branch
80
     */
81
    public function setBranch($branch)
82
    {
83
        exec("git checkout $branch && git reset --hard && git pull");
84
    }
85
86
    /**
87
     * @return string[]
88
     */
89
    protected function getCommits()
90
    {
91
        exec("git log --pretty=format:'%H'", $commits);
92
93
        return $commits;
94
    }
95
96
    /**
97
     * @throws Exception
98
     */
99
    public function execute()
100
    {
101
        // exclude commits that have already been imported
102
        $commits = $this->getCommits();
103
        $imported = $this->getImportedCommits();
104
        $missing = array_diff($commits, $imported);
105
        foreach ($missing as $commit) {
106
            exec("git reset $commit --hard");
107
108
            $metrics = $this->analyzer->execute();
109
            $data = array('metrics' => $metrics) + $this->getEnvironment();
110
111
            // submit to cauditor (note that branch can be empty for PRs)
112
            $uri = "/api/v1/{$data['slug']}/{$data['branch']}/{$data['commit']}";
113
            $uri = preg_replace('/(?<!:)\/+/', '/', $uri);
114
            $result = $this->api->put($uri, $data);
115
116
            if ($result !== false) {
117
                echo "Submitted metrics for {$data['commit']} @ {$data['slug']} {$data['branch']}\n";
118
            } else {
119
                echo "Failed to submit metrics for {$data['commit']} @ {$data['slug']} {$data['branch']}\n";
120
            }
121
        }
122
123
        echo "Done!\n";
124
    }
125
126
    /**
127
     * Returns array of commit hashes that have already been imported.
128
     *
129
     * @return string[]
130
     *
131
     * @throws Exception
132
     */
133
    protected function getImportedCommits()
134
    {
135
        $environment = $this->getEnvironment();
136
        $slug = $environment['slug'];
137
        $branch = $environment['branch'];
138
139
        $imported = $this->api->get("/api/v1/$slug/$branch");
140
        if ($imported === false) {
141
            throw new Exception('Failed to reach API.');
142
        }
143
144
        return json_decode($imported);
145
    }
146
147
    /**
148
     * @return string
149
     */
150
    protected function getDefaultBranch()
151
    {
152
        $config = shell_exec('cat .git/config');
153
        preg_match('/\[branch "(.+)"\]/', $config, $match);
154
155
        return isset($match[1]) ? $match[1] : 'master';
156
    }
157
158
    /**
159
     * @return array
160
     */
161
    protected function getEnvironment()
162
    {
163
        // get build data from CI
164
        $factory = new CIFactory();
165
        $environment = $factory->getCurrent();
166
167
        return array(
168
            'repo' => $environment->getRepo(),
169
            'slug' => $environment->getSlug(),
170
            'branch' => $environment->getBranch(),
171
            'pull-request' => $environment->getPullRequest(),
172
            'commit' => $environment->getCommit(),
173
            'previous-commit' => $environment->getPreviousCommit(),
174
            'author-email' => $environment->getAuthorEmail(),
175
            'timestamp' => $environment->getTimestamp(),
176
        );
177
    }
178
}
179