@@ -5,6 +5,7 @@ module Tapioca
55 module Commands
66 # @abstract
77 class AbstractDsl < CommandWithoutTracker
8+ include FileHelper
89 include SorbetHelper
910 include RBIFilesHelper
1011
@@ -26,7 +27,8 @@ class AbstractDsl < CommandWithoutTracker
2627 #| ?app_root: String,
2728 #| ?halt_upon_load_error: bool,
2829 #| ?compiler_options: Hash[String, untyped],
29- #| ?lsp_addon: bool
30+ #| ?lsp_addon: bool,
31+ #| ?max_diff_lines: Integer
3032 #| ) -> void
3133 def initialize (
3234 requested_constants :,
@@ -46,7 +48,8 @@ def initialize(
4648 app_root : "." ,
4749 halt_upon_load_error : true ,
4850 compiler_options : { } ,
49- lsp_addon : false
51+ lsp_addon : false ,
52+ max_diff_lines : DEFAULT_MAX_DIFF_LINES
5053 )
5154 @requested_constants = requested_constants
5255 @requested_paths = requested_paths
@@ -66,6 +69,7 @@ def initialize(
6669 @skip_constant = skip_constant
6770 @compiler_options = compiler_options
6871 @lsp_addon = lsp_addon
72+ @max_diff_lines = max_diff_lines
6973
7074 super ( )
7175 end
@@ -247,7 +251,7 @@ def compile_dsl_rbi(constant_name, rbi, outpath: @outpath, quiet: false)
247251 def perform_dsl_verification ( dir )
248252 diff = verify_dsl_rbi ( tmp_dir : dir )
249253
250- report_diff_and_exit_if_out_of_date ( diff , :dsl )
254+ report_diff_and_exit_if_out_of_date ( diff , tmp_dir : dir , command : :dsl )
251255 ensure
252256 FileUtils . remove_entry ( dir )
253257 end
@@ -269,7 +273,7 @@ def dsl_rbi_filename(constant_name)
269273 @outpath / "#{ underscore ( constant_name ) } .rbi"
270274 end
271275
272- #: (tmp_dir: Pathname) -> Hash[String , Symbol]
276+ #: (tmp_dir: Pathname) -> Hash[Pathname , Symbol]
273277 def verify_dsl_rbi ( tmp_dir :)
274278 diff = { }
275279
@@ -301,7 +305,7 @@ def verify_dsl_rbi(tmp_dir:)
301305 diff
302306 end
303307
304- #: (Symbol cause, Array[String ] files) -> String
308+ #: (Symbol cause, Array[Pathname ] files) -> String
305309 def build_error_for_files ( cause , files )
306310 filenames = files . map do |file |
307311 @outpath / file
@@ -310,26 +314,66 @@ def build_error_for_files(cause, files)
310314 " File(s) #{ cause } :\n - #{ filenames } "
311315 end
312316
313- #: (Hash[String , Symbol] diff, Symbol command) -> void
314- def report_diff_and_exit_if_out_of_date ( diff , command )
317+ #: (Hash[Pathname , Symbol] diff, tmp_dir: Pathname, command: Symbol ) -> void
318+ def report_diff_and_exit_if_out_of_date ( diff , tmp_dir : , command : )
315319 if diff . empty?
316320 say ( "Nothing to do, all RBIs are up-to-date." )
317- else
318- reasons = diff . group_by ( &:last ) . sort . map do |cause , diff_for_cause |
319- build_error_for_files ( cause , diff_for_cause . map ( &:first ) )
320- end . join ( "\n " )
321+ return
322+ end
321323
322- raise Tapioca ::Error , <<~ERROR
323- #{ set_color ( "RBI files are out-of-date. In your development environment, please run:" , :green ) }
324- #{ set_color ( "`#{ default_command ( command ) } `" , :green , :bold ) }
325- #{ set_color ( "Once it is complete, be sure to commit and push any changes" , :green ) }
326- If you don't observe any changes after running the command locally, ensure your database is in a good
327- state e.g. run `bin/rails db:reset`
324+ reasons = diff . group_by ( &:last ) . sort . map do |cause , diff_for_cause |
325+ build_error_for_files ( cause , diff_for_cause . map ( &:first ) )
326+ end . join ( "\n " )
327+
328+ diff_output = build_diff_output ( diff , tmp_dir )
329+ diff_lines = diff_output . count ( "\n " )
330+
331+ diff_section =
332+ if diff_lines . between? ( 1 , @max_diff_lines )
333+ "#{ set_color ( "Diff:" , :red ) } \n #{ diff_output . chomp } "
334+ elsif diff_lines > @max_diff_lines
335+ truncated_output = diff_output . lines . first ( @max_diff_lines ) . join
336+ "#{ set_color ( "Diff truncated to #{ @max_diff_lines } lines.\n Change the number of displayed lines using the `--max-diff-lines` flag." , :red ) } \n #{ truncated_output . rstrip } "
337+ else
338+ ""
339+ end
328340
329- #{ set_color ( "Reason:" , :red ) }
330- #{ reasons }
331- ERROR
341+ raise Tapioca ::Error , <<~ERROR . rstrip
342+ #{ set_color ( "RBI files are out-of-date. In your development environment, please run:" , :green ) }
343+ #{ set_color ( "`#{ default_command ( command ) } `" , :green , :bold ) }
344+ #{ set_color ( "Once it is complete, be sure to commit and push any changes" , :green ) }
345+ If you don't observe any changes after running the command locally, ensure your database is in a good
346+ state e.g. run `bin/rails db:reset`
347+
348+ #{ set_color ( "Reason:" , :red ) }
349+ #{ reasons }
350+
351+ #{ diff_section }
352+ ERROR
353+ end
354+
355+ #: (Hash[Pathname, Symbol] diff, Pathname tmp_dir) -> String
356+ def build_diff_output ( diff , tmp_dir )
357+ out = String . new
358+ line_count = 0
359+
360+ diff . each do |file , status |
361+ old_path = ( @outpath / file )
362+ new_path = ( tmp_dir / file )
363+
364+ chunk = case status
365+ when :added then file_diff ( file , File ::NULL , new_path )
366+ when :removed then file_diff ( file , old_path , File ::NULL )
367+ when :changed then file_diff ( file , old_path , new_path )
368+ else ""
369+ end
370+
371+ out << chunk
372+ line_count += chunk . count ( "\n " )
373+ break if line_count > @max_diff_lines
332374 end
375+
376+ out
333377 end
334378
335379 #: (Pathname path) -> Array[Pathname]
0 commit comments