# HG changeset patch # User Gregory Szorc # Date 2016-07-01 01:59:53 # Node ID c4fc33c477da9d3bfeedf504a5652c31a4a63c56 # Parent 2ff243c415b43440af82fa3e965105205eff9ee4 hgweb: expose list of per-repo labels to templates hgweb currently offers limited functionality for "classifying" repositories. This patch aims to change that. The web.labels config option list is introduced. Its values are exposed to the "index" and "summary" templates. Custom templates can use template features like ifcontains() to e.g. look for the presence of a specific label and engage specific behavior. For example, a site operator may wish to assign a "defunct" label to a repository so the repository is prominently marked as dead in repository indexes. diff --git a/mercurial/help/config.txt b/mercurial/help/config.txt --- a/mercurial/help/config.txt +++ b/mercurial/help/config.txt @@ -2026,6 +2026,14 @@ The full set of options is: ``ipv6`` Whether to use IPv6. (default: False) +``labels`` + List of string *labels* associated with the repository. + + Labels are exposed as a template keyword and can be used to customize + output. e.g. the ``index`` template can group or filter repositories + by labels and the ``summary`` template can display additional content + if a specific label is present. + ``logoimg`` File name of the logo image that some templates display on each page. The file name is relative to ``staticurl``. That is, the full path to diff --git a/mercurial/hgweb/hgwebdir_mod.py b/mercurial/hgweb/hgwebdir_mod.py --- a/mercurial/hgweb/hgwebdir_mod.py +++ b/mercurial/hgweb/hgwebdir_mod.py @@ -366,7 +366,9 @@ class hgwebdir(object): 'lastchange': d, 'lastchange_sort': d[1]-d[0], 'archives': [], - 'isdirectory': True} + 'isdirectory': True, + 'labels': [], + } seendirs.add(name) yield row @@ -416,6 +418,7 @@ class hgwebdir(object): 'lastchange_sort': d[1]-d[0], 'archives': archivelist(u, "tip", url), 'isdirectory': None, + 'labels': u.configlist('web', 'labels', untrusted=True), } yield row diff --git a/mercurial/hgweb/webcommands.py b/mercurial/hgweb/webcommands.py --- a/mercurial/hgweb/webcommands.py +++ b/mercurial/hgweb/webcommands.py @@ -725,7 +725,8 @@ def summary(web, req, tmpl): shortlog=changelist, node=tip.hex(), symrev='tip', - archives=web.archivelist("tip")) + archives=web.archivelist("tip"), + labels=web.configlist('web', 'labels')) @webcommand('filediff') def filediff(web, req, tmpl): diff --git a/mercurial/templates/json/map b/mercurial/templates/json/map --- a/mercurial/templates/json/map +++ b/mercurial/templates/json/map @@ -109,7 +109,8 @@ summary = '\{ "branches": [{join(branches%branchentry, ", ")}], "shortlog": [{join(shortlog%shortlogentry, ", ")}], "tags": [{join(tags%tagentry, ", ")}], - "archives": [{join(archives%archiveentry, ", ")}] + "archives": [{join(archives%archiveentry, ", ")}], + "labels": {labels|json} }' archiveentry = '\{ "node": {node|json}, @@ -220,5 +221,6 @@ indexentry = '\{ "name": {name|utf8|json}, "description": {description|utf8|json}, "contact": {contact|utf8|json}, - "lastchange": {lastchange|json} + "lastchange": {lastchange|json}, + "labels": {labels|json} }' diff --git a/tests/test-hgweb-json.t b/tests/test-hgweb-json.t --- a/tests/test-hgweb-json.t +++ b/tests/test-hgweb-json.t @@ -848,6 +848,7 @@ summary/ shows a summary of repository s "status": "inactive" } ], + "labels": [], "lastchange": [ 0.0, 0 diff --git a/tests/test-hgwebdir.t b/tests/test-hgwebdir.t --- a/tests/test-hgwebdir.t +++ b/tests/test-hgwebdir.t @@ -62,6 +62,7 @@ create a subdirectory containing reposit $ cat >> f/.hg/hgrc << EOF > [web] > name = fancy name for repo f + > labels = foo, bar > EOF $ cd .. @@ -108,12 +109,14 @@ should succeed "name": "a", "description": "unknown", "contact": "Foo Bar \u003cfoo.bar@example.com\u003e", - "lastchange": [*, *] (glob) + "lastchange": [*, *], (glob) + "labels": [] }, { "name": "b", "description": "unknown", "contact": "Foo Bar \u003cfoo.bar@example.com\u003e", - "lastchange": [*, *] (glob) + "lastchange": [*, *], (glob) + "labels": [] }] } (no-eol) @@ -201,6 +204,218 @@ should succeed, slashy names /astar/ /astar/.hg/patches/ + + $ get-with-headers.py localhost:$HGPORT1 '?style=json' + 200 Script output follows + + { + "entries": [{ + "name": "t/a", + "description": "unknown", + "contact": "Foo Bar \u003cfoo.bar@example.com\u003e", + "lastchange": [*, *], (glob) + "labels": [] + }, { + "name": "b", + "description": "unknown", + "contact": "Foo Bar \u003cfoo.bar@example.com\u003e", + "lastchange": [*, *], (glob) + "labels": [] + }, { + "name": "coll/a", + "description": "unknown", + "contact": "Foo Bar \u003cfoo.bar@example.com\u003e", + "lastchange": [*, *], (glob) + "labels": [] + }, { + "name": "coll/a/.hg/patches", + "description": "unknown", + "contact": "Foo Bar \u003cfoo.bar@example.com\u003e", + "lastchange": [*, *], (glob) + "labels": [] + }, { + "name": "coll/b", + "description": "unknown", + "contact": "Foo Bar \u003cfoo.bar@example.com\u003e", + "lastchange": [*, *], (glob) + "labels": [] + }, { + "name": "coll/c", + "description": "unknown", + "contact": "Foo Bar \u003cfoo.bar@example.com\u003e", + "lastchange": [*, *], (glob) + "labels": [] + }, { + "name": "coll/notrepo/e", + "description": "unknown", + "contact": "Foo Bar \u003cfoo.bar@example.com\u003e", + "lastchange": [*, *], (glob) + "labels": [] + }, { + "name": "fancy name for repo f", + "description": "unknown", + "contact": "Foo Bar \u003cfoo.bar@example.com\u003e", + "lastchange": [*, *], (glob) + "labels": ["foo", "bar"] + }, { + "name": "rcoll/a", + "description": "unknown", + "contact": "Foo Bar \u003cfoo.bar@example.com\u003e", + "lastchange": [*, *], (glob) + "labels": [] + }, { + "name": "rcoll/a/.hg/patches", + "description": "unknown", + "contact": "Foo Bar \u003cfoo.bar@example.com\u003e", + "lastchange": [*, *], (glob) + "labels": [] + }, { + "name": "rcoll/b", + "description": "unknown", + "contact": "Foo Bar \u003cfoo.bar@example.com\u003e", + "lastchange": [*, *], (glob) + "labels": [] + }, { + "name": "rcoll/b/d", + "description": "unknown", + "contact": "Foo Bar \u003cfoo.bar@example.com\u003e", + "lastchange": [*, *], (glob) + "labels": [] + }, { + "name": "rcoll/c", + "description": "unknown", + "contact": "Foo Bar \u003cfoo.bar@example.com\u003e", + "lastchange": [*, *], (glob) + "labels": [] + }, { + "name": "rcoll/notrepo/e", + "description": "unknown", + "contact": "Foo Bar \u003cfoo.bar@example.com\u003e", + "lastchange": [*, *], (glob) + "labels": [] + }, { + "name": "rcoll/notrepo/e/e2", + "description": "unknown", + "contact": "Foo Bar \u003cfoo.bar@example.com\u003e", + "lastchange": [*, *], (glob) + "labels": [] + }, { + "name": "fancy name for repo f", + "description": "unknown", + "contact": "Foo Bar \u003cfoo.bar@example.com\u003e", + "lastchange": [*, *], (glob) + "labels": ["foo", "bar"] + }, { + "name": "rcoll/notrepo/f/f2", + "description": "unknown", + "contact": "Foo Bar \u003cfoo.bar@example.com\u003e", + "lastchange": [*, *], (glob) + "labels": [] + }, { + "name": "star/webdir/a", + "description": "unknown", + "contact": "Foo Bar \u003cfoo.bar@example.com\u003e", + "lastchange": [*, *], (glob) + "labels": [] + }, { + "name": "star/webdir/a/.hg/patches", + "description": "unknown", + "contact": "Foo Bar \u003cfoo.bar@example.com\u003e", + "lastchange": [*, *], (glob) + "labels": [] + }, { + "name": "star/webdir/b", + "description": "unknown", + "contact": "Foo Bar \u003cfoo.bar@example.com\u003e", + "lastchange": [*, *], (glob) + "labels": [] + }, { + "name": "star/webdir/c", + "description": "unknown", + "contact": "Foo Bar \u003cfoo.bar@example.com\u003e", + "lastchange": [*, *], (glob) + "labels": [] + }, { + "name": "star/webdir/notrepo/e", + "description": "unknown", + "contact": "Foo Bar \u003cfoo.bar@example.com\u003e", + "lastchange": [*, *], (glob) + "labels": [] + }, { + "name": "fancy name for repo f", + "description": "unknown", + "contact": "Foo Bar \u003cfoo.bar@example.com\u003e", + "lastchange": [*, *], (glob) + "labels": ["foo", "bar"] + }, { + "name": "starstar/webdir/a", + "description": "unknown", + "contact": "Foo Bar \u003cfoo.bar@example.com\u003e", + "lastchange": [*, *], (glob) + "labels": [] + }, { + "name": "starstar/webdir/a/.hg/patches", + "description": "unknown", + "contact": "Foo Bar \u003cfoo.bar@example.com\u003e", + "lastchange": [*, *], (glob) + "labels": [] + }, { + "name": "starstar/webdir/b", + "description": "unknown", + "contact": "Foo Bar \u003cfoo.bar@example.com\u003e", + "lastchange": [*, *], (glob) + "labels": [] + }, { + "name": "starstar/webdir/b/d", + "description": "unknown", + "contact": "Foo Bar \u003cfoo.bar@example.com\u003e", + "lastchange": [*, *], (glob) + "labels": [] + }, { + "name": "starstar/webdir/c", + "description": "unknown", + "contact": "Foo Bar \u003cfoo.bar@example.com\u003e", + "lastchange": [*, *], (glob) + "labels": [] + }, { + "name": "starstar/webdir/notrepo/e", + "description": "unknown", + "contact": "Foo Bar \u003cfoo.bar@example.com\u003e", + "lastchange": [*, *], (glob) + "labels": [] + }, { + "name": "starstar/webdir/notrepo/e/e2", + "description": "unknown", + "contact": "Foo Bar \u003cfoo.bar@example.com\u003e", + "lastchange": [*, *], (glob) + "labels": [] + }, { + "name": "fancy name for repo f", + "description": "unknown", + "contact": "Foo Bar \u003cfoo.bar@example.com\u003e", + "lastchange": [*, *], (glob) + "labels": ["foo", "bar"] + }, { + "name": "starstar/webdir/notrepo/f/f2", + "description": "unknown", + "contact": "Foo Bar \u003cfoo.bar@example.com\u003e", + "lastchange": [*, *], (glob) + "labels": [] + }, { + "name": "astar", + "description": "unknown", + "contact": "Foo Bar \u003cfoo.bar@example.com\u003e", + "lastchange": [*, *], (glob) + "labels": [] + }, { + "name": "astar/.hg/patches", + "description": "unknown", + "contact": "Foo Bar \u003cfoo.bar@example.com\u003e", + "lastchange": [*, *], (glob) + "labels": [] + }] + } (no-eol) + $ get-with-headers.py localhost:$HGPORT1 '?style=paper' 200 Script output follows