aboutsummaryrefslogtreecommitdiffstats
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