fronde 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/LICENSE +14 -0
- data/bin/fronde +45 -0
- data/lib/fronde/cli.rb +60 -0
- data/lib/fronde/cli/commands.rb +115 -0
- data/lib/fronde/config.rb +137 -0
- data/lib/fronde/config/lisp_config.rb +269 -0
- data/lib/fronde/config/org-config.el +17 -0
- data/lib/fronde/config/ox-fronde.el +114 -0
- data/lib/fronde/emacs.rb +37 -0
- data/lib/fronde/index.rb +130 -0
- data/lib/fronde/index/atom_generator.rb +86 -0
- data/lib/fronde/index/org_generator.rb +114 -0
- data/lib/fronde/org_file.rb +301 -0
- data/lib/fronde/org_file/class_methods.rb +72 -0
- data/lib/fronde/org_file/extracter.rb +72 -0
- data/lib/fronde/org_file/htmlizer.rb +43 -0
- data/lib/fronde/preview.rb +55 -0
- data/lib/fronde/templater.rb +118 -0
- data/lib/fronde/utils.rb +214 -0
- data/lib/fronde/version.rb +6 -0
- data/lib/tasks/org.rake +96 -0
- data/lib/tasks/site.rake +55 -0
- data/lib/tasks/sync.rake +34 -0
- data/lib/tasks/tags.rake +19 -0
- data/locales/en.yml +37 -0
- data/locales/fr.yml +37 -0
- metadata +267 -0
@@ -0,0 +1,55 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'webrick'
|
4
|
+
require 'fronde/config'
|
5
|
+
|
6
|
+
module Fronde # rubocop:disable Style/Documentation
|
7
|
+
# A tiny preview server, which main goal is to replace references to
|
8
|
+
# the target domain by localhost.
|
9
|
+
class PreviewServlet < WEBrick::HTTPServlet::AbstractServlet
|
10
|
+
include WEBrick::HTTPUtils
|
11
|
+
|
12
|
+
def do_GET(request, response) # rubocop:disable Naming/MethodName
|
13
|
+
file = local_path(request.path)
|
14
|
+
response.body = parse_body(file, "http://#{request.host}:#{request.port}")
|
15
|
+
response.status = 200
|
16
|
+
response.content_type = mime_type(file, DefaultMimeTypes)
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
def local_path(requested_path)
|
22
|
+
routes = Fronde::Config.settings.dig('preview', 'routes') || {}
|
23
|
+
return routes[requested_path] if routes.has_key? requested_path
|
24
|
+
local_path = Fronde::Config.settings['public_folder'] + requested_path
|
25
|
+
if File.directory? local_path
|
26
|
+
local_path = format(
|
27
|
+
'%<path>s/index.html', path: local_path.delete_suffix('/')
|
28
|
+
)
|
29
|
+
end
|
30
|
+
return local_path if File.exist? local_path
|
31
|
+
raise WEBrick::HTTPStatus::NotFound, 'Not found.'
|
32
|
+
end
|
33
|
+
|
34
|
+
def parse_body(local_path, local_host)
|
35
|
+
body = IO.read local_path
|
36
|
+
return body unless local_path.match?(/\.(?:ht|x)ml\z/)
|
37
|
+
domain = Fronde::Config.settings['domain']
|
38
|
+
return body if domain == ''
|
39
|
+
body.gsub(/"file:\/\//, format('"%<host>s', host: local_host))
|
40
|
+
.gsub(/"#{domain}/, format('"%<host>s', host: local_host))
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
class << self
|
45
|
+
def start_preview
|
46
|
+
# Inspired by ruby un.rb library, which allows normally to start a
|
47
|
+
# webrick server in one line: ruby -run -e httpd public_html -p 5000
|
48
|
+
port = Fronde::Config.settings.dig('preview', 'server_port') || 5000
|
49
|
+
s = WEBrick::HTTPServer.new(Port: port)
|
50
|
+
s.mount '/', Fronde::PreviewServlet
|
51
|
+
['TERM', 'QUIT', 'INT'].each { |sig| trap(sig, proc { s.shutdown }) }
|
52
|
+
s.start
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,118 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'nokogiri'
|
4
|
+
require 'digest/md5'
|
5
|
+
require 'fronde/org_file'
|
6
|
+
|
7
|
+
module Fronde
|
8
|
+
# Insert custom part inside generated HTML files.
|
9
|
+
class Templater
|
10
|
+
def initialize(source, dom, opts = {})
|
11
|
+
@dom = dom
|
12
|
+
@org_file = source
|
13
|
+
@position = opts['type'] || 'after'
|
14
|
+
@content = extract_content opts
|
15
|
+
@element = @dom.css(opts['selector'])
|
16
|
+
digest = Digest::MD5.hexdigest(@content)
|
17
|
+
@check_line = " Fronde Template: #{digest} "
|
18
|
+
end
|
19
|
+
|
20
|
+
def apply
|
21
|
+
flag_head
|
22
|
+
content = @org_file.format(@content)
|
23
|
+
@element.each do |e|
|
24
|
+
insert_new_node_at e, content
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def in_head?
|
29
|
+
@dom.xpath('//head').children.to_a.filter(&:comment?).each do |c|
|
30
|
+
return true if c.text == @check_line
|
31
|
+
end
|
32
|
+
false
|
33
|
+
end
|
34
|
+
|
35
|
+
class << self
|
36
|
+
def customize_output(file_name, source = nil)
|
37
|
+
templates_to_apply = filter_templates(file_name)
|
38
|
+
return if templates_to_apply.empty?
|
39
|
+
if source.nil?
|
40
|
+
sourcepath = Fronde::OrgFile.source_for_target(file_name)
|
41
|
+
source = Fronde::OrgFile.new(sourcepath)
|
42
|
+
end
|
43
|
+
dom = open_dom(file_name)
|
44
|
+
templates_to_apply.each do |t|
|
45
|
+
tpl = Fronde::Templater.new(source, dom, t)
|
46
|
+
next if tpl.in_head?
|
47
|
+
tpl.apply
|
48
|
+
end
|
49
|
+
write_dom(file_name, dom)
|
50
|
+
end
|
51
|
+
|
52
|
+
private
|
53
|
+
|
54
|
+
def filter_templates(file_name)
|
55
|
+
templates = Fronde::Config.settings['templates']
|
56
|
+
return [] if templates.nil? || templates.empty?
|
57
|
+
templates.filter { |t| check_required_keys(t, file_name) }
|
58
|
+
end
|
59
|
+
|
60
|
+
def open_dom(file_name)
|
61
|
+
file = File.new file_name, 'r'
|
62
|
+
dom = Nokogiri::HTML file
|
63
|
+
file.close
|
64
|
+
dom
|
65
|
+
end
|
66
|
+
|
67
|
+
def write_dom(file_name, dom)
|
68
|
+
file = File.new file_name, 'w'
|
69
|
+
dom.write_to file
|
70
|
+
file.close
|
71
|
+
end
|
72
|
+
|
73
|
+
def check_path(file_name, pathes)
|
74
|
+
pub_folder = Fronde::Config.settings['public_folder']
|
75
|
+
if pathes.is_a?(Array)
|
76
|
+
pathes.each do |tp|
|
77
|
+
return true if File.fnmatch?("#{pub_folder}#{tp}",
|
78
|
+
file_name, File::FNM_DOTMATCH)
|
79
|
+
end
|
80
|
+
return false
|
81
|
+
end
|
82
|
+
File.fnmatch?("#{pub_folder}#{pathes}",
|
83
|
+
file_name, File::FNM_DOTMATCH)
|
84
|
+
end
|
85
|
+
|
86
|
+
def check_required_keys(opts, file_name)
|
87
|
+
return false unless opts.has_key?('selector')
|
88
|
+
return false unless opts.has_key?('content') || opts.has_key?('source')
|
89
|
+
return check_path(file_name, opts['path']) if opts.has_key?('path')
|
90
|
+
true
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
private
|
95
|
+
|
96
|
+
def flag_head
|
97
|
+
@dom.xpath('//head').first.prepend_child("<!--#{@check_line}-->\n")
|
98
|
+
end
|
99
|
+
|
100
|
+
def insert_new_node_at(elem, content)
|
101
|
+
case @position
|
102
|
+
when 'before'
|
103
|
+
elem.add_previous_sibling content
|
104
|
+
when 'replace'
|
105
|
+
elem.replace content
|
106
|
+
else
|
107
|
+
elem.add_next_sibling content
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
def extract_content(opts)
|
112
|
+
return opts['content'] if opts['content']
|
113
|
+
# If we don't have a content option, then we must have a source
|
114
|
+
# one.
|
115
|
+
@dom.css(opts['source']).unlink.to_s
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
data/lib/fronde/utils.rb
ADDED
@@ -0,0 +1,214 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'uri'
|
4
|
+
require 'rainbow'
|
5
|
+
require 'net/http'
|
6
|
+
require 'r18n-core'
|
7
|
+
require 'fronde/config'
|
8
|
+
|
9
|
+
module Fronde
|
10
|
+
# Embeds usefull methods, mainly used in rake tasks.
|
11
|
+
module Utils
|
12
|
+
# @return [Hash] the possible throbber themes
|
13
|
+
THROBBER_FRAMES = {
|
14
|
+
'basic' => '-\|/',
|
15
|
+
'basicdots' => '⋯⋱⋮⋰',
|
16
|
+
'moon' => '🌑🌒🌓🌔🌕🌖🌗🌘',
|
17
|
+
'clock' => '🕛🕐🕑🕒🕓🕔🕕🕖🕗🕘🕙🕚',
|
18
|
+
'bricks' => '⣷⣯⣟⡿⢿⣻⣽⣾',
|
19
|
+
'points' => '·⁘∷⁛∷⁘',
|
20
|
+
'quadrant2' => '▙▛▜▟',
|
21
|
+
'default' => ['⠁ ⠂ ⠄ ⡀ ⠄ ⠂ ⠁', '⠂ ⠁ ⠂ ⠄ ⡀ ⠄ ⠂', '⠄ ⠂ ⠁ ⠂ ⠄ ⡀ ⠄',
|
22
|
+
'⡀ ⠄ ⠂ ⠁ ⠂ ⠄ ⡀', '⠄ ⡀ ⠄ ⠂ ⠁ ⠂ ⠄', '⠂ ⠄ ⡀ ⠄ ⠂ ⠁ ⠂']
|
23
|
+
}.freeze
|
24
|
+
|
25
|
+
# @return [Hash] the possible ~fronde~ options and their
|
26
|
+
# configuration
|
27
|
+
FRONDE_OPTIONS = {
|
28
|
+
'-a' => { long: 'author' },
|
29
|
+
'-f' => { long: 'force', boolean: true },
|
30
|
+
'-h' => { long: 'help', boolean: true, meth: :on_tail },
|
31
|
+
'-l' => { long: 'lang', keyword: 'LOCALE' },
|
32
|
+
'-t' => { long: 'title' },
|
33
|
+
'-v' => { long: 'verbose', boolean: true, meth: :on_tail },
|
34
|
+
'-V' => { long: 'version', boolean: true, meth: :on_tail }
|
35
|
+
}.freeze
|
36
|
+
|
37
|
+
# @return [Hash] the possible ~fronde~ subcommands and their
|
38
|
+
# configuration
|
39
|
+
FRONDE_COMMANDS = {
|
40
|
+
'init' => { opts: ['-a', '-h', '-l', '-t', '-v'] },
|
41
|
+
'config' => { alias: 'init' },
|
42
|
+
'preview' => { opts: ['-h'] },
|
43
|
+
'open' => { opts: ['-a', '-h', '-l', '-t', '-v'] },
|
44
|
+
'edit' => { alias: 'open' },
|
45
|
+
'build' => { opts: ['-f', '-h'] },
|
46
|
+
'publish' => { opts: ['-h'] },
|
47
|
+
'help' => { opts: ['-h'] },
|
48
|
+
'basic' => { opts: ['-h', '-V'], label: '<command>' }
|
49
|
+
}.freeze
|
50
|
+
|
51
|
+
class << self
|
52
|
+
# Animates strings in the user console to alert him that something
|
53
|
+
# is running in the background.
|
54
|
+
#
|
55
|
+
# The animation is chosen among a bunch of themes, with the
|
56
|
+
# configuration option ~throbber~ (retrieved via
|
57
|
+
# {Fronde::Config#settings}).
|
58
|
+
#
|
59
|
+
# @example
|
60
|
+
# long_stuff = Thread.new { very_long_operation }
|
61
|
+
# Fronde::Utils.throbber(long_stuff, 'Computing hard stuff:')
|
62
|
+
#
|
63
|
+
# @param thread [Thread] the long-running operation to decorate
|
64
|
+
# @param message [String] the message to display before the throbber
|
65
|
+
# @return [void]
|
66
|
+
def throbber(thread, message)
|
67
|
+
frames = select_throbber_frames
|
68
|
+
begin
|
69
|
+
run_and_decorate_thread thread, message, frames
|
70
|
+
rescue RuntimeError => e
|
71
|
+
throbber_error message
|
72
|
+
raise e
|
73
|
+
else
|
74
|
+
done = Rainbow('done'.ljust(frames[0].length)).green
|
75
|
+
puts "#{message} #{done}"
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
# Returns the short and long options specification for a given
|
80
|
+
# short option.
|
81
|
+
#
|
82
|
+
# This method use the {Fronde::Utils::FRONDE_OPTIONS} Hash to
|
83
|
+
# retrieve corresponding values.
|
84
|
+
#
|
85
|
+
# @example
|
86
|
+
# spec = Fronde::Utils.decorate_option('-a')
|
87
|
+
# => ['-a AUTHOR', '--author AUTHOR']
|
88
|
+
#
|
89
|
+
# @param short [String] the short option to decorate
|
90
|
+
# @return [Array] the short and long specification for an option
|
91
|
+
def decorate_option(short)
|
92
|
+
opt = Fronde::Utils::FRONDE_OPTIONS[short]
|
93
|
+
long = "--#{opt[:long]}"
|
94
|
+
return [short, long] if opt[:boolean]
|
95
|
+
key = opt[:keyword] || opt[:long].upcase
|
96
|
+
[short + key, format('%<long>s %<key>s', long: long, key: key)]
|
97
|
+
end
|
98
|
+
|
99
|
+
# Returns the ~fronde~ help summary for a given command.
|
100
|
+
#
|
101
|
+
# @param command [String] the command for which a summary
|
102
|
+
# should be given
|
103
|
+
# @return [String]
|
104
|
+
def summarize_command(command)
|
105
|
+
Fronde::Utils::FRONDE_COMMANDS[command][:opts].map do |k|
|
106
|
+
short, long = Fronde::Utils.decorate_option(k)
|
107
|
+
opt = Fronde::Utils::FRONDE_OPTIONS[k]
|
108
|
+
label = [short, long].join(', ')
|
109
|
+
line = [format(' %<opt>s', opt: label).ljust(30)]
|
110
|
+
if R18n.t.fronde.bin.options[opt[:long]].translated?
|
111
|
+
line << R18n.t.fronde.bin.options[opt[:long]]
|
112
|
+
end
|
113
|
+
line.join(' ')
|
114
|
+
end.join("\n")
|
115
|
+
end
|
116
|
+
|
117
|
+
# Returns a formatted list of available commands for ~fronde~.
|
118
|
+
#
|
119
|
+
# @return [String]
|
120
|
+
def list_commands
|
121
|
+
lines = []
|
122
|
+
Fronde::Utils::FRONDE_COMMANDS.each do |cmd, opt|
|
123
|
+
next if cmd == 'basic'
|
124
|
+
line = [' ', cmd.ljust(10)]
|
125
|
+
if opt.has_key? :alias
|
126
|
+
line << R18n.t.fronde.bin.commands.alias(opt[:alias])
|
127
|
+
else
|
128
|
+
line << R18n.t.fronde.bin.commands[cmd]
|
129
|
+
end
|
130
|
+
lines << line.join(' ')
|
131
|
+
end
|
132
|
+
lines.join("\n")
|
133
|
+
end
|
134
|
+
|
135
|
+
# Returns the real command name for a given command, which may be
|
136
|
+
# an alias.
|
137
|
+
#
|
138
|
+
# @param command [String] the command to resolve
|
139
|
+
# @return [String]
|
140
|
+
def resolve_possible_alias(command)
|
141
|
+
return 'basic' unless Fronde::Utils::FRONDE_COMMANDS.include?(command)
|
142
|
+
cmd_opt = Fronde::Utils::FRONDE_COMMANDS[command]
|
143
|
+
return cmd_opt[:alias] if cmd_opt.has_key?(:alias)
|
144
|
+
command
|
145
|
+
end
|
146
|
+
|
147
|
+
# Try to discover the current host operating system.
|
148
|
+
#
|
149
|
+
# @return [String] either apple, windows or linux (default)
|
150
|
+
# :nocov:
|
151
|
+
def current_os
|
152
|
+
if ENV['OS'] == 'Windows_NT' || RUBY_PLATFORM.include?('cygwin')
|
153
|
+
return 'windows'
|
154
|
+
end
|
155
|
+
return 'apple' if RUBY_PLATFORM.include?('darwin')
|
156
|
+
'linux'
|
157
|
+
end
|
158
|
+
# :nocov:
|
159
|
+
|
160
|
+
# Download latest org-mode tarball.
|
161
|
+
#
|
162
|
+
# @param destination [String] where to save the org-mode tarball
|
163
|
+
# @return [String] the downloaded org-mode version
|
164
|
+
def download_org(destination = 'var/tmp')
|
165
|
+
# :nocov:
|
166
|
+
return if Fronde::Config.org_last_version.nil?
|
167
|
+
# :nocov:
|
168
|
+
tarball = "org-#{Fronde::Config.org_last_version}.tar.gz"
|
169
|
+
# Remove version number in dest file to allow easy rake file
|
170
|
+
# task naming
|
171
|
+
dest_file = File.expand_path('org.tar.gz', destination)
|
172
|
+
return if File.exist?(dest_file)
|
173
|
+
uri = URI("https://orgmode.org/#{tarball}")
|
174
|
+
# Will crash on purpose if anything goes wrong
|
175
|
+
Net::HTTP.start(uri.host, uri.port, :use_ssl => true) do |http|
|
176
|
+
http.request(Net::HTTP::Get.new(uri)) do |response|
|
177
|
+
File.open(dest_file, 'w') do |io|
|
178
|
+
response.read_body { |chunk| io.write chunk }
|
179
|
+
end
|
180
|
+
end
|
181
|
+
end
|
182
|
+
end
|
183
|
+
|
184
|
+
private
|
185
|
+
|
186
|
+
def throbber_error(message)
|
187
|
+
warn(
|
188
|
+
format(
|
189
|
+
"%<message>s %<label>s\n%<explanation>s",
|
190
|
+
message: message,
|
191
|
+
label: Rainbow(R18n.t.fronde.error.label).bold.red,
|
192
|
+
explanation: Rainbow(R18n.t.fronde.error.explanation).bold
|
193
|
+
)
|
194
|
+
)
|
195
|
+
end
|
196
|
+
|
197
|
+
def select_throbber_frames
|
198
|
+
model = Fronde::Config.settings['throbber'] || 'default'
|
199
|
+
model = 'default' unless Fronde::Utils::THROBBER_FRAMES.has_key?(model)
|
200
|
+
Fronde::Utils::THROBBER_FRAMES[model]
|
201
|
+
end
|
202
|
+
|
203
|
+
def run_and_decorate_thread(thread, message, frames)
|
204
|
+
thread.abort_on_exception = true
|
205
|
+
current = 0
|
206
|
+
while thread.alive?
|
207
|
+
sleep 0.1
|
208
|
+
print "#{message} #{frames[current % frames.length]}\r"
|
209
|
+
current += 1
|
210
|
+
end
|
211
|
+
end
|
212
|
+
end
|
213
|
+
end
|
214
|
+
end
|
data/lib/tasks/org.rake
ADDED
@@ -0,0 +1,96 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'open-uri'
|
4
|
+
|
5
|
+
# Fronde::Config is required by Fronde::Utils
|
6
|
+
require 'fronde/utils'
|
7
|
+
|
8
|
+
require 'rake/clean'
|
9
|
+
|
10
|
+
CLOBBER.push(
|
11
|
+
'var/tmp/org.tar.gz', 'var/tmp/last_org_version',
|
12
|
+
'var/lib/org-config.el', '.dir-locals.el', 'lib/htmlize.el'
|
13
|
+
)
|
14
|
+
|
15
|
+
namespace :org do
|
16
|
+
directory 'var/tmp'
|
17
|
+
|
18
|
+
desc 'Download last version of Org'
|
19
|
+
file 'var/tmp/org.tar.gz' => 'var/tmp' do
|
20
|
+
verbose = Rake::FileUtilsExt.verbose_flag
|
21
|
+
download = Thread.new do
|
22
|
+
Thread.current[:org_version] = Fronde::Config.org_last_version
|
23
|
+
Fronde::Utils.download_org
|
24
|
+
end
|
25
|
+
if verbose
|
26
|
+
download.join
|
27
|
+
warn "Org version #{download[:org_version]} has been downloaded"
|
28
|
+
else
|
29
|
+
Fronde::Utils.throbber(download, 'Downloading Org:')
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
desc 'Compile Org'
|
34
|
+
task compile: 'var/tmp/org.tar.gz' do |task|
|
35
|
+
verbose = Rake::FileUtilsExt.verbose_flag
|
36
|
+
org_version = Fronde::Config.org_last_version
|
37
|
+
org_dir = "lib/org-#{org_version}"
|
38
|
+
next if Dir.exist?("#{org_dir}/lisp")
|
39
|
+
make = ['make', '-C', org_dir]
|
40
|
+
unless verbose
|
41
|
+
make << '-s'
|
42
|
+
make << 'EMACSQ="emacs -Q --eval \'(setq inhibit-message t)\'"'
|
43
|
+
end
|
44
|
+
build = Thread.new do
|
45
|
+
sh "tar -C lib -xzf #{task.prerequisites[0]}"
|
46
|
+
sh((make + ['compile']).join(' '))
|
47
|
+
sh((make + ['autoloads']).join(' '))
|
48
|
+
Dir.glob('lib/org-[0-9.]*').each do |ov|
|
49
|
+
next if ov == org_dir
|
50
|
+
rm_r ov
|
51
|
+
end
|
52
|
+
end
|
53
|
+
if verbose
|
54
|
+
build.join
|
55
|
+
warn "#{org_version} has been locally installed"
|
56
|
+
else
|
57
|
+
Fronde::Utils.throbber(build, 'Installing Org:')
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
directory 'lib'
|
62
|
+
|
63
|
+
file 'lib/htmlize.el' => 'lib' do
|
64
|
+
htmlize = URI(
|
65
|
+
'https://raw.githubusercontent.com/hniksic/emacs-htmlize/master/htmlize.el'
|
66
|
+
).open.read
|
67
|
+
IO.write 'lib/htmlize.el', htmlize
|
68
|
+
end
|
69
|
+
|
70
|
+
file 'var/lib/org-config.el' => 'lib/htmlize.el' do
|
71
|
+
Fronde::Config.write_org_lisp_config
|
72
|
+
end
|
73
|
+
|
74
|
+
file '.dir-locals.el' => 'var/lib/org-config.el' do
|
75
|
+
Fronde::Config.write_dir_locals
|
76
|
+
end
|
77
|
+
|
78
|
+
desc 'Install Org'
|
79
|
+
multitask install: ['org:compile', '.dir-locals.el'] do
|
80
|
+
mkdir_p "#{Fronde::Config.settings['public_folder']}/assets"
|
81
|
+
Fronde::Config.sources.each do |s|
|
82
|
+
mkdir_p s['path'] unless Dir.exist? s['path']
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
# The following task only run the clobber task (not provided by us)
|
87
|
+
# and the org:install one, which is already tested. Thus, we can
|
88
|
+
# safely remove it from coverage.
|
89
|
+
# :nocov:
|
90
|
+
desc 'Upgrade Org'
|
91
|
+
task :upgrade do
|
92
|
+
Rake::Task['clobber'].execute
|
93
|
+
Rake::Task['org:install'].invoke
|
94
|
+
end
|
95
|
+
# :nocov:
|
96
|
+
end
|