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