falkorlib 0.6.19 → 0.7.0

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.
Files changed (72) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/.rubocop.yml +88 -0
  4. data/.travis.yml +56 -4
  5. data/Gemfile +4 -4
  6. data/Gemfile.lock +55 -27
  7. data/Rakefile +12 -8
  8. data/Vagrantfile +68 -0
  9. data/completion/_falkor +55 -7
  10. data/falkorlib.gemspec +14 -12
  11. data/lib/falkorlib.rb +22 -21
  12. data/lib/falkorlib/bootstrap.rb +5 -1
  13. data/lib/falkorlib/bootstrap/base.rb +385 -693
  14. data/lib/falkorlib/bootstrap/git.rb +137 -0
  15. data/lib/falkorlib/bootstrap/latex.rb +186 -0
  16. data/lib/falkorlib/bootstrap/link.rb +108 -96
  17. data/lib/falkorlib/bootstrap/ruby.rb +102 -0
  18. data/lib/falkorlib/cli.rb +82 -26
  19. data/lib/falkorlib/cli/config.rb +8 -8
  20. data/lib/falkorlib/cli/link.rb +8 -9
  21. data/lib/falkorlib/cli/new.rb +25 -39
  22. data/lib/falkorlib/common.rb +425 -425
  23. data/lib/falkorlib/config.rb +114 -110
  24. data/lib/falkorlib/error.rb +27 -16
  25. data/lib/falkorlib/gem_tasks.rb +12 -11
  26. data/lib/falkorlib/git.rb +3 -4
  27. data/lib/falkorlib/git/base.rb +439 -396
  28. data/lib/falkorlib/git/flow.rb +163 -165
  29. data/lib/falkorlib/git_tasks.rb +31 -31
  30. data/lib/falkorlib/loader.rb +1 -1
  31. data/lib/falkorlib/puppet.rb +3 -5
  32. data/lib/falkorlib/puppet/base.rb +10 -15
  33. data/lib/falkorlib/puppet/modules.rb +367 -365
  34. data/lib/falkorlib/puppet_tasks.rb +11 -8
  35. data/lib/falkorlib/tasks.rb +51 -54
  36. data/lib/falkorlib/tasks/gem.rake +42 -43
  37. data/lib/falkorlib/tasks/gem.rb +12 -11
  38. data/lib/falkorlib/tasks/git.rake +101 -107
  39. data/lib/falkorlib/tasks/git.rb +31 -31
  40. data/lib/falkorlib/tasks/gitflow.rake +131 -141
  41. data/lib/falkorlib/tasks/puppet.rb +11 -8
  42. data/lib/falkorlib/tasks/puppet_modules.rake +143 -154
  43. data/lib/falkorlib/tasks/rspec.rake +94 -59
  44. data/lib/falkorlib/tasks/yard.rake +35 -39
  45. data/lib/falkorlib/version.rb +55 -55
  46. data/lib/falkorlib/versioning.rb +169 -167
  47. data/spec/falkorlib/bootstrap_helpers_spec.rb +106 -56
  48. data/spec/falkorlib/bootstrap_latex_spec.rb +145 -0
  49. data/spec/falkorlib/bootstrap_link_spec.rb +137 -0
  50. data/spec/falkorlib/bootstrap_ruby_spec.rb +118 -0
  51. data/spec/falkorlib/bootstrap_spec.rb +112 -129
  52. data/spec/falkorlib/git_spec.rb +94 -22
  53. data/spec/falkorlib/gitflow_spec.rb +54 -42
  54. data/spec/falkorlib/puppet_modules_spec.rb +35 -26
  55. data/spec/falkorlib/versioning_puppet_module_spec.rb +94 -90
  56. data/spec/falkorlib_spec.rb +5 -0
  57. data/spec/spec_helper.rb +88 -47
  58. data/templates/latex/article-ieee/main.tex.erb +509 -0
  59. data/templates/latex/article/_abstract.tex.erb +19 -0
  60. data/templates/latex/article/_acronyms.tex.erb +116 -0
  61. data/templates/latex/article/_conclusion.tex.erb +25 -0
  62. data/templates/latex/article/_context.tex.erb +17 -0
  63. data/templates/latex/article/_experiments.tex.erb +27 -0
  64. data/templates/latex/article/_implem.tex.erb +17 -0
  65. data/templates/latex/article/_introduction.tex.erb +39 -0
  66. data/templates/latex/article/_related_works.tex.erb +19 -0
  67. data/templates/latex/article/biblio.bib.erb +28 -0
  68. data/templates/latex/article/template.tex.erb +16 -0
  69. data/templates/latex/ieee/IEEEtran.bst +2409 -0
  70. data/templates/latex/ieee/IEEEtran.cls +6347 -0
  71. data/templates/motd/motd.erb +2 -1
  72. metadata +82 -2
@@ -1,470 +1,470 @@
1
1
  # -*- encoding: utf-8 -*-
2
2
  ################################################################################
3
- # Time-stamp: <Sat 2016-10-15 22:49 svarrette>
3
+ # Time-stamp: <Fri 2016-11-11 14:17 svarrette>
4
4
  ################################################################################
5
5
 
6
6
  require "falkorlib"
7
7
  require 'open3'
8
- require 'erb' # required for module generation
8
+ require 'erb' # required for module generation
9
9
  require 'diffy'
10
10
  require 'json'
11
11
  require "pathname"
12
12
  require "facter"
13
13
 
14
14
  module FalkorLib #:nodoc:
