mirror of
https://github.com/Homebrew/brew.git
synced 2025-07-14 16:09:03 +08:00
134 lines
4.0 KiB
Ruby
134 lines
4.0 KiB
Ruby
# typed: strict
|
|
# frozen_string_literal: true
|
|
|
|
require "utils/git"
|
|
require "utils/popen"
|
|
|
|
# Given a {Pathname}, provides methods for querying Git repository information.
|
|
# @see Utils::Git
|
|
# @api private
|
|
class GitRepository
|
|
sig { returns(Pathname) }
|
|
attr_reader :pathname
|
|
|
|
sig { params(pathname: Pathname).void }
|
|
def initialize(pathname)
|
|
@pathname = pathname
|
|
end
|
|
|
|
sig { returns(T::Boolean) }
|
|
def git_repo?
|
|
pathname.join(".git").exist?
|
|
end
|
|
|
|
# Gets the URL of the Git origin remote.
|
|
sig { returns(T.nilable(String)) }
|
|
def origin_url
|
|
popen_git("config", "--get", "remote.origin.url")
|
|
end
|
|
|
|
# Sets the URL of the Git origin remote.
|
|
sig { params(origin: String).returns(T.nilable(T::Boolean)) }
|
|
def origin_url=(origin)
|
|
return if !git_repo? || !Utils::Git.available?
|
|
|
|
safe_system Utils::Git.git, "remote", "set-url", "origin", origin, chdir: pathname
|
|
end
|
|
|
|
# Gets the full commit hash of the HEAD commit.
|
|
sig { params(safe: T::Boolean).returns(T.nilable(String)) }
|
|
def head_ref(safe: false)
|
|
popen_git("rev-parse", "--verify", "--quiet", "HEAD", safe: safe)
|
|
end
|
|
|
|
# Gets a short commit hash of the HEAD commit.
|
|
sig { params(length: T.nilable(Integer), safe: T::Boolean).returns(T.nilable(String)) }
|
|
def short_head_ref(length: nil, safe: false)
|
|
short_arg = length.present? ? "--short=#{length}" : "--short"
|
|
popen_git("rev-parse", short_arg, "--verify", "--quiet", "HEAD", safe: safe)
|
|
end
|
|
|
|
# Gets the relative date of the last commit, e.g. "1 hour ago"
|
|
sig { returns(T.nilable(String)) }
|
|
def last_committed
|
|
popen_git("show", "-s", "--format=%cr", "HEAD")
|
|
end
|
|
|
|
# Gets the name of the currently checked-out branch, or HEAD if the repository is in a detached HEAD state.
|
|
sig { params(safe: T::Boolean).returns(T.nilable(String)) }
|
|
def branch_name(safe: false)
|
|
popen_git("rev-parse", "--abbrev-ref", "HEAD", safe: safe)
|
|
end
|
|
|
|
# Change the name of a local branch
|
|
sig { params(old: String, new: String).void }
|
|
def rename_branch(old:, new:)
|
|
popen_git("branch", "-m", old, new)
|
|
end
|
|
|
|
# Set an upstream branch for a local branch to track
|
|
sig { params(local: String, origin: String).void }
|
|
def set_upstream_branch(local:, origin:)
|
|
popen_git("branch", "-u", "origin/#{origin}", local)
|
|
end
|
|
|
|
# Gets the name of the default origin HEAD branch.
|
|
sig { returns(T.nilable(String)) }
|
|
def origin_branch_name
|
|
popen_git("symbolic-ref", "-q", "--short", "refs/remotes/origin/HEAD")&.split("/")&.last
|
|
end
|
|
|
|
# Returns true if the repository's current branch matches the default origin branch.
|
|
sig { returns(T.nilable(T::Boolean)) }
|
|
def default_origin_branch?
|
|
origin_branch_name == branch_name
|
|
end
|
|
|
|
# Returns the date of the last commit, in YYYY-MM-DD format.
|
|
sig { returns(T.nilable(String)) }
|
|
def last_commit_date
|
|
popen_git("show", "-s", "--format=%cd", "--date=short", "HEAD")
|
|
end
|
|
|
|
# Returns true if the given branch exists on origin
|
|
sig { params(branch: String).returns(T::Boolean) }
|
|
def origin_has_branch?(branch)
|
|
popen_git("ls-remote", "--heads", "origin", branch).present?
|
|
end
|
|
|
|
sig { void }
|
|
def set_head_origin_auto
|
|
popen_git("remote", "set-head", "origin", "--auto")
|
|
end
|
|
|
|
# Gets the full commit message of the specified commit, or of the HEAD commit if unspecified.
|
|
sig { params(commit: String, safe: T::Boolean).returns(T.nilable(String)) }
|
|
def commit_message(commit = "HEAD", safe: false)
|
|
popen_git("log", "-1", "--pretty=%B", commit, "--", safe: safe, err: :out)&.strip
|
|
end
|
|
|
|
sig { returns(String) }
|
|
def to_s
|
|
pathname.to_s
|
|
end
|
|
|
|
private
|
|
|
|
sig { params(args: T.untyped, safe: T::Boolean, err: T.nilable(Symbol)).returns(T.nilable(String)) }
|
|
def popen_git(*args, safe: false, err: nil)
|
|
unless git_repo?
|
|
return unless safe
|
|
|
|
raise "Not a Git repository: #{pathname}"
|
|
end
|
|
|
|
unless Utils::Git.available?
|
|
return unless safe
|
|
|
|
raise "Git is unavailable"
|
|
end
|
|
|
|
Utils.popen_read(Utils::Git.git, *args, safe: safe, chdir: pathname, err: err).chomp.presence
|
|
end
|
|
end
|