yuzu 0.2.1.pre
Sign up to get free protection for your applications and to get access to all the features.
- data/.document +5 -0
- data/.yardopts +7 -0
- data/ChangeLog.md +8 -0
- data/Gemfile +26 -0
- data/Gemfile.lock +30 -0
- data/LICENSE.txt +20 -0
- data/README.md +52 -0
- data/Rakefile +62 -0
- data/bin/yuzu +17 -0
- data/docs/About.md +19 -0
- data/docs/GettingStarted.md +48 -0
- data/docs/Reference.md +97 -0
- data/lib/helpers/object.rb +19 -0
- data/lib/helpers/path.rb +296 -0
- data/lib/helpers/string.rb +35 -0
- data/lib/helpers/system_checks.rb +10 -0
- data/lib/helpers/url.rb +64 -0
- data/lib/html/base.rb +187 -0
- data/lib/uploader/base.rb +59 -0
- data/lib/uploader/config.rb +19 -0
- data/lib/uploader/filesystem_service.rb +72 -0
- data/lib/uploader/ftp_service.rb +90 -0
- data/lib/uploader/s3_service.rb +135 -0
- data/lib/uploader/service.rb +57 -0
- data/lib/uploader/suppressor.rb +25 -0
- data/lib/yuzu.rb +6 -0
- data/lib/yuzu/argparse.rb +60 -0
- data/lib/yuzu/command.rb +104 -0
- data/lib/yuzu/commands/base.rb +150 -0
- data/lib/yuzu/commands/create.rb +68 -0
- data/lib/yuzu/commands/generate.rb +95 -0
- data/lib/yuzu/commands/help.rb +20 -0
- data/lib/yuzu/commands/preview.rb +58 -0
- data/lib/yuzu/commands/publish.rb +43 -0
- data/lib/yuzu/commands/stage.rb +62 -0
- data/lib/yuzu/commands/watch.rb +70 -0
- data/lib/yuzu/content/blog_post.rb +45 -0
- data/lib/yuzu/content/sample_project.rb +130 -0
- data/lib/yuzu/core/config.rb +154 -0
- data/lib/yuzu/core/layout.rb +85 -0
- data/lib/yuzu/core/paginated_file.rb +69 -0
- data/lib/yuzu/core/registrar.rb +32 -0
- data/lib/yuzu/core/siteroot.rb +57 -0
- data/lib/yuzu/core/template.rb +158 -0
- data/lib/yuzu/core/updater.rb +123 -0
- data/lib/yuzu/core/visitor.rb +44 -0
- data/lib/yuzu/core/website_base.rb +150 -0
- data/lib/yuzu/core/website_file.rb +270 -0
- data/lib/yuzu/core/website_folder.rb +176 -0
- data/lib/yuzu/filters/base.rb +86 -0
- data/lib/yuzu/filters/catalog.rb +248 -0
- data/lib/yuzu/filters/categories.rb +58 -0
- data/lib/yuzu/filters/currentpath.rb +35 -0
- data/lib/yuzu/filters/description.rb +16 -0
- data/lib/yuzu/filters/extension.rb +16 -0
- data/lib/yuzu/filters/images.rb +32 -0
- data/lib/yuzu/filters/linkroot.rb +35 -0
- data/lib/yuzu/filters/post_date.rb +45 -0
- data/lib/yuzu/filters/post_title.rb +66 -0
- data/lib/yuzu/filters/post_title_removed.rb +28 -0
- data/lib/yuzu/filters/sidebar.rb +26 -0
- data/lib/yuzu/filters/template.rb +16 -0
- data/lib/yuzu/generators/base.rb +44 -0
- data/lib/yuzu/generators/category_folders.rb +91 -0
- data/lib/yuzu/generators/index.rb +108 -0
- data/lib/yuzu/generators/paginate.rb +136 -0
- data/lib/yuzu/postprocessors/all_categories.rb +48 -0
- data/lib/yuzu/postprocessors/base.rb +34 -0
- data/lib/yuzu/postprocessors/contents_without_first_paragraph.rb +20 -0
- data/lib/yuzu/postprocessors/excerpt.rb +23 -0
- data/lib/yuzu/postprocessors/first_paragraph.rb +16 -0
- data/lib/yuzu/postprocessors/pagination.rb +35 -0
- data/lib/yuzu/postprocessors/recent_posts.rb +27 -0
- data/lib/yuzu/postprocessors/thumbnails.rb +48 -0
- data/lib/yuzu/preprocessors/base.rb +71 -0
- data/lib/yuzu/preprocessors/insert_contents.rb +57 -0
- data/lib/yuzu/renderers/base.rb +23 -0
- data/lib/yuzu/renderers/breadcrumb.rb +163 -0
- data/lib/yuzu/renderers/gallery.rb +24 -0
- data/lib/yuzu/renderers/title.rb +21 -0
- data/lib/yuzu/translators/base.rb +57 -0
- data/lib/yuzu/translators/markdown.rb +21 -0
- data/lib/yuzu/translators/plaintext.rb +17 -0
- data/lib/yuzu/version.rb +12 -0
- data/resources/config/compass.rb +6 -0
- data/resources/config/yuzu.yml +166 -0
- data/resources/git/post-commit +42 -0
- data/resources/sample_content/introduction/_snippets/about_insert_contents.md +3 -0
- data/resources/sample_content/introduction/about.md +6 -0
- data/resources/sample_content/introduction/advanced-posts.md +18 -0
- data/resources/sample_content/introduction/blog/blog-folder-is-special.md +8 -0
- data/resources/sample_content/introduction/getting-started.md +14 -0
- data/resources/sample_content/introduction/index.md +6 -0
- data/resources/sample_content/introduction/sample-post.md +13 -0
- data/resources/sample_projects.yml +7 -0
- data/resources/themes/minimal/_sass/print.sass +0 -0
- data/resources/themes/minimal/_sass/screen.sass +81 -0
- data/resources/themes/minimal/_templates/_block.haml +4 -0
- data/resources/themes/minimal/_templates/_blog.haml +3 -0
- data/resources/themes/minimal/_templates/_footer.haml +2 -0
- data/resources/themes/minimal/_templates/_gallery.haml +25 -0
- data/resources/themes/minimal/_templates/_head.haml +12 -0
- data/resources/themes/minimal/_templates/_header.haml +1 -0
- data/resources/themes/minimal/_templates/_menu.haml +6 -0
- data/resources/themes/minimal/_templates/blog.haml +21 -0
- data/resources/themes/minimal/_templates/generic.haml +26 -0
- data/resources/themes/minimal/_templates/home.haml +15 -0
- data/resources/themes/minimal/_templates/index.haml +21 -0
- data/resources/themes/minimal/css/print.css +0 -0
- data/resources/themes/minimal/css/screen.css +133 -0
- data/resources/themes/minimal/img/favicon.png +0 -0
- data/resources/yard/default/fulldoc/html/css/common.css +16 -0
- data/test/helper.rb +18 -0
- data/test/test_yuzu.rb +8 -0
- data/yuzu.gemspec +182 -0
- metadata +302 -0
@@ -0,0 +1,90 @@
|
|
1
|
+
require 'uploader/base'
|
2
|
+
require 'uploader/service'
|
3
|
+
require 'net/ftp'
|
4
|
+
require 'stringio'
|
5
|
+
|
6
|
+
module Uploader
|
7
|
+
class FtpService < Service
|
8
|
+
|
9
|
+
def connect!
|
10
|
+
$stderr.puts "Opening a persistent FTP connection to #{@config.host}..."
|
11
|
+
|
12
|
+
@ftp = Net::FTP.new
|
13
|
+
@ftp.passive = true
|
14
|
+
@ftp.connect(@config.host)
|
15
|
+
@ftp.login(@config.username, @config.password)
|
16
|
+
rescue
|
17
|
+
$strerr.puts "Something went wrong with the FTP login."
|
18
|
+
end
|
19
|
+
|
20
|
+
def close!
|
21
|
+
@ftp.close
|
22
|
+
end
|
23
|
+
|
24
|
+
def initialized?
|
25
|
+
not @ftp.nil?
|
26
|
+
end
|
27
|
+
|
28
|
+
def upload(remote_path, contents)
|
29
|
+
raise UploadArgumentError if not remote_path.is_a?(Path)
|
30
|
+
|
31
|
+
if contents.is_a?(File)
|
32
|
+
upload_via_ftp(remote_path, contents)
|
33
|
+
|
34
|
+
elsif contents.is_a?(String)
|
35
|
+
upload_contents_via_ftp(remote_path, contents)
|
36
|
+
|
37
|
+
else
|
38
|
+
raise UnrecognizedContentType
|
39
|
+
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def upload_contents_via_ftp(remote_path, contents)
|
44
|
+
file = StringIO.new(contents)
|
45
|
+
upload_via_ftp(remote_path, file, false)
|
46
|
+
end
|
47
|
+
|
48
|
+
def upload_via_ftp(remote_path, file, binary=true)
|
49
|
+
server_path = Path.new(@config.remote_root_path) + remote_path.relative
|
50
|
+
|
51
|
+
$stderr.puts "Opening an FTP connection for #{remote_path}"
|
52
|
+
|
53
|
+
begin
|
54
|
+
attempt_upload!(server_path, file, binary)
|
55
|
+
rescue => e
|
56
|
+
$stderr.puts "FTP Error"
|
57
|
+
$stderr.puts e.message
|
58
|
+
|
59
|
+
create_remote_folder!(server_path)
|
60
|
+
attempt_upload!(server_path, file, binary)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def attempt_upload!(server_path, file, binary)
|
65
|
+
$stderr.puts "Path on server: #{server_path}"
|
66
|
+
if binary
|
67
|
+
file.binmode
|
68
|
+
@ftp.storbinary("STOR #{server_path}", file, Net::FTP::DEFAULT_BLOCKSIZE)
|
69
|
+
else
|
70
|
+
@ftp.storlines("STOR #{server_path}", file)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
def create_remote_folder!(server_path)
|
75
|
+
server_path.descend do |path|
|
76
|
+
begin
|
77
|
+
@ftp.mkdir(path)
|
78
|
+
rescue Net::FTPPermError
|
79
|
+
$stderr.puts "Remote folder already exists."
|
80
|
+
rescue
|
81
|
+
# Ok.
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
Service.register(:ftp => FtpService)
|
88
|
+
end
|
89
|
+
|
90
|
+
|
@@ -0,0 +1,135 @@
|
|
1
|
+
require 'helpers/system_checks'
|
2
|
+
require 'uploader/base'
|
3
|
+
require 'uploader/service'
|
4
|
+
require 'uploader/suppressor'
|
5
|
+
|
6
|
+
module Uploader
|
7
|
+
class S3Service < Service
|
8
|
+
|
9
|
+
def connect!
|
10
|
+
# TODO S3 may not work yet.
|
11
|
+
|
12
|
+
if not SystemChecks.gem_available?('aws/s3')
|
13
|
+
$stderr.puts %Q{\nThe Amazon S3 service requires the aws-s3 gem (vers >= 0.6.2), which is
|
14
|
+
not required by default. Run 'gem install aws-s3' to install it.\n\n}
|
15
|
+
raise LoadError
|
16
|
+
end
|
17
|
+
|
18
|
+
@bucket_name = @config.bucket
|
19
|
+
access_key = ENV[@config.access_key]
|
20
|
+
secret_key = ENV[@config.secret_key]
|
21
|
+
|
22
|
+
$stderr.puts "Connecting to AWS..."
|
23
|
+
|
24
|
+
@suppressor.shutup!
|
25
|
+
|
26
|
+
unless AWS::S3::Base.connected?
|
27
|
+
options = {
|
28
|
+
:access_key_id => access_key,
|
29
|
+
:secret_access_key => secret_key,
|
30
|
+
:use_ssl => true,
|
31
|
+
:port => 443
|
32
|
+
}
|
33
|
+
|
34
|
+
if @config.use_proxy
|
35
|
+
options.update({
|
36
|
+
:proxy => {
|
37
|
+
:host => @config.proxy['host'],
|
38
|
+
:port => @config.proxy['port']
|
39
|
+
}
|
40
|
+
})
|
41
|
+
end
|
42
|
+
|
43
|
+
AWS::S3::Base.establish_connection!(options)
|
44
|
+
@suppressor.ok
|
45
|
+
|
46
|
+
else
|
47
|
+
@suppressor.ok
|
48
|
+
$stderr.puts "AWS already connected."
|
49
|
+
end
|
50
|
+
|
51
|
+
@s3_bucket = AWS::S3::Bucket.find(@bucket_name)
|
52
|
+
end
|
53
|
+
|
54
|
+
def close!
|
55
|
+
AWS::S3::Base.disconnect!
|
56
|
+
end
|
57
|
+
|
58
|
+
def upload(remote_path, contents)
|
59
|
+
raise UploadArgumentError if not remote_path.is_a?(Path)
|
60
|
+
|
61
|
+
if contents.is_a?(File)
|
62
|
+
contents_to_upload = contents.read
|
63
|
+
|
64
|
+
elsif contents.is_a?(String)
|
65
|
+
contents = contents
|
66
|
+
|
67
|
+
else
|
68
|
+
raise UnrecognizedContentType
|
69
|
+
|
70
|
+
end
|
71
|
+
|
72
|
+
upload_contents_to_s3(local_path, contents_to_upload)
|
73
|
+
end
|
74
|
+
|
75
|
+
def upload_contents_to_s3(remote_path, contents, mime_type=nil)
|
76
|
+
$stderr.puts "Attempting to upload #{remote_path} to S3"
|
77
|
+
|
78
|
+
destination = Path.new(@config.remote_root_path) + remote_path
|
79
|
+
|
80
|
+
@suppressor.shutup!
|
81
|
+
|
82
|
+
# Prepare the object.
|
83
|
+
object = @s3_bucket.new_object
|
84
|
+
object.key = destination
|
85
|
+
object.value = contents
|
86
|
+
|
87
|
+
# Store the object first...
|
88
|
+
object.store
|
89
|
+
|
90
|
+
#if not mime_type.blank?
|
91
|
+
# #object.content_type = mime_type
|
92
|
+
# #object.store
|
93
|
+
#else
|
94
|
+
# ext = File.extname(local_path)
|
95
|
+
# if content_types.keys.include? ext
|
96
|
+
# #object.content_type = content_types[ext]
|
97
|
+
# #object.store
|
98
|
+
# end
|
99
|
+
#end
|
100
|
+
|
101
|
+
# ... then set the ACLs.
|
102
|
+
public_read_grant = AWS::S3::ACL::Grant.grant(:public_read)
|
103
|
+
object.acl.grants << public_read_grant
|
104
|
+
object.acl(object.acl)
|
105
|
+
|
106
|
+
@suppressor.ok
|
107
|
+
|
108
|
+
if @s3_bucket.objects.include?(object)
|
109
|
+
$stderr.puts "Successfully uploaded #{local_path} to S3!"
|
110
|
+
else
|
111
|
+
$stderr.puts "Something went wrong uploading #{local_path} to S3."
|
112
|
+
end
|
113
|
+
rescue => detail
|
114
|
+
$stderr.puts "Uploader#upload_contents_to_s3 exception."
|
115
|
+
$stderr.puts detail.message
|
116
|
+
end
|
117
|
+
|
118
|
+
def self.content_types
|
119
|
+
{
|
120
|
+
".png" => "image/png",
|
121
|
+
".jpg" => "image/jpeg",
|
122
|
+
".jpeg" => "image/jpeg",
|
123
|
+
".pdf" => "application/pdf",
|
124
|
+
".jar" => "application/java-archive",
|
125
|
+
".txt" => "text/plain",
|
126
|
+
".html" => "text/html",
|
127
|
+
".css" => "text/css",
|
128
|
+
".js" => "text/javascript"
|
129
|
+
}
|
130
|
+
end
|
131
|
+
|
132
|
+
end
|
133
|
+
Service.register(:s3 => S3Service)
|
134
|
+
end
|
135
|
+
|
@@ -0,0 +1,57 @@
|
|
1
|
+
require 'helpers/path'
|
2
|
+
require 'helpers/system_checks'
|
3
|
+
|
4
|
+
|
5
|
+
module Uploader
|
6
|
+
class UnrecognizedContentType < Exception; end
|
7
|
+
class ServiceNotConnected < Exception; end
|
8
|
+
class UploadArgumentError < Exception; end
|
9
|
+
|
10
|
+
class Service
|
11
|
+
include Helpers
|
12
|
+
|
13
|
+
def initialize(config)
|
14
|
+
@config = config
|
15
|
+
end
|
16
|
+
|
17
|
+
# Called to connect to remote services like FTP and S3.
|
18
|
+
def connect!
|
19
|
+
end
|
20
|
+
|
21
|
+
# Perform the upload operation to this service.
|
22
|
+
#
|
23
|
+
# @param [Path] remote_path The relative path to upload. This is prefixed by "remote_root_path"
|
24
|
+
# set in the uploader Config. You can set remote_root_path to "" if you want complete control
|
25
|
+
# over the path.
|
26
|
+
# @param [File, String] contents The contents to upload into the remote file
|
27
|
+
# destination.
|
28
|
+
# @return nothing
|
29
|
+
def upload(remote_path, contents)
|
30
|
+
end
|
31
|
+
|
32
|
+
# Closes the service connection, if required.
|
33
|
+
def close!
|
34
|
+
end
|
35
|
+
|
36
|
+
def initialized?
|
37
|
+
false
|
38
|
+
end
|
39
|
+
|
40
|
+
@@services = {}
|
41
|
+
|
42
|
+
def self.services
|
43
|
+
@@services
|
44
|
+
end
|
45
|
+
|
46
|
+
# Returns whether this service appears in the Service class's registry.
|
47
|
+
def self.is_registered?(service)
|
48
|
+
@@services.keys.include?(service)
|
49
|
+
end
|
50
|
+
|
51
|
+
# Registers the Service in the registry, so clients of the service can access it by name.
|
52
|
+
def self.register(kwds={})
|
53
|
+
@@services.update(kwds)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# Haml and AWS put out a lot of junk. Redirect stdout and stderr to /dev/null to suppress these
|
2
|
+
# useless warnings, then restore stdout and stderr at the end.
|
3
|
+
class Suppressor
|
4
|
+
def initialize
|
5
|
+
@hole = File.new('/dev/null', 'w')
|
6
|
+
@orig_stdout = $stdout
|
7
|
+
@orig_stderr = $stderr
|
8
|
+
end
|
9
|
+
|
10
|
+
# Redirect stdout to /dev/null
|
11
|
+
def shutup!
|
12
|
+
$stdout = @hole
|
13
|
+
$stderr = @hole
|
14
|
+
end
|
15
|
+
|
16
|
+
# Restore stdout and stderr
|
17
|
+
def ok
|
18
|
+
$stdout = @orig_stdout
|
19
|
+
$stderr = @orig_stderr
|
20
|
+
end
|
21
|
+
|
22
|
+
def close!
|
23
|
+
@hole.close
|
24
|
+
end
|
25
|
+
end
|
data/lib/yuzu.rb
ADDED
@@ -0,0 +1,60 @@
|
|
1
|
+
require 'ostruct'
|
2
|
+
require 'optparse'
|
3
|
+
require 'version'
|
4
|
+
|
5
|
+
module Yuzu::Command
|
6
|
+
HELP_MESSAGE = %Q{
|
7
|
+
This is yuzu, a blog-aware, static-website generator and publisher that converts
|
8
|
+
a folder of text files and images into an HTML5 website.
|
9
|
+
|
10
|
+
Typical Usage
|
11
|
+
|
12
|
+
yuzu [command] [options] [files]
|
13
|
+
|
14
|
+
Available Commands
|
15
|
+
|
16
|
+
help # Show this help page.
|
17
|
+
help [command] # Help about the particular command.
|
18
|
+
create # Creates a new yuzu project in the current folder.
|
19
|
+
preview # Updates files in the preview folder.
|
20
|
+
publish # Publishes files to the currently selected remote server.
|
21
|
+
stage # Updates files in the staging folder.
|
22
|
+
generate # Generate new content like posts and thumbnails.
|
23
|
+
}
|
24
|
+
|
25
|
+
class ArgParser
|
26
|
+
def self.parse(args)
|
27
|
+
options = OpenStruct.new
|
28
|
+
options.output = :quiet # :verbose, :debug
|
29
|
+
|
30
|
+
option_parser = \
|
31
|
+
OptionParser.new do |opts|
|
32
|
+
opts.banner = ""
|
33
|
+
|
34
|
+
opts.separator "Options"
|
35
|
+
opts.separator ""
|
36
|
+
|
37
|
+
opts.on("--verbose", "Run showing verbose output.") do
|
38
|
+
options.output = :verbose
|
39
|
+
end
|
40
|
+
|
41
|
+
opts.on_tail("-h", "--help", "Show this help message.") do
|
42
|
+
puts HELP_MESSAGE
|
43
|
+
puts opts
|
44
|
+
exit
|
45
|
+
end
|
46
|
+
|
47
|
+
opts.on_tail("-v", "--version", "Show version.") do
|
48
|
+
puts Yuzu::Version::STRING
|
49
|
+
exit
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
option_parser.parse!(args)
|
54
|
+
options
|
55
|
+
|
56
|
+
end # End self.parse
|
57
|
+
end # End ArgParser
|
58
|
+
|
59
|
+
end
|
60
|
+
|
data/lib/yuzu/command.rb
ADDED
@@ -0,0 +1,104 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
|
3
|
+
require 'commands/base'
|
4
|
+
require 'argparse'
|
5
|
+
|
6
|
+
require 'helpers/object'
|
7
|
+
require 'helpers/string'
|
8
|
+
|
9
|
+
# Load all the commands.
|
10
|
+
Dir["#{File.dirname(__FILE__)}/commands/*"].each { |c| require c }
|
11
|
+
|
12
|
+
|
13
|
+
CONFIG_NOT_FOUND_MESSAGE = \
|
14
|
+
%Q{Please run this from the root of your project, in the folder containing
|
15
|
+
yuzu.yml or config/yuzu.yml. Or use 'create' to make a new project.}
|
16
|
+
|
17
|
+
|
18
|
+
module Yuzu::Command
|
19
|
+
|
20
|
+
def self.run(command_str, args)
|
21
|
+
start = Time.now
|
22
|
+
|
23
|
+
options = ArgParser.parse(args)
|
24
|
+
|
25
|
+
if command_str.nil?
|
26
|
+
exit
|
27
|
+
end
|
28
|
+
|
29
|
+
command_class, method = parse(command_str.downcase)
|
30
|
+
execute(command_class, method, args[1, args.length] || [], options)
|
31
|
+
|
32
|
+
stop = Time.now
|
33
|
+
delta = stop - start
|
34
|
+
if options.output == :verbose
|
35
|
+
$stderr.puts "Yuzu completed in #{delta} seconds."
|
36
|
+
else
|
37
|
+
$stderr.puts
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def self.parse(command_str)
|
42
|
+
command, method = command_str.split(':').collect {|part| part.strip}
|
43
|
+
method = method.nil? ? :index : method.to_sym
|
44
|
+
|
45
|
+
return Yuzu::Command.const_get(command.capitalize), method
|
46
|
+
rescue
|
47
|
+
raise InvalidCommand
|
48
|
+
end
|
49
|
+
|
50
|
+
def self.execute(command_class, method, args, parsed_options)
|
51
|
+
if command_class.requires_config?
|
52
|
+
config_hash = load_config
|
53
|
+
|
54
|
+
config = \
|
55
|
+
Yuzu::Core::Config.new(
|
56
|
+
config_hash,
|
57
|
+
command_class.service_override,
|
58
|
+
parsed_options
|
59
|
+
)
|
60
|
+
|
61
|
+
command_instance = command_class.new(args, config)
|
62
|
+
command_instance.send(method)
|
63
|
+
|
64
|
+
else
|
65
|
+
command_instance = command_class.new(args)
|
66
|
+
command_instance.send(method)
|
67
|
+
end
|
68
|
+
rescue => e
|
69
|
+
$stderr.puts e.message
|
70
|
+
$stderr.puts e.backtrace
|
71
|
+
raise CommandFailed
|
72
|
+
end
|
73
|
+
|
74
|
+
def self.load_config
|
75
|
+
config_location = locate_config
|
76
|
+
|
77
|
+
if config_location.nil?
|
78
|
+
$stderr.puts CONFIG_NOT_FOUND_MESSAGE
|
79
|
+
Process.exit!(false)
|
80
|
+
end
|
81
|
+
|
82
|
+
YAML.load_file(config_location)
|
83
|
+
end
|
84
|
+
|
85
|
+
def self.locate_config
|
86
|
+
possible_config_locations.each do |path|
|
87
|
+
if File.exists?(path)
|
88
|
+
return path
|
89
|
+
end
|
90
|
+
end
|
91
|
+
return nil
|
92
|
+
end
|
93
|
+
|
94
|
+
def self.possible_config_locations
|
95
|
+
[
|
96
|
+
File.join(Dir.pwd, "yuzu.yml"),
|
97
|
+
File.join(Dir.pwd, "config", "yuzu.yml")
|
98
|
+
]
|
99
|
+
end
|
100
|
+
|
101
|
+
class InvalidCommand < RuntimeError; end
|
102
|
+
class CommandFailed < RuntimeError; end
|
103
|
+
end
|
104
|
+
|