From 15d74d24fb3215be54353278152d67ba226e1924 Mon Sep 17 00:00:00 2001 From: shogosanz Date: Thu, 30 Nov 2017 23:11:00 +0900 Subject: [PATCH 1/5] structure to hash --- exe/junoser | 6 ++ lib/junoser/cli.rb | 4 ++ lib/junoser/display.rb | 1 + lib/junoser/display/delete.rb | 103 ++++++++++++++++++++++++++++++++++ 4 files changed, 114 insertions(+) create mode 100644 lib/junoser/display/delete.rb diff --git a/exe/junoser b/exe/junoser index 9a1c029..727cc4d 100755 --- a/exe/junoser +++ b/exe/junoser @@ -27,6 +27,10 @@ opts = OptionParser.new do |opts| command = :struct end + opts.on '--delete', 'Apply config delete sentence' do + command = :delete + end + opts.on_tail '-h', '--help', 'Show this message' do puts opts exit @@ -46,6 +50,8 @@ when :display_set puts Junoser::Cli.display_set($<) when :struct puts Junoser::Cli.struct($<) +when :delete + puts Junoser::Cli.delete($<) else puts opts abort diff --git a/lib/junoser/cli.rb b/lib/junoser/cli.rb index 70bb46f..51782e6 100644 --- a/lib/junoser/cli.rb +++ b/lib/junoser/cli.rb @@ -25,6 +25,10 @@ def struct(io_or_string) Junoser::Display::Structure.new(io_or_string).transform end + def delete(io_or_string) + Junoser::Display::Delete.new(io_or_string).apply + end + private diff --git a/lib/junoser/display.rb b/lib/junoser/display.rb index c76847d..6f2a636 100644 --- a/lib/junoser/display.rb +++ b/lib/junoser/display.rb @@ -1,5 +1,6 @@ require 'junoser/display/set' require 'junoser/display/structure' +require 'junoser/display/delete' module Junoser module Display diff --git a/lib/junoser/display/delete.rb b/lib/junoser/display/delete.rb new file mode 100644 index 0000000..0e4f825 --- /dev/null +++ b/lib/junoser/display/delete.rb @@ -0,0 +1,103 @@ +require 'junoser/input' +require 'junoser/display/config_store' +require 'junoser/parser' +require 'junoser/transformer' + +module Junoser + module Display + class Delete + def initialize(io_or_string) + @input = io_or_string + end + def apply + sd = Junoser::Input.new(@input).read.split("\n") + d = sd.grep(/^delete /).map {|l| l.sub(/^delete /, 'set ')} + s = sd.grep(/^set /) + set_struct = Junoser::Display::Structure.new(s.join("\n")).transform + set_h = struct_to_hash(set_struct) + d.each do |delete_line| + delete_line_struct = Junoser::Display::Structure.new(delete_line).transform + delete_line_hash = struct_to_hash(delete_line_struct) + set_h = apply_delete(set_h,delete_line_hash) + end + set_h +# set_struct = hash_to_struct(set_h) +# Junoser::Display::Set.new(set_struct).transform + end + + private + + def struct_to_hash(struct) + struct.gsub!(/\n/, '') + hash = struct_to_first_hash(struct) + hash_value_to_hash(hash) + end + + def hash_value_to_hash(hash) + hash.each do |key,value| + if value != {} + hash.store(key,struct_to_first_hash(value)) + hash_value_to_hash(hash[key]) + end + end + end + + def struct_to_first_hash(struct) + hash = {} + ar = ["",""] + num = 0 + flag = 0 + struct << " " + struct.chars.each do |c| + if num != 0 + ar[1] << c + end + if c == "{" + num = num + 1 + flag = 1 + next + end + if c == "}" + num = num - 1 + next + end + if num == 0 + if c == ";" + hash.store(ar[0].strip,{}) + ar = ["",""] + next + end + if flag == 1 + hash.store(ar[0].strip,ar[1].chop.strip) + ar = ["",""] + flag = 0 + end + ar[0] << c + end + end + hash + end + + def apply_delete(set_hash,delete_line_hash) + key,hash = ret_first_key_and_value(delete_line_hash) + if hash == {} + set_hash.delete(key) + set_hash + else + apply_delete(set_hash[key],hash) + end + set_hash + end + +# def hash_to_struct(hash) +# +# end + + def ret_first_key_and_value(hash) + hash.each do |key,hash| + return key,hash + end + end + end + end +end From 6a9343421af252cba6ea8c7576d926803021a01d Mon Sep 17 00:00:00 2001 From: shogosanz Date: Fri, 1 Dec 2017 01:05:03 +0900 Subject: [PATCH 2/5] add delete method --- lib/junoser/display/delete.rb | 28 ++++++++++++++++++++++------ 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/lib/junoser/display/delete.rb b/lib/junoser/display/delete.rb index 0e4f825..e147465 100644 --- a/lib/junoser/display/delete.rb +++ b/lib/junoser/display/delete.rb @@ -20,9 +20,8 @@ def apply delete_line_hash = struct_to_hash(delete_line_struct) set_h = apply_delete(set_h,delete_line_hash) end - set_h -# set_struct = hash_to_struct(set_h) -# Junoser::Display::Set.new(set_struct).transform + set_struct = hash_to_struct(set_h) + Junoser::Display::Set.new(set_struct).transform end private @@ -89,9 +88,26 @@ def apply_delete(set_hash,delete_line_hash) set_hash end -# def hash_to_struct(hash) -# -# end + def hash_to_struct(hash) + struct = "" + hash_to_struct_iter(hash){|str| struct << str} + struct + end + + def hash_to_struct_iter(hash,&block) + hash.each_with_index do |(key,value),i| + yield key + if value != {} + yield "{\n" + hash_to_struct_iter(value,&block) + else + yield ";\n" + end + if i == hash.length - 1 + yield "}\n" + end + end + end def ret_first_key_and_value(hash) hash.each do |key,hash| From 3ba19c19f6fb4ba72ca75d0592237d3d1d94bb14 Mon Sep 17 00:00:00 2001 From: shogosanz Date: Tue, 12 Dec 2017 19:13:52 +0900 Subject: [PATCH 3/5] modify struct_to_first_hash --- lib/junoser/display/delete.rb | 82 ++++++++++++++++++++--------------- 1 file changed, 48 insertions(+), 34 deletions(-) diff --git a/lib/junoser/display/delete.rb b/lib/junoser/display/delete.rb index e147465..d83afb2 100644 --- a/lib/junoser/display/delete.rb +++ b/lib/junoser/display/delete.rb @@ -16,10 +16,15 @@ def apply set_struct = Junoser::Display::Structure.new(s.join("\n")).transform set_h = struct_to_hash(set_struct) d.each do |delete_line| - delete_line_struct = Junoser::Display::Structure.new(delete_line).transform - delete_line_hash = struct_to_hash(delete_line_struct) - set_h = apply_delete(set_h,delete_line_hash) + begin + delete_line_struct = Junoser::Display::Structure.new(delete_line).transform + delete_line_hash = struct_to_hash(delete_line_struct) + set_h = apply_delete(set_h,delete_line_hash) + rescue + next + end end + set_struct = hash_to_struct(set_h) Junoser::Display::Set.new(set_struct).transform end @@ -41,41 +46,50 @@ def hash_value_to_hash(hash) end end - def struct_to_first_hash(struct) - hash = {} - ar = ["",""] - num = 0 - flag = 0 - struct << " " - struct.chars.each do |c| - if num != 0 - ar[1] << c - end - if c == "{" - num = num + 1 - flag = 1 - next - end - if c == "}" - num = num - 1 - next - end - if num == 0 - if c == ";" - hash.store(ar[0].strip,{}) - ar = ["",""] - next + def struct_to_first_hash(struct) + hash = {} + ar = ["",""] + state = 0 + struct.strip! + struct.chars.each do |c| + case state + when 0 then # initial state + case c + when "{" then + state += 1 + when ";" then + hash.store(ar[0].strip,ar[1].strip) + ar = ["",""] + else + ar[0] << c end - if flag == 1 - hash.store(ar[0].strip,ar[1].chop.strip) - ar = ["",""] - flag = 0 + when 1 then + case c + when "{" then + ar[1] << c + state += 1 + when "}" then + hash.store(ar[0].strip,ar[1].strip) + ar = ["",""] + state = 0 + else + ar[1] << c + end + else + case c + when "{" then + ar[1] << c + state += 1 + when "}" then + ar[1] << c + state -= 1 + else + ar[1] << c end - ar[0] << c - end end - hash end + hash + end def apply_delete(set_hash,delete_line_hash) key,hash = ret_first_key_and_value(delete_line_hash) From 3293d3d7f28bcada6e986331a55564c15adc4aa2 Mon Sep 17 00:00:00 2001 From: shogosanz Date: Wed, 13 Dec 2017 19:43:50 +0900 Subject: [PATCH 4/5] split command --- exe/junoser | 6 --- exe/junoser-apply | 27 +++++++++++ lib/junoser/cli.rb | 5 ++- lib/junoser/display.rb | 1 + lib/junoser/display/delete.rb | 84 +++++++++++++++++------------------ lib/junoser/input.rb | 24 ++++++++++ 6 files changed, 98 insertions(+), 49 deletions(-) create mode 100755 exe/junoser-apply diff --git a/exe/junoser b/exe/junoser index 727cc4d..9a1c029 100755 --- a/exe/junoser +++ b/exe/junoser @@ -27,10 +27,6 @@ opts = OptionParser.new do |opts| command = :struct end - opts.on '--delete', 'Apply config delete sentence' do - command = :delete - end - opts.on_tail '-h', '--help', 'Show this message' do puts opts exit @@ -50,8 +46,6 @@ when :display_set puts Junoser::Cli.display_set($<) when :struct puts Junoser::Cli.struct($<) -when :delete - puts Junoser::Cli.delete($<) else puts opts abort diff --git a/exe/junoser-apply b/exe/junoser-apply new file mode 100755 index 0000000..54f110a --- /dev/null +++ b/exe/junoser-apply @@ -0,0 +1,27 @@ +#!/usr/bin/env ruby + +require 'optparse' +require 'pathname' + +$: << File.expand_path('../../lib', Pathname.new(__FILE__).realpath) +require 'junoser' + + +command = :apply +opts = OptionParser.new do |opts| + opts.banner = 'junoser-apply: apply commands to config. (delete)' + opts.define_head 'Usage: junoser-apply [path]' + + opts.on_tail '-h', '--help', 'Show this message' do + puts opts + exit + end +end +opts.parse! +case command + when :apply + puts Junoser::Cli.apply($<) + else + puts opts + abort +end diff --git a/lib/junoser/cli.rb b/lib/junoser/cli.rb index 51782e6..a6c7ce2 100644 --- a/lib/junoser/cli.rb +++ b/lib/junoser/cli.rb @@ -25,10 +25,13 @@ def struct(io_or_string) Junoser::Display::Structure.new(io_or_string).transform end - def delete(io_or_string) + def apply(io_or_string) Junoser::Display::Delete.new(io_or_string).apply end + def compare(io_or_string) + Junoser::Display::Compare.new(io_or_string).diff + end private diff --git a/lib/junoser/display.rb b/lib/junoser/display.rb index 6f2a636..281e0c4 100644 --- a/lib/junoser/display.rb +++ b/lib/junoser/display.rb @@ -1,6 +1,7 @@ require 'junoser/display/set' require 'junoser/display/structure' require 'junoser/display/delete' +require 'junoser/display/compare' module Junoser module Display diff --git a/lib/junoser/display/delete.rb b/lib/junoser/display/delete.rb index d83afb2..9360b76 100644 --- a/lib/junoser/display/delete.rb +++ b/lib/junoser/display/delete.rb @@ -46,50 +46,50 @@ def hash_value_to_hash(hash) end end - def struct_to_first_hash(struct) - hash = {} - ar = ["",""] - state = 0 - struct.strip! - struct.chars.each do |c| - case state - when 0 then # initial state - case c - when "{" then - state += 1 - when ";" then - hash.store(ar[0].strip,ar[1].strip) - ar = ["",""] - else - ar[0] << c - end - when 1 then - case c - when "{" then - ar[1] << c - state += 1 - when "}" then - hash.store(ar[0].strip,ar[1].strip) - ar = ["",""] - state = 0 - else - ar[1] << c - end - else - case c - when "{" then - ar[1] << c - state += 1 - when "}" then - ar[1] << c - state -= 1 - else - ar[1] << c - end + def struct_to_first_hash(struct) + hash = {} + key,value = "","" + state = 0 + struct.strip! + struct.chars.each do |c| + case state + when 0 then # initial state + case c + when "{" then + state += 1 # 1 + when ";" then + hash.store(key.strip,value.strip) + key,value = "","" + else + key << c + end + when 1 then + case c + when "{" then + value << c + state += 1 # 2 + when "}" then + hash.store(key.strip,value.strip) + key,value = "","" + state -= 1 # 0 + else + value << c + end + else + case c + when "{" then + value << c + state += 1 + when "}" then + value << c + state -= 1 + else + value << c + end + end end + hash end - hash - end def apply_delete(set_hash,delete_line_hash) key,hash = ret_first_key_and_value(delete_line_hash) diff --git a/lib/junoser/input.rb b/lib/junoser/input.rb index 713b51e..d87eb00 100644 --- a/lib/junoser/input.rb +++ b/lib/junoser/input.rb @@ -15,6 +15,30 @@ def read content = unify_carriage_return(content) end + def read2 + content1 = if @io_or_string.respond_to?(:read) + @io_or_string.file.read + else + @io_or_string.to_s + end + + content1 = remove_blank_and_comment_line(content1) + content1 = unify_carriage_return(content1) + + @io_or_string.skip + + content2 = if @io_or_string.respond_to?(:read) + @io_or_string.file.read + else + @io_or_string.to_s + end + + content2 = remove_blank_and_comment_line(content2) + content2 = unify_carriage_return(content2) + + return content1,content2 + end + private From 050d8dc72d0746b09f2fcdb12a2273cd54b01a89 Mon Sep 17 00:00:00 2001 From: shogosanz Date: Wed, 13 Dec 2017 19:44:52 +0900 Subject: [PATCH 5/5] add junoser-compare command --- exe/junoser-compare | 27 +++++ lib/junoser/display/compare.rb | 175 +++++++++++++++++++++++++++++++++ 2 files changed, 202 insertions(+) create mode 100755 exe/junoser-compare create mode 100644 lib/junoser/display/compare.rb diff --git a/exe/junoser-compare b/exe/junoser-compare new file mode 100755 index 0000000..e0f3edb --- /dev/null +++ b/exe/junoser-compare @@ -0,0 +1,27 @@ +#!/usr/bin/env ruby + +require 'optparse' +require 'pathname' + +$: << File.expand_path('../../lib', Pathname.new(__FILE__).realpath) +require 'junoser' + + +command = :compare +opts = OptionParser.new do |opts| + opts.banner = 'junoser-compare: output difference between two configs' + opts.define_head 'Usage: junoser-compare [path] [path]' + + opts.on_tail '-h', '--help', 'Show this message' do + puts opts + exit + end +end +opts.parse! +case command + when :compare + puts Junoser::Cli.compare($<) + else + puts opts + abort +end diff --git a/lib/junoser/display/compare.rb b/lib/junoser/display/compare.rb new file mode 100644 index 0000000..a3a57e4 --- /dev/null +++ b/lib/junoser/display/compare.rb @@ -0,0 +1,175 @@ +require 'junoser/input' +require 'junoser/display/config_store' +require 'junoser/parser' +require 'junoser/transformer' + +module Junoser + module Display + class Compare + def initialize(io_or_string) + @input = io_or_string + end + def diff + master,branch = Junoser::Input.new(@input).read2 + master_struct = Junoser::Display::Structure.new(master).transform + branch_struct = Junoser::Display::Structure.new(branch).transform + generate_diff_set_and_delete(master_struct,branch_struct) + end + + private + + def generate_diff_set_and_delete(master,branch) + master_hash = struct_to_hash(master) + branch_hash = struct_to_hash(branch) + set_hash = hash_cmp(master_hash,branch_hash,"set") + delete_hash = hash_cmp(master_hash,branch_hash,"delete") + set_struct = hash_to_struct(set_hash) + delete_struct = hash_to_struct(delete_hash) + set_ = Junoser::Display::Set.new(set_struct).transform + delete_ = Junoser::Display::Set.new(delete_struct).transform + delete_.gsub!(/^set /, 'delete ') + delete_ << "\n" << set_ + end + + + def hash_cmp(master,branch,delete_or_set,depth = 0) + if delete_or_set == "set" and depth == 0 + tmp = master + master = branch + branch = tmp + end + answer = {} + master.each do |key,value| + if branch.key?(key) + if not including(value,branch[key]) + answer.store(key,hash_cmp(value,branch[key],delete_or_set,depth + 1)) + end + else + if delete_or_set == "delete" + answer.store(key,{}) + elsif delete_or_set == "set" + answer.store(key,value) + end + end + end + answer + end + + def including(hash,hash2) + # hash <= hash2 + if hash.keys - hash2.keys == [] + if hash == {} + return true + else + hash.each do |key,value| + if not including(value,hash2[key]) + return false + end + end + end + else + return false + end + true + end + + def struct_to_hash(struct) + struct.gsub!(/\n/, '') + hash = struct_to_first_hash(struct) + hash_value_to_hash(hash) + end + + def hash_value_to_hash(hash) + hash.each do |key,value| + if value != {} + hash.store(key,struct_to_first_hash(value)) + hash_value_to_hash(hash[key]) + end + end + end + + def struct_to_first_hash(struct) + hash = {} + key,value = "","" + state = 0 + struct.strip! + struct.chars.each do |c| + case state + when 0 then # initial state + case c + when "{" then + state += 1 # 1 + when ";" then + hash.store(key.strip,value.strip) + key,value = "","" + else + key << c + end + when 1 then + case c + when "{" then + value << c + state += 1 # 2 + when "}" then + hash.store(key.strip,value.strip) + key,value = "","" + state -= 1 # 0 + else + value << c + end + else + case c + when "{" then + value << c + state += 1 + when "}" then + value << c + state -= 1 + else + value << c + end + end + end + hash + end + + def apply_delete(set_hash,delete_line_hash) + key,hash = ret_first_key_and_value(delete_line_hash) + if hash == {} + set_hash.delete(key) + set_hash + else + apply_delete(set_hash[key],hash) + end + set_hash + end + + def hash_to_struct(hash) + struct = "" + hash_to_struct_iter(hash){|str| struct << str} + struct + end + + def hash_to_struct_iter(hash,&block) + hash.each_with_index do |(key,value),i| + yield key + if value != {} + yield "{\n" + hash_to_struct_iter(value,&block) + else + yield ";\n" + end + if i == hash.length - 1 + yield "}\n" + end + end + end + + def ret_first_key_and_value(hash) + hash.each do |key,hash| + return key,hash + end + end + end + end +end