Пример #1
0
def script_runner(local_tree: WorkingTree,
                  script: str,
                  commit_pending: Optional[bool] = None) -> str:
    """Run a script in a tree and commit the result.

    This ignores newly added files.

    :param local_tree: Local tree to run script in
    :param script: Script to run
    :param commit_pending: Whether to commit pending changes
        (True, False or None: only commit if there were no commits by the
         script)
    :return: Description as reported by script
    """
    last_revision = local_tree.last_revision()
    p = subprocess.Popen(script,
                         cwd=local_tree.basedir,
                         stdout=subprocess.PIPE,
                         shell=True)
    (description_encoded, err) = p.communicate(b"")
    if p.returncode != 0:
        raise errors.BzrCommandError("Script %s failed with error code %d" %
                                     (script, p.returncode))
    new_revision = local_tree.last_revision()
    description = description_encoded.decode()
    if last_revision == new_revision and commit_pending is None:
        # Automatically commit pending changes if the script did not
        # touch the branch.
        commit_pending = True
    if commit_pending:
        try:
            new_revision = local_tree.commit(description,
                                             allow_pointless=False)
        except PointlessCommit:
            pass
    if new_revision == last_revision:
        raise ScriptMadeNoChanges()
    return description
Пример #2
0
def script_runner(   # noqa: C901
    local_tree: WorkingTree, script: Union[str, List[str]],
    commit_pending: Optional[bool] = None,
    resume_metadata=None, subpath: str = '', update_changelog: Optional[bool] = None,
    extra_env: Optional[Dict[str, str]] = None,
    committer: Optional[str] = None
) -> CommandResult:  # noqa: C901
    """Run a script in a tree and commit the result.

    This ignores newly added files.

    Args:
      local_tree: Local tree to run script in
      script: Script to run
      commit_pending: Whether to commit pending changes
        (True, False or None: only commit if there were no commits by the
         script)
    """
    if control_files_in_root(local_tree, subpath):
        debian_path = subpath
    else:
        debian_path = os.path.join(subpath, "debian")
    if update_changelog is None:
        dch_guess = guess_update_changelog(local_tree, debian_path)
        if dch_guess:
            if isinstance(dch_guess, tuple):  # lintian-brush < 1.22
                update_changelog, explanation = dch_guess
            else:
                update_changelog = dch_guess.update_changelog
                explanation = dch_guess.explanation
            logging.info('%s', explanation)
        else:
            # Assume yes.
            update_changelog = True

    cl_path = os.path.join(debian_path, 'changelog')
    try:
        with open(local_tree.abspath(cl_path), 'r') as f:
            cl = Changelog(f)
            source_name = cl[0].package
    except FileNotFoundError:
        source_name = None

    env = dict(os.environ)
    if extra_env:
        env.update(extra_env)

    env['SVP_API'] = '1'
    if source_name:
        env['DEB_SOURCE'] = source_name

    if update_changelog:
        env['DEB_UPDATE_CHANGELOG'] = 'update'
    else:
        env['DEB_UPDATE_CHANGELOG'] = 'leave'

    last_revision = local_tree.last_revision()
    orig_tags = local_tree.branch.tags.get_tag_dict()
    with tempfile.TemporaryDirectory() as td:
        env['SVP_RESULT'] = os.path.join(td, 'result.json')
        if resume_metadata:
            env['SVP_RESUME'] = os.path.join(td, 'resume-metadata.json')
            with open(env['SVP_RESUME'], 'w') as f:
                json.dump(resume_metadata, f)
        p = subprocess.Popen(
            script, cwd=local_tree.abspath(subpath), stdout=subprocess.PIPE,
            shell=isinstance(script, str), env=env)
        (description_encoded, err) = p.communicate(b"")
        try:
            with open(env['SVP_RESULT'], 'r') as f:
                try:
                    result_json = json.load(f)
                except json.decoder.JSONDecodeError as e:
                    raise ResultFileFormatError(e)
        except FileNotFoundError:
            result_json = None
        if p.returncode != 0:
            if result_json is not None:
                raise DetailedFailure.from_json(source_name, result_json)
            raise ScriptFailed(script, p.returncode)
        # If the changelog didn't exist earlier, then hopefully it was created
        # now.
        if source_name is None:
            try:
                with open(local_tree.abspath(cl_path), 'r') as f:
                    cl = Changelog(f)
                    source_name = cl[0].package
            except FileNotFoundError:
                raise MissingChangelog(cl_path)
        if result_json is not None:
            result = CommandResult.from_json(source_name, result_json)
        else:
            result = CommandResult(source=source_name)
    if not result.description:
        result.description = description_encoded.decode().replace("\r", "")
    new_revision = local_tree.last_revision()
    if result.tags is None:
        result.tags = []
        for name, revid in local_tree.branch.tags.get_tag_dict().items():
            if orig_tags.get(name) != revid:
                result.tags.append((name, revid))
    if last_revision == new_revision and commit_pending is None:
        # Automatically commit pending changes if the script did not
        # touch the branch.
        commit_pending = True
    if commit_pending:
        if update_changelog and result.description and local_tree.has_changes():
            add_changelog_entry(
                local_tree,
                os.path.join(debian_path, 'changelog'),
                [result.description])
        local_tree.smart_add([local_tree.abspath(subpath)])
        try:
            new_revision = local_tree.commit(
                result.description, allow_pointless=False,
                committer=committer)
        except PointlessCommit:
            pass
    if new_revision == last_revision:
        raise ScriptMadeNoChanges()
    result.old_revision = last_revision
    result.new_revision = new_revision
    return result
