| 1 | # git-gui branch create support |
| 2 | # Copyright (C) 2006, 2007 Shawn Pearce |
| 3 | |
| 4 | class branch_create { |
| 5 | |
| 6 | field w ; # widget path |
| 7 | field w_rev ; # mega-widget to pick the initial revision |
| 8 | field w_name ; # new branch name widget |
| 9 | |
| 10 | field name {}; # name of the branch the user has chosen |
| 11 | field name_type user; # type of branch name to use |
| 12 | |
| 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 opt_fetch 1; # refetch tracking branch if used? |
| 16 | field reset_ok 0; # did the user agree to reset? |
| 17 | |
| 18 | constructor dialog {} { |
| 19 | global repo_config |
| 20 | |
| 21 | make_dialog top w |
| 22 | wm withdraw $w |
| 23 | wm title $top [mc "%s (%s): Create Branch" [appname] [reponame]] |
| 24 | if {$top ne {.}} { |
| 25 | wm geometry $top "+[winfo rootx .]+[winfo rooty .]" |
| 26 | } |
| 27 | |
| 28 | ttk::label $w.header -text [mc "Create New Branch"] \ |
| 29 | -font font_uibold -anchor center |
| 30 | pack $w.header -side top -fill x |
| 31 | |
| 32 | ttk::frame $w.buttons |
| 33 | ttk::button $w.buttons.create -text [mc Create] \ |
| 34 | -default active \ |
| 35 | -command [cb _create] |
| 36 | pack $w.buttons.create -side right |
| 37 | ttk::button $w.buttons.cancel -text [mc Cancel] \ |
| 38 | -command [list destroy $w] |
| 39 | pack $w.buttons.cancel -side right -padx 5 |
| 40 | pack $w.buttons -side bottom -fill x -pady 10 -padx 10 |
| 41 | |
| 42 | ttk::labelframe $w.desc -text [mc "Branch Name"] |
| 43 | ttk::radiobutton $w.desc.name_r \ |
| 44 | -text [mc "Name:"] \ |
| 45 | -value user \ |
| 46 | -variable @name_type |
| 47 | set w_name $w.desc.name_t |
| 48 | ttk::entry $w_name \ |
| 49 | -width 40 \ |
| 50 | -textvariable @name \ |
| 51 | -validate key \ |
| 52 | -validatecommand [cb _validate %d %S] |
| 53 | grid $w.desc.name_r $w_name -sticky we -padx {0 5} |
| 54 | |
| 55 | ttk::radiobutton $w.desc.match_r \ |
| 56 | -text [mc "Match Tracking Branch Name"] \ |
| 57 | -value match \ |
| 58 | -variable @name_type |
| 59 | grid $w.desc.match_r -sticky we -padx {0 5} -columnspan 2 |
| 60 | |
| 61 | grid columnconfigure $w.desc 1 -weight 1 |
| 62 | pack $w.desc -anchor nw -fill x -pady 5 -padx 5 |
| 63 | |
| 64 | set w_rev [::choose_rev::new $w.rev [mc "Starting Revision"]] |
| 65 | pack $w.rev -anchor nw -fill both -expand 1 -pady 5 -padx 5 |
| 66 | |
| 67 | ttk::labelframe $w.options -text [mc Options] |
| 68 | |
| 69 | ttk::frame $w.options.merge |
| 70 | ttk::label $w.options.merge.l -text [mc "Update Existing Branch:"] |
| 71 | pack $w.options.merge.l -side left |
| 72 | ttk::radiobutton $w.options.merge.no \ |
| 73 | -text [mc No] \ |
| 74 | -value none \ |
| 75 | -variable @opt_merge |
| 76 | pack $w.options.merge.no -side left |
| 77 | ttk::radiobutton $w.options.merge.ff \ |
| 78 | -text [mc "Fast Forward Only"] \ |
| 79 | -value ff \ |
| 80 | -variable @opt_merge |
| 81 | pack $w.options.merge.ff -side left |
| 82 | ttk::radiobutton $w.options.merge.reset \ |
| 83 | -text [mc Reset] \ |
| 84 | -value reset \ |
| 85 | -variable @opt_merge |
| 86 | pack $w.options.merge.reset -side left |
| 87 | pack $w.options.merge -anchor nw |
| 88 | |
| 89 | ttk::checkbutton $w.options.fetch \ |
| 90 | -text [mc "Fetch Tracking Branch"] \ |
| 91 | -variable @opt_fetch |
| 92 | pack $w.options.fetch -anchor nw |
| 93 | |
| 94 | ttk::checkbutton $w.options.checkout \ |
| 95 | -text [mc "Checkout After Creation"] \ |
| 96 | -variable @opt_checkout |
| 97 | pack $w.options.checkout -anchor nw |
| 98 | pack $w.options -anchor nw -fill x -pady 5 -padx 5 |
| 99 | |
| 100 | trace add variable @name_type write [cb _select] |
| 101 | |
| 102 | set name $repo_config(gui.newbranchtemplate) |
| 103 | if {[is_config_true gui.matchtrackingbranch]} { |
| 104 | set name_type match |
| 105 | } |
| 106 | |
| 107 | bind $w <Visibility> [cb _visible] |
| 108 | bind $w <Key-Escape> [list destroy $w] |
| 109 | bind $w <Key-Return> [cb _create]\;break |
| 110 | wm deiconify $w |
| 111 | tkwait window $w |
| 112 | } |
| 113 | |
| 114 | method _create {} { |
| 115 | global repo_config |
| 116 | global M1B |
| 117 | |
| 118 | set spec [$w_rev get_tracking_branch] |
| 119 | switch -- $name_type { |
| 120 | user { |
| 121 | set newbranch $name |
| 122 | } |
| 123 | match { |
| 124 | if {$spec eq {}} { |
| 125 | tk_messageBox \ |
| 126 | -icon error \ |
| 127 | -type ok \ |
| 128 | -title [wm title $w] \ |
| 129 | -parent $w \ |
| 130 | -message [mc "Please select a tracking branch."] |
| 131 | return |
| 132 | } |
| 133 | if {![regsub ^refs/heads/ [lindex $spec 2] {} newbranch]} { |
| 134 | tk_messageBox \ |
| 135 | -icon error \ |
| 136 | -type ok \ |
| 137 | -title [wm title $w] \ |
| 138 | -parent $w \ |
| 139 | -message [mc "Tracking branch %s is not a branch in the remote repository." [$w get]] |
| 140 | return |
| 141 | } |
| 142 | } |
| 143 | } |
| 144 | |
| 145 | if {$newbranch eq {} |
| 146 | || $newbranch eq $repo_config(gui.newbranchtemplate)} { |
| 147 | tk_messageBox \ |
| 148 | -icon error \ |
| 149 | -type ok \ |
| 150 | -title [wm title $w] \ |
| 151 | -parent $w \ |
| 152 | -message [mc "Please supply a branch name."] |
| 153 | focus $w_name |
| 154 | return |
| 155 | } |
| 156 | |
| 157 | if {[catch {git check-ref-format "heads/$newbranch"}]} { |
| 158 | tk_messageBox \ |
| 159 | -icon error \ |
| 160 | -type ok \ |
| 161 | -title [wm title $w] \ |
| 162 | -parent $w \ |
| 163 | -message [mc "'%s' is not an acceptable branch name." $newbranch] |
| 164 | focus $w_name |
| 165 | return |
| 166 | } |
| 167 | |
| 168 | if {$spec ne {} && $opt_fetch} { |
| 169 | set new {} |
| 170 | } elseif {[catch {set new [$w_rev commit_or_die]}]} { |
| 171 | return |
| 172 | } |
| 173 | |
| 174 | set co [::checkout_op::new \ |
| 175 | [$w_rev get] \ |
| 176 | $new \ |
| 177 | refs/heads/$newbranch] |
| 178 | $co parent $w |
| 179 | $co enable_create 1 |
| 180 | $co enable_merge $opt_merge |
| 181 | $co enable_checkout $opt_checkout |
| 182 | if {$spec ne {} && $opt_fetch} { |
| 183 | $co enable_fetch $spec |
| 184 | } |
| 185 | if {$spec ne {}} { |
| 186 | $co remote_source $spec |
| 187 | } |
| 188 | |
| 189 | if {[$co run]} { |
| 190 | destroy $w |
| 191 | } else { |
| 192 | focus $w_name |
| 193 | } |
| 194 | } |
| 195 | |
| 196 | method _validate {d S} { |
| 197 | if {$d == 1} { |
| 198 | if {[regexp {[~^:?*\[\0- ]} $S]} { |
| 199 | return 0 |
| 200 | } |
| 201 | if {[string length $S] > 0} { |
| 202 | set name_type user |
| 203 | } |
| 204 | } |
| 205 | return 1 |
| 206 | } |
| 207 | |
| 208 | method _select {args} { |
| 209 | if {$name_type eq {match}} { |
| 210 | $w_rev pick_tracking_branch |
| 211 | } |
| 212 | } |
| 213 | |
| 214 | method _visible {} { |
| 215 | grab $w |
| 216 | if {$name_type eq {user}} { |
| 217 | $w_name icursor end |
| 218 | focus $w_name |
| 219 | } |
| 220 | } |
| 221 | |
| 222 | } |