@@ -26,7 +26,8 @@ class AbstractDsl < CommandWithoutTracker
2626 #| ?app_root: String,
2727 #| ?halt_upon_load_error: bool,
2828 #| ?compiler_options: Hash[String, untyped],
29- #| ?lsp_addon: bool
29+ #| ?lsp_addon: bool,
30+ #| ?max_diff_lines: Integer
3031 #| ) -> void
3132 def initialize (
3233 requested_constants :,
@@ -46,7 +47,8 @@ def initialize(
4647 app_root : "." ,
4748 halt_upon_load_error : true ,
4849 compiler_options : { } ,
49- lsp_addon : false
50+ lsp_addon : false ,
51+ max_diff_lines : DEFAULT_MAX_DIFF_LINES
5052 )
5153 @requested_constants = requested_constants
5254 @requested_paths = requested_paths
@@ -66,6 +68,7 @@ def initialize(
6668 @skip_constant = skip_constant
6769 @compiler_options = compiler_options
6870 @lsp_addon = lsp_addon
71+ @max_diff_lines = max_diff_lines
6972
7073 super ( )
7174 end
@@ -242,7 +245,7 @@ def compile_dsl_rbi(constant_name, rbi, outpath: @outpath, quiet: false)
242245 def perform_dsl_verification ( dir )
243246 diff = verify_dsl_rbi ( tmp_dir : dir )
244247
245- report_diff_and_exit_if_out_of_date ( diff , :dsl )
248+ report_diff_and_exit_if_out_of_date ( diff , tmp_dir : dir , command : :dsl )
246249 ensure
247250 FileUtils . remove_entry ( dir )
248251 end
@@ -305,26 +308,67 @@ def build_error_for_files(cause, files)
305308 " File(s) #{ cause } :\n - #{ filenames } "
306309 end
307310
308- #: (Hash[String, Symbol] diff, Symbol command) -> void
309- def report_diff_and_exit_if_out_of_date ( diff , command )
311+ #: (Hash[String, Symbol] diff, tmp_dir: Pathname, command: Symbol ) -> void
312+ def report_diff_and_exit_if_out_of_date ( diff , tmp_dir : , command : )
310313 if diff . empty?
311314 say ( "Nothing to do, all RBIs are up-to-date." )
312- else
313- reasons = diff . group_by ( &:last ) . sort . map do |cause , diff_for_cause |
314- build_error_for_files ( cause , diff_for_cause . map ( &:first ) )
315- end . join ( "\n " )
315+ return
316+ end
317+
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+
322+ diff_output = build_diff_output ( diff , tmp_dir )
323+ diff_lines = diff_output . count ( "\n " )
324+
325+ diff_section =
326+ if diff_lines . between? ( 1 , @max_diff_lines )
327+ "#{ set_color ( "Diff:" , :red ) } \n #{ diff_output . chomp } "
328+ elsif diff_lines > @max_diff_lines
329+ truncated_output = diff_output . lines . first ( @max_diff_lines ) . join
330+ "#{ set_color ( "Diff truncated to #{ @max_diff_lines } lines:" , :red ) } \n #{ truncated_output . rstrip } "
331+ else
332+ ""
333+ end
334+
335+ raise Tapioca ::Error , <<~ERROR . rstrip
336+ #{ set_color ( "RBI files are out-of-date. In your development environment, please run:" , :green ) }
337+ #{ set_color ( "`#{ default_command ( command ) } `" , :green , :bold ) }
338+ #{ set_color ( "Once it is complete, be sure to commit and push any changes" , :green ) }
339+ If you don't observe any changes after running the command locally, ensure your database is in a good
340+ state e.g. run `bin/rails db:reset`
316341
317- raise Tapioca ::Error , <<~ERROR
318- #{ set_color ( "RBI files are out-of-date. In your development environment, please run:" , :green ) }
319- #{ set_color ( "`#{ default_command ( command ) } `" , :green , :bold ) }
320- #{ set_color ( "Once it is complete, be sure to commit and push any changes" , :green ) }
321- If you don't observe any changes after running the command locally, ensure your database is in a good
322- state e.g. run `bin/rails db:reset`
342+ #{ set_color ( "Reason:" , :red ) }
343+ #{ reasons }
323344
324- #{ set_color ( "Reason:" , :red ) }
325- #{ reasons }
326- ERROR
345+ #{ diff_section }
346+ ERROR
347+ end
348+
349+ #: (Hash[String, Symbol] diff, Pathname tmp_dir) -> String
350+ def build_diff_output ( diff , tmp_dir )
351+ out = String . new
352+ line_count = 0
353+
354+ diff . each do |file , status |
355+ filename = file . to_s
356+ old_path = ( @outpath / file ) . to_s
357+ new_path = ( tmp_dir / file ) . to_s
358+
359+ chunk = case status
360+ when :added then file_diff ( filename , File ::NULL , new_path )
361+ when :removed then file_diff ( filename , old_path , File ::NULL )
362+ when :changed then file_diff ( filename , old_path , new_path )
363+ else ""
364+ end
365+
366+ out << chunk
367+ line_count += chunk . count ( "\n " )
368+ break if line_count > @max_diff_lines
327369 end
370+
371+ out
328372 end
329373
330374 #: (Pathname path) -> Array[Pathname]
0 commit comments