]> asedeno.scripts.mit.edu Git - git.git/blobdiff - lib/checkout_op.tcl
git-gui: Update swedish translation.
[git.git] / lib / checkout_op.tcl
index 844d8e551c14ba743fbb31746462440b15bb22d0..caca88831b7066c573917542d24a52e832dcff34 100644 (file)
@@ -12,13 +12,16 @@ field new_ref    ; # ref we are updating/creating
 
 field parent_w      .; # window that started us
 field merge_type none; # type of merge to apply to existing branch
 
 field parent_w      .; # window that started us
 field merge_type none; # type of merge to apply to existing branch
+field merge_base   {}; # merge base if we have another ref involved
 field fetch_spec   {}; # refetch tracking branch if used?
 field checkout      1; # actually checkout the branch?
 field create        0; # create the branch if it doesn't exist?
 field fetch_spec   {}; # refetch tracking branch if used?
 field checkout      1; # actually checkout the branch?
 field create        0; # create the branch if it doesn't exist?
+field remote_source {}; # same as fetch_spec, to setup tracking
 
 field reset_ok      0; # did the user agree to reset?
 field fetch_ok      0; # did the fetch succeed?
 
 
 field reset_ok      0; # did the user agree to reset?
 field fetch_ok      0; # did the fetch succeed?
 
+field readtree_d   {}; # buffered output from read-tree
 field update_old   {}; # was the update-ref call deferred?
 field reflog_msg   {}; # log message for the update-ref call
 
 field update_old   {}; # was the update-ref call deferred?
 field reflog_msg   {}; # log message for the update-ref call
 
@@ -42,6 +45,10 @@ method enable_fetch {spec} {
        set fetch_spec $spec
 }
 
        set fetch_spec $spec
 }
 
+method remote_source {spec} {
+       set remote_source $spec
+}
+
 method enable_checkout {co} {
        set checkout $co
 }
 method enable_checkout {co} {
        set checkout $co
 }
