From 01b575d702a9692f596ff75de01544f45523b20c Mon Sep 17 00:00:00 2001 From: "James E. Blair" <jeblair@hp.com> Date: Sun, 31 Aug 2014 13:28:31 -0700 Subject: [PATCH] Add support for abandon/restore Change-Id: I5f85220978c769c16405e188ae88822844a74d95 --- gertty/db.py | 3 +++ gertty/keymap.py | 4 +++ gertty/sync.py | 29 ++++++++++++++++++++ gertty/view/change.py | 61 +++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 97 insertions(+) diff --git a/gertty/db.py b/gertty/db.py index 65eac56..4b230b3 100644 --- a/gertty/db.py +++ b/gertty/db.py @@ -608,6 +608,9 @@ class DatabaseSession(object): def getPendingRebases(self): return self.session().query(Change).filter_by(pending_rebase=True).all() + def getPendingStatusChanges(self): + return self.session().query(Change).filter_by(pending_status=True).all() + def getAccountByID(self, id, name=None, username=None, email=None): try: account = self.session().query(Account).filter_by(id=id).one() diff --git a/gertty/keymap.py b/gertty/keymap.py index e732e0b..070ba84 100644 --- a/gertty/keymap.py +++ b/gertty/keymap.py @@ -45,6 +45,8 @@ SEARCH_RESULTS = 'search results' NEXT_CHANGE = 'next change' PREV_CHANGE = 'previous change' TOGGLE_HIDDEN_COMMENTS = 'toggle hidden comments' +ABANDON_CHANGE = 'abandon change' +RESTORE_CHANGE = 'restore change' REBASE_CHANGE = 'rebase change' REFRESH = 'refresh' EDIT_TOPIC = 'edit topic' @@ -84,6 +86,8 @@ DEFAULT_KEYMAP = { NEXT_CHANGE: 'n', PREV_CHANGE: 'p', TOGGLE_HIDDEN_COMMENTS: 't', + ABANDON_CHANGE: 'ctrl a', + RESTORE_CHANGE: 'ctrl e', REBASE_CHANGE: 'ctrl b', REFRESH: 'ctrl r', EDIT_TOPIC: 'ctrl t', diff --git a/gertty/sync.py b/gertty/sync.py index 242a80b..d5e1b70 100644 --- a/gertty/sync.py +++ b/gertty/sync.py @@ -535,6 +535,8 @@ class UploadReviewsTask(Task): sync.submitTask(SetTopicTask(c.key, self.priority)) for c in session.getPendingRebases(): sync.submitTask(RebaseChangeTask(c.key, self.priority)) + for c in session.getPendingStatusChanges(): + sync.submitTask(ChangeStatusTask(c.key, self.priority)) for m in session.getPendingMessages(): sync.submitTask(UploadReviewTask(m.key, self.priority)) @@ -574,6 +576,33 @@ class RebaseChangeTask(Task): sync.post('changes/%s/rebase' % (change.id,), {}) sync.submitTask(SyncChangeTask(change.id, priority=self.priority)) +class ChangeStatusTask(Task): + def __init__(self, change_key, priority=NORMAL_PRIORITY): + super(ChangeStatusTask, self).__init__(priority) + self.change_key = change_key + + def __repr__(self): + return '<ChangeStatusTask %s>' % (self.change_key,) + + def run(self, sync): + app = sync.app + with app.db.getSession() as session: + change = session.getChange(self.change_key) + if change.pending_status_message: + data = dict(message=change.pending_status_message) + else: + data = {} + change.pending_status = False + change.pending_status_message = None + # Inside db session for rollback + if change.status == 'ABANDONED': + sync.post('changes/%s/abandon' % (change.id,), + data) + elif change.status == 'NEW': + sync.post('changes/%s/restore' % (change.id,), + data) + sync.submitTask(SyncChangeTask(change.id, priority=self.priority)) + class UploadReviewTask(Task): def __init__(self, message_key, priority=NORMAL_PRIORITY): super(UploadReviewTask, self).__init__(priority) diff --git a/gertty/view/change.py b/gertty/view/change.py index a003783..3e0b1cf 100644 --- a/gertty/view/change.py +++ b/gertty/view/change.py @@ -50,6 +50,29 @@ class EditTopicDialog(mywid.ButtonDialog): return None return r +class AbandonRestoreDialog(urwid.WidgetWrap): + signals = ['save', 'cancel'] + def __init__(self, action, text): + self.action = action + save_button = mywid.FixedButton(action) + cancel_button = mywid.FixedButton('Cancel') + urwid.connect_signal(save_button, 'click', + lambda button:self._emit('save')) + urwid.connect_signal(cancel_button, 'click', + lambda button:self._emit('cancel')) + button_widgets = [('pack', save_button), + ('pack', cancel_button)] + button_columns = urwid.Columns(button_widgets, dividechars=2) + rows = [] + self.entry = urwid.Edit(edit_text=text, multiline=True) + rows.append(urwid.Text(u"%s message: " % action)) + rows.append(self.entry) + rows.append(urwid.Divider()) + rows.append(button_columns) + pile = urwid.Pile(rows) + fill = urwid.Filler(pile, valign='top') + super(AbandonRestoreDialog, self).__init__(urwid.LineBox(fill, '%s Change' % (action,))) + class ReviewDialog(urwid.WidgetWrap): signals = ['save', 'cancel'] def __init__(self, revision_row): @@ -345,8 +368,12 @@ class ChangeView(urwid.WidgetWrap): "Toggle the reviewed flag for the current change"), (key(keymap.CHERRY_PICK), "Cherry-pick the most recent revision onto the local repo"), + (key(keymap.ABANDON_CHANGE), + "Abandon this change"), (key(keymap.REBASE_CHANGE), "Rebase this change (remotely)"), + (key(keymap.RESTORE_CHANGE), + "Restore this change"), (key(keymap.REFRESH), "Refresh this change"), (key(keymap.EDIT_TOPIC), @@ -448,6 +475,7 @@ class ChangeView(urwid.WidgetWrap): with self.app.db.getSession() as session: change = session.getChange(self.change_key) self.topic = change.topic or '' + self.pending_status_message = change.pending_status_message or '' if change.reviewed: reviewed = ' (reviewed)' else: @@ -717,9 +745,15 @@ class ChangeView(urwid.WidgetWrap): self.hide_comments = not self.hide_comments self.refresh() return None + if keymap.ABANDON_CHANGE in commands: + self.abandonChange() + return None if keymap.REBASE_CHANGE in commands: self.rebaseChange() return None + if keymap.RESTORE_CHANGE in commands: + self.restoreChange() + return None if keymap.REFRESH in commands: self.app.sync.submitTask( sync.SyncChangeTask(self.change_rest_id, priority=sync.HIGH_PRIORITY)) @@ -740,6 +774,33 @@ class ChangeView(urwid.WidgetWrap): screen = view_side_diff.SideDiffView(self.app, revision_key) self.app.changeScreen(screen) + def abandonChange(self): + dialog = AbandonRestoreDialog(u'Abandon', self.pending_status_message) + urwid.connect_signal(dialog, 'cancel', self.app.backScreen) + urwid.connect_signal(dialog, 'save', lambda button: + self.doAbandonRestoreChange(dialog, 'ABANDONED')) + self.app.popup(dialog) + + def restoreChange(self): + dialog = AbandonRestoreDialog(u'Restore', self.pending_status_message) + urwid.connect_signal(dialog, 'cancel', self.app.backScreen) + urwid.connect_signal(dialog, 'save', lambda button: + self.doAbandonRestoreChange(dialog, 'NEW')) + self.app.popup(dialog) + + def doAbandonRestoreChange(self, dialog, state): + change_key = None + with self.app.db.getSession() as session: + change = session.getChange(self.change_key) + change.status = state + change.pending_status = True + change.pending_status_message = dialog.entry.edit_text + change_key = change.key + self.app.sync.submitTask( + sync.ChangeStatusTask(change_key, sync.HIGH_PRIORITY)) + self.app.backScreen() + self.refresh() + def rebaseChange(self): dialog = mywid.YesNoDialog(u'Rebase Change', u'Perform a remote rebase of this change?')