def run(self, config, args): cookbook = CookBook(config) failed = [] p_name = args.package[0] store = PackagesStore(config) p = store.get_package(p_name) ordered_recipes = map(lambda x: cookbook.get_recipe(x), p.recipes_dependencies()) for recipe in ordered_recipes: if cookbook.recipe_needs_build(recipe.name): raise CommandError( _("Recipe %s is not built yet" % recipe.name)) for recipe in ordered_recipes: # call step function stepfunc = None try: stepfunc = getattr(recipe, 'check') except: m.message('%s has no check step, skipped' % recipe.name) if stepfunc: try: m.message('Running checks for recipe %s' % recipe.name) stepfunc() except Exception as ex: failed.append(recipe.name) m.warning(_("%s checks failed: %s") % (recipe.name, ex)) if failed: raise CommandError( _("Error running %s checks on:\n " + "\n ".join(failed)) % p_name)
def new_call(cmd, cmd_dir=None, fail=True, logfile=None, env=None): cmd = _cmd_string_to_array(cmd, env) if logfile: logfile.write('Running command {!r}\n'.format(cmd)) logfile.flush() try: subprocess.check_call(cmd, cwd=cmd_dir, env=env, stdout=logfile, stderr=subprocess.STDOUT) except SUBPROCESS_EXCEPTIONS as e: returncode = getattr(e, 'returncode', -1) if not fail: stream = logfile or sys.stderr if isinstance(e, FileNotFoundError): stream.write('{}: file not found\n'.format(cmd[0])) if isinstance(e, PermissionError): stream.write('{!r}: permission error\n'.format(cmd)) return returncode msg = '' if logfile: msg = 'Output in logfile {}'.format(logfile.name) raise CommandError(msg, cmd, returncode) return 0
async def async_call(cmd, cmd_dir='.', fail=True, logfile=None, cpu_bound=True, env=None): ''' Run a shell command @param cmd: the command to run @type cmd: str @param cmd_dir: directory where the command will be run @param cmd_dir: str ''' global CPU_BOUND_SEMAPHORE, NON_CPU_BOUND_SEMAPHORE semaphore = CPU_BOUND_SEMAPHORE if cpu_bound else NON_CPU_BOUND_SEMAPHORE async with semaphore: cmd = _cmd_string_to_array(cmd, env) if logfile is None: stream = None else: logfile.write("Running command '%s'\n" % ' '.join([shlex.quote(c) for c in cmd])) logfile.flush() stream = logfile if DRY_RUN: # write to sdterr so it's filtered more easilly m.error("cd %s && %s && cd %s" % (cmd_dir, cmd, os.getcwd())) return env = os.environ.copy() if env is None else env.copy() # Force python scripts to print their output on newlines instead # of on exit. Ensures that we get continuous output in log files. env['PYTHONUNBUFFERED'] = '1' proc = await asyncio.create_subprocess_exec(*cmd, cwd=cmd_dir, stderr=subprocess.STDOUT, stdout=stream, stdin=subprocess.DEVNULL, env=env) await proc.wait() if proc.returncode != 0 and fail: msg = '' if stream: msg = 'Output in logfile {}'.format(logfile.name) raise CommandError(msg, cmd, proc.returncode) return proc.returncode
async def async_call_output(cmd, cmd_dir=None, logfile=None, cpu_bound=True, env=None): ''' Run a shell command and get the output @param cmd: the command to run @type cmd: str @param cmd_dir: directory where the command will be run @param cmd_dir: str ''' global CPU_BOUND_SEMAPHORE, NON_CPU_BOUND_SEMAPHORE semaphore = CPU_BOUND_SEMAPHORE if cpu_bound else NON_CPU_BOUND_SEMAPHORE async with semaphore: cmd = _cmd_string_to_array(cmd, env) if PLATFORM == Platform.WINDOWS: import cerbero.hacks # On Windows, create_subprocess_exec with a PIPE fails while creating # a named pipe using tempfile.mktemp because we override os.path.join # to use / on Windows. Override the tempfile module's reference to the # original implementation, then change it back later so it doesn't leak. # XXX: Get rid of this once we move to Path.as_posix() everywhere tempfile._os.path.join = cerbero.hacks.oldjoin # The tempdir is derived from TMP and TEMP which use / as the path # separator, which fails for the same reason as above. Ensure that \ is # used instead. tempfile.tempdir = str(PurePath(tempfile.gettempdir())) proc = await asyncio.create_subprocess_exec(*cmd, cwd=cmd_dir, stdout=subprocess.PIPE, stderr=logfile, stdin=subprocess.DEVNULL, env=env) (output, unused_err) = await proc.communicate() if PLATFORM == Platform.WINDOWS: os.path.join = cerbero.hacks.join if sys.stdout.encoding: output = output.decode(sys.stdout.encoding, errors='replace') if proc.returncode != 0: raise CommandError(output, cmd, proc.returncode) return output
class CheckPackage(Command): doc = N_('Run checks on a given package') name = 'checkpackage' def __init__(self): Command.__init__(self, [ ArgparseArgument('package', nargs=1, help=_('name of the package to run checks on')), ]) def run(self, config, args): cookbook = CookBook(config) failed = [] p_name = args.package[0] store = PackagesStore(config) p = store.get_package(p_name) ordered_recipes = map(lambda x: cookbook.get_recipe(x), p.recipes_dependencies()) for recipe in ordered_recipes: if cookbook.recipe_needs_build(recipe.name): raise CommandError( _("Recipe %s is not built yet" % recipe.name)) for recipe in ordered_recipes: # call step function stepfunc = None try: stepfunc = getattr(recipe, 'check') except: m.message('%s has no check step, skipped' % recipe.name) if stepfunc: try: m.message('Running checks for recipe %s' % recipe.name) stepfunc() except Exception, ex: failed.append(recipe.name) m.warning(_("%s checks failed: %s") % (recipe.name, ex)) if failed: raise CommandError( _("Error running %s checks on:\n " + "\n ".join(failed)) % p_name)
def check_output(cmd, cmd_dir=None, fail=True, logfile=None, env=None, quiet=False): cmd = _cmd_string_to_array(cmd, env) stderr = logfile if quiet and not logfile: stderr = subprocess.DEVNULL try: o = subprocess.check_output(cmd, cwd=cmd_dir, env=env, stderr=stderr) except SUBPROCESS_EXCEPTIONS as e: msg = getattr(e, 'output', '') if not fail: return msg if logfile: msg += '\nstderr in logfile {}'.format(logfile.name) raise CommandError(msg, cmd, getattr(e, 'returncode', -1)) if sys.stdout.encoding: o = o.decode(sys.stdout.encoding, errors='replace') return o
def call(cmd, cmd_dir='.', fail=True, verbose=False, logfile=None, env=None): ''' Run a shell command DEPRECATED: Use new_call and a cmd array wherever possible @param cmd: the command to run @type cmd: str @param cmd_dir: directory where the command will be run @param cmd_dir: str @param fail: whether or not to raise an exception if the command fails @type fail: bool ''' try: if logfile is None: if verbose: m.message("Running command '%s'" % cmd) stream = None else: logfile.write("Running command '%s'\n" % cmd) logfile.flush() stream = logfile shell = True if PLATFORM == Platform.WINDOWS: # windows do not understand ./ if cmd.startswith('./'): cmd = cmd[2:] # run all processes through sh.exe to get scripts working cmd = '%s "%s"' % ('sh -c', cmd) # fix paths with backslashes cmd = _fix_mingw_cmd(cmd) # Disable shell which uses cmd.exe shell = False if DRY_RUN: # write to sdterr so it's filtered more easilly m.error("cd %s && %s && cd %s" % (cmd_dir, cmd, os.getcwd())) ret = 0 else: if env is not None: env = env.copy() else: env = os.environ.copy() # Force python scripts to print their output on newlines instead # of on exit. Ensures that we get continuous output in log files. env['PYTHONUNBUFFERED'] = '1' ret = subprocess.check_call(cmd, cwd=cmd_dir, bufsize=1, stderr=subprocess.STDOUT, stdout=stream, universal_newlines=True, env=env, shell=shell) except SUBPROCESS_EXCEPTIONS as e: if fail: msg = '' if stream: msg = 'Output in logfile {}'.format(logfile.name) raise CommandError(msg, cmd, getattr(e, 'returncode', -1)) else: ret = 0 return ret