--- /dev/null
+<?php
+/* PageClasses.diff.class.php - phpgitweb
+ * Copyright (C) 2011-2012 Philipp Kreil (pk910)
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+class diff {
+ private $commit, $tree, $diff, $data = array();
+
+ public function __construct($commit, $tree, $diff) {
+ $this->commit = $commit;
+ $this->tree = $tree;
+ $this->diff = $diff;
+ }
+
+ public static function generate_html($commit, $diff_data) {
+ $diff_id = 0;
+ $patch_id = 1;
+ $html = array();
+ foreach($diff_data['tree'] as $tree) {
+ do {
+ if(array_key_exists($diff_id, $diff_data['diffs']))
+ $diff = $diff_data['diffs'][$diff_id];
+ else
+ $diff = null;
+ if($diff && preg_match('/^diff --git (\"(?:[^\\\"]*(?:\\.[^\\\"]*)*)\"|[^ "]*) (.*)$/i', $diff[0], $matches))
+ $to_file = $matches[2];
+ else if($diff && preg_match('/^diff --(cc|combined) ("?.*"?)$/i', $diff[0], $matches))
+ $to_file = $matches[2];
+ else
+ $to_file = null;
+ if(!$to_file || strtolower($to_file) != $tree['to_file']) {
+ if($tree['parents'] > 1) {
+ //jump over missing diffs
+ $diffobj = new diff($commit, $tree, null);
+ $html[] = $diffobj->gen_contentprovider($patch_id);
+ $patch_id++;
+ break;
+ }
+ if(!$to_file)
+ break;
+ }
+ $diffobj = new diff($commit, $tree, $diff);
+ $html[] = $diffobj->gen_contentprovider($patch_id);
+ $diff_id++;
+ do {
+ if(!array_key_exists($diff_id, $diff_data['diffs']))
+ break;
+ $diff = $diff_data['diffs'][$diff_id];
+ if(preg_match('/^diff --git (\"(?:[^\\\"]*(?:\\.[^\\\"]*)*)\"|[^ "]*) (.*)$/i', $diff[0], $matches))
+ $to_file = $matches[2];
+ else if(preg_match('/^diff --(cc|combined) ("?.*"?)$/i', $diff[0], $matches))
+ $to_file = $matches[2];
+ else
+ break;
+ if(!array_key_exists('to_file', $tree))
+ $tree['to_file'] = $tree['file'];
+ if(strtolower($to_file) != $tree['to_file'])
+ break;
+ $diffobj = new diff($commit, $tree, $diff);
+ $html[] = $diffobj->gen_contentprovider(null);
+ $diff_id++;
+ } while(true);
+ $patch_id++;
+ break;
+ } while(true);
+ }
+ return $html;
+ }
+
+ private function gen_diffcmd_header() {
+ $header = array();
+ if(!$this->diff) {
+ $header[] = "diff --cc ";
+ $header[] = new ContentProvider('commitdiff', 'patch_link_blob', array('hash' => $this->commit['id'], 'file' => $this->tree['to_file'], 'path' => ''));
+ } else if($this->tree['parents'] > 1) {
+ preg_match('!^(diff (.*?) )"?.*$!', $this->diff[0], $match);
+ $header[] = $match[1];
+ if(preg_match('/^[0]{40}$/', $this->tree['to_id']))
+ $header[] = $this->tree['to_file'];
+ else
+ $header[] = new ContentProvider('commitdiff', 'patch_link_blob', array('hash' => $this->commit['id'], 'file' => $this->tree['to_file'], 'path' => ''));
+ } else {
+ preg_match('!^(diff (.*?) )"?a/.*$!', $this->diff[0], $match);
+ $header[] = $match[1];
+ if(preg_match('/^[0]{40}$/', $this->tree['from_id']))
+ $header[] = 'a/'.$this->tree['file'];
+ else
+ $header[] = new ContentProvider('commitdiff', 'patch_link_blob', array('hash' => $this->commit['parent'][0], 'file' => $this->tree['from_file'], 'path' => 'a/'));
+ $header[] = ' ';
+ if(preg_match('/^[0]{40}$/', $this->tree['to_id']))
+ $header[] = 'b/'.$this->tree['file'];
+ else
+ $header[] = new ContentProvider('commitdiff', 'patch_link_blob', array('hash' => $this->commit['id'], 'file' => $this->tree['to_file'], 'path' => 'b/'));
+ }
+ return $header;
+ }
+
+ private function gen_index_header($line) {
+ $header = array();
+ if(preg_match('/^((copy|rename) from ).*$/', $line, $matches)) {
+ $header[] = $matches[1];
+ if(array_key_exists('copy', $this->data))
+ $this->data['copy']++;
+ else
+ $this->data['copy'] = 0;
+ $header[] = new ContentProvider('commitdiff', 'patch_link_blob', array('hash' => $this->commit['parent'][$this->data['copy']], 'file' => $this->tree['from_file'], 'path' => ''));
+ } else if(preg_match('/^((copy|rename) to ).*$/', $line, $matches)) {
+ $header[] = $matches[1];
+ $header[] = new ContentProvider('commitdiff', 'patch_link_blob', array('hash' => $this->commit['id'], 'file' => $this->tree['to_file'], 'path' => ''));
+ } else if(preg_match('/^(index )[0-9a-fA-F]{40},[0-9a-fA-F]{40}/', $line, $matches)) { //combined diff
+ $header[] = $matches[1];
+ $parent_id = 0;
+ foreach($this->tree['from_id'] as $from_id) {
+ if($parent_id)
+ $header[] = ',';
+ if(preg_match('/^[0]{40}$/', $from_id))
+ $header[] = '0000000';
+ else
+ $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)));
+ $parent_id++;
+ }
+ } else if(preg_match('/^(index )([0-9a-fA-F]{40})..([0-9a-fA-F]{40})/', $line, $matches)) {
+ $header[] = $matches[1];
+ if(preg_match('/^[0]{40}$/', $matches[2]))
+ $header[] = '0000000';
+ else
+ $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)));
+ $header[] = '..';
+ if(preg_match('/^[0]{40}$/', $matches[3]))
+ $header[] = '0000000';
+ else
+ $header[] = new ContentProvider('commitdiff', 'patch_link_blob_id', array('hash' => $this->commit['id'], 'file' => $this->tree['to_file'], 'id' => substr($matches[3], 0, 7)));
+ } else
+ $header[] = $line;
+ if(preg_match('/([0-7]{6})$/', $line, $matches)) {
+ $ftype = Tools::get_filetype($matches[1], true);
+ $header[] = new ContentProvider('commitdiff', 'patch_fileinfo', array('info' => $ftype));
+ }
+ return $header;
+ }
+
+ private function gen_contentprovider($patch_id) {
+ if(!$this->diff)
+ $pageclass = 'patch_nodiff';
+ else if(!$patch_id)
+ $pageclass = 'patch_continued';
+ else
+ $pageclass = 'patch_normal';
+ $page = new ContentProvider('commitdiff', $pageclass);
+ $page->set('diffcmd', $this->gen_diffcmd_header());
+ if(!$this->diff)
+ return $page;
+ $is_header = true;
+ $first_header = true;
+ for($i = 1; $i < count($this->diff); $i++) {
+ $line = $this->diff[$i];
+ if($is_header) {
+ if(preg_match('/^--- |^diff /', $line))
+ $is_header = false;
+ else {
+ if(!$first_header)
+ $page->append('header', '<br />');
+ $page->append('header', $this->gen_index_header($line));
+ $first_header = false;
+ continue;
+ }
+ }
+ $lineobj = new ContentProvider('commitdiff', 'patch_diffline');
+ //if(preg_match('', $line))
+ }
+ if($is_header)
+ $page->set('patch', '');
+
+ return $page;
+ }
+
+}
+
+?>
\ No newline at end of file