capistrano-git-copy 1.5.0 → 1.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.gitlab-ci.yml +5 -0
- data/.gitmodules +1 -1
- data/.rubocop.yml +5 -0
- data/CHANGELOG.md +4 -0
- data/README.md +0 -7
- data/capistrano-git-copy.gemspec +5 -6
- data/lib/capistrano/git_copy/scm.rb +12 -82
- data/lib/capistrano/git_copy/scm_helpers.rb +93 -0
- data/lib/capistrano/git_copy/version.rb +1 -1
- data/vendor/git-archive-all/git_archive_all.py +64 -170
- metadata +12 -9
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: '0193555dcc7eefb6ad1c129cc92d99314fd5631a386f8daf39e4ef53a5ab9d7d'
|
4
|
+
data.tar.gz: 60b392776e795ee02a8cf2af8c4952c8d33eceb9277a2fd7c782e67b01189da3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e125d7493ca8d54242e211604105b5d138e5c1944a165efdd888fde77599204a40ca47dcd9b5ea4ba16d765b6c2af9fdcc2f8cc5bd93435fb3c8158f5f827282
|
7
|
+
data.tar.gz: d5627c293b8a6cf4b614dae2b86779468eb0fd48baa43ea9ad43ff745bc5437a994785f02575221549c1e9b6627ccad340c7abf65c38b875ff5d084973b19c9d
|
data/.gitlab-ci.yml
ADDED
data/.gitmodules
CHANGED
data/.rubocop.yml
ADDED
data/CHANGELOG.md
CHANGED
data/README.md
CHANGED
@@ -1,10 +1,3 @@
|
|
1
|
-
[](https://rubygems.org/gems/capistrano-git-copy)
|
2
|
-
[](https://gemnasium.com/ydkn/capistrano-git-copy)
|
3
|
-
[](https://codeclimate.com/github/ydkn/capistrano-git-copy)
|
4
|
-
|
5
|
-
[](https://gitter.im/ydkn/capistrano-git-copy)
|
6
|
-
|
7
|
-
|
8
1
|
# Capistrano::GitCopy
|
9
2
|
|
10
3
|
Creates a tar archive locally from the git repository and uploads it to the remote server.
|
data/capistrano-git-copy.gemspec
CHANGED
@@ -1,5 +1,4 @@
|
|
1
|
-
|
2
|
-
lib = File.expand_path('../lib', __FILE__)
|
1
|
+
lib = File.expand_path('lib', __dir__)
|
3
2
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
3
|
require 'capistrano/git_copy/version'
|
5
4
|
|
@@ -10,17 +9,17 @@ Gem::Specification.new do |spec|
|
|
10
9
|
spec.email = ['me@ydkn.de']
|
11
10
|
spec.description = 'Copy local git repository deploy strategy for capistrano.'
|
12
11
|
spec.summary = 'Copy local git repository deploy strategy for capistrano.'
|
13
|
-
spec.homepage = 'https://
|
12
|
+
spec.homepage = 'https://gitlab.com/ydkn/capistrano-git-copy'
|
14
13
|
spec.license = 'MIT'
|
15
14
|
|
16
|
-
spec.files = `git ls-files`.split(
|
15
|
+
spec.files = `git ls-files`.split("\n") + %w[vendor/git-archive-all/git_archive_all.py]
|
17
16
|
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
17
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
18
|
spec.require_paths = ['lib']
|
20
19
|
|
21
20
|
spec.add_dependency 'capistrano', '>= 3.7.0', '< 4.0.0'
|
22
21
|
|
23
|
-
spec.add_development_dependency 'bundler'
|
22
|
+
spec.add_development_dependency 'bundler'
|
24
23
|
spec.add_development_dependency 'rake'
|
25
|
-
spec.add_development_dependency '
|
24
|
+
spec.add_development_dependency 'rubocop'
|
26
25
|
end
|
@@ -1,11 +1,14 @@
|
|
1
1
|
require 'tmpdir'
|
2
2
|
require 'capistrano/scm/plugin'
|
3
|
+
require 'capistrano/git_copy/scm_helpers'
|
3
4
|
|
4
5
|
module Capistrano
|
5
6
|
module GitCopy
|
6
7
|
# SCM plugin for capistrano
|
7
8
|
# uses a local clone and uploads a tar archive to the server
|
8
9
|
class SCM < ::Capistrano::SCM::Plugin
|
10
|
+
include Capistrano::GitCopy::SCMHelpers
|
11
|
+
|
9
12
|
# set default values
|
10
13
|
def set_defaults
|
11
14
|
set_if_empty :with_clean, true
|
@@ -16,7 +19,7 @@ module Capistrano
|
|
16
19
|
|
17
20
|
# define plugin tasks
|
18
21
|
def define_tasks
|
19
|
-
eval_rakefile File.expand_path('
|
22
|
+
eval_rakefile File.expand_path('tasks/git_copy.rake', __dir__)
|
20
23
|
end
|
21
24
|
|
22
25
|
# register capistrano hooks
|
@@ -38,15 +41,7 @@ module Capistrano
|
|
38
41
|
# @return [Boolean] indicates if repo cache exists
|
39
42
|
def test
|
40
43
|
if backend.test("[ -d #{repo_cache_path} ]")
|
41
|
-
|
42
|
-
if backend.test(:git, :status, '>/dev/null 2>/dev/null')
|
43
|
-
true
|
44
|
-
else
|
45
|
-
backend.execute(:rm, '-rf', repo_cache_path)
|
46
|
-
|
47
|
-
false
|
48
|
-
end
|
49
|
-
end
|
44
|
+
check_repo_cache_path
|
50
45
|
else
|
51
46
|
false
|
52
47
|
end
|
@@ -76,26 +71,16 @@ module Capistrano
|
|
76
71
|
end
|
77
72
|
|
78
73
|
# cleanup
|
79
|
-
if fetch(:with_clean)
|
80
|
-
git(:clean, '-d', '-f')
|
81
|
-
end
|
74
|
+
git(:clean, '-d', '-f') if fetch(:with_clean)
|
82
75
|
|
83
|
-
if fetch(:with_submodules)
|
84
|
-
git(:submodule, :foreach, '--recursive', :git, :clean, '-d', '-f')
|
85
|
-
end
|
76
|
+
git(:submodule, :foreach, '--recursive', :git, :clean, '-d', '-f') if fetch(:with_submodules)
|
86
77
|
end
|
87
78
|
|
88
79
|
# Create tar archive
|
89
80
|
#
|
90
81
|
# @return void
|
91
82
|
def prepare_release
|
92
|
-
|
93
|
-
backend.execute(:tar, '-czf', archive_path, '-C', fetch(:upload_path), '.')
|
94
|
-
elsif fetch(:with_submodules)
|
95
|
-
backend.execute(git_archive_all_bin, "--prefix=''", archive_path)
|
96
|
-
else
|
97
|
-
git(:archive, '--format=tar', 'HEAD', '|', 'gzip', "> #{archive_path}")
|
98
|
-
end
|
83
|
+
package_release_archive
|
99
84
|
|
100
85
|
exclude_files_from_archive if fetch(:git_excludes, []).count > 0
|
101
86
|
end
|
@@ -110,9 +95,7 @@ module Capistrano
|
|
110
95
|
|
111
96
|
backend.upload!(archive_path, remote_archive_path)
|
112
97
|
|
113
|
-
|
114
|
-
backend.execute(:tar, '-f', remote_archive_path, '-x', '-C', release_path)
|
115
|
-
backend.execute(:rm, '-f', remote_archive_path)
|
98
|
+
extract_archive_on_remote(remote_archive_path)
|
116
99
|
end
|
117
100
|
|
118
101
|
# Set deployed revision
|
@@ -135,74 +118,21 @@ module Capistrano
|
|
135
118
|
#
|
136
119
|
# @return [String]
|
137
120
|
def tmp_path
|
138
|
-
@
|
121
|
+
@tmp_path ||= File.join(Dir.tmpdir, deploy_id)
|
139
122
|
end
|
140
123
|
|
141
124
|
# Path to repository cache
|
142
125
|
#
|
143
126
|
# @return [String]
|
144
127
|
def repo_cache_path
|
145
|
-
@
|
128
|
+
@repo_cache_path ||= fetch(:git_repo_cach_path, File.join(tmp_path, 'repo'))
|
146
129
|
end
|
147
130
|
|
148
131
|
# Path to archive
|
149
132
|
#
|
150
133
|
# @return [String]
|
151
134
|
def archive_path
|
152
|
-
@
|
153
|
-
end
|
154
|
-
|
155
|
-
private
|
156
|
-
|
157
|
-
def deploy_id
|
158
|
-
[
|
159
|
-
fetch(:application),
|
160
|
-
fetch(:stage),
|
161
|
-
Digest::MD5.hexdigest(fetch(:repo_url))[0..7],
|
162
|
-
Digest::MD5.hexdigest(Dir.getwd)[0..7]
|
163
|
-
].compact.join('_').gsub(/[^\w]/, '')
|
164
|
-
end
|
165
|
-
|
166
|
-
def commit_hash
|
167
|
-
return @_commit_hash if @_commit_hash
|
168
|
-
|
169
|
-
branch = fetch(:branch, 'master').to_s.strip
|
170
|
-
|
171
|
-
if backend.test(:git, 'rev-parse', "origin/#{branch}", '>/dev/null 2>/dev/null')
|
172
|
-
@_commit_hash = backend.capture(:git, 'rev-parse', "origin/#{branch}").strip
|
173
|
-
else
|
174
|
-
@_commit_hash = backend.capture(:git, 'rev-parse', branch).strip
|
175
|
-
end
|
176
|
-
end
|
177
|
-
|
178
|
-
def git_archive_all_bin
|
179
|
-
File.expand_path('../../../../vendor/git-archive-all/git_archive_all.py', __FILE__)
|
180
|
-
end
|
181
|
-
|
182
|
-
def git(*args)
|
183
|
-
backend.execute(:git, *args)
|
184
|
-
end
|
185
|
-
|
186
|
-
def exclude_files_from_archive
|
187
|
-
archive_dir = File.join(tmp_path, 'archive')
|
188
|
-
|
189
|
-
backend.execute(:rm, '-rf', archive_dir)
|
190
|
-
backend.execute(:mkdir, '-p', archive_dir)
|
191
|
-
backend.execute(:tar, '-xzf', archive_path, '-C', archive_dir)
|
192
|
-
|
193
|
-
fetch(:git_excludes, []).each do |f|
|
194
|
-
file_path = File.join(archive_dir, f.gsub(/\A\//, ''))
|
195
|
-
|
196
|
-
unless File.exists?(file_path)
|
197
|
-
backend.warn("#{f} does not exists!")
|
198
|
-
|
199
|
-
next
|
200
|
-
end
|
201
|
-
|
202
|
-
FileUtils.rm_rf(file_path)
|
203
|
-
end
|
204
|
-
|
205
|
-
backend.execute(:tar, '-czf', archive_path, '-C', archive_dir, '.')
|
135
|
+
@archive_path ||= File.join(tmp_path, 'archive.tar.gz')
|
206
136
|
end
|
207
137
|
end
|
208
138
|
end
|
@@ -0,0 +1,93 @@
|
|
1
|
+
require 'tmpdir'
|
2
|
+
|
3
|
+
module Capistrano
|
4
|
+
module GitCopy
|
5
|
+
# Helper methods for capistrano SCM plugin
|
6
|
+
module SCMHelpers
|
7
|
+
private
|
8
|
+
|
9
|
+
def deploy_id
|
10
|
+
[
|
11
|
+
fetch(:application),
|
12
|
+
fetch(:stage),
|
13
|
+
Digest::MD5.hexdigest(fetch(:repo_url))[0..7],
|
14
|
+
Digest::MD5.hexdigest(Dir.getwd)[0..7]
|
15
|
+
].compact.join('_').gsub(/[^\w]/, '')
|
16
|
+
end
|
17
|
+
|
18
|
+
def commit_hash
|
19
|
+
return @commit_hash if @commit_hash
|
20
|
+
|
21
|
+
branch = fetch(:branch, 'master').to_s.strip
|
22
|
+
|
23
|
+
@commit_hash = if backend.test(:git, 'rev-parse', "origin/#{branch}", '>/dev/null 2>/dev/null')
|
24
|
+
backend.capture(:git, 'rev-parse', "origin/#{branch}").strip
|
25
|
+
else
|
26
|
+
backend.capture(:git, 'rev-parse', branch).strip
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def git_archive_all_bin
|
31
|
+
File.expand_path('../../../vendor/git-archive-all/git_archive_all.py', __dir__)
|
32
|
+
end
|
33
|
+
|
34
|
+
def git(*args)
|
35
|
+
backend.execute(:git, *args)
|
36
|
+
end
|
37
|
+
|
38
|
+
def check_repo_cache_path
|
39
|
+
backend.within(repo_cache_path) do
|
40
|
+
if backend.test(:git, :status, '>/dev/null 2>/dev/null')
|
41
|
+
true
|
42
|
+
else
|
43
|
+
backend.execute(:rm, '-rf', repo_cache_path)
|
44
|
+
|
45
|
+
false
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def package_release_archive
|
51
|
+
if fetch(:upload_path) != '.'
|
52
|
+
backend.execute(:tar, '-czf', archive_path, '-C', fetch(:upload_path), '.')
|
53
|
+
elsif fetch(:with_submodules)
|
54
|
+
backend.execute(git_archive_all_bin, "--prefix=''", archive_path)
|
55
|
+
else
|
56
|
+
git(:archive, '--format=tar', 'HEAD', '|', 'gzip', "> #{archive_path}")
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def exclude_files_from_archive
|
61
|
+
archive_dir = File.join(tmp_path, 'archive')
|
62
|
+
|
63
|
+
backend.execute(:rm, '-rf', archive_dir)
|
64
|
+
backend.execute(:mkdir, '-p', archive_dir)
|
65
|
+
backend.execute(:tar, '-xzf', archive_path, '-C', archive_dir)
|
66
|
+
|
67
|
+
remove_file_from_archive_dir(archive_dir)
|
68
|
+
|
69
|
+
backend.execute(:tar, '-czf', archive_path, '-C', archive_dir, '.')
|
70
|
+
end
|
71
|
+
|
72
|
+
def remove_file_from_archive_dir(archive_dir)
|
73
|
+
fetch(:git_excludes, []).each do |f|
|
74
|
+
file_path = File.join(archive_dir, f.gsub(%r{\A/}, ''))
|
75
|
+
|
76
|
+
unless File.exist?(file_path)
|
77
|
+
backend.warn("#{f} does not exists!")
|
78
|
+
|
79
|
+
next
|
80
|
+
end
|
81
|
+
|
82
|
+
FileUtils.rm_rf(file_path)
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
def extract_archive_on_remote(remote_archive_path)
|
87
|
+
backend.execute(:mkdir, '-p', release_path)
|
88
|
+
backend.execute(:tar, '-f', remote_archive_path, '-x', '-C', release_path)
|
89
|
+
backend.execute(:rm, '-f', remote_archive_path)
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
@@ -27,14 +27,29 @@ from __future__ import print_function
|
|
27
27
|
from __future__ import unicode_literals
|
28
28
|
|
29
29
|
import logging
|
30
|
-
from os import extsep, path, readlink
|
30
|
+
from os import extsep, path, readlink
|
31
31
|
from subprocess import CalledProcessError, Popen, PIPE
|
32
32
|
import sys
|
33
|
-
import tarfile
|
34
|
-
from zipfile import ZipFile, ZipInfo, ZIP_DEFLATED
|
35
33
|
import re
|
36
34
|
|
37
|
-
__version__ = "1.
|
35
|
+
__version__ = "1.18.2"
|
36
|
+
|
37
|
+
|
38
|
+
try:
|
39
|
+
# Python 3.3+
|
40
|
+
from shlex import quote
|
41
|
+
except ImportError:
|
42
|
+
_find_unsafe = re.compile(r'[^a-zA-Z0-9_@%+=:,./-]').search
|
43
|
+
|
44
|
+
def quote(s):
|
45
|
+
"""Return a shell-escaped version of the string *s*."""
|
46
|
+
if not s:
|
47
|
+
return "''"
|
48
|
+
|
49
|
+
if _find_unsafe(s) is None:
|
50
|
+
return s
|
51
|
+
|
52
|
+
return "'" + s.replace("'", "'\"'\"'") + "'"
|
38
53
|
|
39
54
|
|
40
55
|
class GitArchiver(object):
|
@@ -48,6 +63,17 @@ class GitArchiver(object):
|
|
48
63
|
>>> archiver = GitArchiver(main_repo_abspath='my/repo/path')
|
49
64
|
>>> archiver.create('output.zip')
|
50
65
|
"""
|
66
|
+
TARFILE_FORMATS = {
|
67
|
+
'tar': 'w',
|
68
|
+
'tbz2': 'w:bz2',
|
69
|
+
'tgz': 'w:gz',
|
70
|
+
'txz': 'w:xz',
|
71
|
+
'bz2': 'w:bz2',
|
72
|
+
'gz': 'w:gz',
|
73
|
+
'xz': 'w:xz'
|
74
|
+
}
|
75
|
+
ZIPFILE_FORMATS = ('.zip',)
|
76
|
+
|
51
77
|
LOG = logging.getLogger('GitArchiver')
|
52
78
|
|
53
79
|
def __init__(self, prefix='', exclude=True, force_sub=False, extra=None, main_repo_abspath=None):
|
@@ -118,7 +144,9 @@ class GitArchiver(object):
|
|
118
144
|
self.LOG.debug("Output format is not explicitly set, determined format is {0}.".format(output_format))
|
119
145
|
|
120
146
|
if not dry_run:
|
121
|
-
if output_format
|
147
|
+
if output_format in self.ZIPFILE_FORMATS:
|
148
|
+
from zipfile import ZipFile, ZipInfo, ZIP_DEFLATED
|
149
|
+
|
122
150
|
archive = ZipFile(path.abspath(output_path), 'w')
|
123
151
|
|
124
152
|
def add_file(file_path, arcname):
|
@@ -129,25 +157,19 @@ class GitArchiver(object):
|
|
129
157
|
i.create_system = 3
|
130
158
|
i.external_attr = 0xA1ED0000
|
131
159
|
archive.writestr(i, readlink(file_path))
|
132
|
-
elif output_format in
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
elif output_format == 'txz':
|
138
|
-
t_mode = 'w:xz'
|
139
|
-
else:
|
140
|
-
t_mode = 'w:{0}'.format(output_format)
|
141
|
-
|
142
|
-
archive = tarfile.open(path.abspath(output_path), t_mode)
|
160
|
+
elif output_format in self.TARFILE_FORMATS:
|
161
|
+
import tarfile
|
162
|
+
|
163
|
+
mode = self.TARFILE_FORMATS[output_format]
|
164
|
+
archive = tarfile.open(path.abspath(output_path), mode)
|
143
165
|
|
144
166
|
def add_file(file_path, arcname):
|
145
167
|
archive.add(file_path, arcname)
|
146
168
|
else:
|
147
|
-
raise
|
169
|
+
raise ValueError("unknown format: {0}".format(output_format))
|
148
170
|
|
149
171
|
def archiver(file_path, arcname):
|
150
|
-
self.LOG.debug("
|
172
|
+
self.LOG.debug("{0} => {1}".format(file_path, arcname))
|
151
173
|
add_file(file_path, arcname)
|
152
174
|
else:
|
153
175
|
archive = None
|
@@ -160,105 +182,28 @@ class GitArchiver(object):
|
|
160
182
|
if archive is not None:
|
161
183
|
archive.close()
|
162
184
|
|
163
|
-
def
|
164
|
-
"""
|
165
|
-
Returns exclude patterns for a given repo. It looks for .gitattributes files in repo_file_paths.
|
166
|
-
|
167
|
-
Resulting dictionary will contain exclude patterns per path (relative to the repo_abspath).
|
168
|
-
E.g. {('.', 'Catalyst', 'Editions', 'Base'): ['Foo*', '*Bar']}
|
169
|
-
|
170
|
-
@param repo_abspath: Absolute path to the git repository.
|
171
|
-
@type repo_abspath: str
|
172
|
-
|
173
|
-
@param repo_file_paths: List of paths relative to the repo_abspath that are under git control.
|
174
|
-
@type repo_file_paths: list
|
175
|
-
|
176
|
-
@return: Dictionary representing exclude patterns.
|
177
|
-
Keys are tuples of strings. Values are lists of strings.
|
178
|
-
Returns None if self.exclude is not set.
|
179
|
-
@rtype: dict or None
|
180
|
-
"""
|
181
|
-
if not self.exclude:
|
182
|
-
return None
|
183
|
-
|
184
|
-
def read_attributes(attributes_abspath):
|
185
|
-
patterns = []
|
186
|
-
if path.isfile(attributes_abspath):
|
187
|
-
attributes = open(attributes_abspath, 'r').readlines()
|
188
|
-
patterns = []
|
189
|
-
for line in attributes:
|
190
|
-
tokens = line.strip().split()
|
191
|
-
if "export-ignore" in tokens[1:]:
|
192
|
-
patterns.append(tokens[0])
|
193
|
-
return patterns
|
194
|
-
|
195
|
-
exclude_patterns = {(): []}
|
196
|
-
|
197
|
-
# There may be no gitattributes.
|
198
|
-
try:
|
199
|
-
global_attributes_abspath = self.run_git_shell("git config --get core.attributesfile", repo_abspath).rstrip()
|
200
|
-
exclude_patterns[()] = read_attributes(global_attributes_abspath)
|
201
|
-
except:
|
202
|
-
# And it's valid to not have them.
|
203
|
-
pass
|
204
|
-
|
205
|
-
for attributes_abspath in [path.join(repo_abspath, f) for f in repo_file_paths if f.endswith(".gitattributes")]:
|
206
|
-
# Each .gitattributes affects only files within its directory.
|
207
|
-
key = tuple(self.get_path_components(repo_abspath, path.dirname(attributes_abspath)))
|
208
|
-
exclude_patterns[key] = read_attributes(attributes_abspath)
|
209
|
-
|
210
|
-
local_attributes_abspath = path.join(repo_abspath, ".git", "info", "attributes")
|
211
|
-
key = tuple(self.get_path_components(repo_abspath, repo_abspath))
|
212
|
-
|
213
|
-
if key in exclude_patterns:
|
214
|
-
exclude_patterns[key].extend(read_attributes(local_attributes_abspath))
|
215
|
-
else:
|
216
|
-
exclude_patterns[key] = read_attributes(local_attributes_abspath)
|
217
|
-
|
218
|
-
return exclude_patterns
|
219
|
-
|
220
|
-
def is_file_excluded(self, repo_abspath, repo_file_path, exclude_patterns):
|
185
|
+
def is_file_excluded(self, repo_abspath, repo_file_path):
|
221
186
|
"""
|
222
187
|
Checks whether file at a given path is excluded.
|
223
188
|
|
224
189
|
@param repo_abspath: Absolute path to the git repository.
|
225
190
|
@type repo_abspath: str
|
226
191
|
|
227
|
-
@param repo_file_path: Path to a file
|
192
|
+
@param repo_file_path: Path to a file relative to repo_abspath.
|
228
193
|
@type repo_file_path: str
|
229
194
|
|
230
|
-
@param exclude_patterns: Exclude patterns with format specified for get_exclude_patterns.
|
231
|
-
@type exclude_patterns: dict
|
232
|
-
|
233
195
|
@return: True if file should be excluded. Otherwise False.
|
234
196
|
@rtype: bool
|
235
197
|
"""
|
236
|
-
|
237
|
-
|
198
|
+
out = self.run_git_shell(
|
199
|
+
'git check-attr -z export-ignore -- %s' % quote(repo_file_path),
|
200
|
+
cwd=repo_abspath
|
201
|
+
).split('\0')
|
238
202
|
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
is_excluded = False
|
245
|
-
# We should check all patterns specified in intermediate directories to the given file.
|
246
|
-
# At the end we should also check for the global patterns (key '()' or empty tuple).
|
247
|
-
while not is_excluded:
|
248
|
-
key = tuple(components)
|
249
|
-
if key in exclude_patterns:
|
250
|
-
patterns = exclude_patterns[key]
|
251
|
-
for p in patterns:
|
252
|
-
if fnmatch(file_name, p) or fnmatch(repo_file_path, p):
|
253
|
-
self.LOG.debug("Exclude pattern matched {0}: {1}".format(p, repo_file_path))
|
254
|
-
is_excluded = True
|
255
|
-
|
256
|
-
if not len(components):
|
257
|
-
break
|
258
|
-
|
259
|
-
components.pop()
|
260
|
-
|
261
|
-
return is_excluded
|
203
|
+
try:
|
204
|
+
return out[2] == 'set'
|
205
|
+
except IndexError:
|
206
|
+
return False
|
262
207
|
|
263
208
|
def archive_all_files(self, archiver):
|
264
209
|
"""
|
@@ -291,14 +236,11 @@ class GitArchiver(object):
|
|
291
236
|
"""
|
292
237
|
repo_abspath = path.join(self.main_repo_abspath, repo_path)
|
293
238
|
repo_file_paths = self.run_git_shell(
|
294
|
-
|
239
|
+
'git ls-files -z --cached --full-name --no-empty-directory',
|
295
240
|
repo_abspath
|
296
|
-
).
|
297
|
-
exclude_patterns = self.get_exclude_patterns(repo_abspath, repo_file_paths)
|
241
|
+
).split('\0')[:-1]
|
298
242
|
|
299
243
|
for repo_file_path in repo_file_paths:
|
300
|
-
# Git puts path in quotes if file path has unicode characters.
|
301
|
-
repo_file_path = repo_file_path.strip('"') # file path relative to current repo
|
302
244
|
repo_file_abspath = path.join(repo_abspath, repo_file_path) # absolute file path
|
303
245
|
main_repo_file_path = path.join(repo_path, repo_file_path) # file path relative to the main repo
|
304
246
|
|
@@ -306,14 +248,14 @@ class GitArchiver(object):
|
|
306
248
|
if not path.islink(repo_file_abspath) and path.isdir(repo_file_abspath):
|
307
249
|
continue
|
308
250
|
|
309
|
-
if self.is_file_excluded(repo_abspath, repo_file_path
|
251
|
+
if self.is_file_excluded(repo_abspath, repo_file_path):
|
310
252
|
continue
|
311
253
|
|
312
254
|
yield main_repo_file_path
|
313
255
|
|
314
256
|
if self.force_sub:
|
315
|
-
self.run_git_shell(
|
316
|
-
self.run_git_shell(
|
257
|
+
self.run_git_shell('git submodule init', repo_abspath)
|
258
|
+
self.run_git_shell('git submodule update', repo_abspath)
|
317
259
|
|
318
260
|
try:
|
319
261
|
repo_gitmodules_abspath = path.join(repo_abspath, ".gitmodules")
|
@@ -322,70 +264,24 @@ class GitArchiver(object):
|
|
322
264
|
lines = f.readlines()
|
323
265
|
|
324
266
|
for l in lines:
|
325
|
-
m = re.match("
|
267
|
+
m = re.match("^\\s*path\\s*=\\s*(.*)\\s*$", l)
|
326
268
|
|
327
269
|
if m:
|
328
|
-
|
329
|
-
|
270
|
+
repo_submodule_path = m.group(1) # relative to repo_path
|
271
|
+
main_repo_submodule_path = path.join(repo_path, repo_submodule_path) # relative to main_repo_abspath
|
330
272
|
|
331
|
-
if self.is_file_excluded(repo_abspath,
|
273
|
+
if self.is_file_excluded(repo_abspath, repo_submodule_path):
|
332
274
|
continue
|
333
275
|
|
334
|
-
for
|
335
|
-
|
276
|
+
for main_repo_submodule_file_path in self.walk_git_files(main_repo_submodule_path):
|
277
|
+
repo_submodule_file_path = main_repo_submodule_file_path.replace(repo_path, "", 1).strip("/")
|
278
|
+
if self.is_file_excluded(repo_abspath, repo_submodule_file_path):
|
336
279
|
continue
|
337
280
|
|
338
|
-
yield
|
281
|
+
yield main_repo_submodule_file_path
|
339
282
|
except IOError:
|
340
283
|
pass
|
341
284
|
|
342
|
-
@staticmethod
|
343
|
-
def get_path_components(repo_abspath, abspath):
|
344
|
-
"""
|
345
|
-
Split given abspath into components relative to repo_abspath.
|
346
|
-
These components are primarily used as unique keys of files and folders within a repository.
|
347
|
-
|
348
|
-
E.g. if repo_abspath is '/Documents/Hobby/ParaView/' and abspath is
|
349
|
-
'/Documents/Hobby/ParaView/Catalyst/Editions/Base/', function will return:
|
350
|
-
['.', 'Catalyst', 'Editions', 'Base']
|
351
|
-
|
352
|
-
First element is always os.curdir (concrete symbol depends on OS).
|
353
|
-
|
354
|
-
@param repo_abspath: Absolute path to the git repository. Normalized via os.path.normpath.
|
355
|
-
@type repo_abspath: str
|
356
|
-
|
357
|
-
@param abspath: Absolute path to a file within repo_abspath. Normalized via os.path.normpath.
|
358
|
-
@type abspath: str
|
359
|
-
|
360
|
-
@return: List of path components.
|
361
|
-
@rtype: list
|
362
|
-
"""
|
363
|
-
repo_abspath = path.normpath(repo_abspath)
|
364
|
-
abspath = path.normpath(abspath)
|
365
|
-
|
366
|
-
if not path.isabs(repo_abspath):
|
367
|
-
raise ValueError("repo_abspath MUST be absolute path.")
|
368
|
-
|
369
|
-
if not path.isabs(abspath):
|
370
|
-
raise ValueError("abspath MUST be absoulte path.")
|
371
|
-
|
372
|
-
if not path.commonprefix([repo_abspath, abspath]):
|
373
|
-
raise ValueError(
|
374
|
-
"abspath (\"{0}\") MUST have common prefix with repo_abspath (\"{1}\")"
|
375
|
-
.format(abspath, repo_abspath)
|
376
|
-
)
|
377
|
-
|
378
|
-
components = []
|
379
|
-
|
380
|
-
while not abspath == repo_abspath:
|
381
|
-
abspath, tail = path.split(abspath)
|
382
|
-
|
383
|
-
if tail:
|
384
|
-
components.insert(0, tail)
|
385
|
-
|
386
|
-
components.insert(0, curdir)
|
387
|
-
return components
|
388
|
-
|
389
285
|
@staticmethod
|
390
286
|
def run_git_shell(cmd, cwd=None):
|
391
287
|
"""
|
@@ -473,11 +369,9 @@ def main():
|
|
473
369
|
if options.prefix is not None:
|
474
370
|
options.prefix = path.join(options.prefix, '')
|
475
371
|
else:
|
476
|
-
import re
|
477
|
-
|
478
372
|
output_name = path.basename(output_file_path)
|
479
373
|
output_name = re.sub(
|
480
|
-
'(
|
374
|
+
'(\\.zip|\\.tar|\\.tbz2|\\.tgz|\\.txz|\\.bz2|\\.gz|\\.xz|\\.tar\\.bz2|\\.tar\\.gz|\\.tar\\.xz)$',
|
481
375
|
'',
|
482
376
|
output_name
|
483
377
|
) or "Archive"
|
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.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Florian Schwab
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-
|
11
|
+
date: 2018-09-24 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: capistrano
|
@@ -34,16 +34,16 @@ dependencies:
|
|
34
34
|
name: bundler
|
35
35
|
requirement: !ruby/object:Gem::Requirement
|
36
36
|
requirements:
|
37
|
-
- - "
|
37
|
+
- - ">="
|
38
38
|
- !ruby/object:Gem::Version
|
39
|
-
version: '
|
39
|
+
version: '0'
|
40
40
|
type: :development
|
41
41
|
prerelease: false
|
42
42
|
version_requirements: !ruby/object:Gem::Requirement
|
43
43
|
requirements:
|
44
|
-
- - "
|
44
|
+
- - ">="
|
45
45
|
- !ruby/object:Gem::Version
|
46
|
-
version: '
|
46
|
+
version: '0'
|
47
47
|
- !ruby/object:Gem::Dependency
|
48
48
|
name: rake
|
49
49
|
requirement: !ruby/object:Gem::Requirement
|
@@ -59,7 +59,7 @@ dependencies:
|
|
59
59
|
- !ruby/object:Gem::Version
|
60
60
|
version: '0'
|
61
61
|
- !ruby/object:Gem::Dependency
|
62
|
-
name:
|
62
|
+
name: rubocop
|
63
63
|
requirement: !ruby/object:Gem::Requirement
|
64
64
|
requirements:
|
65
65
|
- - ">="
|
@@ -80,7 +80,9 @@ extensions: []
|
|
80
80
|
extra_rdoc_files: []
|
81
81
|
files:
|
82
82
|
- ".gitignore"
|
83
|
+
- ".gitlab-ci.yml"
|
83
84
|
- ".gitmodules"
|
85
|
+
- ".rubocop.yml"
|
84
86
|
- CHANGELOG.md
|
85
87
|
- Gemfile
|
86
88
|
- LICENSE.txt
|
@@ -89,10 +91,11 @@ files:
|
|
89
91
|
- capistrano-git-copy.gemspec
|
90
92
|
- lib/capistrano/git_copy.rb
|
91
93
|
- lib/capistrano/git_copy/scm.rb
|
94
|
+
- lib/capistrano/git_copy/scm_helpers.rb
|
92
95
|
- lib/capistrano/git_copy/tasks/git_copy.rake
|
93
96
|
- lib/capistrano/git_copy/version.rb
|
94
97
|
- vendor/git-archive-all/git_archive_all.py
|
95
|
-
homepage: https://
|
98
|
+
homepage: https://gitlab.com/ydkn/capistrano-git-copy
|
96
99
|
licenses:
|
97
100
|
- MIT
|
98
101
|
metadata: {}
|
@@ -112,7 +115,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
112
115
|
version: '0'
|
113
116
|
requirements: []
|
114
117
|
rubyforge_project:
|
115
|
-
rubygems_version: 2.7.
|
118
|
+
rubygems_version: 2.7.7
|
116
119
|
signing_key:
|
117
120
|
specification_version: 4
|
118
121
|
summary: Copy local git repository deploy strategy for capistrano.
|