Esempio n. 1
0
def globpattern(dir, pattern):
    """
    Return leaf names in the specified directory which match the pattern.
    """

    if not hasglob(pattern):
        if pattern == '':
            if os.path.isdir(dir):
                return ['']
            return []

        if os.path.exists(util.normaljoin(dir, pattern)):
            return [pattern]
        return []

    leaves = os.listdir(dir) + ['.', '..']

    # "hidden" filenames are a bit special
    if not pattern.startswith('.'):
        leaves = [leaf for leaf in leaves
                  if not leaf.startswith('.')]

    leaves = fnmatch.filter(leaves, pattern)
    leaves = filter(lambda l: os.path.exists(util.normaljoin(dir, l)), leaves)

    leaves.sort()
    return leaves
def globpattern(dir, pattern):
    """
    Return leaf names in the specified directory which match the pattern.
    """

    if not hasglob(pattern):
        if pattern == '':
            if os.path.isdir(dir):
                return ['']
            return []

        if os.path.exists(util.normaljoin(dir, pattern)):
            return [pattern]
        return []

    leaves = os.listdir(dir) + ['.', '..']

    # "hidden" filenames are a bit special
    if not pattern.startswith('.'):
        leaves = [leaf for leaf in leaves if not leaf.startswith('.')]

    leaves = fnmatch.filter(leaves, pattern)
    leaves = [l for l in leaves if os.path.exists(util.normaljoin(dir, l))]

    leaves.sort()
    return leaves
def glob(fsdir, path):
    """
    Yield paths matching the path glob. Sorts as a bonus. Excludes '.' and '..'
    """

    dir, leaf = os.path.split(path)
    if dir == '':
        return globpattern(fsdir, leaf)

    if hasglob(dir):
        dirsfound = glob(fsdir, dir)
    else:
        dirsfound = [dir]

    r = []

    for dir in dirsfound:
        fspath = util.normaljoin(fsdir, dir)
        if not os.path.isdir(fspath):
            continue

        r.extend((util.normaljoin(dir, found)
                  for found in globpattern(fspath, leaf)))

    return r
Esempio n. 4
0
 def resolve(self, makefile, variables, fd, setting):
     assert os.path.isabs(makefile.workdir)
     fd.write(' '.join([
         util.normaljoin(makefile.workdir, path).replace('\\', '/')
         for path in self._arguments[0].resolvesplit(
             makefile, variables, setting)
     ]))
Esempio n. 5
0
def call(cline, env, cwd, loc, cb, context, echo, justprint=False):
    #TODO: call this once up-front somewhere and save the result?
    shell, msys = util.checkmsyscompat()

    shellreason = None
    if msys and cline.startswith('/'):
        shellreason = "command starts with /"
    else:
        argv, badchar = clinetoargv(cline)
        if argv is None:
            shellreason = "command contains shell-special character '%s'" % (
                badchar, )
        elif len(argv) and argv[0] in shellwords:
            shellreason = "command starts with shell primitive '%s'" % (
                argv[0], )

    if shellreason is not None:
        _log.debug("%s: using shell: %s: '%s'", loc, shellreason, cline)
        if msys:
            if len(cline) > 3 and cline[1] == ':' and cline[2] == '/':
                cline = '/' + cline[0] + cline[2:]
            cline = [shell, "-c", cline]
        context.call(cline,
                     shell=not msys,
                     env=env,
                     cwd=cwd,
                     cb=cb,
                     echo=echo,
                     justprint=justprint)
        return

    if not len(argv):
        cb(res=0)
        return

    if argv[0] == command.makepypath:
        command.main(argv[1:], env, cwd, cb)
        return

    if argv[0:2] == [
            sys.executable.replace('\\', '/'),
            command.makepypath.replace('\\', '/')
    ]:
        command.main(argv[2:], env, cwd, cb)
        return

    if argv[0].find('/') != -1:
        executable = util.normaljoin(cwd, argv[0])
    else:
        executable = None

    context.call(argv,
                 executable=executable,
                 shell=False,
                 env=env,
                 cwd=cwd,
                 cb=cb,
                 echo=echo,
                 justprint=justprint)
Esempio n. 6
0
def glob(fsdir, path):
    """
    Yield paths matching the path glob. Sorts as a bonus. Excludes '.' and '..'
    """

    dir, leaf = os.path.split(path)
    if dir == '':
        return globpattern(fsdir, leaf)

    if hasglob(dir):
        dirsfound = glob(fsdir, dir)
    else:
        dirsfound = [dir]

    r = []

    for dir in dirsfound:
        fspath = util.normaljoin(fsdir, dir)
        if not os.path.isdir(fspath):
            continue

        r.extend((util.normaljoin(dir, found) for found in globpattern(fspath, leaf)))

    return r
