1 """Widgets for Fetch, Push, and Pull"""
5 from qtpy
import QtWidgets
6 from qtpy
.QtCore
import Qt
9 from ..interaction
import Interaction
10 from ..models
import main
11 from ..qtutils
import connect_button
12 from ..qtutils
import get
15 from .. import gitcmds
17 from .. import qtutils
21 from . import standard
30 """Fetch from remote repositories"""
31 return run(context
, Fetch
)
35 """Push to remote repositories"""
36 return run(context
, Push
)
40 """Pull from remote repositories"""
41 return run(context
, Pull
)
44 def run(context
, RemoteDialog
):
45 """Launches fetch/push/pull dialogs."""
46 # Copy global stuff over to speedup startup
47 parent
= qtutils
.active_window()
48 view
= RemoteDialog(context
, parent
=parent
)
53 def combine(result
, prev
):
54 """Combine multiple (status, out, err) tuples into a combined tuple
56 The current state is passed in via `prev`.
57 The status code is a max() over all the subprocess status codes.
58 Individual (out, err) strings are sequentially concatenated together.
61 if isinstance(prev
, (tuple, list)):
63 raise AssertionError('combine() with length %d' % len(prev
))
65 max(prev
[0], result
[0]),
66 combine(prev
[1], result
[1]),
67 combine(prev
[2], result
[2]),
70 combined
= prev
+ '\n\n' + result
79 def uncheck(value
, *checkboxes
):
80 """Uncheck the specified checkboxes if value is True"""
82 for checkbox
in checkboxes
:
83 checkbox
.setChecked(False)
86 def strip_remotes(remote_branches
):
87 """Strip the <remote>/ prefixes from branches
89 e.g. "origin/main" becomes "main".
92 branches
= [utils
.strip_one(branch
) for branch
in remote_branches
]
93 return [branch
for branch
in branches
if branch
!= 'HEAD']
96 def get_default_remote(context
):
97 """Get the name of the default remote to use for pushing.
99 This will be the remote the branch is set to track, if it is set. If it
100 is not, remote.pushDefault will be used (or origin if not set)
103 upstream_remote
= gitcmds
.upstream_remote(context
)
104 return upstream_remote
or context
.cfg
.get('remote.pushDefault', default
='origin')
107 class ActionTask(qtutils
.Task
):
108 """Run actions asynchronously"""
110 def __init__(self
, model_action
, remote
, kwargs
):
111 qtutils
.Task
.__init
__(self
)
112 self
.model_action
= model_action
117 """Runs the model action and captures the result"""
118 return self
.model_action(self
.remote
, **self
.kwargs
)
121 class RemoteActionDialog(standard
.Dialog
):
122 """Interface for performing remote operations"""
124 def __init__(self
, context
, action
, title
, parent
=None, icon
=None):
125 """Customize the dialog based on the remote action"""
126 standard
.Dialog
.__init
__(self
, parent
=parent
)
127 self
.setWindowTitle(title
)
128 if parent
is not None:
129 self
.setWindowModality(Qt
.WindowModal
)
131 self
.context
= context
132 self
.model
= model
= context
.model
134 self
.filtered_remote_branches
= []
135 self
.selected_remotes
= []
137 self
.runtask
= qtutils
.RunTask(parent
=self
)
138 self
.local_label
= QtWidgets
.QLabel()
139 self
.local_label
.setText(N_('Local Branch'))
141 self
.local_branch
= QtWidgets
.QLineEdit()
142 qtutils
.add_completer(self
.local_branch
, model
.local_branches
)
143 self
.local_branch
.textChanged
.connect(lambda x
: self
.update_command_display())
145 self
.local_branches
= QtWidgets
.QListWidget()
146 self
.local_branches
.addItems(model
.local_branches
)
148 self
.remote_label
= QtWidgets
.QLabel()
149 self
.remote_label
.setText(N_('Remote'))
151 self
.remote_name
= QtWidgets
.QLineEdit()
152 qtutils
.add_completer(self
.remote_name
, model
.remotes
)
154 self
.remote_name
.editingFinished
.connect(self
.remote_name_edited
)
155 self
.remote_name
.textEdited
.connect(lambda x
: self
.remote_name_edited())
157 self
.remotes
= QtWidgets
.QListWidget()
159 mode
= QtWidgets
.QAbstractItemView
.ExtendedSelection
160 self
.remotes
.setSelectionMode(mode
)
161 self
.remotes
.addItems(model
.remotes
)
163 self
.remote_branch_label
= QtWidgets
.QLabel()
164 self
.remote_branch_label
.setText(N_('Remote Branch'))
166 self
.remote_branch
= QtWidgets
.QLineEdit()
167 remote_branches
= strip_remotes(model
.remote_branches
)
168 qtutils
.add_completer(self
.remote_branch
, remote_branches
)
170 self
.remote_branches
= QtWidgets
.QListWidget()
171 self
.remote_branches
.addItems(model
.remote_branches
)
173 text
= N_('Prompt on creation')
174 tooltip
= N_('Prompt when pushing creates new remote branches')
175 self
.prompt_checkbox
= qtutils
.checkbox(
176 checked
=True, text
=text
, tooltip
=tooltip
179 text
= N_('Show remote messages')
180 tooltip
= N_('Display remote messages in a separate dialog')
181 self
.remote_messages_checkbox
= qtutils
.checkbox(
182 checked
=False, text
=text
, tooltip
=tooltip
185 text
= N_('Fast-forward only')
187 'Refuse to merge unless the current HEAD is already up-'
188 'to-date or the merge can be resolved as a fast-forward'
190 self
.ff_only_checkbox
= qtutils
.checkbox(
191 checked
=True, text
=text
, tooltip
=tooltip
193 self
.ff_only_checkbox
.toggled
.connect(self
.update_command_display
)
195 text
= N_('No fast-forward')
197 'Create a merge commit even when the merge resolves as a fast-forward'
199 self
.no_ff_checkbox
= qtutils
.checkbox(
200 checked
=False, text
=text
, tooltip
=tooltip
202 self
.no_ff_checkbox
.toggled
.connect(self
.update_command_display
)
205 'Allow non-fast-forward updates. Using "force" can '
206 'cause the remote repository to lose commits; '
209 self
.force_checkbox
= qtutils
.checkbox(
210 checked
=False, text
=text
, tooltip
=tooltip
212 self
.force_checkbox
.toggled
.connect(self
.update_command_display
)
214 self
.tags_checkbox
= qtutils
.checkbox(text
=N_('Include tags '))
215 self
.tags_checkbox
.toggled
.connect(self
.update_command_display
)
218 'Remove remote-tracking branches that no longer exist on the remote'
220 self
.prune_checkbox
= qtutils
.checkbox(text
=N_('Prune '), tooltip
=tooltip
)
221 self
.prune_checkbox
.toggled
.connect(self
.update_command_display
)
223 tooltip
= N_('Rebase the current branch instead of merging')
224 self
.rebase_checkbox
= qtutils
.checkbox(text
=N_('Rebase'), tooltip
=tooltip
)
225 self
.rebase_checkbox
.toggled
.connect(self
.update_command_display
)
227 text
= N_('Set upstream')
228 tooltip
= N_('Configure the remote branch as the the new upstream')
229 self
.upstream_checkbox
= qtutils
.checkbox(text
=text
, tooltip
=tooltip
)
230 self
.upstream_checkbox
.toggled
.connect(self
.update_command_display
)
232 text
= N_('Close on completion')
233 tooltip
= N_('Close dialog when completed')
234 self
.close_on_completion_checkbox
= qtutils
.checkbox(
235 checked
=True, text
=text
, tooltip
=tooltip
238 self
.action_button
= qtutils
.ok_button(title
, icon
=icon
)
239 self
.close_button
= qtutils
.close_button()
240 self
.buttons_group
= utils
.Group(self
.close_button
, self
.action_button
)
241 self
.inputs_group
= utils
.Group(
242 self
.close_on_completion_checkbox
,
244 self
.ff_only_checkbox
,
249 self
.rebase_checkbox
,
253 self
.remote_branches
,
254 self
.upstream_checkbox
,
255 self
.prompt_checkbox
,
256 self
.remote_messages_checkbox
,
258 self
.progress
= standard
.progress_bar(
260 disable
=(self
.buttons_group
, self
.inputs_group
),
263 self
.command_display
= log
.LogWidget(self
.context
, display_usage
=False)
265 self
.local_branch_layout
= qtutils
.hbox(
266 defs
.small_margin
, defs
.spacing
, self
.local_label
, self
.local_branch
269 self
.remote_layout
= qtutils
.hbox(
270 defs
.small_margin
, defs
.spacing
, self
.remote_label
, self
.remote_name
273 self
.remote_branch_layout
= qtutils
.hbox(
276 self
.remote_branch_label
,
280 self
.options_layout
= qtutils
.hbox(
284 self
.ff_only_checkbox
,
288 self
.rebase_checkbox
,
289 self
.upstream_checkbox
,
290 self
.prompt_checkbox
,
291 self
.close_on_completion_checkbox
,
292 self
.remote_messages_checkbox
,
299 self
.remote_input_layout
= qtutils
.vbox(
300 defs
.no_margin
, defs
.spacing
, self
.remote_layout
, self
.remotes
303 self
.local_branch_input_layout
= qtutils
.vbox(
304 defs
.no_margin
, defs
.spacing
, self
.local_branch_layout
, self
.local_branches
307 self
.remote_branch_input_layout
= qtutils
.vbox(
310 self
.remote_branch_layout
,
311 self
.remote_branches
,
316 self
.remote_input_layout
,
317 self
.local_branch_input_layout
,
318 self
.remote_branch_input_layout
,
320 else: # fetch and pull
322 self
.remote_input_layout
,
323 self
.remote_branch_input_layout
,
324 self
.local_branch_input_layout
,
326 self
.top_layout
= qtutils
.hbox(defs
.no_margin
, defs
.spacing
, *widgets
)
328 self
.main_layout
= qtutils
.vbox(
332 self
.command_display
,
335 self
.main_layout
.setStretchFactor(self
.top_layout
, 2)
336 self
.setLayout(self
.main_layout
)
338 default_remote
= get_default_remote(context
)
340 remotes
= model
.remotes
341 if default_remote
in remotes
:
342 idx
= remotes
.index(default_remote
)
343 if self
.select_remote(idx
):
344 self
.set_remote_name(default_remote
)
346 if self
.select_first_remote():
347 self
.set_remote_name(remotes
[0])
349 # Trim the remote list to just the default remote
350 self
.update_remotes(update_command_display
=False)
352 # Setup signals and slots
353 self
.remotes
.itemSelectionChanged
.connect(self
.update_remotes
)
355 local
= self
.local_branches
356 local
.itemSelectionChanged
.connect(self
.update_local_branches
)
358 remote
= self
.remote_branches
359 remote
.itemSelectionChanged
.connect(self
.update_remote_branches
)
361 self
.no_ff_checkbox
.toggled
.connect(
362 lambda x
: uncheck(x
, self
.ff_only_checkbox
, self
.rebase_checkbox
)
365 self
.ff_only_checkbox
.toggled
.connect(
366 lambda x
: uncheck(x
, self
.no_ff_checkbox
, self
.rebase_checkbox
)
369 self
.rebase_checkbox
.toggled
.connect(
370 lambda x
: uncheck(x
, self
.no_ff_checkbox
, self
.ff_only_checkbox
)
373 connect_button(self
.action_button
, self
.action_callback
)
374 connect_button(self
.close_button
, self
.close
)
377 self
, N_('Close'), self
.close
, QtGui
.QKeySequence
.Close
, 'Esc'
380 self
.prune_checkbox
.hide()
384 self
.upstream_checkbox
.hide()
385 self
.prompt_checkbox
.hide()
388 # Fetch and Push-only options
389 self
.force_checkbox
.hide()
390 self
.tags_checkbox
.hide()
391 self
.local_label
.hide()
392 self
.local_branch
.hide()
393 self
.local_branches
.hide()
396 self
.rebase_checkbox
.hide()
397 self
.no_ff_checkbox
.hide()
398 self
.ff_only_checkbox
.hide()
400 self
.init_size(parent
=parent
)
401 self
.set_field_defaults()
403 def set_rebase(self
, value
):
404 """Check the rebase checkbox"""
405 self
.rebase_checkbox
.setChecked(value
)
407 def set_field_defaults(self
):
408 """Set sensible initial defaults"""
409 # Default to "git fetch origin main"
412 self
.set_local_branch('')
413 self
.set_remote_branch('')
414 if action
== PULL
: # Nothing to do when fetching.
416 # Select the current branch by default for push
418 branch
= self
.model
.currentbranch
420 idx
= self
.model
.local_branches
.index(branch
)
423 self
.select_local_branch(idx
)
424 self
.set_remote_branch('')
426 self
.update_command_display()
428 def update_command_display(self
):
429 """Display the git commands that will be run"""
431 for remote
in self
.selected_remotes
:
432 cmd
= ['git', self
.action
.lower()]
433 _
, kwargs
= self
.common_args()
434 args
, kwargs
= main
.remote_args(
437 push
=self
.action
== PUSH
,
438 pull
=self
.action
== PULL
,
441 cmd
.extend(git
.transform_kwargs(**kwargs
))
443 commands
.append(core
.list2cmdline(cmd
))
444 self
.command_display
.set_output('\n'.join(commands
))
446 def set_remote_name(self
, remote_name
):
447 """Set the remote name"""
448 self
.remote_name
.setText(remote_name
)
450 def set_local_branch(self
, branch
):
451 """Set the local branch name"""
452 self
.local_branch
.setText(branch
)
454 self
.local_branch
.selectAll()
456 def set_remote_branch(self
, branch
):
457 """Set the remote branch name"""
458 self
.remote_branch
.setText(branch
)
460 self
.remote_branch
.selectAll()
462 def set_remote_branches(self
, branches
):
463 """Set the list of remote branches"""
464 self
.remote_branches
.clear()
465 self
.remote_branches
.addItems(branches
)
466 self
.filtered_remote_branches
= branches
467 qtutils
.add_completer(self
.remote_branch
, strip_remotes(branches
))
469 def select_first_remote(self
):
470 """Select the first remote in the list view"""
471 return self
.select_remote(0)
473 def select_remote(self
, idx
):
474 """Select a remote by index"""
475 item
= self
.remotes
.item(idx
)
477 item
.setSelected(True)
478 self
.remotes
.setCurrentItem(item
)
479 self
.set_remote_name(item
.text())
485 def select_remote_by_name(self
, remote
):
486 """Select a remote by name"""
487 remotes
= self
.model
.remotes
488 if remote
in remotes
:
489 idx
= remotes
.index(remote
)
490 result
= self
.select_remote(idx
)
495 def set_selected_remotes(self
, remotes
):
496 """Set the list of selected remotes
498 Return True if all remotes were found and selected.
501 # Invalid remote names are ignored.
502 # This handles a remote going away between sessions.
503 # The selection is unchanged when none of the specified remotes exist.
505 for remote
in remotes
:
506 if remote
in self
.model
.remotes
:
510 # Only clear the selection if the specified remotes exist
511 self
.remotes
.clearSelection()
512 found
= all(self
.select_remote_by_name(x
) for x
in remotes
)
515 def select_local_branch(self
, idx
):
516 """Selects a local branch by index in the list view"""
517 item
= self
.local_branches
.item(idx
)
519 item
.setSelected(True)
520 self
.local_branches
.setCurrentItem(item
)
521 self
.set_local_branch(item
.text())
527 def select_remote_branch(self
, idx
):
528 """Selects a remote branch by index in the list view"""
529 item
= self
.remote_branches
.item(idx
)
531 item
.setSelected(True)
532 self
.remote_branches
.setCurrentItem(item
)
533 remote_branch
= item
.text()
534 branch
= remote_branch
.split('/', 1)[-1]
535 self
.set_remote_branch(branch
)
541 def display_remotes(self
, widget
):
542 """Display the available remotes in a listwidget"""
544 for remote_name
in self
.model
.remotes
:
545 url
= self
.model
.remote_url(remote_name
, self
.action
)
546 display
= '{}\t({})'.format(remote_name
, N_('URL: %s') % url
)
547 displayed
.append(display
)
548 qtutils
.set_items(widget
, displayed
)
550 def update_remotes(self
, update_command_display
=True):
551 """Update the remote name when a remote from the list is selected"""
552 widget
= self
.remotes
553 remotes
= self
.model
.remotes
554 selection
= qtutils
.selected_item(widget
, remotes
)
556 self
.selected_remotes
= []
558 self
.set_remote_name(selection
)
559 self
.selected_remotes
= qtutils
.selected_items(self
.remotes
, self
.model
.remotes
)
560 self
.set_remote_to(selection
, self
.selected_remotes
)
561 if update_command_display
:
562 self
.update_command_display()
564 def set_remote_to(self
, _remote
, selected_remotes
):
565 context
= self
.context
566 all_branches
= gitcmds
.branch_list(context
, remote
=True)
570 for remote_name
in selected_remotes
:
571 remote
= remote
or remote_name
# Use the first remote when prepopulating.
572 patterns
.append(remote_name
+ '/*')
574 for branch
in all_branches
:
576 if fnmatch
.fnmatch(branch
, pat
):
577 branches
.append(branch
)
580 self
.set_remote_branches(branches
)
582 self
.set_remote_branches(all_branches
)
584 if self
.action
== FETCH
:
585 self
.set_remote_branch('')
586 elif self
.action
== PUSH
:
587 self
.set_remote_branch('')
588 elif self
.action
== PULL
:
590 current_branch
= self
.context
.model
.currentbranch
591 remote_branch
= '%s/%s' % (remote
, current_branch
)
592 if branches
and remote_branch
in branches
:
593 branch
= current_branch
595 idx
= self
.filtered_remote_branches
.index(remote_branch
)
598 self
.select_remote_branch(idx
)
600 self
.set_remote_branch(branch
)
602 def remote_name_edited(self
):
603 """Update the current remote when the remote name is typed manually"""
604 remote
= self
.remote_name
.text()
605 self
.update_selected_remotes(remote
)
606 self
.set_remote_to(remote
, self
.selected_remotes
)
607 self
.update_command_display()
609 def update_local_branches(self
):
610 """Update the local/remote branch names when a branch is selected"""
611 branches
= self
.model
.local_branches
612 widget
= self
.local_branches
613 selection
= qtutils
.selected_item(widget
, branches
)
616 self
.set_local_branch(selection
)
617 if self
.action
== FETCH
:
618 self
.set_remote_branch(selection
)
619 self
.update_command_display()
621 def update_remote_branches(self
):
622 """Update the remote branch name when a branch is selected"""
623 widget
= self
.remote_branches
624 branches
= self
.filtered_remote_branches
625 selection
= qtutils
.selected_item(widget
, branches
)
628 branch
= utils
.strip_one(selection
)
631 self
.set_remote_branch(branch
)
632 self
.update_command_display()
634 def common_args(self
):
635 """Returns git arguments common to fetch/push/pull"""
636 remote_name
= self
.remote_name
.text()
637 local_branch
= self
.local_branch
.text()
638 remote_branch
= self
.remote_branch
.text()
640 ff_only
= get(self
.ff_only_checkbox
)
641 force
= get(self
.force_checkbox
)
642 no_ff
= get(self
.no_ff_checkbox
)
643 rebase
= get(self
.rebase_checkbox
)
644 set_upstream
= get(self
.upstream_checkbox
)
645 tags
= get(self
.tags_checkbox
)
646 prune
= get(self
.prune_checkbox
)
653 'local_branch': local_branch
,
656 'remote_branch': remote_branch
,
657 'set_upstream': set_upstream
,
665 def push_to_all(self
, _remote
, *args
, **kwargs
):
666 """Push to all selected remotes"""
667 selected_remotes
= self
.selected_remotes
669 for remote
in selected_remotes
:
670 result
= self
.model
.push(remote
, *args
, **kwargs
)
671 all_results
= combine(result
, all_results
)
674 def action_callback(self
):
675 """Perform the actual fetch/push/pull operation"""
677 remote_messages
= get(self
.remote_messages_checkbox
)
679 model_action
= self
.model
.fetch
681 model_action
= self
.push_to_all
682 else: # if action == PULL:
683 model_action
= self
.model
.pull
685 remote_name
= self
.remote_name
.text()
687 errmsg
= N_('No repository selected.')
688 Interaction
.log(errmsg
)
690 remote
, kwargs
= self
.common_args()
691 self
.update_selected_remotes(remote
)
693 # Check if we're about to create a new branch and warn.
694 remote_branch
= self
.remote_branch
.text()
695 local_branch
= self
.local_branch
.text()
697 if action
== PUSH
and not remote_branch
:
698 branch
= local_branch
699 candidate
= f
'{remote}/{branch}'
700 prompt
= get(self
.prompt_checkbox
)
702 if prompt
and candidate
not in self
.model
.remote_branches
:
710 'Branch "%(branch)s" does not exist in "%(remote)s".\n'
711 'A new remote branch will be published.'
715 info_txt
= N_('Create a new remote branch?')
716 ok_text
= N_('Create Remote Branch')
717 if not Interaction
.confirm(
718 title
, msg
, info_txt
, ok_text
, icon
=icons
.cola()
722 if get(self
.force_checkbox
):
724 title
= N_('Force Fetch?')
725 msg
= N_('Non-fast-forward fetch overwrites local history!')
726 info_txt
= N_('Force fetching from %s?') % remote
727 ok_text
= N_('Force Fetch')
729 title
= N_('Force Push?')
731 'Non-fast-forward push overwrites published '
732 'history!\n(Did you pull first?)'
734 info_txt
= N_('Force push to %s?') % remote
735 ok_text
= N_('Force Push')
736 else: # pull: shouldn't happen since the controls are hidden
738 if not Interaction
.confirm(
739 title
, msg
, info_txt
, ok_text
, default
=False, icon
=icons
.discard()
743 self
.progress
.setMaximumHeight(
744 self
.action_button
.height() - defs
.small_margin
* 2
747 # Use a thread to update in the background
748 task
= ActionTask(model_action
, remote
, kwargs
)
750 result
= log
.show_remote_messages(self
, self
.context
)
755 progress
=self
.progress
,
756 finish
=self
.action_completed
,
760 def update_selected_remotes(self
, remote
):
761 """Update the selected remotes when an ad-hoc remote is typed in"""
762 self
.selected_remotes
= qtutils
.selected_items(
763 self
.remotes
, self
.model
.remotes
765 if remote
not in self
.selected_remotes
:
766 self
.selected_remotes
= [remote
]
768 def action_completed(self
, task
):
769 """Grab the results of the action and finish up"""
770 if not task
.result
or not isinstance(task
.result
, (list, tuple)):
773 status
, out
, err
= task
.result
774 command
= 'git %s' % self
.action
.lower()
775 message
= Interaction
.format_command_status(command
, status
)
776 details
= Interaction
.format_out_err(out
, err
)
778 log_message
= message
780 log_message
+= '\n\n' + details
781 Interaction
.log(log_message
)
784 close_on_completion
= get(self
.close_on_completion_checkbox
)
785 if close_on_completion
:
789 if self
.action
== PUSH
:
791 message
+= N_('Have you rebased/pulled lately?')
793 Interaction
.critical(self
.windowTitle(), message
=message
, details
=details
)
795 def export_state(self
):
796 """Export persistent settings"""
797 state
= standard
.Dialog
.export_state(self
)
798 state
['close_on_completion'] = get(self
.close_on_completion_checkbox
)
799 state
['remote_messages'] = get(self
.remote_messages_checkbox
)
802 def apply_state(self
, state
):
803 """Apply persistent settings"""
804 result
= standard
.Dialog
.apply_state(self
, state
)
805 # Restore the "close on completion" checkbox
806 close_on_completion
= bool(state
.get('close_on_completion', True))
807 self
.close_on_completion_checkbox
.setChecked(close_on_completion
)
808 # Restore the "show remote messages" checkbox
809 remote_messages
= bool(state
.get('remote_messages', False))
810 self
.remote_messages_checkbox
.setChecked(remote_messages
)
814 # Use distinct classes so that each saves its own set of preferences
815 class Fetch(RemoteActionDialog
):
816 """Fetch from remote repositories"""
818 def __init__(self
, context
, parent
=None):
819 super().__init
__(context
, FETCH
, N_('Fetch'), parent
=parent
, icon
=icons
.repo())
821 def export_state(self
):
822 """Export persistent settings"""
823 state
= RemoteActionDialog
.export_state(self
)
824 state
['tags'] = get(self
.tags_checkbox
)
825 state
['prune'] = get(self
.prune_checkbox
)
828 def apply_state(self
, state
):
829 """Apply persistent settings"""
830 result
= RemoteActionDialog
.apply_state(self
, state
)
831 tags
= bool(state
.get('tags', False))
832 self
.tags_checkbox
.setChecked(tags
)
833 prune
= bool(state
.get('prune', False))
834 self
.prune_checkbox
.setChecked(prune
)
838 class Push(RemoteActionDialog
):
839 """Push to remote repositories"""
841 def __init__(self
, context
, parent
=None):
842 super().__init
__(context
, PUSH
, N_('Push'), parent
=parent
, icon
=icons
.push())
844 def export_state(self
):
845 """Export persistent settings"""
846 state
= RemoteActionDialog
.export_state(self
)
847 state
['prompt'] = get(self
.prompt_checkbox
)
848 state
['tags'] = get(self
.tags_checkbox
)
851 def apply_state(self
, state
):
852 """Apply persistent settings"""
853 result
= RemoteActionDialog
.apply_state(self
, state
)
854 # Restore the "prompt on creation" checkbox
855 prompt
= bool(state
.get('prompt', True))
856 self
.prompt_checkbox
.setChecked(prompt
)
857 # Restore the "tags" checkbox
858 tags
= bool(state
.get('tags', False))
859 self
.tags_checkbox
.setChecked(tags
)
863 class Pull(RemoteActionDialog
):
864 """Pull from remote repositories"""
866 def __init__(self
, context
, parent
=None):
867 super().__init
__(context
, PULL
, N_('Pull'), parent
=parent
, icon
=icons
.pull())
869 def apply_state(self
, state
):
870 """Apply persistent settings"""
871 result
= RemoteActionDialog
.apply_state(self
, state
)
872 # Rebase has the highest priority
873 rebase
= bool(state
.get('rebase', False))
874 self
.rebase_checkbox
.setChecked(rebase
)
876 ff_only
= not rebase
and bool(state
.get('ff_only', False))
877 no_ff
= not rebase
and not ff_only
and bool(state
.get('no_ff', False))
878 self
.no_ff_checkbox
.setChecked(no_ff
)
879 # Allow users coming from older versions that have rebase=False to
880 # pickup the new ff_only=True default by only setting ff_only False
881 # when it either exists in the config or when rebase=True.
882 if 'ff_only' in state
or rebase
:
883 self
.ff_only_checkbox
.setChecked(ff_only
)
886 def export_state(self
):
887 """Export persistent settings"""
888 state
= RemoteActionDialog
.export_state(self
)
889 state
['ff_only'] = get(self
.ff_only_checkbox
)
890 state
['no_ff'] = get(self
.no_ff_checkbox
)
891 state
['rebase'] = get(self
.rebase_checkbox
)