use_packwerk 0.55.0 → 0.57.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.
Files changed (29) hide show
  1. checksums.yaml +4 -4
  2. data/bin/packs +5 -0
  3. data/lib/use_packwerk/cli.rb +10 -10
  4. data/lib/use_packwerk/code_ownership_post_processor.rb +3 -3
  5. data/lib/use_packwerk/configuration.rb +18 -14
  6. data/lib/use_packwerk/default_user_event_logger.rb +7 -0
  7. data/lib/use_packwerk/logging.rb +1 -2
  8. data/lib/use_packwerk/per_file_processor_interface.rb +1 -2
  9. data/lib/use_packwerk/private/file_move_operation.rb +9 -11
  10. data/lib/use_packwerk/private/interactive_cli/pack_selector.rb +34 -0
  11. data/lib/use_packwerk/private/interactive_cli/team_selector.rb +35 -0
  12. data/lib/use_packwerk/private/interactive_cli/use_cases/add_dependency.rb +30 -0
  13. data/lib/use_packwerk/private/interactive_cli/use_cases/create.rb +27 -0
  14. data/lib/use_packwerk/private/interactive_cli/use_cases/get_info.rb +74 -0
  15. data/lib/use_packwerk/private/interactive_cli/use_cases/interface.rb +34 -0
  16. data/lib/use_packwerk/private/interactive_cli/use_cases/make_public.rb +34 -0
  17. data/lib/use_packwerk/private/interactive_cli/use_cases/move.rb +36 -0
  18. data/lib/use_packwerk/private/interactive_cli/use_cases/nest.rb +31 -0
  19. data/lib/use_packwerk/private/interactive_cli/use_cases/query.rb +51 -0
  20. data/lib/use_packwerk/private/interactive_cli/use_cases/rename.rb +34 -0
  21. data/lib/use_packwerk/private/interactive_cli/use_cases/update_deprecations.rb +25 -0
  22. data/lib/use_packwerk/private/interactive_cli/use_cases/validate.rb +25 -0
  23. data/lib/use_packwerk/private/interactive_cli.rb +48 -0
  24. data/lib/use_packwerk/private/pack_relationship_analyzer.rb +24 -108
  25. data/lib/use_packwerk/private.rb +126 -161
  26. data/lib/use_packwerk/rubocop_post_processor.rb +17 -17
  27. data/lib/use_packwerk/user_event_logger.rb +265 -0
  28. data/lib/use_packwerk.rb +38 -76
  29. metadata +74 -14
@@ -7,6 +7,7 @@ require 'sorbet-runtime'
7
7
 
8
8
  require 'use_packwerk/private/file_move_operation'
9
9
  require 'use_packwerk/private/pack_relationship_analyzer'
10
+ require 'use_packwerk/private/interactive_cli'
10
11
 
11
12
  module UsePackwerk
12
13
  module Private
@@ -18,65 +19,50 @@ module UsePackwerk
18
19
  # This results in the pack not being found, but when we write the package YML it writes to the same place,
19
20
  # causing a behaviorally confusing diff.
20
21
  # We ignore trailing slashes as an ergonomic feature to the user.
21
- pack_name.gsub(/\/$/, '')
22
+ pack_name.gsub(%r{/$}, '')
22
23
  end
23
24
 
24
25
  sig do
25
26
  params(
26
27
  file: String,
27
28
  find: Pathname,
28
- replace_with: Pathname,
29
+ replace_with: Pathname
29
30
  ).void
30
31
  end
31
32
  def self.replace_in_file(file:, find:, replace_with:)
32
33
  file = Pathname.new(file)
33
34
  return if !file.exist?
35
+
34
36
  count = 0
35
37
  file.write(file.read.gsub(find.to_s) do
36
38
  count += 1
37
39
  replace_with.to_s
38
40
  end)
39
- Logging.print "Replaced #{count} occurrence(s) of #{find} in #{file.to_s}" if count > 0
41
+ Logging.print "Replaced #{count} occurrence(s) of #{find} in #{file}" if count > 0
40
42
  end
41
43
 
42
44
  sig do
