packwerk 1.4.0 → 2.0.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 +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
|