lib/fcom/querier.rb in fcom-0.10.0 vs lib/fcom/querier.rb in fcom-0.11.0
- old
+ new
@@ -3,18 +3,20 @@
require_relative 'options_helpers.rb'
# This class executes a system command to retrieve the git history, which is passed through `rg`
# (ripgrep), and then ultimately is fed back to `fcom` for parsing.
class Fcom::Querier
+ prepend MemoWise
include ::Fcom::OptionsHelpers
def initialize(options)
@options = options
end
# rubocop:disable Metrics/CyclomaticComplexity
# rubocop:disable Metrics/PerceivedComplexity
+ # rubocop:disable Metrics/MethodLength
def query
expression_to_match = search_string
expression_to_match = Regexp.escape(expression_to_match).gsub('\\ ', ' ') unless regex_mode?
if expression_to_match.nil? || expression_to_match.empty?
@@ -22,39 +24,90 @@
exit
end
quote = expression_to_match.include?('"') ? "'" : '"'
- command = <<~COMMAND.squish
- git log
- --format="commit %s|%H|%an|%cr (%ci)"
- --patch
- --full-diff
- --no-textconv
- #{%(--author="#{author}") if author}
- #{"--since=#{days}.day" unless days.nil?}
- --
- #{path}
- |
+ commands =
+ filename_by_most_recent_containing_commit.map do |commit, path_at_commit|
+ <<~COMMAND.squish
+ git log
+ --format="commit %s|%H|%an|%cr (%ci)"
+ --patch
+ --full-diff
+ --no-textconv
+ #{%(--author="#{author}") if author}
+ #{"--since=#{days}.day" unless days.nil?}
+ #{commit}
+ --
+ #{path_at_commit}
+ |
- rg #{quote}(#{expression_to_match})|(^commit )|(^diff )#{quote}
- --color never
- #{'--ignore-case' if ignore_case?}
- #{@options[:rg_options]}
- |
+ rg #{quote}(#{expression_to_match})|(^commit )|(^diff )#{quote}
+ --color never
+ #{'--ignore-case' if ignore_case?}
+ #{@options[:rg_options]}
+ |
- #{'exe/' if development?}fcom #{quote}#{search_string}#{quote}
- #{"--days #{days}" if days}
- #{'--regex' if regex_mode?}
- #{'--debug' if debug?}
- #{'--ignore-case' if ignore_case?}
- --path #{path}
- --parse-mode
- --repo #{repo}
- COMMAND
+ #{'exe/' if development?}fcom #{quote}#{search_string}#{quote}
+ #{"--days #{days}" if days}
+ #{'--regex' if regex_mode?}
+ #{'--debug' if debug?}
+ #{'--ignore-case' if ignore_case?}
+ --path #{path_at_commit}
+ --parse-mode
+ --repo #{repo}
+ COMMAND
+ end
- Fcom.logger.debug("Executing command: #{command}")
- system(command)
+ previous_command_generated_output = false
+
+ commands.each do |command|
+ Fcom.logger.debug("Executing command: #{command}")
+ output = `#{command}`
+
+ if output.empty?
+ previous_command_generated_output = false
+ else
+ if previous_command_generated_output
+ puts("\n\n") # print blank lines for spacing
+ end
+
+ previous_command_generated_output = true
+
+ puts(output)
+ end
+ end
end
+ # rubocop:enable Metrics/MethodLength
# rubocop:enable Metrics/PerceivedComplexity
# rubocop:enable Metrics/CyclomaticComplexity
+
+ private
+
+ memo_wise \
+ def filename_by_most_recent_containing_commit
+ {
+ most_recent_commit_with_file => path,
+ }.merge(renames.transform_keys { "#{_1}^" })
+ end
+
+ memo_wise \
+ def most_recent_commit_with_file
+ if system(%(test -e "#{path}"))
+ 'HEAD'
+ else
+ `git log --all -1 --format="%H" -- "#{path}"`.rstrip
+ end
+ end
+
+ memo_wise \
+ def renames
+ `git log HEAD --format=%H --name-status --follow --diff-filter=R -- '#{path}'`.
+ split(/\n(?=[0-9a-f]{40})/).
+ to_h do |sha_and_name_info|
+ sha_and_name_info.
+ match(/(?<sha>[0-9a-f]{40})\n\nR\d+\s+(?<previous_name>\S+)?/).
+ named_captures.
+ values_at('sha', 'previous_name')
+ end
+ end
end