git-gui: Make initial commits work properly.
authorShawn O. Pearce <spearce@spearce.org>
Sat, 18 Nov 2006 07:50:58 +0000 (02:50 -0500)
committerShawn O. Pearce <spearce@spearce.org>
Sat, 18 Nov 2006 07:50:58 +0000 (02:50 -0500)
Apparently I never really tested the logic for making or amending an
initial commit, so although most of the code was here in git-gui it
didn't quite work as it was intended to.

So this is all just bug fixes to make initial commits correctly
generate the list of files going into the initial commit, or to
show a newly added file's diff, and to amend an initial commit.

Because we really want to diff the index against a tree-ish and
there is no such tree-ish on an initial commit we create an empty
tree through git-mktree and diff against that.  This unfortunately
creates a dangling tree, which may confuse a new user who uses
git-gui to make a new commit and then immediately afterwards runs
git fsck-objects to see if their object database is corrupt or not.

Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
git-gui

diff --git a/git-gui b/git-gui
index 12a46e976c0c3f5f6fb366e1c0742e6e74ad6555..e2e0beae95004f2bdcc09e79a59fd5dd2c84d242 100755 (executable)
--- a/git-gui
+++ b/git-gui
@@ -205,6 +205,7 @@ set index_lock_type none
 set HEAD {}
 set PARENT {}
 set commit_type {}
+set empty_tree {}
 
 proc lock_index {type} {
        global index_lock_type disable_on_lock
@@ -240,6 +241,7 @@ proc repository_state {hdvar ctvar} {
        upvar $hdvar hd $ctvar ct
 
        if {[catch {set hd [exec git rev-parse --verify HEAD]}]} {
+               set hd {}
                set ct initial
        } elseif {[file exists [file join $gitdir MERGE_HEAD]]} {
                set ct merge
@@ -248,6 +250,18 @@ proc repository_state {hdvar ctvar} {
        }
 }
 
+proc PARENT {} {
+       global PARENT empty_tree
+
+       if {$PARENT ne {}} {
+               return $PARENT
+       }
+       if {$empty_tree eq {}} {
+               set empty_tree [exec git mktree << {}]
+       }
+       return $empty_tree
+}
+
 proc rescan {after} {
        global HEAD PARENT commit_type
        global ui_index ui_other ui_status_value ui_comm
@@ -257,7 +271,7 @@ proc rescan {after} {
        if {$rescan_active > 0 || ![lock_index read]} return
 
        repository_state new_HEAD new_type
-       if {$commit_type eq {amend}
+       if {[string match amend* $commit_type]
                && $new_type eq {normal}
                && $new_HEAD eq $HEAD} {
        } else {
@@ -296,10 +310,8 @@ proc rescan {after} {
 }
 
 proc rescan_stage2 {fd after} {
-       global gitdir PARENT commit_type
-       global ui_index ui_other ui_status_value ui_comm
-       global rescan_active
-       global buf_rdi buf_rdf buf_rlo
+       global gitdir ui_status_value
+       global rescan_active buf_rdi buf_rdf buf_rlo
 
        if {$fd ne {}} {
                read $fd
@@ -320,7 +332,7 @@ proc rescan_stage2 {fd after} {
 
        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_di [open "| git diff-index --cached -z [PARENT]" r]
        set fd_df [open "| git diff-files -z" r]
        set fd_lo [open $ls_others r]
 
@@ -532,7 +544,7 @@ files list, to prevent possible confusion.
 
 proc show_diff {path {w {}} {lno {}}} {
        global file_states file_lists
-       global PARENT diff_3way diff_active repo_config
+       global diff_3way diff_active repo_config
        global ui_diff current_diff ui_status_value
 
        if {$diff_active || ![lock_index read]} return
@@ -591,7 +603,7 @@ proc show_diff {path {w {}} {lno {}}} {
        }
        }
 
-       lappend cmd $PARENT
+       lappend cmd [PARENT]
        lappend cmd --
        lappend cmd $path
 
@@ -671,7 +683,7 @@ proc read_diff {fd} {
 proc load_last_commit {} {
        global HEAD PARENT commit_type ui_comm
 
-       if {$commit_type eq {amend}} return
+       if {[string match amend* $commit_type]} return
        if {$commit_type ne {normal}} {
                error_popup "Can't amend a $commit_type commit."
                return
@@ -695,23 +707,24 @@ proc load_last_commit {} {
                return
        }
 
+       if {$parent_count > 1} {
+               error_popup {Can't amend a merge commit.}
+               return
+       }
+
        if {$parent_count == 0} {
-               set commit_type amend
-               set HEAD {}
+               set commit_type amend-initial
                set PARENT {}
-               rescan {set ui_status_value {Ready.}}
        } elseif {$parent_count == 1} {
                set commit_type amend
                set PARENT $parent
-               $ui_comm delete 0.0 end
-               $ui_comm insert end $msg
-               $ui_comm edit modified false
-               $ui_comm edit reset
-               rescan {set ui_status_value {Ready.}}
-       } else {
-               error_popup {You can't amend a merge commit.}
-               return
        }
+
+       $ui_comm delete 0.0 end
+       $ui_comm insert end $msg
+       $ui_comm edit modified false
+       $ui_comm edit reset
+       rescan {set ui_status_value {Ready.}}
 }
 
 proc commit_tree {} {
@@ -722,7 +735,7 @@ proc commit_tree {} {
        # -- Our in memory state should match the repository.
        #
        repository_state curHEAD cur_type
-       if {$commit_type eq {amend}
+       if {[string match amend* $commit_type]
                && $cur_type eq {normal}
                && $curHEAD eq $HEAD} {
        } elseif {$commit_type ne $cur_type || $HEAD ne $curHEAD} {
@@ -2559,13 +2572,18 @@ label $ui_coml -text {Commit Message:} \
        -anchor w \
        -justify left \
        -font font_ui
-trace add variable commit_type write {uplevel #0 {
-       switch -glob $commit_type \
-       initial {$ui_coml conf -text {Initial Commit Message:}} \
-       amend   {$ui_coml conf -text {Amended Commit Message:}} \
-       merge   {$ui_coml conf -text {Merge Commit Message:}} \
-       *       {$ui_coml conf -text {Commit Message:}}
-}}
+proc trace_commit_type {varname args} {
+       global ui_coml commit_type
+       switch -glob -- $commit_type {
+       initial       {set txt {Initial Commit Message:}}
+       amend         {set txt {Amended Commit Message:}}
+       amend-initial {set txt {Amended Initial Commit Message:}}
+       merge         {set txt {Merge Commit Message:}}
+       *             {set txt {Commit Message:}}
+       }
+       $ui_coml conf -text $txt
+}
+trace add variable commit_type write trace_commit_type
 text $ui_comm -background white -borderwidth 1 \
        -undo true \
        -maxundo 20 \