From 98d05a552d9d2ea9796d8d4c1a2337f070ea54e2 Mon Sep 17 00:00:00 2001 From: Dawa Ometto Date: Fri, 13 Jan 2023 17:52:19 +0100 Subject: [PATCH 01/19] Don't use treemap for finding pages and file --- lib/gollum-lib/file.rb | 40 +++++++++++++++++++--------------------- lib/gollum-lib/page.rb | 16 ++++++++++------ 2 files changed, 29 insertions(+), 27 deletions(-) diff --git a/lib/gollum-lib/file.rb b/lib/gollum-lib/file.rb index f17ac8ad1..af9c6cec1 100644 --- a/lib/gollum-lib/file.rb +++ b/lib/gollum-lib/file.rb @@ -7,17 +7,6 @@ class File FS_SUPPORT_SYMLINKS = !Gem.win_platform? class << self - - # For use with self.find: returns true if the given query corresponds to the in-repo path of the BlobEntry. - # - # query - The String path to match. - # entry - The BlobEntry to check against. - # global_match - (Not implemented for File, see Page.path_match) - # hyphened_tags - If true, replace spaces in match_path with hyphens. - # case_insensitive - If true, compare query and match_path case-insensitively - def path_match(query, entry, global_match = false, hyphened_tags = false, case_insensitive = false) - path_compare(query, ::File.join('/', entry.path), hyphened_tags, case_insensitive) - end # For use with self.path_match: returns true if 'query' and 'match_path' match, strictly or taking account of the following parameters: # hyphened_tags - If true, replace spaces in match_path with hyphens. @@ -47,18 +36,27 @@ def path_compare(query, match_path, hyphened_tags, case_insensitive) # that if you specify try_on_disk=true, you may or may not get a file # for which on_disk? is actually true. def self.find(wiki, path, version, try_on_disk = false, global_match = false) - map = wiki.tree_map_for(version.to_s) - query_path = Pathname.new(::File.join(['/', wiki.page_file_dir, path].compact)).cleanpath.to_s - query_path.sub!(/^\/\//, '/') if Gem.win_platform? # On Windows, Pathname#cleanpath will leave double slashes at the start of a path intact, so sub them out. + query_path.sub!(/^\/+/, '') # On Windows, Pathname#cleanpath will leave double slashes at the start of a path, so replace all (not just the first) leading slashes + segments = query_path.split('/') + filename = segments.last + dir = segments[0..-2].join('/') - begin - entry = map.detect do |entry| - path_match(query_path, entry, global_match, wiki.hyphened_tag_lookup, wiki.case_insensitive_tag_lookup) + if global_match + return nil + else + begin + root = wiki.repo.git.commit_from_ref(version.to_s) + return nil unless root + tree = dir.empty? ? root.tree : root.tree / dir + return nil unless tree + entry = tree.blobs.find do |blob| + path_compare(filename, blob.name, wiki.hyphened_tag_lookup, wiki.case_insensitive_tag_lookup) + end + entry ? self.new(wiki, entry, dir, version, try_on_disk) : nil + rescue Gollum::Git::NoSuchShaFound + nil end - entry ? self.new(wiki, entry.blob(wiki.repo), entry.dir, version, try_on_disk) : nil - rescue Gollum::Git::NoSuchShaFound - nil end end @@ -74,7 +72,7 @@ def self.find(wiki, path, version, try_on_disk = false, global_match = false) def initialize(wiki, blob, path, version, try_on_disk = false) @wiki = wiki @blob = blob - @path = "#{path}/#{blob.name}"[1..-1] + @path = path.empty? ? blob.name : ::File.join(path, blob.name) @version = version.is_a?(Gollum::Git::Commit) ? version : @wiki.commit_for(version) get_disk_reference if try_on_disk end diff --git a/lib/gollum-lib/page.rb b/lib/gollum-lib/page.rb index 85163fc2f..1db5268e3 100644 --- a/lib/gollum-lib/page.rb +++ b/lib/gollum-lib/page.rb @@ -10,18 +10,22 @@ class << self # # query - The String path to match. # entry - The BlobEntry to check against. - # global_match - If true, find a File matching path's filename, but not its directory (so anywhere in the repo) - def path_match(query, entry, global_match = false, hyphened_tags = false, case_insensitive = false) + def global_path_match(query, entry, hyphened_tags = false, case_insensitive = false) return false if "#{entry.name}".empty? return false unless valid_extension?(entry.name) - entry_name = valid_extension?(query) ? entry.name : strip_filename(entry.name) match_path = ::File.join([ - '/', - global_match ? nil : entry.dir, - entry_name + '/', + entry.dir, + entry.name ].compact) path_compare(query, match_path, hyphened_tags, case_insensitive) end + + def path_compare(query, match_path, hyphened_tags, case_insensitive) + cmp = valid_extension?(query) ? match_path : strip_filename(match_path) + super(query, cmp, hyphened_tags, case_insensitive) + end + end # Checks if a filename has a valid, registered extension From 8dc3f152a2c649ba8973609f1b81243214f58589 Mon Sep 17 00:00:00 2001 From: Dawa Ometto Date: Fri, 13 Jan 2023 18:10:31 +0100 Subject: [PATCH 02/19] Fix relative paths --- lib/gollum-lib/file.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/gollum-lib/file.rb b/lib/gollum-lib/file.rb index af9c6cec1..2bdb3c08d 100644 --- a/lib/gollum-lib/file.rb +++ b/lib/gollum-lib/file.rb @@ -72,7 +72,7 @@ def self.find(wiki, path, version, try_on_disk = false, global_match = false) def initialize(wiki, blob, path, version, try_on_disk = false) @wiki = wiki @blob = blob - @path = path.empty? ? blob.name : ::File.join(path, blob.name) + @path = Pathname.new(::File.join('/', path, blob.name)).cleanpath.to_s[1..-1] @version = version.is_a?(Gollum::Git::Commit) ? version : @wiki.commit_for(version) get_disk_reference if try_on_disk end From 936040f8b49266c11c237b5e96c08dd5ac480ff4 Mon Sep 17 00:00:00 2001 From: Dawa Ometto Date: Fri, 13 Jan 2023 18:10:56 +0100 Subject: [PATCH 03/19] Don't match files for pages --- lib/gollum-lib/page.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/gollum-lib/page.rb b/lib/gollum-lib/page.rb index 1db5268e3..21217a43d 100644 --- a/lib/gollum-lib/page.rb +++ b/lib/gollum-lib/page.rb @@ -22,6 +22,7 @@ def global_path_match(query, entry, hyphened_tags = false, case_insensitive = fa end def path_compare(query, match_path, hyphened_tags, case_insensitive) + return false unless valid_extension?(match_path) cmp = valid_extension?(query) ? match_path : strip_filename(match_path) super(query, cmp, hyphened_tags, case_insensitive) end From a14f75e1e75d5227ab8be5756247eb8ad4848e95 Mon Sep 17 00:00:00 2001 From: Dawa Ometto Date: Sat, 14 Jan 2023 14:18:17 +0100 Subject: [PATCH 04/19] Minor refactor --- lib/gollum-lib/file.rb | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/lib/gollum-lib/file.rb b/lib/gollum-lib/file.rb index 2bdb3c08d..43edae5f4 100644 --- a/lib/gollum-lib/file.rb +++ b/lib/gollum-lib/file.rb @@ -7,6 +7,16 @@ class File FS_SUPPORT_SYMLINKS = !Gem.win_platform? class << self + + # Get a canonical path to a file, removing leading slashes. + # + # path - One or more String path elements to join together + def canonical_path(*path) + # First create a clean path (e.g. no '..'), then remove leading slash. + result = Pathname.new(::File.join(['/', path.compact])).cleanpath.to_s + result.sub!(/^\/+/, '') # On Windows, Pathname#cleanpath will leave double slashes at the start of a path, so replace all (not just the first) leading slashes + result + end # For use with self.path_match: returns true if 'query' and 'match_path' match, strictly or taking account of the following parameters: # hyphened_tags - If true, replace spaces in match_path with hyphens. @@ -36,17 +46,16 @@ def path_compare(query, match_path, hyphened_tags, case_insensitive) # that if you specify try_on_disk=true, you may or may not get a file # for which on_disk? is actually true. def self.find(wiki, path, version, try_on_disk = false, global_match = false) - query_path = Pathname.new(::File.join(['/', wiki.page_file_dir, path].compact)).cleanpath.to_s - query_path.sub!(/^\/+/, '') # On Windows, Pathname#cleanpath will leave double slashes at the start of a path, so replace all (not just the first) leading slashes - segments = query_path.split('/') - filename = segments.last - dir = segments[0..-2].join('/') + path_segments = self.canonical_path(wiki.page_file_dir, path).split('/') + filename = path_segments.last + dir = path_segments[0..-2].join('/') + if global_match return nil else begin - root = wiki.repo.git.commit_from_ref(version.to_s) + root = wiki.commit_for(version.to_s) return nil unless root tree = dir.empty? ? root.tree : root.tree / dir return nil unless tree @@ -72,7 +81,7 @@ def self.find(wiki, path, version, try_on_disk = false, global_match = false) def initialize(wiki, blob, path, version, try_on_disk = false) @wiki = wiki @blob = blob - @path = Pathname.new(::File.join('/', path, blob.name)).cleanpath.to_s[1..-1] + @path = self.class.canonical_path(path, blob.name) @version = version.is_a?(Gollum::Git::Commit) ? version : @wiki.commit_for(version) get_disk_reference if try_on_disk end From d69363a1667e44792ee0e1b2f642eb75deddf914 Mon Sep 17 00:00:00 2001 From: Dawa Ometto Date: Sat, 14 Jan 2023 14:34:43 +0100 Subject: [PATCH 05/19] Reimplement global find --- lib/gollum-lib/file.rb | 10 +++++----- lib/gollum-lib/page.rb | 12 ++++++++++++ 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/lib/gollum-lib/file.rb b/lib/gollum-lib/file.rb index 43edae5f4..2c83c48ec 100644 --- a/lib/gollum-lib/file.rb +++ b/lib/gollum-lib/file.rb @@ -40,19 +40,19 @@ def path_compare(query, match_path, hyphened_tags, case_insensitive) # version - The String version ID to find. # try_on_disk - If true, try to return just a reference to a file # that exists on the disk. - # global_match - If true, find a File matching path's filename, but not it's directory (so anywhere in the repo) + # global_match - If true, find a File matching path's filename, but not its directory (so anywhere in the repo) # # Returns a Gollum::File or nil if the file could not be found. Note # that if you specify try_on_disk=true, you may or may not get a file # for which on_disk? is actually true. def self.find(wiki, path, version, try_on_disk = false, global_match = false) - path_segments = self.canonical_path(wiki.page_file_dir, path).split('/') + query_path = self.canonical_path(wiki.page_file_dir, path) + path_segments = query_path.split('/') filename = path_segments.last dir = path_segments[0..-2].join('/') - - if global_match - return nil + if global_match && self.respond_to?(:global_find) # Only implemented for Gollum::Page + return self.global_find(wiki, version, query_path, try_on_disk) else begin root = wiki.commit_for(version.to_s) diff --git a/lib/gollum-lib/page.rb b/lib/gollum-lib/page.rb index 21217a43d..922bbf6f1 100644 --- a/lib/gollum-lib/page.rb +++ b/lib/gollum-lib/page.rb @@ -21,6 +21,18 @@ def global_path_match(query, entry, hyphened_tags = false, case_insensitive = fa path_compare(query, match_path, hyphened_tags, case_insensitive) end + def global_find(wiki, version, query, try_on_disk) + map = wiki.tree_map_for(version.to_s) + begin + entry = map.detect do |entry| + global_path_match(query, entry, wiki.hyphened_tag_lookup, wiki.case_insensitive_tag_lookup) + end + entry ? self.new(wiki, entry.blob(wiki.repo), entry.dir, version, try_on_disk) : nil + rescue Gollum::Git::NoSuchShaFound + nil + end + end + def path_compare(query, match_path, hyphened_tags, case_insensitive) return false unless valid_extension?(match_path) cmp = valid_extension?(query) ? match_path : strip_filename(match_path) From 6535c0ce35fb543fb67304d3eff70b7e7a502e2f Mon Sep 17 00:00:00 2001 From: Dawa Ometto Date: Sat, 14 Jan 2023 15:34:42 +0100 Subject: [PATCH 06/19] Rewrite File.canonical_path to prevent path traversal. Add test. --- lib/gollum-lib/file.rb | 17 ++++++++++------- test/test_file.rb | 9 +++++++++ 2 files changed, 19 insertions(+), 7 deletions(-) diff --git a/lib/gollum-lib/file.rb b/lib/gollum-lib/file.rb index 2c83c48ec..02be6bee2 100644 --- a/lib/gollum-lib/file.rb +++ b/lib/gollum-lib/file.rb @@ -8,13 +8,16 @@ class File class << self - # Get a canonical path to a file, removing leading slashes. + # Get a canonical path to a file. + # Ensures that the result is always under page_file_dir (prevents path traversal). # - # path - One or more String path elements to join together - def canonical_path(*path) - # First create a clean path (e.g. no '..'), then remove leading slash. - result = Pathname.new(::File.join(['/', path.compact])).cleanpath.to_s - result.sub!(/^\/+/, '') # On Windows, Pathname#cleanpath will leave double slashes at the start of a path, so replace all (not just the first) leading slashes + # path - One or more String path elements to join together. `nil` values are ignored. + # page_file_dir - kwarg String, default: nil + def canonical_path(*path, page_file_dir: nil) + prefix = Pathname.new(::File.join('/', page_file_dir.to_s)) + rest = Pathname.new(::File.join('/', path.compact)).cleanpath + result = Pathname.new(::File.join(prefix, rest)).cleanpath.to_s[1..-1] + result.sub!(/^\/+/, '') if Gem.win_platform? # On Windows, Pathname#cleanpath will leave double slashes at the start of a path, so replace all (not just the first) leading slashes result end @@ -46,7 +49,7 @@ def path_compare(query, match_path, hyphened_tags, case_insensitive) # that if you specify try_on_disk=true, you may or may not get a file # for which on_disk? is actually true. def self.find(wiki, path, version, try_on_disk = false, global_match = false) - query_path = self.canonical_path(wiki.page_file_dir, path) + query_path = self.canonical_path(path, page_file_dir: wiki.page_file_dir) path_segments = query_path.split('/') filename = path_segments.last dir = path_segments[0..-2].join('/') diff --git a/test/test_file.rb b/test/test_file.rb index af5876de9..5f2d2d3b0 100644 --- a/test/test_file.rb +++ b/test/test_file.rb @@ -7,6 +7,15 @@ @wiki = Gollum::Wiki.new(testpath("examples/lotr.git")) end + test 'canonical_path method does not allow path traversal exploit' do + page_file_dir = nil + dir = 'pages' + file = '../../' + assert_equal Gollum::File.canonical_path(dir, file, page_file_dir: page_file_dir), '' + page_file_dir = 'pages' + assert_equal Gollum::File.canonical_path(dir, file, page_file_dir: page_file_dir), 'pages' + end + test "existing file" do commit = @wiki.repo.commits.first file = @wiki.file("Mordor/todo.txt") From d58738bbe37abfd6d9ab9256436f6722bb260a47 Mon Sep 17 00:00:00 2001 From: Dawa Ometto Date: Sat, 14 Jan 2023 15:53:19 +0100 Subject: [PATCH 07/19] Improve test --- lib/gollum-lib/file.rb | 3 ++- test/test_file.rb | 2 ++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/gollum-lib/file.rb b/lib/gollum-lib/file.rb index 02be6bee2..833f8d1dd 100644 --- a/lib/gollum-lib/file.rb +++ b/lib/gollum-lib/file.rb @@ -9,7 +9,8 @@ class File class << self # Get a canonical path to a file. - # Ensures that the result is always under page_file_dir (prevents path traversal). + # Ensures that the result is always under page_file_dir (prevents path traversal), if set. + # Removes leading slashes. # # path - One or more String path elements to join together. `nil` values are ignored. # page_file_dir - kwarg String, default: nil diff --git a/test/test_file.rb b/test/test_file.rb index 5f2d2d3b0..7c744f4ac 100644 --- a/test/test_file.rb +++ b/test/test_file.rb @@ -14,6 +14,8 @@ assert_equal Gollum::File.canonical_path(dir, file, page_file_dir: page_file_dir), '' page_file_dir = 'pages' assert_equal Gollum::File.canonical_path(dir, file, page_file_dir: page_file_dir), 'pages' + # also removes leading slashes + assert_equal Gollum::File.canonical_path('/foo/bar', page_file_dir: page_file_dir), 'pages/foo/bar' end test "existing file" do From c2b47b459245403dd1c58c3ba490f7eab980c9ec Mon Sep 17 00:00:00 2001 From: Dawa Ometto Date: Mon, 16 Jan 2023 00:33:27 +0100 Subject: [PATCH 08/19] GitAccess: improve #tree! performance --- lib/gollum-lib/git_access.rb | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/lib/gollum-lib/git_access.rb b/lib/gollum-lib/git_access.rb index 1967359c4..ef0eca7c0 100644 --- a/lib/gollum-lib/git_access.rb +++ b/lib/gollum-lib/git_access.rb @@ -161,15 +161,11 @@ def tree!(sha) items = [] tree.each do |entry| if entry[:type] == 'blob' + next if @page_file_dir && !entry[:path].start_with?("#{@page_file_dir}/") items << BlobEntry.new(entry[:sha], entry[:path], entry[:size], entry[:mode].to_i(8)) end end - if (dir = @page_file_dir) - regex = /^#{dir}\// - items.select { |i| i.path =~ regex } - else - items - end + items end # Reads the content from the Git db at the given SHA. From e3ae2176dc3fa350580652c3fb65e34631714b57 Mon Sep 17 00:00:00 2001 From: Dawa Ometto Date: Mon, 16 Jan 2023 00:49:24 +0100 Subject: [PATCH 09/19] Expect mode to be an Integer --- lib/gollum-lib/git_access.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/gollum-lib/git_access.rb b/lib/gollum-lib/git_access.rb index ef0eca7c0..2b010c07a 100644 --- a/lib/gollum-lib/git_access.rb +++ b/lib/gollum-lib/git_access.rb @@ -162,7 +162,7 @@ def tree!(sha) tree.each do |entry| if entry[:type] == 'blob' next if @page_file_dir && !entry[:path].start_with?("#{@page_file_dir}/") - items << BlobEntry.new(entry[:sha], entry[:path], entry[:size], entry[:mode].to_i(8)) + items << BlobEntry.new(entry[:sha], entry[:path], entry[:size], entry[:mode]) end end items From 88b3c4c2509043bb4878c98ed1e64bb62010449f Mon Sep 17 00:00:00 2001 From: Dawa Ometto Date: Mon, 16 Jan 2023 00:49:59 +0100 Subject: [PATCH 10/19] Depend on temporary adapter branch for tests --- Gemfile | 1 + 1 file changed, 1 insertion(+) diff --git a/Gemfile b/Gemfile index 8da7c0735..5dae163e5 100644 --- a/Gemfile +++ b/Gemfile @@ -1,6 +1,7 @@ source 'https://rubygems.org' gemspec :name => 'gollum-lib' gem 'irb' +gem 'gollum-rugged_adapter', git: 'https://github.com/dometto/rugged_adapter', branch: 'improve_tree_blobs' if RUBY_PLATFORM == 'java' then group :development do From adcd22249aa2e4cc18e20fe37d448409ddd2234c Mon Sep 17 00:00:00 2001 From: Dawa Ometto Date: Mon, 16 Jan 2023 01:36:44 +0100 Subject: [PATCH 11/19] Utilize Tree#find_blob for further improvements --- lib/gollum-lib/file.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/gollum-lib/file.rb b/lib/gollum-lib/file.rb index 833f8d1dd..d59cc7b33 100644 --- a/lib/gollum-lib/file.rb +++ b/lib/gollum-lib/file.rb @@ -63,8 +63,8 @@ def self.find(wiki, path, version, try_on_disk = false, global_match = false) return nil unless root tree = dir.empty? ? root.tree : root.tree / dir return nil unless tree - entry = tree.blobs.find do |blob| - path_compare(filename, blob.name, wiki.hyphened_tag_lookup, wiki.case_insensitive_tag_lookup) + entry = tree.find_blob do |blob_name| + path_compare(filename, blob_name, wiki.hyphened_tag_lookup, wiki.case_insensitive_tag_lookup) end entry ? self.new(wiki, entry, dir, version, try_on_disk) : nil rescue Gollum::Git::NoSuchShaFound From d01552a0fdc6751c9356783049c74834a0e2a278 Mon Sep 17 00:00:00 2001 From: Dawa Ometto Date: Tue, 28 Mar 2023 17:28:30 +0200 Subject: [PATCH 12/19] Update Gemfile --- Gemfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gemfile b/Gemfile index 5dae163e5..145330de7 100644 --- a/Gemfile +++ b/Gemfile @@ -1,7 +1,7 @@ source 'https://rubygems.org' gemspec :name => 'gollum-lib' gem 'irb' -gem 'gollum-rugged_adapter', git: 'https://github.com/dometto/rugged_adapter', branch: 'improve_tree_blobs' +gem 'gollum-rugged_adapter', git: 'https://github.com/gollum/rugged_adapter' if RUBY_PLATFORM == 'java' then group :development do From 2a23e83535b344b069ab6326a32725a030660091 Mon Sep 17 00:00:00 2001 From: Dawa Ometto Date: Tue, 28 Mar 2023 17:39:43 +0200 Subject: [PATCH 13/19] Update Gemfile --- Gemfile | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Gemfile b/Gemfile index 145330de7..52d4cb760 100644 --- a/Gemfile +++ b/Gemfile @@ -1,10 +1,12 @@ source 'https://rubygems.org' gemspec :name => 'gollum-lib' gem 'irb' -gem 'gollum-rugged_adapter', git: 'https://github.com/gollum/rugged_adapter' if RUBY_PLATFORM == 'java' then + gem 'gollum-rugged_adapter', git: 'gollum-lib_rjgit_adapter', branch: 'tree_find_blob' group :development do gem 'activesupport', '~> 6.0' end +else + gem 'gollum-rugged_adapter', git: 'https://github.com/gollum/rugged_adapter' end From 565eb31acd1ff506ebf11eac35deaa06abed6d37 Mon Sep 17 00:00:00 2001 From: Dawa Ometto Date: Tue, 28 Mar 2023 19:35:03 +0200 Subject: [PATCH 14/19] Update Gemfile --- Gemfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gemfile b/Gemfile index 52d4cb760..24f2b80cb 100644 --- a/Gemfile +++ b/Gemfile @@ -3,7 +3,7 @@ gemspec :name => 'gollum-lib' gem 'irb' if RUBY_PLATFORM == 'java' then - gem 'gollum-rugged_adapter', git: 'gollum-lib_rjgit_adapter', branch: 'tree_find_blob' + gem 'gollum-rjgit_adapter', git: 'https://github.com/dometto/gollum-lib_rjgit_adapter', branch: 'tree_find_blob' group :development do gem 'activesupport', '~> 6.0' end From 28360674af5852ddc53b50734fd6be7522dafa16 Mon Sep 17 00:00:00 2001 From: Dawa Ometto Date: Tue, 16 May 2023 16:10:09 +0200 Subject: [PATCH 15/19] Pathname refactors --- lib/gollum-lib/file.rb | 17 ++++++++--------- lib/gollum-lib/page.rb | 2 +- 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/lib/gollum-lib/file.rb b/lib/gollum-lib/file.rb index d59cc7b33..314695f63 100644 --- a/lib/gollum-lib/file.rb +++ b/lib/gollum-lib/file.rb @@ -15,14 +15,14 @@ class << self # path - One or more String path elements to join together. `nil` values are ignored. # page_file_dir - kwarg String, default: nil def canonical_path(*path, page_file_dir: nil) - prefix = Pathname.new(::File.join('/', page_file_dir.to_s)) - rest = Pathname.new(::File.join('/', path.compact)).cleanpath - result = Pathname.new(::File.join(prefix, rest)).cleanpath.to_s[1..-1] + prefix = Pathname.new('/') + page_file_dir.to_s + rest = Pathname.new('/').join(*path.compact).cleanpath.to_s[1..-1] + result = (prefix + rest).cleanpath.to_s[1..-1] result.sub!(/^\/+/, '') if Gem.win_platform? # On Windows, Pathname#cleanpath will leave double slashes at the start of a path, so replace all (not just the first) leading slashes result end - # For use with self.path_match: returns true if 'query' and 'match_path' match, strictly or taking account of the following parameters: + # For use with self.find: returns true if 'query' and 'match_path' match, strictly or taking account of the following parameters: # hyphened_tags - If true, replace spaces in match_path with hyphens. # case_insensitive - If true, compare query and match_path case-insensitively def path_compare(query, match_path, hyphened_tags, case_insensitive) @@ -51,9 +51,8 @@ def path_compare(query, match_path, hyphened_tags, case_insensitive) # for which on_disk? is actually true. def self.find(wiki, path, version, try_on_disk = false, global_match = false) query_path = self.canonical_path(path, page_file_dir: wiki.page_file_dir) - path_segments = query_path.split('/') - filename = path_segments.last - dir = path_segments[0..-2].join('/') + dir, filename = Pathname.new(query_path).split + dir = dir.to_s if global_match && self.respond_to?(:global_find) # Only implemented for Gollum::Page return self.global_find(wiki, version, query_path, try_on_disk) @@ -61,10 +60,10 @@ def self.find(wiki, path, version, try_on_disk = false, global_match = false) begin root = wiki.commit_for(version.to_s) return nil unless root - tree = dir.empty? ? root.tree : root.tree / dir + tree = dir == '.' ? root.tree : root.tree / dir return nil unless tree entry = tree.find_blob do |blob_name| - path_compare(filename, blob_name, wiki.hyphened_tag_lookup, wiki.case_insensitive_tag_lookup) + path_compare(filename.to_s, blob_name, wiki.hyphened_tag_lookup, wiki.case_insensitive_tag_lookup) end entry ? self.new(wiki, entry, dir, version, try_on_disk) : nil rescue Gollum::Git::NoSuchShaFound diff --git a/lib/gollum-lib/page.rb b/lib/gollum-lib/page.rb index 922bbf6f1..3af699cdf 100644 --- a/lib/gollum-lib/page.rb +++ b/lib/gollum-lib/page.rb @@ -6,7 +6,7 @@ class Page < Gollum::File SUBPAGENAMES = [:header, :footer, :sidebar] class << self - # For use with self.find: returns true if the given query corresponds to the in-repo path of the BlobEntry. + # For use with self.global_find: returns true if the given query corresponds to the in-repo path of the BlobEntry. # # query - The String path to match. # entry - The BlobEntry to check against. From 5e9966bf41005bd4a74cb73a112445d33d44edde Mon Sep 17 00:00:00 2001 From: Dawa Ometto Date: Wed, 24 May 2023 12:51:50 +0200 Subject: [PATCH 16/19] page.rb Pathname refactor --- lib/gollum-lib/page.rb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/gollum-lib/page.rb b/lib/gollum-lib/page.rb index 3af699cdf..0464b2a7a 100644 --- a/lib/gollum-lib/page.rb +++ b/lib/gollum-lib/page.rb @@ -13,11 +13,11 @@ class << self def global_path_match(query, entry, hyphened_tags = false, case_insensitive = false) return false if "#{entry.name}".empty? return false unless valid_extension?(entry.name) - match_path = ::File.join([ - '/', + match_path = Pathname.new('/').join(*[ entry.dir, - entry.name - ].compact) + entry.name + ].compact + ).to_s path_compare(query, match_path, hyphened_tags, case_insensitive) end From a51a7a500e9a6ae4596c09c77c9629fd7d342578 Mon Sep 17 00:00:00 2001 From: Dawa Ometto Date: Wed, 24 May 2023 13:57:02 +0200 Subject: [PATCH 17/19] Depend on the released adapter gems --- Gemfile | 3 --- gollum-lib.gemspec | 4 ++-- gollum-lib_java.gemspec | 2 +- 3 files changed, 3 insertions(+), 6 deletions(-) diff --git a/Gemfile b/Gemfile index 24f2b80cb..8da7c0735 100644 --- a/Gemfile +++ b/Gemfile @@ -3,10 +3,7 @@ gemspec :name => 'gollum-lib' gem 'irb' if RUBY_PLATFORM == 'java' then - gem 'gollum-rjgit_adapter', git: 'https://github.com/dometto/gollum-lib_rjgit_adapter', branch: 'tree_find_blob' group :development do gem 'activesupport', '~> 6.0' end -else - gem 'gollum-rugged_adapter', git: 'https://github.com/gollum/rugged_adapter' end diff --git a/gollum-lib.gemspec b/gollum-lib.gemspec index 3411abb06..7348e652c 100644 --- a/gollum-lib.gemspec +++ b/gollum-lib.gemspec @@ -3,8 +3,8 @@ require File.join(File.dirname(__FILE__), 'lib', 'gollum-lib', 'version.rb') # This file needs to conditionally define the default adapter for MRI and Java, because this is the file that is included from the Gemfile. # In addition, the default Java adapter needs to be defined in gollum-lib_java.gemspec beause that file is used to *build* the Java gem. if RUBY_PLATFORM == 'java' then - default_adapter = ['gollum-rjgit_adapter', '~> 1.0'] + default_adapter = ['gollum-rjgit_adapter', '~> 2.0'] else - default_adapter = ['gollum-rugged_adapter', '~> 2.0'] + default_adapter = ['gollum-rugged_adapter', '~> 3.0'] end Gem::Specification.new &specification(Gollum::Lib::VERSION, default_adapter) diff --git a/gollum-lib_java.gemspec b/gollum-lib_java.gemspec index 8db087479..62772a087 100644 --- a/gollum-lib_java.gemspec +++ b/gollum-lib_java.gemspec @@ -1,4 +1,4 @@ require File.join(File.dirname(__FILE__), 'gemspec.rb') require File.join(File.dirname(__FILE__), 'lib', 'gollum-lib', 'version.rb') -default_adapter = ['gollum-rjgit_adapter', '~> 1.0'] +default_adapter = ['gollum-rjgit_adapter', '~> 2.0'] Gem::Specification.new &specification(Gollum::Lib::VERSION, default_adapter, "java") From 0498f5b94568ca7d7bb73a72d139185b8e904fcb Mon Sep 17 00:00:00 2001 From: Dawa Ometto Date: Tue, 1 Aug 2023 14:57:49 +0200 Subject: [PATCH 18/19] file.rb: remove unneeded version.to_s call. See https://github.com/gollum/gollum/issues/1972 --- lib/gollum-lib/file.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/gollum-lib/file.rb b/lib/gollum-lib/file.rb index 314695f63..62bdfab54 100644 --- a/lib/gollum-lib/file.rb +++ b/lib/gollum-lib/file.rb @@ -58,7 +58,7 @@ def self.find(wiki, path, version, try_on_disk = false, global_match = false) return self.global_find(wiki, version, query_path, try_on_disk) else begin - root = wiki.commit_for(version.to_s) + root = wiki.commit_for(version) return nil unless root tree = dir == '.' ? root.tree : root.tree / dir return nil unless tree From 3c5028cd444a42298ad270e17fd13c40cde5b5aa Mon Sep 17 00:00:00 2001 From: Dawa Ometto Date: Tue, 1 Aug 2023 15:17:38 +0200 Subject: [PATCH 19/19] Provide compatibility with latest minitest. --- gemspec.rb | 2 +- test/helper.rb | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/gemspec.rb b/gemspec.rb index 8cd5663dc..9eb487bb7 100644 --- a/gemspec.rb +++ b/gemspec.rb @@ -33,7 +33,7 @@ def specification(version, default_adapter, platform = nil) s.add_development_dependency 'kramdown', '~> 2.3' s.add_development_dependency 'kramdown-parser-gfm', '~> 1.1.0' s.add_development_dependency 'RedCloth', '~> 4.2.9' - s.add_development_dependency 'mocha', '~> 1.11' + s.add_development_dependency 'mocha', '~> 2.0' s.add_development_dependency 'shoulda', '~> 4.0' s.add_development_dependency 'wikicloth', '~> 0.8.3' s.add_development_dependency 'bibtex-ruby', '~> 6.0' diff --git a/test/helper.rb b/test/helper.rb index cb11ecb3a..9c50c72b1 100644 --- a/test/helper.rb +++ b/test/helper.rb @@ -6,8 +6,8 @@ # external require 'rubygems' require 'shoulda' -require 'mocha/test_unit' require 'minitest/reporters' +require 'mocha/test_unit' require 'twitter_cldr' require 'tempfile' @@ -24,7 +24,7 @@ require 'i18n' I18n.enforce_available_locales = false -MiniTest::Reporters.use! +Minitest::Reporters.use! dir = File.dirname(File.expand_path(__FILE__)) $LOAD_PATH.unshift(File.join(dir, '..', 'lib'))