@@ -2155,16 +2155,11 @@ proc do_delete_branch {} {
2155
2155
tkwait window $w
2156
2156
}
2157
2157
2158
- proc switch_branch {b} {
2159
- global HEAD commit_type file_states current_branch
2160
- global selected_commit_type ui_comm
2158
+ proc switch_branch {new_branch} {
2159
+ global HEAD commit_type current_branch repo_config
2161
2160
2162
2161
if {![lock_index switch]} return
2163
2162
2164
- # -- Backup the selected branch (repository_state resets it)
2165
- #
2166
- set new_branch $current_branch
2167
-
2168
2163
# -- Our in memory state should match the repository.
2169
2164
#
2170
2165
repository_state curType curHEAD curMERGE_HEAD
@@ -2185,19 +2180,110 @@ The rescan will be automatically started now.
2185
2180
return
2186
2181
}
2187
2182
2188
- # -- Toss the message buffer if we are in amend mode.
2183
+ if {$repo_config(gui.trustmtime) eq {true}} {
2184
+ switch_branch_stage2 {} $new_branch
2185
+ } else {
2186
+ set ui_status_value {Refreshing file status...}
2187
+ set cmd [list git update-index]
2188
+ lappend cmd -q
2189
+ lappend cmd --unmerged
2190
+ lappend cmd --ignore-missing
2191
+ lappend cmd --refresh
2192
+ set fd_rf [open " | $cmd " r]
2193
+ fconfigure $fd_rf -blocking 0 -translation binary
2194
+ fileevent $fd_rf readable \
2195
+ [list switch_branch_stage2 $fd_rf $new_branch ]
2196
+ }
2197
+ }
2198
+
2199
+ proc switch_branch_stage2 {fd_rf new_branch} {
2200
+ global ui_status_value HEAD
2201
+
2202
+ if {$fd_rf ne {}} {
2203
+ read $fd_rf
2204
+ if {![eof $fd_rf ]} return
2205
+ close $fd_rf
2206
+ }
2207
+
2208
+ set ui_status_value " Updating working directory to '$new_branch '..."
2209
+ set cmd [list git read-tree]
2210
+ lappend cmd -m
2211
+ lappend cmd -u
2212
+ lappend cmd --exclude-per-directory=.gitignore
2213
+ lappend cmd $HEAD
2214
+ lappend cmd $new_branch
2215
+ set fd_rt [open " | $cmd " r]
2216
+ fconfigure $fd_rt -blocking 0 -translation binary
2217
+ fileevent $fd_rt readable \
2218
+ [list switch_branch_readtree_wait $fd_rt $new_branch ]
2219
+ }
2220
+
2221
+ proc switch_branch_readtree_wait {fd_rt new_branch} {
2222
+ global selected_commit_type commit_type HEAD MERGE_HEAD PARENT
2223
+ global current_branch
2224
+ global ui_comm ui_status_value
2225
+
2226
+ # -- We never get interesting output on stdout; only stderr.
2189
2227
#
2190
- if {[string match amend* $curType ]} {
2191
- $ui_comm delete 0.0 end
2192
- $ui_comm edit reset
2193
- $ui_comm edit modified false
2228
+ read $fd_rt
2229
+ fconfigure $fd_rt -blocking 1
2230
+ if {![eof $fd_rt ]} {
2231
+ fconfigure $fd_rt -blocking 0
2232
+ return
2194
2233
}
2195
2234
2196
- set selected_commit_type new
2197
- set current_branch $new_branch
2235
+ # -- The working directory wasn't in sync with the index and
2236
+ # we'd have to overwrite something to make the switch. A
2237
+ # merge is required.
2238
+ #
2239
+ if {[catch {close $fd_rt } err]} {
2240
+ regsub {^fatal: } $err {} err
2241
+ warn_popup " File level merge required.
2242
+
2243
+ $err
2244
+
2245
+ Staying on branch '$current_branch '."
2246
+ set ui_status_value " Aborted checkout of '$new_branch ' (file level merging is required)."
2247
+ unlock_index
2248
+ return
2249
+ }
2250
+
2251
+ # -- Update the symbolic ref. Core git doesn't even check for failure
2252
+ # here, it Just Works(tm). If it doesn't we are in some really ugly
2253
+ # state that is difficult to recover from within git-gui.
2254
+ #
2255
+ if {[catch {exec git symbolic-ref HEAD " refs/heads/$new_branch " } err]} {
2256
+ error_popup " Failed to set current branch.
2257
+
2258
+ This working directory is only partially switched.
2259
+ We successfully updated your files, but failed to
2260
+ update an internal Git file.
2261
+
2262
+ This should not have occurred. [ appname] will now
2263
+ close and give up.
2198
2264
2265
+ $err "
2266
+ do_quit
2267
+ return
2268
+ }
2269
+
2270
+ # -- Update our repository state. If we were previously in amend mode
2271
+ # we need to toss the current buffer and do a full rescan to update
2272
+ # our file lists. If we weren't in amend mode our file lists are
2273
+ # accurate and we can avoid the rescan.
2274
+ #
2199
2275
unlock_index
2200
- error " NOT FINISHED"
2276
+ set selected_commit_type new
2277
+ if {[string match amend* $commit_type ]} {
2278
+ $ui_comm delete 0.0 end
2279
+ $ui_comm edit reset
2280
+ $ui_comm edit modified false
2281
+ rescan {set ui_status_value " Checked out branch '$current_branch '." }
2282
+ } else {
2283
+ repository_state commit_type HEAD MERGE_HEAD
2284
+ set PARENT $HEAD
2285
+ set ui_status_value " Checked out branch '$current_branch '."
2286
+ }
2201
2287
}
2202
2288
2203
2289
# #####################################################################
0 commit comments