transdifflation 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/Fudgefile ADDED
@@ -0,0 +1,4 @@
1
+ build :default do
2
+ yard :arguments => '-r YardREADME.md', :coverage => 100
3
+ rspec :coverage => 96
4
+ end
data/Gemfile ADDED
@@ -0,0 +1,19 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in transdifflation.gemspec
4
+ gemspec
5
+
6
+ gem 'rails'
7
+
8
+ group :development, :test do
9
+ gem 'fudge', :git => 'git@github.com:Sage/fudge.git'
10
+ gem 'rspec'
11
+ gem 'yard'
12
+ gem 'simplecov'
13
+
14
+ gem 'rspec-rails'
15
+ gem 'guard-sass', :require => false
16
+ gem 'pry'
17
+ gem "guard-rspec"
18
+ gem 'rb-fsevent', :require => false
19
+ end
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2012 Sage
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,72 @@
1
+ # Transdifflation
2
+
3
+ What is Transdifflation? Transdifflation is an acronym of 'Translation' and 'Diff'.
4
+ It compares two .yml locate files, one in your source code (target) and one in others' (gems, other projects) source code (source) and generates a beside-file with the keys you hadn't translated yet.
5
+ Then you can merge it. It is designed to detect changes between versions. By now, target file cannot be renamed, and it is generated in 'config/locales/' + to_locale (param in task). Names are inferred by the task params too.
6
+
7
+ IT NEVER CHANGES YOUR SOURCE FILE, unless it doesn't exists, so it creates for you.
8
+
9
+ ## Installation
10
+
11
+ Add this line to your application's Gemfile:
12
+
13
+ gem 'transdifflation'
14
+
15
+ And then execute:
16
+
17
+ $ bundle
18
+
19
+ Or install it yourself as:
20
+
21
+ $ gem install transdifflation
22
+
23
+ ## Usage
24
+
25
+ It needs a config file (**transdifflation.yml**) placed on your host root, or in 'lib/tasks'. Config file looks like:
26
+
27
+ ```yml
28
+ tasks:
29
+ task_name1: {
30
+ desc: 'Get diff translation from file config/locales/en.yml gem gem_name',
31
+ type: gem,
32
+ params: {
33
+ gem_name: 'gem_name',
34
+ path_in_gem: 'config/locales/en.yml',
35
+ from_locale: 'en',
36
+ to_locale: 'es'
37
+ }
38
+ }
39
+ task_name2: {
40
+ desc: 'Get diff translation from file config/locales/en.yml file in file_path',
41
+ type: file,
42
+ params: {
43
+ tag_name: 'tag_for_file',
44
+ file_path_from_rails_root: '../another_project/config/locales/en.yml',
45
+ from_locale: 'en',
46
+ to_locale: 'fr'
47
+ }
48
+ }
49
+ grouped_tasks:
50
+ task_group_name:
51
+ - task_name1
52
+ - task_name2
53
+ ```
54
+
55
+ These nodes generates rake tasks. There are two types of tasks:
56
+
57
+ * type **gem**: When it rans, it checks where the gem 'gem_name' is installed, and looks inside the gem for the file located in 'path_in_gem'. It uses from_locale and to_locale to translate names and keys inside yaml.
58
+
59
+ * type **file**: When it rans, it looks for the file in 'file_path_from_rails_root' is installed. It uses from_locale and to_locale to translate names and keys inside yaml. Tag_name is used to name target file in our host.
60
+
61
+ Execute ```rake transdifflation:config``` to determine sucess of config file.
62
+
63
+ Also, you can create grouped tasks in a node called 'grouped_taks'. Task **all** is automatially generated.
64
+
65
+
66
+ ## Contributing
67
+
68
+ 1. Fork it
69
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
70
+ 3. Commit your changes (`git commit -am 'Added some feature'`)
71
+ 4. Push to the branch (`git push origin my-new-feature`)
72
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
3
+ require 'rspec/core/rake_task'
4
+ RSpec::Core::RakeTask.new('spec')
@@ -0,0 +1,11 @@
1
+ module Transdifflation
2
+
3
+ # Used when no config file is found for Transdifflation
4
+ class ConfigFileNotFound < ::StandardError ; end
5
+
6
+ # Used when the Transdifflation config file is in error
7
+ class ConfigFileWithErrors < ::StandardError ; end
8
+
9
+
10
+ end
11
+
@@ -0,0 +1,117 @@
1
+ require 'transdifflation'
2
+ require 'rails'
3
+
4
+ module Transdifflation
5
+
6
+ # Adds behaviours to Rails
7
+ class Railtie < Rails::Railtie
8
+ search_locations = %w[config/transdifflation.yml transdifflation.yml]
9
+
10
+ railtie_name :transdifflation
11
+ rake_tasks do
12
+ begin
13
+
14
+ file_task_config = nil
15
+ search_locations.each do |path| #Take config file from these locations
16
+ abs_path = File.expand_path(path, Rails.root)
17
+ if(File.exists?(abs_path))
18
+ file_task_config = abs_path
19
+ break
20
+ end
21
+ end
22
+
23
+ raise Transdifflation::ConfigFileNotFound if file_task_config.nil?
24
+
25
+ tasks_config = YAML.load_file(file_task_config)
26
+ tasks_config.symbolize!
27
+
28
+ raise Transdifflation::ConfigFileWithErrors, "Transdifflation config file has no parent 'tasks' node" if tasks_config[:tasks].nil?
29
+
30
+ #Individual tasks
31
+ task_all = []
32
+ tasks_config[:tasks].each_pair do |key, value|
33
+
34
+ task_name = key.to_s
35
+ task_desc = value[:desc].to_s
36
+
37
+ raise Transdifflation::ConfigFileWithErrors, "Transdifflation task #{task_name}: has no type defined" if value[:type].nil?
38
+
39
+ raise Transdifflation::ConfigFileWithErrors, "Transdifflation task #{task_name}: type defined unknown (%s)" % [value[:type]] if !['gem', 'file'].include?(value[:type])
40
+ task_type = value[:type] == 'gem'? :gem : :file
41
+
42
+ raise Transdifflation::ConfigFileWithErrors, "Transdifflation task #{task_name}: has no params defined" if value[:params].nil?
43
+ params = value[:params]
44
+ raise Transdifflation::ConfigFileWithErrors, "Transdifflation task #{task_name}: param 'gem_name' is not defined" if params[:gem_name].nil? && task_type == :gem
45
+ raise Transdifflation::ConfigFileWithErrors, "Transdifflation task #{task_name}: param 'path_in_gem' is not defined" if params[:path_in_gem].nil? && task_type == :gem
46
+ raise Transdifflation::ConfigFileWithErrors, "Transdifflation task #{task_name}: param 'tag_name' is not defined" if params[:tag_name].nil? && task_type == :file
47
+ raise Transdifflation::ConfigFileWithErrors, "Transdifflation task #{task_name}: param 'file_path' is not defined" if params[:file_path_from_rails_root].nil? && task_type == :file
48
+
49
+ if(task_type == :gem)
50
+
51
+ namespace :transdifflation do
52
+ desc task_desc
53
+ task task_name do
54
+ puts "\nExecuting #{task_name} ************************** "
55
+ comparer = Transdifflation::Comparer.new
56
+ comparer.get_transdifflation_from_gem(params[:gem_name], params[:path_in_gem], params[:from_locale], params[:to_locale])
57
+ end
58
+ end
59
+
60
+ else
61
+
62
+ namespace :transdifflation do
63
+ desc task_desc
64
+ task task_name do
65
+ puts "\nExecuting #{task_name} ************************** "
66
+ comparer = Transdifflation::Comparer.new
67
+ comparer.get_transdifflation_from_file(params[:tag_name], params[:file_path_from_rails_root], params[:from_locale], params[:to_locale])
68
+ end
69
+ end
70
+ end
71
+ task_all.push (task_name)
72
+ end
73
+
74
+ #Grouped tasks
75
+ tasks_config[:grouped_tasks].each_pair do |key, value|
76
+
77
+ value.map! do |item|
78
+ item.to_sym
79
+ end
80
+
81
+ namespace :transdifflation do
82
+ desc "Task #{key} (Grouped Task)"
83
+ task key => value
84
+ end
85
+ end
86
+
87
+ #All tasks
88
+ namespace :transdifflation do
89
+ desc "All tasks"
90
+ task :all => task_all
91
+ end
92
+
93
+ rescue Transdifflation::ConfigFileNotFound
94
+
95
+ #Generate task to set-up
96
+ namespace :transdifflation do
97
+ desc "Task to set-up config file in host"
98
+ task :setup do
99
+ destination_file = File.expand_path('config/transdifflation.yml', Rails.root)
100
+ destination_path = File.dirname(destination_file)
101
+ Transdifflation::Comparer.generate_config_example_file destination_file
102
+ puts "\nCopied a transdifflation.yml example into '#{destination_path}'"
103
+ end
104
+ end
105
+
106
+ rescue Transdifflation::ConfigFileWithErrors => e
107
+
108
+ raise "Gem 'Transdifflation' says => #{e.message}"
109
+
110
+ rescue Exception => e
111
+
112
+ raise "Gem 'Transdifflation' says => #{e.message}"
113
+
114
+ end
115
+ end
116
+ end
117
+ end
@@ -0,0 +1,33 @@
1
+
2
+ #Example generating your config file:
3
+
4
+ #tasks:
5
+ # task_name1: {
6
+ # desc: 'Get diff translation from file config/locales/en.yml gem gem_name',
7
+ # type: gem,
8
+ # params: {
9
+ # gem_name: 'gem_name',
10
+ # path_in_gem: 'config/locales/en.yml',
11
+ # from_locale: 'en',
12
+ # to_locale: 'es'
13
+ # }
14
+ # }
15
+ # task_name2: {
16
+ # desc: 'Get diff translation from file config/locales/en.yml file in file_path',
17
+ # type: file,
18
+ # params: {
19
+ # tag_name: 'tag_for_file',
20
+ # file_path_from_rails_root: '../another_project/config/locales/en.yml',
21
+ # from_locale: 'en',
22
+ # to_locale: 'fr'
23
+ # }
24
+ # }
25
+ #
26
+ #grouped_tasks:
27
+ # task_group_name:
28
+ # - task_name1
29
+ # - task_name2
30
+ #
31
+
32
+
33
+
@@ -0,0 +1,31 @@
1
+
2
+
3
+ module Transdifflation
4
+
5
+ #Class used to convert all keys in a hash (included sub-hashes) in symbols
6
+ class HashSymbolTranslator
7
+ # Convert keys
8
+ def symbolize(hash)
9
+ hash = hash.inject({}) { |memo,(k,v)|
10
+ if(v.instance_of? Hash)
11
+ v = symbolize(v)
12
+ end
13
+ memo[k.to_sym] = v
14
+ memo
15
+ }
16
+ hash
17
+ end
18
+ end
19
+ end
20
+
21
+ class Hash
22
+
23
+ #convert all keys in a Hash (presumily from YAML) in symbols
24
+ def symbolize!
25
+ symbolizer = Transdifflation::HashSymbolTranslator.new
26
+ new_self = symbolizer.symbolize(self)
27
+ self.clear
28
+ self.merge!(new_self)
29
+ end
30
+
31
+ end
@@ -0,0 +1,4 @@
1
+ module Transdifflation
2
+ # Gem version
3
+ VERSION = "0.0.1"
4
+ end
@@ -0,0 +1,65 @@
1
+ module Transdifflation
2
+ # Reads YAML from the specified source
3
+ class YAMLReader
4
+
5
+ # Get YAML content from a gem
6
+ #
7
+ # @param [String] gem_name Installed gem's name
8
+ # @param [String] file_path_to_yaml_in_gem Path of the file inside gem's source code
9
+ def self.read_YAML_from_gem(gem_name, file_path_to_yaml_in_gem)
10
+
11
+ #get where the gem is localized
12
+ gem_SRC =`bundle show #{gem_name}`.chomp
13
+ raise ArgumentError.new("Gem '#{gem_name}' not installed") if ($?.to_i != 0) #get return code and check if is different from zero
14
+
15
+ #get the file within the gem
16
+ yaml_file_in_gem_SRC = File.join( gem_SRC, file_path_to_yaml_in_gem )
17
+ raise ArgumentError.new("File '#{file_path_to_yaml_in_gem}' does not exists in gem '#{gem_name}'") if (!File.file?(yaml_file_in_gem_SRC))
18
+
19
+ #read the yml content file
20
+ get_YAML_content_from_YAML_file(yaml_file_in_gem_SRC)
21
+
22
+ end
23
+
24
+ # Get YAML content from a file in filesystem
25
+ #
26
+ # @param [String] path_to_yaml_relative_from_rails_root Tag name this file will be intalled on host
27
+ def self.read_YAML_from_filesystem(path_to_yaml_relative_from_rails_root)
28
+
29
+ #get the file
30
+ yaml_file_path = File.realpath(path_to_yaml_relative_from_rails_root, Rails.root)
31
+ yaml_file_name = File.basename( yaml_file_path )
32
+ raise ArgumentError.new("File '#{yaml_file_name}' does not exists in path '#{yaml_file_path}'") if (!File.file?(yaml_file_path))
33
+
34
+ #read the yml content file
35
+ get_YAML_content_from_YAML_file(yaml_file_path)
36
+
37
+ end
38
+
39
+ # Get YAML content from a file in filesystem
40
+ #
41
+ # @param [String] path_to_yaml Tag name this file will be intalled on host
42
+ def self.read_YAML_from_pathfile(path_to_yaml)
43
+
44
+ #get the file
45
+ yaml_file_name = File.basename( path_to_yaml )
46
+ raise ArgumentError.new("File '#{yaml_file_name}' does not exists in path '#{path_to_yaml}'") if (!File.file?(path_to_yaml))
47
+
48
+ #read the yml content file
49
+ get_YAML_content_from_YAML_file(path_to_yaml)
50
+ end
51
+
52
+ private
53
+
54
+ def self.get_YAML_content_from_YAML_file(yml_path_file)
55
+
56
+ #read the yml content file
57
+ yml_source_content = YAML.load_file(yml_path_file)
58
+ yml_source_content = {} if (yml_source_content == false)
59
+
60
+ #return
61
+ yml_source_content
62
+
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,28 @@
1
+ module Transdifflation
2
+
3
+ # Writes YAML
4
+ class YAMLWriter
5
+
6
+ #Method used to prettify generated YAML
7
+ def self.to_yaml(hash)
8
+ method = hash.respond_to?(:ya2yaml) ? :ya2yaml : :to_yaml
9
+ string = hash.deep_stringify_keys.send(method)
10
+ yaml_string = string.gsub("!ruby/symbol ", ":").sub("---","")
11
+ yaml_string = yaml_string.gsub(/(\?) "([\w\s\\]+)"\n/) do |match|
12
+ match.sub(/\?\s+/, "").chomp
13
+ end
14
+ yaml_string = yaml_string.split("\n").map(&:rstrip).join("\n").strip
15
+ end
16
+ end
17
+ end
18
+
19
+ #Method used to prettify generated YAML. Expands Hash class
20
+ class Hash
21
+ # Convert keys into strings recursively
22
+ def deep_stringify_keys
23
+ new_hash = {}
24
+ self.each do |key, value|
25
+ new_hash.merge!(key.to_s => (value.is_a?(Hash) ? value.deep_stringify_keys : value))
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,248 @@
1
+ require 'transdifflation/version'
2
+ require 'transdifflation/yaml_reader'
3
+ require 'transdifflation/yaml_writer'
4
+ require 'transdifflation/exceptions'
5
+ require 'transdifflation/utilities'
6
+
7
+ # The main module for the program
8
+ module Transdifflation
9
+
10
+ require 'transdifflation/railtie' if defined?(Rails)
11
+
12
+ # Implements the core
13
+ class Comparer
14
+
15
+ #const string added to keys not translated
16
+ NOT_TRANSLATED = "**NOT_TRANSLATED** "
17
+ #Instance variable to get if changes have been detected
18
+ attr_reader :has_changes
19
+
20
+ def initialize()
21
+ @has_changes = false
22
+ end
23
+
24
+ # Get Diff from YAML translation locale file from a gem and generate differences in a file on our host
25
+ #
26
+ # @param [String] gem_name Installed gem's name
27
+ # @param [String] path_to_yaml_in_gem Path of the file inside gem's source code
28
+ # @param [Symbol] from_locale Default locale in gem. Used to translate 'from'
29
+ # @param [Symbol] to_locale Default locale in host. Used to translate 'to'
30
+ def get_transdifflation_from_gem(gem_name, path_to_yaml_in_gem, from_locale=:en, to_locale=:es )
31
+
32
+ #default values in optional params
33
+ from_locale ||= :en
34
+ to_locale ||= :es #sorry, this gem was developed in Spain :)
35
+
36
+ yml_gem_content = YAMLReader.read_YAML_from_gem(gem_name, path_to_yaml_in_gem)
37
+ puts "Loaded YAML content from gem '#{gem_name}', file '#{path_to_yaml_in_gem}'"
38
+
39
+
40
+ #build the file name in our host
41
+ filename_in_gem_SRC = File.basename( path_to_yaml_in_gem )
42
+ host_target_filename = filename_in_gem_SRC.gsub(/-?#{from_locale}\./) do |match_s|
43
+ match_s.sub("#{from_locale}", "#{to_locale}")
44
+ end
45
+ host_target_file = File.join( Rails.root, "config/locales/#{to_locale}", "#{gem_name}.#{host_target_filename}")
46
+
47
+ if(!File.file? host_target_file)
48
+ get_first_time_file(yml_gem_content, host_target_file, from_locale, to_locale)
49
+ else
50
+ generate_diff_file(yml_gem_content, host_target_file, from_locale, to_locale)
51
+ end
52
+
53
+ @has_changes
54
+ end
55
+
56
+
57
+
58
+ # Get Diff from YAML translation locale file from filesystem and generate differences in a file on our host
59
+ #
60
+ # @param [String] tag_name Tag name this file will be installed on host
61
+ # @param [String] path_to_yaml_relative_from_rails_root Path to the file in system, relative from Rails.root
62
+ # @param [Symbol] from_locale Default locale in gem. Used to translate 'from'
63
+ # @param [Symbol] to_locale Default locale in host. Used to translate 'to'
64
+ def get_transdifflation_from_file(tag_name, path_to_yaml_relative_from_rails_root, from_locale=:en, to_locale=:es )
65
+
66
+ #default values in optional params
67
+ from_locale ||= :en
68
+ to_locale ||= :es #sorry, this gem was developed in Spain :)
69
+
70
+ yml_source_content = YAMLReader.read_YAML_from_pathfile(path_to_yaml_relative_from_rails_root)
71
+ puts "Loaded YAML content from file '#{path_to_yaml_relative_from_rails_root}'"
72
+
73
+ #build the file name in our host
74
+ filename_in_SRC = File.basename( path_to_yaml_relative_from_rails_root )
75
+ host_target_filename = filename_in_SRC.gsub(/-?#{from_locale}\./) do |match_s|
76
+ match_s.sub("#{from_locale}", "#{to_locale}")
77
+ end
78
+ host_target_file = File.join( Rails.root, "config/locales/#{to_locale}", "#{tag_name}.#{host_target_filename}")
79
+
80
+ if(!File.file? host_target_file)
81
+ get_first_time_file(yml_source_content, host_target_file, from_locale, to_locale)
82
+ else
83
+ generate_diff_file(yml_source_content, host_target_file, from_locale, to_locale)
84
+ end
85
+
86
+ @has_changes
87
+ end
88
+
89
+
90
+
91
+
92
+
93
+
94
+ private
95
+
96
+ # Build the initial translation file
97
+ #
98
+ # @param [String] yml_source_content Content to translate
99
+ # @param [String] host_target_file The filename to create
100
+ # @param [Symbol] from_locale Default locale in gem. Used to translate 'from'
101
+ # @param [Symbol] to_locale Default locale in host. Used to translate 'to'
102
+ def get_first_time_file(yml_source_content, host_target_file, from_locale, to_locale)
103
+
104
+ puts "Target translation file '#{host_target_file}' not found, generating it for the first time"
105
+
106
+ #create a file
107
+ host_target_file_stream = File.open(host_target_file, "a+:UTF-8")
108
+
109
+ begin
110
+
111
+ translated_yaml = {}
112
+ #translate from source yaml content, to target existant yml
113
+ translate_keys_in_same_yaml(yml_source_content, translated_yaml, from_locale, to_locale)
114
+
115
+ host_target_file_stream.write(YAMLWriter.to_yaml(translated_yaml))
116
+ @has_changes = true
117
+ ensure
118
+
119
+ host_target_file_stream.close
120
+ end
121
+
122
+ end
123
+
124
+
125
+ # Recursively translate hash from YAML file
126
+ #
127
+ # @param [Hash] source Hash from origin YAML file
128
+ # @param [Hash] target Hash from target YAML file
129
+ # @param [Symbol] from_locale Locale used to translate 'from'
130
+ # @param [Symbol] to_locale Locale used to translate 'to'
131
+ # @param [Boolean] add_NOT_TRANSLATED Boolean to set if it should add "**NOT_TRANSLATED** " to value (default = true)
132
+ def translate_keys_in_same_yaml(source, target, from_locale, to_locale, add_NOT_TRANSLATED=true)
133
+
134
+ source.each_pair { |source_key, source_value|
135
+
136
+ key_is_symbol = source_key.instance_of? Symbol
137
+
138
+ source_key_translated = source_key.to_s.sub(/^#{from_locale}$/, "#{to_locale}")
139
+ source_key_translated = source_key_translated.to_sym if key_is_symbol
140
+
141
+ #if value is a hash, we call it recursively
142
+ if (source_value.instance_of? Hash)
143
+
144
+ if(!target.has_key? (source_key_translated))
145
+ target[source_key_translated] = Hash.new
146
+ end
147
+
148
+ translate_keys_in_same_yaml(source_value, target[source_key_translated], from_locale, to_locale, add_NOT_TRANSLATED) #recurrence of other hashes
149
+
150
+ else
151
+ #it's a leaf node
152
+ target[source_key_translated] = (add_NOT_TRANSLATED ? "#{NOT_TRANSLATED}#{source_value}" : "#{source_value}") if !target.has_key? (source_key_translated)
153
+ end
154
+ }
155
+ end
156
+
157
+ def generate_diff_file(yml_source_content, host_target_file, from_locale, to_locale)
158
+
159
+ existant_yml = YAMLReader.read_YAML_from_pathfile(host_target_file)
160
+ added_diff_hash, removed_diff_hash = Hash.new, Hash.new
161
+
162
+ generate_added_diff(yml_source_content, existant_yml, added_diff_hash, Array.new, from_locale, to_locale)
163
+ generate_added_diff(existant_yml, yml_source_content, removed_diff_hash, Array.new, to_locale, from_locale, false)
164
+
165
+ if (removed_diff_hash.length > 0)
166
+ #we have to reprocess hash to show user what happened
167
+ temp_removed_diff_hash = {}
168
+ translate_keys_in_same_yaml(removed_diff_hash, temp_removed_diff_hash, from_locale, to_locale, false)
169
+ removed_diff_hash = temp_removed_diff_hash
170
+
171
+ end
172
+
173
+
174
+ if( added_diff_hash.length > 0 || removed_diff_hash.length > 0 )
175
+
176
+ diff_file = File.join(File.dirname(host_target_file), "#{File.basename(host_target_file)}.diff")
177
+ diff_file_stream = File.new(diff_file, "w+:UTF-8")
178
+ begin
179
+
180
+ if (added_diff_hash.length > 0)
181
+ diff_file_stream.write("ADDED KEYS (Keys not found in your file, founded in source file) ********************\n")
182
+ diff_file_stream.write(YAMLWriter.to_yaml(added_diff_hash)) #we can't use YAML#dump due to issues wuth Utf8 chars
183
+ end
184
+
185
+ if (removed_diff_hash.length > 0)
186
+ diff_file_stream.write("\n\n") if (added_diff_hash.length > 0)
187
+ diff_file_stream.write("REMOVED KEYS (Keys not found in source file, founded in your file) ********************\n")
188
+ diff_file_stream.write(YAMLWriter.to_yaml(removed_diff_hash)) #we can't use YAML#dump due to issues wuth Utf8 chars
189
+ end
190
+
191
+ ensure
192
+ diff_file_stream.close
193
+ end
194
+ puts "File #{File.basename( host_target_file )} processed >> %s" % [ "#{File.basename( diff_file )} has the changes!"]
195
+ @has_changes = true
196
+ else
197
+ puts "File #{File.basename( host_target_file )} processed >> No changes!"
198
+ end
199
+ end
200
+
201
+
202
+ # Recursively generate difference hash from YAML file
203
+ #
204
+ # @param [Hash] source Hash from origin YAML file
205
+ # @param [Hash] target Hash from target YAML file
206
+ # @param [Hash] added_diff_hash Hash containing differences; at the first time, it should be empty
207
+ # @param [Array] key_trace_passed Array containing trace of the key generated, recursively. At the first time, it should be empty
208
+ # @param [Symbol] from_locale Default locale in gem. Used to translate 'from'
209
+ # @param [Symbol] to_locale Default locale in host. Used to translate 'to'
210
+ # @param [Boolean] add_NOT_TRANSLATED Boolean to set if it should add "**NOT_TRANSLATED** " to value (default = true)
211
+ # @return [Hash] the resulting hash translated
212
+ def generate_added_diff(source, target, added_diff_hash, key_trace_passed, from_locale, to_locale, add_NOT_TRANSLATED=true)
213
+
214
+ source.each_pair { |source_key, source_value|
215
+ key_trace = key_trace_passed.dup #each pair should have a clear copy of the same array
216
+ key_is_symbol = source_key.instance_of? Symbol
217
+ source_key_translated = source_key.to_s.sub(/^#{from_locale}$/, "#{to_locale}")
218
+ source_key_translated = source_key_translated.to_sym if key_is_symbol
219
+
220
+ #if value is a hash, we call it recursively
221
+ if (source_value.instance_of? Hash)
222
+ key_trace.push source_key_translated #add the key to the trace to be generated if necessary
223
+ target[source_key_translated] = Hash.new if(!target.has_key? (source_key_translated)) #to continue trace, otherwise, node will not exist in next iteration
224
+ generate_added_diff(source_value, target[source_key_translated], added_diff_hash, key_trace, from_locale, to_locale) #recursively call
225
+ else #it's a leaf node
226
+
227
+ if !target.has_key? (source_key_translated)
228
+ added_diff_hash_positioned = added_diff_hash #pointer to added_diff_hash
229
+ key_trace.each do |key| #add the keys if necessary on the accurate level
230
+ added_diff_hash_positioned [key] = Hash.new if(!added_diff_hash_positioned.has_key? key )
231
+ added_diff_hash_positioned = added_diff_hash_positioned [key] #and position pointer to next level
232
+ end
233
+ added_diff_hash_positioned[source_key_translated] = (add_NOT_TRANSLATED ? "#{NOT_TRANSLATED}#{source_value}" : "#{source_value}") #add the inexistant key
234
+ end
235
+ end
236
+ }
237
+ end
238
+
239
+
240
+
241
+
242
+
243
+ def self.generate_config_example_file(path)
244
+ FileUtils.copy(File.expand_path('./transdifflation/transdifflation.yml', File.dirname( __FILE__ )), path)
245
+ end
246
+
247
+ end
248
+ end
@@ -0,0 +1,18 @@
1
+ require 'rubygems'
2
+ require 'simplecov'
3
+ SimpleCov.start do
4
+ add_filter "spec/"
5
+ end
6
+
7
+ require 'transdifflation/version'
8
+ require 'transdifflation/yaml_reader'
9
+ require 'transdifflation/yaml_writer'
10
+ require 'transdifflation/exceptions'
11
+ require 'transdifflation/utilities'
12
+ require 'yaml'
13
+
14
+
15
+ RSpec.configure do |config|
16
+ # some (optional) config here
17
+
18
+ end
@@ -0,0 +1,20 @@
1
+ # require 'spec_helper'
2
+ # require 'transdifflation'
3
+
4
+ #describe :get_transdifflation_from_gem do
5
+ # it 'convert a key in a Hash (presumily from YAML) in symbol' do
6
+ # gem_name = 'rake'
7
+ # path_to_yaml_in_gem = '.'
8
+ # from_locale= :en
9
+ # to_locale = :es
10
+ # Transdifflation::Comparer
11
+ # end
12
+ # xit 'another test' do
13
+
14
+
15
+ # end
16
+
17
+
18
+
19
+
20
+ # end
@@ -0,0 +1,27 @@
1
+ require 'spec_helper'
2
+
3
+ describe :symbolize! do
4
+ it 'convert a key in a Hash (presumily from YAML) in symbol' do
5
+ example_hash = { "es" => 666 }
6
+ example_hash.symbolize!
7
+ example_hash.should == { :es => 666 }
8
+ end
9
+
10
+ it 'convert all keys in a Hash (presumily from YAML) in symbols' do
11
+ example_hash = { "es" => 666, "lala" => "truururur" }
12
+ example_hash.symbolize!
13
+ example_hash.should == { :es => 666, :lala => "truururur" }
14
+ end
15
+
16
+ it 'convert all keys in a Hash (presumily from YAML) in symbols but if there is a hash it should leave it' do
17
+ example_hash = { :es => 666, "lala" => "truururur" }
18
+ example_hash.symbolize!
19
+ example_hash.should == { :es => 666, :lala => "truururur" }
20
+ end
21
+
22
+ it 'should return something usefull on nil' do
23
+ example_hash = Hash.new
24
+ example_hash.symbolize!
25
+ example_hash.should == {}
26
+ end
27
+ end
@@ -0,0 +1,87 @@
1
+ require 'spec_helper'
2
+
3
+
4
+ describe :YAMLReader do
5
+
6
+ before(:each) do
7
+ unless defined?(::Rails)
8
+ @mocked_rails_class = true
9
+ class ::Rails
10
+ end
11
+ end
12
+ end
13
+ describe :read_YAML_from_filesystem do
14
+ it 'should raise an error exception when read_YAML_from_filesystem get nil as an argument' do
15
+ File.stub(:basename).and_return(nil)
16
+ File.stub(:realpath).and_return('/')
17
+ ::Rails.should_receive(:root).and_return('/rails')
18
+
19
+ expect {Transdifflation::YAMLReader.read_YAML_from_filesystem('whatever')}.to raise_error(ArgumentError)
20
+ end
21
+
22
+ it 'should not raise an error if the file exists at read_YAML_from_filesystem' do
23
+ File.stub(:basename).and_return(nil)
24
+ File.stub(:realpath).and_return('/')
25
+ # Stubbing File to make it exist
26
+ File.stub(:file?).and_return(true)
27
+ ::Rails.should_receive(:root).and_return('/rails')
28
+
29
+ expect {Transdifflation::YAMLReader.read_YAML_from_filesystem('whatever')}.to_not raise_error(ArgumentError)
30
+ end
31
+ end
32
+
33
+ describe :read_YAML_from_gem do
34
+ it 'should raise an error exception when a gem does not exist' do
35
+ File.stub(:join).and_return(nil)
36
+ File.stub(:file?).and_return(true)
37
+
38
+ a_gem = 'one_random_gem'
39
+ a_path = './'
40
+
41
+ expect {Transdifflation::YAMLReader.read_YAML_from_gem(a_gem, a_path)}.to raise_error(ArgumentError)
42
+ end
43
+
44
+ it 'should not raise an error exception when a gem exists (rspec)' do
45
+ a_gem = 'rspec'
46
+ a_path = 'README.md'
47
+
48
+ Transdifflation::YAMLReader.stub(:get_YAML_content_from_YAML_file).and_return(':a => 2')
49
+ expect {Transdifflation::YAMLReader.read_YAML_from_gem(a_gem, a_path)}.to_not raise_error(ArgumentError)
50
+ end
51
+ end
52
+
53
+ describe :read_YAML_from_pathfile do
54
+ it 'should raise an error exception when a path does not exist' do
55
+ File.stub(:file?).and_return(false)
56
+ a_path = './'
57
+
58
+ expect {Transdifflation::YAMLReader.read_YAML_from_pathfile(a_path)}.to raise_error(ArgumentError)
59
+ end
60
+
61
+ it 'should not raise an error exception when a path exists (rspec)' do
62
+ File.stub(:basename).and_return(nil)
63
+ File.stub(:file?).and_return(true)
64
+ a_path = 'README.md'
65
+
66
+ Transdifflation::YAMLReader.stub(:get_YAML_content_from_YAML_file).and_return(':a => 2')
67
+ expect {Transdifflation::YAMLReader.read_YAML_from_pathfile(a_path)}.to_not raise_error(ArgumentError)
68
+ end
69
+ end
70
+
71
+ describe :get_YAML_content_from_YAML_file do
72
+ it 'should return {} when there is no YAML file' do
73
+ a_yml_path = 'bad.yml'
74
+ YAML.stub(:load_file).and_return(false)
75
+
76
+ Transdifflation::YAMLReader.get_YAML_content_from_YAML_file(a_yml_path).should == {}
77
+ end
78
+
79
+ it 'should return the YAML in case it load properly the file' do
80
+ a_yml_path = 'good.yml'
81
+ YAML.stub(:load_file).and_return(['badger', 'elephant', 'tiger'])
82
+
83
+ Transdifflation::YAMLReader.get_YAML_content_from_YAML_file(a_yml_path).should == ['badger', 'elephant', 'tiger']
84
+ end
85
+ end
86
+
87
+ end
@@ -0,0 +1,28 @@
1
+ require 'spec_helper'
2
+
3
+
4
+ describe :YAMLWriter do
5
+ describe :to_yaml do
6
+ it 'should convert to ya2yaml format an input hash' do
7
+ hashy = {:en=>{:date=>{:formats=>{:default=>"%d/%m/%Y", :short=>"%d %b"}}}}
8
+ Transdifflation::YAMLWriter.to_yaml(hashy).should be == ":en:\n :date:\n :formats:\n :default: ! '%d/%m/%Y'\n :short: ! '%d %b'"
9
+ end
10
+
11
+ it 'should convert to ya2yaml format with just one term' do
12
+ hashy = {:movie => "Avengers"}
13
+ Transdifflation::YAMLWriter.to_yaml(hashy).should be == ":movie: Avengers"
14
+ end
15
+ end
16
+
17
+ describe :deep_stringify_keys do
18
+ it 'should not change anything printing the hash exactly how it is' do
19
+ hashy = {:en=>{:date=>{:formats=>{:default=>"%d/%m/%Y", :short=>"%d %b"}}}}
20
+ hashy.deep_stringify_keys.should == {:en=>{:date=>{:formats=>{:default=>"%d/%m/%Y", :short=>"%d %b"}}}}
21
+ end
22
+ it 'should print all the nodes from a hash in the exact same order' do
23
+ hashy = {:en=>{:date=>{:formats=>{:default=>"%d/%m/%Y", :short=>"%d %b"}}}}
24
+ hashy.deep_stringify_keys.should == hashy
25
+ end
26
+ end
27
+
28
+ end
@@ -0,0 +1,31 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path('../lib/transdifflation/version', __FILE__)
3
+
4
+ Gem::Specification.new do |gem|
5
+ gem.authors = ["Steve Belicha & Javier Mey"]
6
+ gem.email = ["steve.belicha@sage.com; javier.mey@sage.com"]
7
+ gem.description = %q{Compares yml locate files with yours and generate diff files to maintain gems or adjacent projects }
8
+ gem.summary = %q{Compares yml locate files with yours and generate diff files to maintain gems or adjacent projects}
9
+ gem.homepage = ""
10
+
11
+ gem.files = `git ls-files`.split($\)
12
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
13
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
14
+ gem.name = "transdifflation"
15
+ gem.require_paths = ["lib"]
16
+ gem.version = "0.0.1"
17
+
18
+ #Dependencies
19
+ gem.add_dependency 'rails', '~> 3.2.8'
20
+
21
+ gem.add_development_dependency 'rspec', '>= 2.8.0'
22
+ gem.add_development_dependency 'guard-rspec'
23
+ gem.add_development_dependency 'yard'
24
+ gem.add_development_dependency 'redcarpet'
25
+ gem.add_development_dependency 'RedCloth'
26
+ gem.add_development_dependency 'simplecov'
27
+ gem.add_development_dependency 'rb-inotify'
28
+ gem.add_development_dependency 'libnotify'
29
+ gem.add_development_dependency 'pry'
30
+ end
31
+
metadata ADDED
@@ -0,0 +1,233 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: transdifflation
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Steve Belicha & Javier Mey
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-10-11 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rails
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ~>
20
+ - !ruby/object:Gem::Version
21
+ version: 3.2.8
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ~>
28
+ - !ruby/object:Gem::Version
29
+ version: 3.2.8
30
+ - !ruby/object:Gem::Dependency
31
+ name: rspec
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: 2.8.0
38
+ type: :development
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: 2.8.0
46
+ - !ruby/object:Gem::Dependency
47
+ name: guard-rspec
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ - !ruby/object:Gem::Dependency
63
+ name: yard
64
+ requirement: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ! '>='
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
70
+ type: :development
71
+ prerelease: false
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ! '>='
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
78
+ - !ruby/object:Gem::Dependency
79
+ name: redcarpet
80
+ requirement: !ruby/object:Gem::Requirement
81
+ none: false
82
+ requirements:
83
+ - - ! '>='
84
+ - !ruby/object:Gem::Version
85
+ version: '0'
86
+ type: :development
87
+ prerelease: false
88
+ version_requirements: !ruby/object:Gem::Requirement
89
+ none: false
90
+ requirements:
91
+ - - ! '>='
92
+ - !ruby/object:Gem::Version
93
+ version: '0'
94
+ - !ruby/object:Gem::Dependency
95
+ name: RedCloth
96
+ requirement: !ruby/object:Gem::Requirement
97
+ none: false
98
+ requirements:
99
+ - - ! '>='
100
+ - !ruby/object:Gem::Version
101
+ version: '0'
102
+ type: :development
103
+ prerelease: false
104
+ version_requirements: !ruby/object:Gem::Requirement
105
+ none: false
106
+ requirements:
107
+ - - ! '>='
108
+ - !ruby/object:Gem::Version
109
+ version: '0'
110
+ - !ruby/object:Gem::Dependency
111
+ name: simplecov
112
+ requirement: !ruby/object:Gem::Requirement
113
+ none: false
114
+ requirements:
115
+ - - ! '>='
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ none: false
122
+ requirements:
123
+ - - ! '>='
124
+ - !ruby/object:Gem::Version
125
+ version: '0'
126
+ - !ruby/object:Gem::Dependency
127
+ name: rb-inotify
128
+ requirement: !ruby/object:Gem::Requirement
129
+ none: false
130
+ requirements:
131
+ - - ! '>='
132
+ - !ruby/object:Gem::Version
133
+ version: '0'
134
+ type: :development
135
+ prerelease: false
136
+ version_requirements: !ruby/object:Gem::Requirement
137
+ none: false
138
+ requirements:
139
+ - - ! '>='
140
+ - !ruby/object:Gem::Version
141
+ version: '0'
142
+ - !ruby/object:Gem::Dependency
143
+ name: libnotify
144
+ requirement: !ruby/object:Gem::Requirement
145
+ none: false
146
+ requirements:
147
+ - - ! '>='
148
+ - !ruby/object:Gem::Version
149
+ version: '0'
150
+ type: :development
151
+ prerelease: false
152
+ version_requirements: !ruby/object:Gem::Requirement
153
+ none: false
154
+ requirements:
155
+ - - ! '>='
156
+ - !ruby/object:Gem::Version
157
+ version: '0'
158
+ - !ruby/object:Gem::Dependency
159
+ name: pry
160
+ requirement: !ruby/object:Gem::Requirement
161
+ none: false
162
+ requirements:
163
+ - - ! '>='
164
+ - !ruby/object:Gem::Version
165
+ version: '0'
166
+ type: :development
167
+ prerelease: false
168
+ version_requirements: !ruby/object:Gem::Requirement
169
+ none: false
170
+ requirements:
171
+ - - ! '>='
172
+ - !ruby/object:Gem::Version
173
+ version: '0'
174
+ description: ! 'Compares yml locate files with yours and generate diff files to maintain
175
+ gems or adjacent projects '
176
+ email:
177
+ - steve.belicha@sage.com; javier.mey@sage.com
178
+ executables: []
179
+ extensions: []
180
+ extra_rdoc_files: []
181
+ files:
182
+ - .gitignore
183
+ - Fudgefile
184
+ - Gemfile
185
+ - LICENSE
186
+ - README.md
187
+ - Rakefile
188
+ - lib/transdifflation.rb
189
+ - lib/transdifflation/exceptions.rb
190
+ - lib/transdifflation/railtie.rb
191
+ - lib/transdifflation/transdifflation.yml
192
+ - lib/transdifflation/utilities.rb
193
+ - lib/transdifflation/version.rb
194
+ - lib/transdifflation/yaml_reader.rb
195
+ - lib/transdifflation/yaml_writer.rb
196
+ - spec/spec_helper.rb
197
+ - spec/transdifflation_spec.rb
198
+ - spec/utilities_spec.rb
199
+ - spec/yaml_reader_spec.rb
200
+ - spec/yaml_writer_spec.rb
201
+ - transdifflation.gemspec
202
+ homepage: ''
203
+ licenses: []
204
+ post_install_message:
205
+ rdoc_options: []
206
+ require_paths:
207
+ - lib
208
+ required_ruby_version: !ruby/object:Gem::Requirement
209
+ none: false
210
+ requirements:
211
+ - - ! '>='
212
+ - !ruby/object:Gem::Version
213
+ version: '0'
214
+ required_rubygems_version: !ruby/object:Gem::Requirement
215
+ none: false
216
+ requirements:
217
+ - - ! '>='
218
+ - !ruby/object:Gem::Version
219
+ version: '0'
220
+ requirements: []
221
+ rubyforge_project:
222
+ rubygems_version: 1.8.24
223
+ signing_key:
224
+ specification_version: 3
225
+ summary: Compares yml locate files with yours and generate diff files to maintain
226
+ gems or adjacent projects
227
+ test_files:
228
+ - spec/spec_helper.rb
229
+ - spec/transdifflation_spec.rb
230
+ - spec/utilities_spec.rb
231
+ - spec/yaml_reader_spec.rb
232
+ - spec/yaml_writer_spec.rb
233
+ has_rdoc: