1 from qtpy
import QtWidgets
2 from qtpy
import QtCore
3 from qtpy
.QtCore
import Qt
4 from qtpy
.QtCore
import Signal
7 from ..interaction
import Interaction
8 from ..qtutils
import get
11 from .. import qtutils
13 from . import completion
14 from . import standard
17 def create_new_branch(context
, revision
=''):
18 """Launches a dialog for creating a new branch"""
19 view
= CreateBranchDialog(context
, parent
=qtutils
.active_window())
21 view
.set_revision(revision
)
27 def __init__(self
, context
):
28 self
.context
= context
33 self
.revision
= 'HEAD'
37 class CreateThread(QtCore
.QThread
):
38 command
= Signal(object, object, object)
39 result
= Signal(object)
41 def __init__(self
, opts
, parent
):
42 QtCore
.QThread
.__init
__(self
, parent
)
46 branch
= self
.opts
.branch
47 revision
= self
.opts
.revision
48 reset
= self
.opts
.reset
49 checkout
= self
.opts
.checkout
50 track
= self
.opts
.track
51 context
= self
.opts
.context
57 if track
and '/' in revision
:
58 remote
= revision
.split('/', 1)[0]
59 status
, out
, err
= git
.fetch(remote
)
60 self
.command
.emit(status
, out
, err
)
61 results
.append(('fetch', status
, out
, err
))
64 status
, out
, err
= model
.create_branch(
65 branch
, revision
, force
=reset
, track
=track
67 self
.command
.emit(status
, out
, err
)
69 results
.append(('branch', status
, out
, err
))
70 if status
== 0 and checkout
:
71 status
, out
, err
= git
.checkout(branch
)
72 self
.command
.emit(status
, out
, err
)
73 results
.append(('checkout', status
, out
, err
))
76 self
.result
.emit(results
)
79 class CreateBranchDialog(standard
.Dialog
):
80 """A dialog for creating branches."""
82 def __init__(self
, context
, parent
=None):
83 standard
.Dialog
.__init
__(self
, parent
=parent
)
84 self
.setWindowTitle(N_('Create Branch'))
85 if parent
is not None:
86 self
.setWindowModality(Qt
.WindowModal
)
88 self
.context
= context
89 self
.model
= context
.model
90 self
.opts
= CreateOpts(context
)
91 self
.thread
= CreateThread(self
.opts
, self
)
95 self
.branch_name_label
= QtWidgets
.QLabel()
96 self
.branch_name_label
.setText(N_('Branch Name'))
98 self
.branch_name
= completion
.GitCreateBranchLineEdit(context
)
99 self
.branch_validator
= completion
.BranchValidator(
100 context
.git
, parent
=self
.branch_name
102 self
.branch_name
.setValidator(self
.branch_validator
)
104 self
.rev_label
= QtWidgets
.QLabel()
105 self
.rev_label
.setText(N_('Starting Revision'))
107 self
.revision
= completion
.GitRefLineEdit(context
)
108 current
= gitcmds
.current_branch(context
)
110 self
.revision
.setText(current
)
112 self
.local_radio
= qtutils
.radio(text
=N_('Local branch'), checked
=True)
113 self
.remote_radio
= qtutils
.radio(text
=N_('Tracking branch'))
114 self
.tag_radio
= qtutils
.radio(text
=N_('Tag'))
116 self
.branch_list
= QtWidgets
.QListWidget()
118 self
.update_existing_label
= QtWidgets
.QLabel()
119 self
.update_existing_label
.setText(N_('Update Existing Branch:'))
121 self
.no_update_radio
= qtutils
.radio(text
=N_('No'))
122 self
.ffwd_only_radio
= qtutils
.radio(text
=N_('Fast Forward Only'), checked
=True)
123 self
.reset_radio
= qtutils
.radio(text
=N_('Reset'))
125 text
= N_('Fetch Tracking Branch')
126 self
.fetch_checkbox
= qtutils
.checkbox(text
=text
, checked
=True)
128 text
= N_('Checkout After Creation')
129 self
.checkout_checkbox
= qtutils
.checkbox(text
=text
, checked
=True)
131 icon
= icons
.branch()
132 self
.create_button
= qtutils
.create_button(
133 text
=N_('Create Branch'), icon
=icon
, default
=True
135 self
.close_button
= qtutils
.close_button()
137 self
.options_checkbox_layout
= qtutils
.hbox(
141 self
.checkout_checkbox
,
145 self
.branch_name_layout
= qtutils
.hbox(
146 defs
.margin
, defs
.spacing
, self
.branch_name_label
, self
.branch_name
149 self
.rev_radio_group
= qtutils
.buttongroup(
150 self
.local_radio
, self
.remote_radio
, self
.tag_radio
153 self
.rev_radio_layout
= qtutils
.hbox(
162 self
.rev_start_textinput_layout
= qtutils
.hbox(
163 defs
.no_margin
, defs
.spacing
, self
.rev_label
, defs
.spacing
, self
.revision
166 self
.rev_start_layout
= qtutils
.vbox(
169 self
.rev_radio_layout
,
171 self
.rev_start_textinput_layout
,
174 self
.options_radio_group
= qtutils
.buttongroup(
175 self
.no_update_radio
, self
.ffwd_only_radio
, self
.reset_radio
178 self
.options_radio_layout
= qtutils
.hbox(
181 self
.update_existing_label
,
182 self
.no_update_radio
,
183 self
.ffwd_only_radio
,
188 self
.buttons_layout
= qtutils
.hbox(
196 self
.main_layout
= qtutils
.vbox(
199 self
.branch_name_layout
,
200 self
.rev_start_layout
,
202 self
.options_radio_layout
,
203 self
.options_checkbox_layout
,
206 self
.setLayout(self
.main_layout
)
208 qtutils
.add_close_action(self
)
209 qtutils
.connect_button(self
.close_button
, self
.close
)
210 qtutils
.connect_button(self
.create_button
, self
.create_branch
)
211 qtutils
.connect_toggle(self
.local_radio
, self
.display_model
)
212 qtutils
.connect_toggle(self
.remote_radio
, self
.display_model
)
213 qtutils
.connect_toggle(self
.tag_radio
, self
.display_model
)
215 branches
= self
.branch_list
216 branches
.itemSelectionChanged
.connect(self
.branch_item_changed
)
219 thread
.command
.connect(Interaction
.log_status
, type=Qt
.QueuedConnection
)
220 thread
.result
.connect(self
.thread_result
, type=Qt
.QueuedConnection
)
222 self
.init_size(settings
=context
.settings
, parent
=parent
)
225 def set_revision(self
, revision
):
226 self
.revision
.setText(revision
)
229 self
.opts
.revision
= get(self
.revision
)
230 self
.opts
.branch
= get(self
.branch_name
)
231 self
.opts
.checkout
= get(self
.checkout_checkbox
)
232 self
.opts
.reset
= get(self
.reset_radio
)
233 self
.opts
.fetch
= get(self
.fetch_checkbox
)
234 self
.opts
.track
= get(self
.remote_radio
)
236 def create_branch(self
):
237 """Creates a branch; called by the "Create Branch" button"""
238 context
= self
.context
240 revision
= self
.opts
.revision
241 branch
= self
.opts
.branch
242 no_update
= get(self
.no_update_radio
)
243 ffwd_only
= get(self
.ffwd_only_radio
)
244 existing_branches
= gitcmds
.branch_list(context
)
247 if not branch
or not revision
:
248 Interaction
.critical(
250 N_('Please provide both a branch name and revision expression.'),
253 if branch
in existing_branches
:
255 msg
= N_('Branch "%s" already exists.') % branch
256 Interaction
.critical(N_('Branch Exists'), msg
)
258 # Whether we should prompt the user for lost commits
259 commits
= gitcmds
.rev_list_range(context
, revision
, branch
)
260 check_branch
= bool(commits
)
263 msg
= N_('Resetting "%(branch)s" to "%(revision)s" will lose commits.') % {
265 'revision': revision
,
268 Interaction
.critical(N_('Branch Exists'), msg
)
271 for idx
, commit
in enumerate(commits
):
272 subject
= commit
[1][0 : min(len(commit
[1]), 16)]
273 if len(subject
) < len(commit
[1]):
275 lines
.append('\t' + commit
[0][:8] + '\t' + subject
)
277 skip
= len(commits
) - 5
278 lines
.append('\t(%s)' % (N_('%d skipped') % skip
))
280 line
= N_('Recovering lost commits may not be easy.')
283 info_text
= N_('Reset "%(branch)s" to "%(revision)s"?') % {
285 'revision': revision
,
288 if not Interaction
.confirm(
298 title
= N_('Create Branch')
299 label
= N_('Updating')
300 self
.progress
= standard
.progress(title
, label
, self
)
304 def thread_result(self
, results
):
308 for cmd
, status
, _
, _
in results
:
310 Interaction
.critical(
311 N_('Error Creating Branch'),
313 N_('"%(command)s" returned exit status "%(status)d"')
315 'command': 'git ' + cmd
,
324 def branch_item_changed(self
, *rest
):
325 """This callback is called when the branch selection changes"""
326 # When the branch selection changes then we should update
327 # the "Revision Expression" accordingly.
328 qlist
= self
.branch_list
329 remote_branch
= qtutils
.selected_item(qlist
, self
.branch_sources())
330 if not remote_branch
:
332 # Update the model with the selection
333 self
.revision
.setText(remote_branch
)
335 # Set the branch field if we're branching from a remote branch.
336 if not get(self
.remote_radio
):
338 branch
= gitcmds
.strip_remote(self
.model
.remotes
, remote_branch
)
341 # Signal that we've clicked on a remote branch
342 self
.branch_name
.set_value(branch
)
344 def display_model(self
):
345 """Sets the branch list to the available branches"""
346 branches
= self
.branch_sources()
347 qtutils
.set_items(self
.branch_list
, branches
)
349 def branch_sources(self
):
350 """Get the list of items for populating the branch root list."""
351 if get(self
.local_radio
):
352 value
= self
.model
.local_branches
353 elif get(self
.remote_radio
):
354 value
= self
.model
.remote_branches
355 elif get(self
.tag_radio
):
356 value
= self
.model
.tags
362 self
.branch_name
.dispose()
363 self
.revision
.dispose()