capistrano-git-copy 1.5.5 → 1.5.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitlab-ci.yml +0 -1
- data/.rubocop.yml +1 -1
- data/CHANGELOG.md +4 -0
- data/capistrano-git-copy.gemspec +1 -0
- data/lib/capistrano/git_copy/version.rb +1 -1
- data/vendor/git-archive-all/git_archive_all.py +149 -90
- metadata +17 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 447065540bb8fa941ac498cc168caeacac3f44c04f35b9dcac56b99b971359da
|
4
|
+
data.tar.gz: f112754d2f94ebfa49ae6f8360318f362e006fb66a687e27e5d68eb1bbd87a9a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 71daf64e5bcc8d77bdec87c24ffa90b1b0c7e9d370a49719ba8afea79b966ff1318a1a7d1ea2b8ff98f21eb2f14e4f45da71514d21c9a2cd30b43a52d4e68229
|
7
|
+
data.tar.gz: eb902360bbbcbef39d11d0c2058ff42f5936129a4963818d731606bfde0176d5d01781f4a26c7b879f650fbc0cc2925cce5b1f5296cacc63550d11f738a80a0e
|
data/.gitlab-ci.yml
CHANGED
data/.rubocop.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -6,6 +6,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
6
6
|
|
7
7
|
## [Unreleased]
|
8
8
|
|
9
|
+
## [1.5.6] - 2019-11-10
|
10
|
+
### Changed
|
11
|
+
- updated _git-archive-all_ to 1.20.0
|
12
|
+
|
9
13
|
## [1.5.5] - 2019-06-19
|
10
14
|
### Fixed
|
11
15
|
- usage with git versions >= 2.22.0
|
data/capistrano-git-copy.gemspec
CHANGED
@@ -32,24 +32,88 @@ from subprocess import CalledProcessError, Popen, PIPE
|
|
32
32
|
import sys
|
33
33
|
import re
|
34
34
|
|
35
|
-
__version__ = "1.
|
35
|
+
__version__ = "1.20.0"
|
36
36
|
|
37
37
|
|
38
38
|
try:
|
39
|
-
# Python 3.
|
40
|
-
from
|
39
|
+
# Python 3.2+
|
40
|
+
from os import fsdecode
|
41
41
|
except ImportError:
|
42
|
-
|
42
|
+
def fsdecode(filename):
|
43
|
+
if not isinstance(filename, unicode):
|
44
|
+
return filename.decode(sys.getfilesystemencoding(), 'strict')
|
45
|
+
else:
|
46
|
+
return filename
|
47
|
+
|
48
|
+
try:
|
49
|
+
# Python 3.2+
|
50
|
+
from os import fsencode
|
51
|
+
except ImportError:
|
52
|
+
def fsencode(filename):
|
53
|
+
if not isinstance(filename, bytes):
|
54
|
+
return filename.encode(sys.getfilesystemencoding(), 'strict')
|
55
|
+
else:
|
56
|
+
return filename
|
57
|
+
|
58
|
+
|
59
|
+
def git_fsdecode(filename):
|
60
|
+
"""
|
61
|
+
Decode filename from git output into str.
|
62
|
+
"""
|
63
|
+
if sys.platform.startswith('win32'):
|
64
|
+
return filename.decode('utf-8')
|
65
|
+
else:
|
66
|
+
return fsdecode(filename)
|
67
|
+
|
68
|
+
|
69
|
+
def git_fsencode(filename):
|
70
|
+
"""
|
71
|
+
Encode filename from str into git input.
|
72
|
+
"""
|
73
|
+
if sys.platform.startswith('win32'):
|
74
|
+
return filename.encode('utf-8')
|
75
|
+
else:
|
76
|
+
return fsencode(filename)
|
77
|
+
|
78
|
+
|
79
|
+
try:
|
80
|
+
# Python 3.6+
|
81
|
+
from os import fspath as _fspath
|
43
82
|
|
44
|
-
def
|
45
|
-
"""
|
46
|
-
|
47
|
-
|
83
|
+
def fspath(filename, decoder=fsdecode, encoder=fsencode):
|
84
|
+
"""
|
85
|
+
Convert filename into bytes or str, depending on what's the best type
|
86
|
+
to represent paths for current Python and platform.
|
87
|
+
"""
|
88
|
+
# Python 3.6+: str can represent any path (PEP 383)
|
89
|
+
# str is not required on Windows (PEP 529)
|
90
|
+
# Decoding is still applied for consistency and to follow PEP 519 recommendation.
|
91
|
+
return decoder(_fspath(filename))
|
92
|
+
except ImportError:
|
93
|
+
def fspath(filename, decoder=fsdecode, encoder=fsencode):
|
94
|
+
# Python 3.4 and 3.5: str can represent any path (PEP 383),
|
95
|
+
# but str is required on Windows (no PEP 529)
|
96
|
+
#
|
97
|
+
# Python 2.6 and 2.7: str cannot represent any path (no PEP 383),
|
98
|
+
# str is required on Windows (no PEP 529)
|
99
|
+
# bytes is required on POSIX (no PEP 383)
|
100
|
+
if sys.version_info > (3,):
|
101
|
+
import pathlib
|
102
|
+
if isinstance(filename, pathlib.PurePath):
|
103
|
+
return str(filename)
|
104
|
+
else:
|
105
|
+
return decoder(filename)
|
106
|
+
elif sys.platform.startswith('win32'):
|
107
|
+
return decoder(filename)
|
108
|
+
else:
|
109
|
+
return encoder(filename)
|
48
110
|
|
49
|
-
if _find_unsafe(s) is None:
|
50
|
-
return s
|
51
111
|
|
52
|
-
|
112
|
+
def git_fspath(filename):
|
113
|
+
"""
|
114
|
+
fspath representation of git output.
|
115
|
+
"""
|
116
|
+
return fspath(filename, git_fsdecode, git_fsencode)
|
53
117
|
|
54
118
|
|
55
119
|
class GitArchiver(object):
|
@@ -85,54 +149,43 @@ class GitArchiver(object):
|
|
85
149
|
baz
|
86
150
|
foo/
|
87
151
|
bar
|
88
|
-
@type prefix: str
|
89
152
|
|
90
153
|
@param exclude: Determines whether archiver should follow rules specified in .gitattributes files.
|
91
|
-
@type exclude: bool
|
92
154
|
|
93
155
|
@param force_sub: Determines whether submodules are initialized and updated before archiving.
|
94
|
-
@type force_sub: bool
|
95
156
|
|
96
157
|
@param extra: List of extra paths to include in the resulting archive.
|
97
|
-
@type extra: list
|
98
158
|
|
99
159
|
@param main_repo_abspath: Absolute path to the main repository (or one of subdirectories).
|
100
160
|
If given path is path to a subdirectory (but not a submodule directory!) it will be replaced
|
101
161
|
with abspath to top-level directory of the repository.
|
102
162
|
If None, current cwd is used.
|
103
|
-
@type main_repo_abspath: str
|
104
163
|
|
105
164
|
@param git_version: Version of Git that determines whether various workarounds are on.
|
106
165
|
If None, tries to resolve via Git's CLI.
|
107
|
-
@type git_version: tuple or None
|
108
166
|
"""
|
167
|
+
self._should_decode_path = None
|
168
|
+
self._check_attr_gens = {}
|
169
|
+
|
109
170
|
if git_version is None:
|
110
171
|
git_version = self.get_git_version()
|
111
172
|
|
112
173
|
if git_version is not None and git_version < (1, 6, 1):
|
113
174
|
raise ValueError("git of version 1.6.1 and higher is required")
|
114
175
|
|
115
|
-
|
116
|
-
extra = []
|
176
|
+
self.git_version = git_version
|
117
177
|
|
118
178
|
if main_repo_abspath is None:
|
119
179
|
main_repo_abspath = path.abspath('')
|
120
180
|
elif not path.isabs(main_repo_abspath):
|
121
181
|
raise ValueError("main_repo_abspath must be an absolute path")
|
122
182
|
|
123
|
-
|
124
|
-
main_repo_abspath = path.abspath(self.run_git_shell('git rev-parse --show-toplevel', main_repo_abspath).rstrip())
|
125
|
-
except CalledProcessError:
|
126
|
-
raise ValueError("{0} is not part of a git repository".format(main_repo_abspath))
|
183
|
+
self.main_repo_abspath = self.resolve_git_main_repo_abspath(main_repo_abspath)
|
127
184
|
|
128
|
-
self.prefix = prefix
|
185
|
+
self.prefix = fspath(prefix)
|
129
186
|
self.exclude = exclude
|
130
|
-
self.extra = extra
|
187
|
+
self.extra = [fspath(e) for e in extra] if extra is not None else []
|
131
188
|
self.force_sub = force_sub
|
132
|
-
self.main_repo_abspath = main_repo_abspath
|
133
|
-
self.git_version = git_version
|
134
|
-
|
135
|
-
self._check_attr_gens = {}
|
136
189
|
|
137
190
|
def create(self, output_path, dry_run=False, output_format=None, compresslevel=None):
|
138
191
|
"""
|
@@ -142,15 +195,16 @@ class GitArchiver(object):
|
|
142
195
|
Supported formats are: gz, zip, bz2, xz, tar, tgz, txz
|
143
196
|
|
144
197
|
@param output_path: Output file path.
|
145
|
-
@type output_path: str
|
146
198
|
|
147
199
|
@param dry_run: Determines whether create should do nothing but print what it would archive.
|
148
|
-
@type dry_run: bool
|
149
200
|
|
150
201
|
@param output_format: Determines format of the output archive. If None, format is determined from extension
|
151
202
|
of output_file_path.
|
152
|
-
|
203
|
+
|
204
|
+
@param compresslevel: Optional compression level. Interpretation depends on the output format.
|
153
205
|
"""
|
206
|
+
output_path = fspath(output_path)
|
207
|
+
|
154
208
|
if output_format is None:
|
155
209
|
file_name, file_ext = path.splitext(output_path)
|
156
210
|
output_format = file_ext[len(extsep):].lower()
|
@@ -195,13 +249,13 @@ class GitArchiver(object):
|
|
195
249
|
raise ValueError("unknown format: {0}".format(output_format))
|
196
250
|
|
197
251
|
def archiver(file_path, arcname):
|
198
|
-
self.LOG.debug("{0} => {1}".format(file_path, arcname))
|
252
|
+
self.LOG.debug(fspath("{0} => {1}").format(file_path, arcname))
|
199
253
|
add_file(file_path, arcname)
|
200
254
|
else:
|
201
255
|
archive = None
|
202
256
|
|
203
257
|
def archiver(file_path, arcname):
|
204
|
-
self.LOG.info("{0} => {1}".format(file_path, arcname))
|
258
|
+
self.LOG.info(fspath("{0} => {1}").format(file_path, arcname))
|
205
259
|
|
206
260
|
self.archive_all_files(archiver)
|
207
261
|
|
@@ -213,17 +267,14 @@ class GitArchiver(object):
|
|
213
267
|
Checks whether file at a given path is excluded.
|
214
268
|
|
215
269
|
@param repo_abspath: Absolute path to the git repository.
|
216
|
-
@type repo_abspath: str
|
217
270
|
|
218
271
|
@param repo_file_path: Path to a file relative to repo_abspath.
|
219
|
-
@type repo_file_path: str
|
220
272
|
|
221
273
|
@return: True if file should be excluded. Otherwise False.
|
222
|
-
@rtype: bool
|
223
274
|
"""
|
224
275
|
next(self._check_attr_gens[repo_abspath])
|
225
276
|
attrs = self._check_attr_gens[repo_abspath].send(repo_file_path)
|
226
|
-
return attrs['export-ignore'] == 'set'
|
277
|
+
return attrs['export-ignore'] == b'set'
|
227
278
|
|
228
279
|
def archive_all_files(self, archiver):
|
229
280
|
"""
|
@@ -231,7 +282,6 @@ class GitArchiver(object):
|
|
231
282
|
|
232
283
|
@param archiver: Callable that accepts 2 arguments:
|
233
284
|
abspath to file on the system and relative path within archive.
|
234
|
-
@type archiver: Callable
|
235
285
|
"""
|
236
286
|
for file_path in self.extra:
|
237
287
|
archiver(path.abspath(file_path), path.join(self.prefix, file_path))
|
@@ -239,7 +289,7 @@ class GitArchiver(object):
|
|
239
289
|
for file_path in self.walk_git_files():
|
240
290
|
archiver(path.join(self.main_repo_abspath, file_path), path.join(self.prefix, file_path))
|
241
291
|
|
242
|
-
def walk_git_files(self, repo_path=''):
|
292
|
+
def walk_git_files(self, repo_path=fspath('')):
|
243
293
|
"""
|
244
294
|
An iterator method that yields a file path relative to main_repo_abspath
|
245
295
|
for each file that should be included in the archive.
|
@@ -249,20 +299,24 @@ class GitArchiver(object):
|
|
249
299
|
Recurs into submodules as well.
|
250
300
|
|
251
301
|
@param repo_path: Path to the git submodule repository relative to main_repo_abspath.
|
252
|
-
@type repo_path: str
|
253
302
|
|
254
303
|
@return: Iterator to traverse files under git control relative to main_repo_abspath.
|
255
|
-
@rtype: Iterable
|
256
304
|
"""
|
257
|
-
repo_abspath = path.join(self.main_repo_abspath, repo_path)
|
305
|
+
repo_abspath = path.join(self.main_repo_abspath, fspath(repo_path))
|
258
306
|
assert repo_abspath not in self._check_attr_gens
|
259
|
-
self._check_attr_gens[repo_abspath] = self.
|
307
|
+
self._check_attr_gens[repo_abspath] = self.check_git_attr(repo_abspath, ['export-ignore'])
|
260
308
|
|
261
309
|
try:
|
262
310
|
repo_file_paths = self.run_git_shell(
|
263
311
|
'git ls-files -z --cached --full-name --no-empty-directory',
|
264
|
-
repo_abspath
|
265
|
-
)
|
312
|
+
cwd=repo_abspath
|
313
|
+
)
|
314
|
+
repo_file_paths = repo_file_paths.split(b'\0')[:-1]
|
315
|
+
|
316
|
+
if sys.platform.startswith('win32'):
|
317
|
+
repo_file_paths = (git_fspath(p.replace(b'/', b'\\')) for p in repo_file_paths)
|
318
|
+
else:
|
319
|
+
repo_file_paths = map(git_fspath, repo_file_paths)
|
266
320
|
|
267
321
|
for repo_file_path in repo_file_paths:
|
268
322
|
repo_file_abspath = path.join(repo_abspath, repo_file_path) # absolute file path
|
@@ -282,7 +336,7 @@ class GitArchiver(object):
|
|
282
336
|
self.run_git_shell('git submodule update', repo_abspath)
|
283
337
|
|
284
338
|
try:
|
285
|
-
repo_gitmodules_abspath = path.join(repo_abspath, ".gitmodules")
|
339
|
+
repo_gitmodules_abspath = path.join(repo_abspath, fspath(".gitmodules"))
|
286
340
|
|
287
341
|
with open(repo_gitmodules_abspath) as f:
|
288
342
|
lines = f.readlines()
|
@@ -291,7 +345,7 @@ class GitArchiver(object):
|
|
291
345
|
m = re.match("^\\s*path\\s*=\\s*(.*)\\s*$", l)
|
292
346
|
|
293
347
|
if m:
|
294
|
-
repo_submodule_path = m.group(1) # relative to repo_path
|
348
|
+
repo_submodule_path = fspath(m.group(1)) # relative to repo_path
|
295
349
|
main_repo_submodule_path = path.join(repo_path, repo_submodule_path) # relative to main_repo_abspath
|
296
350
|
|
297
351
|
if self.is_file_excluded(repo_abspath, repo_submodule_path):
|
@@ -309,22 +363,19 @@ class GitArchiver(object):
|
|
309
363
|
self._check_attr_gens[repo_abspath].close()
|
310
364
|
del self._check_attr_gens[repo_abspath]
|
311
365
|
|
312
|
-
def
|
366
|
+
def check_git_attr(self, repo_abspath, attrs):
|
313
367
|
"""
|
314
|
-
Generator that returns attributes for
|
368
|
+
Generator that returns git attributes for received paths relative to repo_abspath.
|
315
369
|
|
316
|
-
>>>
|
370
|
+
>>> archiver = GitArchiver(...)
|
371
|
+
>>> g = archiver.check_git_attr('repo_path', ['export-ignore'])
|
317
372
|
>>> next(g)
|
318
373
|
>>> attrs = g.send('relative_path')
|
319
374
|
>>> print(attrs['export-ignore'])
|
320
375
|
|
321
376
|
@param repo_abspath: Absolute path to a git repository.
|
322
|
-
@type repo_abspath: str
|
323
377
|
|
324
|
-
@param attrs: Attributes to check
|
325
|
-
@type attrs: [str]
|
326
|
-
|
327
|
-
@rtype: generator
|
378
|
+
@param attrs: Attributes to check
|
328
379
|
"""
|
329
380
|
def make_process():
|
330
381
|
env = dict(environ, GIT_FLUSH='1')
|
@@ -332,7 +383,7 @@ class GitArchiver(object):
|
|
332
383
|
return Popen(cmd, shell=True, stdin=PIPE, stdout=PIPE, cwd=repo_abspath, env=env)
|
333
384
|
|
334
385
|
def read_attrs(process, repo_file_path):
|
335
|
-
process.stdin.write(repo_file_path
|
386
|
+
process.stdin.write(repo_file_path + b'\0')
|
336
387
|
process.stdin.flush()
|
337
388
|
|
338
389
|
# For every attribute check-attr will output: <path> NUL <attribute> NUL <info> NUL
|
@@ -349,7 +400,8 @@ class GitArchiver(object):
|
|
349
400
|
nuls_count += 1
|
350
401
|
|
351
402
|
if nuls_count % 3 == 0:
|
352
|
-
yield
|
403
|
+
yield path, attr, info
|
404
|
+
|
353
405
|
path, attr, info = b'', b'', b''
|
354
406
|
elif nuls_count % 3 == 0:
|
355
407
|
path += b
|
@@ -362,7 +414,7 @@ class GitArchiver(object):
|
|
362
414
|
"""
|
363
415
|
Compatibility with versions 1.8.5 and below that do not recognize -z for output.
|
364
416
|
"""
|
365
|
-
process.stdin.write(repo_file_path
|
417
|
+
process.stdin.write(repo_file_path + b'\0')
|
366
418
|
process.stdin.flush()
|
367
419
|
|
368
420
|
# For every attribute check-attr will output: <path>: <attribute>: <info>\n
|
@@ -383,11 +435,11 @@ class GitArchiver(object):
|
|
383
435
|
if attr_start == -1:
|
384
436
|
raise RuntimeError("unexpected output of check-attr: {0}".format(line))
|
385
437
|
|
386
|
-
info = line[info_start + 2:len(line) - 1] # trim leading ": " and trailing \n
|
387
|
-
attr = line[attr_start + 2:info_start] # trim leading ": "
|
388
438
|
path = line[:attr_start]
|
439
|
+
attr = line[attr_start + 2:info_start] # trim leading ": "
|
440
|
+
info = line[info_start + 2:len(line) - 1] # trim leading ": " and trailing \n
|
441
|
+
yield path, attr, info
|
389
442
|
|
390
|
-
yield map(self.decode_git_output, (path, attr, info))
|
391
443
|
lines_count += 1
|
392
444
|
|
393
445
|
if not attrs:
|
@@ -395,17 +447,19 @@ class GitArchiver(object):
|
|
395
447
|
|
396
448
|
process = make_process()
|
397
449
|
|
450
|
+
if self.git_version is None or self.git_version > (1, 8, 5):
|
451
|
+
reader = read_attrs
|
452
|
+
else:
|
453
|
+
reader = read_attrs_old
|
454
|
+
|
398
455
|
try:
|
399
456
|
while True:
|
400
457
|
repo_file_path = yield
|
458
|
+
repo_file_path = git_fsencode(fspath(repo_file_path))
|
401
459
|
repo_file_attrs = {}
|
402
460
|
|
403
|
-
if self.git_version is None or self.git_version > (1, 8, 5):
|
404
|
-
reader = read_attrs
|
405
|
-
else:
|
406
|
-
reader = read_attrs_old
|
407
|
-
|
408
461
|
for path, attr, value in reader(process, repo_file_path):
|
462
|
+
attr = attr.decode('utf-8')
|
409
463
|
repo_file_attrs[attr] = value
|
410
464
|
|
411
465
|
yield repo_file_attrs
|
@@ -413,36 +467,31 @@ class GitArchiver(object):
|
|
413
467
|
process.stdin.close()
|
414
468
|
process.wait()
|
415
469
|
|
416
|
-
|
417
|
-
def decode_git_output(cls, output):
|
470
|
+
def resolve_git_main_repo_abspath(self, abspath):
|
418
471
|
"""
|
419
|
-
|
420
|
-
|
421
|
-
@type output: bytes
|
422
|
-
|
423
|
-
@rtype: str
|
472
|
+
Return absolute path to the repo for a given path.
|
424
473
|
"""
|
425
|
-
|
474
|
+
try:
|
475
|
+
main_repo_abspath = self.run_git_shell('git rev-parse --show-toplevel', cwd=abspath).rstrip()
|
476
|
+
return path.abspath(git_fspath(main_repo_abspath))
|
477
|
+
except CalledProcessError as e:
|
478
|
+
raise ValueError("{0} is not part of a git repository ({1})".format(abspath, e.returncode))
|
426
479
|
|
427
480
|
@classmethod
|
428
481
|
def run_git_shell(cls, cmd, cwd=None):
|
429
482
|
"""
|
430
|
-
|
483
|
+
Run git shell command, read output and decode it into a unicode string.
|
431
484
|
|
432
485
|
@param cmd: Command to be executed.
|
433
|
-
@type cmd: str
|
434
486
|
|
435
|
-
@type cwd: str
|
436
487
|
@param cwd: Working directory.
|
437
488
|
|
438
|
-
@rtype: str
|
439
489
|
@return: Output of the command.
|
440
490
|
|
441
491
|
@raise CalledProcessError: Raises exception if return code of the command is non-zero.
|
442
492
|
"""
|
443
493
|
p = Popen(cmd, shell=True, stdout=PIPE, cwd=cwd)
|
444
494
|
output, _ = p.communicate()
|
445
|
-
output = cls.decode_git_output(output)
|
446
495
|
|
447
496
|
if p.returncode:
|
448
497
|
if sys.version_info > (2, 6):
|
@@ -458,8 +507,6 @@ class GitArchiver(object):
|
|
458
507
|
Return version of git current shell points to.
|
459
508
|
|
460
509
|
If version cannot be parsed None is returned.
|
461
|
-
|
462
|
-
@rtype: tuple or None
|
463
510
|
"""
|
464
511
|
try:
|
465
512
|
output = cls.run_git_shell('git version')
|
@@ -474,18 +521,21 @@ class GitArchiver(object):
|
|
474
521
|
return None
|
475
522
|
|
476
523
|
try:
|
477
|
-
return tuple(int(v) for v in version.split('.'))
|
524
|
+
return tuple(int(v) if v.isdigit() else 0 for v in version.split(b'.'))
|
478
525
|
except ValueError:
|
479
526
|
cls.LOG.warning("Unable to parse Git version \"%s\".", version)
|
480
527
|
return None
|
481
528
|
|
482
529
|
|
483
|
-
def main():
|
530
|
+
def main(argv=None):
|
531
|
+
if argv is None:
|
532
|
+
argv = sys.argv
|
533
|
+
|
484
534
|
from optparse import OptionParser, SUPPRESS_HELP
|
485
535
|
|
486
536
|
parser = OptionParser(
|
487
|
-
usage="usage: %prog [-v] [--prefix PREFIX] [--no-exclude]
|
488
|
-
" [--extra EXTRA1 ...] [--dry-run] [-0 | ... | -9] OUTPUT_FILE",
|
537
|
+
usage="usage: %prog [-v] [-C BASE_REPO] [--prefix PREFIX] [--no-exclude]"
|
538
|
+
" [--force-submodules] [--extra EXTRA1 ...] [--dry-run] [-0 | ... | -9] OUTPUT_FILE",
|
489
539
|
version="%prog {0}".format(__version__)
|
490
540
|
)
|
491
541
|
|
@@ -497,6 +547,13 @@ def main():
|
|
497
547
|
OUTPUT_FILE name is used by default to avoid tarbomb.
|
498
548
|
You can set it to '' in order to explicitly request tarbomb""")
|
499
549
|
|
550
|
+
parser.add_option('-C',
|
551
|
+
type='string',
|
552
|
+
dest='base_repo',
|
553
|
+
default=None,
|
554
|
+
help="""use BASE_REPO as the main repository git working directory to archive.
|
555
|
+
Defaults to current directory when empty""")
|
556
|
+
|
500
557
|
parser.add_option('-v', '--verbose',
|
501
558
|
action='store_true',
|
502
559
|
dest='verbose',
|
@@ -531,7 +588,7 @@ def main():
|
|
531
588
|
dest='compresslevel',
|
532
589
|
help=SUPPRESS_HELP)
|
533
590
|
|
534
|
-
options, args = parser.parse_args()
|
591
|
+
options, args = parser.parse_args(argv[1:])
|
535
592
|
|
536
593
|
if len(args) != 1:
|
537
594
|
parser.error("You must specify exactly one output file")
|
@@ -561,13 +618,15 @@ def main():
|
|
561
618
|
archiver = GitArchiver(options.prefix,
|
562
619
|
options.exclude,
|
563
620
|
options.force_sub,
|
564
|
-
options.extra
|
621
|
+
options.extra,
|
622
|
+
path.abspath(options.base_repo) if options.base_repo is not None else None
|
623
|
+
)
|
565
624
|
archiver.create(output_file_path, options.dry_run, compresslevel=options.compresslevel)
|
566
625
|
except Exception as e:
|
567
626
|
parser.exit(2, "{0}\n".format(e))
|
568
627
|
|
569
|
-
|
628
|
+
return 0
|
570
629
|
|
571
630
|
|
572
631
|
if __name__ == '__main__':
|
573
|
-
main()
|
632
|
+
sys.exit(main())
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: capistrano-git-copy
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.5.
|
4
|
+
version: 1.5.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Florian Schwab
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-
|
11
|
+
date: 2019-11-10 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: capistrano
|
@@ -72,6 +72,20 @@ dependencies:
|
|
72
72
|
- - ">="
|
73
73
|
- !ruby/object:Gem::Version
|
74
74
|
version: '0'
|
75
|
+
- !ruby/object:Gem::Dependency
|
76
|
+
name: rubocop-performance
|
77
|
+
requirement: !ruby/object:Gem::Requirement
|
78
|
+
requirements:
|
79
|
+
- - ">="
|
80
|
+
- !ruby/object:Gem::Version
|
81
|
+
version: '0'
|
82
|
+
type: :development
|
83
|
+
prerelease: false
|
84
|
+
version_requirements: !ruby/object:Gem::Requirement
|
85
|
+
requirements:
|
86
|
+
- - ">="
|
87
|
+
- !ruby/object:Gem::Version
|
88
|
+
version: '0'
|
75
89
|
description: Copy local git repository deploy strategy for capistrano.
|
76
90
|
email:
|
77
91
|
- me@ydkn.de
|
@@ -114,7 +128,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
114
128
|
- !ruby/object:Gem::Version
|
115
129
|
version: '0'
|
116
130
|
requirements: []
|
117
|
-
rubygems_version: 3.0.
|
131
|
+
rubygems_version: 3.0.6
|
118
132
|
signing_key:
|
119
133
|
specification_version: 4
|
120
134
|
summary: Copy local git repository deploy strategy for capistrano.
|