11"""Fixtures and utilities for testing vcs2l."""
22
33import os
4+ import re
45import shutil
56import subprocess
67import tarfile
@@ -18,115 +19,121 @@ def to_file_url(path):
1819 return urljoin ('file:' , pathname2url (path ))
1920
2021
22+ def extract_commit (url ):
23+ """Extract commit hash from version for zip/tar clients."""
24+ m = re .search (r'vcs2l-([a-f0-9]{40})' , url )
25+ return m .group (1 ) if m else None
26+
27+
28+ def setup_git_repository (temp_dir ):
29+ """Create a git repository for testing."""
30+ repo_root = os .path .dirname (os .path .dirname (__file__ ))
31+ gitrepo_path = os .path .join (temp_dir .name , 'gitrepo' )
32+
33+ subprocess .check_call (['git' , 'clone' , '--branch' , 'main' , repo_root , gitrepo_path ])
34+
35+ return gitrepo_path
36+
37+
38+ def setup_tar_archive (temp_dir , target_commit ):
39+ """Create a tar archive for testing by checking out the target commit."""
40+ gitrepo_path = os .path .join (temp_dir .name , 'gitrepo' )
41+ tar_path = os .path .join (temp_dir .name , 'tar' )
42+
43+ subprocess .check_call (['git' , 'clone' , gitrepo_path , tar_path ])
44+ subprocess .check_call (['git' , 'checkout' , target_commit ], cwd = tar_path )
45+ shutil .rmtree (os .path .join (tar_path , '.git' )) # .git not present in tar archive
46+
47+ archive_dir = os .path .join (temp_dir .name , 'archive' )
48+ os .makedirs (archive_dir , exist_ok = True )
49+ tarball_path = os .path .join (archive_dir , f'{ target_commit } .tar.gz' )
50+
51+ with tarfile .TarFile .open (tarball_path , 'w:gz' ) as tar :
52+ tar .add (tar_path , arcname = f'vcs2l-{ target_commit } ' )
53+
54+ return tarball_path
55+
56+
57+ def setup_zip_archive (temp_dir , target_commit ):
58+ """Create a zip archive for testing by checking out the target commit."""
59+ gitrepo_path = os .path .join (temp_dir .name , 'gitrepo' )
60+ zip_path = os .path .join (temp_dir .name , 'zip' )
61+
62+ subprocess .check_call (['git' , 'clone' , gitrepo_path , zip_path ])
63+ subprocess .check_call (['git' , 'checkout' , target_commit ], cwd = zip_path )
64+ shutil .rmtree (os .path .join (zip_path , '.git' )) # .git not present in zip archive
65+
66+ archive_dir = os .path .join (temp_dir .name , 'archive' )
67+ os .makedirs (archive_dir , exist_ok = True )
68+ zip_path = os .path .join (archive_dir , f'{ target_commit } .zip' )
69+
70+ with zipfile .ZipFile (zip_path , 'w' ) as zipf :
71+ for root , dirs , files in os .walk (zip_path ):
72+ # Add directory entries
73+ for dir_name in dirs :
74+ dir_path = os .path .join (root , dir_name )
75+ arcname = (
76+ os .path .join (
77+ f'vcs2l-{ target_commit } ' , os .path .relpath (dir_path , zip_path )
78+ )
79+ + '/'
80+ )
81+ zipf .write (dir_path , arcname )
82+
83+ # Add files
84+ for file in files :
85+ file_path = os .path .join (root , file )
86+ arcname = os .path .join (
87+ f'vcs2l-{ target_commit } ' , os .path .relpath (file_path , zip_path )
88+ )
89+ zipf .write (file_path , arcname )
90+
91+ return zip_path
92+
93+
2194class StagedReposFile (unittest .TestCase ):
2295 """Fixture for testing git, tar, and zip clients."""
2396
2497 _git = which ('git' )
25- _git_env = {
26- ** os .environ ,
27- 'GIT_AUTHOR_NAME' : 'vcs2l' ,
28- 'GIT_AUTHOR_DATE' : '2005-01-01T00:00:00-06:00' ,
29- 'GIT_AUTHOR_EMAIL' : 'vcs2l@example.com' ,
30- 'GIT_COMMITTER_NAME' : 'vcs2l' ,
31- 'GIT_COMMITTER_DATE' : '2005-01-01T00:00:00-06:00' ,
32- 'GIT_COMMITTER_EMAIL' : 'vcs2l@example.com' ,
33- 'GIT_CONFIG_GLOBAL' : os .path .join (os .path .dirname (__file__ ), '.gitconfig' ),
34- 'LANG' : 'en_US.UTF-8' ,
35- }
36- _commit_date = '2005-01-01T00:00:00'
37-
3898 temp_dir = None
3999 repos_file_path = None
40100
41101 @classmethod
42- def setUpClass (cls ):
102+ def setUpClass (cls , repos_file = None ):
43103 if not cls ._git :
44104 raise unittest .SkipTest ('`git` was not found' )
45105
46106 cls .temp_dir = TemporaryDirectory (suffix = '.vcstmp' )
47107
48- # Create the staged git repository
49- gitrepo_path = os .path .join (cls .temp_dir .name , 'gitrepo' )
50- os .mkdir (gitrepo_path )
51- shutil .copy (
52- os .path .join (os .path .dirname (os .path .dirname (__file__ )), 'LICENSE' ),
53- gitrepo_path ,
54- )
55- for command in (
56- ('init' , '--quiet' , '.' ),
57- ('commit' , '--quiet' , '--allow-empty' , '-m' , '0.1.26' ),
58- ('tag' , '0.1.26' ),
59- ('checkout' , '--quiet' , '-b' , 'license' ),
60- ('add' , 'LICENSE' ),
61- ('commit' , '--quiet' , '-m' , 'Add LICENSE' ),
62- ('checkout' , '--quiet' , 'main' ),
63- ('merge' , '--no-ff' , '--quiet' , 'license' , '-m' , "Merge branch 'license'" ),
64- ('branch' , '--quiet' , '-D' , 'license' ),
65- ('commit' , '--quiet' , '--allow-empty' , '-m' , 'update changelog' ),
66- ('commit' , '--quiet' , '--allow-empty' , '-m' , '0.1.27' ),
67- ('tag' , '0.1.27' ),
68- ('commit' , '--quiet' , '--allow-empty' , '-m' , "codin' codin' codin'" ),
69- ):
70- subprocess .check_call (
71- [
72- cls ._git ,
73- * command ,
74- ],
75- cwd = gitrepo_path ,
76- env = cls ._git_env ,
77- )
108+ if repos_file is None :
109+ raise ValueError ('A repos file must be provided' )
78110
79- # Create the archive stage
80- archive_path = os .path .join (cls .temp_dir .name , 'archive_dir' )
81- os .mkdir (archive_path )
82- with open (os .path .join (archive_path , 'file_name.txt' ), 'wb' ) as f :
83- f .write (b'Lorem Ipsum\n ' )
84-
85- # Create a tar file
86- tarball_path = os .path .join (cls .temp_dir .name , 'archive.tar.gz' )
87- with tarfile .TarFile .open (tarball_path , 'w:gz' ) as f :
88- f .add (archive_path , 'archive_dir' )
89-
90- # Create a zip file
91- zip_path = os .path .join (cls .temp_dir .name , 'archive.zip' )
92- with zipfile .ZipFile (zip_path , mode = 'w' ) as f :
93- f .write (
94- os .path .join (archive_path , 'file_name.txt' ),
95- os .path .join ('archive_dir' , 'file_name.txt' ),
96- )
111+ with open (repos_file , 'r' , encoding = 'utf-8' ) as f :
112+ repos_data = yaml .safe_load (f )
97113
98- # Populate the staged.repos file
99- repos = {
100- 'immutable/hash' : {
101- 'type' : 'git' ,
102- 'url' : to_file_url (gitrepo_path ),
103- 'version' : '5b3504594f7354121cf024dc734bf79e270cffd3' ,
104- },
105- 'immutable/hash_tar' : {
106- 'type' : 'tar' ,
107- 'url' : to_file_url (tarball_path ),
108- 'version' : 'archive_dir' ,
109- },
110- 'immutable/hash_zip' : {
111- 'type' : 'zip' ,
112- 'url' : to_file_url (zip_path ),
113- 'version' : 'archive_dir' ,
114- },
115- 'immutable/tag' : {
116- 'type' : 'git' ,
117- 'url' : to_file_url (gitrepo_path ),
118- 'version' : 'tags/0.1.27' ,
119- },
120- 'vcs2l' : {
121- 'type' : 'git' ,
122- 'url' : to_file_url (gitrepo_path ),
123- 'version' : 'heads/main' ,
124- },
125- 'without_version' : {
126- 'type' : 'git' ,
127- 'url' : to_file_url (gitrepo_path ),
128- },
129- }
114+ repos = repos_data .get ('repositories' )
115+
116+ # Create the temp git repository
117+ gitrepo_path = setup_git_repository (cls .temp_dir )
118+
119+ # Use the existing file as a baseline
120+ repos = repos_data ['repositories' ].copy ()
121+
122+ for repo_name , repo_config in repos .items ():
123+ if repo_config ['type' ] == 'git' :
124+ repos [repo_name ]['url' ] = to_file_url (gitrepo_path )
125+
126+ elif repo_config ['type' ] == 'tar' :
127+ extracted_commit = extract_commit (repo_config ['version' ])
128+ repos [repo_name ]['url' ] = to_file_url (
129+ setup_tar_archive (cls .temp_dir , extracted_commit )
130+ )
131+
132+ elif repo_config ['type' ] == 'zip' :
133+ extracted_commit = extract_commit (repo_config ['version' ])
134+ repos [repo_name ]['url' ] = to_file_url (
135+ setup_zip_archive (cls .temp_dir , extracted_commit )
136+ )
130137
131138 cls .repos_file_path = os .path .join (cls .temp_dir .name , 'staged.repos' )
132139 with open (cls .repos_file_path , 'wb' ) as f :
0 commit comments