diff --git a/nix_update/__init__.py b/nix_update/__init__.py index 164ffba..6bca191 100644 --- a/nix_update/__init__.py +++ b/nix_update/__init__.py @@ -7,7 +7,7 @@ from typing import NoReturn, Optional from .eval import Package from .options import Options from .update import update -from .utils import run +from .utils import run, is_nix_flakes def die(msg: str) -> NoReturn: @@ -48,14 +48,13 @@ def parse_args() -> Options: def nix_shell(options: Options) -> None: - with tempfile.NamedTemporaryFile(mode="w") as f: - f.write( - f""" - with import {options.import_path}; mkShell {{ buildInputs = [ {options.attribute} ]; }} - """ - ) - f.flush() - run(["nix-shell", f.name], stdout=None, check=False) + import_path = os.path.realpath(options.import_path) + expr = f"with import {import_path} {{}}; mkShell {{ buildInputs = [ {options.attribute} ]; }}" + with tempfile.TemporaryDirectory() as d: + path = os.path.join(d, "default.nix") + with open(path, "w") as f: + f.write(expr) + run(["nix-shell", path], stdout=None, check=False) def git_commit(git_dir: str, attribute: str, package: Package) -> None: @@ -115,24 +114,26 @@ def validate_git_dir(import_path: str) -> str: def nix_run(options: Options) -> None: + if is_nix_flakes(): + cmd = ["nix", "shell", "--experimental-features", "nix-command"] + else: + cmd = ["nix", "run"] run( - ["nix", "run", "-f", options.import_path, options.attribute], - stdout=None, - check=False, + cmd + ["-f", options.import_path, options.attribute], stdout=None, check=False, ) def nix_build(options: Options) -> None: + cmd = ["nix", "build"] + if is_nix_flakes(): + cmd += ["--experimental-features", "nix-command"] run( - ["nix", "build", "-f", options.import_path, options.attribute], - stdout=None, - check=False, + cmd + ["-f", options.import_path, options.attribute], stdout=None, check=False, ) def main() -> None: options = parse_args() - if not os.path.exists(options.import_path): die(f"path {options.import_path} does not exists") diff --git a/nix_update/eval.py b/nix_update/eval.py index f9b6452..8d6f5f8 100644 --- a/nix_update/eval.py +++ b/nix_update/eval.py @@ -4,7 +4,7 @@ from typing import List, Optional from .errors import UpdateError from .options import Options -from .utils import run +from .utils import run, is_nix_flakes @dataclass @@ -48,9 +48,21 @@ def eval_expression(import_path: str, attr: str) -> str: def eval_attr(opts: Options) -> Package: - res = run( - ["nix", "eval", "--json", eval_expression(opts.import_path, opts.attribute)] - ) + expr = eval_expression(opts.import_path, opts.attribute) + if is_nix_flakes(): + cmd = [ + "nix", + "eval", + "--json", + "--impure", + "--experimental-features", + "nix-command", + "--expr", + expr, + ] + else: + cmd = ["nix", "eval", "--json", expr] + res = run(cmd) out = json.loads(res.stdout) package = Package(**out) if package.old_version == "": diff --git a/nix_update/utils.py b/nix_update/utils.py index 9606d4b..5df2256 100644 --- a/nix_update/utils.py +++ b/nix_update/utils.py @@ -3,6 +3,7 @@ import subprocess import sys from pathlib import Path from typing import IO, Any, Callable, List, Optional, Union +from functools import lru_cache HAS_TTY = sys.stdout.isatty() ROOT = Path(os.path.dirname(os.path.realpath(__file__))) @@ -22,6 +23,15 @@ warn = color_text(31, file=sys.stderr) info = color_text(32) +@lru_cache(maxsize=None) +def is_nix_flakes() -> bool: + try: + subprocess.run(["nix", "flake", "--help"], stdout=subprocess.DEVNULL) + except subprocess.CalledProcessError: + return False + return True + + def run( command: List[str], cwd: Optional[Union[Path, str]] = None,