contrib/nix/flake.nix
changeset 50453 be676c313c7b
child 51702 541292a02e09
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/nix/flake.nix	Mon Apr 17 00:27:46 2023 +0200
@@ -0,0 +1,177 @@
+# flake.nix - Nix-defined package and devel env for the Mercurial project.
+#
+# Copyright 2021-2023 Pacien TRAN-GIRARD <pacien.trangirard@pacien.net>
+#
+# This software may be used and distributed according to the terms of the
+# GNU General Public License version 2 or any later version.
+
+# Usage summary, from the root of this repository:
+#
+# Enter a shell with development tools:
+#   nix develop 'hg+file:.?dir=contrib/nix'
+#
+# Running mercurial:
+#   nix run 'hg+file:.?dir=contrib/nix' -- version
+#
+# Running the test suite in a sandbox:
+#   nix build 'hg+file:.?dir=contrib/nix#mercurial-tests' -L
+
+{
+  inputs = {
+    nixpkgs.url = "github:NixOS/nixpkgs/nixos-22.11";
+    nixpkgs-black.url = "github:NixOS/nixpkgs/c7cb72b0";  # black 20.8b1
+    # rust-overlay.url = "github:oxalica/rust-overlay";
+    flake-utils.url = "github:numtide/flake-utils";
+    flaky-utils.url = "git+https://cgit.pacien.net/libs/flaky-utils";
+  };
+
+  outputs = {
+    self
+  , nixpkgs
+  , nixpkgs-black
+  # , rust-overlay
+  , flake-utils
+  , flaky-utils
+  }:
+  flake-utils.lib.eachDefaultSystem (system:
+  let
+    # overlays = [ (import rust-overlay) ];
+    pkgs = import nixpkgs { inherit system; };
+
+    # We're in the contrib/nix sub-directory.
+    src = ../..;
+
+    # For snapshots, to satisfy extension minimum version requirements.
+    dummyVersion = "99.99";
+
+    pin = {
+      # The test suite has issues with the latest/current versions of Python.
+      # Use an older recommended version instead, matching the CI.
+      python = pkgs.python39;
+
+      # The project uses a pinned version (rust/clippy.toml) for compiling,
+      # but uses formatter features from nightly.
+      # TODO: make cargo use the formatter from nightly automatically
+      #       (not supported by rustup/cargo yet? workaround?)
+      # rustPlatform = pkgs.rust-bin.stable."1.61.0".default;
+      # rustPlatformFormatter = pkgs.rust-bin.nightly."2023-04-20".default;
+
+      # The CI uses an old version of the Black code formatter,
+      # itself depending on old Python libraries.
+      # The formatting rules have changed in more recent versions.
+      inherit (import nixpkgs-black { inherit system; }) black;
+    };
+
+  in rec {
+    apps.mercurial = apps.mercurial-rust;
+    apps.default = apps.mercurial;
+    apps.mercurial-c = flake-utils.lib.mkApp {
+      drv = packages.mercurial-c;
+    };
+    apps.mercurial-rust = flake-utils.lib.mkApp {
+      drv = packages.mercurial-rust;
+    };
+
+    packages.mercurial = packages.mercurial-rust;
+    packages.default = packages.mercurial;
+
+    packages.mercurial-c = pin.python.pkgs.buildPythonApplication {
+      format = "other";
+      pname = "mercurial";
+      version = "SNAPSHOT";
+      passthru.exePath = "/bin/hg";
+      inherit src;
+
+      postPatch = ''
+        echo 'version = b"${toString dummyVersion}"' \
+          > mercurial/__version__.py
+
+        patchShebangs .
+
+        for f in **/*.{py,c,t}; do
+          # not only used in shebangs
+          substituteAllInPlace "$f" '/bin/sh' '${pkgs.stdenv.shell}'
+        done
+      '';
+
+      buildInputs = with pin.python.pkgs; [
+        docutils
+      ];
+
+      nativeBuildInputs = with pkgs; [
+        gettext
+        installShellFiles
+      ];
+
+      makeFlags = [
+        "PREFIX=$(out)"
+      ];
+
+      buildPhase = ''
+        make local
+      '';
+
+      # Test suite is huge ; run on-demand in a separate package instead.
+      doCheck = false;
+    };
+
+    packages.mercurial-rust = packages.mercurial-c.overrideAttrs (super: {
+      cargoRoot = "rust";
+      cargoDeps = pkgs.rustPlatform.importCargoLock {
+        lockFile = "${src}/rust/Cargo.lock";
+      };
+
+      nativeBuildInputs = (super.nativeBuildInputs or []) ++ (
+        with pkgs.rustPlatform; [
+          cargoSetupHook
+          rust.cargo
+          rust.rustc
+        ]
+      );
+
+      makeFlags = (super.makeFlags or []) ++ [
+        "PURE=--rust"
+      ];
+    });
+
+    packages.mercurial-tests = pkgs.stdenv.mkDerivation {
+      pname = "mercurial-tests";
+      version = "SNAPSHOT";
+      inherit src;
+
+      buildInputs = with pkgs; [
+        pin.python
+        pin.black
+        unzip
+        which
+        sqlite
+      ];
+
+      postPatch = (packages.mercurial.postPatch or "") + ''
+        # * paths emitted by our wrapped hg look like ..hg-wrapped-wrapped
+        # * 'hg' is a wrapper; don't run using python directly
+        for f in **/*.t; do
+          substituteInPlace 2>/dev/null "$f" \
+            --replace '*/hg:' '*/*hg*:' \
+            --replace '"$PYTHON" "$BINDIR"/hg' '"$BINDIR"/hg'
+        done
+      '';
+
+      buildPhase = ''
+        export HGTEST_REAL_HG="${packages.mercurial}/bin/hg"
+        export HGMODULEPOLICY="rust+c"
+        export HGTESTFLAGS="--blacklist blacklists/nix"
+        make check 2>&1 | tee "$out"
+      '';
+    };
+
+    devShell = flaky-utils.lib.mkDevShell {
+      inherit pkgs;
+
+      tools = [
+        pin.python
+        pin.black
+      ];
+    };
+  });
+}