]> git.ipfire.org Git - thirdparty/git.git/blame - lib/index.tcl
git-gui: remove 'no such variable' for s error when encounter unknown file states
[thirdparty/git.git] / lib / index.tcl
CommitLineData
f522c9b5
SP
1# git-gui index (add/remove) support
2# Copyright (C) 2006, 2007 Shawn Pearce
3
d4e890e5
SP
4proc _delete_indexlock {} {
5 if {[catch {file delete -- [gitdir index.lock]} err]} {
6 error_popup [strcat [mc "Unable to unlock the index."] "\n\n$err"]
7 }
8}
9
10proc _close_updateindex {fd after} {
c80d7be5 11 global use_ttk NS
d4e890e5
SP
12 fconfigure $fd -blocking 1
13 if {[catch {close $fd} err]} {
14 set w .indexfried
c80d7be5
PT
15 Dialog $w
16 wm withdraw $w
d4e890e5
SP
17 wm title $w [strcat "[appname] ([reponame]): " [mc "Index Error"]]
18 wm geometry $w "+[winfo rootx .]+[winfo rooty .]"
ea888f84
PT
19 set s [mc "Updating the Git index failed. A rescan will be automatically started to resynchronize git-gui."]
20 text $w.msg -yscrollcommand [list $w.vs set] \
21 -width [string length $s] -relief flat \
22 -borderwidth 0 -highlightthickness 0 \
c80d7be5 23 -background [get_bg_color $w]
ea888f84 24 $w.msg tag configure bold -font font_uibold -justify center
c80d7be5 25 ${NS}::scrollbar $w.vs -command [list $w.msg yview]
ea888f84
PT
26 $w.msg insert end $s bold \n\n$err {}
27 $w.msg configure -state disabled
28
c80d7be5 29 ${NS}::button $w.continue \
d4e890e5
SP
30 -text [mc "Continue"] \
31 -command [list destroy $w]
c80d7be5 32 ${NS}::button $w.unlock \
d4e890e5
SP
33 -text [mc "Unlock Index"] \
34 -command "destroy $w; _delete_indexlock"
ea888f84
PT
35 grid $w.msg - $w.vs -sticky news
36 grid $w.unlock $w.continue - -sticky se -padx 2 -pady 2
37 grid columnconfigure $w 0 -weight 1
38 grid rowconfigure $w 0 -weight 1
d4e890e5
SP
39
40 wm protocol $w WM_DELETE_WINDOW update
ea888f84 41 bind $w.continue <Visibility> "
d4e890e5 42 grab $w
ea888f84 43 focus %W
d4e890e5 44 "
c80d7be5 45 wm deiconify $w
d4e890e5
SP
46 tkwait window $w
47
48 $::main_status stop
49 unlock_index
50 rescan $after 0
51 return
52 }
53
f4e9996b 54 $::main_status stop
d4e890e5
SP
55 unlock_index
56 uplevel #0 $after
57}
58
f522c9b5 59proc update_indexinfo {msg pathList after} {
699d5601 60 global update_index_cp
f522c9b5
SP
61
62 if {![lock_index update]} return
63
64 set update_index_cp 0
65 set pathList [lsort $pathList]
66 set totalCnt [llength $pathList]
67 set batch [expr {int($totalCnt * .01) + 1}]
68 if {$batch > 25} {set batch 25}
69
1cad232f 70 $::main_status start $msg [mc "files"]
0b812616 71 set fd [git_write update-index -z --index-info]
f522c9b5
SP
72 fconfigure $fd \
73 -blocking 0 \
74 -buffering full \
75 -buffersize 512 \
76 -encoding binary \
77 -translation binary
78 fileevent $fd writable [list \
79 write_update_indexinfo \
80 $fd \
81 $pathList \
82 $totalCnt \
83 $batch \
f522c9b5
SP
84 $after \
85 ]
86}
87
1cad232f 88proc write_update_indexinfo {fd pathList totalCnt batch after} {
699d5601 89 global update_index_cp
f522c9b5
SP
90 global file_states current_diff_path
91
92 if {$update_index_cp >= $totalCnt} {
d4e890e5 93 _close_updateindex $fd $after
f522c9b5
SP
94 return
95 }
96
97 for {set i $batch} \
98 {$update_index_cp < $totalCnt && $i > 0} \
99 {incr i -1} {
100 set path [lindex $pathList $update_index_cp]
101 incr update_index_cp
102
103 set s $file_states($path)
104 switch -glob -- [lindex $s 0] {
105 A? {set new _O}
106 M? {set new _M}
e681cb7d 107 T_ {set new _T}
f522c9b5
SP
108 D_ {set new _D}
109 D? {set new _?}
110 ?? {continue}
111 }
112 set info [lindex $s 2]
113 if {$info eq {}} continue
114
115 puts -nonewline $fd "$info\t[encoding convertto $path]\0"
116 display_file $path $new
117 }
118
1cad232f 119 $::main_status update $update_index_cp $totalCnt
f522c9b5
SP
120}
121
122proc update_index {msg pathList after} {
699d5601 123 global update_index_cp
f522c9b5
SP
124
125 if {![lock_index update]} return
126
127 set update_index_cp 0
128 set pathList [lsort $pathList]
129 set totalCnt [llength $pathList]
130 set batch [expr {int($totalCnt * .01) + 1}]
131 if {$batch > 25} {set batch 25}
132
1cad232f 133 $::main_status start $msg [mc "files"]
0b812616 134 set fd [git_write update-index --add --remove -z --stdin]
f522c9b5
SP
135 fconfigure $fd \
136 -blocking 0 \
137 -buffering full \
138 -buffersize 512 \
139 -encoding binary \
140 -translation binary
141 fileevent $fd writable [list \
142 write_update_index \
143 $fd \
144 $pathList \
145 $totalCnt \
146 $batch \
f522c9b5
SP
147 $after \
148 ]
149}
150
1cad232f 151proc write_update_index {fd pathList totalCnt batch after} {
699d5601 152 global update_index_cp
f522c9b5
SP
153 global file_states current_diff_path
154
155 if {$update_index_cp >= $totalCnt} {
d4e890e5 156 _close_updateindex $fd $after
f522c9b5
SP
157 return
158 }
159
160 for {set i $batch} \
161 {$update_index_cp < $totalCnt && $i > 0} \
162 {incr i -1} {
163 set path [lindex $pathList $update_index_cp]
164 incr update_index_cp
165
166 switch -glob -- [lindex $file_states($path) 0] {
167 AD {set new __}
168 ?D {set new D_}
169 _O -
170 AM {set new A_}
e681cb7d 171 _T {set new T_}
ff515d81 172 _U -
f522c9b5
SP
173 U? {
174 if {[file exists $path]} {
175 set new M_
176 } else {
177 set new D_
178 }
179 }
180 ?M {set new M_}
181 ?? {continue}
182 }
183 puts -nonewline $fd "[encoding convertto $path]\0"
184 display_file $path $new
185 }
186
1cad232f 187 $::main_status update $update_index_cp $totalCnt
f522c9b5
SP
188}
189
190proc checkout_index {msg pathList after} {
699d5601 191 global update_index_cp
f522c9b5
SP
192
193 if {![lock_index update]} return
194
195 set update_index_cp 0
196 set pathList [lsort $pathList]
197 set totalCnt [llength $pathList]
198 set batch [expr {int($totalCnt * .01) + 1}]
199 if {$batch > 25} {set batch 25}
200
1cad232f 201 $::main_status start $msg [mc "files"]
0b812616
SP
202 set fd [git_write checkout-index \
203 --index \
204 --quiet \
205 --force \
206 -z \
207 --stdin \
208 ]
f522c9b5
SP
209 fconfigure $fd \
210 -blocking 0 \
211 -buffering full \
212 -buffersize 512 \
213 -encoding binary \
214 -translation binary
215 fileevent $fd writable [list \
216 write_checkout_index \
217 $fd \
218 $pathList \
219 $totalCnt \
220 $batch \
f522c9b5
SP
221 $after \
222 ]
223}
224
1cad232f 225proc write_checkout_index {fd pathList totalCnt batch after} {
699d5601 226 global update_index_cp
f522c9b5
SP
227 global file_states current_diff_path
228
229 if {$update_index_cp >= $totalCnt} {
d4e890e5 230 _close_updateindex $fd $after
f522c9b5
SP
231 return
232 }
233
234 for {set i $batch} \
235 {$update_index_cp < $totalCnt && $i > 0} \
236 {incr i -1} {
237 set path [lindex $pathList $update_index_cp]
238 incr update_index_cp
239 switch -glob -- [lindex $file_states($path) 0] {
240 U? {continue}
241 ?M -
e681cb7d 242 ?T -
f522c9b5
SP
243 ?D {
244 puts -nonewline $fd "[encoding convertto $path]\0"
245 display_file $path ?_
246 }
247 }
248 }
249
1cad232f 250 $::main_status update $update_index_cp $totalCnt
f522c9b5
SP
251}
252
253proc unstage_helper {txt paths} {
254 global file_states current_diff_path
255
256 if {![lock_index begin-update]} return
257
258 set pathList [list]
259 set after {}
260 foreach path $paths {
261 switch -glob -- [lindex $file_states($path) 0] {
262 A? -
263 M? -
e681cb7d 264 T_ -
f522c9b5
SP
265 D? {
266 lappend pathList $path
267 if {$path eq $current_diff_path} {
268 set after {reshow_diff;}
269 }
270 }
271 }
272 }
273 if {$pathList eq {}} {
274 unlock_index
275 } else {
276 update_indexinfo \
277 $txt \
278 $pathList \
699d5601 279 [concat $after [list ui_ready]]
f522c9b5
SP
280 }
281}
282
283proc do_unstage_selection {} {
284 global current_diff_path selected_paths
285
286 if {[array size selected_paths] > 0} {
287 unstage_helper \
288 {Unstaging selected files from commit} \
289 [array names selected_paths]
290 } elseif {$current_diff_path ne {}} {
291 unstage_helper \
c8c4854b 292 [mc "Unstaging %s from commit" [short_path $current_diff_path]] \
f522c9b5
SP
293 [list $current_diff_path]
294 }
295}
296
297proc add_helper {txt paths} {
298 global file_states current_diff_path
299
300 if {![lock_index begin-update]} return
301
302 set pathList [list]
303 set after {}
304 foreach path $paths {
305 switch -glob -- [lindex $file_states($path) 0] {
0aea2842
AG
306 _U -
307 U? {
308 if {$path eq $current_diff_path} {
309 unlock_index
310 merge_stage_workdir $path
311 return
312 }
313 }
f522c9b5
SP
314 _O -
315 ?M -
316 ?D -
0aea2842 317 ?T {
f522c9b5
SP
318 lappend pathList $path
319 if {$path eq $current_diff_path} {
320 set after {reshow_diff;}
321 }
322 }
323 }
324 }
325 if {$pathList eq {}} {
326 unlock_index
327 } else {
328 update_index \
329 $txt \
330 $pathList \
5e6d7768 331 [concat $after {ui_status [mc "Ready to commit."]}]
f522c9b5
SP
332 }
333}
334
335proc do_add_selection {} {
336 global current_diff_path selected_paths
337
338 if {[array size selected_paths] > 0} {
339 add_helper \
340 {Adding selected files} \
341 [array names selected_paths]
342 } elseif {$current_diff_path ne {}} {
343 add_helper \
c8c4854b 344 [mc "Adding %s" [short_path $current_diff_path]] \
f522c9b5
SP
345 [list $current_diff_path]
346 }
347}
348
349proc do_add_all {} {
350 global file_states
351
352 set paths [list]
353 foreach path [array names file_states] {
354 switch -glob -- [lindex $file_states($path) 0] {
355 U? {continue}
356 ?M -
e681cb7d 357 ?T -
f522c9b5
SP
358 ?D {lappend paths $path}
359 }
360 }
361 add_helper {Adding all changed files} $paths
362}
363
364proc revert_helper {txt paths} {
365 global file_states current_diff_path
366
367 if {![lock_index begin-update]} return
368
369 set pathList [list]
370 set after {}
371 foreach path $paths {
372 switch -glob -- [lindex $file_states($path) 0] {
373 U? {continue}
374 ?M -
e681cb7d 375 ?T -
f522c9b5
SP
376 ?D {
377 lappend pathList $path
378 if {$path eq $current_diff_path} {
379 set after {reshow_diff;}
380 }
381 }
382 }
383 }
384
1ac17950
CS
385
386 # Split question between singular and plural cases, because
387 # such distinction is needed in some languages. Previously, the
388 # code used "Revert changes in" for both, but that can't work
389 # in languages where 'in' must be combined with word from
390 # rest of string (in diffrent way for both cases of course).
391 #
392 # FIXME: Unfortunately, even that isn't enough in some languages
393 # as they have quite complex plural-form rules. Unfortunately,
394 # msgcat doesn't seem to support that kind of string translation.
395 #
f522c9b5
SP
396 set n [llength $pathList]
397 if {$n == 0} {
398 unlock_index
399 return
400 } elseif {$n == 1} {
1ac17950 401 set query [mc "Revert changes in file %s?" [short_path [lindex $pathList]]]
f522c9b5 402 } else {
1ac17950 403 set query [mc "Revert changes in these %i files?" $n]
f522c9b5
SP
404 }
405
406 set reply [tk_dialog \
407 .confirm_revert \
408 "[appname] ([reponame])" \
d4544601
CS
409 "$query
410
411[mc "Any unstaged changes will be permanently lost by the revert."]" \
f522c9b5
SP
412 question \
413 1 \
1ac17950
CS
414 [mc "Do Nothing"] \
415 [mc "Revert Changes"] \
f522c9b5
SP
416 ]
417 if {$reply == 1} {
418 checkout_index \
419 $txt \
420 $pathList \
699d5601 421 [concat $after [list ui_ready]]
f522c9b5
SP
422 } else {
423 unlock_index
424 }
425}
426
427proc do_revert_selection {} {
428 global current_diff_path selected_paths
429
430 if {[array size selected_paths] > 0} {
431 revert_helper \
700e5603 432 [mc "Reverting selected files"] \
f522c9b5
SP
433 [array names selected_paths]
434 } elseif {$current_diff_path ne {}} {
435 revert_helper \
700e5603 436 [mc "Reverting %s" [short_path $current_diff_path]] \
f522c9b5
SP
437 [list $current_diff_path]
438 }
439}
440
441proc do_select_commit_type {} {
442 global commit_type selected_commit_type
443
444 if {$selected_commit_type eq {new}
445 && [string match amend* $commit_type]} {
446 create_new_commit
447 } elseif {$selected_commit_type eq {amend}
448 && ![string match amend* $commit_type]} {
449 load_last_commit
450
451 # The amend request was rejected...
452 #
453 if {![string match amend* $commit_type]} {
454 set selected_commit_type new
455 }
456 }
457}