get old version from git

This commit is contained in:
Jörg Thalheim 2020-12-01 09:30:17 +01:00
parent d9d4c02ae7
commit 7344500e46
No known key found for this signature in database
GPG Key ID: 003F2096411B5F92
7 changed files with 148 additions and 22 deletions

View File

@ -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
];

View File

@ -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,
)

View File

@ -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
View 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)

View File

@ -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
View 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
View 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")