lib/code_ownership.rb in code_ownership-1.29.2 vs lib/code_ownership.rb in code_ownership-1.29.3
- old
+ new
@@ -56,11 +56,10 @@
ownership_information << 'This team owns nothing in this category.'
else
ownership_information += ownership_for_mapper
end
-
ownership_information << ""
end
ownership_information.join("\n")
end
@@ -91,12 +90,30 @@
# Given a backtrace from either `Exception#backtrace` or `caller`, find the
# first line that corresponds to a file with assigned ownership
sig { params(backtrace: T.nilable(T::Array[String]), excluded_teams: T::Array[::CodeTeams::Team]).returns(T.nilable(::CodeTeams::Team)) }
def for_backtrace(backtrace, excluded_teams: [])
- return unless backtrace
+ first_owned_file_for_backtrace(backtrace, excluded_teams: excluded_teams)&.first
+ end
+ # Given a backtrace from either `Exception#backtrace` or `caller`, find the
+ # first owned file in it, useful for figuring out which file is being blamed.
+ sig { params(backtrace: T.nilable(T::Array[String]), excluded_teams: T::Array[::CodeTeams::Team]).returns(T.nilable([::CodeTeams::Team, String])) }
+ def first_owned_file_for_backtrace(backtrace, excluded_teams: [])
+ backtrace_with_ownership(backtrace).each do |(team, file)|
+ if team && !excluded_teams.include?(team)
+ return [team, file]
+ end
+ end
+
+ nil
+ end
+
+ sig { params(backtrace: T.nilable(T::Array[String])).returns(T::Enumerable[[T.nilable(::CodeTeams::Team), String]]) }
+ def backtrace_with_ownership(backtrace)
+ return [] unless backtrace
+
# The pattern for a backtrace hasn't changed in forever and is considered
# stable: https://github.com/ruby/ruby/blob/trunk/vm_backtrace.c#L303-L317
#
# This pattern matches a line like the following:
#
@@ -108,21 +125,22 @@
(?<line>\d+) # Matches '43'
:in\s
`(?<function>.*)' # Matches "`block (3 levels) in create'"
\z}x
- backtrace.each do |line|
+ backtrace.lazy.filter_map do |line|
match = line.match(backtrace_line)
+ next unless match
- if match
- team = CodeOwnership.for_file(T.must(match[:file]))
- if team && !excluded_teams.include?(team)
- return team
- end
- end
+ file = T.must(match[:file])
+
+ [
+ CodeOwnership.for_file(file),
+ file,
+ ]
end
- nil
end
+ private_class_method(:backtrace_with_ownership)
sig { params(klass: T.nilable(T.any(Class, Module))).returns(T.nilable(::CodeTeams::Team)) }
def for_class(klass)
@memoized_values ||= T.let(@memoized_values, T.nilable(T::Hash[String, T.nilable(::CodeTeams::Team)]))
@memoized_values ||= {}