Add support for starred changes

Change-Id: I2d57f0471f009e5e38d3652dbe3b0d9ac8854d7c
This commit is contained in:
James E. Blair 2015-02-12 18:50:15 -08:00
parent ac0c988603
commit 5dffc27d16
6 changed files with 117 additions and 7 deletions

View File

@ -0,0 +1,41 @@
"""add starred
Revision ID: 4a802b741d2f
Revises: 312cd5a9f878
Create Date: 2015-02-12 18:10:19.187733
"""
# revision identifiers, used by Alembic.
revision = '4a802b741d2f'
down_revision = '312cd5a9f878'
import warnings
from alembic import op
import sqlalchemy as sa
from gertty.dbsupport import sqlite_alter_columns
def upgrade():
with warnings.catch_warnings():
warnings.simplefilter("ignore")
op.add_column('change', sa.Column('starred', sa.Boolean()))
op.add_column('change', sa.Column('pending_starred', sa.Boolean()))
connection = op.get_bind()
change = sa.sql.table('change',
sa.sql.column('starred', sa.Boolean()),
sa.sql.column('pending_starred', sa.Boolean()))
connection.execute(change.update().values({'starred':False,
'pending_starred':False}))
sqlite_alter_columns('change', [
sa.Column('starred', sa.Boolean(), index=True, nullable=False),
sa.Column('pending_starred', sa.Boolean(), index=True, nullable=False),
])
def downgrade():
pass

View File

@ -58,8 +58,10 @@ change_table = Table(
Column('status', String(16), index=True, nullable=False),
Column('hidden', Boolean, index=True, nullable=False),
Column('reviewed', Boolean, index=True, nullable=False),
Column('starred', Boolean, index=True, nullable=False),
Column('pending_rebase', Boolean, index=True, nullable=False),
Column('pending_topic', Boolean, index=True, nullable=False),
Column('pending_starred', Boolean, index=True, nullable=False),
Column('pending_status', Boolean, index=True, nullable=False),
Column('pending_status_message', Text),
)
@ -180,11 +182,12 @@ class Branch(object):
self.name = name
class Change(object):
def __init__(self, project, id, owner, number, branch,
change_id, subject, created, updated, status,
topic=None, hidden=False, reviewed=False,
def __init__(self, project, id, owner, number, branch, change_id,
subject, created, updated, status, topic=None,
hidden=False, reviewed=False, starred=False,
pending_rebase=False, pending_topic=False,
pending_status=False, pending_status_message=None):
pending_starred=False, pending_status=False,
pending_status_message=None):
self.project_key = project.key
self.account_key = owner.key
self.id = id
@ -198,8 +201,10 @@ class Change(object):
self.status = status
self.hidden = hidden
self.reviewed = reviewed
self.starred = starred
self.pending_rebase = pending_rebase
self.pending_topic = pending_topic
self.pending_starred = pending_starred
self.pending_status = pending_status
self.pending_status_message = pending_status_message
@ -668,6 +673,9 @@ class DatabaseSession(object):
def getPendingRebases(self):
return self.session().query(Change).filter_by(pending_rebase=True).all()
def getPendingStarred(self):
return self.session().query(Change).filter_by(pending_starred=True).all()
def getPendingStatusChanges(self):
return self.session().query(Change).filter_by(pending_status=True).all()

View File

