[ Web Proxy ]
URL:
Viewing: https://raw.githubusercontent.com/QuantStack/git2cpp/main/test/test_clone.py [Back]  [Original]

import subprocess

import pytest

from .conftest import GIT2CPP_TEST_WASM, get_filemode_lines, set_filemode

xsimd_url = "https://github.com/xtensor-stack/xsimd.git"
xtl_url = "https://github.com/xtensor-stack/xtl.git"


def test_clone(git2cpp_path, tmp_path, run_in_tmp_path):
    clone_cmd = [git2cpp_path, "clone", xtl_url]
    p_clone = subprocess.run(clone_cmd, capture_output=True, cwd=tmp_path, text=True)
    assert p_clone.returncode == 0

    assert (tmp_path / "xtl").exists()
    assert (tmp_path / "xtl/include").exists()


def test_clone_is_bare(git2cpp_path, tmp_path, run_in_tmp_path):
    clone_cmd = [git2cpp_path, "clone", "--bare", xtl_url]
    p_clone = subprocess.run(clone_cmd, capture_output=True, cwd=tmp_path, text=True)
    assert p_clone.returncode == 0

    assert (tmp_path / "xtl").is_dir()

    status_cmd = [git2cpp_path, "status"]
    p_status = subprocess.run(status_cmd, capture_output=True, cwd=tmp_path / "xtl", text=True)
    assert p_status.returncode != 0
    assert "This operation is not allowed against bare repositories" in p_status.stderr

    branch_cmd = [git2cpp_path, "branch"]
    p_branch = subprocess.run(branch_cmd, capture_output=True, cwd=tmp_path / "xtl", text=True)
    assert p_branch.returncode == 0
    assert p_branch.stdout.strip() == "* master"


def test_clone_shallow(git2cpp_path, tmp_path, run_in_tmp_path):
    clone_cmd = [git2cpp_path, "clone", "--depth", "1", xtl_url]
    p_clone = subprocess.run(clone_cmd, capture_output=True, cwd=tmp_path, text=True)
    assert p_clone.returncode == 0
    assert (tmp_path / "xtl").exists()

    xtl_path = tmp_path / "xtl"

    cmd_log = [git2cpp_path, "log"]
    p_log = subprocess.run(cmd_log, capture_output=True, cwd=xtl_path, text=True)
    assert p_log.returncode == 0
    assert p_log.stdout.count("Author") == 1


@pytest.mark.parametrize("protocol", ["http", "https"])
def test_clone_private_repo(git2cpp_path, tmp_path, run_in_tmp_path, private_test_repo, protocol):
    # Succeeds with correct credentials.
    # Note that http succeeds by redirecting to https.
    username = "abc"  # Can be any non-empty string.
    password = private_test_repo["token"]
    input = f"{username}\n{password}\n"
    repo_path = tmp_path / private_test_repo["repo_name"]
    url = private_test_repo["https_url" if protocol == "https" else "http_url"]

    clone_cmd = [git2cpp_path, "clone", url]
    p_clone = subprocess.run(clone_cmd, capture_output=True, text=True, input=input)
    assert p_clone.returncode == 0
    assert repo_path.exists()
    # Single request for username and password.
    assert p_clone.stdout.count("Username:") == 1
    assert p_clone.stdout.count("Password:") == 1

    status_cmd = [git2cpp_path, "status"]
    p_status = subprocess.run(status_cmd, cwd=repo_path, capture_output=True, text=True)
    assert p_status.returncode == 0
    assert "On branch main" in p_status.stdout
    assert "Your branch is up to date with 'origin/main'" in p_status.stdout


