Skip to content
Snippets Groups Projects
update-nixpkgs 1.8 KiB
Newer Older
  • Learn to ignore specific revisions
  • #!/usr/bin/env python
    
    import argparse
    import json
    from pathlib import Path
    
    import httpx
    from ps_tools import get_url_hash
    
    # We pass this to builtins.fetchTarball which only supports sha256
    HASH_TYPE = "sha256"
    
    DEFAULT_CHANNEL = "nixos-21.05"
    CHANNEL_URL_TEMPLATE = "https://channels.nixos.org/{channel}/nixexprs.tar.xz"
    
    
    def get_nixos_channel_url(*, channel):
        """
        Get the URL for the current release of the given nixos channel.
    
        `https://channels.nixos.org/<channel>` redirects to the path on
        `https://releases.nixos.org` that corresponds to the current release
        of that channel. This captures that redirect, so we can pin against
        the release.
        """
        response = httpx.head(
            CHANNEL_URL_TEMPLATE.format(channel=channel), allow_redirects=False
        )
        response.raise_for_status()
        assert response.is_redirect
        return str(response.next_request.url)
    
    
    def main():
        parser = argparse.ArgumentParser(description="Update a pinned nixos repository.")
        parser.add_argument(
            "repo_file",
            metavar="repo-file",
            nargs="?",
            default=Path(__file__).parent.with_name("nixpkgs-2105.json"),
            type=Path,
            help="JSON file with pinned configuration.",
        )
        parser.add_argument(
            "--dry-run",
            action="store_true",
        )
        parser.set_defaults(channel=DEFAULT_CHANNEL)
        args = parser.parse_args()
    
        repo_file = args.repo_file
        config = json.loads(repo_file.read_text())
    
        config["url"] = get_nixos_channel_url(channel=args.channel)
        hash_data = get_url_hash(HASH_TYPE, name=config["name"], url=config["url"])
        config["sha256"] = hash_data["outputHash"]
    
        output = json.dumps(config, indent=2)
        if args.dry_run:
            print(output)
        else:
            repo_file.write_text(output)
    
    
    if __name__ == "__main__":
        main()