class ChefCLI::CookbookProfiler::Git
def self.uncache
def self.uncache @@git_memo = {} end
def clean?
def clean? git!("diff-files --quiet", returns: [0, 1]).exitstatus == 0 end
def current_branch
def current_branch @current_branch ||= detect_current_branch end
def detect_current_branch
def detect_current_branch branch = git!("rev-parse --abbrev-ref HEAD").stdout.strip @unborn_branch = false branch rescue Mixlib::ShellOut::ShellCommandFailed => e # "unborn" branch, i.e. one with no commits or # verify_ref_cmd didn't error, we don't know why # the original git command failed, so re-raise. unborn_branch_ref || raise(e) end
def get_repo_path
def get_repo_path unless @repo_path @repo_path = system_command("git rev-parse --show-toplevel", { cwd: cookbook_path }).stdout.strip end @repo_path end
def git(subcommand, options = {})
def git(subcommand, options = {}) # memoize commands per-repo repo_path = get_repo_path memo_key = [repo_path, subcommand, options] if @@git_memo.key?(memo_key) rv = @@git_memo[memo_key] else options = { cwd: cookbook_path }.merge(options) rv = system_command("git #{subcommand}", options) @@git_memo[memo_key] = rv end rv end
def git!(subcommand, options = {})
def git!(subcommand, options = {}) cmd = git(subcommand, options) cmd.error! cmd end
def have_remote?
def have_remote? !remote_name.empty? && remote_name != "." end
def initialize(cookbook_path)
def initialize(cookbook_path) @cookbook_path = cookbook_path @repo_path = nil @unborn_branch = nil @unborn_branch_ref = nil end
def profile_data
-
(Hash)
- Hashed used for pinning cookbook versions within a Policyfile.lock
def profile_data { "scm" => "git", # To get this info, you need to do something like: # figure out branch or assume 'main' # git config --get branch.main.remote # git config --get remote.opscode.url "remote" => remote, "revision" => revision, "working_tree_clean" => clean?, "published" => !unpublished_commits?, "synchronized_remote_branches" => synchronized_remotes, } end
def remote
def remote @remote_url ||= if have_remote? git!("config --get remote.#{remote_name}.url").stdout.strip else nil end end
def remote_name
def remote_name @remote_name ||= git!("config --get branch.#{current_branch}.remote", returns: [0, 1]).stdout.strip end
def revision
def revision git!("rev-parse HEAD").stdout.strip rescue Mixlib::ShellOut::ShellCommandFailed => e # We may have an "unborn" branch, i.e. one with no commits. if unborn_branch_ref nil else # if we got here, but verify_ref_cmd didn't error, we don't know why # the original git command failed, so re-raise. raise e end end
def synchronized_remotes
def synchronized_remotes @synchronized_remotes ||= git!("branch -r --contains #{revision}").stdout.lines.map(&:strip) rescue Mixlib::ShellOut::ShellCommandFailed => e # We may have an "unborn" branch, i.e. one with no commits. if unborn_branch_ref [] else # if we got here, but verify_ref_cmd didn't error, we don't know why # the original git command failed, so re-raise. raise e end end
def unborn_branch_ref
def unborn_branch_ref @unborn_branch_ref ||= begin strict_branch_ref = git!("symbolic-ref -q HEAD").stdout.strip verify_ref_cmd = git("show-ref --verify #{strict_branch_ref}") if verify_ref_cmd.error? @unborn_branch = true strict_branch_ref else # if we got here, but verify_ref_cmd didn't error, then `git # rev-parse` is probably failing for a reason we haven't anticipated. # Calling code should detect this and re-raise. nil end end end
def unpublished_commits?
def unpublished_commits? synchronized_remotes.empty? end