started diff parser
authorpk910 <philipp@zoelle1.de>
Fri, 15 Feb 2013 21:36:02 +0000 (22:36 +0100)
committerpk910 <philipp@zoelle1.de>
Fri, 15 Feb 2013 21:36:02 +0000 (22:36 +0100)
htdocs/lib/ContentProvider.class.php
htdocs/lib/GitCommand.class.php
htdocs/lib/PHPGitWeb.class.php
htdocs/lib/PageClasses.diff.class.php [new file with mode: 0644]
htdocs/pages/commitdiff.class.php
htdocs/templates/default/commitdiff.tpl

index 76b2eb0f1e1a508053a9df9d46d1c8048fbd703a..cbfd7c332301c7ebd5b7d8d2463dd6b33536879f 100644 (file)
@@ -112,8 +112,9 @@ class ContentProvider {
                else {
                        $template_html = $this->load_template($this->template, $subtemplate);
                }
                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;
        }
                
                return $template_html;
        }
index 1e4b07f6b4c29e4001c22e2bc2031804ea7809ee..86174b5e6e29551eba91a7757378208d913fe9eb 100644 (file)
@@ -153,17 +153,18 @@ class GitCommand {
                                $files = explode("\t", $entry['file']);
                                $entry['from_file'] = $files[0];
                                $entry['to_file'] = $files[1];
                                $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]);
                } 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['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['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;
        }
                }
                return $entry;
        }
index 95cbe23157f071afd89b2cf0224d948db4546a1e..fc278afc2af1318a57b054a35b2c7c766a3d6784 100644 (file)
@@ -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/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 {
 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 (file)
index 0000000..ff53a20
--- /dev/null
@@ -0,0 +1,192 @@
+<?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
index 096385c18b5f5aa8d62e111b73a2a39ea477ab98..e8bb17f6999a3918434312ec41830b970950da0a 100644 (file)
@@ -82,7 +82,7 @@ class page_commitdiff {
                $difftree->push_difftree_data($diff_data['tree']);
                $this->page->set('difftree', $difftree->generate_difftree($project, $commit, true));
                
                $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;
        }
                
                return $this->page;
        }
index 0ee2b3866313c459c99ca789ef5f3265b6d0c192..398aa0c304ace115b6ddacd1f7d5dc71656cd153 100644 (file)
 <div class="patchset">
 %patchset%
 </div>
 <div class="patchset">
 %patchset%
 </div>
-</div>
\ No newline at end of file
+</div>
+
+# [patch_continued]
+<div class="patch cont">
+<div class="diff header">%diffcmd%</div>
+<div class="diff extended_header">
+%header%
+</div>
+%patch%
+</div>
+
+# [patch_normal]
+<div class="patch" id="patch%patch_id%">
+<div class="diff header">%diffcmd%</div>
+<div class="diff extended_header">
+%header%
+</div>
+%patch%
+</div>
+
+# [patch_nodiff]
+<div class="patch" id="patch%patch_id%">
+<div class="diff header">%diffcmd%</div>
+<div class="diff nodifferences">Simple merge</div>
+</div>
+
+# [patch_link_blob]
+<a class="path" href="?p=%project%&a=blob&h=%hash%&f=%file%">%path%%file%</a>
+
+# [patch_link_blob_id]
+<a class="path" href="?p=%project%&a=blob&h=%hash%&f=%file%">%id%</a>
+
+# [patch_fileinfo]
+<span class="info"> (%info%)</span>
+
+# [patch_diffline]
+<div class="diff%class%">%line%</div>