capistrano-git-copy 1.1.0 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: d4ae3564eccef2c188c4176c2ad8f2276b1f7c88
4
- data.tar.gz: 993bfa2dc61a9c78376b5af0847f7c0fed5c6ae3
3
+ metadata.gz: e7784ccb4cb4af337de3e9023b46775da88e48e4
4
+ data.tar.gz: 7f9abc9ceefb06d7247ecdc7c6080bdb2dd6a751
5
5
  SHA512:
6
- metadata.gz: 4833479a333245dda86f3b10fe27b90fd5050be08b9ec10444d751c11745c75d586de4d6e67b5d25ea1d1869b888aeb22aa1e71f219579f268f839a76b98c7b5
7
- data.tar.gz: 31bd01e829bd93683883deb00a2ba0f960979d1f5badd3e77b4f7e6d855eb8b0a12b9607e05e98b676d2d87de7a22de1312c8989da00f3455abdee9e442a024e
6
+ metadata.gz: 8dd0c5ad1efaf9c7c8a9da570d2c4bd51c4ecc52f3c85c8d8edffdea818d03489d628e5de526e18f5f8049491ee2cac52735c1a86fb40ed9ac8cc6d51fb89073
7
+ data.tar.gz: 10200bb1f194a6489a2cfc77a8086d093a6bda24349f1a56c49b585c88cd8d6d5e596972363ed7d54e1a1a7f7dafbbba6ba32b5fe266d9c3f8893d1d9951ec3b
data/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # Change Log
2
2
 
3
+ ## 1.2.0 (2016-01-25)
4
+ ### Changes
5
+ - Check if local repository mirror is working and reinitialize if necessary
6
+ - Added config option `git_excludes` to exclude files and directories
7
+ - updated _git-archive-all_ to v1.13
8
+
3
9
  ## 1.1.0 (2015-08-10)
4
10
  ### Changes
5
11
  - Deprecated: require 'capistrano/git/copy'
data/README.md CHANGED
@@ -29,12 +29,17 @@ Now use `git_copy` as your SCM type in your `config/deploy.rb`:
29
29
 
30
30
  set :scm, :git_copy
31
31
 
32
- By default, it includes all submodules into the deployment package. However,
33
- if they are not needed in a particular deployment, you can disable them with
32
+ By default, it includes all submodules into the deployment package. However,
33
+ if they are not needed in a particular deployment, you can disable them with
34
34
  a configuration option:
35
35
 
36
36
  set :with_submodules, false
37
37
 
38
+ Besides using `export-ignore` in `.gitattributes` it's possible exclude files and directories by
39
+ adding them to `git_excludes`:
40
+
41
+ set :git_excludes, %w(config/database.yml.example test rspec)
42
+
38
43
  ## Notes
39
44
 
