added commit difftree
[phpgitweb.git] / htdocs / pages / commit.class.php
index 17f5678758cf9312409876c3ec94ce5838a1fb4b..3c10b4486d1798bb7675eaac08b9de1863202158 100644 (file)
 
 require_once('pages/shortlog.class.php');
 
+class difftree {
+       
+       public function generate_difftree($project, $commit, $patch_link) {
+               $difftree = new ContentProvider('commit', 'difftree');
+               $tree = GitCommand::get_commit_changes($project['path'], $commit['id'], $commit['parent']);
+               $entry_count = 0;
+               if(count($commit['parent']) > 1)
+                       $difftree->set('class', ' combined');
+               else
+                       $difftree->set('class', '');
+               foreach($tree as $entry) {
+                       $entry_count++;
+                       $difftree->append('tree', $this->tree_entry($entry_count, (($entry_count % 2) ? 'dark' : 'light'), $commit, $entry, $patch_link));
+               }
+               if(count($tree) == 0)
+                       $difftree->set('tree', '');
+               return $difftree;
+       }
+       
+       private function tree_entry($diffid, $class, $commit, $entry, $patch_link) {
+               $tree = new ContentProvider('commit', 'tree');
+               $tree->set('class', $class);
+               $tree->set('hash', $commit['id']);
+               $tree->set('file', $entry['file']);
+               
+               if(count($commit['parent']) > 1) {
+                       if(preg_match('/^[0]{40}$/', $entry['to_id'])) //file doesn't exist in the result (child) commit
+                               $tree->set('file', $entry['file']);
+                       else
+                               $tree->set('file', new ContentProvider('commit', 'tree_file_link', array('file' => $entry['file'])));
+                       
+                       $tree->set('specials', '');
+                       
+                       if($patch_link)
+                               $tree->append('merge', new ContentProvider('commit', 'tree_merge_patch_link', array("patch_marker" => "patch".$diffid)));
+                       
+                       $has_history = false;
+                       $not_deleted = false;
+                       
+                       for($i = 0; $i < count($commit['parent']); $i++) {
+                               $status = $entry['status'][$i];
+                               $merge = null;
+                               
+                               $has_history = ($has_history || ($status != 'A'));
+                               $not_deleted = ($not_deleted || ($status != 'D'));
+                               
+                               switch($status) {
+                               case 'A': //Added
+                                       $merge = new ContentProvider('commit', 'tree_merge_new');
+                                       break;
+                               case 'D': //Deleted
+                                       $merge = new ContentProvider('commit', 'tree_merge');
+                                       $merge->set('class', '');
+                                       $blob_link = new ContentProvider('commit', 'tree_merge_blob', array('hash' => $commit['parent'][$i], 'file' => $entry['file']));
+                                       $merge->set('links', array($blob_link, ' | '));
+                                       break;
+                               default:
+                                       $merge = new ContentProvider('commit', 'tree_merge');
+                                       if($entry['from_id'][$i] == $entry['to_id']) {
+                                               $merge->set('class', ' nochange');
+                                               $merge->set('links', ' | ');
+                                       } else {
+                                               $merge->set('class', '');
+                                               $merge->set('links', new ContentProvider('commit', 'tree_merge_diff', array('hash' => $commit['id'], 'parent' => $commit['parent'][$i], 'file' => $entry['file'], 'id' => ($i + 1))));
+                                       }
+                               }
+                               $tree->append('merge', $merge);
+                       }
+                       
+                       $tree->set('links', '');
+                       if($not_deleted) {
+                               $tree->append('links', new ContentProvider('commit', 'tree_merge_blob', array('hash' => $commit['id'], 'file' => $entry['file'])));
+                               if($has_history)
+                                       $tree->append('links', ' | ');
+                       }
+                       if($has_history)
+                               $tree->append('links', new ContentProvider('commit', 'tree_merge_history', array('hash' => $commit['id'], 'file' => $entry['file'])));
+                       
+               } else {
+                       $tree->set('file', new ContentProvider('commit', 'tree_file_link', array('file' => $entry['file'])));
+                       $tree->set('merge', '');
+                       
+                       $from_type = Tools::get_filetype($entry['from_mode']);
+                       $to_type = Tools::get_filetype($entry['to_mode']);
+                       
+                       $from_mode = (Tools::is_regular_file($entry['from_mode']) ? Tools::get_file_permissions($entry['from_mode']) : null);
+                       $to_mode = (Tools::is_regular_file($entry['to_mode']) ? Tools::get_file_permissions($entry['to_mode']) : null);
+                       
+                       $link_placeholders = array(
+                                       "hash" => $commit['id'],
+                                       "file" => $entry['file'],
+                                       "parent" => (count($commit['parent']) ? $commit['parent'][0] : ""),
+                               );
+                       if($patch_link)
+                               $tree->append('links', new ContentProvider('commit', 'tree_patch_link', array("patch_marker" => "patch".$diffid)));
+                       
+                       switch($entry['status']) {
+                       case 'A': //Added
+                               $tree->set('specials', new ContentProvider('commit', (Tools::is_regular_file($entry['to_mode']) ? 'tree_new_file' : 'tree_new'), array('type' => $to_type, 'mode' => $to_mode)));
+                               $tree->append('links', new ContentProvider('commit', 'tree_new_links', $link_placeholders));
+                               break;
+                       case 'D': //Deleted
+                               $tree->set('specials', new ContentProvider('commit', 'tree_deleted', array('type' => $from_type)));
+                               $tree->append('links', new ContentProvider('commit', 'tree_deleted_links', $link_placeholders));
+                               break;
+                       case 'M': //Modified
+                       case 'T': //Type changed
+                               if($entry['from_mode'] != $entry['to_mode']) {
+                                       $modified = new ContentProvider('commit', 'tree_changed');
+                                       $tree->set('specials', $modified);
+                                       if($from_type != $to_type)
+                                               $modified->append('changes', new ContentProvider('commit', 'tree_changed_type', array('from' => $from_type, 'to' => $to_type)));
+                                       if($from_mode != $to_mode && $to_mode) {
+                                               if($from_mode)
+                                                       $modified->append('changes', new ContentProvider('commit', 'tree_changed_mode', array('from' => $from_mode, 'to' => $to_mode)));
+                                               else
+                                                       $modified->append('changes', new ContentProvider('commit', 'tree_changed_mode_to', array('to' => $to_mode)));
+                                       }
+                               } else
+                                       $tree->set('specials', '');
+                               if($entry['from_id'] != $entry['to_id'])
+                                       $tree->append('links', new ContentProvider('commit', 'tree_changed_links_diff', $link_placeholders));
+                               $tree->append('links', new ContentProvider('commit', 'tree_changed_links', $link_placeholders));
+                               break;
+                       case 'R': //Renamed
+                       case 'C': //Copied
+                               $actions = array('R' => 'tree_moved', 'C' => 'tree_copied');
+                               $move = new ContentProvider('commit', $actions[$entry['status']]);
+                               $tree->set('specials', $move);
+                               $tree->set('file', $entry['to_file']);
+                               $move->set('file', $entry['from_file']);
+                               $move->set('hash', $commit['parent'][0]);
+                               $move->set('similarity', $entry['similarity']);
+                               if($from_mode != $to_mode)
+                                       $move->set('mode', new ContentProvider('commit', 'tree_moved_mode', array('mode' => $to_mode)));
+                               else
+                                       $move->set('mode', '');
+                               if($entry['from_id'] != $entry['to_id'])
+                                       $tree->append('links', new ContentProvider('commit', 'tree_moved_links_diff', $link_placeholders));
+                               $tree->append('links', new ContentProvider('commit', 'tree_moved_links', $link_placeholders));
+                               break;
+                       default:
+                               
+                       }
+                       
+               }
+               return $tree;
+       }
+       
+}
+
 class page_commit {
     private $page, $phpgitweb;
        private $commitid;
@@ -70,6 +221,8 @@ class page_commit {
                foreach($commit['parent'] as $parent) {
                        $this->page->append('parents', new ContentProvider('commit', 'parent', array('hash' => $parent, 'head' => $commit['id'])));
                }
+               if(count($commit['parent']) == 0)
+                       $this->page->set('parents', '');
                
                $refs = new ContentProvider('commit', 'commit_refs');
                $found = false;
@@ -89,9 +242,14 @@ class page_commit {
                }
                $this->page->set('refs', ($found ? $refs : ""));
                
+               $difftree = new difftree();
+               $this->page->set('difftree', $difftree->generate_difftree($project, $commit, false));
+               
                return $this->page;
        }
        
+       
+       
 }
 
 ?>
\ No newline at end of file