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.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/.rubocop.yml +88 -0
- data/.travis.yml +56 -4
- data/Gemfile +4 -4
- data/Gemfile.lock +55 -27
- data/Rakefile +12 -8
- data/Vagrantfile +68 -0
- data/completion/_falkor +55 -7
- data/falkorlib.gemspec +14 -12
- data/lib/falkorlib.rb +22 -21
- data/lib/falkorlib/bootstrap.rb +5 -1
- data/lib/falkorlib/bootstrap/base.rb +385 -693
- data/lib/falkorlib/bootstrap/git.rb +137 -0
- data/lib/falkorlib/bootstrap/latex.rb +186 -0
- data/lib/falkorlib/bootstrap/link.rb +108 -96
- data/lib/falkorlib/bootstrap/ruby.rb +102 -0
- data/lib/falkorlib/cli.rb +82 -26
- data/lib/falkorlib/cli/config.rb +8 -8
- data/lib/falkorlib/cli/link.rb +8 -9
- data/lib/falkorlib/cli/new.rb +25 -39
- data/lib/falkorlib/common.rb +425 -425
- data/lib/falkorlib/config.rb +114 -110
- data/lib/falkorlib/error.rb +27 -16
- data/lib/falkorlib/gem_tasks.rb +12 -11
- data/lib/falkorlib/git.rb +3 -4
- data/lib/falkorlib/git/base.rb +439 -396
- data/lib/falkorlib/git/flow.rb +163 -165
- data/lib/falkorlib/git_tasks.rb +31 -31
- data/lib/falkorlib/loader.rb +1 -1
- data/lib/falkorlib/puppet.rb +3 -5
- data/lib/falkorlib/puppet/base.rb +10 -15
- data/lib/falkorlib/puppet/modules.rb +367 -365
- data/lib/falkorlib/puppet_tasks.rb +11 -8
- data/lib/falkorlib/tasks.rb +51 -54
- data/lib/falkorlib/tasks/gem.rake +42 -43
- data/lib/falkorlib/tasks/gem.rb +12 -11
- data/lib/falkorlib/tasks/git.rake +101 -107
- data/lib/falkorlib/tasks/git.rb +31 -31
- data/lib/falkorlib/tasks/gitflow.rake +131 -141
- data/lib/falkorlib/tasks/puppet.rb +11 -8
- data/lib/falkorlib/tasks/puppet_modules.rake +143 -154
- data/lib/falkorlib/tasks/rspec.rake +94 -59
- data/lib/falkorlib/tasks/yard.rake +35 -39
- data/lib/falkorlib/version.rb +55 -55
- data/lib/falkorlib/versioning.rb +169 -167
- data/spec/falkorlib/bootstrap_helpers_spec.rb +106 -56
- data/spec/falkorlib/bootstrap_latex_spec.rb +145 -0
- data/spec/falkorlib/bootstrap_link_spec.rb +137 -0
- data/spec/falkorlib/bootstrap_ruby_spec.rb +118 -0
- data/spec/falkorlib/bootstrap_spec.rb +112 -129
- data/spec/falkorlib/git_spec.rb +94 -22
- data/spec/falkorlib/gitflow_spec.rb +54 -42
- data/spec/falkorlib/puppet_modules_spec.rb +35 -26
- data/spec/falkorlib/versioning_puppet_module_spec.rb +94 -90
- data/spec/falkorlib_spec.rb +5 -0
- data/spec/spec_helper.rb +88 -47
- data/templates/latex/article-ieee/main.tex.erb +509 -0
- data/templates/latex/article/_abstract.tex.erb +19 -0
- data/templates/latex/article/_acronyms.tex.erb +116 -0
- data/templates/latex/article/_conclusion.tex.erb +25 -0
- data/templates/latex/article/_context.tex.erb +17 -0
- data/templates/latex/article/_experiments.tex.erb +27 -0
- data/templates/latex/article/_implem.tex.erb +17 -0
- data/templates/latex/article/_introduction.tex.erb +39 -0
- data/templates/latex/article/_related_works.tex.erb +19 -0
- data/templates/latex/article/biblio.bib.erb +28 -0
- data/templates/latex/article/template.tex.erb +16 -0
- data/templates/latex/ieee/IEEEtran.bst +2409 -0
- data/templates/latex/ieee/IEEEtran.cls +6347 -0
- data/templates/motd/motd.erb +2 -1
- metadata +82 -2
data/lib/falkorlib/common.rb
CHANGED
@@ -1,470 +1,470 @@
|
|
1
1
|
# -*- encoding: utf-8 -*-
|
2
2
|
################################################################################
|
3
|
-
# Time-stamp: <
|
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'
|
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
|
-
#
|
17
|
-
|
18
|
-
|
19
|
-
|
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
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
50
|
+
# Print a text in red
|
51
|
+
def red(str)
|
52
|
+
(COLOR == true) ? Term::ANSIColor.red(str) : str
|
53
|
+
end
|
48
54
|
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
55
|
+
# Print a text in cyan
|
56
|
+
def cyan(str)
|
57
|
+
(COLOR == true) ? Term::ANSIColor.cyan(str) : str
|
58
|
+
end
|
53
59
|
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
60
|
+
# Print an info message
|
61
|
+
def info(str)
|
62
|
+
puts green("[INFO] " + str)
|
63
|
+
end
|
58
64
|
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
65
|
+
# Print an warning message
|
66
|
+
def warning(str)
|
67
|
+
puts cyan("/!\\ WARNING: " + str)
|
68
|
+
end
|
69
|
+
alias_method :warn, :warning
|
63
70
|
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
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
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
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
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
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
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
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
|
-
|
98
|
-
|
99
|
-
|
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
|
-
|
107
|
-
|
110
|
+
## Check for the presence of a given command
|
111
|
+
def command?(name)
|
112
|
+
`which #{name}`
|
113
|
+
$?.success?
|
114
|
+
end
|
108
115
|
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
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
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
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
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
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
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
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
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
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
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
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
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
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
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
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
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
|
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
|
-
|
337
|
-
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
|
344
|
-
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
|
350
|
-
|
351
|
-
|
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
|
-
|
363
|
-
|
364
|
-
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
|
370
|
-
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
|
377
|
-
|
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
|
-
|
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
|