Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix changing branch of pins with 'git+ssh://' and 'xyz+https://' urls #1722

Merged
merged 1 commit into from
Jul 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions src/alire/alire-user_pins.adb
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ with Alire.Utils.User_Input;
with Alire.Utils.TTY;
with Alire.VFS;

with Ada.Strings.Unbounded;
with AAA.Strings;

with GNAT.OS_Lib;

package body Alire.User_Pins is
Expand Down Expand Up @@ -465,6 +468,8 @@ package body Alire.User_Pins is
-----------------

function Load_Remote return Pin is
use Ada.Strings.Unbounded;
use AAA.Strings;
Result : Pin :=
(Kind => To_Git,
URL => +This.Checked_Pop (Keys.URL,
Expand All @@ -473,6 +478,21 @@ package body Alire.User_Pins is
Commit => <>,
Local_Path => <>);
begin
-- "git+ssh://"" and "ssh+git://" are deprecated, so treat them as
-- identical to "ssh://"
if Has_Prefix (To_String (Result.URL), "git+ssh://")
or else Has_Prefix (To_String (Result.URL), "ssh+git://")
then
Replace_Slice (Result.URL, 1, 7, "ssh");
end if;

-- Likewise, anything of the form "xyz+https://" should be treated
-- as just "https://"
if Contains (To_String (Result.URL), "+http") then
Result.URL := To_Unbounded_String
(Tail (To_String (Result.URL), '+'));
end if;

if This.Contains (Keys.Branch)
and then This.Contains (Keys.Commit)
then
Expand Down
98 changes: 98 additions & 0 deletions testsuite/tests/pin/branch-remote-protocols/test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
"""
Check pinning to branches with "git+ssh://" and "xyz+https://" urls
"""

import os
import subprocess

from drivers.alr import alr_pin, alr_unpin, init_local_crate
from drivers.helpers import init_git_repo, git_branch
from drivers.asserts import assert_eq


# Create a crate with differing branches.
init_local_crate(name="remote", enter=False)
LOCAL_REPO_PATH = os.path.join(os.getcwd(), "remote")
# On the default branch, test_file contains "This is the main branch.\n".
test_file_path = os.path.join(LOCAL_REPO_PATH, "test_file")
with open(test_file_path, "w") as f:
f.write("This is the main branch.\n")
init_git_repo("remote")
os.chdir("remote")
default_branch = git_branch()
# On the "other" branch, test_file contains "This is the other branch.\n".
subprocess.run(["git", "checkout", "-b", "other"]).check_returncode()
with open(test_file_path, "w") as f:
f.write("This is the other branch.\n")
subprocess.run(["git", "add", "test_file"]).check_returncode()
subprocess.run(["git", "commit", "-m", "Change test_file"]).check_returncode()
# Return to the default branch
subprocess.run(["git", "checkout", default_branch]).check_returncode()
os.chdir("..")


# Prepare a directory on PATH at which to mock git.
ACTUAL_GIT_PATH = (
subprocess.run(["bash", "-c", "type -p git"], capture_output=True)
.stdout.decode()
.strip()
)
MOCK_PATH = os.path.join(os.getcwd(), "mock_path")
os.mkdir(MOCK_PATH)
os.environ["PATH"] = f'{MOCK_PATH}:{os.environ["PATH"]}'


# Perform the actual tests
URLs = [
"git+ssh://ssh.gitlab.company-name.com/path/to/repo.git",
"xyz+https://github.com/path/to/repo.git",
]
SANITISED_URLS = [
"ssh://ssh.gitlab.company-name.com/path/to/repo.git",
"https://github.com/path/to/repo.git",
]
CACHE_TEST_FILE_PATH = "alire/cache/pins/remote/test_file"
for URL, S_URL in zip(URLs, SANITISED_URLS):
# Mock git with a wrapper that naively converts the url into the local path
# to the "remote" crate.
wrapper_script = "\n".join(
[
"#! /usr/bin/env python",
"import subprocess, sys",
'if sys.argv[1:] == ["config", "--list"]:',
f' print("remote.origin.url={S_URL}\\n")',
"else:",
" args = [",
f' ("{LOCAL_REPO_PATH}" if a == "{S_URL}" else a)',
" for a in sys.argv[1:]",
" ]",
f' subprocess.run(["{ACTUAL_GIT_PATH}"] + args).check_returncode()',
]
)
wrapper_descriptor = os.open(
os.path.join(MOCK_PATH, "git"),
flags=(os.O_WRONLY | os.O_CREAT | os.O_TRUNC),
mode=0o764,
)
with open(wrapper_descriptor, "w") as f:
f.write(wrapper_script)

# Create an empty crate, and pin the default branch of the test repo
init_local_crate()
alr_pin("remote", url=URL, branch=default_branch)
with open(CACHE_TEST_FILE_PATH) as f:
assert_eq("This is the main branch.\n", f.read())

# Edit pin to point to the other branch, and verify the cached copy changes
# as it should
alr_unpin("remote", update=False)
alr_pin("remote", url=URL, branch="other")
with open(CACHE_TEST_FILE_PATH) as f:
assert_eq("This is the other branch.\n", f.read())


# Restore PATH
os.environ["PATH"] = os.environ["PATH"][len(MOCK_PATH) + 1 :]


print("SUCCESS")
4 changes: 4 additions & 0 deletions testsuite/tests/pin/branch-remote-protocols/test.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
driver: python-script
control:
- [SKIP, "skip_linux", "Test is Linux-only"]
indexes: {}
Loading