Add reviewkeys
Reviewkeys are a customizable shortcut for leaving predefined votes on a change. For example, if you want to leave a +2 review with no comment, you might simply hit the "meta-2" key. The following configuration block is recommended for use with OpenStack's Gerrit: reviewkeys: - key: 'meta 0' approvals: [] - key: 'meta 1' approvals: - category: 'Code-Review' value: 1 - key: 'meta 2' approvals: - category: 'Code-Review' value: 2 - key: 'meta 3' approvals: - category: 'Code-Review' value: 2 - category: 'Workflow' value: 1 Change-Id: I466024d71d5b1d89fcdc32355e2a9fe13abf5c28
This commit is contained in:
parent
2fcb7bc219
commit
705ca5c766
@ -192,7 +192,7 @@ class App(object):
|
|||||||
text += '<%s>%s %s\n' % (d['key'], space, d['name'])
|
text += '<%s>%s %s\n' % (d['key'], space, d['name'])
|
||||||
text += "\nThis Screen\n"
|
text += "\nThis Screen\n"
|
||||||
text += "===========\n"
|
text += "===========\n"
|
||||||
text += self.loop.widget.help
|
text += self.loop.widget.help()
|
||||||
dialog = mywid.MessageDialog('Help', text)
|
dialog = mywid.MessageDialog('Help', text)
|
||||||
lines = text.split('\n')
|
lines = text.split('\n')
|
||||||
urwid.connect_signal(dialog, 'close',
|
urwid.connect_signal(dialog, 'close',
|
||||||
|
@ -13,8 +13,13 @@
|
|||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
|
import collections
|
||||||
import getpass
|
import getpass
|
||||||
import os
|
import os
|
||||||
|
try:
|
||||||
|
import ordereddict
|
||||||
|
except:
|
||||||
|
pass
|
||||||
import yaml
|
import yaml
|
||||||
|
|
||||||
import voluptuous as v
|
import voluptuous as v
|
||||||
@ -22,6 +27,11 @@ import voluptuous as v
|
|||||||
import gertty.commentlink
|
import gertty.commentlink
|
||||||
import gertty.palette
|
import gertty.palette
|
||||||
|
|
||||||
|
try:
|
||||||
|
OrderedDict = collections.OrderedDict
|
||||||
|
except AttributeError:
|
||||||
|
OrderedDict = ordereddict.OrderedDict
|
||||||
|
|
||||||
DEFAULT_CONFIG_PATH='~/.gertty.yaml'
|
DEFAULT_CONFIG_PATH='~/.gertty.yaml'
|
||||||
|
|
||||||
class ConfigSchema(object):
|
class ConfigSchema(object):
|
||||||
@ -65,11 +75,20 @@ class ConfigSchema(object):
|
|||||||
|
|
||||||
dashboards = [dashboard]
|
dashboards = [dashboard]
|
||||||
|
|
||||||
|
reviewkey_approval = {v.Required('category'): str,
|
||||||
|
v.Required('value'): int}
|
||||||
|
|
||||||
|
reviewkey = {v.Required('approvals'): [reviewkey_approval],
|
||||||
|
v.Required('key'): str}
|
||||||
|
|
||||||
|
reviewkeys = [reviewkey]
|
||||||
|
|
||||||
def getSchema(self, data):
|
def getSchema(self, data):
|
||||||
schema = v.Schema({v.Required('servers'): self.servers,
|
schema = v.Schema({v.Required('servers'): self.servers,
|
||||||
'palettes': self.palettes,
|
'palettes': self.palettes,
|
||||||
'commentlinks': self.commentlinks,
|
'commentlinks': self.commentlinks,
|
||||||
'dashboards': self.dashboards,
|
'dashboards': self.dashboards,
|
||||||
|
'reviewkeys': self.reviewkeys,
|
||||||
})
|
})
|
||||||
return schema
|
return schema
|
||||||
|
|
||||||
@ -122,10 +141,14 @@ class Config(object):
|
|||||||
text="{url}",
|
text="{url}",
|
||||||
url="{url}"))])))
|
url="{url}"))])))
|
||||||
|
|
||||||
self.dashboards = {}
|
self.dashboards = OrderedDict()
|
||||||
for d in self.config.get('dashboards', []):
|
for d in self.config.get('dashboards', []):
|
||||||
self.dashboards[d['key']] = d
|
self.dashboards[d['key']] = d
|
||||||
|
|
||||||
|
self.reviewkeys = OrderedDict()
|
||||||
|
for k in self.config.get('reviewkeys', []):
|
||||||
|
self.reviewkeys[k['key']] = k
|
||||||
|
|
||||||
def getServer(self, name=None):
|
def getServer(self, name=None):
|
||||||
for server in self.config['servers']:
|
for server in self.config['servers']:
|
||||||
if name is None or name == server['name']:
|
if name is None or name == server['name']:
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
# Copyright 2014 OpenStack Foundation
|
# Copyright 2014 OpenStack Foundation
|
||||||
|
# Copyright 2014 Hewlett-Packard Development Company, L.P.
|
||||||
#
|
#
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||||
# not use this file except in compliance with the License. You may obtain
|
# not use this file except in compliance with the License. You may obtain
|
||||||
@ -85,34 +86,13 @@ class ReviewDialog(urwid.WidgetWrap):
|
|||||||
super(ReviewDialog, self).__init__(urwid.LineBox(fill, 'Review'))
|
super(ReviewDialog, self).__init__(urwid.LineBox(fill, 'Review'))
|
||||||
|
|
||||||
def save(self):
|
def save(self):
|
||||||
message_key = None
|
approvals = {}
|
||||||
with self.app.db.getSession() as session:
|
for category, group in self.button_groups.items():
|
||||||
revision = session.getRevision(self.revision_row.revision_key)
|
for button in group:
|
||||||
change = revision.change
|
if button.state:
|
||||||
pending_approvals = {}
|
approvals[category] = int(button.get_label())
|
||||||
for approval in change.pending_approvals:
|
message = self.message.edit_text.strip()
|
||||||
pending_approvals[approval.category] = approval
|
self.change_view.saveReview(self.revision_row.revision_key, approvals, message)
|
||||||
for category, group in self.button_groups.items():
|
|
||||||
approval = pending_approvals.get(category)
|
|
||||||
if not approval:
|
|
||||||
approval = change.createApproval(u'(draft)', category, 0, pending=True)
|
|
||||||
pending_approvals[category] = approval
|
|
||||||
for button in group:
|
|
||||||
if button.state:
|
|
||||||
approval.value = int(button.get_label())
|
|
||||||
message = None
|
|
||||||
for m in revision.messages:
|
|
||||||
if m.pending:
|
|
||||||
message = m
|
|
||||||
break
|
|
||||||
if not message:
|
|
||||||
message = revision.createMessage(None,
|
|
||||||
datetime.datetime.utcnow(),
|
|
||||||
u'(draft)', '', pending=True)
|
|
||||||
message.message = self.message.edit_text.strip()
|
|
||||||
message_key = message.key
|
|
||||||
change.reviewed = True
|
|
||||||
return message_key
|
|
||||||
|
|
||||||
def keypress(self, size, key):
|
def keypress(self, size, key):
|
||||||
r = super(ReviewDialog, self).keypress(size, key)
|
r = super(ReviewDialog, self).keypress(size, key)
|
||||||
@ -142,9 +122,6 @@ class ReviewButton(mywid.FixedButton):
|
|||||||
def closeReview(self, save):
|
def closeReview(self, save):
|
||||||
if save:
|
if save:
|
||||||
message_key = self.dialog.save()
|
message_key = self.dialog.save()
|
||||||
self.change_view.app.sync.submitTask(
|
|
||||||
sync.UploadReviewTask(message_key, sync.HIGH_PRIORITY))
|
|
||||||
self.change_view.refresh()
|
|
||||||
self.change_view.app.backScreen()
|
self.change_view.app.backScreen()
|
||||||
|
|
||||||
class RevisionRow(urwid.WidgetWrap):
|
class RevisionRow(urwid.WidgetWrap):
|
||||||
@ -293,15 +270,23 @@ class ChangeMessageBox(mywid.HyperText):
|
|||||||
self.set_text(text+comment_text)
|
self.set_text(text+comment_text)
|
||||||
|
|
||||||
class ChangeView(urwid.WidgetWrap):
|
class ChangeView(urwid.WidgetWrap):
|
||||||
help = """
|
_help = """
|
||||||
<c> Checkout the most recent revision into the local repo.
|
<c> Checkout the most recent revision into the local repo.
|
||||||
<d> Show the diff of the mont recent revision.
|
<d> Show the diff of the mont recent revision.
|
||||||
<k> Toggle the hidden flag for the current change.
|
<k> Toggle the hidden flag for the current change.
|
||||||
<r> Leave a review for the most recent revision.
|
<r> Leave a review for the most recent revision.
|
||||||
<v> Toggle the reviewed flag for the current change.
|
<v> Toggle the reviewed flag for the current change.
|
||||||
<x> Cherry-pick the most recent revision onto the local repo.
|
<x> Cherry-pick the most recent revision onto the local repo.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
def help(self):
|
||||||
|
text = self._help
|
||||||
|
for k in self.app.config.reviewkeys.values():
|
||||||
|
space = max(6 - len(k['key']), 0) * ' '
|
||||||
|
action = ', '.join(['{category}:{value}'.format(**a) for a in k['approvals']])
|
||||||
|
text += '<%s>%s %s\n' % (k['key'], space, action)
|
||||||
|
return text
|
||||||
|
|
||||||
def __init__(self, app, change_key):
|
def __init__(self, app, change_key):
|
||||||
super(ChangeView, self).__init__(urwid.Pile([]))
|
super(ChangeView, self).__init__(urwid.Pile([]))
|
||||||
self.app = app
|
self.app = app
|
||||||
@ -579,7 +564,54 @@ class ChangeView(urwid.WidgetWrap):
|
|||||||
row = self.revision_rows[self.last_revision_key]
|
row = self.revision_rows[self.last_revision_key]
|
||||||
row.cherryPick(None)
|
row.cherryPick(None)
|
||||||
return None
|
return None
|
||||||
|
if r in self.app.config.reviewkeys:
|
||||||
|
self.reviewKey(self.app.config.reviewkeys[r])
|
||||||
|
return None
|
||||||
return r
|
return r
|
||||||
|
|
||||||
def diff(self, revision_key):
|
def diff(self, revision_key):
|
||||||
self.app.changeScreen(view_diff.DiffView(self.app, revision_key))
|
self.app.changeScreen(view_diff.DiffView(self.app, revision_key))
|
||||||
|
|
||||||
|
def reviewKey(self, reviewkey):
|
||||||
|
approvals = {}
|
||||||
|
for a in reviewkey['approvals']:
|
||||||
|
approvals[a['category']] = a['value']
|
||||||
|
self.app.log.debug("Reviewkey %s with approvals %s" %
|
||||||
|
(reviewkey['key'], approvals))
|
||||||
|
row = self.revision_rows[self.last_revision_key]
|
||||||
|
self.saveReview(row.revision_key, approvals, '')
|
||||||
|
|
||||||
|
def saveReview(self, revision_key, approvals, message):
|
||||||
|
message_key = None
|
||||||
|
with self.app.db.getSession() as session:
|
||||||
|
revision = session.getRevision(revision_key)
|
||||||
|
change = revision.change
|
||||||
|
pending_approvals = {}
|
||||||
|
for approval in change.pending_approvals:
|
||||||
|
pending_approvals[approval.category] = approval
|
||||||
|
|
||||||
|
categories = set()
|
||||||
|
for label in change.permitted_labels:
|
||||||
|
categories.add(label.category)
|
||||||
|
for category in categories:
|
||||||
|
value = approvals.get(category, 0)
|
||||||
|
approval = pending_approvals.get(category)
|
||||||
|
if not approval:
|
||||||
|
approval = change.createApproval(u'(draft)', category, 0, pending=True)
|
||||||
|
pending_approvals[category] = approval
|
||||||
|
approval.value = value
|
||||||
|
pending_message = None
|
||||||
|
for m in revision.messages:
|
||||||
|
if m.pending:
|
||||||
|
pending_message = m
|
||||||
|
break
|
||||||
|
if not pending_message:
|
||||||
|
pending_message = revision.createMessage(None,
|
||||||
|
datetime.datetime.utcnow(),
|
||||||
|
u'(draft)', '', pending=True)
|
||||||
|
pending_message.message = message
|
||||||
|
message_key = pending_message.key
|
||||||
|
change.reviewed = True
|
||||||
|
self.app.sync.submitTask(
|
||||||
|
sync.UploadReviewTask(message_key, sync.HIGH_PRIORITY))
|
||||||
|
self.refresh()
|
||||||
|
@ -67,12 +67,15 @@ class ChangeListHeader(urwid.WidgetWrap):
|
|||||||
self._w.contents.append((urwid.Text(' %s' % category[0]), self._w.options('given', 3)))
|
self._w.contents.append((urwid.Text(' %s' % category[0]), self._w.options('given', 3)))
|
||||||
|
|
||||||
class ChangeListView(urwid.WidgetWrap):
|
class ChangeListView(urwid.WidgetWrap):
|
||||||
help = """
|
_help = """
|
||||||
<k> Toggle the hidden flag for the currently selected change.
|
<k> Toggle the hidden flag for the currently selected change.
|
||||||
<l> Toggle whether only unreviewed or all changes are displayed.
|
<l> Toggle whether only unreviewed or all changes are displayed.
|
||||||
<v> Toggle the reviewed flag for the currently selected change.
|
<v> Toggle the reviewed flag for the currently selected change.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
def help(self):
|
||||||
|
return self._help
|
||||||
|
|
||||||
def __init__(self, app, query, query_desc=None, unreviewed=False):
|
def __init__(self, app, query, query_desc=None, unreviewed=False):
|
||||||
super(ChangeListView, self).__init__(urwid.Pile([]))
|
super(ChangeListView, self).__init__(urwid.Pile([]))
|
||||||
self.app = app
|
self.app = app
|
||||||
|
@ -210,11 +210,14 @@ class DiffContextButton(urwid.WidgetWrap):
|
|||||||
self.view.expandChunk(self.diff, self.chunk, from_end=-10)
|
self.view.expandChunk(self.diff, self.chunk, from_end=-10)
|
||||||
|
|
||||||
class DiffView(urwid.WidgetWrap):
|
class DiffView(urwid.WidgetWrap):
|
||||||
help = """
|
_help = """
|
||||||
<Enter> Add an inline comment
|
<Enter> Add an inline comment
|
||||||
<p> Select old/new patchsets to diff
|
<p> Select old/new patchsets to diff
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
def help(self):
|
||||||
|
return self._help
|
||||||
|
|
||||||
def __init__(self, app, new_revision_key):
|
def __init__(self, app, new_revision_key):
|
||||||
super(DiffView, self).__init__(urwid.Pile([]))
|
super(DiffView, self).__init__(urwid.Pile([]))
|
||||||
self.log = logging.getLogger('gertty.view.diff')
|
self.log = logging.getLogger('gertty.view.diff')
|
||||||
|
@ -66,11 +66,14 @@ class ProjectListHeader(urwid.WidgetWrap):
|
|||||||
super(ProjectListHeader, self).__init__(urwid.Columns(cols))
|
super(ProjectListHeader, self).__init__(urwid.Columns(cols))
|
||||||
|
|
||||||
class ProjectListView(urwid.WidgetWrap):
|
class ProjectListView(urwid.WidgetWrap):
|
||||||
help = """
|
_help = """
|
||||||
<l> Toggle whether only subscribed projects or all projects are listed.
|
<l> Toggle whether only subscribed projects or all projects are listed.
|
||||||
<s> Toggle the subscription flag for the currently selected project.
|
<s> Toggle the subscription flag for the currently selected project.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
def help(self):
|
||||||
|
return self._help
|
||||||
|
|
||||||
def __init__(self, app):
|
def __init__(self, app):
|
||||||
super(ProjectListView, self).__init__(urwid.Pile([]))
|
super(ProjectListView, self).__init__(urwid.Pile([]))
|
||||||
self.app = app
|
self.app = app
|
||||||
|
Loading…
x
Reference in New Issue
Block a user