X-Git-Url: https://asedeno.scripts.mit.edu/gitweb/?a=blobdiff_plain;f=lib%2Fcommit.tcl;h=2977315624fc5deeecff275d8dc8b3f2e3210a70;hb=b2ca414973c3bcd00f2b94538bd9c755387f30a0;hp=0de2a28fa5e031bd6c3a090f9288527aed78b188;hpb=4ca131250c9e56efec638831d6157aaf4f130be9;p=git.git diff --git a/lib/commit.tcl b/lib/commit.tcl index 0de2a28fa..297731562 100644 --- a/lib/commit.tcl +++ b/lib/commit.tcl @@ -6,26 +6,26 @@ proc load_last_commit {} { global repo_config if {[llength $PARENT] == 0} { - error_popup {There is nothing to amend. + error_popup [mc "There is nothing to amend. You are about to create the initial commit. There is no commit before this to amend. -} +"] return } repository_state curType curHEAD curMERGE_HEAD if {$curType eq {merge}} { - error_popup {Cannot amend while merging. + error_popup [mc "Cannot amend while merging. You are currently in the middle of a merge that has not been fully completed. You cannot amend the prior commit unless you first abort the current merge activity. -} +"] return } set msg {} set parents [list] if {[catch { - set fd [open "| git cat-file commit $curHEAD" r] + set fd [git_read cat-file commit $curHEAD] fconfigure $fd -encoding binary -translation lf if {[catch {set enc $repo_config(i18n.commitencoding)}]} { set enc utf-8 @@ -37,11 +37,16 @@ You are currently in the middle of a merge that has not been fully completed. Y set enc [string tolower [string range $line 9 end]] } } - set msg [encoding convertfrom $enc [read $fd]] - set msg [string trim $msg] + set msg [read $fd] close $fd + + set enc [tcl_encoding $enc] + if {$enc ne {}} { + set msg [encoding convertfrom $enc $msg] + } + set msg [string trim $msg] } err]} { - error_popup "Error loading commit data for amend:\n\n$err" + error_popup [strcat [mc "Error loading commit data for amend:"] "\n\n$err"] return } @@ -58,7 +63,7 @@ You are currently in the middle of a merge that has not been fully completed. Y $ui_comm insert end $msg $ui_comm edit reset $ui_comm edit modified false - rescan {set ui_status_value {Ready.}} + rescan ui_ready } set GIT_COMMITTER_IDENT {} @@ -68,12 +73,12 @@ proc committer_ident {} { if {$GIT_COMMITTER_IDENT eq {}} { if {[catch {set me [git var GIT_COMMITTER_IDENT]} err]} { - error_popup "Unable to obtain your identity:\n\n$err" + error_popup [strcat [mc "Unable to obtain your identity:"] "\n\n$err"] return {} } if {![regexp {^(.*) [0-9]+ [-+0-9]+$} \ $me me GIT_COMMITTER_IDENT]} { - error_popup "Invalid GIT_COMMITTER_IDENT:\n\n$me" + error_popup [strcat [mc "Invalid GIT_COMMITTER_IDENT:"] "\n\n$me"] return {} } } @@ -108,12 +113,12 @@ proc create_new_commit {} { $ui_comm delete 0.0 end $ui_comm edit reset $ui_comm edit modified false - rescan {set ui_status_value {Ready.}} + rescan ui_ready } proc commit_tree {} { global HEAD commit_type file_states ui_comm repo_config - global ui_status_value pch_error + global pch_error if {[committer_ident] eq {}} return if {![lock_index update]} return @@ -125,14 +130,14 @@ proc commit_tree {} { && $curType eq {normal} && $curHEAD eq $HEAD} { } elseif {$commit_type ne $curType || $HEAD ne $curHEAD} { - info_popup {Last scanned state does not match repository state. + 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 another commit can be created. The rescan will be automatically started now. -} +"] unlock_index - rescan {set ui_status_value {Ready.}} + rescan ui_ready return } @@ -144,28 +149,30 @@ The rescan will be automatically started now. _? {continue} A? - D? - + T_ - M? {set files_ready 1} + _U - U? { - error_popup "Unmerged files cannot be committed. + error_popup [mc "Unmerged files cannot be committed. -File [short_path $path] has merge conflicts. You must resolve them and add the file before committing. -" +File %s has merge conflicts. You must resolve them and stage the file before committing. +" [short_path $path]] unlock_index return } default { - error_popup "Unknown file state [lindex $s 0] detected. + error_popup [mc "Unknown file state %s detected. -File [short_path $path] cannot be committed by this program. -" +File %s cannot be committed by this program. +" [lindex $s 0] [short_path $path]] } } } if {!$files_ready && ![string match *merge $curType]} { - info_popup {No changes to commit. + info_popup [mc "No changes to commit. -You must add at least 1 file before you can commit. -} +You must stage at least 1 file before you can commit. +"] unlock_index return } @@ -175,57 +182,64 @@ You must add at least 1 file before you can commit. set msg [string trim [$ui_comm get 1.0 end]] regsub -all -line {[ \t\r]+$} $msg {} msg if {$msg eq {}} { - error_popup {Please supply a commit message. + error_popup [mc "Please supply a commit message. A good commit message has the following format: -- First line: Describe in one sentance what you did. +- First line: Describe in one sentence what you did. - Second line: Blank - Remaining lines: Describe why this change is good. -} +"] unlock_index return } - # -- Run the pre-commit hook. + # -- Build the message file. # - set pchook [gitdir hooks pre-commit] + 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 { + puts stderr [mc "warning: Tcl does not support encoding '%s'." $enc] + fconfigure $msg_wt -encoding utf-8 + } + puts $msg_wt $msg + close $msg_wt - # On Cygwin [file executable] might lie so we need to ask - # the shell if the hook is executable. Yes that's annoying. + # -- Run the pre-commit hook. # - if {[is_Cygwin] && [file isfile $pchook]} { - set pchook [list sh -c [concat \ - "if test -x \"$pchook\";" \ - "then exec \"$pchook\" 2>&1;" \ - "fi"]] - } elseif {[file executable $pchook]} { - set pchook [list $pchook |& cat] - } else { - commit_writetree $curHEAD $msg + set fd_ph [githook_read pre-commit] + if {$fd_ph eq {}} { + commit_commitmsg $curHEAD $msg_p return } - set ui_status_value {Calling pre-commit hook...} + ui_status [mc "Calling pre-commit hook..."] set pch_error {} - set fd_ph [open "| $pchook" r] - fconfigure $fd_ph -blocking 0 -translation binary + fconfigure $fd_ph -blocking 0 -translation binary -eofchar {} fileevent $fd_ph readable \ - [list commit_prehook_wait $fd_ph $curHEAD $msg] + [list commit_prehook_wait $fd_ph $curHEAD $msg_p] } -proc commit_prehook_wait {fd_ph curHEAD msg} { - global pch_error ui_status_value +proc commit_prehook_wait {fd_ph curHEAD msg_p} { + global pch_error append pch_error [read $fd_ph] fconfigure $fd_ph -blocking 1 if {[eof $fd_ph]} { if {[catch {close $fd_ph}]} { - set ui_status_value {Commit declined by pre-commit hook.} + catch {file delete $msg_p} + ui_status [mc "Commit declined by pre-commit hook."] hook_failed_popup pre-commit $pch_error unlock_index } else { - commit_writetree $curHEAD $msg + commit_commitmsg $curHEAD $msg_p } set pch_error {} return @@ -233,26 +247,63 @@ proc commit_prehook_wait {fd_ph curHEAD msg} { fconfigure $fd_ph -blocking 0 } -proc commit_writetree {curHEAD msg} { - global ui_status_value +proc commit_commitmsg {curHEAD msg_p} { + global pch_error + + # -- Run the commit-msg hook. + # + set fd_ph [githook_read commit-msg $msg_p] + if {$fd_ph eq {}} { + commit_writetree $curHEAD $msg_p + return + } + + ui_status [mc "Calling commit-msg hook..."] + set pch_error {} + fconfigure $fd_ph -blocking 0 -translation binary -eofchar {} + fileevent $fd_ph readable \ + [list commit_commitmsg_wait $fd_ph $curHEAD $msg_p] +} + +proc commit_commitmsg_wait {fd_ph curHEAD msg_p} { + global pch_error + + append pch_error [read $fd_ph] + fconfigure $fd_ph -blocking 1 + if {[eof $fd_ph]} { + if {[catch {close $fd_ph}]} { + catch {file delete $msg_p} + ui_status [mc "Commit declined by commit-msg hook."] + hook_failed_popup commit-msg $pch_error + unlock_index + } else { + commit_writetree $curHEAD $msg_p + } + set pch_error {} + return + } + fconfigure $fd_ph -blocking 0 +} - set ui_status_value {Committing changes...} - set fd_wt [open "| git write-tree" r] +proc commit_writetree {curHEAD msg_p} { + ui_status [mc "Committing changes..."] + set fd_wt [git_read write-tree] fileevent $fd_wt readable \ - [list commit_committree $fd_wt $curHEAD $msg] + [list commit_committree $fd_wt $curHEAD $msg_p] } -proc commit_committree {fd_wt curHEAD msg} { +proc commit_committree {fd_wt curHEAD msg_p} { global HEAD PARENT MERGE_HEAD commit_type - global all_heads current_branch - global ui_status_value ui_comm selected_commit_type + global current_branch + global ui_comm selected_commit_type global file_states selected_paths rescan_active global repo_config gets $fd_wt tree_id - if {$tree_id eq {} || [catch {close $fd_wt} err]} { - error_popup "write-tree failed:\n\n$err" - set ui_status_value {Commit failed.} + if {[catch {close $fd_wt} err]} { + catch {file delete $msg_p} + error_popup [strcat [mc "write-tree failed:"] "\n\n$err"] + ui_status [mc "Commit failed."] unlock_index return } @@ -260,31 +311,32 @@ proc commit_committree {fd_wt curHEAD msg} { # -- Verify this wasn't an empty change. # if {$commit_type eq {normal}} { - set old_tree [git rev-parse "$PARENT^{tree}"] + set fd_ot [git_read cat-file commit $PARENT] + fconfigure $fd_ot -encoding binary -translation lf + set old_tree [gets $fd_ot] + close $fd_ot + + if {[string equal -length 5 {tree } $old_tree] + && [string length $old_tree] == 45} { + set old_tree [string range $old_tree 5 end] + } else { + error [mc "Commit %s appears to be corrupt" $PARENT] + } + if {$tree_id eq $old_tree} { - info_popup {No changes to commit. + catch {file delete $msg_p} + info_popup [mc "No changes to commit. No files were modified by this commit and it was not a merge commit. A rescan will be automatically started now. -} +"] unlock_index - rescan {set ui_status_value {No changes to commit.}} + rescan {ui_status [mc "No changes to commit."]} return } } - # -- Build the message. - # - set msg_p [gitdir COMMIT_EDITMSG] - set msg_wt [open $msg_p w] - if {[catch {set enc $repo_config(i18n.commitencoding)}]} { - set enc utf-8 - } - fconfigure $msg_wt -encoding binary -translation binary - puts -nonewline $msg_wt [encoding convertto $enc $msg] - close $msg_wt - # -- Create the commit. # set cmd [list commit-tree $tree_id] @@ -293,8 +345,9 @@ A rescan will be automatically started now. } lappend cmd <$msg_p if {[catch {set cmt_id [eval git $cmd]} err]} { - error_popup "commit-tree failed:\n\n$err" - set ui_status_value {Commit failed.} + catch {file delete $msg_p} + error_popup [strcat [mc "commit-tree failed:"] "\n\n$err"] + ui_status [mc "Commit failed."] unlock_index return } @@ -305,18 +358,16 @@ A rescan will be automatically started now. if {$commit_type ne {normal}} { append reflogm " ($commit_type)" } - set i [string first "\n" $msg] - if {$i >= 0} { - set subject [string range $msg 0 [expr {$i - 1}]] - } else { - set subject $msg - } + set msg_fd [open $msg_p r] + gets $msg_fd subject + close $msg_fd append reflogm {: } $subject if {[catch { git update-ref -m $reflogm HEAD $cmt_id $curHEAD } err]} { - error_popup "update-ref failed:\n\n$err" - set ui_status_value {Commit failed.} + catch {file delete $msg_p} + error_popup [strcat [mc "update-ref failed:"] "\n\n$err"] + ui_status [mc "Commit failed."] unlock_index return } @@ -342,33 +393,25 @@ A rescan will be automatically started now. # -- Run the post-commit hook. # - set pchook [gitdir hooks post-commit] - if {[is_Cygwin] && [file isfile $pchook]} { - set pchook [list sh -c [concat \ - "if test -x \"$pchook\";" \ - "then exec \"$pchook\";" \ - "fi"]] - } elseif {![file executable $pchook]} { - set pchook {} - } - if {$pchook ne {}} { - catch {exec $pchook &} + set fd_ph [githook_read post-commit] + if {$fd_ph ne {}} { + upvar #0 pch_error$cmt_id pc_err + set pc_err {} + fconfigure $fd_ph -blocking 0 -translation binary -eofchar {} + fileevent $fd_ph readable \ + [list commit_postcommit_wait $fd_ph $cmt_id] } $ui_comm delete 0.0 end $ui_comm edit reset $ui_comm edit modified false + if {$::GITGUI_BCK_exists} { + catch {file delete [gitdir GITGUI_BCK]} + set ::GITGUI_BCK_exists 0 + } if {[is_enabled singlecommit]} do_quit - # -- Make sure our current branch exists. - # - if {$commit_type eq {initial}} { - lappend all_heads $current_branch - set all_heads [lsort -unique $all_heads] - populate_branch_menu - } - # -- Update in memory status # set selected_commit_type new @@ -387,6 +430,7 @@ A rescan will be automatically started now. __ - A_ - M_ - + T_ - D_ { unset file_states($path) catch {unset selected_paths($path)} @@ -410,6 +454,20 @@ A rescan will be automatically started now. display_all_files unlock_index reshow_diff - set ui_status_value \ - "Created commit [string range $cmt_id 0 7]: $subject" + ui_status [mc "Created commit %s: %s" [string range $cmt_id 0 7] $subject] +} + +proc commit_postcommit_wait {fd_ph cmt_id} { + upvar #0 pch_error$cmt_id 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-commit $pch_error 0 + } + unset pch_error + return + } + fconfigure $fd_ph -blocking 0 }