-
Notifications
You must be signed in to change notification settings - Fork 356
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #308 from adrienthebo/issue/master/rk-16-extract-g…
…it-implementation REVIEW: Refactor Git implementation, extract platform specific code
- Loading branch information
Showing
23 changed files
with
835 additions
and
181 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
require 'r10k/git' | ||
require 'r10k/git/base_repository' | ||
require 'r10k/logging' | ||
|
||
# Create and manage Git bare repositories. | ||
class R10K::Git::BareRepository < R10K::Git::BaseRepository | ||
|
||
# @return [Pathname] The path to this Git repository | ||
def git_dir | ||
@path | ||
end | ||
|
||
# @param basedir [String] The base directory of the Git repository | ||
# @param dirname [String] The directory name of the Git repository | ||
def initialize(basedir, dirname) | ||
@path = Pathname.new(File.join(basedir, dirname)) | ||
end | ||
|
||
def clone(remote) | ||
git ['clone', '--mirror', remote, git_dir.to_s] | ||
end | ||
|
||
def fetch | ||
git ['fetch', '--prune'], :git_dir => git_dir.to_s | ||
end | ||
|
||
def exist? | ||
@path.exist? | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,102 @@ | ||
require 'r10k/git' | ||
require 'r10k/logging' | ||
|
||
class R10K::Git::BaseRepository | ||
|
||
# @abstract | ||
# @return [Pathname] The path to the Git directory | ||
def git_dir | ||
raise NotImplementedError | ||
end | ||
|
||
# Resolve the given Git ref to a commit | ||
# | ||
# @param pattern [String] The git ref to resolve | ||
# @return [String, nil] The commit SHA if the ref could be resolved, nil otherwise. | ||
def resolve(pattern) | ||
result = git ['rev-parse', "#{pattern}^{commit}"], :git_dir => git_dir.to_s, :raise_on_fail => false | ||
if result.success? | ||
result.stdout | ||
end | ||
end | ||
|
||
# For compatibility with R10K::Git::Ref | ||
# @todo remove alias | ||
alias rev_parse resolve | ||
|
||
# @return [Array<String>] All local branches in this repository | ||
def branches | ||
for_each_ref('refs/heads') | ||
end | ||
|
||
# @return [Array<String>] All tags in this repository | ||
def tags | ||
for_each_ref('refs/tags') | ||
end | ||
|
||
# @return [Symbol] The type of the given ref, one of :branch, :tag, :commit, or :unknown | ||
def ref_type(pattern) | ||
if branches.include? pattern | ||
:branch | ||
elsif tags.include? pattern | ||
:tag | ||
elsif resolve(pattern) | ||
:commit | ||
else | ||
:unknown | ||
end | ||
end | ||
|
||
include R10K::Logging | ||
|
||
private | ||
|
||
# @param pattern [String] | ||
def for_each_ref(pattern) | ||
matcher = %r[#{pattern}/(.*)$] | ||
output = git ['for-each-ref', pattern, '--format', '%(refname)'], :git_dir => git_dir.to_s | ||
output.stdout.scan(matcher).flatten | ||
end | ||
|
||
# Wrap git commands | ||
# | ||
# @param cmd [Array<String>] cmd The arguments for the git prompt | ||
# @param opts [Hash] opts | ||
# | ||
# @option opts [String] :path | ||
# @option opts [String] :git_dir | ||
# @option opts [String] :work_tree | ||
# @option opts [String] :raise_on_fail | ||
# | ||
# @raise [R10K::ExecutionFailure] If the executed command exited with a | ||
# nonzero exit code. | ||
# | ||
# @return [String] The git command output | ||
def git(cmd, opts = {}) | ||
raise_on_fail = opts.fetch(:raise_on_fail, true) | ||
|
||
argv = %w{git} | ||
|
||
if opts[:path] | ||
argv << "--git-dir" << File.join(opts[:path], '.git') | ||
argv << "--work-tree" << opts[:path] | ||
else | ||
if opts[:git_dir] | ||
argv << "--git-dir" << opts[:git_dir] | ||
end | ||
if opts[:work_tree] | ||
argv << "--work-tree" << opts[:work_tree] | ||
end | ||
end | ||
|
||
argv.concat(cmd) | ||
|
||
subproc = R10K::Util::Subprocess.new(argv) | ||
subproc.raise_on_fail = raise_on_fail | ||
subproc.logger = self.logger | ||
|
||
result = subproc.execute | ||
|
||
result | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
require 'r10k/git/thin_repository' | ||
require 'r10k/git/errors' | ||
require 'forwardable' | ||
|
||
# Manage how Git repositories are created and set to specific refs | ||
class R10K::Git::StatefulRepository | ||
|
||
# @!attribute [r] repo | ||
# @api private | ||
attr_reader :repo | ||
|
||
extend Forwardable | ||
def_delegators :@repo, :head | ||
|
||
# Create a new shallow git working directory | ||
# | ||
# @param ref [String] The git ref to check out | ||
# @param remote [String] The git remote to use for the repo | ||
# @param basedir [String] The path containing the Git repo | ||
# @param dirname [String] The directory name of the Git repo | ||
def initialize(ref, remote, basedir, dirname) | ||
@ref = ref | ||
@remote = remote | ||
|
||
@repo = R10K::Git::ThinRepository.new(basedir, dirname) | ||
@cache = R10K::Git::Cache.generate(remote) | ||
end | ||
|
||
def sync | ||
@cache.sync | ||
|
||
sha = @cache.resolve(@ref) | ||
|
||
if sha.nil? | ||
raise R10K::Git::UnresolvableRefError.new("Unable to sync repo to unresolvable ref '#{@ref}'", :git_dir => @repo.git_dir) | ||
end | ||
|
||
case status | ||
when :absent | ||
@repo.clone(@remote, {:ref => sha}) | ||
when :mismatched | ||
@repo.path.rmtree | ||
@repo.clone(@remote, {:ref => sha}) | ||
when :outdated | ||
@repo.fetch | ||
@repo.checkout(sha) | ||
end | ||
end | ||
|
||
def status | ||
if !@repo.exist? | ||
:absent | ||
elsif !@repo.git_dir.exist? | ||
:mismatched | ||
elsif !(@repo.origin == @remote) | ||
:mismatched | ||
elsif !(@repo.head == @cache.resolve(@ref)) | ||
:outdated | ||
elsif @cache.ref_type(@ref) == :branch && !@cache.synced? | ||
:outdated | ||
else | ||
:insync | ||
end | ||
end | ||
end |
Oops, something went wrong.