1#!/usr/local/bin/ruby 2# pkg-plist generator by Brian Fundakowski Feldman <green@FreeBSD.org> 3# (public domain) 4 5class Plist 6 def initialize(no_manpages = true, mtree = []) 7 @no_manpages = no_manpages 8 @mtree = mtree 9 self 10 end 11 def make(dir) 12 @root = dir.to_s + '/' 13 imake('', 0, '') 14 end 15 private 16 def imake(dir, level, prevwd) 17 thiswd = prevwd + dir # always ends in '/' 18 rootedwd = @root + thiswd 19 subs = [] 20 Dir.foreach(rootedwd) {|dirent| 21 next if dirent =~ /^\.\.?$/ 22 if test(?d, rootedwd + dirent) 23 subs.concat(imake(dirent + '/', level + 1, thiswd)) 24 else 25 if thiswd !~ /^man\// || !@no_manpages 26 subs.push(thiswd + dirent) 27 end 28 end 29 } 30 thiswd.chop! 31 # Strip mtree-created directories 32 if level > 0 && !@mtree.find {|x| x == thiswd} 33 subs.push('@dir ' + thiswd) 34 end 35 return subs 36 end 37end 38 39class Mtree 40 def initialize(strip = 1) 41 @paths = [] 42 @curlevel = [] 43 @strip = strip.to_i 44 @curline = '' 45 @global_settings = {} 46 self 47 end 48 def parse_line(line) 49 line.chomp! 50 if line.empty? || line[0, 1] == '#' 51 return 52 end 53 if line[-1, 1] == "\\" 54 @curline.concat(line[0..-2]) 55 next 56 end 57 line = @curline + line 58 @curline = '' 59 case line[/\S.+/] 60 when /^\/(\S+)/ 61 case $1 62 when 'set' 63 $'.split.each {|setting| 64 key, value, = setting.split(/=/) 65 @global_settings[key] = value 66 } 67 when 'unset' 68 $'.split.each {|setting| @global_settings.delete(setting)} 69 else 70 raise "invalid command \"#{$1}\"" 71 end 72 when '..' 73 if @curlevel.pop.nil? 74 raise '".." with no previous directory' 75 end 76 else 77 spline = line.split() 78 path = spline[0] 79 settings = @global_settings.dup 80 if spline.size > 1 81 spline[1..-1].each {|setting| 82 key, value, = setting.split(/=/) 83 settings[key] = value 84 } 85 end 86 @paths.push(@curlevel + [path]) 87 if settings['type'] == nil || settings['type'] == 'dir' 88 @curlevel.push(path) 89 end 90 end 91 self 92 end 93 def Mtree.read(filename) 94 m = Mtree.new 95 open(filename, 'r') {|file| 96 file.each_line {|line| m.parse_line(line)} 97 } 98 m 99 end 100 def paths(strip = @strip) 101 @paths.collect {|path| path[strip..-1].join('/')} 102 end 103end 104 105if __FILE__ == $0 106 require 'getopts' 107 if !getopts('Md', 'm:') || ARGV.size != 1 108 $stderr.print <<-USAGE_EOF 109usage: #{$0} [-Md] [-m mtree] somepath 110 Generate a pkg-plist to stdout given a previously empty somepath which 111 a port has been installed into (PREFIX=somepath). The mtree file is 112 consulted to prevent base directories from being added to the plist. 113 The -M argument allows manpages to be added to the plist. 114 The -d argument puts all @dir commands at the end of the plist. 115USAGE_EOF 116 exit 1 117 end 118 mtree = $OPT_m || '/etc/mtree/BSD.local.dist' 119 pl = Plist.new(!$OPT_M, Mtree.read(mtree).paths).make(ARGV[0]) 120 if $OPT_d 121 plnotdirrm = [] 122 pldirrm = [] 123 pl.each {|ent| 124 if ent =~ /^@dir / 125 pldirrm.push(ent) 126 else 127 plnotdirrm.push(ent) 128 end 129 plnotdirrm.sort! 130 pldirrm.sort! 131 pl = plnotdirrm + pldirrm.reverse 132 } 133 else 134 pl.sort! 135 end 136 puts(pl.join("\n")) 137end 138