rwdeliza 0.03
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/ElizaData/database/db.1 +7015 -0
- data/ElizaData/database/db.10 +7001 -0
- data/ElizaData/database/db.11 +7001 -0
- data/ElizaData/database/db.12 +7003 -0
- data/ElizaData/database/db.13 +7003 -0
- data/ElizaData/database/db.14 +7008 -0
- data/ElizaData/database/db.15 +7001 -0
- data/ElizaData/database/db.16 +7001 -0
- data/ElizaData/database/db.17 +7001 -0
- data/ElizaData/database/db.18 +7001 -0
- data/ElizaData/database/db.19 +7001 -0
- data/ElizaData/database/db.2 +7001 -0
- data/ElizaData/database/db.20 +5467 -0
- data/ElizaData/database/db.3 +7001 -0
- data/ElizaData/database/db.4 +7001 -0
- data/ElizaData/database/db.5 +7001 -0
- data/ElizaData/database/db.6 +7001 -0
- data/ElizaData/database/db.7 +7001 -0
- data/ElizaData/database/db.8 +7001 -0
- data/ElizaData/database/db.9 +7001 -0
- data/ElizaData/responses/hello.res +1 -0
- data/ElizaData/responses/i_agree.res +1 -0
- data/ElizaData/responses/i_am_listening_to_you.res +1 -0
- data/ElizaData/responses/please_explain.res +1 -0
- data/ElizaData/responses/thank_you.res +1 -0
- data/ElizaData/tiny.dict +211 -0
- data/ElizaData/words/adjectives1.words +906 -0
- data/ElizaData/words/adjectives2w.words +1 -0
- data/ElizaData/words/noun0.words +15 -0
- data/ElizaData/words/noun1.words +1391 -0
- data/ElizaData/words/noun2.words +1924 -0
- data/ElizaData/words/noun4.words +330 -0
- data/ElizaData/words/pronoun1.words +6 -0
- data/ElizaData/words/verb4.words +350 -0
- data/ElizaData/words/verb42.words +391 -0
- data/ElizaData/words/verb42w.words +1 -0
- data/ElizaData/words/verb43.words +402 -0
- data/ElizaData/words/verb43w.words +1 -0
- data/ElizaData/words/verb45.words +452 -0
- data/ElizaData/words/verb4w.words +1 -0
- data/ElizaData/words/verb5.words +13 -0
- data/ElizaData/words/verb61.words +35 -0
- data/ElizaData/words/verb62.words +41 -0
- data/ElizaData/words/verb83.words +17 -0
- data/Readme.txt +462 -0
- data/bin/rwdeliza +19 -0
- data/code/01rwdcore/01rwdcore.rb +29 -0
- data/code/01rwdcore/02helptexthashbegin.rb +4 -0
- data/code/01rwdcore/03helptexthash.rb +23 -0
- data/code/01rwdcore/04helptextend.rb +6 -0
- data/code/01rwdcore/jumplinkcommand.rb +26 -0
- data/code/01rwdcore/openhelpwindow.rb +31 -0
- data/code/01rwdcore/returntomain.rb +10 -0
- data/code/01rwdcore/rundocuments.rb +10 -0
- data/code/01rwdcore/runeditconfiguration.rb +10 -0
- data/code/01rwdcore/runhelpabout.rb +10 -0
- data/code/01rwdcore/runopentinkerdocument.rb +7 -0
- data/code/01rwdcore/rwdtinkerversion.rb +22 -0
- data/code/01rwdcore/rwdwindowreturn.rb +9 -0
- data/code/01rwdcore/selectiontab.rb +9 -0
- data/code/01rwdcore/setuphelpaboutoptions.rb +13 -0
- data/code/01rwdcore/setuptinkerdocuments.rb +6 -0
- data/code/01rwdcore/test_cases.rb +109 -0
- data/code/01rwdcore/test_harness.rb +13 -0
- data/code/01rwdcore/uploadreturns.rb +62 -0
- data/code/dd0viewphoto/dd0viewphoto.rb +3 -0
- data/code/superant.com.rwdeliza/0uninstallapplet.rb +10 -0
- data/code/superant.com.rwdeliza/eliza01.rb +45 -0
- data/code/superant.com.rwdeliza/helptexthashrwdeliza.rb +39 -0
- data/code/superant.com.rwdeliza/openhelpwindowrwdeliza.rb +23 -0
- data/code/superant.com.rwdeliza/runrwdshellwindow.rb +12 -0
- data/code/superant.com.rwdeliza/rwdtinkerversion.rb +10 -0
- data/code/superant.com.rwdeliza/tagsentence.rb +39 -0
- data/code/superant.com.rwdtinkerbackwindow/diagnostictab.rb +19 -0
- data/code/superant.com.rwdtinkerbackwindow/helptexthashtinkerwin2.rb +61 -0
- data/code/superant.com.rwdtinkerbackwindow/initiateapplets.rb +240 -0
- data/code/superant.com.rwdtinkerbackwindow/installgemapplet.rb +34 -0
- data/code/superant.com.rwdtinkerbackwindow/installremotegem.rb +20 -0
- data/code/superant.com.rwdtinkerbackwindow/listgemdirs.rb +12 -0
- data/code/superant.com.rwdtinkerbackwindow/listgemzips.rb +53 -0
- data/code/superant.com.rwdtinkerbackwindow/listinstalledfiles.rb +12 -0
- data/code/superant.com.rwdtinkerbackwindow/listzips.rb +27 -0
- data/code/superant.com.rwdtinkerbackwindow/loadconfigurationrecord.rb +22 -0
- data/code/superant.com.rwdtinkerbackwindow/loadconfigurationvariables.rb +14 -0
- data/code/superant.com.rwdtinkerbackwindow/network.rb +87 -0
- data/code/superant.com.rwdtinkerbackwindow/openappletname.rb +19 -0
- data/code/superant.com.rwdtinkerbackwindow/openhelpwindowtinkerwin2.rb +38 -0
- data/code/superant.com.rwdtinkerbackwindow/remotegemlist.rb +24 -0
- data/code/superant.com.rwdtinkerbackwindow/removeapplet.rb +46 -0
- data/code/superant.com.rwdtinkerbackwindow/removeappletvariables.rb +52 -0
- data/code/superant.com.rwdtinkerbackwindow/runremoteinstall.rb +11 -0
- data/code/superant.com.rwdtinkerbackwindow/runrwdtinkerbackwindow.rb +15 -0
- data/code/superant.com.rwdtinkerbackwindow/rwdtinkerwin2version.rb +13 -0
- data/code/superant.com.rwdtinkerbackwindow/saveconfigurationrecord.rb +19 -0
- data/code/superant.com.rwdtinkerbackwindow/viewappletcontents.rb +22 -0
- data/code/superant.com.rwdtinkerbackwindow/viewgemappletcontents.rb +24 -0
- data/code/superant.com.words/dictlookup.rb +20 -0
- data/code/superant.com.words/runfortunewindow.rb +14 -0
- data/code/superant.com.words/runrwdwordsbackwindow.rb +10 -0
- data/code/superant.com.words/runrwdwordsversion.rb +14 -0
- data/code/superant.com.words/rwdtinkerversion.rb +10 -0
- data/code/zz0applicationend/zz0end.rb +4 -0
- data/configuration/language.dist +8 -0
- data/configuration/rwdapplicationidentity.dist +3 -0
- data/configuration/rwdtinker.dist +18 -0
- data/configuration/rwdweliza-0.03.dist +31 -0
- data/configuration/tinkerwin2variables.dist +17 -0
- data/gui/00coreguibegin/applicationguitop.rwd +4 -0
- data/gui/frontwindow0/cc0openphoto.rwd +22 -0
- data/gui/frontwindowselections/00selectiontabbegin.rwd +11 -0
- data/gui/frontwindowselections/jumplinkcommands.rwd +15 -0
- data/gui/frontwindowselections/wwselectionend.rwd +3 -0
- data/gui/frontwindowtdocuments/00documentbegin.rwd +6 -0
- data/gui/frontwindowtdocuments/tinkerdocuments.rwd +14 -0
- data/gui/frontwindowtdocuments/zzdocumentend.rwd +8 -0
- data/gui/helpaboutbegin/zzzrwdlasttab.rwd +6 -0
- data/gui/helpaboutbegin/zzzzhelpscreenstart.rwd +3 -0
- data/gui/helpaboutbegin/zzzzzzhelpabouttab.rwd +15 -0
- data/gui/helpaboutzend/helpscreenend.rwd +3 -0
- data/gui/helpaboutzend/zhelpscreenstart2.rwd +3 -0
- data/gui/helpaboutzend/zzzzhelpabout2.rwd +15 -0
- data/gui/helpaboutzend/zzzzhelpscreen2end.rwd +3 -0
- data/gui/tinkerbackwindows/superant.com.refreshwindow/fortunerefreshwindowtwo.rwd +9 -0
- data/gui/tinkerbackwindows/superant.com.rwdeliza/1appname.rwd +5 -0
- data/gui/tinkerbackwindows/superant.com.rwdeliza/1eliza.rwd +21 -0
- data/gui/tinkerbackwindows/superant.com.rwdeliza/4sentance.rwd +21 -0
- data/gui/tinkerbackwindows/superant.com.rwdeliza/98jumplinkcommands.rwd +17 -0
- data/gui/tinkerbackwindows/superant.com.rwdeliza/zbackend.rwd +6 -0
- data/gui/tinkerbackwindows/superant.com.rwdschedulebackwindow/1appname.rwd +5 -0
- data/gui/tinkerbackwindows/superant.com.rwdschedulebackwindow/20downloadftp.rwd +45 -0
- data/gui/tinkerbackwindows/superant.com.rwdschedulebackwindow/67viewconfiguration.rwd +29 -0
- data/gui/tinkerbackwindows/superant.com.rwdschedulebackwindow/70rwddiagnostics.rwd +16 -0
- data/gui/tinkerbackwindows/superant.com.rwdschedulebackwindow/m01menubegin.rwd +18 -0
- data/gui/tinkerbackwindows/superant.com.rwdschedulebackwindow/zvbackend.rwd +6 -0
- data/gui/tinkerbackwindows/superant.com.tinkerbackwindow/1appname.rwd +5 -0
- data/gui/tinkerbackwindows/superant.com.tinkerbackwindow/40rwdlistzips.rwd +41 -0
- data/gui/tinkerbackwindows/superant.com.tinkerbackwindow/45installremotezip.rwd +44 -0
- data/gui/tinkerbackwindows/superant.com.tinkerbackwindow/50rwdlistapplets.rwd +44 -0
- data/gui/tinkerbackwindows/superant.com.tinkerbackwindow/60editconfiguration.rwd +30 -0
- data/gui/tinkerbackwindows/superant.com.tinkerbackwindow/70rwddiagnostics.rwd +29 -0
- data/gui/tinkerbackwindows/superant.com.tinkerbackwindow/81jumplinkcommands.rwd +17 -0
- data/gui/tinkerbackwindows/superant.com.tinkerbackwindow/9backend.rwd +6 -0
- data/gui/tinkerbackwindows/superant.com.tinkerhelpwindow/1appname.rwd +31 -0
- data/gui/tinkerbackwindows/superant.com.tinkerhelpwindow/9end.rwd +4 -0
- data/gui/tinkerbackwindows/superant.com.versionwindow/1appname.rwd +19 -0
- data/gui/tinkerbackwindows/superant.com.versionwindow/helpaboutwindow.rwd +17 -0
- data/gui/tinkerbackwindows/superant.com.words/1appname.rwd +4 -0
- data/gui/tinkerbackwindows/superant.com.words/1dictionary.rwd +19 -0
- data/gui/tinkerbackwindows/superant.com.words/3rwdfortune.rwd +14 -0
- data/gui/tinkerbackwindows/superant.com.words/77jumplinkcommands.rwd +17 -0
- data/gui/tinkerbackwindows/superant.com.words/z9end.rwd +6 -0
- data/gui/zzcoreguiend/yy9rwdend.rwd +4 -0
- data/init.rb +277 -0
- data/installed/rwdweliza-0.03.inf +24 -0
- data/installed/temp.rb +1 -0
- data/lang/en/rwdcore/languagefile.rb +58 -0
- data/lang/es/rwdcore/languagefile-es.rb +62 -0
- data/lang/fr/rwdcore/languagefile.rb +64 -0
- data/lang/jp/rwdcore/languagefile.rb +72 -0
- data/lang/nl/rwdcore/languagefile.rb +75 -0
- data/lib/dict.rb +438 -0
- data/lib/druida.rb +499 -0
- data/lib/hashslice.rb +71 -0
- data/lib/linguistics.rb +360 -0
- data/lib/linguistics/en.rb +1601 -0
- data/lib/linguistics/en/infinitive.rb +1148 -0
- data/lib/linguistics/en/linkparser.rb +142 -0
- data/lib/linguistics/en/wordnet.rb +253 -0
- data/lib/linguistics/iso639.rb +456 -0
- data/lib/linkparser.rb +461 -0
- data/lib/linkparser/connection.rb +81 -0
- data/lib/linkparser/connector.rb +201 -0
- data/lib/linkparser/definition.rb +225 -0
- data/lib/linkparser/dictionary.rb +208 -0
- data/lib/linkparser/linkage.rb +185 -0
- data/lib/linkparser/log.rb +39 -0
- data/lib/linkparser/sentence.rb +79 -0
- data/lib/linkparser/utils.rb +540 -0
- data/lib/linkparser/word.rb +92 -0
- data/lib/rconftool.rb +380 -0
- data/lib/rwd/browser.rb +123 -0
- data/lib/rwd/ftools.rb +174 -0
- data/lib/rwd/mime.rb +328 -0
- data/lib/rwd/net.rb +866 -0
- data/lib/rwd/ruby.rb +889 -0
- data/lib/rwd/rwd.rb +1942 -0
- data/lib/rwd/sgml.rb +236 -0
- data/lib/rwd/thread.rb +63 -0
- data/lib/rwd/tree.rb +371 -0
- data/lib/rwd/xml.rb +101 -0
- data/lib/zip/ioextras.rb +114 -0
- data/lib/zip/stdrubyext.rb +111 -0
- data/lib/zip/tempfile_bugfixed.rb +195 -0
- data/lib/zip/zip.rb +1378 -0
- data/lib/zip/zipfilesystem.rb +558 -0
- data/lib/zip/ziprequire.rb +61 -0
- data/rwd_files/HowTo_Eliza.txt +195 -0
- data/rwd_files/HowTo_Tinker.txt +471 -0
- data/rwd_files/HowTo_TinkerWin2.txt +202 -0
- data/rwd_files/Readme.txt +57 -0
- data/rwd_files/RubyWebDialogs.html +6 -0
- data/rwd_files/favicon.ico +0 -0
- data/rwd_files/rdoc-style.css +175 -0
- data/rwd_files/rwdapplications.html +54 -0
- data/rwd_files/tinker.png +0 -0
- data/rwdconfig.dist +21 -0
- data/rwdeliza.rb +1 -0
- data/tests/RubyGauge.rb +179 -0
- data/tests/checkdepends.sh +4 -0
- data/tests/cleancnf.sh +6 -0
- data/tests/makedist-rwdweliza.rb +56 -0
- data/tests/makedist.rb +66 -0
- data/tests/rdep.rb +354 -0
- data/tests/totranslate.lang +93 -0
- data/zips/rwdwaddresses-1.05.zip +0 -0
- data/zips/rwdwcalc-0.61.zip +0 -0
- data/zips/rwdwgutenberg-0.09.zip +0 -0
- data/zips/rwdwschedule-1.04.zip +0 -0
- data/zips/rwdwshell-1.04.zip +0 -0
- data/zips/temp.rb +1 -0
- data/zips/wrubyslippers-1.06.zip +0 -0
- metadata +282 -0
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
#!/usr/bin/ruby
|
|
2
|
+
#
|
|
3
|
+
# word.rb - hold the class declaration for the LinkParser::Linkage::Word
|
|
4
|
+
# class.
|
|
5
|
+
#
|
|
6
|
+
# == Synopsis
|
|
7
|
+
#
|
|
8
|
+
#
|
|
9
|
+
# == Rcsid
|
|
10
|
+
#
|
|
11
|
+
# $Id: word.rb,v 1.9 2003/09/09 19:27:43 stillflame Exp $
|
|
12
|
+
#
|
|
13
|
+
# == Authors
|
|
14
|
+
#
|
|
15
|
+
# Martin Chase <stillflame@FaerieMUD.org>
|
|
16
|
+
#
|
|
17
|
+
#:include: COPYRIGHT
|
|
18
|
+
#
|
|
19
|
+
#---
|
|
20
|
+
#
|
|
21
|
+
# Please see the file COPYRIGHT for licensing details.
|
|
22
|
+
#
|
|
23
|
+
|
|
24
|
+
class LinkParser
|
|
25
|
+
class Word
|
|
26
|
+
|
|
27
|
+
### Word use constants.
|
|
28
|
+
Subject = "subject"
|
|
29
|
+
Object = "object"
|
|
30
|
+
Determiner = "determiner"
|
|
31
|
+
Verb = "verb"
|
|
32
|
+
Unknown = "unknown"
|
|
33
|
+
|
|
34
|
+
### Fill in word name and connect connections correctly.
|
|
35
|
+
def initialize( sentence, index, left=[], right=[], suffix='' )
|
|
36
|
+
@definition = sentence.definitions[index]
|
|
37
|
+
@name = sentence.names[index]
|
|
38
|
+
@position = index
|
|
39
|
+
@left = left
|
|
40
|
+
@right = right
|
|
41
|
+
@suffix = suffix
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
### the LinkParser::Definition object that this is related to
|
|
45
|
+
attr_reader :definition
|
|
46
|
+
|
|
47
|
+
### the english language word represented by this object
|
|
48
|
+
attr_reader :name
|
|
49
|
+
|
|
50
|
+
### the position of the word within the sentence
|
|
51
|
+
attr_reader :position
|
|
52
|
+
|
|
53
|
+
### the LinkParser::Linkage::Link objects that connect to the left of
|
|
54
|
+
### this word
|
|
55
|
+
attr_accessor :left
|
|
56
|
+
|
|
57
|
+
### the LinkParser::Linkage::Link objects that connect to the right of
|
|
58
|
+
### this word
|
|
59
|
+
attr_accessor :right
|
|
60
|
+
|
|
61
|
+
### the suffix or suffixes that this word has limited its usage to
|
|
62
|
+
attr_reader :suffix
|
|
63
|
+
|
|
64
|
+
### Simple stringy version
|
|
65
|
+
def to_s
|
|
66
|
+
@name.to_s
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
### Merges the other word into this word.
|
|
70
|
+
def combine!(other)
|
|
71
|
+
@right += other.right
|
|
72
|
+
@left += other.left
|
|
73
|
+
self
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
### Simple equality test.
|
|
77
|
+
def ==(other)
|
|
78
|
+
@name == other.to_s if other.respond_to?(:to_s)
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
### Returns the way this word is being used in the sentence.
|
|
82
|
+
def use
|
|
83
|
+
return Object if @left.find {|c| c.name.match /^O/}
|
|
84
|
+
return Subject if @right.find {|c| c.name.match /^S/}
|
|
85
|
+
return Verb if @left.find {|c| c.name.match /^S/} or
|
|
86
|
+
@right.find {|c| c.name.match /^O/}
|
|
87
|
+
return Determiner if @right.find {|c| c.name.match /^D/}
|
|
88
|
+
return Unknown
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
end # class Word
|
|
92
|
+
end # class LinkParser
|
data/lib/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
|