packwerk 1.4.0 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +1 -0
- data/Gemfile.lock +1 -1
- data/README.md +0 -2
- data/UPGRADING.md +54 -0
- data/USAGE.md +0 -42
- data/lib/packwerk/application_validator.rb +0 -53
- data/lib/packwerk/association_inspector.rb +1 -1
- data/lib/packwerk/cli.rb +10 -15
- data/lib/packwerk/configuration.rb +34 -4
- data/lib/packwerk/constant_discovery.rb +1 -1
- data/lib/packwerk/formatters/offenses_formatter.rb +1 -1
- data/lib/packwerk/formatters/progress_formatter.rb +1 -1
- data/lib/packwerk/generators/configuration_file.rb +4 -19
- data/lib/packwerk/generators/templates/packwerk.yml.erb +0 -6
- data/lib/packwerk/run_context.rb +1 -1
- data/lib/packwerk/version.rb +1 -1
- data/lib/packwerk.rb +3 -9
- metadata +4 -7
- data/lib/packwerk/generators/inflections_file.rb +0 -43
- data/lib/packwerk/generators/templates/inflections.yml +0 -6
- data/lib/packwerk/inflections/custom.rb +0 -33
- data/lib/packwerk/inflections/default.rb +0 -73
- data/lib/packwerk/inflector.rb +0 -49
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a473db2c54adea132ca7e61a51072b570d7e37b7d63c021259eef3cc7625177b
|
4
|
+
data.tar.gz: 1b8486e61969621fac562d2fb6ebe47dcf6f71fcd13f6d18524337a3ed831ac2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8c05f0ce6e8b398a87e98453c721d00707628918ce8455600c1cb00fb2cb9c68efc6bea373323e889d36fc3658ff45db3508b0e6386b876da58ca50cdb53ab9f
|
7
|
+
data.tar.gz: 51586b68f489ff1f32df06338d05a64cab753da56c11575b3c5c8fa55019e9a8527e0a20c54c8695e1432307227d26c10f01b0d6c610e41c55d84296be000bd8
|
data/CHANGELOG.md
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
See https://github.com/Shopify/packwerk/releases.
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -35,8 +35,6 @@ Watch a [1-minute video demo](https://www.youtube.com/watch?v=NwqlyBAxVpQ&featur
|
|
35
35
|
gem 'packwerk'
|
36
36
|
```
|
37
37
|
|
38
|
-
_Note: Packwerk has to be grouped in production environment within the Gemfile if your Rails app has custom inflections._
|
39
|
-
|
40
38
|
2. Install the gem
|
41
39
|
|
42
40
|
Execute:
|
data/UPGRADING.md
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
# Upgrading from 1.x to 2.0
|
2
|
+
|
3
|
+
With Packwerk 2.0, we made a few changes to simplify the setup. Updating will require removing some previously necessary files and configuration.
|
4
|
+
|
5
|
+
## Gem group
|
6
|
+
|
7
|
+
Because packwerk is no longer involved in specifying the application's inflections, it doesn't have to live in the `production` group in your `Gemfile` anymore. We recommend moving it to the `development` group.
|
8
|
+
|
9
|
+
## Removing application config caches
|
10
|
+
|
11
|
+
### Load paths
|
12
|
+
We no longer require the `load_paths` key in `packwerk.yml`. You can simply delete the load_paths key as it will not be read anymore. Instead, Packwerk will ask Rails for load paths. If you're using spring, make sure to properly set up spring (see [USAGE.md](USAGE.md#setting-up-spring)) to keep packwerk fast.
|
13
|
+
|
14
|
+
### Inflections
|
15
|
+
We no longer require a custom `inflections.yml` file. Instead, you'll want to revert BACK to using the `inflections.rb` initializer as you would have done prior to adopting packwerk. To do this, you'll want to convert back to using the plain [ActiveSupport Inflections API](https://api.rubyonrails.org/classes/ActiveSupport/Inflector/Inflections.html).
|
16
|
+
|
17
|
+
|
18
|
+
Given the following example `inflections.yml`, here is an example `inflections.rb` that would follow. Tip: if you're using git, you can run `git log config/inflections.yml`, find the first commit that introduced `inflections.yml`, find the COMMIT_SHA, and then run `git show COMMIT_SHA` to see what your inflections file looked like before (note that you may have changed `inflections.yml` since then, though).
|
19
|
+
|
20
|
+
`config/inflections.yml`
|
21
|
+
```yml
|
22
|
+
# List your inflections in this file instead of `inflections.rb`
|
23
|
+
# See steps to set up custom inflections:
|
24
|
+
# https://github.com/Shopify/packwerk/blob/main/USAGE.md#Inflections
|
25
|
+
|
26
|
+
acronym:
|
27
|
+
- 'HTML'
|
28
|
+
- 'API'
|
29
|
+
|
30
|
+
singular:
|
31
|
+
- ['oxen', 'oxen']
|
32
|
+
|
33
|
+
irregular:
|
34
|
+
- ['person', 'people']
|
35
|
+
|
36
|
+
uncountable:
|
37
|
+
- 'fish'
|
38
|
+
- 'sheep'
|
39
|
+
```
|
40
|
+
|
41
|
+
`config/initializers/inflections.rb`
|
42
|
+
```ruby
|
43
|
+
ActiveSupport::Inflector.inflections(:en) do |inflect|
|
44
|
+
inflect.acronym('HTML')
|
45
|
+
inflect.acronym('API')
|
46
|
+
|
47
|
+
inflect.singular('oxen', 'oxen')
|
48
|
+
|
49
|
+
inflect.irregular('person', 'people')
|
50
|
+
|
51
|
+
inflect.uncountable('fish')
|
52
|
+
inflect.uncountable('sheep')
|
53
|
+
end
|
54
|
+
```
|
data/USAGE.md
CHANGED
@@ -9,7 +9,6 @@
|
|
9
9
|
* [Setting up Spring](#setting-up-spring)
|
10
10
|
* [Configuring Packwerk](#configuring-packwerk)
|
11
11
|
* [Using a custom ERB parser](#using-a-custom-erb-parser)
|
12
|
-
* [Inflections](#inflections)
|
13
12
|
* [Validating the package system](#validating-the-package-system)
|
14
13
|
* [Defining packages](#defining-packages)
|
15
14
|
* [Package metadata](#package-metadata)
|
@@ -57,7 +56,6 @@ Here is a list of files generated:
|
|
57
56
|
|-----------------------------|--------------|------------|
|
58
57
|
| Packwerk configuration | packwerk.yml | See [Setting up the configuration file](#Setting-up-the-configuration-file) |
|
59
58
|
| Root package | package.yml | A package for the root folder |
|
60
|
-
| Custom inflections | config/inflections.yml | A custom inflections file is only required if you have custom inflections in `inflections.rb`, see [Inflections](#Inflections) |
|
61
59
|
|
62
60
|
After that, you may begin creating packages for your application. See [Defining packages](#Defining-packages)
|
63
61
|
|
@@ -77,7 +75,6 @@ Packwerk reads from the `packwerk.yml` configuration file in the root directory.
|
|
77
75
|
| include | **/*.{rb,rake,erb} | list of patterns for folder paths to include |
|
78
76
|
| exclude | {bin,node_modules,script,tmp,vendor}/**/* | list of patterns for folder paths to exclude |
|
79
77
|
| package_paths | **/ | a single pattern or a list of patterns to find package configuration files, see: [Defining packages](#Defining-packages) |
|
80
|
-
| load_paths | All application autoload paths | list of load paths |
|
81
78
|
| custom_associations | N/A | list of custom associations, if any |
|
82
79
|
| parallel | true | when true, fork code parsing out to subprocesses |
|
83
80
|
|
@@ -103,45 +100,6 @@ end
|
|
103
100
|
Packwerk::Parsers::Factory.instance.erb_parser_class = CustomParser
|
104
101
|
```
|
105
102
|
|
106
|
-
### Inflections
|
107
|
-
|
108
|
-
Packwerk requires custom inflections to be defined in `inflections.yml` instead of the traditional `inflections.rb`. This is because Packwerk accounts for custom inflections, such as acronyms, when resolving constants. Additionally, Packwerk interprets Active Record associations as references to constants. For example, `has_many :birds` is a reference to the `Bird` constant.
|
109
|
-
|
110
|
-
In order to make your custom inflections compatible with Active Support and Packwerk, you must create a `config/inflections.yml` file and point `ActiveSupport::Inflector` to that file.
|
111
|
-
|
112
|
-
In `inflections.rb`, add:
|
113
|
-
|
114
|
-
```rb
|
115
|
-
require "packwerk/inflections/custom"
|
116
|
-
|
117
|
-
ActiveSupport::Inflector.inflections do |inflect|
|
118
|
-
# please add all custom inflections in the file below.
|
119
|
-
Packwerk::Inflections::Custom.new(
|
120
|
-
Rails.root.join("config", "inflections.yml")
|
121
|
-
).apply_to(inflect)
|
122
|
-
end
|
123
|
-
```
|
124
|
-
|
125
|
-
_Note: Packwerk has to be grouped in production environment within the Gemfile if you have custom inflections._
|
126
|
-
|
127
|
-
Next, move your existing custom inflections into `config/inflections.yml`:
|
128
|
-
|
129
|
-
```yaml
|
130
|
-
acronym:
|
131
|
-
- 'GraphQL'
|
132
|
-
- 'MRuby'
|
133
|
-
- 'TOS'
|
134
|
-
irregular:
|
135
|
-
- ['analysis', 'analyses']
|
136
|
-
- ['reserve', 'reserves']
|
137
|
-
uncountable:
|
138
|
-
- 'payment_details'
|
139
|
-
singular:
|
140
|
-
- [!ruby/regexp /status$/, 'status']
|
141
|
-
```
|
142
|
-
|
143
|
-
Any new inflectors should be added to `config/inflections.yml`.
|
144
|
-
|
145
103
|
## Validating the package system
|
146
104
|
|
147
105
|
There are some criteria that an application must meet in order to have a valid package system. These criteria include having a valid autoload path cache, package definition files, and application folder structure. The dependency graph within the package system also has to be acyclic.
|
@@ -1,7 +1,6 @@
|
|
1
1
|
# typed: true
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
|
-
require "active_support/inflector/inflections"
|
5
4
|
require "constant_resolver"
|
6
5
|
require "pathname"
|
7
6
|
require "yaml"
|
@@ -14,19 +13,15 @@ module Packwerk
|
|
14
13
|
@config_file_path = config_file_path
|
15
14
|
@configuration = configuration
|
16
15
|
@environment = environment
|
17
|
-
|
18
|
-
@application_load_paths = ApplicationLoadPaths.extract_relevant_paths(configuration.root_path, environment)
|
19
16
|
end
|
20
17
|
|
21
18
|
Result = Struct.new(:ok?, :error_value)
|
22
19
|
|
23
20
|
def check_all
|
24
21
|
results = [
|
25
|
-
check_autoload_path_cache,
|
26
22
|
check_package_manifests_for_privacy,
|
27
23
|
check_package_manifest_syntax,
|
28
24
|
check_application_structure,
|
29
|
-
check_inflection_file,
|
30
25
|
check_acyclic_graph,
|
31
26
|
check_package_manifest_paths,
|
32
27
|
check_valid_package_dependencies,
|
@@ -36,21 +31,6 @@ module Packwerk
|
|
36
31
|
merge_results(results)
|
37
32
|
end
|
38
33
|
|
39
|
-
def check_autoload_path_cache
|
40
|
-
expected = Set.new(@application_load_paths)
|
41
|
-
actual = Set.new(@configuration.load_paths)
|
42
|
-
if expected == actual
|
43
|
-
Result.new(true)
|
44
|
-
else
|
45
|
-
Result.new(
|
46
|
-
false,
|
47
|
-
"Load path cache in #{@config_file_path} incorrect!\n"\
|
48
|
-
"Paths missing from file:\n#{format_yaml_strings(expected - actual)}\n"\
|
49
|
-
"Extraneous load paths in file:\n#{format_yaml_strings(actual - expected)}"
|
50
|
-
)
|
51
|
-
end
|
52
|
-
end
|
53
|
-
|
54
34
|
def check_package_manifests_for_privacy
|
55
35
|
privacy_settings = package_manifests_settings_for("enforce_privacy")
|
56
36
|
|
@@ -142,39 +122,6 @@ module Packwerk
|
|
142
122
|
end
|
143
123
|
end
|
144
124
|
|
145
|
-
def check_inflection_file
|
146
|
-
inflections_file = @configuration.inflections_file
|
147
|
-
|
148
|
-
application_inflections = ActiveSupport::Inflector.inflections
|
149
|
-
packwerk_inflections = Packwerk::Inflector.from_file(inflections_file).inflections
|
150
|
-
|
151
|
-
results = %i(plurals singulars uncountables humans acronyms).map do |type|
|
152
|
-
expected = application_inflections.public_send(type).to_set
|
153
|
-
actual = packwerk_inflections.public_send(type).to_set
|
154
|
-
|
155
|
-
if expected == actual
|
156
|
-
Result.new(true)
|
157
|
-
else
|
158
|
-
missing_msg = unless (expected - actual).empty?
|
159
|
-
"Expected #{type} to be specified in file: #{expected - actual}"
|
160
|
-
end
|
161
|
-
extraneous_msg = unless (actual - expected).empty?
|
162
|
-
"Extraneous #{type} was specified in file: #{actual - expected}"
|
163
|
-
end
|
164
|
-
Result.new(
|
165
|
-
false,
|
166
|
-
[missing_msg, extraneous_msg].join("\n")
|
167
|
-
)
|
168
|
-
end
|
169
|
-
end
|
170
|
-
|
171
|
-
merge_results(
|
172
|
-
results,
|
173
|
-
separator: "\n",
|
174
|
-
errors_headline: "Inflections specified in #{inflections_file} don't line up with application!\n"
|
175
|
-
)
|
176
|
-
end
|
177
|
-
|
178
125
|
def check_acyclic_graph
|
179
126
|
edges = package_set.flat_map do |package|
|
180
127
|
package.dependencies.map { |dependency| [package, package_set.fetch(dependency)] }
|
@@ -19,7 +19,7 @@ module Packwerk
|
|
19
19
|
CustomAssociations
|
20
20
|
)
|
21
21
|
|
22
|
-
sig { params(inflector: Inflector, custom_associations: CustomAssociations).void }
|
22
|
+
sig { params(inflector: T.class_of(ActiveSupport::Inflector), custom_associations: CustomAssociations).void }
|
23
23
|
def initialize(inflector:, custom_associations: Set.new)
|
24
24
|
@inflector = inflector
|
25
25
|
@associations = T.let(RAILS_ASSOCIATIONS + custom_associations, CustomAssociations)
|
data/lib/packwerk/cli.rb
CHANGED
@@ -53,8 +53,6 @@ module Packwerk
|
|
53
53
|
output_result(parse_run(args).check)
|
54
54
|
when "detect-stale-violations"
|
55
55
|
output_result(parse_run(args).detect_stale_violations)
|
56
|
-
when "update"
|
57
|
-
update(args)
|
58
56
|
when "update-deprecations"
|
59
57
|
output_result(parse_run(args).update_deprecations)
|
60
58
|
when "validate"
|
@@ -88,14 +86,13 @@ module Packwerk
|
|
88
86
|
|
89
87
|
def generate_configs
|
90
88
|
configuration_file = Packwerk::Generators::ConfigurationFile.generate(
|
91
|
-
load_paths: Packwerk::ApplicationLoadPaths.extract_relevant_paths(@configuration.root_path, @environment),
|
92
89
|
root: @configuration.root_path,
|
93
90
|
out: @out
|
94
91
|
)
|
95
|
-
|
92
|
+
|
96
93
|
root_package = Packwerk::Generators::RootPackage.generate(root: @configuration.root_path, out: @out)
|
97
94
|
|
98
|
-
success = configuration_file &&
|
95
|
+
success = configuration_file && root_package
|
99
96
|
|
100
97
|
result = if success
|
101
98
|
<<~EOS
|
@@ -115,11 +112,6 @@ module Packwerk
|
|
115
112
|
success
|
116
113
|
end
|
117
114
|
|
118
|
-
def update(paths)
|
119
|
-
warn("`packwerk update` is deprecated in favor of `packwerk update-deprecations`.")
|
120
|
-
output_result(parse_run(paths).update_deprecations)
|
121
|
-
end
|
122
|
-
|
123
115
|
def output_result(result)
|
124
116
|
@out.puts
|
125
117
|
@out.puts(result.message)
|
@@ -139,11 +131,6 @@ module Packwerk
|
|
139
131
|
|
140
132
|
def validate(_paths)
|
141
133
|
@progress_formatter.started_validation do
|
142
|
-
checker = Packwerk::ApplicationValidator.new(
|
143
|
-
config_file_path: @configuration.config_path,
|
144
|
-
configuration: @configuration,
|
145
|
-
environment: @environment,
|
146
|
-
)
|
147
134
|
result = checker.check_all
|
148
135
|
|
149
136
|
list_validation_errors(result)
|
@@ -152,6 +139,14 @@ module Packwerk
|
|
152
139
|
end
|
153
140
|
end
|
154
141
|
|
142
|
+
def checker
|
143
|
+
Packwerk::ApplicationValidator.new(
|
144
|
+
config_file_path: @configuration.config_path,
|
145
|
+
configuration: @configuration,
|
146
|
+
environment: @environment,
|
147
|
+
)
|
148
|
+
end
|
149
|
+
|
155
150
|
def list_validation_errors(result)
|
156
151
|
@out.puts
|
157
152
|
if result.ok?
|
@@ -34,24 +34,54 @@ module Packwerk
|
|
34
34
|
DEFAULT_EXCLUDE_GLOBS = ["{bin,node_modules,script,tmp,vendor}/**/*"]
|
35
35
|
|
36
36
|
attr_reader(
|
37
|
-
:include, :exclude, :root_path, :package_paths, :custom_associations, :
|
38
|
-
:config_path,
|
37
|
+
:include, :exclude, :root_path, :package_paths, :custom_associations, :config_path
|
39
38
|
)
|
40
39
|
|
41
40
|
def initialize(configs = {}, config_path: nil)
|
41
|
+
if configs["load_paths"]
|
42
|
+
warning = <<~WARNING
|
43
|
+
DEPRECATION WARNING: The 'load_paths' key in `packwerk.yml` is deprecated.
|
44
|
+
This value is no longer cached, and you can remove the key from `packwerk.yml`.
|
45
|
+
WARNING
|
46
|
+
|
47
|
+
warn(warning)
|
48
|
+
end
|
49
|
+
|
50
|
+
inflection_file = File.expand_path(configs["inflections_file"] || "config/inflections.yml", @root_path)
|
51
|
+
if configs["inflections_file"]
|
52
|
+
warning = <<~WARNING
|
53
|
+
DEPRECATION WARNING: The 'inflections_file' key in `packwerk.yml` is deprecated.
|
54
|
+
This value is no longer cached, and you can remove the key from `packwerk.yml`.
|
55
|
+
You can also delete #{configs["inflections_file"]}.
|
56
|
+
WARNING
|
57
|
+
|
58
|
+
warn(warning)
|
59
|
+
end
|
60
|
+
|
61
|
+
if Pathname.new(inflection_file).exist?
|
62
|
+
warning = <<~WARNING
|
63
|
+
DEPRECATION WARNING: Inflections YMLs in packwerk are now deprecated.
|
64
|
+
This value is no longer cached, and you can now delete #{inflection_file}
|
65
|
+
WARNING
|
66
|
+
|
67
|
+
warn(warning)
|
68
|
+
end
|
69
|
+
|
42
70
|
@include = configs["include"] || DEFAULT_INCLUDE_GLOBS
|
43
71
|
@exclude = configs["exclude"] || DEFAULT_EXCLUDE_GLOBS
|
44
72
|
root = config_path ? File.dirname(config_path) : "."
|
45
73
|
@root_path = File.expand_path(root)
|
46
74
|
@package_paths = configs["package_paths"] || "**/"
|
47
75
|
@custom_associations = configs["custom_associations"] || []
|
48
|
-
@load_paths = (configs["load_paths"] || []).uniq
|
49
|
-
@inflections_file = File.expand_path(configs["inflections_file"] || "config/inflections.yml", @root_path)
|
50
76
|
@parallel = configs.key?("parallel") ? configs["parallel"] : true
|
51
77
|
|
52
78
|
@config_path = config_path
|
53
79
|
end
|
54
80
|
|
81
|
+
def load_paths
|
82
|
+
@load_paths ||= ApplicationLoadPaths.extract_relevant_paths(@root_path, "test")
|
83
|
+
end
|
84
|
+
|
55
85
|
def parallel?
|
56
86
|
@parallel
|
57
87
|
end
|
@@ -45,7 +45,7 @@ module Packwerk
|
|
45
45
|
begin
|
46
46
|
constant = @resolver.resolve(const_name, current_namespace_path: current_namespace_path)
|
47
47
|
rescue ConstantResolver::Error => e
|
48
|
-
raise(ConstantResolver::Error, e.message
|
48
|
+
raise(ConstantResolver::Error, e.message)
|
49
49
|
end
|
50
50
|
|
51
51
|
return unless constant
|
@@ -44,7 +44,7 @@ module Packwerk
|
|
44
44
|
|
45
45
|
sig { params(offenses: T::Array[T.nilable(Offense)]).returns(String) }
|
46
46
|
def offenses_summary(offenses)
|
47
|
-
offenses_string =
|
47
|
+
offenses_string = "offense".pluralize(offenses.length)
|
48
48
|
"#{offenses.length} #{offenses_string} detected"
|
49
49
|
end
|
50
50
|
end
|
@@ -16,7 +16,7 @@ module Packwerk
|
|
16
16
|
|
17
17
|
def started(target_files)
|
18
18
|
files_size = target_files.size
|
19
|
-
files_string =
|
19
|
+
files_string = "file".pluralize(files_size)
|
20
20
|
@out.puts("📦 Packwerk is inspecting #{files_size} #{files_string}")
|
21
21
|
end
|
22
22
|
|
@@ -11,18 +11,15 @@ module Packwerk
|
|
11
11
|
CONFIGURATION_TEMPLATE_FILE_PATH = "templates/packwerk.yml.erb"
|
12
12
|
|
13
13
|
class << self
|
14
|
-
def generate(
|
15
|
-
new(
|
14
|
+
def generate(root:, out:)
|
15
|
+
new(root: root, out: out).generate
|
16
16
|
end
|
17
17
|
end
|
18
18
|
|
19
|
-
sig { params(
|
20
|
-
def initialize(
|
21
|
-
@load_paths = load_paths
|
19
|
+
sig { params(root: String, out: T.any(StringIO, IO)).void }
|
20
|
+
def initialize(root:, out: $stdout)
|
22
21
|
@root = root
|
23
22
|
@out = out
|
24
|
-
|
25
|
-
set_template_variables
|
26
23
|
end
|
27
24
|
|
28
25
|
sig { returns(T::Boolean) }
|
@@ -43,18 +40,6 @@ module Packwerk
|
|
43
40
|
|
44
41
|
private
|
45
42
|
|
46
|
-
def set_template_variables
|
47
|
-
@load_paths_formatted = if @load_paths.empty?
|
48
|
-
"# load_paths:\n# - 'app/models'\n"
|
49
|
-
else
|
50
|
-
@load_paths.map { |path| "- #{path}\n" }.join
|
51
|
-
end
|
52
|
-
|
53
|
-
@load_paths_comment = unless @load_paths.empty?
|
54
|
-
"# These load paths were auto generated by Packwerk.\nload_paths:\n"
|
55
|
-
end
|
56
|
-
end
|
57
|
-
|
58
43
|
def render
|
59
44
|
ERB.new(template, trim_mode: "-").result(binding)
|
60
45
|
end
|
@@ -12,12 +12,6 @@
|
|
12
12
|
# Patterns to find package configuration files
|
13
13
|
# package_paths: "**/"
|
14
14
|
|
15
|
-
# List of application load paths
|
16
|
-
<%= @load_paths_comment -%>
|
17
|
-
<%= @load_paths_formatted %>
|
18
15
|
# List of custom associations, if any
|
19
16
|
# custom_associations:
|
20
17
|
# - "cache_belongs_to"
|
21
|
-
|
22
|
-
# Location of inflections file
|
23
|
-
# inflections_file: "config/inflections.yml"
|
data/lib/packwerk/run_context.rb
CHANGED
@@ -24,7 +24,7 @@ module Packwerk
|
|
24
24
|
|
25
25
|
class << self
|
26
26
|
def from_configuration(configuration)
|
27
|
-
inflector = ::
|
27
|
+
inflector = ActiveSupport::Inflector
|
28
28
|
new(
|
29
29
|
root_path: configuration.root_path,
|
30
30
|
load_paths: configuration.load_paths,
|
data/lib/packwerk/version.rb
CHANGED
data/lib/packwerk.rb
CHANGED
@@ -5,6 +5,9 @@ require "sorbet-runtime"
|
|
5
5
|
require "active_support"
|
6
6
|
require "fileutils"
|
7
7
|
|
8
|
+
# Provides String#pluralize
|
9
|
+
require "active_support/core_ext/string"
|
10
|
+
|
8
11
|
module Packwerk
|
9
12
|
extend ActiveSupport::Autoload
|
10
13
|
|
@@ -21,7 +24,6 @@ module Packwerk
|
|
21
24
|
autoload :FileProcessor
|
22
25
|
autoload :FilesForProcessing
|
23
26
|
autoload :Graph
|
24
|
-
autoload :Inflector
|
25
27
|
autoload :Node
|
26
28
|
autoload :NodeProcessor
|
27
29
|
autoload :NodeProcessorFactory
|
@@ -42,13 +44,6 @@ module Packwerk
|
|
42
44
|
autoload :Version
|
43
45
|
autoload :ViolationType
|
44
46
|
|
45
|
-
module Inflections
|
46
|
-
extend ActiveSupport::Autoload
|
47
|
-
|
48
|
-
autoload :Custom
|
49
|
-
autoload :Default
|
50
|
-
end
|
51
|
-
|
52
47
|
module OutputStyles
|
53
48
|
extend ActiveSupport::Autoload
|
54
49
|
|
@@ -71,7 +66,6 @@ module Packwerk
|
|
71
66
|
extend ActiveSupport::Autoload
|
72
67
|
|
73
68
|
autoload :ConfigurationFile
|
74
|
-
autoload :InflectionsFile
|
75
69
|
autoload :RootPackage
|
76
70
|
end
|
77
71
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: packwerk
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 2.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Shopify Inc.
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-
|
11
|
+
date: 2021-12-08 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -195,6 +195,7 @@ files:
|
|
195
195
|
- ".gitignore"
|
196
196
|
- ".rubocop.yml"
|
197
197
|
- ".ruby-version"
|
198
|
+
- CHANGELOG.md
|
198
199
|
- CODEOWNERS
|
199
200
|
- CODE_OF_CONDUCT.md
|
200
201
|
- CONTRIBUTING.md
|
@@ -204,6 +205,7 @@ files:
|
|
204
205
|
- README.md
|
205
206
|
- Rakefile
|
206
207
|
- TROUBLESHOOT.md
|
208
|
+
- UPGRADING.md
|
207
209
|
- USAGE.md
|
208
210
|
- bin/console
|
209
211
|
- bin/m
|
@@ -231,15 +233,10 @@ files:
|
|
231
233
|
- lib/packwerk/formatters/offenses_formatter.rb
|
232
234
|
- lib/packwerk/formatters/progress_formatter.rb
|
233
235
|
- lib/packwerk/generators/configuration_file.rb
|
234
|
-
- lib/packwerk/generators/inflections_file.rb
|
235
236
|
- lib/packwerk/generators/root_package.rb
|
236
|
-
- lib/packwerk/generators/templates/inflections.yml
|
237
237
|
- lib/packwerk/generators/templates/package.yml
|
238
238
|
- lib/packwerk/generators/templates/packwerk.yml.erb
|
239
239
|
- lib/packwerk/graph.rb
|
240
|
-
- lib/packwerk/inflections/custom.rb
|
241
|
-
- lib/packwerk/inflections/default.rb
|
242
|
-
- lib/packwerk/inflector.rb
|
243
240
|
- lib/packwerk/node.rb
|
244
241
|
- lib/packwerk/node_processor.rb
|
245
242
|
- lib/packwerk/node_processor_factory.rb
|
@@ -1,43 +0,0 @@
|
|
1
|
-
# typed: true
|
2
|
-
# frozen_string_literal: true
|
3
|
-
|
4
|
-
module Packwerk
|
5
|
-
module Generators
|
6
|
-
class InflectionsFile
|
7
|
-
extend T::Sig
|
8
|
-
|
9
|
-
class << self
|
10
|
-
def generate(root:, out:)
|
11
|
-
new(root, out: out).generate
|
12
|
-
end
|
13
|
-
end
|
14
|
-
|
15
|
-
def initialize(root, out: $stdout)
|
16
|
-
@root = root
|
17
|
-
@out = out
|
18
|
-
end
|
19
|
-
|
20
|
-
sig { returns(T::Boolean) }
|
21
|
-
def generate
|
22
|
-
ruby_inflection_file_exist = Dir.glob("#{@root}/**/inflections.rb").any?
|
23
|
-
yaml_inflection_file_exist = Dir.glob("#{@root}/**/inflections.yml").any?
|
24
|
-
|
25
|
-
if !ruby_inflection_file_exist || yaml_inflection_file_exist
|
26
|
-
return true
|
27
|
-
end
|
28
|
-
|
29
|
-
@out.puts("📦 Generating `inflections.yml` file...")
|
30
|
-
|
31
|
-
destination_file_path = File.join(@root, "config")
|
32
|
-
FileUtils.mkdir_p(destination_file_path)
|
33
|
-
|
34
|
-
source_file_path = File.join(__dir__, "/templates/inflections.yml")
|
35
|
-
FileUtils.cp(source_file_path, destination_file_path)
|
36
|
-
|
37
|
-
@out.puts("✅ `inflections.yml` generated in #{destination_file_path}")
|
38
|
-
|
39
|
-
true
|
40
|
-
end
|
41
|
-
end
|
42
|
-
end
|
43
|
-
end
|
@@ -1,33 +0,0 @@
|
|
1
|
-
# typed: true
|
2
|
-
# frozen_string_literal: true
|
3
|
-
|
4
|
-
require "yaml"
|
5
|
-
|
6
|
-
module Packwerk
|
7
|
-
module Inflections
|
8
|
-
class Custom
|
9
|
-
SUPPORTED_INFLECTION_METHODS = %w(acronym human irregular plural singular uncountable)
|
10
|
-
|
11
|
-
attr_accessor :inflections
|
12
|
-
|
13
|
-
def initialize(custom_inflection_file = nil)
|
14
|
-
if custom_inflection_file && File.exist?(custom_inflection_file)
|
15
|
-
@inflections = YAML.load_file(custom_inflection_file) || {}
|
16
|
-
|
17
|
-
invalid_inflections = @inflections.keys - SUPPORTED_INFLECTION_METHODS
|
18
|
-
raise ArgumentError, "Unsupported inflection types: #{invalid_inflections}" if invalid_inflections.any?
|
19
|
-
else
|
20
|
-
@inflections = []
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
|
-
def apply_to(inflections_object)
|
25
|
-
@inflections.each do |inflection_type, inflections|
|
26
|
-
inflections.each do |inflection|
|
27
|
-
inflections_object.public_send(inflection_type, *Array(inflection))
|
28
|
-
end
|
29
|
-
end
|
30
|
-
end
|
31
|
-
end
|
32
|
-
end
|
33
|
-
end
|
@@ -1,73 +0,0 @@
|
|
1
|
-
# typed: true
|
2
|
-
# frozen_string_literal: true
|
3
|
-
|
4
|
-
module Packwerk
|
5
|
-
module Inflections
|
6
|
-
module Default
|
7
|
-
class << self
|
8
|
-
def apply_to(inflections_object)
|
9
|
-
# copied from active_support/inflections
|
10
|
-
# https://github.com/rails/rails/blob/d2ae2c3103e93783971d5356d0b3fd1b4070d6cf/activesupport/lib/active_support/inflections.rb#L12
|
11
|
-
inflections_object.plural(/$/, "s")
|
12
|
-
inflections_object.plural(/s$/i, "s")
|
13
|
-
inflections_object.plural(/^(ax|test)is$/i, '\1es')
|
14
|
-
inflections_object.plural(/(octop|vir)us$/i, '\1i')
|
15
|
-
inflections_object.plural(/(octop|vir)i$/i, '\1i')
|
16
|
-
inflections_object.plural(/(alias|status)$/i, '\1es')
|
17
|
-
inflections_object.plural(/(bu)s$/i, '\1ses')
|
18
|
-
inflections_object.plural(/(buffal|tomat)o$/i, '\1oes')
|
19
|
-
inflections_object.plural(/([ti])um$/i, '\1a')
|
20
|
-
inflections_object.plural(/([ti])a$/i, '\1a')
|
21
|
-
inflections_object.plural(/sis$/i, "ses")
|
22
|
-
inflections_object.plural(/(?:([^f])fe|([lr])f)$/i, '\1\2ves')
|
23
|
-
inflections_object.plural(/(hive)$/i, '\1s')
|
24
|
-
inflections_object.plural(/([^aeiouy]|qu)y$/i, '\1ies')
|
25
|
-
inflections_object.plural(/(x|ch|ss|sh)$/i, '\1es')
|
26
|
-
inflections_object.plural(/(matr|vert|ind)(?:ix|ex)$/i, '\1ices')
|
27
|
-
inflections_object.plural(/^(m|l)ouse$/i, '\1ice')
|
28
|
-
inflections_object.plural(/^(m|l)ice$/i, '\1ice')
|
29
|
-
inflections_object.plural(/^(ox)$/i, '\1en')
|
30
|
-
inflections_object.plural(/^(oxen)$/i, '\1')
|
31
|
-
inflections_object.plural(/(quiz)$/i, '\1zes')
|
32
|
-
|
33
|
-
inflections_object.singular(/s$/i, "")
|
34
|
-
inflections_object.singular(/(ss)$/i, '\1')
|
35
|
-
inflections_object.singular(/(n)ews$/i, '\1ews')
|
36
|
-
inflections_object.singular(/([ti])a$/i, '\1um')
|
37
|
-
inflections_object.singular(/((a)naly|(b)a|(d)iagno|(p)arenthe|(p)rogno|(s)ynop|(t)he)(sis|ses)$/i, '\1sis')
|
38
|
-
inflections_object.singular(/(^analy)(sis|ses)$/i, '\1sis')
|
39
|
-
inflections_object.singular(/([^f])ves$/i, '\1fe')
|
40
|
-
inflections_object.singular(/(hive)s$/i, '\1')
|
41
|
-
inflections_object.singular(/(tive)s$/i, '\1')
|
42
|
-
inflections_object.singular(/([lr])ves$/i, '\1f')
|
43
|
-
inflections_object.singular(/([^aeiouy]|qu)ies$/i, '\1y')
|
44
|
-
inflections_object.singular(/(s)eries$/i, '\1eries')
|
45
|
-
inflections_object.singular(/(m)ovies$/i, '\1ovie')
|
46
|
-
inflections_object.singular(/(x|ch|ss|sh)es$/i, '\1')
|
47
|
-
inflections_object.singular(/^(m|l)ice$/i, '\1ouse')
|
48
|
-
inflections_object.singular(/(bus)(es)?$/i, '\1')
|
49
|
-
inflections_object.singular(/(o)es$/i, '\1')
|
50
|
-
inflections_object.singular(/(shoe)s$/i, '\1')
|
51
|
-
inflections_object.singular(/(cris|test)(is|es)$/i, '\1is')
|
52
|
-
inflections_object.singular(/^(a)x[ie]s$/i, '\1xis')
|
53
|
-
inflections_object.singular(/(octop|vir)(us|i)$/i, '\1us')
|
54
|
-
inflections_object.singular(/(alias|status)(es)?$/i, '\1')
|
55
|
-
inflections_object.singular(/^(ox)en/i, '\1')
|
56
|
-
inflections_object.singular(/(vert|ind)ices$/i, '\1ex')
|
57
|
-
inflections_object.singular(/(matr)ices$/i, '\1ix')
|
58
|
-
inflections_object.singular(/(quiz)zes$/i, '\1')
|
59
|
-
inflections_object.singular(/(database)s$/i, '\1')
|
60
|
-
|
61
|
-
inflections_object.irregular("person", "people")
|
62
|
-
inflections_object.irregular("man", "men")
|
63
|
-
inflections_object.irregular("child", "children")
|
64
|
-
inflections_object.irregular("sex", "sexes")
|
65
|
-
inflections_object.irregular("move", "moves")
|
66
|
-
inflections_object.irregular("zombie", "zombies")
|
67
|
-
|
68
|
-
inflections_object.uncountable(%w(equipment information rice money species series fish sheep jeans police))
|
69
|
-
end
|
70
|
-
end
|
71
|
-
end
|
72
|
-
end
|
73
|
-
end
|
data/lib/packwerk/inflector.rb
DELETED
@@ -1,49 +0,0 @@
|
|
1
|
-
# typed: true
|
2
|
-
# frozen_string_literal: true
|
3
|
-
|
4
|
-
require "active_support/inflector"
|
5
|
-
|
6
|
-
module Packwerk
|
7
|
-
# A custom inflector used, among other things, to map between constant names and file names.
|
8
|
-
class Inflector
|
9
|
-
class << self
|
10
|
-
extend T::Sig
|
11
|
-
|
12
|
-
def default
|
13
|
-
@default ||= new(custom_inflector: Inflections::Custom.new)
|
14
|
-
end
|
15
|
-
|
16
|
-
sig { params(inflections_file: String).returns(::Packwerk::Inflector) }
|
17
|
-
def from_file(inflections_file)
|
18
|
-
new(custom_inflector: Inflections::Custom.new(inflections_file))
|
19
|
-
end
|
20
|
-
end
|
21
|
-
|
22
|
-
extend T::Sig
|
23
|
-
include ::ActiveSupport::Inflector # For #camelize, #classify, #pluralize, #singularize
|
24
|
-
|
25
|
-
sig do
|
26
|
-
params(
|
27
|
-
custom_inflector: Inflections::Custom
|
28
|
-
).void
|
29
|
-
end
|
30
|
-
def initialize(custom_inflector:)
|
31
|
-
@inflections = ::ActiveSupport::Inflector::Inflections.new
|
32
|
-
|
33
|
-
Inflections::Default.apply_to(@inflections)
|
34
|
-
custom_inflector.apply_to(@inflections)
|
35
|
-
end
|
36
|
-
|
37
|
-
def pluralize(word, count = nil)
|
38
|
-
if count == 1
|
39
|
-
singularize(word)
|
40
|
-
else
|
41
|
-
super(word)
|
42
|
-
end
|
43
|
-
end
|
44
|
-
|
45
|
-
def inflections(_ = nil)
|
46
|
-
@inflections
|
47
|
-
end
|
48
|
-
end
|
49
|
-
end
|