diff mercurial/bundlecaches.py @ 51978:aa7f4a45d8fa

clonebundles: allow manifest to specify sha256 digest of bundles
author Joerg Sonnenberger <joerg@bec.de>
date Thu, 27 Jun 2024 03:32:52 +0200
parents 1c5810ce737e
children 48572371d478 961900fbd67c
line wrap: on
line diff
--- a/mercurial/bundlecaches.py	Thu Oct 03 14:45:01 2024 +0200
+++ b/mercurial/bundlecaches.py	Thu Jun 27 03:32:52 2024 +0200
@@ -6,6 +6,7 @@
 from __future__ import annotations
 
 import collections
+import re
 import typing
 
 from typing import (
@@ -27,6 +28,7 @@
     error,
     requirements as requirementsmod,
     sslutil,
+    url as urlmod,
     util,
 )
 from .utils import stringutil
@@ -406,6 +408,9 @@
     return False
 
 
+digest_regex = re.compile(b'^[a-z0-9]+:[0-9a-f]+(,[a-z0-9]+:[0-9a-f]+)*$')
+
+
 def filterclonebundleentries(
     repo, entries, streamclonerequested=False, pullbundles=False
 ):
@@ -481,6 +486,43 @@
                 )
                 continue
 
+        if b'DIGEST' in entry:
+            if not digest_regex.match(entry[b'DIGEST']):
+                repo.ui.debug(
+                    b'filtering %s due to a bad DIGEST attribute\n' % url
+                )
+                continue
+            supported = 0
+            seen = {}
+            for digest_entry in entry[b'DIGEST'].split(b','):
+                algo, digest = digest_entry.split(b':')
+                if algo not in seen:
+                    seen[algo] = digest
+                elif seen[algo] != digest:
+                    repo.ui.debug(
+                        b'filtering %s due to conflicting %s digests\n'
+                        % (url, algo)
+                    )
+                    supported = 0
+                    break
+                digester = urlmod.digesthandler.digest_algorithms.get(algo)
+                if digester is None:
+                    continue
+                if len(digest) != digester().digest_size * 2:
+                    repo.ui.debug(
+                        b'filtering %s due to a bad %s digest\n' % (url, algo)
+                    )
+                    supported = 0
+                    break
+                supported += 1
+            else:
+                if supported == 0:
+                    repo.ui.debug(
+                        b'filtering %s due to lack of supported digest\n' % url
+                    )
+            if supported == 0:
+                continue
+
         newentries.append(entry)
 
     return newentries