]> rtime.felk.cvut.cz Git - git.git/blob - git-gui/lib/index.tcl
Merge branch 'maint' of git://repo.or.cz/git-gui into maint
[git.git] / git-gui / lib / index.tcl
1 # git-gui index (add/remove) support
2 # Copyright (C) 2006, 2007 Shawn Pearce
3
4 proc update_indexinfo {msg pathList after} {
5         global update_index_cp
6
7         if {![lock_index update]} return
8
9         set update_index_cp 0
10         set pathList [lsort $pathList]
11         set totalCnt [llength $pathList]
12         set batch [expr {int($totalCnt * .01) + 1}]
13         if {$batch > 25} {set batch 25}
14
15         ui_status [format \
16                 "%s... %i/%i files (%.2f%%)" \
17                 $msg \
18                 $update_index_cp \
19                 $totalCnt \
20                 0.0]
21         set fd [git_write update-index -z --index-info]
22         fconfigure $fd \
23                 -blocking 0 \
24                 -buffering full \
25                 -buffersize 512 \
26                 -encoding binary \
27                 -translation binary
28         fileevent $fd writable [list \
29                 write_update_indexinfo \
30                 $fd \
31                 $pathList \
32                 $totalCnt \
33                 $batch \
34                 $msg \
35                 $after \
36                 ]
37 }
38
39 proc write_update_indexinfo {fd pathList totalCnt batch msg after} {
40         global update_index_cp
41         global file_states current_diff_path
42
43         if {$update_index_cp >= $totalCnt} {
44                 close $fd
45                 unlock_index
46                 uplevel #0 $after
47                 return
48         }
49
50         for {set i $batch} \
51                 {$update_index_cp < $totalCnt && $i > 0} \
52                 {incr i -1} {
53                 set path [lindex $pathList $update_index_cp]
54                 incr update_index_cp
55
56                 set s $file_states($path)
57                 switch -glob -- [lindex $s 0] {
58                 A? {set new _O}
59                 M? {set new _M}
60                 D_ {set new _D}
61                 D? {set new _?}
62                 ?? {continue}
63                 }
64                 set info [lindex $s 2]
65                 if {$info eq {}} continue
66
67                 puts -nonewline $fd "$info\t[encoding convertto $path]\0"
68                 display_file $path $new
69         }
70
71         ui_status [format \
72                 "%s... %i/%i files (%.2f%%)" \
73                 $msg \
74                 $update_index_cp \
75                 $totalCnt \
76                 [expr {100.0 * $update_index_cp / $totalCnt}]]
77 }
78
79 proc update_index {msg pathList after} {
80         global update_index_cp
81
82         if {![lock_index update]} return
83
84         set update_index_cp 0
85         set pathList [lsort $pathList]
86         set totalCnt [llength $pathList]
87         set batch [expr {int($totalCnt * .01) + 1}]
88         if {$batch > 25} {set batch 25}
89
90         ui_status [format \
91                 "%s... %i/%i files (%.2f%%)" \
92                 $msg \
93                 $update_index_cp \
94                 $totalCnt \
95                 0.0]
96         set fd [git_write update-index --add --remove -z --stdin]
97         fconfigure $fd \
98                 -blocking 0 \
99                 -buffering full \
100                 -buffersize 512 \
101                 -encoding binary \
102                 -translation binary
103         fileevent $fd writable [list \
104                 write_update_index \
105                 $fd \
106                 $pathList \
107                 $totalCnt \
108                 $batch \
109                 $msg \
110                 $after \
111                 ]
112 }
113
114 proc write_update_index {fd pathList totalCnt batch msg after} {
115         global update_index_cp
116         global file_states current_diff_path
117
118         if {$update_index_cp >= $totalCnt} {
119                 close $fd
120                 unlock_index
121                 uplevel #0 $after
122                 return
123         }
124
125         for {set i $batch} \
126                 {$update_index_cp < $totalCnt && $i > 0} \
127                 {incr i -1} {
128                 set path [lindex $pathList $update_index_cp]
129                 incr update_index_cp
130
131                 switch -glob -- [lindex $file_states($path) 0] {
132                 AD {set new __}
133                 ?D {set new D_}
134                 _O -
135                 AM {set new A_}
136                 U? {
137                         if {[file exists $path]} {
138                                 set new M_
139                         } else {
140                                 set new D_
141                         }
142                 }
143                 ?M {set new M_}
144                 ?? {continue}
145                 }
146                 puts -nonewline $fd "[encoding convertto $path]\0"
147                 display_file $path $new
148         }
149
150         ui_status [format \
151                 "%s... %i/%i files (%.2f%%)" \
152                 $msg \
153                 $update_index_cp \
154                 $totalCnt \
155                 [expr {100.0 * $update_index_cp / $totalCnt}]]
156 }
157
158 proc checkout_index {msg pathList after} {
159         global update_index_cp
160
161         if {![lock_index update]} return
162
163         set update_index_cp 0
164         set pathList [lsort $pathList]
165         set totalCnt [llength $pathList]
166         set batch [expr {int($totalCnt * .01) + 1}]
167         if {$batch > 25} {set batch 25}
168
169         ui_status [format \
170                 "%s... %i/%i files (%.2f%%)" \
171                 $msg \
172                 $update_index_cp \
173                 $totalCnt \
174                 0.0]
175         set fd [git_write checkout-index \
176                 --index \
177                 --quiet \
178                 --force \
179                 -z \
180                 --stdin \
181                 ]
182         fconfigure $fd \
183                 -blocking 0 \
184                 -buffering full \
185                 -buffersize 512 \
186                 -encoding binary \
187                 -translation binary
188         fileevent $fd writable [list \
189                 write_checkout_index \
190                 $fd \
191                 $pathList \
192                 $totalCnt \
193                 $batch \
194                 $msg \
195                 $after \
196                 ]
197 }
198
199 proc write_checkout_index {fd pathList totalCnt batch msg after} {
200         global update_index_cp
201         global file_states current_diff_path
202
203         if {$update_index_cp >= $totalCnt} {
204                 close $fd
205                 unlock_index
206                 uplevel #0 $after
207                 return
208         }
209
210         for {set i $batch} \
211                 {$update_index_cp < $totalCnt && $i > 0} \
212                 {incr i -1} {
213                 set path [lindex $pathList $update_index_cp]
214                 incr update_index_cp
215                 switch -glob -- [lindex $file_states($path) 0] {
216                 U? {continue}
217                 ?M -
218                 ?D {
219                         puts -nonewline $fd "[encoding convertto $path]\0"
220                         display_file $path ?_
221                 }
222                 }
223         }
224
225         ui_status [format \
226                 "%s... %i/%i files (%.2f%%)" \
227                 $msg \
228                 $update_index_cp \
229                 $totalCnt \
230                 [expr {100.0 * $update_index_cp / $totalCnt}]]
231 }
232
233 proc unstage_helper {txt paths} {
234         global file_states current_diff_path
235
236         if {![lock_index begin-update]} return
237
238         set pathList [list]
239         set after {}
240         foreach path $paths {
241                 switch -glob -- [lindex $file_states($path) 0] {
242                 A? -
243                 M? -
244                 D? {
245                         lappend pathList $path
246                         if {$path eq $current_diff_path} {
247                                 set after {reshow_diff;}
248                         }
249                 }
250                 }
251         }
252         if {$pathList eq {}} {
253                 unlock_index
254         } else {
255                 update_indexinfo \
256                         $txt \
257                         $pathList \
258                         [concat $after [list ui_ready]]
259         }
260 }
261
262 proc do_unstage_selection {} {
263         global current_diff_path selected_paths
264
265         if {[array size selected_paths] > 0} {
266                 unstage_helper \
267                         {Unstaging selected files from commit} \
268                         [array names selected_paths]
269         } elseif {$current_diff_path ne {}} {
270                 unstage_helper \
271                         "Unstaging [short_path $current_diff_path] from commit" \
272                         [list $current_diff_path]
273         }
274 }
275
276 proc add_helper {txt paths} {
277         global file_states current_diff_path
278
279         if {![lock_index begin-update]} return
280
281         set pathList [list]
282         set after {}
283         foreach path $paths {
284                 switch -glob -- [lindex $file_states($path) 0] {
285                 _O -
286                 ?M -
287                 ?D -
288                 U? {
289                         lappend pathList $path
290                         if {$path eq $current_diff_path} {
291                                 set after {reshow_diff;}
292                         }
293                 }
294                 }
295         }
296         if {$pathList eq {}} {
297                 unlock_index
298         } else {
299                 update_index \
300                         $txt \
301                         $pathList \
302                         [concat $after {ui_status {Ready to commit.}}]
303         }
304 }
305
306 proc do_add_selection {} {
307         global current_diff_path selected_paths
308
309         if {[array size selected_paths] > 0} {
310                 add_helper \
311                         {Adding selected files} \
312                         [array names selected_paths]
313         } elseif {$current_diff_path ne {}} {
314                 add_helper \
315                         "Adding [short_path $current_diff_path]" \
316                         [list $current_diff_path]
317         }
318 }
319
320 proc do_add_all {} {
321         global file_states
322
323         set paths [list]
324         foreach path [array names file_states] {
325                 switch -glob -- [lindex $file_states($path) 0] {
326                 U? {continue}
327                 ?M -
328                 ?D {lappend paths $path}
329                 }
330         }
331         add_helper {Adding all changed files} $paths
332 }
333
334 proc revert_helper {txt paths} {
335         global file_states current_diff_path
336
337         if {![lock_index begin-update]} return
338
339         set pathList [list]
340         set after {}
341         foreach path $paths {
342                 switch -glob -- [lindex $file_states($path) 0] {
343                 U? {continue}
344                 ?M -
345                 ?D {
346                         lappend pathList $path
347                         if {$path eq $current_diff_path} {
348                                 set after {reshow_diff;}
349                         }
350                 }
351                 }
352         }
353
354         set n [llength $pathList]
355         if {$n == 0} {
356                 unlock_index
357                 return
358         } elseif {$n == 1} {
359                 set s "[short_path [lindex $pathList]]"
360         } else {
361                 set s "these $n files"
362         }
363
364         set reply [tk_dialog \
365                 .confirm_revert \
366                 "[appname] ([reponame])" \
367                 "Revert changes in $s?
368
369 Any unstaged changes will be permanently lost by the revert." \
370                 question \
371                 1 \
372                 {Do Nothing} \
373                 {Revert Changes} \
374                 ]
375         if {$reply == 1} {
376                 checkout_index \
377                         $txt \
378                         $pathList \
379                         [concat $after [list ui_ready]]
380         } else {
381                 unlock_index
382         }
383 }
384
385 proc do_revert_selection {} {
386         global current_diff_path selected_paths
387
388         if {[array size selected_paths] > 0} {
389                 revert_helper \
390                         {Reverting selected files} \
391                         [array names selected_paths]
392         } elseif {$current_diff_path ne {}} {
393                 revert_helper \
394                         "Reverting [short_path $current_diff_path]" \
395                         [list $current_diff_path]
396         }
397 }
398
399 proc do_select_commit_type {} {
400         global commit_type selected_commit_type
401
402         if {$selected_commit_type eq {new}
403                 && [string match amend* $commit_type]} {
404                 create_new_commit
405         } elseif {$selected_commit_type eq {amend}
406                 && ![string match amend* $commit_type]} {
407                 load_last_commit
408
409                 # The amend request was rejected...
410                 #
411                 if {![string match amend* $commit_type]} {
412                         set selected_commit_type new
413                 }
414         }
415 }