diff --git a/mercurial/hgweb/hgweb_mod.py b/mercurial/hgweb/hgweb_mod.py
index e0c0545e2e557b94554840690deb94de4941408e_bWVyY3VyaWFsL2hnd2ViL2hnd2ViX21vZC5weQ==..fda5a4b853ab8627295cb16f6144b56825867ac9_bWVyY3VyaWFsL2hnd2ViL2hnd2ViX21vZC5weQ== 100644
--- a/mercurial/hgweb/hgweb_mod.py
+++ b/mercurial/hgweb/hgweb_mod.py
@@ -230,8 +230,9 @@
 
     def sendtemplate(self, name, **kwargs):
         """Helper function to send a response generated from a template."""
-        kwargs = pycompat.byteskwargs(kwargs)
-        self.res.setbodygen(self.tmpl.generate(name, kwargs))
+        if self.req.method != b'HEAD':
+            kwargs = pycompat.byteskwargs(kwargs)
+            self.res.setbodygen(self.tmpl.generate(name, kwargs))
         return self.res.sendresponse()
 
 
diff --git a/mercurial/hgweb/request.py b/mercurial/hgweb/request.py
index e0c0545e2e557b94554840690deb94de4941408e_bWVyY3VyaWFsL2hnd2ViL3JlcXVlc3QucHk=..fda5a4b853ab8627295cb16f6144b56825867ac9_bWVyY3VyaWFsL2hnd2ViL3JlcXVlc3QucHk= 100644
--- a/mercurial/hgweb/request.py
+++ b/mercurial/hgweb/request.py
@@ -485,6 +485,7 @@
             self._bodybytes is None
             and self._bodygen is None
             and not self._bodywillwrite
+            and self._req.method != b'HEAD'
         ):
             raise error.ProgrammingError(b'response body not defined')
 
@@ -594,6 +595,8 @@
                 yield chunk
         elif self._bodywillwrite:
             self._bodywritefn = write
+        elif self._req.method == b'HEAD':
+            pass
         else:
             error.ProgrammingError(b'do not know how to send body')
 
diff --git a/mercurial/hgweb/server.py b/mercurial/hgweb/server.py
index e0c0545e2e557b94554840690deb94de4941408e_bWVyY3VyaWFsL2hnd2ViL3NlcnZlci5weQ==..fda5a4b853ab8627295cb16f6144b56825867ac9_bWVyY3VyaWFsL2hnd2ViL3NlcnZlci5weQ== 100644
--- a/mercurial/hgweb/server.py
+++ b/mercurial/hgweb/server.py
@@ -151,6 +151,9 @@
     def do_GET(self):
         self.do_POST()
 
+    def do_HEAD(self):
+        self.do_POST()
+
     def do_hgweb(self):
         self.sent_headers = False
         path, query = _splitURI(self.path)
@@ -246,7 +249,11 @@
             self.send_header(*h)
             if h[0].lower() == 'content-length':
                 self.length = int(h[1])
-        if self.length is None and saved_status[0] != common.HTTP_NOT_MODIFIED:
+        if (
+            self.length is None
+            and saved_status[0] != common.HTTP_NOT_MODIFIED
+            and self.command != 'HEAD'
+        ):
             self._chunked = (
                 not self.close_connection and self.request_version == 'HTTP/1.1'
             )
diff --git a/mercurial/hgweb/webcommands.py b/mercurial/hgweb/webcommands.py
index e0c0545e2e557b94554840690deb94de4941408e_bWVyY3VyaWFsL2hnd2ViL3dlYmNvbW1hbmRzLnB5..fda5a4b853ab8627295cb16f6144b56825867ac9_bWVyY3VyaWFsL2hnd2ViL3dlYmNvbW1hbmRzLnB5 100644
--- a/mercurial/hgweb/webcommands.py
+++ b/mercurial/hgweb/webcommands.py
@@ -1299,6 +1299,9 @@
             b'sendresponse() should not emit data if writing later'
         )
 
+    if web.req.method == b'HEAD':
+        return []
+
     bodyfh = web.res.getbodyfile()
 
     archival.archive(