From 5a1b314c0a0ab8ed9be7b857c7996d8a3f87e7ed Mon Sep 17 00:00:00 2001 From: pk910 Date: Fri, 15 Feb 2013 22:36:02 +0100 Subject: [PATCH] started diff parser --- htdocs/lib/ContentProvider.class.php | 5 +- htdocs/lib/GitCommand.class.php | 9 +- htdocs/lib/PHPGitWeb.class.php | 1 + htdocs/lib/PageClasses.diff.class.php | 192 ++++++++++++++++++++++++ htdocs/pages/commitdiff.class.php | 2 +- htdocs/templates/default/commitdiff.tpl | 38 ++++- 6 files changed, 239 insertions(+), 8 deletions(-) create mode 100644 htdocs/lib/PageClasses.diff.class.php diff --git a/htdocs/lib/ContentProvider.class.php b/htdocs/lib/ContentProvider.class.php index 76b2eb0..cbfd7c3 100644 --- a/htdocs/lib/ContentProvider.class.php +++ b/htdocs/lib/ContentProvider.class.php @@ -112,8 +112,9 @@ class ContentProvider { else { $template_html = $this->load_template($this->template, $subtemplate); } - $template_html = preg_replace_callback('/%([^%]*)%/', array($this, "replace_placeholder"), $template_html); - $template_html = preg_replace_callback('/%([^%]*)%/', array($this, "replace_placeholder"), $template_html); + $template_html = preg_replace('/([\r\n]*)$/mD', '', $template_html); + $template_html = preg_replace_callback('/%([^%\n]*)%/', array($this, "replace_placeholder"), $template_html); + $template_html = preg_replace_callback('/%([^%\n]*)%/', array($this, "replace_placeholder"), $template_html); return $template_html; } diff --git a/htdocs/lib/GitCommand.class.php b/htdocs/lib/GitCommand.class.php index 1e4b07f..86174b5 100644 --- a/htdocs/lib/GitCommand.class.php +++ b/htdocs/lib/GitCommand.class.php @@ -153,17 +153,18 @@ class GitCommand { $files = explode("\t", $entry['file']); $entry['from_file'] = $files[0]; $entry['to_file'] = $files[1]; - } + } else + $entry['from_file'] = $entry['to_file'] = $entry['file']; } else if(preg_match('/^(::+)((?:[0-7]{6} )+)((?:[0-9a-fA-F]{40} )+)([a-zA-Z]+)\t(.*)$/i', $line, $matches)) { $entry['parents'] = strlen($matches[1]); $from_modes = explode(" ", $matches[2]); - $entry['from_mode'] = array_slice($from_modes, 1); + $entry['from_mode'] = array_slice($from_modes, 1, -1); $entry['to_mode'] = $from_modes[0]; $from_ids = explode(" ", $matches[3]); - $entry['from_id'] = array_slice($from_ids, 1); + $entry['from_id'] = array_slice($from_ids, 1, -1); $entry['to_id'] = $from_ids[0]; $entry['status'] = str_split($matches[4]); - $entry['file'] = $matches[5]; + $entry['file'] = $entry['from_file'] = $entry['to_file'] = $matches[5]; } return $entry; } diff --git a/htdocs/lib/PHPGitWeb.class.php b/htdocs/lib/PHPGitWeb.class.php index 95cbe23..fc278af 100644 --- a/htdocs/lib/PHPGitWeb.class.php +++ b/htdocs/lib/PHPGitWeb.class.php @@ -25,6 +25,7 @@ require_once("lib/Tools.class.php"); require_once("lib/Validation.class.php"); require_once("lib/PageClasses.difftree.class.php"); require_once("lib/PageClasses.shortlog.class.php"); +require_once("lib/PageClasses.diff.class.php"); require_once("lib/graph.class.php"); class PHPGitWeb { diff --git a/htdocs/lib/PageClasses.diff.class.php b/htdocs/lib/PageClasses.diff.class.php new file mode 100644 index 0000000..ff53a20 --- /dev/null +++ b/htdocs/lib/PageClasses.diff.class.php @@ -0,0 +1,192 @@ +. + */ + +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', '
'); + $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 diff --git a/htdocs/pages/commitdiff.class.php b/htdocs/pages/commitdiff.class.php index 096385c..e8bb17f 100644 --- a/htdocs/pages/commitdiff.class.php +++ b/htdocs/pages/commitdiff.class.php @@ -82,7 +82,7 @@ class page_commitdiff { $difftree->push_difftree_data($diff_data['tree']); $this->page->set('difftree', $difftree->generate_difftree($project, $commit, true)); - + $this->page->set('patchset', diff::generate_html($commit, $diff_data)); return $this->page; } diff --git a/htdocs/templates/default/commitdiff.tpl b/htdocs/templates/default/commitdiff.tpl index 0ee2b38..398aa0c 100644 --- a/htdocs/templates/default/commitdiff.tpl +++ b/htdocs/templates/default/commitdiff.tpl @@ -36,4 +36,40 @@
%patchset%
- \ No newline at end of file + + +# [patch_continued] +
+
%diffcmd%
+
+%header% +
+%patch% +
+ +# [patch_normal] +
+
%diffcmd%
+
+%header% +
+%patch% +
+ +# [patch_nodiff] +
+
%diffcmd%
+
Simple merge
+
+ +# [patch_link_blob] +%path%%file% + +# [patch_link_blob_id] +%id% + +# [patch_fileinfo] + (%info%) + +# [patch_diffline] +
%line%
-- 2.20.1