1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461
|
# Part of the A-A-P recipe executive: process the command line arguments.
# Copyright (C) 2002-2003 Stichting NLnet Labs
# Permission to copy and use this file is specified in the file COPYING.
# If this file is missing you can find it here: http://www.a-a-p.org/COPYING
# The arguments come in three catogeries
# - options
# start with a dash: in the form "-v", "--version", "-f foo".
# - variable assignments
# contain an equal sign: "foo=asdf"
# - targets
# the rest
# The code for handing options originally comes from SCons.
import string
import getopt
from Args import Args
from Error import *
from AapVersion import *
import Global
#
# function called for -v and --version
#
def opt_version(opt, arg):
print _("A-A-P recipe executive version %s; released %s %s GMT") \
% (version_string, version_date, version_time)
arg = arg # avoid PyChecker warning
opt = opt # avoid PyChecker warning
raise NormalExit
#
# function called for -h and --help
#
def opt_help(opt, arg):
global option_list
help_opts = filter(lambda x: x.helpline, option_list)
print _("Usage: aap [OPTION] [VAR=VALUE] [TARGET] ...\n") \
+ _("Options:\n") \
+ string.join(map(lambda x: x.helpline, help_opts), "\n") + "\n"
arg = arg # avoid PyChecker warning
opt = opt # avoid PyChecker warning
raise NormalExit
#
# function called for --changed=FILE
#
def opt_changed(opt, arg):
from Sign import sign_clear_file
sign_clear_file(arg, 1)
opt = opt # avoid PyChecker warning
#
# The following variables are filled with all the possible options.
#
option_list = [] # list of all Option objects
short_opts = "" # string of short (single-character) options
long_opts = [] # array of long (--) options
option_dict = {} # mapping of each option string to its Option object
def options_init():
"""Initialize command-line arguments processing.
This is in a function mainly so we can easily single-step over
it in the debugger.
"""
class Option:
"""Class for command-line option information.
This exists to provide a central location for everything
describing a command-line option, so that we can change
options without having to update the code to handle the
option in one place, the -h help message in another place,
etc. There are no methods here, only attributes.
You can initialize an Option with the following:
func The function that will be called when this
option is processed on the command line.
Calling sequence is:
func(opt, arg)
If there is no func, then this Option probably
stores an optstring to be printed.
name The generic option name. Usually either func or name
is used. When a name is specified, the option is stored for
later use.
helpline
The string to be printed in -h output. If no
helpline is specified but a help string is
specified (the usual case), a helpline will be
constructed automatically from the short, long,
arg, and help attributes. (In practice, then,
setting helpline without setting func allows you
to print arbitrary lines of text in the -h
output.)
short The string for short, single-hyphen
command-line options.
Do not include the hyphen:
'a' for -a, 'xy' for -x and -y, etc.
long An array of strings for long, double-hyphen
command-line options. Do not include
the hyphens:
['my-option', 'verbose']
arg If this option takes an argument, this string
specifies how you want it to appear in the
-h output ('DIRECTORY', 'FILE', etc.).
help The help string that will be printed for
this option in the -h output. Must be
49 characters or fewer.
future If non-zero, this indicates that this feature
will be supported in a future release, not
the currently planned one. SCons will
recognize the option, but it won't show up
in the -h output.
The following attribute is derived from the supplied attributes:
optstring
A string, with hyphens, describing the flags
for this option, as constructed from the
specified short, long and arg attributes.
All Option objects are stored in the global option_list list,
in the order in which they're created. This is the list
that's used to generate -h output, so the order in which the
objects are created is the order in which they're printed.
"""
def __init__(self,
func = None,
name = None,
helpline = None,
short = None,
long = None,
arg = None,
append = 0,
help = None,
future = None):
self.func = func
self.name = name
self.short = short
self.long = long
self.arg = arg
self.append = append
self.help = help
# process the short and long option names to create a help line.
opts = []
if self.short:
for c in self.short:
if arg:
c = c + " " + arg
opts = opts + ['-' + c]
if self.long:
l = self.long
if arg:
l = map(lambda x,a=arg: x + "=" + a, self.long)
opts = opts + map(lambda x: '--' + x, l)
self.optstring = string.join(opts, ', ')
if helpline:
self.helpline = helpline
elif help and not future:
if len(self.optstring) <= 26:
sep = " " * (28 - len(self.optstring))
else:
sep = self.helpstring = "\n" + " " * 30
self.helpline = " " + self.optstring + sep + self.help
else:
self.helpline = None
# Add the newly created Option object to the list of objects.
global option_list
option_list.append(self)
# In the following instantiations, the help string should be no
# longer than 49 characters. Use the following as a guide:
# help = _("1234567890123456789012345678901234567890123456789")
Option(func = opt_version,
short = 'V', long = ['version'],
help = _("Print version information and exit"))
Option(func = opt_help,
short = 'h', long = ['help'],
help = _("Print help message (this one) and exit"))
Option(name = "verbose",
short = 'v', long = ['verbose'],
help = _("Print more information"))
Option(name = "silent",
short = 's', long = ['silent'],
help = _("Print less information"))
Option(name = "debug",
short = 'd', long = ['debug'], arg = 'FLAGS',
help = _("Debug the specified items"))
Option(name = "profile",
long = ['profile'], arg = 'FILE',
help = _("Profile A-A-P execution and write results in FILE"))
Option(name = "nobuild",
short = 'n', long = ['nobuild'],
help = _("Print the build commands but do not execute them"))
Option(func = opt_changed,
long = ['changed'], arg = 'FILE',
help = _("Consider FILE changed"))
Option(name = "touch",
short = 't', long = ['touch'],
help = _("Update target signatures, do not build"))
Option(name = "force",
short = 'F', long = ['force'],
help = _("Force rebuilding"))
Option(name = "contents",
short = 'C', long = ['contents'],
help = _("Only build when file contents changed"))
Option(name = "command",
short = 'c', long = ['command'], arg = 'CMD', append = 1,
help = _("Execute a command after reading the recipe"))
Option(name = "continue",
short = 'k', long = ['continue'],
help = _("Continue building after an error"))
Option(name = "stop",
short = 'S', long = ['stop'],
help = _("Stop building at first error (default)"))
Option(name = "fetch-recipe",
short = 'R', long = ['fetch-recipe'],
help = _("Fetch recipe file and child recipes"))
Option(name = "nofetch-recipe",
short = 'N', long = ['nofetch-recipe'],
help = _('Do not fetch recipes for "fetch" target'))
Option(name = "nocache",
short = 'a', long = ['nocache'],
help = _("Always download files, don't use the cache"))
Option(name = "local",
short = 'l', long = ['local'],
help = _("Do not recurse into subdirectories"))
Option(name = "jobs",
short = 'j', long = ['jobs'], arg = 'N',
help = _("Maximum number of parallel jobs"))
Option(name = "search-up",
short = 'u', long = ['search-up', 'up'],
help = _("Search directory tree upwards for main.aap recipe"))
Option(name = "include",
short = 'I', long = ['include'], arg = 'DIR', append = 1,
help = _("Directory to search for included recipes"))
Option(name = "recipe",
short = 'f', long = ['recipe'], arg = 'FILE',
help = _("Recipe file to be executed"))
Option(name = "install",
long = ['install'], arg = 'NAME',
help = _("install package NAME"))
Option(name = "end",
short = '-',
help = _("End of options, targets and assignments follow"))
# Now that all Option objects are created, make the list of short and long
# option names for use with getopt().
# This also makes a dictonary to be able to find each Option object by the
# option name.
global short_opts
global long_opts
global option_dict
for o in option_list:
if o.short:
for c in o.short:
option_dict['-' + c] = o
short_opts = short_opts + o.short
if o.arg:
short_opts = short_opts + ":"
if o.long:
for l in o.long:
option_dict['--' + l] = o
if o.arg:
long_opts = long_opts + map(lambda a: a + "=", o.long)
else:
long_opts = long_opts + o.long
#
# The main function to process the command line arguments.
#
def doargs(argv):
"""
Process the command line arguments "argv".
Returns an Args object with the resuting args and targets.
"""
global short_opts
global long_opts
global option_dict
options_init()
#
# Start with an empty Args object.
#
args = Args()
#
# First extract the options.
#
# It looks like Python 2.0 changed the name of the exception class raised
# by getopt.
try:
getopt_err = getopt.GetoptError
except:
getopt_err = getopt.error
# Loop over the arguments.
# getopt() stops when a non-option is encountered. When a single '-' is
# found this is considered a non-option. "--" is recognized as the final
# option.
# Parse targets and assignments until another option is found.
while argv:
try:
prev_argv = argv
cmd_opts, argv = getopt.getopt(argv, short_opts, long_opts)
except getopt_err, x:
raise UserError, _("Invalid argument: ") + str(x)
else:
# For the recognized options call a function and/or add the
# argument to the argument dictionary for later use.
# Note that a function may cause us to exit!
for opt, arg in cmd_opts:
o = option_dict[opt]
if o.func:
o.func(opt, arg)
if o.name:
if not arg:
arg = 1
if o.append:
if args.options.has_key(o.name):
args.options[o.name].append(arg)
else:
args.options[o.name] = [ arg ]
else:
args.options[o.name] = arg
# Did we encounter "--"?
if not args.options.has_key("end"):
n = len(prev_argv) - len(argv)
if n > 0 and prev_argv[n - 1] == "--":
args.options["end"] = 1
#
# Get variable assignments and targets.
# An argument starting with '-' may be another option, unless "--"
# has been encountered.
#
while argv:
if argv[0] == '-':
raise UserError, _("Invalid argument: - (reading from stdin not implemented yet)")
elif argv[0][0] == '-' and not args.options.has_key("end"):
break
elif '=' in argv[0]:
name, value = string.split(argv[0], '=', 1)
args.values[name] = value
else:
args.targets.append(argv[0])
# Using a "refresh", "fetch" or "update" target implies the
# --fetch-recipe option, unless --nofetch-recipe was used.
if (not args.options.has_key("nofetch-recipe")
and (argv[0] == "refresh"
or argv[0] == "fetch"
or argv[0] == "update")):
args.options["fetch-recipe"] = 1
argv = argv[1:]
return args
def local_arg():
"""Return non-zero if the "-l" or "--local" argument was given. zero
string otherwise."""
if Global.cmd_args.options.has_key("local"):
return 1
return 0
def error_continue():
"""Return TRUE if we are supposed to continue after an error."""
return Global.cmd_args.options.get("continue")
def add_cmdline_settings(recdict):
"""Add the settings from the command line to "recdict"."""
from Util import varchar
for k in Global.cmd_args.values.keys():
# Only add items with a valid variable name.
add = 1
for c in k:
if not varchar(c):
add = 0
break
if add:
recdict[k] = Global.cmd_args.values[k]
# Also add it to the _arg scope, so that we know what was set by
# the user.
recdict["_arg"][k] = Global.cmd_args.values[k]
def copy_global_options(cmd_args_from, cmd_args_to):
"""
Copy global command line options from "cmd_args_from" to "cmd_args_to".
"""
global_options = [
"contents",
"continue",
"force",
"nobuild",
"nocache",
"nofetch-recipe",
"silent",
"stop",
"touch",
"verbose",
]
for k in cmd_args_from.options.keys():
if k in global_options and not cmd_args_to.options.has_key(k):
cmd_args_to.options[k] = cmd_args_from.options[k]
# vim: set sw=4 et sts=4 tw=79 fo+=l:
|