smc-get 0.1.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.
- data/COPYING +674 -0
- data/README.rdoc +148 -0
- data/VERSION.txt +1 -0
- data/bin/smc-get +31 -0
- data/config/smc-get.yml +32 -0
- data/lib/smc_get.rb +21 -0
- data/lib/smc_get/cui.rb +289 -0
- data/lib/smc_get/cui_commands/command.rb +81 -0
- data/lib/smc_get/cui_commands/getinfo.rb +91 -0
- data/lib/smc_get/cui_commands/help.rb +64 -0
- data/lib/smc_get/cui_commands/install.rb +91 -0
- data/lib/smc_get/cui_commands/list.rb +80 -0
- data/lib/smc_get/cui_commands/search.rb +109 -0
- data/lib/smc_get/cui_commands/uninstall.rb +78 -0
- data/lib/smc_get/cui_commands/version.rb +57 -0
- data/lib/smc_get/errors.rb +113 -0
- data/lib/smc_get/gui.rb +19 -0
- data/lib/smc_get/package.rb +279 -0
- data/lib/smc_get/smc_get.rb +139 -0
- data/test/test_smc-get-cui.rb +121 -0
- data/test/test_smc-get-lib.rb +170 -0
- metadata +87 -0
data/README.rdoc
ADDED
@@ -0,0 +1,148 @@
|
|
1
|
+
= SMC-GET -- level repository manager for Secret Maryo Chronicles
|
2
|
+
smc-get - Library and command-line for managing SMC level packages.
|
3
|
+
|
4
|
+
Author:: Luiji Maryo (mailto:luiji@users.sourceforge.net)
|
5
|
+
Contributor:: Marvin Gülker (mailto:sutniuq@gmx.net)
|
6
|
+
Copyright:: Copyright (C) 2010-2011 Entertaining Software, Inc.
|
7
|
+
Copyright:: Copyright (C) 2011 Marvin Gülker
|
8
|
+
License:: GNU General Public License (see COPYING)
|
9
|
+
|
10
|
+
= Synopsis for use as a command-line tool
|
11
|
+
smc-get install mypackage
|
12
|
+
smc-get uninstall mypackage
|
13
|
+
smc-get help
|
14
|
+
|
15
|
+
= Synopsis for use as a library
|
16
|
+
require 'smc_get'
|
17
|
+
#Initialize the library
|
18
|
+
SmcGet.setup(
|
19
|
+
#From where to download packages
|
20
|
+
"https://github.com/Luiji/Secret-Maryo-Chronicles-Contributed-Levels/raw/master/",
|
21
|
+
#Where to install packages (your SMC installation)
|
22
|
+
"/usr/local/share/smc"
|
23
|
+
)
|
24
|
+
#Get a package
|
25
|
+
pkg = SmcGet::Package.new("mypackage")
|
26
|
+
#Install it!
|
27
|
+
pkg.install
|
28
|
+
#...or remove it.
|
29
|
+
pkg.uninstall
|
30
|
+
|
31
|
+
= Description
|
32
|
+
smc-get is a library and command-line tool for installing, uninstalling, etc.
|
33
|
+
level packages from the Secret Maryo Chronicles Contributed Levels Repository.
|
34
|
+
|
35
|
+
== Prototype Notice
|
36
|
+
|
37
|
+
This program is a prototype for functionality that will eventually be merged
|
38
|
+
with Secret Maryo Chronicles. It is subject to change and should not be used
|
39
|
+
for anything other then testing.
|
40
|
+
|
41
|
+
= Usage
|
42
|
+
|
43
|
+
== Using it as a command-line
|
44
|
+
smc-get's main purpose is to be used as a command-line utility. It should be
|
45
|
+
executed in the syntax:
|
46
|
+
smc-get COMMAND [PARAMETERS...]
|
47
|
+
Where <tt>COMMAND</tt> is the command and <tt>PARAMATERS...</tt> are the
|
48
|
+
parameters for that command.
|
49
|
+
|
50
|
+
To get help on the various commands, use the help command.
|
51
|
+
smc-get help [COMMAND]
|
52
|
+
Ommit the +COMMAND+ if you want general usage information.
|
53
|
+
|
54
|
+
=== Configuration file
|
55
|
+
smc-get requires a configuration file when used as a commandline tool.
|
56
|
+
By default it searches for <tt>smc-get.yml</tt> in the <b>config/</b>
|
57
|
+
subdirectory of your smc-get installation, then for <tt>smc-get-conf.yml</tt>
|
58
|
+
in the user's home directory and then for the file specified via the <tt>-c</tt>
|
59
|
+
commandline switch, if existant. Values set in later evaluated configuration
|
60
|
+
files override those in prevously evaluated ones; see
|
61
|
+
smc-get help
|
62
|
+
for more explanation. If you want to use the CUI from your scripts, you
|
63
|
+
can specify a config file via <tt>-c</tt>, but make sure it contains all
|
64
|
+
possible options, otherwise those in the global or user-level config files
|
65
|
+
may affect your program. See below for an example.
|
66
|
+
|
67
|
+
Be careful when using +sudo+, because it changes the environment variables.
|
68
|
+
smc-get may not find your user-level configuration file when using sudo,
|
69
|
+
because it derives the path from the +USER+ environment variable which may
|
70
|
+
get set to +root+ when using +sudo+.
|
71
|
+
|
72
|
+
In the configuration file you can set some general options, look into
|
73
|
+
the file which is quite self-explanatory. A sample configuration may
|
74
|
+
look like this:
|
75
|
+
data_directory: "/usr/local/share/smc"
|
76
|
+
repo_url: "https://github.com/Luiji/Secret-Maryo-Chronicles-Contributed-Levels/raw/master/"
|
77
|
+
|
78
|
+
== Using it as a library
|
79
|
+
smc-get, although mainly targetted at being a command-line utility, may also be
|
80
|
+
used as a library. This is useful when, for instance, creating a GUI front-end.
|
81
|
+
|
82
|
+
To initialize the library, indicate which repository you are using and
|
83
|
+
where you want smc-get to install the packages to (which is usually your
|
84
|
+
SMC installation path)
|
85
|
+
SmcGet.setup(
|
86
|
+
"https://github.com/Luiji/Secret-Maryo-Chronicles-Contributed-Levels/raw/master/",
|
87
|
+
"/usr/local/share/smc"
|
88
|
+
)
|
89
|
+
|
90
|
+
For interacting with the SMC repository, smc-get exposes an object-oriented API
|
91
|
+
centered around the SmcGet::Package class. After you initialized the library
|
92
|
+
as explained above, you can query, install and uninstall packages.
|
93
|
+
pkg = SmcGet::Package.new("mypackage")
|
94
|
+
pkg.install
|
95
|
+
|
96
|
+
If the function fails, it will raise various exceptions. When creating a GUI,
|
97
|
+
you should catch these exceptions and present them as message boxes.
|
98
|
+
begin
|
99
|
+
Package.new("mypackage").install
|
100
|
+
rescue SmcGet::Errors::NoSuchPackageError
|
101
|
+
alert 'No such package "mypackage"!'
|
102
|
+
end
|
103
|
+
|
104
|
+
All errors smc-get raises are subclasses of SmcGet::Errors::SmcGetError. That
|
105
|
+
means, if you rescue from this exception, you can handle all package-related
|
106
|
+
errors at once:
|
107
|
+
begin
|
108
|
+
Package.new("mypackage").install
|
109
|
+
rescue SmcGet::Errors::SmcGetError => e
|
110
|
+
alert e.message
|
111
|
+
end
|
112
|
+
|
113
|
+
Furhtermore, these error messages should have a pretty informative message set,
|
114
|
+
so unless you want to localize the error messages you can just reach them
|
115
|
+
through (the messages, not the whole exceptions, of course).
|
116
|
+
|
117
|
+
The configuration file only contains settings for the commandline user
|
118
|
+
interface, so you don't need it here. If you want to use the CUI from
|
119
|
+
your scripts, do
|
120
|
+
require "smc_get"
|
121
|
+
require "smc_get/cui"
|
122
|
+
|
123
|
+
cui = SmcGet::CUI.new(ARGV)
|
124
|
+
cui.start
|
125
|
+
The configuration file from the <b>config/</b> directory will automatically
|
126
|
+
be loaded as well as the user-level configuration file; you may specify another
|
127
|
+
configuration file by placing the appropriate option in ARGV:
|
128
|
+
ARGV.unshift("-c")
|
129
|
+
ARGV.unshift("YOURCONFIGFILE.yml")
|
130
|
+
|
131
|
+
cui = SmcGet::CUI.new(ARGV)
|
132
|
+
cui.start
|
133
|
+
|
134
|
+
= License
|
135
|
+
|
136
|
+
smc-get is licensed under the GNU General Public License. For more information,
|
137
|
+
see COPYING.
|
138
|
+
|
139
|
+
= Website
|
140
|
+
|
141
|
+
This software was written by Entertaining Software, Inc. Visit us at
|
142
|
+
http://www.entertainingsoftware.com.
|
143
|
+
|
144
|
+
This software is hosted at GitHub. The project page can be found at
|
145
|
+
http://github.com/Luiji/smc-get.
|
146
|
+
|
147
|
+
This software was written for Secret Maryo Chronicles. Visit them at
|
148
|
+
http://www.secretmaryo.org.
|
data/VERSION.txt
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.1.0
|
data/bin/smc-get
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
#Encoding: UTF-8
|
3
|
+
################################################################################
|
4
|
+
# This file is part of smc-get.
|
5
|
+
# Copyright (C) 2010-2011 Entertaining Software, Inc.
|
6
|
+
# Copyright (C) 2011 Marvin Gülker
|
7
|
+
#
|
8
|
+
# This program is free software: you can redistribute it and/or modify
|
9
|
+
# it under the terms of the GNU General Public License as published by
|
10
|
+
# the Free Software Foundation, either version 3 of the License, or
|
11
|
+
# (at your option) any later version.
|
12
|
+
#
|
13
|
+
# This program is distributed in the hope that it will be useful,
|
14
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
15
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
16
|
+
# GNU General Public License for more details.
|
17
|
+
#
|
18
|
+
# You should have received a copy of the GNU General Public License
|
19
|
+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
20
|
+
################################################################################
|
21
|
+
|
22
|
+
if RUBY_VERSION =~ /^1.8/ #1.8 doesn't have require_relative
|
23
|
+
require File.join(File.expand_path(File.dirname(__FILE__)), "..", "lib", "smc_get", "smc_get")
|
24
|
+
require File.join(File.expand_path(File.dirname(__FILE__)), "..", "lib", "smc_get", "cui")
|
25
|
+
else
|
26
|
+
require_relative "../lib/smc_get/smc_get"
|
27
|
+
require_relative "../lib/smc_get/cui"
|
28
|
+
end
|
29
|
+
|
30
|
+
cui = SmcGet::CUI.new(ARGV)
|
31
|
+
cui.start
|
data/config/smc-get.yml
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
#Encoding: UTF-8
|
2
|
+
################################################################################
|
3
|
+
# This file is part of smc-get.
|
4
|
+
# Copyright (C) 2010-2011 Entertaining Software, Inc.
|
5
|
+
# Copyright (C) 2011 Marvin Gülker
|
6
|
+
#
|
7
|
+
# This program is free software: you can redistribute it and/or modify
|
8
|
+
# it under the terms of the GNU General Public License as published by
|
9
|
+
# the Free Software Foundation, either version 3 of the License, or
|
10
|
+
# (at your option) any later version.
|
11
|
+
#
|
12
|
+
# This program is distributed in the hope that it will be useful,
|
13
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
14
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
15
|
+
# GNU General Public License for more details.
|
16
|
+
#
|
17
|
+
# You should have received a copy of the GNU General Public License
|
18
|
+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
19
|
+
################################################################################
|
20
|
+
#
|
21
|
+
#This is the configuration file for smc-get.
|
22
|
+
---
|
23
|
+
#This is the directory where everything gets installed into.
|
24
|
+
#Set this to the installation directory of SMC, e.g.
|
25
|
+
#/usr/share/smc.
|
26
|
+
data_directory: "/usr/share/smc"
|
27
|
+
#This is the URL of the repository where packages are downloaded from.
|
28
|
+
repo_url: "https://github.com/Luiji/Secret-Maryo-Chronicles-Contributed-Levels/raw/master/"
|
29
|
+
#This is the maximum number of tries smc-get makes in order to
|
30
|
+
#download a package.
|
31
|
+
max_tries: 3
|
32
|
+
|
data/lib/smc_get.rb
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
#Encoding: UTF-8
|
2
|
+
################################################################################
|
3
|
+
# This file is part of smc-get.
|
4
|
+
# Copyright (C) 2010-2011 Entertaining Software, Inc.
|
5
|
+
# Copyright (C) 2011 Marvin Gülker
|
6
|
+
#
|
7
|
+
# This program is free software: you can redistribute it and/or modify
|
8
|
+
# it under the terms of the GNU General Public License as published by
|
9
|
+
# the Free Software Foundation, either version 3 of the License, or
|
10
|
+
# (at your option) any later version.
|
11
|
+
#
|
12
|
+
# This program is distributed in the hope that it will be useful,
|
13
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
14
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
15
|
+
# GNU General Public License for more details.
|
16
|
+
#
|
17
|
+
# You should have received a copy of the GNU General Public License
|
18
|
+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
19
|
+
################################################################################
|
20
|
+
|
21
|
+
require_relative "smc_get/smc_get"
|
data/lib/smc_get/cui.rb
ADDED
@@ -0,0 +1,289 @@
|
|
1
|
+
#Encoding: UTF-8
|
2
|
+
################################################################################
|
3
|
+
# This file is part of smc-get.
|
4
|
+
# Copyright (C) 2010-2011 Entertaining Software, Inc.
|
5
|
+
# Copyright (C) 2011 Marvin Gülker
|
6
|
+
#
|
7
|
+
# This program is free software: you can redistribute it and/or modify
|
8
|
+
# it under the terms of the GNU General Public License as published by
|
9
|
+
# the Free Software Foundation, either version 3 of the License, or
|
10
|
+
# (at your option) any later version.
|
11
|
+
#
|
12
|
+
# This program is distributed in the hope that it will be useful,
|
13
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
14
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
15
|
+
# GNU General Public License for more details.
|
16
|
+
#
|
17
|
+
# You should have received a copy of the GNU General Public License
|
18
|
+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
19
|
+
################################################################################
|
20
|
+
|
21
|
+
#Load all the files in the cui_commands directory.
|
22
|
+
require_relative "cui_commands/command"
|
23
|
+
Dir[File.join(File.expand_path(File.dirname(__FILE__)), "cui_commands", "*.rb")].each do |filename|
|
24
|
+
require_relative "cui_commands/#{File.basename(filename)}"
|
25
|
+
end
|
26
|
+
|
27
|
+
module SmcGet
|
28
|
+
|
29
|
+
#This is the Console User Interface smc-get exposes. Each command
|
30
|
+
#is represented by a class in the CUICommands module. Those classes
|
31
|
+
#have three methods: ::help, which should return a summary on how to use
|
32
|
+
#the command (NOT print it, that's done by an internal method), #parse,
|
33
|
+
#which gets the command-line for the subcommand passed in form of an
|
34
|
+
#array you should destructively (i.e. removing the elements) analyse,
|
35
|
+
#and #execute which finally executes the command. You are free to print out
|
36
|
+
#anything inside that method.
|
37
|
+
#
|
38
|
+
#Note that inside the #parse method you can set instance variables
|
39
|
+
#as you would do for any normal class. You can then grep their values
|
40
|
+
#inside the #execute method. Furthermore, if inside #parse you detect
|
41
|
+
#an error in the commandline the user provided to you, raise the
|
42
|
+
#CUI::InvalidCommandline exception with a meaningful message which will
|
43
|
+
#then be presented to the user.
|
44
|
+
#
|
45
|
+
#The last things one should do when adding a command, is to provide
|
46
|
+
#a ::help class method that returns help on the usage of the command
|
47
|
+
#(it will be called when the user issues <tt>smc-get help YOURCOMMAND</tt>
|
48
|
+
#and it's return value will be shown to the user) and to provide
|
49
|
+
#a ::summary class method whose return value is integrated in the
|
50
|
+
#output of <tt>smc-get help</tt> under the COMMANDS section.
|
51
|
+
#
|
52
|
+
#In every method you add, you can make use of the CUI.debug method. If you
|
53
|
+
#hand it a string, it will be printed only if running in debug mode, and
|
54
|
+
#if you hand it any other object, it's +inspect+ value will be printed--if
|
55
|
+
#running in debug mode. See the SmcGet::CUICommands::Command class's
|
56
|
+
#documentation for more information on the hook methods.
|
57
|
+
#
|
58
|
+
#Internally the flow is as follows:
|
59
|
+
#1. The user calls CUI#initialize with ARGV.
|
60
|
+
#2. That method triggers CUI#parse_commandline and passes ARGV to it.
|
61
|
+
#3. #parse_commandline analyses the array it receives and figures out
|
62
|
+
# what command class inside the CUICommands module to instantiate.
|
63
|
+
#4. CUICommand::Command.new calls #parse on the instantiated Command
|
64
|
+
# object (this is a subclass of CUICommand::Command). Note that
|
65
|
+
# smc-get has not been set up for now, and calls to Package.new or
|
66
|
+
# the like will fail.
|
67
|
+
#5. The user calls CUI#start.
|
68
|
+
#6. #start looks into @command and invokes the #execute method on it.
|
69
|
+
#7. #start shuts down the interpreter via #exit. If the command execution
|
70
|
+
# method returned an integer value, it is used as the exit status.
|
71
|
+
#
|
72
|
+
#Have a look at the existing commands to see how it works. Especially
|
73
|
+
#+help+ is quite easy to understand, so begin there.
|
74
|
+
class CUI
|
75
|
+
|
76
|
+
#Default location of the configuration file.
|
77
|
+
DEFAULT_CONFIG_FILE = CONFIG_DIR + "smc-get.yml"
|
78
|
+
#Name of the configuration file a user may put in his home
|
79
|
+
#directory.
|
80
|
+
USER_CONFIG_FILE_NAME = ".smc-get-conf.yml"
|
81
|
+
|
82
|
+
#The help message displayed to the user when issueing "help".
|
83
|
+
GENERAL_HELP =<<EOF
|
84
|
+
USAGE:
|
85
|
+
#{File.basename($0)} [OPTIONS] COMMAND [PARAMETERS...]
|
86
|
+
|
87
|
+
DESCRIPTION:
|
88
|
+
Install and uninstall levels from the Secret Maryo Chronicles contributed level
|
89
|
+
repository.
|
90
|
+
|
91
|
+
COMMANDS:
|
92
|
+
#{str = ''
|
93
|
+
CUICommands.constants.sort.each do |c|
|
94
|
+
next if c == :Command or c == :InvalidCommandline
|
95
|
+
str << ' ' << CUICommands.const_get(c).summary << "\n"
|
96
|
+
end
|
97
|
+
str}
|
98
|
+
|
99
|
+
Use "help COMMAND" to get help on a specific command. "help" without an
|
100
|
+
argument displays this message.
|
101
|
+
|
102
|
+
OPTIONS FOR #{File.basename($0)} itself
|
103
|
+
-c\t--config-file FILE\tUse FILE as the configuration file.
|
104
|
+
-d\t--data-directory DIR\tSet the directory where to save packages into.
|
105
|
+
-D\t--debug\t\t\tEnter debug mode. A normal user shouldn't use this.
|
106
|
+
-r\t--repo-url URL\t\tSet the URL of the remote package repository.
|
107
|
+
|
108
|
+
CONFIGURATION FILES
|
109
|
+
You can use three kinds of configuration files with #{File.basename($0)}. They are,
|
110
|
+
in the order in which they are evaluated:
|
111
|
+
|
112
|
+
1. Global configuration file #{DEFAULT_CONFIG_FILE}.
|
113
|
+
2. If existant, user-level configuration file #{File.join(ENV["HOME"], USER_CONFIG_FILE_NAME)}.
|
114
|
+
3. If existant, configuration file given on the commandline via the -c option.
|
115
|
+
|
116
|
+
Configuration files loaded later overwrite values set in previously loaded
|
117
|
+
configuration files, i.e. values set in the configuration file provided via
|
118
|
+
the commandline override those in the global and user-level configuration
|
119
|
+
file, and those in the user-level configuration file override those in the
|
120
|
+
global configuration file, etc.
|
121
|
+
There is a 4th way to set options for #{File.basename($0)}:
|
122
|
+
|
123
|
+
4. Options given via the commandline
|
124
|
+
|
125
|
+
They override anything set in the configuration files, so specifying
|
126
|
+
'-d /opt/smc' on the commandline would override any 'data_directory'
|
127
|
+
setting in any of the configuration files.
|
128
|
+
|
129
|
+
BUG REPORTING
|
130
|
+
|
131
|
+
Report bugs to: luiji@users.sourceforge.net
|
132
|
+
smc-get home page: <http://www.secretmaryo.org/>
|
133
|
+
EOF
|
134
|
+
|
135
|
+
#Writes <tt>obj.inspect</tt> to $stdout if the CUI is running in debug
|
136
|
+
#mode. If +obj+ is a string, it is simply written out.
|
137
|
+
def self.debug(obj)
|
138
|
+
if @DEBUG_MODE
|
139
|
+
if obj.kind_of? String
|
140
|
+
puts obj
|
141
|
+
else
|
142
|
+
puts(obj.inspect)
|
143
|
+
end
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
@DEBUG_MODE = false
|
148
|
+
|
149
|
+
#Returns wheather or not we're running in debug mode.
|
150
|
+
def self.debug_mode?
|
151
|
+
@DEBUG_MODE
|
152
|
+
end
|
153
|
+
|
154
|
+
#Set to +true+ to enable debug mode.
|
155
|
+
def self.debug_mode=(val)
|
156
|
+
@DEBUG_MODE = val
|
157
|
+
end
|
158
|
+
|
159
|
+
#Creates a new CUI. Pass in ARGV or a set of command-line arguments
|
160
|
+
#you want to and read this class's documentation for knowing what
|
161
|
+
#happens then. Call #start on the returned object when you want
|
162
|
+
#to execute everything.
|
163
|
+
def initialize(argv)
|
164
|
+
@config = {}
|
165
|
+
parse_commandline(argv)
|
166
|
+
load_config_file
|
167
|
+
SmcGet.setup(@config[:repo_url], @config[:data_directory])
|
168
|
+
end
|
169
|
+
|
170
|
+
#Starts executing of the CUI. This method never returns, it
|
171
|
+
#calls #exit after the command has finished.
|
172
|
+
def start
|
173
|
+
begin
|
174
|
+
ret = @command.execute(@config)
|
175
|
+
#If numbers are returned they are supposed to be the exit code.
|
176
|
+
if ret.kind_of? Integer
|
177
|
+
exit ret
|
178
|
+
else
|
179
|
+
exit
|
180
|
+
end
|
181
|
+
rescue Errno::EACCES, Errors::SmcGetError => e
|
182
|
+
$stderr.puts(e.message) #All SmcGetErrors should have an informative message (and the EACCES one too)
|
183
|
+
exit 2
|
184
|
+
rescue => e #Ouch. Fatal error not intended.
|
185
|
+
$stderr.puts("[BUG] #{e.class}")
|
186
|
+
$stderr.puts("Please file a bug report at https://github.com/Luiji/smc-get/issues")
|
187
|
+
$stderr.puts("and attach this message. Describe what you did so we can")
|
188
|
+
$stderr.puts("reproduce it. ")
|
189
|
+
raise #Bubble up
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|
193
|
+
private
|
194
|
+
|
195
|
+
#Destructively searches through +argv+ (i.e. emptying it) and
|
196
|
+
#sets the CLI up. Besides when +help+ is used as the
|
197
|
+
#command, nothing is actually executed.
|
198
|
+
#
|
199
|
+
#This method instantiates one of the various classes in the
|
200
|
+
#CUICommands module, making smc-get easily extendable by
|
201
|
+
#adding a new class inside that module.
|
202
|
+
def parse_commandline(argv)
|
203
|
+
#Get options for smc-get itself, rather than it's subcommands. Values set
|
204
|
+
#here override anything set in any configuration file; but since the
|
205
|
+
#keys are turned to symbols in #load_config_file, we have to use
|
206
|
+
#strings as keys here (otherwise merging with the config files'
|
207
|
+
#settings would fail).
|
208
|
+
@cmd_config = nil
|
209
|
+
while !argv.empty? and argv.first.start_with?("-") #All options start with a hyphen, commands cannot
|
210
|
+
arg = argv.shift
|
211
|
+
case arg
|
212
|
+
when "-c", "--config-file" then @cmd_config = Pathname.new(argv.shift)
|
213
|
+
when "-d", "--data-directory" then @config["data_directory"] = argv.shift
|
214
|
+
when "-D", "--debug" then CUI.debug_mode = true
|
215
|
+
when "-r", "--repo-url" then @config["repo_url"] = argv.shift
|
216
|
+
else
|
217
|
+
$stderr.puts("Invalid option #{arg}.")
|
218
|
+
$stderr.puts("Try #$0 help.")
|
219
|
+
exit 1
|
220
|
+
end
|
221
|
+
end
|
222
|
+
|
223
|
+
#If nothing is left, the command was left out. Assume 'help'.
|
224
|
+
argv << "help" if argv.empty?
|
225
|
+
|
226
|
+
#Now parse the subcommand.
|
227
|
+
command = argv.shift.to_sym
|
228
|
+
CUI.debug("Found subcommand #{command}.")
|
229
|
+
sym = :"#{command.capitalize}Command"
|
230
|
+
if CUICommands.const_defined?(sym)
|
231
|
+
begin
|
232
|
+
@command = CUICommands.const_get(sym).new(argv)
|
233
|
+
rescue CUICommands::InvalidCommandline => e
|
234
|
+
$stderr.puts(e.message)
|
235
|
+
$stderr.puts("Try #$0 help.")
|
236
|
+
exit 1
|
237
|
+
end
|
238
|
+
else
|
239
|
+
$stderr.puts "Unrecognized command #{command}. Try 'help'."
|
240
|
+
exit 1
|
241
|
+
end
|
242
|
+
end
|
243
|
+
|
244
|
+
#Loads the configuration file from the <b>config/</b> directory.
|
245
|
+
def load_config_file
|
246
|
+
#First, load the global configuration file.
|
247
|
+
CUI.debug("Loading global config #{DEFAULT_CONFIG_FILE}.")
|
248
|
+
hsh = YAML.load_file(DEFAULT_CONFIG_FILE)
|
249
|
+
CUI.debug(hsh)
|
250
|
+
|
251
|
+
#Second, load the user config which overrides values set in
|
252
|
+
#the global config.
|
253
|
+
user_config_file = Pathname.new(ENV["HOME"]) + USER_CONFIG_FILE_NAME
|
254
|
+
CUI.debug("Loading user-level config #{user_config_file}.")
|
255
|
+
if user_config_file.file?
|
256
|
+
hsh.merge!(YAML.load_file(user_config_file.to_s))
|
257
|
+
else
|
258
|
+
CUI.debug("Not found.")
|
259
|
+
end
|
260
|
+
CUI.debug(hsh)
|
261
|
+
|
262
|
+
#Third, load the config file from the commandline, if any. This overrides
|
263
|
+
#values set in the user and global config.
|
264
|
+
if @cmd_config
|
265
|
+
CUI.debug("Loading -c option config #{@cmd_config}.")
|
266
|
+
if @cmd_config.file?
|
267
|
+
hsh.merge!(YAML.load_file(@cmd_config.to_s))
|
268
|
+
else
|
269
|
+
$stderr.puts("Configuration file #{@cmd_config} not found.")
|
270
|
+
end
|
271
|
+
CUI.debug(hsh)
|
272
|
+
end
|
273
|
+
|
274
|
+
#Fourth, check for values on the commandline. They override anything
|
275
|
+
#set previously. They are set directly in @config, so we simply have
|
276
|
+
#to retain the old values in it.
|
277
|
+
CUI.debug("Loading commandline options.")
|
278
|
+
@config.merge!(hsh){|key, old_val, new_val| old_val}
|
279
|
+
CUI.debug(@config)
|
280
|
+
|
281
|
+
#Fifth, turn all keys into symbols, because that's more Ruby-like.
|
282
|
+
CUI.debug("Converting to symbols.")
|
283
|
+
@config = Hash[@config.map{|k, v| [k.to_sym, v]}]
|
284
|
+
CUI.debug(@config)
|
285
|
+
end
|
286
|
+
|
287
|
+
end
|
288
|
+
|
289
|
+
end
|