def test_clone_private_repo_fails_then_succeeds(
    git2cpp_path, tmp_path, run_in_tmp_path, private_test_repo
):
    # Fails with wrong credentials, then succeeds with correct ones.
    username = "xyz"  # Can be any non-empty string.
    password = private_test_repo["token"]
    input = f"wrong1\nwrong2\n{username}\n{password}"
    repo_path = tmp_path / private_test_repo["repo_name"]

    clone_cmd = [git2cpp_path, "clone", private_test_repo["https_url"]]
    p_clone = subprocess.run(clone_cmd, capture_output=True, text=True, input=input)
    assert p_clone.returncode == 0
    assert repo_path.exists()
    # Two requests for username and password.
    assert p_clone.stdout.count("Username:") == 2
    assert p_clone.stdout.count("Password:") == 2

    status_cmd = [git2cpp_path, "status"]
    p_status = subprocess.run(status_cmd, cwd=repo_path, capture_output=True, text=True)
    assert p_status.returncode == 0
    assert "On branch main" in p_status.stdout
    assert "Your branch is up to date with 'origin/main'" in p_status.stdout


def test_clone_private_repo_fails_on_no_username(
    git2cpp_path, tmp_path, run_in_tmp_path, private_test_repo
):
    input = "\n"
    repo_path = tmp_path / private_test_repo["repo_name"]

    clone_cmd = [git2cpp_path, "clone", private_test_repo["https_url"]]
    p_clone = subprocess.run(clone_cmd, capture_output=True, text=True, input=input)

    assert p_clone.returncode != 0
    assert "No username specified" in p_clone.stderr
    assert not repo_path.exists()
    assert p_clone.stdout.count("Username:") == 1
    assert p_clone.stdout.count("Password:") == 0


def test_clone_private_repo_fails_on_no_password(
    git2cpp_path, tmp_path, run_in_tmp_path, private_test_repo
):
    input = "username\n\n"  # Note no password between the \n

    repo_path = tmp_path / private_test_repo["repo_name"]

    clone_cmd = [git2cpp_path, "clone", private_test_repo["https_url"]]
    p_clone = subprocess.run(clone_cmd, capture_output=True, text=True, input=input)

    assert p_clone.returncode != 0
    assert "No password specified" in p_clone.stderr
    assert not repo_path.exists()
    assert p_clone.stdout.count("Username:") == 1
    assert p_clone.stdout.count("Password:") == 1


def test_clone_private_repo_fails_with_no_credential_callback(
    git2cpp_path, tmp_path, run_in_tmp_path, disable_credential_callback
):
    clone_cmd = [git2cpp_path, "clone", "https://github.com/QuantStack/git2cpp-test-private"]
    p_clone = subprocess.run(clone_cmd, capture_output=True, text=True)

    assert p_clone.returncode != 0
    assert "Cloning into 'git2cpp-test-private'..." in p_clone.stdout
    assert "error: remote authentication required but no callback set" in p_clone.stderr


@pytest.mark.parametrize("protocol", ["http", "https"])
def test_clone_gitlab(git2cpp_path, tmp_path, run_in_tmp_path, protocol):
    repo_url = f"{protocol}://gitlab.quantstack.net/ianthomas23_group/cockle-playground"

    clone_cmd = [git2cpp_path, "clone", repo_url]
    p_clone = subprocess.run(clone_cmd, capture_output=True, cwd=tmp_path, text=True)
    assert p_clone.returncode == 0

    repo_path = tmp_path / "cockle-playground"
    assert repo_path.is_dir()
    assert (repo_path / "src").is_dir()

    status_cmd = [git2cpp_path, "status"]
    p_status = subprocess.run(status_cmd, capture_output=True, cwd=repo_path, text=True)
    assert p_status.returncode == 0
    assert "On branch main" in p_status.stdout
    assert "Your branch is up to date with 'origin/main'" in p_status.stdout


