@@ -19,6 +19,10 @@ This finds the merge-base commit between the master branch (ci/master) and the
source branch, and stores it in the database as the starting point for
cherry-picking.
+To list all tracked source branches::
+
+ ./tools/pickman/pickman list-sources
+
To compare branches and show commits that need to be cherry-picked::
./tools/pickman/pickman compare
@@ -35,6 +35,7 @@ def parse_args(argv):
add_source.add_argument('source', help='Source branch name')
subparsers.add_parser('compare', help='Compare branches')
+ subparsers.add_parser('list-sources', help='List tracked source branches')
subparsers.add_parser('test', help='Run tests')
return parser.parse_args(argv)
@@ -92,6 +92,28 @@ def do_add_source(args, dbs):
return 0
+def do_list_sources(args, dbs): # pylint: disable=unused-argument
+ """List all tracked source branches
+
+ Args:
+ args (Namespace): Parsed arguments
+ dbs (Database): Database instance
+
+ Returns:
+ int: 0 on success
+ """
+ sources = dbs.source_get_all()
+
+ if not sources:
+ tout.info('No source branches tracked')
+ else:
+ tout.info('Tracked source branches:')
+ for name, last_commit in sources:
+ tout.info(f' {name}: {last_commit[:12]}')
+
+ return 0
+
+
def do_compare(args, dbs): # pylint: disable=unused-argument
"""Compare branches and print results.
@@ -133,6 +155,7 @@ def do_test(args, dbs): # pylint: disable=unused-argument
COMMANDS = {
'add-source': do_add_source,
'compare': do_compare,
+ 'list-sources': do_list_sources,
'test': do_test,
}
@@ -178,6 +178,15 @@ class Database:
return rec[0]
return None
+ def source_get_all(self):
+ """Get all source branches and their last commits
+
+ Return:
+ list of tuple: (name, last_commit) pairs
+ """
+ res = self.execute('SELECT name, last_commit FROM source ORDER BY name')
+ return res.fetchall()
+
def source_set(self, name, commit):
"""Set the last cherry-picked commit for a source branch
@@ -287,6 +287,76 @@ class TestDatabase(unittest.TestCase):
self.assertIs(dbs1, dbs2)
dbs1.close()
+ def test_source_get_all(self):
+ """Test getting all sources."""
+ with terminal.capture():
+ dbs = database.Database(self.db_path)
+ dbs.start()
+
+ # Empty initially
+ self.assertEqual(dbs.source_get_all(), [])
+
+ # Add some sources
+ dbs.source_set('branch-a', 'abc123')
+ dbs.source_set('branch-b', 'def456')
+ dbs.commit()
+
+ # Should be sorted by name
+ sources = dbs.source_get_all()
+ self.assertEqual(len(sources), 2)
+ self.assertEqual(sources[0], ('branch-a', 'abc123'))
+ self.assertEqual(sources[1], ('branch-b', 'def456'))
+ dbs.close()
+
+
+class TestListSources(unittest.TestCase):
+ """Tests for list-sources command."""
+
+ def setUp(self):
+ """Set up test fixtures."""
+ fd, self.db_path = tempfile.mkstemp(suffix='.db')
+ os.close(fd)
+ os.unlink(self.db_path)
+ self.old_db_fname = control.DB_FNAME
+ control.DB_FNAME = self.db_path
+ database.Database.instances.clear()
+
+ def tearDown(self):
+ """Clean up test fixtures."""
+ control.DB_FNAME = self.old_db_fname
+ if os.path.exists(self.db_path):
+ os.unlink(self.db_path)
+ database.Database.instances.clear()
+
+ def test_list_sources_empty(self):
+ """Test list-sources with no sources"""
+ args = argparse.Namespace(cmd='list-sources')
+ with terminal.capture() as (stdout, _):
+ ret = control.do_pickman(args)
+ self.assertEqual(ret, 0)
+ self.assertIn('No source branches tracked', stdout.getvalue())
+
+ def test_list_sources(self):
+ """Test list-sources with sources"""
+ # Add some sources first
+ with terminal.capture():
+ dbs = database.Database(self.db_path)
+ dbs.start()
+ dbs.source_set('us/next', 'abc123def456')
+ dbs.source_set('other/branch', 'def456abc789')
+ dbs.commit()
+ dbs.close()
+
+ database.Database.instances.clear()
+ args = argparse.Namespace(cmd='list-sources')
+ with terminal.capture() as (stdout, _):
+ ret = control.do_pickman(args)
+ self.assertEqual(ret, 0)
+ output = stdout.getvalue()
+ self.assertIn('Tracked source branches:', output)
+ self.assertIn('other/branch: def456abc789', output)
+ self.assertIn('us/next: abc123def456', output)
+
if __name__ == '__main__':
unittest.main()