43
45
  params(
44
46
  pack_name: String,
45
47
  enforce_privacy: T::Boolean,
46
- enforce_dependencies: T.nilable(T::Boolean)
48
+ enforce_dependencies: T.nilable(T::Boolean),
49
+ team: T.nilable(CodeTeams::Team)
47
50
  ).void
48
51
  end
49
- def self.create_pack!(pack_name:, enforce_privacy:, enforce_dependencies:)
52
+ def self.create_pack!(pack_name:, enforce_privacy:, enforce_dependencies:, team:)
50
53
  Logging.section('👋 Hi!') do
51
- intro = <<~INTRO
52
- You are creating a pack, which is great. Check out #{UsePackwerk.config.documentation_link} for more info!
53
-
54
- Please bring any questions or issues you have in your development process to #ruby-modularity or #product-infrastructure.
55
- We'd be happy to try to help through pairing, accepting feedback, changing our process, changing our tools, and more.
56
- INTRO
54
+ intro = UsePackwerk.config.user_event_logger.before_create_pack(pack_name)
57
55
  Logging.print_bold_green(intro)
58
56
  end
59
57
 
60
58
  pack_name = Private.clean_pack_name(pack_name)
61
59
 
62
- package = create_pack_if_not_exists!(pack_name: pack_name, enforce_privacy: enforce_privacy, enforce_dependencies: enforce_dependencies)
60
+ package = create_pack_if_not_exists!(pack_name: pack_name, enforce_privacy: enforce_privacy, enforce_dependencies: enforce_dependencies, team: team)
63
61
  add_public_directory(package)
64
62
  add_readme_todo(package)
65
63
 
66
64
  Logging.section('Next steps') do
67
- next_steps = <<~NEXT_STEPS
68
- Your next steps might be:
69
-
70
- 1) Move files into your pack with `bin/use_packwerk move #{pack_name} path/to/file.rb`
71
-
72
- 2) Run `bin/packwerk update-deprecations` to update the violations. Make sure to run `spring stop` if you've added new load paths (new top-level directories) in your pack.
73
-
74
- 3) Update TODO lists for rubocop implemented protections. See #{UsePackwerk.config.documentation_link} for more info
75
-
76
- 4) Expose public API in #{pack_name}/app/public. Try `bin/use_packwerk make_public #{pack_name}/path/to/file.rb`
77
-
78
- 5) Update your readme at #{pack_name}/README.md
79
- NEXT_STEPS
65
+ next_steps = UsePackwerk.config.user_event_logger.after_create_pack(pack_name)
80
66
 
81
67
  Logging.print_bold_green(next_steps)
82
68
  end
@@ -91,9 +77,9 @@ module UsePackwerk
91
77
  end
92
78
  def self.move_to_pack!(pack_name:, paths_relative_to_root:, per_file_processors: [])
93
79
  pack_name = Private.clean_pack_name(pack_name)
94
- package = ParsePackwerk.all.find { |package| package.name == pack_name }
80
+ package = ParsePackwerk.all.find { |p| p.name == pack_name }
95
81
  if package.nil?
96
- raise StandardError.new("Can not find package with name #{pack_name}. Make sure the argument is of the form `packs/my_pack/`")
82
+ raise StandardError, "Can not find package with name #{pack_name}. Make sure the argument is of the form `packs/my_pack/`"
97
83
  end
98
84
 
99
85
  add_public_directory(package)
@@ -118,9 +104,9 @@ module UsePackwerk
118
104
  # Later, if we choose to go back to moving whole directories at a time, it should be a refactor and all tests should still pass
119
105
  #
120
106
  if origin_pathname.directory?
121
- origin_pathname.glob('**/*.*').reject do |path|
122
- path.to_s.include?(ParsePackwerk::PACKAGE_YML_NAME) ||
123
- path.to_s.include?(ParsePackwerk::DEPRECATED_REFERENCES_YML_NAME)
107
+ origin_pathname.glob('**/*.*').reject do |origin_path|
108
+ origin_path.to_s.include?(ParsePackwerk::PACKAGE_YML_NAME) ||
109
+ origin_path.to_s.include?(ParsePackwerk::DEPRECATED_REFERENCES_YML_NAME)
124
110
  end
125
111
  else
126
112
  origin_pathname
