mirror of
https://github.com/Mic92/nix-update.git
synced 2024-11-03 21:04:49 +03:00
get old version from git
This commit is contained in:
parent
d9d4c02ae7
commit
7344500e46
@ -7,7 +7,11 @@ python3.pkgs.buildPythonApplication rec {
|
||||
src = ./.;
|
||||
buildInputs = [ makeWrapper ];
|
||||
checkInputs = [
|
||||
mypy python3.pkgs.black python3.pkgs.flake8 glibcLocales
|
||||
python3.pkgs.pytest
|
||||
python3.pkgs.black
|
||||
python3.pkgs.flake8
|
||||
glibcLocales
|
||||
mypy
|
||||
# technically not a test input, but we need it for development in PATH
|
||||
nixFlakes
|
||||
];
|
||||
|
@ -62,7 +62,6 @@ def nix_shell(options: Options) -> None:
|
||||
|
||||
|
||||
def git_commit(git_dir: str, attribute: str, package: Package) -> None:
|
||||
|
||||
run(["git", "-C", git_dir, "add", package.filename], stdout=None)
|
||||
diff = run(["git", "-C", git_dir, "diff", "--staged"])
|
||||
if len(diff.stdout) == 0:
|
||||
@ -79,7 +78,7 @@ def git_commit(git_dir: str, attribute: str, package: Package) -> None:
|
||||
)
|
||||
else:
|
||||
with tempfile.NamedTemporaryFile(mode="w") as f:
|
||||
f.write(f"{attribute}:")
|
||||
f.write(f"{attribute}: {package.old_version} -> {package.new_version}")
|
||||
f.flush()
|
||||
run(
|
||||
["git", "-C", git_dir, "commit", "--verbose", "--template", f.name],
|
||||
@ -120,7 +119,9 @@ def validate_git_dir(import_path: str) -> str:
|
||||
def nix_run(options: Options) -> None:
|
||||
cmd = ["nix", "shell", "--experimental-features", "nix-command"]
|
||||
run(
|
||||
cmd + ["-f", options.import_path, options.attribute], stdout=None, check=False,
|
||||
cmd + ["-f", options.import_path, options.attribute],
|
||||
stdout=None,
|
||||
check=False,
|
||||
)
|
||||
|
||||
|
||||
@ -135,7 +136,9 @@ def nix_build(options: Options) -> None:
|
||||
options.attribute,
|
||||
]
|
||||
run(
|
||||
cmd, stdout=None, check=False,
|
||||
cmd,
|
||||
stdout=None,
|
||||
check=False,
|
||||
)
|
||||
|
||||
|
||||
|
@ -1,12 +1,19 @@
|
||||
import json
|
||||
from dataclasses import dataclass
|
||||
from typing import List, Optional
|
||||
from dataclasses import dataclass, InitVar, field
|
||||
from typing import List, Optional, Dict, Any
|
||||
|
||||
from .errors import UpdateError
|
||||
from .options import Options
|
||||
from .utils import run
|
||||
|
||||
|
||||
@dataclass
|
||||
class Position:
|
||||
file: str
|
||||
line: int
|
||||
column: int
|
||||
|
||||
|
||||
@dataclass
|
||||
class Package:
|
||||
attribute: str
|
||||
@ -23,20 +30,32 @@ class Package:
|
||||
cargo_sha256: Optional[str]
|
||||
tests: Optional[List[str]]
|
||||
|
||||
raw_version_position: InitVar[Optional[Dict[str, Any]]]
|
||||
|
||||
new_version: Optional[str] = None
|
||||
version_position: Optional[Position] = field(init=False)
|
||||
|
||||
def __post_init__(self, raw_version_position: Optional[Dict[str, Any]]) -> None:
|
||||
if raw_version_position is None:
|
||||
self.version_position = None
|
||||
else:
|
||||
self.version_position = Position(**raw_version_position)
|
||||
|
||||
|
||||
def eval_expression(import_path: str, attr: str) -> str:
|
||||
return f"""(with import {import_path} {{}};
|
||||
let
|
||||
pkg = {attr};
|
||||
raw_version_position = builtins.unsafeGetAttrPos "version" pkg;
|
||||
|
||||
position = if pkg ? isRubyGem then
|
||||
builtins.unsafeGetAttrPos "version" pkg
|
||||
raw_version_position
|
||||
else
|
||||
builtins.unsafeGetAttrPos "src" pkg;
|
||||
in {{
|
||||
name = pkg.name;
|
||||
old_version = (builtins.parseDrvName pkg.name).version;
|
||||
inherit raw_version_position;
|
||||
filename = position.file;
|
||||
line = position.line;
|
||||
urls = pkg.src.urls or null;
|
||||
|
50
nix_update/git.py
Normal file
50
nix_update/git.py
Normal file
@ -0,0 +1,50 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import subprocess
|
||||
from typing import Optional
|
||||
import re
|
||||
|
||||
|
||||
def old_version_from_diff(
|
||||
diff: str, linenumber: int, new_version: str
|
||||
) -> Optional[str]:
|
||||
current_line = 0
|
||||
old_str = None
|
||||
new_str = None
|
||||
regex = re.compile(r"^@@ -(\d+),(\d+) \+(\d+),(\d+) @@$")
|
||||
for line in diff.split("\n"):
|
||||
match = regex.match(line)
|
||||
if match:
|
||||
current_line = int(match.group(3))
|
||||
elif line.startswith("~"):
|
||||
current_line += 1
|
||||
if current_line > linenumber:
|
||||
return None
|
||||
elif linenumber == current_line and line.startswith("-"):
|
||||
old_str = line[1:]
|
||||
elif linenumber == current_line and line.startswith("+"):
|
||||
if new_version not in line:
|
||||
old_str = None
|
||||
else:
|
||||
new_str = line[1:]
|
||||
break
|
||||
if not new_str or not old_str:
|
||||
return None
|
||||
idx = new_str.index(new_version)
|
||||
prefix = new_str[:idx]
|
||||
suffix = new_str[idx + len(new_version):]
|
||||
return old_str.lstrip(prefix).rstrip(suffix)
|
||||
|
||||
|
||||
def old_version_from_git(
|
||||
filename: str, linenumber: int, new_version: str
|
||||
) -> Optional[str]:
|
||||
proc = subprocess.run(
|
||||
["git", "diff", "--color=never", "--word-diff=porcelain", "--", filename],
|
||||
text=True,
|
||||
stdout=subprocess.PIPE,
|
||||
)
|
||||
assert proc.stdout is not None
|
||||
if len(proc.stdout) == 0:
|
||||
return None
|
||||
return old_version_from_diff(proc.stdout, linenumber, new_version)
|
@ -8,9 +8,10 @@ from .eval import Package, eval_attr
|
||||
from .options import Options
|
||||
from .utils import info, run
|
||||
from .version import fetch_latest_version
|
||||
from .git import old_version_from_git
|
||||
|
||||
|
||||
def update_version(package: Package) -> None:
|
||||
def replace_version(package: Package) -> None:
|
||||
old_version = package.old_version
|
||||
new_version = package.new_version
|
||||
assert new_version is not None
|
||||
@ -90,23 +91,35 @@ def update_cargo_sha256_hash(opts: Options, filename: str, current_hash: str) ->
|
||||
replace_hash(filename, current_hash, target_hash)
|
||||
|
||||
|
||||
def update_version(package: Package, version: str) -> None:
|
||||
if version == "auto":
|
||||
if not package.url:
|
||||
if package.urls:
|
||||
url = package.urls[0]
|
||||
else:
|
||||
raise UpdateError(
|
||||
"Could not find a url in the derivations src attribute"
|
||||
)
|
||||
new_version = fetch_latest_version(url)
|
||||
else:
|
||||
new_version = version
|
||||
package.new_version = new_version
|
||||
position = package.version_position
|
||||
if new_version == package.old_version and position:
|
||||
recovered_version = old_version_from_git(
|
||||
position.file, position.line, new_version
|
||||
)
|
||||
if recovered_version:
|
||||
package.old_version = recovered_version
|
||||
return
|
||||
replace_version(package)
|
||||
|
||||
|
||||
def update(opts: Options) -> Package:
|
||||
package = eval_attr(opts)
|
||||
|
||||
if opts.version != "skip":
|
||||
if opts.version == "auto":
|
||||
if not package.url:
|
||||
if package.urls:
|
||||
url = package.urls[0]
|
||||
else:
|
||||
raise UpdateError(
|
||||
"Could not find a url in the derivations src attribute"
|
||||
)
|
||||
new_version = fetch_latest_version(url)
|
||||
else:
|
||||
new_version = opts.version
|
||||
package.new_version = new_version
|
||||
update_version(package)
|
||||
update_version(package, opts.version)
|
||||
|
||||
update_src_hash(opts, package.filename, package.hash)
|
||||
|
||||
|
21
tests/consul.patch
Normal file
21
tests/consul.patch
Normal file
@ -0,0 +1,21 @@
|
||||
diff --git a/pkgs/servers/consul/default.nix b/pkgs/servers/consul/default.nix
|
||||
index eef9054ae70..334528e7673 100644
|
||||
--- a/pkgs/servers/consul/default.nix
|
||||
+++ b/pkgs/servers/consul/default.nix
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
~
|
||||
buildGoModule rec {
|
||||
~
|
||||
pname = "consul";
|
||||
~
|
||||
version =
|
||||
-"1.8.6";
|
||||
+"1.9.0";
|
||||
~
|
||||
rev = "v${version}";
|
||||
~
|
||||
|
||||
~
|
||||
# Note: Currently only release tags are supported, because they have the Consul UI
|
||||
~
|
16
tests/test_git.py
Normal file
16
tests/test_git.py
Normal file
@ -0,0 +1,16 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
from pathlib import Path
|
||||
from unittest import TestCase
|
||||
from nix_update.git import old_version_from_diff
|
||||
|
||||
|
||||
TEST_ROOT = Path(__file__).parent.resolve()
|
||||
|
||||
|
||||
class WordDiff(TestCase):
|
||||
def test_worddiff(self) -> None:
|
||||
with open(TEST_ROOT.joinpath("consul.patch")) as f:
|
||||
diff = f.read()
|
||||
s = old_version_from_diff(diff, 5, "1.9.0")
|
||||
self.assertEqual(s, "1.8.6")
|
Loading…
Reference in New Issue
Block a user