Esempio n. 7
0
def call(cline, env, cwd, loc, cb, context, echo, justprint=False):
    #TODO: call this once up-front somewhere and save the result?
    shell, msys = util.checkmsyscompat()

    shellreason = None
    if msys and cline.startswith('/'):
        shellreason = "command starts with /"
    else:
        argv, badchar = clinetoargv(cline, blacklist_gray=True)
        if argv is None:
            shellreason = "command contains shell-special character '%s'" % (badchar,)
        elif len(argv) and argv[0] in shellwords:
            shellreason = "command starts with shell primitive '%s'" % (argv[0],)
        else:
            argv = doglobbing(argv, cwd)

    if shellreason is not None:
        _log.debug("%s: using shell: %s: '%s'", loc, shellreason, cline)
        if msys:
            if len(cline) > 3 and cline[1] == ':' and cline[2] == '/':
                cline = '/' + cline[0] + cline[2:]
        cline = [shell, "-c", cline]
        context.call(cline, shell=False, env=env, cwd=cwd, cb=cb, echo=echo,
                     justprint=justprint)
        return

    if not len(argv):
        cb(res=0)
        return

    if argv[0] == command.makepypath:
        command.main(argv[1:], env, cwd, cb)
        return

    if argv[0:2] == [sys.executable.replace('\\', '/'),
                     command.makepypath.replace('\\', '/')]:
        command.main(argv[2:], env, cwd, cb)
        return

    if argv[0].find('/') != -1:
        executable = util.normaljoin(cwd, argv[0])
    else:
        executable = None

    context.call(argv, executable=executable, shell=False, env=env, cwd=cwd, cb=cb,
                 echo=echo, justprint=justprint)
Esempio n. 8
0
def prepare_command(cline, cwd, loc):
    """
    Returns a list of command and arguments for the given command line string.
    If the command needs to be run through a shell for some reason, the
    returned list contains the shell invocation.
    """

    #TODO: call this once up-front somewhere and save the result?
    shell, msys = util.checkmsyscompat()

    shellreason = None
    executable = None
    if msys and cline.startswith('/'):
        shellreason = "command starts with /"
    else:
        argv, badchar = clinetoargv(cline, cwd)
        if argv is None:
            shellreason = "command contains shell-special character '%s'" % (
                badchar, )
        elif len(argv) and argv[0] in shellwords:
            shellreason = "command starts with shell primitive '%s'" % (
                argv[0], )
        elif argv and (os.sep in argv[0]
                       or os.altsep and os.altsep in argv[0]):
            executable = util.normaljoin(cwd, argv[0])
            # Avoid "%1 is not a valid Win32 application" errors, assuming
            # that if the executable path is to be resolved with PATH, it will
            # be a Win32 executable.
            if sys.platform == 'win32' and os.path.isfile(executable) and open(
                    executable, 'rb').read(2) == "#!":
                shellreason = "command executable starts with a hashbang"

    if shellreason is not None:
        _log.debug("%s: using shell: %s: '%s'", loc, shellreason, cline)
        if msys:
            if len(cline) > 3 and cline[1] == ':' and cline[2] == '/':
                cline = '/' + cline[0] + cline[2:]
        argv = [shell, "-c", cline]
        executable = None

    return executable, argv
Esempio n. 9
0
def prepare_command(cline, cwd, loc):
    """
    Returns a list of command and arguments for the given command line string.
    If the command needs to be run through a shell for some reason, the
    returned list contains the shell invocation.
    """

    #TODO: call this once up-front somewhere and save the result?
    shell, msys = util.checkmsyscompat()

    shellreason = None
    executable = None
    if msys and cline.startswith('/'):
        shellreason = "command starts with /"
    else:
        argv, badchar = clinetoargv(cline, cwd)
        if argv is None:
            shellreason = "command contains shell-special character '%s'" % (badchar,)
        elif len(argv) and argv[0] in shellwords:
            shellreason = "command starts with shell primitive '%s'" % (argv[0],)
        elif argv and (os.sep in argv[0] or os.altsep and os.altsep in argv[0]):
            executable = util.normaljoin(cwd, argv[0])
            # Avoid "%1 is not a valid Win32 application" errors, assuming
            # that if the executable path is to be resolved with PATH, it will
            # be a Win32 executable.
            if sys.platform == 'win32' and os.path.isfile(executable) and open(executable, 'rb').read(2) == "#!":
                shellreason = "command executable starts with a hashbang"

    if shellreason is not None:
        _log.debug("%s: using shell: %s: '%s'", loc, shellreason, cline)
        if msys:
            if len(cline) > 3 and cline[1] == ':' and cline[2] == '/':
                cline = '/' + cline[0] + cline[2:]
        argv = [shell, "-c", cline]
        executable = None

    return executable, argv
