qrpm 0.2.0 → 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,202 +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
- # TODO TODO TODO
120
-
121
- # Expand shell expansions ($(shell command))
122
- #
123
- def expand_shell_commands(object)
124
- case object
125
- when Array; object.map { |e| expand_shell_commands(e) }
126
- when Hash; object.map { |k,v| [k, expand_shell_commands(v)] }.to_h
127
- when String;
128
- puts object.scan(/\$\(([^\)]+)\)/)
129
- object.scan(/\$\(([^\)]+)\)/)
130
-
131
- when Integer, Float, true, false, nil; object
132
- else
133
- raise "Illegal object: #{object}"
134
- end
135
- end
136
-
137
-
138
- # Returns array of variables in the object. Variables can be either '$name' or
139
- # '${name}'. The variables are returned in left-to-right order
140
- #
141
- def collect_variables(object, include_keys: false)
142
- case object
143
- when Array; object.map { |obj| collect_variables(obj) }
144
- when Hash; object.map { |k,v| (include_keys ? collect_variables(k) : []) + collect_variables(v) }
145
- when String; object.scan(/\$([\w_]+)|\$\{([\w_]+)\}/)
146
- when Integer, Float, true, false, nil; []
147
- else
148
- raise "Illegal object: #{object}"
149
- end.flatten.compact.uniq
150
- end
151
-
152
- # Expand variables in the given string
153
- #
154
- # The method takes care to substite left-to-rigth to avoid a variable expansion
155
- # to infer with the name of an immediately preceding variable. Eg. $a$b; if $b
156
- # is resolved to 'c' then a search would otherwise be made for a variable named
157
- # '$ac'
158
- #
159
- def expand_variables(object, include_key: false)
160
- case object
161
- when Array; object.map { |e| expand_variables(e) }
162
- when Hash; object.map { |k,v| [expand_variables(k), expand_variables(v)] }.to_h
163
- when String
164
- s = object.dup
165
- collect_variables(object).each { |k| s.sub!(/\$#{k}|\$\{#{k}\}/, fields[k].to_s) }
166
- s
167
- when Integer, Float, true, false, nil; object
168
- else
169
- raise "Illegal object: #{object}"
170
- end
171
- end
172
-
173
- # Expands fields (but not directories). The algorithm allows fields to be
174
- # defined in any order
175
- #
176
- def expand_fields
177
- variables = fields.map { |k,v| [k, collect_variables(v)] }.to_h
178
- variables.values.flatten.uniq.each { |var|
179
- fields[var].nil? || fields[var].is_a?(String) or "Can't use '#{var}' as variable"
180
- }
181
-
182
- @fields, unresolved = fields.partition { |k,v| variables[k].empty? }.map(&:to_h)
183
- changed = true
184
- while changed && !unresolved.empty?
185
- changed = false
186
- unresolved.delete_if { |k,v|
187
- if variables[k].all? { |var| fields.key? var }
188
- fields[k] = expand_variables(unresolved[k])
189
- changed = true
190
- end
191
- }
192
- end
193
- unresolved.empty? or raise "Unresolved variables: #{unresolved.join(", ")}"
194
- end
195
-
196
- def expand_dirs
197
- @dirs = expand_variables(dirs)
198
- end
199
- end
200
- end
201
-
202
-