[PATCH 1 of 5] extdata: add extdatasource reader

Yuya Nishihara yuya at tcha.org
Fri Sep 23 21:17:31 EDT 2016


On Thu, 22 Sep 2016 13:21:35 -0500, Matt Mackall wrote:
> # HG changeset patch
> # User Matt Mackall <mpm at selenic.com>
> # Date 1473794045 18000
> #      Tue Sep 13 14:14:05 2016 -0500
> # Node ID 19bf2776dfe39befdc479253e1e7d030b41c08f9
> # Parent  5271ae66615207f39cc41d78f4541bc6f8ca6ff6
> extdata: add extdatasource reader

> +def extdatasource(repo, source):
> +    """gather a map of rev -> value dict from the specified source
> +
> +    A source spec is treated as a URL, with a special case shell: type
> +    for parsing the output from a shell command.
> +
> +    The data is parsed as a series of newline-separated records where
> +    each record is a revision specifier optionally followed by a space
> +    and a freeform string value. If the revision is known locally, it
> +    is converted to a rev, otherwise the record is skipped.
> +
> +    Note that both key and value are treated as UTF-8 and converted to
> +    the local encoding. This allows uniformity between local and
> +    remote data sources.
> +    """
> +
> +    spec = repo.ui.config("extdata", source)
> +    if not spec:
> +        raise util.Abourt(_("unknown extdata source '%s'") % source)
> +
> +    try:
> +        # prepare for future expansion
> +        expand = spec % ()
> +    except TypeError:
> +        raise error.Abort(_("extdata doesn't support parameters yet"),
> +                          hint=_("use double % for escaping"))

Using '%' as a parameter symbol would be a bit unfortunate since URLs have
%HEX-escape syntax. How about using '$' or '{...}' ?

> +    if spec.startswith("shell:"):
> +        # external commands should be run relative to the repo root
> +        cmd = spec[6:]
> +        cwd = os.getcwd()
> +        os.chdir(repo.root)
> +        try:
> +            src = util.popen(cmd)
> +        finally:
> +            os.chdir(cwd)

Temporary chdir() may cause problems in hgweb, which can be threaded.

> +    else:
> +        # treat as a URL or file
> +        src = url.open(repo.ui, spec)
> +
> +    try:
> +        for l in src.readlines():
> +            if " " in l:
> +                k, v = l.strip().split(" ", 1)
> +            else:
> +                k, v = l.strip(), ""
> +
> +            k = encoding.tolocal(k)
> +            if k in repo:

If k is an ambiguous short hash, 'k in repo' would raise LookupError.

> +                # we ignore data for nodes that don't exist locally
> +                data[repo[k].rev()] = encoding.tolocal(v)


More information about the Mercurial-devel mailing list