2 /* PageClasses.diff.class.php - phpgitweb
3 * Copyright (C) 2011-2012 Philipp Kreil (pk910)
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.
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.
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 private $commit, $tree, $diff, $data = array();
22 public function __construct($commit, $tree, $diff) {
23 $this->commit = $commit;
28 public static function generate_html($commit, $diff_data) {
32 foreach($diff_data['tree'] as $tree) {
34 if(array_key_exists($diff_id, $diff_data['diffs']))
35 $diff = $diff_data['diffs'][$diff_id];
38 if($diff && preg_match('/^diff --git (\"(?:[^\\\"]*(?:\\.[^\\\"]*)*)\"|[^ "]*) (.*)$/i', $diff[0], $matches))
39 $to_file = $matches[2];
40 else if($diff && preg_match('/^diff --(cc|combined) ("?.*"?)$/i', $diff[0], $matches))
41 $to_file = $matches[2];
44 if(!$to_file || strtolower($to_file) != $tree['to_file']) {
45 if($tree['parents'] > 1) {
46 //jump over missing diffs
47 $diffobj = new diff($commit, $tree, null);
48 $html[] = $diffobj->gen_contentprovider($patch_id);
55 $diffobj = new diff($commit, $tree, $diff);
56 $html[] = $diffobj->gen_contentprovider($patch_id);
59 if(!array_key_exists($diff_id, $diff_data['diffs']))
61 $diff = $diff_data['diffs'][$diff_id];
62 if(preg_match('/^diff --git (\"(?:[^\\\"]*(?:\\.[^\\\"]*)*)\"|[^ "]*) (.*)$/i', $diff[0], $matches))
63 $to_file = $matches[2];
64 else if(preg_match('/^diff --(cc|combined) ("?.*"?)$/i', $diff[0], $matches))
65 $to_file = $matches[2];
68 if(!array_key_exists('to_file', $tree))
69 $tree['to_file'] = $tree['file'];
70 if(strtolower($to_file) != $tree['to_file'])
72 $diffobj = new diff($commit, $tree, $diff);
73 $html[] = $diffobj->gen_contentprovider(null);
81 if(count($commit['parent']) > 1)
82 $html[] = new ContentProvider('commitdiff', 'patch_nopatch_merge');
84 $html[] = new ContentProvider('commitdiff', 'patch_nopatch_simple');
89 private function gen_diffcmd_header() {
92 $header[] = "diff --cc ";
93 $header[] = new ContentProvider('commitdiff', 'patch_link_blob', array('hash' => $this->commit['id'], 'file' => $this->tree['to_file'], 'file_hash' => $this->tree['to_id'], 'path' => ''));
94 } else if($this->tree['parents'] > 1) {
95 preg_match('!^(diff (.*?) )"?.*$!', $this->diff[0], $match);
96 $header[] = $match[1];
97 if(preg_match('/^[0]{40}$/', $this->tree['to_id']))
98 $header[] = $this->tree['to_file'];
100 $header[] = new ContentProvider('commitdiff', 'patch_link_blob', array('hash' => $this->commit['id'], 'file' => $this->tree['to_file'], 'file_hash' => $this->tree['to_id'], 'path' => ''));
102 preg_match('!^(diff (.*?) )"?a/.*$!', $this->diff[0], $match);
103 $header[] = $match[1];
104 if(preg_match('/^[0]{40}$/', $this->tree['from_id']))
105 $header[] = 'a/'.$this->tree['file'];
107 $header[] = new ContentProvider('commitdiff', 'patch_link_blob', array('hash' => $this->commit['parent'][0], 'file' => $this->tree['from_file'], 'file_hash' => $this->tree['from_id'], 'path' => 'a/'));
109 if(preg_match('/^[0]{40}$/', $this->tree['to_id']))
110 $header[] = 'b/'.$this->tree['file'];
112 $header[] = new ContentProvider('commitdiff', 'patch_link_blob', array('hash' => $this->commit['id'], 'file' => $this->tree['to_file'], 'file_hash' => $this->tree['to_id'], 'path' => 'b/'));
117 private function gen_index_header($line) {
119 if(preg_match('/^((copy|rename) from ).*$/', $line, $matches)) {
120 $header[] = $matches[1];
121 if(array_key_exists('copy', $this->data))
122 $this->data['copy']++;
124 $this->data['copy'] = 0;
125 if(is_array($this->tree['from_id']))
126 $from_id = $this->tree['from_id'][$this->data['copy']];
128 $from_id = $this->tree['from_id'];
129 $header[] = new ContentProvider('commitdiff', 'patch_link_blob', array('hash' => $this->commit['parent'][$this->data['copy']], 'file' => $this->tree['from_file'], 'file_hash' => $from_id, 'path' => ''));
130 } else if(preg_match('/^((copy|rename) to ).*$/', $line, $matches)) {
131 $header[] = $matches[1];
132 $header[] = new ContentProvider('commitdiff', 'patch_link_blob', array('hash' => $this->commit['id'], 'file' => $this->tree['to_file'], 'file_hash' => $this->tree['to_id'], 'path' => ''));
133 } else if(preg_match('/^(index )[0-9a-fA-F]{40},[0-9a-fA-F]{40}/', $line, $matches)) { //combined diff
134 $header[] = $matches[1];
136 foreach($this->tree['from_id'] as $from_id) {
139 if(preg_match('/^[0]{40}$/', $from_id))
140 $header[] = '0000000';
142 $header[] = new ContentProvider('commitdiff', 'patch_link_blob_id', array('hash' => $this->commit['parent'][$parent_id], 'file' => $this->tree['from_file'], 'file_hash' => $from_id, 'id' => substr($from_id, 0, 7)));
145 } else if(preg_match('/^(index )([0-9a-fA-F]{40})..([0-9a-fA-F]{40})/', $line, $matches)) {
146 $header[] = $matches[1];
147 if(preg_match('/^[0]{40}$/', $matches[2]))
148 $header[] = '0000000';
150 $header[] = new ContentProvider('commitdiff', 'patch_link_blob_id', array('hash' => $this->commit['parent'][0], 'file' => $this->tree['from_file'], 'file_hash' => $this->tree['from_id'], 'id' => substr($matches[2], 0, 7)));
152 if(preg_match('/^[0]{40}$/', $matches[3]))
153 $header[] = '0000000';
155 $header[] = new ContentProvider('commitdiff', 'patch_link_blob_id', array('hash' => $this->commit['id'], 'file' => $this->tree['to_file'], 'file_hash' => $this->tree['to_id'], 'id' => substr($matches[3], 0, 7)));
158 if(preg_match('/([0-7]{6})$/', $line, $matches)) {
159 $ftype = Tools::get_filetype($matches[1], true);
160 $header[] = new ContentProvider('commitdiff', 'patch_fileinfo', array('info' => $ftype));
165 private function format_line($line) {
166 $lineobj = new ContentProvider('commitdiff', 'patch_diffline');
168 if($this->tree['parents'] > 1) {
169 $prefix = substr($line, 0, $this->tree['parents']);
170 if(preg_match('/@/', $prefix))
171 $class = " chunk_header";
172 else if(preg_match('/\\/', $prefix))
173 $class = " incomplete";
174 else if(preg_match('/+/', $prefix))
176 else if(preg_match('/-/', $prefix))
179 $prefix = substr($line, 0, 1);
181 $class = " chunk_header";
182 else if($prefix == '\\')
183 $class = " incomplete";
184 else if($prefix == '+')
186 else if($prefix == '-')
189 $lineobj->set('class', $class);
190 $line = Tools::replaceTabs($line);
191 $lineobj->set('line', htmlentities($line));
196 private function gen_contentprovider($patch_id) {
198 $pageclass = 'patch_nodiff';
200 $pageclass = 'patch_continued';
202 $pageclass = 'patch_normal';
203 $page = new ContentProvider('commitdiff', $pageclass);
204 $page->set('diffcmd', $this->gen_diffcmd_header());
205 $page->set('patch_id', $patch_id);
209 $first_header = true;
210 for($i = 1; $i < count($this->diff); $i++) {
211 $line = $this->diff[$i];
213 if(preg_match('/^--- |^diff /', $line))
217 $page->append('header', '<br />');
218 $page->append('header', $this->gen_index_header($line));
219 $first_header = false;
223 $page->append('patch', $this->format_line($line));
227 $page->set('patch', '');