Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 27 additions & 19 deletions salt/hg/config/hg.apache.conf.jinja
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,14 @@
Require all granted
</Directory>

Alias /icons/ "/usr/share/apache2/icons/"

<Directory "/usr/share/apache2/icons">
Options FollowSymlinks
AllowOverride None
Require all granted
</Directory>

# The lookup app is better run with few processes, since it uses a cache.
WSGIDaemonProcess hglookup user=hg group=hg \
threads=2 processes=1 maximum-requests=1000 \
Expand All @@ -36,38 +44,38 @@

WSGIScriptAlias /lookup /srv/hg/wsgi/lookup.wsgi

# We need enough threads/processes for many long-running clones to run in
# parallel (e.g. for buildbots)
# NOTE: maximum-requests suspected to corrupt responses, see
# http://mercurial.selenic.com/bts/issue2595
WSGIDaemonProcess hgweb user=hg group=hg \
threads=2 processes=6 maximum-requests=1024 inactivity-timeout=300 \
display-name=hgweb
WSGIProcessGroup hgweb
# A lightweight standin for revision app to maintain support for /lookup
WSGIDaemonProcess hgrev user=hg group=hg \
threads=2 processes=4 maximum-requests=1000 \
display-name=hgrev
# The Location hack ensures the lookup app is run within
# this process group
<LocationMatch "^(.*)/rev/([A-Fa-f0-9]{12,40})/?">
WSGIProcessGroup hgrev
</LocationMatch>

WSGIScriptAliasMatch "^(.*)/rev/([A-Fa-f0-9]{12,40})/?" /srv/hg/wsgi/rev.wsgi

WSGIScriptAlias / /srv/hg/wsgi/python.wsgi
# Staticly serve hg repos over HTTP
DocumentRoot /srv/hg/hg-static/
<Directory /srv/hg/hg-static>
Options Indexes FollowSymlinks
IndexOptions FancyIndexing SuppressColumnSorting
HeaderName README.html
Require all granted
</Directory>

ErrorDocument 410 /410.html
RedirectMatch gone "/cpython/annotate/.*/NEWS$"
RedirectMatch gone "/cpython-fullhistory/annotate/.*/NEWS$"

<Directory /srv/hg/wsgi>
Require all granted
</Directory>

# Static files: logo, CSS, favicon... (wired to .../static/)
# This is optional but a bit faster than letting Mercurial serve the files
# NOTE: needs to be changed if hg gets wired to another dir or python
# version

AliasMatch /static/([^/]*) /usr/share/mercurial/templates/static/$1
<Directory /usr/share/mercurial/templates/static/>
Require all granted
</Directory>

<Location /_server-status>
SetHandler server-status

Require ip 127.0.0.1
</Location>
</VirtualHost>
60 changes: 60 additions & 0 deletions salt/hg/files/hg/src/hgrev.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
# hgrev.py
#
# Dump a revision of a given hg repo as a patch
#
# Written by Ee Durbin, 2025.

import os
import shlex
import subprocess
from wsgiref.simple_server import make_server


class hgrev(object):
def __init__(self, verbose=False):
self.verbose = verbose

def successful_response(self, response, contents):
headers = [("Content-Type", "text/plain")]
response("200 OK", headers)
return [contents.encode()]

def failed_response(self, response, detail=""):
headers = [("Content-Type", "text/plain")]
response("404 Not Found", headers)
return [
detail.encode(),
"\nUsage: path/to/hg/repo/rev/HGHEXNODE (12 or 40 hex characters)\n".encode(),
]

def __call__(self, env, response):
node = env.get("SCRIPT_NAME", "").strip("/")
repository = os.path.dirname(node).rstrip("/rev")
rev = os.path.basename(node)

hg_repo = os.path.join("/srv/hg/repos", repository, ".hg")
if not os.path.exists(hg_repo):
return self.failed_response(
response,
detail=f"repo not found ({repository}) ({rev})",
)

command = ["hg", "log", "-v", "-p", "-r", shlex.quote(rev)]

try:
result = subprocess.run(
command, cwd=hg_repo, capture_output=True, text=True, shell=False
)
except Exception as e:
return self.failed_response(response, detail=str(e))

return self.successful_response(response, result.stdout)


if __name__ == "__main__":
application = hgrev(verbose=True)

httpd = make_server("", 8124, application)
sa = httpd.socket.getsockname()
print("Serving HTTP on", sa[0], "port", sa[1], "...")
httpd.serve_forever()
10 changes: 10 additions & 0 deletions salt/hg/files/hg/wsgi/rev.wsgi
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import os
import sys

home = os.path.expanduser('~hg')

sys.path.insert(0, os.path.join(home, 'src'))

from hgrev import hgrev

application = hgrev()