# HG changeset patch
# User Matt Mackall <m...@selenic.com>
# Date 1473794045 18000
#      Tue Sep 13 14:14:05 2016 -0500
# Node ID 19bf2776dfe39befdc479253e1e7d030b41c08f9
# Parent  5271ae66615207f39cc41d78f4541bc6f8ca6ff6
extdata: add extdatasource reader

This adds basic support for extdata, a way to add external data
sources for revsets and templates. An extdata data source is simply a
list of lines of the form:

<revision identifier>[<space><freeform text>]\n

An extdata source is configured thusly:

[extdata]
name = <a url or path>

urls of the form shell: are launch shell commands to generate data.

diff -r 5271ae666152 -r 19bf2776dfe3 mercurial/scmutil.py
--- a/mercurial/scmutil.py      Wed Sep 21 17:05:27 2016 -0400
+++ b/mercurial/scmutil.py      Tue Sep 13 14:14:05 2016 -0500
@@ -29,6 +29,7 @@
     phases,
     revset,
     similar,
+    url,
     util,
 )
 
@@ -1418,3 +1419,66 @@
             return
 
         self._queue.put(fh, block=True, timeout=None)
+
+def extdatasources(repo):
+    sources = set()
+    for k, v in repo.ui.configitems("extdata"):
+        sources.add(k)
+    return sources
+
+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"))
+
+    data = {}
+    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)
+    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:
+                # we ignore data for nodes that don't exist locally
+                data[repo[k].rev()] = encoding.tolocal(v)
+    finally:
+        src.close()
+
+    return data
_______________________________________________
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel

Reply via email to