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'], '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'], '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'], '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'], '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 $header[] = new ContentProvider('commitdiff', 'patch_link_blob', array('hash' => $this->commit['parent'][$this->data['copy']], 'file' => $this->tree['from_file'], 'path' => ''));
126 } else if(preg_match('/^((copy|rename) to ).*$/', $line, $matches)) {
127 $header[] = $matches[1];
128 $header[] = new ContentProvider('commitdiff', 'patch_link_blob', array('hash' => $this->commit['id'], 'file' => $this->tree['to_file'], 'path' => ''));
129 } else if(preg_match('/^(index )[0-9a-fA-F]{40},[0-9a-fA-F]{40}/', $line, $matches)) { //combined diff
130 $header[] = $matches[1];
132 foreach($this->tree['from_id'] as $from_id) {
135 if(preg_match('/^[0]{40}$/', $from_id))
136 $header[] = '0000000';
138 $header[] = new ContentProvider('commitdiff', 'patch_link_blob_id', array('hash' => $this->commit['parent'][$parent_id], 'file' => $this->tree['from_file'], 'id' => substr($from_id, 0, 7)));
141 } else if(preg_match('/^(index )([0-9a-fA-F]{40})..([0-9a-fA-F]{40})/', $line, $matches)) {
142 $header[] = $matches[1];
143 if(preg_match('/^[0]{40}$/', $matches[2]))
144 $header[] = '0000000';
146 $header[] = new ContentProvider('commitdiff', 'patch_link_blob_id', array('hash' => $this->commit['parent'][0], 'file' => $this->tree['from_file'], 'id' => substr($matches[2], 0, 7)));
148 if(preg_match('/^[0]{40}$/', $matches[3]))
149 $header[] = '0000000';
151 $header[] = new ContentProvider('commitdiff', 'patch_link_blob_id', array('hash' => $this->commit['id'], 'file' => $this->tree['to_file'], 'id' => substr($matches[3], 0, 7)));
154 if(preg_match('/([0-7]{6})$/', $line, $matches)) {
155 $ftype = Tools::get_filetype($matches[1], true);
156 $header[] = new ContentProvider('commitdiff', 'patch_fileinfo', array('info' => $ftype));
161 private function format_line($line) {
162 $lineobj = new ContentProvider('commitdiff', 'patch_diffline');
164 if($this->tree['parents'] > 1) {
165 $prefix = substr($line, 0, $this->tree['parents']);
166 if(preg_match('/@/', $prefix))
167 $class = " chunk_header";
168 else if(preg_match('/\\/', $prefix))
169 $class = " incomplete";
170 else if(preg_match('/+/', $prefix))
172 else if(preg_match('/-/', $prefix))
175 $prefix = substr($line, 0, 1);
177 $class = " chunk_header";
178 else if($prefix == '\\')
179 $class = " incomplete";
180 else if($prefix == '+')
182 else if($prefix == '-')
185 $lineobj->set('class', $class);
186 $line = Tools::replaceTabs($line);
187 $lineobj->set('line', htmlentities($line));
192 private function gen_contentprovider($patch_id) {
194 $pageclass = 'patch_nodiff';
196 $pageclass = 'patch_continued';
198 $pageclass = 'patch_normal';
199 $page = new ContentProvider('commitdiff', $pageclass);
200 $page->set('diffcmd', $this->gen_diffcmd_header());
201 $page->set('patch_id', $patch_id);
205 $first_header = true;
206 for($i = 1; $i < count($this->diff); $i++) {
207 $line = $this->diff[$i];
209 if(preg_match('/^--- |^diff /', $line))
213 $page->append('header', '<br />');
214 $page->append('header', $this->gen_index_header($line));
215 $first_header = false;
219 $page->append('patch', $this->format_line($line));
223 $page->set('patch', '');