From 25e5866f1ca93a3fd4bfb6352ea78d108de2b089 Mon Sep 17 00:00:00 2001 From: Pierre-Yves Chibon Date: Oct 10 2017 09:44:41 +0000 Subject: [PATCH 1/3] Add to pagure-admin the actions: get-watch and update-watch With their corresponding unit-tests Signed-off-by: Pierre-Yves Chibon --- diff --git a/pagure/cli/admin.py b/pagure/cli/admin.py index f6f5f2c..52da23d 100644 --- a/pagure/cli/admin.py +++ b/pagure/cli/admin.py @@ -30,6 +30,15 @@ from pagure import (SESSION, APP, generate_user_key_files) # noqa: E402 _log = logging.getLogger(__name__) +WATCH = { + '-1': 'reset the watch status to default', + '0': 'unwatch, don\'t notify the user of anything', + '1': 'watch issues and PRs', + '2': 'watch commits', + '3': 'watch issues, PRs and commits', +} + + def _parser_refresh_gitolite(subparser): """ Set up the CLI argument parser for the refresh-gitolite action. """ local_parser = subparser.add_parser( @@ -129,6 +138,34 @@ def _parser_admin_token(subparser): _parser_admin_token_create(subsubparser) +def _parser_get_watch(subparser): + """ Set up the CLI argument parser for the get-watch action. """ + # Update watch status + local_parser = subparser.add_parser( + 'get-watch', help="Get someone's watch status on a project") + local_parser.add_argument( + 'project', help="Project (as namespace/project if there " + "is a namespace) -- Fork not supported") + local_parser.add_argument( + 'user', help="User to get the watch status of") + local_parser.set_defaults(func=do_get_watch_status) + + +def _parser_update_watch(subparser): + """ Set up the CLI argument parser for the update-watch action. """ + # Update watch status + local_parser = subparser.add_parser( + 'update-watch', help="Update someone's watch status on a project") + local_parser.add_argument( + 'project', help="Project to update (as namespace/project if there " + "is a namespace) -- Fork not supported") + local_parser.add_argument( + 'user', help="User to update the watch status of") + local_parser.add_argument( + '-s', '--status', help="Watch status to update to") + local_parser.set_defaults(func=do_update_watch_status) + + def parse_arguments(): """ Set-up the argument parsing. """ parser = argparse.ArgumentParser( @@ -152,6 +189,12 @@ def parse_arguments(): # Admin token actions _parser_admin_token(subparser) + # get-watch + _parser_get_watch(subparser) + + # update-watch + _parser_update_watch(subparser) + return parser.parse_args() @@ -167,6 +210,23 @@ def _get_input(text): return raw_input(text) +def _get_project(arg_project, user=None): + ''' From the project specified to the CLI, extract the actual project. + ''' + namespace = None + if '/' in arg_project: + if arg_project.count('/') > 1: + raise pagure.exceptions.PagureException( + 'Invalid project name, has more than one "/": %s' % + arg_project) + namespace, name = arg_project.split('/') + else: + name = arg_project + + return pagure.lib._get_project( + SESSION, namespace=namespace, name=name, user=user) + + def do_generate_acl(args): """ Regenerate the gitolite ACL file. @@ -182,17 +242,7 @@ def do_generate_acl(args): title = None project = None if args.project: - namespace = None - if '/' in args.project: - if args.project.count('/') > 1: - raise pagure.exceptions.PagureException( - 'Invalid project name, has more than one "/": %s' % - args.project) - namespace, name = args.project.split('/') - else: - name = args.project - project = pagure.lib._get_project( - SESSION, namespace=namespace, name=name, user=args.user) + project = _get_project(args.project, user=args.user) title = project.fullname if args.all_: title = 'all' @@ -358,6 +408,84 @@ def do_create_admin_token(args): print(pagure.lib.add_token_to_user(SESSION, None, acls, args.user)) +def do_get_watch_status(args): + """ Get the watch status of an user on a project. + + :arg args: the argparse object returned by ``parse_arguments()``. + + """ + _log.debug('user: %s', args.user) + _log.debug('project: %s', args.project) + # Validate user + pagure.lib.get_user(SESSION, args.user) + + # Get the project + project = _get_project(args.project) + + if project is None: + raise pagure.exceptions.PagureException( + 'No project found with: %s' % args.project) + + level = pagure.lib.get_watch_level_on_repo( + session=SESSION, + user=args.user, + repo=project.name, + repouser=None, + namespace=project.namespace) or [] + + # Specify that issues == 'issues & PRs' + if 'issues' in level: + level.append('pull-requests') + + print('On %s user: %s is watching the following items: %s' % ( + project.fullname, args.user, ', '.join(level) or None)) + + +def do_update_watch_status(args): + """ Update the watch status of an user on a project. + + :arg args: the argparse object returned by ``parse_arguments()``. + + """ + + _log.debug('user: %s', args.user) + _log.debug('status: %s', args.status) + _log.debug('project: %s', args.project) + + # Validate user + pagure.lib.get_user(SESSION, args.user) + + # Ask the status if none were given + if args.status is None: + print('The watch status can be one of the following: ') + for lvl in WATCH: + print('%s: %s' % (lcl, WATCH[lvl])) + args.status = _get_input('Status:') + + # Validate the status + if args.status not in WATCH: + raise pagure.exceptions.PagureException( + 'Invalid status provided: %s not in %s' % ( + args.status, ', '.join(sorted(WATCH.keys())))) + + # Get the project + project = _get_project(args.project) + + if project is None: + raise pagure.exceptions.PagureException( + 'No project found with: %s' % args.project) + + print('Updating watch status of %s to %s (%s) on %s' % ( + args.user, args.status, WATCH[args.status], args.project)) + + pagure.lib.update_watch_status( + session=SESSION, + project=project, + user=args.user, + watch=args.status) + SESSION.commit() + + def main(): """ Start of the application. """ diff --git a/tests/test_pagure_admin.py b/tests/test_pagure_admin.py index 638744f..2f32a54 100644 --- a/tests/test_pagure_admin.py +++ b/tests/test_pagure_admin.py @@ -53,6 +53,8 @@ def _get_ouput(cmd): class PagureAdminHelptests(tests.Modeltests): """ Tests for pagure-admin --help """ + maxDiff = None + def test_parse_arguments(self): """ Test the parse_arguments function of pagure-admin, empty. """ if 'BUILD_ID' in os.environ: @@ -62,10 +64,10 @@ class PagureAdminHelptests(tests.Modeltests): output = _get_ouput(cmd) self.assertEqual(output[0], '') self.assertEqual(output[1], '''usage: admin.py [-h] [--debug] - {refresh-gitolite,refresh-ssh,clear-hook-token,admin-token} + {refresh-gitolite,refresh-ssh,clear-hook-token,admin-token,get-watch,update-watch} ... admin.py: error: too few arguments -''') +''') # noqa def test_parse_arguments_help(self): """ Test the parse_arguments function of pagure-admin. """ @@ -73,7 +75,7 @@ admin.py: error: too few arguments self.assertEqual( _get_ouput(cmd)[0], '''usage: admin.py [-h] [--debug] - {refresh-gitolite,refresh-ssh,clear-hook-token,admin-token} + {refresh-gitolite,refresh-ssh,clear-hook-token,admin-token,get-watch,update-watch} ... The admin CLI for this pagure instance @@ -83,13 +85,15 @@ optional arguments: --debug Increase the verbosity of the information displayed actions: - {refresh-gitolite,refresh-ssh,clear-hook-token,admin-token} + {refresh-gitolite,refresh-ssh,clear-hook-token,admin-token,get-watch,update-watch} refresh-gitolite Re-generate the gitolite config file refresh-ssh Re-write to disk every user's ssh key stored in the database clear-hook-token Generate a new hook token for every project in this instance admin-token Manages the admin tokens for this instance + get-watch Get someone's watch status on a project + update-watch Update someone's watch status on a project ''') def test_parser_refresh_gitolite_help(self): @@ -219,6 +223,40 @@ optional arguments: admin.py admin-token: error: invalid choice: 'foo' (choose from 'list', 'info', 'expire', 'create') ''') # noqa + def test_parser_get_watch(self): + """ Test the _parser_get_watch function of pagure-admin. """ + cmd = ['python', PAGURE_ADMIN, 'get-watch', '--help'] + self.assertEqual( + _get_ouput(cmd)[0], + '''usage: admin.py get-watch [-h] project user + +positional arguments: + project Project (as namespace/project if there is a namespace) -- Fork + not supported + user User to get the watch status of + +optional arguments: + -h, --help show this help message and exit +''') + + def test_parser_update_watch(self): + """ Test the _parser_update_watch function of pagure-admin. """ + cmd = ['python', PAGURE_ADMIN, 'update-watch', '--help'] + self.assertEqual( + _get_ouput(cmd)[0], + '''usage: admin.py update-watch [-h] [-s STATUS] project user + +positional arguments: + project Project to update (as namespace/project if there is a + namespace) -- Fork not supported + user User to update the watch status of + +optional arguments: + -h, --help show this help message and exit + -s STATUS, --status STATUS + Watch status to update to +''') + class PagureAdminAdminTokenEmptytests(tests.Modeltests): """ Tests for pagure-admin admin-token when there is nothing in the DB @@ -563,5 +601,286 @@ class PagureAdminAdminTokentests(tests.Modeltests): self.assertEqual(output, 'No admin tokens found\n') +class PagureAdminGetWatchTests(tests.Modeltests): + """ Tests for pagure-admin get-watch """ + + def setUp(self): + """ Set up the environnment, ran before every tests. """ + super(PagureAdminGetWatchTests, self).setUp() + + self.configfile = os.path.join(self.path, 'config') + self.dbpath = "sqlite:///%s/pagure_dev.sqlite" % self.path + with open(self.configfile, 'w') as stream: + stream.write('DB_URL="%s"\n' % self.dbpath) + + os.environ['PAGURE_CONFIG'] = self.configfile + + createdb = os.path.abspath( + os.path.join(tests.HERE, '..', 'createdb.py')) + cmd = ['python', createdb] + _get_ouput(cmd) + + self.session = pagure.lib.model.create_tables( + self.dbpath, acls=pagure.APP.config.get('ACLS', {})) + + # Create the user pingou + item = pagure.lib.model.User( + user='pingou', + fullname='PY C', + password='foo', + default_email='bar@pingou.com', + ) + self.session.add(item) + item = pagure.lib.model.UserEmail( + user_id=1, + email='bar@pingou.com') + self.session.add(item) + + # Create the user foo + item = pagure.lib.model.User( + user='foo', + fullname='foo B.', + password='foob', + default_email='foo@pingou.com', + ) + self.session.add(item) + + # Create two projects for the user pingou + item = pagure.lib.model.Project( + user_id=1, # pingou + name='test', + description='namespaced test project', + hook_token='aaabbbeee', + namespace='somenamespace', + ) + self.session.add(item) + + item = pagure.lib.model.Project( + user_id=1, # pingou + name='test', + description='Test project', + hook_token='aaabbbccc', + namespace=None, + ) + self.session.add(item) + + self.session.commit() + + # Make the imported pagure use the correct db session + pagure.cli.admin.SESSION = self.session + + def tearDown(self): + """ Tear down the environnment after running the tests. """ + super(PagureAdminGetWatchTests, self).tearDown() + del(os.environ['PAGURE_CONFIG']) + + def test_get_watch_get_project_unknown_project(self): + """ Test the get-watch function of pagure-admin with an unknown + project. + """ + + cmd = ['python', PAGURE_ADMIN, 'get-watch', 'foobar', 'pingou'] + output = _get_ouput(cmd)[0] + self.assertEqual('No project found with: foobar\n', output) + + def test_get_watch_get_project_invalid_project(self): + """ Test the get-watch function of pagure-admin with an invalid + project. + """ + + cmd = ['python', PAGURE_ADMIN, 'get-watch', 'fo/o/bar', 'pingou'] + output = _get_ouput(cmd)[0] + self.assertEqual( + 'Invalid project name, has more than one "/": fo/o/bar\n', + output) + + def test_get_watch_get_project_invalid_user(self): + """ Test the get-watch function of pagure-admin on a invalid user. + """ + + cmd = ['python', PAGURE_ADMIN, 'get-watch', 'test', 'beebop'] + output = _get_ouput(cmd)[0] + self.assertEqual('No user "beebop" found\n', output) + + def test_get_watch_get_project(self): + """ Test the get-watch function of pagure-admin on a regular project. + """ + + cmd = ['python', PAGURE_ADMIN, 'get-watch', 'test', 'pingou'] + output = _get_ouput(cmd)[0] + self.assertEqual( + 'On test user: pingou is watching the following items: ' + 'issues, pull-requests\n', output) + + def test_get_watch_get_project_not_watching(self): + """ Test the get-watch function of pagure-admin on a regular project. + """ + + cmd = ['python', PAGURE_ADMIN, 'get-watch', 'test', 'foo'] + output = _get_ouput(cmd)[0] + self.assertEqual( + 'On test user: foo is watching the following items: None\n', + output) + + def test_get_watch_get_project_namespaced(self): + """ Test the get-watch function of pagure-admin on a namespaced project. + """ + + cmd = [ + 'python', PAGURE_ADMIN, 'get-watch', + 'somenamespace/test', 'pingou'] + output = _get_ouput(cmd)[0] + self.assertEqual( + 'On somenamespace/test user: pingou is watching the following ' + 'items: issues, pull-requests\n', output) + + def test_get_watch_get_project_namespaced_not_watching(self): + """ Test the get-watch function of pagure-admin on a namespaced project. + """ + + cmd = [ + 'python', PAGURE_ADMIN, 'get-watch', + 'somenamespace/test', 'foo'] + output = _get_ouput(cmd)[0] + self.assertEqual( + 'On somenamespace/test user: foo is watching the following ' + 'items: None\n', output) + + +class PagureAdminUpdateWatchTests(tests.Modeltests): + """ Tests for pagure-admin update-watch """ + + def setUp(self): + """ Set up the environnment, ran before every tests. """ + super(PagureAdminUpdateWatchTests, self).setUp() + + self.configfile = os.path.join(self.path, 'config') + self.dbpath = "sqlite:///%s/pagure_dev.sqlite" % self.path + with open(self.configfile, 'w') as stream: + stream.write('DB_URL="%s"\n' % self.dbpath) + + os.environ['PAGURE_CONFIG'] = self.configfile + + createdb = os.path.abspath( + os.path.join(tests.HERE, '..', 'createdb.py')) + cmd = ['python', createdb] + _get_ouput(cmd) + + self.session = pagure.lib.model.create_tables( + self.dbpath, acls=pagure.APP.config.get('ACLS', {})) + + # Create the user pingou + item = pagure.lib.model.User( + user='pingou', + fullname='PY C', + password='foo', + default_email='bar@pingou.com', + ) + self.session.add(item) + item = pagure.lib.model.UserEmail( + user_id=1, + email='bar@pingou.com') + self.session.add(item) + + # Create the user foo + item = pagure.lib.model.User( + user='foo', + fullname='foo B.', + password='foob', + default_email='foo@pingou.com', + ) + self.session.add(item) + + # Create two projects for the user pingou + item = pagure.lib.model.Project( + user_id=1, # pingou + name='test', + description='namespaced test project', + hook_token='aaabbbeee', + namespace='somenamespace', + ) + self.session.add(item) + + item = pagure.lib.model.Project( + user_id=1, # pingou + name='test', + description='Test project', + hook_token='aaabbbccc', + namespace=None, + ) + self.session.add(item) + + self.session.commit() + + # Make the imported pagure use the correct db session + pagure.cli.admin.SESSION = self.session + + def tearDown(self): + """ Tear down the environnment after running the tests. """ + super(PagureAdminUpdateWatchTests, self).tearDown() + del(os.environ['PAGURE_CONFIG']) + + def test_get_watch_update_project_unknown_project(self): + """ Test the update-watch function of pagure-admin on an unknown + project. + """ + + cmd = ['python', PAGURE_ADMIN, 'update-watch', 'foob', 'pingou', '-s=1'] + output = _get_ouput(cmd)[0] + self.assertEqual('No project found with: foob\n', output) + + def test_get_watch_update_project_invalid_project(self): + """ Test the update-watch function of pagure-admin on an invalid + project. + """ + + cmd = ['python', PAGURE_ADMIN, 'update-watch', 'fo/o/b', 'pingou', '-s=1'] + output = _get_ouput(cmd)[0] + self.assertEqual( + 'Invalid project name, has more than one "/": fo/o/b\n', + output) + + def test_get_watch_update_project_invalid_user(self): + """ Test the update-watch function of pagure-admin on an invalid user. + """ + + cmd = ['python', PAGURE_ADMIN, 'update-watch', 'test', 'foob', '-s=1'] + output = _get_ouput(cmd)[0] + self.assertEqual('No user "foob" found\n', output) + + def test_get_watch_update_project_invalid_status(self): + """ Test the update-watch function of pagure-admin with an invalid + status. + """ + + cmd = ['python', PAGURE_ADMIN, 'update-watch', 'test', 'pingou', '-s=10'] + output = _get_ouput(cmd)[0] + self.assertEqual( + 'Invalid status provided: 10 not in -1, 0, 1, 2, 3\n', output) + + def test_get_watch_update_project_no_effect(self): + """ Test the update-watch function of pagure-admin with a regular + project - nothing changed. + """ + + cmd = ['python', PAGURE_ADMIN, 'get-watch', 'test', 'pingou'] + output = _get_ouput(cmd)[0] + self.assertEqual( + 'On test user: pingou is watching the following items: ' + 'issues, pull-requests\n', output) + + cmd = ['python', PAGURE_ADMIN, 'update-watch', 'test', 'pingou', '-s=1'] + output = _get_ouput(cmd)[0] + self.assertEqual( + 'Updating watch status of pingou to 1 (watch issues and PRs) ' + 'on test\n', output) + + cmd = ['python', PAGURE_ADMIN, 'get-watch', 'test', 'pingou'] + output = _get_ouput(cmd)[0] + self.assertEqual( + 'On test user: pingou is watching the following items: ' + 'issues, pull-requests\n', output) + + if __name__ == '__main__': unittest.main(verbosity=2) From 3a016c244187140ec4973eeffcf2fd7a04b4a772 Mon Sep 17 00:00:00 2001 From: Pierre-Yves Chibon Date: Oct 10 2017 13:29:34 +0000 Subject: [PATCH 2/3] Add to pagure-admin the actions: read-only This action allows to get or set the read-only status of a project. With its corresponding unit-tests Signed-off-by: Pierre-Yves Chibon Signed-off-by: Pierre-Yves Chibon --- diff --git a/pagure/cli/admin.py b/pagure/cli/admin.py index 52da23d..5411d77 100644 --- a/pagure/cli/admin.py +++ b/pagure/cli/admin.py @@ -166,6 +166,22 @@ def _parser_update_watch(subparser): local_parser.set_defaults(func=do_update_watch_status) +def _parser_read_only(subparser): + """ Set up the CLI argument parser for the refresh-gitolite action. """ + local_parser = subparser.add_parser( + 'read-only', + help='Get or set the read-only flag on a project') + local_parser.add_argument( + '--user', help="User of the project (to use only on forks)") + local_parser.add_argument( + 'project', help="Project to update (as namespace/project if there " + "is a namespace)") + local_parser.add_argument( + '--ro', + help="Read-Only status to set (has to be: true or false), do not " + "specify to get the current status") + local_parser.set_defaults(func=do_read_only) + def parse_arguments(): """ Set-up the argument parsing. """ parser = argparse.ArgumentParser( @@ -195,6 +211,9 @@ def parse_arguments(): # update-watch _parser_update_watch(subparser) + # read-only + _parser_read_only(subparser) + return parser.parse_args() @@ -486,6 +505,47 @@ def do_update_watch_status(args): SESSION.commit() +def do_read_only(args): + """ Set or update the read-only status of a project. + + :arg args: the argparse object returned by ``parse_arguments()``. + + """ + + _log.debug('project: %s', args.project) + _log.debug('user: %s', args.user) + _log.debug('read-only: %s', args.ro) + + # Validate user + pagure.lib.get_user(SESSION, args.user) + + # Get the project + project = _get_project(args.project) + + if project is None: + raise pagure.exceptions.PagureException( + 'No project found with: %s' % args.project) + + # Validate ro flag + if args.ro and args.ro.lower() not in ['true', 'false']: + raise pagure.exceptions.PagureException( + 'Invalid read-only status specified: %s is not in: ' + 'true, false' % args.ro.lower()) + + if not args.ro: + print( + 'The current read-only flag of the project %s is set to %s' % ( + project.fullname, project.read_only)) + else: + pagure.lib.update_read_only_mode( + SESSION, project, read_only=(args.ro.lower() == 'true') + ) + SESSION.commit() + print( + 'The read-only flag of the project %s has been set to %s' % ( + project.fullname, args.ro.lower() == 'true')) + + def main(): """ Start of the application. """ diff --git a/tests/test_pagure_admin.py b/tests/test_pagure_admin.py index 2f32a54..acd98f6 100644 --- a/tests/test_pagure_admin.py +++ b/tests/test_pagure_admin.py @@ -64,7 +64,7 @@ class PagureAdminHelptests(tests.Modeltests): output = _get_ouput(cmd) self.assertEqual(output[0], '') self.assertEqual(output[1], '''usage: admin.py [-h] [--debug] - {refresh-gitolite,refresh-ssh,clear-hook-token,admin-token,get-watch,update-watch} + {refresh-gitolite,refresh-ssh,clear-hook-token,admin-token,get-watch,update-watch,read-only} ... admin.py: error: too few arguments ''') # noqa @@ -75,7 +75,7 @@ admin.py: error: too few arguments self.assertEqual( _get_ouput(cmd)[0], '''usage: admin.py [-h] [--debug] - {refresh-gitolite,refresh-ssh,clear-hook-token,admin-token,get-watch,update-watch} + {refresh-gitolite,refresh-ssh,clear-hook-token,admin-token,get-watch,update-watch,read-only} ... The admin CLI for this pagure instance @@ -85,7 +85,7 @@ optional arguments: --debug Increase the verbosity of the information displayed actions: - {refresh-gitolite,refresh-ssh,clear-hook-token,admin-token,get-watch,update-watch} + {refresh-gitolite,refresh-ssh,clear-hook-token,admin-token,get-watch,update-watch,read-only} refresh-gitolite Re-generate the gitolite config file refresh-ssh Re-write to disk every user's ssh key stored in the database @@ -94,6 +94,7 @@ actions: admin-token Manages the admin tokens for this instance get-watch Get someone's watch status on a project update-watch Update someone's watch status on a project + read-only Get or set the read-only flag on a project ''') def test_parser_refresh_gitolite_help(self): @@ -257,6 +258,25 @@ optional arguments: Watch status to update to ''') + def test_parser_read_only(self): + """ Test the _parser_update_watch function of pagure-admin. """ + cmd = ['python', PAGURE_ADMIN, 'read-only', '--help'] + print _get_ouput(cmd)[0] + self.assertEqual( + _get_ouput(cmd)[0], + '''usage: admin.py read-only [-h] [--user USER] [--ro RO] project + +positional arguments: + project Project to update (as namespace/project if there is a + namespace) + +optional arguments: + -h, --help show this help message and exit + --user USER User of the project (to use only on forks) + --ro RO Read-Only status to set (has to be: true or false), do not + specify to get the current status +''') + class PagureAdminAdminTokenEmptytests(tests.Modeltests): """ Tests for pagure-admin admin-token when there is nothing in the DB @@ -882,5 +902,165 @@ class PagureAdminUpdateWatchTests(tests.Modeltests): 'issues, pull-requests\n', output) +class PagureAdminReadOnlyTests(tests.Modeltests): + """ Tests for pagure-admin read-only """ + + def setUp(self): + """ Set up the environnment, ran before every tests. """ + super(PagureAdminReadOnlyTests, self).setUp() + + self.configfile = os.path.join(self.path, 'config') + self.dbpath = "sqlite:///%s/pagure_dev.sqlite" % self.path + with open(self.configfile, 'w') as stream: + stream.write('DB_URL="%s"\n' % self.dbpath) + + os.environ['PAGURE_CONFIG'] = self.configfile + + createdb = os.path.abspath( + os.path.join(tests.HERE, '..', 'createdb.py')) + cmd = ['python', createdb] + _get_ouput(cmd) + + self.session = pagure.lib.model.create_tables( + self.dbpath, acls=pagure.APP.config.get('ACLS', {})) + + # Create the user pingou + item = pagure.lib.model.User( + user='pingou', + fullname='PY C', + password='foo', + default_email='bar@pingou.com', + ) + self.session.add(item) + item = pagure.lib.model.UserEmail( + user_id=1, + email='bar@pingou.com') + self.session.add(item) + + # Create two projects for the user pingou + item = pagure.lib.model.Project( + user_id=1, # pingou + name='test', + description='namespaced test project', + hook_token='aaabbbeee', + namespace='somenamespace', + ) + self.session.add(item) + + item = pagure.lib.model.Project( + user_id=1, # pingou + name='test', + description='Test project', + hook_token='aaabbbccc', + namespace=None, + ) + self.session.add(item) + + self.session.commit() + + # Make the imported pagure use the correct db session + pagure.cli.admin.SESSION = self.session + + def tearDown(self): + """ Tear down the environnment after running the tests. """ + super(PagureAdminReadOnlyTests, self).tearDown() + del(os.environ['PAGURE_CONFIG']) + + def test_read_only_unknown_project(self): + """ Test the read-only function of pagure-admin on an unknown + project. + """ + + cmd = ['python', PAGURE_ADMIN, 'read-only', 'foob'] + output = _get_ouput(cmd)[0] + self.assertEqual('No project found with: foob\n', output) + + def test_read_only_invalid_project(self): + """ Test the read-only function of pagure-admin on an invalid + project. + """ + + cmd = ['python', PAGURE_ADMIN, 'read-only', 'fo/o/b'] + output = _get_ouput(cmd)[0] + self.assertEqual( + 'Invalid project name, has more than one "/": fo/o/b\n', + output) + + def test_read_only(self): + """ Test the read-only function of pagure-admin to get status of + a non-namespaced project. + """ + + cmd = ['python', PAGURE_ADMIN, 'read-only', 'test'] + output = _get_ouput(cmd)[0] + self.assertEqual( + 'The current read-only flag of the project test is set to True\n', + output) + + def test_read_only_namespace(self): + """ Test the read-only function of pagure-admin to get status of + a namespaced project. + """ + + cmd = ['python', PAGURE_ADMIN, 'read-only', 'somenamespace/test'] + output = _get_ouput(cmd)[0] + self.assertEqual( + 'The current read-only flag of the project somenamespace/test '\ + 'is set to True\n', output) + + def test_read_only_namespace_changed(self): + """ Test the read-only function of pagure-admin to set the status of + a namespaced project. + """ + + # Before + cmd = ['python', PAGURE_ADMIN, 'read-only', 'somenamespace/test'] + output = _get_ouput(cmd)[0] + self.assertEqual( + 'The current read-only flag of the project somenamespace/test '\ + 'is set to True\n', output) + + cmd = [ + 'python', PAGURE_ADMIN, 'read-only', + 'somenamespace/test', '--ro', 'false'] + output = _get_ouput(cmd)[0] + self.assertEqual( + 'The read-only flag of the project somenamespace/test has been ' + 'set to False\n', output) + + # After + cmd = ['python', PAGURE_ADMIN, 'read-only', 'somenamespace/test'] + output = _get_ouput(cmd)[0] + self.assertEqual( + 'The current read-only flag of the project somenamespace/test '\ + 'is set to False\n', output) + + def test_read_only_no_change(self): + """ Test the read-only function of pagure-admin to set the status of + a namespaced project. + """ + + # Before + cmd = ['python', PAGURE_ADMIN, 'read-only', 'test'] + output = _get_ouput(cmd)[0] + self.assertEqual( + 'The current read-only flag of the project test '\ + 'is set to True\n', output) + + cmd = [ + 'python', PAGURE_ADMIN, 'read-only', 'test', '--ro', 'true'] + output = _get_ouput(cmd)[0] + self.assertEqual( + 'The read-only flag of the project test has been ' + 'set to True\n', output) + + # After + cmd = ['python', PAGURE_ADMIN, 'read-only', 'test'] + output = _get_ouput(cmd)[0] + self.assertEqual( + 'The current read-only flag of the project test '\ + 'is set to True\n', output) + + if __name__ == '__main__': unittest.main(verbosity=2) From 5fec8cb072926a888ce9bcb956c4805af640cc81 Mon Sep 17 00:00:00 2001 From: Pierre-Yves Chibon Date: Oct 10 2017 13:30:02 +0000 Subject: [PATCH 3/3] Don't change the read-only flag of a project if there is no need for it Signed-off-by: Pierre-Yves Chibon --- diff --git a/pagure/lib/__init__.py b/pagure/lib/__init__.py index 33fdef9..beba1af 100644 --- a/pagure/lib/__init__.py +++ b/pagure/lib/__init__.py @@ -4519,5 +4519,6 @@ def update_read_only_mode(session, repo, read_only=True): or not isinstance(repo, model.Project) or read_only not in [True, False]): return - repo.read_only = read_only - session.add(repo) + if repo.read_only != read_only: + repo.read_only = read_only + session.add(repo)