sphinx_tv 0.9.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +18 -0
- data/Gemfile +4 -0
- data/MIT-LICENSE +20 -0
- data/README.rdoc +54 -0
- data/Rakefile +2 -0
- data/bin/sphinx_tv +6 -0
- data/lib/modules/mysql.rb +155 -0
- data/lib/modules/mythtv.rb +198 -0
- data/lib/modules/shepherd.rb +95 -0
- data/lib/modules/sphinx_module.rb +55 -0
- data/lib/sphinx_tv.rb +233 -0
- data/lib/sphinx_tv/cpan.rb +26 -0
- data/lib/sphinx_tv/download.rb +84 -0
- data/lib/sphinx_tv/version.rb +3 -0
- data/resources/MyConfig.pm.erb +49 -0
- data/resources/MythTv/MythBackend.plist.erb +19 -0
- data/sphinx_tv.gemspec +23 -0
- metadata +111 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright 2011 David Monagle
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.rdoc
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
= SphinxTV
|
2
|
+
|
3
|
+
The purpose of this gem is to provide an installer/configurator to ease the setup of a Mac Mini as a media server.
|
4
|
+
MythTV is the primary focus for this installer (MythTV + Big Cat in the OS makes for the Sphinx name.) Included in the
|
5
|
+
modules is Shepherd, an Australian TV grabber which integrates well with MythTV and allows for a great free TV guide
|
6
|
+
on the MythTV side of things.
|
7
|
+
|
8
|
+
At this point SphinxTV is regarded to be in extreme Alpha. It is on Github in the interests of the people that are
|
9
|
+
alpha testing it for me. I intend to continue to develop and expand on this as time allows (this is a hobby project
|
10
|
+
for me at this point.)
|
11
|
+
|
12
|
+
The goal is to have a website up and running in the coming months that will help detail the setup of a very functional
|
13
|
+
home entertainment system using Mac Mini hardware.
|
14
|
+
|
15
|
+
== Gem Installation ==
|
16
|
+
|
17
|
+
Easy:
|
18
|
+
|
19
|
+
gem install sphinx_tv
|
20
|
+
|
21
|
+
== Using SphinxTV ==
|
22
|
+
|
23
|
+
=== Setup ===
|
24
|
+
|
25
|
+
sphinx_tv setup
|
26
|
+
|
27
|
+
Turn on the modules that you wish to install and configure.
|
28
|
+
|
29
|
+
=== Download ===
|
30
|
+
|
31
|
+
sphinx_tv download
|
32
|
+
|
33
|
+
Option step but will just do all the necessary downloading for the modules that have been configured in the setup stage.
|
34
|
+
|
35
|
+
=== Installation ===
|
36
|
+
|
37
|
+
sphinx_tv install
|
38
|
+
|
39
|
+
This runs through the install of each module. If the download wasn't run seperately, then the downloads will be done
|
40
|
+
on-demand at ths start of the module install.
|
41
|
+
|
42
|
+
=== Configuration ===
|
43
|
+
|
44
|
+
sphinx_tv configure
|
45
|
+
|
46
|
+
Post installation configuration.
|
47
|
+
|
48
|
+
== Modules ==
|
49
|
+
|
50
|
+
=== MySQL ===
|
51
|
+
|
52
|
+
=== MythTV ===
|
53
|
+
|
54
|
+
=== Shepherd ===
|
data/Rakefile
ADDED
data/bin/sphinx_tv
ADDED
@@ -0,0 +1,155 @@
|
|
1
|
+
class MySQL < SphinxModule
|
2
|
+
def check(quiet = false)
|
3
|
+
result = true
|
4
|
+
unless mysql_installed?
|
5
|
+
result = false
|
6
|
+
puts "The MySQL server doesn't appear to be installed.'".red unless quiet
|
7
|
+
end
|
8
|
+
unless File.exists? "/etc/paths.d/mysql"
|
9
|
+
result = false
|
10
|
+
puts "MySQL paths.d file is not configured.".red unless quiet
|
11
|
+
end
|
12
|
+
unless File.exists? "/usr/lib/libmysqlclient.18.dylib"
|
13
|
+
result = false
|
14
|
+
puts "MySQL does not have a symbolic link set up for the libmysqlclient dynlib.".red unless quiet
|
15
|
+
end
|
16
|
+
unless File.exists? "/var/mysql/mysql.sock"
|
17
|
+
result = false
|
18
|
+
puts "MySQL socket does not exist.".red unless quiet
|
19
|
+
end
|
20
|
+
|
21
|
+
puts "MySQL is OK.".green if result
|
22
|
+
result
|
23
|
+
end
|
24
|
+
|
25
|
+
def configure
|
26
|
+
unless mysql_installed?
|
27
|
+
puts "\nOnce you have MySQL installed, you may return to this menu to setup root access\n"
|
28
|
+
end
|
29
|
+
exit = false
|
30
|
+
until exit do
|
31
|
+
choose do |menu|
|
32
|
+
menu.header = "\nMySQL Configuration".cyan
|
33
|
+
menu.prompt = "Select an option: "
|
34
|
+
if mysql_installed?
|
35
|
+
menu.choice("Setup root access") { set_mysql_root_access }
|
36
|
+
end
|
37
|
+
menu.choice("Done") {
|
38
|
+
exit = true
|
39
|
+
}
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def download
|
45
|
+
url = "http://cdn.mysql.com/Downloads/MySQL-5.5/mysql-5.5.25a-osx10.6-x86_64.dmg"
|
46
|
+
puts "Downloading MySQL".cyan
|
47
|
+
puts url
|
48
|
+
result = Download.url(url, SphinxTv::download_path("mysql.dmg"))
|
49
|
+
end
|
50
|
+
|
51
|
+
def install
|
52
|
+
puts "Installing MySQL".cyan
|
53
|
+
unless check(true)
|
54
|
+
download
|
55
|
+
Download.mount(SphinxTv::download_path("mysql.dmg"), "mysql*") do |volume|
|
56
|
+
self.install_mysql_server volume
|
57
|
+
self.install_mysql_prefpane volume
|
58
|
+
self.install_mysql_startup volume
|
59
|
+
end
|
60
|
+
else
|
61
|
+
puts "MySQL is installed.".green
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
protected
|
66
|
+
|
67
|
+
def mysql_installed?
|
68
|
+
File.exists?("/usr/local/mysql/bin/mysql")
|
69
|
+
end
|
70
|
+
|
71
|
+
def install_mysql_server volume
|
72
|
+
puts "Installing MySQL Server".cyan
|
73
|
+
puts "This will configure the MySQL server. A graphical installer should open now."
|
74
|
+
files = Dir.glob File.join(volume, "mysql*")
|
75
|
+
if (files.size == 0)
|
76
|
+
puts "Could not find installer file in volume #{volume}".red
|
77
|
+
return
|
78
|
+
end
|
79
|
+
%x[open #{files[0]}]
|
80
|
+
ask "\nPress enter when the install is complete!".magenta
|
81
|
+
|
82
|
+
# Create the paths.d file
|
83
|
+
if mysql_installed?
|
84
|
+
puts "Creating global path file /etc/paths.d/mysql".cyan
|
85
|
+
%x[sudo #{SphinxTv::SUDO_PROMPT} bash -c 'echo "/usr/local/mysql/bin" > /etc/paths.d/mysql']
|
86
|
+
end
|
87
|
+
|
88
|
+
# Create the symbolic link to the client library
|
89
|
+
unless File.exists? "/usr/lib/libmysqlclient.18.dylib"
|
90
|
+
puts "Linking dynamic libraries".cyan
|
91
|
+
%x[sudo #{SphinxTv::SUDO_PROMPT} ln -s /usr/local/mysql/lib/libmysqlclient.18.dylib /usr/lib]
|
92
|
+
end
|
93
|
+
|
94
|
+
# Create the mysql socket
|
95
|
+
unless File.exists? "/tmp/mysql.sock"
|
96
|
+
puts "Creating link to mysql socket".cyan
|
97
|
+
%x[sudo #{SphinxTv::SUDO_PROMPT} mkdir -p /var/mysql]
|
98
|
+
%x[sudo #{SphinxTv::SUDO_PROMPT} ln -s /tmp/mysql.sock /var/mysql/]
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
def install_mysql_prefpane volume
|
103
|
+
puts "Installing MySQL Prefpane\n".cyan
|
104
|
+
puts "Select the option to install for all users of the computer"
|
105
|
+
puts "On the Prefpane, tick the option to start the MySQL Server on Startup"
|
106
|
+
puts "Click the button to start the MySQL Server"
|
107
|
+
files = Dir.glob File.join(volume, "MySQL.prefpane")
|
108
|
+
if (files.size == 0)
|
109
|
+
puts "Could not find Prefpane file in volume #{volume}".red
|
110
|
+
return
|
111
|
+
end
|
112
|
+
%x[open #{files[0]}]
|
113
|
+
ask "\nPress enter when the install is complete!".magenta
|
114
|
+
end
|
115
|
+
|
116
|
+
def install_mysql_startup volume
|
117
|
+
puts "Installing MySQL Startup".cyan
|
118
|
+
files = Dir.glob File.join(volume, "MySQLStartup*")
|
119
|
+
if (files.size == 0)
|
120
|
+
puts "Could not find startup installer file in volume #{volume}".red
|
121
|
+
return
|
122
|
+
end
|
123
|
+
%x[open #{files[0]}]
|
124
|
+
ask "\nPress enter when the install is complete!".magenta
|
125
|
+
end
|
126
|
+
|
127
|
+
def set_mysql_root_access
|
128
|
+
puts "This will allow you to set the root password for your database.".yellow
|
129
|
+
puts "It will give you a more secure SQL server on your network but if you lose".yellow
|
130
|
+
puts "the root password at any point, it will cause you pain.".yellow
|
131
|
+
response = ask("Set up root privileges? ") { |q| q.default = "No" }
|
132
|
+
return if !/Y/i.match(response)
|
133
|
+
old_root_pass = ask("Enter the current root password: ") { |q| q.echo = "*" }
|
134
|
+
root_pass = ask("Enter the new root password: ") { |q| q.echo = "*" }
|
135
|
+
root_pass_confirm = ask("Re-enter the new root password: ") { |q| q.echo = "*" }
|
136
|
+
if root_pass != root_pass_confirm
|
137
|
+
puts "Passwords do not match!".red
|
138
|
+
return
|
139
|
+
end
|
140
|
+
hostname = %x[hostname].strip
|
141
|
+
hostname_short = /^[^\.]+/.match(hostname)
|
142
|
+
mysql_commands = Array.new.tap do |c|
|
143
|
+
c << "DROP USER ''@'localhost';" if old_root_pass.empty?
|
144
|
+
c << "SET PASSWORD FOR 'root'@'localhost' = PASSWORD('#{root_pass}');"
|
145
|
+
c << "SET PASSWORD FOR 'root'@'127.0.0.1' = PASSWORD('#{root_pass}');"
|
146
|
+
c << "SET PASSWORD FOR 'root'@'#{hostname}' = PASSWORD('#{root_pass}');"
|
147
|
+
c << "SET PASSWORD FOR 'root'@'#{hostname_short}' = PASSWORD('#{root_pass}');"
|
148
|
+
end
|
149
|
+
password_param = old_root_pass.empty? ? "" : " --password=#{old_root_pass}"
|
150
|
+
mysql_commands.each do |sql|
|
151
|
+
puts sql
|
152
|
+
%x[/usr/local/mysql/bin/mysql -u root#{password_param} -e "#{sql}"]
|
153
|
+
end
|
154
|
+
end
|
155
|
+
end
|
@@ -0,0 +1,198 @@
|
|
1
|
+
require 'nokogiri'
|
2
|
+
require 'open-uri'
|
3
|
+
|
4
|
+
class MythTv < SphinxModule
|
5
|
+
def initialize
|
6
|
+
@config = {
|
7
|
+
:version => SphinxTv::VERSION
|
8
|
+
}
|
9
|
+
load_configuration
|
10
|
+
end
|
11
|
+
|
12
|
+
def check(quiet = false)
|
13
|
+
result = true
|
14
|
+
result = false unless mythtv_backend_installed?(quiet)
|
15
|
+
result = false unless mythtv_frontend_installed?(quiet)
|
16
|
+
unless @config[:database_password]
|
17
|
+
result = false
|
18
|
+
puts "Assuming no database is set up as the MythTV database password is not set.'".red unless quiet
|
19
|
+
end
|
20
|
+
unless File.exists? "/usr/local/bin/mythfilldatabase"
|
21
|
+
result = false
|
22
|
+
puts "No symbolic link to mythfilldatabase found".red unless quiet
|
23
|
+
end
|
24
|
+
|
25
|
+
puts "MythTV is OK.".green if result
|
26
|
+
result
|
27
|
+
end
|
28
|
+
|
29
|
+
def configure
|
30
|
+
exit = false
|
31
|
+
until exit do
|
32
|
+
choose do |menu|
|
33
|
+
menu.header = "\nMythTV Configuration".cyan
|
34
|
+
menu.prompt = "Select an option: "
|
35
|
+
if mythtv_backend_installed?
|
36
|
+
menu.choice("Setup database") { setup_database }
|
37
|
+
end
|
38
|
+
menu.choice("Create Storage Directories") { create_storage_directories }
|
39
|
+
if mythtv_backend_running?
|
40
|
+
menu.choice("MythTV Backend Control " + "Loaded".green) { mythtv_backend_control(false) }
|
41
|
+
else
|
42
|
+
menu.choice("MythTV Backend Control " + "Unloaded".red) { mythtv_backend_control(true) }
|
43
|
+
end
|
44
|
+
menu.choice("Done") {
|
45
|
+
exit = true
|
46
|
+
}
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def download
|
52
|
+
doc = Nokogiri::HTML(open('http://sourceforge.net/projects/mythtvformacosx/files/'))
|
53
|
+
|
54
|
+
doc.css('tr.file a').each do |link|
|
55
|
+
if /\.dmg\/download$/.match(link[:href])
|
56
|
+
filename = nil
|
57
|
+
if /MythBack.*10\.7/.match(link[:href])
|
58
|
+
filename = "MythBackend.dmg"
|
59
|
+
elsif /MythFront.*10\.7/.match(link[:href])
|
60
|
+
filename = "MythFrontend.dmg"
|
61
|
+
end
|
62
|
+
if filename
|
63
|
+
puts "Downloading #{filename}".cyan
|
64
|
+
puts link[:href]
|
65
|
+
Download::url(link[:href], SphinxTv::download_path(filename))
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def install
|
72
|
+
puts "Installing MythTV".cyan
|
73
|
+
unless check(true)
|
74
|
+
download
|
75
|
+
install_mythtv_backend unless mythtv_backend_installed?
|
76
|
+
install_mythtv_frontend unless mythtv_frontend_installed?
|
77
|
+
|
78
|
+
unless File.exists? "/usr/local/bin/mythfilldatabase"
|
79
|
+
puts "Creating link to mythfilldatabase".cyan
|
80
|
+
%x[sudo #{SphinxTv::SUDO_PROMPT} mkdir -p /usr/local/bin]
|
81
|
+
%x[sudo #{SphinxTv::SUDO_PROMPT} ln -s /Applications/MythBackend.app/Contents/MacOS/mythfilldatabase /usr/local/bin/mythfilldatabase]
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
private
|
87
|
+
|
88
|
+
def mythtv_backend_running?
|
89
|
+
result = %x[ps ax | grep MythBackend | grep -v grep]
|
90
|
+
return false if result.strip.empty?
|
91
|
+
true
|
92
|
+
end
|
93
|
+
|
94
|
+
def mythtv_backend_control(load)
|
95
|
+
%x[sudo #{SphinxTv::SUDO_PROMPT} launchctl #{load ? "load" : "unload"} -w /Library/LaunchDaemons/MythBackend.plist]
|
96
|
+
end
|
97
|
+
|
98
|
+
def mythtv_frontend_installed?(quiet = true)
|
99
|
+
result = true
|
100
|
+
unless File.exists? "/Applications/MythFrontend.app"
|
101
|
+
result = false
|
102
|
+
puts "MythFrontend application not installed.".red unless quiet
|
103
|
+
end
|
104
|
+
result
|
105
|
+
end
|
106
|
+
|
107
|
+
def mythtv_backend_installed?(quiet = true)
|
108
|
+
result = true
|
109
|
+
unless File.exists? "/Applications/MythBackend.app"
|
110
|
+
result = false
|
111
|
+
puts "MythBackend application not installed.".red unless quiet
|
112
|
+
end
|
113
|
+
unless File.exists? "/Library/LaunchDaemons/MythBackend.plist"
|
114
|
+
result = false
|
115
|
+
puts "MythBackend LaunchDaemon does not exist.".red unless quiet
|
116
|
+
end
|
117
|
+
result
|
118
|
+
end
|
119
|
+
|
120
|
+
def install_mythtv_backend
|
121
|
+
Download.mount(SphinxTv::download_path("MythBackend.dmg"), "MythBackend*") do |volume|
|
122
|
+
puts "Installing MythTVBackend".cyan
|
123
|
+
mythtv_files = ["MythBackend.app", "MythTv-Setup.app"]
|
124
|
+
mythtv_files.each do |file|
|
125
|
+
%x[cp -Rf #{volume}/#{file} /Applications 2>&1]
|
126
|
+
end
|
127
|
+
@username = Etc.getlogin
|
128
|
+
unless File.exists? "/var/log/mythtv"
|
129
|
+
puts "Creating MythTV log directory...".cyan
|
130
|
+
%x[sudo #{SphinxTv::SUDO_PROMPT} mkdir -p /var/log/mythtv]
|
131
|
+
%x[sudo #{SphinxTv::SUDO_PROMPT} chmod a+rwx /var/log/mythtv]
|
132
|
+
end
|
133
|
+
|
134
|
+
puts "Creating MythBackend LaunchDaemon file...".cyan
|
135
|
+
SphinxTv::copy_template(SphinxTv::resources_path("MythTv/MythBackend.plist.erb"), SphinxTv::cache_path("MythBackend.plist"), binding)
|
136
|
+
%x[sudo #{SphinxTv::SUDO_PROMPT} cp #{SphinxTv::cache_path("MythBackend.plist")} /Library/LaunchDaemons]
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
def install_mythtv_frontend
|
141
|
+
Download.mount(SphinxTv::download_path("MythFrontend.dmg"), "MythFrontend*") do |volume|
|
142
|
+
puts "Installing MythTVFrontend".cyan
|
143
|
+
mythtv_files = ["MythFrontend.app", "MythWelcome.app", "MythAVTest.app"]
|
144
|
+
mythtv_files.each do |file|
|
145
|
+
%x[cp -Rf #{volume}/#{file} /Applications 2>&1]
|
146
|
+
end
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
def setup_database
|
151
|
+
puts "This will create the MythTV database if it doesn't already exist and set appropriate privileges."
|
152
|
+
root_pass = ask("Enter your mysql root password: ") { |q| q.echo = "*" }
|
153
|
+
@config[:database_password] ||= SphinxTv::get_password_with_confirmation("Enter a password for the mythtv MySQL user: ")
|
154
|
+
return if @config[:database_password].nil?
|
155
|
+
save_configuration
|
156
|
+
hostname = %x[hostname].strip
|
157
|
+
hostname_short = /^[^\.]+/.match(hostname)
|
158
|
+
mysql_commands = Array.new.tap do |c|
|
159
|
+
c << "CREATE DATABASE IF NOT EXISTS mythconverg;"
|
160
|
+
c << "GRANT ALL ON mythconverg.* TO mythtv@localhost IDENTIFIED BY '#{@config[:database_password]}';"
|
161
|
+
c << "GRANT ALL ON mythconverg.* TO mythtv@#{hostname} IDENTIFIED BY '#{@config[:database_password]}';"
|
162
|
+
c << "FLUSH PRIVILEGES;"
|
163
|
+
c << "GRANT CREATE TEMPORARY TABLES ON mythconverg.* TO mythtv@localhost IDENTIFIED BY '#{@config[:database_password]}';"
|
164
|
+
c << "GRANT CREATE TEMPORARY TABLES ON mythconverg.* TO mythtv@#{hostname} IDENTIFIED BY '#{@config[:database_password]}';"
|
165
|
+
c << "FLUSH PRIVILEGES;"
|
166
|
+
c << "ALTER DATABASE mythconverg DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;"
|
167
|
+
end
|
168
|
+
password_param = root_pass.empty? ? "" : " --password=#{root_pass}"
|
169
|
+
mysql_commands.each do |sql|
|
170
|
+
puts sql
|
171
|
+
%x[/usr/local/mysql/bin/mysql -u root#{password_param} -e "#{sql}"]
|
172
|
+
end
|
173
|
+
|
174
|
+
puts "Creating mysql.txt in /etc/mythtv".cyan
|
175
|
+
%x[sudo #{SphinxTv::SUDO_PROMPT} mkdir -p /etc/mythtv]
|
176
|
+
%x[sudo #{SphinxTv::SUDO_PROMPT} chmod a+rwx /etc/mythtv]
|
177
|
+
outfile = File.open("/etc/mythtv/mysql.txt", "w")
|
178
|
+
outfile.puts("DBHostName=#{hostname}")
|
179
|
+
outfile.puts("DBUserName=mythtv")
|
180
|
+
outfile.puts("DBPassword=#{@config[:database_password]}")
|
181
|
+
outfile.puts("DBName=mythconverg")
|
182
|
+
outfile.puts("DBType=QMYSQL3")
|
183
|
+
outfile.close
|
184
|
+
%x[chmod o-w /etc/mythtv/mysql.txt]
|
185
|
+
end
|
186
|
+
|
187
|
+
def create_storage_directories
|
188
|
+
storage_root = ask("Enter the storage directory root: ") { |q| q.default = "/Volumes/MythTV" }
|
189
|
+
directories = ['Backups', 'Banners', 'Coverart', 'Fanart', 'LiveTV', 'Recordings', 'Screenshots', 'Trailers']
|
190
|
+
directories.each do |directory|
|
191
|
+
full_dir = File.join(storage_root, directory)
|
192
|
+
puts full_dir
|
193
|
+
%x[sudo #{SphinxTv::SUDO_PROMPT} mkdir -p #{full_dir}]
|
194
|
+
end
|
195
|
+
%x[sudo #{SphinxTv::SUDO_PROMPT} chown -Rf #{Etc.getlogin} #{storage_root}]
|
196
|
+
%x[sudo #{SphinxTv::SUDO_PROMPT} chmod -Rf ugo+rwx #{storage_root}]
|
197
|
+
end
|
198
|
+
end
|
@@ -0,0 +1,95 @@
|
|
1
|
+
class Shepherd < SphinxModule
|
2
|
+
def initialize
|
3
|
+
@config = {
|
4
|
+
:version => SphinxTv::VERSION
|
5
|
+
}
|
6
|
+
load_configuration
|
7
|
+
end
|
8
|
+
|
9
|
+
def check(quiet = false)
|
10
|
+
result = true
|
11
|
+
|
12
|
+
unless File.exists? "/usr/local/share/xmltv"
|
13
|
+
result = false
|
14
|
+
puts "XMLTV is not installed.".red unless quiet
|
15
|
+
end
|
16
|
+
|
17
|
+
unless File.exists? File.join(Etc.getpwuid.dir, ".shepherd")
|
18
|
+
result = false
|
19
|
+
puts "Shepherd is not installed.".red unless quiet
|
20
|
+
end
|
21
|
+
|
22
|
+
puts "Shepherd is OK.".green if result
|
23
|
+
result
|
24
|
+
end
|
25
|
+
|
26
|
+
def download
|
27
|
+
doc = Nokogiri::HTML(open('http://sourceforge.net/projects/xmltv/files/xmltv/0.5.63/'))
|
28
|
+
|
29
|
+
url = "http://www.whuffy.com/shepherd/shepherd"
|
30
|
+
puts "Downloading Shepherd".cyan
|
31
|
+
puts url
|
32
|
+
result = Download.url(url, SphinxTv::download_path("shepherd"))
|
33
|
+
|
34
|
+
doc.css('tr.file a').each do |link|
|
35
|
+
if /\.tar\.bz2\/download$/.match(link[:href])
|
36
|
+
filename = nil
|
37
|
+
filename = "xmltv.tar.bz2" if /xmltv/.match(link[:href])
|
38
|
+
if filename
|
39
|
+
puts "Downloading #{filename}".cyan
|
40
|
+
puts link[:href]
|
41
|
+
Download::url(link[:href], SphinxTv::download_path(filename))
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def install
|
48
|
+
unless check(true)
|
49
|
+
download
|
50
|
+
install_perl_prerequisites
|
51
|
+
install_xmltv unless File.exists? "/usr/local/share/xmltv"
|
52
|
+
|
53
|
+
unless File.exists? "/Library/Perl/5.12/Shepherd"
|
54
|
+
puts "Creating symlink for Shepherd/MythTV perl library...".cyan
|
55
|
+
home_dir = Etc.getpwuid.dir
|
56
|
+
%x[sudo #{SphinxTv::SUDO_PROMPT} ln -s #{home_dir}/.shepherd/references/Shepherd /Library/Perl/5.12]
|
57
|
+
end
|
58
|
+
puts "Installing Shepherd".cyan
|
59
|
+
system("perl #{SphinxTv::download_path("shepherd")} --configure")
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def install_perl_prerequisites
|
64
|
+
|
65
|
+
Cpan::create_config_file
|
66
|
+
|
67
|
+
shepherd_mandatory_perl_modules = "YAML XML::Twig Algorithm::Diff Compress::Zlib Cwd Data::Dumper Date::Manip Getopt::Long \
|
68
|
+
List::Compare LWP::UserAgent POSIX Digest::SHA1"
|
69
|
+
|
70
|
+
shepherd_optional_perl_modules = "DateTime::Format::Strptime File::Basename File::Path HTML::Entities \
|
71
|
+
HTML::TokeParser HTML::TreeBuilder IO::File Storable Time::HiRes XML::DOM \
|
72
|
+
XML::DOM::NodeList XML::Simple Storable HTTP::Cookies File::Basename \
|
73
|
+
LWP::ConnCache Digest::MD5 Archive::Zip IO::String \
|
74
|
+
DateTime::Format::Strptime \
|
75
|
+
HTTP::Cache::Transparent Crypt::SSLeay DBD::mysql "
|
76
|
+
|
77
|
+
perl_modules = shepherd_mandatory_perl_modules.split(" ") + shepherd_optional_perl_modules.split(" ")
|
78
|
+
puts "Installing required perl modules...".cyan
|
79
|
+
Cpan::install(perl_modules)
|
80
|
+
end
|
81
|
+
|
82
|
+
def install_xmltv
|
83
|
+
puts "Extracting XMLTV...".cyan
|
84
|
+
%x[tar -jxf #{SphinxTv::download_path("xmltv.tar.bz2")} -C #{SphinxTv::cache_path}]
|
85
|
+
puts "Compiling XMLTV...".cyan
|
86
|
+
commands = Array.new.tap do |c|
|
87
|
+
c << "cd #{Sphinx.cache_path}/xmltv*"
|
88
|
+
c << "perl Makefile.PL"
|
89
|
+
c << "make"
|
90
|
+
c << "make test"
|
91
|
+
c << "sudo #{SphinxTv::SUDO_PROMPT} make install"
|
92
|
+
end
|
93
|
+
puts %x[#{commands.join(";")}]
|
94
|
+
end
|
95
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
class SphinxModule
|
2
|
+
def initialize
|
3
|
+
@config = {
|
4
|
+
:version => SphinxTv::VERSION
|
5
|
+
}
|
6
|
+
end
|
7
|
+
|
8
|
+
def load_configuration
|
9
|
+
config_file = File.join(SphinxTv::CONFIG_DIRECTORY, "#{self.class.to_s.downcase}.yml")
|
10
|
+
unless File.exists? config_file
|
11
|
+
return false
|
12
|
+
end
|
13
|
+
c = YAML::load_file config_file
|
14
|
+
@config.merge! c
|
15
|
+
return true
|
16
|
+
end
|
17
|
+
|
18
|
+
def save_configuration
|
19
|
+
def save_configuration
|
20
|
+
Dir.mkdir(SphinxTv::CONFIG_DIRECTORY) unless File.exists? SphinxTv::CONFIG_DIRECTORY
|
21
|
+
File.open(File.join(SphinxTv::CONFIG_DIRECTORY, "#{self.class.to_s.downcase}.yml"), "w") do |file|
|
22
|
+
file.write @config.to_yaml
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def check(quiet = false)
|
28
|
+
return true
|
29
|
+
end
|
30
|
+
|
31
|
+
def setup
|
32
|
+
puts "#{self.class.to_s} does not have a setup menu.".red
|
33
|
+
return false
|
34
|
+
end
|
35
|
+
|
36
|
+
def configure
|
37
|
+
puts "#{self.class.to_s} does not have a configuration menu.".red
|
38
|
+
return false
|
39
|
+
end
|
40
|
+
|
41
|
+
def download
|
42
|
+
end
|
43
|
+
|
44
|
+
def install
|
45
|
+
puts "#{self.class.to_s} does not have an install function.".red
|
46
|
+
end
|
47
|
+
|
48
|
+
def uninstall
|
49
|
+
puts "#{self.class.to_s} does not have an uninstall function.".red
|
50
|
+
end
|
51
|
+
|
52
|
+
def update
|
53
|
+
puts "#{self.class.to_s} does not have an update function.".red
|
54
|
+
end
|
55
|
+
end
|
data/lib/sphinx_tv.rb
ADDED
@@ -0,0 +1,233 @@
|
|
1
|
+
require "colorize"
|
2
|
+
require "etc"
|
3
|
+
require "yaml"
|
4
|
+
require 'optparse'
|
5
|
+
require "highline/import"
|
6
|
+
require "modules/sphinx_module"
|
7
|
+
require "sphinx_tv/download"
|
8
|
+
require "sphinx_tv/cpan"
|
9
|
+
require "erb"
|
10
|
+
require "version"
|
11
|
+
|
12
|
+
class SphinxTv
|
13
|
+
SUDO_PROMPT = "-p \"#{"Your administrator password is required to peform this step: ".yellow}\""
|
14
|
+
CONFIG_DIRECTORY = File.join(Etc.getpwuid.dir, ".sphinx_tv")
|
15
|
+
MODULES = ["MySQL", "MythTv", "Shepherd"]
|
16
|
+
MODULE_DEFAULTS = {
|
17
|
+
"MySQL" => {
|
18
|
+
:active => true,
|
19
|
+
:setup => false,
|
20
|
+
:configure => true,
|
21
|
+
},
|
22
|
+
"MythTv" => {
|
23
|
+
:active => true,
|
24
|
+
:setup => false,
|
25
|
+
:configure => true,
|
26
|
+
:depends => ["MySQL"],
|
27
|
+
},
|
28
|
+
"Shepherd" => {
|
29
|
+
:active => false,
|
30
|
+
:setup => false,
|
31
|
+
:configure => true,
|
32
|
+
:depends => ["MythTv"],
|
33
|
+
},
|
34
|
+
}
|
35
|
+
|
36
|
+
def initialize
|
37
|
+
@config = {
|
38
|
+
:version => VERSION,
|
39
|
+
:modules => MODULE_DEFAULTS
|
40
|
+
}
|
41
|
+
end
|
42
|
+
|
43
|
+
def self.root_directory
|
44
|
+
File.expand_path '../..', __FILE__
|
45
|
+
end
|
46
|
+
|
47
|
+
def self.resources_path(file = "")
|
48
|
+
File.join(root_directory, "resources", file)
|
49
|
+
end
|
50
|
+
|
51
|
+
def self.download_path(file = "")
|
52
|
+
download_directory = File.join(CONFIG_DIRECTORY, "downloads")
|
53
|
+
Dir.mkdir(download_directory) unless File.exists? download_directory
|
54
|
+
return File.join(download_directory, file)
|
55
|
+
end
|
56
|
+
|
57
|
+
def self.cache_path(file = "")
|
58
|
+
cache_directory = File.join(CONFIG_DIRECTORY, "cache")
|
59
|
+
Dir.mkdir(cache_directory) unless File.exists? cache_directory
|
60
|
+
return File.join(cache_directory, file)
|
61
|
+
end
|
62
|
+
|
63
|
+
def self.copy_template(source, dest, b)
|
64
|
+
t = ERB.new File.new(source).read, nil, "%"
|
65
|
+
outfile = File.open(dest, "w")
|
66
|
+
outfile.write(t.result(b || binding))
|
67
|
+
outfile.close
|
68
|
+
end
|
69
|
+
|
70
|
+
def self.get_password_with_confirmation(prompt = nil)
|
71
|
+
pass = ask(prompt || "Enter a password: ") { |q| q.echo = "*" }
|
72
|
+
pass_confirm = ask("Re-enter the password: ") { |q| q.echo = "*" }
|
73
|
+
if pass != pass_confirm
|
74
|
+
puts "Passwords do not match!".red
|
75
|
+
return nil
|
76
|
+
end
|
77
|
+
pass
|
78
|
+
end
|
79
|
+
|
80
|
+
def load_configuration
|
81
|
+
config_file = File.join(CONFIG_DIRECTORY, "sphinx.yml")
|
82
|
+
unless File.exists? config_file
|
83
|
+
puts "Configuration file does not exist. Using defaults.".yellow
|
84
|
+
return false
|
85
|
+
end
|
86
|
+
c = YAML::load_file config_file
|
87
|
+
@config.merge! c
|
88
|
+
return true
|
89
|
+
end
|
90
|
+
|
91
|
+
def save_configuration
|
92
|
+
Dir.mkdir(CONFIG_DIRECTORY) unless File.exists? CONFIG_DIRECTORY
|
93
|
+
File.open(File.join(CONFIG_DIRECTORY, "sphinx.yml"), "w") do |file|
|
94
|
+
file.write @config.to_yaml
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
def module_select
|
99
|
+
exit = false
|
100
|
+
until exit do
|
101
|
+
choose do |menu|
|
102
|
+
menu.header = "\nSelect Modules".cyan
|
103
|
+
menu.prompt = "Select optional modules to toggle: "
|
104
|
+
MODULES.each do |m|
|
105
|
+
options = @config[:modules][m]
|
106
|
+
menu.choice("#{m}: " + (options[:active] ? "On".green : "Off".red)) do |choice|
|
107
|
+
m = /^([^:]*)/.match(choice)[0]
|
108
|
+
toggle_module m
|
109
|
+
end
|
110
|
+
end
|
111
|
+
menu.choice(:done) {
|
112
|
+
exit = true
|
113
|
+
}
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
def toggle_module(m)
|
119
|
+
options = @config[:modules][m]
|
120
|
+
|
121
|
+
options[:active] = !options[:active]
|
122
|
+
if (options[:active])
|
123
|
+
if (options[:depends])
|
124
|
+
options[:depends].each do |d|
|
125
|
+
toggle_module d unless @config[:modules][d][:active]
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
def module_menu(action, title)
|
132
|
+
exit = false
|
133
|
+
until exit do
|
134
|
+
choose do |menu|
|
135
|
+
menu.header = "\n#{title}".cyan
|
136
|
+
menu.prompt = "Select a module: "
|
137
|
+
MODULES.each do |m|
|
138
|
+
options = @config[:modules][m]
|
139
|
+
if (options[action])
|
140
|
+
menu.choice(m) do |m|
|
141
|
+
require File.join("modules", m)
|
142
|
+
mod = eval("#{m}.new")
|
143
|
+
mod.send(action)
|
144
|
+
end
|
145
|
+
end
|
146
|
+
end
|
147
|
+
menu.choice(:done) {
|
148
|
+
exit = true
|
149
|
+
}
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
def run_selected_modules &block
|
155
|
+
MODULES.each do |m|
|
156
|
+
if @config[:modules][m][:active]
|
157
|
+
require File.join("modules", m)
|
158
|
+
mod = eval("#{m}.new")
|
159
|
+
yield mod
|
160
|
+
end
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
def setup
|
165
|
+
exit = false
|
166
|
+
until exit do
|
167
|
+
choose do |menu|
|
168
|
+
menu.header = "\nSphinx Installer".cyan
|
169
|
+
menu.prompt = "Select an option: "
|
170
|
+
|
171
|
+
menu.choice("Select Modules") { module_select }
|
172
|
+
menu.choice("Setup Modules") { module_menu(:setup, "Module Setup") }
|
173
|
+
menu.choice("Save Configuration") {
|
174
|
+
save_configuration
|
175
|
+
puts "Configuration Saved.".green
|
176
|
+
exit = true
|
177
|
+
}
|
178
|
+
menu.choice("Cancel") {
|
179
|
+
puts "Exiting without saving configuration.".red
|
180
|
+
exit = true
|
181
|
+
}
|
182
|
+
end
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
def run
|
187
|
+
@no_config = load_configuration
|
188
|
+
|
189
|
+
action = nil
|
190
|
+
|
191
|
+
optparse = OptionParser.new do |opts|
|
192
|
+
# Set a banner, displayed at the top
|
193
|
+
# of the help screen.
|
194
|
+
opts.banner = "Usage: sphinx [options] action"
|
195
|
+
|
196
|
+
# This displays the help screen, all programs are
|
197
|
+
# assumed to have this option.
|
198
|
+
opts.on('-h', '--help', 'Display this screen') do
|
199
|
+
puts opts
|
200
|
+
exit
|
201
|
+
end
|
202
|
+
end
|
203
|
+
|
204
|
+
# Parse the command-line. Remember there are two forms
|
205
|
+
# of the parse method. The 'parse' method simply parses
|
206
|
+
# ARGV, while the 'parse!' method parses ARGV and removes
|
207
|
+
# any options found there, as well as any parameters for
|
208
|
+
# the options. What's left is the list of files to resize.
|
209
|
+
optparse.parse!
|
210
|
+
# Set the selected modules unless it was overridden
|
211
|
+
|
212
|
+
action = ARGV[0]
|
213
|
+
case action
|
214
|
+
when "setup"
|
215
|
+
setup
|
216
|
+
when "configure"
|
217
|
+
module_menu(:configure, "Configure Modules")
|
218
|
+
when "check"
|
219
|
+
run_selected_modules { |m| m.check }
|
220
|
+
when "install"
|
221
|
+
run_selected_modules { |m| m.install }
|
222
|
+
when "uninstall"
|
223
|
+
run_selected_modules { |m| m.uninstall }
|
224
|
+
when "download"
|
225
|
+
run_selected_modules { |m| m.download }
|
226
|
+
when "update"
|
227
|
+
run_selected_modules { |m| m.update }
|
228
|
+
else
|
229
|
+
puts "Use the --help switch if you need a list of valid actions"
|
230
|
+
end
|
231
|
+
end
|
232
|
+
|
233
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'expect'
|
2
|
+
require 'pty'
|
3
|
+
|
4
|
+
class Cpan
|
5
|
+
def self.install modules
|
6
|
+
modules.each do |m|
|
7
|
+
result = %x[perl -M#{m} -e 1 2>&1].strip
|
8
|
+
if result.empty?
|
9
|
+
puts "Module '#{m}' is installed".green
|
10
|
+
else
|
11
|
+
puts "Installing perl module: #{m}".cyan
|
12
|
+
system("sudo #{Sphinx::SUDO_PROMPT} cpan -j #{Sphinx::cache_path("MyConfig.pm")} -f -i #{m}")
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.create_config_file
|
18
|
+
unless File.exists? Sphinx::cache_path("MyConfig.pm")
|
19
|
+
puts "Creating cpan config...".cyan
|
20
|
+
|
21
|
+
@cache_dir = Sphinx::cache_path
|
22
|
+
Sphinx::copy_template(Sphinx::resources_path("MyConfig.pm.erb"), Sphinx::cache_path("MyConfig.pm"), binding)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
@@ -0,0 +1,84 @@
|
|
1
|
+
module Download
|
2
|
+
def self.url file_url, filename
|
3
|
+
Dir::mkdir("cache") unless FileTest::directory?("cache")
|
4
|
+
|
5
|
+
z_option = (File.exists?(filename) ? " -z #{filename}" : "")
|
6
|
+
result = %x[curl -L -w "%{http_code} %{url_effective}"#{z_option} -o #{filename}.download #{file_url}]
|
7
|
+
if /304/.match(result)
|
8
|
+
puts "Up to date: ".green + filename
|
9
|
+
return false
|
10
|
+
else
|
11
|
+
if /200/.match(result)
|
12
|
+
begin
|
13
|
+
File.rename "#{filename}.download", filename
|
14
|
+
rescue
|
15
|
+
end
|
16
|
+
puts "Updated: ".yellow + filename
|
17
|
+
return true
|
18
|
+
else
|
19
|
+
File.delete "#{filename}.download" if File.exists? "#{filename}.download"
|
20
|
+
puts "File not found: ".red + file_url
|
21
|
+
return false
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.open_volume(filename, volume_search, &block)
|
27
|
+
if File.exists?(filename)
|
28
|
+
result = %x[open #{filename}]
|
29
|
+
volume = find_mounted_volume volume_search
|
30
|
+
if volume.size == 0
|
31
|
+
puts "Could not find #{filename} volume".red
|
32
|
+
else
|
33
|
+
yield volume
|
34
|
+
end
|
35
|
+
else
|
36
|
+
puts "File hasn't been downloaded #{filename}".red
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def self.exists?
|
41
|
+
if File.exists?(filename)
|
42
|
+
return true
|
43
|
+
else
|
44
|
+
puts "File hasn't been downloaded #{filename}".red
|
45
|
+
return false
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def self.mount(filename, volume_search, &block)
|
50
|
+
if File.exists?(filename)
|
51
|
+
result = %x[open #{filename}]
|
52
|
+
volume = self.find_mounted_volume volume_search
|
53
|
+
if volume.size == 0
|
54
|
+
puts "Could not find #{filename} volume".red
|
55
|
+
else
|
56
|
+
yield volume
|
57
|
+
end
|
58
|
+
else
|
59
|
+
yield filename
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def self.find_mounted_volume search
|
64
|
+
not_found = true
|
65
|
+
retries = 0
|
66
|
+
while not_found && retries < 30
|
67
|
+
volumes = Dir.glob "/Volumes/#{search}"
|
68
|
+
if volumes.size == 0
|
69
|
+
retries += 1
|
70
|
+
sleep 2
|
71
|
+
elsif volumes.size > 1
|
72
|
+
puts "Too many similar disk images mounted, please unmount all but latest version".red
|
73
|
+
puts "Here are the mounted matching images:"
|
74
|
+
volumes.each do |volume|
|
75
|
+
puts volume
|
76
|
+
end
|
77
|
+
return ""
|
78
|
+
else
|
79
|
+
return volumes[0]
|
80
|
+
end
|
81
|
+
end
|
82
|
+
return ""
|
83
|
+
end
|
84
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
$CPAN::Config = {
|
2
|
+
'auto_commit' => q[0],
|
3
|
+
'build_cache' => q[100],
|
4
|
+
'build_dir' => q[<%= @cache_dir %>/.cpan/build],
|
5
|
+
'build_dir_reuse' => q[0],
|
6
|
+
'build_requires_install_policy' => q[yes],
|
7
|
+
'cache_metadata' => q[1],
|
8
|
+
'check_sigs' => q[0],
|
9
|
+
'commandnumber_in_prompt' => q[1],
|
10
|
+
'connect_to_internet_ok' => q[1],
|
11
|
+
'cpan_home' => q[<%= @cache_dir %>/.cpan],
|
12
|
+
'ftp_passive' => q[1],
|
13
|
+
'ftp_proxy' => q[],
|
14
|
+
'getcwd' => q[cwd],
|
15
|
+
'halt_on_failure' => q[0],
|
16
|
+
'http_proxy' => q[],
|
17
|
+
'inactivity_timeout' => q[0],
|
18
|
+
'index_expire' => q[1],
|
19
|
+
'inhibit_startup_message' => q[0],
|
20
|
+
'keep_source_where' => q[<%= @cache_dir %>/.cpan/sources],
|
21
|
+
'load_module_verbosity' => q[none],
|
22
|
+
'make_arg' => q[],
|
23
|
+
'make_install_arg' => q[],
|
24
|
+
'make_install_make_command' => q[],
|
25
|
+
'makepl_arg' => q[],
|
26
|
+
'mbuild_arg' => q[],
|
27
|
+
'mbuild_install_arg' => q[],
|
28
|
+
'mbuild_install_build_command' => q[./Build],
|
29
|
+
'mbuildpl_arg' => q[],
|
30
|
+
'no_proxy' => q[],
|
31
|
+
'pager' => q[/usr/bin/less],
|
32
|
+
'perl5lib_verbosity' => q[none],
|
33
|
+
'prefer_installer' => q[MB],
|
34
|
+
'prefs_dir' => q[<%= @cache_dir %>/.cpan/prefs],
|
35
|
+
'prerequisites_policy' => q[follow],
|
36
|
+
'scan_cache' => q[atstart],
|
37
|
+
'shell' => q[/bin/bash],
|
38
|
+
'show_upload_date' => q[0],
|
39
|
+
'tar_verbosity' => q[none],
|
40
|
+
'term_is_latin' => q[1],
|
41
|
+
'term_ornaments' => q[1],
|
42
|
+
'trust_test_report_history' => q[0],
|
43
|
+
'urllist' => [],
|
44
|
+
'use_sqlite' => q[0],
|
45
|
+
'version_timeout' => q[15],
|
46
|
+
'yaml_load_code' => q[0],
|
47
|
+
};
|
48
|
+
1;
|
49
|
+
__END__
|
@@ -0,0 +1,19 @@
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
2
|
+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
3
|
+
<plist version="1.0">
|
4
|
+
<dict>
|
5
|
+
<key>KeepAlive</key>
|
6
|
+
<true/>
|
7
|
+
<key>Label</key>
|
8
|
+
<string>MythBackend</string>
|
9
|
+
<key>ProgramArguments</key>
|
10
|
+
<array>
|
11
|
+
<string>/Applications/MythBackend.app/Contents/MacOS/MythBackend</string>
|
12
|
+
<string>--logpath</string>
|
13
|
+
<string>/var/log/mythtv</string>
|
14
|
+
</array>
|
15
|
+
<key>UserName</key>
|
16
|
+
<string><%= @username %></string>
|
17
|
+
</dict>
|
18
|
+
</plist>
|
19
|
+
|
data/sphinx_tv.gemspec
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
require File.expand_path('../lib/sphinx_tv/version', __FILE__)
|
3
|
+
|
4
|
+
Gem::Specification.new do |gem|
|
5
|
+
gem.authors = ["David Monagle"]
|
6
|
+
gem.email = ["david.monagle@intrica.com.au"]
|
7
|
+
gem.date = '2012-07-15'
|
8
|
+
gem.summary = "SphinxTV is an installer/configurator for MythTV (and others) for OSX"
|
9
|
+
gem.description = "SphinxTV is an installer/configurator for MythTV (and others) for OSX"
|
10
|
+
gem.homepage = ""
|
11
|
+
|
12
|
+
gem.files = `git ls-files`.split($\)
|
13
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
14
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
15
|
+
gem.name = "sphinx_tv"
|
16
|
+
gem.require_paths = ["lib"]
|
17
|
+
gem.version = SphinxTv::VERSION
|
18
|
+
gem.homepage =
|
19
|
+
'http://sphinxtv.intrica.com.au'
|
20
|
+
gem.add_dependency 'colorize'
|
21
|
+
gem.add_dependency 'highline'
|
22
|
+
gem.add_dependency 'nokogiri'
|
23
|
+
end
|
metadata
ADDED
@@ -0,0 +1,111 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: sphinx_tv
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.9.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- David Monagle
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-07-15 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: colorize
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '0'
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: highline
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ! '>='
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '0'
|
38
|
+
type: :runtime
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0'
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: nokogiri
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ! '>='
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '0'
|
54
|
+
type: :runtime
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ! '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
description: SphinxTV is an installer/configurator for MythTV (and others) for OSX
|
63
|
+
email:
|
64
|
+
- david.monagle@intrica.com.au
|
65
|
+
executables:
|
66
|
+
- sphinx_tv
|
67
|
+
extensions: []
|
68
|
+
extra_rdoc_files: []
|
69
|
+
files:
|
70
|
+
- .gitignore
|
71
|
+
- Gemfile
|
72
|
+
- MIT-LICENSE
|
73
|
+
- README.rdoc
|
74
|
+
- Rakefile
|
75
|
+
- bin/sphinx_tv
|
76
|
+
- lib/modules/mysql.rb
|
77
|
+
- lib/modules/mythtv.rb
|
78
|
+
- lib/modules/shepherd.rb
|
79
|
+
- lib/modules/sphinx_module.rb
|
80
|
+
- lib/sphinx_tv.rb
|
81
|
+
- lib/sphinx_tv/cpan.rb
|
82
|
+
- lib/sphinx_tv/download.rb
|
83
|
+
- lib/sphinx_tv/version.rb
|
84
|
+
- resources/MyConfig.pm.erb
|
85
|
+
- resources/MythTv/MythBackend.plist.erb
|
86
|
+
- sphinx_tv.gemspec
|
87
|
+
homepage: http://sphinxtv.intrica.com.au
|
88
|
+
licenses: []
|
89
|
+
post_install_message:
|
90
|
+
rdoc_options: []
|
91
|
+
require_paths:
|
92
|
+
- lib
|
93
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
94
|
+
none: false
|
95
|
+
requirements:
|
96
|
+
- - ! '>='
|
97
|
+
- !ruby/object:Gem::Version
|
98
|
+
version: '0'
|
99
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
100
|
+
none: false
|
101
|
+
requirements:
|
102
|
+
- - ! '>='
|
103
|
+
- !ruby/object:Gem::Version
|
104
|
+
version: '0'
|
105
|
+
requirements: []
|
106
|
+
rubyforge_project:
|
107
|
+
rubygems_version: 1.8.24
|
108
|
+
signing_key:
|
109
|
+
specification_version: 3
|
110
|
+
summary: SphinxTV is an installer/configurator for MythTV (and others) for OSX
|
111
|
+
test_files: []
|