@@ -61,3 +61,76 @@ def git_clone(
6161 )
6262
6363 return output_dir
64+
65+
66+ def git_clone_fast (
67+ * ,
68+ output_dir : pathlib .Path ,
69+ repo_url : str ,
70+ ref : str = "HEAD" ,
71+ ) -> None :
72+ """Efficient, blobless git clone with all submodules
73+
74+ The function clones a git repository with submodules with a blob filter.
75+ A blobless clone contains the full git history but no blobs. Blobs are
76+ downloaded on demand. Pip's VCS feature uses similar tricks to speed
77+ up builds from a VCS URL.
78+
79+ The *ref* parameter can be any tree-ish reference like a commit, tag, or
80+ branch. To force a tag, use ``refs/tags/v1.0`` to fetch the ``v1.0`` tag.
81+
82+ Like in :command:`pip`, submodules are automatically cloned recursively.
83+
84+ .. note::
85+
86+ :command:`git` and ``libcurl`` do not support :envvar:`NETRC`. Use
87+ :file:`~/.netrc` or :file:`.gitconfig` for authentication.
88+ """
89+ parsed_url = urlparse (repo_url )
90+ # Create a clean URL without any credentials for logging
91+ clean_url = parsed_url ._replace (netloc = parsed_url .hostname or "" ).geturl ()
92+ logger .info (
93+ "cloning %s, tree-ish %r, into %s" ,
94+ clean_url ,
95+ ref ,
96+ output_dir ,
97+ )
98+
99+ # Clone repo without blobs, don't check out HEAD
100+ cmd : list [str ]
101+ cmd = [
102+ "git" ,
103+ "clone" ,
104+ "--filter=blob:none" ,
105+ "--no-checkout" ,
106+ repo_url ,
107+ str (output_dir ),
108+ ]
109+ external_commands .run (cmd , network_isolation = False )
110+
111+ # check out reference / tag
112+ logger .debug ("check out ref" )
113+ cmd = [
114+ "git" ,
115+ "checkout" ,
116+ ref ,
117+ ]
118+ external_commands .run (cmd , cwd = str (output_dir ), network_isolation = False )
119+
120+ # clone submodules if ".gitmodules" exist.
121+ if output_dir .joinpath (".gitmodules" ).is_file ():
122+ # recursive clone of all submodules, filter out unnecessary blobs,
123+ # 4 jobs in parallel
124+ logger .debug ("update submodules" )
125+ cmd = [
126+ "git" ,
127+ "submodule" ,
128+ "update" ,
129+ "--init" ,
130+ "--recursive" ,
131+ "--filter=blob:none" ,
132+ "--jobs=4" ,
133+ ]
134+ external_commands .run (cmd , cwd = str (output_dir ), network_isolation = False )
135+ else :
136+ logger .debug ("no .gitmodules file" )
0 commit comments