-
-
Save ozbillwang/35ec00811eef2093b87195e283752206 to your computer and use it in GitHub Desktop.
Interactively merge several YAML files into one
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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