def checkGitRepo(self): missing_revisions = set() change_number = None change_id = None with self.app.db.getSession() as session: change = session.getChange(self.change_key) change_number = change.number change_id = change.id repo = gitrepo.get_repo(change.project.name, self.app.config) for revision in change.revisions: if not repo.hasCommit(revision.parent): missing_revisions.add(revision.parent) if not repo.hasCommit(revision.commit): missing_revisions.add(revision.commit) if missing_revisions: break if missing_revisions: if self.app.sync.offline: raise gertty.view.DisplayError("Git commits not present in local repository") self.app.log.warning("Missing some commits for change %s %s", change_number, missing_revisions) task = sync.SyncChangeTask(change_id, force_fetch=True, priority=sync.HIGH_PRIORITY) self.app.sync.submitTask(task) succeeded = task.wait(300) if not succeeded: raise gertty.view.DisplayError("Git commits not present in local repository")
def checkGitRepo(self): missing_revisions = set() change_number = None change_id = None with self.app.db.getSession() as session: change = session.getChange(self.change_key) change_number = change.number change_id = change.id repo = gitrepo.get_repo(change.project.name, self.app.config) for revision in change.revisions: if not repo.hasCommit(revision.parent): missing_revisions.add(revision.parent) if not repo.hasCommit(revision.commit): missing_revisions.add(revision.commit) if missing_revisions: break if missing_revisions: if self.app.sync.offline: raise gertty.view.DisplayError( "Git commits not present in local repository") self.app.log.warning("Missing some commits for change %s %s", change_number, missing_revisions) task = sync.SyncChangeTask(change_id, force_fetch=True, priority=sync.HIGH_PRIORITY) self.app.sync.submitTask(task) succeeded = task.wait(300) if not succeeded: raise gertty.view.DisplayError( "Git commits not present in local repository")
def localCherryPickCommit(self, project_name, commit_sha): repo = gitrepo.get_repo(project_name, self.config) try: repo.cherryPick(commit_sha) dialog = mywid.MessageDialog('Cherry-Pick', 'Change cherry-picked in %s' % repo.path) min_height=8 except gitrepo.GitCheckoutError as e: dialog = mywid.MessageDialog('Error', e.msg) min_height=12 urwid.connect_signal(dialog, 'close', lambda button: self.backScreen()) self.popup(dialog, min_height=min_height)
def _init(self): del self._w.contents[:] self.searchInit() with self.app.db.getSession() as session: new_revision = session.getRevision(self.new_revision_key) old_comments = [] new_comments = [] self.old_file_keys = {} self.new_file_keys = {} if self.old_revision_key is not None: old_revision = session.getRevision(self.old_revision_key) self.old_revision_num = old_revision.number old_str = 'patchset %s' % self.old_revision_num self.base_commit = old_revision.commit for f in old_revision.files: old_comments += f.comments self.old_file_keys[f.path] = f.key show_old_commit = True else: old_revision = None self.old_revision_num = None old_str = 'base' self.base_commit = new_revision.parent show_old_commit = False # The old files are the same as the new files since we # are diffing from base -> change, however, we should # use the old file names for file lookup. for f in new_revision.files: if f.old_path: self.old_file_keys[f.old_path] = f.key else: self.old_file_keys[f.path] = f.key self.title = u'Diff of %s change %s from %s to patchset %s' % ( new_revision.change.project.name, new_revision.change.number, old_str, new_revision.number) self.short_title = u'Diff of %s' % (new_revision.change.number,) self.new_revision_num = new_revision.number self.change_key = new_revision.change.key self.project_name = new_revision.change.project.name self.commit = new_revision.commit for f in new_revision.files: new_comments += f.comments self.new_file_keys[f.path] = f.key comment_lists = {} comment_filenames = set() for comment in new_comments: path = comment.file.path if comment.parent: if old_revision: # we're not looking at the base continue key = 'old' if comment.file.old_path: path = comment.file.old_path else: key = 'new' if comment.draft: key += 'draft' key += '-' + str(comment.line) key += '-' + path comment_list = comment_lists.get(key, []) if comment.draft: message = comment.message else: message = [('comment-name', comment.author.name), ('comment', u': '+comment.message)] comment_list.append((comment.key, message)) comment_lists[key] = comment_list comment_filenames.add(path) for comment in old_comments: if comment.parent: continue path = comment.file.path key = 'old' if comment.draft: key += 'draft' key += '-' + str(comment.line) key += '-' + path comment_list = comment_lists.get(key, []) if comment.draft: message = comment.message else: message = [('comment-name', comment.author.name), ('comment', u': '+comment.message)] comment_list.append((comment.key, message)) comment_lists[key] = comment_list comment_filenames.add(path) repo = gitrepo.get_repo(self.project_name, self.app.config) self._w.contents.append((self.app.header, ('pack', 1))) self.file_reminder = self.makeFileReminder() self._w.contents.append((self.file_reminder, ('pack', 1))) lines = [] # The initial set of lines to display self.file_diffs = [{}, {}] # Mapping of fn -> DiffFile object (old, new) # this is a list of files: diffs = repo.diff(self.base_commit, self.commit, show_old_commit=show_old_commit) for diff in diffs: comment_filenames.discard(diff.oldname) comment_filenames.discard(diff.newname) # There are comments referring to these files which do not # appear in the diff so we should create fake diff objects # that contain the full text. for filename in comment_filenames: diff = repo.getFile(self.base_commit, self.commit, filename) if diff: diffs.append(diff) else: self.log.debug("Unable to find file %s in commit %s" % (filename, self.commit)) for i, diff in enumerate(diffs): if i > 0: lines.append(urwid.Text('')) self.file_diffs[gitrepo.OLD][diff.oldname] = diff self.file_diffs[gitrepo.NEW][diff.newname] = diff lines.extend(self.makeFileHeader(diff, comment_lists)) for chunk in diff.chunks: if chunk.context: if not chunk.first: lines += self.makeLines(diff, chunk.lines[:10], comment_lists) del chunk.lines[:10] button = DiffContextButton(self, diff, chunk) chunk.button = button lines.append(button) if not chunk.last: lines += self.makeLines(diff, chunk.lines[-10:], comment_lists) del chunk.lines[-10:] chunk.calcRange() chunk.button.update() if not chunk.lines: lines.remove(button) else: lines += self.makeLines(diff, chunk.lines, comment_lists) listwalker = urwid.SimpleFocusListWalker(lines) self.listbox = urwid.ListBox(listwalker) self._w.contents.append((self.listbox, ('weight', 1))) self.old_focus = 2 self.draft_comments = [] self._w.set_focus(self.old_focus) self.handleUndisplayedComments(comment_lists) self.app.status.update(title=self.title)
def refresh(self): with self.app.db.getSession() as session: change = session.getChange(self.change_key) # When we first open the change, update its last_seen # time. if not self.marked_seen: change.last_seen = datetime.datetime.utcnow() self.marked_seen = True self.topic = change.topic or '' self.pending_status_message = change.pending_status_message or '' reviewed = hidden = starred = held = '' if change.reviewed: reviewed = ' (reviewed)' if change.hidden: hidden = ' (hidden)' if change.starred: starred = '* ' if change.held: held = ' (held)' self.title = '%sChange %s%s%s%s' % (starred, change.number, reviewed, hidden, held) self.app.status.update(title=self.title) self.project_key = change.project.key self.project_name = change.project.name self.change_rest_id = change.id self.change_id = change.change_id if change.owner: self.owner_email = change.owner.email else: self.owner_email = None self.change_id_label.text.set_text(('change-data', change.change_id)) self.owner_label.text.set_text(('change-data', change.owner_name)) self.project_label.text.set_text(('change-data', change.project.name)) self.branch_label.set_text(('change-data', change.branch)) self.topic_label.text.set_text(('change-data', self.topic)) self.created_label.set_text(('change-data', str(self.app.time(change.created)))) self.updated_label.set_text(('change-data', str(self.app.time(change.updated)))) self.status_label.set_text(('change-data', change.status)) self.permalink_url = urlparse.urljoin(self.app.config.url, str(change.number)) self.permalink_label.text.set_text(('change-data', self.permalink_url)) self.commit_message.set_text(change.revisions[-1].message) categories = [] approval_headers = [urwid.Text(('table-header', 'Name'))] for label in change.labels: if label.category in categories: continue approval_headers.append(urwid.Text(('table-header', label.category))) categories.append(label.category) votes = mywid.Table(approval_headers) approvals_for_name = {} pending_message = change.revisions[-1].getPendingMessage() for approval in change.approvals: # Don't display draft approvals unless they are pending-upload if approval.draft and not pending_message: continue approvals = approvals_for_name.get(approval.reviewer.name) if not approvals: approvals = {} row = [] if approval.reviewer.username == self.app.config.username: style = 'reviewer-own-name' else: style = 'reviewer-name' row.append(urwid.Text((style, approval.reviewer.name))) for i, category in enumerate(categories): w = urwid.Text(u'', align=urwid.CENTER) approvals[category] = w row.append(w) approvals_for_name[approval.reviewer.name] = approvals votes.addRow(row) if str(approval.value) != '0': cat_min, cat_max = change.getMinMaxPermittedForCategory(approval.category) if approval.value > 0: val = '+%i' % approval.value if approval.value == cat_max: val = ('max-label', val) else: val = ('positive-label', val) else: val = '%i' % approval.value if approval.value == cat_min: val = ('min-label', val) else: val = ('negative-label', val) approvals[approval.category].set_text(val) votes = urwid.Padding(votes, width='pack') # TODO: update the existing table rather than replacing it # wholesale. It will become more important if the table # gets selectable items (like clickable names). self.grid.contents[2] = (votes, ('given', 80)) self.refreshDependencies(session, change) repo = gitrepo.get_repo(change.project.name, self.app.config) # The listbox has both revisions and messages in it (and # may later contain the vote table and change header), so # keep track of the index separate from the loop. listbox_index = self.listbox_patchset_start for revno, revision in enumerate(change.revisions): self.last_revision_key = revision.key row = self.revision_rows.get(revision.key) if not row: row = RevisionRow(self.app, self, repo, revision, expanded=(revno==len(change.revisions)-1)) self.listbox.body.insert(listbox_index, row) self.revision_rows[revision.key] = row row.update(revision) # Revisions are extremely unlikely to be deleted, skip # that case. listbox_index += 1 if len(self.listbox.body) == listbox_index: self.listbox.body.insert(listbox_index, urwid.Divider()) listbox_index += 1 # Get the set of messages that should be displayed display_messages = [] result_systems = {} for message in change.messages: if (message.revision == change.revisions[-1] and message.author and message.author.name): for commentlink in self.app.config.commentlinks: results = commentlink.getTestResults(self.app, message.message) if results: result_system = result_systems.get(message.author.name, {}) result_systems[message.author.name] = result_system result_system.update(results) skip = False if self.hide_comments and message.author and message.author.name: for regex in self.app.config.hide_comments: if regex.match(message.author.name): skip = True break if not skip: display_messages.append(message) # The set of message keys currently displayed unseen_keys = set(self.message_rows.keys()) # Make sure all of the messages that should be displayed are for message in display_messages: row = self.message_rows.get(message.key) if not row: box = ChangeMessageBox(self.app, message) row = urwid.Padding(box, width=80) self.listbox.body.insert(listbox_index, row) self.message_rows[message.key] = row else: unseen_keys.remove(message.key) if message.created != row.original_widget.message_created: row.original_widget.refresh(message) listbox_index += 1 # Remove any messages that should not be displayed for key in unseen_keys: row = self.message_rows.get(key) self.listbox.body.remove(row) del self.message_rows[key] listbox_index -= 1 self._updateTestResults(result_systems)
def refresh(self): with self.app.db.getSession() as session: change = session.getChange(self.change_key) # When we first open the change, update its last_seen # time. if not self.marked_seen: change.last_seen = datetime.datetime.utcnow() self.marked_seen = True self.topic = change.topic or '' self.pending_status_message = change.pending_status_message or '' reviewed = hidden = starred = held = '' if change.reviewed: reviewed = ' (reviewed)' if change.hidden: hidden = ' (hidden)' if change.starred: starred = '* ' if change.held: held = ' (held)' self.title = '%sChange %s%s%s%s' % (starred, change.number, reviewed, hidden, held) self.app.status.update(title=self.title) self.project_key = change.project.key self.project_name = change.project.name self.change_rest_id = change.id self.change_id = change.change_id if change.owner: self.owner_email = change.owner.email else: self.owner_email = None self.change_id_label.text.set_text( ('change-data', change.change_id)) self.owner_label.text.set_text(('change-data', change.owner_name)) self.project_label.text.set_text( ('change-data', change.project.name)) self.branch_label.set_text(('change-data', change.branch)) self.topic_label.text.set_text(('change-data', self.topic)) self.created_label.set_text( ('change-data', str(self.app.time(change.created)))) self.updated_label.set_text( ('change-data', str(self.app.time(change.updated)))) self.status_label.set_text(('change-data', change.status)) self.permalink_url = urlparse.urljoin(self.app.config.url, str(change.number)) self.permalink_label.text.set_text( ('change-data', self.permalink_url)) self.commit_message.set_text(change.revisions[-1].message) categories = [] approval_headers = [urwid.Text(('table-header', 'Name'))] for label in change.labels: if label.category in categories: continue approval_headers.append( urwid.Text(('table-header', label.category))) categories.append(label.category) votes = mywid.Table(approval_headers) approvals_for_name = {} pending_message = change.revisions[-1].getPendingMessage() for approval in change.approvals: # Don't display draft approvals unless they are pending-upload if approval.draft and not pending_message: continue approvals = approvals_for_name.get(approval.reviewer.name) if not approvals: approvals = {} row = [] if approval.reviewer.username == self.app.config.username: style = 'reviewer-own-name' else: style = 'reviewer-name' row.append(urwid.Text((style, approval.reviewer.name))) for i, category in enumerate(categories): w = urwid.Text(u'', align=urwid.CENTER) approvals[category] = w row.append(w) approvals_for_name[approval.reviewer.name] = approvals votes.addRow(row) if str(approval.value) != '0': cat_min, cat_max = change.getMinMaxPermittedForCategory( approval.category) if approval.value > 0: val = '+%i' % approval.value if approval.value == cat_max: val = ('max-label', val) else: val = ('positive-label', val) else: val = '%i' % approval.value if approval.value == cat_min: val = ('min-label', val) else: val = ('negative-label', val) approvals[approval.category].set_text(val) votes = urwid.Padding(votes, width='pack') # TODO: update the existing table rather than replacing it # wholesale. It will become more important if the table # gets selectable items (like clickable names). self.grid.contents[2] = (votes, ('given', 80)) self.refreshDependencies(session, change) repo = gitrepo.get_repo(change.project.name, self.app.config) # The listbox has both revisions and messages in it (and # may later contain the vote table and change header), so # keep track of the index separate from the loop. listbox_index = self.listbox_patchset_start for revno, revision in enumerate(change.revisions): self.last_revision_key = revision.key row = self.revision_rows.get(revision.key) if not row: row = RevisionRow( self.app, self, repo, revision, expanded=(revno == len(change.revisions) - 1)) self.listbox.body.insert(listbox_index, row) self.revision_rows[revision.key] = row row.update(revision) # Revisions are extremely unlikely to be deleted, skip # that case. listbox_index += 1 if len(self.listbox.body) == listbox_index: self.listbox.body.insert(listbox_index, urwid.Divider()) listbox_index += 1 # Get the set of messages that should be displayed display_messages = [] result_systems = {} for message in change.messages: if (message.revision == change.revisions[-1] and message.author and message.author.name): for commentlink in self.app.config.commentlinks: results = commentlink.getTestResults( self.app, message.message) if results: result_system = result_systems.get( message.author.name, {}) result_systems[message.author.name] = result_system result_system.update(results) skip = False if self.hide_comments and message.author and message.author.name: for regex in self.app.config.hide_comments: if regex.match(message.author.name): skip = True break if not skip: display_messages.append(message) # The set of message keys currently displayed unseen_keys = set(self.message_rows.keys()) # Make sure all of the messages that should be displayed are for message in display_messages: row = self.message_rows.get(message.key) if not row: box = ChangeMessageBox(self.app, message) row = urwid.Padding(box, width=80) self.listbox.body.insert(listbox_index, row) self.message_rows[message.key] = row else: unseen_keys.remove(message.key) if message.created != row.original_widget.message_created: row.original_widget.refresh(message) listbox_index += 1 # Remove any messages that should not be displayed for key in unseen_keys: row = self.message_rows.get(key) self.listbox.body.remove(row) del self.message_rows[key] listbox_index -= 1 self._updateTestResults(result_systems)