File: DoArgs.py

package info (click to toggle)
aap 1.072-1.1
  • links: PTS
  • area: main
  • in suites: etch, etch-m68k, lenny
  • size: 4,976 kB
  • ctags: 2,160
  • sloc: python: 15,113; makefile: 62; sh: 13
file content (461 lines) | stat: -rw-r--r-- 15,741 bytes parent folder | download | duplicates (2)
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: