bundler-gem_bytes 0.1.0 → 0.2.2
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/.release-please-manifest.json +3 -0
- data/CHANGELOG.md +38 -0
- data/README.md +129 -32
- data/Rakefile +9 -0
- data/lib/bundler/gem_bytes/actions/gemspec/attribute.rb +51 -0
- data/lib/bundler/gem_bytes/actions/gemspec/attribute_node.rb +32 -0
- data/lib/bundler/gem_bytes/actions/gemspec/delete_dependency.rb +106 -0
- data/lib/bundler/gem_bytes/actions/gemspec/dependency.rb +73 -0
- data/lib/bundler/gem_bytes/actions/gemspec/dependency_node.rb +32 -0
- data/lib/bundler/gem_bytes/actions/gemspec/gem_specification.rb +121 -0
- data/lib/bundler/gem_bytes/actions/gemspec/upsert_dependency.rb +210 -0
- data/lib/bundler/gem_bytes/actions/gemspec.rb +281 -0
- data/lib/bundler/gem_bytes/actions.rb +43 -0
- data/lib/bundler/gem_bytes/bundler_command.rb +7 -7
- data/lib/bundler/gem_bytes/script_executor.rb +30 -10
- data/lib/bundler/gem_bytes/version.rb +1 -1
- data/lib/bundler/gem_bytes.rb +4 -0
- data/release-please-config.json +22 -0
- metadata +100 -8
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ad62897e0c19142e68da32d5cc2b63e1c2622beeaa9ecda235b48679f50ab3e2
|
4
|
+
data.tar.gz: e3a1340866ca56329fc9d03e4acae7dd1357ac288551ac6c196c79180d5818ff
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 64d2885ac473cea7a79cd7a48a04681ea9d60d0b3e027db73f64b622c827d49656aaf06c7c02b6f4bc46ff2c058b5b6b547f2545714a8d3886c55409a2b70f0e
|
7
|
+
data.tar.gz: 0f226e9914850042449dfd32b190f1f5f3b129ab16b334afa624489bf8633222ba18104017d4489fa820dcd12bb907ea3c89c8aeea80f7bc5a798d763e758fef
|
data/CHANGELOG.md
CHANGED
@@ -5,6 +5,44 @@ All notable changes to the process_executer gem will be documented in this file.
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
7
7
|
|
8
|
+
## [0.2.2](https://github.com/main-branch/bundler-gem_bytes/compare/v0.2.1...v0.2.2) (2025-04-16)
|
9
|
+
|
10
|
+
|
11
|
+
### Bug Fixes
|
12
|
+
|
13
|
+
* Automate commit-to-publish workflow version file path wrong ([4220bd4](https://github.com/main-branch/bundler-gem_bytes/commit/4220bd4428cc4841d56c65fb86540d9237b0944b))
|
14
|
+
|
15
|
+
## [0.2.1](https://github.com/main-branch/bundler-gem_bytes/compare/v0.2.0...v0.2.1) (2025-04-16)
|
16
|
+
|
17
|
+
|
18
|
+
### Features
|
19
|
+
|
20
|
+
* Add a gemspec action to make modification to a project gemspec ([d83d145](https://github.com/main-branch/bundler-gem_bytes/commit/d83d14598922fe8b54de12b92232e8cae6e6e668))
|
21
|
+
* Add the remove_dependency sub-action to the gemspec action ([ba1ff7b](https://github.com/main-branch/bundler-gem_bytes/commit/ba1ff7b8401ff7dd29c37f457da14452ce55c8f2))
|
22
|
+
|
23
|
+
|
24
|
+
### Bug Fixes
|
25
|
+
|
26
|
+
* Allow dependencies to have multiple version constraints ([4217151](https://github.com/main-branch/bundler-gem_bytes/commit/421715118af964e5e53ae35cda445e5b2dfd4f48))
|
27
|
+
* Automate commit-to-publish workflow ([3d018da](https://github.com/main-branch/bundler-gem_bytes/commit/3d018da4b2ac3caceaa81dd12a0b7771fc03db18))
|
28
|
+
|
29
|
+
## v0.2.0 (2024-10-30)
|
30
|
+
|
31
|
+
[Full Changelog](https://github.com/main-branch/bundler-gem_bytes/compare/v0.1.0..v0.2.0)
|
32
|
+
|
33
|
+
Changes since v0.1.0:
|
34
|
+
|
35
|
+
* 96829fd docs: update the releasing guidelines
|
36
|
+
* 25c57f9 feat: make #remove_dependency available for gembytes scripts
|
37
|
+
* b285af5 docs: add development debugging instructions in the README.md
|
38
|
+
* ea05a44 fix: output an informative error when the gemspec parsed is not valid Ruby
|
39
|
+
* 2147776 test: add fully integrated test that installs and runs gembytes via bundler
|
40
|
+
* ab907b4 test: exclude lines from test coverage due to JRuby false positives
|
41
|
+
* 03692ad feat: make #add_dependency available for gembytes scripts
|
42
|
+
* 5d41e08 chore: add Bundler::GemBytes::Actions module to extend the API for gembytes scripts
|
43
|
+
* 6f7be90 chore: add class to upsert a gem dependency into a gemspec
|
44
|
+
* cf1ab4f chore: rake clobber should remove the .bundle directory
|
45
|
+
|
8
46
|
## v0.1.0 (2024-10-17)
|
9
47
|
|
10
48
|
[Full Changelog](https://github.com/main-branch/bundler-gem_bytes/compare/ce13f25..v0.1.0)
|
data/README.md
CHANGED
@@ -7,9 +7,6 @@ Version](https://badge.fury.io/rb/bundler-gem_bytes.svg)](https://badge.fury.io/
|
|
7
7
|
Log](https://img.shields.io/badge/CHANGELOG-Latest-green)](https://rubydoc.info/gems/bundler-gem_bytes/file/CHANGELOG.md)
|
8
8
|
[](https://github.com/main-branch/bundler-gem_bytes/actions/workflows/continuous-integration.yml)
|
10
|
-
[](https://codeclimate.com/github/main-branch/bundler-gem_bytes/maintainability)
|
11
|
-
[](https://codeclimate.com/github/main-branch/bundler-gem_bytes/test_coverage)
|
13
10
|
[](https://conventionalcommits.org)
|
15
12
|
[](https://main-branch.slack.com/archives/C07RKRKTLDT)
|
@@ -36,18 +33,21 @@ own script**
|
|
36
33
|
|
37
34
|
* [Installation](#installation)
|
38
35
|
* [Usage](#usage)
|
39
|
-
|
40
|
-
|
36
|
+
* [Example](#example)
|
37
|
+
* [Handling Errors](#handling-errors)
|
41
38
|
* [Development](#development)
|
39
|
+
* [How this gem works](#how-this-gem-works)
|
40
|
+
* [Debugging](#debugging)
|
41
|
+
* [Releasing](#releasing)
|
42
42
|
* [Contributing](#contributing)
|
43
|
-
|
44
|
-
|
43
|
+
* [Commit message guidelines](#commit-message-guidelines)
|
44
|
+
* [Pull request guidelines](#pull-request-guidelines)
|
45
45
|
* [License](#license)
|
46
46
|
* [Code of Conduct](#code-of-conduct)
|
47
47
|
|
48
48
|
## Installation
|
49
49
|
|
50
|
-
Install
|
50
|
+
Install the `bundler gem-bytes` command as follows:
|
51
51
|
|
52
52
|
```shell
|
53
53
|
bundle plugin install bunder-gem_bytes
|
@@ -79,42 +79,106 @@ After checking out the repo, run `bin/setup` to install dependencies. Then, run
|
|
79
79
|
workflow. You can also run `bin/console` for an interactive prompt that will allow
|
80
80
|
you to experiment.
|
81
81
|
|
82
|
-
|
83
|
-
release a new version, update the version number in `version.rb`, and then run
|
84
|
-
`bundle exec rake release`, which will create a git tag for the version, push git
|
85
|
-
commits and the created tag, and push the `.gem` file to
|
86
|
-
[rubygems.org](https://rubygems.org).
|
82
|
+
### How this gem works
|
87
83
|
|
88
|
-
|
89
|
-
|
84
|
+
1. The user runs the `bundler gem-bytes` command from the command line, passing the
|
85
|
+
path or URL to a GemBytes script:
|
90
86
|
|
91
|
-
```shell
|
92
|
-
bundler
|
93
|
-
```
|
87
|
+
```shell
|
88
|
+
bundler gem-bytes [SCRIPT]
|
89
|
+
```
|
94
90
|
|
95
|
-
|
91
|
+
2. The `plugins.rb` file (in the root directory of this project) defines
|
92
|
+
`Bundler::GemBytes::BundlerCommand` class as the handler for the `gem-bytes`
|
93
|
+
bundler command:
|
96
94
|
|
97
|
-
```
|
98
|
-
|
99
|
-
bundler-gem_bytes
|
100
|
-
-----
|
101
|
-
gem-bytes
|
95
|
+
```ruby
|
96
|
+
require 'bundler/gem_bytes'
|
102
97
|
|
103
|
-
|
104
|
-
|
98
|
+
# Register Bundler::GemBytes::BundlerCommand as the handler for the `gem-bytes`
|
99
|
+
# bundler command
|
105
100
|
|
106
|
-
|
101
|
+
Bundler::Plugin::API.command('gem-bytes', Bundler::GemBytes::BundlerCommand)
|
102
|
+
```
|
107
103
|
|
108
|
-
|
109
|
-
|
110
|
-
|
104
|
+
3. Bundler invokes the gem-bytes plugin by creating an instance of
|
105
|
+
`Bundler::GemBytes::BundlerCommand` and then calling `#exec(command, args)` on
|
106
|
+
that instance. Where:
|
107
|
+
|
108
|
+
* `command` is the bundler command given on the command line. It will always be
|
109
|
+
"gem-bytes".
|
110
|
+
* `args` is the array of any other arguments given on the command line after the
|
111
|
+
command. In this case, we expect the script path or URI.
|
112
|
+
|
113
|
+
4. The `BundlerCommand` instance creates a `Bundler::GemBytes::ScriptExecutor`
|
114
|
+
instance and calls `#execute(path_or_uri)` on that instance. This method in turn
|
115
|
+
calls `Thor::Actions#apply(path_or_uri)` to load the external script and execute
|
116
|
+
it in the context of the `ScriptExecutor` instance.
|
111
117
|
|
112
|
-
|
118
|
+
The `#apply` method, part of the `Thor::Actions` module, loads and executes the
|
119
|
+
script within the context of the `ScriptExecutor` instance.
|
120
|
+
|
121
|
+
If an error occurs during script execution, `BundlerCommand` catches the error, outputs an error message to `stderr`, and exits with a status code of `1`.
|
122
|
+
|
123
|
+
5. The `ScriptExecutor` class provides the environment/binding in which the GemBytes
|
124
|
+
script is executed, allowing the script to use instance methods and context from
|
125
|
+
`ScriptExecutor`. In addition to core Ruby and Active Support, the API available
|
126
|
+
to this script includes methods from both the
|
127
|
+
[`Thor::Actions`](https://github.com/rails/thor/wiki/Actions) and
|
128
|
+
`Bundler::GemBytes::Actions` modules, which provide utilities for file
|
129
|
+
manipulation, template generation, and other tasks essential for script execution.
|
130
|
+
|
131
|
+
### Debugging
|
132
|
+
|
133
|
+
To debug this gem it is recommended that you create a test project and install
|
134
|
+
this plugin with bundler from source code as follows:
|
113
135
|
|
114
136
|
```shell
|
115
|
-
|
137
|
+
# 1. Create a temp directory for testing (from the root directory of the project)
|
138
|
+
mkdir temp
|
139
|
+
cd temp
|
140
|
+
|
141
|
+
# 2. Create an new, empty RubyGem project to test
|
142
|
+
BUNDLE_IGNORE_CONFIG=TRUE bundle gem foo --no-test --no-ci --no-mit --no-coc --no-linter --no-changelog
|
143
|
+
cd foo
|
144
|
+
|
145
|
+
# 3. Install the plugin from source
|
146
|
+
BUNDLE_IGNORE_CONFIG=TRUE bundle plugin install --path ../.. bundler-gem_bytes
|
147
|
+
|
148
|
+
# 4. Create a gembytes script to add a development dependency on rubocop
|
149
|
+
cat <<SCRIPT > gem_bytes_script.rb
|
150
|
+
gemspec do
|
151
|
+
add_development_dependency "rubocop", "~> 1.68"
|
152
|
+
end
|
153
|
+
SCRIPT
|
154
|
+
|
155
|
+
# 5. Modify code, set breakpoints, or add binding.{irb|pry} calls to the source
|
156
|
+
|
157
|
+
# 6. Run the plugin
|
158
|
+
BUNDLE_IGNORE_CONFIG=TRUE bundle gem-bytes gem_bytes_script.rb
|
159
|
+
|
160
|
+
# Repeat 4 - 6 until satisified :)
|
116
161
|
```
|
117
162
|
|
163
|
+
### Releasing
|
164
|
+
|
165
|
+
To release a new version of this gem, run `create-github-release [TYPE]` where
|
166
|
+
TYPE is MAJOR, MINOR, or PATCH according to SemVer based on the changes that
|
167
|
+
have been made since the last release:
|
168
|
+
|
169
|
+
* MAJOR: changes that break compatibility with previous versions, such as removing a
|
170
|
+
public method, changing a method signature, or modifying the expected behavior of a
|
171
|
+
method.
|
172
|
+
* MINOR: changes that add new features, enhance existing features, or deprecate
|
173
|
+
features in a backward-compatible way, such as adding a new method or improving
|
174
|
+
performance without breaking existing functionality.
|
175
|
+
* PATCH: changes that fix bugs or make other small modifications that do not affect
|
176
|
+
the API or alter existing functionality, such as fixing user-facing typos or
|
177
|
+
updating user documentation.
|
178
|
+
|
179
|
+
This command must be run from the project root directory with a clean worktree on the
|
180
|
+
default branch.
|
181
|
+
|
118
182
|
## Contributing
|
119
183
|
|
120
184
|
Bug reports and pull requests are welcome on GitHub at
|
@@ -158,3 +222,36 @@ License](https://opensource.org/licenses/MIT).
|
|
158
222
|
Everyone interacting in the Bundler::GemBytes project's codebases, issue trackers,
|
159
223
|
chat rooms and mailing lists is expected to follow the [code of
|
160
224
|
conduct](https://github.com/main-branch/bundler-gem_bytes/blob/main/CODE_OF_CONDUCT.md).
|
225
|
+
|
226
|
+
gemspec path do |spec_var, spec|
|
227
|
+
add_dependency 'example', '~> 1.1'
|
228
|
+
add_runtime_dependency 'example', '~> 1.1', '>= 1.1.4'
|
229
|
+
add_development_dependency "rubocop", "~> 1.68"
|
230
|
+
|
231
|
+
remove_dependency "example"
|
232
|
+
|
233
|
+
attr "description", "#{spec.description}. Enhanced by GemBytes."
|
234
|
+
attr "author", ENV['USER']
|
235
|
+
attr "files", "Dir['lib/**/*.rb'] + Dir['bin/*']", quote: false
|
236
|
+
attr "authors", <% spec.authors %>.append('GemBytes').inspect, quote: false
|
237
|
+
|
238
|
+
remove_attr "license"
|
239
|
+
|
240
|
+
metadata "homepage_url", "https://github.com/example/"
|
241
|
+
|
242
|
+
remove_metadata "wiki_uri"
|
243
|
+
|
244
|
+
in_block("if RUBY_PLATFORM != 'java'", "end") do
|
245
|
+
development_dependency 'redcarpet', '~> 3.5'
|
246
|
+
development_dependency 'yard', '~> 0.9'
|
247
|
+
development_dependency 'yardstick', '~> 0.9'
|
248
|
+
end
|
249
|
+
|
250
|
+
code <<~CODE
|
251
|
+
if RUBY_PLATFORM != 'java'
|
252
|
+
<%= spec_var %>.add_development_dependency 'redcarpet', '~> 3.5'
|
253
|
+
<%= spec_var %>.add_development_dependency 'yard', '~> 0.9'
|
254
|
+
<%= spec_var %>.add_development_dependency 'yardstick', '~> 0.9'
|
255
|
+
end
|
256
|
+
CODE
|
257
|
+
end
|
data/Rakefile
CHANGED
@@ -25,6 +25,13 @@ rescue Bundler::BundlerError => e
|
|
25
25
|
exit e.status_code
|
26
26
|
end
|
27
27
|
|
28
|
+
# Make it so that calling `rake release` just calls `rake release:rubygems_push` to
|
29
|
+
# avoid creating and pushing a new tag.
|
30
|
+
|
31
|
+
Rake::Task['release'].clear
|
32
|
+
desc 'Customized release task to avoid creating a new tag'
|
33
|
+
task release: 'release:rubygem_push'
|
34
|
+
|
28
35
|
CLEAN << 'pkg'
|
29
36
|
CLOBBER << 'Gemfile.lock'
|
30
37
|
|
@@ -56,6 +63,7 @@ unless RUBY_PLATFORM == 'java'
|
|
56
63
|
|
57
64
|
YARD::Rake::YardocTask.new(:build) do |t|
|
58
65
|
t.files = %w[lib/**/*.rb examples/**/*]
|
66
|
+
t.options = ['--markup-provider', 'redcarpet', '--markup', 'markdown']
|
59
67
|
t.stats_options = ['--list-undoc']
|
60
68
|
end
|
61
69
|
|
@@ -85,3 +93,4 @@ end
|
|
85
93
|
|
86
94
|
CLOBBER << 'package-lock.json'
|
87
95
|
CLOBBER << 'node_modules'
|
96
|
+
CLOBBER << '.bundle'
|
@@ -0,0 +1,51 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'parser/current'
|
4
|
+
require 'rubocop-ast'
|
5
|
+
require 'active_support/core_ext/object'
|
6
|
+
|
7
|
+
module Bundler
|
8
|
+
module GemBytes
|
9
|
+
module Actions
|
10
|
+
class Gemspec < Parser::TreeRewriter
|
11
|
+
# Holds the components of a attribute: a name and a value
|
12
|
+
#
|
13
|
+
# @api public
|
14
|
+
#
|
15
|
+
# Attributes in the gemspec look like the following:
|
16
|
+
#
|
17
|
+
# ```ruby
|
18
|
+
# Gem::Specification.new do |spec|
|
19
|
+
# spec.name = 'test'
|
20
|
+
# end
|
21
|
+
# ```
|
22
|
+
#
|
23
|
+
# @!attribute [r] name
|
24
|
+
# The name of the attribute
|
25
|
+
# @example
|
26
|
+
# attribute.name #=> "test"
|
27
|
+
#
|
28
|
+
# @return [String]
|
29
|
+
# @api public
|
30
|
+
#
|
31
|
+
# @!attribute [r] value
|
32
|
+
# The value of the attribute expressed as an AST tree
|
33
|
+
# @example
|
34
|
+
# attribute.value.to_sexp #=> 's(:str, "my_description")'
|
35
|
+
# @return [Parser::AST::Node]
|
36
|
+
# @api public
|
37
|
+
#
|
38
|
+
# @!method to_a()
|
39
|
+
# Converts the attribute into an array
|
40
|
+
# @example
|
41
|
+
# dependency.to_a #=> ["description", [:str, "my_description"]]
|
42
|
+
# @return [Array]
|
43
|
+
# @api public
|
44
|
+
#
|
45
|
+
Attribute = Struct.new(:name, :value) do
|
46
|
+
def to_a = [name, value.to_sexp_array]
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'parser/current'
|
4
|
+
require 'rubocop-ast'
|
5
|
+
require 'active_support/core_ext/object'
|
6
|
+
|
7
|
+
module Bundler
|
8
|
+
module GemBytes
|
9
|
+
module Actions
|
10
|
+
class Gemspec < Parser::TreeRewriter
|
11
|
+
# Maps a dependency declaration to the AST that represents it
|
12
|
+
# @api public
|
13
|
+
#
|
14
|
+
# @!attribute [r] node
|
15
|
+
# The AST node for the attribute
|
16
|
+
# @example
|
17
|
+
# attribute_node.node #=> ...
|
18
|
+
# @return [Parser::AST::Node]
|
19
|
+
# @api public
|
20
|
+
#
|
21
|
+
# @!attribute [r] attribute
|
22
|
+
# The components of the attribute from the AST node
|
23
|
+
# @example
|
24
|
+
# attribute_node.attribute.to_a #=> ["description", [:str, "My deescription"]]
|
25
|
+
# @return [Dependency]
|
26
|
+
# @api public
|
27
|
+
#
|
28
|
+
AttributeNode = Struct.new(:node, :attribute)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,106 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'parser/current'
|
4
|
+
require 'rubocop-ast'
|
5
|
+
require 'active_support/core_ext/object'
|
6
|
+
|
7
|
+
module Bundler
|
8
|
+
module GemBytes
|
9
|
+
module Actions
|
10
|
+
class Gemspec < Parser::TreeRewriter
|
11
|
+
# Remove a dependency in a gemspec
|
12
|
+
#
|
13
|
+
# If a dependency on the given gem is not found, this action does nothing.
|
14
|
+
#
|
15
|
+
# If one or more dependencies are found on the same gem as gem_name,
|
16
|
+
# the are removed from the gemspec.
|
17
|
+
#
|
18
|
+
# The gemspec is updated via calls to the tree_rewriter object.
|
19
|
+
#
|
20
|
+
# @!attribute [r] tree_rewriter
|
21
|
+
# The object that updates the source
|
22
|
+
# @return [Parser::TreeRewriter]
|
23
|
+
# @api private
|
24
|
+
#
|
25
|
+
# @!attribute [r] gemspec_block
|
26
|
+
# The root AST node of the Gem::Specification block from the gemspec
|
27
|
+
# @return [Parser::AST::Node]
|
28
|
+
# @api private
|
29
|
+
#
|
30
|
+
# @!attribute [r] receiver_name
|
31
|
+
# The name of the receiver for the Gem::Specification block
|
32
|
+
# @return [Symbol]
|
33
|
+
# @api private
|
34
|
+
#
|
35
|
+
# @!attribute [r] dependencies
|
36
|
+
# The dependency declarations found in the gemspec file
|
37
|
+
# @return [Array<DependencyNode>]
|
38
|
+
# @api private
|
39
|
+
#
|
40
|
+
# @!attribute [r] gem_name
|
41
|
+
# The name of the gem to remove dependency on
|
42
|
+
# @return [String]
|
43
|
+
# @api private
|
44
|
+
#
|
45
|
+
# @api public
|
46
|
+
class DeleteDependency
|
47
|
+
# Initializes the delete dependency action
|
48
|
+
# @param tree_rewriter [Parser::TreeRewriter] The object that updates the source
|
49
|
+
# @param gemspec_block [Parser::AST::Node] The Gem::Specification block
|
50
|
+
# @param receiver_name [Symbol] The name of the receiver for the Gem::Specification block
|
51
|
+
# @param dependencies [Array<DependencyNode>] The dependency declarations found in the gemspec file
|
52
|
+
# @api private
|
53
|
+
def initialize(tree_rewriter, gemspec_block, receiver_name, dependencies)
|
54
|
+
@tree_rewriter = tree_rewriter
|
55
|
+
@gemspec_block = gemspec_block
|
56
|
+
@receiver_name = receiver_name
|
57
|
+
@dependencies = dependencies
|
58
|
+
end
|
59
|
+
|
60
|
+
attr_reader :tree_rewriter, :gemspec_block, :receiver_name, :dependencies, :gem_name
|
61
|
+
|
62
|
+
# Adds or updates a dependency to the Gem::Specification block
|
63
|
+
#
|
64
|
+
# @example
|
65
|
+
# delete_dependency = DeleteDependency.new(tree_rewriter, gemspec_block, receiver_name, dependencies)
|
66
|
+
# gem_name = 'rubocop'
|
67
|
+
# depete_dependency.call(gem_name)
|
68
|
+
# @param gem_name [String] The name of the gem to remove dependency on
|
69
|
+
# @return [void]
|
70
|
+
# @api public
|
71
|
+
def call(gem_name)
|
72
|
+
@gem_name = gem_name
|
73
|
+
matching_dependencies = dependencies.select { |d| d.dependency.gem_name == gem_name }
|
74
|
+
|
75
|
+
delete_dependencies(matching_dependencies) if matching_dependencies.any?
|
76
|
+
end
|
77
|
+
|
78
|
+
# Removes the matching dependencies from the gemspec
|
79
|
+
# @param matching_dependencies [Array<DependencyNode>] The existing dependencies that match gem_name
|
80
|
+
# @return [void]
|
81
|
+
# @api private
|
82
|
+
def delete_dependencies(matching_dependencies)
|
83
|
+
matching_dependencies.each do |found_dependency|
|
84
|
+
tree_rewriter.replace(full_line_range(found_dependency), '')
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
private
|
89
|
+
|
90
|
+
# Expand the range for a node to include any leading whitespace and newline
|
91
|
+
# @param dependency_node [DependencyNode] The node to remove
|
92
|
+
# @return [Parser::Source::Range] The range of the whole line including whitespace
|
93
|
+
# @api private
|
94
|
+
def full_line_range(dependency_node)
|
95
|
+
range = dependency_node.node.loc.expression
|
96
|
+
source_buffer = range.source_buffer
|
97
|
+
# The whole line including leading and trailing whitespace
|
98
|
+
line_range = source_buffer.line_range(range.line)
|
99
|
+
# Expand the range to include the leading newline
|
100
|
+
line_range.with(begin_pos: line_range.begin_pos - 1)
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'parser/current'
|
4
|
+
require 'rubocop-ast'
|
5
|
+
require 'active_support/core_ext/object'
|
6
|
+
|
7
|
+
module Bundler
|
8
|
+
module GemBytes
|
9
|
+
module Actions
|
10
|
+
class Gemspec < Parser::TreeRewriter
|
11
|
+
# Holds the components of a dependency declaration
|
12
|
+
#
|
13
|
+
# @api public
|
14
|
+
#
|
15
|
+
# A dependency declaration is a call to `add_dependency`,
|
16
|
+
# `add_runtime_dependency`, or `add_development_dependency` in the
|
17
|
+
# Gem::Specification block.
|
18
|
+
#
|
19
|
+
# For example, the following is a dependency declaration:
|
20
|
+
#
|
21
|
+
# ```ruby
|
22
|
+
# spec.add_dependency 'rubocop', '~> 1.0'
|
23
|
+
# ```
|
24
|
+
#
|
25
|
+
# Would be represented by a Dependency object with the following
|
26
|
+
# attributes:
|
27
|
+
# * method_name: :add_dependency
|
28
|
+
# * gem_name: 'rubocop'
|
29
|
+
# * version_constraint: '~> 1.0'
|
30
|
+
#
|
31
|
+
# @!attribute [r] method_name
|
32
|
+
# The name of the method called to add the dependency
|
33
|
+
#
|
34
|
+
# Must be one of the following:
|
35
|
+
#
|
36
|
+
# * :add_dependency
|
37
|
+
# * :add_runtime_dependency
|
38
|
+
# * :add_development_dependency
|
39
|
+
#
|
40
|
+
# @example
|
41
|
+
# dependency.method_name #=> :add_dependency
|
42
|
+
#
|
43
|
+
# @return [Symbol]
|
44
|
+
# @api public
|
45
|
+
#
|
46
|
+
# @!attribute [r] gem_name
|
47
|
+
# The name of the gem being depended on
|
48
|
+
# @example
|
49
|
+
# dependency.gem_name #=> "rubocop"
|
50
|
+
# @return [String]
|
51
|
+
# @api public
|
52
|
+
#
|
53
|
+
# @!attribute [r] version_constraints
|
54
|
+
# The version constraints for the dependency
|
55
|
+
# @example
|
56
|
+
# dependency.version_constraints #=> ["~> 1.68", ">= 1.68.3"]
|
57
|
+
# @return [Array<String>]
|
58
|
+
# @api public
|
59
|
+
#
|
60
|
+
# @!method to_a()
|
61
|
+
# Converts the dependency into an array
|
62
|
+
# @example
|
63
|
+
# dependency.to_a #=> [:add_runtime_dependency, "rubocop", "~> 1.68"]
|
64
|
+
# @return [Array]
|
65
|
+
# @api public
|
66
|
+
#
|
67
|
+
Dependency = Struct.new(:method_name, :gem_name, :version_constraints) do
|
68
|
+
def to_a = [method_name, gem_name, *version_constraints]
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'parser/current'
|
4
|
+
require 'rubocop-ast'
|
5
|
+
require 'active_support/core_ext/object'
|
6
|
+
|
7
|
+
module Bundler
|
8
|
+
module GemBytes
|
9
|
+
module Actions
|
10
|
+
class Gemspec < Parser::TreeRewriter
|
11
|
+
# Maps a dependency declaration to the AST that represents it
|
12
|
+
# @api public
|
13
|
+
#
|
14
|
+
# @!attribute [r] node
|
15
|
+
# The AST node for the dependency declaration
|
16
|
+
# @example
|
17
|
+
# dependency_node.node #=> ...
|
18
|
+
# @return [Parser::AST::Node]
|
19
|
+
# @api public
|
20
|
+
#
|
21
|
+
# @!attribute [r] dependency
|
22
|
+
# The components of the dependency declaration from the AST node
|
23
|
+
# @example
|
24
|
+
# dependency_node.dependency.to_a #=> [:add_dependency, 'rubocop', '~> 1.68']
|
25
|
+
# @return [Dependency]
|
26
|
+
# @api public
|
27
|
+
#
|
28
|
+
DependencyNode = Struct.new(:node, :dependency)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|