@pytest.mark.skipif(not GIT2CPP_TEST_WASM, reason="Only test in WebAssembly")
def test_clone_timeout(git2cpp_path, tmp_path, run_in_tmp_path):
    # Set very short timeout.
    subprocess.run(["export", "GIT_HTTP_TIMEOUT=0.001"], check=True)

    # Check timeout is set.
    check_env_cmd = ["env"]
    p_check_env = subprocess.run(check_env_cmd, capture_output=True, cwd=tmp_path, text=True)
    assert "GIT_HTTP_TIMEOUT=0.001" in p_check_env.stdout

    # Clone fails with timeout.
    clone_cmd = [git2cpp_path, "clone", xtl_url]
    p_clone = subprocess.run(clone_cmd, capture_output=True, cwd=tmp_path, text=True)
    assert p_clone.returncode != 0
    assert "network request timed out connecting to" in p_clone.stderr
    assert (
        "set a longer timeout in seconds using the environment variable GIT_HTTP_TIMEOUT"
        in p_clone.stderr
    )
    assert "the current value is 0.001 seconds" in p_clone.stderr

    # Set more reasonable timeout.
    subprocess.run(["export", "GIT_HTTP_TIMEOUT=10"], check=True)

    # Check timeout is set.
    p_check_env = subprocess.run(check_env_cmd, capture_output=True, cwd=tmp_path, text=True)
    assert "GIT_HTTP_TIMEOUT=10" in p_check_env.stdout

    # Clone succeeds.
    clone_cmd = [git2cpp_path, "clone", xtl_url]
    p_clone = subprocess.run(clone_cmd, capture_output=True, cwd=tmp_path, text=True)
    assert p_clone.returncode == 0

    assert (tmp_path / "xtl").exists()
    assert (tmp_path / "xtl/include").exists()


@pytest.mark.skipif(not GIT2CPP_TEST_WASM, reason="Only test in WebAssembly")
def test_clone_negative_timeout_ignored(git2cpp_path, tmp_path, run_in_tmp_path):
    # Set negative timeout.
    subprocess.run(["export", "GIT_HTTP_TIMEOUT=-1"], check=True)

    # Check timeout is set.
    check_env_cmd = ["env"]
    p_check_env = subprocess.run(check_env_cmd, capture_output=True, cwd=tmp_path, text=True)
    assert "GIT_HTTP_TIMEOUT=-1" in p_check_env.stdout

    # Clone succeeds, ignoring invalid timeout.
    clone_cmd = [git2cpp_path, "clone", xtl_url]
    p_clone = subprocess.run(clone_cmd, capture_output=True, cwd=tmp_path, text=True)
    assert p_clone.returncode == 0

    assert (tmp_path / "xtl").exists()
    assert (tmp_path / "xtl/include").exists()

    assert (
        "environment variable GIT_HTTP_TIMEOUT must be a positive number of seconds"
        in p_clone.stdout
    )


def test_clone_large_repo(git2cpp_path, tmp_path, run_in_tmp_path):
    clone_cmd = [git2cpp_path, "clone", xsimd_url]
    p_clone = subprocess.run(clone_cmd, capture_output=True, cwd=tmp_path, text=True)
    assert p_clone.returncode == 0

    assert (tmp_path / "xsimd").exists()
    assert (tmp_path / "xsimd/include").exists()
    assert (tmp_path / "xsimd/xsimdConfig.cmake.in").exists()


def test_clone_filemode(git2cpp_path, tmp_path, run_in_tmp_path):
    clone_cmd = [git2cpp_path, "clone", xtl_url]
    p_clone = subprocess.run(clone_cmd, capture_output=True, cwd=tmp_path, text=True)
    assert p_clone.returncode == 0

    xtl_path = tmp_path / "xtl"

    filemode_lines = get_filemode_lines(git2cpp_path, xtl_path)
    if GIT2CPP_TEST_WASM:
        # In WebAssembly core.filemode=false is set by an in-memory config override that has higher
        # priority than the repository's config file, so is listed after it.
        assert filemode_lines == ["core.filemode=true", "core.filemode=false"]
    else:
        assert filemode_lines == ["core.filemode=true"]

    # Setting writes to the repository's config file, not the in-memory override.
    set_filemode(git2cpp_path, xtl_path, "true")
    filemode_lines = get_filemode_lines(git2cpp_path, xtl_path)
    if GIT2CPP_TEST_WASM:
        assert filemode_lines == ["core.filemode=true", "core.filemode=false"]
    else:
        assert filemode_lines == ["core.filemode=true"]

    set_filemode(git2cpp_path, xtl_path, "false")
    filemode_lines = get_filemode_lines(git2cpp_path, xtl_path)
    if GIT2CPP_TEST_WASM:
        assert filemode_lines == ["core.filemode=false", "core.filemode=false"]
    else:
        assert filemode_lines == ["core.filemode=false"]

Web Proxy Viewer  |  New URL  |  Original Page