| 
									
										
										
										
											2015-08-03 13:09:07 +01:00
										 |  |  | require "pathname" | 
					
						
							|  |  |  | require "exceptions" | 
					
						
							|  |  |  | require "utils/json" | 
					
						
							|  |  |  | require "utils/inreplace" | 
					
						
							|  |  |  | require "utils/popen" | 
					
						
							|  |  |  | require "utils/fork" | 
					
						
							| 
									
										
										
										
											2015-09-01 16:52:15 +08:00
										 |  |  | require "utils/git" | 
					
						
							| 
									
										
										
										
											2016-03-28 09:16:40 +01:00
										 |  |  | require "utils/analytics" | 
					
						
							| 
									
										
										
										
											2015-08-03 13:09:07 +01:00
										 |  |  | require "open-uri" | 
					
						
							| 
									
										
										
										
											2011-03-16 02:46:46 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-10-15 14:42:19 +01:00
										 |  |  | class Tty | 
					
						
							| 
									
										
										
										
											2013-03-31 15:18:38 -05:00
										 |  |  |   class << self | 
					
						
							| 
									
										
										
										
											2015-12-07 13:11:34 +00:00
										 |  |  |     def tick | 
					
						
							|  |  |  |       # necessary for 1.8.7 unicode handling since many installs are on 1.8.7 | 
					
						
							|  |  |  |       @tick ||= ["2714".hex].pack("U*") | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def cross | 
					
						
							|  |  |  |       # necessary for 1.8.7 unicode handling since many installs are on 1.8.7 | 
					
						
							|  |  |  |       @cross ||= ["2718".hex].pack("U*") | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def strip_ansi(string) | 
					
						
							|  |  |  |       string.gsub(/\033\[\d+(;\d+)*m/, "") | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-08-03 13:09:07 +01:00
										 |  |  |     def blue | 
					
						
							|  |  |  |       bold 34
 | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def white | 
					
						
							|  |  |  |       bold 39
 | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def red | 
					
						
							|  |  |  |       underline 31
 | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def yellow | 
					
						
							|  |  |  |       underline 33
 | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def reset | 
					
						
							|  |  |  |       escape 0
 | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def em | 
					
						
							|  |  |  |       underline 39
 | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def green | 
					
						
							|  |  |  |       bold 32
 | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def gray | 
					
						
							|  |  |  |       bold 30
 | 
					
						
							|  |  |  |     end | 
					
						
							| 
									
										
										
										
											2011-08-23 23:19:32 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-10-02 21:56:05 +02:00
										 |  |  |     def highlight | 
					
						
							| 
									
										
										
										
											2015-10-16 15:24:16 +02:00
										 |  |  |       bold 39
 | 
					
						
							| 
									
										
										
										
											2015-10-02 21:56:05 +02:00
										 |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-08-23 23:19:32 +01:00
										 |  |  |     def width | 
					
						
							|  |  |  |       `/usr/bin/tput cols`.strip.to_i | 
					
						
							|  |  |  |     end | 
					
						
							| 
									
										
										
										
											2011-07-25 10:21:44 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-03-31 15:18:38 -05:00
										 |  |  |     def truncate(str) | 
					
						
							|  |  |  |       str.to_s[0, width - 4] | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     private | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-08-03 13:09:07 +01:00
										 |  |  |     def color(n) | 
					
						
							| 
									
										
										
										
											2009-10-15 14:42:19 +01:00
										 |  |  |       escape "0;#{n}" | 
					
						
							|  |  |  |     end | 
					
						
							| 
									
										
										
										
											2015-08-03 13:09:07 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def bold(n) | 
					
						
							| 
									
										
										
										
											2009-10-15 14:42:19 +01:00
										 |  |  |       escape "1;#{n}" | 
					
						
							|  |  |  |     end | 
					
						
							| 
									
										
										
										
											2015-08-03 13:09:07 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def underline(n) | 
					
						
							| 
									
										
										
										
											2009-10-15 14:42:19 +01:00
										 |  |  |       escape "4;#{n}" | 
					
						
							|  |  |  |     end | 
					
						
							| 
									
										
										
										
											2015-08-03 13:09:07 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def escape(n) | 
					
						
							| 
									
										
										
										
											2009-10-15 14:42:19 +01:00
										 |  |  |       "\033[#{n}m" if $stdout.tty? | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  |   end | 
					
						
							|  |  |  | end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-08-03 13:09:07 +01:00
										 |  |  | def ohai(title, *sput) | 
					
						
							| 
									
										
										
										
											2013-03-31 15:18:38 -05:00
										 |  |  |   title = Tty.truncate(title) if $stdout.tty? && !ARGV.verbose? | 
					
						
							| 
									
										
										
										
											2009-10-15 14:42:19 +01:00
										 |  |  |   puts "#{Tty.blue}==>#{Tty.white} #{title}#{Tty.reset}" | 
					
						
							| 
									
										
										
										
											2014-07-19 23:59:43 -05:00
										 |  |  |   puts sput | 
					
						
							| 
									
										
										
										
											2009-07-31 02:51:17 +01:00
										 |  |  | end | 
					
						
							| 
									
										
										
										
											2009-07-31 03:56:46 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-08-03 13:09:07 +01:00
										 |  |  | def oh1(title) | 
					
						
							| 
									
										
										
										
											2013-03-31 15:18:38 -05:00
										 |  |  |   title = Tty.truncate(title) if $stdout.tty? && !ARGV.verbose? | 
					
						
							| 
									
										
										
										
											2012-11-13 12:50:24 +01:00
										 |  |  |   puts "#{Tty.green}==>#{Tty.white} #{title}#{Tty.reset}" | 
					
						
							| 
									
										
										
										
											2011-08-23 23:19:32 +01:00
										 |  |  | end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-08-29 10:56:24 +01:00
										 |  |  | # Print a warning (do this rarely) | 
					
						
							| 
									
										
										
										
											2015-08-03 13:09:07 +01:00
										 |  |  | def opoo(warning) | 
					
						
							| 
									
										
										
										
											2015-06-23 15:56:05 +01:00
										 |  |  |   $stderr.puts "#{Tty.yellow}Warning#{Tty.reset}: #{warning}" | 
					
						
							| 
									
										
										
										
											2009-08-10 16:48:30 +01:00
										 |  |  | end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-08-03 13:09:07 +01:00
										 |  |  | def onoe(error) | 
					
						
							| 
									
										
										
										
											2014-08-02 16:59:52 -03:00
										 |  |  |   $stderr.puts "#{Tty.red}Error#{Tty.reset}: #{error}" | 
					
						
							| 
									
										
										
										
											2009-08-10 16:48:30 +01:00
										 |  |  | end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-08-03 13:09:07 +01:00
										 |  |  | def ofail(error) | 
					
						
							| 
									
										
										
										
											2012-04-30 14:08:59 +10:00
										 |  |  |   onoe error | 
					
						
							|  |  |  |   Homebrew.failed = true | 
					
						
							|  |  |  | end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-08-03 13:09:07 +01:00
										 |  |  | def odie(error) | 
					
						
							| 
									
										
										
										
											2012-04-14 17:17:16 +10:00
										 |  |  |   onoe error | 
					
						
							|  |  |  |   exit 1
 | 
					
						
							|  |  |  | end | 
					
						
							| 
									
										
										
										
											2010-11-09 13:00:33 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-07 13:11:34 +00:00
										 |  |  | def pretty_installed(f) | 
					
						
							|  |  |  |   if !$stdout.tty? | 
					
						
							|  |  |  |     "#{f}" | 
					
						
							|  |  |  |   elsif ENV["HOMEBREW_NO_EMOJI"] | 
					
						
							|  |  |  |     "#{Tty.highlight}#{Tty.green}#{f} (installed)#{Tty.reset}" | 
					
						
							|  |  |  |   else | 
					
						
							|  |  |  |     "#{Tty.highlight}#{f} #{Tty.green}#{Tty.tick}#{Tty.reset}" | 
					
						
							|  |  |  |   end | 
					
						
							|  |  |  | end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def pretty_uninstalled(f) | 
					
						
							|  |  |  |   if !$stdout.tty? | 
					
						
							|  |  |  |     "#{f}" | 
					
						
							|  |  |  |   elsif ENV["HOMEBREW_NO_EMOJI"] | 
					
						
							|  |  |  |     "#{Tty.red}#{f} (uninstalled)#{Tty.reset}" | 
					
						
							|  |  |  |   else | 
					
						
							|  |  |  |     "#{f} #{Tty.red}#{Tty.cross}#{Tty.reset}" | 
					
						
							|  |  |  |   end | 
					
						
							|  |  |  | end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-08-03 13:09:07 +01:00
										 |  |  | def pretty_duration(s) | 
					
						
							| 
									
										
										
										
											2015-10-07 22:48:42 +02:00
										 |  |  |   s = s.to_i | 
					
						
							|  |  |  |   res = "" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if s > 59
 | 
					
						
							|  |  |  |     m = s / 60
 | 
					
						
							|  |  |  |     s %= 60
 | 
					
						
							|  |  |  |     res = "#{m} minute#{plural m}" | 
					
						
							|  |  |  |     return res if s == 0
 | 
					
						
							|  |  |  |     res << " " | 
					
						
							|  |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   res + "#{s} second#{plural s}" | 
					
						
							| 
									
										
										
										
											2009-08-10 16:48:30 +01:00
										 |  |  | end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-08-03 13:09:07 +01:00
										 |  |  | def plural(n, s = "s") | 
					
						
							| 
									
										
										
										
											2014-05-26 11:19:00 -07:00
										 |  |  |   (n == 1) ? "" : s | 
					
						
							|  |  |  | end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-08-03 13:09:07 +01:00
										 |  |  | def interactive_shell(f = nil) | 
					
						
							| 
									
										
										
										
											2010-08-20 10:01:49 -07:00
										 |  |  |   unless f.nil? | 
					
						
							| 
									
										
										
										
											2015-08-03 13:09:07 +01:00
										 |  |  |     ENV["HOMEBREW_DEBUG_PREFIX"] = f.prefix | 
					
						
							|  |  |  |     ENV["HOMEBREW_DEBUG_INSTALL"] = f.full_name | 
					
						
							| 
									
										
										
										
											2010-08-20 10:01:49 -07:00
										 |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-07-28 14:50:58 +08:00
										 |  |  |   if ENV["SHELL"].include?("zsh") && ENV["HOME"].start_with?(HOMEBREW_TEMP.resolved_path.to_s) | 
					
						
							|  |  |  |     FileUtils.touch "#{ENV["HOME"]}/.zshrc" | 
					
						
							|  |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-08-03 13:09:07 +01:00
										 |  |  |   Process.wait fork { exec ENV["SHELL"] } | 
					
						
							| 
									
										
										
										
											2014-03-29 17:47:42 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-06-10 11:33:17 -05:00
										 |  |  |   if $?.success? | 
					
						
							|  |  |  |     return | 
					
						
							|  |  |  |   elsif $?.exited? | 
					
						
							| 
									
										
										
										
											2016-04-10 22:53:56 -04:00
										 |  |  |     raise "Aborted due to non-zero exit status (#{$?.exitstatus})" | 
					
						
							| 
									
										
										
										
											2014-06-10 11:33:17 -05:00
										 |  |  |   else | 
					
						
							|  |  |  |     raise $?.inspect | 
					
						
							| 
									
										
										
										
											2009-11-09 17:44:29 +00:00
										 |  |  |   end | 
					
						
							| 
									
										
										
										
											2009-07-31 03:56:46 +01:00
										 |  |  | end | 
					
						
							| 
									
										
										
										
											2009-08-11 12:20:55 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-01-13 09:00:51 +00:00
										 |  |  | module Homebrew | 
					
						
							| 
									
										
										
										
											2015-09-08 16:06:39 +08:00
										 |  |  |   def self._system(cmd, *args) | 
					
						
							| 
									
										
										
										
											2014-03-29 02:24:01 -05:00
										 |  |  |     pid = fork do | 
					
						
							| 
									
										
										
										
											2010-01-13 09:00:51 +00:00
										 |  |  |       yield if block_given? | 
					
						
							| 
									
										
										
										
											2015-08-03 13:09:07 +01:00
										 |  |  |       args.collect!(&:to_s) | 
					
						
							| 
									
										
										
										
											2014-09-20 13:53:09 -05:00
										 |  |  |       exec(cmd, *args) rescue nil | 
					
						
							| 
									
										
										
										
											2010-01-13 09:00:51 +00:00
										 |  |  |       exit! 1 # never gets here unless exec failed | 
					
						
							|  |  |  |     end | 
					
						
							| 
									
										
										
										
											2014-03-29 02:24:01 -05:00
										 |  |  |     Process.wait(pid) | 
					
						
							| 
									
										
										
										
											2010-01-13 09:00:51 +00:00
										 |  |  |     $?.success? | 
					
						
							|  |  |  |   end | 
					
						
							| 
									
										
										
										
											2014-06-30 19:15:03 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-08 16:06:39 +08:00
										 |  |  |   def self.system(cmd, *args) | 
					
						
							|  |  |  |     puts "#{cmd} #{args*" "}" if ARGV.verbose? | 
					
						
							|  |  |  |     _system(cmd, *args) | 
					
						
							|  |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-08 17:46:34 +08:00
										 |  |  |   def self.git_origin | 
					
						
							| 
									
										
										
										
											2015-09-08 15:19:27 +08:00
										 |  |  |     return unless Utils.git_available? | 
					
						
							| 
									
										
										
										
											2015-09-08 17:46:34 +08:00
										 |  |  |     HOMEBREW_REPOSITORY.cd { `git config --get remote.origin.url 2>/dev/null`.chuzzle } | 
					
						
							|  |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-06-30 19:15:03 -05:00
										 |  |  |   def self.git_head | 
					
						
							| 
									
										
										
										
											2015-09-08 15:19:27 +08:00
										 |  |  |     return unless Utils.git_available? | 
					
						
							| 
									
										
										
										
											2014-06-30 19:15:03 -05:00
										 |  |  |     HOMEBREW_REPOSITORY.cd { `git rev-parse --verify -q HEAD 2>/dev/null`.chuzzle } | 
					
						
							|  |  |  |   end | 
					
						
							| 
									
										
										
										
											2014-10-04 16:09:48 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-07-18 21:55:50 -07:00
										 |  |  |   def self.git_short_head | 
					
						
							| 
									
										
										
										
											2015-09-08 15:19:27 +08:00
										 |  |  |     return unless Utils.git_available? | 
					
						
							| 
									
										
										
										
											2015-07-18 21:55:50 -07:00
										 |  |  |     HOMEBREW_REPOSITORY.cd { `git rev-parse --short=4 --verify -q HEAD 2>/dev/null`.chuzzle } | 
					
						
							|  |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-10-04 16:09:48 -07:00
										 |  |  |   def self.git_last_commit | 
					
						
							| 
									
										
										
										
											2015-09-08 15:19:27 +08:00
										 |  |  |     return unless Utils.git_available? | 
					
						
							| 
									
										
										
										
											2014-10-04 16:09:48 -07:00
										 |  |  |     HOMEBREW_REPOSITORY.cd { `git show -s --format="%cr" HEAD 2>/dev/null`.chuzzle } | 
					
						
							|  |  |  |   end | 
					
						
							| 
									
										
										
										
											2015-01-02 12:42:02 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-07-18 21:55:50 -07:00
										 |  |  |   def self.git_last_commit_date | 
					
						
							| 
									
										
										
										
											2015-09-08 15:19:27 +08:00
										 |  |  |     return unless Utils.git_available? | 
					
						
							| 
									
										
										
										
											2015-07-18 21:55:50 -07:00
										 |  |  |     HOMEBREW_REPOSITORY.cd { `git show -s --format="%cd" --date=short HEAD 2>/dev/null`.chuzzle } | 
					
						
							|  |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   def self.homebrew_version_string | 
					
						
							| 
									
										
										
										
											2015-09-08 15:19:27 +08:00
										 |  |  |     if pretty_revision = git_short_head | 
					
						
							| 
									
										
										
										
											2015-07-18 21:55:50 -07:00
										 |  |  |       last_commit = git_last_commit_date | 
					
						
							|  |  |  |       "#{HOMEBREW_VERSION} (git revision #{pretty_revision}; last commit #{last_commit})" | 
					
						
							|  |  |  |     else | 
					
						
							|  |  |  |       "#{HOMEBREW_VERSION} (no git repository)" | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-03-06 15:01:54 +08:00
										 |  |  |   def self.core_tap_version_string | 
					
						
							|  |  |  |     require "tap" | 
					
						
							|  |  |  |     tap = CoreTap.instance | 
					
						
							|  |  |  |     return "N/A" unless tap.installed? | 
					
						
							|  |  |  |     if pretty_revision = tap.git_short_head | 
					
						
							|  |  |  |       last_commit = tap.git_last_commit_date | 
					
						
							|  |  |  |       "(git revision #{pretty_revision}; last commit #{last_commit})" | 
					
						
							|  |  |  |     else | 
					
						
							|  |  |  |       "(no git repository)" | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-08-03 13:09:07 +01:00
										 |  |  |   def self.install_gem_setup_path!(gem, version = nil, executable = gem) | 
					
						
							| 
									
										
										
										
											2015-01-02 12:42:02 +00:00
										 |  |  |     require "rubygems" | 
					
						
							| 
									
										
										
										
											2016-01-05 01:09:54 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     # Add Gem binary directory and (if missing) Ruby binary directory to PATH. | 
					
						
							|  |  |  |     path = ENV["PATH"].split(File::PATH_SEPARATOR) | 
					
						
							|  |  |  |     path.unshift(RUBY_BIN) if which("ruby") != RUBY_PATH | 
					
						
							|  |  |  |     path.unshift("#{Gem.user_dir}/bin") | 
					
						
							|  |  |  |     ENV["PATH"] = path.join(File::PATH_SEPARATOR) | 
					
						
							| 
									
										
										
										
											2015-01-05 19:14:55 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-19 05:37:07 +01:00
										 |  |  |     if Gem::Specification.find_all_by_name(gem, version).empty? | 
					
						
							|  |  |  |       ohai "Installing or updating '#{gem}' gem" | 
					
						
							|  |  |  |       install_args = %W[--no-ri --no-rdoc --user-install #{gem}] | 
					
						
							|  |  |  |       install_args << "--version" << version if version | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       # Do `gem install [...]` without having to spawn a separate process or | 
					
						
							|  |  |  |       # having to find the right `gem` binary for the running Ruby interpreter. | 
					
						
							|  |  |  |       require "rubygems/commands/install_command" | 
					
						
							|  |  |  |       install_cmd = Gem::Commands::InstallCommand.new | 
					
						
							|  |  |  |       install_cmd.handle_options(install_args) | 
					
						
							|  |  |  |       exit_code = 1 # Should not matter as `install_cmd.execute` always throws. | 
					
						
							|  |  |  |       begin | 
					
						
							|  |  |  |         install_cmd.execute | 
					
						
							|  |  |  |       rescue Gem::SystemExitException => e | 
					
						
							|  |  |  |         exit_code = e.exit_code | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  |       odie "Failed to install/update the '#{gem}' gem." if exit_code != 0
 | 
					
						
							| 
									
										
										
										
											2015-01-05 19:14:55 +00:00
										 |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     unless which executable | 
					
						
							|  |  |  |       odie <<-EOS.undent
 | 
					
						
							|  |  |  |         The '#{gem}' gem is installed but couldn't find '#{executable}' in the PATH: | 
					
						
							|  |  |  |         #{ENV["PATH"]} | 
					
						
							|  |  |  |       EOS | 
					
						
							|  |  |  |     end | 
					
						
							| 
									
										
										
										
											2015-01-02 12:42:02 +00:00
										 |  |  |   end | 
					
						
							| 
									
										
										
										
											2016-04-18 17:39:21 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  |   # Hash of Module => Set(method_names) | 
					
						
							|  |  |  |   @@injected_dump_stat_modules = {} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   def inject_dump_stats!(the_module, pattern) | 
					
						
							|  |  |  |     @@injected_dump_stat_modules[the_module] ||= [] | 
					
						
							|  |  |  |     injected_methods = @@injected_dump_stat_modules[the_module] | 
					
						
							|  |  |  |     the_module.module_eval do | 
					
						
							|  |  |  |       instance_methods.grep(pattern).each do |name| | 
					
						
							|  |  |  |         next if injected_methods.include? name | 
					
						
							|  |  |  |         method = instance_method(name) | 
					
						
							|  |  |  |         define_method(name) do |*args, &block| | 
					
						
							|  |  |  |           begin | 
					
						
							|  |  |  |             time = Time.now | 
					
						
							|  |  |  |             method.bind(self).call(*args, &block) | 
					
						
							|  |  |  |           ensure | 
					
						
							|  |  |  |             $times[name] ||= 0
 | 
					
						
							|  |  |  |             $times[name] += Time.now - time | 
					
						
							|  |  |  |           end | 
					
						
							|  |  |  |         end | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if $times.nil? | 
					
						
							|  |  |  |       $times = {} | 
					
						
							|  |  |  |       at_exit do | 
					
						
							|  |  |  |         col_width = [$times.keys.map(&:size).max + 2, 15].max | 
					
						
							|  |  |  |         $times.sort_by { |_k, v| v }.each do |method, time| | 
					
						
							|  |  |  |           puts format("%-*s %0.4f sec", col_width, "#{method}:", time) | 
					
						
							|  |  |  |         end | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  |   end | 
					
						
							| 
									
										
										
										
											2010-01-13 09:00:51 +00:00
										 |  |  | end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-03-10 17:03:17 +00:00
										 |  |  | def with_system_path | 
					
						
							| 
									
										
										
										
											2015-08-03 13:09:07 +01:00
										 |  |  |   old_path = ENV["PATH"] | 
					
						
							|  |  |  |   ENV["PATH"] = "/usr/bin:/bin" | 
					
						
							| 
									
										
										
										
											2013-03-10 17:03:17 +00:00
										 |  |  |   yield | 
					
						
							|  |  |  | ensure | 
					
						
							| 
									
										
										
										
											2015-08-03 13:09:07 +01:00
										 |  |  |   ENV["PATH"] = old_path | 
					
						
							| 
									
										
										
										
											2013-03-10 17:03:17 +00:00
										 |  |  | end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-08-03 13:09:07 +01:00
										 |  |  | def run_as_not_developer(&_block) | 
					
						
							|  |  |  |   old = ENV.delete "HOMEBREW_DEVELOPER" | 
					
						
							|  |  |  |   yield | 
					
						
							|  |  |  | ensure | 
					
						
							|  |  |  |   ENV["HOMEBREW_DEVELOPER"] = old | 
					
						
							| 
									
										
										
										
											2015-05-18 18:44:27 +08:00
										 |  |  | end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-08-11 12:20:55 -07:00
										 |  |  | # Kernel.system but with exceptions | 
					
						
							| 
									
										
										
										
											2015-08-03 13:09:07 +01:00
										 |  |  | def safe_system(cmd, *args) | 
					
						
							|  |  |  |   Homebrew.system(cmd, *args) || raise(ErrorDuringExecution.new(cmd, args)) | 
					
						
							| 
									
										
										
										
											2010-01-13 09:00:51 +00:00
										 |  |  | end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | # prints no output | 
					
						
							| 
									
										
										
										
											2015-08-03 13:09:07 +01:00
										 |  |  | def quiet_system(cmd, *args) | 
					
						
							| 
									
										
										
										
											2015-09-08 16:06:39 +08:00
										 |  |  |   Homebrew._system(cmd, *args) do | 
					
						
							| 
									
										
										
										
											2012-07-06 12:56:18 -08:00
										 |  |  |     # Redirect output streams to `/dev/null` instead of closing as some programs | 
					
						
							|  |  |  |     # will fail to execute if they can't write to an open stream. | 
					
						
							| 
									
										
										
										
											2015-08-03 13:09:07 +01:00
										 |  |  |     $stdout.reopen("/dev/null") | 
					
						
							|  |  |  |     $stderr.reopen("/dev/null") | 
					
						
							| 
									
										
										
										
											2009-11-09 17:44:29 +00:00
										 |  |  |   end | 
					
						
							| 
									
										
										
										
											2009-08-11 12:20:55 -07:00
										 |  |  | end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-08-03 13:09:07 +01:00
										 |  |  | def curl(*args) | 
					
						
							| 
									
										
										
										
											2016-04-04 11:46:33 +01:00
										 |  |  |   curl = Pathname.new ENV["HOMEBREW_CURL"] | 
					
						
							| 
									
										
										
										
											2016-04-07 14:57:37 +08:00
										 |  |  |   curl = Pathname.new "/usr/bin/curl" unless curl.exist? | 
					
						
							| 
									
										
										
										
											2015-08-03 13:09:07 +01:00
										 |  |  |   raise "#{curl} is not executable" unless curl.exist? && curl.executable? | 
					
						
							| 
									
										
										
										
											2011-09-14 12:18:35 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-18 16:03:44 -05:00
										 |  |  |   flags = HOMEBREW_CURL_ARGS | 
					
						
							|  |  |  |   flags = flags.delete("#") if ARGV.verbose? | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-04 11:46:33 +01:00
										 |  |  |   args = [flags, HOMEBREW_USER_AGENT_CURL, *args] | 
					
						
							| 
									
										
										
										
											2015-08-03 13:09:07 +01:00
										 |  |  |   args << "--verbose" if ENV["HOMEBREW_CURL_VERBOSE"] | 
					
						
							| 
									
										
										
										
											2015-11-01 00:08:40 -07:00
										 |  |  |   args << "--silent" if !$stdout.tty? || ENV["TRAVIS"] | 
					
						
							| 
									
										
										
										
											2011-08-26 13:27:55 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-09-19 23:29:07 +01:00
										 |  |  |   safe_system curl, *args | 
					
						
							| 
									
										
										
										
											2009-08-11 12:20:55 -07:00
										 |  |  | end | 
					
						
							| 
									
										
										
										
											2009-09-04 15:22:25 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-07 13:11:34 +00:00
										 |  |  | def puts_columns(items) | 
					
						
							| 
									
										
										
										
											2009-12-18 16:28:30 -08:00
										 |  |  |   return if items.empty? | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-10-02 21:47:40 +02:00
										 |  |  |   unless $stdout.tty? | 
					
						
							| 
									
										
										
										
											2010-10-25 21:11:45 -07:00
										 |  |  |     puts items | 
					
						
							| 
									
										
										
										
											2015-10-02 21:47:40 +02:00
										 |  |  |     return | 
					
						
							|  |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   # TTY case: If possible, output using multiple columns. | 
					
						
							|  |  |  |   console_width = Tty.width | 
					
						
							|  |  |  |   console_width = 80 if console_width <= 0
 | 
					
						
							| 
									
										
										
										
											2015-12-07 13:11:34 +00:00
										 |  |  |   plain_item_lengths = items.map { |s| Tty.strip_ansi(s).length } | 
					
						
							|  |  |  |   max_len = plain_item_lengths.max | 
					
						
							| 
									
										
										
										
											2015-10-02 21:47:40 +02:00
										 |  |  |   col_gap = 2 # number of spaces between columns | 
					
						
							|  |  |  |   gap_str = " " * col_gap | 
					
						
							|  |  |  |   cols = (console_width + col_gap) / (max_len + col_gap) | 
					
						
							|  |  |  |   cols = 1 if cols < 1
 | 
					
						
							|  |  |  |   rows = (items.size + cols - 1) / cols | 
					
						
							|  |  |  |   cols = (items.size + rows - 1) / rows # avoid empty trailing columns | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if cols >= 2
 | 
					
						
							|  |  |  |     col_width = (console_width + col_gap) / cols - col_gap | 
					
						
							| 
									
										
										
										
											2015-10-02 21:56:05 +02:00
										 |  |  |     items = items.each_with_index.map do |item, index| | 
					
						
							|  |  |  |       item + "".ljust(col_width - plain_item_lengths[index]) | 
					
						
							|  |  |  |     end | 
					
						
							| 
									
										
										
										
											2015-10-02 21:47:40 +02:00
										 |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if cols == 1
 | 
					
						
							|  |  |  |     puts items | 
					
						
							|  |  |  |   else | 
					
						
							|  |  |  |     rows.times do |row_index| | 
					
						
							|  |  |  |       item_indices_for_row = row_index.step(items.size - 1, rows).to_a | 
					
						
							|  |  |  |       puts items.values_at(*item_indices_for_row).join(gap_str) | 
					
						
							|  |  |  |     end | 
					
						
							| 
									
										
										
										
											2009-09-22 20:43:06 +02:00
										 |  |  |   end | 
					
						
							| 
									
										
										
										
											2009-09-04 15:22:25 -07:00
										 |  |  | end | 
					
						
							| 
									
										
										
										
											2009-09-05 14:03:41 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-08-03 13:09:07 +01:00
										 |  |  | def which(cmd, path = ENV["PATH"]) | 
					
						
							| 
									
										
										
										
											2014-07-06 11:16:10 -05:00
										 |  |  |   path.split(File::PATH_SEPARATOR).each do |p| | 
					
						
							| 
									
										
										
										
											2015-08-14 22:57:49 +02:00
										 |  |  |     begin | 
					
						
							|  |  |  |       pcmd = File.expand_path(cmd, p) | 
					
						
							|  |  |  |     rescue ArgumentError | 
					
						
							|  |  |  |       # File.expand_path will raise an ArgumentError if the path is malformed. | 
					
						
							|  |  |  |       # See https://github.com/Homebrew/homebrew/issues/32789 | 
					
						
							|  |  |  |       next | 
					
						
							|  |  |  |     end | 
					
						
							| 
									
										
										
										
											2014-07-06 13:35:44 -05:00
										 |  |  |     return Pathname.new(pcmd) if File.file?(pcmd) && File.executable?(pcmd) | 
					
						
							| 
									
										
										
										
											2014-03-16 11:52:11 -07:00
										 |  |  |   end | 
					
						
							| 
									
										
										
										
											2015-08-03 13:09:07 +01:00
										 |  |  |   nil | 
					
						
							| 
									
										
										
										
											2012-03-03 15:50:24 -08:00
										 |  |  | end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-01-02 23:08:51 +08:00
										 |  |  | def which_all(cmd, path = ENV["PATH"]) | 
					
						
							|  |  |  |   path.split(File::PATH_SEPARATOR).map do |p| | 
					
						
							|  |  |  |     begin | 
					
						
							|  |  |  |       pcmd = File.expand_path(cmd, p) | 
					
						
							|  |  |  |     rescue ArgumentError | 
					
						
							|  |  |  |       # File.expand_path will raise an ArgumentError if the path is malformed. | 
					
						
							|  |  |  |       # See https://github.com/Homebrew/homebrew/issues/32789 | 
					
						
							|  |  |  |       next | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  |     Pathname.new(pcmd) if File.file?(pcmd) && File.executable?(pcmd) | 
					
						
							|  |  |  |   end.compact.uniq | 
					
						
							|  |  |  | end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-12-16 14:27:58 -08:00
										 |  |  | def which_editor | 
					
						
							| 
									
										
										
										
											2015-08-03 13:09:07 +01:00
										 |  |  |   editor = ENV.values_at("HOMEBREW_EDITOR", "VISUAL", "EDITOR").compact.first | 
					
						
							| 
									
										
										
										
											2011-12-16 14:27:58 -08:00
										 |  |  |   return editor unless editor.nil? | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   # Find Textmate | 
					
						
							| 
									
										
										
										
											2015-01-05 15:23:35 -05:00
										 |  |  |   editor = "mate" if which "mate" | 
					
						
							| 
									
										
										
										
											2013-11-28 11:21:54 -08:00
										 |  |  |   # Find BBEdit / TextWrangler | 
					
						
							| 
									
										
										
										
											2015-01-05 15:23:35 -05:00
										 |  |  |   editor ||= "edit" if which "edit" | 
					
						
							| 
									
										
										
										
											2014-06-04 13:29:00 -10:00
										 |  |  |   # Find vim | 
					
						
							| 
									
										
										
										
											2015-01-05 15:23:35 -05:00
										 |  |  |   editor ||= "vim" if which "vim" | 
					
						
							| 
									
										
										
										
											2014-06-04 13:29:00 -10:00
										 |  |  |   # Default to standard vim | 
					
						
							| 
									
										
										
										
											2015-01-05 15:23:35 -05:00
										 |  |  |   editor ||= "/usr/bin/vim" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   opoo <<-EOS.undent
 | 
					
						
							|  |  |  |     Using #{editor} because no editor was set in the environment. | 
					
						
							|  |  |  |     This may change in the future, so we recommend setting EDITOR, VISUAL, | 
					
						
							|  |  |  |     or HOMEBREW_EDITOR to your preferred text editor. | 
					
						
							|  |  |  |   EOS | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   editor | 
					
						
							| 
									
										
										
										
											2011-12-16 14:27:58 -08:00
										 |  |  | end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-08-03 13:09:07 +01:00
										 |  |  | def exec_editor(*args) | 
					
						
							| 
									
										
										
										
											2012-12-27 23:34:29 -06:00
										 |  |  |   safe_exec(which_editor, *args) | 
					
						
							|  |  |  | end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-08-03 13:09:07 +01:00
										 |  |  | def exec_browser(*args) | 
					
						
							|  |  |  |   browser = ENV["HOMEBREW_BROWSER"] || ENV["BROWSER"] || OS::PATH_OPEN | 
					
						
							| 
									
										
										
										
											2012-12-27 23:34:29 -06:00
										 |  |  |   safe_exec(browser, *args) | 
					
						
							|  |  |  | end | 
					
						
							| 
									
										
										
										
											2010-11-08 13:06:45 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-08-03 13:09:07 +01:00
										 |  |  | def safe_exec(cmd, *args) | 
					
						
							| 
									
										
										
										
											2012-12-27 23:34:29 -06:00
										 |  |  |   # This buys us proper argument quoting and evaluation | 
					
						
							|  |  |  |   # of environment variables in the cmd parameter. | 
					
						
							| 
									
										
										
										
											2014-09-20 11:42:19 -05:00
										 |  |  |   exec "/bin/sh", "-c", "#{cmd} \"$@\"", "--", *args | 
					
						
							| 
									
										
										
										
											2009-09-05 14:03:41 -04:00
										 |  |  | end | 
					
						
							| 
									
										
										
										
											2009-09-08 15:31:28 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-11-09 13:00:33 +00:00
										 |  |  | # GZips the given paths, and returns the gzipped paths | 
					
						
							| 
									
										
										
										
											2015-08-03 13:09:07 +01:00
										 |  |  | def gzip(*paths) | 
					
						
							| 
									
										
										
										
											2010-09-12 22:55:52 +02:00
										 |  |  |   paths.collect do |path| | 
					
						
							| 
									
										
										
										
											2015-08-03 13:09:07 +01:00
										 |  |  |     with_system_path { safe_system "gzip", path } | 
					
						
							| 
									
										
										
										
											2010-11-09 13:00:33 +00:00
										 |  |  |     Pathname.new("#{path}.gz") | 
					
						
							| 
									
										
										
										
											2010-09-12 22:55:52 +02:00
										 |  |  |   end | 
					
						
							| 
									
										
										
										
											2010-01-29 10:15:33 -08:00
										 |  |  | end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-05-10 10:14:20 -07:00
										 |  |  | # Returns array of architectures that the given command or library is built for. | 
					
						
							| 
									
										
										
										
											2015-08-03 13:09:07 +01:00
										 |  |  | def archs_for_command(cmd) | 
					
						
							| 
									
										
										
										
											2012-05-28 20:39:05 -05:00
										 |  |  |   cmd = which(cmd) unless Pathname.new(cmd).absolute? | 
					
						
							|  |  |  |   Pathname.new(cmd).archs | 
					
						
							| 
									
										
										
										
											2009-09-08 15:31:28 -07:00
										 |  |  | end | 
					
						
							| 
									
										
										
										
											2009-10-15 12:36:09 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-09-11 20:59:59 -04:00
										 |  |  | def ignore_interrupts(opt = nil) | 
					
						
							|  |  |  |   std_trap = trap("INT") do | 
					
						
							| 
									
										
										
										
											2012-09-27 16:21:39 -05:00
										 |  |  |     puts "One sec, just cleaning up" unless opt == :quietly | 
					
						
							| 
									
										
										
										
											2012-09-11 20:59:59 -04:00
										 |  |  |   end | 
					
						
							| 
									
										
										
										
											2009-11-06 17:09:14 +00:00
										 |  |  |   yield | 
					
						
							|  |  |  | ensure | 
					
						
							|  |  |  |   trap("INT", std_trap) | 
					
						
							|  |  |  | end | 
					
						
							| 
									
										
										
										
											2009-11-09 18:24:36 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | def nostdout | 
					
						
							|  |  |  |   if ARGV.verbose? | 
					
						
							|  |  |  |     yield | 
					
						
							|  |  |  |   else | 
					
						
							|  |  |  |     begin | 
					
						
							| 
									
										
										
										
											2014-07-06 15:03:25 -05:00
										 |  |  |       out = $stdout.dup | 
					
						
							|  |  |  |       $stdout.reopen("/dev/null") | 
					
						
							| 
									
										
										
										
											2009-11-09 18:24:36 +00:00
										 |  |  |       yield | 
					
						
							|  |  |  |     ensure | 
					
						
							| 
									
										
										
										
											2014-07-06 15:03:25 -05:00
										 |  |  |       $stdout.reopen(out) | 
					
						
							|  |  |  |       out.close | 
					
						
							| 
									
										
										
										
											2009-11-09 18:24:36 +00:00
										 |  |  |     end | 
					
						
							|  |  |  |   end | 
					
						
							| 
									
										
										
										
											2010-01-13 09:00:51 +00:00
										 |  |  | end | 
					
						
							| 
									
										
										
										
											2010-04-07 21:01:12 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-09-15 20:11:17 -07:00
										 |  |  | def paths | 
					
						
							| 
									
										
										
										
											2015-08-03 13:09:07 +01:00
										 |  |  |   @paths ||= ENV["PATH"].split(File::PATH_SEPARATOR).collect do |p| | 
					
						
							| 
									
										
										
										
											2013-09-15 20:11:17 -07:00
										 |  |  |     begin | 
					
						
							| 
									
										
										
										
											2015-08-03 13:09:07 +01:00
										 |  |  |       File.expand_path(p).chomp("/") | 
					
						
							| 
									
										
										
										
											2013-09-15 20:11:17 -07:00
										 |  |  |     rescue ArgumentError | 
					
						
							|  |  |  |       onoe "The following PATH component is invalid: #{p}" | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  |   end.uniq.compact | 
					
						
							|  |  |  | end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-24 21:03:20 +08:00
										 |  |  | # return the shell profile file based on users' preference shell | 
					
						
							|  |  |  | def shell_profile | 
					
						
							|  |  |  |   case ENV["SHELL"] | 
					
						
							|  |  |  |   when %r{/(ba)?sh} then "~/.bash_profile" | 
					
						
							|  |  |  |   when %r{/zsh} then "~/.zshrc" | 
					
						
							|  |  |  |   when %r{/ksh} then "~/.kshrc" | 
					
						
							|  |  |  |   else "~/.bash_profile" | 
					
						
							|  |  |  |   end | 
					
						
							|  |  |  | end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-08-03 13:09:07 +01:00
										 |  |  | module GitHub | 
					
						
							|  |  |  |   extend self | 
					
						
							| 
									
										
										
										
											2014-02-08 20:41:11 -05:00
										 |  |  |   ISSUES_URI = URI.parse("https://api.github.com/search/issues") | 
					
						
							| 
									
										
										
										
											2013-06-22 22:46:40 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-16 22:24:33 -05:00
										 |  |  |   Error = Class.new(RuntimeError) | 
					
						
							| 
									
										
										
										
											2014-02-08 20:41:11 -05:00
										 |  |  |   HTTPNotFoundError = Class.new(Error) | 
					
						
							| 
									
										
										
										
											2013-07-01 16:58:16 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-16 22:24:33 -05:00
										 |  |  |   class RateLimitExceededError < Error | 
					
						
							|  |  |  |     def initialize(reset, error) | 
					
						
							|  |  |  |       super <<-EOS.undent
 | 
					
						
							| 
									
										
										
										
											2016-03-25 18:35:06 +08:00
										 |  |  |         GitHub API Error: #{error} | 
					
						
							| 
									
										
										
										
											2015-10-19 14:54:39 +02:00
										 |  |  |         Try again in #{pretty_ratelimit_reset(reset)}, or create a personal access token: | 
					
						
							| 
									
										
										
										
											2015-10-20 19:03:24 +08:00
										 |  |  |           #{Tty.em}https://github.com/settings/tokens/new?scopes=&description=Homebrew#{Tty.reset} | 
					
						
							| 
									
										
										
										
											2016-03-12 18:36:12 -08:00
										 |  |  |         and then set the token as: export HOMEBREW_GITHUB_API_TOKEN="your_new_token" | 
					
						
							| 
									
										
										
										
											2015-10-19 14:54:39 +02:00
										 |  |  |       EOS | 
					
						
							| 
									
										
										
										
											2014-02-16 22:24:33 -05:00
										 |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def pretty_ratelimit_reset(reset) | 
					
						
							| 
									
										
										
										
											2015-10-07 22:48:42 +02:00
										 |  |  |       pretty_duration(Time.at(reset) - Time.now) | 
					
						
							| 
									
										
										
										
											2014-02-16 22:24:33 -05:00
										 |  |  |     end | 
					
						
							|  |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-16 22:24:33 -05:00
										 |  |  |   class AuthenticationFailedError < Error | 
					
						
							|  |  |  |     def initialize(error) | 
					
						
							| 
									
										
										
										
											2016-03-12 18:36:12 -08:00
										 |  |  |       message = "GitHub #{error}\n" | 
					
						
							|  |  |  |       if ENV["HOMEBREW_GITHUB_API_TOKEN"] | 
					
						
							|  |  |  |         message << <<-EOS.undent
 | 
					
						
							|  |  |  |           HOMEBREW_GITHUB_API_TOKEN may be invalid or expired; check: | 
					
						
							| 
									
										
										
										
											2015-10-20 19:03:24 +08:00
										 |  |  |           #{Tty.em}https://github.com/settings/tokens#{Tty.reset} | 
					
						
							| 
									
										
										
										
											2016-03-12 18:36:12 -08:00
										 |  |  |         EOS | 
					
						
							|  |  |  |       else | 
					
						
							|  |  |  |         message << <<-EOS.undent
 | 
					
						
							| 
									
										
										
										
											2016-03-25 18:35:06 +08:00
										 |  |  |           The GitHub credentials in the OS X keychain may be invalid. | 
					
						
							| 
									
										
										
										
											2016-03-12 18:36:12 -08:00
										 |  |  |           Clear them with: | 
					
						
							|  |  |  |             printf "protocol=https\\nhost=github.com\\n" | git credential-osxkeychain erase | 
					
						
							| 
									
										
										
										
											2016-03-25 18:35:06 +08:00
										 |  |  |           Or create a personal access token: | 
					
						
							|  |  |  |             #{Tty.em}https://github.com/settings/tokens/new?scopes=&description=Homebrew#{Tty.reset} | 
					
						
							|  |  |  |           and then set the token as: export HOMEBREW_GITHUB_API_TOKEN="your_new_token" | 
					
						
							| 
									
										
										
										
											2016-03-12 18:36:12 -08:00
										 |  |  |         EOS | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  |       super message | 
					
						
							| 
									
										
										
										
											2014-02-16 22:24:33 -05:00
										 |  |  |     end | 
					
						
							|  |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-03-08 11:43:39 +00:00
										 |  |  |   def api_credentials | 
					
						
							|  |  |  |     @api_credentials ||= begin | 
					
						
							|  |  |  |       if ENV["HOMEBREW_GITHUB_API_TOKEN"] | 
					
						
							|  |  |  |         ENV["HOMEBREW_GITHUB_API_TOKEN"] | 
					
						
							|  |  |  |       else | 
					
						
							| 
									
										
										
										
											2016-03-10 10:24:08 +00:00
										 |  |  |         github_credentials = Utils.popen("git credential-osxkeychain get", "w+") do |io| | 
					
						
							| 
									
										
										
										
											2016-03-08 11:43:39 +00:00
										 |  |  |           io.puts "protocol=https\nhost=github.com" | 
					
						
							|  |  |  |           io.close_write | 
					
						
							|  |  |  |           io.read | 
					
						
							|  |  |  |         end | 
					
						
							|  |  |  |         github_username = github_credentials[/username=(.+)/, 1] | 
					
						
							|  |  |  |         github_password = github_credentials[/password=(.+)/, 1] | 
					
						
							| 
									
										
										
										
											2016-03-10 10:24:08 +00:00
										 |  |  |         if github_username && github_password | 
					
						
							|  |  |  |           [github_password, github_username] | 
					
						
							|  |  |  |         else | 
					
						
							|  |  |  |           [] | 
					
						
							|  |  |  |         end | 
					
						
							| 
									
										
										
										
											2016-03-08 11:43:39 +00:00
										 |  |  |       end | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-03-25 18:35:06 +08:00
										 |  |  |   def api_credentials_type | 
					
						
							|  |  |  |     token, username = api_credentials | 
					
						
							|  |  |  |     if token && !token.empty? | 
					
						
							|  |  |  |       if username && !username.empty? | 
					
						
							|  |  |  |         :keychain | 
					
						
							|  |  |  |       else | 
					
						
							|  |  |  |         :environment | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  |     else | 
					
						
							|  |  |  |       :none | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   def api_credentials_error_message(response_headers) | 
					
						
							|  |  |  |     @api_credentials_error_message_printed ||= begin | 
					
						
							|  |  |  |       unauthorized = (response_headers["status"] == "401 Unauthorized") | 
					
						
							|  |  |  |       scopes = response_headers["x-accepted-oauth-scopes"].to_s.split(", ") | 
					
						
							|  |  |  |       if !unauthorized && scopes.empty? | 
					
						
							|  |  |  |         credentials_scopes = response_headers["x-oauth-scopes"].to_s.split(", ") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         case GitHub.api_credentials_type | 
					
						
							|  |  |  |         when :keychain | 
					
						
							|  |  |  |           onoe <<-EOS.undent
 | 
					
						
							|  |  |  |             Your OS X keychain GitHub credentials do not have sufficient scope! | 
					
						
							|  |  |  |             Scopes they have: #{credentials_scopes} | 
					
						
							|  |  |  |             Create a personal access token: https://github.com/settings/tokens | 
					
						
							|  |  |  |             and then set HOMEBREW_GITHUB_API_TOKEN as the authentication method instead. | 
					
						
							|  |  |  |           EOS | 
					
						
							|  |  |  |         when :environment | 
					
						
							|  |  |  |           onoe <<-EOS.undent
 | 
					
						
							|  |  |  |             Your HOMEBREW_GITHUB_API_TOKEN does not have sufficient scope! | 
					
						
							|  |  |  |             Scopes it has: #{credentials_scopes} | 
					
						
							|  |  |  |             Create a new personal access token: https://github.com/settings/tokens | 
					
						
							|  |  |  |             and then set the new HOMEBREW_GITHUB_API_TOKEN as the authentication method instead. | 
					
						
							|  |  |  |           EOS | 
					
						
							| 
									
										
										
										
											2016-03-08 11:43:39 +00:00
										 |  |  |         end | 
					
						
							|  |  |  |       end | 
					
						
							| 
									
										
										
										
											2016-03-25 18:35:06 +08:00
										 |  |  |       true | 
					
						
							| 
									
										
										
										
											2016-03-08 11:43:39 +00:00
										 |  |  |     end | 
					
						
							|  |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-03-25 18:35:06 +08:00
										 |  |  |   def api_headers | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2016-04-04 11:46:33 +01:00
										 |  |  |       "User-Agent" => HOMEBREW_USER_AGENT_RUBY, | 
					
						
							| 
									
										
										
										
											2016-03-25 18:35:06 +08:00
										 |  |  |       "Accept"     => "application/vnd.github.v3+json" | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-08-03 13:09:07 +01:00
										 |  |  |   def open(url, &_block) | 
					
						
							| 
									
										
										
										
											2013-10-22 16:18:31 -07:00
										 |  |  |     # This is a no-op if the user is opting out of using the GitHub API. | 
					
						
							| 
									
										
										
										
											2015-08-03 13:09:07 +01:00
										 |  |  |     return if ENV["HOMEBREW_NO_GITHUB_API"] | 
					
						
							| 
									
										
										
										
											2013-10-22 16:18:31 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-01 01:21:59 -05:00
										 |  |  |     require "net/https" | 
					
						
							| 
									
										
										
										
											2013-08-02 18:18:34 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-03-25 18:35:06 +08:00
										 |  |  |     headers = api_headers | 
					
						
							|  |  |  |     token, username = api_credentials | 
					
						
							|  |  |  |     case api_credentials_type | 
					
						
							|  |  |  |     when :keychain | 
					
						
							|  |  |  |       headers[:http_basic_authentication] = [username, token] | 
					
						
							|  |  |  |     when :environment | 
					
						
							|  |  |  |       headers["Authorization"] = "token #{token}" | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-06-24 20:59:26 -05:00
										 |  |  |     begin | 
					
						
							| 
									
										
										
										
											2016-03-25 18:35:06 +08:00
										 |  |  |       Kernel.open(url, headers) { |f| yield Utils::JSON.load(f.read) } | 
					
						
							| 
									
										
										
										
											2014-06-24 20:59:26 -05:00
										 |  |  |     rescue OpenURI::HTTPError => e | 
					
						
							|  |  |  |       handle_api_error(e) | 
					
						
							| 
									
										
										
										
											2014-11-20 22:25:33 -06:00
										 |  |  |     rescue EOFError, SocketError, OpenSSL::SSL::SSLError => e | 
					
						
							| 
									
										
										
										
											2014-06-24 20:59:26 -05:00
										 |  |  |       raise Error, "Failed to connect to: #{url}\n#{e.message}", e.backtrace | 
					
						
							|  |  |  |     rescue Utils::JSON::Error => e | 
					
						
							|  |  |  |       raise Error, "Failed to parse JSON response\n#{e.message}", e.backtrace | 
					
						
							| 
									
										
										
										
											2014-02-08 16:04:53 -05:00
										 |  |  |     end | 
					
						
							| 
									
										
										
										
											2014-02-16 22:24:33 -05:00
										 |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   def handle_api_error(e) | 
					
						
							| 
									
										
										
										
											2016-01-28 05:51:25 +01:00
										 |  |  |     if e.io.meta.fetch("x-ratelimit-remaining", 1).to_i <= 0
 | 
					
						
							| 
									
										
										
										
											2014-02-16 22:24:33 -05:00
										 |  |  |       reset = e.io.meta.fetch("x-ratelimit-reset").to_i | 
					
						
							| 
									
										
										
										
											2014-02-16 22:24:33 -05:00
										 |  |  |       error = Utils::JSON.load(e.io.read)["message"] | 
					
						
							|  |  |  |       raise RateLimitExceededError.new(reset, error) | 
					
						
							| 
									
										
										
										
											2014-02-16 22:24:33 -05:00
										 |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-03-25 18:35:06 +08:00
										 |  |  |     GitHub.api_credentials_error_message(e.io.meta) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-16 22:24:33 -05:00
										 |  |  |     case e.io.status.first | 
					
						
							| 
									
										
										
										
											2014-02-16 22:24:33 -05:00
										 |  |  |     when "401", "403" | 
					
						
							| 
									
										
										
										
											2014-02-16 22:24:33 -05:00
										 |  |  |       raise AuthenticationFailedError.new(e.message) | 
					
						
							| 
									
										
										
										
											2014-02-16 22:24:33 -05:00
										 |  |  |     when "404" | 
					
						
							| 
									
										
										
										
											2014-02-08 20:41:11 -05:00
										 |  |  |       raise HTTPNotFoundError, e.message, e.backtrace | 
					
						
							| 
									
										
										
										
											2013-05-22 19:58:11 -05:00
										 |  |  |     else | 
					
						
							| 
									
										
										
										
											2016-01-28 05:51:25 +01:00
										 |  |  |       error = Utils::JSON.load(e.io.read)["message"] rescue nil | 
					
						
							|  |  |  |       raise Error, [e.message, error].compact.join("\n"), e.backtrace | 
					
						
							| 
									
										
										
										
											2013-05-14 10:42:46 -04:00
										 |  |  |     end | 
					
						
							| 
									
										
										
										
											2013-05-07 14:07:25 -04:00
										 |  |  |   end | 
					
						
							| 
									
										
										
										
											2013-06-22 22:46:39 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-08-03 13:09:07 +01:00
										 |  |  |   def issues_matching(query, qualifiers = {}) | 
					
						
							| 
									
										
										
										
											2014-02-08 20:41:11 -05:00
										 |  |  |     uri = ISSUES_URI.dup | 
					
						
							| 
									
										
										
										
											2014-02-13 17:39:53 -05:00
										 |  |  |     uri.query = build_query_string(query, qualifiers) | 
					
						
							| 
									
										
										
										
											2014-02-08 20:41:11 -05:00
										 |  |  |     open(uri) { |json| json["items"] } | 
					
						
							| 
									
										
										
										
											2013-06-22 22:46:39 -05:00
										 |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-07-08 14:22:44 +01:00
										 |  |  |   def repository(user, repo) | 
					
						
							|  |  |  |     open(URI.parse("https://api.github.com/repos/#{user}/#{repo}")) { |j| j } | 
					
						
							|  |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-13 17:39:53 -05:00
										 |  |  |   def build_query_string(query, qualifiers) | 
					
						
							|  |  |  |     s = "q=#{uri_escape(query)}+" | 
					
						
							|  |  |  |     s << build_search_qualifier_string(qualifiers) | 
					
						
							|  |  |  |     s << "&per_page=100" | 
					
						
							|  |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   def build_search_qualifier_string(qualifiers) | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2016-04-04 02:00:21 +08:00
										 |  |  |       :repo => "Homebrew/homebrew-core", | 
					
						
							| 
									
										
										
										
											2015-08-03 13:09:07 +01:00
										 |  |  |       :in => "title" | 
					
						
							|  |  |  |     }.update(qualifiers).map do |qualifier, value| | 
					
						
							| 
									
										
										
										
											2014-02-13 17:39:53 -05:00
										 |  |  |       "#{qualifier}:#{value}" | 
					
						
							| 
									
										
										
										
											2015-08-03 13:09:07 +01:00
										 |  |  |     end.join("+") | 
					
						
							| 
									
										
										
										
											2014-02-13 17:39:53 -05:00
										 |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-01-10 17:32:15 -06:00
										 |  |  |   def uri_escape(query) | 
					
						
							|  |  |  |     if URI.respond_to?(:encode_www_form_component) | 
					
						
							|  |  |  |       URI.encode_www_form_component(query) | 
					
						
							|  |  |  |     else | 
					
						
							|  |  |  |       require "erb" | 
					
						
							|  |  |  |       ERB::Util.url_encode(query) | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-04 02:00:21 +08:00
										 |  |  |   def issues_for_formula(name, options = {}) | 
					
						
							|  |  |  |     tap = options[:tap] || CoreTap.instance | 
					
						
							|  |  |  |     issues_matching(name, :state => "open", :repo => "#{tap.user}/homebrew-#{tap.repo}") | 
					
						
							| 
									
										
										
										
											2010-09-11 20:22:54 +01:00
										 |  |  |   end | 
					
						
							| 
									
										
										
										
											2012-01-11 20:49:08 -06:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-13 23:14:30 -05:00
										 |  |  |   def print_pull_requests_matching(query) | 
					
						
							| 
									
										
										
										
											2015-08-03 13:09:07 +01:00
										 |  |  |     return [] if ENV["HOMEBREW_NO_GITHUB_API"] | 
					
						
							| 
									
										
										
										
											2015-07-17 11:31:54 -07:00
										 |  |  |     ohai "Searching pull requests..." | 
					
						
							| 
									
										
										
										
											2013-10-22 16:18:31 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-13 17:39:53 -05:00
										 |  |  |     open_or_closed_prs = issues_matching(query, :type => "pr") | 
					
						
							| 
									
										
										
										
											2014-02-08 20:41:11 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-08-03 13:09:07 +01:00
										 |  |  |     open_prs = open_or_closed_prs.select { |i| i["state"] == "open" } | 
					
						
							| 
									
										
										
										
											2014-01-20 17:46:33 -08:00
										 |  |  |     if open_prs.any? | 
					
						
							|  |  |  |       puts "Open pull requests:" | 
					
						
							|  |  |  |       prs = open_prs | 
					
						
							|  |  |  |     elsif open_or_closed_prs.any? | 
					
						
							|  |  |  |       puts "Closed pull requests:" | 
					
						
							|  |  |  |       prs = open_or_closed_prs | 
					
						
							|  |  |  |     else | 
					
						
							|  |  |  |       return | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-13 23:14:30 -05:00
										 |  |  |     prs.each { |i| puts "#{i["title"]} (#{i["html_url"]})" } | 
					
						
							| 
									
										
										
										
											2012-01-11 20:49:08 -06:00
										 |  |  |   end | 
					
						
							| 
									
										
										
										
											2014-02-08 20:41:11 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |   def private_repo?(user, repo) | 
					
						
							|  |  |  |     uri = URI.parse("https://api.github.com/repos/#{user}/#{repo}") | 
					
						
							|  |  |  |     open(uri) { |json| json["private"] } | 
					
						
							|  |  |  |   end | 
					
						
							| 
									
										
										
										
											2010-09-11 20:22:54 +01:00
										 |  |  | end | 
					
						
							| 
									
										
										
										
											2015-11-17 16:12:31 +05:30
										 |  |  | 
 | 
					
						
							|  |  |  | def disk_usage_readable(size_in_bytes) | 
					
						
							| 
									
										
										
										
											2015-12-30 16:56:05 +08:00
										 |  |  |   if size_in_bytes >= 1_073_741_824
 | 
					
						
							|  |  |  |     size = size_in_bytes.to_f / 1_073_741_824
 | 
					
						
							|  |  |  |     unit = "G" | 
					
						
							|  |  |  |   elsif size_in_bytes >= 1_048_576
 | 
					
						
							|  |  |  |     size = size_in_bytes.to_f / 1_048_576
 | 
					
						
							|  |  |  |     unit = "M" | 
					
						
							|  |  |  |   elsif size_in_bytes >= 1_024
 | 
					
						
							|  |  |  |     size = size_in_bytes.to_f / 1_024
 | 
					
						
							|  |  |  |     unit = "K" | 
					
						
							| 
									
										
										
										
											2015-11-17 16:12:31 +05:30
										 |  |  |   else | 
					
						
							| 
									
										
										
										
											2015-12-30 16:56:05 +08:00
										 |  |  |     size = size_in_bytes | 
					
						
							|  |  |  |     unit = "B" | 
					
						
							| 
									
										
										
										
											2015-11-17 16:12:31 +05:30
										 |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-30 16:56:05 +08:00
										 |  |  |   # avoid trailing zero after decimal point | 
					
						
							|  |  |  |   if (size * 10).to_i % 10 == 0
 | 
					
						
							|  |  |  |     "#{size.to_i}#{unit}" | 
					
						
							| 
									
										
										
										
											2015-11-17 16:12:31 +05:30
										 |  |  |   else | 
					
						
							| 
									
										
										
										
											2015-12-30 16:56:05 +08:00
										 |  |  |     "#{"%.1f" % size}#{unit}" | 
					
						
							| 
									
										
										
										
											2015-11-17 16:12:31 +05:30
										 |  |  |   end | 
					
						
							|  |  |  | end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def number_readable(number) | 
					
						
							|  |  |  |   numstr = number.to_i.to_s | 
					
						
							|  |  |  |   (numstr.size - 3).step(1, -3) { |i| numstr.insert(i, ",") } | 
					
						
							|  |  |  |   numstr | 
					
						
							|  |  |  | end |