Skip to content

Commit

Permalink
Fix changing branch of pins with 'git+ssh://' and 'xyz+https://' urls (
Browse files Browse the repository at this point in the history
  • Loading branch information
Seb-MCaw authored Jul 29, 2024
1 parent 16b060b commit 1604866
Show file tree
Hide file tree
Showing 3 changed files with 122 additions and 0 deletions.
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: {}

0 comments on commit 1604866

Please sign in to comment.