Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions lib/code_ownership.rb
Original file line number Diff line number Diff line change
Expand Up @@ -315,5 +315,7 @@ def self.for_package(package)
sig { void }
def self.bust_caches!
Private::FilePathTeamCache.bust_cache!
Private::FilePathFinder.instance_variable_set(:@pwd, nil)
Private::FilePathFinder.instance_variable_set(:@pwd_prefix, nil)
end
end
22 changes: 19 additions & 3 deletions lib/code_ownership/private/file_path_finder.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,29 @@ module Private
module FilePathFinder
extend T::Sig

sig { returns(String) }
def self.pwd_prefix
@pwd_prefix ||= T.let("#{Dir.pwd}/", T.nilable(String))
end

sig { returns(Pathname) }
def self.pwd
@pwd ||= T.let(Pathname.pwd, T.nilable(Pathname))
end

# Returns a string version of the relative path to a Rails constant,
# or nil if it can't find anything
sig { params(klass: T.nilable(T.any(T::Class[T.anything], T::Module[T.anything]))).returns(T.nilable(String)) }
def self.path_from_klass(klass)
if klass
path = Object.const_source_location(klass.to_s)&.first
(path && Pathname.new(path).relative_path_from(Pathname.pwd).to_s) || nil
return nil unless path

if path.start_with?(pwd_prefix)
path.delete_prefix(pwd_prefix)
else
Pathname.new(path).relative_path_from(pwd).to_s
end
end
rescue NameError
nil
Expand All @@ -30,15 +46,15 @@ def self.from_backtrace(backtrace)
# ./app/controllers/some_controller.rb:43:in `block (3 levels) in create'
#
backtrace_line = if RUBY_VERSION >= '3.4.0'
%r{\A(#{Pathname.pwd}/|\./)?
%r{\A(#{pwd}/|\./)?
(?<file>.+) # Matches 'app/controllers/some_controller.rb'
:
(?<line>\d+) # Matches '43'
:in\s
'(?<function>.*)' # Matches "`block (3 levels) in create'"
\z}x
else
%r{\A(#{Pathname.pwd}/|\./)?
%r{\A(#{pwd}/|\./)?
(?<file>.+) # Matches 'app/controllers/some_controller.rb'
:
(?<line>\d+) # Matches '43'
Expand Down
3 changes: 1 addition & 2 deletions lib/code_ownership/private/team_finder.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,8 @@ def self.for_file(file_path, allow_raise: false)
return FilePathTeamCache.get(file_path) if FilePathTeamCache.cached?(file_path)

result = T.let(RustCodeOwners.for_file(file_path), T.nilable(T::Hash[Symbol, String]))
return if result.nil?

if result[:team_name].nil?
if result.nil? || result[:team_name].nil?
FilePathTeamCache.set(file_path, nil)
else
FilePathTeamCache.set(file_path, T.let(find_team!(T.must(result[:team_name]), allow_raise: allow_raise), T.nilable(CodeTeams::Team)))
Expand Down
13 changes: 9 additions & 4 deletions spec/lib/code_ownership/private/team_finder_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,16 @@
expect(CodeOwnership::Private::FilePathTeamCache.cached?(file_path)).to be true
end

it 'does not cache when rust returns nil' do
allow(RustCodeOwners).to receive(:for_file).with(file_path).and_return(nil)
it 'caches nil when rust returns nil' do
allow(RustCodeOwners).to receive(:for_file).with(file_path)
.and_return(nil, { team_name: 'Bar' })

expect(described_class.for_file(file_path)).to be_nil
expect(CodeOwnership::Private::FilePathTeamCache.cached?(file_path)).to be false
first = described_class.for_file(file_path)
second = described_class.for_file(file_path)

expect(first).to be_nil
expect(second).to be_nil
expect(CodeOwnership::Private::FilePathTeamCache.cached?(file_path)).to be true
end

it 'caches nil when team_name is nil' do
Expand Down