15
+ # @abstract
16
+ # Recipe for all my toolbox and versatile Ruby functions I'm using
17
+ # everywhere.
18
+ # You'll typically want to include the `FalkorLib::Common` module to bring
19
+ # the corresponding definitions into yoru scope.
20
+ #
21
+ # @example:
22
+ # require 'falkorlib'
23
+ # include FalkorLib::Common
24
+ #
25
+ # info 'exemple of information text'
26
+ # really_continue?
27
+ # run %{ echo 'this is an executed command' }
28
+ #
29
+ # Falkor.config.debug = true
30
+ # run %{ echo 'this is a simulated command that *will not* be executed' }
31
+ # error "that's an error text, let's exit with status code 1"
32
+ #
33
+ module Common
34
+
35
+ module_function
36
+
37
+ ##################################
38
+ ### Default printing functions ###
39
+ ##################################
40
+ # Print a text in bold
41
+ def bold(str)
42
+ (COLOR == true) ? Term::ANSIColor.bold(str) : str
43
+ end
15
44
 
16
- # @abstract
17
- # Recipe for all my toolbox and versatile Ruby functions I'm using
18
- # everywhere.
19
- # You'll typically want to include the `FalkorLib::Common` module to bring
20
- # the corresponding definitions into yoru scope.
21
- #
22
- # @example:
23
- # require 'falkorlib'
24
- # include FalkorLib::Common
25
- #
26
- # info 'exemple of information text'
27
- # really_continue?
28
- # run %{ echo 'this is an executed command' }
29
- #
30
- # Falkor.config.debug = true
31
- # run %{ echo 'this is a simulated command that *will not* be executed' }
32
- # error "that's an error text, let's exit with status code 1"
33
- #
34
- module Common
35
- module_function
36
- ##################################
37
- ### Default printing functions ###
38
- ##################################
39
- # Print a text in bold
40
- def bold(str)
41
- COLOR == true ? Term::ANSIColor.bold(str) : str
42
- end
45
+ # Print a text in green
46
+ def green(str)
47
+ (COLOR == true) ? Term::ANSIColor.green(str) : str
48
+ end
43
49
 
44
- # Print a text in green
45
- def green(str)
46
- COLOR == true ? Term::ANSIColor.green(str) : str
47
- end
50
+ # Print a text in red
51
+ def red(str)
52
+ (COLOR == true) ? Term::ANSIColor.red(str) : str
53
+ end
48
54
 
49
- # Print a text in red
50
- def red(str)
51
- COLOR == true ? Term::ANSIColor.red(str) : str
52
- end
55
+ # Print a text in cyan
56
+ def cyan(str)
57
+ (COLOR == true) ? Term::ANSIColor.cyan(str) : str
58
+ end
53
59
 
54
- # Print a text in cyan
55
- def cyan(str)
56
- COLOR == true ? Term::ANSIColor.cyan(str) : str
57
- end
60
+ # Print an info message
61
+ def info(str)
62
+ puts green("[INFO] " + str)
63
+ end
58
64
 
59
- # Print an info message
60
- def info(str)
61
- puts green("[INFO] " + str)
62
- end
65
+ # Print an warning message
66
+ def warning(str)
67
+ puts cyan("/!\\ WARNING: " + str)
68
+ end
69
+ alias_method :warn, :warning
63
70
 
64
- # Print an warning message
65
- def warning(str)
66
- puts cyan("/!\\ WARNING: " + str)
67
- end
68
- alias :warn :warning
71
+ ## Print an error message and abort
72
+ def error(str)
73
+ #abort red("*** ERROR *** " + str)
74
+ $stderr.puts red("*** ERROR *** " + str)
75
+ exit 1
76
+ end
69
77
 
70
- ## Print an error message and abort
71
- def error(str)
72
- #abort red("*** ERROR *** " + str)
73
- $stderr.puts red("*** ERROR *** " + str)
74
- exit 1
75
- end
78
+ ## simple helper text to mention a non-implemented feature
79
+ def not_implemented
80
+ error("NOT YET IMPLEMENTED")
81
+ end
76
82
 
77
- ## simple helper text to mention a non-implemented feature
78
- def not_implemented()
79
- error("NOT YET IMPLEMENTED")
80
- end
83
+ ##############################
84
+ ### Interaction functions ###
85
+ ##############################
86
+
87
+ ## Ask a question
88
+ def ask(question, default_answer = '')
89
+ return default_answer if FalkorLib.config[:no_interaction]
90
+ print "#{question} "
91
+ print "[Default: #{default_answer}]" unless default_answer == ''
92
+ print ": "
93
+ STDOUT.flush
94
+ answer = STDIN.gets.chomp
95
+ (answer.empty?) ? default_answer : answer
96
+ end
81
97
 
82
- ##############################
83
- ### Interaction functions ###
84
- ##############################
85
-
86
- ## Ask a question
87
- def ask(question, default_answer='')
88
- return default_answer if FalkorLib.config[:no_interaction]
89
- print "#{question} "
90
- print "[Default: #{default_answer}]" unless default_answer == ''
91
- print ": "
92
- STDOUT.flush
93
- answer = STDIN.gets.chomp
94
- return answer.empty?() ? default_answer : answer
95
- end
98
+ ## Ask whether or not to really continue
99
+ def really_continue?(default_answer = 'Yes')
100
+ return if FalkorLib.config[:no_interaction]
101
+ pattern = (default_answer =~ /yes/i) ? '(Y|n)' : '(y|N)'
102
+ answer = ask( cyan("=> Do you really want to continue #{pattern}?"), default_answer)
103
+ exit 0 if answer =~ /n.*/i
104
+ end
96
105
 
