Skip to content

Commit

Permalink
Resolve schema conflicts
Browse files Browse the repository at this point in the history
  • Loading branch information
tpope committed Aug 24, 2011
1 parent 40e9537 commit 2f1f390
Show file tree
Hide file tree
Showing 2 changed files with 53 additions and 17 deletions.
8 changes: 8 additions & 0 deletions README.markdown
Expand Up @@ -7,6 +7,7 @@ Git hooks. It fires after events like
* pulling in upstream changes
* switching branches
* stepping through a bisect
* conflict in schema

Usage
-----
Expand All @@ -31,3 +32,10 @@ Each time your current HEAD changes, hookup checks to see if any
migrations have been added, deleted, or modified. Deleted and modified
migrations are given the `rake db:migrate:down` treatment, then `rake
db:migrate` is invoked to bring everything else up to date.

Schema Resolving
----------------

Each time there's a conflict in `db/schema.rb` on the
`Rails::Schema.define` line, hookup resolves it in favor of the newer of
the two versions.
62 changes: 45 additions & 17 deletions lib/hookup.rb
Expand Up @@ -3,10 +3,16 @@ 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
Expand All @@ -27,29 +33,38 @@ def run(*argv)
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?
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

hook_dir = File.join(dir, 'hooks')
Dir.mkdir(hook_dir, 0755) unless File.directory?(hook_dir)
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

hook = File.join(hook_dir, 'post-checkout')
system 'git', 'config', 'merge.railsschema.driver', 'hookup resolve-schema %A %O %B %L'

unless File.exist?(hook)
File.open(hook, 'w', 0777) do |f|
f.puts "#!/bin/bash"
end
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!"
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'
Expand Down Expand Up @@ -116,4 +131,17 @@ def migrate(old, new, *args)
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

0 comments on commit 2f1f390

Please sign in to comment.