Skip to content
Snippets Groups Projects
__init__.py 4.29 KiB
Newer Older
try:
  basestring
except NameError:
  basestring = (str, bytes)
def read_yaml(config_path):
    """ Read a yaml config file and returns the results as a dict
    """
    with open(config_path) as config_file:
        return yaml.safe_load(config_file.read())
def get_reference_hash(repo_id, hash_data):
    """ Returns the hash of repo_id and json-encodable hash_data
    """
    hash_value = "{0}-{1}".format(
        repo_id, json.dumps(hash_data, sort_keys=True)
    )
    tarball_hash = hashlib.sha1(hash_value).hexdigest()[:8]

    return tarball_hash


def get_format_data(repo):
    """ Returns a dict with the values of format keys for this repository
    """
    raw_format_data = json.loads(
        shell_exec(["hg", "-R", repo, "debugformat", "-T", "json"])
    )

    format_data = {}

    for format_value in raw_format_data:
        repo_value = format_value["repo"]
        if isinstance(repo_value, basestring):
            # String values should be valid ASCII
            repo_value = repo_value.encode("ascii")
        # Keys should be valid ASCII
        format_data[format_value["name"].encode("ascii")] = repo_value

    return format_data


def check_format_data(repo):
    """ Return the list of mismatched format values between default and repo

    Read the output of `debugformat` against the repo and the list of
    mismatched values
    """
    # Format information
    raw_format_data = json.loads(
        shell_exec(["hg", "-R", repo, "debugformat", "-T", "json"])
    )

    mismatch = []

    for format_value in raw_format_data:
        format_name = format_value["name"]
        repo_value = format_value["repo"]

        if format_value["config"] != repo_value:
            mismatch.append((format_name, repo_value, format_value["config"]))
def gather_repo_stats(repo, repo_id, repo_source):
    """gather repo related stats and returns a json-encodable dict

    The dict contains:
        - the repo_id given in parameter
        - is the repo enabled (True by default)
        - the repo_source given in parameter
        - the hgversion taken from the hg binary
        - the number of revisions and hidden revisions
        - the number of heads and hidden heads
        - the number of named branches and hidden named branches
        - the format info taken from `hg debugformat`
    """
    hgversion = shell_exec(["hg", "version", "-T", "{ver}"])

    numrevs = count_line_exec(["hg", "-R", repo, "log", "-T", "{rev}\n"])
    numrevshidden = count_line_exec(
        ["hg", "-R", repo, "--hidden", "log", "-T", "{rev}\n"]
    )

    numheads = count_line_exec(
        ["hg", "-R", repo, "heads", "-t", "-T", "{rev}\n"]
    )
    numheadshidden = count_line_exec(
        ["hg", "-R", repo, "--hidden", "heads", "-t", "-T", "{rev}\n"]
    )

    numbranches = count_line_exec(
        ["hg", "-R", repo, "branches", "-c", "-T", "{rev}\n"]
    )
    numbrancheshidden = count_line_exec(
        ["hg", "-R", repo, "--hidden", "branches", "-c", "-T", "{rev}\n"]
    )

    # Format information
    format_data = get_format_data(repo)

    # Generate YAML file
    return {
        "reference-repo": {
            "id": repo_id,
            "enabled": True,
            "source": repo_source,
            "hg-version": hgversion,
            "number-revisions": {"visible": numrevs, "all": numrevshidden},
            "number-heads": {"visible": numheads, "all": numheadshidden},
            "number-named-branch": {
                "visible": numbranches,
                "all": numbrancheshidden,
            },
            "format-info": format_data,
        }
    }


def shell_exec(command, env=None):
    """return the standard output of a given command

    - stderr is discarded
    - non-zero return code will raise `subprocess.CalledProcessError`
    """
    process = subprocess.Popen(
        command, stdout=subprocess.PIPE, shell=False, env=env
    )
    output, unused_err = process.communicate()
    retcode = process.poll()
    if retcode:
        raise subprocess.CalledProcessError(retcode, command)
    return output


def count_line_exec(command, env=None):
    """execute the given command and count the number of stdout lines

    Similar to `cmd | wc -l`
    """
    output = shell_exec(command, env)
    return len(output.splitlines())