some changes ...
[phpgitweb.git] / htdocs / lib / PageClasses.difftree.class.php
1 <?php
2 /* PageClasses.difftree.class.php - phpgitweb
3  * Copyright (C) 2011-2012  Philipp Kreil (pk910)
4  * 
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.
9  * 
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.
14  * 
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/>. 
17  */
18
19 class difftree {
20         private $difftree_data = null;
21         
22         public function push_difftree_data($data) {
23                 $this->difftree_data = $data;
24         }
25         
26         public function generate_difftree($project, $commit, $patch_link) {
27                 $difftree = new ContentProvider('commit', 'difftree');
28                 if($this->difftree_data)
29                         $tree = $this->difftree_data;
30                 else
31                         $tree = GitCommand::get_commit_changes($project['path'], $commit['id'], $commit['parent']);
32                 $entry_count = 0;
33                 if(count($commit['parent']) > 1)
34                         $difftree->set('class', ' combined');
35                 else
36                         $difftree->set('class', '');
37                 $difftree->set('tree_count', '');
38                 foreach($tree as $entry) {
39                         $entry_count++;
40                         $difftree->append('tree', $this->tree_entry($entry_count, (($entry_count % 2) ? 'dark' : 'light'), $commit, $entry, $patch_link));
41                 }
42                 if($entry_count == 0)
43                         $difftree->set('tree', '');
44                 else if($entry_count > 10)
45                         $difftree->set('tree_count', new ContentProvider('commit', 'tree_count', array('count' => $entry_count)));
46                 return $difftree;
47         }
48         
49         private function tree_entry($diffid, $class, $commit, $entry, $patch_link) {
50                 $tree = new ContentProvider('commit', 'tree');
51                 $tree->set('class', $class);
52                 $tree->set('hash', $commit['id']);
53                 $tree->set('file', $entry['file']);
54                 $tree->set('file_hash', $entry['to_id']);
55                 
56                 if(count($commit['parent']) > 1) {
57                         if(preg_match('/^[0]{40}$/', $entry['to_id'])) //file doesn't exist in the result (child) commit
58                                 $tree->set('file', $entry['file']);
59                         else
60                                 $tree->set('file', new ContentProvider('commit', 'tree_file_link', array('file' => $entry['file'], 'file_hash' => $entry['to_id'])));
61                         
62                         $tree->set('specials', '');
63                         
64                         if($patch_link)
65                                 $tree->append('merge', new ContentProvider('commit', 'tree_merge_patch_link', array("patch_marker" => "patch".$diffid)));
66                         
67                         $has_history = false;
68                         $not_deleted = false;
69                         
70                         for($i = 0; $i < count($commit['parent']); $i++) {
71                                 $status = $entry['status'][$i];
72                                 $merge = null;
73                                 
74                                 $has_history = ($has_history || ($status != 'A'));
75                                 $not_deleted = ($not_deleted || ($status != 'D'));
76                                 
77                                 switch($status) {
78                                 case 'A': //Added
79                                         $merge = new ContentProvider('commit', 'tree_merge_new');
80                                         break;
81                                 case 'D': //Deleted
82                                         $merge = new ContentProvider('commit', 'tree_merge');
83                                         $merge->set('class', '');
84                                         $blob_link = new ContentProvider('commit', 'tree_merge_blob', array('hash' => $commit['parent'][$i], 'file' => $entry['file'], 'file_hash' => $entry['to_id']));
85                                         $merge->set('links', array($blob_link, ' | '));
86                                         break;
87                                 default:
88                                         $merge = new ContentProvider('commit', 'tree_merge');
89                                         if($entry['from_id'][$i] == $entry['to_id']) {
90                                                 $merge->set('class', ' nochange');
91                                                 $merge->set('links', ' | ');
92                                         } else {
93                                                 $merge->set('class', '');
94                                                 $params = array(
95                                                                         'hash' => $commit['id'], 
96                                                                         'parent' => $commit['parent'][$i], 
97                                                                         'file' => $entry['file'], 
98                                                                         'file_hash' => $entry['to_id'],
99                                                                         'parent_file_hash' => $entry['from_id'][$i],
100                                                                         'id' => ($i + 1)
101                                                                 );
102                                                 $merge->set('links', new ContentProvider('commit', 'tree_merge_diff', $params));
103                                         }
104                                 }
105                                 $tree->append('merge', $merge);
106                         }
107                         
108                         $tree->set('links', '');
109                         if($not_deleted) {
110                                 $tree->append('links', new ContentProvider('commit', 'tree_merge_blob', array('hash' => $commit['id'], 'file' => $entry['file'], 'file_hash' => $entry['to_id'])));
111                                 if($has_history)
112                                         $tree->append('links', ' | ');
113                         }
114                         if($has_history)
115                                 $tree->append('links', new ContentProvider('commit', 'tree_merge_history', array('hash' => $commit['id'], 'file' => $entry['file'], 'file_hash' => $entry['to_id'])));
116                         
117                 } else {
118                         $tree->set('file', new ContentProvider('commit', 'tree_file_link', array('file' => $entry['to_file'], 'file_hash' => $entry['to_id'])));
119                         $tree->set('merge', '');
120                         
121                         $from_type = Tools::get_filetype($entry['from_mode']);
122                         $to_type = Tools::get_filetype($entry['to_mode']);
123                         
124                         $from_mode = (Tools::is_regular_file($entry['from_mode']) ? Tools::get_file_permissions($entry['from_mode']) : null);
125                         $to_mode = (Tools::is_regular_file($entry['to_mode']) ? Tools::get_file_permissions($entry['to_mode']) : null);
126                         
127                         $link_placeholders = array(
128                                         "hash" => $commit['id'],
129                                         "file" => $entry['file'],
130                                         "file_hash"     => $entry['to_id'],
131                                         "parent_file_hash"      => $entry['from_id'],
132                                         "parent" => (count($commit['parent']) ? $commit['parent'][0] : ""),
133                                 );
134                         if($patch_link)
135                                 $tree->append('links', new ContentProvider('commit', 'tree_patch_link', array("patch_marker" => "patch".$diffid)));
136                         
137                         switch($entry['status']) {
138                         case 'A': //Added
139                                 $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)));
140                                 $tree->append('links', new ContentProvider('commit', 'tree_new_links', $link_placeholders));
141                                 break;
142                         case 'D': //Deleted
143                                 $tree->set('specials', new ContentProvider('commit', 'tree_deleted', array('type' => $from_type)));
144                                 $tree->append('links', new ContentProvider('commit', 'tree_deleted_links', $link_placeholders));
145                                 break;
146                         case 'M': //Modified
147                         case 'T': //Type changed
148                                 if($entry['from_mode'] != $entry['to_mode']) {
149                                         $modified = new ContentProvider('commit', 'tree_changed');
150                                         $tree->set('specials', $modified);
151                                         if($from_type != $to_type)
152                                                 $modified->append('changes', new ContentProvider('commit', 'tree_changed_type', array('from' => $from_type, 'to' => $to_type)));
153                                         if($from_mode != $to_mode && $to_mode) {
154                                                 if($from_mode)
155                                                         $modified->append('changes', new ContentProvider('commit', 'tree_changed_mode', array('from' => $from_mode, 'to' => $to_mode)));
156                                                 else
157                                                         $modified->append('changes', new ContentProvider('commit', 'tree_changed_mode_to', array('to' => $to_mode)));
158                                         }
159                                 } else
160                                         $tree->set('specials', '');
161                                 if(!$patch_link && $entry['from_id'] != $entry['to_id'])
162                                         $tree->append('links', new ContentProvider('commit', 'tree_changed_links_diff', $link_placeholders));
163                                 $tree->append('links', new ContentProvider('commit', 'tree_changed_links', $link_placeholders));
164                                 break;
165                         case 'R': //Renamed
166                         case 'C': //Copied
167                                 $actions = array('R' => 'tree_moved', 'C' => 'tree_copied');
168                                 $move = new ContentProvider('commit', $actions[$entry['status']]);
169                                 $tree->set('specials', $move);
170                                 $move->set('file', $entry['from_file']);
171                                 $move->set('file_hash', $entry['to_id']);
172                                 $move->set('hash', $commit['parent'][0]);
173                                 $move->set('similarity', $entry['similarity']);
174                                 if($from_mode != $to_mode)
175                                         $move->set('mode', new ContentProvider('commit', 'tree_moved_mode', array('mode' => $to_mode)));
176                                 else
177                                         $move->set('mode', '');
178                                 if($entry['from_id'] != $entry['to_id'])
179                                         $tree->append('links', new ContentProvider('commit', 'tree_moved_links_diff', $link_placeholders));
180                                 $tree->append('links', new ContentProvider('commit', 'tree_moved_links', $link_placeholders));
181                                 break;
182                         default:
183                                 
184                         }
185                         
186                 }
187                 return $tree;
188         }
189         
190 }
191
192 ?>