field new_expr ; # expression the user saw/thinks this is
field new_hash ; # commit SHA-1 we are switching to
field new_ref ; # ref we are updating/creating
+field old_hash ; # commit SHA-1 that was checked out when we started
field parent_w .; # window that started us
field merge_type none; # type of merge to apply to existing branch
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?
set fetch_spec $spec
}
+method remote_source {spec} {
+ set remote_source $spec
+}
+
method enable_checkout {co} {
set checkout $co
}
}
method _update_ref {} {
- global null_sha1 current_branch
+ global null_sha1 current_branch repo_config
set ref $new_ref
set new $new_hash
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.
# -- Our in memory state should match the repository.
#
- repository_state curType curHEAD curMERGE_HEAD
+ repository_state curType old_hash curMERGE_HEAD
if {[string match amend* $commit_type]
&& $curType eq {normal}
- && $curHEAD eq $HEAD} {
- } elseif {$commit_type ne $curType || $HEAD ne $curHEAD} {
+ && $old_hash eq $HEAD} {
+ } elseif {$commit_type ne $curType || $HEAD ne $old_hash} {
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.
return
}
- if {$curHEAD eq $new_hash} {
+ if {$old_hash eq $new_hash} {
_after_readtree $this
} elseif {[is_config_true gui.trustmtime]} {
_readtree $this
}
method _after_readtree {} {
- global selected_commit_type commit_type HEAD MERGE_HEAD PARENT
+ global commit_type HEAD MERGE_HEAD PARENT
global current_branch is_detached
global ui_comm
If you wanted to be on a branch, create one now starting from 'This Detached Checkout'."]
}
+ # -- Run the post-checkout hook.
+ #
+ set fd_ph [githook_read post-checkout $old_hash $new_hash 1]
+ if {$fd_ph ne {}} {
+ global pch_error
+ set pch_error {}
+ fconfigure $fd_ph -blocking 0 -translation binary -eofchar {}
+ fileevent $fd_ph readable [cb _postcheckout_wait $fd_ph]
+ } else {
+ _update_repo_state $this
+ }
+}
+
+method _postcheckout_wait {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}]} {
+ hook_failed_popup post-checkout $pch_error 0
+ }
+ unset pch_error
+ _update_repo_state $this
+ return
+ }
+ fconfigure $fd_ph -blocking 0
+}
+
+method _update_repo_state {} {
# -- Update our repository state. If we were previously in
# amend mode we need to toss the current buffer and do a
# full rescan to update our file lists. If we weren't in
# amend mode our file lists are accurate and we can avoid
# the rescan.
#
+ global commit_type_is_amend commit_type HEAD MERGE_HEAD PARENT
+ global ui_comm
+
unlock_index
- set selected_commit_type new
+ set name [_name $this]
+ set commit_type_is_amend 0
if {[string match amend* $commit_type]} {
$ui_comm delete 0.0 end
$ui_comm edit reset