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