Skip to content

Commit b49a658

Browse files
authored
Merge pull request #22317 from HaraldNordgren/file-url-basename
parse_basename: fix local test failures
2 parents eb6acfe + fdfa2e0 commit b49a658

2 files changed

Lines changed: 48 additions & 3 deletions

File tree

Library/Homebrew/download_strategy/abstract_file_download_strategy.rb

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -82,8 +82,10 @@ def resolved_url_and_basename
8282
def parse_basename(url, search_query: true)
8383
components = { path: T.let([], T::Array[String]), query: T.let([], T::Array[String]) }
8484

85+
file_url = T.let(false, T::Boolean)
8586
if url.match?(URI::RFC2396_PARSER.make_regexp)
8687
uri = URI(url)
88+
file_url = uri.scheme == "file"
8789

8890
if (uri_query = uri.query.presence)
8991
URI.decode_www_form(uri_query).each do |key, param|
@@ -109,9 +111,13 @@ def parse_basename(url, search_query: true)
109111
# extensions (e.g. tar.gz).
110112
# Given a URL like https://example.com/download.php?file=foo-1.0.tar.gz
111113
# the basename we want is "foo-1.0.tar.gz", not "download.php".
112-
[*components[:path], *components[:query]].reverse_each do |path|
113-
path = Pathname(path)
114-
return path.basename.to_s if path.extname.present?
114+
# Skipped for file:// URLs since their paths can contain ancestor
115+
# directories with dots (e.g. "github.com") that aren't real extensions.
116+
unless file_url
117+
[*components[:path], *components[:query]].reverse_each do |path|
118+
path = Pathname(path)
119+
return path.basename.to_s if path.extname.present?
120+
end
115121
end
116122

117123
filename = components[:path].last
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
# typed: false
2+
# frozen_string_literal: true
3+
4+
require "download_strategy"
5+
6+
RSpec.describe AbstractFileDownloadStrategy do
7+
subject(:strategy) { Class.new(described_class).new(url, "foo", "1.2.3") }
8+
9+
let(:url) { "https://example.com/foo.tar.gz" }
10+
11+
describe "#parse_basename" do
12+
it "returns the final path segment for simple URLs" do
13+
expect(strategy.send(:parse_basename, "https://example.com/foo.tar.gz")).to eq("foo.tar.gz")
14+
end
15+
16+
it "prefers a path segment with an extension over later extensionless segments" do
17+
expect(strategy.send(:parse_basename, "https://example.com/foo-1.0.tar.gz/download")).to eq("foo-1.0.tar.gz")
18+
end
19+
20+
it "extracts the basename from a response-content-disposition query parameter" do
21+
url = "https://example.com/download.php?file=ignored&response-content-disposition=attachment;filename=\"real.tar.gz\""
22+
expect(strategy.send(:parse_basename, url)).to eq("real.tar.gz")
23+
end
24+
25+
it "uses the query value when the path has no extension" do
26+
url = "https://example.com/download.php?file=foo-1.0.tar.gz"
27+
expect(strategy.send(:parse_basename, url)).to eq("foo-1.0.tar.gz")
28+
end
29+
30+
it "returns the final segment for file:// URLs even when an ancestor directory contains a dot" do
31+
expect(strategy.send(:parse_basename, "file:///Users/me/git-repos/github.com/Homebrew/brew/naked_executable"))
32+
.to eq("naked_executable")
33+
end
34+
35+
it "returns the final segment for file:// URLs with an extension" do
36+
expect(strategy.send(:parse_basename, "file:///tmp/foo.tar.gz")).to eq("foo.tar.gz")
37+
end
38+
end
39+
end

0 commit comments

Comments
 (0)