gemfile_locker 0.2.0 → 0.3.0
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 +5 -5
- data/gemfile_locker.gemspec +2 -1
- data/lib/gemfile_locker/gem_entry.rb +54 -0
- data/lib/gemfile_locker/gem_entry/git_ref.rb +54 -0
- data/lib/gemfile_locker/gem_entry/versions.rb +52 -0
- data/lib/gemfile_locker/gemfile_processor.rb +26 -53
- data/lib/gemfile_locker/locker.rb +13 -6
- data/lib/gemfile_locker/unlocker.rb +2 -2
- data/lib/gemfile_locker/version.rb +1 -1
- metadata +26 -9
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: d2725a59f53ef8af74767a9452e43e17e5c1e402acfa78a97570698a40209c92
|
4
|
+
data.tar.gz: cfdf2128c68cde403638e976ca6a25454b342a2436134369a1c086c95eb893ce
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 78b6f30fb6d863984499c8f48de1d5f29070c35d861b1637cac54729d400ac0026392efe876ba0bb50dc070608a157e4cde6d301ec6cef3eee74146a0b1e01b8
|
7
|
+
data.tar.gz: 3e06350ba9b4be3c59f79b502399660b3c48147473f00f162183a91e10e67e409f7a13842db3e2cfcf8b4a82834972089581590f8be9d456df1c3deae3a456e5
|
data/gemfile_locker.gemspec
CHANGED
@@ -27,8 +27,9 @@ TXT
|
|
27
27
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
28
28
|
spec.require_paths = ['lib']
|
29
29
|
|
30
|
-
spec.add_runtime_dependency 'thor', '~> 0.19'
|
31
30
|
spec.add_runtime_dependency 'bundler', '~> 1.13'
|
31
|
+
spec.add_runtime_dependency 'parser', '~> 2.0'
|
32
|
+
spec.add_runtime_dependency 'thor', '~> 0.19'
|
32
33
|
|
33
34
|
spec.add_development_dependency 'rake', '~> 10.0'
|
34
35
|
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
module GemfileLocker
|
2
|
+
class GemEntry
|
3
|
+
attr_reader :rewriter, :node
|
4
|
+
|
5
|
+
def initialize(rewriter, node)
|
6
|
+
@rewriter = rewriter
|
7
|
+
@node = node
|
8
|
+
end
|
9
|
+
|
10
|
+
def name
|
11
|
+
node.children[2].children[0]
|
12
|
+
end
|
13
|
+
|
14
|
+
# Overriden in prepended modules.
|
15
|
+
def lock(**options)
|
16
|
+
end
|
17
|
+
|
18
|
+
# Overriden in prepended modules.
|
19
|
+
def unlock
|
20
|
+
end
|
21
|
+
|
22
|
+
require 'gemfile_locker/gem_entry/versions'
|
23
|
+
prepend Versions
|
24
|
+
|
25
|
+
require 'gemfile_locker/gem_entry/git_ref'
|
26
|
+
prepend GitRef
|
27
|
+
|
28
|
+
protected
|
29
|
+
|
30
|
+
# Node with gem options, if present.
|
31
|
+
def options_node
|
32
|
+
result = node.children.last
|
33
|
+
result if result.type == :hash
|
34
|
+
end
|
35
|
+
|
36
|
+
# Change content of string, keeping quoting style.
|
37
|
+
def replace_string_node(target, value)
|
38
|
+
quote = target.loc.begin.source
|
39
|
+
rewriter.replace(target.loc.expression, "#{quote}#{value}#{quote}")
|
40
|
+
end
|
41
|
+
|
42
|
+
# Remove node with preceding comma.
|
43
|
+
def remove_node_with_comma(target)
|
44
|
+
expression = target.loc.expression
|
45
|
+
comma_pos = expression.source_buffer.source.rindex(',', expression.begin_pos)
|
46
|
+
rewriter.remove(expression.with(begin_pos: comma_pos))
|
47
|
+
end
|
48
|
+
|
49
|
+
# Quote style used in name of gem.
|
50
|
+
def name_quote
|
51
|
+
node.children[2].loc.begin.source
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
module GemfileLocker
|
2
|
+
class GemEntry
|
3
|
+
module GitRef
|
4
|
+
def lock(options)
|
5
|
+
git_ref = options[:git_ref]
|
6
|
+
set_git_ref(git_ref) if git_ref && !has_git_tag?
|
7
|
+
super
|
8
|
+
end
|
9
|
+
|
10
|
+
def unlock
|
11
|
+
remove_git_ref
|
12
|
+
super
|
13
|
+
end
|
14
|
+
|
15
|
+
def has_git_tag?
|
16
|
+
git_option_nodes.any? { |pair| pair.children[0].children[0] == :tag }
|
17
|
+
end
|
18
|
+
|
19
|
+
def set_git_ref(ref) # rubocop:disable AccessorMethodName
|
20
|
+
ref_node = ref_option_node
|
21
|
+
return replace_string_node(ref_node.children[1], ref) if ref_node
|
22
|
+
git_nodes = git_option_nodes
|
23
|
+
insert_after_node = git_nodes.any? ? git_nodes.last : node.children.last
|
24
|
+
quote = name_quote
|
25
|
+
rewriter.insert_after(insert_after_node.loc.expression.end, ", ref: #{quote}#{ref}#{quote}")
|
26
|
+
end
|
27
|
+
|
28
|
+
def remove_git_ref
|
29
|
+
ref_node = ref_option_node
|
30
|
+
remove_node_with_comma(ref_node) if ref_node
|
31
|
+
end
|
32
|
+
|
33
|
+
protected
|
34
|
+
|
35
|
+
def ref_option_node
|
36
|
+
return unless options_node
|
37
|
+
options_node.children.find do |pair|
|
38
|
+
pair.children[0].to_sexp_array == [:sym, :ref]
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
RELATED_OPTIONS = /\A(git*|branch|tag)\z/
|
43
|
+
|
44
|
+
def git_option_nodes
|
45
|
+
return [] unless options_node
|
46
|
+
options_node.children.reverse.select do |pair|
|
47
|
+
key_node = pair.children[0]
|
48
|
+
next unless key_node.type == :sym
|
49
|
+
RELATED_OPTIONS =~ key_node.children[0].to_s
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
module GemfileLocker
|
2
|
+
class GemEntry
|
3
|
+
module Versions
|
4
|
+
EXTRA_VERSION_REGEXP = /\A[><]/
|
5
|
+
|
6
|
+
def lock(options)
|
7
|
+
version = options[:version]
|
8
|
+
set_version(version) if version
|
9
|
+
super
|
10
|
+
end
|
11
|
+
|
12
|
+
def unlock
|
13
|
+
remove_version
|
14
|
+
super
|
15
|
+
end
|
16
|
+
|
17
|
+
def locked?
|
18
|
+
version_nodes.any?
|
19
|
+
end
|
20
|
+
|
21
|
+
def set_version(version) # rubocop:disable AccessorMethodName
|
22
|
+
version_nodes = self.version_nodes
|
23
|
+
if version_nodes.any?
|
24
|
+
replace_string_node(version_nodes.first, version)
|
25
|
+
else
|
26
|
+
quote = name_quote
|
27
|
+
rewriter.insert_after(node.children[2].loc.end, ", #{quote}#{version}#{quote}")
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def remove_version
|
32
|
+
# If multiple version strings are given, keep that which start with `>, >=, <, <=`.
|
33
|
+
version_nodes = self.version_nodes(strict: ->(versions) { versions.size > 1 })
|
34
|
+
version_nodes.each do |arg_node|
|
35
|
+
remove_node_with_comma(arg_node)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
protected
|
40
|
+
|
41
|
+
def version_nodes(strict_if: nil, strict: !strict_if)
|
42
|
+
result = node.children.drop(3).select { |arg_node| arg_node.type == :str }
|
43
|
+
if strict_if && strict_if[result] || strict
|
44
|
+
result = result.reject do |arg_node|
|
45
|
+
EXTRA_VERSION_REGEXP =~ arg_node.children[0]
|
46
|
+
end
|
47
|
+
end
|
48
|
+
result
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -1,27 +1,22 @@
|
|
1
|
+
require 'parser'
|
2
|
+
require 'parser/current'
|
3
|
+
require 'gemfile_locker/gem_entry'
|
4
|
+
|
1
5
|
module GemfileLocker
|
2
6
|
class GemfileProcessor
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
GEM_MATCH_FIELDS = %i(
|
17
|
-
prefix
|
18
|
-
name
|
19
|
-
name_quote
|
20
|
-
version_prefix
|
21
|
-
version
|
22
|
-
version_quote
|
23
|
-
suffix
|
24
|
-
).freeze
|
7
|
+
class Rewriter < Parser::TreeRewriter
|
8
|
+
def rewrite(*args, &block)
|
9
|
+
@rewrite_block = block
|
10
|
+
super(*args)
|
11
|
+
end
|
12
|
+
|
13
|
+
def on_send(node)
|
14
|
+
children = node.children
|
15
|
+
return unless children[0].nil? && node.children[1] == :gem
|
16
|
+
gem_entry = GemEntry.new(self, node)
|
17
|
+
@rewrite_block[gem_entry]
|
18
|
+
end
|
19
|
+
end
|
25
20
|
|
26
21
|
attr_reader :path, :options
|
27
22
|
|
@@ -30,47 +25,25 @@ module GemfileLocker
|
|
30
25
|
end
|
31
26
|
|
32
27
|
def call(string)
|
33
|
-
|
34
|
-
|
28
|
+
buffer = Parser::Source::Buffer.new('(Gemfile)')
|
29
|
+
buffer.source = string
|
30
|
+
parser = Parser::CurrentRuby.new
|
31
|
+
ast = parser.parse(buffer)
|
32
|
+
Rewriter.new.rewrite(buffer, ast) do |gem_entry|
|
33
|
+
process_gem(gem_entry) unless skip_gem?(gem_entry)
|
35
34
|
end
|
36
35
|
end
|
37
36
|
|
38
|
-
def skip_gem?(
|
37
|
+
def skip_gem?(gem_entry)
|
39
38
|
if options[:only]
|
40
|
-
!options[:only].include?(
|
39
|
+
!options[:only].include?(gem_entry.name)
|
41
40
|
elsif options[:except]
|
42
|
-
options[:except].include?(
|
43
|
-
end
|
44
|
-
end
|
45
|
-
|
46
|
-
def process_gems(string)
|
47
|
-
string.gsub(GEM_LINE_REGEX) do
|
48
|
-
match = Regexp.last_match
|
49
|
-
data = Hash[GEM_MATCH_FIELDS.map { |x| [x, match[x]] }]
|
50
|
-
result = yield data
|
51
|
-
result ||= data
|
52
|
-
GEM_MATCH_FIELDS.map { |x| result[x] }.join
|
41
|
+
options[:except].include?(gem_entry.name)
|
53
42
|
end
|
54
43
|
end
|
55
44
|
|
56
45
|
def process_gem(_name, _data)
|
57
46
|
raise 'Abstract method'
|
58
47
|
end
|
59
|
-
|
60
|
-
def set_gem_version(data, version)
|
61
|
-
data = data.dup
|
62
|
-
if version
|
63
|
-
data[:version_prefix] ||= ", #{data[:name_quote] || "'"}"
|
64
|
-
data[:version_quote] ||= data[:name_quote] || "'"
|
65
|
-
data[:version] = version
|
66
|
-
else
|
67
|
-
%i(
|
68
|
-
version_prefix
|
69
|
-
version
|
70
|
-
version_quote
|
71
|
-
).each { |x| data.delete(x) }
|
72
|
-
end
|
73
|
-
data
|
74
|
-
end
|
75
48
|
end
|
76
49
|
end
|
@@ -20,14 +20,15 @@ module GemfileLocker
|
|
20
20
|
@bundler_specs ||= Bundler::LockfileParser.new(lockfile).specs
|
21
21
|
end
|
22
22
|
|
23
|
-
def process_gem(
|
24
|
-
name =
|
25
|
-
|
26
|
-
|
23
|
+
def process_gem(gem_entry)
|
24
|
+
name = gem_entry.name
|
25
|
+
spec = bundler_specs.find { |x| x.name == name }
|
26
|
+
return unless spec
|
27
|
+
gem_entry.lock(version: prepare_version(spec.version), git_ref: prepare_git_ref(spec))
|
27
28
|
end
|
28
29
|
|
29
|
-
def skip_gem?(
|
30
|
-
super ||
|
30
|
+
def skip_gem?(gem_entry)
|
31
|
+
super || gem_entry.locked? && !options[:force]
|
31
32
|
end
|
32
33
|
|
33
34
|
private
|
@@ -40,5 +41,11 @@ module GemfileLocker
|
|
40
41
|
version.to_s
|
41
42
|
end
|
42
43
|
end
|
44
|
+
|
45
|
+
def prepare_git_ref(spec)
|
46
|
+
if spec.source.is_a?(Bundler::Source::Git)
|
47
|
+
spec.source.options['ref'] || spec.source.revision[0...7]
|
48
|
+
end
|
49
|
+
end
|
43
50
|
end
|
44
51
|
end
|
metadata
CHANGED
@@ -1,43 +1,57 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: gemfile_locker
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Max Melentiev
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2018-06-18 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
|
-
name:
|
14
|
+
name: bundler
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
17
|
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '
|
19
|
+
version: '1.13'
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: '
|
26
|
+
version: '1.13'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
|
-
name:
|
28
|
+
name: parser
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
31
|
- - "~>"
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: '
|
33
|
+
version: '2.0'
|
34
34
|
type: :runtime
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
38
|
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version: '
|
40
|
+
version: '2.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: thor
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0.19'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0.19'
|
41
55
|
- !ruby/object:Gem::Dependency
|
42
56
|
name: rake
|
43
57
|
requirement: !ruby/object:Gem::Requirement
|
@@ -81,6 +95,9 @@ files:
|
|
81
95
|
- lib/gemfile_locker.rb
|
82
96
|
- lib/gemfile_locker/cli.rb
|
83
97
|
- lib/gemfile_locker/file_editor.rb
|
98
|
+
- lib/gemfile_locker/gem_entry.rb
|
99
|
+
- lib/gemfile_locker/gem_entry/git_ref.rb
|
100
|
+
- lib/gemfile_locker/gem_entry/versions.rb
|
84
101
|
- lib/gemfile_locker/gemfile_processor.rb
|
85
102
|
- lib/gemfile_locker/locker.rb
|
86
103
|
- lib/gemfile_locker/unlocker.rb
|
@@ -104,7 +121,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
104
121
|
version: '0'
|
105
122
|
requirements: []
|
106
123
|
rubyforge_project:
|
107
|
-
rubygems_version: 2.
|
124
|
+
rubygems_version: 2.7.7
|
108
125
|
signing_key:
|
109
126
|
specification_version: 4
|
110
127
|
summary: Tool to manage Gemfile. Lock and unlock all dependencies for safe `bundle
|