qrpm 0.0.3 → 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.
- checksums.yaml +4 -4
- data/.ruby-version +1 -1
- data/NOTES +7 -0
- data/TODO +30 -0
- data/doc/pg.yml +37 -0
- data/doc/qrpm2.rb +69 -0
- data/doc/qrpm2.yml +55 -0
- data/example/configure +0 -0
- data/example/make +0 -0
- data/example/my_package_name-1.2.3-4.x86_64.rpm +0 -0
- data/example/my_package_name.spec +49 -0
- data/example.yml +84 -0
- data/exe/qrpm +134 -42
- data/lib/qrpm/compiler.rb +238 -0
- data/lib/qrpm/fragment.rb +177 -0
- data/lib/qrpm/lexer.rb +41 -0
- data/lib/qrpm/node.rb +372 -31
- data/lib/qrpm/qrpm.rb +182 -53
- data/lib/qrpm/rpm.rb +107 -60
- data/lib/qrpm/template.erb +28 -29
- data/lib/qrpm/template.yml +15 -12
- data/lib/qrpm/utils.rb +10 -0
- data/lib/qrpm/version.rb +1 -1
- data/lib/qrpm.rb +107 -1
- data/qrpm.gemspec +3 -3
- metadata +51 -10
- data/lib/qrpm/parser.rb +0 -183
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
|
-
|