| 
									
										
										
										
											2012-09-11 22:13:41 -07:00
										 |  |  | require 'stringio' | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-09 10:26:46 -08:00
										 |  |  | class Patches | 
					
						
							| 
									
										
										
										
											2012-08-07 01:37:46 -05:00
										 |  |  |   include Enumerable | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-09 10:26:46 -08:00
										 |  |  |   # The patches defined in a formula and the DATA from that file | 
					
						
							|  |  |  |   def initialize patches | 
					
						
							|  |  |  |     @patches = [] | 
					
						
							|  |  |  |     return if patches.nil? | 
					
						
							| 
									
										
										
										
											2012-03-20 23:24:55 +01:00
										 |  |  |     n = 0
 | 
					
						
							| 
									
										
										
										
											2012-03-09 10:26:46 -08:00
										 |  |  |     normalize_patches(patches).each do |patch_p, urls| | 
					
						
							|  |  |  |       # Wrap the urls list in an array if it isn't already; | 
					
						
							|  |  |  |       # DATA.each does each line, which doesn't work so great | 
					
						
							|  |  |  |       urls = [urls] unless urls.kind_of? Array | 
					
						
							| 
									
										
										
										
											2012-03-20 23:24:55 +01:00
										 |  |  |       urls.each do |url| | 
					
						
							| 
									
										
										
										
											2012-03-09 10:26:46 -08:00
										 |  |  |         @patches << Patch.new(patch_p, '%03d-homebrew.diff' % n, url) | 
					
						
							| 
									
										
										
										
											2012-03-20 23:24:55 +01:00
										 |  |  |         n += 1
 | 
					
						
							| 
									
										
										
										
											2012-03-09 10:26:46 -08:00
										 |  |  |       end | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-04-29 11:51:04 -07:00
										 |  |  |   def external_patches? | 
					
						
							|  |  |  |     not external_curl_args.empty? | 
					
						
							| 
									
										
										
										
											2012-03-09 10:26:46 -08:00
										 |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   def each(&blk) | 
					
						
							|  |  |  |     @patches.each(&blk) | 
					
						
							|  |  |  |   end | 
					
						
							|  |  |  |   def empty? | 
					
						
							|  |  |  |     @patches.empty? | 
					
						
							|  |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-04-29 11:51:04 -07:00
										 |  |  |   def download! | 
					
						
							|  |  |  |     return unless external_patches? | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # downloading all at once is much more efficient, especially for FTP | 
					
						
							|  |  |  |     curl(*external_curl_args) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     external_patches.each{|p| p.stage!} | 
					
						
							|  |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-04-07 00:49:56 -05:00
										 |  |  |   private | 
					
						
							| 
									
										
										
										
											2012-03-09 10:26:46 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-04-29 11:51:04 -07:00
										 |  |  |   def external_patches | 
					
						
							| 
									
										
										
										
											2013-05-23 12:50:31 -07:00
										 |  |  |     @patches.select{|p| p.external?} | 
					
						
							| 
									
										
										
										
											2012-04-29 11:51:04 -07:00
										 |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   # Collects the urls and output names of all external patches | 
					
						
							|  |  |  |   def external_curl_args | 
					
						
							|  |  |  |     external_patches.collect{|p| p.curl_args}.flatten | 
					
						
							|  |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-09 10:26:46 -08:00
										 |  |  |   def normalize_patches patches | 
					
						
							|  |  |  |     if patches.kind_of? Hash | 
					
						
							|  |  |  |       patches | 
					
						
							|  |  |  |     else | 
					
						
							|  |  |  |       { :p1 => patches } # We assume -p1 | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class Patch | 
					
						
							| 
									
										
										
										
											2012-04-29 11:51:04 -07:00
										 |  |  |   # Used by formula to unpack after downloading | 
					
						
							| 
									
										
										
										
											2012-03-09 10:26:46 -08:00
										 |  |  |   attr_reader :compression | 
					
						
							| 
									
										
										
										
											2012-04-29 11:51:04 -07:00
										 |  |  |   attr_reader :compressed_filename | 
					
						
							| 
									
										
										
										
											2012-05-03 20:22:47 -07:00
										 |  |  |   # Used by audit | 
					
						
							|  |  |  |   attr_reader :url | 
					
						
							| 
									
										
										
										
											2012-03-09 10:26:46 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   def initialize patch_p, filename, url | 
					
						
							|  |  |  |     @patch_p = patch_p | 
					
						
							|  |  |  |     @patch_filename = filename | 
					
						
							| 
									
										
										
										
											2012-04-29 11:51:04 -07:00
										 |  |  |     @compressed_filename = nil | 
					
						
							|  |  |  |     @compression = nil | 
					
						
							| 
									
										
										
										
											2012-03-09 10:26:46 -08:00
										 |  |  |     @url = nil | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-09-11 22:13:41 -07:00
										 |  |  |     if url.kind_of? IO or url.kind_of? StringIO | 
					
						
							|  |  |  |       # File-like objects. Most common when DATA is passed. | 
					
						
							| 
									
										
										
										
											2012-03-09 10:26:46 -08:00
										 |  |  |       write_data url | 
					
						
							|  |  |  |     elsif looks_like_url(url) | 
					
						
							| 
									
										
										
										
											2012-04-29 11:51:04 -07:00
										 |  |  |       @url = url # Save URL to mark this as an external patch | 
					
						
							| 
									
										
										
										
											2012-03-09 10:26:46 -08:00
										 |  |  |     else | 
					
						
							|  |  |  |       # it's a file on the local filesystem | 
					
						
							|  |  |  |       # use URL as the filename for patch | 
					
						
							|  |  |  |       @patch_filename = url | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-04-29 11:51:04 -07:00
										 |  |  |   # rename the downloaded file to take compression into account | 
					
						
							|  |  |  |   def stage! | 
					
						
							|  |  |  |     return unless external? | 
					
						
							|  |  |  |     detect_compression! | 
					
						
							|  |  |  |     case @compression | 
					
						
							|  |  |  |     when :gzip | 
					
						
							|  |  |  |       @compressed_filename = @patch_filename + '.gz' | 
					
						
							|  |  |  |       FileUtils.mv @patch_filename, @compressed_filename | 
					
						
							|  |  |  |     when :bzip2 | 
					
						
							|  |  |  |       @compressed_filename = @patch_filename + '.bz2' | 
					
						
							|  |  |  |       FileUtils.mv @patch_filename, @compressed_filename | 
					
						
							|  |  |  |     end | 
					
						
							| 
									
										
										
										
											2012-03-09 10:26:46 -08:00
										 |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-04-29 11:51:04 -07:00
										 |  |  |   def external? | 
					
						
							|  |  |  |     not @url.nil? | 
					
						
							| 
									
										
										
										
											2012-03-09 10:26:46 -08:00
										 |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   def patch_args | 
					
						
							|  |  |  |     ["-#{@patch_p}", '-i', @patch_filename] | 
					
						
							|  |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   def curl_args | 
					
						
							| 
									
										
										
										
											2012-04-29 11:51:04 -07:00
										 |  |  |     [@url, '-o', @patch_filename] | 
					
						
							| 
									
										
										
										
											2012-03-09 10:26:46 -08:00
										 |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-04-07 00:49:56 -05:00
										 |  |  |   private | 
					
						
							| 
									
										
										
										
											2012-03-09 10:26:46 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-04-29 11:51:04 -07:00
										 |  |  |   # Detect compression type from the downloaded patch. | 
					
						
							|  |  |  |   def detect_compression! | 
					
						
							|  |  |  |     # If nil we have not tried to detect yet | 
					
						
							|  |  |  |     if @compression.nil? | 
					
						
							|  |  |  |       path = Pathname.new(@patch_filename) | 
					
						
							|  |  |  |       if path.exist? | 
					
						
							|  |  |  |         @compression = path.compression_type | 
					
						
							|  |  |  |         @compression ||= :none # If nil, convert to :none | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-09 10:26:46 -08:00
										 |  |  |   # Write the given file object (DATA) out to a local file for patch | 
					
						
							|  |  |  |   def write_data f | 
					
						
							|  |  |  |     pn = Pathname.new @patch_filename | 
					
						
							| 
									
										
										
										
											2012-04-04 08:26:13 -07:00
										 |  |  |     pn.write(brew_var_substitution(f.read.to_s)) | 
					
						
							| 
									
										
										
										
											2012-03-09 10:26:46 -08:00
										 |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   # Do any supported substitutions of HOMEBREW vars in a DATA patch | 
					
						
							|  |  |  |   def brew_var_substitution s | 
					
						
							|  |  |  |     s.gsub("HOMEBREW_PREFIX", HOMEBREW_PREFIX) | 
					
						
							|  |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   def looks_like_url str | 
					
						
							|  |  |  |     str =~ %r[^\w+\://] | 
					
						
							|  |  |  |   end | 
					
						
							|  |  |  | end |