97
- ## Ask whether or not to really continue
98
- def really_continue?(default_answer = 'Yes')
99
- return if FalkorLib.config[:no_interaction]
100
- pattern = (default_answer =~ /yes/i) ? '(Y|n)' : '(y|N)'
101
- answer = ask( cyan("=> Do you really want to continue #{pattern}?"), default_answer)
102
- exit 0 if answer =~ /n.*/i
103
- end
106
+ ############################
107
+ ### Execution functions ###
108
+ ############################
104
109
 
105
- ############################
106
- ### Execution functions ###
107
- ############################
110
+ ## Check for the presence of a given command
111
+ def command?(name)
112
+ `which #{name}`
113
+ $?.success?
114
+ end
108
115
 
109
- ## Check for the presence of a given command
110
- def command?(name)
111
- `which #{name}`
112
- $?.success?
116
+ ## Execute a given command, return exit code and print nicely stdout and stderr
117
+ def nice_execute(cmd)
118
+ puts bold("[Running] #{cmd.gsub(/^\s*/, ' ')}")
119
+ stdout, stderr, exit_status = Open3.capture3( cmd )
120
+ unless stdout.empty?
121
+ stdout.each_line do |line|
122
+ print "** [out] #{line}"
123
+ $stdout.flush
113
124
  end
114
-
115
- ## Execute a given command, return exit code and print nicely stdout and stderr
116
- def nice_execute(cmd)
117
- puts bold("[Running] #{cmd.gsub(/^\s*/, ' ')}")
118
- stdout, stderr, exit_status = Open3.capture3( cmd )
119
- unless stdout.empty?
120
- stdout.each_line do |line|
121
- print "** [out] #{line}"
122
- $stdout.flush
123
- end
124
- end
125
- unless stderr.empty?
126
- stderr.each_line do |line|
127
- $stderr.print red("** [err] #{line}")
128
- $stderr.flush
129
- end
130
- end
131
- exit_status
125
+ end
126
+ unless stderr.empty?
127
+ stderr.each_line do |line|
128
+ $stderr.print red("** [err] #{line}")
129
+ $stderr.flush
132
130
  end
131
+ end
132
+ exit_status
133
+ end
133
134
 
134
- # Simpler version that use the system call
135
- def execute(cmd)
136
- puts bold("[Running] #{cmd.gsub(/^\s*/, ' ')}")
137
- system(cmd)
138
- $?
139
- end
135
+ # Simpler version that use the system call
136
+ def execute(cmd)
137
+ puts bold("[Running] #{cmd.gsub(/^\s*/, ' ')}")
138
+ system(cmd)
139
+ $?.exitstatus
140
+ end
140
141
 