@@ -130,7 +116,7 @@ module UsePackwerk
130
116
  FileMoveOperation.new(
131
117
  origin_pathname: origin_pathname,
132
118
  destination_pathname: FileMoveOperation.destination_pathname_for_package_move(origin_pathname, package_location),
133
- destination_pack: package,
119
+ destination_pack: package
134
120
  )
135
121
  end
136
122
  file_move_operations.each do |file_move_operation|
@@ -140,89 +126,87 @@ module UsePackwerk
140
126
  end
141
127
  end
142
128
 
143
- per_file_processors.each do |per_file_processor|
144
- per_file_processor.print_final_message!
145
- end
129
+ per_file_processors.each(&:print_final_message!)
146
130
  end
147
131
 
148
- sig do
149
- params(
150
- pack_name: String,
151
- parent_name: String,
152
- per_file_processors: T::Array[PerFileProcessorInterface],
153
- ).void
154
- end
155
- def self.move_to_parent!(
156
- pack_name:,
157
- parent_name:,
158
- per_file_processors: []
159
- )
160
- pack_name = Private.clean_pack_name(pack_name)
161
- package = ParsePackwerk.all.find { |package| package.name == pack_name }
162
- if package.nil?
163
- raise StandardError.new("Can not find package with name #{pack_name}. Make sure the argument is of the form `packs/my_pack/`")
164
- end
165
-
166
- parent_name = Private.clean_pack_name(parent_name)
167
- parent_package = ParsePackwerk.all.find { |package| package.name == parent_name }
168
- if parent_package.nil?
169
- parent_package = create_pack_if_not_exists!(pack_name: parent_name, enforce_privacy: true, enforce_dependencies: true)
132
+ sig do
133
+ params(
134
+ pack_name: String,
135
+ parent_name: String,
136
+ per_file_processors: T::Array[PerFileProcessorInterface]
137
+ ).void
170
138
  end
171
-
172
- # First we create a new pack that has the exact same properties of the old one!
173
- package_last_name = package.directory.basename
174
- new_package_name = parent_package.directory.join(package_last_name).to_s
175
-
176
- new_package = ParsePackwerk::Package.new(
177
- name: new_package_name,
178
- enforce_privacy: package.enforce_dependencies,
179
- enforce_dependencies: package.enforce_dependencies,
180
- dependencies: package.dependencies,
181
- metadata: package.metadata,
182
- )
183
- ParsePackwerk.write_package_yml!(new_package)
184
- ParsePackwerk.bust_cache!
185
-
186
- # Move everything from the old pack to the new one
187
- self.move_to_pack!(
188
- pack_name: new_package_name,
189
- paths_relative_to_root: [package.directory.to_s],
190
- per_file_processors: per_file_processors,
139
+ def self.move_to_parent!(
140
+ pack_name:,
141
+ parent_name:,
142
+ per_file_processors: []
191
143
  )
144
+ pack_name = Private.clean_pack_name(pack_name)
145
+ package = ParsePackwerk.all.find { |p| p.name == pack_name }
146
+ if package.nil?
147
+ raise StandardError, "Can not find package with name #{pack_name}. Make sure the argument is of the form `packs/my_pack/`"
148
+ end
192
149
 
193
- # Then delete the old package.yml and deprecated_references.yml files
194
- package.yml.delete
195
- deprecated_references_file = ParsePackwerk::DeprecatedReferences.for(package).pathname
196
- deprecated_references_file.delete if deprecated_references_file.exist?
150
+ parent_name = Private.clean_pack_name(parent_name)
151
+ parent_package = ParsePackwerk.all.find { |p| p.name == parent_name }
152
+ if parent_package.nil?
153
+ parent_package = create_pack_if_not_exists!(pack_name: parent_name, enforce_privacy: true, enforce_dependencies: true)
154
+ end
197
155
 
198
- ParsePackwerk.bust_cache!
156
+ # First we create a new pack that has the exact same properties of the old one!
157
+ package_last_name = package.directory.basename
158
+ new_package_name = parent_package.directory.join(package_last_name).to_s
199
159
 
200
- ParsePackwerk.all.each do |other_package|
201
- new_dependencies = other_package.dependencies.map{|d| d == pack_name ? new_package_name : d}
202
- if other_package.name == parent_name && !new_dependencies.include?(new_package_name)
203
- new_dependencies += [new_package_name]
204
- end
160
+ new_package = ParsePackwerk::Package.new(
161
+ name: new_package_name,
162
+ enforce_privacy: package.enforce_dependencies,
163
+ enforce_dependencies: package.enforce_dependencies,
164
+ dependencies: package.dependencies,
165
+ metadata: package.metadata
166
+ )
167
+ ParsePackwerk.write_package_yml!(new_package)
168
+ ParsePackwerk.bust_cache!
205
169
 
206
- new_other_package = ParsePackwerk::Package.new(
207
- name: other_package.name,
208
- enforce_privacy: other_package.enforce_privacy,
209
- enforce_dependencies: other_package.enforce_dependencies,
210
- dependencies: new_dependencies.uniq.sort,
211
- metadata: other_package.metadata,
170
+ # Move everything from the old pack to the new one
171
+ move_to_pack!(
172
+ pack_name: new_package_name,
173
+ paths_relative_to_root: [package.directory.to_s],
174
+ per_file_processors: per_file_processors
212
175
  )
213
176
 
214
- ParsePackwerk.write_package_yml!(new_other_package)
215
- end
177
+ # Then delete the old package.yml and deprecated_references.yml files
178
+ package.yml.delete
179
+ deprecated_references_file = ParsePackwerk::DeprecatedReferences.for(package).pathname
180
+ deprecated_references_file.delete if deprecated_references_file.exist?
216
181
 
217
- sorbet_config = Pathname.new('sorbet/config')
218
- if sorbet_config.exist?
219
- UsePackwerk.replace_in_file(
220
- file: sorbet_config.to_s,
221
- find: package.directory.join('spec'),
222
- replace_with: new_package.directory.join('spec'),
223
- )
182
+ ParsePackwerk.bust_cache!
183
+
184
+ ParsePackwerk.all.each do |other_package|
185
+ new_dependencies = other_package.dependencies.map { |d| d == pack_name ? new_package_name : d }
186
+ if other_package.name == parent_name && !new_dependencies.include?(new_package_name)
187
+ new_dependencies += [new_package_name]
188
+ end
189
+
190
+ new_other_package = ParsePackwerk::Package.new(
191
+ name: other_package.name,
192
+ enforce_privacy: other_package.enforce_privacy,
193
+ enforce_dependencies: other_package.enforce_dependencies,
194
+ dependencies: new_dependencies.uniq.sort,
195
+ metadata: other_package.metadata
196
+ )
197
+
198
+ ParsePackwerk.write_package_yml!(new_other_package)
199
+ end
200
+
201
+ sorbet_config = Pathname.new('sorbet/config')
202
+ if sorbet_config.exist?
203
+ UsePackwerk.replace_in_file(
204
+ file: sorbet_config.to_s,
205
+ find: package.directory.join('spec'),
206
+ replace_with: new_package.directory.join('spec')
207
+ )
208
+ end
224
209
  end
225
- end
226
210
 
227
211
  sig do
228
212
  params(
@@ -242,7 +226,6 @@ module UsePackwerk
242
226
  end
243
227
  end
244
228
 
245
-
246
229
  file_move_operations = file_paths.map do |path|
247
230
  package = T.must(ParsePackwerk.package_from_path(path))
248
231
  origin_pathname = Pathname.new(path).cleanpath
@@ -250,7 +233,7 @@ module UsePackwerk
250
233
  FileMoveOperation.new(
251
234
  origin_pathname: origin_pathname,
252
235
  destination_pathname: FileMoveOperation.destination_pathname_for_new_public_api(origin_pathname),
253
- destination_pack: package,
236
+ destination_pack: package
254
237
  )
255
238
  end
256
239
 
@@ -272,15 +255,15 @@ module UsePackwerk
272
255
  all_packages = ParsePackwerk.all
273
256
 
274
257
  pack_name = Private.clean_pack_name(pack_name)
275
- package = all_packages.find { |package| package.name == pack_name }
258
+ package = all_packages.find { |p| p.name == pack_name }
276
259
  if package.nil?
277
- raise StandardError.new("Can not find package with name #{pack_name}. Make sure the argument is of the form `packs/my_pack/`")
260
+ raise StandardError, "Can not find package with name #{pack_name}. Make sure the argument is of the form `packs/my_pack/`"
278
261
  end
279
262
 
280
263
  dependency_name = Private.clean_pack_name(dependency_name)
281
- package_dependency = all_packages.find { |package| package.name == dependency_name }
264
+ package_dependency = all_packages.find { |p| p.name == dependency_name }
282
265
  if package_dependency.nil?
283
- raise StandardError.new("Can not find package with name #{dependency_name}. Make sure the argument is of the form `packs/my_pack/`")
266
+ raise StandardError, "Can not find package with name #{dependency_name}. Make sure the argument is of the form `packs/my_pack/`"
284
267
  end
285
268
 
286
269
  new_package = ParsePackwerk::Package.new(
@@ -288,7 +271,7 @@ module UsePackwerk
288
271
  dependencies: (package.dependencies + [dependency_name]).uniq.sort,
289
272
  enforce_privacy: package.enforce_privacy,
290
273
  enforce_dependencies: package.enforce_dependencies,
291
- metadata: package.metadata,
274
+ metadata: package.metadata
292
275
  )
293
276
  ParsePackwerk.write_package_yml!(new_package)
294
277
  end
@@ -322,63 +305,29 @@ module UsePackwerk
322
305
  # use git mv so that git knows that it was a move
323
306
  FileUtils.mv(origin, destination)
324
307
  elsif !origin.exist? && destination.exist?
325
- Logging.print ColorizedString.new("[SKIP] Not moving #{origin.to_s}, does not exist, (#{destination.to_s} already exists)").red
308
+ Logging.print ColorizedString.new("[SKIP] Not moving #{origin}, does not exist, (#{destination} already exists)").red
326
309
  else
327
- Logging.print ColorizedString.new("[SKIP] Not moving #{origin.to_s}, does not exist").red
310
+ Logging.print ColorizedString.new("[SKIP] Not moving #{origin}, does not exist").red
328
311
  end
329
312
  end
330
313
 
331
- sig { params(package: ParsePackwerk::Package).void }
314
+ sig { params(package: ParsePackwerk::Package).void }
332
315
  def self.add_public_directory(package)
333
316
  public_directory = package.directory.join('app/public')
334
317
 
335
318
  if public_directory.glob('**/**.rb').none?
336
319
  FileUtils.mkdir_p(public_directory)
337
- todo_md = <<~TODO
338
- This directory holds your public API!
339
-
340
- Any classes, constants, or modules that you want other packs to use and you intend to support should go in here.
341
- Anything that is considered private should go in other folders.
342
-
343
- If another pack uses classes, constants, or modules that are not in your public folder, it will be considered a "privacy violation" by packwerk.
344
- You can prevent other packs from using private API by using package_protections.
345
-
346
- Want to find how your private API is being used today?
347
- Try running: `bin/use_packwerk list_top_privacy_violations #{package.name}`
348
-
349
- Want to move something into this folder?
350
- Try running: `bin/use_packwerk make_public #{package.name}/path/to/file.rb`
351
-
352
- One more thing -- feel free to delete this file and replace it with a README.md describing your package in the main package directory.
353
-
354
- See #{UsePackwerk.config.documentation_link} for more info!
355
- TODO
320
+ todo_md = UsePackwerk.config.user_event_logger.on_create_public_directory_todo(package.name)
356
321
  public_directory.join('TODO.md').write(todo_md)
357
322
  end
358
323
  end
359
324
 
360
- sig { params(package: ParsePackwerk::Package).void }
325
+ sig { params(package: ParsePackwerk::Package).void }
361
326
  def self.add_readme_todo(package)
362
327
  pack_directory = package.directory
363
328
 
364
329
  if !pack_directory.join('README.md').exist?
365
- readme_todo_md = <<~TODO
366
- Welcome to `#{package.name}`!
367
-
368
- If you're the author, please consider replacing this file with a README.md, which may contain:
369
- - What your pack is and does
370
- - How you expect people to use your pack
371
- - Example usage of your pack's public API (which lives in `#{package.name}/app/public`)
372
- - Limitations, risks, and important considerations of usage
373
- - How to get in touch with eng and other stakeholders for questions or issues pertaining to this pack (note: it is recommended to add ownership in `#{package.name}/package.yml` under the `owner` metadata key)
374
- - What SLAs/SLOs (service level agreements/objectives), if any, your package provides
375
- - When in doubt, keep it simple
376
- - Anything else you may want to include!
377
-
378
- README.md files are under version control and should change as your public API changes.
379
-
380
- See #{UsePackwerk.config.documentation_link} for more info!
381
- TODO
330
+ readme_todo_md = UsePackwerk.config.user_event_logger.on_create_readme_todo(package.name)
382
331
  pack_directory.join('README_TODO.md').write(readme_todo_md)
383
332
  end
384
333
  end
@@ -387,18 +336,16 @@ module UsePackwerk
387
336
  params(
388
337
  pack_name: String,
389
338
  enforce_privacy: T::Boolean,
390
- enforce_dependencies: T.nilable(T::Boolean)
339
+ enforce_dependencies: T.nilable(T::Boolean),
340
+ team: T.nilable(CodeTeams::Team)
391
341
  ).returns(ParsePackwerk::Package)
392
342
  end
393
- def self.create_pack_if_not_exists!(pack_name:, enforce_privacy:, enforce_dependencies:)
343
+ def self.create_pack_if_not_exists!(pack_name:, enforce_privacy:, enforce_dependencies:, team: nil)
394
344
  if PERMITTED_PACK_LOCATIONS.none? { |permitted_location| pack_name.start_with?(permitted_location) }
395
- raise StandardError.new("UsePackwerk only supports packages in the the following directories: #{PERMITTED_PACK_LOCATIONS.inspect}. Please make sure to pass in the name of the pack including the full directory path, e.g. `packs/my_pack`.")
345
+ raise StandardError, "UsePackwerk only supports packages in the the following directories: #{PERMITTED_PACK_LOCATIONS.inspect}. Please make sure to pass in the name of the pack including the full directory path, e.g. `packs/my_pack`."
396
346
  end
397
347
 
398
- existing_package = ParsePackwerk.all.find { |package| package.name == pack_name }
399
-
400
- package_location = Pathname.new(pack_name)
401
-
348
+ existing_package = ParsePackwerk.all.find { |p| p.name == pack_name }
402
349
  if existing_package.nil?
403
350
  should_enforce_dependenceies = enforce_dependencies.nil? ? UsePackwerk.config.enforce_dependencies : enforce_dependencies
404
351
 
@@ -407,9 +354,9 @@ module UsePackwerk
407
354
  enforce_privacy: enforce_privacy,
408
355
  dependencies: [],
409
356
  metadata: {
410
- 'owner' => 'MyTeam'
357
+ 'owner' => team.nil? ? 'MyTeam' : team.name
411
358
  },
412
- name: pack_name,
359
+ name: pack_name
413
360
  )
414
361
 
415
362
  ParsePackwerk.write_package_yml!(package)
@@ -417,7 +364,7 @@ module UsePackwerk
417
364
  package = rewrite_package_with_original_packwerk_values(package)
418
365
 
419
366
  current_contents = package.yml.read
420
- new_contents = current_contents.gsub("MyTeam", "MyTeam # specify your team here, or delete this key if this package is not owned by one team")
367
+ new_contents = current_contents.gsub('MyTeam', 'MyTeam # specify your team here, or delete this key if this package is not owned by one team')
421
368
  package.yml.write(new_contents)
422
369
  existing_package = package
423
370
  end
@@ -428,19 +375,37 @@ module UsePackwerk
428
375
  sig { params(original_package: ParsePackwerk::Package).returns(ParsePackwerk::Package) }
429
376
  def self.rewrite_package_with_original_packwerk_values(original_package)
430
377
  ParsePackwerk.bust_cache!
431
- package_with_protection_defaults = T.must(ParsePackwerk.all.find { |package| package.name == original_package.name })
378
+ package_with_protection_defaults = T.must(ParsePackwerk.all.find { |p| p.name == original_package.name })
432
379
  # PackageProtections also sets `enforce_privacy` and `enforce_dependency` to be true, so we set these back down to their original values
433
380
  package = ParsePackwerk::Package.new(
434
381
  enforce_dependencies: original_package.enforce_dependencies,
435
382
  enforce_privacy: original_package.enforce_privacy,
436
383
  dependencies: original_package.dependencies,
437
384
  metadata: package_with_protection_defaults.metadata,
438
- name: original_package.name,
385
+ name: original_package.name
439
386
  )
440
387
 
441
388
  ParsePackwerk.write_package_yml!(package)
442
389
  package
443
390
  end
391
+
392
+ sig { void }
393
+ def self.load_client_configuration
394
+ @loaded_client_configuration ||= T.let(false, T.nilable(T::Boolean))
395
+ return if @loaded_client_configuration
396
+
397
+ @loaded_client_configuration = true
398
+ client_configuration = Pathname.pwd.join('config/use_packwerk.rb')
399
+ require client_configuration.to_s if client_configuration.exist?
400
+ end
401
+
402
+ sig { void }
403
+ def self.bust_cache!
404
+ UsePackwerk.config.bust_cache!
405
+ # This comes explicitly after `PackageProtections.config.bust_cache!` because
406
+ # otherwise `PackageProtections.config` will attempt to reload the client configuratoin.
407
+ @loaded_client_configuration = false
408
+ end
444
409
  end
445
410
 
446
411
  private_constant :Private
@@ -15,7 +15,7 @@ module UsePackwerk
15
15
  UsePackwerk.replace_in_file(
16
16
  file: rubocop_todo.to_s,
17
17
  find: relative_path_to_origin,
18
- replace_with: relative_path_to_destination,
18
+ replace_with: relative_path_to_destination
19
19
  )
20
20
  end
21
21
 
@@ -26,23 +26,23 @@ module UsePackwerk
26
26
  new_origin_rubocop_todo = loaded_origin_rubocop_todo.dup
27
27
 
28
28
  loaded_origin_rubocop_todo.each do |cop_name, cop_config|
29
- if cop_config['Exclude'].include?(relative_path_to_origin.to_s)
30
- new_origin_rubocop_todo[cop_name]['Exclude'] = cop_config['Exclude'] - [relative_path_to_origin.to_s]
31
- origin_rubocop_todo.write(YAML.dump(new_origin_rubocop_todo))
32
-
33
- destination_rubocop_todo = file_move_operation.destination_pack.directory.join('.rubocop_todo.yml')
34
- if destination_rubocop_todo.exist?
35
- new_destination_rubocop_todo = YAML.load_file(destination_rubocop_todo).dup
36
- else
37
- new_destination_rubocop_todo = {}
38
- end
39
-
40
- new_destination_rubocop_todo[cop_name] ||= { 'Exclude' => [] }
41
-
42
- new_destination_rubocop_todo[cop_name]['Exclude'] += [relative_path_to_destination.to_s]
43
- destination_rubocop_todo.write(YAML.dump(new_destination_rubocop_todo))
29
+ next unless cop_config['Exclude'].include?(relative_path_to_origin.to_s)
30
+
31
+ new_origin_rubocop_todo[cop_name]['Exclude'] = cop_config['Exclude'] - [relative_path_to_origin.to_s]
32
+ origin_rubocop_todo.write(YAML.dump(new_origin_rubocop_todo))
33
+
34
+ destination_rubocop_todo = file_move_operation.destination_pack.directory.join('.rubocop_todo.yml')
35
+ if destination_rubocop_todo.exist?
36
+ new_destination_rubocop_todo = YAML.load_file(destination_rubocop_todo).dup
37
+ else
38
+ new_destination_rubocop_todo = {}
44
39
  end
45
- end
40
+
41
+ new_destination_rubocop_todo[cop_name] ||= { 'Exclude' => [] }
42
+
43
+ new_destination_rubocop_todo[cop_name]['Exclude'] += [relative_path_to_destination.to_s]
44
+ destination_rubocop_todo.write(YAML.dump(new_destination_rubocop_todo))
45
+ end
46
46
  end
47
47
  end
48
48
  end