blob: 019c7381b25bb9d49aae6a04fb1c36054db34d69 [file] [log] [blame]
# repoman: Argument parser
# Copyright 2007-2021 Gentoo Authors
# Distributed under the terms of the GNU General Public License v2
"""This module contains functions used in Repoman to parse CLI arguments."""
import argparse
import logging
# import our initialized portage instance
from repoman._portage import portage
from portage import _unicode_decode
from portage import util
def parse_args(argv, repoman_default_opts):
"""Use a customized optionParser to parse command line arguments for repoman
Args:
argv - a sequence of command line arguments
Returns:
(opts, args), just like a call to parser.parse_args()
"""
argv = portage._decode_argv(argv)
modes = {
"commit": "Run a scan then commit changes",
"ci": "Run a scan then commit changes",
"fix": "Fix simple QA issues (stray digests, missing digests)",
"full": "Scan directory tree and print all issues (not a summary)",
"help": "Show this screen",
"manifest": "Generate a Manifest (fetches files if necessary)",
"manifest-check": "Check Manifests for missing or incorrect digests",
"scan": "Scan directory tree for QA issues",
}
output_choices = {
"default": "The normal output format",
"column": "Columnar output suitable for use with grep",
}
mode_keys = list(modes)
mode_keys.sort()
output_keys = sorted(output_choices)
parser = argparse.ArgumentParser(
usage="repoman [options] [mode]",
description="Modes: %s" % " | ".join(mode_keys),
epilog="For more help consult the man page.",
)
parser.add_argument(
"-a",
"--ask",
dest="ask",
action="store_true",
default=False,
help="Request a confirmation before commiting",
)
parser.add_argument(
"-b",
"--bug",
dest="bug",
action="append",
metavar="<BUG-NO|BUG-URL>",
default=[],
help=(
"Mention a Gentoo or upstream bug in the commit footer; "
"takes either Gentoo bug number or full bug URL"
),
)
parser.add_argument(
"-c",
"--closes",
dest="closes",
action="append",
metavar="<PR-NO|PR-URL>",
default=[],
help=(
"Adds a Closes footer to close GitHub pull request (or compatible); "
"takes either GitHub PR number or full PR URL"
),
)
parser.add_argument(
"-m",
"--commitmsg",
dest="commitmsg",
help="specify a commit message on the command line",
)
parser.add_argument(
"-M",
"--commitmsgfile",
dest="commitmsgfile",
help="specify a path to a file that contains a commit message",
)
parser.add_argument(
"--digest",
choices=("y", "n"),
metavar="<y|n>",
help="Automatically update Manifest digests for modified files",
)
parser.add_argument(
"-p",
"--pretend",
dest="pretend",
default=False,
action="store_true",
help="don't commit or fix anything; just show what would be done",
)
parser.add_argument(
"-q",
"--quiet",
dest="quiet",
action="count",
default=0,
help="do not print unnecessary messages",
)
parser.add_argument(
"--echangelog",
choices=("y", "n", "force"),
metavar="<y|n|force>",
help=(
"for commit mode, call echangelog if ChangeLog is unmodified (or "
"regardless of modification if 'force' is specified)"
),
)
parser.add_argument(
"--experimental-inherit",
choices=("y", "n"),
metavar="<y|n>",
default="n",
help=(
"Enable experimental inherit.missing checks which may misbehave"
" when the internal eclass database becomes outdated"
),
)
parser.add_argument(
"--experimental-repository-modules",
choices=("y", "n"),
metavar="<y|n>",
default="n",
help="Enable experimental repository modules",
)
parser.add_argument(
"-f",
"--force",
dest="force",
action="store_true",
default=False,
help="Commit with QA violations",
)
parser.add_argument(
"-S",
"--straight-to-stable",
dest="straight_to_stable",
default=False,
action="store_true",
help="Allow committing straight to stable",
)
parser.add_argument(
"--vcs", dest="vcs", help="Force using specific VCS instead of autodetection"
)
parser.add_argument(
"-v",
"--verbose",
dest="verbosity",
action="count",
help="be very verbose in output",
default=0,
)
parser.add_argument(
"-V", "--version", dest="version", action="store_true", help="show version info"
)
parser.add_argument(
"-x",
"--xmlparse",
dest="xml_parse",
action="store_true",
default=False,
help="forces the metadata.xml parse check to be carried out",
)
parser.add_argument(
"--if-modified",
choices=("y", "n"),
default="n",
metavar="<y|n>",
help="only check packages that have uncommitted modifications",
)
parser.add_argument(
"-i",
"--ignore-arches",
dest="ignore_arches",
action="store_true",
default=False,
help="ignore arch-specific failures (where arch != host)",
)
parser.add_argument(
"--ignore-default-opts",
action="store_true",
help="do not use the REPOMAN_DEFAULT_OPTS environment variable",
)
parser.add_argument(
"-I",
"--ignore-masked",
dest="ignore_masked",
action="store_true",
default=False,
help="ignore masked packages (not allowed with commit mode)",
)
parser.add_argument(
"--include-arches",
dest="include_arches",
metavar="ARCHES",
action="append",
help=(
"A space separated list of arches used to "
"filter the selection of profiles for dependency checks"
),
)
parser.add_argument(
"--include-profiles",
dest="include_profiles",
metavar="PROFILES",
action="append",
help=(
"A space separated list of profiles used to "
"define the selection of profiles for dependency checks"
),
)
parser.add_argument(
"-d",
"--include-dev",
dest="include_dev",
action="store_true",
default=False,
help="include dev profiles in dependency checks",
)
parser.add_argument(
"-e",
"--include-exp-profiles",
choices=("y", "n"),
metavar="<y|n>",
default=False,
help="include exp profiles in dependency checks",
)
parser.add_argument(
"--unmatched-removal",
dest="unmatched_removal",
action="store_true",
default=False,
help=(
"enable strict checking of package.mask and package.unmask files"
" for unmatched removal atoms"
),
)
parser.add_argument(
"--without-mask",
dest="without_mask",
action="store_true",
default=False,
help=(
"behave as if no package.mask entries exist"
" (not allowed with commit mode)"
),
)
parser.add_argument(
"--output-style",
dest="output_style",
choices=output_keys,
help="select output type",
default="default",
)
parser.add_argument(
"-j",
"--jobs",
dest="jobs",
action="store",
type=int,
default=1,
help="Specifies the number of jobs (processes) to run simultaneously.",
)
parser.add_argument(
"-l",
"--load-average",
dest="load_average",
action="store",
type=float,
default=None,
help="Specifies that no new jobs (processes) should be started if there are others "
"jobs running and the load average is at least load (a floating-point number).",
)
parser.add_argument(
"--mode",
dest="mode",
choices=mode_keys,
help="specify which mode repoman will run in (default=full)",
)
# Modes help is included earlier, in the parser description.
parser.add_argument(
"mode_positional",
nargs="?",
metavar="mode",
choices=mode_keys,
help=argparse.SUPPRESS,
)
opts = parser.parse_args(argv[1:])
if not opts.ignore_default_opts:
default_opts = util.shlex_split(repoman_default_opts)
if default_opts:
opts = parser.parse_args(default_opts + argv[1:])
args = []
if opts.mode is not None:
args.append(opts.mode)
if opts.mode_positional is not None:
args.append(opts.mode_positional)
if len(set(args)) > 1:
parser.error("multiple modes specified: %s" % " ".join(args))
opts.mode = args[0] if args else None
if opts.mode == "help":
parser.print_help()
parser.exit()
if not opts.mode:
opts.mode = "full"
if opts.mode == "ci":
opts.mode = "commit" # backwards compat shortcut
# Use verbosity and quiet options to appropriately fiddle with the loglevel
for val in range(opts.verbosity):
logger = logging.getLogger()
logger.setLevel(logger.getEffectiveLevel() - 10)
for val in range(opts.quiet):
logger = logging.getLogger()
logger.setLevel(logger.getEffectiveLevel() + 10)
if opts.mode == "commit" and opts.commitmsg:
opts.commitmsg = _unicode_decode(opts.commitmsg)
if opts.mode == "commit" and not (opts.force or opts.pretend):
if opts.ignore_masked:
opts.ignore_masked = False
logging.warn("Commit mode automatically disables --ignore-masked")
if opts.without_mask:
opts.without_mask = False
logging.warn("Commit mode automatically disables --without-mask")
return (opts, args)