From 7eec6a3a255d7d7ca0c29814345ee9358f6fd300 Mon Sep 17 00:00:00 2001 From: David Broder-Rodgers Date: Thu, 8 Dec 2016 21:41:24 +0000 Subject: Updated resource auditing to detect invalid mirrors when using --online --- Library/Homebrew/dev-cmd/audit.rb | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'Library/Homebrew/dev-cmd') diff --git a/Library/Homebrew/dev-cmd/audit.rb b/Library/Homebrew/dev-cmd/audit.rb index 5ed363f7c..3a4429c86 100644 --- a/Library/Homebrew/dev-cmd/audit.rb +++ b/Library/Homebrew/dev-cmd/audit.rb @@ -1490,6 +1490,11 @@ class ResourceAuditor return unless @online urls.each do |url| + begin + nostdout { curl "--connect-timeout", "15", "-o", "/dev/null", "-r", "0-0", url } + rescue ErrorDuringExecution + problem "The mirror #{u} is not reachable (curl exit code #{$?.exitstatus})" + end check_insecure_mirror(url) if url.start_with? "http:" end end -- cgit v1.2.3 From ea440ca3284138ebe3be26d5763f8c6af93749b1 Mon Sep 17 00:00:00 2001 From: David Broder-Rodgers Date: Sat, 10 Dec 2016 11:10:29 +0000 Subject: Markups to online mirror auditing --- Library/Homebrew/dev-cmd/audit.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'Library/Homebrew/dev-cmd') diff --git a/Library/Homebrew/dev-cmd/audit.rb b/Library/Homebrew/dev-cmd/audit.rb index 3a4429c86..db7973eb3 100644 --- a/Library/Homebrew/dev-cmd/audit.rb +++ b/Library/Homebrew/dev-cmd/audit.rb @@ -1491,9 +1491,9 @@ class ResourceAuditor return unless @online urls.each do |url| begin - nostdout { curl "--connect-timeout", "15", "-o", "/dev/null", "-r", "0-0", url } + nostdout { curl "--connect-timeout", "15", "--output", "/dev/null", "--range", "0-0", url } rescue ErrorDuringExecution - problem "The mirror #{u} is not reachable (curl exit code #{$?.exitstatus})" + problem "The mirror #{url} is not reachable (curl exit code #{$?.exitstatus})" end check_insecure_mirror(url) if url.start_with? "http:" end -- cgit v1.2.3 From ed9f775b778bad961a9e2fb178fce3a7af201e75 Mon Sep 17 00:00:00 2001 From: David Broder-Rodgers Date: Sat, 10 Dec 2016 14:20:47 +0000 Subject: Added support for returning HTTP status codes and for git and svn URLs --- Library/Homebrew/dev-cmd/audit.rb | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) (limited to 'Library/Homebrew/dev-cmd') diff --git a/Library/Homebrew/dev-cmd/audit.rb b/Library/Homebrew/dev-cmd/audit.rb index db7973eb3..839d1c429 100644 --- a/Library/Homebrew/dev-cmd/audit.rb +++ b/Library/Homebrew/dev-cmd/audit.rb @@ -1490,10 +1490,20 @@ class ResourceAuditor return unless @online urls.each do |url| - begin - nostdout { curl "--connect-timeout", "15", "--output", "/dev/null", "--range", "0-0", url } - rescue ErrorDuringExecution - problem "The mirror #{url} is not reachable (curl exit code #{$?.exitstatus})" + if url.start_with? "http", "ftp" + status_code, _, _ = curl_output "--connect-timeout", "15", "--output", "/dev/null", "--range", "0-0", \ + "--write-out", "%{http_code}", url + unless status_code.start_with? "20" + problem "The mirror #{url} is not reachable (HTTP status code #{status_code})" + end + elsif url.start_with? "git" + unless Utils.git_remote_exists url + problem "The mirror #{url} is not a valid git URL" + end + elsif url.start_with? "svn" + unless Utils.svn_remote_exists url + problem "The mirror #{url} is not a valid svn URL" + end end check_insecure_mirror(url) if url.start_with? "http:" end -- cgit v1.2.3 From 3e7dfe4aaba2aa41d01f6fd06a9dd40298d118d3 Mon Sep 17 00:00:00 2001 From: David Broder-Rodgers Date: Sun, 11 Dec 2016 21:36:58 +0000 Subject: Updated mirror audit problem message --- Library/Homebrew/dev-cmd/audit.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'Library/Homebrew/dev-cmd') diff --git a/Library/Homebrew/dev-cmd/audit.rb b/Library/Homebrew/dev-cmd/audit.rb index 839d1c429..460302fb7 100644 --- a/Library/Homebrew/dev-cmd/audit.rb +++ b/Library/Homebrew/dev-cmd/audit.rb @@ -1494,15 +1494,15 @@ class ResourceAuditor status_code, _, _ = curl_output "--connect-timeout", "15", "--output", "/dev/null", "--range", "0-0", \ "--write-out", "%{http_code}", url unless status_code.start_with? "20" - problem "The mirror #{url} is not reachable (HTTP status code #{status_code})" + problem "The URL #{url} is not reachable (HTTP status code #{status_code})" end elsif url.start_with? "git" unless Utils.git_remote_exists url - problem "The mirror #{url} is not a valid git URL" + problem "The URL #{url} is not a valid git URL" end elsif url.start_with? "svn" unless Utils.svn_remote_exists url - problem "The mirror #{url} is not a valid svn URL" + problem "The URL #{url} is not a valid svn URL" end end check_insecure_mirror(url) if url.start_with? "http:" -- cgit v1.2.3 From d3ac333197de4d2fcb560bf95e5cd4df81871bbd Mon Sep 17 00:00:00 2001 From: David Broder-Rodgers Date: Mon, 12 Dec 2016 21:18:22 +0000 Subject: Rubocop styling fixes --- Library/Homebrew/dev-cmd/audit.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'Library/Homebrew/dev-cmd') diff --git a/Library/Homebrew/dev-cmd/audit.rb b/Library/Homebrew/dev-cmd/audit.rb index 460302fb7..b323297e4 100644 --- a/Library/Homebrew/dev-cmd/audit.rb +++ b/Library/Homebrew/dev-cmd/audit.rb @@ -1491,8 +1491,8 @@ class ResourceAuditor return unless @online urls.each do |url| if url.start_with? "http", "ftp" - status_code, _, _ = curl_output "--connect-timeout", "15", "--output", "/dev/null", "--range", "0-0", \ - "--write-out", "%{http_code}", url + status_code, = curl_output "--connect-timeout", "15", "--output", "/dev/null", "--range", "0-0", \ + "--write-out", "%{http_code}", url unless status_code.start_with? "20" problem "The URL #{url} is not reachable (HTTP status code #{status_code})" end -- cgit v1.2.3 From a731f4e17cc45bed5ed0f1121326551c558ce583 Mon Sep 17 00:00:00 2001 From: David Broder-Rodgers Date: Tue, 10 Jan 2017 20:13:14 +0000 Subject: Updated HTTP mirror check to use new url_status_code method --- Library/Homebrew/dev-cmd/audit.rb | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) (limited to 'Library/Homebrew/dev-cmd') diff --git a/Library/Homebrew/dev-cmd/audit.rb b/Library/Homebrew/dev-cmd/audit.rb index b323297e4..f187f17f5 100644 --- a/Library/Homebrew/dev-cmd/audit.rb +++ b/Library/Homebrew/dev-cmd/audit.rb @@ -174,7 +174,7 @@ class FormulaAuditor @specs = %w[stable devel head].map { |s| formula.send(s) }.compact end - def url_status_code(url, range: false) + def self.url_status_code(url, range: false) # The system Curl is too old and unreliable with HTTPS homepages on # Yosemite and below. return "200" unless DevelopmentTools.curl_handles_most_https_homepages? @@ -195,7 +195,7 @@ class FormulaAuditor user_agent: user_agent, ) status_code = Open3.popen3(*args) { |_, stdout, _, _| stdout.read } - break if status_code.start_with? "20" + break if status_code.start_with? "2" end status_code end @@ -619,7 +619,7 @@ class FormulaAuditor return unless @online - status_code = url_status_code(homepage) + status_code = FormulaAuditor.url_status_code(homepage, user_agent: :browser) return if status_code.start_with? "20" problem "The homepage #{homepage} is not reachable (HTTP status code #{status_code})" end @@ -1491,9 +1491,8 @@ class ResourceAuditor return unless @online urls.each do |url| if url.start_with? "http", "ftp" - status_code, = curl_output "--connect-timeout", "15", "--output", "/dev/null", "--range", "0-0", \ - "--write-out", "%{http_code}", url - unless status_code.start_with? "20" + status_code = FormulaAuditor.url_status_code url + unless status_code.start_with? "2" problem "The URL #{url} is not reachable (HTTP status code #{status_code})" end elsif url.start_with? "git" -- cgit v1.2.3 From 81b3368c9cba0f9db93af5732d8f10e75d00cdf9 Mon Sep 17 00:00:00 2001 From: David Broder-Rodgers Date: Tue, 24 Jan 2017 20:35:07 +0000 Subject: Added better check for HTTP git URLs --- Library/Homebrew/dev-cmd/audit.rb | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'Library/Homebrew/dev-cmd') diff --git a/Library/Homebrew/dev-cmd/audit.rb b/Library/Homebrew/dev-cmd/audit.rb index f187f17f5..c685dacae 100644 --- a/Library/Homebrew/dev-cmd/audit.rb +++ b/Library/Homebrew/dev-cmd/audit.rb @@ -1490,15 +1490,15 @@ class ResourceAuditor return unless @online urls.each do |url| - if url.start_with? "http", "ftp" + if url.start_with?("git") || url.end_with?(".git") + unless Utils.git_remote_exists url + problem "The URL #{url} is not a valid git URL" + end + elsif url.start_with? "http", "ftp" status_code = FormulaAuditor.url_status_code url unless status_code.start_with? "2" problem "The URL #{url} is not reachable (HTTP status code #{status_code})" end - elsif url.start_with? "git" - unless Utils.git_remote_exists url - problem "The URL #{url} is not a valid git URL" - end elsif url.start_with? "svn" unless Utils.svn_remote_exists url problem "The URL #{url} is not a valid svn URL" -- cgit v1.2.3 From a699d284d038907f884bb48f928f2e75ebadfc11 Mon Sep 17 00:00:00 2001 From: David Broder-Rodgers Date: Tue, 24 Jan 2017 23:11:50 +0000 Subject: Use DownloadStrategyDetector to classify mirror URLs --- Library/Homebrew/dev-cmd/audit.rb | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) (limited to 'Library/Homebrew/dev-cmd') diff --git a/Library/Homebrew/dev-cmd/audit.rb b/Library/Homebrew/dev-cmd/audit.rb index c685dacae..a7c9de576 100644 --- a/Library/Homebrew/dev-cmd/audit.rb +++ b/Library/Homebrew/dev-cmd/audit.rb @@ -1490,16 +1490,18 @@ class ResourceAuditor return unless @online urls.each do |url| - if url.start_with?("git") || url.end_with?(".git") - unless Utils.git_remote_exists url - problem "The URL #{url} is not a valid git URL" - end - elsif url.start_with? "http", "ftp" + strategy = DownloadStrategyDetector.detect(url) + if strategy <= CurlDownloadStrategy + problem url status_code = FormulaAuditor.url_status_code url unless status_code.start_with? "2" problem "The URL #{url} is not reachable (HTTP status code #{status_code})" end - elsif url.start_with? "svn" + elsif strategy <= GitDownloadStrategy + unless Utils.git_remote_exists url + problem "The URL #{url} is not a valid git URL" + end + elsif strategy <= SubversionDownloadStrategy unless Utils.svn_remote_exists url problem "The URL #{url} is not a valid svn URL" end -- cgit v1.2.3 From 12501b4046339b6becd42e37730873babeaa9dc2 Mon Sep 17 00:00:00 2001 From: David Broder-Rodgers Date: Mon, 30 Jan 2017 18:30:57 +0000 Subject: Prevent mirror curl for file:/// URL --- Library/Homebrew/dev-cmd/audit.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Library/Homebrew/dev-cmd') diff --git a/Library/Homebrew/dev-cmd/audit.rb b/Library/Homebrew/dev-cmd/audit.rb index a7c9de576..180783f79 100644 --- a/Library/Homebrew/dev-cmd/audit.rb +++ b/Library/Homebrew/dev-cmd/audit.rb @@ -1491,7 +1491,7 @@ class ResourceAuditor return unless @online urls.each do |url| strategy = DownloadStrategyDetector.detect(url) - if strategy <= CurlDownloadStrategy + if strategy <= CurlDownloadStrategy && !url.start_with?("file") problem url status_code = FormulaAuditor.url_status_code url unless status_code.start_with? "2" -- cgit v1.2.3 From 55bc2a30195db915a60c862bf1c3d4ba6cd3cd4a Mon Sep 17 00:00:00 2001 From: David Broder-Rodgers Date: Mon, 20 Feb 2017 19:00:27 +0000 Subject: Merged 404 and security mirror auditing logic --- Library/Homebrew/dev-cmd/audit.rb | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) (limited to 'Library/Homebrew/dev-cmd') diff --git a/Library/Homebrew/dev-cmd/audit.rb b/Library/Homebrew/dev-cmd/audit.rb index 180783f79..6e454f4d2 100644 --- a/Library/Homebrew/dev-cmd/audit.rb +++ b/Library/Homebrew/dev-cmd/audit.rb @@ -174,7 +174,7 @@ class FormulaAuditor @specs = %w[stable devel head].map { |s| formula.send(s) }.compact end - def self.url_status_code(url, range: false) + def url_status_code(url, range: false) # The system Curl is too old and unreliable with HTTPS homepages on # Yosemite and below. return "200" unless DevelopmentTools.curl_handles_most_https_homepages? @@ -619,8 +619,8 @@ class FormulaAuditor return unless @online - status_code = FormulaAuditor.url_status_code(homepage, user_agent: :browser) - return if status_code.start_with? "20" + status_code = url_status_code(homepage) + return if status_code.start_with? "2" problem "The homepage #{homepage} is not reachable (HTTP status code #{status_code})" end @@ -1492,11 +1492,7 @@ class ResourceAuditor urls.each do |url| strategy = DownloadStrategyDetector.detect(url) if strategy <= CurlDownloadStrategy && !url.start_with?("file") - problem url - status_code = FormulaAuditor.url_status_code url - unless status_code.start_with? "2" - problem "The URL #{url} is not reachable (HTTP status code #{status_code})" - end + check_http_mirror url elsif strategy <= GitDownloadStrategy unless Utils.git_remote_exists url problem "The URL #{url} is not a valid git URL" @@ -1506,12 +1502,20 @@ class ResourceAuditor problem "The URL #{url} is not a valid svn URL" end end - check_insecure_mirror(url) if url.start_with? "http:" end end - def check_insecure_mirror(url) + def check_http_mirror(url) details = get_content_details(url) + + if details[:status].nil? + problem "The URL #{url} is not reachable" + elsif !details[:status].start_with? "2" + problem "The URL #{url} is not reachable (HTTP status code #{details[:status]})" + end + + return unless url.start_with? "http:" + secure_url = url.sub "http", "https" secure_details = get_content_details(secure_url) -- cgit v1.2.3 From 125a6eee2165039d3b7329543d2e33e321c267d2 Mon Sep 17 00:00:00 2001 From: Mike McQuaid Date: Mon, 20 Feb 2017 22:48:03 +0000 Subject: audit: fix `brew style`. --- Library/Homebrew/dev-cmd/audit.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Library/Homebrew/dev-cmd') diff --git a/Library/Homebrew/dev-cmd/audit.rb b/Library/Homebrew/dev-cmd/audit.rb index 6e454f4d2..b63d39905 100644 --- a/Library/Homebrew/dev-cmd/audit.rb +++ b/Library/Homebrew/dev-cmd/audit.rb @@ -1506,7 +1506,7 @@ class ResourceAuditor end def check_http_mirror(url) - details = get_content_details(url) + details = get_content_details(url) if details[:status].nil? problem "The URL #{url} is not reachable" -- cgit v1.2.3 From 168a96d91912c9adc19d8729d0cb6ac54aef7590 Mon Sep 17 00:00:00 2001 From: Markus Reiter Date: Tue, 21 Feb 2017 21:55:11 +0100 Subject: Exclude specs with `:needs_macos` tag when not on macOS. --- Library/Homebrew/dev-cmd/tests.rb | 2 ++ 1 file changed, 2 insertions(+) (limited to 'Library/Homebrew/dev-cmd') diff --git a/Library/Homebrew/dev-cmd/tests.rb b/Library/Homebrew/dev-cmd/tests.rb index 244fbe027..246b5fa46 100644 --- a/Library/Homebrew/dev-cmd/tests.rb +++ b/Library/Homebrew/dev-cmd/tests.rb @@ -84,6 +84,8 @@ module Homebrew "--format", "ParallelTests::RSpec::RuntimeLogger", "--out", "tmp/parallel_runtime_rspec.log" ] + spec_args << "--tag" << "~needs_macos" unless OS.mac? + run_tests "parallel_rspec", spec_files, spec_args if (fs_leak_log = HOMEBREW_LIBRARY_PATH/"tmp/fs_leak.log").file? -- cgit v1.2.3 From 5390897883f11fe2257e57bd5547cb1bbb144fb0 Mon Sep 17 00:00:00 2001 From: Mike McQuaid Date: Thu, 23 Feb 2017 09:09:33 +0000 Subject: audit: refactor http content checks. --- Library/Homebrew/dev-cmd/audit.rb | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) (limited to 'Library/Homebrew/dev-cmd') diff --git a/Library/Homebrew/dev-cmd/audit.rb b/Library/Homebrew/dev-cmd/audit.rb index b63d39905..aa9dd775a 100644 --- a/Library/Homebrew/dev-cmd/audit.rb +++ b/Library/Homebrew/dev-cmd/audit.rb @@ -1492,7 +1492,7 @@ class ResourceAuditor urls.each do |url| strategy = DownloadStrategyDetector.detect(url) if strategy <= CurlDownloadStrategy && !url.start_with?("file") - check_http_mirror url + check_http_content url elsif strategy <= GitDownloadStrategy unless Utils.git_remote_exists url problem "The URL #{url} is not a valid git URL" @@ -1505,7 +1505,7 @@ class ResourceAuditor end end - def check_http_mirror(url) + def check_http_content(url) details = get_content_details(url) if details[:status].nil? @@ -1519,10 +1519,16 @@ class ResourceAuditor secure_url = url.sub "http", "https" secure_details = get_content_details(secure_url) - return if !details[:status].start_with?("2") || !secure_details[:status].start_with?("2") + if !details[:status].to_s.start_with?("2") || + !secure_details[:status].to_s.start_with?("2") + return + end - etag_match = details[:etag] && details[:etag] == secure_details[:etag] - content_length_match = details[:content_length] && details[:content_length] == secure_details[:content_length] + etag_match = details[:etag] && + details[:etag] == secure_details[:etag] + content_length_match = + details[:content_length] && + details[:content_length] == secure_details[:content_length] file_match = details[:file_hash] == secure_details[:file_hash] return if !etag_match && !content_length_match && !file_match -- cgit v1.2.3 From 5e9057500419d1a2b41efe784e9f12ae232e7f6e Mon Sep 17 00:00:00 2001 From: Mike McQuaid Date: Thu, 23 Feb 2017 09:09:58 +0000 Subject: audit: handle redirects in get_content_details. --- Library/Homebrew/dev-cmd/audit.rb | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'Library/Homebrew/dev-cmd') diff --git a/Library/Homebrew/dev-cmd/audit.rb b/Library/Homebrew/dev-cmd/audit.rb index aa9dd775a..493f1eb09 100644 --- a/Library/Homebrew/dev-cmd/audit.rb +++ b/Library/Homebrew/dev-cmd/audit.rb @@ -1542,12 +1542,16 @@ class ResourceAuditor def get_content_details(url) out = {} output, = curl_output "--connect-timeout", "15", "--include", url - split = output.partition("\r\n\r\n") - headers = split.first - out[:status] = headers[%r{HTTP\/.* (\d+)}, 1] + status_code = :unknown + while status_code == :unknown || status_code.to_s.start_with?("3") + headers, _, output = output.partition("\r\n\r\n") + status_code = headers[%r{HTTP\/.* (\d+)}, 1] + end + + out[:status] = status_code out[:etag] = headers[%r{ETag: ([wW]\/)?"(([^"]|\\")*)"}, 2] out[:content_length] = headers[/Content-Length: (\d+)/, 1] - out[:file_hash] = Digest::SHA256.digest split.last + out[:file_hash] = Digest::SHA256.digest output out end end -- cgit v1.2.3 From 96a8f8f1727e3d6445d42570d287f4f7013d5ea1 Mon Sep 17 00:00:00 2001 From: Mike McQuaid Date: Thu, 23 Feb 2017 09:14:54 +0000 Subject: audit: check for version aliases. Current version aliases should be provided for versioned formulae so people can `brew install foo@1.2` to provide pin-like behaviour. --- Library/Homebrew/dev-cmd/audit.rb | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) (limited to 'Library/Homebrew/dev-cmd') diff --git a/Library/Homebrew/dev-cmd/audit.rb b/Library/Homebrew/dev-cmd/audit.rb index 9ffef0f99..9da5d28b4 100644 --- a/Library/Homebrew/dev-cmd/audit.rb +++ b/Library/Homebrew/dev-cmd/audit.rb @@ -295,6 +295,27 @@ class FormulaAuditor problem "File should end with a newline" unless text.trailing_newline? + versioned_formulae = Dir[formula.path.to_s.gsub(/\.rb$/, "@*.rb")] + needs_versioned_alias = !versioned_formulae.empty? && + formula.tap && + formula.aliases.grep(/.@\d/).empty? + if needs_versioned_alias + _, last_alias_version = File.basename(versioned_formulae.sort.reverse.first) + .gsub(/\.rb$/, "") + .split("@") + major, minor, = formula.version.to_s.split(".") + alias_name = if last_alias_version.split(".").length == 1 + "#{formula.name}@#{major}" + else + "#{formula.name}@#{major}.#{minor}" + end + problem <<-EOS.undent + Formula has other versions so create an alias: + cd #{formula.tap.alias_dir} + ln -s #{formula.path.to_s.gsub(formula.tap.path, "..")} #{alias_name} + EOS + end + return unless @strict present = audit_components @@ -410,7 +431,8 @@ class FormulaAuditor problem "Dependency '#{dep.name}' was renamed; use new name '#{dep_f.name}'." end - if @@aliases.include?(dep.name) + if @@aliases.include?(dep.name) && + (core_formula? || !dep_f.versioned_formula?) problem "Dependency '#{dep.name}' is an alias; use the canonical name '#{dep.to_formula.full_name}'." end -- cgit v1.2.3 From 9fa014710d22e30c0be05bddc78e073373def5bd Mon Sep 17 00:00:00 2001 From: Mike McQuaid Date: Thu, 23 Feb 2017 10:15:06 +0000 Subject: audit: further refactor http content checks. Check homepages and don’t check mirrors unless `—strict`. --- Library/Homebrew/dev-cmd/audit.rb | 144 ++++++++++++++++++-------------------- 1 file changed, 69 insertions(+), 75 deletions(-) (limited to 'Library/Homebrew/dev-cmd') diff --git a/Library/Homebrew/dev-cmd/audit.rb b/Library/Homebrew/dev-cmd/audit.rb index 493f1eb09..65b109f3b 100644 --- a/Library/Homebrew/dev-cmd/audit.rb +++ b/Library/Homebrew/dev-cmd/audit.rb @@ -174,30 +174,62 @@ class FormulaAuditor @specs = %w[stable devel head].map { |s| formula.send(s) }.compact end - def url_status_code(url, range: false) - # The system Curl is too old and unreliable with HTTPS homepages on - # Yosemite and below. - return "200" unless DevelopmentTools.curl_handles_most_https_homepages? + def self.check_http_content(url, user_agents: [:default]) + details = nil + user_agent = nil + user_agents.each do |ua| + details = http_content_headers_and_checksum(url, user_agent: ua) + user_agent = ua + break if details[:status].to_s.start_with?("2") + end - extra_args = [ - "--connect-timeout", "15", - "--output", "/dev/null", - "--write-out", "%{http_code}" - ] - extra_args << "--range" << "0-0" if range - extra_args << url - - status_code = nil - [:browser, :default].each do |user_agent| - args = curl_args( - extra_args: extra_args, - show_output: true, - user_agent: user_agent, - ) - status_code = Open3.popen3(*args) { |_, stdout, _, _| stdout.read } - break if status_code.start_with? "2" - end - status_code + return "The URL #{url} is not reachable" unless details[:status] + unless details[:status].start_with? "2" + return "The URL #{url} is not reachable (HTTP status code #{details[:status]})" + end + + return unless url.start_with? "http:" + + secure_url = url.sub "http", "https" + secure_details = + http_content_headers_and_checksum(secure_url, user_agent: user_agent) + + if !details[:status].to_s.start_with?("2") || + !secure_details[:status].to_s.start_with?("2") + return + end + + etag_match = details[:etag] && + details[:etag] == secure_details[:etag] + content_length_match = + details[:content_length] && + details[:content_length] == secure_details[:content_length] + file_match = details[:file_hash] == secure_details[:file_hash] + + return if !etag_match && !content_length_match && !file_match + "The URL #{url} could use HTTPS rather than HTTP" + end + + def self.http_content_headers_and_checksum(url, user_agent: :default) + args = curl_args( + extra_args: ["--connect-timeout", "15", "--include", url], + show_output: true, + user_agent: user_agent, + ) + output = Open3.popen3(*args) { |_, stdout, _, _| stdout.read } + + status_code = :unknown + while status_code == :unknown || status_code.to_s.start_with?("3") + headers, _, output = output.partition("\r\n\r\n") + status_code = headers[%r{HTTP\/.* (\d+)}, 1] + end + + { + status: status_code, + etag: headers[%r{ETag: ([wW]\/)?"(([^"]|\\")*)"}, 2], + content_length: headers[/Content-Length: (\d+)/, 1], + file_hash: Digest::SHA256.digest(output), + } end def audit_style @@ -619,9 +651,13 @@ class FormulaAuditor return unless @online - status_code = url_status_code(homepage) - return if status_code.start_with? "2" - problem "The homepage #{homepage} is not reachable (HTTP status code #{status_code})" + # The system Curl is too old and unreliable with HTTPS homepages on + # Yosemite and below. + return unless DevelopmentTools.curl_handles_most_https_homepages? + if http_content_problem = FormulaAuditor.check_http_content(homepage, + user_agents: [:browser, :default]) + problem http_content_problem + end end def audit_bottle_spec @@ -671,11 +707,11 @@ class FormulaAuditor %w[Stable Devel HEAD].each do |name| next unless spec = formula.send(name.downcase) - ra = ResourceAuditor.new(spec, online: @online).audit + ra = ResourceAuditor.new(spec, online: @online, strict: @strict).audit problems.concat ra.problems.map { |problem| "#{name}: #{problem}" } spec.resources.each_value do |resource| - ra = ResourceAuditor.new(resource, online: @online).audit + ra = ResourceAuditor.new(resource, online: @online, strict: @strict).audit problems.concat ra.problems.map { |problem| "#{name} resource #{resource.name.inspect}: #{problem}" } @@ -1231,6 +1267,7 @@ class ResourceAuditor @using = resource.using @specs = resource.specs @online = options[:online] + @strict = options[:strict] @problems = [] end @@ -1492,7 +1529,10 @@ class ResourceAuditor urls.each do |url| strategy = DownloadStrategyDetector.detect(url) if strategy <= CurlDownloadStrategy && !url.start_with?("file") - check_http_content url + next if !@strict && mirrors.include?(url) + if http_content_problem = FormulaAuditor.check_http_content(url) + problem http_content_problem + end elsif strategy <= GitDownloadStrategy unless Utils.git_remote_exists url problem "The URL #{url} is not a valid git URL" @@ -1505,53 +1545,7 @@ class ResourceAuditor end end - def check_http_content(url) - details = get_content_details(url) - - if details[:status].nil? - problem "The URL #{url} is not reachable" - elsif !details[:status].start_with? "2" - problem "The URL #{url} is not reachable (HTTP status code #{details[:status]})" - end - - return unless url.start_with? "http:" - - secure_url = url.sub "http", "https" - secure_details = get_content_details(secure_url) - - if !details[:status].to_s.start_with?("2") || - !secure_details[:status].to_s.start_with?("2") - return - end - - etag_match = details[:etag] && - details[:etag] == secure_details[:etag] - content_length_match = - details[:content_length] && - details[:content_length] == secure_details[:content_length] - file_match = details[:file_hash] == secure_details[:file_hash] - - return if !etag_match && !content_length_match && !file_match - problem "The URL #{url} could use HTTPS rather than HTTP" - end - def problem(text) @problems << text end - - def get_content_details(url) - out = {} - output, = curl_output "--connect-timeout", "15", "--include", url - status_code = :unknown - while status_code == :unknown || status_code.to_s.start_with?("3") - headers, _, output = output.partition("\r\n\r\n") - status_code = headers[%r{HTTP\/.* (\d+)}, 1] - end - - out[:status] = status_code - out[:etag] = headers[%r{ETag: ([wW]\/)?"(([^"]|\\")*)"}, 2] - out[:content_length] = headers[/Content-Length: (\d+)/, 1] - out[:file_hash] = Digest::SHA256.digest output - out - end end -- cgit v1.2.3 From b984be675ddd07ccbf7151355a22096de47c5c50 Mon Sep 17 00:00:00 2001 From: Mike McQuaid Date: Fri, 24 Feb 2017 08:45:39 +0000 Subject: audit: use using for HTTPS detection. --- Library/Homebrew/dev-cmd/audit.rb | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'Library/Homebrew/dev-cmd') diff --git a/Library/Homebrew/dev-cmd/audit.rb b/Library/Homebrew/dev-cmd/audit.rb index 65b109f3b..cf5bdcdc4 100644 --- a/Library/Homebrew/dev-cmd/audit.rb +++ b/Library/Homebrew/dev-cmd/audit.rb @@ -1527,9 +1527,10 @@ class ResourceAuditor return unless @online urls.each do |url| - strategy = DownloadStrategyDetector.detect(url) + next if !@strict && mirrors.include?(url) + + strategy = DownloadStrategyDetector.detect(url, using) if strategy <= CurlDownloadStrategy && !url.start_with?("file") - next if !@strict && mirrors.include?(url) if http_content_problem = FormulaAuditor.check_http_content(url) problem http_content_problem end -- cgit v1.2.3 From 1284f29561d944e069d201db9043489417b85ff4 Mon Sep 17 00:00:00 2001 From: Mike McQuaid Date: Fri, 24 Feb 2017 08:51:15 +0000 Subject: audit: don't try to HTTP check non-HTTP content. --- Library/Homebrew/dev-cmd/audit.rb | 2 ++ 1 file changed, 2 insertions(+) (limited to 'Library/Homebrew/dev-cmd') diff --git a/Library/Homebrew/dev-cmd/audit.rb b/Library/Homebrew/dev-cmd/audit.rb index cf5bdcdc4..e49f65dd2 100644 --- a/Library/Homebrew/dev-cmd/audit.rb +++ b/Library/Homebrew/dev-cmd/audit.rb @@ -175,6 +175,8 @@ class FormulaAuditor end def self.check_http_content(url, user_agents: [:default]) + return unless url.start_with? "http" + details = nil user_agent = nil user_agents.each do |ua| -- cgit v1.2.3 From 75724c5b5da769faa682803a55b29e2de9bad741 Mon Sep 17 00:00:00 2001 From: ilovezfs Date: Sat, 25 Feb 2017 03:03:37 -0800 Subject: audit: whitelist more unstable versions already in core These were imported from homebrew/games. --- Library/Homebrew/dev-cmd/audit.rb | 3 +++ 1 file changed, 3 insertions(+) (limited to 'Library/Homebrew/dev-cmd') diff --git a/Library/Homebrew/dev-cmd/audit.rb b/Library/Homebrew/dev-cmd/audit.rb index e49f65dd2..ab7abf1e6 100644 --- a/Library/Homebrew/dev-cmd/audit.rb +++ b/Library/Homebrew/dev-cmd/audit.rb @@ -740,6 +740,7 @@ class FormulaAuditor unstable_whitelist = %w[ aalib 1.4rc5 + angolmois 2.0.0alpha2 automysqlbackup 3.0-rc6 aview 1.3.0rc1 distcc 3.2rc1 @@ -747,6 +748,8 @@ class FormulaAuditor ftgl 2.1.3-rc5 hidapi 0.8.0-rc1 libcaca 0.99b19 + nethack4 4.3.0-beta2 + opensyobon 1.0rc2 premake 4.4-beta5 pwnat 0.3-beta pxz 4.999.9 -- cgit v1.2.3 From 6cb56297378cb57ade790c392dacf4a3bf02f7da Mon Sep 17 00:00:00 2001 From: EricFromCanada Date: Sat, 25 Feb 2017 17:27:08 -0500 Subject: Work around man page generator bug for pull.rb To work around ronn's [issue with nested lists](https://github.com/rtomayko/ronn/issues/35), treat each item as a separate paragraph with alternate list markers. --- Library/Homebrew/dev-cmd/pull.rb | 53 +++++++++++++++++++++++----------------- 1 file changed, 31 insertions(+), 22 deletions(-) (limited to 'Library/Homebrew/dev-cmd') diff --git a/Library/Homebrew/dev-cmd/pull.rb b/Library/Homebrew/dev-cmd/pull.rb index c2342d39c..98a62e578 100644 --- a/Library/Homebrew/dev-cmd/pull.rb +++ b/Library/Homebrew/dev-cmd/pull.rb @@ -1,33 +1,42 @@ -#: `pull` [`--bottle`] [`--bump`] [`--clean`] [`--ignore-whitespace`] [`--resolve`] [`--branch-okay`] [`--no-pbcopy`] [`--no-publish`] [] -#: +#: * `pull` [`--bottle`] [`--bump`] [`--clean`] [`--ignore-whitespace`] [`--resolve`] [`--branch-okay`] [`--no-pbcopy`] [`--no-publish`] []: #: Gets a patch from a GitHub commit or pull request and applies it to Homebrew. #: Optionally, installs the formulae changed by the patch. #: #: Each may be one of: -#: * The ID number of a PR (Pull Request) in the homebrew/core GitHub +#: +#: ~ The ID number of a PR (pull request) in the homebrew/core GitHub #: repository -#: * The URL of a PR on GitHub, using either the web page or API URL +#: +#: ~ The URL of a PR on GitHub, using either the web page or API URL #: formats. In this form, the PR may be on Homebrew/brew, #: Homebrew/homebrew-core or any tap. -#: * The URL of a commit on GitHub -#: * A "http://bot.brew.sh/job/..." string specifying a testing job ID #: -#: If `--bottle` was passed, handle bottles, pulling the bottle-update -#: commit and publishing files on Bintray. -#: If `--bump` was passed, for one-formula PRs, automatically reword -#: commit message to our preferred format. -#: If `--clean` was passed, do not rewrite or otherwise modify the -#: commits found in the pulled PR. -#: If `--ignore-whitespace` was passed, silently ignore whitespace -#: discrepancies when applying diffs. -#: If `--resolve` was passed, when a patch fails to apply, leave in -#: progress and allow user to -#: resolve, instead of aborting. -#: If `--branch-okay` was passed, do not warn if pulling to a branch -#: besides master (useful for testing). -#: If `--no-pbcopy` was passed, do not copy anything to the system -# clipboard. -#: If `--no-publish` was passed, do not publish bottles to Bintray. +#: ~ The URL of a commit on GitHub +#: +#: ~ A "http://bot.brew.sh/job/..." string specifying a testing job ID +#: +#: If `--bottle` is passed, handle bottles, pulling the bottle-update +#: commit and publishing files on Bintray. +#: +#: If `--bump` is passed, for one-formula PRs, automatically reword +#: commit message to our preferred format. +#: +#: If `--clean` is passed, do not rewrite or otherwise modify the +#: commits found in the pulled PR. +#: +#: If `--ignore-whitespace` is passed, silently ignore whitespace +#: discrepancies when applying diffs. +#: +#: If `--resolve` is passed, when a patch fails to apply, leave in +#: progress and allow user to resolve, instead of aborting. +#: +#: If `--branch-okay` is passed, do not warn if pulling to a branch +#: besides master (useful for testing). +#: +#: If `--no-pbcopy` is passed, do not copy anything to the system +#: clipboard. +#: +#: If `--no-publish` is passed, do not publish bottles to Bintray. require "net/http" require "net/https" -- cgit v1.2.3 From afc539f86e2be27744838d0db6f85bcfe20fa857 Mon Sep 17 00:00:00 2001 From: EricFromCanada Date: Sat, 25 Feb 2017 17:37:57 -0500 Subject: Update brew's man page formatting and grammar Also update command specifications to match descriptions. --- Library/Homebrew/dev-cmd/boneyard-formula-pr.rb | 2 +- Library/Homebrew/dev-cmd/bottle.rb | 3 +-- Library/Homebrew/dev-cmd/bump-formula-pr.rb | 13 ++++++------- Library/Homebrew/dev-cmd/create.rb | 3 +-- Library/Homebrew/dev-cmd/formula.rb | 2 +- Library/Homebrew/dev-cmd/linkage.rb | 2 +- Library/Homebrew/dev-cmd/mirror.rb | 2 +- Library/Homebrew/dev-cmd/release-notes.rb | 6 +++--- Library/Homebrew/dev-cmd/tests.rb | 2 +- Library/Homebrew/dev-cmd/update-test.rb | 8 ++++---- 10 files changed, 20 insertions(+), 23 deletions(-) (limited to 'Library/Homebrew/dev-cmd') diff --git a/Library/Homebrew/dev-cmd/boneyard-formula-pr.rb b/Library/Homebrew/dev-cmd/boneyard-formula-pr.rb index 3066d2ee6..7531ef9cf 100644 --- a/Library/Homebrew/dev-cmd/boneyard-formula-pr.rb +++ b/Library/Homebrew/dev-cmd/boneyard-formula-pr.rb @@ -1,5 +1,5 @@ #: @hide_from_man_page -#: * `boneyard-formula-pr` [`--dry-run`] [`--local`] [`--reason=`] : +#: * `boneyard-formula-pr` [`--dry-run`] [`--local`] [`--reason=`] : #: Creates a pull request to boneyard a formula. #: #: If `--dry-run` is passed, print what would be done rather than doing it. diff --git a/Library/Homebrew/dev-cmd/bottle.rb b/Library/Homebrew/dev-cmd/bottle.rb index 7367e5c37..91bdcba93 100644 --- a/Library/Homebrew/dev-cmd/bottle.rb +++ b/Library/Homebrew/dev-cmd/bottle.rb @@ -1,6 +1,5 @@ -#: * `bottle` [`--verbose`] [`--no-rebuild`] [`--keep-old`] [`--skip-relocation`] [`--root-url=`] [`--force-core-tap`]: +#: * `bottle` [`--verbose`] [`--no-rebuild`] [`--keep-old`] [`--skip-relocation`] [`--root-url=`] [`--force-core-tap`]: #: * `bottle` `--merge` [`--no-commit`] [`--keep-old`] [`--write`]: -#: #: Generate a bottle (binary package) from a formula installed with #: `--build-bottle`. diff --git a/Library/Homebrew/dev-cmd/bump-formula-pr.rb b/Library/Homebrew/dev-cmd/bump-formula-pr.rb index bfe9c7776..6c7b7d5b5 100644 --- a/Library/Homebrew/dev-cmd/bump-formula-pr.rb +++ b/Library/Homebrew/dev-cmd/bump-formula-pr.rb @@ -1,8 +1,7 @@ -#: * `bump-formula-pr` [`--devel`] [`--dry-run`] [`--audit`|`--strict`] [`--message=`] `--url=` `--sha256=` : -#: * `bump-formula-pr` [`--devel`] [`--dry-run`] [`--audit`|`--strict`] [`--message=`] `--tag=` `--revision=` : -#: Creates a pull request to update the formula with a new url or a new tag. +#: * `bump-formula-pr` [`--devel`] [`--dry-run` [`--write`]] [`--audit`|`--strict`] [`--mirror=`] [`--version=`] [`--message=`] (`--url=` `--sha256=`|`--tag=` `--revision=`) : +#: Creates a pull request to update the formula with a new URL or a new tag. #: -#: If a is specified, the checksum of the new download must +#: If a is specified, the checksum of the new download must #: also be specified. A best effort to determine the and #: name will be made if either or both values are not supplied by the user. #: @@ -21,17 +20,17 @@ #: #: If `--strict` is passed, run `brew audit --strict` before opening the PR. #: -#: If `--mirror=` is passed, use the value as a mirror url. +#: If `--mirror=` is passed, use the value as a mirror URL. #: #: If `--version=` is passed, use the value to override the value -#: parsed from the url or tag. Note that `--version=0` can be used to delete +#: parsed from the URL or tag. Note that `--version=0` can be used to delete #: an existing `version` override from a formula if it has become redundant. #: #: If `--message=` is passed, append to the default PR #: message. #: #: Note that this command cannot be used to transition a formula from a -#: url-and-sha256 style specification into a tag-and-revision style +#: URL-and-sha256 style specification into a tag-and-revision style #: specification, nor vice versa. It must use whichever style specification #: the preexisting formula already uses. diff --git a/Library/Homebrew/dev-cmd/create.rb b/Library/Homebrew/dev-cmd/create.rb index b4cda0fad..9c58dc71a 100644 --- a/Library/Homebrew/dev-cmd/create.rb +++ b/Library/Homebrew/dev-cmd/create.rb @@ -3,8 +3,7 @@ #: Homebrew will attempt to automatically derive the formula name #: and version, but if it fails, you'll have to make your own template. The `wget` #: formula serves as a simple example. For the complete API have a look at -#: -#: +#: . #: #: If `--autotools` is passed, create a basic template for an Autotools-style build. #: If `--cmake` is passed, create a basic template for a CMake-style build. diff --git a/Library/Homebrew/dev-cmd/formula.rb b/Library/Homebrew/dev-cmd/formula.rb index 71687dfa7..67d11edce 100644 --- a/Library/Homebrew/dev-cmd/formula.rb +++ b/Library/Homebrew/dev-cmd/formula.rb @@ -1,5 +1,5 @@ #: * `formula` : -#: Display the path where is +#: Display the path where is located. require "formula" diff --git a/Library/Homebrew/dev-cmd/linkage.rb b/Library/Homebrew/dev-cmd/linkage.rb index 44e0f224e..e4da827f2 100644 --- a/Library/Homebrew/dev-cmd/linkage.rb +++ b/Library/Homebrew/dev-cmd/linkage.rb @@ -1,4 +1,4 @@ -#: * `linkage` [`--test`] [`--reverse`] : +#: * `linkage` [`--test`] [`--reverse`] : #: Checks the library links of an installed formula. #: #: Only works on installed formulae. An error is raised if it is run on diff --git a/Library/Homebrew/dev-cmd/mirror.rb b/Library/Homebrew/dev-cmd/mirror.rb index bd5868726..10811493c 100644 --- a/Library/Homebrew/dev-cmd/mirror.rb +++ b/Library/Homebrew/dev-cmd/mirror.rb @@ -1,5 +1,5 @@ #: @hide_from_man_page -#: * `mirror` [`--test`] [ ...]: +#: * `mirror` [`--test`] : #: Reuploads the stable URL for a formula to Bintray to use it as a mirror. module Homebrew diff --git a/Library/Homebrew/dev-cmd/release-notes.rb b/Library/Homebrew/dev-cmd/release-notes.rb index 919243764..eb398fcfb 100644 --- a/Library/Homebrew/dev-cmd/release-notes.rb +++ b/Library/Homebrew/dev-cmd/release-notes.rb @@ -1,7 +1,7 @@ -#: * `release-notes` [] []: +#: * `release-notes` [`--markdown`] [] []: #: Output the merged pull requests on Homebrew/brew between two Git refs. -#: If no `previous_tag` is provided it defaults to the newest tag. -#: If no `end_ref` is provided it defaults to `origin/master`. +#: If no is provided it defaults to the newest tag. +#: If no is provided it defaults to `origin/master`. #: #: If `--markdown` is passed, output as a Markdown list. diff --git a/Library/Homebrew/dev-cmd/tests.rb b/Library/Homebrew/dev-cmd/tests.rb index 6276d1c1b..0c8621a01 100644 --- a/Library/Homebrew/dev-cmd/tests.rb +++ b/Library/Homebrew/dev-cmd/tests.rb @@ -1,4 +1,4 @@ -#: * `tests` [`-v`] [`--coverage`] [`--generic`] [`--no-compat`] [`--only=`] [`--seed` ] [`--trace`] [`--online`] [`--official-cmd-taps`]: +#: * `tests` [`-v`] [`--coverage`] [`--generic`] [`--no-compat`] [`--only=``:`] [`--seed` ] [`--trace`] [`--online`] [`--official-cmd-taps`]: #: Run Homebrew's unit and integration tests. require "fileutils" diff --git a/Library/Homebrew/dev-cmd/update-test.rb b/Library/Homebrew/dev-cmd/update-test.rb index 3b8dc11f9..9704426dd 100644 --- a/Library/Homebrew/dev-cmd/update-test.rb +++ b/Library/Homebrew/dev-cmd/update-test.rb @@ -1,14 +1,14 @@ -#: * `update-test` [`--commit=`] [`--before=`] [`--keep-tmp`]: +#: * `update-test` [`--commit=`] [`--before=`] [`--keep-tmp`]: #: Runs a test of `brew update` with a new repository clone. #: #: If no arguments are passed, use `origin/master` as the start commit. #: -#: If `--commit=` is passed, use `` as the start commit. +#: If `--commit=` is passed, use as the start commit. #: -#: If `--before=` is passed, use the commit at `` as the +#: If `--before=` is passed, use the commit at as the #: start commit. #: -#: If `--to-tag` is passed, set HOMEBREW_UPDATE_TO_TAG to test updating +#: If `--to-tag` is passed, set `HOMEBREW_UPDATE_TO_TAG` to test updating #: between tags. #: #: If `--keep-tmp` is passed, retain the temporary directory containing -- cgit v1.2.3 From 177aefdf555488653572f1f98bf4d6d8c7a03671 Mon Sep 17 00:00:00 2001 From: Misty De Meo Date: Sun, 26 Feb 2017 14:53:00 +1100 Subject: xcodebuild audit: match xcodebuild with no args Closes #2199. Signed-off-by: Misty De Meo --- Library/Homebrew/dev-cmd/audit.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Library/Homebrew/dev-cmd') diff --git a/Library/Homebrew/dev-cmd/audit.rb b/Library/Homebrew/dev-cmd/audit.rb index 134965355..35d590b69 100644 --- a/Library/Homebrew/dev-cmd/audit.rb +++ b/Library/Homebrew/dev-cmd/audit.rb @@ -924,7 +924,7 @@ class FormulaAuditor end end - if text =~ /xcodebuild[ (]["'*]/ && !text.include?("SYMROOT=") + if text =~ /xcodebuild[ (]*["'*]*/ && !text.include?("SYMROOT=") problem 'xcodebuild should be passed an explicit "SYMROOT"' end -- cgit v1.2.3 From e3f4701f385c286a2cc72c5d07870cc9a6ce0bf4 Mon Sep 17 00:00:00 2001 From: Misty De Meo Date: Sun, 26 Feb 2017 16:49:09 +1100 Subject: audit: fix audit on formulae without homepages --- Library/Homebrew/dev-cmd/audit.rb | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'Library/Homebrew/dev-cmd') diff --git a/Library/Homebrew/dev-cmd/audit.rb b/Library/Homebrew/dev-cmd/audit.rb index 35d590b69..a8c18f7b6 100644 --- a/Library/Homebrew/dev-cmd/audit.rb +++ b/Library/Homebrew/dev-cmd/audit.rb @@ -605,6 +605,11 @@ class FormulaAuditor def audit_homepage homepage = formula.homepage + if homepage.nil? || homepage.empty? + problem "Formula should have a homepage." + return + end + unless homepage =~ %r{^https?://} problem "The homepage should start with http or https (URL is #{homepage})." end -- cgit v1.2.3