akester/storehouse

Fork Project

59675c2f7e65dca0825716dee731b5c972e7705f

Authored By: Andrew Kester Date: July 7, 2017 2:59 am

Fixing issues with SVN diffs.

The --git option would try and output the diff of binary files, which would crash the diff parser. To combat this, we dropped the --git option.

The issue there is that added and removed files have no diff, so we have to also add a GetDiffSummary command that will get the associated files. This will feed into a new parameter of diffs that will handle special cases for added and removed files in the frontend.

src/StorehouseBundle/Entity/VCS/Diff.php
36 36
      */
37 37
     public $file2;
38 38
 
39
+    /**
40
+     * Type of diff (modified, added, or removed)
41
+     *
42
+     * @var string
43
+     */
44
+    public $type = 'modified';
45
+
46 39
     /**
47 40
      * Diff groups we've extracted
48 41
      *
src/StorehouseBundle/Utils/VCS/Commands/Helpers/ExtractDiff.php
80 80
         return $output;
81 81
     }
82 82
 
83
+    /**
84
+     * Get files that are beind diffed from an SVN style diff.
85
+     *
86
+     * @param string $line
87
+     *            Line to extract data form
88
+     * @return unknown[]|\StorehouseBundle\Entity\VCS\File[]
89
+     */
90
+    private static function getSvnFile($line)
91
+    {
92
+        $matches = array();
93
+        $output = array();
94
+
95
+        preg_match('/Index:[\s]+(.*)/', $line, $matches);
96
+        $file = new File();
97
+        $file->path = $matches[1];
98
+
99
+        $output['file1'] = $file;
100
+        $output['file2'] = $file;
101
+
102
+        return $output;
103
+    }
104
+
105 83
     /**
106 84
      * Extract a generic diff
107 85
      *
119 141
                     case 'hg':
120 142
                         $files = self::getHgFiles($line);
121 143
                         break;
122
+                    case 'svn':
123
+                        $files = self::getSvnFile($line);
124
+                        break;
125 144
                 }
126 145
                 $diff->file1 = $files['file1'];
127 146
                 $diff->file2 = $files['file2'];
208 233
      *            Diff output
209 234
      * @return \StorehouseBundle\Utils\VCS\Commands\Helpers\NULL[]|\StorehouseBundle\Entity\VCS\Diff[]
210 235
      */
236
-    public static function extractSvnDiff($output)
211
+    public static function extractSvnDiff($output, $paths)
212 237
     {
238
-        return self::extractDiff($output, 'diff --git', 'git');
213
+        $diffs = self::extractDiff($output, 'Index', 'svn');
214
+
215
+        /* Process summary output to get added and removed files */
216
+        foreach ($paths as $path) {
217
+            if ($path->getAttribute('item') == 'modified') {
218
+                continue;
219
+            }
220
+
221
+            $file = new File();
222
+            $file->path = $path->nodeValue;
223
+
224
+            $diff = new Diff();
225
+            $diff->file1 = $file;
226
+            $diff->file2 = $file;
227
+            $diff->type = $path->getAttribute('item');
228
+
229
+            $diffs[] = $diff;
230
+        }
231
+
232
+        return $diffs;
233 239
     }
234 240
 
235 241
     /**
src/StorehouseBundle/Utils/VCS/Commands/SVN/GetDiffCommand.php
29 29
      *
30 30
      * @var string
31 31
      */
32
-    protected $command = 'diff -r {{start}}:{{end}} --git';
32
+    protected $command = 'diff -r {{start}}:{{end}}';
33 33
 
34 34
     /**
35 35
      * Keys that are required to run this command.
42 42
         'path'
43 43
     );
44 44
 
45
+    /**
46
+     * Commands that need to be ran before this command.
47
+     *
48
+     * @var array
49
+     */
50
+    public $requisites = array(
51
+        GetDiffSummaryCommand::class
52
+    );
53
+
54 45
     /**
55 46
      *
56 47
      * {@inheritdoc}
50 59
      */
51 60
     public function processOutput($output, $extraOutput = null)
52 61
     {
62
-        return ExtractDiff::extractSvnDiff($output);
53
+        return ExtractDiff::extractSvnDiff($output, $extraOutput[0]);
54 63
     }
55 64
 }
src/StorehouseBundle/Utils/VCS/Commands/SVN/GetDiffSummaryCommand.php
0
+<?php
1
+namespace StorehouseBundle\Utils\VCS\Commands\SVN;
2
+
3
+use StorehouseBundle\Utils\VCS\Commands\Helpers\ExtractDiff;
4
+
5
+/*
6
+ * The Storehouse - Project Storage for Big Ideas
7
+ *
8
+ * This file is part of The Storehouse. Copyright 2017 Andrew Kester.
9
+ *
10
+ * This program is free software: you can redistribute it and/or modify
11
+ * it under the terms of the GNU Affero General Public License as published
12
+ * by the Free Software Foundation, either version 3 of the License, or
13
+ * (at your option) any later version.
14
+ *
15
+ * This program is distributed in the hope that it will be useful,
16
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
17
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18
+ * GNU Affero General Public License for more details.
19
+ *
20
+ * You should have received a copy of the GNU Affero General Public License
21
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
22
+ */
23
+class GetDiffSummaryCommand extends AbstractSVNCommand
24
+{
25
+
26
+    /**
27
+     * The command template to execute.
28
+     *
29
+     * @var string
30
+     */
31
+    protected $command = 'diff -r {{start}}:{{end}} --summarize --xml';
32
+
33
+    /**
34
+     * Keys that are required to run this command.
35
+     *
36
+     * @var array
37
+     */
38
+    protected $requiredKeys = array(
39
+        'start',
40
+        'end',
41
+        'path'
42
+    );
43
+
44
+    /**
45
+     *
46
+     * {@inheritdoc}
47
+     *
48
+     * @see \StorehouseBundle\Utils\VCS\Command\AbstractCommand::processOutput()
49
+     */
50
+    public function processOutput($output, $extraOutput = null)
51
+    {
52
+        $xml = new \DOMDocument();
53
+        $xml->loadXml(implode(' ', $output));
54
+
55
+        /* We go through and replace the project / file path so downstream processors don't have to */
56
+        foreach ($xml->getElementsByTagName('path') as $element) {
57
+
58
+            $element->nodeValue = str_replace('file://' . $this->getArgument('project') . '/', '', $element->nodeValue);
59
+        }
60
+
61
+        return $xml->getElementsByTagName('path');
62
+    }
63
+}
64 1