class Commands(object): def __init__(self, config): self.config = config try: self.client = CoprClient.create_from_file_config(config) except (copr_exceptions.CoprNoConfException, copr_exceptions.CoprConfigException): print(no_config_warning.format(config or "~/.config/copr")) self.client = CoprClient( copr_url=u"http://copr.fedoraproject.org", no_config=True ) def requires_api_auth(func): """ Decorator that checks config presence """ def wrapper(self, args): if self.client.no_config: print("Error: Operation requires api authentication") print(no_config_warning.format(self.config or "~/.config/copr")) sys.exit(6) return func(self, args) wrapper.__doc__ = func.__doc__ wrapper.__name__ = func.__name__ return wrapper def check_username_presence(func): """ Decorator that checks if username was provided """ def wrapper(self, args): if self.client.no_config and args.username is None: print("Error: Operation requires username\n" "Pass username to command or create `~/.config/copr`") sys.exit(6) if args.username is None and self.client.username is None: print("Error: Operation requires username\n" "Pass username to command or add it to `~/.config/copr`") sys.exit(6) return func(self, args) wrapper.__doc__ = func.__doc__ wrapper.__name__ = func.__name__ return wrapper def _watch_builds(self, build_ids): """ :param build_ids: list of build IDs """ print("Watching build(s): (this may be safely interrupted)") prevstatus = defaultdict(lambda: None) failed_ids = [] watched = set(build_ids) done = set() try: while watched != done: for build_id in watched: if build_id in done: continue build_details = self.client.get_build_details(build_id) if build_details.output != "ok": errmsg = " Build {1}: Unable to get build status: {0}". \ format(build_details.error, build_id) raise copr_exceptions.CoprRequestException(errmsg) now = datetime.datetime.now() if prevstatus[build_id] != build_details.status: prevstatus[build_id] = build_details.status print(" {0} Build {2}: {1}".format( now.strftime("%H:%M:%S"), build_details.status, build_id)) if build_details.status in ["failed"]: failed_ids.append(build_id) if build_details.status in ["succeeded", "skipped", "failed", "canceled"]: done.add(build_id) if build_details.status == "unknown": raise copr_exceptions.CoprBuildException( "Unknown status.") if watched == done: break time.sleep(30) if failed_ids: raise copr_exceptions.CoprBuildException( "Build(s) {0} failed.".format( ", ".join(str(x) for x in failed_ids))) except KeyboardInterrupt: pass @requires_api_auth def action_build(self, args): """ Method called when the 'build' action has been selected by the user. :param args: argparse arguments provided by the user """ bar = None progress_callback = None if os.path.exists(args.pkgs[0]): bar = ProgressBar(max=os.path.getsize(args.pkgs[0])) def progress_callback(monitor): bar.next(n=8192) print('Uploading package {0}'.format(args.pkgs[0])) data = { "pkgs": args.pkgs, "progress_callback": progress_callback, } return self.process_build(args, self.client.create_new_build, data, bar=bar) @requires_api_auth def action_build_pypi(self, args): """ Method called when the 'buildpypi' action has been selected by the user. :param args: argparse arguments provided by the user """ username, copr = parse_name(args.copr) data = { "pypi_package_name": args.packagename, "pypi_package_version": args.packageversion, "python_versions": args.pythonversions, } return self.process_build(args, self.client.create_new_build_pypi, data) @requires_api_auth def action_build_tito(self, args): """ Method called when the 'buildtito' action has been selected by the user. :param args: argparse arguments provided by the user """ data = { "git_url": args.git_url, "git_dir": args.git_dir, "git_branch": args.git_branch, "tito_test": args.tito_test, } return self.process_build(args, self.client.create_new_build_tito, data) @requires_api_auth def action_build_mock(self, args): """ Method called when the 'build-mock' action has been selected by the user. :param args: argparse arguments provided by the user """ data = { "scm_type": args.scm_type, "scm_url": args.scm_url, "scm_branch": args.scm_branch, "spec": args.spec, } return self.process_build(args, self.client.create_new_build_mock, data) @requires_api_auth def action_build_rubygems(self, args): """ Method called when the 'buildgem' action has been selected by the user. :param args: argparse arguments provided by the user """ data = {"gem_name": args.gem_name} return self.process_build(args, self.client.create_new_build_rubygems, data) def process_build(self, args, build_function, data, bar=None): username, copr = parse_name(args.copr) result = build_function(username=username, projectname=copr, chroots=args.chroots, memory=args.memory, timeout= args.timeout, **data) if bar: bar.finish() if result.output != "ok": print(result.error) return print(result.message) build_ids = [bw.build_id for bw in result.builds_list] print("Created builds: {0}".format(" ".join(map(str, build_ids)))) if not args.nowait: self._watch_builds(build_ids) @requires_api_auth def action_create(self, args): """ Method called when the 'create' action has been selected by the user. :param args: argparse arguments provided by the user """ username, copr = parse_name(args.name) result = self.client.create_project( username=username, projectname=copr, description=args.description, instructions=args.instructions, chroots=args.chroots, repos=args.repos, initial_pkgs=args.initial_pkgs) print(result.message) @requires_api_auth def action_modify_project(self, args): """ Method called when the 'modify' action has been selected by the user. :param args: argparse arguments provided by the user """ username, copr = parse_name(args.name) result = self.client.modify_project( username=username, projectname=copr, description=args.description, instructions=args.instructions, repos=args.repos, disable_createrepo=args.disable_createrepo) @requires_api_auth def action_delete(self, args): """ Method called when the 'delete' action has been selected by the user. :param args: argparse arguments provided by the user """ username, copr = parse_name(args.copr) result = self.client.delete_project(username=username, projectname=copr) print(result.message) @requires_api_auth def action_fork(self, args): """ Method called when the 'fork' action has been selected by the user. :param args: argparse arguments provided by the user """ username, copr = parse_name(args.dst) result = self.client.fork_project(source=args.src, username=username, projectname=copr, confirm=args.confirm) print(result.message) @check_username_presence def action_list(self, args): """ Method called when the 'list' action has been selected by the user. :param args: argparse arguments provided by the user """ username = args.username or self.client.username result = self.client.get_projects_list(username) # import ipdb; ipdb.set_trace() if result.output != "ok": print(result.error) print("Un-expected data returned, please report this issue") elif not result.projects_list: print("No copr retrieved for user: '******'".format(username)) return for prj in result.projects_list: print(prj) def action_status(self, args): result = self.client.get_build_details(args.build_id) print(result.status) def action_download_build(self, args): result = self.client.get_build_details(args.build_id) base_len = len(os.path.split(result.results)) for chroot, url in result.results_by_chroot.items(): if args.chroots and chroot not in args.chroots: continue cmd = "wget -r -nH --no-parent --reject 'index.html*'".split(' ') cmd.extend(['-P', os.path.join(args.dest, chroot)]) cmd.extend(['--cut-dirs', str(base_len + 4)]) cmd.append(url) subprocess.call(cmd) @requires_api_auth def action_cancel(self, args): """ Method called when the 'cancel' action has been selected by the user. :param args: argparse arguments provided by the user """ result = self.client.cancel_build(args.build_id) print(result.status) def action_watch_build(self, args): self._watch_builds(args.build_id) ######################################################### ### Package actions ### ######################################################### @requires_api_auth def action_add_or_edit_package_tito(self, args): ownername, projectname = parse_name(args.copr) data = { "package_name": args.name, "git_url": args.git_url, "git_dir": args.git_dir, "git_branch": args.git_branch, "tito_test": args.tito_test == 'on', "webhook_rebuild": args.webhook_rebuild == 'on', } if args.create: result = self.client.add_package_tito(ownername=ownername, projectname=projectname, **data) else: result = self.client.edit_package_tito(ownername=ownername, projectname=projectname, **data) print(result.message) @requires_api_auth def action_add_or_edit_package_pypi(self, args): ownername, projectname = parse_name(args.copr) data = { "package_name": args.name, "pypi_package_name": args.packagename, "pypi_package_version": args.packageversion, "python_versions": args.pythonversions, "webhook_rebuild": args.webhook_rebuild == 'on', } if args.create: result = self.client.add_package_pypi(ownername=ownername, projectname=projectname, **data) else: result = self.client.edit_package_pypi(ownername=ownername, projectname=projectname, **data) print(result.message) @requires_api_auth def action_add_or_edit_package_mockscm(self, args): ownername, projectname = parse_name(args.copr) data = { "package_name": args.name, "scm_type": args.scm_type, "scm_url": args.scm_url, "scm_branch": args.scm_branch, "spec": args.spec, "webhook_rebuild": args.webhook_rebuild == 'on', } if args.create: result = self.client.add_package_mockscm(ownername=ownername, projectname=projectname, **data) else: result = self.client.edit_package_mockscm(ownername=ownername, projectname=projectname, **data) print(result.message) @requires_api_auth def action_add_or_edit_package_urls(self, args): ownername, projectname = parse_name(args.copr) data = { "package_name": args.name, "urls": '\n'.join(args.urls.split(',')), "webhook_rebuild": args.webhook_rebuild == 'on', } if args.create: result = self.client.add_package_urls(ownername=ownername, projectname=projectname, **data) else: result = self.client.edit_package_urls(ownername=ownername, projectname=projectname, **data) print(result.message) @requires_api_auth def action_add_or_edit_package_upload(self, args): ownername, projectname = parse_name(args.copr) data = { "package_name": args.name, "webhook_rebuild": args.webhook_rebuild == 'on', } if args.create: result = self.client.add_package_upload(ownername=ownername, projectname=projectname, **data) else: result = self.client.edit_package_upload(ownername=ownername, projectname=projectname, **data) print(result.message) @requires_api_auth def action_add_or_edit_package_rubygems(self, args): ownername, projectname = parse_name(args.copr) data = { "package_name": args.name, "gem_name": args.gem_name, "webhook_rebuild": args.webhook_rebuild == 'on', } if args.create: result = self.client.add_package_rubygems(ownername=ownername, projectname=projectname, **data) else: result = self.client.edit_package_rubygems(ownername=ownername, projectname=projectname, **data) print(result.message) def action_list_packages(self, args): ownername, projectname = parse_name(args.copr) result = self.client.get_packages_list(ownername=ownername, projectname=projectname) print(simplejson.dumps(result.packages_list, indent=4, sort_keys=True, for_json=True)) def action_get_package(self, args): ownername, projectname = parse_name(args.copr) data = { "pkg_name": args.name } result = self.client.get_package(ownername=ownername, projectname=projectname, **data) print(simplejson.dumps(result.package, indent=4, sort_keys=True, for_json=True)) def action_delete_package(self, args): ownername, projectname = parse_name(args.copr) data = { "pkg_name": args.name } result = self.client.delete_package(ownername=ownername, projectname=projectname, **data) print(result.message) def action_reset_package(self, args): ownername, projectname = parse_name(args.copr) data = { "pkg_name": args.name } result = self.client.reset_package(ownername=ownername, projectname=projectname, **data) print(result.message)
class Commands(object): def __init__(self, config): self.config = config try: self.client = CoprClient.create_from_file_config(config) except (copr_exceptions.CoprNoConfException, copr_exceptions.CoprConfigException): print(no_config_warning.format(config or "~/.config/copr")) self.client = CoprClient( copr_url=u"http://copr.fedoraproject.org", no_config=True ) def requires_api_auth(func): """ Decorator that checks config presence """ def wrapper(self, args): if self.client.no_config: print("Error: Operation requires api authentication") print(no_config_warning.format(self.config or "~/.config/copr")) sys.exit(6) return func(self, args) wrapper.__doc__ = func.__doc__ wrapper.__name__ = func.__name__ return wrapper def check_username_presence(func): """ Decorator that checks if username was provided """ def wrapper(self, args): if self.client.no_config and args.username is None: print("Error: Operation requires username\n" "Pass username to command or create `~/.config/copr`") sys.exit(6) if args.username is None and self.client.username is None: print("Error: Operation requires username\n" "Pass username to command or add it to `~/.config/copr`") sys.exit(6) return func(self, args) wrapper.__doc__ = func.__doc__ wrapper.__name__ = func.__name__ return wrapper def _watch_builds(self, build_ids): """ :param build_ids: list of build IDs """ print("Watching build(s): (this may be safely interrupted)") prevstatus = defaultdict(lambda: None) failed_ids = [] watched = set(build_ids) done = set() try: while watched != done: for build_id in watched: if build_id in done: continue build_details = self.client.get_build_details(build_id) if build_details.output != "ok": errmsg = " Build {1}: Unable to get build status: {0}". \ format(build_details.error, build_id) raise copr_exceptions.CoprRequestException(errmsg) now = datetime.datetime.now() if prevstatus[build_id] != build_details.status: prevstatus[build_id] = build_details.status print(" {0} Build {2}: {1}".format( now.strftime("%H:%M:%S"), build_details.status, build_id)) if build_details.status in ["failed"]: failed_ids.append(build_id) if build_details.status in ["succeeded", "skipped", "failed", "canceled"]: done.add(build_id) if build_details.status == "unknown": raise copr_exceptions.CoprBuildException( "Unknown status.") if watched == done: break time.sleep(30) if failed_ids: raise copr_exceptions.CoprBuildException( "Build(s) {0} failed.".format( ", ".join(str(x) for x in failed_ids))) except KeyboardInterrupt: pass @requires_api_auth def action_build(self, args): """ Method called when the 'build' action has been selected by the user. :param args: argparse arguments provided by the user """ bar = None progress_callback = None if os.path.exists(args.pkgs[0]): bar = ProgressBar(max=os.path.getsize(args.pkgs[0])) def progress_callback(monitor): bar.next(n=8192) print('Uploading package {0}'.format(args.pkgs[0])) data = { "pkgs": args.pkgs, "progress_callback": progress_callback, } return self.process_build(args, self.client.create_new_build, data, bar=bar) @requires_api_auth def action_build_pypi(self, args): """ Method called when the 'buildpypi' action has been selected by the user. :param args: argparse arguments provided by the user """ username, copr = parse_name(args.copr) data = { "pypi_package_name": args.packagename, "pypi_package_version": args.packageversion, "python_versions": args.pythonversions, } return self.process_build(args, self.client.create_new_build_pypi, data) @requires_api_auth def action_build_tito(self, args): """ Method called when the 'buildtito' action has been selected by the user. :param args: argparse arguments provided by the user """ data = { "git_url": args.git_url, "git_dir": args.git_dir, "git_branch": args.git_branch, "tito_test": args.tito_test, } return self.process_build(args, self.client.create_new_build_tito, data) @requires_api_auth def action_build_mock(self, args): """ Method called when the 'build-mock' action has been selected by the user. :param args: argparse arguments provided by the user """ data = { "scm_type": args.scm_type, "scm_url": args.scm_url, "scm_branch": args.scm_branch, "spec": args.spec, } return self.process_build(args, self.client.create_new_build_mock, data) @requires_api_auth def action_build_rubygems(self, args): """ Method called when the 'buildgem' action has been selected by the user. :param args: argparse arguments provided by the user """ data = {"gem_name": args.gem_name} return self.process_build(args, self.client.create_new_build_rubygems, data) def process_build(self, args, build_function, data, bar=None): username, copr = parse_name(args.copr) result = build_function(username=username, projectname=copr, chroots=args.chroots, memory=args.memory, timeout= args.timeout, **data) if bar: bar.finish() if result.output != "ok": print(result.error) return print(result.message) build_ids = [bw.build_id for bw in result.builds_list] print("Created builds: {0}".format(" ".join(map(str, build_ids)))) if not args.nowait: self._watch_builds(build_ids) @requires_api_auth def action_create(self, args): """ Method called when the 'create' action has been selected by the user. :param args: argparse arguments provided by the user """ username, copr = parse_name(args.name) result = self.client.create_project( username=username, projectname=copr, description=args.description, instructions=args.instructions, chroots=args.chroots, repos=args.repos, initial_pkgs=args.initial_pkgs) print(result.message) @requires_api_auth def action_modify_project(self, args): """ Method called when the 'modify' action has been selected by the user. :param args: argparse arguments provided by the user """ username, copr = parse_name(args.name) result = self.client.modify_project( username=username, projectname=copr, description=args.description, instructions=args.instructions, repos=args.repos, disable_createrepo=args.disable_createrepo) @requires_api_auth def action_delete(self, args): """ Method called when the 'delete' action has been selected by the user. :param args: argparse arguments provided by the user """ username, copr = parse_name(args.copr) result = self.client.delete_project(username=username, projectname=copr) print(result.message) @requires_api_auth def action_fork(self, args): """ Method called when the 'fork' action has been selected by the user. :param args: argparse arguments provided by the user """ username, copr = parse_name(args.dst) result = self.client.fork_project(source=args.src, username=username, projectname=copr, confirm=args.confirm) print(result.message) @check_username_presence def action_list(self, args): """ Method called when the 'list' action has been selected by the user. :param args: argparse arguments provided by the user """ username = args.username or self.client.username result = self.client.get_projects_list(username) # import ipdb; ipdb.set_trace() if result.output != "ok": print(result.error) print("Un-expected data returned, please report this issue") elif not result.projects_list: print("No copr retrieved for user: '******'".format(username)) return for prj in result.projects_list: print(prj) def action_status(self, args): result = self.client.get_build_details(args.build_id) print(result.status) def action_download_build(self, args): result = self.client.get_build_details(args.build_id) base_len = len(os.path.split(result.results)) for chroot, url in result.results_by_chroot.items(): if args.chroots and chroot not in args.chroots: continue cmd = "wget -r -nH --no-parent --reject 'index.html*'".split(' ') cmd.extend(['-P', os.path.join(args.dest, chroot)]) cmd.extend(['--cut-dirs', str(base_len + 4)]) cmd.append(url) subprocess.call(cmd) @requires_api_auth def action_cancel(self, args): """ Method called when the 'cancel' action has been selected by the user. :param args: argparse arguments provided by the user """ result = self.client.cancel_build(args.build_id) print(result.status) def action_watch_build(self, args): self._watch_builds(args.build_id) ######################################################### ### Package actions ### ######################################################### @requires_api_auth def action_add_or_edit_package_tito(self, args): ownername, projectname = parse_name(args.copr) data = { "package_name": args.name, "git_url": args.git_url, "git_dir": args.git_dir, "git_branch": args.git_branch, "tito_test": args.tito_test == 'on', "webhook_rebuild": args.webhook_rebuild == 'on', } if args.create: result = self.client.add_package_tito(ownername=ownername, projectname=projectname, **data) else: result = self.client.edit_package_tito(ownername=ownername, projectname=projectname, **data) print(result.message) @requires_api_auth def action_add_or_edit_package_pypi(self, args): ownername, projectname = parse_name(args.copr) data = { "package_name": args.name, "pypi_package_name": args.packagename, "pypi_package_version": args.packageversion, "python_versions": args.pythonversions, "webhook_rebuild": args.webhook_rebuild == 'on', } if args.create: result = self.client.add_package_pypi(ownername=ownername, projectname=projectname, **data) else: result = self.client.edit_package_pypi(ownername=ownername, projectname=projectname, **data) print(result.message) @requires_api_auth def action_add_or_edit_package_mockscm(self, args): ownername, projectname = parse_name(args.copr) data = { "package_name": args.name, "scm_type": args.scm_type, "scm_url": args.scm_url, "scm_branch": args.scm_branch, "spec": args.spec, "webhook_rebuild": args.webhook_rebuild == 'on', } if args.create: result = self.client.add_package_mockscm(ownername=ownername, projectname=projectname, **data) else: result = self.client.edit_package_mockscm(ownername=ownername, projectname=projectname, **data) print(result.message) @requires_api_auth def action_add_or_edit_package_urls(self, args): ownername, projectname = parse_name(args.copr) data = { "package_name": args.name, "urls": '\n'.join(args.urls.split(',')), "webhook_rebuild": args.webhook_rebuild == 'on', } if args.create: result = self.client.add_package_urls(ownername=ownername, projectname=projectname, **data) else: result = self.client.edit_package_urls(ownername=ownername, projectname=projectname, **data) print(result.message) @requires_api_auth def action_add_or_edit_package_upload(self, args): ownername, projectname = parse_name(args.copr) data = { "package_name": args.name, "webhook_rebuild": args.webhook_rebuild == 'on', } if args.create: result = self.client.add_package_upload(ownername=ownername, projectname=projectname, **data) else: result = self.client.edit_package_upload(ownername=ownername, projectname=projectname, **data) print(result.message) @requires_api_auth def action_add_or_edit_package_rubygems(self, args): ownername, projectname = parse_name(args.copr) data = { "package_name": args.name, "gem_name": args.gem_name, "webhook_rebuild": args.webhook_rebuild == 'on', } if args.create: result = self.client.add_package_rubygems(ownername=ownername, projectname=projectname, **data) else: result = self.client.edit_package_rubygems(ownername=ownername, projectname=projectname, **data) print(result.message) def action_list_packages(self, args): ownername, projectname = parse_name(args.copr) data = { "with_latest_build": args.with_latest_build, "with_latest_succeeded_build": args.with_latest_succeeded_build, "with_all_builds": args.with_all_builds, } result = self.client.get_packages_list(ownername=ownername, projectname=projectname, **data) print(simplejson.dumps(result.packages_list, indent=4, sort_keys=True, for_json=True)) def action_list_package_names(self, args): ownername, projectname = parse_name(args.copr) result = self.client.get_packages_list(ownername=ownername, projectname=projectname) for package in result.packages_list: print(package.name) def action_get_package(self, args): ownername, projectname = parse_name(args.copr) data = { "pkg_name": args.name, "with_latest_build": args.with_latest_build, "with_latest_succeeded_build": args.with_latest_succeeded_build, "with_all_builds": args.with_all_builds, } result = self.client.get_package(ownername=ownername, projectname=projectname, **data) print(simplejson.dumps(result.package, indent=4, sort_keys=True, for_json=True)) def action_delete_package(self, args): ownername, projectname = parse_name(args.copr) data = { "pkg_name": args.name } result = self.client.delete_package(ownername=ownername, projectname=projectname, **data) print(result.message) def action_reset_package(self, args): ownername, projectname = parse_name(args.copr) data = { "pkg_name": args.name } result = self.client.reset_package(ownername=ownername, projectname=projectname, **data) print(result.message) def action_build_package(self, args): ownername, projectname = parse_name(args.copr) data = { "pkg_name": args.name } result = self.client.build_package(ownername=ownername, projectname=projectname, **data) if result.output != "ok": print(result.error) return print(result.message) build_ids = [bw.build_id for bw in result.builds_list] print("Created builds: {0}".format(" ".join(map(str, build_ids)))) if not args.nowait: self._watch_builds(build_ids)