class Thicket::Log
Constants
- LOG_PARSE_REGEX
Public Class Methods
# File lib/thicket/log.rb, line 10 def initialize(options) @options = options @count_parsed = 0 end
Public Instance Methods
Gets a printable version of the log for purposes of printing to a terminal. This effectively builds the final printable log to display to the user.
# File lib/thicket/log.rb, line 18 def print FileUtils.cd(git_working_directory) `#{git_log_command}`.encode("UTF-8", invalid: :replace, undef: :replace) .split("\n") .each do |l| puts process_git_log_line(l) next unless @options[:limit] && @count_parsed >= @options[:limit] puts "..." puts "Stopped after #{@options[:limit]} commits. More commit history exists." break end rescue Errno::EPIPE, SystemExit, Interrupt exit end
Private Instance Methods
The path to the git executable. Honors the passed in command line option, and falls back to just “git”.
# File lib/thicket/log.rb, line 184 def git_executable @options[:git_binary] || "git" end
The command string which gets the raw git log input straight from git. Includes all formatting and color escape codes.
# File lib/thicket/log.rb, line 173 def git_log_command format = "%C(yellow)%h %Cgreen%aI %Cblue{%an}%Cred%d %Creset%s" cmd = +"#{git_executable} log --oneline --decorate --color " \ "--graph --pretty=format:'#{format}'" cmd << " --all" if @options[:all] cmd end
The directory which represents the git project that we want to retreive logs for. Uses the command line option if it was provided, and falls back to the current working directory otherwise.
# File lib/thicket/log.rb, line 191 def git_working_directory @options[:project_directory] || Dir.pwd end
Takes an input log string and a commit date/time and replaces it in the log string with a formatted version.
# File lib/thicket/log.rb, line 55 def process_date_time(time_string, line, have_refs) seconds_ago = Time.now - Time.iso8601(time_string) measure = TimeMeasure.measures.find { |m| m.threshold < seconds_ago } quantity = (seconds_ago / measure.length).floor to_sub = +"#{quantity}#{measure.abbreviation}".rjust(3) to_sub << "\e[31m" if have_refs # add color if we have refs in this line line.sub(time_string, to_sub) end
Takes a single line of raw, colored git log output and manipulates it into the desired format.
# File lib/thicket/log.rb, line 39 def process_git_log_line(line) @padding_char = @padding_char == " " ? "-" : " " line.match(LOG_PARSE_REGEX) do |matcher| line = process_date_time(matcher[1], line, matcher[3]) line = process_refs(matcher[3], line) if matcher[3] && @options[:consolidate_refs] line = process_message_prefix(matcher[4], line) if @options[:color_prefixes] line = process_author_name(matcher[2], line) @count_parsed += 1 end line end
Takes an input log string and commit message, finds commit messages prefixes, and darkens them.
# File lib/thicket/log.rb, line 121 def process_message_prefix(message, line) prefix_regex = %r{^(?=.*[0-9])([A-Z\d-]+?[: \/])} message.match(prefix_regex) do |matcher| prefix = matcher[1] return line.sub(/([^\/])#{prefix}/, "\\1\e[30m#{prefix}\e[m") end line end
Takes an input log string and a refs list, and formats the refs list in a more consolidated way.
# File lib/thicket/log.rb, line 67 def process_refs(refs, line) original_refs = refs main_remote = @options[:main_remote] || "origin" refs = strip_color(refs).split(",").map(&:strip) tags = [] head_ref_index = refs.find_index { |r| r.start_with?("HEAD -> ") } refs_to_delete = [] refs.each do |r| refs_to_delete << r if r == "#{main_remote}/HEAD" next if r.start_with?("#{main_remote}/") ref_without_head = r.sub("HEAD -> ", "") branch = "#{main_remote}/#{ref_without_head}" if refs.include?(branch) refs_to_delete << branch r << "#" end if r.start_with?("tag:") tag = r tag.slice!("tag: ") refs_to_delete << r tags << tag end end refs[head_ref_index].sub!("HEAD -> ", "@") if head_ref_index refs.delete_if { |r| refs_to_delete.include? r } refs = if refs.any? "(#{refs.join(", ")})" else "" end substitute = if tags.any? tags = "\e[35m[#{tags.join(", ")}]\e[0m" if refs.empty? tags else "#{refs} #{tags}" end else refs end line.sub("(#{original_refs})", substitute) end
Strips ANSI color escape codes from a string. Colorize's String#uncolorize would be used, but it seems to only remove escape codes which match a strict pattern, which git log's colored output doesn't follow.
# File lib/thicket/log.rb, line 156 def strip_color(string) color_escape_regex = /\e\[([;\d]+)?m/ string.gsub(color_escape_regex, "").chomp end
Gets the width of the terminal window in columns. Memoizes the result to avoid more shell calls, and because the terminal size won't be changing during the execution of this script.
# File lib/thicket/log.rb, line 164 def terminal_width @terminal_width ||= `tput cols`.to_i rescue Errno::ENOENT puts "Failed to determine terminal column width." exit end