qrpm 0.2.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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
-