]> asedeno.scripts.mit.edu Git - git.git/blobdiff - lib/commit.tcl
git-gui: Show special diffs for complex conflict cases.
[git.git] / lib / commit.tcl
index f857a2ff5bb3d0e151ea471a16a1b233117afc70..2977315624fc5deeecff275d8dc8b3f2e3210a70 100644 (file)
@@ -6,19 +6,19 @@ proc load_last_commit {} {
        global repo_config
 
        if {[llength $PARENT] == 0} {
        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.
 
 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}} {
                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.
 
 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
        }
 
                return
        }
 
@@ -46,7 +46,7 @@ You are currently in the middle of a merge that has not been fully completed.  Y
                        }
                        set msg [string trim $msg]
                } err]} {
                        }
                        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
        }
 
                return
        }
 
@@ -73,12 +73,12 @@ proc committer_ident {} {
 
        if {$GIT_COMMITTER_IDENT eq {}} {
                if {[catch {set me [git var GIT_COMMITTER_IDENT]} err]} {
 
        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]} {
                        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 {}
                }
        }
                        return {}
                }
        }
@@ -130,12 +130,12 @@ proc commit_tree {} {
                && $curType eq {normal}
                && $curHEAD eq $HEAD} {
        } elseif {$commit_type ne $curType || $HEAD ne $curHEAD} {
                && $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.
 
 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 ui_ready
                return
                unlock_index
                rescan ui_ready
                return
@@ -149,28 +149,30 @@ The rescan will be automatically started now.
                _? {continue}
                A? -
                D? -
                _? {continue}
                A? -
                D? -
+               T_ -
                M? {set files_ready 1}
                M? {set files_ready 1}
+               _U -
                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 stage 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 {
                        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]} {
                }
                }
        }
        if {!$files_ready && ![string match *merge $curType]} {
-               info_popup {No changes to commit.
+               info_popup [mc "No changes to commit.
 
 You must stage at least 1 file before you can commit.
 
 You must stage at least 1 file before you can commit.
-}
+"]
                unlock_index
                return
        }
                unlock_index
                return
        }
@@ -180,57 +182,64 @@ You must stage 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 {}} {
        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:
 
 
 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.
 - Second line: Blank
 - Remaining lines: Describe why this change is good.
-}
+"]
                unlock_index
                return
        }
 
                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
        }
 
                return
        }
 
-       ui_status {Calling pre-commit hook...}
+       ui_status [mc "Calling pre-commit hook..."]
        set pch_error {}
        set pch_error {}
-       set fd_ph [open "| $pchook" r]
        fconfigure $fd_ph -blocking 0 -translation binary -eofchar {}
        fileevent $fd_ph readable \
        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} {
+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}]} {
        global pch_error
 
        append pch_error [read $fd_ph]
        fconfigure $fd_ph -blocking 1
        if {[eof $fd_ph]} {
                if {[catch {close $fd_ph}]} {
-                       ui_status {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 {
                        hook_failed_popup pre-commit $pch_error
                        unlock_index
                } else {
-                       commit_writetree $curHEAD $msg
+                       commit_commitmsg $curHEAD $msg_p
                }
                set pch_error {}
                return
                }
                set pch_error {}
                return
@@ -238,14 +247,52 @@ proc commit_prehook_wait {fd_ph curHEAD msg} {
        fconfigure $fd_ph -blocking 0
 }
 
        fconfigure $fd_ph -blocking 0
 }
 
-proc commit_writetree {curHEAD msg} {
-       ui_status {Committing changes...}
+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
+}
+
+proc commit_writetree {curHEAD msg_p} {
+       ui_status [mc "Committing changes..."]
        set fd_wt [git_read write-tree]
        fileevent $fd_wt readable \
        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 current_branch
        global ui_comm selected_commit_type
        global HEAD PARENT MERGE_HEAD commit_type
        global current_branch
        global ui_comm selected_commit_type
@@ -253,9 +300,10 @@ proc commit_committree {fd_wt curHEAD msg} {
        global repo_config
 
        gets $fd_wt tree_id
        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"
-               ui_status {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
        }
                unlock_index
                return
        }
@@ -272,40 +320,23 @@ proc commit_committree {fd_wt curHEAD msg} {
                        && [string length $old_tree] == 45} {
                        set old_tree [string range $old_tree 5 end]
                } else {
                        && [string length $old_tree] == 45} {
                        set old_tree [string range $old_tree 5 end]
                } else {
-                       error "Commit $PARENT appears to be corrupt"
+                       error [mc "Commit %s appears to be corrupt" $PARENT]
                }
 
                if {$tree_id eq $old_tree} {
                }
 
                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.
 
 No files were modified by this commit and it was not a merge commit.
 
 A rescan will be automatically started now.
-}
+"]
                        unlock_index
                        unlock_index
-                       rescan {ui_status {No changes to commit.}}
+                       rescan {ui_status [mc "No changes to commit."]}
                        return
                }
        }
 
                        return
                }
        }
 
-       # -- Build the message.
-       #
-       set msg_p [gitdir COMMIT_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 "warning: Tcl does not support encoding '$enc'."
-               fconfigure $msg_wt -encoding utf-8
-       }
-       puts -nonewline $msg_wt $msg
-       close $msg_wt
-
        # -- Create the commit.
        #
        set cmd [list commit-tree $tree_id]
        # -- Create the commit.
        #
        set cmd [list commit-tree $tree_id]
@@ -314,8 +345,9 @@ A rescan will be automatically started now.
        }
        lappend cmd <$msg_p
        if {[catch {set cmt_id [eval git $cmd]} err]} {
        }
        lappend cmd <$msg_p
        if {[catch {set cmt_id [eval git $cmd]} err]} {
-               error_popup "commit-tree failed:\n\n$err"
-               ui_status {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
        }
                unlock_index
                return
        }
@@ -326,18 +358,16 @@ A rescan will be automatically started now.
        if {$commit_type ne {normal}} {
                append reflogm " ($commit_type)"
        }
        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]} {
        append reflogm {: } $subject
        if {[catch {
                        git update-ref -m $reflogm HEAD $cmt_id $curHEAD
                } err]} {
-               error_popup "update-ref failed:\n\n$err"
-               ui_status {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
        }
                unlock_index
                return
        }
@@ -363,17 +393,13 @@ A rescan will be automatically started now.
 
        # -- Run the post-commit hook.
        #
 
        # -- 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 delete 0.0 end
@@ -404,6 +430,7 @@ A rescan will be automatically started now.
                __ -
                A_ -
                M_ -
                __ -
                A_ -
                M_ -
+               T_ -
                D_ {
                        unset file_states($path)
                        catch {unset selected_paths($path)}
                D_ {
                        unset file_states($path)
                        catch {unset selected_paths($path)}
@@ -427,5 +454,20 @@ A rescan will be automatically started now.
        display_all_files
        unlock_index
        reshow_diff
        display_all_files
        unlock_index
        reshow_diff
-       ui_status "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
 }
 }