@ -37,6 +37,7 @@ CHANGE_SEARCH = 'change search'
# Change screen:
TOGGLE_REVIEWED = 'toggle reviewed'
TOGGLE_HIDDEN = 'toggle hidden'
TOGGLE_STARRED = 'toggle starred'
REVIEW = 'review'
DIFF = 'diff'
LOCAL_CHECKOUT = 'local checkout'
@ -84,6 +85,7 @@ DEFAULT_KEYMAP = {
TOGGLE_REVIEWED: 'v',
TOGGLE_HIDDEN: 'k',
TOGGLE_STARRED: '*',
REVIEW: 'r',
DIFF: 'd',
LOCAL_CHECKOUT: 'c',

View File

@ -249,7 +249,7 @@ def SearchParser():
def p_is_term(p):
'''is_term : OP_IS string'''
#TODO: implement starred, watched, owner, reviewer, draft
#TODO: implement watched, draft
username = p.parser.username
if p[2] == 'reviewed':
filters = []
@ -269,6 +269,8 @@ def SearchParser():
p[0] = gertty.db.change_table.c.status == 'ABANDONED'
elif p[2] == 'owner':
p[0] = gertty.db.account_table.c.username == username
elif p[2] == 'starred':
p[0] = gertty.db.change_table.c.starred == True
elif p[2] == 'reviewer':
filters = []
filters.append(gertty.db.approval_table.c.change_key == gertty.db.change_table.c.key)
@ -277,7 +279,7 @@ def SearchParser():
s = select([gertty.db.change_table.c.key], correlate=False).where(and_(*filters))
p[0] = gertty.db.change_table.c.key.in_(s)
else:
raise gertty.search.SearchSyntaxError('Syntax error: has:%s is not supported' % p[2])
raise gertty.search.SearchSyntaxError('Syntax error: is:%s is not supported' % p[2])
def p_status_term(p):
'''status_term : OP_STATUS string'''

View File

@ -382,6 +382,10 @@ class SyncChangeTask(Task):
if change.status != remote_change['status']:
change.status = remote_change['status']
result.status_changed = True
if remote_change.get('starred'):
change.starred = True
else:
change.starred = False
change.subject = remote_change['subject']
change.updated = dateutil.parser.parse(remote_change['updated'])
change.topic = remote_change.get('topic')
@ -660,6 +664,8 @@ class UploadReviewsTask(Task):
sync.submitTask(RebaseChangeTask(c.key, self.priority))
for c in session.getPendingStatusChanges():
sync.submitTask(ChangeStatusTask(c.key, self.priority))
for c in session.getPendingStarred():
sync.submitTask(ChangeStarredTask(c.key, self.priority))
for c in session.getPendingCherryPicks():
sync.submitTask(SendCherryPickTask(c.key, self.priority))
for r in session.getPendingCommitMessages():
@ -703,6 +709,27 @@ class RebaseChangeTask(Task):
sync.post('changes/%s/rebase' % (change.id,), {})
sync.submitTask(SyncChangeTask(change.id, priority=self.priority))
class ChangeStarredTask(Task):
def __init__(self, change_key, priority=NORMAL_PRIORITY):
super(ChangeStarredTask, self).__init__(priority)
self.change_key = change_key
def __repr__(self):
return '<ChangeStarredTask %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.starred:
sync.put('accounts/self/starred.changes/%s' % (change.id,),
data={})
else:
sync.delete('accounts/self/starred.changes/%s' % (change.id,),
data={})
change.pending_starred = False
sync.submitTask(SyncChangeTask(change.id, priority=self.priority))
class ChangeStatusTask(Task):
def __init__(self, change_key, priority=NORMAL_PRIORITY):
super(ChangeStatusTask, self).__init__(priority)
@ -949,6 +976,17 @@ class Sync(object):
'User-Agent': self.user_agent})
self.log.debug('Received: %s' % (r.text,))
def delete(self, path, data):
url = self.url(path)
self.log.debug('DELETE: %s' % (url,))
self.log.debug('data: %s' % (data,))
r = self.session.delete(url, data=json.dumps(data).encode('utf8'),
verify=self.app.config.verify_ssl,
auth=self.auth,
headers = {'Content-Type': 'application/json;charset=UTF-8',
'User-Agent': self.user_agent})
self.log.debug('Received: %s' % (r.text,))
def syncSubscribedProjects(self):
task = SyncSubscribedProjectsTask(LOW_PRIORITY)
self.submitTask(task)

View File

@ -410,6 +410,8 @@ class ChangeView(urwid.WidgetWrap):
"Back to the list of changes"),
(key(keymap.TOGGLE_REVIEWED),
"Toggle the reviewed flag for the current change"),
(key(keymap.TOGGLE_STARRED),
"Toggle the starred flag for the current change"),
(key(keymap.LOCAL_CHERRY_PICK),
"Cherry-pick the most recent revision onto the local repo"),
(key(keymap.ABANDON_CHANGE),
@ -549,7 +551,12 @@ class ChangeView(urwid.WidgetWrap):
hidden = ' (hidden)'
else:
hidden = ''
self.title = 'Change %s%s%s' % (change.number, reviewed, hidden)
if change.starred:
starred = '* '
else:
starred = ''
self.title = '%sChange %s%s%s' % (starred, change.number,
reviewed, hidden)
self.app.status.update(title=self.title)
self.project_key = change.project.key
self.change_rest_id = change.id
@ -759,6 +766,14 @@ class ChangeView(urwid.WidgetWrap):
change = session.getChange(self.change_key)
change.hidden = not change.hidden
def toggleStarred(self):
with self.app.db.getSession() as session:
change = session.getChange(self.change_key)
change.starred = not change.starred
change.pending_starred = True
self.app.sync.submitTask(
sync.ChangeStarredTask(self.change_key, sync.HIGH_PRIORITY))
def keypress(self, size, key):
r = super(ChangeView, self).keypress(size, key)
commands = self.app.config.keymap.getCommands(r)
@ -770,6 +785,10 @@ class ChangeView(urwid.WidgetWrap):
self.toggleHidden()
self.refresh()
return None
if keymap.TOGGLE_STARRED in commands:
self.toggleStarred()
self.refresh()
return None
if keymap.REVIEW in commands:
row = self.revision_rows[self.last_revision_key]
row.review_button.openReview()