From c45899ef99d428f03b2cc7c92f93adebf77e8d2e Mon Sep 17 00:00:00 2001 From: Ed Bartosh Date: Tue, 25 Sep 2012 18:07:17 +0300 Subject: [PATCH] Implemented command line parsing using argparse Fixes: #259 Change-Id: I25c6eabfedc30f089a0c5cb4cebaac3b31b97c8c --- gitbuildsys/cmd_build.py | 96 +++-- gitbuildsys/cmd_changelog.py | 19 +- gitbuildsys/cmd_chroot.py | 13 +- gitbuildsys/cmd_export.py | 80 ++-- gitbuildsys/cmd_import.py | 28 +- gitbuildsys/cmd_remotebuild.py | 66 ++-- gitbuildsys/cmd_submit.py | 31 +- gitbuildsys/parsing.py | 88 +++++ tests/test_changelog.py | 2 +- tests/test_help.py | 20 +- tests/test_import.py | 33 +- tools/gbs | 833 ++++++++++++++++------------------------- 12 files changed, 598 insertions(+), 711 deletions(-) create mode 100644 gitbuildsys/parsing.py diff --git a/gitbuildsys/cmd_build.py b/gitbuildsys/cmd_build.py index 93bfd94..c6c7c90 100644 --- a/gitbuildsys/cmd_build.py +++ b/gitbuildsys/cmd_build.py @@ -59,7 +59,7 @@ SUPPORTEDARCHS = [ 'armv7l', ] -def prepare_repos_and_build_conf(opts, arch): +def prepare_repos_and_build_conf(args, arch): '''generate repos and build conf options for depanneur''' cmd_opts = [] @@ -73,13 +73,13 @@ def prepare_repos_and_build_conf(opts, arch): os.makedirs(cachedir) msger.info('generate repositories ...') - if opts.skip_conf_repos: + if args.skip_conf_repos: repos = [] else: repos = [i.url for i in configmgr.get_current_profile().repos] - if opts.repositories: - for i in opts.repositories: + if args.repositories: + for i in args.repositories: try: opt_repo = SafeURL(i) except ValueError, err: @@ -97,8 +97,8 @@ def prepare_repos_and_build_conf(opts, arch): 'following repos:\n%s' % (arch, '\n'.join(repos))) cmd_opts += [('--repository=%s' % url.full) for url in repourls] - if opts.dist: - distconf = opts.dist + if args.dist: + distconf = args.dist if not os.path.exists(distconf): msger.error('specified build conf %s does not exists' % distconf) else: @@ -129,32 +129,32 @@ def prepare_repos_and_build_conf(opts, arch): return cmd_opts -def prepare_depanneur_opts(opts): +def prepare_depanneur_opts(args): '''generate extra options for depanneur''' cmd_opts = [] - if opts.exclude: - cmd_opts += ['--exclude=%s' % i for i in opts.exclude] - if opts.exclude_from_file: - cmd_opts += ['--exclude-from-file=%s' % opts.exclude_from_file] - if opts.overwrite: + if args.exclude: + cmd_opts += ['--exclude=%s' % i for i in args.exclude] + if args.exclude_from_file: + cmd_opts += ['--exclude-from-file=%s' % args.exclude_from_file] + if args.overwrite: cmd_opts += ['--overwrite'] - if opts.clean_once: + if args.clean_once: cmd_opts += ['--clean-once'] - if opts.debug: + if args.debug: cmd_opts += ['--debug'] - if opts.incremental: + if args.incremental: cmd_opts += ['--incremental'] - if opts.keepgoing: + if args.keepgoing: cmd_opts += ['--keepgoing'] - if opts.no_configure: + if args.no_configure: cmd_opts += ['--no-configure'] - if opts.binary_list: - if not os.path.exists(opts.binary_list): + if args.binary_list: + if not os.path.exists(args.binary_list): msger.error('specified binary list file %s not exists' %\ - opts.binary_list) - cmd_opts += ['--binary=%s' % opts.binary_list] - cmd_opts += ['--threads=%s' % opts.threads] + args.binary_list) + cmd_opts += ['--binary=%s' % args.binary_list] + cmd_opts += ['--threads=%s' % args.threads] return cmd_opts @@ -266,19 +266,13 @@ def setup_qemu_emulator(): return qemu_emulator -def do(opts, args): - """ - Main of build module - """ - workdir = os.getcwd() - if len(args) > 1: - msger.error('only one work directory can be specified in args.') - if len(args) == 1: - workdir = os.path.abspath(args[0]) +def main(args): + """gbs build entry point.""" - if opts.commit and opts.include_all: + if args.commit and args.include_all: raise errors.Usage('--commit can\'t be specified together with '\ '--include-all') + workdir = args.gitdir try: repo = RpmGitRepository(workdir) @@ -287,8 +281,8 @@ def do(opts, args): pass hostarch = get_hostarch() - if opts.arch: - buildarch = opts.arch + if args.arch: + buildarch = args.arch else: buildarch = hostarch msger.info('No arch specified, using system arch: %s' % hostarch) @@ -302,8 +296,8 @@ def do(opts, args): build_root = os.path.expanduser('~/GBS-ROOT/') if 'TIZEN_BUILD_ROOT' in os.environ: build_root = os.environ['TIZEN_BUILD_ROOT'] - if opts.buildroot: - build_root = opts.buildroot + if args.buildroot: + build_root = args.buildroot os.environ['TIZEN_BUILD_ROOT'] = build_root # get virtual env from system env first @@ -314,19 +308,19 @@ def do(opts, args): cmd += ['--arch=%s' % buildarch] - if opts.clean: + if args.clean: cmd += ['--clean'] # check & prepare repos and build conf - cmd += prepare_repos_and_build_conf(opts, buildarch) + cmd += prepare_repos_and_build_conf(args, buildarch) cmd += ['--path=%s' % workdir] - if opts.ccache: + if args.ccache: cmd += ['--ccache'] - if opts.extra_packs: - cmd += ['--extra-packs=%s' % opts.extra_packs] + if args.extra_packs: + cmd += ['--extra-packs=%s' % args.extra_packs] if hostarch != buildarch and buildarch in CHANGE_PERSONALITY: cmd = [ CHANGE_PERSONALITY[buildarch] ] + cmd @@ -338,19 +332,19 @@ def do(opts, args): msger.error('%s' % exc) # Extra depanneur special command options - cmd += prepare_depanneur_opts(opts) + cmd += prepare_depanneur_opts(args) # Extra options for gbs export - if opts.include_all: + if args.include_all: cmd += ['--include-all'] - if opts.commit: - cmd += ['--commit=%s' % opts.commit] - if opts.upstream_branch: - cmd += ['--upstream-branch=%s' % opts.upstream_branch] - if opts.upstream_tag: - cmd += ['--upstream-tag=%s' % opts.upstream_tag] - if opts.squash_patches_until: - cmd += ['--squash-patches-until=%s' % opts.squash_patches_until] + if args.commit: + cmd += ['--commit=%s' % args.commit] + if args.upstream_branch: + cmd += ['--upstream-branch=%s' % args.upstream_branch] + if args.upstream_tag: + cmd += ['--upstream-tag=%s' % args.upstream_tag] + if args.squash_patches_until: + cmd += ['--squash-patches-until=%s' % args.squash_patches_until] msger.debug("running command: %s" % ' '.join(cmd)) retcode = os.system(' '.join(cmd)) diff --git a/gitbuildsys/cmd_changelog.py b/gitbuildsys/cmd_changelog.py index f205d8f..d477b69 100644 --- a/gitbuildsys/cmd_changelog.py +++ b/gitbuildsys/cmd_changelog.py @@ -79,10 +79,11 @@ def make_log_entries(commits, git_repo): return entries -def do(opts, _args): +def main(args): + """gbs changelog entry point.""" try: - repo = RpmGitRepository('.') + repo = RpmGitRepository(args.gitdir) except GitRepositoryError, err: msger.error(str(err)) @@ -103,9 +104,9 @@ def do(opts, _args): else: msger.error("Found no changes nor spec files under packaging dir") - # get the commit start from the opts.since - if opts.since: - since = opts.since + # get the commit start from the args.since + if args.since: + since = args.since else: since = get_latest_rev(fn_changes) @@ -114,8 +115,8 @@ def do(opts, _args): try: commitid_since = repo.rev_parse(since) except GitRepositoryError: - if opts.since: - msger.error("Invalid commit: %s" % (opts.since)) + if args.since: + msger.error("Invalid commit: %s" % (since)) else: msger.error("Can't find last commit ID in the log, "\ "please specify it by '--since'") @@ -126,9 +127,9 @@ def do(opts, _args): if not commits: msger.error("Nothing found between %s and HEAD" % commitid_since) - if opts.message: + if args.message: author = repo.get_author_info() - lines = ["- %s" % line for line in opts.message.split(os.linesep) \ + lines = ["- %s" % line for line in args.message.split(os.linesep) \ if line.strip()] new_entries = ["* %s %s <%s> %s" % \ (datetime.datetime.now().strftime("%a %b %d %Y"), diff --git a/gitbuildsys/cmd_chroot.py b/gitbuildsys/cmd_chroot.py index e69dd90..c126e8f 100644 --- a/gitbuildsys/cmd_chroot.py +++ b/gitbuildsys/cmd_chroot.py @@ -21,21 +21,20 @@ import os import subprocess -from gitbuildsys import msger, errors +from gitbuildsys import msger -def do(opts, args): +def main(args): + """gbs chroot entry point.""" - if len(args) != 1: - raise errors.Usage('no build root directory specified') + build_root = args.buildroot - build_root = os.path.abspath(args[0]) running_lock = '%s/not-ready' % build_root - if os.path.exists(running_lock) or not os.path.exists(build_root): + if os.path.exists(running_lock): msger.error('build root %s is not ready' % build_root) msger.info('chroot %s' % build_root) user = 'abuild' - if opts.root: + if args.root: user = 'root' cmd = ['sudo', 'chroot', build_root, 'su', user] diff --git a/gitbuildsys/cmd_export.py b/gitbuildsys/cmd_export.py index b23b133..b8a14fb 100644 --- a/gitbuildsys/cmd_export.py +++ b/gitbuildsys/cmd_export.py @@ -24,7 +24,7 @@ import re import shutil import errno -from gitbuildsys import msger, runner, utils, errors +from gitbuildsys import msger, utils, errors from gitbuildsys.conf import configmgr from gbp.scripts.buildpackage_rpm import main as gbp_build @@ -45,12 +45,12 @@ def mkdir_p(path): else: raise -def is_native_pkg(repo, opts): +def is_native_pkg(repo, args): """ Determine if the package is "native" """ - if opts.upstream_branch: - upstream_branch = opts.upstream_branch + if args.upstream_branch: + upstream_branch = args.upstream_branch else: upstream_branch = configmgr.get('upstream_branch', 'general') return not repo.has_branch(upstream_branch) @@ -59,17 +59,17 @@ def transform_var_format_from_shell_to_python(whole): '''replace string like ${xxx} with %(xxx)s''' return re.sub(r'\$\{([^}]+)\}', r'%(\1)s', whole) -def create_gbp_export_args(repo, commit, export_dir, tmp_dir, spec, opts, +def create_gbp_export_args(repo, commit, export_dir, tmp_dir, spec, args, force_native=False): """ Construct the cmdline argument list for git-buildpackage export """ - if opts.upstream_branch: - upstream_branch = opts.upstream_branch + if args.upstream_branch: + upstream_branch = args.upstream_branch else: upstream_branch = configmgr.get('upstream_branch', 'general') - if opts.upstream_tag: - upstream_tag = opts.upstream_tag + if args.upstream_tag: + upstream_tag = args.upstream_tag else: upstream_tag = configmgr.get('upstream_tag', 'general') upstream_tag = transform_var_format_from_shell_to_python(upstream_tag) @@ -77,13 +77,13 @@ def create_gbp_export_args(repo, commit, export_dir, tmp_dir, spec, opts, msger.debug("Using upstream tag format: '%s'" % upstream_tag) # Get patch squashing option - if opts.squash_patches_until: - squash_patches_until = opts.squash_patches_until + if args.squash_patches_until: + squash_patches_until = args.squash_patches_until else: squash_patches_until = configmgr.get('squash_patches_until', 'general') # Now, start constructing the argument list - args = ["argv[0] placeholder", + argv = ["argv[0] placeholder", "--git-ignore-new", "--git-upstream-branch=upstream", "--git-export-dir=%s" % export_dir, @@ -93,21 +93,21 @@ def create_gbp_export_args(repo, commit, export_dir, tmp_dir, spec, opts, "--git-export=%s" % commit, "--git-upstream-branch=%s" % upstream_branch, "--git-upstream-tag=%s" % upstream_tag] - if force_native or is_native_pkg(repo, opts): - args.extend(["--git-no-patch-export", + if force_native or is_native_pkg(repo, args): + argv.extend(["--git-no-patch-export", "--git-upstream-tree=%s" % commit]) else: - args.extend(["--git-patch-export", + argv.extend(["--git-patch-export", "--git-patch-export-compress=100k", "--git-force-create", "--git-patch-export-squash-until=%s" % squash_patches_until, "--git-patch-export-ignore-path=^packaging/.*"]) if repo.has_branch("pristine-tar"): - args.extend(["--git-pristine-tar"]) + argv.extend(["--git-pristine-tar"]) - if opts.source_rpm: - args.extend(['--git-builder=rpmbuild', + if args.source_rpm: + argv.extend(['--git-builder=rpmbuild', '--git-rpmbuild-builddir=.', '--git-rpmbuild-builddir=.', '--git-rpmbuild-rpmdir=.', @@ -118,11 +118,11 @@ def create_gbp_export_args(repo, commit, export_dir, tmp_dir, spec, opts, '--short-circuit', '-bs', ]) else: - args.extend(["--git-builder=osc", "--git-export-only"]) + argv.extend(["--git-builder=osc", "--git-export-only"]) - return args + return argv -def export_sources(repo, commit, export_dir, spec, opts): +def export_sources(repo, commit, export_dir, spec, args): """ Export packaging files using git-buildpackage """ @@ -130,10 +130,10 @@ def export_sources(repo, commit, export_dir, spec, opts): directory=True) gbp_args = create_gbp_export_args(repo, commit, export_dir, tmp.path, - spec, opts) + spec, args) try: ret = gbp_build(gbp_args) - if ret == 2 and not is_native_pkg(repo, opts): + if ret == 2 and not is_native_pkg(repo, args): # Try falling back to old logic of one monolithic tarball msger.warning("Generating upstream tarball and/or generating "\ "patches failed. GBS tried this as you have "\ @@ -146,7 +146,7 @@ def export_sources(repo, commit, export_dir, spec, opts): msger.info("Falling back to the old method of generating one "\ "monolithic source archive") gbp_args = create_gbp_export_args(repo, commit, export_dir, - tmp.path, spec, opts, + tmp.path, spec, args, force_native=True) ret = gbp_build(gbp_args) if ret: @@ -155,27 +155,20 @@ def export_sources(repo, commit, export_dir, spec, opts): msger.error("Repository error: %s" % excobj) -def do(opts, args): - """ - The main plugin call - """ - workdir = os.getcwd() +def main(args): + """gbs export entry point.""" - if len(args) > 1: - msger.error('only one work directory can be specified in args.') - if len(args) == 1: - workdir = os.path.abspath(args[0]) - - if opts.commit and opts.include_all: + if args.commit and args.include_all: raise errors.Usage('--commit can\'t be specified together with '\ '--include-all') + workdir = args.gitdir try: repo = RpmGitRepository(workdir) except GitRepositoryError, err: msger.error(str(err)) - utils.git_status_checker(repo, opts) + utils.git_status_checker(repo, args) workdir = repo.path if not os.path.exists("%s/packaging" % workdir): @@ -183,11 +176,11 @@ def do(opts, args): # Only guess spec filename here, parse later when we have the correct # spec file at hand - specfile = utils.guess_spec(workdir, opts.spec) + specfile = utils.guess_spec(workdir, args.spec) outdir = "%s/packaging" % workdir - if opts.outdir: - outdir = opts.outdir + if args.outdir: + outdir = args.outdir mkdir_p(outdir) outdir = os.path.abspath(outdir) tmpdir = configmgr.get('tmpdir', 'general') @@ -196,14 +189,14 @@ def do(opts, args): export_dir = tempd.path with utils.Workdir(workdir): - if opts.commit: - commit = opts.commit - elif opts.include_all: + if args.commit: + commit = args.commit + elif args.include_all: commit = 'WC.UNTRACKED' else: commit = 'HEAD' relative_spec = specfile.replace('%s/' % workdir, '') - export_sources(repo, commit, export_dir, relative_spec, opts) + export_sources(repo, commit, export_dir, relative_spec, args) try: spec = rpm.parse_spec(os.path.join(export_dir, @@ -218,7 +211,6 @@ def do(opts, args): spec.release) shutil.rmtree(outdir, ignore_errors=True) shutil.move(export_dir, outdir) - msger.info('source rpm generated to:\n %s/%s.src.rpm' % \ (outdir, os.path.basename(outdir))) diff --git a/gitbuildsys/cmd_import.py b/gitbuildsys/cmd_import.py index a764189..71bee7e 100644 --- a/gitbuildsys/cmd_import.py +++ b/gitbuildsys/cmd_import.py @@ -25,31 +25,27 @@ from gitbuildsys import msger from gbp.scripts.import_srpm import main as gbp_import_srpm from gbp.scripts.import_orig_rpm import main as gbp_import_orig -def do(opts, args): +def main(args): + """gbs import entry point.""" - if opts.author_name: - os.environ["GIT_AUTHOR_NAME"] = opts.author_name - if opts.author_email: - os.environ["GIT_AUTHOR_EMAIL"] = opts.author_email + if args.author_name: + os.environ["GIT_AUTHOR_NAME"] = args.author_name + if args.author_email: + os.environ["GIT_AUTHOR_EMAIL"] = args.author_email - if len(args) < 1: - msger.error('missing argument, please reference gbs import --help.') - if len(args) > 1: - msger.error('too many arguments! Please reference gbs import --help.') - if not os.path.exists(args[0]): - msger.error('%s not exist' % args[0]) + path = args.path params = ["argv[0] placeholder", "--packaging-dir=packaging", - "--upstream-branch=%s" % opts.upstream_branch, args[0]] + "--upstream-branch=%s" % args.upstream_branch, path] - if args[0].endswith('.src.rpm') or args[0].endswith('.spec'): + if path.endswith('.src.rpm') or path.endswith('.spec'): params.append("--no-patch-import") if gbp_import_srpm(params): - msger.error("Failed to import %s" % args[0]) + msger.error("Failed to import %s" % path) else: - if opts.no_merge: + if args.no_merge: params.insert(1, '--no-merge') if gbp_import_orig(params): - msger.error('Failed to import %s' % args[0]) + msger.error('Failed to import %s' % path) msger.info('done.') diff --git a/gitbuildsys/cmd_remotebuild.py b/gitbuildsys/cmd_remotebuild.py index 06ef1b2..e759d75 100644 --- a/gitbuildsys/cmd_remotebuild.py +++ b/gitbuildsys/cmd_remotebuild.py @@ -45,27 +45,11 @@ passx=%(passwdx)s """ -def do(opts, args): - - obs_repo = None - obs_arch = None - - if len(args) == 0: - workdir = os.getcwd() - elif len(args) == 1: - workdir = os.path.abspath(args[0]) - elif len(args) == 2 and opts.buildlog: - workdir = os.getcwd() - obs_repo = args[0] - obs_arch = args[1] - elif len(args) == 3 and opts.buildlog: - workdir = os.path.abspath(args[0]) - obs_repo = args[1] - obs_arch = args[2] - else: - msger.error('Invalid arguments, see gbs remotebuild -h for more info') +def main(args): + """gbs remotebuild entry point.""" obsconf = configmgr.get_current_profile().obs + if not obsconf or not obsconf.url: msger.error('no obs api found, please add it to gbs conf and try again') @@ -75,25 +59,32 @@ def do(opts, args): msger.error('empty user is not allowed for remotebuild, ' 'please add user/passwd to gbs conf, and try again') - if opts.commit and opts.include_all: - raise errors.Usage('--commit can\'t be specified together with '\ + if args.commit and args.include_all: + raise errors.Usage('--commit can\'t be specified together with ' '--include-all') + obs_repo = args.repository + obs_arch = args.arch + + if args.buildlog and None in (obs_repo, obs_arch): + msger.error('please specify arch(-A) and repository(-R)') + + workdir = args.gitdir + try: repo = RpmGitRepository(workdir) except GitRepositoryError, err: msger.error(str(err)) - if not (opts.buildlog or opts.status): - utils.git_status_checker(repo, opts) - workdir = repo.path + if not (args.buildlog or args.status): + utils.git_status_checker(repo, args) # TODO: check ./packaging dir at first specs = glob.glob('%s/packaging/*.spec' % workdir) if not specs: msger.error('no spec file found under /packaging sub-directory') - specfile = utils.guess_spec(workdir, opts.spec) + specfile = utils.guess_spec(workdir, args.spec) # get 'name' and 'version' from spec file try: spec = gbp.rpm.parse_spec(specfile) @@ -104,16 +95,13 @@ def do(opts, args): msger.error('can\'t get correct name.') package = spec.name - if opts.base_obsprj is None: - base_prj = obsconf.base or 'Tizen:Main' - else: - base_prj = opts.base_obsprj + base_prj = args.base_obsprj - if opts.target_obsprj is None: + if args.target_obsprj is None: target_prj = obsconf.target or \ "home:%s:gbs:%s" % (apiurl.user, base_prj) else: - target_prj = opts.target_obsprj + target_prj = args.target_obsprj api_passwd = apiurl.passwd if apiurl.passwd else '' # Create temporary oscrc @@ -135,7 +123,7 @@ def do(opts, args): api = OSC(apiurl, oscrc=oscrcpath) try: - if opts.buildlog: + if args.buildlog: archlist = [] status = api.get_results(target_prj, package) @@ -158,7 +146,7 @@ def do(opts, args): return 0 - if opts.status: + if args.status: results = [] status = api.get_results(target_prj, package) @@ -175,7 +163,7 @@ def do(opts, args): if not api.exists(target_prj): # FIXME: How do you know that a certain user does not have # permissions to create any project, anywhewre? - if opts.target_obsprj and \ + if args.target_obsprj and \ not target_prj.startswith('home:%s:' % apiurl.user): msger.error('no permission to create project %s, only sub ' 'projects of home:%s are ' @@ -194,17 +182,17 @@ def do(opts, args): msger.error(str(err)) with utils.Workdir(workdir): - if opts.commit: - commit = opts.commit - elif opts.include_all: + if args.commit: + commit = args.commit + elif args.include_all: commit = 'WC.UNTRACKED' else: commit = 'HEAD' relative_spec = specfile.replace('%s/' % workdir, '') - export_sources(repo, commit, exportdir, relative_spec, opts) + export_sources(repo, commit, exportdir, relative_spec, args) try: - commit_msg = repo.get_commit_info(opts.commit or 'HEAD')['subject'] + commit_msg = repo.get_commit_info(args.commit or 'HEAD')['subject'] except GitRepositoryError, exc: msger.error('failed to get commit info: %s' % exc) diff --git a/gitbuildsys/cmd_submit.py b/gitbuildsys/cmd_submit.py index 6ef9f29..0c9cb36 100644 --- a/gitbuildsys/cmd_submit.py +++ b/gitbuildsys/cmd_submit.py @@ -16,8 +16,7 @@ # with this program; if not, write to the Free Software Foundation, Inc., 59 # Temple Place - Suite 330, Boston, MA 02111-1307, USA. -"""Implementation of subcmd: submit -""" +"""Implementation of subcmd: submit""" import os import time @@ -27,31 +26,25 @@ from gitbuildsys import msger, errors from gbp.rpm.git import GitRepositoryError, RpmGitRepository -def do(opts, args): +def main(args): + """gbs submit entry point.""" - workdir = os.getcwd() - if len(args) > 1: - msger.error('only one work directory can be specified in args.') - if len(args) == 1: - workdir = os.path.abspath(args[0]) - - if opts.msg is None: - raise errors.Usage('message for tag must be specified with -m option') + workdir = args.gitdir try: repo = RpmGitRepository(workdir) - commit = repo.rev_parse(opts.commit) - if opts.target: - target_branch = opts.target + commit = repo.rev_parse(args.commit) + if args.target: + target_branch = args.target else: target_branch = repo.get_branch() except GitRepositoryError, err: msger.error(str(err)) - if not opts.target: + if not args.target: try: upstream = repo.get_upstream_branch(target_branch) - if upstream and upstream.startswith(opts.remote): + if upstream and upstream.startswith(args.remote): target_branch = os.path.basename(upstream) else: msger.warning('can\'t find upstream branch for current branch '\ @@ -67,14 +60,14 @@ def do(opts, args): tagname = 'submit/%s/%s' % (target_branch, time.strftime( \ '%Y%m%d.%H%M%S', time.gmtime())) msger.info('creating tag: %s' % tagname) - repo.create_tag(tagname, msg=opts.msg, commit=commit, sign=opts.sign, - keyid=opts.user_key) + repo.create_tag(tagname, msg=args.msg, commit=commit, sign=args.sign, + keyid=args.user_key) except GitRepositoryError, err: msger.error('failed to create tag %s: %s ' % (tagname, str(err))) try: msger.info('pushing tag to remote server') - repo.push_tag(opts.remote, tagname) + repo.push_tag(args.remote, tagname) except GitRepositoryError, err: repo.delete_tag(tagname) msger.error('failed to push tag %s :%s' % (tagname, str(err))) diff --git a/gitbuildsys/parsing.py b/gitbuildsys/parsing.py new file mode 100644 index 0000000..68c0cea --- /dev/null +++ b/gitbuildsys/parsing.py @@ -0,0 +1,88 @@ +#!/usr/bin/env python +# vim: ai ts=4 sts=4 et sw=4 +# +# Copyright (c) 2011 Intel, Inc. +# +# This program is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by the Free +# Software Foundation; version 2 of the License +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., 59 +# Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +"""Local additions to commandline parsing.""" + +import re +import functools + +from argparse import RawDescriptionHelpFormatter + +class GbsHelpFormatter(RawDescriptionHelpFormatter): + """Changed default arparse help output by request from cmdln lovers.""" + + def __init__(self, *args, **kwargs): + super(GbsHelpFormatter, self).__init__(*args, **kwargs) + self._aliases = {} + + def add_argument(self, action): + """Collect aliases.""" + + if action.choices: + for item, parser in action.choices.iteritems(): + self._aliases[str(item)] = parser.get_default('alias') + + return super(GbsHelpFormatter, self).add_argument(action) + + def format_help(self): + """ + There is no safe and documented way in argparser to reformat + help output through APIs as almost all of them are private, + so this method just parses the output and changes it. + """ + result = [] + subcomm = False + for line in super(GbsHelpFormatter, self).format_help().split('\n'): + if line.strip().startswith('{'): + continue + if line.startswith('optional arguments:'): + line = 'Global Options:' + if line.startswith('usage:'): + line = "Usage: gbs [GLOBAL-OPTS] SUBCOMMAND [OPTS]" + if subcomm: + match = re.match("[ ]+([^ ]+)[ ]+(.+)", line) + if match: + name, help_text = match.group(1), match.group(2) + alias = self._aliases.get(name) or '' + if alias: + alias = "(%s)" % alias + line = " %-22s%s" % ("%s %s" % (name, alias), help_text) + if line.strip().startswith('subcommands:'): + line = 'Subcommands:' + subcomm = True + result.append(line) + return '\n'.join(result) + +def subparser(func): + """Convenient decorator for subparsers.""" + @functools.wraps(func) + def wrapper(parser): + """ + Create subparser + Set first line of function's docstring as a help + and the rest of the lines as a description. + Set attribute 'module' of subparser to 'cmd'+first part of function name + """ + splitted = func.__doc__.split('\n') + name = func.__name__.split('_')[0] + subpar = parser.add_parser(name, help=splitted[0], + description='\n'.join(splitted[1:]), + formatter_class=RawDescriptionHelpFormatter) + subpar.set_defaults(module="cmd_%s" % name) + return func(subpar) + return wrapper diff --git a/tests/test_changelog.py b/tests/test_changelog.py index 905c430..c948e43 100644 --- a/tests/test_changelog.py +++ b/tests/test_changelog.py @@ -32,7 +32,7 @@ from gbp.git.repository import GitRepository from gitbuildsys import cmd_changelog -GBS = imp.load_source("gbs", "./tools/gbs").Gbs().main +GBS = imp.load_source("gbs", "./tools/gbs").main ENV = {} def setup_module(): diff --git a/tests/test_help.py b/tests/test_help.py index 724f19b..8a94645 100644 --- a/tests/test_help.py +++ b/tests/test_help.py @@ -23,7 +23,7 @@ import imp from nose.tools import eq_ -GBS = imp.load_source("gbs", "./tools/gbs").Gbs().main +GBS = imp.load_source("gbs", "./tools/gbs").main class TestHelp(unittest.TestCase): """Test help output of gbs commands""" @@ -31,16 +31,20 @@ class TestHelp(unittest.TestCase): @staticmethod def test_subcommand_help(): """Test running gbs help with all possible subcommands.""" - for sub in [ "build", "lb", "remotebuild", "rb", "changelog", + for sub in [ "build", "lb", "remotebuild", "rb", "changelog", "ch", "submit", "sr", "export", "ex", "import", "im", - "chroot"]: + "chroot", "chr"]: - eq_(GBS(argv=["gbs", "help", sub]), None) - eq_(GBS(argv=["gbs", sub, "--help"]), 0) + try: + print '>>>sub', sub + GBS(argv=["gbs", sub, "--help"]) + except SystemExit, err: + eq_(err.code, 0) @staticmethod def test_help(): """Test running gbs --help and gbs help.""" - eq_(GBS(argv=["gbs", "--help"]), 0) - eq_(GBS(argv=["gbs", "help"]), None) - + try: + GBS(argv=["gbs", "--help"]) + except SystemExit, err: + eq_(err.code, 0) diff --git a/tests/test_import.py b/tests/test_import.py index a554f59..3fa70d9 100644 --- a/tests/test_import.py +++ b/tests/test_import.py @@ -30,7 +30,7 @@ from nose.tools import eq_, raises from gbp.git.repository import GitRepository -GBS = imp.load_source("gbs", "./tools/gbs").Gbs +GBS = imp.load_source("gbs", "./tools/gbs").main def with_data(fname): """ @@ -66,7 +66,6 @@ class TestImport(unittest.TestCase): def __init__(self, method): super(TestImport, self).__init__(method) - self.gbs = GBS().main def setUp(self): self.tmp = tempfile.mkdtemp(prefix="test-gbs-import-") @@ -81,7 +80,7 @@ class TestImport(unittest.TestCase): @with_data("ail-0.2.29-2.3.src.rpm") def test_import_srcrpm(self, srcrpm): """Test importing from source rpm.""" - eq_(self.gbs(argv=["gbs", "import", srcrpm]), None) + eq_(GBS(argv=["gbs", "import", srcrpm]), None) repo = GitRepository("./ail") eq_(repo.get_local_branches(), ['master', 'upstream']) eq_(repo.get_tags(), ['upstream/0.2.29', 'vendor/0.2.29-2.3']) @@ -89,8 +88,8 @@ class TestImport(unittest.TestCase): @with_data("bluez_unpacked") def test_import_spec(self, srcdir): """Test importing from spec.""" - eq_(self.gbs(argv=["gbs", "import", - os.path.join(srcdir, 'bluez.spec')]), None) + eq_(GBS(argv=["gbs", "import", + os.path.join(srcdir, 'bluez.spec')]), None) repo = GitRepository("./bluez") eq_(repo.get_local_branches(), ['master', 'upstream']) eq_(repo.get_tags(), ['upstream/4.87', 'vendor/4.87-1']) @@ -103,7 +102,7 @@ class TestImport(unittest.TestCase): # Create empty git repo repo = GitRepository.create("./repo_dir") os.chdir(repo.path) - eq_(self.gbs(argv=["gbs", "import", srcrpm]), None) + eq_(GBS(argv=["gbs", "import", srcrpm]), None) eq_(repo.get_local_branches(), ['master', 'upstream']) eq_(repo.get_tags(), ['upstream/0.2.29', 'vendor/0.2.29-2.5']) @@ -112,9 +111,9 @@ class TestImport(unittest.TestCase): @with_data("app-core-1.2-19.3.src.rpm") def test_set_author_name_email(self, srcrpm): """Test --author-name and --author-email command line options.""" - eq_(self.gbs(argv=["gbs", "import", "--author-name=test", - "--author-email=test@otctools.jf.intel.com", - srcrpm]), None) + eq_(GBS(argv=["gbs", "import", "--author-name=test", + "--author-email=test@otctools.jf.intel.com", + srcrpm]), None) repo = GitRepository("./app-core") eq_(repo.get_local_branches(), ['master', 'upstream']) eq_(repo.get_tags(), ['upstream/1.2', 'vendor/1.2-19.3']) @@ -122,8 +121,8 @@ class TestImport(unittest.TestCase): @with_data("ail-0.2.29-2.3.src.rpm") def test_specify_upstream(self, srcrpm): """Test --upstream command line option.""" - eq_(self.gbs(argv=["gbs", "import", "--upstream=upstream", - srcrpm]), None) + eq_(GBS(argv=["gbs", "import", "--upstream=upstream", + srcrpm]), None) repo = GitRepository("./ail") eq_(repo.get_local_branches(), ['master', 'upstream']) eq_(repo.get_tags(), ['upstream/0.2.29', 'vendor/0.2.29-2.3']) @@ -132,31 +131,31 @@ class TestImport(unittest.TestCase): @with_data("bison-1.27.tar.gz") def test_is_not_git_repository(self, tarball): """Test raising exception when importing tarball outside of git.""" - self.gbs(argv=["gbs", "import", tarball]) + GBS(argv=["gbs", "import", tarball]) @raises(SystemExit) @with_data("bad.src.rpm") def test_error_reading_pkg_header(self, srcrpm): """Test raising exception when importing from bad package.""" - self.gbs(argv=["gbs", "import", srcrpm]) + GBS(argv=["gbs", "import", srcrpm]) @raises(SystemExit) @with_data("bad.spec") def test_cant_parse_specfile(self, spec): """Test raising exception when importing from non-parseable spec.""" - self.gbs(argv=["gbs", "import", spec]) + GBS(argv=["gbs", "import", spec]) @raises(SystemExit) def test_missing_argument(self): """Test raising exception when running gbs without any arguments.""" - self.gbs(argv=["gbs", "import"]) + GBS(argv=["gbs", "import"]) @raises(SystemExit) def test_too_many_arguments(self): """Test raising exception when running gbs with too many arguments.""" - self.gbs(argv=["gbs", "import", "1", "2"]) + GBS(argv=["gbs", "import", "1", "2"]) @raises(SystemExit) def test_path_doesnt_exist(self): """Test raising exception when running gbs with not existing path.""" - self.gbs(argv=["gbs", "import", "I don't exist!"]) + GBS(argv=["gbs", "import", "I don't exist!"]) diff --git a/tools/gbs b/tools/gbs index 7377284..202a18c 100755 --- a/tools/gbs +++ b/tools/gbs @@ -16,519 +16,352 @@ # with this program; if not, write to the Free Software Foundation, Inc., 59 # Temple Place - Suite 330, Boston, MA 02111-1307, USA. +"""Gbs - commandline tool for Tizen developers. Main module.""" + import sys -import re +import os + +from argparse import ArgumentParser from gitbuildsys import __version__ from gitbuildsys import msger, errors -from osc import cmdln - -def handle_repository(option, opt_str, value, parser): - if not value: - raise errors.Usage("option %s: need value" % opt_str) - if value[0] == '-': - raise errors.Usage("option %s: invalid value %s" % (opt_str, value)) - if getattr(parser.values, option.dest) is None: - setattr(parser.values, option.dest, []) - getattr(parser.values, option.dest).append(value) - -def handle_project(option, opt_str, value, parser): - if not value: - raise errors.Usage("option %s: need value" % opt_str) - if value[0] == '-': - raise errors.Usage("option %s: invalid project name %s, cannot " \ - "start with '-'" % (opt_str, value)) - if not re.match(r'^(\w|:|\.|-)+$', value): - raise errors.Usage("option %s: invalid project name %s, only word " \ - "character, ':', '.' and '-' are supported" \ - % (opt_str, value)) - setattr(parser.values, option.dest, value) - -class Gbs(cmdln.Cmdln): - """gbs - the command line tool for Tizen package developers - - Usage: gbs [GLOBAL-OPTS] SUBCOMMAND [OPTS] [ARGS...] - Try 'gbs help SUBCOMAND' for help on a specific subcommand. - - ${command_list} - global ${option_list} - ${help_list} +from gitbuildsys.parsing import subparser, GbsHelpFormatter + +@subparser +def import_parser(parser): + """import spec file/source rpm/tar ball to git repository + Examples: + $ gbs import /path/to/specfile.spec + $ gbs import /path/to/package-version.src.rpm + $ gbs import /path/to/tarball.tar.gz """ - name = 'gbs' - version = __version__ - - def get_optparser(self): - optparser = cmdln.CmdlnOptionParser(self, version=self.version) - optparser.add_option('-d', '--debug', action='store_true', - dest='debug', - help='print debug message') - optparser.add_option('-v', '--verbose', action='store_true', - dest='verbose', - help='verbose information') - optparser.add_option('-c', '--conf', dest='conf', - help='specify config file for gbs') - return optparser - - def postoptparse(self): - from gitbuildsys.conf import configmgr - if self.options.verbose: - msger.set_loglevel('verbose') - - if self.options.debug: - msger.set_loglevel('debug') - - if self.options.conf: - configmgr.reset_from_conf(self.options.conf) - @cmdln.alias('sr') - @cmdln.option('-m', '--msg', - default=None, - dest='msg', - help='specify tag message info') - @cmdln.option('-c', '--commit', - default='HEAD', - dest='commit', - help='specify a commit ID to submit') - @cmdln.option('-s', '--sign', - action='store_true', - default=False, - dest='sign', - help='make a GPG-signed tag') - @cmdln.option('-u', '--user-key', - default=None, - dest='user_key', - help='using the given key to make a GPG-signed tag') - @cmdln.option('-t', '--target', - default=None, - dest='target', - help='specify target version to submit, eg: trunk.') - @cmdln.option('-r', '--remote', - default='origin', - dest='remote', - help='specify gerrit project server, default value is '\ - 'origin for example:\nssh://user@review.tizen.org:29418'\ - '/public/base/gcc') - def do_submit(self, _subcmd, opts, *args): - """${cmd_name}: submit tag to gerrit and trigger building in OBS - - Usage: - gbs submit -m [options] - - Examples: - gbs submit -m 'release for 0.1' - gbs submit -c -m 'release for 0.2' - gbs submit -m 'release for 0.3' -s - gbs submit -r ssh://user@review.tizen.org:29418/public/base/gcc\ - -m 'release for 0.4' - - ${cmd_option_list} - """ - - from gitbuildsys import cmd_submit as cmd - cmd.do(opts, args) - - @cmdln.alias('ex') - @cmdln.option('-o', '--outdir', - default=None, - dest='outdir', - help='output directory') - @cmdln.option('--spec', - default=None, - dest='spec', - help='specify a spec file to use') - @cmdln.option('-c', '--commit', - default=None, - dest='commit', - help='specify a commit ID to export') - @cmdln.option('--include-all', - action='store_true', - default=False, - dest='include_all', - help='uncommitted changes and untracked files would be '\ - 'included while generating tar ball') - @cmdln.option('--source-rpm', - action='store_true', - default=False, - dest='source_rpm', - help='generate source rpm') - @cmdln.option('--upstream-branch', - default=None, - dest='upstream_branch', - help='upstream branch') - @cmdln.option('--upstream-tag', - default=None, - dest='upstream_tag', - help="upstream tag format, '${upstreamversion}' is "\ - "expanded to the version in the spec file. "\ - "E.g. 'v${upstreamversion}'") - @cmdln.option('--squash-patches-until', - default=None, - dest='squash_patches_until', - help="when generating patches, squash patches up to given "\ - "commit-ish into one monolithic diff file. Format is "\ - "the commit-ish optionally followed by a colon and "\ - "diff filename base.") - def do_export(self, _subcmd, opts, *args): - """${cmd_name}: export files and prepare for build - - Usage: - gbs export - - ${cmd_option_list} - """ - - from gitbuildsys import cmd_export as cmd - cmd.do(opts, args) - - @cmdln.alias('lb') - @cmdln.option('-D', '--dist', - default=None, - dest='dist', - help='specify distribution configuration file, which should ' \ - 'be a full path') - @cmdln.option('-R', '--repository', - action="callback", - default=None, - type='string', - dest='repositories', - callback=handle_repository, - help='specify package repositories, only rpm-md format ' \ - 'is supported') - @cmdln.option('-B', '--buildroot', - default=None, - dest='buildroot', - help='specify build root to setup chroot environment. '\ - 'By default, ~/GBS-ROOT/ will be used, and if no ' \ - '-B option, but TIZEN_BUILD_ROOT env exists, then '\ - '${TIZEN_BUILD_ROOT} will used as build root') - @cmdln.option('-A', '--arch', - default=None, - dest='arch', - help='build target arch ') - @cmdln.option('-C', '--clean', - action='store_true', - default=False, - dest='clean', - help='delete old build root before initialization') - @cmdln.option('--ccache', - action="store_true", - default=False, - dest='ccache', - help='use ccache to speed up rebuilds') - @cmdln.option('--skip-conf-repos', - action="store_true", - default=False, - dest='skip_conf_repos', - help='skip repositories mentioned in config file') - @cmdln.option('-c', '--commit', - default=None, - dest='commit', - help='specify a commit ID to build') - @cmdln.option('--spec', - default=None, - dest='spec', - help='specify a spec file to use') - @cmdln.option('--extra-packs', - default=None, - dest='extra_packs', - help='specify extra packages to install to build root '\ - 'multiple packages can be separated by comma') - @cmdln.option('--include-all', - action='store_true', - default=False, - dest='include_all', - help='uncommitted changes and untracked files would be '\ - 'included while generating tar ball') - @cmdln.option('--upstream-branch', - default=None, - dest='upstream_branch', - help='upstream branch') - @cmdln.option('--upstream-tag', - default=None, - dest='upstream_tag', - help="upstream tag format, '${upstreamversion}' is "\ - "expanded to the version in the spec file. "\ - "E.g. 'v${upstreamversion}'") - @cmdln.option('--squash-patches-until', - default=None, - dest='squash_patches_until', - help="when generating patches, squash patches up to given "\ - "commit-ish into one monolithic diff file. Format is "\ - "the commit-ish optionally followed by a colon and "\ - "diff filename base.") + parser.add_argument('path', type=os.path.abspath, + help='path to spec, srcrpm or tarball') + + parser.add_argument('--author-name', help='author name of git commit') + parser.add_argument('--author-email', help='author email of git commit') + parser.add_argument('--upstream_branch', default='upstream', + help='specify upstream branch for new package version') + parser.add_argument('--no-merge', action='store_true', + help='don\'t merge new upstream branch to master') + + parser.set_defaults(alias="im") + return parser + +@subparser +def export_parser(parser): + """export files and prepare for build + Examples: + $ gbs export --spec packaging/my.spec --commit d64065c + $ gbs export --source-rpm -o /tmp/ + $ gbs export --include-all + """ + + parser.add_argument('gitdir', nargs='?', type=os.path.abspath, + default=os.getcwd(), + help='path to git repository') + + parser.add_argument('-o', '--outdir', help='output directory') + parser.add_argument('--spec', help='specify a spec file to use') + parser.add_argument('-c', '--commit', help='specify a commit ID to export') + parser.add_argument('--include-all', action='store_true', + help='uncommitted changes and untracked files ' + 'would be included while generating tar ball') + parser.add_argument('--source-rpm', action='store_true', + help='generate source rpm') + parser.add_argument('--upstream-branch', help='upstream branch') + parser.add_argument('--upstream-tag', + help="upstream tag format, '${upstreamversion}' is " + 'expanded to the version in the spec file. ' + "E.g. 'v${upstreamversion}'") + parser.add_argument('--squash-patches-until', + help='when generating patches, squash patches up ' + 'to given commit-ish into one monolithic diff file. ' + 'Format is the commit-ish optionally followed by a ' + 'colon and diff filename base.') + + parser.set_defaults(alias="ex") + return parser + +@subparser +def build_parser(parser): + """local build package + Examples: + $ mkdir tizen-packages + $ cp package1 package2 package3 ... tizen-packages/ + $ gbs build -A ia32 tizen-packages # build all packages from tizen-packages + $ cd tizen-packages/ + $ gbs build -A ia32 # build all packages under current dir + $ gbs build -A ia32 --overwrite --include-all + $ gbs build -A i586 --threads=2 + $ gbs build -A i586 --threads=2 --exclude=dlog --exclude=eglibc + $ gbs build -A i586 --threads=4 --binary-list=/path/to/pkgs.list + $ cd package1/ + $ gbs build -A i586 --incremental # only support build one package + """ + + parser.add_argument('gitdir', nargs='?', type=os.path.abspath, + default=os.getcwd(), + help='path to git repository') + + parser.add_argument('-D', '--dist', + help='specify distribution configuration file, ' + 'which should be a full path') + parser.add_argument('-R', '--repository', dest='repositories', + action="append", help='specify package repositories, ' + 'only rpm-md format is supported') + parser.add_argument('-B', '--buildroot', + help='specify build root to setup chroot environment. ' + 'By default, ~/GBS-ROOT/ will be used, and if no ' + '-B option, but TIZEN_BUILD_ROOT env exists, then ' + '${TIZEN_BUILD_ROOT} will used as build root') + parser.add_argument('-A', '--arch', help='build target arch ') + parser.add_argument('-C', '--clean', action='store_true', + help='delete old build root before initialization') + parser.add_argument('--ccache', action="store_true", + help='use ccache to speed up rebuilds') + parser.add_argument('--skip-conf-repos', action="store_true", + help='skip repositories mentioned in config file') + parser.add_argument('-c', '--commit', help='specify a commit ID to build') + parser.add_argument('--spec', help='specify a spec file to use') + parser.add_argument('--extra-packs', + help='specify extra packages to install to build root ' + 'multiple packages can be separated by comma') + parser.add_argument('--include-all', action='store_true', + help='uncommitted changes and untracked files would be ' + 'included while generating tar ball') + parser.add_argument('--upstream-branch', help='upstream branch') + parser.add_argument('--upstream-tag', + help="upstream tag format, '${upstreamversion}' is " + "expanded to the version in the spec file. " + "E.g. 'v${upstreamversion}'") + parser.add_argument('--squash-patches-until', + help='when generating patches, squash patches up ' + 'to given commit-ish into one monolithic diff file. ' + 'Format is the commit-ish optionally followed by a ' + 'colon and diff filename base.') # depanneur special options - @cmdln.option('--clean-once', - action='store_true', - default=False, - dest='clean_once', - help='clean the build environment only once when you start '\ - 'building multiple packages, after that use existing '\ - 'environment for all packages.') - @cmdln.option('--overwrite', - action='store_true', - default=False, - dest='overwrite', - help='overwrite existing binaries and build them anyway') - @cmdln.option('--incremental', - action='store_true', - default=False, - dest='incremental', - help='build a package from the local git tree incremental.' \ - 'If the build fails, changes can be done directly to ' \ - 'the source and build can continue from where it ' \ - 'stopped') - @cmdln.option('--debug', - action='store_true', - default=False, - dest='debug', - help='debug output') - @cmdln.option('--binary-list', - default=None, - dest='binary_list', - help='specify a binary list file. Packages listed in '\ - 'this file will be selected to be built. The format '\ - 'of binary-list file is one package for one line, '\ + parser.add_argument('--clean-once', action='store_true', + help='clean the build environment only once when you ' + 'start building multiple packages, after that use ' + 'existing environment for all packages.') + parser.add_argument('--overwrite', action='store_true', + help='overwrite existing binaries and build ' + 'them anyway') + parser.add_argument('--incremental', action='store_true', + help='build a package from the local git tree ' + 'incremental. If the build fails, changes can be done ' + 'directly to the source and build can continue from ' + 'where it stopped') + parser.add_argument('--debug', action='store_true', help='debug output') + parser.add_argument('--binary-list', + help='specify a binary list file. Packages listed in ' + 'this file will be selected to be built. The format ' + 'of binary-list file is one package for one line, ' 'and only binary RPM name is accepted') - @cmdln.option('--threads', - default=1, - dest='threads', - help='number of threads to build package in parallel') - @cmdln.option('--exclude', - action="append", - default=None, - type="string", - dest='exclude', - help='specify a package to be excluded to be built') - @cmdln.option('--exclude-from-file', - default=None, - dest='exclude_from_file', - help='specify an exclude package list text file, the '\ - 'format is one package in one line, and only binary '\ - 'RPM package name is accepted. Packages listed in '\ - 'this file will be skipped to be built.') - @cmdln.option('--keepgoing', - action='store_true', - default=False, - dest='keepgoing', - help='if a package build fails, do not abort and continue '\ - 'building other packages in the queue') - @cmdln.option('--no-configure', - action='store_true', - default=False, - dest='no_configure', - help='this option disables running configure scripts and auto '\ - 'generation of auto-tools to make incremental build ' \ - 'possible. This requires the configure scripts in the '\ - 'spec to be refereneced using the %configure, %reconfigre '\ - 'and %autogen macros') - - def do_build(self, _subcmd, opts, *args): - """${cmd_name}: local build package - - Usage: - gbs build -R repository [options] [package git dir] - - [package git dir] is optional, if not specified, current dir would - be used, and all packages in this dir would be scheduled to be built. - - Examples: - $ mkdir tizen-packages - $ cp package1 package2 package3 ... tizen-packages/ - $ gbs build -A ia32 tizen-packages # build all packages under tizen-packages - $ cd tizen-packages/ - $ gbs build -A ia32 # build all packages under current dir - $ gbs build -A ia32 --overwrite --include-all - $ gbs build -A i586 --threads=2 - $ gbs build -A i586 --threads=2 --exclude=dlog --exclude=eglibc - $ gbs build -A i586 --threads=4 --binary-list=/path/to/pkgs.list - $ cd package1/ - $ gbs build -A i586 --incremental # only support build one package - - ${cmd_option_list} - """ - - from gitbuildsys import cmd_build as cmd - cmd.do(opts, args) - - @cmdln.alias('ch') - @cmdln.option('-r', '--root', - action='store_true', - default=False, - dest='root', - help='chroot as root instead of abuild by default') - def do_chroot(self, subcmd, opts, *args): - """${cmd_name}: chroot to build root - - Usage: - gbs chroot [options] - - Note: The default location of build root located at: - ~/GBS-ROOT/local/scratch.{arch}.*, which will be different - if -B option specified while running gbs build - - ${cmd_option_list} - """ - - from gitbuildsys import cmd_chroot as cmd - cmd.do(opts, args) - - @cmdln.alias('rb') - @cmdln.option('-T', '--target-obsprj', - action='callback', - default=None, - dest='target_obsprj', - type='string', - callback=handle_project, - help='OBS project where package will be checked in ' \ - '(default is home::gbs:Tizen:Main)') - @cmdln.option('-B', '--base-obsprj', - action='callback', - default=None, - dest='base_obsprj', - type='string', - callback=handle_project, - help='OBS project to branch from (default is Tizen:Main)') - @cmdln.option('--spec', - default=None, - dest='spec', - help='specify a spec file to use') - @cmdln.option('-c', '--commit', - default=None, - dest='commit', - help='specify a commit ID to build') - @cmdln.option('--buildlog', - action='store_true', - default=False, - dest='buildlog', - help='get buildlog from build sever') - @cmdln.option('--status', - action='store_true', - default=False, - dest='status', - help='get build status from build server') - @cmdln.option('--include-all', - action='store_true', - default=False, - dest='include_all', - help='uncommitted changes and untracked files will be '\ - 'included while generating tar ball') - @cmdln.option('--upstream-branch', - default=None, - dest='upstream_branch', - help='upstream branch') - @cmdln.option('--upstream-tag', - default=None, - dest='upstream_tag', - help="upstream tag format, '${upstreamversion}' is "\ - "expanded to the version in the spec file. "\ - "E.g. 'v${upstreamversion}'") - @cmdln.option('--squash-patches-until', - default=None, - dest='squash_patches_until', - help="when generating patches, squash patches up to given "\ - "commit-ish into one monolithic diff file. Format is "\ - "the commit-ish optionally followed by a colon and "\ - "diff filename base.") - def do_remotebuild(self, subcmd, opts, *args): - """${cmd_name}: remote build package - - Usage: - gbs remotebuild [options] [package git dir] \ -[--buildlog repo arch] [--status] - - [package git dir] is optional, if not specified, current dir would - be used. - - Examples: - $ gbs remotebuild - $ gbs remotebuild -B Test - $ gbs remotebuild -B Test -T home::gbs - $ gbs remotebuild - - ${cmd_option_list} - """ - - from gitbuildsys import cmd_remotebuild as cmd - cmd.do(opts, args) - - - @cmdln.alias('im') - @cmdln.option('--author-name', - default=None, - dest='author_name', - help='author name of git commit') - @cmdln.option('--author-email', - default=None, - dest='author_email', - help='author email of git commit') - @cmdln.option('--upstream_branch', - default='upstream', - dest='upstream_branch', - help='specify upstream branch for new version of package') - @cmdln.option('--no-merge', - action='store_true', - default=False, - dest='no_merge', - help='don\'t merge new upstream branch to master') - def do_import(self, subcmd, opts, *args): - """${cmd_name}: import spec file/source rpm/tar ball to git repository - - Usage: - gbs import [options] specfile | source rpm | tar ball - - Examples: - $ gbs import /path/to/specfile/ - $ gbs import /path/to/src.rpm - $ gbs import /path/to/tarball - - ${cmd_option_list} - """ - - from gitbuildsys import cmd_import as cmd - cmd.do(opts, args) - - - @cmdln.alias('ch') - @cmdln.option('-s', '--since', - default=None, - dest='since', - help='commit to start from') - @cmdln.option('-m', '--message', - default=None, - dest='message', - help='use given message as the changelog entry') - def do_changelog(self, _subcmd, opts, *args): - """${cmd_name}: update the changelog file with the git commit messages - - Usage: - gbs changelog [options] - - Examples: - $ gbs changelog - $ gbs changelog --since=COMMIT_ID - $ gbs changelog -m 'new upstream release 0.0.1' - - ${cmd_option_list} - """ - - from gitbuildsys import cmd_changelog as cmd - cmd.do(opts, args) - - @cmdln.hide() - def do_man(self, argv): - """${cmd_name}: generates a man page - - usage: - ${name} man - """ - return cmdln.Cmdln.do_man(self, argv) + parser.add_argument('--threads', type=int, default=1, + help='number of threads to build package in parallel') + parser.add_argument('--exclude', action="append", + help='specify a package to be excluded to be built') + parser.add_argument('--exclude-from-file', + help='specify an exclude package list text file, the ' + 'format is one package in one line, and only binary ' + 'RPM package name is accepted. Packages listed in ' + 'this file will be skipped to be built.') + parser.add_argument('--keepgoing', action='store_true', + help='if a package build fails, do not abort and ' + 'continue building other packages in the queue') + parser.add_argument('--no-configure', action='store_true', + help='this option disables running configure scripts ' + 'and auto generation of auto-tools to make incremental ' + 'build possible. This requires the configure scripts ' + 'in the spec to be refereneced using the %%configure, ' + '%%reconfigre and %%autogen macros') + + parser.set_defaults(alias="lb") + return parser + +@subparser +def remotebuild_parser(parser): + """remote build package + Examples: + $ gbs remotebuild + $ gbs remotebuild -B Test + $ gbs remotebuild -B Test -T home::gbs + $ gbs remotebuild + """ + + parser.add_argument('gitdir', nargs='?', type=os.path.abspath, + default=os.getcwd(), + help='path to git repository') + + parser.add_argument('-T', '--target-obsprj', + help='OBS project where package will be checked in ' + '(default is home::gbs:Tizen:Main)') + parser.add_argument('-B', '--base-obsprj', default="Tizen:Main", + help='OBS project to branch from') + parser.add_argument('--spec', help='specify a spec file to use') + parser.add_argument('-c', '--commit', help='specify a commit ID to build') + parser.add_argument('--buildlog', action='store_true', + help='get buildlog from build sever') + parser.add_argument('--status', action='store_true', + help='get build status from build server') + parser.add_argument('-R', '--repository', + help='OBS repository for --buildlog') + parser.add_argument('-A', '--arch', + help='OBS build architecture for --buildlog') + parser.add_argument('--include-all', action='store_true', + help='uncommitted changes and untracked files will be ' + 'included while generating tar ball') + parser.add_argument('--upstream-branch', help='upstream branch') + parser.add_argument('--upstream-tag', + help="upstream tag format, '${upstreamversion}' is " + "expanded to the version in the spec file. " + "E.g. 'v${upstreamversion}'") + parser.add_argument('--squash-patches-until', + help='when generating patches, squash patches up to ' + 'given commit-ish into one monolithic diff file. ' + 'Format is the commit-ish optionally followed by a ' + 'colon and diff filename base.') + + parser.set_defaults(alias="rb") + return parser + +@subparser +def chroot_parser(parser): + """chroot to build root + Examples: + $ gbs chroot /var/tmp/mybuildroot + $ gbs chroot --root /var/tmp/mybuildroot + + Note: The default location of build root located at: + ~/GBS-ROOT/local/scratch.{arch}.*, which will be different + if -B option specified while running gbs build + """ + + parser.add_argument('buildroot', type=os.path.abspath, + help='path to build root') + + parser.add_argument('-r', '--root', action='store_true', + help='chroot as root instead of abuild by default') + + parser.set_defaults(alias="chr") + return parser + +@subparser +def changelog_parser(parser): + """update the changelog file with the git commit messages + Examples: + $ gbs changelog + $ gbs changelog --since=COMMIT_ID + $ gbs changelog -m 'new upstream release 0.0.1' + """ + + parser.add_argument('gitdir', nargs='?', type=os.path.abspath, + default=os.getcwd(), + help='path to git repository') + + parser.add_argument('-s', '--since', + help='commit to start from') + parser.add_argument('-m', '--message', + help='use given message as the changelog entry') + parser.set_defaults(alias='ch') + return parser + +@subparser +def submit_parser(parser): + """submit tag to gerrit and trigger building in OBS + Examples: + $ gbs submit -m 'release for 0.1' + $ gbs submit -c -m 'release for 0.2' + $ gbs submit -m 'release for 0.3' -s + $ gbs submit -r ssh://user@review.tizen.org:29418/public/base/gcc -m 'release for 0.4' + """ + + parser.add_argument('gitdir', nargs='?', type=os.path.abspath, + default=os.getcwd(), + help='path to git repository') + + parser.add_argument('-m', '--msg', required=True, + help='specify tag message info') + parser.add_argument('-c', '--commit', default='HEAD', + help='specify a commit ID to submit') + parser.add_argument('-s', '--sign', action='store_true', + help='make a GPG-signed tag') + parser.add_argument('-u', '--user-key', + help='using the given key to make a GPG-signed tag') + parser.add_argument('-t', '--target', + help='specify target version to submit, eg: trunk.') + parser.add_argument('-r', '--remote', default='origin', + help='specify gerrit project server, default value is ' + 'origin for example:\nssh://user@review.tizen.org:29418' + '/public/base/gcc') + + parser.set_defaults(alias="sr") + return parser + +def main(argv): + """Script entry point.""" + + # Create top level parser + epilog = "Try 'gbs SUBCOMAND --help' for help on a specific subcommand." + description = "gbs - the command line tool for Tizen package developers" + parser = ArgumentParser(description=description, epilog=epilog, + formatter_class=GbsHelpFormatter) + + parser.add_argument('-V', '--version', action='version', + version='%(prog)s ' + __version__) + parser.add_argument('-c', '--conf', help='specify config file for gbs') + parser.add_argument('-d', '--debug', action='store_true', + help='debug output') + parser.add_argument('-v', '--verbose', action='store_true', + help='verbose output') + + # hacked by the request of cmdln lovers + parser.format_usage = parser.format_help + + # Create parsers for subcommands + subparsers = parser.add_subparsers(title='subcommands') + + # collect aliases + aliases = {} + for name, obj in globals().iteritems(): + if name.endswith('_parser') and callable(obj): + aliases[obj(subparsers).get_default('alias')] = name.split('_')[0] + + # replace aliases with real commands + positionals = [(i, arg) for i, arg in enumerate(argv[1:]) \ + if not arg.startswith('-')] + if positionals: + i, cmd = positionals[0] + if cmd in aliases: + argv[i+1] = aliases[cmd] + + # Parse arguments + args = parser.parse_args(argv[1:]) + + # Set log level for --debug and --verbose + if args.verbose: + msger.set_loglevel('verbose') + + if args.debug: + msger.set_loglevel('debug') + + # Process configuration file if --conf is used + if args.conf: + from gitbuildsys.conf import configmgr + configmgr.reset_from_conf(args.conf) + + # Import target module and call 'main' from it + module = __import__("gitbuildsys.%s" % args.module, fromlist=[args.module]) + return module.main(args) if __name__ == '__main__': try: - sys.exit(Gbs().main()) - + sys.exit(main(sys.argv)) except KeyboardInterrupt: msger.error('\n^C caught, program aborted.') -- 2.7.4