Esempio n. 10
0
 def resolve(self, makefile, variables, fd, setting):
     assert os.path.isabs(makefile.workdir)
     fd.write(' '.join([util.normaljoin(makefile.workdir, path).replace('\\', '/')
                        for path in self._arguments[0].resolvesplit(makefile, variables, setting)]))
Esempio n. 11
0
def main(args, env, cwd, cb):
    """
    Start a single makefile execution, given a command line, working directory, and environment.

    @param cb a callback to notify with an exit code when make execution is finished.
    """

    try:
        makelevel = int(env.get('MAKELEVEL', '0'))

        op = OptionParser()
        op.add_option('-f',
                      '--file',
                      '--makefile',
                      action='append',
                      dest='makefiles',
                      default=[])
        op.add_option('-d', action="store_true", dest="verbose", default=False)
        op.add_option('-k',
                      '--keep-going',
                      action="store_true",
                      dest="keepgoing",
                      default=False)
        op.add_option('--debug-log', dest="debuglog", default=None)
        op.add_option('-C', '--directory', dest="directory", default=None)
        op.add_option('-v',
                      '--version',
                      action="store_true",
                      dest="printversion",
                      default=False)
        op.add_option('-j', '--jobs', type="int", dest="jobcount", default=1)
        op.add_option('-w',
                      '--print-directory',
                      action="store_true",
                      dest="printdir")
        op.add_option('--no-print-directory',
                      action="store_false",
                      dest="printdir",
                      default=True)
        op.add_option('-s',
                      '--silent',
                      action="store_true",
                      dest="silent",
                      default=False)
        op.add_option('-n',
                      '--just-print',
                      '--dry-run',
                      '--recon',
                      action="store_true",
                      dest="justprint",
                      default=False)

        options, arguments1 = op.parse_args(parsemakeflags(env))
        options, arguments2 = op.parse_args(args, values=options)

        op.destroy()

        arguments = arguments1 + arguments2

        if options.printversion:
            _version()
            cb(0)
            return

        shortflags = []
        longflags = []

        if options.keepgoing:
            shortflags.append('k')

        if options.printdir:
            shortflags.append('w')

        if options.silent:
            shortflags.append('s')
            options.printdir = False

        if options.justprint:
            shortflags.append('n')

        loglevel = logging.WARNING
        if options.verbose:
            loglevel = logging.DEBUG
            shortflags.append('d')

        logkwargs = {}
        if options.debuglog:
            logkwargs['filename'] = options.debuglog
            longflags.append('--debug-log=%s' % options.debuglog)

        if options.directory is None:
            workdir = cwd
        else:
            workdir = util.normaljoin(cwd, options.directory)

        if options.jobcount != 1:
            longflags.append('-j%i' % (options.jobcount, ))

        makeflags = ''.join(shortflags)
        if len(longflags):
            makeflags += ' ' + ' '.join(longflags)

        logging.basicConfig(level=loglevel, **logkwargs)

        context = process.getcontext(options.jobcount)

        if options.printdir:
            print "make.py[%i]: Entering directory '%s'" % (makelevel, workdir)
            sys.stdout.flush()

        if len(options.makefiles) == 0:
            if os.path.exists(util.normaljoin(workdir, 'Makefile')):
                options.makefiles.append('Makefile')
            else:
                print "No makefile found"
                cb(2)
                return

        ostmts, targets, overrides = parserdata.parsecommandlineargs(arguments)

        _MakeContext(makeflags, makelevel, workdir, context, env, targets,
                     options, ostmts, overrides, cb)
    except (util.MakeError), e:
        print e
        if options.printdir:
            print "make.py[%i]: Leaving directory '%s'" % (makelevel, workdir)
        sys.stdout.flush()
        cb(2)
        return
Esempio n. 12
0
"""
Makefile execution.

Multiple `makes` can be run within the same process. Each one has an entirely data.Makefile and .Target
structure, environment, and working directory. Typically they will all share a parallel execution context,
except when a submake specifies -j1 when the parent make is building in parallel.
"""

import os, subprocess, sys, logging, time, traceback, re
from optparse import OptionParser
import data, parserdata, process, util

# TODO: If this ever goes from relocatable package to system-installed, this may need to be
# a configured-in path.

makepypath = util.normaljoin(os.path.dirname(__file__), '../make.py')

