nix-update/nix_update/eval.py

112 lines
3.3 KiB
Python
Raw Normal View History

2020-03-23 13:38:04 +03:00
import json
from dataclasses import InitVar, dataclass, field
from typing import Any, Dict, List, Optional
2022-11-24 20:33:58 +03:00
from urllib.parse import ParseResult, urlparse
2020-03-23 13:38:04 +03:00
from .errors import UpdateError
2020-04-21 12:06:55 +03:00
from .options import Options
from .utils import run
2022-11-21 23:07:18 +03:00
from .version.version import Version, VersionPreference
2020-03-23 13:38:04 +03:00
2020-12-01 11:30:17 +03:00
@dataclass
class Position:
file: str
line: int
column: int
2020-03-23 13:38:04 +03:00
@dataclass
class Package:
attribute: str
2020-03-23 13:38:04 +03:00
name: str
2020-03-24 16:25:17 +03:00
old_version: str
2020-03-23 13:38:04 +03:00
filename: str
line: int
urls: Optional[List[str]]
url: Optional[str]
2022-11-24 20:33:58 +03:00
src_homepage: Optional[str]
changelog: Optional[str]
2020-03-23 13:38:04 +03:00
rev: str
hash: Optional[str]
2022-09-17 03:11:22 +03:00
vendor_hash: Optional[str]
2020-05-08 12:21:06 +03:00
vendor_sha256: Optional[str]
cargo_deps: Optional[str]
2022-11-10 18:56:55 +03:00
npm_deps: Optional[str]
tests: List[str]
2020-03-23 13:38:04 +03:00
2020-12-01 11:30:17 +03:00
raw_version_position: InitVar[Optional[Dict[str, Any]]]
2022-11-24 20:33:58 +03:00
parsed_url: Optional[ParseResult] = None
new_version: Optional[Version] = None
2020-12-01 11:30:17 +03:00
version_position: Optional[Position] = field(init=False)
2022-11-24 20:33:58 +03:00
diff_url: Optional[str] = None
2020-12-01 11:30:17 +03:00
def __post_init__(self, raw_version_position: Optional[Dict[str, Any]]) -> None:
2022-11-24 20:33:58 +03:00
url = self.url or (self.urls[0] if self.urls else None)
if url:
self.parsed_url = urlparse(url)
2020-12-01 11:30:17 +03:00
if raw_version_position is None:
self.version_position = None
else:
self.version_position = Position(**raw_version_position)
2020-03-24 16:25:17 +03:00
2020-03-23 13:38:04 +03:00
def eval_expression(import_path: str, attr: str) -> str:
2021-08-15 16:54:09 +03:00
return f"""(
let
inputs = (if (builtins.hasAttr "overlays" (builtins.functionArgs (import {import_path}))) then {{ overlays = []; }} else {{ }});
in
with import {import_path} inputs;
2020-03-23 13:38:04 +03:00
let
pkg = {attr};
2020-12-01 11:30:17 +03:00
raw_version_position = builtins.unsafeGetAttrPos "version" pkg;
2020-04-21 17:16:18 +03:00
position = if pkg ? isRubyGem then
2020-12-01 11:30:17 +03:00
raw_version_position
2020-04-21 17:16:18 +03:00
else
builtins.unsafeGetAttrPos "src" pkg;
2020-03-23 13:38:04 +03:00
in {{
name = pkg.name;
old_version = pkg.version or (builtins.parseDrvName pkg.name).version;
2020-12-01 11:30:17 +03:00
inherit raw_version_position;
filename = position.file;
line = position.line;
2020-03-23 13:38:04 +03:00
urls = pkg.src.urls or null;
url = pkg.src.url or null;
2022-01-15 15:45:51 +03:00
rev = pkg.src.rev or null;
hash = pkg.src.outputHash or null;
2022-09-17 03:11:22 +03:00
vendor_hash = pkg.vendorHash or null;
2020-05-08 12:21:06 +03:00
vendor_sha256 = pkg.vendorSha256 or null;
2022-11-15 04:58:20 +03:00
cargo_deps = (pkg.cargoDeps or null).outputHash or null;
2022-11-20 21:19:07 +03:00
npm_deps = (pkg.npmDeps or null).outputHash or null;
tests = builtins.attrNames (pkg.passthru.tests or {{}});
2022-11-24 20:33:58 +03:00
src_homepage = pkg.src.meta.homepage or null;
changelog = pkg.meta.changelog or null;
2020-03-23 13:38:04 +03:00
}})"""
def eval_attr(opts: Options) -> Package:
expr = eval_expression(opts.import_path, opts.attribute)
cmd = [
"nix",
"eval",
"--json",
"--impure",
"--extra-experimental-features",
"nix-command",
"--expr",
expr,
]
res = run(cmd)
2020-03-23 13:38:04 +03:00
out = json.loads(res.stdout)
package = Package(attribute=opts.attribute, **out)
if opts.override_filename is not None:
package.filename = opts.override_filename
if opts.version_preference != VersionPreference.SKIP and package.old_version == "":
2020-03-23 13:38:04 +03:00
raise UpdateError(
f"Nix's builtins.parseDrvName could not parse the version from {package.name}"
)
return package