branches()
click to toggle source
def branches
@branches ||= repo.branches.select { |b| remote_map.has_key?(b.name) }.sort_by { |b| b.name }
end
check_bundler()
click to toggle source
def check_bundler
return unless use_bundler?
begin
require 'bundler'
ENV['BUNDLE_GEMFILE'] ||= File.expand_path('Gemfile')
Gem.loaded_specs.clear
Bundler.setup
rescue Bundler::GemNotFound, Bundler::GitError
puts
print 'Gems are missing. '.yellow
if config("bundler.autoinstall") == 'true'
puts "Running `bundle install`.".yellow
system "bundle", "install"
else
puts "You should `bundle install`.".yellow
end
end
end
checkout(branch_name)
click to toggle source
def checkout(branch_name)
output = repo.git.checkout({}, branch_name)
unless on_branch?(branch_name)
raise GitError.new("Failed to checkout #{branch_name}", output)
end
end
get_repo()
click to toggle source
def get_repo
repo_dir = %xgit rev-parse --show-toplevel`.chomp
if $? == 0
Dir.chdir repo_dir
@repo = Grit::Repo.new(repo_dir)
else
raise GitError, "We don't seem to be in a git repository."
end
end
is_fast_forward?(a, b)
click to toggle source
def is_fast_forward?(a, b)
merge_base(a.name, b.name) == b.commit.sha
end
log(branch, remote)
click to toggle source
def log(branch, remote)
if log_hook = config("rebase.log-hook")
system('sh', '-c', log_hook, 'git-up', branch.name, remote.name)
end
end
merge_base(a, b)
click to toggle source
def merge_base(a, b)
repo.git.send("merge-base", {}, a, b).strip
end
on_branch?(branch_name=nil)
click to toggle source
def on_branch?(branch_name=nil)
repo.head.respond_to?(:name) and repo.head.name == branch_name
end
rebase(target_branch)
click to toggle source
def rebase(target_branch)
current_branch = repo.head
arguments = config("rebase.arguments")
output, err = repo.git.sh("#{Grit::Git.git_binary} rebase #{arguments} #{target_branch.name}")
unless on_branch?(current_branch.name) and is_fast_forward?(current_branch, target_branch)
raise GitError.new("Failed to rebase #{current_branch.name} onto #{target_branch.name}", output+err)
end
end
rebase_all_branches()
click to toggle source
def rebase_all_branches
col_width = branches.map { |b| b.name.length }.max + 1
branches.each do |branch|
remote = remote_map[branch.name]
print branch.name.ljust(col_width)
if remote.commit.sha == branch.commit.sha
puts "up to date".green
next
end
base = merge_base(branch.name, remote.name)
if base == remote.commit.sha
puts "ahead of upstream".green
next
end
if base == branch.commit.sha
puts "fast-forwarding...".yellow
elsif config("rebase.auto") == 'false'
puts "diverged".red
next
else
puts "rebasing...".yellow
end
log(branch, remote)
checkout(branch.name)
rebase(remote)
end
end
remote_for_branch(branch)
click to toggle source
def remote_for_branch(branch)
remote_name = repo.config["branch.#{branch.name}.remote"] || "origin"
remote_branch = repo.config["branch.#{branch.name}.merge"] || branch.name
remote_branch.sub!(%r{^refs/heads/}, '')
repo.remotes.find { |r| r.name == "#{remote_name}/#{remote_branch}" }
end
remote_map()
click to toggle source
def remote_map
@remote_map ||= repo.branches.inject({}) { |map, branch|
if remote = remote_for_branch(branch)
map[branch.name] = remote
end
map
}
end
remotes()
click to toggle source
def remotes
@remotes ||= remote_map.values.map { |r| r.name.split('/', 2).first }.uniq
end
repo()
click to toggle source
def repo
@repo ||= get_repo
end
returning_to_current_branch() { || ... }
click to toggle source
def returning_to_current_branch
unless repo.head.respond_to?(:name)
puts "You're not currently on a branch. I'm exiting in case you're in the middle of something.".red
return
end
branch_name = repo.head.name
yield
unless on_branch?(branch_name)
puts "returning to #{branch_name}".magenta
checkout(branch_name)
end
end
run()
click to toggle source
def run
command = ['git', 'fetch', '--multiple']
command << '--prune' if prune?
command += config("fetch.all") ? ['--all'] : remotes
system(*command)
raise GitError, "`git fetch` failed" unless $? == 0
@remote_map = nil
Grit::Git.with_timeout(0) do
with_stash do
returning_to_current_branch do
rebase_all_branches
end
end
end
check_bundler
rescue GitError => e
puts e.message
exit 1
end
with_stash() { || ... }
click to toggle source
def with_stash
stashed = false
if change_count > 0
puts "stashing #{change_count} changes".magenta
repo.git.stash
stashed = true
end
yield
if stashed
puts "unstashing".magenta
repo.git.stash({}, "pop")
end
end