1 # git-gui branch create support
2 # Copyright (C) 2006, 2007 Shawn Pearce
6 field w
; # widget path
7 field w_rev
; # mega-widget to pick the initial revision
8 field w_name
; # new branch name widget
10 field name
{}; # name of the branch the user has chosen
11 field name_type user
; # type of branch name to use
13 field opt_merge ff
; # type of merge to apply to existing branch
14 field opt_checkout
1; # automatically checkout the new branch?
15 field reset_ok
0; # did the user agree to reset?
17 constructor dialog
{} {
21 wm title
$top "[appname] ([reponame]): Create Branch"
23 wm geometry
$top "+[winfo rootx .]+[winfo rooty .]"
26 label $w.header
-text {Create New Branch
} -font font_uibold
27 pack $w.header
-side top
-fill x
30 button $w.buttons.create
-text Create
\
33 pack $w.buttons.create
-side right
34 button $w.buttons.cancel
-text {Cancel
} \
35 -command [list destroy $w]
36 pack $w.buttons.cancel
-side right
-padx 5
37 pack $w.buttons
-side bottom
-fill x
-pady 10 -padx 10
39 labelframe $w.desc
-text {Branch Name
}
40 radiobutton $w.desc.name_r
\
45 set w_name
$w.desc.name_t
52 -validatecommand [cb _validate
%d
%S
]
53 grid $w.desc.name_r
$w_name -sticky we
-padx {0 5}
55 radiobutton $w.desc.match_r
\
57 -text {Match Tracking Branch Name
} \
60 grid $w.desc.match_r
-sticky we
-padx {0 5} -columnspan 2
62 grid columnconfigure
$w.desc
1 -weight 1
63 pack $w.desc
-anchor nw
-fill x
-pady 5 -padx 5
65 set w_rev
[::choose_rev::new $w.rev
{Starting Revision
}]
66 pack $w.rev
-anchor nw
-fill both
-expand 1 -pady 5 -padx 5
68 labelframe $w.
options -text {Options
}
70 frame $w.
options.merge
71 label $w.
options.merge.l
-text {Update Existing Branch
:}
72 pack $w.
options.merge.l
-side left
73 radiobutton $w.
options.merge.no
\
77 pack $w.
options.merge.no
-side left
78 radiobutton $w.
options.merge.ff
\
79 -text {Fast Forward Only
} \
82 pack $w.
options.merge.ff
-side left
83 radiobutton $w.
options.merge.reset
\
87 pack $w.
options.merge.reset
-side left
88 pack $w.
options.merge
-anchor nw
90 checkbutton $w.
options.checkout
\
91 -text {Checkout After Creation
} \
92 -variable @opt_checkout
93 pack $w.
options.checkout
-anchor nw
94 pack $w.
options -anchor nw
-fill x
-pady 5 -padx 5
96 trace add
variable @name_type write
[cb _select
]
98 set name
$repo_config(gui.newbranchtemplate
)
99 if {[is_config_true gui.matchtrackingbranch
]} {
103 bind $w <Visibility
> [cb _visible
]
104 bind $w <Key-Escape
> [list destroy $w]
105 bind $w <Key-Return
> [cb _create
]\;break
110 global null_sha1 repo_config
111 global all_heads current_branch
113 switch -- $name_type {
118 set spec
[$w_rev get_tracking_branch
]
123 -title [wm title
$w] \
125 -message "Please select a tracking branch."
128 if {![regsub ^refs
/heads
/ [lindex $spec 2] {} newbranch
]} {
132 -title [wm title
$w] \
134 -message "Tracking branch [$w get] is not a branch in the remote repository."
141 ||
$newbranch eq
$repo_config(gui.newbranchtemplate
)} {
145 -title [wm title
$w] \
147 -message "Please supply a branch name."
152 if {$newbranch eq
$current_branch} {
156 -title [wm title
$w] \
158 -message "'$newbranch' already exists and is the current branch."
163 if {[catch {git check-ref-format
"heads/$newbranch"}]} {
167 -title [wm title
$w] \
169 -message "'$newbranch' is not an acceptable branch name."
174 if {[catch {set new
[$w_rev commit_or_die
]}]} {
178 set ref refs
/heads
/$newbranch
179 if {[catch {set cur
[git rev-parse
--verify "$ref^0"]}]} {
180 # Assume it does not exist, and that is what the error was.
182 set reflog_msg
"branch: Created from [$w_rev get]"
184 } elseif
{$opt_merge eq
{no
}} {
188 -title [wm title
$w] \
190 -message "Branch '$newbranch' already exists."
195 catch {set mrb
[git merge-base
$new $cur]}
196 switch -- $opt_merge {
199 # The current branch is actually newer.
202 } elseif
{$mrb eq
$cur} {
203 # The current branch is older.
205 set reflog_msg
"merge [$w_rev get]: Fast-forward"
210 -title [wm title
$w] \
212 -message "Branch '$newbranch' already exists.\n\nIt cannot fast-forward to [$w_rev get].\nA merge is required."
219 # The current branch is older.
221 set reflog_msg
"merge [$w_rev get]: Fast-forward"
223 # The current branch will lose things.
225 if {[_confirm_reset
$this $newbranch $cur $new]} {
226 set reflog_msg
"reset [$w_rev get]"
236 -title [wm title
$w] \
238 -message "Branch '$newbranch' already exists."
247 git update-ref
-m $reflog_msg $ref $new $cur
252 -title [wm title
$w] \
254 -message "Failed to create '$newbranch'.\n\n$err"
259 if {$cur eq
$null_sha1} {
260 lappend all_heads
$newbranch
261 set all_heads
[lsort -uniq $all_heads]
267 switch_branch
$newbranch
271 method _confirm_reset
{newbranch cur new
} {
273 set gitk
[list do_gitk
[list $cur ^
$new]]
275 set c
$w.confirm_reset
277 wm title
$c "Confirm Branch Reset"
278 wm geometry
$c "+[winfo rootx $w]+[winfo rooty $w]"
280 pack [label $c.msg1
\
283 -text "Resetting '$newbranch' to [$w_rev get] will lose the following commits:" \
293 -xscrollcommand [list $c.
list.sbx
set] \
294 -yscrollcommand [list $c.
list.sby
set]
295 scrollbar $c.
list.sbx
-orient h
-command [list $list xview
]
296 scrollbar $c.
list.sby
-orient v
-command [list $list yview
]
297 pack $c.
list.sbx
-fill x
-side bottom
298 pack $c.
list.sby
-fill y
-side right
299 pack $list -fill both
-expand 1
300 pack $c.
list -fill both
-expand 1 -padx 5 -pady 5
302 pack [label $c.msg2
\
305 -text "Recovering lost commits may not be easy." \
307 pack [label $c.msg3
\
310 -text "Reset '$newbranch'?" \
314 button $c.buttons.visualize
\
317 pack $c.buttons.visualize
-side left
318 button $c.buttons.reset
\
324 pack $c.buttons.reset
-side right
325 button $c.buttons.cancel
\
328 -command [list destroy $c]
329 pack $c.buttons.cancel
-side right
-padx 5
330 pack $c.buttons
-side bottom
-fill x
-pady 10 -padx 10
332 set fd
[open "| git rev-list --pretty=oneline $cur ^$new" r
]
333 while {[gets $fd line
] > 0} {
334 set abbr
[string range
$line 0 7]
335 set subj
[string range
$line 41 end
]
336 $list insert end
"$abbr $subj\n"
339 $list configure
-state disabled
341 bind $c <Key-v
> $gitk
343 bind $c <Visibility
> "
345 focus $c.buttons.cancel
347 bind $c <Key-Return
> [list destroy $c]
348 bind $c <Key-Escape
> [list destroy $c]
353 method _validate
{d S
} {
355 if {[regexp {[~^
:?
*\[\0- ]} $S]} {
358 if {[string length
$S] > 0} {
365 method _select
{args
} {
366 if {$name_type eq
{match
}} {
367 $w_rev pick_tracking_branch
373 if {$name_type eq
{user
}} {