class GitUp

Constants

VERSION

Public Instance Methods

branches() click to toggle source
# File lib/git-up.rb, line 79
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
# File lib/git-up.rb, line 162
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
# File lib/git-up.rb, line 137
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
# File lib/git-up.rb, line 68
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
# File lib/git-up.rb, line 183
def is_fast_forward?(a, b)
  merge_base(a.name, b.name) == b.commit.sha
end
log(branch, remote) click to toggle source
# File lib/git-up.rb, line 145
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
# File lib/git-up.rb, line 187
def merge_base(a, b)
  repo.git.send("merge-base", {}, a, b).strip
end
on_branch?(branch_name=nil) click to toggle source
# File lib/git-up.rb, line 191
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
# File lib/git-up.rb, line 151
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
# File lib/git-up.rb, line 29
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
# File lib/git-up.rb, line 97
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
# File lib/git-up.rb, line 87
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
# File lib/git-up.rb, line 83
def remotes
  @remotes ||= remote_map.values.map { |r| r.name.split('/', 2).first }.uniq
end
repo() click to toggle source
# File lib/git-up.rb, line 64
def repo
  @repo ||= get_repo
end
returning_to_current_branch() { || ... } click to toggle source
# File lib/git-up.rb, line 121
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
# File lib/git-up.rb, line 5
def run
  command = ['git', 'fetch', '--multiple']
  command << '--prune' if prune?
  command += config("fetch.all") ? ['--all'] : remotes

  # puts command.join(" ") # TODO: implement a 'debug' config option
  system(*command)
  raise GitError, "`git fetch` failed" unless $? == 0
  @remote_map = nil # flush cache after fetch

  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
# File lib/git-up.rb, line 104
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