qrpm 0.0.3 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
data/lib/qrpm/parser.rb DELETED
@@ -1,183 +0,0 @@
1
-
2
- module Qrpm
3
- class Parser
4
- DICT_FIELDS = (Rpm::FIELDS - %w(requires)).map { |f| [f, true] }.to_h
5
-
6
- attr_reader :fields # Hash from field to value (which can be of any type)
7
- attr_reader :dirs # Hash from directory to list of entries
8
- attr_reader :files # List of files
9
- attr_reader :rpm # Resulting RPM object
10
-
11
- def initialize(fields)
12
- @fields = fields.dup
13
- @dirs = {}
14
- @files = []
15
- end
16
-
17
- def parse(yaml)
18
- # Collect .qrpm file variables and directories and the list of required
19
- # packages. Variables are merged into +fields+
20
- yaml.each { |k,v|
21
- if k =~ /[\/.]/ || DIRS.key?(k) || DIRS.key?(k.sub(/^pck/, ""))
22
- (dirs[k] ||= []).concat v
23
- elsif k =~ /^[\w_]+$/
24
- fields[k] = v if !fields.key?(k)
25
- else
26
- raise "Illegal key/value: #{k}: #{v}"
27
- end
28
- }
29
-
30
- # Check for mandatory variables
31
- Rpm::MANDATORY_FIELDS.each { |f|
32
- fields.key?(f) or raise "Missing mandatory variable: #{f}"
33
- }
34
-
35
- # Get full name of user
36
- fullname = Etc.getpwnam(ENV['USER'])&.gecos
37
- if fullname.nil? || fullname == ""
38
- fullname = ENV['USER']
39
- end
40
-
41
- # Defaults for description and packager fields
42
- fields["description"] ||= fields["summary"]
43
- fields["packager"] ||= fullname
44
- fields["release"] ||= "0"
45
- fields["license"] ||= "GPL"
46
-
47
- # Expand variables in fields. The expansion mechanism doesn't depend on the order
48
- # of the variables
49
- expand_fields
50
-
51
- # Expand variables in directory entries. The algorithm is simpler than in
52
- # #expand_fields because no further variable defitinitions can happend
53
- expand_dirs
54
-
55
- # Replace symbolic directory names
56
- @dirs = dirs.map { |dir, files|
57
- if DIRS.key?(dir)
58
- dir = DIRS[dir]
59
- elsif dir =~ /^pck(.*)$/ && DIRS.key?($1)
60
- dir = "#{DIRS[$1]}/#{fields["name"]}"
61
- end
62
- [dir, files]
63
- }.to_h
64
-
65
- # Build files
66
- dirs.each { |dir, nodes|
67
- nodes.each { |node|
68
- case node
69
- when Hash
70
- node = node.dup
71
- if node.key?("file")
72
- name = node.delete("name")
73
- file = node.delete("file")
74
- perm = node.delete("perm")
75
- node.empty? or raise "Illegal keys for file in directory #{dir}: #{node.keys}"
76
- files << Qrpm::File.new(dir, name, file, perm)
77
- elsif node.key?("link")
78
- name = node.delete("name")
79
- link = node.delete("link")
80
- node.empty? or raise "Illegal keys for link in directory #{dir}: #{node.keys}"
81
- files << Qrpm::Link.new(dir, name, link)
82
- else
83
- raise "Need either a 'file' or 'link' field for directory #{dir}"
84
- end
85
- when String
86
- files << Qrpm::File.new(dir, nil, node, nil)
87
- else
88
- raise "Illegal value for directory #{dir}: #{node}"
89
- end
90
- }
91
- }
92
-
93
- @rpm = Rpm.new(fields, files)
94
- end
95
-
96
- def self.parse(dict, yaml)
97
- Parser.new(dict).parse(yaml)
98
- end
99
-
100
- private
101
- MANDATORY_FIELDS = %w(name summary version)
102
-
103
- DIRS = {
104
- "etcdir" => "/etc",
105
- "bindir" => "/usr/bin",
106
- "sbindir" => "/usr/sbin",
107
- "libdir" => "/usr/lib",
108
- "libexecdir" => "/usr/libexec",
109
- "sharedir" => "/usr/share",
110
- "vardir" => "/var/lib",
111
- "spooldir" => "/var/spool",
112
- "rundir" => "/var/run",
113
- "lockdir" => "/var/lock",
114
- "cachedir" => "/var/cache",
115
- "tmpdir" => "/tmp",
116
- "logdir" => "/var/log"
117
- }
118
-
119
- # Returns array of variables in the object. Variables can be either '$name' or
120
- # '${name}'. The variables are returned in left-to-right order
121
- #
122
- def collect_variables(object, include_keys: false)
123
- case object
124
- when Array; object.map { |obj| collect_variables(obj) }
125
- when Hash; object.map { |k,v| (include_keys ? collect_variables(k) : []) + collect_variables(v) }
126
- when String; object.scan(/\$([\w_]+)|\$\{([\w_]+)\}/)
127
- when Integer, Float, true, false, nil; []
128
- else
129
- raise "Illegal object: #{object}"
130
- end.flatten.compact.uniq
131
- end
132
-
133
- # Expand variables in the given string
134
- #
135
- # The method takes care to substite left-to-rigth to avoid a variable expansion
136
- # to infer with the name of an immediately preceding variable. Eg. $a$b; if $b
137
- # is resolved to 'c' then a search would otherwise be made for a variable named
138
- # '$ac'
139
- #
140
- def expand_variables(object, include_key: false)
141
- case object
142
- when Array; object.map { |e| expand_variables(e) }
143
- when Hash; object.map { |k,v| [expand_variables(k), expand_variables(v)] }.to_h
144
- when String
145
- s = object.dup
146
- collect_variables(object).each { |k| s.sub!(/\$#{k}|\$\{#{k}\}/, fields[k].to_s) }
147
- s
148
- when Integer, Float, true, false, nil; object
149
- else
150
- raise "Illegal object: #{object}"
151
- end
152
- end
153
-
154
- # Expands fields (but not directories). The algorithm allows fields to be
155
- # defined in any order
156
- #
157
- def expand_fields
158
- variables = fields.map { |k,v| [k, collect_variables(v)] }.to_h
159
- variables.values.flatten.uniq.each { |var|
160
- fields[var].nil? || fields[var].is_a?(String) or "Can't use '#{var}' as variable"
161
- }
162
-
163
- @fields, unresolved = fields.partition { |k,v| variables[k].empty? }.map(&:to_h)
164
- changed = true
165
- while changed && !unresolved.empty?
166
- changed = false
167
- unresolved.delete_if { |k,v|
168
- if variables[k].all? { |var| fields.key? var }
169
- fields[k] = expand_variables(unresolved[k])
170
- changed = true
171
- end
172
- }
173
- end
174
- unresolved.empty? or raise "Unresolved variables: #{unresolved.join(", ")}"
175
- end
176
-
177
- def expand_dirs
178
- @dirs = expand_variables(dirs)
179
- end
180
- end
181
- end
182
-
183
-