summaryrefslogtreecommitdiff
path: root/Tools/scripts/plist
blob: 6a903ad15f3362610ba81764af9cf47da2303378 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
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
#!/usr/local/bin/ruby
# pkg-plist generator by Brian Fundakowski Feldman <green@FreeBSD.org>
# (public domain)
# $FreeBSD$

class Plist
	def initialize(no_manpages = true, mtree = [])
		@no_manpages = no_manpages
		@mtree = mtree
		self
	end
	def make(dir)
		@root = dir.to_s + '/'
		imake('', 0, '')
	end
	private
	def imake(dir, level, prevwd)
		thiswd = prevwd + dir				# always ends in '/'
		rootedwd = @root + thiswd
		subs = []
		Dir.foreach(rootedwd) {|dirent|
			next if dirent =~ /^\.\.?$/
			if test(?d, rootedwd + dirent)
				subs.concat(imake(dirent + '/', level + 1, thiswd))
			else
				if thiswd !~ /^man\// || !@no_manpages
						subs.push(thiswd + dirent)
				end
			end
		}
		thiswd.chop!
		# Strip mtree-created directories
		if level > 0 && !@mtree.find {|x| x == thiswd}
			subs.push('@dirrm ' + thiswd)
		end
		return subs
	end
end

class Mtree
	def initialize(strip = 1)
		@paths = []
		@curlevel = []
		@strip = strip.to_i
		@curline = ''
		@global_settings = {}
		self
	end
	def parse_line(line)
		line.chomp!
		if line.empty? || line[0, 1] == '#'
			return
		end
		if line[-1, 1] == "\\"
			@curline.concat(line[0..-2])
			next
		end
		line = @curline + line
		@curline = ''
		case line[/\S.+/]
		when /^\/(\S+)/
			case $1
			when 'set'
				$'.split.each {|setting|
					key, value, = setting.split(/=/)
					@global_settings[key] = value
				}
			when 'unset'
				$'.split.each {|setting| @global_settings.delete(setting)}
			else
				raise "invalid command \"#{$1}\""
			end
		when '..'
			if @curlevel.pop.nil?
				raise '".." with no previous directory'
			end
		else
			spline = line.split()
			path = spline[0]
			settings = @global_settings.dup
			if spline.size > 1
				spline[1..-1].each {|setting|
					key, value, = setting.split(/=/)
					settings[key] = value
				}
			end
			@paths.push(@curlevel + [path])
			if settings['type'] == nil || settings['type'] == 'dir'
				@curlevel.push(path)
			end
		end
		self
	end
	def Mtree.read(filename)
		m = Mtree.new
		open(filename, 'r') {|file|
			file.each_line {|line| m.parse_line(line)}
		}
		m
	end
	def paths(strip = @strip)
		@paths.collect {|path| path[strip..-1].join('/')}
	end
end

if __FILE__ == $0
	require 'getopts'
	if !getopts('Md', 'm:') || ARGV.size != 1
		$stderr.print <<-USAGE_EOF
usage: #{$0} [-Md] [-m mtree] somepath
       Generate a pkg-plist to stdout given a previously empty somepath which
       a port has been installed into (PREFIX=somepath).  The mtree file is
       consulted to prevent base directories from being added to the plist.
       The -M argument allows manpages to be added to the plist.
       The -d argument puts all @dirrm commands at the end of the plist.
USAGE_EOF
		exit 1
	end
	mtree = $OPT_m || '/etc/mtree/BSD.local.dist'
	pl = Plist.new(!$OPT_M, Mtree.read(mtree).paths).make(ARGV[0])
	if $OPT_d
		plnotdirrm = []
		pldirrm = []
		pl.each {|ent|
			if ent =~ /^@dirrm /
				pldirrm.push(ent)
			else
				plnotdirrm.push(ent)
			end
			plnotdirrm.sort!
			pldirrm.sort!
			pl = plnotdirrm + pldirrm.reverse
		}
	else
	  	pl.sort!
	end
	puts(pl.join("\n"))
end