From b4ebc28459a0d2b5e6831ddb4cb7476e8c53afec Mon Sep 17 00:00:00 2001 From: Mikolaj Izdebski Date: Thu, 3 Oct 2019 23:54:27 +0200 Subject: [PATCH] [admin] Implement collection forking --- koschei/admin.py | 71 +++++++++++++++++++ test/admin_test.py | 34 ++++++++- .../AdminTest/test_collection_commands.yml | 6 ++ 3 files changed, 108 insertions(+), 3 deletions(-) diff --git a/koschei/admin.py b/koschei/admin.py index 5388013f..055b8405 100644 --- a/koschei/admin.py +++ b/koschei/admin.py @@ -578,6 +578,77 @@ def execute(self, session, master_collection, new_name, display_name, ) +class ForkCollection(CreateOrEditCollectionCommand, Command): + """ + Fork collection. + """ + + def setup_parser(self, parser): + parser.add_argument( + 'master_collection', + help="Master collection from which new collection should be branched", + ) + parser.add_argument( + 'new_name', + help="New name for the master collection after the branched copy is created", + ) + parser.add_argument( + '-d', '--display-name', + required=True, + help="Human readable name for forked collection", + ) + parser.add_argument( + '-t', '--target', + required=True, + help="New Koji target for forked collection", + ) + parser.add_argument( + '--dest-tag', + help="Destination tag for forked collection (defaults to build tag)", + ) + + def execute(self, session, master_collection, new_name, display_name, + target, dest_tag): + master = ( + session.db.query(Collection) + .filter_by(name=master_collection) + ).one() + if not master: + sys.exit("Collection not found") + forked = ( + session.db.query(Collection) + .filter_by(name=new_name) + ).first() + if forked: + sys.exit("Forked collection already exists") + forked = Collection( + name=new_name, + target=target, + dest_tag=dest_tag, + order=master.order, + display_name=display_name, + ) + for key in ('secondary_mode', 'priority_coefficient', 'bugzilla_product', + 'poll_untracked', 'build_group', 'bugzilla_version'): + setattr(forked, key, getattr(master, key)) + self.set_koji_tags(session, forked) + session.db.add(forked) + session.db.flush() + for group_rel in ( + session.db.query(CollectionGroupRelation) + .filter_by(collection_id=master.id) + ): + session.db.add(CollectionGroupRelation( + collection_id=forked.id, + group_id=group_rel.group_id, + )) + + data.copy_collection(session, master, forked, minimal=True) + session.log_user_action( + "Collection {} forked from {}".format(new_name, master_collection) + ) + + class CreateOrEditCollectionGroupCommand(object): create = True diff --git a/test/admin_test.py b/test/admin_test.py index d6af3a3e..04b63965 100644 --- a/test/admin_test.py +++ b/test/admin_test.py @@ -167,6 +167,33 @@ def test_collection_commands(self): self.assertEqual(1, len(group.collections)) self.assertIs(collection, group.collections[0]) + # test fork collection + self.call_command( + 'fork-collection f28 f28-side-42 -d"Side tag 42" -t f28-side-42' + ) + forked = self.db.query(Collection).filter_by(name='f28-side-42').one() + self.assertIsNot(forked, collection) + self.assertEqual("f28-side-42", forked.target) + self.assertEqual("f28-side-42", forked.build_tag) + self.assertEqual("f28-side-42", forked.dest_tag) + self.assertEqual("rawhide", forked.bugzilla_version) + self.assertEqual(128, forked.order) + self.assertEqual("f28", collection.target) + self.assertEqual("f28-build", collection.build_tag) + self.assertEqual("f28-build", collection.dest_tag) + self.assertEqual("rawhide", collection.bugzilla_version) + self.assertEqual(128, collection.order) + rnv_forked = ( + self.db.query(Package) + .filter_by(name='rnv', collection=forked) + .one() + ) + self.assertIsNot(rnv_forked, rnv) + self.assertEqual(2, len(group.collections)) + self.assertCountEqual([collection, forked], group.collections) + + self.db.execute("DISCARD TEMP") + # test branch collection self.call_command( 'branch-collection f28 f29 -d"Fedora 28" -t f29 --bugzilla-version 28' @@ -189,8 +216,8 @@ def test_collection_commands(self): .one() ) self.assertIsNot(rnv_branched, rnv) - self.assertEqual(2, len(group.collections)) - self.assertCountEqual([collection, branched], group.collections) + self.assertEqual(3, len(group.collections)) + self.assertCountEqual([collection, branched, forked], group.collections) # test delete collection self.call_command('delete-collection --force f28') @@ -199,11 +226,12 @@ def test_collection_commands(self): with self.assertRaises(InvalidRequestError): self.db.refresh(rnv_branched) - self.assertEqual(1, len(group.collections)) + self.assertEqual(2, len(group.collections)) self.assert_action_log( "Collection f28 created", "Collection f28 modified", + "Collection f28-side-42 forked from f28", "Collection f29 branched from f28", "Collection f28 deleted", ) diff --git a/test/data/AdminTest/test_collection_commands.yml b/test/data/AdminTest/test_collection_commands.yml index 79d7090d..0924289f 100644 --- a/test/data/AdminTest/test_collection_commands.yml +++ b/test/data/AdminTest/test_collection_commands.yml @@ -18,3 +18,9 @@ dest_tag_name: f29-pending id: 2032 name: f29 +- method: getBuildTarget + args: + - f28-side-42 + result: + build_tag_name: f28-side-42 + dest_tag_name: f28-side-42