1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439
|
# frozen_string_literal: true
require 'active_support'
require 'active_support/deprecation'
module Git
Deprecation = ActiveSupport::Deprecation.new('5.0.0', 'Git')
end
require 'git/author'
require 'git/base'
require 'git/branch'
require 'git/branches'
require 'git/command_line_result'
require 'git/command_line'
require 'git/config'
require 'git/diff'
require 'git/encoding_utils'
require 'git/errors'
require 'git/escaped_path'
require 'git/fsck_object'
require 'git/fsck_result'
require 'git/index'
require 'git/lib'
require 'git/log'
require 'git/object'
require 'git/path'
require 'git/remote'
require 'git/repository'
require 'git/status'
require 'git/stash'
require 'git/stashes'
require 'git/url'
require 'git/version'
require 'git/working_directory'
require 'git/worktree'
require 'git/worktrees'
# The Git module provides the basic functions to open a git
# reference to work with. You can open a working directory,
# open a bare repository, initialize a new repo or clone an
# existing remote repository.
#
# @author Scott Chacon (mailto:schacon@gmail.com)
#
module Git
# g.config('user.name', 'Scott Chacon') # sets value
# g.config('user.email', 'email@email.com') # sets value
# g.config('user.name') # returns 'Scott Chacon'
# g.config # returns whole config hash
def config(name = nil, value = nil)
lib = Git::Lib.new
if name && value
# set value
lib.config_set(name, value)
elsif name
# return value
lib.config_get(name)
else
# return hash
lib.config_list
end
end
def self.configure
yield Base.config
end
def self.config
Base.config
end
def global_config(name = nil, value = nil)
self.class.global_config(name, value)
end
# Open a bare repository
#
# Opens a bare repository located in the `git_dir` directory.
# Since there is no working copy, you can not checkout or commit
# but you can do most read operations.
#
# @see https://git-scm.com/docs/gitglossary#Documentation/gitglossary.txt-aiddefbarerepositoryabarerepository
# What is a bare repository?
#
# @example Open a bare repository and retrieve the first commit SHA
# repository = Git.bare('ruby-git.git')
# puts repository.log[0].sha #=> "64c6fa011d3287bab9158049c85f3e85718854a0"
#
# @param [Pathname] git_dir The path to the bare repository directory
# containing an initialized Git repository. If a relative path is given, it
# is converted to an absolute path using
# [File.expand_path](https://www.rubydoc.info/stdlib/core/File.expand_path).
#
# @param [Hash] options The options for this command (see list of valid
# options below)
#
# @option options [String, nil] :git_ssh An optional custom SSH command
#
# - If not specified, uses the global config (Git.configure { |c| c.git_ssh = ... }).
# - If nil, disables SSH for this instance.
# - If a non-empty string, uses that value for this instance.
#
# @option options [Logger] :log A logger to use for Git operations. Git commands
# are logged at the `:info` level. Additional logging is done at the `:debug`
# level.
#
# @return [Git::Base] an object that can execute git commands in the context
# of the bare repository.
#
def self.bare(git_dir, options = {})
Base.bare(git_dir, options)
end
# Clone a repository into an empty or newly created directory
#
# @see https://git-scm.com/docs/git-clone git clone
# @see https://git-scm.com/docs/git-clone#_git_urls_a_id_urls_a GIT URLs
#
# @param repository_url [URI, Pathname] The (possibly remote) repository url to clone
# from. See [GIT URLS](https://git-scm.com/docs/git-clone#_git_urls_a_id_urls_a)
# for more information.
#
# @param directory [Pathname, nil] The directory to clone into
#
# If `directory` is a relative directory it is relative to the `path` option if
# given. If `path` is not given, `directory` is relative to the current working
# directory.
#
# If `nil`, `directory` will be set to the basename of the last component of
# the path from the `repository_url`. For example, for the URL:
# `https://github.com/org/repo.git`, `directory` will be set to `repo`.
#
# If the last component of the path is `.git`, the next-to-last component of
# the path is used. For example, for the URL `/Users/me/foo/.git`, `directory`
# will be set to `foo`.
#
# @param [Hash] options The options for this command (see list of valid
# options below)
#
# @option options [Boolean] :bare Make a bare Git repository. See
# [what is a bare repository?](https://git-scm.com/docs/gitglossary#Documentation/gitglossary.txt-aiddefbarerepositoryabarerepository).
#
# @option options [String] :branch The name of a branch or tag to checkout
# instead of the default branch.
#
# @option options [Array, String] :config A list of configuration options to
# set on the newly created repository.
#
# @option options [Integer] :depth Create a shallow clone with a history
# truncated to the specified number of commits.
#
# @option options [String] :filter Request that the server send a partial
# clone according to the given filter
#
# @option options [Boolean, nil] :single_branch Control whether the clone
# limits fetch refspecs to a single branch.
# - If nil (default), no flag is passed and the Git default is used.
# - If true, `--single-branch` is passed to limit the refspec to the
# checkout branch.
# - If false, `--no-single-branch` is passed to broaden the refspec (useful
# for shallow clones that should include all branches).
#
# @option options [String, nil] :git_ssh An optional custom SSH command
#
# - If not specified, uses the global config (Git.configure { |c| c.git_ssh = ... }).
# - If nil, disables SSH for this instance.
# - If a non-empty string, uses that value for this instance.
#
# @option options [Logger] :log A logger to use for Git operations. Git
# commands are logged at the `:info` level. Additional logging is done
# at the `:debug` level.
#
# @option options [Boolean] :mirror Set up a mirror of the source repository.
#
# @option options [String] :origin Use the value instead `origin` to track
# the upstream repository.
#
# @option options [Pathname] :path The directory to clone into. May be used
# as an alternative to the `directory` parameter. If specified, the
# `path` option is used instead of the `directory` parameter.
#
# @option options [Boolean] :recursive After the clone is created, initialize
# all submodules within, using their default settings.
#
# @example Clone into the default directory `ruby-git`
# git = Git.clone('https://github.com/ruby-git/ruby-git.git')
#
# @example Clone and then checkout the `development` branch
# git = Git.clone('https://github.com/ruby-git/ruby-git.git', branch: 'development')
#
# @example Clone into a different directory `my-ruby-git`
# git = Git.clone('https://github.com/ruby-git/ruby-git.git', 'my-ruby-git')
# # or:
# git = Git.clone('https://github.com/ruby-git/ruby-git.git', path: 'my-ruby-git')
#
# @example Create a bare repository in the directory `ruby-git.git`
# git = Git.clone('https://github.com/ruby-git/ruby-git.git', bare: true)
#
# @example Clone a repository and set a single config option
# git = Git.clone(
# 'https://github.com/ruby-git/ruby-git.git',
# config: 'submodule.recurse=true'
# )
#
# @example Clone a repository and set multiple config options
# git = Git.clone(
# 'https://github.com/ruby-git/ruby-git.git',
# config: ['user.name=John Doe', 'user.email=john@doe.com']
# )
#
# @example Clone using a specific SSH key
# git = Git.clone(
# 'git@github.com:ruby-git/ruby-git.git',
# 'local-dir',
# git_ssh: 'ssh -i /path/to/private_key'
# )
#
# @return [Git::Base] an object that can execute git commands in the context
# of the cloned local working copy or cloned repository.
#
def self.clone(repository_url, directory = nil, options = {})
clone_to_options = options.slice(:bare, :mirror)
directory ||= Git::URL.clone_to(repository_url, **clone_to_options)
Base.clone(repository_url, directory, options)
end
# Returns the name of the default branch of the given repository
#
# @example with a URI string
# Git.default_branch('https://github.com/ruby-git/ruby-git') # => 'master'
# Git.default_branch('https://github.com/rspec/rspec-core') # => 'main'
#
# @example with a URI object
# repository_uri = URI('https://github.com/ruby-git/ruby-git')
# Git.default_branch(repository_uri) # => 'master'
#
# @example with a local repository
# Git.default_branch('.') # => 'master'
#
# @example with a local repository Pathname
# repository_path = Pathname('.')
# Git.default_branch(repository_path) # => 'master'
#
# @example with the logging option
# logger = Logger.new(STDOUT, level: Logger::INFO)
# Git.default_branch('.', log: logger) # => 'master'
# I, [2022-04-13T16:01:33.221596 #18415] INFO -- : git '-c' 'core.quotePath=true'
# '-c' 'color.ui=false' ls-remote '--symref' '--' '.' 'HEAD' 2>&1
#
# @param repository [URI, Pathname, String] The (possibly remote) repository to get the default branch name for
#
# See [GIT URLS](https://git-scm.com/docs/git-clone#_git_urls_a_id_urls_a)
# for more information.
#
# @param [Hash] options The options for this command (see list of valid
# options below)
#
# @option options [Logger] :log A logger to use for Git operations. Git
# commands are logged at the `:info` level. Additional logging is done
# at the `:debug` level.
#
# @return [String] the name of the default branch
#
def self.default_branch(repository, options = {})
Base.repository_default_branch(repository, options)
end
# Export the current HEAD (or a branch, if <tt>options[:branch]</tt>
# is specified) into the +name+ directory, then remove all traces of git from the
# directory.
#
# See +clone+ for options. Does not obey the <tt>:remote</tt> option,
# since the .git info will be deleted anyway; always uses the default
# remote, 'origin.'
def self.export(repository, name, options = {})
options.delete(:remote)
repo = clone(repository, name, { depth: 1 }.merge(options))
repo.checkout("origin/#{options[:branch]}") if options[:branch]
FileUtils.rm_r File.join(repo.dir.to_s, '.git')
end
# Same as g.config, but forces it to be at the global level
#
# g.config('user.name', 'Scott Chacon') # sets value
# g.config('user.email', 'email@email.com') # sets value
# g.config('user.name') # returns 'Scott Chacon'
# g.config # returns whole config hash
def self.global_config(name = nil, value = nil)
lib = Git::Lib.new(nil, nil)
if name && value
# set value
lib.global_config_set(name, value)
elsif name
# return value
lib.global_config_get(name)
else
# return hash
lib.global_config_list
end
end
# Create an empty Git repository or reinitialize an existing Git repository
#
# @param [Pathname] directory If the `:bare` option is NOT given or is not
# `true`, the repository will be created in `"#{directory}/.git"`.
# Otherwise, the repository is created in `"#{directory}"`.
#
# All directories along the path to `directory` are created if they do not exist.
#
# A relative path is referenced from the current working directory of the process
# and converted to an absolute path using
# [File.expand_path](https://www.rubydoc.info/stdlib/core/File.expand_path).
#
# @param [Hash] options The options for this command (see list of valid
# options below)
#
# @option options [Boolean] :bare Instead of creating a repository at
# `"#{directory}/.git"`, create a bare repository at `"#{directory}"`.
# See [what is a bare repository?](https://git-scm.com/docs/gitglossary#Documentation/gitglossary.txt-aiddefbarerepositoryabarerepository).
#
# @option options [String] :initial_branch Use the specified name for the
# initial branch in the newly created repository.
#
# @option options [Pathname] :repository the path to put the newly initialized
# Git repository. The default for non-bare repository is `"#{directory}/.git"`.
#
# A relative path is referenced from the current working directory of the process
# and converted to an absolute path using
# [File.expand_path](https://www.rubydoc.info/stdlib/core/File.expand_path).
#
# @option options [String, nil] :git_ssh An optional custom SSH command
#
# - If not specified, uses the global config (Git.configure { |c| c.git_ssh = ... }).
# - If nil, disables SSH for this instance.
# - If a non-empty string, uses that value for this instance.
#
# @option options [Logger] :log A logger to use for Git operations. Git
# commands are logged at the `:info` level. Additional logging is done
# at the `:debug` level.
#
# @return [Git::Base] an object that can execute git commands in the context
# of the newly initialized repository
#
# @example Initialize a repository in the current directory
# git = Git.init
#
# @example Initialize a repository in some other directory
# git = Git.init '~/code/ruby-git'
#
# @example Initialize a bare repository
# git = Git.init '~/code/ruby-git.git', bare: true
#
# @example Initialize a repository in a non-default location (outside of the working copy)
# git = Git.init '~/code/ruby-git', repository: '~/code/ruby-git.git'
#
# @see https://git-scm.com/docs/git-init git init
#
def self.init(directory = '.', options = {})
Base.init(directory, options)
end
# returns a Hash containing information about the references
# of the target repository
#
# options
# :refs
#
# @param [String|NilClass] location the target repository location or nil for '.'
# @return [{String=>Hash}] the available references of the target repo.
def self.ls_remote(location = nil, options = {})
Git::Lib.new.ls_remote(location, options)
end
# Open a an existing Git working directory
#
# Git.open will most likely be the most common way to create
# a git reference, referring to an existing working directory.
#
# If not provided in the options, the library will assume
# the repository and index are in the default places (`.git/`, `.git/index`).
#
# @example Open the Git working directory in the current directory
# git = Git.open
#
# @example Open a Git working directory in some other directory
# git = Git.open('~/Projects/ruby-git')
#
# @example Use a logger to see what is going on
# logger = Logger.new(STDOUT)
# git = Git.open('~/Projects/ruby-git', log: logger)
#
# @example Open a working copy whose repository is in a non-standard directory
# git = Git.open('~/Projects/ruby-git', repository: '~/Project/ruby-git.git')
#
# @param [Pathname] working_dir the path to the working directory to use
# for git commands.
#
# A relative path is referenced from the current working directory of the process
# and converted to an absolute path using
# [File.expand_path](https://www.rubydoc.info/stdlib/core/File.expand_path).
#
# @param [Hash] options The options for this command (see list of valid
# options below)
#
# @option options [Pathname] :repository used to specify a non-standard path to
# the repository directory. The default is `"#{working_dir}/.git"`.
#
# @option options [Pathname] :index used to specify a non-standard path to an
# index file. The default is `"#{working_dir}/.git/index"`
#
# @option options [String, nil] :git_ssh An optional custom SSH command
#
# - If not specified, uses the global config (Git.configure { |c| c.git_ssh = ... }).
# - If nil, disables SSH for this instance.
# - If a non-empty string, uses that value for this instance.
#
# @option options [Logger] :log A logger to use for Git operations. Git
# commands are logged at the `:info` level. Additional logging is done
# at the `:debug` level.
#
# @return [Git::Base] an object that can execute git commands in the context
# of the opened working copy
#
def self.open(working_dir, options = {})
Base.open(working_dir, options)
end
# Return the version of the git binary
#
# @example
# Git.binary_version # => [2, 46, 0]
#
# @return [Array<Integer>] the version of the git binary
#
def self.binary_version(binary_path = Git::Base.config.binary_path)
Base.binary_version(binary_path)
end
end
|