def patchwork_status(branch, count, start, end, dest_branch, force, show_comments, url): """Check the status of patches in patchwork This finds the series in patchwork using the Series-link tag, checks for new comments and review tags, displays then and creates a new branch with the review tags. Args: branch (str): Branch to create patches from (None = current) count (int): Number of patches to produce, or -1 to produce patches for the current branch back to the upstream commit start (int): Start partch to use (0=first / top of branch) end (int): End patch to use (0=last one in series, 1=one before that, etc.) dest_branch (str): Name of new branch to create with the updated tags (None to not create a branch) force (bool): With dest_branch, force overwriting an existing branch show_comments (bool): True to display snippets from the comments provided by reviewers url (str): URL of patchwork server, e.g. 'https://patchwork.ozlabs.org'. This is ignored if the series provides a Series-patchwork-url tag. Raises: ValueError: if the branch has no Series-link value """ if count == -1: # Work out how many patches to send if we can count = (gitutil.CountCommitsToBranch(branch) - start) series = patchstream.get_metadata(branch, start, count - end) warnings = 0 for cmt in series.commits: if cmt.warn: print('%d warnings for %s:' % (len(cmt.warn), cmt.hash)) for warn in cmt.warn: print('\t', warn) warnings += 1 print if warnings: raise ValueError('Please fix warnings before running status') links = series.get('links') if not links: raise ValueError("Branch has no Series-links value") # Find the link without a version number (we don't support versions yet) found = [link for link in links.split() if not ':' in link] if not found: raise ValueError('Series-links has no current version (without :)') # Allow the series to override the URL if 'patchwork_url' in series: url = series.patchwork_url # Import this here to avoid failing on other commands if the dependencies # are not present from patman import status status.check_patchwork_status(series, found[0], branch, dest_branch, force, show_comments, url)
def test_find_new_responses(self): """Test operation of find_new_responses()""" commit1 = Commit('abcd') commit1.subject = 'Subject 1' commit2 = Commit('ef12') commit2.subject = 'Subject 2' patch1 = status.Patch('1') patch1.parse_subject('[1/2] Subject 1') patch1.name = patch1.raw_subject patch1.content = 'This is my patch content' comment1a = {'content': 'Reviewed-by: %s\n' % self.joe} patch1.comments = [comment1a] patch2 = status.Patch('2') patch2.parse_subject('[2/2] Subject 2') patch2.name = patch2.raw_subject patch2.content = 'Some other patch content' comment2a = { 'content': 'Reviewed-by: %s\nTested-by: %s\n' % (self.mary, self.leb) } comment2b = {'content': 'Reviewed-by: %s' % self.fred} patch2.comments = [comment2a, comment2b] # This test works by setting up commits and patch for use by the fake # Rest API function _fake_patchwork2(). It calls various functions in # the status module after setting up tags in the commits, checking that # things behaves as expected self.commits = [commit1, commit2] self.patches = [patch1, patch2] count = 2 new_rtag_list = [None] * count review_list = [None, None] # Check that the tags are picked up on the first patch status.find_new_responses(new_rtag_list, review_list, 0, commit1, patch1, None, self._fake_patchwork2) self.assertEqual(new_rtag_list[0], {'Reviewed-by': {self.joe}}) # Now the second patch status.find_new_responses(new_rtag_list, review_list, 1, commit2, patch2, None, self._fake_patchwork2) self.assertEqual(new_rtag_list[1], { 'Reviewed-by': {self.mary, self.fred}, 'Tested-by': {self.leb} }) # Now add some tags to the commit, which means they should not appear as # 'new' tags when scanning comments new_rtag_list = [None] * count commit1.rtags = {'Reviewed-by': {self.joe}} status.find_new_responses(new_rtag_list, review_list, 0, commit1, patch1, None, self._fake_patchwork2) self.assertEqual(new_rtag_list[0], {}) # For the second commit, add Ed and Fred, so only Mary should be left commit2.rtags = {'Tested-by': {self.leb}, 'Reviewed-by': {self.fred}} status.find_new_responses(new_rtag_list, review_list, 1, commit2, patch2, None, self._fake_patchwork2) self.assertEqual(new_rtag_list[1], {'Reviewed-by': {self.mary}}) # Check that the output patches expectations: # 1 Subject 1 # Reviewed-by: Joe Bloggs <*****@*****.**> # 2 Subject 2 # Tested-by: Lord Edmund Blackaddër <*****@*****.**> # Reviewed-by: Fred Bloggs <*****@*****.**> # + Reviewed-by: Mary Bloggs <*****@*****.**> # 1 new response available in patchwork series = Series() series.commits = [commit1, commit2] terminal.set_print_test_mode() status.check_patchwork_status(series, '1234', None, None, False, False, None, self._fake_patchwork2) lines = iter(terminal.get_print_test_lines()) col = terminal.Color() self.assertEqual(terminal.PrintLine(' 1 Subject 1', col.BLUE), next(lines)) self.assertEqual( terminal.PrintLine(' Reviewed-by: ', col.GREEN, newline=False, bright=False), next(lines)) self.assertEqual(terminal.PrintLine(self.joe, col.WHITE, bright=False), next(lines)) self.assertEqual(terminal.PrintLine(' 2 Subject 2', col.BLUE), next(lines)) self.assertEqual( terminal.PrintLine(' Reviewed-by: ', col.GREEN, newline=False, bright=False), next(lines)) self.assertEqual( terminal.PrintLine(self.fred, col.WHITE, bright=False), next(lines)) self.assertEqual( terminal.PrintLine(' Tested-by: ', col.GREEN, newline=False, bright=False), next(lines)) self.assertEqual(terminal.PrintLine(self.leb, col.WHITE, bright=False), next(lines)) self.assertEqual( terminal.PrintLine(' + Reviewed-by: ', col.GREEN, newline=False), next(lines)) self.assertEqual(terminal.PrintLine(self.mary, col.WHITE), next(lines)) self.assertEqual( terminal.PrintLine( '1 new response available in patchwork (use -d to write them to a new branch)', None), next(lines))
def test_review_snippets(self): """Test showing of review snippets""" def _to_submitter(who): m_who = re.match('(.*) <(.*)>', who) return {'name': m_who.group(1), 'email': m_who.group(2)} commit1 = Commit('abcd') commit1.subject = 'Subject 1' commit2 = Commit('ef12') commit2.subject = 'Subject 2' patch1 = status.Patch('1') patch1.parse_subject('[1/2] Subject 1') patch1.name = patch1.raw_subject patch1.content = 'This is my patch content' comment1a = { 'submitter': _to_submitter(self.joe), 'content': '''Hi Fred, On some date Fred wrote: > diff --git a/file.c b/file.c > Some code > and more code Here is my comment above the above... Reviewed-by: %s ''' % self.joe } patch1.comments = [comment1a] patch2 = status.Patch('2') patch2.parse_subject('[2/2] Subject 2') patch2.name = patch2.raw_subject patch2.content = 'Some other patch content' comment2a = { 'content': 'Reviewed-by: %s\nTested-by: %s\n' % (self.mary, self.leb) } comment2b = { 'submitter': _to_submitter(self.fred), 'content': '''Hi Fred, On some date Fred wrote: > diff --git a/tools/patman/commit.py b/tools/patman/commit.py > @@ -41,6 +41,9 @@ class Commit: > self.rtags = collections.defaultdict(set) > self.warn = [] > > + def __str__(self): > + return self.subject > + > def add_change(self, version, info): > """Add a new change line to the change list for a version. > A comment Reviewed-by: %s ''' % self.fred } patch2.comments = [comment2a, comment2b] # This test works by setting up commits and patch for use by the fake # Rest API function _fake_patchwork2(). It calls various functions in # the status module after setting up tags in the commits, checking that # things behaves as expected self.commits = [commit1, commit2] self.patches = [patch1, patch2] # Check that the output patches expectations: # 1 Subject 1 # Reviewed-by: Joe Bloggs <*****@*****.**> # 2 Subject 2 # Tested-by: Lord Edmund Blackaddër <*****@*****.**> # Reviewed-by: Fred Bloggs <*****@*****.**> # + Reviewed-by: Mary Bloggs <*****@*****.**> # 1 new response available in patchwork series = Series() series.commits = [commit1, commit2] terminal.set_print_test_mode() status.check_patchwork_status(series, '1234', None, None, False, True, None, self._fake_patchwork2) lines = iter(terminal.get_print_test_lines()) col = terminal.Color() self.assertEqual(terminal.PrintLine(' 1 Subject 1', col.BLUE), next(lines)) self.assertEqual( terminal.PrintLine(' + Reviewed-by: ', col.GREEN, newline=False), next(lines)) self.assertEqual(terminal.PrintLine(self.joe, col.WHITE), next(lines)) self.assertEqual(terminal.PrintLine('Review: %s' % self.joe, col.RED), next(lines)) self.assertEqual(terminal.PrintLine(' Hi Fred,', None), next(lines)) self.assertEqual(terminal.PrintLine('', None), next(lines)) self.assertEqual(terminal.PrintLine(' > File: file.c', col.MAGENTA), next(lines)) self.assertEqual(terminal.PrintLine(' > Some code', col.MAGENTA), next(lines)) self.assertEqual( terminal.PrintLine(' > and more code', col.MAGENTA), next(lines)) self.assertEqual( terminal.PrintLine(' Here is my comment above the above...', None), next(lines)) self.assertEqual(terminal.PrintLine('', None), next(lines)) self.assertEqual(terminal.PrintLine(' 2 Subject 2', col.BLUE), next(lines)) self.assertEqual( terminal.PrintLine(' + Reviewed-by: ', col.GREEN, newline=False), next(lines)) self.assertEqual(terminal.PrintLine(self.fred, col.WHITE), next(lines)) self.assertEqual( terminal.PrintLine(' + Reviewed-by: ', col.GREEN, newline=False), next(lines)) self.assertEqual(terminal.PrintLine(self.mary, col.WHITE), next(lines)) self.assertEqual( terminal.PrintLine(' + Tested-by: ', col.GREEN, newline=False), next(lines)) self.assertEqual(terminal.PrintLine(self.leb, col.WHITE), next(lines)) self.assertEqual(terminal.PrintLine('Review: %s' % self.fred, col.RED), next(lines)) self.assertEqual(terminal.PrintLine(' Hi Fred,', None), next(lines)) self.assertEqual(terminal.PrintLine('', None), next(lines)) self.assertEqual( terminal.PrintLine(' > File: tools/patman/commit.py', col.MAGENTA), next(lines)) self.assertEqual( terminal.PrintLine(' > Line: 41 / 41: class Commit:', col.MAGENTA), next(lines)) self.assertEqual( terminal.PrintLine(' > + return self.subject', col.MAGENTA), next(lines)) self.assertEqual(terminal.PrintLine(' > +', col.MAGENTA), next(lines)) self.assertEqual( terminal.PrintLine( ' > def add_change(self, version, info):', col.MAGENTA), next(lines)) self.assertEqual( terminal.PrintLine( ' > """Add a new change line to the change list for a version.', col.MAGENTA), next(lines)) self.assertEqual(terminal.PrintLine(' >', col.MAGENTA), next(lines)) self.assertEqual(terminal.PrintLine(' A comment', None), next(lines)) self.assertEqual(terminal.PrintLine('', None), next(lines)) self.assertEqual( terminal.PrintLine( '4 new responses available in patchwork (use -d to write them to a new branch)', None), next(lines))
def test_create_branch(self): """Test operation of create_branch()""" repo = self.make_git_tree() branch = 'first' dest_branch = 'first2' count = 2 gitdir = os.path.join(self.gitdir, '.git') # Set up the test git tree. We use branch 'first' which has two commits # in it series = patchstream.get_metadata_for_list(branch, gitdir, count) self.assertEqual(2, len(series.commits)) patch1 = status.Patch('1') patch1.parse_subject('[1/2] %s' % series.commits[0].subject) patch1.name = patch1.raw_subject patch1.content = 'This is my patch content' comment1a = {'content': 'Reviewed-by: %s\n' % self.joe} patch1.comments = [comment1a] patch2 = status.Patch('2') patch2.parse_subject('[2/2] %s' % series.commits[1].subject) patch2.name = patch2.raw_subject patch2.content = 'Some other patch content' comment2a = { 'content': 'Reviewed-by: %s\nTested-by: %s\n' % (self.mary, self.leb) } comment2b = {'content': 'Reviewed-by: %s' % self.fred} patch2.comments = [comment2a, comment2b] # This test works by setting up patches for use by the fake Rest API # function _fake_patchwork3(). The fake patch comments above should # result in new review tags that are collected and added to the commits # created in the destination branch. self.patches = [patch1, patch2] count = 2 # Expected output: # 1 i2c: I2C things # + Reviewed-by: Joe Bloggs <*****@*****.**> # 2 spi: SPI fixes # + Reviewed-by: Fred Bloggs <*****@*****.**> # + Reviewed-by: Mary Bloggs <*****@*****.**> # + Tested-by: Lord Edmund Blackaddër <*****@*****.**> # 4 new responses available in patchwork # 4 responses added from patchwork into new branch 'first2' # <unittest.result.TestResult run=8 errors=0 failures=0> terminal.set_print_test_mode() status.check_patchwork_status(series, '1234', branch, dest_branch, False, False, None, self._fake_patchwork3, repo) lines = terminal.get_print_test_lines() self.assertEqual(12, len(lines)) self.assertEqual( "4 responses added from patchwork into new branch 'first2'", lines[11].text) # Check that the destination branch has the new tags new_series = patchstream.get_metadata_for_list(dest_branch, gitdir, count) self.assertEqual({'Reviewed-by': {self.joe}}, new_series.commits[0].rtags) self.assertEqual( { 'Tested-by': {self.leb}, 'Reviewed-by': {self.fred, self.mary} }, new_series.commits[1].rtags) # Now check the actual test of the first commit message. We expect to # see the new tags immediately below the old ones. stdout = patchstream.get_list(dest_branch, count=count, git_dir=gitdir) lines = iter( [line.strip() for line in stdout.splitlines() if '-by:' in line]) # First patch should have the review tag self.assertEqual('Reviewed-by: %s' % self.joe, next(lines)) # Second patch should have the sign-off then the tested-by and two # reviewed-by tags self.assertEqual('Signed-off-by: %s' % self.leb, next(lines)) self.assertEqual('Reviewed-by: %s' % self.fred, next(lines)) self.assertEqual('Reviewed-by: %s' % self.mary, next(lines)) self.assertEqual('Tested-by: %s' % self.leb, next(lines))