40
45
  * Uses [git-archive-all](https://github.com/Kentzo/git-archive-all) for bundling repositories.
@@ -13,7 +13,7 @@ Gem::Specification.new do |spec|
13
13
  spec.homepage = 'https://github.com/ydkn/capistrano-git-copy'
14
14
  spec.license = 'MIT'
15
15
 
16
- spec.files = `git ls-files`.split($/) + %w( vendor/git-archive-all/git-archive-all )
16
+ spec.files = `git ls-files`.split($/) + %w( vendor/git-archive-all/git_archive_all.py )
17
17
  spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
18
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
19
  spec.require_paths = ['lib']
@@ -1 +1 @@
1
- STDERR.puts("[DEPRECATION] Please change \"require 'capistrano/git/copy'\" to \"require 'capistrano/git_copy'\" in your Capfile.")
1
+ STDERR.puts("[DEPRECATION] Please change \"require 'capistrano/git/copy'\" to \"require 'capistrano/git_copy'\" in your Capfile, and make sure to disable the default require in your Gemfile with 'gem \"capistrano-git-copy\", require: false\"' to make this warning disappear.")
@@ -1,6 +1,7 @@
1
1
  namespace :load do
2
2
  task :defaults do
3
- set :with_submodules, true
3
+ set :with_submodules, fetch(:with_submodules, true)
4
+ set :git_excludes, fetch(:git_excludes, [])
4
5
  end
5
6
  end
6
7
 
@@ -6,53 +6,66 @@ module Capistrano
6
6
  # Utility stuff to avoid cluttering of deploy.cap
7
7
  class Utility
8
8
  attr_reader :with_submodules
9
+ attr_reader :git_excludes
9
10
 
10
11
  def initialize(context)
11
- @context = context
12
+ @context = context
12
13
  @with_submodules = fetch(:with_submodules, true)
14
+ @git_excludes = fetch(:git_excludes, [])
13
15
  end
14
16
 
15
- # Check if repo cache exists
17
+ # Check if repo cache exists and is valid
16
18
  #
17
19
  # @return [Boolean] indicates if repo cache exists
18
20
  def test
19
- test! " [ -d #{repo_path} ] "
21
+ if test!("[ -d #{repo_path} ]")
22
+ @context.within(repo_path) do
23
+ if test!(:git, :status, '>/dev/null 2>/dev/null')
24
+ true
25
+ else
26
+ execute(:rm, '-rf', repo_path)
27
+ false
28
+ end
29
+ end
30
+ else
31
+ false
32
+ end
20
33
  end
21
34
 
22
35
  # Check if repo is accessible
23
36
  #
24
37
  # @return void
25
38
  def check
26
- git :'ls-remote --heads', repo_url
39
+ git(:'ls-remote --heads', repo_url)
27
40
  end
28
41
 
29
42
  # Clone repo to cache
30
43
  #
31
44
  # @return void
32
45
  def clone
33
- execute :mkdir, '-p', tmp_path
46
+ execute(:mkdir, '-p', tmp_path)
34
47
 
35
- git :clone, fetch(:repo_url), repo_path
48
+ git(:clone, fetch(:repo_url), repo_path)
36
49
  end
37
50
 
38
51
  # Update repo and submodules to branch
39
52
  #
40
53
  # @return void
41
54
  def update
42
- git :remote, :update
43
- git :reset, '--hard', commit_hash
55
+ git(:remote, :update)
56
+ git(:reset, '--hard', commit_hash)
44
57
 
45
58
  # submodules
46
59
  if with_submodules
47
- git :submodule, :init
48
- git :submodule, :update
49
- git :submodule, :foreach, '--recursive', :git, :submodule, :update, '--init'
60
+ git(:submodule, :init)
61
+ git(:submodule, :update)
62
+ git(:submodule, :foreach, '--recursive', :git, :submodule, :update, '--init')
50
63
  end
51
64
 
52
65
  # cleanup
53
- git :clean, '-d', '-f'
66
+ git(:clean, '-d', '-f')
54
67
  if with_submodules
55
- git :submodule, :foreach, '--recursive', :git, :clean, '-d', '-f'
68
+ git(:submodule, :foreach, '--recursive', :git, :clean, '-d', '-f')
56
69
  end
57
70
  end
58
71
 
@@ -61,9 +74,30 @@ module Capistrano
61
74
  # @return void
62
75
  def prepare_release
63
76
  if with_submodules
64
- execute git_archive_all_bin, "--prefix=''", archive_path
77
+ execute(git_archive_all_bin, "--prefix=''", archive_path)
65
78
  else
66
- git "archive --format=tar HEAD | gzip > #{archive_path}"
79
+ git(:archive, '--format=tar', 'HEAD', '|', 'gzip', "> #{archive_path}")
80
+ end
81
+
82
+ if git_excludes.count > 0
83
+ archive_dir = File.join(tmp_path, 'archive')
84
+
85
+ execute :rm, '-rf', archive_dir
86
+ execute :mkdir, '-p', archive_dir
87
+ execute :tar, '-xzf', archive_path, '-C', archive_dir
88
+
89
+ git_excludes.each do |f|
90
+ file_path = File.join(archive_dir, f.gsub(/\A\//, ''))
91
+
92
+ unless File.exists?(file_path)
93
+ warn("#{f} does not exists!")
94
+ next
95
+ end
96
+
97
+ FileUtils.rm_rf(file_path)
98
+ end
99
+
100
+ execute :tar, '-czf', archive_path, '-C', archive_dir, '.'
67
101
  end
68
102
  end
69
103
 
@@ -73,11 +107,11 @@ module Capistrano
73
107
  def release
74
108
  remote_archive_path = File.join(fetch(:deploy_to), File.basename(archive_path))
75
109
 
76
- upload! archive_path, remote_archive_path
110
+ upload!(archive_path, remote_archive_path)
77
111
 
78
- execute :mkdir, '-p', release_path
79
- execute :tar, '-f', remote_archive_path, '-x', '-C', release_path
80
- execute :rm, '-f', remote_archive_path
112
+ execute(:mkdir, '-p', release_path)
113
+ execute(:tar, '-f', remote_archive_path, '-x', '-C', release_path)
114
+ execute(:rm, '-f', remote_archive_path)
81
115
  end
82
116
 
83
117
  # Set deployed revision
@@ -91,9 +125,9 @@ module Capistrano
91
125
  #
92
126
  # @return void
93
127
  def cleanup
94
- execute :rm, '-rf', tmp_path
128
+ execute(:rm, '-rf', tmp_path)
95
129
 
96
- info 'Local repo cache was removed'
130
+ info('Local repo cache was removed')
97
131
  end
98
132
 
99
133
  # Temporary path for all git-copy operations
@@ -143,12 +177,16 @@ module Capistrano
143
177
  @context.info(*args)
144
178
  end
145
179
 
180
+ def warn(*args)
181
+ @context.warn(*args)
182
+ end
183
+
146
184
  def git(*args)
147
185
  execute(:git, *args)
148
186
  end
149
187
 
150
188
  def git_archive_all_bin
151
- File.expand_path('../../../../vendor/git-archive-all/git-archive-all', __FILE__)
189
+ File.expand_path('../../../../vendor/git-archive-all/git_archive_all.py', __FILE__)
152
190
  end
153
191
 
154
192
  def deploy_id
@@ -165,7 +203,7 @@ module Capistrano
165
203
 
166
204
  branch = fetch(:branch, 'master').to_s.strip
167
205
 
168
- if test! :git, 'rev-parse', "origin/#{branch}", '>/dev/null 2>/dev/null'
206
+ if test!(:git, 'rev-parse', "origin/#{branch}", '>/dev/null 2>/dev/null')
169
207
  @_commit_hash = capture(:git, 'rev-parse', "origin/#{branch}").strip
170
208
  else
171
209
  @_commit_hash = capture(:git, 'rev-parse', branch).strip
@@ -3,6 +3,6 @@ module Capistrano
3
3
  # GitCopy
4
4
  module GitCopy
5
5
  # gem version
6
- VERSION = '1.1.0'
6
+ VERSION = '1.2.0'
7
7
  end
8
8
  end
@@ -1,11 +1,31 @@
1
1
  #! /usr/bin/env python
2
2
  # coding=utf-8
3
3
 
4
+ # The MIT License (MIT)
5
+ #
6
+ # Copyright (c) 2010 Ilya Kulakov
7
+ #
8
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
9
+ # of this software and associated documentation files (the "Software"), to deal
10
+ # in the Software without restriction, including without limitation the rights
11
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12
+ # copies of the Software, and to permit persons to whom the Software is
13
+ # furnished to do so, subject to the following conditions:
14
+ #
15
+ # The above copyright notice and this permission notice shall be included in
16
+ # all copies or substantial portions of the Software.
17
+ #
18
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24
+ # THE SOFTWARE.
25
+
4
26
  from __future__ import print_function
5
27
  from __future__ import unicode_literals
6
28
 
7
- __version__ = "1.9"
8
-
9
29
  import logging
10
30
  from os import extsep, path, readlink, curdir
11
31
  from subprocess import CalledProcessError, Popen, PIPE
@@ -13,6 +33,8 @@ import sys
13
33
  import tarfile
14
34
  from zipfile import ZipFile, ZipInfo, ZIP_DEFLATED
15
35
 
36
+ __version__ = "1.13"
37
+
16
38
 
17
39
  class GitArchiver(object):
18
40
  """
@@ -64,9 +86,12 @@ class GitArchiver(object):
64
86
  try:
65
87
  self.run_shell("[ -d .git ] || git rev-parse --git-dir > /dev/null 2>&1", main_repo_abspath)
66
88
  except Exception as e:
67
- raise ValueError("Not a git repository (or any of the parent directories).")
89
+ raise ValueError("{0} not a git repository (or any of the parent directories).".format(main_repo_abspath))
68
90
 
69
- main_repo_abspath = path.abspath(self.read_git_shell('git rev-parse --show-toplevel', main_repo_abspath).rstrip())
91
+ main_repo_abspath = path.abspath(
92
+ self.read_git_shell('git rev-parse --show-toplevel', main_repo_abspath)
93
+ .rstrip()
94
+ )
70
95
 
71
96
  self.prefix = prefix
72
97
  self.exclude = exclude
@@ -94,7 +119,7 @@ class GitArchiver(object):
94
119
  if output_format is None:
95
120
  file_name, file_ext = path.splitext(output_path)
96
121
  output_format = file_ext[len(extsep):].lower()
97
- self.LOG.debug("Output format is not explicitly set, determined format is {}.".format(output_format))
122
+ self.LOG.debug("Output format is not explicitly set, determined format is {0}.".format(output_format))
98
123
 
99
124
  if not dry_run:
100
125
  if output_format == 'zip':
@@ -116,21 +141,25 @@ class GitArchiver(object):
116
141
  elif output_format == 'txz':
117
142
  t_mode = 'w:xz'
118
143
  else:
119
- t_mode = 'w:{}'.format(output_format)
144
+ t_mode = 'w:{0}'.format(output_format)
120
145
 
121
146
  archive = tarfile.open(path.abspath(output_path), t_mode)
122
- add_file = lambda file_path, arcname: archive.add(file_path, arcname)
147
+
148
+ def add_file(file_path, arcname):
149
+ archive.add(file_path, arcname)
123
150
  else:
124
- raise RuntimeError("Unknown format: {}".format(output_format))
151
+ raise RuntimeError("Unknown format: {0}".format(output_format))
125
152
 
126
153
  def archiver(file_path, arcname):
127
- self.LOG.debug("Compressing {} => {}...".format(file_path, arcname))
154
+ self.LOG.debug("Compressing {0} => {1}...".format(file_path, arcname))
128
155
  add_file(file_path, arcname)
129
156
  else:
130
157
  archive = None
131
- archiver = lambda file_path, arcname: self.LOG.info("{} => {}".format(file_path, arcname))
132
158
 
133
- self.archive_all_files(archiver)
159
+ def archiver(file_path, arcname):
160
+ self.LOG.info("{0} => {1}".format(file_path, arcname))
161
+
162
+ self.archive_all_files(archiver) # this will take care of submodule init and update
134
163
 
135
164
  if archive is not None:
136
165
  archive.close()
@@ -225,7 +254,7 @@ class GitArchiver(object):
225
254
  patterns = exclude_patterns[key]
226
255
  for p in patterns:
227
256
  if fnmatch(file_name, p) or fnmatch(repo_file_path, p):
228
- self.LOG.debug("Exclude pattern matched {}: {}".format(p, repo_file_path))
257
+ self.LOG.debug("Exclude pattern matched {0}: {1}".format(p, repo_file_path))
229
258
  is_excluded = True
230
259
 
231
260
  if not len(components):
@@ -239,7 +268,8 @@ class GitArchiver(object):
239
268
  """
240
269
  Archive all files using archiver.
241
270
 
242
- @param archiver: Function that accepts 2 arguments: abspath to file on the system and relative path within archive.
271
+ @param archiver: Callable that accepts 2 arguments:
272
+ abspath to file on the system and relative path within archive.
243
273
  """
244
274
  for file_path in self.extra:
245
275
  archiver(path.abspath(file_path), path.join(self.prefix, file_path))
@@ -263,7 +293,10 @@ class GitArchiver(object):
263
293
  @return: Iterator to traverse files under git control relative to main_repo_abspath.
264
294
  """
265
295
  repo_abspath = path.join(self.main_repo_abspath, repo_path)
266
- repo_file_paths = self.read_git_shell("git ls-files --cached --full-name --no-empty-directory", repo_abspath).splitlines()
296
+ repo_file_paths = self.read_git_shell(
297
+ "git ls-files --cached --full-name --no-empty-directory",
298
+ repo_abspath
299
+ ).splitlines()
267
300
  exclude_patterns = self.get_exclude_patterns(repo_abspath, repo_file_paths)
268
301
 
269
302
  for repo_file_path in repo_file_paths:
@@ -273,7 +306,9 @@ class GitArchiver(object):
273
306
  main_repo_file_path = path.join(repo_path, repo_file_path) # file path relative to the main repo
274
307
 
275
308
  # Only list symlinks and files that don't start with git.
276
- if file_name.startswith(".git") or (not path.islink(main_repo_file_path) and path.isdir(main_repo_file_path)):
309
+ if file_name.startswith(".git") or (
310
+ not path.islink(main_repo_file_path) and path.isdir(main_repo_file_path)
311
+ ):
277
312
  continue
278
313
 
279
314
  if self.is_file_excluded(repo_abspath, repo_file_path, exclude_patterns):
@@ -322,7 +357,10 @@ class GitArchiver(object):
322
357
  raise ValueError("abspath MUST be absoulte path.")
323
358
 
324
359
  if not path.commonprefix([repo_abspath, abspath]):
325
- raise ValueError("abspath (\"{}\") MUST have common prefix with repo_abspath (\"{}\")".format(abspath, repo_abspath))
360
+ raise ValueError(
361
+ "abspath (\"{0}\") MUST have common prefix with repo_abspath (\"{1}\")"
362
+ .format(abspath, repo_abspath)
363
+ )
326
364
 
327
365
  components = []
328
366
 
@@ -383,7 +421,7 @@ class GitArchiver(object):
383
421
  output = output.decode(encoding)
384
422
 
385
423
  if p.returncode:
386
- if sys.version_info > (2,6):
424
+ if sys.version_info > (2, 6):
387
425
  raise CalledProcessError(returncode=p.returncode, cmd=cmd, output=output)
388
426
  else:
389
427
  raise CalledProcessError(returncode=p.returncode, cmd=cmd)
@@ -411,7 +449,7 @@ class GitArchiver(object):
411
449
  output = output.decode('unicode_escape').encode('raw_unicode_escape').decode('utf-8')
412
450
 
413
451
  if p.returncode:
414
- if sys.version_info > (2,6):
452
+ if sys.version_info > (2, 6):
415
453
  raise CalledProcessError(returncode=p.returncode, cmd=cmd, output=output)
416
454
  else:
417
455
  raise CalledProcessError(returncode=p.returncode, cmd=cmd)
@@ -419,17 +457,22 @@ class GitArchiver(object):
419
457
  return output
420
458
 
421
459
 
422
- if __name__ == '__main__':
460
+ def main():
423
461
  from optparse import OptionParser
424
462
 
425
- parser = OptionParser(usage="usage: %prog [-v] [--prefix PREFIX] [--no-exclude] [--force-submodules] [--extra EXTRA1 [EXTRA2]] [--dry-run] OUTPUT_FILE",
426
- version="%prog {}".format(__version__))
463
+ parser = OptionParser(
464
+ usage="usage: %prog [-v] [--prefix PREFIX] [--no-exclude] [--force-submodules]"
465
+ " [--extra EXTRA1 [EXTRA2]] [--dry-run] OUTPUT_FILE",
466
+ version="%prog {0}".format(__version__)
467
+ )
427
468
 
428
469
  parser.add_option('--prefix',
429
470
  type='string',
430
471
  dest='prefix',
431
472
  default=None,
432
- help="prepend PREFIX to each filename in the archive. OUTPUT_FILE name is used by default to avoid tarbomb. You can set it to '' in order to explicitly request tarbomb")
473
+ help="""prepend PREFIX to each filename in the archive.
474
+ OUTPUT_FILE name is used by default to avoid tarbomb.
475
+ You can set it to '' in order to explicitly request tarbomb""")
433
476
 
434
477
  parser.add_option('-v', '--verbose',
435
478
  action='store_true',
@@ -445,7 +488,7 @@ if __name__ == '__main__':
445
488
  parser.add_option('--force-submodules',
446
489
  action='store_true',
447
490
  dest='force_sub',
448
- help="force a git submodule init && git submodule update at each level before iterating submodules")
491
+ help='force a git submodule init && git submodule update at each level before iterating submodules')
449
492
 
450
493
  parser.add_option('--extra',
451
494
  action='append',
@@ -475,7 +518,11 @@ if __name__ == '__main__':
475
518
  import re
476
519
 
477
520
  output_name = path.basename(output_file_path)
478
- output_name = re.sub('(\.zip|\.tar|\.tgz|\.txz|\.gz|\.bz2|\.xz|\.tar\.gz|\.tar\.bz2|\.tar\.xz)$', '', output_name) or "Archive"
521
+ output_name = re.sub(
522
+ '(\.zip|\.tar|\.tgz|\.txz|\.gz|\.bz2|\.xz|\.tar\.gz|\.tar\.bz2|\.tar\.xz)$',
523
+ '',
524
+ output_name
525
+ ) or "Archive"
479
526
  options.prefix = path.join(output_name, '')
480
527
 
481
528
  try:
@@ -489,6 +536,10 @@ if __name__ == '__main__':
489
536
  options.extra)
490
537
  archiver.create(output_file_path, options.dry_run)
491
538
  except Exception as e:
492
- parser.exit(2, "{}\n".format(e))
539
+ parser.exit(2, "{0}\n".format(e))
493
540
 
494
541
  sys.exit(0)
542
+
543
+
544
+ if __name__ == '__main__':
545
+ 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.1.0
4
+ version: 1.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Florian Schwab
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-08-10 00:00:00.000000000 Z
11
+ date: 2016-01-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: capistrano
@@ -93,7 +93,7 @@ files:
93
93
  - lib/capistrano/git_copy/tasks/deploy.cap
94
94
  - lib/capistrano/git_copy/utility.rb
95
95
  - lib/capistrano/git_copy/version.rb
96
- - vendor/git-archive-all/git-archive-all
96
+ - vendor/git-archive-all/git_archive_all.py
97
97
  homepage: https://github.com/ydkn/capistrano-git-copy
98
98
  licenses:
99
99
  - MIT
@@ -114,7 +114,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
114
114
  version: '0'
115
115
  requirements: []
116
116
  rubyforge_project:
117
- rubygems_version: 2.4.8
117
+ rubygems_version: 2.5.1
118
118
  signing_key:
119
119
  specification_version: 4
120
120
  summary: Copy local git repository deploy strategy for capistrano