feat!: token support for cloning

This commit is contained in:
2026-06-27 22:57:58 +03:00
parent 28f1fda048
commit 206a8730a8
11 changed files with 336 additions and 45 deletions
+37 -6
View File
@@ -2,27 +2,58 @@ from tempfile import NamedTemporaryFile
import pytest
from src.config import Config, read_toml_config
from src.config import Config, FetchConfig, read_toml_config
@pytest.mark.parametrize(
"config_data, expected",
[
(
'[main]\ntoken = "something"\n'
'[main]\napi_token = "something"\n'
'format = "{owner}/{name}"\n'
'ssh_key = "/tmp/no_key"\n'
'endpoint = "https://example.com"\n'
'out_dir = "/home/user/repositories"',
'out_dir = "/home/user/repositories"\n'
"\n"
"[fetch]\n"
'ssh_key = "/tmp/no_key"',
Config(
token="something",
api_token="something",
repository_format="{owner}/{name}",
out_dir="/home/user/repositories",
endpoint="https://example.com",
ssh_key_path="/tmp/no_key",
fetch=FetchConfig(ssh_key="/tmp/no_key"),
),
),
(
'[main]\napi_token = "something"\n'
'format = "{owner}/{name}"\n'
'endpoint = "https://example.com"\n'
'out_dir = "/home/user/repositories"\n'
"\n"
"[fetch]\n"
'user = "alex"\n'
'token = "repo-token"',
Config(
api_token="something",
repository_format="{owner}/{name}",
out_dir="/home/user/repositories",
endpoint="https://example.com",
fetch=FetchConfig(user="alex", token="repo-token"),
),
),
("[main]", None),
(
'[main]\napi_token = "something"\n'
'format = "{owner}/{name}"\n'
'endpoint = "https://example.com"\n'
'out_dir = "/home/user/repositories"\n'
"\n"
"[fetch]\n"
'ssh_key = "/tmp/no_key"\n'
'user = "alex"\n'
'token = "repo-token"',
None,
),
("not valid toml", None),
],
)
+72
View File
@@ -0,0 +1,72 @@
import base64
import os
import subprocess
from src.git import git_clone, git_pull, http_git_env, ssh_git_env
def test_ssh_git_env_uses_requested_identity_file():
env = ssh_git_env("/tmp/test_key")
assert env == {
"GIT_SSH_COMMAND": "ssh -i /tmp/test_key -o IdentitiesOnly=yes"
}
def test_ssh_git_env_quotes_identity_file_path():
env = ssh_git_env("/tmp/test key")
assert env == {
"GIT_SSH_COMMAND": "ssh -i '/tmp/test key' -o IdentitiesOnly=yes"
}
def test_http_git_env_uses_basic_auth_header_without_url_credentials():
env = http_git_env(user="alex", token="secret")
expected_credentials = base64.b64encode(b"alex:secret").decode("ascii")
assert env == {
"GIT_CONFIG_COUNT": "1",
"GIT_CONFIG_KEY_0": "http.extraHeader",
"GIT_CONFIG_VALUE_0": f"Authorization: Basic {expected_credentials}",
}
def test_git_clone_passes_url_and_env_to_git(monkeypatch, tmp_path):
calls = []
env = {"GIT_SSH_COMMAND": "ssh -i /tmp/test_key -o IdentitiesOnly=yes"}
def fake_check_call(args, cwd, env):
calls.append((args, cwd, env))
monkeypatch.setattr(subprocess, "check_call", fake_check_call)
assert git_clone(
repository_url="ssh://git@example.com/owner/repo.git",
repository=str(tmp_path),
env=env,
)
args, cwd, actual_env = calls[0]
assert args == ["git", "clone", "ssh://git@example.com/owner/repo.git", "."]
assert cwd == str(tmp_path)
assert os.environ.items() <= actual_env.items()
assert env.items() <= actual_env.items()
def test_git_pull_passes_env_to_git(monkeypatch, tmp_path):
calls = []
env = {"GIT_CONFIG_COUNT": "1"}
def fake_check_call(args, cwd, env):
calls.append((args, cwd, env))
monkeypatch.setattr(subprocess, "check_call", fake_check_call)
assert git_pull(repository=str(tmp_path), env=env)
args, cwd, actual_env = calls[0]
assert args == ["git", "pull"]
assert cwd == str(tmp_path)
assert os.environ.items() <= actual_env.items()
assert env.items() <= actual_env.items()
+119
View File
@@ -0,0 +1,119 @@
import datetime
import importlib.util
from pathlib import Path
from src.config import Config, FetchConfig
from src.models import GiteaRepository, GiteaUser
def load_mirror_module():
module_path = Path(__file__).parent.parent / "gitea-mirror.py"
spec = importlib.util.spec_from_file_location("gitea_mirror", module_path)
module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(module)
return module
def make_repo() -> GiteaRepository:
return GiteaRepository(
ssh_url="ssh://git@example.com/alex/repo.git",
clone_url="https://example.com/alex/repo.git",
name="repo",
id=42,
updated_at=datetime.datetime.now(),
owner=GiteaUser(
id=23,
login="alex",
email="alex@example.com",
),
)
def make_config(tmp_path, fetch: FetchConfig) -> Config:
return Config(
api_token="api-token",
endpoint="https://example.com",
repository_format="{owner}/{name}",
out_dir=str(tmp_path),
fetch=fetch,
)
def test_process_repo_clones_with_ssh_url_and_key_env(monkeypatch, tmp_path):
mirror = load_mirror_module()
calls = []
def fake_git_clone(repository_url, repository, env):
calls.append((repository_url, repository, env))
return True
monkeypatch.setattr(mirror, "git_clone", fake_git_clone)
mirror.process_repo(
config=make_config(tmp_path, FetchConfig(ssh_key="/tmp/test_key")),
repo=make_repo(),
)
assert calls == [
(
"ssh://git@example.com/alex/repo.git",
str(tmp_path / "alex" / "repo"),
{
"GIT_SSH_COMMAND": (
"ssh -i /tmp/test_key -o IdentitiesOnly=yes"
),
},
)
]
def test_process_repo_clones_with_https_url_and_auth_env(monkeypatch, tmp_path):
mirror = load_mirror_module()
calls = []
def fake_git_clone(repository_url, repository, env):
calls.append((repository_url, repository, env))
return True
monkeypatch.setattr(mirror, "git_clone", fake_git_clone)
mirror.process_repo(
config=make_config(tmp_path, FetchConfig(user="alex", token="secret")),
repo=make_repo(),
)
repository_url, repository, env = calls[0]
assert repository_url == "https://example.com/alex/repo.git"
assert repository == str(tmp_path / "alex" / "repo")
assert env["GIT_CONFIG_COUNT"] == "1"
assert env["GIT_CONFIG_KEY_0"] == "http.extraHeader"
assert env["GIT_CONFIG_VALUE_0"].startswith("Authorization: Basic ")
def test_process_repo_pulls_existing_repo_with_fetch_env(monkeypatch, tmp_path):
mirror = load_mirror_module()
calls = []
repo_path = tmp_path / "alex" / "repo" / ".git"
repo_path.mkdir(parents=True)
def fake_git_pull(repository, env):
calls.append((repository, env))
return True
monkeypatch.setattr(mirror, "git_pull", fake_git_pull)
mirror.process_repo(
config=make_config(tmp_path, FetchConfig(ssh_key="/tmp/test_key")),
repo=make_repo(),
)
assert calls == [
(
str(tmp_path / "alex" / "repo"),
{
"GIT_SSH_COMMAND": (
"ssh -i /tmp/test_key -o IdentitiesOnly=yes"
),
},
)
]