Skip to content

Instantly share code, notes, and snippets.

@ozbillwang
Forked from branch14/merge_locales.rb
Created October 18, 2016 03:15
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 ozbillwang/35ec00811eef2093b87195e283752206 to your computer and use it in GitHub Desktop.
Save ozbillwang/35ec00811eef2093b87195e283752206 to your computer and use it in GitHub Desktop.
Interactively merge several YAML files into one
#!/usr/bin/env ruby
#
# synopsis
#
# ruby merge_locales.rb config/locales translations.yml
require 'yaml'
require 'rubygems'
require 'highline/import'
::Hash.class_eval do
class MergeConflict < StandardError; end
def deep_merge(other, &bloc)
other.keys.inject(dup) do |result, key|
begin
case result[key]
when Hash
if other[key].is_a?(Hash)
result[key] = result[key].deep_merge(other[key], &bloc)
result
else
raise MergeConflict
end
when nil then result.merge key => other[key]
else
raise MergeConflict
end
rescue MergeConflict
if bloc.nil?
result[key] = other[key]
else
result[key] = bloc.call(result, other, key)
end
result
end
end
end
end
result = ARGV.inject({}) do |result, path|
files = [path] if File.file?(path) && path.match(/\.yml$/)
files ||= Dir.glob( File.join(path, '**', '*.yml')).to_a
files.inject(result) do |inner_result, file|
warn "loading #{file}"
yaml = File.open(file) { |yf| YAML::load(yf) }
inner_result.deep_merge(yaml) do |res, other, key|
if res[key] == other[key]
res[key]
else
warn "Conflict on key: '#{key}'"
warn " 1. #{res[key].inspect}"
warn " 2. #{other[key].inspect}"
select = ask('')
case select
when '1' then res[key]
when '2' then other[key]
end
end
end
end
end
YAML.dump(result, STDOUT)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment