3eae308700
-----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQIcBAABCAAGBQJYCJqmAAoJEDn3Aot9nM55uKQP/11BTzhOr9K3SLzwCr01ylGP 94AOA511vx3fIX5aWQ29S96tGbluo73RdbVsWFKKJcKSErpFPscFEiRkyjeMXE2T yWWOPOg08tm28ppZNp0Kqjb8VykUUKuG6gVT59DNFUZUqHYQbiQy+t8nwT+Qow3U dvo6lksovfSaW2FORWIi5KF5gD4v2F9qsbFgr725a8UoBrOmF0SWaCG4/ZYj0WxF 0rq8LjpvmMuQqd06DAoGMIsHa71R61En2QWfJ4YoE5+QRq8wQl37FmX+ojiA1rzY CG/vJO2Tw4v54wHKK1TCXG7LR4JhTcQZOa6zd8HHsPRn+viGDCMVUG9uMewfxH+m F47EVMxiKf0subm3fUhycqkvso0r6mOAddhz47RKT7tqU4XOnhPyGw0x6m7evawg Sz2+fOK3wwX2Qec5o3vBZKaEcOftSrLuZmbi5/j43crvcf+OAs9s/jdq/Ulpkks2 JI2i0DLzHABTbDn6QsuysEZnituks8T8Fdm5NOldritgBNVY81ifatekFscxt6Ct OrT9eGJk6iZiX1RvS+R7wykKJCBkxiyHqM8vSj5tPWjApgtnopPMudzNX41geaL9 ADeb8LVMTTNL/md8KED0deypilcPNnPbW035rAbyCpAsKbtgO3zdfzdzxsQ+dIvc MQpCDP5QPPr3toRVdNmb =VyhL -----END PGP SIGNATURE----- Merge tag 'gitgui-0.21.0' of git://repo.or.cz/git-gui git-gui 0.21.0 * tag 'gitgui-0.21.0' of git://repo.or.cz/git-gui: (22 commits) git-gui: set version 0.21 git-gui: Mark 'All' in remote.tcl for translation git-gui i18n: Updated Bulgarian translation (565,0f,0u) git-gui: avoid persisting modified author identity git-gui: handle the encoding of Git's output correctly git-gui: unicode file name support on windows git-gui: Update Russian translation git-gui: maintain backwards compatibility for merge syntax git-gui i18n: mark string in lib/error.tcl for translation git-gui: fix incorrect use of Tcl append command git-gui i18n: mark "usage:" strings for translation git-gui i18n: internationalize use of colon punctuation git-gui: ensure the file in the diff pane is in the list of selected files git-gui: support for $FILENAMES in tool definitions git-gui: fix initial git gui message encoding git-gui/po/glossary/txt-to-pot.sh: use the $( ... ) construct for command substitution git-gui (Windows): use git-gui.exe in `Create Desktop Shortcut` git-gui: fix detection of Cygwin Amend tab ordering and text widget border and highlighting. Allow keyboard control to work in the staging widgets. ...
485 lines
10 KiB
Tcl
485 lines
10 KiB
Tcl
# git-gui index (add/remove) support
|
|
# Copyright (C) 2006, 2007 Shawn Pearce
|
|
|
|
proc _delete_indexlock {} {
|
|
if {[catch {file delete -- [gitdir index.lock]} err]} {
|
|
error_popup [strcat [mc "Unable to unlock the index."] "\n\n$err"]
|
|
}
|
|
}
|
|
|
|
proc _close_updateindex {fd after} {
|
|
global use_ttk NS
|
|
fconfigure $fd -blocking 1
|
|
if {[catch {close $fd} err]} {
|
|
set w .indexfried
|
|
Dialog $w
|
|
wm withdraw $w
|
|
wm title $w [strcat "[appname] ([reponame]): " [mc "Index Error"]]
|
|
wm geometry $w "+[winfo rootx .]+[winfo rooty .]"
|
|
set s [mc "Updating the Git index failed. A rescan will be automatically started to resynchronize git-gui."]
|
|
text $w.msg -yscrollcommand [list $w.vs set] \
|
|
-width [string length $s] -relief flat \
|
|
-borderwidth 0 -highlightthickness 0 \
|
|
-background [get_bg_color $w]
|
|
$w.msg tag configure bold -font font_uibold -justify center
|
|
${NS}::scrollbar $w.vs -command [list $w.msg yview]
|
|
$w.msg insert end $s bold \n\n$err {}
|
|
$w.msg configure -state disabled
|
|
|
|
${NS}::button $w.continue \
|
|
-text [mc "Continue"] \
|
|
-command [list destroy $w]
|
|
${NS}::button $w.unlock \
|
|
-text [mc "Unlock Index"] \
|
|
-command "destroy $w; _delete_indexlock"
|
|
grid $w.msg - $w.vs -sticky news
|
|
grid $w.unlock $w.continue - -sticky se -padx 2 -pady 2
|
|
grid columnconfigure $w 0 -weight 1
|
|
grid rowconfigure $w 0 -weight 1
|
|
|
|
wm protocol $w WM_DELETE_WINDOW update
|
|
bind $w.continue <Visibility> "
|
|
grab $w
|
|
focus %W
|
|
"
|
|
wm deiconify $w
|
|
tkwait window $w
|
|
|
|
$::main_status stop
|
|
unlock_index
|
|
rescan $after 0
|
|
return
|
|
}
|
|
|
|
$::main_status stop
|
|
unlock_index
|
|
uplevel #0 $after
|
|
}
|
|
|
|
proc update_indexinfo {msg pathList after} {
|
|
global update_index_cp
|
|
|
|
if {![lock_index update]} return
|
|
|
|
set update_index_cp 0
|
|
set pathList [lsort $pathList]
|
|
set totalCnt [llength $pathList]
|
|
set batch [expr {int($totalCnt * .01) + 1}]
|
|
if {$batch > 25} {set batch 25}
|
|
|
|
$::main_status start $msg [mc "files"]
|
|
set fd [git_write update-index -z --index-info]
|
|
fconfigure $fd \
|
|
-blocking 0 \
|
|
-buffering full \
|
|
-buffersize 512 \
|
|
-encoding binary \
|
|
-translation binary
|
|
fileevent $fd writable [list \
|
|
write_update_indexinfo \
|
|
$fd \
|
|
$pathList \
|
|
$totalCnt \
|
|
$batch \
|
|
$after \
|
|
]
|
|
}
|
|
|
|
proc write_update_indexinfo {fd pathList totalCnt batch after} {
|
|
global update_index_cp
|
|
global file_states current_diff_path
|
|
|
|
if {$update_index_cp >= $totalCnt} {
|
|
_close_updateindex $fd $after
|
|
return
|
|
}
|
|
|
|
for {set i $batch} \
|
|
{$update_index_cp < $totalCnt && $i > 0} \
|
|
{incr i -1} {
|
|
set path [lindex $pathList $update_index_cp]
|
|
incr update_index_cp
|
|
|
|
set s $file_states($path)
|
|
switch -glob -- [lindex $s 0] {
|
|
A? {set new _O}
|
|
MT -
|
|
TM -
|
|
T_ {set new _T}
|
|
M? {set new _M}
|
|
TD -
|
|
D_ {set new _D}
|
|
D? {set new _?}
|
|
?? {continue}
|
|
}
|
|
set info [lindex $s 2]
|
|
if {$info eq {}} continue
|
|
|
|
puts -nonewline $fd "$info\t[encoding convertto utf-8 $path]\0"
|
|
display_file $path $new
|
|
}
|
|
|
|
$::main_status update $update_index_cp $totalCnt
|
|
}
|
|
|
|
proc update_index {msg pathList after} {
|
|
global update_index_cp
|
|
|
|
if {![lock_index update]} return
|
|
|
|
set update_index_cp 0
|
|
set pathList [lsort $pathList]
|
|
set totalCnt [llength $pathList]
|
|
set batch [expr {int($totalCnt * .01) + 1}]
|
|
if {$batch > 25} {set batch 25}
|
|
|
|
$::main_status start $msg [mc "files"]
|
|
set fd [git_write update-index --add --remove -z --stdin]
|
|
fconfigure $fd \
|
|
-blocking 0 \
|
|
-buffering full \
|
|
-buffersize 512 \
|
|
-encoding binary \
|
|
-translation binary
|
|
fileevent $fd writable [list \
|
|
write_update_index \
|
|
$fd \
|
|
$pathList \
|
|
$totalCnt \
|
|
$batch \
|
|
$after \
|
|
]
|
|
}
|
|
|
|
proc write_update_index {fd pathList totalCnt batch after} {
|
|
global update_index_cp
|
|
global file_states current_diff_path
|
|
|
|
if {$update_index_cp >= $totalCnt} {
|
|
_close_updateindex $fd $after
|
|
return
|
|
}
|
|
|
|
for {set i $batch} \
|
|
{$update_index_cp < $totalCnt && $i > 0} \
|
|
{incr i -1} {
|
|
set path [lindex $pathList $update_index_cp]
|
|
incr update_index_cp
|
|
|
|
switch -glob -- [lindex $file_states($path) 0] {
|
|
AD {set new __}
|
|
?D {set new D_}
|
|
_O -
|
|
AT -
|
|
AM {set new A_}
|
|
TM -
|
|
MT -
|
|
_T {set new T_}
|
|
_U -
|
|
U? {
|
|
if {[file exists $path]} {
|
|
set new M_
|
|
} else {
|
|
set new D_
|
|
}
|
|
}
|
|
?M {set new M_}
|
|
?? {continue}
|
|
}
|
|
puts -nonewline $fd "[encoding convertto utf-8 $path]\0"
|
|
display_file $path $new
|
|
}
|
|
|
|
$::main_status update $update_index_cp $totalCnt
|
|
}
|
|
|
|
proc checkout_index {msg pathList after} {
|
|
global update_index_cp
|
|
|
|
if {![lock_index update]} return
|
|
|
|
set update_index_cp 0
|
|
set pathList [lsort $pathList]
|
|
set totalCnt [llength $pathList]
|
|
set batch [expr {int($totalCnt * .01) + 1}]
|
|
if {$batch > 25} {set batch 25}
|
|
|
|
$::main_status start $msg [mc "files"]
|
|
set fd [git_write checkout-index \
|
|
--index \
|
|
--quiet \
|
|
--force \
|
|
-z \
|
|
--stdin \
|
|
]
|
|
fconfigure $fd \
|
|
-blocking 0 \
|
|
-buffering full \
|
|
-buffersize 512 \
|
|
-encoding binary \
|
|
-translation binary
|
|
fileevent $fd writable [list \
|
|
write_checkout_index \
|
|
$fd \
|
|
$pathList \
|
|
$totalCnt \
|
|
$batch \
|
|
$after \
|
|
]
|
|
}
|
|
|
|
proc write_checkout_index {fd pathList totalCnt batch after} {
|
|
global update_index_cp
|
|
global file_states current_diff_path
|
|
|
|
if {$update_index_cp >= $totalCnt} {
|
|
_close_updateindex $fd $after
|
|
return
|
|
}
|
|
|
|
for {set i $batch} \
|
|
{$update_index_cp < $totalCnt && $i > 0} \
|
|
{incr i -1} {
|
|
set path [lindex $pathList $update_index_cp]
|
|
incr update_index_cp
|
|
switch -glob -- [lindex $file_states($path) 0] {
|
|
U? {continue}
|
|
?M -
|
|
?T -
|
|
?D {
|
|
puts -nonewline $fd "[encoding convertto utf-8 $path]\0"
|
|
display_file $path ?_
|
|
}
|
|
}
|
|
}
|
|
|
|
$::main_status update $update_index_cp $totalCnt
|
|
}
|
|
|
|
proc unstage_helper {txt paths} {
|
|
global file_states current_diff_path
|
|
|
|
if {![lock_index begin-update]} return
|
|
|
|
set pathList [list]
|
|
set after {}
|
|
foreach path $paths {
|
|
switch -glob -- [lindex $file_states($path) 0] {
|
|
A? -
|
|
M? -
|
|
T? -
|
|
D? {
|
|
lappend pathList $path
|
|
if {$path eq $current_diff_path} {
|
|
set after {reshow_diff;}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if {$pathList eq {}} {
|
|
unlock_index
|
|
} else {
|
|
update_indexinfo \
|
|
$txt \
|
|
$pathList \
|
|
[concat $after [list ui_ready]]
|
|
}
|
|
}
|
|
|
|
proc do_unstage_selection {} {
|
|
global current_diff_path selected_paths
|
|
|
|
if {[array size selected_paths] > 0} {
|
|
unstage_helper \
|
|
[mc "Unstaging selected files from commit"] \
|
|
[array names selected_paths]
|
|
} elseif {$current_diff_path ne {}} {
|
|
unstage_helper \
|
|
[mc "Unstaging %s from commit" [short_path $current_diff_path]] \
|
|
[list $current_diff_path]
|
|
}
|
|
}
|
|
|
|
proc add_helper {txt paths} {
|
|
global file_states current_diff_path
|
|
|
|
if {![lock_index begin-update]} return
|
|
|
|
set pathList [list]
|
|
set after {}
|
|
foreach path $paths {
|
|
switch -glob -- [lindex $file_states($path) 0] {
|
|
_U -
|
|
U? {
|
|
if {$path eq $current_diff_path} {
|
|
unlock_index
|
|
merge_stage_workdir $path
|
|
return
|
|
}
|
|
}
|
|
_O -
|
|
?M -
|
|
?D -
|
|
?T {
|
|
lappend pathList $path
|
|
if {$path eq $current_diff_path} {
|
|
set after {reshow_diff;}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if {$pathList eq {}} {
|
|
unlock_index
|
|
} else {
|
|
update_index \
|
|
$txt \
|
|
$pathList \
|
|
[concat $after {ui_status [mc "Ready to commit."]}]
|
|
}
|
|
}
|
|
|
|
proc do_add_selection {} {
|
|
global current_diff_path selected_paths
|
|
|
|
if {[array size selected_paths] > 0} {
|
|
add_helper \
|
|
[mc "Adding selected files"] \
|
|
[array names selected_paths]
|
|
} elseif {$current_diff_path ne {}} {
|
|
add_helper \
|
|
[mc "Adding %s" [short_path $current_diff_path]] \
|
|
[list $current_diff_path]
|
|
}
|
|
}
|
|
|
|
proc do_add_all {} {
|
|
global file_states
|
|
|
|
set paths [list]
|
|
set untracked_paths [list]
|
|
foreach path [array names file_states] {
|
|
switch -glob -- [lindex $file_states($path) 0] {
|
|
U? {continue}
|
|
?M -
|
|
?T -
|
|
?D {lappend paths $path}
|
|
?O {lappend untracked_paths $path}
|
|
}
|
|
}
|
|
if {[llength $untracked_paths]} {
|
|
set reply 0
|
|
switch -- [get_config gui.stageuntracked] {
|
|
no {
|
|
set reply 0
|
|
}
|
|
yes {
|
|
set reply 1
|
|
}
|
|
ask -
|
|
default {
|
|
set reply [ask_popup [mc "Stage %d untracked files?" \
|
|
[llength $untracked_paths]]]
|
|
}
|
|
}
|
|
if {$reply} {
|
|
set paths [concat $paths $untracked_paths]
|
|
}
|
|
}
|
|
add_helper [mc "Adding all changed files"] $paths
|
|
}
|
|
|
|
proc revert_helper {txt paths} {
|
|
global file_states current_diff_path
|
|
|
|
if {![lock_index begin-update]} return
|
|
|
|
set pathList [list]
|
|
set after {}
|
|
foreach path $paths {
|
|
switch -glob -- [lindex $file_states($path) 0] {
|
|
U? {continue}
|
|
?M -
|
|
?T -
|
|
?D {
|
|
lappend pathList $path
|
|
if {$path eq $current_diff_path} {
|
|
set after {reshow_diff;}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
# Split question between singular and plural cases, because
|
|
# such distinction is needed in some languages. Previously, the
|
|
# code used "Revert changes in" for both, but that can't work
|
|
# in languages where 'in' must be combined with word from
|
|
# rest of string (in different way for both cases of course).
|
|
#
|
|
# FIXME: Unfortunately, even that isn't enough in some languages
|
|
# as they have quite complex plural-form rules. Unfortunately,
|
|
# msgcat doesn't seem to support that kind of string translation.
|
|
#
|
|
set n [llength $pathList]
|
|
if {$n == 0} {
|
|
unlock_index
|
|
return
|
|
} elseif {$n == 1} {
|
|
set query [mc "Revert changes in file %s?" [short_path [lindex $pathList]]]
|
|
} else {
|
|
set query [mc "Revert changes in these %i files?" $n]
|
|
}
|
|
|
|
set reply [tk_dialog \
|
|
.confirm_revert \
|
|
"[appname] ([reponame])" \
|
|
"$query
|
|
|
|
[mc "Any unstaged changes will be permanently lost by the revert."]" \
|
|
question \
|
|
1 \
|
|
[mc "Do Nothing"] \
|
|
[mc "Revert Changes"] \
|
|
]
|
|
if {$reply == 1} {
|
|
checkout_index \
|
|
$txt \
|
|
$pathList \
|
|
[concat $after [list ui_ready]]
|
|
} else {
|
|
unlock_index
|
|
}
|
|
}
|
|
|
|
proc do_revert_selection {} {
|
|
global current_diff_path selected_paths
|
|
|
|
if {[array size selected_paths] > 0} {
|
|
revert_helper \
|
|
[mc "Reverting selected files"] \
|
|
[array names selected_paths]
|
|
} elseif {$current_diff_path ne {}} {
|
|
revert_helper \
|
|
[mc "Reverting %s" [short_path $current_diff_path]] \
|
|
[list $current_diff_path]
|
|
}
|
|
}
|
|
|
|
proc do_select_commit_type {} {
|
|
global commit_type selected_commit_type
|
|
|
|
if {$selected_commit_type eq {new}
|
|
&& [string match amend* $commit_type]} {
|
|
create_new_commit
|
|
} elseif {$selected_commit_type eq {amend}
|
|
&& ![string match amend* $commit_type]} {
|
|
load_last_commit
|
|
|
|
# The amend request was rejected...
|
|
#
|
|
if {![string match amend* $commit_type]} {
|
|
set selected_commit_type new
|
|
}
|
|
}
|
|
}
|