rwdschedule 0.96 → 0.97
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/Readme.txt +5 -0
- data/bin/rwdschedule +18 -18
- data/code/dd0viewphoto/dd0viewphoto.rb +4 -0
- data/code/superant.com.rwdtinkerbackwindow/helptexthashtinkerwin2.rb +4 -1
- data/code/superant.com.rwdtinkerbackwindow/installapplet.rb +5 -3
- data/code/superant.com.rwdtinkerbackwindow/removeapplet.rb +10 -6
- data/code/superant.com.schedule/loadconfigurationrecord.rb +11 -0
- data/configuration/language.dist +7 -0
- data/configuration/rwdapplicationidentity.dist +3 -0
- data/configuration/rwdcalendar.dist +10 -0
- data/configuration/rwdschedule.dist +15 -0
- data/configuration/{rwdtinker.cnf → rwdtinker.dist} +3 -4
- data/configuration/{tinkerwin2variables.cnf → tinkerwin2variables.dist} +6 -1
- data/extras/cmdline_parse +47 -0
- data/extras/config_file +69 -0
- data/extras/errorMsg +19 -0
- data/extras/makePlaylist +34 -0
- data/extras/mp3controld +289 -0
- data/extras/playlist +186 -0
- data/extras/rconftool.rb +380 -0
- data/extras/showHelp +18 -0
- data/gui/tinkerbackwindows/superant.com.rwdschedulebackwindow/67viewconfiguration.rwd +11 -1
- data/init.rb +42 -37
- data/rwd_files/HowTo_Schedule.txt +5 -0
- data/rwd_files/HowTo_Tinker.txt +16 -0
- data/rwdconfig.dist +6 -0
- data/tests/checkdepends.sh +4 -0
- data/tests/cleancnf.sh +5 -0
- data/tests/makedist.rb +29 -0
- data/tests/rdep.rb +354 -0
- metadata +26 -23
- data/configuration/language.cnf +0 -5
- data/configuration/rwdapplicationidentity.cnf +0 -3
- data/configuration/rwdcalendar.cnf +0 -4
- data/configuration/rwdcalendarversion.cnf +0 -4
- data/configuration/rwdschedule.cnf +0 -7
- data/configuration/rwdscheduleversion.cnf +0 -3
- data/configuration/rwdtinkerversion.cnf +0 -2
- data/configuration/tinkerwin2version.cnf +0 -3
- data/lang/alanguagehashbegin.rb +0 -4
- data/lang/languagehash.rb +0 -4
- data/lang/templangfile.rb +0 -22
- data/lang/vlanguagehashend.rb +0 -6
- data/lang/wlocallangstart.rb +0 -5
- data/lang/xlocallangfile.rb +0 -22
- data/lang/zlocallangend.rb +0 -2
- data/rwdschedule-0.96.gem +0 -0
data/extras/playlist
ADDED
@@ -0,0 +1,186 @@
|
|
1
|
+
#!ruby
|
2
|
+
|
3
|
+
# --- Playlist class ---
|
4
|
+
#
|
5
|
+
# Author: Magnus Engstr�m
|
6
|
+
# Email: magnus@gisab.se
|
7
|
+
# File: playlist
|
8
|
+
#
|
9
|
+
# Description
|
10
|
+
# -----------
|
11
|
+
# The Playlist class handles everything a playlist should be able to manage.
|
12
|
+
# Shuffle it, unshuffle it, wrap it if desired, add new songs, find songs and
|
13
|
+
# so on. Cool huh? :)
|
14
|
+
# ----------------------
|
15
|
+
|
16
|
+
class Playlist
|
17
|
+
# create_from_file() creates a playlist from a file and returns either a Playlist instance or -1 in case of error
|
18
|
+
# This function should be used instead of the ::new, because this one
|
19
|
+
# returns -1 on file read errors, which the ::new doesn't.
|
20
|
+
def Playlist::create_from_file(filename)
|
21
|
+
# Check that the file is readable
|
22
|
+
if(FileTest::readable_real?(filename))
|
23
|
+
new(filename) # Return the Playlist class instance
|
24
|
+
else
|
25
|
+
-1 # Return -1 on error
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
# initialize reads the playlist from a file and returns the Playlist instance
|
30
|
+
def initialize(filename)
|
31
|
+
|
32
|
+
@filename = filename # Store the filename for later use
|
33
|
+
@playlist = Array::new() # This hash contains the whole playlist
|
34
|
+
@index = 0 # Playlist's current position
|
35
|
+
@wrap = false # Don't repeat the list as default
|
36
|
+
|
37
|
+
# Parse these fields, separated with double pipes (||) (songname, artist, album, year, comment, tracknum, genre_id, genre)
|
38
|
+
File::foreach(filename) { |line| # Iterate through every line in the file
|
39
|
+
foo = line.split(/\|\|/)
|
40
|
+
@playlist << { "filename" => foo[0], "songname" => foo[1], "artist" => foo[2], "album" => foo[3], "year" => foo[4], "comment" => foo[5], "tracknum" => foo[6], "genre_id" => foo[7], "genre" => foo[8] } # Add a hash to the @playlist array with all values found in the playlist file
|
41
|
+
}
|
42
|
+
|
43
|
+
end
|
44
|
+
|
45
|
+
def insert(song, placement = 0)
|
46
|
+
# Check song information
|
47
|
+
return -1 if(song.type != Hash)
|
48
|
+
song = { "filename" => song["filename"], "songname" => song["songname"], "artist" => song["artist"], "album" => song["album"], "year" => song["year"], "comment" => song["comment"], "tracknum" => song["tracknum"], "genre_id" => song["genre_id"], "genre" => song["genre"] }
|
49
|
+
|
50
|
+
# Check minimum and maximum values
|
51
|
+
placement = 0 if(placement < 0)
|
52
|
+
placement = @playlist.length() if(placement > @playlist.length() )
|
53
|
+
|
54
|
+
# Retrieve the two parts of the split playlist
|
55
|
+
first = @playlist[0...placement]
|
56
|
+
second = @playlist[placement...@playlist.length()]
|
57
|
+
|
58
|
+
# Put it together again
|
59
|
+
@playlist = Array::new()
|
60
|
+
@playlist = first
|
61
|
+
@playlist << song
|
62
|
+
@playlist.concat(second)
|
63
|
+
|
64
|
+
end
|
65
|
+
|
66
|
+
def remove(placement = 0)
|
67
|
+
# Check boundaries
|
68
|
+
placement = 0 if(placement < 0)
|
69
|
+
placement = @playlist.length()-1 if( placement >= @playlist.length() )
|
70
|
+
|
71
|
+
# Delete the item
|
72
|
+
@playlist.delete_at(placement)
|
73
|
+
end
|
74
|
+
|
75
|
+
def find(search_string, case_insensitive = false, fields = ["songname", "filename"])
|
76
|
+
case_insensitive = nil if(case_insensitive == false)
|
77
|
+
|
78
|
+
results = Array::new()
|
79
|
+
regex = Regexp::new(search_string, case_insensitive) # The regex that will be matched
|
80
|
+
|
81
|
+
# Iterate through the playlist to find one or more matching songs
|
82
|
+
@playlist.length().times { |index|
|
83
|
+
# Iterate through the user supplied list of fields to be searched
|
84
|
+
fields.each { |field|
|
85
|
+
# Make sure this is a hash, so we don't go and crash, or make someone's dog sick :)
|
86
|
+
if(@playlist[index].type == Hash)
|
87
|
+
results << index if( regex.match(@playlist[index][field]) && !(results.include?(index)) ) # If it matches, and if it doesn't already is in the results. We don't want duplicates :)
|
88
|
+
end
|
89
|
+
}
|
90
|
+
}
|
91
|
+
|
92
|
+
results # Return the results
|
93
|
+
|
94
|
+
end
|
95
|
+
|
96
|
+
def shuffle()
|
97
|
+
# Iterate through the playlist
|
98
|
+
( 0...@playlist.length() ).each { |i|
|
99
|
+
j = rand @playlist.length() # Grab a random value between 0 and @playlist.length()
|
100
|
+
|
101
|
+
# Maintain index
|
102
|
+
if(@index == j)
|
103
|
+
@index = i
|
104
|
+
elsif(@index == i)
|
105
|
+
@index = j
|
106
|
+
end
|
107
|
+
|
108
|
+
@playlist[i], @playlist[j] = @playlist[j], @playlist[i]
|
109
|
+
}
|
110
|
+
end
|
111
|
+
|
112
|
+
def re_read()
|
113
|
+
# Maintain index
|
114
|
+
current_filename = @playlist[@index]["filename"]
|
115
|
+
|
116
|
+
# Create a new playlist array
|
117
|
+
@playlist = Array::new()
|
118
|
+
@index = 0
|
119
|
+
foo_index = 0 # Just to keep the count while adding all songs to the @playlist
|
120
|
+
|
121
|
+
# Parse these fields, separated with double pipes (||) (songname, artist, album, year, comment, tracknum, genre_id, genre)
|
122
|
+
# Iterate through every line in the file
|
123
|
+
File::foreach(@filename) { |line|
|
124
|
+
foo = line.split(/\|\|/) # Separate the fields with double pipes (||)
|
125
|
+
@playlist << { "filename" => foo[0], "songname" => foo[1], "artist" => foo[2], "album" => foo[3], "year" => foo[4], "comment" => foo[5], "tracknum" => foo[6], "genre_id" => foo[7], "genre" => foo[8] } # Add a hash to the @playlist array with all values found in the playlist file
|
126
|
+
|
127
|
+
# Maintain index
|
128
|
+
@index = foo_index if(foo[0] == current_filename)
|
129
|
+
foo_index += 1
|
130
|
+
}
|
131
|
+
|
132
|
+
end
|
133
|
+
|
134
|
+
def next()
|
135
|
+
# Increase the counter and return -1 if the playlist went to far, and wrap isn't true
|
136
|
+
@index += 1
|
137
|
+
if( @index >= @playlist.length() )
|
138
|
+
if(@wrap)
|
139
|
+
@index = 0
|
140
|
+
else
|
141
|
+
@index -= 1
|
142
|
+
-1 # Return an error
|
143
|
+
end
|
144
|
+
else
|
145
|
+
@index
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
def prev()
|
150
|
+
# Decrease the counter and return -1 if the playlist went to far, and wrap isn't true
|
151
|
+
@index -= 1
|
152
|
+
if( @index < 0 )
|
153
|
+
if(@wrap)
|
154
|
+
@index = @playlist.length() -1
|
155
|
+
else
|
156
|
+
@index += 1
|
157
|
+
-1 # Return an error
|
158
|
+
end
|
159
|
+
else
|
160
|
+
@index
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
def song_info(index = @index)
|
165
|
+
@playlist[index]
|
166
|
+
end
|
167
|
+
|
168
|
+
def goto(index = 0)
|
169
|
+
if( index >= 0 && index < @playlist.length() )
|
170
|
+
@index = index
|
171
|
+
else
|
172
|
+
return -1
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
def length()
|
177
|
+
@playlist.length()
|
178
|
+
end
|
179
|
+
|
180
|
+
def each()
|
181
|
+
@playlist.each { |song| yield(song) }
|
182
|
+
end
|
183
|
+
|
184
|
+
attr_reader :wrap, :index, :filename
|
185
|
+
attr_writer :wrap
|
186
|
+
end
|
data/extras/rconftool.rb
ADDED
@@ -0,0 +1,380 @@
|
|
1
|
+
#!/usr/local/bin/ruby -w
|
2
|
+
|
3
|
+
# Copyright (c) 2005 Brian Candler
|
4
|
+
#
|
5
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
# of this software and associated documentation files (the "Software"), to
|
7
|
+
# deal in the Software without restriction, including without limitation the
|
8
|
+
# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
9
|
+
# sell copies of the Software, and to permit persons to whom the Software is
|
10
|
+
# furnished to do so, subject to the following conditions:
|
11
|
+
#
|
12
|
+
# The above copyright notice and this permission notice shall be included in
|
13
|
+
# all copies or substantial portions of the Software.
|
14
|
+
#
|
15
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
20
|
+
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
21
|
+
# IN THE SOFTWARE.
|
22
|
+
|
23
|
+
##########################################################################
|
24
|
+
# rconftool is a reimplementation of Sam Varshavchik's sysconftool in Ruby.
|
25
|
+
# See http://www.courier-mta.org/sysconftool/ for details of the original.
|
26
|
+
# Its purpose is to keep configuration files "fresh" when upgrading an
|
27
|
+
# application from one version to another, ensuring that all necessary
|
28
|
+
# settings are present and obsolete ones removed.
|
29
|
+
#
|
30
|
+
# rconftool can be called as a library function or from the command line. It
|
31
|
+
# can also install groups of files recursively from one directory tree into
|
32
|
+
# another.
|
33
|
+
##########################################################################
|
34
|
+
|
35
|
+
require 'fileutils'
|
36
|
+
|
37
|
+
module Rconftool
|
38
|
+
VERSION = "0.1"
|
39
|
+
class NoVersionLine < RuntimeError; end
|
40
|
+
|
41
|
+
# This module function installs a single source (.dist) file to a target
|
42
|
+
# location, having first merged in any compatible settings from the
|
43
|
+
# target file if it existed previously [if it does not exist, any settings
|
44
|
+
# from 'oldfile' are used instead]
|
45
|
+
#
|
46
|
+
# If the distfile is not in sysconftool format (i.e. doesn't have a
|
47
|
+
# ##VERSION: header within the first 20 lines), then for safety it is only
|
48
|
+
# installed if the target file does not already exist. No attempt at data
|
49
|
+
# merging is made in that case.
|
50
|
+
|
51
|
+
def self.install(distfile, targetfile=nil, oldfile=nil, opt={})
|
52
|
+
debug = opt[:debug] || $stdout
|
53
|
+
|
54
|
+
targetfile ||= distfile
|
55
|
+
if opt[:strip_regexp]
|
56
|
+
targetfile = targetfile.sub(opt[:strip_regexp], '')
|
57
|
+
oldfile = oldfile.sub(opt[:strip_regexp], '') if oldfile
|
58
|
+
end
|
59
|
+
if opt[:add_suffix]
|
60
|
+
targetfile = targetfile + opt[:add_suffix]
|
61
|
+
oldfile = oldfile + opt[:add_suffix] if oldfile
|
62
|
+
end
|
63
|
+
raise Errno::EEXIST, "#{distfile}: dist and target filenames are the same" if distfile == targetfile
|
64
|
+
|
65
|
+
# Read in the source (.dist) file
|
66
|
+
begin
|
67
|
+
src = ConfigFile.new(distfile)
|
68
|
+
rescue NoVersionLine
|
69
|
+
# Fallback behaviour when installing a file which is not in sysconftool
|
70
|
+
# format: we install the file only if it doesn't already exist
|
71
|
+
if File.exist?(targetfile)
|
72
|
+
debug << "#{targetfile}: already exists, skipping\n"
|
73
|
+
return
|
74
|
+
end
|
75
|
+
return if opt[:noclobber]
|
76
|
+
copyfrom = (oldfile and File.exist?(oldfile)) ? oldfile : distfile
|
77
|
+
if File.symlink?(copyfrom)
|
78
|
+
File.symlink(File.readlink(copyfrom), targetfile)
|
79
|
+
debug << "#{targetfile}: symlink copied from #{copyfrom}\n"
|
80
|
+
else
|
81
|
+
FileUtils.cp copyfrom, targetfile, :preserve=>true
|
82
|
+
debug << "#{targetfile}: copied from #{copyfrom}\n"
|
83
|
+
end
|
84
|
+
return
|
85
|
+
end
|
86
|
+
|
87
|
+
# OK, so we have a sysconftool file to install. Read in the existing
|
88
|
+
# target file, or if that does not exist, the oldfile
|
89
|
+
begin
|
90
|
+
old = ConfigFile.new
|
91
|
+
old.read(targetfile)
|
92
|
+
rescue NoVersionLine
|
93
|
+
# That's OK; the old target will be renamed to .bak
|
94
|
+
rescue Errno::ENOENT
|
95
|
+
begin
|
96
|
+
target_missing = true
|
97
|
+
old.read(oldfile) if oldfile
|
98
|
+
rescue Errno::ENOENT, NoVersionLine
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
# Same VERSION? No merge is required
|
103
|
+
if src.version == old.version and not opt[:force]
|
104
|
+
if target_missing
|
105
|
+
FileUtils.cp oldfile, targetfile, :preserve=>true
|
106
|
+
debug << "#{targetfile}: same VERSION, copied from #{oldfile}\n"
|
107
|
+
return
|
108
|
+
end
|
109
|
+
debug << "#{targetfile}: same VERSION, no change\n"
|
110
|
+
return
|
111
|
+
end
|
112
|
+
|
113
|
+
# Merge in old settings (note: any settings which are in targetfile but
|
114
|
+
# not in distfile will be silently dropped)
|
115
|
+
debug << "#{targetfile}:\n"
|
116
|
+
src.settings[1..-1].each do |src_setting|
|
117
|
+
name = src_setting.name
|
118
|
+
old_setting = old[name]
|
119
|
+
unless old_setting
|
120
|
+
debug << " #{name}: new\n"
|
121
|
+
next
|
122
|
+
end
|
123
|
+
if old_setting.version == src_setting.version
|
124
|
+
debug << " #{name}: unchanged\n"
|
125
|
+
src_setting.add_comment("\n DEFAULT SETTING from #{distfile}:\n")
|
126
|
+
src_setting.add_comment(src_setting.content)
|
127
|
+
src_setting.content = old_setting.content
|
128
|
+
next
|
129
|
+
end
|
130
|
+
# Otherwise, must install updated setting and comment out
|
131
|
+
# the current setting for reference
|
132
|
+
debug << " #{name}: UPDATED\n"
|
133
|
+
src_setting.add_comment("\n Previous setting (inserted by rconftool):\n\n")
|
134
|
+
src_setting.add_comment(old_setting.content)
|
135
|
+
end
|
136
|
+
|
137
|
+
return if opt[:noclobber]
|
138
|
+
|
139
|
+
# Write out the new file and carry forward permissions
|
140
|
+
begin
|
141
|
+
tempfile = targetfile+".new#{$$}"
|
142
|
+
src.write(tempfile)
|
143
|
+
st = File.stat(distfile)
|
144
|
+
begin
|
145
|
+
File.chown(st.uid, st.gid, tempfile)
|
146
|
+
rescue Errno::EPERM
|
147
|
+
end
|
148
|
+
File.chmod(st.mode, tempfile)
|
149
|
+
File.rename(targetfile, targetfile+".bak") unless target_missing
|
150
|
+
File.rename(tempfile, targetfile)
|
151
|
+
rescue
|
152
|
+
File.delete(tempfile) rescue nil
|
153
|
+
raise
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
HEADER_ID = '__header__'
|
158
|
+
|
159
|
+
# Object to represent a single setting
|
160
|
+
|
161
|
+
class Setting
|
162
|
+
attr_reader :name, :version
|
163
|
+
attr_accessor :content
|
164
|
+
|
165
|
+
def initialize(name, version)
|
166
|
+
@name = name.gsub(/\s+/,'')
|
167
|
+
@version = version.gsub(/s+/,'')
|
168
|
+
@comment = ""
|
169
|
+
@content = ""
|
170
|
+
@in_content = false
|
171
|
+
end
|
172
|
+
def <<(str)
|
173
|
+
@in_content = true unless /\A#/ =~ str
|
174
|
+
if @in_content
|
175
|
+
@content << str
|
176
|
+
else
|
177
|
+
@comment << str
|
178
|
+
end
|
179
|
+
end
|
180
|
+
# Add text to 'comment' portion of setting, prefixing each line with '#'
|
181
|
+
def add_comment(str)
|
182
|
+
@comment << str.gsub(/^/,'#')
|
183
|
+
end
|
184
|
+
def to_s
|
185
|
+
return "#{@comment}#{@content}" if @name == HEADER_ID
|
186
|
+
return "##NAME: #{@name}:#{@version}\n#{@comment}#{@content}"
|
187
|
+
end
|
188
|
+
end # class Setting
|
189
|
+
|
190
|
+
# Object to represent an entire configuration file. It consists of
|
191
|
+
# an array of Setting objects, with the first one having a special name
|
192
|
+
# (__header__). We also keep a hash of setting name => setting object
|
193
|
+
# to enable us to find a particular setting quickly.
|
194
|
+
|
195
|
+
class ConfigFile
|
196
|
+
attr_reader :version, :settings
|
197
|
+
|
198
|
+
def initialize(filename=nil)
|
199
|
+
read(filename) if filename
|
200
|
+
end
|
201
|
+
|
202
|
+
# fetch a setting by name
|
203
|
+
def [](item)
|
204
|
+
@settings_hash[item]
|
205
|
+
end
|
206
|
+
|
207
|
+
def read(filename)
|
208
|
+
@version = nil
|
209
|
+
curr_setting = Setting.new(HEADER_ID,'')
|
210
|
+
@settings = [curr_setting]
|
211
|
+
@settings_hash = {}
|
212
|
+
|
213
|
+
File.open(filename) do |f|
|
214
|
+
# VERSION header must occur within first 20 lines
|
215
|
+
20.times do
|
216
|
+
line = f.gets
|
217
|
+
break unless line
|
218
|
+
curr_setting << line
|
219
|
+
if line =~ /\A##VERSION:/
|
220
|
+
@version = line
|
221
|
+
break
|
222
|
+
end
|
223
|
+
end
|
224
|
+
raise NoVersionLine, "#{filename}: No VERSION line found" unless @version
|
225
|
+
|
226
|
+
while line = f.gets
|
227
|
+
unless line =~ /\A##NAME:(.*):(.*)/
|
228
|
+
curr_setting << line
|
229
|
+
next
|
230
|
+
end
|
231
|
+
curr_setting = Setting.new($1,$2)
|
232
|
+
@settings << curr_setting
|
233
|
+
@settings_hash[curr_setting.name] = curr_setting
|
234
|
+
end
|
235
|
+
end
|
236
|
+
end
|
237
|
+
|
238
|
+
def write(filename)
|
239
|
+
File.open(filename,"w") do |f|
|
240
|
+
@settings.each do |s|
|
241
|
+
f << s.to_s
|
242
|
+
end
|
243
|
+
end
|
244
|
+
end
|
245
|
+
end # class ConfigFile
|
246
|
+
|
247
|
+
# Yield directory contents recursively, without doing chdir(). Note
|
248
|
+
# that yielded pathnames are relative to the base directory given;
|
249
|
+
# so that, for example, you can simulate 'cp -r /foo/bar/ /baz/' by
|
250
|
+
# recurse_dir("/foo/bar") { |n| copy("/foo/bar/"+n,"/baz/"+n) unless
|
251
|
+
# File.directory?("/foo/bar/"+n) }
|
252
|
+
# Current behaviour is that if a directory is a symlink, we follow it.
|
253
|
+
# (Perhaps the block we yield should return true/false?)
|
254
|
+
|
255
|
+
def self.recurse_dir(base)
|
256
|
+
base = base+File::SEPARATOR unless base[-1,1] == File::SEPARATOR
|
257
|
+
dirs = ['']
|
258
|
+
while dir = dirs.pop
|
259
|
+
yield dir unless dir == ''
|
260
|
+
Dir.foreach(base+dir) do |n|
|
261
|
+
next if n == '.' || n == '..'
|
262
|
+
target = dir + n
|
263
|
+
if File.directory?(base+target)
|
264
|
+
dirs << target+File::SEPARATOR
|
265
|
+
next
|
266
|
+
end
|
267
|
+
yield target
|
268
|
+
end
|
269
|
+
end
|
270
|
+
end
|
271
|
+
|
272
|
+
class Processor
|
273
|
+
attr_reader :o
|
274
|
+
|
275
|
+
# Parse command-line options and set the @o options hash
|
276
|
+
|
277
|
+
def initialize(argv=nil)
|
278
|
+
require 'optparse'
|
279
|
+
|
280
|
+
@o = { :strip_regexp => /\.dist\z/ }
|
281
|
+
return unless argv
|
282
|
+
opts = OptionParser.new do |opts|
|
283
|
+
opts.banner = "rconftool version #{VERSION}"
|
284
|
+
opts.separator "Usage: #{$0} [options]"
|
285
|
+
opts.separator ""
|
286
|
+
opts.separator "Specific options:"
|
287
|
+
|
288
|
+
opts.on("-n", "--noclobber", "Dummy run") do
|
289
|
+
@o[:noclobber] = true
|
290
|
+
end
|
291
|
+
opts.on("-f", "--force", "Update files even if VERSION is same") do
|
292
|
+
@o[:force] = true
|
293
|
+
end
|
294
|
+
opts.on("-q", "--quiet", "No progress reporting") do
|
295
|
+
@o[:debug] = ""
|
296
|
+
end
|
297
|
+
opts.on("--targetdir DIR", "Where to write merged config files") do |dir|
|
298
|
+
@o[:targetdir] = dir
|
299
|
+
end
|
300
|
+
opts.on("--olddir DIR", "If file does not exist in targetdir,",
|
301
|
+
"try to merge from here") do |dir|
|
302
|
+
@o[:olddir] = dir
|
303
|
+
end
|
304
|
+
opts.on("--[no-]recursive", "Traverse directories recursively") do |v|
|
305
|
+
@o[:recursive] = v
|
306
|
+
end
|
307
|
+
opts.on("--strip-suffix FOO", "Remove suffix FOO from target filenames",
|
308
|
+
"(default .dist)") do |suffix|
|
309
|
+
@o[:strip_regexp] = /#{Regexp.escape(suffix)}\z/
|
310
|
+
end
|
311
|
+
opts.on("-a", "--add-suffix FOO", "Add suffix FOO to target filenames") do |suffix|
|
312
|
+
@o[:add_suffix] = suffix
|
313
|
+
end
|
314
|
+
|
315
|
+
opts.on_tail("-?", "--help", "Show this message") do
|
316
|
+
puts opts
|
317
|
+
exit
|
318
|
+
end
|
319
|
+
end
|
320
|
+
opts.parse!(argv)
|
321
|
+
end
|
322
|
+
|
323
|
+
# Process a list of files, [src1,src2,...]. If recursive mode has been
|
324
|
+
# enabled, then subdirectories of destdir are created as necessary
|
325
|
+
# when 'src' is a directory, and the mode/ownership of these newly
|
326
|
+
# created directories is copied from the original.
|
327
|
+
|
328
|
+
def run(files)
|
329
|
+
done_work = false
|
330
|
+
files.each do |f|
|
331
|
+
if not File.directory?(f)
|
332
|
+
dst = old = nil
|
333
|
+
dst = @o[:targetdir] + File::SEPARATOR + File.basename(f) if @o[:targetdir]
|
334
|
+
old = @o[:olddir] + File::SEPARATOR + File.basename(f) if @o[:olddir]
|
335
|
+
Rconftool::install(f, dst, old, @o)
|
336
|
+
elsif not @o[:recursive]
|
337
|
+
raise Errno::EISDIR, "#{f} (not copied). Need --recursive?"
|
338
|
+
else
|
339
|
+
Rconftool::recurse_dir(f) do |nf|
|
340
|
+
src = f + File::SEPARATOR + nf
|
341
|
+
dst = old = nil
|
342
|
+
dst = @o[:targetdir] + File::SEPARATOR + nf if @o[:targetdir]
|
343
|
+
old = @o[:olddir] + File::SEPARATOR + nf if @o[:olddir]
|
344
|
+
if File.directory?(src)
|
345
|
+
if dst and not File.directory?(dst)
|
346
|
+
orig = File.stat(src)
|
347
|
+
Dir.mkdir(dst, orig.mode)
|
348
|
+
begin
|
349
|
+
File.chown(orig.uid, orig.gid, dst)
|
350
|
+
rescue Errno::EPERM
|
351
|
+
end
|
352
|
+
end
|
353
|
+
else
|
354
|
+
Rconftool::install(src, dst, old, @o)
|
355
|
+
end
|
356
|
+
end
|
357
|
+
end
|
358
|
+
done_work = true
|
359
|
+
end
|
360
|
+
unless done_work
|
361
|
+
$stderr.puts "Usage: #{$0} [options] src1 src2 ...\n"+
|
362
|
+
"Try #{$0} --help for more information\n"
|
363
|
+
exit 1
|
364
|
+
end
|
365
|
+
end
|
366
|
+
end # class Processor
|
367
|
+
|
368
|
+
end # module Rconftool
|
369
|
+
|
370
|
+
# Run from command line?
|
371
|
+
if __FILE__ == $0
|
372
|
+
|
373
|
+
begin
|
374
|
+
s = Rconftool::Processor.new(ARGV)
|
375
|
+
s.run(ARGV)
|
376
|
+
rescue Exception => e
|
377
|
+
$stderr.puts "#{$0}: #{e}"
|
378
|
+
end
|
379
|
+
|
380
|
+
end
|
data/extras/showHelp
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
|
3
|
+
# --- showHelp ----
|
4
|
+
#
|
5
|
+
# Author: Magnus Engstr�m
|
6
|
+
# Email: magnus@gisab.se
|
7
|
+
# File: showHelp
|
8
|
+
#
|
9
|
+
# Description
|
10
|
+
# -----------
|
11
|
+
# This function
|
12
|
+
# print the help
|
13
|
+
# message on STDOUT
|
14
|
+
# -----------------
|
15
|
+
|
16
|
+
def showHelp()
|
17
|
+
STDOUT.puts("MaGnuX Mp3 Management server - Ruby Edition v0.2a\n-------------------------------------------------\n\n--help\t\t\tShow this message\n--debug on\t\tShow some debug data\n--configfile file\tSelect configuration file\n--daemon, -D (yes*|no)\tGo to background on startup\n\n")
|
18
|
+
end
|
@@ -26,7 +26,17 @@ $rwdguivar=
|
|
26
26
|
<row> <p align=\"right\">7:</p> <text size=70 name=\"a_schconfigline7\"/> </row>
|
27
27
|
<row> <p align=\"right\">8:</p> <text size=70 name=\"a_schconfigline8\"/> </row>
|
28
28
|
<row> <p align=\"right\">9:</p> <text size=70 name=\"a_schconfigline9\"/> </row>
|
29
|
-
|
29
|
+
<row> <p align=\"right\">10:</p> <text size=70 name=\"a_schconfigline10\"/> </row>
|
30
|
+
<row> <p align=\"right\">11:</p> <text size=70 name=\"a_schconfigline11\"/> </row>
|
31
|
+
|
32
|
+
<row> <p align=\"right\">12:</p> <text size=70 name=\"a_schconfigline12\"/> </row>
|
33
|
+
<row> <p align=\"right\">13:</p> <text size=70 name=\"a_schconfigline13\"/> </row>
|
34
|
+
<row> <p align=\"right\">14:</p> <text size=70 name=\"a_schconfigline14\"/> </row>
|
35
|
+
<row> <p align=\"right\">15:</p> <text size=70 name=\"a_schconfigline15\"/> </row>
|
36
|
+
<row> <p align=\"right\">16:</p> <text size=70 name=\"a_schconfigline16\"/> </row>
|
37
|
+
<row> <p align=\"right\">17:</p> <text size=70 name=\"a_schconfigline17\"/> </row>
|
38
|
+
<row> <p align=\"right\">18:</p> <text size=70 name=\"a_schconfigline18\"/> </row>
|
39
|
+
|
30
40
|
</table>
|
31
41
|
<p>%extraschconfigdatadisplay%</p>
|
32
42
|
<p>
|