Skip to content

Instantly share code, notes, and snippets.

@mkhl
Created November 25, 2008 09:38
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mkhl/28864 to your computer and use it in GitHub Desktop.
Save mkhl/28864 to your computer and use it in GitHub Desktop.
An old version of gx, plus a few macros I used to use.
#!/usr/bin/env ruby
# evanphx's old version of the gx git macro facility, slightly modified.
# I guess this is completely superseded by git aliases by now, but I like
# having it around somewhere...
class GitProxy
def initialize(prog="git")
@prog = prog
@record = false
@recording = []
@verbose = false
end
def method_missing(cmd, *args)
str = "#{@prog} #{cmd}"
str << (" " + args.join(' ')) unless args.empty?
puts "GX: Running '#{str}'" if @verbose
if !@record and !block_given?
system str
else
ran = [:git, cmd, args.dup]
args.delete_if { |i| i =~ /%./ }
IO.popen(str, "r") do |io|
io.each_line do |line|
puts line
ran << line
yield line if block_given?
end
end
@recording << ran if @record
end
end
alias :run :method_missing
def record!
@record = true
end
attr_accessor :recording, :verbose
end
class GX
def initialize
@gx_dir = File.join ENV['HOME'], ".gx"
@recording_flag = File.join(@gx_dir, "recording")
@macros_path = File.join(@gx_dir, "macros")
@full_flag = File.join(@gx_dir, "fullpass")
Dir.mkdir @gx_dir unless File.exists?(@gx_dir)
Dir.mkdir @macros_path unless File.exists?(@macros_path)
@git = GitProxy.new(ENV['GIT_PATH'] || 'git')
if recording?
@git.record!
cur = Marshal.load File.read(@recording_flag) rescue nil
@git.recording = cur if cur
end
@fullpass = File.exists?(@full_flag)
setup_commands
scan_macros
end
def verbose=(value)
@git.verbose = value
end
def setup_commands
@commands = {
:record => method(:record),
:save => method(:save),
:macros => method(:macros)
}
end
def scan_macros
@macros = {}
Dir[@macros_path+"/*.rb"].each do |macro|
@macros[File.basename(macro, ".rb").to_sym] = macro
end
end
def recording?
File.exists? @recording_flag
end
def git(command, *args, &block)
@git.run command, *args, &block
end
def convert_to_options(args)
opts = {}
i = 0
while i < args.size
if /^-(\w+)/.match(args[i])
opt = $1
if /^-/.match(args[i + 1])
opts[opt] = true
else
opts[opt] = args[i += 1]
end
elsif /^--(.+)(?:=(.+))?/.match(args[i])
opts[$1.to_sym] = ($2 or true)
else
break
end
i += 1
end
args.slice!(0, i) if i > 0
args << opts
end
def run(command, *args)
@command = command.to_sym
if handler = @commands[@command]
convert_to_options(args)
out = handler.call(*args)
elsif (!recording? or @fullpass) and macro = @macros[@command]
out = run_macro macro, *args
else
out = @git.run command, *args
end
if recording?
File.open(@recording_flag, "w") do |f|
f << Marshal.dump(@git.recording)
end
end
out
end
def run_macro(macro, *args)
old = @args
@args = args
out = instance_eval File.read(macro)
@args = old
out
end
def error(str)
puts "GX Error: #{str}"
exit 1
end
def record(opts)
puts "Recording of commands has begun..."
File.open(@recording_flag, "w") { }
if opts[:full] or opts[:f]
File.open(@full_flag, "w") { }
end
end
def save(name, opts)
puts "Saving macro as '#{name}'"
File.open(File.join(@macros_path, "#{name}.rb"), "w") do |f|
@git.recording.each do |command|
if command[0] == :git
f.puts compose_command(command[1], command[2])
else
f.puts "perform '#{command[1]}'"
end
end
end
File.unlink @recording_flag
File.unlink @full_flag if @fullpass
end
def compose_command(command, args)
if args.empty?
"git :#{command}, *@args"
else
if args.last == "%-"
arg.pop
no_extra = true
else
no_extra = false
end
skip = false
sargs = args.map do |i|
if skip
skip = false
nil
elsif i == "%%"
skip = true
"@args.shift"
else
i.dump
end
end.compact.join(", ")
sargs << ", *@args" unless no_extra
"git :#{command}, #{sargs}"
end
end
def macros(opts)
puts "Available macros:"
@macros.each do |name, macro|
puts " #{name}"
end
end
end
gx = GX.new
command = ARGV.shift
unless command
puts "Usage: gx <command> <args>"
puts " Commands which gx does not recognized are passed through to git."
exit 1
end
gx.verbose = ENV['GX_VERBOSE']
gx.run command, *ARGV
branch = run :'test-branch', 'master'
git :stash
git :checkout, "master"
git :merge, branch
git :checkout, branch
branch = run :'test-branch', 'master'
git :stash, "save"
git :checkout, "master"
git :pull, *@args
git :checkout, branch
git :rebase, "master"
branch = run :'test-branch', 'master'
git :stash
git :checkout, "master"
git :push
git :checkout, branch
branch = nil
git :branch do |line|
branch = line[2..-1].chomp if /\*/ === line
end
error "Couldn't figure out which branch you're on!" if branch.nil?
error "Already on branch \"#{branch}\"" if @args.include? branch
branch
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment