From 2554cf7b37a989c6a29ac79a422ed8a06169a885 Mon Sep 17 00:00:00 2001 From: Lubomír Sedlář Date: Apr 13 2018 15:32:26 +0000 Subject: Add command to delete resolved review branches These can accumulate quite quickly, and having to delete them manually is a lot of work. Instead we can add `pag review --cleanup` command to delete all review branches that correspond to merged or closed pull requests. There's a warning printed because this command could potentially cause loss of data (user reviews pull request and starts their own work on the review branch). --- diff --git a/pag/commands/review.py b/pag/commands/review.py index 8ff6e15..348e1ec 100644 --- a/pag/commands/review.py +++ b/pag/commands/review.py @@ -69,6 +69,23 @@ def get_local_branch(pr): @eager_command +def cleanup_branches(ctx): + """Delete all branches that correspond to merged or closed pull requests. + + This function never returns due to the decorator exiting the whole program. + + :param ctx: Click context. Passed automatically by the decorator + """ + repo = in_git_repo() + opened_requests = set(str(pr['id']) for pr in list_pull_requests(repo)) + + _, out = run(['git', 'branch', '--list', 'review/*'], echo=False) + branches = [b for b in out.split() if b.split('/', 3)[1] not in opened_requests] + if branches: + run(['git', 'branch', '-D'] + branches) + + +@eager_command def list_pulls(ctx): """Print information about opened pull requests. @@ -116,6 +133,11 @@ def open_current(ctx): @click.option('-l', '--list', is_flag=True, callback=list_pulls, expose_value=False, is_eager=True, help='List opened pull requests on this repo') +@click.option('-c', '--cleanup', is_flag=True, callback=cleanup_branches, + expose_value=False, is_eager=True, + help='Delete branches corresponding to merged/closed pull ' + 'requests. WARNING: This can potentially delete useful ' + 'data!') @click.option('-o', '--open', is_flag=True, callback=open_current, expose_value=False, is_eager=True, help='Open currently reviewed PR in browser') diff --git a/tests/test_review.py b/tests/test_review.py index fca81b8..0985f9d 100644 --- a/tests/test_review.py +++ b/tests/test_review.py @@ -152,3 +152,36 @@ class ReviewTest(unittest.TestCase): mock.call(['git', 'checkout', 'review/2344/1'], graceful=False), ]) self.assertEqual(result.exit_code, 0) + + @mock.patch('pag.commands.review.run') + @mock.patch('pag.commands.review.list_pull_requests', new=lambda _: LIST_RESPONSE['requests']) + @mock.patch('pag.commands.review.in_git_repo', new=lambda: 'pagure') + def test_cleanup_merged_branches(self, run): + run.return_value = (0, 'review/1/1\nreview/1/2\n') + + result = self.runner.invoke(review, ['--cleanup']) + + self.assertEqual(result.exit_code, 0) + + self.assertEqual( + run.call_args_list, + [ + mock.call(['git', 'branch', '--list', 'review/*'], echo=False), + mock.call(['git', 'branch', '-D', 'review/1/1', 'review/1/2']), + ]) + + @mock.patch('pag.commands.review.run') + @mock.patch('pag.commands.review.list_pull_requests', new=lambda _: LIST_RESPONSE['requests']) + @mock.patch('pag.commands.review.in_git_repo', new=lambda: 'pagure') + def test_keep_branch_for_opened_pr(self, run): + run.return_value = (0, 'review/2344/1\nreview/2344/2\n') + + result = self.runner.invoke(review, ['--cleanup']) + + self.assertEqual(result.exit_code, 0) + + self.assertEqual( + run.call_args_list, + [ + mock.call(['git', 'branch', '--list', 'review/*'], echo=False), + ])