summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: 0fd49d0)
raw | patch | inline | side by side (parent: 0fd49d0)
author | Shawn O. Pearce <spearce@spearce.org> | |
Wed, 24 Jan 2007 21:51:59 +0000 (16:51 -0500) | ||
committer | Shawn O. Pearce <spearce@spearce.org> | |
Thu, 25 Jan 2007 05:25:31 +0000 (00:25 -0500) |
If the user selects a different branch from the Branch menu, or asks
us to create a new branch and immediately checkout that branch we
now perform the update of the working directory by way of a 2 way
read-tree invocation.
This emulates the behavior of `git checkout branch` or the behavior
of `git checkout -b branch initrev`. We don't however support the
-m style behavior, where a switch can occur with file level merging
performed by merge-recursive. Support for this is planned for a
future update.
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
us to create a new branch and immediately checkout that branch we
now perform the update of the working directory by way of a 2 way
read-tree invocation.
This emulates the behavior of `git checkout branch` or the behavior
of `git checkout -b branch initrev`. We don't however support the
-m style behavior, where a switch can occur with file level merging
performed by merge-recursive. Support for this is planned for a
future update.
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
git-gui.sh | patch | blob | history |
diff --git a/git-gui.sh b/git-gui.sh
index 5171db6f278854e60f8473b25cd7acbd58eb024a..b5c2c7406d2d09d7d52a2c3fd25d79cec64fa48f 100755 (executable)
--- a/git-gui.sh
+++ b/git-gui.sh
tkwait window $w
}
-proc switch_branch {b} {
- global HEAD commit_type file_states current_branch
- global selected_commit_type ui_comm
+proc switch_branch {new_branch} {
+ global HEAD commit_type current_branch repo_config
if {![lock_index switch]} return
- # -- Backup the selected branch (repository_state resets it)
- #
- set new_branch $current_branch
-
# -- Our in memory state should match the repository.
#
repository_state curType curHEAD curMERGE_HEAD
return
}
- # -- Toss the message buffer if we are in amend mode.
+ if {$repo_config(gui.trustmtime) eq {true}} {
+ switch_branch_stage2 {} $new_branch
+ } else {
+ set ui_status_value {Refreshing file status...}
+ set cmd [list git update-index]
+ lappend cmd -q
+ lappend cmd --unmerged
+ lappend cmd --ignore-missing
+ lappend cmd --refresh
+ set fd_rf [open "| $cmd" r]
+ fconfigure $fd_rf -blocking 0 -translation binary
+ fileevent $fd_rf readable \
+ [list switch_branch_stage2 $fd_rf $new_branch]
+ }
+}
+
+proc switch_branch_stage2 {fd_rf new_branch} {
+ global ui_status_value HEAD
+
+ if {$fd_rf ne {}} {
+ read $fd_rf
+ if {![eof $fd_rf]} return
+ close $fd_rf
+ }
+
+ set ui_status_value "Updating working directory to '$new_branch'..."
+ set cmd [list git read-tree]
+ lappend cmd -m
+ lappend cmd -u
+ lappend cmd --exclude-per-directory=.gitignore
+ lappend cmd $HEAD
+ lappend cmd $new_branch
+ set fd_rt [open "| $cmd" r]
+ fconfigure $fd_rt -blocking 0 -translation binary
+ fileevent $fd_rt readable \
+ [list switch_branch_readtree_wait $fd_rt $new_branch]
+}
+
+proc switch_branch_readtree_wait {fd_rt new_branch} {
+ global selected_commit_type commit_type HEAD MERGE_HEAD PARENT
+ global current_branch
+ global ui_comm ui_status_value
+
+ # -- We never get interesting output on stdout; only stderr.
#
- if {[string match amend* $curType]} {
- $ui_comm delete 0.0 end
- $ui_comm edit reset
- $ui_comm edit modified false
+ read $fd_rt
+ fconfigure $fd_rt -blocking 1
+ if {![eof $fd_rt]} {
+ fconfigure $fd_rt -blocking 0
+ return
}
- set selected_commit_type new
- set current_branch $new_branch
+ # -- 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_rt} err]} {
+ regsub {^fatal: } $err {} err
+ warn_popup "File level merge required.
+
+$err
+
+Staying on branch '$current_branch'."
+ set ui_status_value "Aborted checkout of '$new_branch' (file level merging is required)."
+ unlock_index
+ return
+ }
+
+ # -- Update the symbolic ref. Core git doesn't even check for failure
+ # here, it Just Works(tm). If it doesn't we are in some really ugly
+ # state that is difficult to recover from within git-gui.
+ #
+ if {[catch {exec git symbolic-ref HEAD "refs/heads/$new_branch"} err]} {
+ error_popup "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 should not have occurred. [appname] will now
+close and give up.
+$err"
+ do_quit
+ return
+ }
+
+ # -- 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.
+ #
unlock_index
- error "NOT FINISHED"
+ set selected_commit_type new
+ if {[string match amend* $commit_type]} {
+ $ui_comm delete 0.0 end
+ $ui_comm edit reset
+ $ui_comm edit modified false
+ rescan {set ui_status_value "Checked out branch '$current_branch'."}
+ } else {
+ repository_state commit_type HEAD MERGE_HEAD
+ set PARENT $HEAD
+ set ui_status_value "Checked out branch '$current_branch'."
+ }
}
######################################################################