141
- ## Execute in a given directory
142
- def execute_in_dir(path, cmd)
143
- exit_status = 0
144
- Dir.chdir(path) do
145
- exit_status = run %{ #{cmd} }
146
- end
147
- exit_status
148
- end # execute_in_dir
149
-
150
- ## Execute a given command - exit if status != 0
151
- def exec_or_exit(cmd)
152
- status = execute(cmd)
153
- if (status.to_i != 0)
154
- error("The command '#{cmd}' failed with exit status #{status.to_i}")
155
- end
156
- status
157
- end
142
+ ## Execute in a given directory
143
+ def execute_in_dir(path, cmd)
144
+ exit_status = 0
145
+ Dir.chdir(path) do
146
+ exit_status = run %( #{cmd} )
147
+ end
148
+ exit_status
149
+ end # execute_in_dir
150
+
151
+ ## Execute a given command - exit if status != 0
152
+ def exec_or_exit(cmd)
153
+ status = execute(cmd)
154
+ if (status.to_i.nonzero?)
155
+ error("The command '#{cmd}' failed with exit status #{status.to_i}")
156
+ end
157
+ status
158
+ end
158
159
 
159
- ## "Nice" way to present run commands
160
- ## Ex: run %{ hostname -f }
161
- def run(cmds)
162
- exit_status = 0
163
- puts bold("[Running]\n#{cmds.gsub(/^\s*/, ' ')}")
164
- $stdout.flush
165
- #puts cmds.split(/\n */).inspect
166
- cmds.split(/\n */).each do |cmd|
167
- next if cmd.empty?
168
- system("#{cmd}") unless FalkorLib.config.debug
169
- exit_status = $?
170
- end
171
- exit_status
172
- end
160
+ ## "Nice" way to present run commands
161
+ ## Ex: run %{ hostname -f }
162
+ def run(cmds)
163
+ exit_status = 0
164
+ puts bold("[Running]\n#{cmds.gsub(/^\s*/, ' ')}")
165
+ $stdout.flush
166
+ #puts cmds.split(/\n */).inspect
167
+ cmds.split(/\n */).each do |cmd|
168
+ next if cmd.empty?
169
+ system(cmd.to_s) unless FalkorLib.config.debug
170
+ exit_status = $?.exitstatus
171
+ end
172
+ exit_status
173
+ end
173
174
 
174
- ## List items from a glob pattern to ask for a unique choice
175
- # Supported options:
176
- # :only_files [boolean]: list only files in the glob
177
- # :only_dirs [boolean]: list only directories in the glob
178
- # :pattern_include [array of strings]: pattern(s) to include for listing
179
- # :pattern_exclude [array of strings]: pattern(s) to exclude for listing
180
- # :text [string]: text to put
181
- def list_items(glob_pattern, options = {})
182
- list = { 0 => 'Exit' }
183
- index = 1
184
- raw_list = { 0 => 'Exit' }
185
-
186
- Dir["#{glob_pattern}"].each do |elem|
187
- #puts "=> element '#{elem}' - dir = #{File.directory?(elem)}; file = #{File.file?(elem)}"
188
- next if (! options[:only_files].nil?) && options[:only_files] && File.directory?(elem)
189
- next if (! options[:only_dirs].nil?) && options[:only_dirs] && File.file?(elem)
190
- entry = File.basename(elem)
191
- # unless options[:pattern_include].nil?
192
- # select_entry = false
193
- # options[:pattern_include].each do |pattern|
194
- # #puts "considering pattern '#{pattern}' on entry '#{entry}'"
195
- # select_entry |= entry =~ /#{pattern}/
196
- # end
197
- # next unless select_entry
198
- # end
199
- unless options[:pattern_exclude].nil?
200
- select_entry = false
201
- options[:pattern_exclude].each do |pattern|
202
- #puts "considering pattern '#{pattern}' on entry '#{entry}'"
203
- select_entry |= entry =~ /#{pattern}/
204
- end
205
- next if select_entry
206
- end
207
- #puts "selected entry = '#{entry}'"
208
- list[index] = entry
209
- raw_list[index] = elem
210
- index += 1
211
- end
212
- text = options[:text].nil? ? "select the index" : options[:text]
213
- default_idx = options[:default].nil? ? 0 : options[:default]
214
- raise SystemExit.new('Empty list') if index == 1
215
- #ap list
216
- #ap raw_list
217
- # puts list.to_yaml
218
- # answer = ask("=> #{text}", "#{default_idx}")
219
- # raise SystemExit.new('exiting selection') if answer == '0'
220
- # raise RangeError.new('Undefined index') if Integer(answer) >= list.length
221
- # raw_list[Integer(answer)]
222
- select_from(list, text, default_idx, raw_list)
175
+ ## List items from a glob pattern to ask for a unique choice
176
+ # Supported options:
177
+ # :only_files [boolean]: list only files in the glob
178
+ # :only_dirs [boolean]: list only directories in the glob
179
+ # :pattern_include [array of strings]: pattern(s) to include for listing
180
+ # :pattern_exclude [array of strings]: pattern(s) to exclude for listing
181
+ # :text [string]: text to put
182
+ def list_items(glob_pattern, options = {})
183
+ list = { 0 => 'Exit' }
184
+ index = 1
185
+ raw_list = { 0 => 'Exit' }
186
+
187
+ Dir[glob_pattern.to_s].each do |elem|
188
+ #puts "=> element '#{elem}' - dir = #{File.directory?(elem)}; file = #{File.file?(elem)}"
189
+ next if (!options[:only_files].nil?) && options[:only_files] && File.directory?(elem)
190
+ next if (!options[:only_dirs].nil?) && options[:only_dirs] && File.file?(elem)
191
+ entry = File.basename(elem)
192
+ # unless options[:pattern_include].nil?
193
+ # select_entry = false
194
+ # options[:pattern_include].each do |pattern|
195
+ # #puts "considering pattern '#{pattern}' on entry '#{entry}'"
196
+ # select_entry |= entry =~ /#{pattern}/
197
+ # end
198
+ # next unless select_entry
199
+ # end
200
+ unless options[:pattern_exclude].nil?
201
+ select_entry = false
202
+ options[:pattern_exclude].each do |pattern|
203
+ #puts "considering pattern '#{pattern}' on entry '#{entry}'"
204
+ select_entry |= entry =~ /#{pattern}/
205
+ end
206
+ next if select_entry
223
207
  end
208
+ #puts "selected entry = '#{entry}'"
209
+ list[index] = entry
210
+ raw_list[index] = elem
211
+ index += 1
212
+ end
213
+ text = (options[:text].nil?) ? "select the index" : options[:text]
214
+ default_idx = (options[:default].nil?) ? 0 : options[:default]
215
+ raise SystemExit, 'Empty list' if index == 1
216
+ #ap list
217
+ #ap raw_list
218
+ # puts list.to_yaml
219
+ # answer = ask("=> #{text}", "#{default_idx}")
220
+ # raise SystemExit.new('exiting selection') if answer == '0'
221
+ # raise RangeError.new('Undefined index') if Integer(answer) >= list.length
222
+ # raw_list[Integer(answer)]
223
+ select_from(list, text, default_idx, raw_list)
224
+ end
224
225
 
225
- ## Display a indexed list to select an i
226
- def select_from(list, text = 'Select the index', default_idx = 0, raw_list = list)
227
- error "list and raw_list differs in size" if list.size != raw_list.size
228
- l = list
229
- raw_l = raw_list
230
- if list.kind_of?(Array)
231
- l = raw_l = { 0 => 'Exit' }
232
- list.each_with_index do |e, idx|
233
- l[idx+1] = e
234
- raw_l[idx+1] = raw_list[idx]
235
- end
236
- end
237
- puts l.to_yaml
238
- answer = ask("=> #{text}", "#{default_idx}")
239
- raise SystemExit.new('exiting selection') if answer == '0'
240
- raise RangeError.new('Undefined index') if Integer(answer) >= l.length
241
- raw_l[Integer(answer)]
242
- end # select_from
243
-
244
-
245
- ###############################
246
- ### YAML File loading/store ###
247
- ###############################
248
-
249
- # Return the yaml content as a Hash object
250
- def load_config(file)
251
- unless File.exists?(file)
252
- raise FalkorLib::Error, "Unable to find the YAML file '#{file}'"
253
- end
254
- loaded = YAML::load_file(file)
255
- unless loaded.is_a?(Hash)
256
- raise FalkorLib::Error, "Corrupted or invalid YAML file '#{file}'"
257
- end
258
- loaded
226
+ ## Display a indexed list to select an i
227
+ def select_from(list, text = 'Select the index', default_idx = 0, raw_list = list)
228
+ error "list and raw_list differs in size" if list.size != raw_list.size
229
+ l = list
230
+ raw_l = raw_list
231
+ if list.is_a?(Array)
232
+ l = raw_l = { 0 => 'Exit' }
233
+ list.each_with_index do |e, idx|
234
+ l[idx + 1] = e
235
+ raw_l[idx + 1] = raw_list[idx]
259
236
  end
237
+ end
238
+ puts l.to_yaml
239
+ answer = ask("=> #{text}", default_idx.to_s)
240
+ raise SystemExit, 'exiting selection' if answer == '0'
241
+ raise RangeError, 'Undefined index' if Integer(answer) >= l.length
242
+ raw_l[Integer(answer)]
243
+ end # select_from
244
+
245
+
246
+ ###############################
247
+ ### YAML File loading/store ###
248
+ ###############################
249
+
250
+ # Return the yaml content as a Hash object
251
+ def load_config(file)
252
+ unless File.exist?(file)
253
+ raise FalkorLib::Error, "Unable to find the YAML file '#{file}'"
254
+ end
255
+ loaded = YAML.load_file(file)
256
+ unless loaded.is_a?(Hash)
257
+ raise FalkorLib::Error, "Corrupted or invalid YAML file '#{file}'"
258
+ end
259
+ loaded
260
+ end
260
261
 
261
- # Store the Hash object as a Yaml file
262
- # Supported options:
263
- # :header [string]: additional info to place in the header of the (stored) file
264
- # :no_interaction [boolean]: do not interact
265
- def store_config(filepath, hash, options = {})
266
- content = "# " + File.basename(filepath) + "\n"
267
- content += "# /!\\ DO NOT EDIT THIS FILE: it has been automatically generated\n"
268
- if options[:header]
269
- options[:header].split("\n").each { |line| content += "# #{line}" }
270
- end
271
- content += hash.to_yaml
272
- show_diff_and_write(content, filepath, options)
273
- # File.open( filepath, 'w') do |f|
274
- # f.print "# ", File.basename(filepath), "\n"
275
- # f.puts "# /!\\ DO NOT EDIT THIS FILE: it has been automatically generated"
276
- # if options[:header]
277
- # options[:header].split("\n").each do |line|
278
- # f.puts "# #{line}"
279
- # end
280
- # end
281
- # f.puts hash.to_yaml
282
- # end
283
- end
262
+ # Store the Hash object as a Yaml file
263
+ # Supported options:
264
+ # :header [string]: additional info to place in the header of the (stored) file
265
+ # :no_interaction [boolean]: do not interact
266
+ def store_config(filepath, hash, options = {})
267
+ content = "# " + File.basename(filepath) + "\n"
268
+ content += "# /!\\ DO NOT EDIT THIS FILE: it has been automatically generated\n"
269
+ if options[:header]
270
+ options[:header].split("\n").each { |line| content += "# #{line}" }
271
+ end
272
+ content += hash.to_yaml
273
+ show_diff_and_write(content, filepath, options)
274
+ # File.open( filepath, 'w') do |f|
275
+ # f.print "# ", File.basename(filepath), "\n"
276
+ # f.puts "# /!\\ DO NOT EDIT THIS FILE: it has been automatically generated"
277
+ # if options[:header]
278
+ # options[:header].split("\n").each do |line|
279
+ # f.puts "# #{line}"
280
+ # end
281
+ # end
282
+ # f.puts hash.to_yaml
283
+ # end
284
+ end
284
285
 
285
- #################################
286
- ### [ERB] template generation ###
287
- #################################
288
-
289
- # Bootstrap the destination directory `rootdir` using the template
290
- # directory `templatedir`. the hash table `config` hosts the elements to
291
- # feed ERB files which **should** have the extension .erb.
292
- # The initialization is performed as follows:
293
- # * a rsync process is initiated to duplicate the directory structure
294
- # and the symlinks, and exclude .erb files
295
- # * each erb files (thus with extension .erb) is interpreted, the
296
- # corresponding file is generated without the .erb extension
297
- # Supported options:
298
- # :erb_exclude [array of strings]: pattern(s) to exclude from erb file
299
- # interpretation and thus to copy 'as is'
300
- # :no_interaction [boolean]: do not interact
301
- def init_from_template(templatedir, rootdir, config = {},
302
- options = {
303
- :erb_exclude => [],
304
- :no_interaction => false
305
- })
306
- error "Unable to find the template directory" unless File.directory?(templatedir)
307
- warning "about to initialize/update the directory #{rootdir}"
308
- really_continue?
309
- run %{ mkdir -p #{rootdir} } unless File.directory?( rootdir )
310
- run %{ rsync --exclude '*.erb' --exclude '.texinfo*' -avzu #{templatedir}/ #{rootdir}/ }
311
- Dir["#{templatedir}/**/*.erb"].each do |erbfile|
312
- relative_outdir = Pathname.new( File.realpath( File.dirname(erbfile) )).relative_path_from Pathname.new(templatedir)
313
- filename = File.basename(erbfile, '.erb')
314
- outdir = File.realpath( File.join(rootdir, relative_outdir.to_s) )
315
- outfile = File.join(outdir, filename)
316
- unless options[:erb_exclude].nil?
317
- exclude_entry = false
318
- options[:erb_exclude].each do |pattern|
319
- exclude_entry |= erbfile =~ /#{pattern}/
320
- end
321
- if exclude_entry
322
- info "copying non-interpreted ERB file"
323
- # copy this file since it has been probably excluded from teh rsync process
324
- run %{ cp #{erbfile} #{outdir}/ }
325
- next
326
- end
327
- end
328
- # Let's go
329
- info "updating '#{relative_outdir.to_s}/#{filename}'"
330
- puts " using ERB template '#{erbfile}'"
331
- write_from_erb_template(erbfile, outfile, config, options)
332
- end
286
+ #################################
287
+ ### [ERB] template generation ###
288
+ #################################
289
+
290
+ # Bootstrap the destination directory `rootdir` using the template
291
+ # directory `templatedir`. the hash table `config` hosts the elements to
292
+ # feed ERB files which **should** have the extension .erb.
293
+ # The initialization is performed as follows:
294
+ # * a rsync process is initiated to duplicate the directory structure
295
+ # and the symlinks, and exclude .erb files
296
+ # * each erb files (thus with extension .erb) is interpreted, the
297
+ # corresponding file is generated without the .erb extension
298
+ # Supported options:
299
+ # :erb_exclude [array of strings]: pattern(s) to exclude from erb file
300
+ # interpretation and thus to copy 'as is'
301
+ # :no_interaction [boolean]: do not interact
302
+ def init_from_template(templatedir, rootdir, config = {},
303
+ options = {
304
+ :erb_exclude => [],
305
+ :no_interaction => false
306
+ })
307
+ error "Unable to find the template directory" unless File.directory?(templatedir)
308
+ warning "about to initialize/update the directory #{rootdir}"
309
+ really_continue? unless options[:no_interaction]
310
+ run %( mkdir -p #{rootdir} ) unless File.directory?( rootdir )
311
+ run %( rsync --exclude '*.erb' --exclude '.texinfo*' -avzu #{templatedir}/ #{rootdir}/ )
312
+ Dir["#{templatedir}/**/*.erb"].each do |erbfile|
313
+ relative_outdir = Pathname.new( File.realpath( File.dirname(erbfile) )).relative_path_from Pathname.new(templatedir)
314
+ filename = File.basename(erbfile, '.erb')
315
+ outdir = File.realpath( File.join(rootdir, relative_outdir.to_s) )
316
+ outfile = File.join(outdir, filename)
317
+ unless options[:erb_exclude].nil?
318
+ exclude_entry = false
319
+ options[:erb_exclude].each do |pattern|
320
+ exclude_entry |= erbfile =~ /#{pattern}/
321
+ end
322
+ if exclude_entry
323
+ info "copying non-interpreted ERB file"
324
+ # copy this file since it has been probably excluded from teh rsync process
325
+ run %( cp #{erbfile} #{outdir}/ )
326
+ next
327
+ end
333
328
  end
329
+ # Let's go
330
+ info "updating '#{relative_outdir}/#{filename}'"
331
+ puts " using ERB template '#{erbfile}'"
332
+ write_from_erb_template(erbfile, outfile, config, options)
333
+ end
334
+ end
334
335
 
335
- ###
336
- # ERB generation of the file `outfile` using the source template file `erbfile`
337
- # Supported options:
338
- # :no_interaction [boolean]: do not interact
339
- # :srcdir [string]: source dir for all considered ERB files
340
- def write_from_erb_template(erbfile, outfile, config = {},
341
- options = {
342
- :no_interaction => false,
343
- })
344
- erbfiles = erbfile.is_a?(Array) ? erbfile : [ erbfile ]
345
- content = ""
346
- erbfiles.each do |f|
347
- erb = options[:srcdir].nil? ? f : File.join(options[:srcdir], f)
348
- unless File.exists? (erb)
349
- warning "Unable to find the template ERBfile '#{erb}'"
350
- really_continue? unless options[:no_interaction]
351
- next
352
- end
353
- content += ERB.new(File.read("#{erb}"), nil, '<>').result(binding)
354
- end
355
- # error "Unable to find the template file #{erbfile}" unless File.exists? (erbfile )
356
- # template = File.read("#{erbfile}")
357
- # output = ERB.new(template, nil, '<>')
358
- # content = output.result(binding)
359
- show_diff_and_write(content, outfile, options)
336
+ ###
337
+ # ERB generation of the file `outfile` using the source template file `erbfile`
338
+ # Supported options:
339
+ # :no_interaction [boolean]: do not interact
340
+ # :srcdir [string]: source dir for all considered ERB files
341
+ def write_from_erb_template(erbfile, outfile, config = {},
342
+ options = {
343
+ :no_interaction => false
344
+ })
345
+ erbfiles = (erbfile.is_a?(Array)) ? erbfile : [ erbfile ]
346
+ content = ""
347
+ erbfiles.each do |f|
348
+ erb = (options[:srcdir].nil?) ? f : File.join(options[:srcdir], f)
349
+ unless File.exist?(erb)
350
+ warning "Unable to find the template ERBfile '#{erb}'"
351
+ really_continue? unless options[:no_interaction]
352
+ next
360
353
  end
354
+ content += ERB.new(File.read(erb.to_s), nil, '<>').result(binding)
355
+ end
356
+ # error "Unable to find the template file #{erbfile}" unless File.exists? (erbfile )
357
+ # template = File.read("#{erbfile}")
358
+ # output = ERB.new(template, nil, '<>')
359
+ # content = output.result(binding)
360
+ show_diff_and_write(content, outfile, options)
361
+ end
361
362
 
362
- ## Show the difference between a `content` string and an destination file (using Diff algorithm).
363
- # Obviosuly, if the outfile does not exists, no difference is proposed.
364
- # Supported options:
365
- # :no_interaction [boolean]: do not interact
366
- # :json_pretty_format [boolean]: write a json content, in pretty format
367
- # :no_commit [boolean]: do not (offer to) commit the changes
368
- # return 0 if nothing happened, 1 if a write has been done
369
- def show_diff_and_write(content, outfile, options = {
370
- :no_interaction => false,
371
- :json_pretty_format => false,
372
- :no_commit => false,
373
- })
374
- if File.exists?( outfile )
375
- ref = File.read( outfile )
376
- if options[:json_pretty_format]
377
- ref = JSON.pretty_generate (JSON.parse( IO.read( outfile ) ))
378
- end
379
- if ref == content
380
- warn "Nothing to update"
381
- return 0
382
- end
383
- warn "the file '#{outfile}' already exists and will be overwritten."
384
- warn "Expected difference: \n------"
385
- Diffy::Diff.default_format = :color
386
- puts Diffy::Diff.new(ref, content, :context => 1)
387
- else
388
- watch = options[:no_interaction] ? 'no' : ask( cyan(" ==> Do you want to see the generated file before commiting the writing (y|N)"), 'No')
389
- puts content if watch =~ /y.*/i
390
- end
391
- proceed = options[:no_interaction] ? 'yes' : ask( cyan(" ==> proceed with the writing (Y|n)"), 'Yes')
392
- return 0 if proceed =~ /n.*/i
393
- info("=> writing #{outfile}")
394
- File.open("#{outfile}", "w+") do |f|
395
- f.write content
396
- end
397
- if FalkorLib::Git.init?(File.dirname(outfile)) and ! options[:no_commit]
398
- do_commit = options[:no_interaction] ? 'yes' : ask( cyan(" ==> commit the changes (Y|n)"), 'Yes')
399
- FalkorLib::Git.add(outfile, "update content of '#{File.basename(outfile)}'") if do_commit =~ /y.*/i
400
- end
401
- return 1
363
+ ## Show the difference between a `content` string and an destination file (using Diff algorithm).
364
+ # Obviosuly, if the outfile does not exists, no difference is proposed.
365
+ # Supported options:
366
+ # :no_interaction [boolean]: do not interact
367
+ # :json_pretty_format [boolean]: write a json content, in pretty format
368
+ # :no_commit [boolean]: do not (offer to) commit the changes
369
+ # return 0 if nothing happened, 1 if a write has been done
370
+ def show_diff_and_write(content, outfile, options = {
371
+ :no_interaction => false,
372
+ :json_pretty_format => false,
373
+ :no_commit => false
374
+ })
375
+ if File.exist?( outfile )
376
+ ref = File.read( outfile )
377
+ if options[:json_pretty_format]
378
+ ref = JSON.pretty_generate(JSON.parse( IO.read( outfile ) ))
402
379
  end
403
-
404
-
405
- ## Blind copy of a source file `src` into its destination directory `dstdir`
406
- # Supported options:
407
- # :no_interaction [boolean]: do not interact
408
- # :srcdir [string]: source directory, make the `src` file relative to that directory
409
- # :outfile [string]: alter the outfile name (File.basename(src) by default)
410
- # :no_commit [boolean]: do not (offer to) commit the changes
411
- def write_from_template(src,dstdir,options = {
412
- :no_interaction => false,
413
- :no_commit => false,
414
- :srcdir => '',
415
- :outfile => ''
416
- })
417
- srcfile = options[:srcdir].nil? ? src : File.join(options[:srcdir], src)
418
- error "Unable to find the source file #{srcfile}" unless File.exists? ( srcfile )
419
- error "The destination directory '#{dstdir}' do not exist" unless File.directory?( dstdir )
420
- dstfile = options[:outfile].nil? ? File.basename(srcfile) : options[:outfile]
421
- outfile = File.join(dstdir, dstfile)
422
- content = File.read( srcfile )
423
- show_diff_and_write(content, outfile, options)
424
- end # copy_from_template
425
-
426
-
427
- ### RVM init
428
- def init_rvm(rootdir = Dir.pwd, gemset = '')
429
- rvm_files = {
430
- :version => File.join(rootdir, '.ruby-version'),
431
- :gemset => File.join(rootdir, '.ruby-gemset')
432
- }
433
- unless File.exists?( "#{rvm_files[:version]}")
434
- v = select_from(FalkorLib.config[:rvm][:rubies],
435
- "Select RVM ruby to configure for this directory",
436
- 3)
437
- File.open( rvm_files[:version], 'w') do |f|
438
- f.puts v
439
- end
440
- end
441
- unless File.exists?( "#{rvm_files[:gemset]}")
442
- g = gemset.empty? ? ask("Enter RVM gemset name for this directory", File.basename(rootdir)) : gemset
443
- File.open( rvm_files[:gemset], 'w') do |f|
444
- f.puts g
445
- end
446
- end
447
-
380
+ if ref == content
381
+ warn "Nothing to update"
382
+ return 0
448
383
  end
384
+ warn "the file '#{outfile}' already exists and will be overwritten."
385
+ warn "Expected difference: \n------"
386
+ Diffy::Diff.default_format = :color
387
+ puts Diffy::Diff.new(ref, content, :context => 1)
388
+ else
389
+ watch = (options[:no_interaction]) ? 'no' : ask( cyan(" ==> Do you want to see the generated file before commiting the writing (y|N)"), 'No')
390
+ puts content if watch =~ /y.*/i
391
+ end
392
+ proceed = (options[:no_interaction]) ? 'yes' : ask( cyan(" ==> proceed with the writing (Y|n)"), 'Yes')
393
+ return 0 if proceed =~ /n.*/i
394
+ info("=> writing #{outfile}")
395
+ File.open(outfile.to_s, "w+") do |f|
396
+ f.write content
397
+ end
398
+ if FalkorLib::Git.init?(File.dirname(outfile)) && !options[:no_commit]
399
+ do_commit = (options[:no_interaction]) ? 'yes' : ask( cyan(" ==> commit the changes (Y|n)"), 'Yes')
400
+ FalkorLib::Git.add(outfile, "update content of '#{File.basename(outfile)}'") if do_commit =~ /y.*/i
401
+ end
402
+ 1
403
+ end
449
404
 
450
- ###### normalize_path ######
451
- # Normalize a path and return the absolute path foreseen
452
- # Ex: '.' return Dir.pwd
453
- # Supported options:
454
- # * :relative [boolean] return relative path to the root dir
455
- ##
456
- def normalized_path(dir = Dir.pwd, options = {})
457
- rootdir = FalkorLib::Git.init?(dir) ? FalkorLib::Git.rootdir(dir) : dir
458
- path = dir
459
- path = Dir.pwd if dir == '.'
460
- path = File.join(Dir.pwd, dir) unless (dir =~ /^\// or dir == '.')
461
- if (options[:relative] or options[:relative_to])
462
- root = options[:relative_to] ? options[:relative_to] : rootdir
463
- relative_path_to_root = Pathname.new( File.realpath(path) ).relative_path_from Pathname.new(root)
464
- path = relative_path_to_root.to_s
465
- end
466
- return path
467
- end # normalize_path
468
405
 
406
+ ## Blind copy of a source file `src` into its destination directory `dstdir`
407
+ # Supported options:
408
+ # :no_interaction [boolean]: do not interact
409
+ # :srcdir [string]: source directory, make the `src` file relative to that directory
410
+ # :outfile [string]: alter the outfile name (File.basename(src) by default)
411
+ # :no_commit [boolean]: do not (offer to) commit the changes
412
+ def write_from_template(src, dstdir, options = {
413
+ :no_interaction => false,
414
+ :no_commit => false,
415
+ :srcdir => '',
416
+ :outfile => ''
417
+ })
418
+ srcfile = (options[:srcdir].nil?) ? src : File.join(options[:srcdir], src)
419
+ error "Unable to find the source file #{srcfile}" unless File.exist?( srcfile )
420
+ error "The destination directory '#{dstdir}' do not exist" unless File.directory?( dstdir )
421
+ dstfile = (options[:outfile].nil?) ? File.basename(srcfile) : options[:outfile]
422
+ outfile = File.join(dstdir, dstfile)
423
+ content = File.read( srcfile )
424
+ show_diff_and_write(content, outfile, options)
425
+ end # copy_from_template
426
+
427
+
428
+ ### RVM init
429
+ def init_rvm(rootdir = Dir.pwd, gemset = '')
430
+ rvm_files = {
431
+ :version => File.join(rootdir, '.ruby-version'),
432
+ :gemset => File.join(rootdir, '.ruby-gemset')
433
+ }
434
+ unless File.exist?( (rvm_files[:version]).to_s)
435
+ v = select_from(FalkorLib.config[:rvm][:rubies],
436
+ "Select RVM ruby to configure for this directory",
437
+ 3)
438
+ File.open( rvm_files[:version], 'w') do |f|
439
+ f.puts v
440
+ end
441
+ end
442
+ unless File.exist?( (rvm_files[:gemset]).to_s)
443
+ g = (gemset.empty?) ? ask("Enter RVM gemset name for this directory", File.basename(rootdir)) : gemset
444
+ File.open( rvm_files[:gemset], 'w') do |f|
445
+ f.puts g
446
+ end
447
+ end
469
448
  end
449
+
450
+ ###### normalize_path ######
451
+ # Normalize a path and return the absolute path foreseen
452
+ # Ex: '.' return Dir.pwd
453
+ # Supported options:
454
+ # * :relative [boolean] return relative path to the root dir
455
+ ##
456
+ def normalized_path(dir = Dir.pwd, options = {})
457
+ rootdir = (FalkorLib::Git.init?(dir)) ? FalkorLib::Git.rootdir(dir) : dir
458
+ path = dir
459
+ path = Dir.pwd if dir == '.'
460
+ path = File.join(Dir.pwd, dir) unless (dir =~ /^\// || (dir == '.'))
461
+ if (options[:relative] || options[:relative_to])
462
+ root = (options[:relative_to]) ? options[:relative_to] : rootdir
463
+ relative_path_to_root = Pathname.new( File.realpath(path) ).relative_path_from Pathname.new(root)
464
+ path = relative_path_to_root.to_s
465
+ end
466
+ path
467
+ end # normalize_path
468
+
469
+ end
470
470
  end