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 # pylint: disable=no-member
217 branches
.itemSelectionChanged
.connect(self
.branch_item_changed
)
220 thread
.command
.connect(Interaction
.log_status
, type=Qt
.QueuedConnection
)
221 thread
.result
.connect(self
.thread_result
, type=Qt
.QueuedConnection
)
223 self
.init_size(settings
=context
.settings
, parent
=parent
)
226 def set_revision(self
, revision
):
227 self
.revision
.setText(revision
)
230 self
.opts
.revision
= get(self
.revision
)
231 self
.opts
.branch
= get(self
.branch_name
)
232 self
.opts
.checkout
= get(self
.checkout_checkbox
)
233 self
.opts
.reset
= get(self
.reset_radio
)
234 self
.opts
.fetch
= get(self
.fetch_checkbox
)
235 self
.opts
.track
= get(self
.remote_radio
)
237 def create_branch(self
):
238 """Creates a branch; called by the "Create Branch" button"""
239 context
= self
.context
241 revision
= self
.opts
.revision
242 branch
= self
.opts
.branch
243 no_update
= get(self
.no_update_radio
)
244 ffwd_only
= get(self
.ffwd_only_radio
)
245 existing_branches
= gitcmds
.branch_list(context
)
248 if not branch
or not revision
:
249 Interaction
.critical(
251 N_('Please provide both a branch name and revision expression.'),
254 if branch
in existing_branches
:
256 msg
= N_('Branch "%s" already exists.') % branch
257 Interaction
.critical(N_('Branch Exists'), msg
)
259 # Whether we should prompt the user for lost commits
260 commits
= gitcmds
.rev_list_range(context
, revision
, branch
)
261 check_branch
= bool(commits
)
264 msg
= N_('Resetting "%(branch)s" to "%(revision)s" will lose commits.') % {
266 'revision': revision
,
269 Interaction
.critical(N_('Branch Exists'), msg
)
272 for idx
, commit
in enumerate(commits
):
273 subject
= commit
[1][0 : min(len(commit
[1]), 16)]
274 if len(subject
) < len(commit
[1]):
276 lines
.append('\t' + commit
[0][:8] + '\t' + subject
)
278 skip
= len(commits
) - 5
279 lines
.append('\t(%s)' % (N_('%d skipped') % skip
))
281 line
= N_('Recovering lost commits may not be easy.')
284 info_text
= N_('Reset "%(branch)s" to "%(revision)s"?') % {
286 'revision': revision
,
289 if not Interaction
.confirm(
299 title
= N_('Create Branch')
300 label
= N_('Updating')
301 self
.progress
= standard
.progress(title
, label
, self
)
305 def thread_result(self
, results
):
309 for cmd
, status
, _
, _
in results
:
311 Interaction
.critical(
312 N_('Error Creating Branch'),
314 N_('"%(command)s" returned exit status "%(status)d"')
316 'command': 'git ' + cmd
,
325 # pylint: disable=unused-argument
326 def branch_item_changed(self
, *rest
):
327 """This callback is called when the branch selection changes"""
328 # When the branch selection changes then we should update
329 # the "Revision Expression" accordingly.
330 qlist
= self
.branch_list
331 remote_branch
= qtutils
.selected_item(qlist
, self
.branch_sources())
332 if not remote_branch
:
334 # Update the model with the selection
335 self
.revision
.setText(remote_branch
)
337 # Set the branch field if we're branching from a remote branch.
338 if not get(self
.remote_radio
):
340 branch
= gitcmds
.strip_remote(self
.model
.remotes
, remote_branch
)
343 # Signal that we've clicked on a remote branch
344 self
.branch_name
.set_value(branch
)
346 def display_model(self
):
347 """Sets the branch list to the available branches"""
348 branches
= self
.branch_sources()
349 qtutils
.set_items(self
.branch_list
, branches
)
351 def branch_sources(self
):
352 """Get the list of items for populating the branch root list."""
353 if get(self
.local_radio
):
354 value
= self
.model
.local_branches
355 elif get(self
.remote_radio
):
356 value
= self
.model
.remote_branches
357 elif get(self
.tag_radio
):
358 value
= self
.model
.tags
364 self
.branch_name
.dispose()
365 self
.revision
.dispose()