def _get_id(cmd):
    p = subprocess.run(cmd, stdout=subprocess.PIPE)
    try:
        p.check_returncode()
    except subprocess.CalledProcessError as err:
        logging.critical(f"{err} Please check path and revision.")
    else:
        return tools.get_string(p.stdout).strip()
Exemple #2
0
def _get_id(cmd):
    cmd = tuple(cmd)
    if cmd not in _ID_CACHE:
        p = subprocess.run(cmd, stdout=subprocess.PIPE)
        try:
            p.check_returncode()
        except subprocess.CalledProcessError as err:
            logging.critical(f"{err} Please check path and revision.")
        else:
            _ID_CACHE[cmd] = tools.get_string(p.stdout).strip()
    return _ID_CACHE[cmd]
def _get_id(cmd):
    cmd = tuple(cmd)
    if cmd not in _ID_CACHE:
        try:
            result = tools.get_string(subprocess.check_output(cmd).strip())
        except subprocess.CalledProcessError:
            logging.critical(
                'Call failed: "{}". Please check path and revision.'.format(
                    " ".join(cmd)))
        else:
            assert result
            _ID_CACHE[cmd] = result
    return _ID_CACHE[cmd]
def hg_id(repo, args=None, rev=None):
    args = args or []
    if rev:
        args.extend(['-r', str(rev)])
    cmd = ('hg', 'id', '--repository', repo) + tuple(args)
    if cmd not in _HG_ID_CACHE:
        try:
            result = tools.get_string(subprocess.check_output(cmd).strip())
        except subprocess.CalledProcessError:
            logging.critical(
                'Call failed: "{}". Please check path and revision.'.format(
                    ' '.join(cmd)))
        else:
            assert result
            _HG_ID_CACHE[cmd] = result
    return _HG_ID_CACHE[cmd]
Exemple #5
0
    def _redirect_streams(self):
        """
        Redirect output from original stdout and stderr streams to new
        streams if redirection is requested in the constructor and limit
        the output written to the new streams.

        Redirection could also be achieved py passing suitable
        parameters to Popen, but neither Popen.wait() nor
        Popen.communicate() allow limiting the redirected output.

        Code adapted from the Python 2 version of subprocess.py.
        """
        fd_to_infile = {}
        fd_to_outfile = {}
        fd_to_limits = {}
        fd_to_bytes = {}

        poller = select.poll()

        def register_and_append(file_obj, eventmask):
            poller.register(file_obj.fileno(), eventmask)
            fd_to_infile[file_obj.fileno()] = file_obj
            fd_to_bytes[file_obj.fileno()] = 0

        def close_unregister_and_remove(fd):
            poller.unregister(fd)
            fd_to_infile[fd].close()
            fd_to_infile.pop(fd)

        select_POLLIN_POLLPRI = select.POLLIN | select.POLLPRI

        for (
                stream_name,
            (new_stream, limits),
        ) in self.redirected_streams_and_limits.items():
            old_stream = getattr(self.process, stream_name)
            register_and_append(old_stream, select_POLLIN_POLLPRI)
            fd = old_stream.fileno()
            fd_to_outfile[fd] = new_stream
            fd_to_limits[fd] = limits

        while fd_to_infile:
            try:
                ready = poller.poll()
            except OSError as e:
                if e.args[0] == errno.EINTR:
                    continue
                raise

            for fd, mode in ready:
                if mode & select_POLLIN_POLLPRI:
                    data = os.read(fd, 4096)
                    if not data:
                        close_unregister_and_remove(fd)
                    if fd_to_outfile[fd]:
                        outfile = fd_to_outfile[fd]
                        _, hard_limit = fd_to_limits[fd]
                        if (hard_limit is not None
                                and fd_to_bytes[fd] + len(data) > hard_limit):
                            # Don't write to this outfile in subsequent rounds.
                            fd_to_outfile[fd] = None
                            logging.error(
                                f"{self.name} wrote {hard_limit / 1024} KiB (hard limit) "
                                f"to {outfile.name} -> abort command")
                            self.process.terminate()
                            # Strip extra bytes.
                            data = data[:hard_limit - fd_to_bytes[fd]]
                        outfile.write(tools.get_string(data))
                        fd_to_bytes[fd] += len(data)
                else:
                    # Ignore hang up or errors.
                    close_unregister_and_remove(fd)

        # Check soft limit.
        for fd, outfile in fd_to_outfile.items():
            # Ignore streams that exceeded the hard limit.
            if outfile is not None:
                soft_limit, _ = fd_to_limits[fd]
                bytes_written = fd_to_bytes[fd]
                if soft_limit is not None and bytes_written > soft_limit:
                    logging.error(
                        f"{self.name} finished and wrote {bytes_written / 1024} KiB "
                        f"to {outfile.name} (soft limit: {soft_limit / 1024} KiB)"
                    )