about summary refs log tree commit diff
path: root/nixpkgs/maintainers/scripts/sha256-to-SRI.py
diff options
context:
space:
mode:
Diffstat (limited to 'nixpkgs/maintainers/scripts/sha256-to-SRI.py')
-rwxr-xr-xnixpkgs/maintainers/scripts/sha256-to-SRI.py149
1 files changed, 0 insertions, 149 deletions
diff --git a/nixpkgs/maintainers/scripts/sha256-to-SRI.py b/nixpkgs/maintainers/scripts/sha256-to-SRI.py
deleted file mode 100755
index dcacb4c58044..000000000000
--- a/nixpkgs/maintainers/scripts/sha256-to-SRI.py
+++ /dev/null
@@ -1,149 +0,0 @@
-#!/usr/bin/env nix-shell
-#! nix-shell -i "python3 -I" -p "python3.withPackages(p: with p; [ rich structlog ])"
-
-from contextlib import contextmanager
-from pathlib import Path
-from structlog.contextvars import bound_contextvars as log_context
-
-import re, structlog
-
-
-logger = structlog.getLogger("sha256-to-SRI")
-
-
-nix32alphabet = "0123456789abcdfghijklmnpqrsvwxyz"
-nix32inverted  = { c: i for i, c in enumerate(nix32alphabet) }
-
-def nix32decode(s: str) -> bytes:
-    # only support sha256 hashes for now
-    assert len(s) == 52
-    out = [ 0 for _ in range(32) ]
-    # TODO: Do better than a list of byte-sized ints
-
-    for n, c in enumerate(reversed(s)):
-        digit = nix32inverted[c]
-        i, j = divmod(5 * n, 8)
-        out[i] = out[i] | (digit << j) & 0xff
-        rem = digit >> (8 - j)
-        if rem == 0:
-            continue
-        elif i < 31:
-            out[i+1] = rem
-        else:
-            raise ValueError(f"Invalid nix32 hash: '{s}'")
-
-    return bytes(out)
-
-
-def toSRI(digest: bytes) -> str:
-    from base64 import b64encode
-    assert len(digest) == 32
-    return f"sha256-{b64encode(digest).decode()}"
-
-
-RE = {
-    'nix32': f"[{nix32alphabet}]" "{52}",
-    'hex':    "[0-9A-Fa-f]{64}",
-    'base64': "[A-Za-z0-9+/]{43}=",
-}
-RE['sha256'] = '|'.join(
-    f"{'(sha256-)?' if name == 'base64' else ''}"
-    f"(?P<{name}>{r})"
-    for name, r in RE.items()
-)
-
-def sha256toSRI(m: re.Match) -> str:
-    """Produce the equivalent SRI string for any match of RE['sha256']"""
-    if m['nix32'] is not None:
-        return toSRI(nix32decode(m['nix32']))
-    if m['hex'] is not None:
-        from binascii import unhexlify
-        return toSRI(unhexlify(m['hex']))
-    if m['base64'] is not None:
-        from base64 import b64decode
-        return toSRI(b64decode(m['base64']))
-
-    raise ValueError("Got a match where none of the groups captured")
-
-
-# Ohno I used evil, irregular backrefs instead of making 2 variants  ^^'
-_def_re = re.compile(
-    "sha256 = (?P<quote>[\"'])"
-    f"({RE['sha256']})"
-    "(?P=quote);"
-)
-
-def defToSRI(s: str) -> str:
-    def f(m: re.Match[str]) -> str:
-        try:
-            return f'hash = "{sha256toSRI(m)}";'
-
-        except ValueError as exn:
-            begin, end = m.span()
-            match = m.string[begin:end]
-
-            logger.error(
-                "Skipping",
-                exc_info = exn,
-            )
-            return match
-
-    return _def_re.sub(f, s)
-
-
-@contextmanager
-def atomicFileUpdate(target: Path):
-    '''Atomically replace the contents of a file.
-
-    Guarantees that no temporary files are left behind, and `target` is either
-    left untouched, or overwritten with new content if no exception was raised.
-
-    Yields a pair `(original, new)` of open files.
-    `original` is the pre-existing file at `target`, open for reading;
-    `new` is an empty, temporary file in the same filder, open for writing.
-
-    Upon exiting the context, the files are closed; if no exception was
-    raised, `new` (atomically) replaces the `target`, otherwise it is deleted.
-    '''
-    # That's mostly copied from noto-emoji.py, should DRY it out
-    from tempfile import mkstemp
-    fd, _p = mkstemp(
-        dir = target.parent,
-        prefix = target.name,
-    )
-    tmpPath = Path(_p)
-
-    try:
-        with target.open() as original:
-            with tmpPath.open('w') as new:
-                yield (original, new)
-
-        tmpPath.replace(target)
-
-    except Exception:
-        tmpPath.unlink(missing_ok = True)
-        raise
-
-
-def fileToSRI(p: Path):
-    with atomicFileUpdate(p) as (og, new):
-        for i, line in enumerate(og):
-            with log_context(line=i):
-                new.write(defToSRI(line))
-
-
-if __name__ == "__main__":
-    from sys import argv, stderr
-
-    for arg in argv[1:]:
-        p = Path(arg)
-        with log_context(path=str(p)):
-            try:
-                fileToSRI(p)
-            except Exception as exn:
-                logger.error(
-                    "Unhandled exception, skipping file!",
-                    exc_info = exn,
-                )
-            else:
-                logger.info("Finished processing file")