Class: RightGit::Git::Repository
- Inherits:
-
Object
- Object
- RightGit::Git::Repository
- Includes:
- RightSupport::Log::Mixin
- Defined in:
- lib/right_git/git/repository.rb
Overview
Provides an API for managing a git repository that is suitable for automation. It is assumed that gestures like creating a new repository, branch or tag are manual tasks beyond the scope of automation so those are not covered here. What is provided are APIs for cloning, fetching, listing and grooming git-related objects.
Constant Summary collapse
- COMMIT_SHA1_REGEX =
/^commit ([0-9a-fA-F]{40})$/
- SUBMODULE_STATUS_REGEX =
/^([+\- ])([0-9a-fA-F]{40}) (.*) (.*)$/
Instance Attribute Summary collapse
-
#repo_dir ⇒ Object
readonly
Returns the value of attribute repo_dir.
-
#shell ⇒ Object
readonly
Returns the value of attribute shell.
Class Method Summary collapse
-
.clone_to(repo_url, destination, options = {}) ⇒ Repository
Factory method to clone the repo given by URL to the given destination and return a new Repository object.
Instance Method Summary collapse
-
#branch(branch_name) ⇒ Branch
Factory method for a branch object referencing this repository.
-
#branch_for(branch_name) ⇒ Object
deprecated
Deprecated.
alias for #branch
-
#branches(options = {}) ⇒ Array
Generates a list of known (checked-out) branches from the current git directory.
-
#checkout_to(revision, options = {}) ⇒ TrueClass
Checkout.
-
#clean(*args) ⇒ TrueClass
Cleans the current repository of untracked files.
-
#clean_all(options = {}) ⇒ TrueClass
Cleans everything and optionally cleans .gitignored files.
-
#fetch(*args) ⇒ TrueClass
Fetches using the given options, if any.
-
#fetch_all(options = {}) ⇒ TrueClass
Fetches branch and tag information from remote origin.
-
#git_output(*args) ⇒ String
Executes and returns the output for a git command.
-
#hard_reset_to(revision) ⇒ TrueClass
Performs a hard reset to the given revision, if given, or else the last checked-out SHA.
-
#initialize(repo_dir, options = {}) ⇒ Repository
constructor
A new instance of Repository.
-
#log(revision, options = {}) ⇒ Array
Generates a list of commits using the given ‘git log’ arguments.
-
#sha_for(revision) ⇒ String
Determines the SHA referenced by the given revision.
-
#spit_output(*args) ⇒ TrueClass
Prints the output for a git command.
-
#submodule_paths(options = {}) ⇒ Array
Queries the recursive list of submodule paths for the current workspace.
-
#tag_for(tag_name) ⇒ Branch
Factory method for a tag object referencing this repository.
-
#tags ⇒ Array
Generates a list of known (fetched) tags from the current git directory.
-
#update_submodules(options = {}) ⇒ TrueClass
Updates submodules for the current workspace.
-
#vet_output(*args) ⇒ TrueClass
msysgit on Windows exits zero even when checkout|reset|fetch fails so we need to scan the output for error or fatal messages.
Constructor Details
#initialize(repo_dir, options = {}) ⇒ Repository
Returns a new instance of Repository.
49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 |
# File 'lib/right_git/git/repository.rb', line 49 def initialize(repo_dir, = {}) = { :shell => nil, :logger => nil }.merge() if repo_dir && ::File.directory?(repo_dir) @repo_dir = ::File.(repo_dir) else raise ::ArgumentError.new('A valid repo_dir is required') end @shell = [:shell] || ::RightGit::Shell::Default self.logger = [:logger] || self.class.logger end |
Instance Attribute Details
#repo_dir ⇒ Object (readonly)
Returns the value of attribute repo_dir.
43 44 45 |
# File 'lib/right_git/git/repository.rb', line 43 def repo_dir @repo_dir end |
#shell ⇒ Object (readonly)
Returns the value of attribute shell.
43 44 45 |
# File 'lib/right_git/git/repository.rb', line 43 def shell @shell end |
Class Method Details
.clone_to(repo_url, destination, options = {}) ⇒ Repository
Factory method to clone the repo given by URL to the given destination and return a new Repository object.
Note that cloning to the default working directory-relative location is not currently supported.
76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 |
# File 'lib/right_git/git/repository.rb', line 76 def self.clone_to(repo_url, destination, = {}) destination = ::File.(destination) git_args = ['clone', '--', repo_url, destination] expected_git_dir = ::File.join(destination, '.git') if ::File.directory?(expected_git_dir) raise ::ArgumentError, "Destination is already a git repository: #{destination.inspect}" end repo = self.new('.', ) repo.vet_output(git_args) if ::File.directory?(expected_git_dir) repo.instance_variable_set(:@repo_dir, destination) else raise GitError, "Failed to clone #{repo_url.inspect} to #{destination.inspect}" end repo end |
Instance Method Details
#branch(branch_name) ⇒ Branch
Factory method for a branch object referencing this repository. The branch may be hypothetical (e.g. does not exist yet).
132 133 134 |
# File 'lib/right_git/git/repository.rb', line 132 def branch(branch_name) Branch.new(self, branch_name) end |
#branch_for(branch_name) ⇒ Object
alias for #branch
121 122 123 124 |
# File 'lib/right_git/git/repository.rb', line 121 def branch_for(branch_name) warn "#{self.class.name}#branch_for is deprecated; please use #{self.class.name}#branch instead" branch(branch_name) end |
#branches(options = {}) ⇒ Array
Generates a list of known (checked-out) branches from the current git directory.
143 144 145 146 147 148 149 150 151 |
# File 'lib/right_git/git/repository.rb', line 143 def branches( = {}) branches = BranchCollection.new(self) if [:all] branches else branches.local end end |
#checkout_to(revision, options = {}) ⇒ TrueClass
Checkout.
241 242 243 244 245 246 247 248 249 |
# File 'lib/right_git/git/repository.rb', line 241 def checkout_to(revision, = {}) = { :force => false }.merge() git_args = ['checkout', revision] git_args << '--force' if [:force] vet_output(git_args) true end |
#clean(*args) ⇒ TrueClass
Cleans the current repository of untracked files.
206 207 208 209 210 |
# File 'lib/right_git/git/repository.rb', line 206 def clean(*args) git_args = ['clean', args] spit_output(git_args) true end |
#clean_all(options = {}) ⇒ TrueClass
Cleans everything and optionally cleans .gitignored files.
220 221 222 223 224 225 226 227 228 229 230 231 232 |
# File 'lib/right_git/git/repository.rb', line 220 def clean_all( = {}) = { :directories => false, :gitignored => false, :submodules => false, }.merge() git_args = ['-f'] # force is required or else -n only lists files. git_args << '-f' if [:submodules] # double-tap -f to kill untracked submodules git_args << '-d' if [:directories] git_args << '-x' if [:gitignored] clean(git_args) true end |
#fetch(*args) ⇒ TrueClass
Fetches using the given options, if any.
100 101 102 103 |
# File 'lib/right_git/git/repository.rb', line 100 def fetch(*args) vet_output(['fetch', args]) true end |
#fetch_all(options = {}) ⇒ TrueClass
Fetches branch and tag information from remote origin.
111 112 113 114 115 116 117 118 |
# File 'lib/right_git/git/repository.rb', line 111 def fetch_all( = {}) = { :prune => false }.merge() git_args = ['--all'] git_args << '--prune' if [:prune] fetch(git_args) fetch('--tags') # need a separate call for tags or else you don't get all the tags true end |
#git_output(*args) ⇒ String
Executes and returns the output for a git command. Raises on failure.
331 332 333 |
# File 'lib/right_git/git/repository.rb', line 331 def git_output(*args) inner_execute(:output_for, args) end |
#hard_reset_to(revision) ⇒ TrueClass
Performs a hard reset to the given revision, if given, or else the last checked-out SHA.
257 258 259 260 261 262 |
# File 'lib/right_git/git/repository.rb', line 257 def hard_reset_to(revision) git_args = ['reset', '--hard'] git_args << revision if revision vet_output(git_args) true end |
#log(revision, options = {}) ⇒ Array
Generates a list of commits using the given ‘git log’ arguments.
180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 |
# File 'lib/right_git/git/repository.rb', line 180 def log(revision, = {}) = { :skip => nil, :tail => 10_000, :merges => false, :no_merges => false, :full_hashes => false, }.merge() skip = [:skip] git_args = [ 'log', "-n#{[:tail]}", "--format=\"#{[:full_hashes] ? Commit::LOG_FORMAT_LONG : Commit::LOG_FORMAT}\"" # double-quotes are Windows friendly ] git_args << "--skip #{skip}" if skip git_args << "--merges" if [:merges] git_args << "--no-merges" if [:no_merges] git_args << revision if revision git_output(git_args).lines.map { |line| Commit.new(self, line.strip) } end |
#sha_for(revision) ⇒ String
Determines the SHA referenced by the given revision. Raises on failure.
308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 |
# File 'lib/right_git/git/repository.rb', line 308 def sha_for(revision) # note that 'git show-ref' produces easier-to-parse output but it matches # both local and remote branch to a simple branch name whereas 'git show' # matches at-most-one and requires origin/ for remote branches. git_args = ['show', revision].compact result = nil git_output(git_args).lines.each do |line| if matched = COMMIT_SHA1_REGEX.match(line.strip) result = matched[1] break end end unless result raise GitError, 'Unable to locate commit in show output.' end result end |
#spit_output(*args) ⇒ TrueClass
Prints the output for a git command. Raises on failure.
340 341 342 |
# File 'lib/right_git/git/repository.rb', line 340 def spit_output(*args) inner_execute(:execute, args) end |
#submodule_paths(options = {}) ⇒ Array
Queries the recursive list of submodule paths for the current workspace.
270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 |
# File 'lib/right_git/git/repository.rb', line 270 def submodule_paths( = {}) = { :recursive => false }.merge() git_args = ['submodule', 'status'] git_args << '--recursive' if [:recursive] git_output(git_args).lines.map do |line| data = line.chomp if matched = SUBMODULE_STATUS_REGEX.match(data) matched[3] else raise GitError, "Unexpected output from submodule status: #{data.inspect}" end end end |
#tag_for(tag_name) ⇒ Branch
Factory method for a tag object referencing this repository.
158 159 160 |
# File 'lib/right_git/git/repository.rb', line 158 def tag_for(tag_name) Tag.new(self, tag_name) end |
#tags ⇒ Array
Generates a list of known (fetched) tags from the current git directory.
165 166 167 |
# File 'lib/right_git/git/repository.rb', line 165 def git_output('tag').lines.map { |line| Tag.new(self, line.strip) } end |
#update_submodules(options = {}) ⇒ TrueClass
Updates submodules for the current workspace.
293 294 295 296 297 298 299 300 301 |
# File 'lib/right_git/git/repository.rb', line 293 def update_submodules( = {}) = { :recursive => false }.merge() git_args = ['submodule', 'update', '--init'] git_args << '--recursive' if [:recursive] spit_output(git_args) true end |
#vet_output(*args) ⇒ TrueClass
msysgit on Windows exits zero even when checkout|reset|fetch fails so we need to scan the output for error or fatal messages. it does no harm to do the same on Linux even though the exit code works properly there.
351 352 353 354 355 356 357 358 |
# File 'lib/right_git/git/repository.rb', line 351 def vet_output(*args) last_output = git_output(*args).strip logger.info(last_output) unless last_output.empty? if last_output.downcase =~ /^(error|fatal):/ raise GitError, "Git exited zero but an error was detected in output." end true end |