class ModuleSync::Repository
Wrapper for Git
in ModuleSync
context
Public Class Methods
new(directory:, remote:)
click to toggle source
# File lib/modulesync/repository.rb, line 6 def initialize(directory:, remote:) @directory = directory @remote = remote end
Public Instance Methods
checkout_branch(branch)
click to toggle source
# File lib/modulesync/repository.rb, line 123 def checkout_branch(branch) selected_branch = branch || repo.current_branch || 'master' repo.branch(selected_branch).checkout selected_branch end
clone()
click to toggle source
# File lib/modulesync/repository.rb, line 73 def clone puts "Cloning from '#{@remote}'" @git = Git.clone(@remote, @directory) end
cloned?()
click to toggle source
# File lib/modulesync/repository.rb, line 69 def cloned? Dir.exist? File.join(@directory, '.git') end
default_branch()
click to toggle source
# File lib/modulesync/repository.rb, line 33 def default_branch # `Git.default_branch` requires ruby-git >= 1.17.0 return Git.default_branch(repo.dir) if Git.respond_to? :default_branch symbolic_ref = repo.branches.find { |b| b.full.include?('remotes/origin/HEAD') } return unless symbolic_ref %r{remotes/origin/HEAD\s+->\s+origin/(?<branch>.+?)$}.match(symbolic_ref.full)[:branch] end
default_reset_branch(branch)
click to toggle source
# File lib/modulesync/repository.rb, line 93 def default_reset_branch(branch) remote_branch_exists?(branch) ? branch : default_branch end
git()
click to toggle source
# File lib/modulesync/repository.rb, line 11 def git @git ||= Git.open @directory end
local_branch_exists?(branch)
click to toggle source
# File lib/modulesync/repository.rb, line 24 def local_branch_exists?(branch) repo.branches.local.collect(&:name).include?(branch) end
prepare_workspace(branch:, operate_offline:)
click to toggle source
# File lib/modulesync/repository.rb, line 78 def prepare_workspace(branch:, operate_offline:) if cloned? puts "Overriding any local changes to repository in '#{@directory}'" git.fetch 'origin', prune: true unless operate_offline git.reset_hard switch(branch: branch) git.pull('origin', branch) if !operate_offline && remote_branch_exists?(branch) else raise ModuleSync::Error, 'Unable to clone in offline mode.' if operate_offline clone switch(branch: branch) end end
push(branch:, remote_branch:, remote_name: 'origin')
click to toggle source
# File lib/modulesync/repository.rb, line 169 def push(branch:, remote_branch:, remote_name: 'origin') raise ModuleSync::Error, 'Repository must be locally available before trying to push' unless cloned? remote_url = git.remote(remote_name).url remote_branch ||= branch puts "Push branch '#{branch}' to '#{remote_url}' (#{remote_name}/#{remote_branch})" git.push(remote_name, "#{branch}:#{remote_branch}", force: true) end
puts(*args)
click to toggle source
# File lib/modulesync/repository.rb, line 207 def puts(*args) $stdout.puts(*args) if ModuleSync.options[:verbose] end
remote_branch_differ?(local_branch, remote_branch)
click to toggle source
# File lib/modulesync/repository.rb, line 28 def remote_branch_differ?(local_branch, remote_branch) !remote_branch_exists?(remote_branch) || repo.diff("#{local_branch}..origin/#{remote_branch}").any? end
remote_branch_exists?(branch)
click to toggle source
# File lib/modulesync/repository.rb, line 20 def remote_branch_exists?(branch) repo.branches.remote.collect(&:name).include?(branch) end
repo()
click to toggle source
This is an alias to minimize code alteration
# File lib/modulesync/repository.rb, line 16 def repo git end
reset_workspace(branch:, operate_offline:, source_branch: nil)
click to toggle source
# File lib/modulesync/repository.rb, line 97 def reset_workspace(branch:, operate_offline:, source_branch: nil) raise if branch.nil? if cloned? source_branch ||= "origin/#{default_reset_branch branch}" puts "Hard-resetting any local changes to repository in '#{@directory}' from branch '#{source_branch}'" switch(branch: branch) git.fetch 'origin', prune: true unless operate_offline git.reset_hard source_branch git.clean(d: true, force: true) else raise ModuleSync::Error, 'Unable to clone in offline mode.' if operate_offline clone switch(branch: branch) end end
show_changes(options)
click to toggle source
# File lib/modulesync/repository.rb, line 188 def show_changes(options) checkout_branch(options[:branch]) $stdout.puts 'Files changed:' repo.diff('HEAD', '--').each do |diff| $stdout.puts diff.patch end $stdout.puts 'Files added:' untracked_unignored_files.each_key do |file| $stdout.puts file end $stdout.puts "\n\n" $stdout.puts '--------------------------------' git.diff('HEAD', '--').any? || untracked_unignored_files.any? end
submit_changes(files, options)
click to toggle source
Git
add/rm, git commit, git push
# File lib/modulesync/repository.rb, line 130 def submit_changes(files, options) message = options[:message] branch = checkout_branch(options[:branch]) files.each do |file| if repo.status.deleted.include?(file) repo.remove(file) elsif File.exist? File.join(@directory, file) repo.add(file) end end begin opts_commit = {} opts_push = {} opts_commit = { amend: true } if options[:amend] opts_push = { force: true } if options[:force] if options[:pre_commit_script] script = "#{File.dirname(File.dirname(__FILE__))}/../contrib/#{options[:pre_commit_script]}" `#{script} #{@directory}` end repo.commit(message, opts_commit) if options[:remote_branch] if remote_branch_differ?(branch, options[:remote_branch]) repo.push('origin', "#{branch}:#{options[:remote_branch]}", opts_push) puts "Changes have been pushed to: '#{branch}:#{options[:remote_branch]}'" end else repo.push('origin', branch, opts_push) puts "Changes have been pushed to: '#{branch}'" end rescue Git::GitExecuteError => e raise unless e.message.match?(/working (directory|tree) clean/) puts "There were no changes in '#{@directory}'. Not committing." return false end true end
switch(branch:)
click to toggle source
# File lib/modulesync/repository.rb, line 43 def switch(branch:) unless branch branch = default_branch puts "Using repository's default branch: #{branch}" end return if repo.current_branch == branch if local_branch_exists?(branch) puts "Switching to branch #{branch}" repo.checkout(branch) elsif remote_branch_exists?(branch) puts "Creating local branch #{branch} from origin/#{branch}" repo.checkout("origin/#{branch}") repo.branch(branch).checkout else base_branch = default_branch unless base_branch puts "Couldn't detect default branch. Falling back to assuming 'master'" base_branch = 'master' end puts "Creating new branch #{branch} from #{base_branch}" repo.checkout("origin/#{base_branch}") repo.branch(branch).checkout end end
tag(version, tag_pattern)
click to toggle source
# File lib/modulesync/repository.rb, line 116 def tag(version, tag_pattern) tag = tag_pattern % version puts "Tagging with #{tag}" repo.add_tag(tag) repo.push('origin', tag) end
untracked_unignored_files()
click to toggle source
Needed because of a bug in the git gem that lists ignored files as untracked under some circumstances github.com/schacon/ruby-git/issues/130
# File lib/modulesync/repository.rb, line 182 def untracked_unignored_files ignore_path = File.join @directory, '.gitignore' ignored = File.exist?(ignore_path) ? File.read(ignore_path).split : [] repo.status.untracked.keep_if { |f, _| ignored.none? { |i| File.fnmatch(i, f) } } end