Module: Rconftool
- Defined in:
- lib/rconftool.rb
Defined Under Namespace
Classes: ConfigFile, NoVersionLine, Processor, Setting
Constant Summary collapse
- VERSION =
"0.1"
- HEADER_ID =
'__header__'
Class Method Summary collapse
-
.install(distfile, targetfile = nil, oldfile = nil, opt = {}) ⇒ Object
This module function installs a single source (.dist) file to a target location, having first merged in any compatible settings from the target file if it existed previously [if it does not exist, any settings from ‘oldfile’ are used instead].
-
.recurse_dir(base) ⇒ Object
Yield directory contents recursively, without doing chdir().
Class Method Details
.install(distfile, targetfile = nil, oldfile = nil, opt = {}) ⇒ Object
This module function installs a single source (.dist) file to a target location, having first merged in any compatible settings from the target file if it existed previously [if it does not exist, any settings from ‘oldfile’ are used instead]
If the distfile is not in sysconftool format (i.e. doesn’t have a ##VERSION: header within the first 20 lines), then for safety it is only installed if the target file does not already exist. No attempt at data merging is made in that case.
51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 |
# File 'lib/rconftool.rb', line 51 def self.install(distfile, targetfile=nil, oldfile=nil, opt={}) debug = opt[:debug] || $stdout targetfile ||= distfile if opt[:strip_regexp] targetfile = targetfile.sub(opt[:strip_regexp], '') oldfile = oldfile.sub(opt[:strip_regexp], '') if oldfile end if opt[:add_suffix] targetfile = targetfile + opt[:add_suffix] oldfile = oldfile + opt[:add_suffix] if oldfile end raise Errno::EEXIST, "#{distfile}: dist and target filenames are the same" if distfile == targetfile # Read in the source (.dist) file begin src = ConfigFile.new(distfile) rescue NoVersionLine # Fallback behaviour when installing a file which is not in sysconftool # format: we install the file only if it doesn't already exist if File.exist?(targetfile) debug << "#{targetfile}: already exists, skipping\n" return end return if opt[:noclobber] copyfrom = (oldfile and File.exist?(oldfile)) ? oldfile : distfile if File.symlink?(copyfrom) File.symlink(File.readlink(copyfrom), targetfile) debug << "#{targetfile}: symlink copied from #{copyfrom}\n" else FileUtils.cp copyfrom, targetfile, :preserve=>true debug << "#{targetfile}: copied from #{copyfrom}\n" end return end # OK, so we have a sysconftool file to install. Read in the existing # target file, or if that does not exist, the oldfile begin old = ConfigFile.new old.read(targetfile) rescue NoVersionLine # That's OK; the old target will be renamed to .bak rescue Errno::ENOENT begin target_missing = true old.read(oldfile) if oldfile rescue Errno::ENOENT, NoVersionLine end end # Same VERSION? No merge is required if src.version == old.version and not opt[:force] if target_missing FileUtils.cp oldfile, targetfile, :preserve=>true debug << "#{targetfile}: same VERSION, copied from #{oldfile}\n" return end debug << "#{targetfile}: same VERSION, no change\n" return end # Merge in old settings (note: any settings which are in targetfile but # not in distfile will be silently dropped) debug << "#{targetfile}:\n" src.settings[1..-1].each do |src_setting| name = src_setting.name old_setting = old[name] unless old_setting debug << " #{name}: new\n" next end if old_setting.version == src_setting.version if $DEBUG $stderr.puts "old setting: #{old_setting.version}" $stderr.puts "src setting: #{src_setting.version}" end debug << " #{name}: unchanged\n" src_setting.add_comment("\n DEFAULT SETTING from #{distfile}:\n") src_setting.add_comment(src_setting.content) src_setting.content = old_setting.content next end # Otherwise, must install updated setting and comment out # the current setting for reference debug << " #{name}: UPDATED\n" src_setting.add_comment("\n Previous setting (inserted by rconftool):\n\n") src_setting.add_comment(old_setting.content) end return if opt[:noclobber] # Write out the new file and carry forward permissions begin tempfile = targetfile+".new#{$$}" src.write(tempfile) st = File.stat(distfile) begin File.chown(st.uid, st.gid, tempfile) rescue Errno::EPERM end File.chmod(st.mode, tempfile) File.rename(targetfile, targetfile+".bak") unless target_missing File.rename(tempfile, targetfile) rescue File.delete(tempfile) rescue nil raise end end |
.recurse_dir(base) ⇒ Object
Yield directory contents recursively, without doing chdir(). Note that yielded pathnames are relative to the base directory given; so that, for example, you can simulate ‘cp -r /foo/bar/ /baz/’ by
recurse_dir("/foo/bar") { |n| copy("/foo/bar/"+n,"/baz/"+n) unless
File.directory?("/foo/bar/"+n) }
Current behaviour is that if a directory is a symlink, we follow it. (Perhaps the block we yield should return true/false?)
262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 |
# File 'lib/rconftool.rb', line 262 def self.recurse_dir(base) base = base+File::SEPARATOR unless base[-1,1] == File::SEPARATOR dirs = [''] while dir = dirs.pop yield dir unless dir == '' Dir.foreach(base+dir) do |n| next if n == '.' || n == '..' target = dir + n if File.directory?(base+target) dirs << target+File::SEPARATOR next end yield target end end end |