lib/hookup.rb in hookup-1.0.3 vs lib/hookup.rb in hookup-1.1.0
- old
+ new
@@ -1,14 +1,20 @@
class Hookup
class Error < RuntimeError
end
+ class Failure < Error
+ end
+
EMPTY_DIR = '4b825dc642cb6eb9a060e54bf8d69288fbee4904'
def self.run(*argv)
new.run(*argv)
+ rescue Failure => e
+ puts e
+ exit 1
rescue Error => e
puts e
exit
end
@@ -25,29 +31,43 @@
raise Error, "Invalid arguments for #{command}"
end
end
end
+ def git_dir
+ unless @git_dir
+ @git_dir = %x{git rev-parse --git-dir}.chomp
+ raise Error, dir unless $?.success?
+ end
+ @git_dir
+ end
+
def install
- dir = %x{git rev-parse --git-dir}.chomp
- raise Error, dir unless $?.success?
- hook = File.join(dir, 'hooks', 'post-checkout')
- unless File.exist?(hook)
- File.open(hook, 'w', 0777) do |f|
- f.puts "#!/bin/bash"
- end
+ append(File.join(git_dir, 'hooks', 'post-checkout'), 0777) do |body, f|
+ f.puts "#!/bin/bash" unless body
+ f.puts %(hookup post-checkout "$@") if body !~ /hookup/
end
- if File.read(hook) =~ /^[^#]*\bhookup\b/
- puts "Already hooked up!"
- else
- File.open(hook, "a") do |f|
- f.puts %(hookup post-checkout "$@")
- end
- puts "Hooked up!"
+
+ append(File.join(git_dir, 'info', 'attributes')) do |body, f|
+ map = 'db/schema.rb merge=railsschema'
+ f.puts map unless body.to_s.include?(map)
end
+
+ system 'git', 'config', 'merge.railsschema.driver', 'hookup resolve-schema %A %O %B %L'
+
+ puts "Hooked up!"
end
+ def append(file, *args)
+ Dir.mkdir(File.dirname(file)) unless File.directory?(File.dirname(file))
+ body = File.read(file) if File.exist?(file)
+ File.open(file, 'a', *args) do |f|
+ yield body, f
+ end
+ end
+ protected :append
+
def post_checkout(*args)
old, new = args.shift, args.shift || 'HEAD'
if old == '0000000000000000000000000000000000000000'
old = EMPTY_DIR
elsif old.nil?
@@ -77,13 +97,14 @@
end
def migrate(old, new, *args)
return if args.first == '0'
- schema = %x{git diff --name-status #{old} #{new} -- db/schema.rb}
- if schema =~ /^A/
- system 'rake', 'db:create'
+ schemas = %w(db/schema.rb db/development_structure.sql).select do |schema|
+ status = %x{git diff --name-status #{old} #{new} -- #{schema}}.chomp
+ system 'rake', 'db:create' if status =~ /^A/
+ status !~ /^D/ && !status.empty?
end
migrations = %x{git diff --name-status #{old} #{new} -- db/migrate}.scan(/.+/).map {|l| l.split(/\t/) }
begin
migrations.select {|(t,f)| %w(D M).include?(t)}.reverse.each do |type, file|
@@ -104,10 +125,23 @@
if migrations.any? {|(t,f)| %w(A M).include?(t)}
system 'rake', 'db:migrate'
end
ensure
- system 'git', 'checkout', '--', 'db/schema.rb' if migrations.any?
+ system 'git', 'checkout', '--', *schemas if schemas.any?
+ end
+ end
+
+ def resolve_schema(a, o, b, marker_size = 7)
+ system 'git', 'merge-file', "--marker-size=#{marker_size}", a, o, b
+ body = File.read(a)
+ asd = "ActiveRecord::Schema.define"
+ x = body.sub!(/^<+ .*\n#{asd}\(:version => (\d+)\) do\n=+\n#{asd}\(:version => (\d+)\) do\n>+ .*/) do
+ "#{asd}(:version => #{[$1, $2].max}) do"
+ end
+ File.open(a, 'w') { |f| f.write(body) }
+ if body.include?('<' * marker_size.to_i)
+ raise Failure, 'Failed to automatically resolve schema conflict'
end
end
end