1 # git-gui branch (create/delete) support
2 # Copyright (C) 2006, 2007 Shawn Pearce
4 proc load_all_heads
{} {
6 global some_heads_tracking
9 set rh_len
[expr {[string length
$rh] + 1}]
11 set fd
[open "| git for-each-ref --format=%(refname) $rh" r
]
12 while {[gets $fd line
] > 0} {
13 if {!$some_heads_tracking ||
![is_tracking_branch
$line]} {
14 lappend all_heads
[string range
$line $rh_len end
]
19 set all_heads
[lsort $all_heads]
22 proc load_all_tags
{} {
24 set fd
[open "| git for-each-ref --format=%(refname) refs/tags" r
]
25 while {[gets $fd line
] > 0} {
26 if {![regsub ^refs
/tags
/ $line {} name
]} continue
27 lappend all_tags
$name
31 return [lsort $all_tags]
34 proc populate_branch_menu
{} {
35 global all_heads disable_on_lock
38 set last
[$m index last
]
39 for {set i
0} {$i <= $last} {incr i
} {
40 if {[$m type
$i] eq
{separator
}} {
43 foreach a
$disable_on_lock {
44 if {[lindex $a 0] ne
$m ||
[lindex $a 2] < $i} {
48 set disable_on_lock
$new_dol
53 if {$all_heads ne
{}} {
56 foreach b
$all_heads {
59 -command [list switch_branch
$b] \
60 -variable current_branch
\
62 lappend disable_on_lock
\
63 [list $m entryconf
[$m index last
] -state]
67 proc radio_selector
{varname value args
} {
72 proc switch_branch
{new_branch
} {
73 global HEAD commit_type current_branch repo_config
75 if {![lock_index
switch]} return
77 # -- Our in memory state should match the repository.
79 repository_state curType curHEAD curMERGE_HEAD
80 if {[string match amend
* $commit_type]
81 && $curType eq
{normal
}
82 && $curHEAD eq
$HEAD} {
83 } elseif
{$commit_type ne
$curType ||
$HEAD ne
$curHEAD} {
84 info_popup
{Last scanned state does not match repository state.
86 Another Git program has modified this repository since the last
scan. A rescan must be performed before the current branch can be changed.
88 The rescan will be automatically started now.
91 rescan
{set ui_status_value
{Ready.
}}
95 # -- Don't do a pointless switch.
97 if {$current_branch eq
$new_branch} {
102 if {$repo_config(gui.trustmtime
) eq
{true
}} {
103 switch_branch_stage2
{} $new_branch
105 set ui_status_value
{Refreshing
file status...
}
106 set cmd
[list git update-index
]
108 lappend cmd
--unmerged
109 lappend cmd
--ignore-missing
110 lappend cmd
--refresh
111 set fd_rf
[open "| $cmd" r
]
112 fconfigure $fd_rf -blocking 0 -translation binary
113 fileevent $fd_rf readable
\
114 [list switch_branch_stage2
$fd_rf $new_branch]
118 proc switch_branch_stage2
{fd_rf new_branch
} {
119 global ui_status_value HEAD
123 if {![eof $fd_rf]} return
127 set ui_status_value
"Updating working directory to '$new_branch'..."
128 set cmd
[list git read-tree
]
131 lappend cmd
--exclude-per
-directory
=.gitignore
133 lappend cmd
$new_branch
134 set fd_rt
[open "| $cmd" r
]
135 fconfigure $fd_rt -blocking 0 -translation binary
136 fileevent $fd_rt readable
\
137 [list switch_branch_readtree_wait
$fd_rt $new_branch]
140 proc switch_branch_readtree_wait
{fd_rt new_branch
} {
141 global selected_commit_type commit_type HEAD MERGE_HEAD PARENT
142 global current_branch
143 global ui_comm ui_status_value
145 # -- We never get interesting output on stdout; only stderr.
148 fconfigure $fd_rt -blocking 1
150 fconfigure $fd_rt -blocking 0
154 # -- The working directory wasn't in sync with the index and
155 # we'd have to overwrite something to make the switch. A
158 if {[catch {close $fd_rt} err
]} {
159 regsub {^fatal
: } $err {} err
160 warn_popup
"File level merge required.
164 Staying on branch '$current_branch'."
165 set ui_status_value
"Aborted checkout of '$new_branch' (file level merging is required)."
170 # -- Update the symbolic ref. Core git doesn't even check for failure
171 # here, it Just Works(tm). If it doesn't we are in some really ugly
172 # state that is difficult to recover from within git-gui.
174 if {[catch {git symbolic-ref HEAD
"refs/heads/$new_branch"} err
]} {
175 error_popup
"Failed to set current branch.
177 This working directory is only partially switched. We successfully updated your files, but failed to update an internal Git file.
179 This should not have occurred. [appname] will now close and give up.
186 # -- Update our repository state. If we were previously in amend mode
187 # we need to toss the current buffer and do a full rescan to update
188 # our file lists. If we weren't in amend mode our file lists are
189 # accurate and we can avoid the rescan.
192 set selected_commit_type new
193 if {[string match amend
* $commit_type]} {
194 $ui_comm delete
0.0 end
196 $ui_comm edit modified false
197 rescan
{set ui_status_value
"Checked out branch '$current_branch'."}
199 repository_state commit_type HEAD MERGE_HEAD
201 set ui_status_value
"Checked out branch '$current_branch'."