_simpleopts = re.compile(r'^[a-zA-Z]+(\s|$)')


def parsemakeflags(env):
    """
    Parse MAKEFLAGS from the environment into a sequence of command-line arguments.
    """

    makeflags = env.get('MAKEFLAGS', '')
    makeflags = makeflags.strip()

    if makeflags == '':
        return []
Esempio n. 13
0
def main(args, env, cwd, cb):
    """
    Start a single makefile execution, given a command line, working directory, and environment.

    @param cb a callback to notify with an exit code when make execution is finished.
    """

    try:
        makelevel = int(env.get('MAKELEVEL', '0'))

        op = OptionParser()
        op.add_option('-f', '--file', '--makefile',
                      action='append',
                      dest='makefiles',
                      default=[])
        op.add_option('-d',
                      action="store_true",
                      dest="verbose", default=False)
        op.add_option('-k', '--keep-going',
                      action="store_true",
                      dest="keepgoing", default=False)
        op.add_option('--debug-log',
                      dest="debuglog", default=None)
        op.add_option('-C', '--directory',
                      dest="directory", default=None)
        op.add_option('-v', '--version', action="store_true",
                      dest="printversion", default=False)
        op.add_option('-j', '--jobs', type="int",
                      dest="jobcount", default=1)
        op.add_option('-w', '--print-directory', action="store_true",
                      dest="printdir")
        op.add_option('--no-print-directory', action="store_false",
                      dest="printdir", default=True)
        op.add_option('-s', '--silent', action="store_true",
                      dest="silent", default=False)
        op.add_option('-n', '--just-print', '--dry-run', '--recon',
                      action="store_true",
                      dest="justprint", default=False)

        options, arguments1 = op.parse_args(parsemakeflags(env))
        options, arguments2 = op.parse_args(args, values=options)

        op.destroy()

        arguments = arguments1 + arguments2

        if options.printversion:
            _version()
            cb(0)
            return

        shortflags = []
        longflags = []

        if options.keepgoing:
            shortflags.append('k')

        if options.printdir:
            shortflags.append('w')

        if options.silent:
            shortflags.append('s')
            options.printdir = False

        if options.justprint:
            shortflags.append('n')

        loglevel = logging.WARNING
        if options.verbose:
            loglevel = logging.DEBUG
            shortflags.append('d')

        logkwargs = {}
        if options.debuglog:
            logkwargs['filename'] = options.debuglog
            longflags.append('--debug-log=%s' % options.debuglog)

        if options.directory is None:
            workdir = cwd
        else:
            workdir = util.normaljoin(cwd, options.directory)

        if options.jobcount != 1:
            longflags.append('-j%i' % (options.jobcount,))

        makeflags = ''.join(shortflags)
        if len(longflags):
            makeflags += ' ' + ' '.join(longflags)

        logging.basicConfig(level=loglevel, **logkwargs)

        context = process.getcontext(options.jobcount)

        if options.printdir:
            print "make.py[%i]: Entering directory '%s'" % (makelevel, workdir)
            sys.stdout.flush()

        if len(options.makefiles) == 0:
            if os.path.exists(util.normaljoin(workdir, 'Makefile')):
                options.makefiles.append('Makefile')
            else:
                print "No makefile found"
                cb(2)
                return

        ostmts, targets, overrides = parserdata.parsecommandlineargs(arguments)

        _MakeContext(makeflags, makelevel, workdir, context, env, targets, options, ostmts, overrides, cb)
    except (util.MakeError), e:
        print e
        if options.printdir:
            print "make.py[%i]: Leaving directory '%s'" % (makelevel, workdir)
        sys.stdout.flush()
        cb(2)
        return
Esempio n. 14
0
"""
Makefile execution.

Multiple `makes` can be run within the same process. Each one has an entirely data.Makefile and .Target
structure, environment, and working directory. Typically they will all share a parallel execution context,
except when a submake specifies -j1 when the parent make is building in parallel.
"""

import os, subprocess, sys, logging, time, traceback, re
from optparse import OptionParser
import data, parserdata, process, util

# TODO: If this ever goes from relocatable package to system-installed, this may need to be
# a configured-in path.

makepypath = util.normaljoin(os.path.dirname(__file__), '../make.py')

_simpleopts = re.compile(r'^[a-zA-Z]+(\s|$)')
def parsemakeflags(env):
    """
    Parse MAKEFLAGS from the environment into a sequence of command-line arguments.
    """

    makeflags = env.get('MAKEFLAGS', '')
    makeflags = makeflags.strip()

    if makeflags == '':
        return []

    if _simpleopts.match(makeflags):
        makeflags = '-' + makeflags