lib/gdk/version_checker.rb (58 lines of code) (raw):
# frozen_string_literal: true
require 'date'
require 'json'
module GDK
class VersionChecker
TIMESTAMP_FORMAT = '%Y-%m-%dT%H:%M:%S%z'
COMMIT_JSON = '{"sha": "%h", "timestamp": "%ad"}'
SHOW_COMMIT_CMD = "show -s --format='#{COMMIT_JSON}' --date=format:'#{TIMESTAMP_FORMAT}'".freeze
DIFF_FORMAT =
"Current commit (%<current_commit>s) is %<diff>s origin/%<main_branch>s (%<latest_main_commit>s)"
GitCommit = Data.define(:sha, :timestamp)
def initialize(service_path:, main_branch: 'main')
@service_path = service_path
@main_branch = main_branch
end
def diff_message
return if current_commit.sha == latest_main_commit.sha
format(
DIFF_FORMAT,
current_commit: current_commit.sha,
diff: commits_diff,
main_branch: main_branch,
latest_main_commit: latest_main_commit.sha
).strip
end
def latest_main_commit
@latest_main_commit ||= begin
git("fetch")
commit(ref: "origin/#{main_branch}")
end
end
def current_commit
@current_commit ||= commit
end
private
attr_reader :service_path, :main_branch
def commits_diff
commits_ahead = count_commits_between(current_commit, latest_main_commit)
commits_behind = count_commits_between(latest_main_commit, current_commit)
ahead_message = "#{commits_ahead} commits ahead of" if commits_ahead.positive?
behind_message = "#{commits_behind} commits behind" if commits_behind.positive?
[behind_message, ahead_message].compact.join(' and is ')
end
def count_commits_between(from_commit, to_commit)
git("rev-list --count --left-only #{from_commit.sha}...#{to_commit.sha}").to_i
end
def commit(ref: nil)
git("#{SHOW_COMMIT_CMD} #{ref}")
.then { |string| JSON.parse(string, symbolize_names: true) }
.then { |hash| hash.merge(timestamp: ::DateTime.strptime(hash[:timestamp], TIMESTAMP_FORMAT)) }
.then { |hash| GitCommit.new(**hash) }
end
def git(cmd)
Shellout
.new("git #{cmd}".strip, chdir: service_path)
.run
end
end
end