##
## task management
-set status_active 0
+set rescan_active 0
set diff_active 0
set last_clicked {}
}
}
-proc update_status {{final Ready.}} {
+proc rescan {after} {
global HEAD PARENT commit_type
global ui_index ui_other ui_status_value ui_comm
- global status_active file_states
+ global rescan_active file_states
global repo_config
- if {$status_active || ![lock_index read]} return
+ if {$rescan_active > 0 || ![lock_index read]} return
repository_state new_HEAD new_type
if {$commit_type eq {amend}
}
if {$repo_config(gui.trustmtime) eq {true}} {
- update_status_stage2 {} $final
+ rescan_stage2 {} $after
} else {
- set status_active 1
+ set rescan_active 1
set ui_status_value {Refreshing file status...}
set cmd [list git update-index]
lappend cmd -q
set fd_rf [open "| $cmd" r]
fconfigure $fd_rf -blocking 0 -translation binary
fileevent $fd_rf readable \
- [list update_status_stage2 $fd_rf $final]
+ [list rescan_stage2 $fd_rf $after]
}
}
-proc update_status_stage2 {fd final} {
+proc rescan_stage2 {fd after} {
global gitdir PARENT commit_type
global ui_index ui_other ui_status_value ui_comm
- global status_active
+ global rescan_active
global buf_rdi buf_rdf buf_rlo
if {$fd ne {}} {
set buf_rdf {}
set buf_rlo {}
- set status_active 3
+ set rescan_active 3
set ui_status_value {Scanning for modified files ...}
set fd_di [open "| git diff-index --cached -z $PARENT" r]
set fd_df [open "| git diff-files -z" r]
fconfigure $fd_di -blocking 0 -translation binary
fconfigure $fd_df -blocking 0 -translation binary
fconfigure $fd_lo -blocking 0 -translation binary
- fileevent $fd_di readable [list read_diff_index $fd_di $final]
- fileevent $fd_df readable [list read_diff_files $fd_df $final]
- fileevent $fd_lo readable [list read_ls_others $fd_lo $final]
+ fileevent $fd_di readable [list read_diff_index $fd_di $after]
+ fileevent $fd_df readable [list read_diff_files $fd_df $after]
+ fileevent $fd_lo readable [list read_ls_others $fd_lo $after]
}
proc load_message {file} {
return 0
}
-proc read_diff_index {fd final} {
+proc read_diff_index {fd after} {
global buf_rdi
append buf_rdi [read $fd]
set buf_rdi {}
}
- status_eof $fd buf_rdi $final
+ rescan_done $fd buf_rdi $after
}
-proc read_diff_files {fd final} {
+proc read_diff_files {fd after} {
global buf_rdf
append buf_rdf [read $fd]
set buf_rdf {}
}
- status_eof $fd buf_rdf $final
+ rescan_done $fd buf_rdf $after
}
-proc read_ls_others {fd final} {
+proc read_ls_others {fd after} {
global buf_rlo
append buf_rlo [read $fd]
foreach p [lrange $pck 0 end-1] {
display_file $p _O
}
- status_eof $fd buf_rlo $final
+ rescan_done $fd buf_rlo $after
}
-proc status_eof {fd buf final} {
- global status_active ui_status_value
+proc rescan_done {fd buf after} {
+ global rescan_active
global file_states repo_config
upvar $buf to_clear
if {![eof $fd]} return
set to_clear {}
close $fd
- if {[incr status_active -1] > 0} return
+ if {[incr rescan_active -1] > 0} return
prune_selection
unlock_index
display_all_files
if {$repo_config(gui.partialinclude) ne {true}} {
- set pathList [list]
+ set pathList [list]
foreach path [array names file_states] {
switch -- [lindex $file_states($path) 0] {
AM -
}
}
if {$pathList ne {}} {
- update_index $pathList
+ update_index \
+ "Updating included files" \
+ $pathList \
+ [concat {reshow_diff;} $after]
return
}
}
reshow_diff
- set ui_status_value $final
+ uplevel #0 $after
}
proc prune_selection {} {
set commit_type amend
set HEAD {}
set PARENT {}
- update_status
+ rescan {set ui_status_value {Ready.}}
} elseif {$parent_count == 1} {
set commit_type amend
set PARENT $parent
$ui_comm insert end $msg
$ui_comm edit modified false
$ui_comm edit reset
- update_status
+ rescan {set ui_status_value {Ready.}}
} else {
error_popup {You can't amend a merge commit.}
return
}
proc commit_tree {} {
- global tcl_platform HEAD gitdir commit_type file_states
- global pch_error
- global ui_status_value ui_comm
+ global HEAD commit_type file_states ui_comm repo_config
if {![lock_index update]} return
error_popup {Last scanned state does not match repository state.
Its highly likely that another Git program modified the
-repository since our last scan. A rescan is required
+repository since the last scan. A rescan is required
before committing.
+
+A rescan will be automatically started now.
}
unlock_index
- update_status
+ rescan {set ui_status_value {Ready.}}
return
}
#
set files_ready 0
foreach path [array names file_states] {
- set s $file_states($path)
- switch -glob -- [lindex $s 0] {
+ switch -glob -- [lindex $file_states($path) 0] {
_? {continue}
A? -
D? -
return
}
- # -- Ask the pre-commit hook for the go-ahead.
+ # -- Update included files if partialincludes are off.
#
+ if {$repo_config(gui.partialinclude) ne {true}} {
+ set pathList [list]
+ foreach path [array names file_states] {
+ switch -glob -- [lindex $file_states($path) 0] {
+ A? -
+ M? {lappend pathList $path}
+ }
+ }
+ if {$pathList ne {}} {
+ unlock_index
+ update_index \
+ "Updating included files" \
+ $pathList \
+ [concat {lock_index update;} \
+ [list commit_prehook $curHEAD $msg]]
+ return
+ }
+ }
+
+ commit_prehook $curHEAD $msg
+}
+
+proc commit_prehook {curHEAD msg} {
+ global tcl_platform gitdir ui_status_value pch_error
+
+ # On Cygwin [file executable] might lie so we need to ask
+ # the shell if the hook is executable. Yes that's annoying.
+
set pchook [file join $gitdir hooks pre-commit]
- if {$tcl_platform(platform) eq {windows} && [file isfile $pchook]} {
+ if {$tcl_platform(platform) eq {windows}
+ && [file isfile $pchook]} {
set pchook [list sh -c [concat \
"if test -x \"$pchook\";" \
"then exec \"$pchook\" 2>&1;" \
} elseif {[file executable $pchook]} {
set pchook [list $pchook |& cat]
} else {
- set pchook {}
- }
- if {$pchook ne {}} {
- set ui_status_value {Calling pre-commit hook...}
- set pch_error {}
- set fd_ph [open "| $pchook" r]
- fconfigure $fd_ph -blocking 0 -translation binary
- fileevent $fd_ph readable \
- [list commit_stage1 $fd_ph $curHEAD $msg]
- } else {
- commit_stage2 $curHEAD $msg
+ commit_writetree $curHEAD $msg
+ return
}
+
+ set ui_status_value {Calling pre-commit hook...}
+ set pch_error {}
+ set fd_ph [open "| $pchook" r]
+ fconfigure $fd_ph -blocking 0 -translation binary
+ fileevent $fd_ph readable \
+ [list commit_prehook_wait $fd_ph $curHEAD $msg]
}
-proc commit_stage1 {fd_ph curHEAD msg} {
+proc commit_prehook_wait {fd_ph curHEAD msg} {
global pch_error ui_status_value
append pch_error [read $fd_ph]
hook_failed_popup pre-commit $pch_error
unlock_index
} else {
- commit_stage2 $curHEAD $msg
+ commit_writetree $curHEAD $msg
}
set pch_error {}
- } else {
- fconfigure $fd_ph -blocking 0
+ return
}
+ fconfigure $fd_ph -blocking 0
}
-proc commit_stage2 {curHEAD msg} {
+proc commit_writetree {curHEAD msg} {
global ui_status_value
- # -- Write the tree in the background.
- #
set ui_status_value {Committing changes...}
set fd_wt [open "| git write-tree" r]
- fileevent $fd_wt readable [list commit_stage3 $fd_wt $curHEAD $msg]
+ fileevent $fd_wt readable \
+ [list commit_committree $fd_wt $curHEAD $msg]
}
-proc commit_stage3 {fd_wt curHEAD msg} {
+proc commit_committree {fd_wt curHEAD msg} {
global single_commit gitdir HEAD PARENT commit_type tcl_platform
global ui_status_value ui_comm
global file_states selected_paths
before a pull can be started.
}
unlock_index
- update_status
+ rescan {set ui_status_value {Ready.}}
return
}
if {$success} {
repository_state HEAD commit_type
set PARENT $HEAD
- set $ui_status_value {Ready.}
+ set $ui_status_value "Pulling $branch from $remote complete."
} else {
- update_status \
- "Conflicts detected while pulling $branch from $remote."
+ set m "Conflicts detected while pulling $branch from $remote."
+ rescan "set ui_status_value {$m}"
}
}
}
proc display_file {path state} {
- global file_states file_lists selected_paths status_active
+ global file_states file_lists selected_paths rescan_active
set old_m [merge_state $path $state]
- if {$status_active} return
+ if {$rescan_active > 0} return
set s $file_states($path)
set new_m [lindex $s 0]
$ui_other conf -state disabled
}
-proc update_index {pathList} {
+proc update_index {msg pathList after} {
global update_index_cp update_index_rsd ui_status_value
if {![lock_index update]} return
if {$batch > 25} {set batch 25}
set ui_status_value [format \
- "Including files ... %i/%i files (%.2f%%)" \
+ "$msg... %i/%i files (%.2f%%)" \
$update_index_cp \
$totalCnt \
0.0]
$pathList \
$totalCnt \
$batch \
+ $msg \
+ $after \
]
}
-proc write_update_index {fd pathList totalCnt batch} {
+proc write_update_index {fd pathList totalCnt batch msg after} {
global update_index_cp update_index_rsd ui_status_value
global file_states ui_fname_value
if {$update_index_cp >= $totalCnt} {
close $fd
unlock_index
- set ui_status_value {Ready.}
- if {$update_index_rsd} {
- reshow_diff
- }
+ if {$update_index_rsd} reshow_diff
+ uplevel #0 $after
return
}
set path [lindex $pathList $update_index_cp]
incr update_index_cp
- switch -- [lindex $file_states($path) 0] {
- AM -
- _O {set new A*}
- _M -
- MM {set new M*}
+ switch -glob -- [lindex $file_states($path) 0] {
AD -
+ MD -
_D {set new D*}
- default {continue}
+
+ _M -
+ MM -
+ M_ {set new M*}
+
+ _O -
+ AM -
+ A_ {set new A*}
+
+ ?? {continue}
}
puts -nonewline $fd $path
}
set ui_status_value [format \
- "Including files ... %i/%i files (%.2f%%)" \
+ "$msg... %i/%i files (%.2f%%)" \
$update_index_cp \
$totalCnt \
[expr {100.0 * $update_index_cp / $totalCnt}]]
}
proc do_rescan {} {
- update_status
+ rescan {set ui_status_value {Ready.}}
}
proc do_include_all {} {
if {$pathList eq {}} {
unlock_index
} else {
- update_index $pathList
+ update_index \
+ "Including all modified files" \
+ $pathList \
+ {set ui_status_value {Ready to commit.}}
}
}
$ui_other tag remove in_sel 0.0 end
if {$col == 0} {
- update_index [list $path]
+ update_index \
+ "Including [short_path $path]" \
+ [list $path] \
+ {set ui_status_value {Ready.}}
} else {
show_diff $path $w $lno
}
populate_remote_menu .mbar.push To push_to
populate_pull_menu .mbar.pull
}
-after 1 update_status
+after 1 do_rescan