@@ -64,14 +71,19 @@ method run {} {
                set r_head [lindex $fetch_spec 2]
                regsub ^refs/heads/ $r_head {} r_name
 
                set r_head [lindex $fetch_spec 2]
                regsub ^refs/heads/ $r_head {} r_name
 
+               set cmd [list git fetch $remote]
+               if {$l_trck ne {}} {
+                       lappend cmd +$r_head:$l_trck
+               } else {
+                       lappend cmd $r_head
+               }
+
                _toplevel $this {Refreshing Tracking Branch}
                set w_cons [::console::embed \
                        $w.console \
                _toplevel $this {Refreshing Tracking Branch}
                set w_cons [::console::embed \
                        $w.console \
-                       "Fetching $r_name from $remote"]
+                       [mc "Fetching %s from %s" $r_name $remote]]
                pack $w.console -fill both -expand 1
                pack $w.console -fill both -expand 1
-               $w_cons exec \
-                       [list git fetch $remote +$r_head:$l_trck] \
-                       [cb _finish_fetch]
+               $w_cons exec $cmd [cb _finish_fetch]
 
                bind $w <$M1B-Key-w> break
                bind $w <$M1B-Key-W> break
 
                bind $w <$M1B-Key-w> break
                bind $w <$M1B-Key-W> break
@@ -112,9 +124,12 @@ method _noop {} {}
 method _finish_fetch {ok} {
        if {$ok} {
                set l_trck [lindex $fetch_spec 0]
 method _finish_fetch {ok} {
        if {$ok} {
                set l_trck [lindex $fetch_spec 0]
+               if {$l_trck eq {}} {
+                       set l_trck FETCH_HEAD
+               }
                if {[catch {set new_hash [git rev-parse --verify "$l_trck^0"]} err]} {
                        set ok 0
                if {[catch {set new_hash [git rev-parse --verify "$l_trck^0"]} err]} {
                        set ok 0
-                       $w_cons insert "fatal: Cannot resolve $l_trck"
+                       $w_cons insert [mc "fatal: Cannot resolve %s" $l_trck]
                        $w_cons insert $err
                }
        }
                        $w_cons insert $err
                }
        }
@@ -127,7 +142,7 @@ method _finish_fetch {ok} {
                destroy $w
                set w {}
        } else {
                destroy $w
                set w {}
        } else {
-               button $w.close -text Close -command [list destroy $w]
+               button $w.close -text [mc Close] -command [list destroy $w]
                pack $w.close -side bottom -anchor e -padx 10 -pady 10
        }
 
                pack $w.close -side bottom -anchor e -padx 10 -pady 10
        }
 
@@ -135,7 +150,7 @@ method _finish_fetch {ok} {
 }
 
 method _update_ref {} {
 }
 
 method _update_ref {} {
-       global null_sha1 current_branch
+       global null_sha1 current_branch repo_config
 
        set ref $new_ref
        set new $new_hash
 
        set ref $new_ref
        set new $new_hash
@@ -156,17 +171,34 @@ method _update_ref {} {
                # Assume it does not exist, and that is what the error was.
                #
                if {!$create} {
                # Assume it does not exist, and that is what the error was.
                #
                if {!$create} {
-                       _error $this "Branch '$newbranch' does not exist."
+                       _error $this [mc "Branch '%s' does not exist." $newbranch]
                        return 0
                }
 
                set reflog_msg "branch: Created from $new_expr"
                set cur $null_sha1
                        return 0
                }
 
                set reflog_msg "branch: Created from $new_expr"
                set cur $null_sha1
+
+               if {($repo_config(branch.autosetupmerge) eq {true}
+                       || $repo_config(branch.autosetupmerge) eq {always})
+                       && $remote_source ne {}
+                       && "refs/heads/$newbranch" eq $ref} {
+
+                       set c_remote [lindex $remote_source 1]
+                       set c_merge [lindex $remote_source 2]
+                       if {[catch {
+                                       git config branch.$newbranch.remote $c_remote
+                                       git config branch.$newbranch.merge  $c_merge
+                               } err]} {
+                               _error $this [strcat \
+                               [mc "Failed to configure simplified git-pull for '%s'." $newbranch] \
+                               "\n\n$err"]
+                       }
+               }
        } elseif {$create && $merge_type eq {none}} {
                # We were told to create it, but not do a merge.
                # Bad.  Name shouldn't have existed.
                #
        } elseif {$create && $merge_type eq {none}} {
                # We were told to create it, but not do a merge.
                # Bad.  Name shouldn't have existed.
                #
-               _error $this "Branch '$newbranch' already exists."
+               _error $this [mc "Branch '%s' already exists." $newbranch]
                return 0
        } elseif {!$create && $merge_type eq {none}} {
                # We aren't creating, it exists and we don't merge.
                return 0
        } elseif {!$create && $merge_type eq {none}} {
                # We aren't creating, it exists and we don't merge.
@@ -179,29 +211,25 @@ method _update_ref {} {
                # No merge would be required, don't compute anything.
                #
        } else {
                # No merge would be required, don't compute anything.
                #
        } else {
-               set mrb {}
-               catch {set mrb [git merge-base $new $cur]}
-               switch -- $merge_type {
-               ff {
-                       if {$mrb eq $new} {
-                               # The current branch is actually newer.
-                               #
-                               set new $cur
-                       } elseif {$mrb eq $cur} {
-                               # The current branch is older.
-                               #
-                               set reflog_msg "merge $new_expr: Fast-forward"
-                       } else {
-                               _error $this "Branch '$newbranch' already exists.\n\nIt cannot fast-forward to $new_expr.\nA merge is required."
-                               return 0
+               catch {set merge_base [git merge-base $new $cur]}
+               if {$merge_base eq $cur} {
+                       # The current branch is older.
+                       #
+                       set reflog_msg "merge $new_expr: Fast-forward"
+               } else {
+                       switch -- $merge_type {
+                       ff {
+                               if {$merge_base eq $new} {
+                                       # The current branch is actually newer.
+                                       #
+                                       set new $cur
+                                       set new_hash $cur
+                               } else {
+                                       _error $this [mc "Branch '%s' already exists.\n\nIt cannot fast-forward to %s.\nA merge is required." $newbranch $new_expr]
+                                       return 0
+                               }
                        }
                        }
-               }
-               reset {
-                       if {$mrb eq $cur} {
-                               # The current branch is older.
-                               #
-                               set reflog_msg "merge $new_expr: Fast-forward"
-                       } else {
+                       reset {
                                # The current branch will lose things.
                                #
                                if {[_confirm_reset $this $cur]} {
                                # The current branch will lose things.
                                #
                                if {[_confirm_reset $this $cur]} {
@@ -210,11 +238,11 @@ method _update_ref {} {
                                        return 0
                                }
                        }
                                        return 0
                                }
                        }
-               }
-               default {
-                       _error $this "Only 'ff' and 'reset' merge is currently supported."
-                       return 0
-               }
+                       default {
+                               _error $this [mc "Merge strategy '%s' not supported." $merge_type]
+                               return 0
+                       }
+                       }
                }
        }
 
                }
        }
 
@@ -230,7 +258,7 @@ method _update_ref {} {
                if {[catch {
                                git update-ref -m $reflog_msg $ref $new $cur
                        } err]} {
                if {[catch {
                                git update-ref -m $reflog_msg $ref $new $cur
                        } err]} {
-                       _error $this "Failed to update '$newbranch'.\n\n$err"
+                       _error $this [strcat [mc "Failed to update '%s'." $newbranch] "\n\n$err"]
                        return 0
                }
        }
                        return 0
                }
        }
@@ -242,7 +270,7 @@ method _checkout {} {
        if {[lock_index checkout_op]} {
                after idle [cb _start_checkout]
        } else {
        if {[lock_index checkout_op]} {
                after idle [cb _start_checkout]
        } else {
-               _error $this "Index is already locked."
+               _error $this [mc "Staging area (index) is already locked."]
                delete_this
        }
 }
                delete_this
        }
 }
@@ -257,28 +285,30 @@ method _start_checkout {} {
                && $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 the current branch can be changed.
 
 The rescan will be automatically started now.
 
 Another Git program has modified this repository since the last scan.  A rescan must be performed before the current branch can be changed.
 
 The rescan will be automatically started now.
-}
+"]
                unlock_index
                rescan ui_ready
                delete_this
                return
        }
 
                unlock_index
                rescan ui_ready
                delete_this
                return
        }
 
