1313import shutil
1414from typing import Optional
1515
16+ from cfbs .git import ls_remote , treeish_exists
1617from cfbs .utils import (
1718 cfbs_dir ,
1819 cp ,
@@ -136,28 +137,19 @@ def _get_path_from_url(url):
136137 return path
137138
138139
139- def _get_git_repo_commit_sha (repo_path ):
140- assert os .path .isdir (os .path .join (repo_path , ".git" ))
141-
142- with open (os .path .join (repo_path , ".git" , "HEAD" ), "r" ) as f :
143- head_ref_info = f .read ()
144-
145- assert head_ref_info .startswith ("ref: " )
146- head_ref = head_ref_info [5 :].strip ()
147-
148- with open (os .path .join (repo_path , ".git" , head_ref )) as f :
149- return f .read ().strip ()
150-
151-
152140def _clone_and_checkout (url , path , treeish ):
153141 # NOTE: If any of these shell (git) commands fail, we will exit
154142 if not os .path .exists (os .path .join (path , ".git" )):
155143 sh ("git clone --no-checkout %s %s" % (url , path ))
144+ if not treeish_exists (treeish , path ):
145+ raise CFBSExitError ("%s not found in %s" % (treeish , url ))
146+
156147 sh ("git checkout " + treeish , directory = path )
157148
158149
159- def clone_url_repo (repo_url : str , commit : Optional [str ] = None ):
160- """Clones a Git repository at `repo_url` URL, optionally checking out the `commit` commit.
150+ def clone_url_repo (repo_url : str , reference : Optional [str ] = None ):
151+ """Clones a Git repository at `repo_url` URL, optionally checking out the `reference` commit or branch.
152+ If `reference` is `None`, the repository's default branch will be used for the checkout.
161153
162154 Returns path to the `cfbs.json` located in the cloned Git repository, and the Git commit hash.
163155 """
@@ -170,20 +162,23 @@ def clone_url_repo(repo_url: str, commit: Optional[str] = None):
170162 repo_dir = os .path .join (downloads , repo_path )
171163 os .makedirs (repo_dir , exist_ok = True )
172164
173- if commit is not None :
174- commit_path = os .path .join (repo_dir , commit )
175- _clone_and_checkout (repo_url , commit_path , commit )
165+ if reference is None :
166+ reference = "HEAD"
167+
168+ # always store versions of the repository in cfbs/downloads by commit hash
169+ # therefore for branches, first find the commit it points to
170+ if is_a_commit_hash (reference ):
171+ commit = reference
176172 else :
177- master_path = os .path .join (repo_dir , "master" )
178- sh ("git clone %s %s" % (repo_url , master_path ))
179- commit = _get_git_repo_commit_sha (master_path )
180-
181- commit_path = os .path .join (repo_dir , commit )
182- if os .path .exists (commit_path ):
183- # Already cloned in the commit dir, just remove the 'master' clone
184- sh ("rm -rf %s" % master_path )
185- else :
186- sh ("mv %s %s" % (master_path , commit_path ))
173+ # `reference` is a branch
174+ commit = ls_remote (repo_url , reference )
175+ if commit is None :
176+ raise CFBSExitError (
177+ "Failed to find branch %s at %s" % (reference , repo_url )
178+ )
179+
180+ commit_path = os .path .join (repo_dir , commit )
181+ _clone_and_checkout (repo_url , commit_path , commit )
187182
188183 json_path = os .path .join (commit_path , "cfbs.json" )
189184 if os .path .exists (json_path ):
0 commit comments