0
# Repository Handling
1
2
Support for Git repositories, zip files, and URL-based templates with automatic cloning, extraction, and local caching. This module enables cookiecutter to work with templates from various sources including local directories, remote Git repositories, and zip archives.
3
4
## Capabilities
5
6
### Repository Detection and Processing
7
8
Determine repository type and locate template directories from various sources.
9
10
```python { .api }
11
def determine_repo_dir(
12
template,
13
abbreviations,
14
clone_to_dir,
15
checkout,
16
no_input,
17
password=None,
18
directory=None
19
):
20
"""
21
Locate repository directory from template reference.
22
23
Parameters:
24
- template: str - Template path, URL, or abbreviation
25
- abbreviations: dict - Repository abbreviations (e.g., 'gh' -> GitHub URL)
26
- clone_to_dir: str - Directory to clone repositories into
27
- checkout: str, optional - Branch, tag, or commit to checkout
28
- no_input: bool - Whether to prompt user for input
29
- password: str, optional - Password for protected repositories
30
- directory: str, optional - Subdirectory within repository containing template
31
32
Returns:
33
tuple - (repo_directory_path, should_cleanup_bool)
34
"""
35
36
def repository_has_cookiecutter_json(repo_directory):
37
"""
38
Check if directory contains cookiecutter.json.
39
40
Parameters:
41
- repo_directory: str - Directory path to check
42
43
Returns:
44
bool - True if cookiecutter.json exists in directory
45
"""
46
```
47
48
### URL and Path Analysis
49
50
Analyze template references to determine their type and format.
51
52
```python { .api }
53
def is_repo_url(value):
54
"""
55
Check if value is a repository URL.
56
57
Parameters:
58
- value: str - Value to check
59
60
Returns:
61
bool - True if value appears to be a repository URL
62
"""
63
64
def is_zip_file(value):
65
"""
66
Check if value is a zip file.
67
68
Parameters:
69
- value: str - Value to check (file path or URL)
70
71
Returns:
72
bool - True if value appears to be a zip file
73
"""
74
75
def expand_abbreviations(template, abbreviations):
76
"""
77
Expand template name abbreviations.
78
79
Parameters:
80
- template: str - Template reference (may contain abbreviation)
81
- abbreviations: dict - Abbreviation mapping (e.g., 'gh' -> GitHub URL pattern)
82
83
Returns:
84
str - Expanded template URL or original template if no abbreviation
85
"""
86
```
87
88
### Version Control Operations
89
90
Clone repositories using Git or Mercurial.
91
92
```python { .api }
93
def clone(repo_url, checkout=None, clone_to_dir=".", no_input=False):
94
"""
95
Clone repository to directory.
96
97
Parameters:
98
- repo_url: str - Repository URL to clone
99
- checkout: str, optional - Branch, tag, or commit to checkout after clone
100
- clone_to_dir: str - Directory to clone into
101
- no_input: bool - Whether to prompt for user input on conflicts
102
103
Returns:
104
str - Path to cloned repository directory
105
"""
106
107
def identify_repo(repo_url):
108
"""
109
Determine if repo URL is git or hg.
110
111
Parameters:
112
- repo_url: str - Repository URL
113
114
Returns:
115
str - Repository type ('git' or 'hg')
116
"""
117
118
def is_vcs_installed(repo_type):
119
"""
120
Check if VCS is installed.
121
122
Parameters:
123
- repo_type: str - Version control system type ('git' or 'hg')
124
125
Returns:
126
bool - True if VCS is available on the system
127
"""
128
```
129
130
### Zip File Handling
131
132
Download and extract zip archives containing templates.
133
134
```python { .api }
135
def unzip(zip_uri, is_url, clone_to_dir=".", no_input=False, password=None):
136
"""
137
Download and unpack zipfile from URI.
138
139
Parameters:
140
- zip_uri: str - URI to zip file (local path or URL)
141
- is_url: bool - Whether zip_uri is a URL or local path
142
- clone_to_dir: str - Directory to extract zip contents
143
- no_input: bool - Whether to prompt for user input
144
- password: str, optional - Password for protected zip files
145
146
Returns:
147
str - Path to extracted directory
148
"""
149
```
150
151
## Repository Constants
152
153
```python { .api }
154
REPO_REGEX: Pattern # Regex pattern for matching repository URLs
155
156
BRANCH_ERRORS: list # List of branch-related error strings for VCS operations
157
```
158
159
## Usage Examples
160
161
### Working with Git Repositories
162
163
```python
164
from cookiecutter.repository import determine_repo_dir, clone
165
from cookiecutter.config import get_user_config
166
167
# Get user configuration for abbreviations
168
config = get_user_config()
169
170
# Determine repository directory from GitHub URL
171
repo_dir, cleanup = determine_repo_dir(
172
template='https://github.com/audreyfeldroy/cookiecutter-pypackage.git',
173
abbreviations=config['abbreviations'],
174
clone_to_dir=config['cookiecutters_dir'],
175
checkout='master',
176
no_input=True
177
)
178
179
# Direct cloning
180
cloned_path = clone(
181
repo_url='https://github.com/user/template-repo.git',
182
checkout='v2.0.0',
183
clone_to_dir='./templates'
184
)
185
```
186
187
### Using Repository Abbreviations
188
189
```python
190
from cookiecutter.repository import expand_abbreviations, determine_repo_dir
191
from cookiecutter.config import BUILTIN_ABBREVIATIONS
192
193
# Expand GitHub abbreviation
194
full_url = expand_abbreviations(
195
'gh:audreyfeldroy/cookiecutter-pypackage',
196
BUILTIN_ABBREVIATIONS
197
)
198
# Returns: 'https://github.com/audreyfeldroy/cookiecutter-pypackage.git'
199
200
# Use with custom abbreviations
201
custom_abbrevs = {
202
'gh': 'https://github.com/{}.git',
203
'company': 'https://git.company.com/{}.git'
204
}
205
206
company_url = expand_abbreviations(
207
'company:internal/python-template',
208
custom_abbrevs
209
)
210
# Returns: 'https://git.company.com/internal/python-template.git'
211
```
212
213
### Working with Zip Files
214
215
```python
216
from cookiecutter.repository import unzip, is_zip_file
217
218
# Check if source is a zip file
219
template_source = 'https://github.com/user/template/archive/master.zip'
220
if is_zip_file(template_source):
221
# Extract zip file
222
extracted_path = unzip(
223
zip_uri=template_source,
224
is_url=True,
225
clone_to_dir='./templates',
226
password=None
227
)
228
print(f"Template extracted to: {extracted_path}")
229
230
# Local zip file
231
local_zip = './my-template.zip'
232
if is_zip_file(local_zip):
233
extracted_path = unzip(
234
zip_uri=local_zip,
235
is_url=False,
236
clone_to_dir='./templates'
237
)
238
```
239
240
### Repository Validation
241
242
```python
243
from cookiecutter.repository import (
244
repository_has_cookiecutter_json,
245
is_repo_url,
246
is_vcs_installed
247
)
248
249
# Validate repository structure
250
repo_path = './downloaded-template'
251
if repository_has_cookiecutter_json(repo_path):
252
print("Valid cookiecutter template found")
253
else:
254
print("No cookiecutter.json found in repository")
255
256
# Check URL format
257
template_ref = 'https://github.com/user/repo.git'
258
if is_repo_url(template_ref):
259
print("Template reference is a repository URL")
260
261
# Verify VCS availability
262
if is_vcs_installed('git'):
263
print("Git is available for cloning repositories")
264
else:
265
print("Git not found - cannot clone repositories")
266
```
267
268
### Advanced Repository Handling
269
270
```python
271
from cookiecutter.repository import determine_repo_dir, identify_repo
272
from cookiecutter.exceptions import RepositoryNotFound, RepositoryCloneFailed
273
274
try:
275
# Handle different repository types
276
template_sources = [
277
'gh:audreyfeldroy/cookiecutter-pypackage', # GitHub abbreviation
278
'https://bitbucket.org/user/template.git', # Bitbucket Git
279
'https://gitlab.com/user/template.git', # GitLab Git
280
'./local-template/', # Local directory
281
'https://example.com/template.zip' # Zip file URL
282
]
283
284
config = get_user_config()
285
286
for template in template_sources:
287
try:
288
# Determine repository type and get directory
289
repo_dir, should_cleanup = determine_repo_dir(
290
template=template,
291
abbreviations=config['abbreviations'],
292
clone_to_dir=config['cookiecutters_dir'],
293
checkout=None,
294
no_input=True,
295
directory='subdirectory' # Look for template in subdirectory
296
)
297
298
print(f"Template ready at: {repo_dir}")
299
300
# Use the template...
301
302
# Cleanup if needed
303
if should_cleanup:
304
import shutil
305
shutil.rmtree(repo_dir)
306
307
except RepositoryNotFound:
308
print(f"Repository not found: {template}")
309
except RepositoryCloneFailed:
310
print(f"Failed to clone repository: {template}")
311
312
except Exception as e:
313
print(f"Repository handling error: {e}")
314
```
315
316
### Submodule and Branch Handling
317
318
```python
319
from cookiecutter.repository import clone, identify_repo
320
321
# Clone specific branch or tag
322
branches_to_try = ['main', 'master', 'develop', 'v2.0.0']
323
324
for branch in branches_to_try:
325
try:
326
repo_path = clone(
327
repo_url='https://github.com/user/template.git',
328
checkout=branch,
329
clone_to_dir='./templates',
330
no_input=True
331
)
332
print(f"Successfully cloned branch/tag: {branch}")
333
break
334
except Exception:
335
print(f"Failed to clone {branch}, trying next...")
336
continue
337
```