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