| 
									
										
										
										
											2025-07-31 17:31:27 +01:00
										 |  |  | # typed: strict | 
					
						
							| 
									
										
										
										
											2025-06-09 19:06:16 +01:00
										 |  |  | # frozen_string_literal: true | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | module DiskUsageExtension | 
					
						
							|  |  |  |   extend T::Helpers | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   requires_ancestor { Pathname } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   sig { returns(Integer) } | 
					
						
							|  |  |  |   def disk_usage | 
					
						
							| 
									
										
										
										
											2025-07-31 17:31:27 +01:00
										 |  |  |     @disk_usage ||= T.let(nil, T.nilable(Integer)) | 
					
						
							|  |  |  |     return @disk_usage unless @disk_usage.nil? | 
					
						
							| 
									
										
										
										
											2025-06-09 19:06:16 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-07-31 17:31:27 +01:00
										 |  |  |     @file_count, @disk_usage = compute_disk_usage | 
					
						
							| 
									
										
										
										
											2025-06-09 19:06:16 +01:00
										 |  |  |     @disk_usage | 
					
						
							|  |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   sig { returns(Integer) } | 
					
						
							|  |  |  |   def file_count | 
					
						
							| 
									
										
										
										
											2025-07-31 17:31:27 +01:00
										 |  |  |     @file_count ||= T.let(nil, T.nilable(Integer)) | 
					
						
							|  |  |  |     return @file_count unless @file_count.nil? | 
					
						
							| 
									
										
										
										
											2025-06-09 19:06:16 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-07-31 17:31:27 +01:00
										 |  |  |     @file_count, @disk_usage = compute_disk_usage | 
					
						
							| 
									
										
										
										
											2025-06-09 19:06:16 +01:00
										 |  |  |     @file_count | 
					
						
							|  |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   sig { returns(String) } | 
					
						
							|  |  |  |   def abv | 
					
						
							|  |  |  |     out = +"" | 
					
						
							| 
									
										
										
										
											2025-07-31 17:31:27 +01:00
										 |  |  |     @file_count, @disk_usage = compute_disk_usage | 
					
						
							| 
									
										
										
										
											2025-06-09 19:06:16 +01:00
										 |  |  |     out << "#{number_readable(@file_count)} files, " if @file_count > 1
 | 
					
						
							|  |  |  |     out << disk_usage_readable(@disk_usage).to_s | 
					
						
							|  |  |  |     out.freeze | 
					
						
							|  |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   private | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-07-31 17:31:27 +01:00
										 |  |  |   sig { returns([Integer, Integer]) } | 
					
						
							| 
									
										
										
										
											2025-06-09 19:06:16 +01:00
										 |  |  |   def compute_disk_usage | 
					
						
							|  |  |  |     if symlink? && !exist? | 
					
						
							| 
									
										
										
										
											2025-07-31 17:31:27 +01:00
										 |  |  |       file_count = 1
 | 
					
						
							|  |  |  |       disk_usage = 0
 | 
					
						
							|  |  |  |       return [file_count, disk_usage] | 
					
						
							| 
									
										
										
										
											2025-06-09 19:06:16 +01:00
										 |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     path = if symlink? | 
					
						
							|  |  |  |       resolved_path | 
					
						
							|  |  |  |     else | 
					
						
							|  |  |  |       self | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if path.directory? | 
					
						
							|  |  |  |       scanned_files = Set.new | 
					
						
							| 
									
										
										
										
											2025-07-31 17:31:27 +01:00
										 |  |  |       file_count = 0
 | 
					
						
							|  |  |  |       disk_usage = 0
 | 
					
						
							| 
									
										
										
										
											2025-06-09 19:06:16 +01:00
										 |  |  |       path.find do |f| | 
					
						
							|  |  |  |         if f.directory? | 
					
						
							| 
									
										
										
										
											2025-07-31 17:31:27 +01:00
										 |  |  |           disk_usage += f.lstat.size | 
					
						
							| 
									
										
										
										
											2025-06-09 19:06:16 +01:00
										 |  |  |         else | 
					
						
							| 
									
										
										
										
											2025-07-31 17:31:27 +01:00
										 |  |  |           file_count += 1 if f.basename.to_s != ".DS_Store" | 
					
						
							| 
									
										
										
										
											2025-06-09 19:06:16 +01:00
										 |  |  |           # use Pathname#lstat instead of Pathname#stat to get info of symlink itself. | 
					
						
							|  |  |  |           stat = f.lstat | 
					
						
							|  |  |  |           file_id = [stat.dev, stat.ino] | 
					
						
							|  |  |  |           # count hardlinks only once. | 
					
						
							|  |  |  |           unless scanned_files.include?(file_id) | 
					
						
							| 
									
										
										
										
											2025-07-31 17:31:27 +01:00
										 |  |  |             disk_usage += stat.size | 
					
						
							| 
									
										
										
										
											2025-06-09 19:06:16 +01:00
										 |  |  |             scanned_files.add(file_id) | 
					
						
							|  |  |  |           end | 
					
						
							|  |  |  |         end | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  |     else | 
					
						
							| 
									
										
										
										
											2025-07-31 17:31:27 +01:00
										 |  |  |       file_count = 1
 | 
					
						
							|  |  |  |       disk_usage = path.lstat.size | 
					
						
							| 
									
										
										
										
											2025-06-09 19:06:16 +01:00
										 |  |  |     end | 
					
						
							| 
									
										
										
										
											2025-07-31 17:31:27 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     [file_count, disk_usage] | 
					
						
							| 
									
										
										
										
											2025-06-09 19:06:16 +01:00
										 |  |  |   end | 
					
						
							|  |  |  | end |