Add support for starred changes
Change-Id: I2d57f0471f009e5e38d3652dbe3b0d9ac8854d7c
This commit is contained in:
parent
ac0c988603
commit
5dffc27d16
41
gertty/alembic/versions/4a802b741d2f_add_starred.py
Normal file
41
gertty/alembic/versions/4a802b741d2f_add_starred.py
Normal 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
|
16
gertty/db.py
16
gertty/db.py
@ -58,8 +58,10 @@ change_table = Table(
|
|||||||
Column('status', String(16), index=True, nullable=False),
|
Column('status', String(16), index=True, nullable=False),
|
||||||
Column('hidden', Boolean, index=True, nullable=False),
|
Column('hidden', Boolean, index=True, nullable=False),
|
||||||
Column('reviewed', 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_rebase', Boolean, index=True, nullable=False),
|
||||||
Column('pending_topic', 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', Boolean, index=True, nullable=False),
|
||||||
Column('pending_status_message', Text),
|
Column('pending_status_message', Text),
|
||||||
)
|
)
|
||||||
@ -180,11 +182,12 @@ class Branch(object):
|
|||||||
self.name = name
|
self.name = name
|
||||||
|
|
||||||
class Change(object):
|
class Change(object):
|
||||||
def __init__(self, project, id, owner, number, branch,
|
def __init__(self, project, id, owner, number, branch, change_id,
|
||||||
change_id, subject, created, updated, status,
|
subject, created, updated, status, topic=None,
|
||||||
topic=None, hidden=False, reviewed=False,
|
hidden=False, reviewed=False, starred=False,
|
||||||
pending_rebase=False, pending_topic=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.project_key = project.key
|
||||||
self.account_key = owner.key
|
self.account_key = owner.key
|
||||||
self.id = id
|
self.id = id
|
||||||
@ -198,8 +201,10 @@ class Change(object):
|
|||||||
self.status = status
|
self.status = status
|
||||||
self.hidden = hidden
|
self.hidden = hidden
|
||||||
self.reviewed = reviewed
|
self.reviewed = reviewed
|
||||||
|
self.starred = starred
|
||||||
self.pending_rebase = pending_rebase
|
self.pending_rebase = pending_rebase
|
||||||
self.pending_topic = pending_topic
|
self.pending_topic = pending_topic
|
||||||
|
self.pending_starred = pending_starred
|
||||||
self.pending_status = pending_status
|
self.pending_status = pending_status
|
||||||
self.pending_status_message = pending_status_message
|
self.pending_status_message = pending_status_message
|
||||||
|
|
||||||
@ -668,6 +673,9 @@ class DatabaseSession(object):
|
|||||||
def getPendingRebases(self):
|
def getPendingRebases(self):
|
||||||
return self.session().query(Change).filter_by(pending_rebase=True).all()
|
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):
|
def getPendingStatusChanges(self):
|
||||||
return self.session().query(Change).filter_by(pending_status=True).all()
|
return self.session().query(Change).filter_by(pending_status=True).all()
|
||||||
|
|
||||||
|
@ -37,6 +37,7 @@ CHANGE_SEARCH = 'change search'
|
|||||||
# Change screen:
|
# Change screen:
|
||||||
TOGGLE_REVIEWED = 'toggle reviewed'
|
TOGGLE_REVIEWED = 'toggle reviewed'
|
||||||
TOGGLE_HIDDEN = 'toggle hidden'
|
TOGGLE_HIDDEN = 'toggle hidden'
|
||||||
|
TOGGLE_STARRED = 'toggle starred'
|
||||||
REVIEW = 'review'
|
REVIEW = 'review'
|
||||||
DIFF = 'diff'
|
DIFF = 'diff'
|
||||||
LOCAL_CHECKOUT = 'local checkout'
|
LOCAL_CHECKOUT = 'local checkout'
|
||||||
@ -84,6 +85,7 @@ DEFAULT_KEYMAP = {
|
|||||||
|
|
||||||
TOGGLE_REVIEWED: 'v',
|
TOGGLE_REVIEWED: 'v',
|
||||||
TOGGLE_HIDDEN: 'k',
|
TOGGLE_HIDDEN: 'k',
|
||||||
|
TOGGLE_STARRED: '*',
|
||||||
REVIEW: 'r',
|
REVIEW: 'r',
|
||||||
DIFF: 'd',
|
DIFF: 'd',
|
||||||
LOCAL_CHECKOUT: 'c',
|
LOCAL_CHECKOUT: 'c',
|
||||||
|
@ -249,7 +249,7 @@ def SearchParser():
|
|||||||
|
|
||||||
def p_is_term(p):
|
def p_is_term(p):
|
||||||
'''is_term : OP_IS string'''
|
'''is_term : OP_IS string'''
|
||||||
#TODO: implement starred, watched, owner, reviewer, draft
|
#TODO: implement watched, draft
|
||||||
username = p.parser.username
|
username = p.parser.username
|
||||||
if p[2] == 'reviewed':
|
if p[2] == 'reviewed':
|
||||||
filters = []
|
filters = []
|
||||||
@ -269,6 +269,8 @@ def SearchParser():
|
|||||||
p[0] = gertty.db.change_table.c.status == 'ABANDONED'
|
p[0] = gertty.db.change_table.c.status == 'ABANDONED'
|
||||||
elif p[2] == 'owner':
|
elif p[2] == 'owner':
|
||||||
p[0] = gertty.db.account_table.c.username == username
|
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':
|
elif p[2] == 'reviewer':
|
||||||
filters = []
|
filters = []
|
||||||
filters.append(gertty.db.approval_table.c.change_key == gertty.db.change_table.c.key)
|
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))
|
s = select([gertty.db.change_table.c.key], correlate=False).where(and_(*filters))
|
||||||
p[0] = gertty.db.change_table.c.key.in_(s)
|
p[0] = gertty.db.change_table.c.key.in_(s)
|
||||||
else:
|
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):
|
def p_status_term(p):
|
||||||
'''status_term : OP_STATUS string'''
|
'''status_term : OP_STATUS string'''
|
||||||
|
@ -382,6 +382,10 @@ class SyncChangeTask(Task):
|
|||||||
if change.status != remote_change['status']:
|
if change.status != remote_change['status']:
|
||||||
change.status = remote_change['status']
|
change.status = remote_change['status']
|
||||||
result.status_changed = True
|
result.status_changed = True
|
||||||
|
if remote_change.get('starred'):
|
||||||
|
change.starred = True
|
||||||
|
else:
|
||||||
|
change.starred = False
|
||||||
change.subject = remote_change['subject']
|
change.subject = remote_change['subject']
|
||||||
change.updated = dateutil.parser.parse(remote_change['updated'])
|
change.updated = dateutil.parser.parse(remote_change['updated'])
|
||||||
change.topic = remote_change.get('topic')
|
change.topic = remote_change.get('topic')
|
||||||
@ -660,6 +664,8 @@ class UploadReviewsTask(Task):
|
|||||||
sync.submitTask(RebaseChangeTask(c.key, self.priority))
|
sync.submitTask(RebaseChangeTask(c.key, self.priority))
|
||||||
for c in session.getPendingStatusChanges():
|
for c in session.getPendingStatusChanges():
|
||||||
sync.submitTask(ChangeStatusTask(c.key, self.priority))
|
sync.submitTask(ChangeStatusTask(c.key, self.priority))
|
||||||
|
for c in session.getPendingStarred():
|
||||||
|
sync.submitTask(ChangeStarredTask(c.key, self.priority))
|
||||||
for c in session.getPendingCherryPicks():
|
for c in session.getPendingCherryPicks():
|
||||||
sync.submitTask(SendCherryPickTask(c.key, self.priority))
|
sync.submitTask(SendCherryPickTask(c.key, self.priority))
|
||||||
for r in session.getPendingCommitMessages():
|
for r in session.getPendingCommitMessages():
|
||||||
@ -703,6 +709,27 @@ class RebaseChangeTask(Task):
|
|||||||
sync.post('changes/%s/rebase' % (change.id,), {})
|
sync.post('changes/%s/rebase' % (change.id,), {})
|
||||||
sync.submitTask(SyncChangeTask(change.id, priority=self.priority))
|
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):
|
class ChangeStatusTask(Task):
|
||||||
def __init__(self, change_key, priority=NORMAL_PRIORITY):
|
def __init__(self, change_key, priority=NORMAL_PRIORITY):
|
||||||
super(ChangeStatusTask, self).__init__(priority)
|
super(ChangeStatusTask, self).__init__(priority)
|
||||||
@ -949,6 +976,17 @@ class Sync(object):
|
|||||||
'User-Agent': self.user_agent})
|
'User-Agent': self.user_agent})
|
||||||
self.log.debug('Received: %s' % (r.text,))
|
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):
|
def syncSubscribedProjects(self):
|
||||||
task = SyncSubscribedProjectsTask(LOW_PRIORITY)
|
task = SyncSubscribedProjectsTask(LOW_PRIORITY)
|
||||||
self.submitTask(task)
|
self.submitTask(task)
|
||||||
|
@ -410,6 +410,8 @@ class ChangeView(urwid.WidgetWrap):
|
|||||||
"Back to the list of changes"),
|
"Back to the list of changes"),
|
||||||
(key(keymap.TOGGLE_REVIEWED),
|
(key(keymap.TOGGLE_REVIEWED),
|
||||||
"Toggle the reviewed flag for the current change"),
|
"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),
|
(key(keymap.LOCAL_CHERRY_PICK),
|
||||||
"Cherry-pick the most recent revision onto the local repo"),
|
"Cherry-pick the most recent revision onto the local repo"),
|
||||||
(key(keymap.ABANDON_CHANGE),
|
(key(keymap.ABANDON_CHANGE),
|
||||||
@ -549,7 +551,12 @@ class ChangeView(urwid.WidgetWrap):
|
|||||||
hidden = ' (hidden)'
|
hidden = ' (hidden)'
|
||||||
else:
|
else:
|
||||||
hidden = ''
|
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.app.status.update(title=self.title)
|
||||||
self.project_key = change.project.key
|
self.project_key = change.project.key
|
||||||
self.change_rest_id = change.id
|
self.change_rest_id = change.id
|
||||||
@ -759,6 +766,14 @@ class ChangeView(urwid.WidgetWrap):
|
|||||||
change = session.getChange(self.change_key)
|
change = session.getChange(self.change_key)
|
||||||
change.hidden = not change.hidden
|
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):
|
def keypress(self, size, key):
|
||||||
r = super(ChangeView, self).keypress(size, key)
|
r = super(ChangeView, self).keypress(size, key)
|
||||||
commands = self.app.config.keymap.getCommands(r)
|
commands = self.app.config.keymap.getCommands(r)
|
||||||
@ -770,6 +785,10 @@ class ChangeView(urwid.WidgetWrap):
|
|||||||
self.toggleHidden()
|
self.toggleHidden()
|
||||||
self.refresh()
|
self.refresh()
|
||||||
return None
|
return None
|
||||||
|
if keymap.TOGGLE_STARRED in commands:
|
||||||
|
self.toggleStarred()
|
||||||
|
self.refresh()
|
||||||
|
return None
|
||||||
if keymap.REVIEW in commands:
|
if keymap.REVIEW in commands:
|
||||||
row = self.revision_rows[self.last_revision_key]
|
row = self.revision_rows[self.last_revision_key]
|
||||||
row.review_button.openReview()
|
row.review_button.openReview()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user