Skip to content

Instantly share code, notes, and snippets.

@fujii
Created September 10, 2015 10:07
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 fujii/713842eac5dd7f5b085e to your computer and use it in GitHub Desktop.
Save fujii/713842eac5dd7f5b085e to your computer and use it in GitHub Desktop.
#! /usr/bin/ruby
$p4_rebase_txt = 'p4-rebase.txt'
$p4description = 'p4-description.txt'
def parse_description(s)
lines = s.split("\n")
until lines.empty? || lines[0] == "Description:"
lines.shift
end
lines.shift
desc = []
desc.push(lines.shift[1..-1]) while /^\t/ =~ lines[0]
desc
end
def p4_description(cls)
old = %x(p4 change -o #{cls[0]})
desc = parse_description(old)
desc.pop if /^P4-Rebase: [0-9, ]*$/ =~ desc[-1]
desc << %Q(P4-Rebase: #{cls.join(", ")})
return desc.join("\n") + "\n"
end
def read_description()
open($p4description) do |io|
io.readline(nil)
end
end
def write_description(s)
open($p4description, 'w') do |io|
io.print(s)
end
end
def print_desc(desc)
puts '-' * 20
print desc
puts '-' * 20
end
def description(cls)
desc = p4_description(cls)
write_description(desc)
print_desc(desc)
end
def run_cmd(*cmd)
puts cmd.join(' ')
system(*cmd) or exit $?
end
def skip?(cl)
while true
print "cl.#{cl} c:continue/s:skip (default: c): "
case gets.chomp
when "c", "C", "" then return false
when "s", "S" then return true
end
end
end
def p4_submit()
desc = read_description()
run_cmd(*%W(p4 submit -d) << desc)
end
def need_submit?
%x(p4 opened) != ""
end
def submit(cl, query)
return unless need_submit?
if query && skip?(cl)
run_cmd(*%W(p4 revert //...))
else
p4_submit
end
end
def need_resolve?
%x(p4 resolve -n) != ""
end
def merge(src, cl, target, i_opt, r_opt)
run_cmd(*%W(p4 integ) + i_opt + ["#{src}@#{cl},@#{cl}", target])
run_cmd(*%W(p4 resolve -am))
conflicted = need_resolve?
run_cmd(*%W(p4 resolve) + r_opt) if conflicted
conflicted
end
def usage
puts "Usage:"
puts " p4-rebase init source[revRange] target"
puts " p4-rebase run"
exit
end
def strip_rev_range(path_rev)
return path_rev.sub(/[@#].*/, '')
end
def init(argv)
usage if argv.length != 2
src_rev, target = *argv
src = strip_rev_range(src_rev)
changes = %x(p4 changes #{src_rev}).split("\n")
exit $? if $? != 0
open($p4_rebase_txt, "w") do |io|
io.puts "source: #{src}"
io.puts "target: #{target}"
io.puts "integrate: -f -Ds"
io.puts "resolve: "
io.puts
changes.reverse.each do |c|
/Change ([0-9]+) on (.*)/ =~ c
io.puts %Q(pick #{$1}\t#{$2})
end
end
end
def parse_header(io)
$_, s, * = *io.gets.split
raise SyntaxError unless $_ == "source:"
$_, t, * = *io.gets.split
raise SyntaxError unless $_ == "target:"
$_, *i = *io.gets.split
raise SyntaxError unless $_ == "integrate:"
$_, *r = *io.gets.split
raise SyntaxError unless $_ == "resolve:"
raise SyntaxError unless io.gets == "\n"
return s, t, i, r
end
def parse_cmds(io)
cmds = []
io.readlines.each do |line|
cmd, cl, * = line.split
case cmd
when "pick"
when "edit"
when "squash"
else
raise SyntaxError
end
cmds << [cmd, cl]
end
return cmds
end
def parse_text(io)
s, t, i, r = parse_header(io)
cmds = parse_cmds(io)
return s, t, i, r, cmds
end
def run(argv)
usage if argv.length != 0
src, target, i_opt, r_opt, cmds = open($p4_rebase_txt) {|io| parse_text(io)}
until cmds.empty?
query = true
cmd, cl = cmds.shift
case cmd
when "pick" then query = merge(src, cl, target, i_opt, r_opt)
when "edit" then merge(src, cl, target, i_opt, r_opt)
else abort
end
cls = [cl]
while cmds[0] && cmds[0][0] == "squash"
cmd, cl = cmds.shift
query = merge(src, cl, target, i_opt, r_opt) || query
cls << cl
end
description(cls)
submit(cl, query)
end
end
def main
case ARGV.shift
when "init"
init(ARGV)
when "run"
run(ARGV)
else
usage()
end
end
main
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment