aboutsummaryrefslogtreecommitdiffstats
path: root/git-gui/lib
diff options
context:
space:
mode:
Diffstat (limited to 'git-gui/lib')
-rw-r--r--git-gui/lib/blame.tcl16
-rw-r--r--git-gui/lib/branch_delete.tcl4
-rw-r--r--git-gui/lib/checkout_op.tcl43
-rw-r--r--git-gui/lib/choose_repository.tcl37
-rw-r--r--git-gui/lib/commit.tcl35
-rw-r--r--git-gui/lib/database.tcl21
-rw-r--r--git-gui/lib/diff.tcl42
-rw-r--r--git-gui/lib/index.tcl34
-rw-r--r--git-gui/lib/mergetool.tcl4
-rw-r--r--git-gui/lib/remote_branch_delete.tcl26
-rw-r--r--git-gui/lib/shortcut.tcl2
-rw-r--r--git-gui/lib/tools.tcl2
12 files changed, 202 insertions, 64 deletions
diff --git a/git-gui/lib/blame.tcl b/git-gui/lib/blame.tcl
index 1f3b08f9ef..8525b79aaa 100644
--- a/git-gui/lib/blame.tcl
+++ b/git-gui/lib/blame.tcl
@@ -1245,6 +1245,18 @@ method _open_tooltip {cur_w} {
$tooltip_t conf -state disabled
_position_tooltip $this
+
+ # On MacOS raising a window causes it to acquire focus.
+ # Tk 8.5 on MacOS seems to properly support wm transient,
+ # so we can safely counter the effect there.
+ if {$::have_tk85 && [is_MacOSX]} {
+ update
+ if {$w eq {}} {
+ raise .
+ } else {
+ raise $w
+ }
+ }
}
method _position_tooltip {} {
@@ -1268,7 +1280,9 @@ method _position_tooltip {} {
append g $pos_y
wm geometry $tooltip_wm $g
- raise $tooltip_wm
+ if {![is_MacOSX]} {
+ raise $tooltip_wm
+ }
}
method _hide_tooltip {} {
diff --git a/git-gui/lib/branch_delete.tcl b/git-gui/lib/branch_delete.tcl
index ef1930b491..20d5e42307 100644
--- a/git-gui/lib/branch_delete.tcl
+++ b/git-gui/lib/branch_delete.tcl
@@ -51,7 +51,7 @@ constructor dialog {} {
$w.check \
[mc "Delete Only If Merged Into"] \
]
- $w_check none [mc "Always (Do not perform merge test.)"]
+ $w_check none [mc "Always (Do not perform merge checks)"]
pack $w.check -anchor nw -fill x -pady 5 -padx 5
foreach h [load_all_heads] {
@@ -112,7 +112,7 @@ method _delete {} {
}
if {$to_delete eq {}} return
if {$check_cmt eq {}} {
- set msg [mc "Recovering deleted branches is difficult. \n\n Delete the selected branches?"]
+ set msg [mc "Recovering deleted branches is difficult.\n\nDelete the selected branches?"]
if {[tk_messageBox \
-icon warning \
-type yesno \
diff --git a/git-gui/lib/checkout_op.tcl b/git-gui/lib/checkout_op.tcl
index caca88831b..9e7412c446 100644
--- a/git-gui/lib/checkout_op.tcl
+++ b/git-gui/lib/checkout_op.tcl
@@ -9,6 +9,7 @@ field w_cons {}; # embedded console window object
field new_expr ; # expression the user saw/thinks this is
field new_hash ; # commit SHA-1 we are switching to
field new_ref ; # ref we are updating/creating
+field old_hash ; # commit SHA-1 that was checked out when we started
field parent_w .; # window that started us
field merge_type none; # type of merge to apply to existing branch
@@ -280,11 +281,11 @@ method _start_checkout {} {
# -- Our in memory state should match the repository.
#
- repository_state curType curHEAD curMERGE_HEAD
+ repository_state curType old_hash curMERGE_HEAD
if {[string match amend* $commit_type]
&& $curType eq {normal}
- && $curHEAD eq $HEAD} {
- } elseif {$commit_type ne $curType || $HEAD ne $curHEAD} {
+ && $old_hash eq $HEAD} {
+ } elseif {$commit_type ne $curType || $HEAD ne $old_hash} {
info_popup [mc "Last scanned state does not match repository state.
Another Git program has modified this repository since the last scan. A rescan must be performed before the current branch can be changed.
@@ -297,7 +298,7 @@ The rescan will be automatically started now.
return
}
- if {$curHEAD eq $new_hash} {
+ if {$old_hash eq $new_hash} {
_after_readtree $this
} elseif {[is_config_true gui.trustmtime]} {
_readtree $this
@@ -453,13 +454,47 @@ method _after_readtree {} {
If you wanted to be on a branch, create one now starting from 'This Detached Checkout'."]
}
+ # -- Run the post-checkout hook.
+ #
+ set fd_ph [githook_read post-checkout $old_hash $new_hash 1]
+ if {$fd_ph ne {}} {
+ global pch_error
+ set pch_error {}
+ fconfigure $fd_ph -blocking 0 -translation binary -eofchar {}
+ fileevent $fd_ph readable [cb _postcheckout_wait $fd_ph]
+ } else {
+ _update_repo_state $this
+ }
+}
+
+method _postcheckout_wait {fd_ph} {
+ global pch_error
+
+ append pch_error [read $fd_ph]
+ fconfigure $fd_ph -blocking 1
+ if {[eof $fd_ph]} {
+ if {[catch {close $fd_ph}]} {
+ hook_failed_popup post-checkout $pch_error 0
+ }
+ unset pch_error
+ _update_repo_state $this
+ return
+ }
+ fconfigure $fd_ph -blocking 0
+}
+
+method _update_repo_state {} {
# -- Update our repository state. If we were previously in
# amend mode we need to toss the current buffer and do a
# full rescan to update our file lists. If we weren't in
# amend mode our file lists are accurate and we can avoid
# the rescan.
#
+ global selected_commit_type commit_type HEAD MERGE_HEAD PARENT
+ global ui_comm
+
unlock_index
+ set name [_name $this]
set selected_commit_type new
if {[string match amend* $commit_type]} {
$ui_comm delete 0.0 end
diff --git a/git-gui/lib/choose_repository.tcl b/git-gui/lib/choose_repository.tcl
index f9ff62a3b2..3f8f3030fa 100644
--- a/git-gui/lib/choose_repository.tcl
+++ b/git-gui/lib/choose_repository.tcl
@@ -235,6 +235,8 @@ proc _get_recentrepos {} {
foreach p [get_config gui.recentrepo] {
if {[_is_git [file join $p .git]]} {
lappend recent $p
+ } else {
+ _unset_recentrepo $p
}
}
return [lsort $recent]
@@ -243,6 +245,7 @@ proc _get_recentrepos {} {
proc _unset_recentrepo {p} {
regsub -all -- {([()\[\]{}\.^$+*?\\])} $p {\\\1} p
git config --global --unset gui.recentrepo "^$p\$"
+ load_config 1
}
proc _append_recentrepos {path} {
@@ -261,6 +264,7 @@ proc _append_recentrepos {path} {
lappend recent $path
git config --global --add gui.recentrepo $path
+ load_config 1
while {[llength $recent] > 10} {
_unset_recentrepo [lindex $recent 0]
@@ -398,6 +402,8 @@ method _do_new {} {
grid $w_body.where.l $w_body.where.t $w_body.where.b -sticky ew
pack $w_body.where -fill x
+ grid columnconfigure $w_body.where 1 -weight 1
+
trace add variable @local_path write [cb _write_local_path]
bind $w_body.h <Destroy> [list trace remove variable @local_path write [cb _write_local_path]]
update
@@ -964,7 +970,34 @@ method _readtree_wait {fd} {
return
}
- set done 1
+ # -- Run the post-checkout hook.
+ #
+ set fd_ph [githook_read post-checkout [string repeat 0 40] \
+ [git rev-parse HEAD] 1]
+ if {$fd_ph ne {}} {
+ global pch_error
+ set pch_error {}
+ fconfigure $fd_ph -blocking 0 -translation binary -eofchar {}
+ fileevent $fd_ph readable [cb _postcheckout_wait $fd_ph]
+ } else {
+ set done 1
+ }
+}
+
+method _postcheckout_wait {fd_ph} {
+ global pch_error
+
+ append pch_error [read $fd_ph]
+ fconfigure $fd_ph -blocking 1
+ if {[eof $fd_ph]} {
+ if {[catch {close $fd_ph}]} {
+ hook_failed_popup post-checkout $pch_error 0
+ }
+ unset pch_error
+ set done 1
+ return
+ }
+ fconfigure $fd_ph -blocking 0
}
######################################################################
@@ -998,6 +1031,8 @@ method _do_open {} {
grid $w_body.where.l $w_body.where.t $w_body.where.b -sticky ew
pack $w_body.where -fill x
+ grid columnconfigure $w_body.where 1 -weight 1
+
trace add variable @local_path write [cb _write_local_path]
bind $w_body.h <Destroy> [list trace remove variable @local_path write [cb _write_local_path]]
update
diff --git a/git-gui/lib/commit.tcl b/git-gui/lib/commit.tcl
index 9cc8410595..7f459cd564 100644
--- a/git-gui/lib/commit.tcl
+++ b/git-gui/lib/commit.tcl
@@ -115,6 +115,23 @@ proc create_new_commit {} {
rescan ui_ready
}
+proc setup_commit_encoding {msg_wt {quiet 0}} {
+ global repo_config
+
+ if {[catch {set enc $repo_config(i18n.commitencoding)}]} {
+ set enc utf-8
+ }
+ set use_enc [tcl_encoding $enc]
+ if {$use_enc ne {}} {
+ fconfigure $msg_wt -encoding $use_enc
+ } else {
+ if {!$quiet} {
+ error_popup [mc "warning: Tcl does not support encoding '%s'." $enc]
+ }
+ fconfigure $msg_wt -encoding utf-8
+ }
+}
+
proc commit_tree {} {
global HEAD commit_type file_states ui_comm repo_config
global pch_error
@@ -200,16 +217,7 @@ A good commit message has the following format:
set msg_p [gitdir GITGUI_EDITMSG]
set msg_wt [open $msg_p w]
fconfigure $msg_wt -translation lf
- if {[catch {set enc $repo_config(i18n.commitencoding)}]} {
- set enc utf-8
- }
- set use_enc [tcl_encoding $enc]
- if {$use_enc ne {}} {
- fconfigure $msg_wt -encoding $use_enc
- } else {
- error_popup [mc "warning: Tcl does not support encoding '%s'." $enc]
- fconfigure $msg_wt -encoding utf-8
- }
+ setup_commit_encoding $msg_wt
puts $msg_wt $msg
close $msg_wt
@@ -362,6 +370,7 @@ A rescan will be automatically started now.
append reflogm " ($commit_type)"
}
set msg_fd [open $msg_p r]
+ setup_commit_encoding $msg_fd 1
gets $msg_fd subject
close $msg_fd
append reflogm {: } $subject
@@ -398,8 +407,8 @@ A rescan will be automatically started now.
#
set fd_ph [githook_read post-commit]
if {$fd_ph ne {}} {
- upvar #0 pch_error$cmt_id pc_err
- set pc_err {}
+ global pch_error
+ set pch_error {}
fconfigure $fd_ph -blocking 0 -translation binary -eofchar {}
fileevent $fd_ph readable \
[list commit_postcommit_wait $fd_ph $cmt_id]
@@ -461,7 +470,7 @@ A rescan will be automatically started now.
}
proc commit_postcommit_wait {fd_ph cmt_id} {
- upvar #0 pch_error$cmt_id pch_error
+ global pch_error
append pch_error [read $fd_ph]
fconfigure $fd_ph -blocking 1
diff --git a/git-gui/lib/database.tcl b/git-gui/lib/database.tcl
index a18ac8b430..d4e0bed0b6 100644
--- a/git-gui/lib/database.tcl
+++ b/git-gui/lib/database.tcl
@@ -89,27 +89,26 @@ proc do_fsck_objects {} {
}
proc hint_gc {} {
- set object_limit 8
+ set ndirs 1
+ set limit 8
if {[is_Windows]} {
- set object_limit 1
+ set ndirs 4
+ set limit 1
}
- set objects_current [llength [glob \
- -directory [gitdir objects 42] \
+ set count [llength [glob \
-nocomplain \
- -tails \
-- \
- *]]
+ [gitdir objects 4\[0-[expr {$ndirs-1}]\]/*]]]
- if {$objects_current >= $object_limit} {
- set objects_current [expr {$objects_current * 250}]
- set object_limit [expr {$object_limit * 250}]
+ if {$count >= $limit * $ndirs} {
+ set objects_current [expr {$count * 256/$ndirs}]
if {[ask_popup \
[mc "This repository currently has approximately %i loose objects.
-To maintain optimal performance it is strongly recommended that you compress the database when more than %i loose objects exist.
+To maintain optimal performance it is strongly recommended that you compress the database.
-Compress the database now?" $objects_current $object_limit]] eq yes} {
+Compress the database now?" $objects_current]] eq yes} {
do_gc
}
}
diff --git a/git-gui/lib/diff.tcl b/git-gui/lib/diff.tcl
index bbbf15c875..066755b864 100644
--- a/git-gui/lib/diff.tcl
+++ b/git-gui/lib/diff.tcl
@@ -51,11 +51,16 @@ proc force_diff_encoding {enc} {
proc handle_empty_diff {} {
global current_diff_path file_states file_lists
+ global diff_empty_count
set path $current_diff_path
set s $file_states($path)
if {[lindex $s 0] ne {_M}} return
+ # Prevent infinite rescan loops
+ incr diff_empty_count
+ if {$diff_empty_count > 1} return
+
info_popup [mc "No differences detected.
%s has no changes.
@@ -250,7 +255,7 @@ proc show_other_diff {path w m cont_info} {
proc start_show_diff {cont_info {add_opts {}}} {
global file_states file_lists
- global is_3way_diff diff_active repo_config
+ global is_3way_diff is_submodule_diff diff_active repo_config
global ui_diff ui_index ui_workdir
global current_diff_path current_diff_side current_diff_header
@@ -260,6 +265,7 @@ proc start_show_diff {cont_info {add_opts {}}} {
set s $file_states($path)
set m [lindex $s 0]
set is_3way_diff 0
+ set is_submodule_diff 0
set diff_active 1
set current_diff_header {}
@@ -290,6 +296,16 @@ proc start_show_diff {cont_info {add_opts {}}} {
lappend cmd $path
}
+ if {[string match {160000 *} [lindex $s 2]]
+ || [string match {160000 *} [lindex $s 3]]} {
+ set is_submodule_diff 1
+ if {$w eq $ui_index} {
+ set cmd [list submodule summary --cached -- $path]
+ } else {
+ set cmd [list submodule summary --files -- $path]
+ }
+ }
+
if {[catch {set fd [eval git_read --nice $cmd]} err]} {
set diff_active 0
unlock_index
@@ -307,9 +323,10 @@ proc start_show_diff {cont_info {add_opts {}}} {
}
proc read_diff {fd cont_info} {
- global ui_diff diff_active
+ global ui_diff diff_active is_submodule_diff
global is_3way_diff is_conflict_diff current_diff_header
global current_diff_queue
+ global diff_empty_count
$ui_diff conf -state normal
while {[gets $fd line] >= 0} {
@@ -368,6 +385,23 @@ proc read_diff {fd cont_info} {
set tags {}
}
}
+ } elseif {$is_submodule_diff} {
+ if {$line == ""} continue
+ if {[regexp {^\* } $line]} {
+ set line [string replace $line 0 1 {Submodule }]
+ set tags d_@
+ } else {
+ set op [string range $line 0 2]
+ switch -- $op {
+ { <} {set tags d_-}
+ { >} {set tags d_+}
+ { W} {set tags {}}
+ default {
+ puts "error: Unhandled submodule diff marker: {$op}"
+ set tags {}
+ }
+ }
+ }
} else {
set op [string index $line 0]
switch -- $op {
@@ -415,7 +449,10 @@ proc read_diff {fd cont_info} {
if {[$ui_diff index end] eq {2.0}} {
handle_empty_diff
+ } else {
+ set diff_empty_count 0
}
+
set callback [lindex $cont_info 1]
if {$callback ne {}} {
eval $callback
@@ -627,6 +664,7 @@ proc apply_line {x y} {
}
set i_l $next_l
}
+ set patch "$patch$pre_context"
set patch "@@ -$hln,$n +$hln,[eval expr $n $sign 1] @@\n$patch"
if {[catch {
diff --git a/git-gui/lib/index.tcl b/git-gui/lib/index.tcl
index d33896a0ce..0b58bd8876 100644
--- a/git-gui/lib/index.tcl
+++ b/git-gui/lib/index.tcl
@@ -14,29 +14,31 @@ proc _close_updateindex {fd after} {
toplevel $w
wm title $w [strcat "[appname] ([reponame]): " [mc "Index Error"]]
wm geometry $w "+[winfo rootx .]+[winfo rooty .]"
- pack [label $w.msg \
- -justify left \
- -anchor w \
- -text [strcat \
- [mc "Updating the Git index failed. A rescan will be automatically started to resynchronize git-gui."] \
- "\n\n$err"] \
- ] -anchor w
-
- frame $w.buttons
- button $w.buttons.continue \
+ 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 [$w cget -background]
+ $w.msg tag configure bold -font font_uibold -justify center
+ scrollbar $w.vs -command [list $w.msg yview]
+ $w.msg insert end $s bold \n\n$err {}
+ $w.msg configure -state disabled
+
+ button $w.continue \
-text [mc "Continue"] \
-command [list destroy $w]
- pack $w.buttons.continue -side right -padx 5
- button $w.buttons.unlock \
+ button $w.unlock \
-text [mc "Unlock Index"] \
-command "destroy $w; _delete_indexlock"
- pack $w.buttons.unlock -side right
- pack $w.buttons -side bottom -fill x -pady 10 -padx 10
+ 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.buttons.continue <Visibility> "
+ bind $w.continue <Visibility> "
grab $w
- focus $w.buttons.continue
+ focus %W
"
tkwait window $w
diff --git a/git-gui/lib/mergetool.tcl b/git-gui/lib/mergetool.tcl
index eb2b4b56a4..3fe90e6970 100644
--- a/git-gui/lib/mergetool.tcl
+++ b/git-gui/lib/mergetool.tcl
@@ -88,7 +88,7 @@ proc merge_load_stages {path cont} {
set merge_stages(3) {}
set merge_stages_buf {}
- set merge_stages_fd [eval git_read ls-files -u -z -- $path]
+ set merge_stages_fd [eval git_read ls-files -u -z -- {$path}]
fconfigure $merge_stages_fd -blocking 0 -translation binary -encoding binary
fileevent $merge_stages_fd readable [list read_merge_stages $merge_stages_fd $cont]
@@ -382,7 +382,7 @@ proc merge_tool_finish {fd} {
delete_temp_files $mtool_tmpfiles
ui_status [mc "Merge tool failed."]
} else {
- if {[is_config_true merge.keepbackup]} {
+ if {[is_config_true mergetool.keepbackup]} {
file rename -force -- $backup "$mtool_target.orig"
}
diff --git a/git-gui/lib/remote_branch_delete.tcl b/git-gui/lib/remote_branch_delete.tcl
index 89eb0f70f2..241642062e 100644
--- a/git-gui/lib/remote_branch_delete.tcl
+++ b/git-gui/lib/remote_branch_delete.tcl
@@ -208,15 +208,15 @@ method _delete {} {
return
}
- if {[tk_messageBox \
- -icon warning \
- -type yesno \
- -title [wm title $w] \
- -parent $w \
- -message [mc "Recovering deleted branches is difficult.
-
-Delete the selected branches?"]] ne yes} {
- return
+ if {$checktype ne {head}} {
+ if {[tk_messageBox \
+ -icon warning \
+ -type yesno \
+ -title [wm title $w] \
+ -parent $w \
+ -message [mc "Recovering deleted branches is difficult.\n\nDelete the selected branches?"]] ne yes} {
+ return
+ }
}
destroy $w
@@ -250,6 +250,8 @@ method _write_url {args} { set urltype url }
method _write_check_head {args} { set checktype head }
method _write_head_list {args} {
+ global current_branch
+
$head_m delete 0 end
foreach abr $head_list {
$head_m insert end radiobutton \
@@ -258,7 +260,11 @@ method _write_head_list {args} {
-variable @check_head
}
if {[lsearch -exact -sorted $head_list $check_head] < 0} {
- set check_head {}
+ if {[lsearch -exact -sorted $head_list $current_branch] < 0} {
+ set check_head {}
+ } else {
+ set check_head $current_branch
+ }
}
}
diff --git a/git-gui/lib/shortcut.tcl b/git-gui/lib/shortcut.tcl
index 38c3151b05..2f20eb39c0 100644
--- a/git-gui/lib/shortcut.tcl
+++ b/git-gui/lib/shortcut.tcl
@@ -54,7 +54,7 @@ proc do_cygwin_shortcut {} {
$argv0]
win32_create_lnk $fn [list \
$sh -c \
- "CHERE_INVOKING=1 source /etc/profile;[sq $me]" \
+ "CHERE_INVOKING=1 source /etc/profile;[sq $me] &" \
] \
[file dirname [file normalize [gitdir]]]
} err]} {
diff --git a/git-gui/lib/tools.tcl b/git-gui/lib/tools.tcl
index 6ae63b6c7c..95e6e5553e 100644
--- a/git-gui/lib/tools.tcl
+++ b/git-gui/lib/tools.tcl
@@ -146,7 +146,7 @@ proc tools_complete {fullname w {ok 1}} {
}
if {$ok} {
- set msg [mc "Tool completed succesfully: %s" $fullname]
+ set msg [mc "Tool completed successfully: %s" $fullname]
} else {
set msg [mc "Tool failed: %s" $fullname]
}