Пример #3
0
def script_runner(  # noqa: C901
    local_tree: WorkingTree,
    script: Union[str, List[str]],
    commit_pending: Optional[bool] = None,
    resume_metadata=None,
    subpath: str = '',
    committer: Optional[str] = None,
    extra_env: Optional[Dict[str, str]] = None,
) -> CommandResult:  # noqa: C901
    """Run a script in a tree and commit the result.

    This ignores newly added files.

    Args:
      local_tree: Local tree to run script in
      script: Script to run
      commit_pending: Whether to commit pending changes
        (True, False or None: only commit if there were no commits by the
         script)
    """
    env = dict(os.environ)
    if extra_env:
        env.update(extra_env)
    env['SVP_API'] = '1'
    last_revision = local_tree.last_revision()
    orig_tags = local_tree.branch.tags.get_tag_dict()
    with tempfile.TemporaryDirectory() as td:
        env['SVP_RESULT'] = os.path.join(td, 'result.json')
        if resume_metadata:
            env['SVP_RESUME'] = os.path.join(td, 'resume-metadata.json')
            with open(env['SVP_RESUME'], 'w') as f:
                json.dump(resume_metadata, f)
        p = subprocess.Popen(script,
                             cwd=local_tree.abspath(subpath),
                             stdout=subprocess.PIPE,
                             shell=isinstance(script, str),
                             env=env)
        (description_encoded, err) = p.communicate(b"")
        try:
            with open(env['SVP_RESULT'], 'r') as f:
                try:
                    result_json = json.load(f)
                except json.decoder.JSONDecodeError as e:
                    raise ResultFileFormatError(e)
        except FileNotFoundError:
            result_json = None
        if p.returncode != 0:
            if result_json is not None:
                raise DetailedFailure.from_json(result_json)
            raise ScriptFailed(script, p.returncode)
        if result_json is not None:
            result = CommandResult.from_json(result_json)
        else:
            result = CommandResult()
    if not result.description:
        result.description = description_encoded.decode()
    new_revision = local_tree.last_revision()
    if result.tags is None:
        result.tags = []
        for name, revid in local_tree.branch.tags.get_tag_dict().items():
            if orig_tags.get(name) != revid:
                result.tags.append((name, revid))
    if last_revision == new_revision and commit_pending is None:
        # Automatically commit pending changes if the script did not
        # touch the branch.
        commit_pending = True
    if commit_pending:
        local_tree.smart_add([local_tree.abspath(subpath)])
        try:
            new_revision = local_tree.commit(result.description,
                                             allow_pointless=False,
                                             committer=committer)
        except PointlessCommit:
            pass
    if new_revision == last_revision:
        raise ScriptMadeNoChanges()
    result.old_revision = last_revision
    result.new_revision = local_tree.last_revision()
    return result