diff --git a/nix_update/update.py b/nix_update/update.py index 1c80de8..d886edb 100644 --- a/nix_update/update.py +++ b/nix_update/update.py @@ -314,6 +314,9 @@ def update_version( package.diff_url = f"https://{package.parsed_url.netloc}/{owner}/{repo}/compare/{package.rev}...{new_version.rev or new_version.number}" elif GITLAB_API.match(package.parsed_url.geturl()) and package.src_homepage: package.diff_url = f"{package.src_homepage}-/compare/{package.rev}...{new_version.rev or new_version.number}" + elif package.parsed_url.netloc in ["bitbucket.org", "bitbucket.io"]: + _, owner, repo, *_ = package.parsed_url.path.split("/") + package.diff_url = f"https://{package.parsed_url.netloc}/{owner}/{repo}/branches/compare/{new_version.rev or new_version.number}%0D{package.rev}" return replace_version(package) diff --git a/nix_update/version/__init__.py b/nix_update/version/__init__.py index 458ffec..401c077 100644 --- a/nix_update/version/__init__.py +++ b/nix_update/version/__init__.py @@ -5,6 +5,7 @@ from urllib.parse import ParseResult from ..errors import VersionError +from .bitbucket import fetch_bitbucket_snapshots, fetch_bitbucket_versions from .crate import fetch_crate_versions from .gitea import fetch_gitea_snapshots, fetch_gitea_versions from .github import fetch_github_snapshots, fetch_github_versions @@ -39,12 +40,14 @@ def __call__(self, url: ParseResult, branch: str) -> list[Version]: fetch_rubygem_versions, fetch_savannah_versions, fetch_sourcehut_versions, + fetch_bitbucket_versions, ] branch_snapshots_fetchers: list[SnapshotFetcher] = [ fetch_gitea_snapshots, fetch_github_snapshots, fetch_gitlab_snapshots, + fetch_bitbucket_snapshots, ] diff --git a/nix_update/version/bitbucket.py b/nix_update/version/bitbucket.py new file mode 100644 index 0000000..4d2234c --- /dev/null +++ b/nix_update/version/bitbucket.py @@ -0,0 +1,30 @@ +import json +from urllib.parse import ParseResult +from urllib.request import urlopen + +from .version import Version + + +def fetch_bitbucket_versions(url: ParseResult) -> list[Version]: + if url.netloc not in ["bitbucket.org", "bitbucket.io"]: + return [] + + _, owner, repo, *_ = url.path.split("/") + # paging controlled by pagelen parameter, by default it is 10 + tags_url = f"https://{url.netloc}/!api/2.0/repositories/{owner}/{repo}/refs/tags?sort=-target.date" + resp = urlopen(tags_url) + tags = json.loads(resp.read())["values"] + return [Version(tag["name"]) for tag in tags] + + +def fetch_bitbucket_snapshots(url: ParseResult, branch: str) -> list[Version]: + if url.netloc not in ["bitbucket.org", "bitbucket.io"]: + return [] + + _, owner, repo, *_ = url.path.split("/") + # seems to ignore pagelen parameter (always returns one entry) + commits_url = f'https://{url.netloc}/!api/2.0/repositories/{owner}/{repo}/refs?q=name="{branch}"' + resp = urlopen(commits_url) + ref = json.loads(resp.read())["values"][0]["target"] + date = ref["date"][:10] # to YYYY-MM-DD + return [Version(f"unstable-{date}", rev=ref["hash"])] diff --git a/tests/test_bitbucket.py b/tests/test_bitbucket.py new file mode 100644 index 0000000..d91dc24 --- /dev/null +++ b/tests/test_bitbucket.py @@ -0,0 +1,80 @@ +import subprocess + +import conftest + +from nix_update import main + + +# integration test for bitbucket versions (fetch_bitbucket_versions), mostly +# copied from test_gitea.py. +# run directly with 'nix develop -c pytest -s ./tests/test_bitbucket.py'. +def test_version(helpers: conftest.Helpers) -> None: + with helpers.testpkgs(init_git=True) as path: + main(["--file", str(path), "--commit", "bitbucket"]) + version = subprocess.run( + [ + "nix", + "eval", + "--raw", + "--extra-experimental-features", + "nix-command", + "-f", + path, + "bitbucket.version", + ], + check=True, + text=True, + stdout=subprocess.PIPE, + ).stdout.strip() + assert tuple(map(int, version.split("."))) > (1, 0) + commit = subprocess.run( + ["git", "-C", path, "log", "-1"], + text=True, + stdout=subprocess.PIPE, + check=True, + ).stdout.strip() + print(commit) + assert version in commit + assert "bitbucket" in commit + assert "/jongsoftdev/youless-python-bridge/branches/compare/" in commit + assert "%0D1.0" in commit + + +# integration test for bitbucket snapshots +def test_snapshot(helpers: conftest.Helpers) -> None: + with helpers.testpkgs(init_git=True) as path: + main( + [ + "--file", + str(path), + "--commit", + "--version=branch=master", + "bitbucket-snapshot", + ] + ) + version = subprocess.run( + [ + "nix", + "eval", + "--raw", + "--extra-experimental-features", + "nix-command", + "-f", + path, + "bitbucket-snapshot.version", + ], + check=True, + text=True, + stdout=subprocess.PIPE, + ).stdout.strip() + commit = subprocess.run( + ["git", "-C", path, "log", "-1"], + text=True, + stdout=subprocess.PIPE, + check=True, + ).stdout.strip() + print(commit) + assert version in commit + assert "bitbucket" in commit + assert "/jongsoftdev/youless-python-bridge/branches/compare/" in commit + assert "%0Dc04342ef36dd5ba8f7d9b9fce2fb4926ef401fd5" in commit diff --git a/tests/testpkgs/bitbucket.nix b/tests/testpkgs/bitbucket.nix new file mode 100644 index 0000000..affd956 --- /dev/null +++ b/tests/testpkgs/bitbucket.nix @@ -0,0 +1,28 @@ +{ stdenv, fetchFromBitbucket, isSnapshot }: + +let + # Why this package? No reason, I just found a small package that uses tags + # for release by grepping through nixpkgs for fetchFromBitbucket. + owner = "jongsoftdev"; + repo = "youless-python-bridge"; + # As of 2023-11-22, latest version is 1.0.1, so we will be testing that it + # finds a version greater than 1.0. The rev from 2022-10-01 is an untagged + # commit. + version = + if (isSnapshot) + then "unstable-2022-10-01" + else "1.0"; + rev = + if (isSnapshot) + then "c04342ef36dd5ba8f7d9b9fce2fb4926ef401fd5" + else "1.0"; +in +stdenv.mkDerivation rec { + pname = repo; + inherit version; + src = fetchFromBitbucket { + inherit owner repo version rev; + # dont care about hash + hash = "sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA="; + }; +} diff --git a/tests/testpkgs/default.nix b/tests/testpkgs/default.nix index 28d535f..0da7f34 100644 --- a/tests/testpkgs/default.nix +++ b/tests/testpkgs/default.nix @@ -1,5 +1,7 @@ { pkgs ? import { } }: { + bitbucket = pkgs.callPackage ./bitbucket.nix { isSnapshot = false; }; + bitbucket-snapshot = pkgs.callPackage ./bitbucket.nix { isSnapshot = true; }; cargoLock.expand = pkgs.callPackage ./cargo-lock-expand { }; cargoLock.update = pkgs.callPackage ./cargo-lock-update { }; crate = pkgs.callPackage ./crate.nix { };