Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
50.00% covered (danger)
50.00%
17 / 34
40.00% covered (danger)
40.00%
2 / 5
CRAP
0.00% covered (danger)
0.00%
0 / 1
Git
50.00% covered (danger)
50.00%
17 / 34
40.00% covered (danger)
40.00%
2 / 5
16.00
0.00% covered (danger)
0.00%
0 / 1
 __construct
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getChangedFiles
100.00% covered (success)
100.00%
16 / 16
100.00% covered (success)
100.00%
1 / 1
3
 checkout
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
2
 getSha1
0.00% covered (danger)
0.00%
0 / 5
0.00% covered (danger)
0.00%
0 / 1
2
 findNonMergeCommit
0.00% covered (danger)
0.00%
0 / 8
0.00% covered (danger)
0.00%
0 / 1
6
1<?php
2/**
3 * Copyright (C) 2018 Kunal Mehta <legoktm@debian.org>
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
17 */
18
19namespace MediaWiki\Tool\PatchCoverage;
20
21use Symfony\Component\Process\Process;
22
23/**
24 * Wrapper around git
25 */
26class Git {
27
28    /**
29     * @var string[]
30     */
31    private static $status = [
32        'A' => 'added',
33        'D' => 'deleted',
34        'M' => 'modified',
35        'R' => 'renamed',
36    ];
37
38    /**
39     * @var string
40     */
41    private $path;
42
43    /**
44     * @param string $path
45     */
46    public function __construct( $path ) {
47        $this->path = $path;
48    }
49
50    /**
51     * @param string $ref
52     *
53     * @return GitChanged
54     */
55    public function getChangedFiles( $ref ) {
56        $process = new Process(
57            [ 'git', 'diff', '--name-status', $ref . '^', $ref ]
58        );
59        $process->setWorkingDirectory( $this->path );
60        $process->mustRun();
61        $changed = new GitChanged();
62        $lines = explode( "\n", trim( $process->getOutput() ) );
63        foreach ( $lines as $line ) {
64            $status = self::$status[$line[0]];
65            if ( $status === 'renamed' ) {
66                $matches = [];
67                preg_match( '/R\d{3}\s*(\S*)\s*(\S*)/', $line, $matches );
68                $changed->renamed[$matches[1]] = $matches[2];
69            } else {
70                $file = trim( substr( $line, 1 ) );
71                $changed->{$status}[] = $file;
72            }
73        }
74
75        return $changed;
76    }
77
78    /**
79     * git checkout
80     *
81     * @param string $ref
82     */
83    public function checkout( $ref ) {
84        $process = new Process(
85            [ 'git', 'checkout', $ref ]
86        );
87        $process->mustRun();
88    }
89
90    /**
91     * Get a SHA1 for any ref
92     *
93     * @param string $ref
94     *
95     * @return string
96     */
97    public function getSha1( $ref ) {
98        $process = new Process(
99            [ 'git', 'rev-parse', $ref ]
100        );
101        $process->mustRun();
102        return trim( $process->getOutput() );
103    }
104
105    /**
106     * If $ref is a merge commit, get its parent,
107     * otherwise return $ref
108     *
109     * @param string $ref
110     *
111     * @return string
112     */
113    public function findNonMergeCommit( $ref ) {
114        $process = new Process(
115            [ 'git', 'log', '--format=%P', $ref, '-n1' ]
116        );
117        $process->mustRun();
118        $exploded = explode( ' ', trim( $process->getOutput() ) );
119        if ( count( $exploded ) > 1 ) {
120            return end( $exploded );
121        } else {
122            return $this->getSha1( $ref );
123        }
124    }
125}