1 """This controller handles the remote dialog."""
5 from PyQt4
.QtGui
import QDialog
8 from cola
import serializer
10 from cola
import qtutils
11 from cola
.views
import remote
12 from cola
.qobserver
import QObserver
14 def remote_action(parent
, action
):
15 """Launches fetch/push/pull dialogs."""
16 # TODO: subclass model
17 model
= serializer
.clone(cola
.model())
19 model
.tags_checkbox
= False
20 model
.rebase_checkbox
= False
21 model
.ffwd_only_checkbox
= True
23 view
= remote
.RemoteView(parent
, action
)
24 controller
= RemoteController(model
, view
, action
)
27 class RemoteController(QObserver
):
28 """Provides control for the remote-action dialog."""
29 def __init__(self
, model
, view
, action
):
30 QObserver
.__init
__(self
, model
, view
)
31 self
.add_observables('remotename',
41 """The current mode; one of fetch/push/pull"""
43 self
.action_method
= {
44 'fetch': self
.gen_remote_callback(self
.model
.fetch_helper
),
45 'push': self
.gen_remote_callback(self
.model
.push_helper
),
46 'pull': self
.gen_remote_callback(self
.model
.pull_helper
),
48 """Callbacks corresponding to the 3 (fetch/push/pull) modes"""
50 self
.add_actions(remotes
= self
.display_remotes
)
51 self
.add_callbacks(action_button
= self
.action_method
,
52 remotes
= self
.update_remotes
,
53 local_branches
= self
.update_local_branches
,
54 remote_branches
= self
.update_remote_branches
)
56 remotes
= self
.model
.remotes
57 if 'origin' in remotes
:
58 idx
= remotes
.index('origin')
59 if self
.view
.select_remote(idx
):
60 self
.model
.set_remotename('origin')
62 if self
.view
.select_first_remote():
63 self
.model
.set_remotename(remotes
[0])
65 # Select the current branch by default for push
68 branches
= self
.model
.local_branches
69 branch
= self
.model
.currentbranch
70 if branch
not in branches
:
72 idx
= branches
.index(branch
)
73 if self
.view
.select_local_branch(idx
):
74 self
.model
.set_local_branch(branch
)
76 def display_remotes(self
, widget
):
77 """Display the available remotes in a listwidget"""
79 for remotename
in self
.model
.remotes
:
80 url
= self
.model
.remote_url(remotename
)
81 display
= ('%s\t(%s %s)'
82 % (remotename
, unicode(self
.tr('URL:')), url
))
83 displayed
.append(display
)
84 qtutils
.set_items(widget
,displayed
)
86 def update_remotes(self
,*rest
):
87 """Update the remote name when a remote from the list is selected"""
88 widget
= self
.view
.remotes
89 remotes
= self
.model
.remotes
90 selection
= qtutils
.selected_item(widget
, remotes
)
93 self
.model
.set_remotename(selection
)
94 self
.view
.remotename
.selectAll()
96 if self
.action
!= 'pull':
98 all_branches
= gitcmds
.branch_list(remote
=True)
100 pat
= selection
+ '/*'
101 for branch
in all_branches
:
102 if fnmatch
.fnmatch(branch
, pat
):
103 branches
.append(branch
)
105 self
.model
.set_remote_branches(branches
)
107 self
.model
.set_remote_branches(all_branches
)
108 self
.model
.set_remote_branch('')
110 def update_local_branches(self
,*rest
):
111 """Update the local/remote branch names when a branch is selected"""
112 branches
= self
.model
.local_branches
113 widget
= self
.view
.local_branches
114 selection
= qtutils
.selected_item(widget
, branches
)
118 self
.model
.set_local_branch(selection
)
119 self
.model
.set_remote_branch(selection
)
121 self
.view
.local_branch
.selectAll()
122 self
.view
.remote_branch
.selectAll()
124 def update_remote_branches(self
,*rest
):
125 """Update the remote branch name when a branch is selected"""
126 widget
= self
.view
.remote_branches
127 branches
= self
.model
.remote_branches
128 selection
= qtutils
.selected_item(widget
,branches
)
131 branch
= utils
.basename(selection
)
134 self
.model
.set_remote_branch(branch
)
135 self
.view
.remote_branch
.selectAll()
137 def common_args(self
):
138 """Returns git arguments common to fetch/push/pulll"""
140 return (self
.model
.remotename
,
142 'local_branch': self
.model
.local_branch
,
143 'remote_branch': self
.model
.remote_branch
,
144 'ffwd': self
.model
.ffwd_only_checkbox
,
145 'tags': self
.model
.tags_checkbox
,
146 'rebase': self
.model
.rebase_checkbox
,
149 #+-------------------------------------------------------------
151 def gen_remote_callback(self
, modelaction
):
152 """Generates a Qt callback for fetch/push/pull.
154 def remote_callback():
155 if not self
.model
.remotename
:
156 errmsg
= self
.tr('No repository selected.')
157 qtutils
.log(1, errmsg
)
159 remote
, kwargs
= self
.common_args()
162 # Check if we're about to create a new branch and warn.
163 if action
== 'push' and not self
.model
.remote_branch
:
164 branch
= self
.model
.local_branch
165 candidate
= '%s/%s' % (remote
, branch
)
166 if candidate
not in self
.model
.remote_branches
:
167 msg
= ('Branch "' + branch
+ '" does not exist in ' +
168 remote
+ '.\n\nCreate a new branch?')
169 if not qtutils
.question(self
.view
, 'Create New Branch?',
173 if not self
.model
.ffwd_only_checkbox
:
174 if action
== 'fetch':
175 msg
= ('Non-fast-forward fetch overwrites local '
176 'history!\n\tContinue?')
177 elif action
== 'push':
178 msg
= ('Non-fast-forward push overwrites published '
179 'history!\nAre you sure you want to do this? '
180 '(Did you pull first?)\n\tContinue?')
181 else: # pull: shouldn't happen since the controls are hidden
182 msg
= "You probably don't want to do this.\n\tContinue?"
183 if not qtutils
.question(self
.view
,
184 'Force %s?' % action
.title(), msg
, default
=False):
186 status
, output
= modelaction(remote
, **kwargs
)
187 if not output
: # git fetch --tags --verbose doesn't print anything...
188 output
= self
.tr('Already up-to-date.')
189 # Force the status to 1 so that we always display the log
190 qtutils
.log(1, output
)
192 return remote_callback