-       if {[is_config_true gui.trustmtime]} {
+       if {$curHEAD eq $new_hash} {
+               _after_readtree $this
+       } elseif {[is_config_true gui.trustmtime]} {
                _readtree $this
        } else {
                _readtree $this
        } else {
-               ui_status {Refreshing file status...}
-               set cmd [list git update-index]
-               lappend cmd -q
-               lappend cmd --unmerged
-               lappend cmd --ignore-missing
-               lappend cmd --refresh
-               set fd [open "| $cmd" r]
+               ui_status [mc "Refreshing file status..."]
+               set fd [git_read update-index \
+                       -q \
+                       --unmerged \
+                       --ignore-missing \
+                       --refresh \
+                       ]
                fconfigure $fd -blocking 0 -translation binary
                fileevent $fd readable [cb _refresh_wait $fd]
        }
                fconfigure $fd -blocking 0 -translation binary
                fileevent $fd readable [cb _refresh_wait $fd]
        }
@@ -309,51 +339,60 @@ method _name {} {
 method _readtree {} {
        global HEAD
 
 method _readtree {} {
        global HEAD
 
-       ui_status "Updating working directory to '[_name $this]'..."
-       set cmd [list git read-tree]
-       lappend cmd -m
-       lappend cmd -u
-       lappend cmd --exclude-per-directory=.gitignore
-       lappend cmd $HEAD
-       lappend cmd $new_hash
-       set fd [open "| $cmd" r]
+       set readtree_d {}
+       $::main_status start \
+               [mc "Updating working directory to '%s'..." [_name $this]] \
+               [mc "files checked out"]
+
+       set fd [git_read --stderr read-tree \
+               -m \
+               -u \
+               -v \
+               --exclude-per-directory=.gitignore \
+               $HEAD \
+               $new_hash \
+               ]
        fconfigure $fd -blocking 0 -translation binary
        fileevent $fd readable [cb _readtree_wait $fd]
 }
 
 method _readtree_wait {fd} {
        fconfigure $fd -blocking 0 -translation binary
        fileevent $fd readable [cb _readtree_wait $fd]
 }
 
 method _readtree_wait {fd} {
-       global selected_commit_type commit_type HEAD MERGE_HEAD PARENT
-       global current_branch is_detached
-       global ui_comm
+       global current_branch
+
+       set buf [read $fd]
+       $::main_status update_meter $buf
+       append readtree_d $buf
 
 
-       # -- We never get interesting output on stdout; only stderr.
-       #
-       read $fd
        fconfigure $fd -blocking 1
        if {![eof $fd]} {
                fconfigure $fd -blocking 0
                return
        }
 
        fconfigure $fd -blocking 1
        if {![eof $fd]} {
                fconfigure $fd -blocking 0
                return
        }
 
-       set name [_name $this]
-
-       # -- The working directory wasn't in sync with the index and
-       #    we'd have to overwrite something to make the switch. A
-       #    merge is required.
-       #
-       if {[catch {close $fd} err]} {
+       if {[catch {close $fd}]} {
+               set err $readtree_d
                regsub {^fatal: } $err {} err
                regsub {^fatal: } $err {} err
-               warn_popup "File level merge required.
+               $::main_status stop [mc "Aborted checkout of '%s' (file level merging is required)." [_name $this]]
+               warn_popup [strcat [mc "File level merge required."] "
 
 $err
 
 
 $err
 
-Staying on branch '$current_branch'."
-               ui_status "Aborted checkout of '$name' (file level merging is required)."
+" [mc "Staying on branch '%s'." $current_branch]]
                unlock_index
                delete_this
                return
        }
 
                unlock_index
                delete_this
                return
        }
 
+       $::main_status stop
+       _after_readtree $this
+}
+
+method _after_readtree {} {
+       global selected_commit_type commit_type HEAD MERGE_HEAD PARENT
+       global current_branch is_detached
+       global ui_comm
+
+       set name [_name $this]
        set log "checkout: moving"
        if {!$is_detached} {
                append log " from $current_branch"
        set log "checkout: moving"
        if {!$is_detached} {
                append log " from $current_branch"
@@ -368,22 +407,24 @@ Staying on branch '$current_branch'."
        set rn [string length $rh]
        if {[string equal -length $rn $rh $new_ref]} {
                set new_branch [string range $new_ref $rn end]
        set rn [string length $rh]
        if {[string equal -length $rn $rh $new_ref]} {
                set new_branch [string range $new_ref $rn end]
-               append log " to $new_branch"
-
-               if {[catch {
-                               git symbolic-ref -m $log HEAD $new_ref
-                       } err]} {
-                       _fatal $this $err
+               if {$is_detached || $current_branch ne $new_branch} {
+                       append log " to $new_branch"
+                       if {[catch {
+                                       git symbolic-ref -m $log HEAD $new_ref
+                               } err]} {
+                               _fatal $this $err
+                       }
+                       set current_branch $new_branch
+                       set is_detached 0
                }
                }
-               set current_branch $new_branch
-               set is_detached 0
        } else {
        } else {
-               append log " to $new_expr"
-
-               if {[catch {
-                               _detach_HEAD $log $new_hash
-                       } err]} {
-                       _fatal $this $err
+               if {!$is_detached || $new_hash ne $HEAD} {
+                       append log " to $new_expr"
+                       if {[catch {
+                                       _detach_HEAD $log $new_hash
+                               } err]} {
+                               _fatal $this $err
+                       }
                }
                set current_branch HEAD
                set is_detached 1
                }
                set current_branch HEAD
                set is_detached 1
@@ -407,9 +448,9 @@ Staying on branch '$current_branch'."
        }
 
        if {$is_detached} {
        }
 
        if {$is_detached} {
-               info_popup "You are no longer on a local branch.
+               info_popup [mc "You are no longer on a local branch.
 
 
-If you wanted to be on a branch, create one now starting from 'This Detached Checkout'."
+If you wanted to be on a branch, create one now starting from 'This Detached Checkout'."]
        }
 
        # -- Update our repository state.  If we were previously in
        }
 
        # -- Update our repository state.  If we were previously in
@@ -424,11 +465,11 @@ If you wanted to be on a branch, create one now starting from 'This Detached Che
                $ui_comm delete 0.0 end
                $ui_comm edit reset
                $ui_comm edit modified false
                $ui_comm delete 0.0 end
                $ui_comm edit reset
                $ui_comm edit modified false
-               rescan [list ui_status "Checked out '$name'."]
+               rescan [list ui_status [mc "Checked out '%s'." $name]]
        } else {
                repository_state commit_type HEAD MERGE_HEAD
                set PARENT $HEAD
        } else {
                repository_state commit_type HEAD MERGE_HEAD
                set PARENT $HEAD
-               ui_status "Checked out '$name'."
+               ui_status [mc "Checked out '%s'." $name]
        }
        delete_this
 }
        }
        delete_this
 }
@@ -456,7 +497,7 @@ method _confirm_reset {cur} {
        pack [label $w.msg1 \
                -anchor w \
                -justify left \
        pack [label $w.msg1 \
                -anchor w \
                -justify left \
-               -text "Resetting '$name' to $new_expr will lose the following commits:" \
+               -text [mc "Resetting '%s' to '%s' will lose the following commits:" $name $new_expr]\
                ] -anchor w
 
        set list $w.list.l
                ] -anchor w
 
        set list $w.list.l
@@ -478,21 +519,21 @@ method _confirm_reset {cur} {
        pack [label $w.msg2 \
                -anchor w \
                -justify left \
        pack [label $w.msg2 \
                -anchor w \
                -justify left \
-               -text {Recovering lost commits may not be easy.} \
+               -text [mc "Recovering lost commits may not be easy."] \
                ]
        pack [label $w.msg3 \
                -anchor w \
                -justify left \
                ]
        pack [label $w.msg3 \
                -anchor w \
                -justify left \
-               -text "Reset '$name'?" \
+               -text [mc "Reset '%s'?" $name] \
                ]
 
        frame $w.buttons
        button $w.buttons.visualize \
                ]
 
        frame $w.buttons
        button $w.buttons.visualize \
-               -text Visualize \
+               -text [mc Visualize] \
                -command $gitk
        pack $w.buttons.visualize -side left
        button $w.buttons.reset \
                -command $gitk
        pack $w.buttons.visualize -side left
        button $w.buttons.reset \
-               -text Reset \
+               -text [mc Reset] \
                -command "
                        set @reset_ok 1
                        destroy $w
                -command "
                        set @reset_ok 1
                        destroy $w
@@ -500,12 +541,12 @@ method _confirm_reset {cur} {
        pack $w.buttons.reset -side right
        button $w.buttons.cancel \
                -default active \
        pack $w.buttons.reset -side right
        button $w.buttons.cancel \
                -default active \
-               -text Cancel \
+               -text [mc Cancel] \
                -command [list destroy $w]
        pack $w.buttons.cancel -side right -padx 5
        pack $w.buttons -side bottom -fill x -pady 10 -padx 10
 
                -command [list destroy $w]
        pack $w.buttons.cancel -side right -padx 5
        pack $w.buttons -side bottom -fill x -pady 10 -padx 10
 
-       set fd [open "| git rev-list --pretty=oneline $cur ^$new_hash" r]
+       set fd [git_read rev-list --pretty=oneline $cur ^$new_hash]
        while {[gets $fd line] > 0} {
                set abbr [string range $line 0 7]
                set subj [string range $line 41 end]
        while {[gets $fd line] > 0} {
                set abbr [string range $line 0 7]
                set subj [string range $line 41 end]
@@ -556,13 +597,13 @@ method _toplevel {title} {
 }
 
 method _fatal {err} {
 }
 
 method _fatal {err} {
-       error_popup "Failed to set current branch.
+       error_popup [strcat [mc "Failed to set current branch.
 
 This working directory is only partially switched.  We successfully updated your files, but failed to update an internal Git file.
 
 
 This working directory is only partially switched.  We successfully updated your files, but failed to update an internal Git file.
 
-This should not have occurred.  [appname] will now close and give up.
+This should not have occurred.  %s will now close and give up." [appname]] "
 
 
-$err"
+$err"]
        exit 1
 }
 
        exit 1
 }