qrpm 0.0.1
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 +7 -0
- data/.rspec +3 -0
- data/.ruby-version +1 -0
- data/Gemfile +10 -0
- data/README.md +35 -0
- data/Rakefile +8 -0
- data/bin/console +15 -0
- data/bin/setup +8 -0
- data/clean +3 -0
- data/cmd +12 -0
- data/example/bin/a_file +1 -0
- data/example/bin/another_file +0 -0
- data/example/qrpm.yml +31 -0
- data/example/share/some_data +1 -0
- data/example/share/some_other_data +0 -0
- data/exe/qrpm +99 -0
- data/lib/qrpm/node.rb +54 -0
- data/lib/qrpm/parser.rb +173 -0
- data/lib/qrpm/qrpm.rb +63 -0
- data/lib/qrpm/render.rb +25 -0
- data/lib/qrpm/rpm.rb +114 -0
- data/lib/qrpm/template.erb +73 -0
- data/lib/qrpm/template.yml +88 -0
- data/lib/qrpm/version.rb +5 -0
- data/lib/qrpm.rb +16 -0
- data/packager.sh +65 -0
- data/packager.yml +32 -0
- data/program.sh +19 -0
- data/qrpm.gemspec +47 -0
- metadata +100 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 5a7181b2cc45c65645e039fc5fba4d758698e2558acafe9f9173a955f7af7895
|
4
|
+
data.tar.gz: 714b179b5f0f235ddd7b6098ea674579fc8dec671db6d76570e9c9128d7edae7
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: eaf5dc6516f01dcc9a912f1982f7008f2d1ff667aff8cabf9197945726d43690bc4d28836a186d2a3f5b245f17ecf2d8c7744facbdd7fe6f81d8d32aaf6ce3c3
|
7
|
+
data.tar.gz: eb40981a98a3408f545ef8b42ce6a9f1f70657393886542857911f74865759e2227de458648a04c94a0b9edcc3d18a8a5b54ca3035f6c15fc8ddca5a057f7501
|
data/.rspec
ADDED
data/.ruby-version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
ruby-2.7.1
|
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
# Qrpm
|
2
|
+
|
3
|
+
Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/qrpm`. To experiment with that code, run `bin/console` for an interactive prompt.
|
4
|
+
|
5
|
+
TODO: Delete this and the text above, and describe your gem
|
6
|
+
|
7
|
+
## Installation
|
8
|
+
|
9
|
+
Add this line to your application's Gemfile:
|
10
|
+
|
11
|
+
```ruby
|
12
|
+
gem 'qrpm'
|
13
|
+
```
|
14
|
+
|
15
|
+
And then execute:
|
16
|
+
|
17
|
+
$ bundle install
|
18
|
+
|
19
|
+
Or install it yourself as:
|
20
|
+
|
21
|
+
$ gem install qrpm
|
22
|
+
|
23
|
+
## Usage
|
24
|
+
|
25
|
+
TODO: Write usage instructions here
|
26
|
+
|
27
|
+
## Development
|
28
|
+
|
29
|
+
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
30
|
+
|
31
|
+
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
32
|
+
|
33
|
+
## Contributing
|
34
|
+
|
35
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/qrpm.
|
data/Rakefile
ADDED
data/bin/console
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require "bundler/setup"
|
5
|
+
require "qrpm"
|
6
|
+
|
7
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
8
|
+
# with your gem easier. You can also use a different console, if you like.
|
9
|
+
|
10
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
11
|
+
# require "pry"
|
12
|
+
# Pry.start
|
13
|
+
|
14
|
+
require "irb"
|
15
|
+
IRB.start(__FILE__)
|
data/bin/setup
ADDED
data/clean
ADDED
data/cmd
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
#!/usr/bin/bash
|
2
|
+
|
3
|
+
set -e
|
4
|
+
|
5
|
+
VERSION=1.2.4
|
6
|
+
PG_VERSION=13
|
7
|
+
|
8
|
+
rm -f example/*.rpm
|
9
|
+
#sudo rpm -e my_package_name 2>/dev/null || true
|
10
|
+
bundle exec exe/qrpm $@ --force -C example VERSION=$VERSION PG_VERSION=$PG_VERSION qrpm.yml
|
11
|
+
#sudo rpm -i example/my_package_name-1.2.3-4.x86_64.rpm
|
12
|
+
|
data/example/bin/a_file
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
hej
|
File without changes
|
data/example/qrpm.yml
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
|
2
|
+
name: my_package_name
|
3
|
+
summary: This is a summary of the package
|
4
|
+
description: Optional longer description of the package
|
5
|
+
version: 1.2.3
|
6
|
+
release: 4
|
7
|
+
packager: null
|
8
|
+
requires:
|
9
|
+
- ruby
|
10
|
+
- httpd
|
11
|
+
- postgresql13
|
12
|
+
|
13
|
+
make: # List of commands to build project
|
14
|
+
- echo "Hej du" > bin/another_file
|
15
|
+
|
16
|
+
bindir:
|
17
|
+
- bin/a_file
|
18
|
+
- bin/another_file
|
19
|
+
- name: an_alias
|
20
|
+
file: bin/a_file
|
21
|
+
|
22
|
+
sbindir:
|
23
|
+
- link: /bin/a_file
|
24
|
+
|
25
|
+
pcksharedir:
|
26
|
+
- share/some_data
|
27
|
+
|
28
|
+
vardir:
|
29
|
+
- share/some_other_data
|
30
|
+
|
31
|
+
|
@@ -0,0 +1 @@
|
|
1
|
+
hejdu
|
File without changes
|
data/exe/qrpm
ADDED
@@ -0,0 +1,99 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
#$LOAD_PATH.unshift "/home/clr/prj/shellopts/lib"
|
4
|
+
|
5
|
+
require_relative '../lib/qrpm/qrpm.rb'
|
6
|
+
require_relative '../lib/qrpm.rb'
|
7
|
+
|
8
|
+
require 'yaml'
|
9
|
+
require 'shellopts'
|
10
|
+
require 'indented_io'
|
11
|
+
|
12
|
+
# TODO
|
13
|
+
# o Fix BuildRoot (contains absolute path)
|
14
|
+
# o Enable escape of $
|
15
|
+
|
16
|
+
begin
|
17
|
+
SPEC = %(
|
18
|
+
@ Quick RPM builder
|
19
|
+
|
20
|
+
'qrpm' creates a RPM package from a simple YAML specification file
|
21
|
+
|
22
|
+
A template YAML qrpm configuration file can be generated by the --template
|
23
|
+
option. It is in YAML format with the extension that a single '__END__'
|
24
|
+
terminates the file and that $NAME or ${NAME} are variables that will be
|
25
|
+
expanded. The variables can either be specified in the configuration file
|
26
|
+
or given on the command line in <variable>=<value> format
|
27
|
+
|
28
|
+
-- VARIABLE=VALUE... [QRPM-FILE]
|
29
|
+
|
30
|
+
-t,template=OFILE?
|
31
|
+
Generate a template qrpm.yml file in the current directory. Customize it
|
32
|
+
to create RPM packages of your project
|
33
|
+
|
34
|
+
-s,spec=OFILE?
|
35
|
+
Only create the spec file and not the RPM package. Use this option to
|
36
|
+
inspect what RPM is going to do
|
37
|
+
|
38
|
+
-S,source
|
39
|
+
Create a source RPM file instead of a regular RPM file
|
40
|
+
|
41
|
+
-f,force
|
42
|
+
Create package even if repository is dirty. Normally qrpm checks if the
|
43
|
+
current directory is a Git directory and then if there are no changed
|
44
|
+
files
|
45
|
+
|
46
|
+
-C,directory=EDIR
|
47
|
+
Change to directory before doing anything else
|
48
|
+
|
49
|
+
-d,dump
|
50
|
+
Dump internal data and exit
|
51
|
+
)
|
52
|
+
|
53
|
+
opts, args = ShellOpts.process(SPEC, ARGV)
|
54
|
+
|
55
|
+
Dir.chdir(opts.directory) if opts.directory?
|
56
|
+
|
57
|
+
if opts.template?
|
58
|
+
outfile = opts.template || Qrpm::QRPM_CONFIG_FILE
|
59
|
+
FileUtils::cp Qrpm::QRPM_CONFIG_FILE_TEMPLATE, outfile
|
60
|
+
exit
|
61
|
+
end
|
62
|
+
|
63
|
+
# Collect var=val settings in the dict hash and sets the configuration file
|
64
|
+
dict = {}
|
65
|
+
while arg = args.extract(0..1)
|
66
|
+
if arg =~ /^(.*?)=(.*)$/
|
67
|
+
dict[$1] = $2
|
68
|
+
else
|
69
|
+
file = arg
|
70
|
+
break
|
71
|
+
end
|
72
|
+
end
|
73
|
+
args.empty? or args.expect(0) # Generates an illegal-number-of-arguments error
|
74
|
+
|
75
|
+
# Check configuration file
|
76
|
+
file ||= QRPM_CONFIG_FILE
|
77
|
+
::File.exist?(file) or raise "Can't find '#{file}'"
|
78
|
+
|
79
|
+
# Check if repository is clean
|
80
|
+
opts.force? || `git status --porcelain 2>/dev/null` == "" or raise "Repository is dirty"
|
81
|
+
|
82
|
+
# Load the qrpm configuration file
|
83
|
+
yaml = YAML.load(IO.read(file).sub(/^__END__\s*$/m, ""))
|
84
|
+
|
85
|
+
# Parse QRPM file
|
86
|
+
rpm = Qrpm::Parser.parse(dict, yaml)
|
87
|
+
|
88
|
+
if opts.dump?
|
89
|
+
rpm.dump
|
90
|
+
exit
|
91
|
+
end
|
92
|
+
|
93
|
+
target = (opts.spec? ? :spec : (opts.source? ? :srpm : :rpm))
|
94
|
+
rpm.build(target: target, file: opts.spec)
|
95
|
+
|
96
|
+
rescue RuntimeError => ex
|
97
|
+
ShellOpts.error ex.message
|
98
|
+
end
|
99
|
+
|
data/lib/qrpm/node.rb
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
|
2
|
+
module Qrpm
|
3
|
+
class Node
|
4
|
+
attr_reader :directory # Destination directory
|
5
|
+
attr_reader :name # Defaults to last element of file/link
|
6
|
+
def path() "#{directory}/#{name}" end
|
7
|
+
|
8
|
+
def initialize(directory, name)
|
9
|
+
@directory, @name = directory, name
|
10
|
+
end
|
11
|
+
|
12
|
+
def file?() self.class == Qrpm::File end
|
13
|
+
def link?() self.class == Qrpm::Link end
|
14
|
+
|
15
|
+
def dump(&block)
|
16
|
+
puts self.class
|
17
|
+
indent {
|
18
|
+
puts "directory: #{directory}"
|
19
|
+
puts "name : #{name}"
|
20
|
+
yield if block_given?
|
21
|
+
}
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
class File < Node
|
26
|
+
attr_reader :file # Path to file in the source repository
|
27
|
+
attr_reader :perm # Defaults to nil - using the current permissions
|
28
|
+
def initialize(directory, name, file, perm = nil)
|
29
|
+
super(directory, name || file.sub(/.*\//, ""))
|
30
|
+
@file, @perm = file, perm
|
31
|
+
end
|
32
|
+
def dump
|
33
|
+
super {
|
34
|
+
puts "file : #{file}"
|
35
|
+
puts "perm : #{perm}"
|
36
|
+
}
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
class Link < Node
|
41
|
+
attr_reader :link # Destination file of link
|
42
|
+
|
43
|
+
def initialize(directory, name, link)
|
44
|
+
super(directory, name || link.sub(/.*\//, ""))
|
45
|
+
@link = link
|
46
|
+
end
|
47
|
+
def dump
|
48
|
+
super {
|
49
|
+
puts "link : #{link}"
|
50
|
+
}
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
data/lib/qrpm/parser.rb
ADDED
@@ -0,0 +1,173 @@
|
|
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
|
+
# Defaults for description and packager fields
|
36
|
+
fields["description"] ||= fields["summary"]
|
37
|
+
fields["packager"] ||= ENV['USER']
|
38
|
+
fields["release"] ||= "0"
|
39
|
+
fields["license"] ||= "GPL"
|
40
|
+
|
41
|
+
# Expand variables in fields. The expansion mechanism doesn't depend on the order
|
42
|
+
# of the variables
|
43
|
+
expand_fields
|
44
|
+
|
45
|
+
# Replace symbolic directory names
|
46
|
+
@dirs = dirs.map { |dir, files|
|
47
|
+
if DIRS.key?(dir)
|
48
|
+
dir = DIRS[dir]
|
49
|
+
elsif dir =~ /^pck(.*)$/ && DIRS.key?($1)
|
50
|
+
dir = "#{DIRS[$1]}/#{fields["name"]}"
|
51
|
+
end
|
52
|
+
[dir, files]
|
53
|
+
}.to_h
|
54
|
+
|
55
|
+
# Build files
|
56
|
+
dirs.each { |dir, nodes|
|
57
|
+
nodes.each { |node|
|
58
|
+
case node
|
59
|
+
when Hash
|
60
|
+
node = node.dup
|
61
|
+
if node.key?("file")
|
62
|
+
name = node.delete("name")
|
63
|
+
file = node.delete("file")
|
64
|
+
perm = node.delete("perm")
|
65
|
+
node.empty? or raise "Illegal keys for file in directory #{dir}: #{node.keys}"
|
66
|
+
files << Qrpm::File.new(dir, name, file, perm)
|
67
|
+
elsif node.key?("link")
|
68
|
+
name = node.delete("name")
|
69
|
+
link = node.delete("link")
|
70
|
+
node.empty? or raise "Illegal keys for link in directory #{dir}: #{node.keys}"
|
71
|
+
files << Qrpm::Link.new(dir, name, link)
|
72
|
+
else
|
73
|
+
raise "Need either a 'file' or 'link' field for directory #{dir}"
|
74
|
+
end
|
75
|
+
when String
|
76
|
+
files << Qrpm::File.new(dir, nil, node, nil)
|
77
|
+
else
|
78
|
+
raise "Illegal value for directory #{dir}: #{node}"
|
79
|
+
end
|
80
|
+
}
|
81
|
+
}
|
82
|
+
|
83
|
+
@rpm = Rpm.new(fields, files)
|
84
|
+
end
|
85
|
+
|
86
|
+
def self.parse(dict, yaml)
|
87
|
+
Parser.new(dict).parse(yaml)
|
88
|
+
end
|
89
|
+
|
90
|
+
private
|
91
|
+
MANDATORY_FIELDS = %w(name summary version)
|
92
|
+
|
93
|
+
DIRS = {
|
94
|
+
"etcdir" => "/etc",
|
95
|
+
"bindir" => "/usr/bin",
|
96
|
+
"sbindir" => "/usr/sbin",
|
97
|
+
"libdir" => "/usr/lib",
|
98
|
+
"libexecdir" => "/usr/libexec",
|
99
|
+
"sharedir" => "/usr/share",
|
100
|
+
"vardir" => "/var/lib",
|
101
|
+
"spooldir" => "/var/spool",
|
102
|
+
"rundir" => "/var/run",
|
103
|
+
"lockdir" => "/var/lock",
|
104
|
+
"cachedir" => "/var/cache",
|
105
|
+
"tmpdir" => "/tmp",
|
106
|
+
"logdir" => "/var/log"
|
107
|
+
}
|
108
|
+
|
109
|
+
# Returns array of variables in the object. Variables can be either '$name' or
|
110
|
+
# '${name}'. The variables are returned in left-to-right order
|
111
|
+
#
|
112
|
+
def collect_variables(object, include_keys: false)
|
113
|
+
case object
|
114
|
+
when Array; object.map { |obj| collect_variables(obj) }
|
115
|
+
when Hash; object.map { |k,v| (include_keys ? collect_variables(k) : []) + collect_variables(v) }
|
116
|
+
when String; object.scan(/\$([\w_]+)|\$\{([\w_]+)\}/)
|
117
|
+
when Integer, Float, true, false, nil; []
|
118
|
+
else
|
119
|
+
raise "Illegal object: #{object}"
|
120
|
+
end.flatten.compact.uniq
|
121
|
+
end
|
122
|
+
|
123
|
+
# Expand variables in the given string
|
124
|
+
#
|
125
|
+
# The method takes case to substite left-to-rigth to avoid a variable expansion
|
126
|
+
# to infer with the name of an immediately preceding variable. Eg. $a$b; if $b
|
127
|
+
# is resolved to 'c' then a search would otherwise be made for a variable named
|
128
|
+
# '$ac'
|
129
|
+
#
|
130
|
+
def expand_variables(object, include_key: false)
|
131
|
+
case object
|
132
|
+
when Array; object.map { |e| expand_variables(e) }
|
133
|
+
when Hash; object.map { |k,v| [expand_variables(k), expand_variables(v)] }.to_h
|
134
|
+
when String
|
135
|
+
s = object.dup
|
136
|
+
collect_variables(object).each { |k| s.sub!(/\$#{k}|\$\{#{k}\}/, fields[k].to_s) }
|
137
|
+
s
|
138
|
+
when Integer, Float, true, false, nil; object
|
139
|
+
else
|
140
|
+
raise "Illegal object: #{object}"
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
# Expands fields (but not directories). The algorithm allows fields to be
|
145
|
+
# defined in any order
|
146
|
+
#
|
147
|
+
def expand_fields
|
148
|
+
variables = fields.map { |k,v| [k, collect_variables(v)] }.to_h
|
149
|
+
variables.values.flatten.uniq.each { |var|
|
150
|
+
fields[var].nil? || fields[var].is_a?(String) or "Can't use '#{var}' as variable"
|
151
|
+
}
|
152
|
+
|
153
|
+
@fields, unresolved = fields.partition { |k,v| variables[k].empty? }.map(&:to_h)
|
154
|
+
changed = true
|
155
|
+
while changed && !unresolved.empty?
|
156
|
+
changed = false
|
157
|
+
unresolved.delete_if { |k,v|
|
158
|
+
if variables[k].all? { |var| fields.key? var }
|
159
|
+
fields[k] = expand_variables(unresolved[k])
|
160
|
+
changed = true
|
161
|
+
end
|
162
|
+
}
|
163
|
+
end
|
164
|
+
unresolved.empty? or raise "Unresolved variables: #{unresolved.join(", ")}"
|
165
|
+
end
|
166
|
+
|
167
|
+
def expand_dirs
|
168
|
+
@dirs = expand_variables(dirs)
|
169
|
+
end
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
173
|
+
|
data/lib/qrpm/qrpm.rb
ADDED
@@ -0,0 +1,63 @@
|
|
1
|
+
|
2
|
+
__END__
|
3
|
+
# Returns array of variables in the string. Variables can be either '$name' or
|
4
|
+
# '${name}'. The variables are returned in left-to-right order
|
5
|
+
#
|
6
|
+
def collect_exprs(expr)
|
7
|
+
expr.scan(/\$([\w_]+)|\$\{([\w_]+)\}/).flatten.compact
|
8
|
+
end
|
9
|
+
|
10
|
+
# Expand variables in the given string
|
11
|
+
#
|
12
|
+
# The method takes case to substite left-to-rigth to avoid a variable expansion
|
13
|
+
# to infer with the name of an immediately preceding variable. Eg. $a$b; if $b
|
14
|
+
# is resolved to 'c' then a search would otherwise be made for a variable named
|
15
|
+
# '$ac'
|
16
|
+
#
|
17
|
+
def expand_expr(dict, value)
|
18
|
+
value = value.dup
|
19
|
+
collect_exprs(value).each { |k| value.sub!(/\$#{k}|\$\{#{k}\}/, dict[k]) }
|
20
|
+
value
|
21
|
+
end
|
22
|
+
|
23
|
+
def expand_dict(dict)
|
24
|
+
expressions = dict.map { |k,v| [k, collect_exprs(v)] }.to_h
|
25
|
+
result = expressions.select { |k, v| v.empty? }.map { |k,v| [k, dict[k]] }.to_h
|
26
|
+
unresolved = dict.keys - result.keys
|
27
|
+
|
28
|
+
changed = true
|
29
|
+
while changed && !unresolved.empty?
|
30
|
+
changed = false
|
31
|
+
unresolved.delete_if { |k|
|
32
|
+
if expressions[k].all? { |var| result.key? var }
|
33
|
+
result[k] = expand_expr(result, dict[k])
|
34
|
+
changed = true
|
35
|
+
end
|
36
|
+
}
|
37
|
+
end
|
38
|
+
unresolved.empty? or raise "Unresolved variables: #{unresolved.join(", ")}"
|
39
|
+
|
40
|
+
result
|
41
|
+
end
|
42
|
+
|
43
|
+
# +value+ will typically be a dirs hash
|
44
|
+
def expand_object(dict, object)
|
45
|
+
case object
|
46
|
+
when Array; object.map { |v| expand_object(dict, v) }
|
47
|
+
when Hash
|
48
|
+
object.map { |k,v|
|
49
|
+
key = expand_expr(dict, k)
|
50
|
+
object = expand_object(dict, v)
|
51
|
+
[key, object]
|
52
|
+
}.to_h
|
53
|
+
when String
|
54
|
+
expand_expr(dict, object)
|
55
|
+
else
|
56
|
+
object
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def expand_dirs(dict, dirs)
|
61
|
+
expand_object(dict, dirs)
|
62
|
+
end
|
63
|
+
|
data/lib/qrpm/render.rb
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
module Qrpm
|
2
|
+
class RpmBuilder
|
3
|
+
def initialize
|
4
|
+
end
|
5
|
+
|
6
|
+
def build
|
7
|
+
# Create directories
|
8
|
+
|
9
|
+
# Collect sources
|
10
|
+
|
11
|
+
# Copy sources
|
12
|
+
|
13
|
+
# Create spec file
|
14
|
+
end
|
15
|
+
|
16
|
+
|
17
|
+
end
|
18
|
+
|
19
|
+
|
20
|
+
|
21
|
+
|
22
|
+
def render(dict, files)
|
23
|
+
|
24
|
+
end
|
25
|
+
end
|
data/lib/qrpm/rpm.rb
ADDED
@@ -0,0 +1,114 @@
|
|
1
|
+
require 'erb'
|
2
|
+
require 'fileutils'
|
3
|
+
|
4
|
+
module Qrpm
|
5
|
+
class Rpm
|
6
|
+
# Defines the following member methods:
|
7
|
+
#
|
8
|
+
# name Package name
|
9
|
+
# version Version
|
10
|
+
# release Release
|
11
|
+
# license License (defaults to GPL)
|
12
|
+
# summary Short one-line description of package
|
13
|
+
# description Description
|
14
|
+
# packager Name of the packager (defaults to the value of the $USER
|
15
|
+
# environment variable)
|
16
|
+
# require Array of required packages
|
17
|
+
# make Controls the build process:
|
18
|
+
# null Search the top-level directory for configure or
|
19
|
+
# make files and runs them. Skip building if not
|
20
|
+
# found. This is the default
|
21
|
+
# true Expect the top-level directory to contain
|
22
|
+
# configure make files and runs them. It is an
|
23
|
+
# error if the Makefile is missing
|
24
|
+
# (array of commands)
|
25
|
+
# Runs the commands to build the project
|
26
|
+
#
|
27
|
+
FIELDS = %w(name version release group license summary description packager requires make)
|
28
|
+
MANDATORY_FIELDS = %w(name summary version)
|
29
|
+
TEMPLATE = "#{::File.dirname(__FILE__)}/template.erb"
|
30
|
+
|
31
|
+
RPM_DIRS = %w(SOURCES BUILD RPMS SPECS SRPMS tmp)
|
32
|
+
|
33
|
+
# Field accessor methods
|
34
|
+
FIELDS.each { |f| eval "def #{f}() @fields[\"#{f}\"] end" }
|
35
|
+
|
36
|
+
attr_reader :fields
|
37
|
+
attr_reader :nodes
|
38
|
+
|
39
|
+
# The content of the SPEC file
|
40
|
+
attr_reader :spec
|
41
|
+
|
42
|
+
def files() @files ||= nodes.select(&:file?) end
|
43
|
+
def links() @lines ||= nodes.select(&:link?) end
|
44
|
+
|
45
|
+
def has_configure?() ::File.exist? "configure" end
|
46
|
+
def has_make?() ::File.exist? "make" end
|
47
|
+
|
48
|
+
def initialize(fields, nodes, template: TEMPLATE)
|
49
|
+
@fields, @nodes = fields, nodes
|
50
|
+
@template = template
|
51
|
+
end
|
52
|
+
|
53
|
+
def build(target: :rpm, file: nil)
|
54
|
+
Dir.mktmpdir { |rootdir|
|
55
|
+
rootdir = "/home/clr/prj/qrpm/tmp"
|
56
|
+
FileUtils.rm_rf(rootdir)
|
57
|
+
FileUtils.mkdir_p(rootdir)
|
58
|
+
|
59
|
+
spec_file = file || "#{name}.spec"
|
60
|
+
tar_file = "#{name}.tar.gz"
|
61
|
+
spec_path = "#{rootdir}/SPECS/#{spec_file}"
|
62
|
+
tar_path = "#{rootdir}/SOURCES/#{tar_file}"
|
63
|
+
|
64
|
+
# Create directories
|
65
|
+
RPM_DIRS.each { |dir| FileUtils.mkdir_p "#{rootdir}/#{dir}" }
|
66
|
+
|
67
|
+
# Directory for tarball creation. This lives inside the RPM directory
|
68
|
+
# structure and is removed before we start rpmbuild
|
69
|
+
tarroot = "#{rootdir}/tmp/#{name}"
|
70
|
+
FileUtils.mkdir(tarroot)
|
71
|
+
|
72
|
+
# Copy files
|
73
|
+
FileUtils.cp_r(".", tarroot, preserve: true)
|
74
|
+
|
75
|
+
# Roll tarball and put it in the SOURCES directory
|
76
|
+
system "tar zcf #{tar_path} -C #{rootdir}/tmp #{name}" or raise "Can't roll tarball"
|
77
|
+
|
78
|
+
# Remove temporary tar dir
|
79
|
+
FileUtils.rm_rf tarroot
|
80
|
+
|
81
|
+
# Create spec file
|
82
|
+
renderer = ERB.new(IO.read(@template).sub(/^__END__\n.*/m, ""), trim_mode: "-")
|
83
|
+
@spec = renderer.result(binding)
|
84
|
+
|
85
|
+
# Emit spec or build RPM
|
86
|
+
if target == :spec
|
87
|
+
IO.write(spec_file, @spec)
|
88
|
+
else
|
89
|
+
IO.write(spec_path, @spec)
|
90
|
+
system "rpmbuild -v -ba --define \"_topdir #{rootdir}\" #{rootdir}/SPECS/#{name}.spec" or
|
91
|
+
raise "Failed building RPM file"
|
92
|
+
if target == :srpm
|
93
|
+
system "cp #{rootdir}/SRPMS/* ." or raise "Failed copying SRPM file"
|
94
|
+
elsif target == :rpm
|
95
|
+
system "cp #{rootdir}/RPMS/*/#{name}-[0-9]* ." or raise "Failed copying RPM file"
|
96
|
+
else
|
97
|
+
raise ArgumentError, "Not a valid value for :target - #{target.inspect}"
|
98
|
+
end
|
99
|
+
end
|
100
|
+
}
|
101
|
+
end
|
102
|
+
|
103
|
+
def dump
|
104
|
+
puts self.class
|
105
|
+
indent {
|
106
|
+
puts "fields"
|
107
|
+
indent { fields.each { |k,v| puts "#{k}: #{v.inspect}" } }
|
108
|
+
puts "nodes"
|
109
|
+
indent { nodes.map(&:dump) }
|
110
|
+
}
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
@@ -0,0 +1,73 @@
|
|
1
|
+
|
2
|
+
Name: <%= name %>
|
3
|
+
Summary: <%= summary %>
|
4
|
+
Version: <%= version %>
|
5
|
+
Release: <%= release %>
|
6
|
+
License: <%= license %>
|
7
|
+
Packager: <%= packager %>
|
8
|
+
<% if group -%>
|
9
|
+
Group: <%= group %>
|
10
|
+
<% end -%>
|
11
|
+
<% for pck in requires || [] -%>
|
12
|
+
Requires: <%= pck %>
|
13
|
+
<% end -%>
|
14
|
+
Source: %{name}.tar.gz
|
15
|
+
BuildRoot: <%= rootdir %>/tmp/%{name}-%{version}
|
16
|
+
|
17
|
+
%description
|
18
|
+
<%= description %>
|
19
|
+
|
20
|
+
%prep
|
21
|
+
%setup -n <%= name %>
|
22
|
+
|
23
|
+
%build
|
24
|
+
<% if make.nil? -%>
|
25
|
+
<% if has_configure? -%>
|
26
|
+
./configure
|
27
|
+
<% end -%>
|
28
|
+
<% if has_make? -%>
|
29
|
+
make
|
30
|
+
<% end -%>
|
31
|
+
<% elsif make == false -%>
|
32
|
+
<% elsif make == true -%>
|
33
|
+
<% if has_configure? -%>
|
34
|
+
./configure
|
35
|
+
<% end -%>
|
36
|
+
make
|
37
|
+
<% elsif make.is_a? Array -%>
|
38
|
+
<% for cmd in make -%>
|
39
|
+
<%= cmd %>
|
40
|
+
<% end -%>
|
41
|
+
<% end -%>
|
42
|
+
|
43
|
+
%install
|
44
|
+
mkdir -p <%= nodes.map { |f| "%{buildroot}#{f.directory}" }.uniq.join(" ") %>
|
45
|
+
<% for file in files -%>
|
46
|
+
cp <%= file.file %> %{buildroot}<%= file.path %>
|
47
|
+
<% end -%>
|
48
|
+
<% for link in links -%>
|
49
|
+
touch %{buildroot}<%= link.path %>
|
50
|
+
<% end -%>
|
51
|
+
|
52
|
+
%files
|
53
|
+
<% for file in files -%>
|
54
|
+
<%= file.path %>
|
55
|
+
<% end -%>
|
56
|
+
<% for link in links -%>
|
57
|
+
%ghost <%= link.path %>
|
58
|
+
<% end -%>
|
59
|
+
|
60
|
+
%clean
|
61
|
+
%if "%{clean}" != ""
|
62
|
+
rm -rf %{_topdir}/BUILD/%{name}
|
63
|
+
[ $(basename %{buildroot}) == "%{name}-%{version}-%{release}.%{_target_cpu}" ] && rm -rf %{buildroot}
|
64
|
+
%endif
|
65
|
+
|
66
|
+
%post
|
67
|
+
<% for file in files.select(&:perm) -%>
|
68
|
+
chmod <%= file.perm %> <%= file.path %>
|
69
|
+
<% end -%>
|
70
|
+
<% for file in links -%>
|
71
|
+
ln -sf <%= link.link %> <%= link.path %>
|
72
|
+
<% end -%>
|
73
|
+
|
@@ -0,0 +1,88 @@
|
|
1
|
+
|
2
|
+
# Package information
|
3
|
+
#
|
4
|
+
name: # Name of package. It is used in the package name
|
5
|
+
summary: # Short summary of package
|
6
|
+
description: # Optional longer description
|
7
|
+
version: # Version
|
8
|
+
release: # Release. Optional
|
9
|
+
packager: # Packager, default $USER
|
10
|
+
requires: # List of required packages
|
11
|
+
|
12
|
+
# Build information
|
13
|
+
#
|
14
|
+
make: null # make can be undefined or null (use make if present), false
|
15
|
+
# (don't use make), true (use make), or a list of shell
|
16
|
+
# commands to build the project
|
17
|
+
|
18
|
+
# Directories, files, and links
|
19
|
+
#
|
20
|
+
# This section contains entries that are (possibly empty) directories with a
|
21
|
+
# array of files or links. Directories can either identify a builtin standard
|
22
|
+
# directory or be a path to a directory. In the typical case, the directory
|
23
|
+
# will contain a simple list of files from the build directory:
|
24
|
+
#
|
25
|
+
# bindir:
|
26
|
+
# - my_bin_files/my_program
|
27
|
+
# - my_sh_files/my_shell_script
|
28
|
+
#
|
29
|
+
# /opt/my_files:
|
30
|
+
# - src/my_data
|
31
|
+
#
|
32
|
+
# The example will create the following files and directories
|
33
|
+
#
|
34
|
+
# /usr/bin/my_program
|
35
|
+
# /usr/bin/my_shell_script
|
36
|
+
# /opt/my_files/
|
37
|
+
# /opt/my_files/my_data
|
38
|
+
#
|
39
|
+
# Files can also be specified using the following attributes
|
40
|
+
#
|
41
|
+
# name: Destination file name. Default is the last path component in :file
|
42
|
+
# file: Path to source file
|
43
|
+
# perm: Octal permissions. Defaults are the source file's permissions
|
44
|
+
#
|
45
|
+
# It is used like this
|
46
|
+
#
|
47
|
+
# /opt/my_files
|
48
|
+
# - name: data
|
49
|
+
# file: src/my_data
|
50
|
+
# perm: 600
|
51
|
+
#
|
52
|
+
# This will copy src/my_data to a 'data' file in the /opt/my_files directory
|
53
|
+
# with permissions 0600
|
54
|
+
#
|
55
|
+
# Links can only be specified using attributes
|
56
|
+
#
|
57
|
+
# name: Destination file name. Default is the last path component in :link
|
58
|
+
# link: Path to the file that will be pointed to by the link
|
59
|
+
#
|
60
|
+
# To create a symbolic link in /var/lib/ from my_app to /opt/my_files/data:
|
61
|
+
#
|
62
|
+
# libdir:
|
63
|
+
# - name: my_app
|
64
|
+
# link: /opt/my_files/data
|
65
|
+
#
|
66
|
+
# The following standard directories are defined:
|
67
|
+
#
|
68
|
+
# etcdir /etc Configuration files
|
69
|
+
# bindir /usr/bin Executables
|
70
|
+
# sbindir /usr/sbin System executables
|
71
|
+
# libdir /usr/lib Libraries (both binary and clear text)
|
72
|
+
# libexecdir /usr/libexec Executable subprograms (not meant to be
|
73
|
+
# called indepentently)
|
74
|
+
# sharedir /usr/share Constant data files. FIXME: Always a subdir
|
75
|
+
# vardir /var/lib Variable data files
|
76
|
+
# spooldir /var/spool Spool files
|
77
|
+
# rundir /var/run Run files
|
78
|
+
# lockdir /var/lock Lock files
|
79
|
+
# cachedir /var/cache Cache directory
|
80
|
+
# tmpdir /tmp Temporary directory (deleted when the '
|
81
|
+
# machine starts)
|
82
|
+
# logdir /var/log Log directory
|
83
|
+
#
|
84
|
+
# Each standard directory can also be prefixed a 'pck'. That will create a
|
85
|
+
# subdirectory with the package's name in the base standard directory. Eg.
|
86
|
+
# 'pcketcdir' will create the directory '/etc/<name>'
|
87
|
+
#
|
88
|
+
|
data/lib/qrpm/version.rb
ADDED
data/lib/qrpm.rb
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "qrpm/version"
|
4
|
+
require_relative "qrpm/node.rb"
|
5
|
+
require_relative "qrpm/rpm.rb"
|
6
|
+
require_relative "qrpm/parser.rb"
|
7
|
+
|
8
|
+
module Qrpm
|
9
|
+
class Error < RuntimeError; end
|
10
|
+
|
11
|
+
QRPM_CONFIG_FILE = "qrpm.yml"
|
12
|
+
|
13
|
+
QRPM_SHARE_DIR = "#{::File.dirname(__FILE__)}/../lib/qrpm"
|
14
|
+
QRPM_CONFIG_FILE_TEMPLATE = "#{QRPM_SHARE_DIR}/template.yml"
|
15
|
+
QRPM_ERB_FILE = "#{QRPM_SHARE_DIR}/template.erb"
|
16
|
+
end
|
data/packager.sh
ADDED
@@ -0,0 +1,65 @@
|
|
1
|
+
#!/usr/bin/bash
|
2
|
+
|
3
|
+
# This scripts creates and build a simple RPM package
|
4
|
+
#
|
5
|
+
# Prerequisites:
|
6
|
+
# - rpm-build, make and gcc (as it's a c file) packages must be installed
|
7
|
+
#
|
8
|
+
|
9
|
+
# Ref. http://aerostitch.github.io/linux_and_unix/RedHat/build_sample_rpm.html
|
10
|
+
|
11
|
+
# Holds the name of the root directory containing the necessary structure to
|
12
|
+
# build RPM packages.
|
13
|
+
RPM_ROOT_DIR=~/rpm_factory
|
14
|
+
|
15
|
+
PKG_NAME=dummy_package
|
16
|
+
PKG_TAR=/tmp/${PKG_NAME}.tar.gz
|
17
|
+
BINARY_FILE=hello_world
|
18
|
+
# Recreate the root directory and its structure if necessary
|
19
|
+
mkdir -p ${RPM_ROOT_DIR}/{SOURCES,BUILD,RPMS,SPECS,SRPMS,tmp}
|
20
|
+
pushd $RPM_ROOT_DIR
|
21
|
+
cp ${PKG_TAR} ${RPM_ROOT_DIR}/SOURCES/
|
22
|
+
|
23
|
+
# Creating a basic spec file
|
24
|
+
cat << __EOF__ > ${RPM_ROOT_DIR}/SPECS/${PKG_NAME}.spec
|
25
|
+
Summary: This package is a sample for quickly build dummy RPM package.
|
26
|
+
Name: $PKG_NAME
|
27
|
+
Version: 1.0
|
28
|
+
Release: 0
|
29
|
+
License: GPL
|
30
|
+
Packager: $USER
|
31
|
+
Group: Development/Tools
|
32
|
+
Source: %{name}.tar.gz
|
33
|
+
BuildRequires: coreutils
|
34
|
+
BuildRoot: ${RPM_ROOT_DIR}/tmp/%{name}-%{version}
|
35
|
+
|
36
|
+
%description
|
37
|
+
%{summary}
|
38
|
+
|
39
|
+
%prep
|
40
|
+
%setup -n ${PKG_NAME}
|
41
|
+
|
42
|
+
%build
|
43
|
+
make $BINARY_FILE
|
44
|
+
|
45
|
+
%install
|
46
|
+
mkdir -p "%{buildroot}/opt/${PKG_NAME}"
|
47
|
+
cp $BINARY_FILE "%{buildroot}/opt/${PKG_NAME}/"
|
48
|
+
|
49
|
+
%files
|
50
|
+
/opt/${PKG_NAME}/hello_world
|
51
|
+
|
52
|
+
%clean
|
53
|
+
%if "%{clean}" != ""
|
54
|
+
rm -rf %{_topdir}/BUILD/%{name}
|
55
|
+
[ $(basename %{buildroot}) == "%{name}-%{version}-%{release}.%{_target_cpu}" ] && rm -rf %{buildroot}
|
56
|
+
%endif
|
57
|
+
|
58
|
+
%post
|
59
|
+
chmod 755 -R /opt/${PKG_NAME}
|
60
|
+
__EOF__
|
61
|
+
|
62
|
+
rpmbuild -v -bb --define "_topdir ${RPM_ROOT_DIR}" SPECS/${PKG_NAME}.spec
|
63
|
+
popd
|
64
|
+
|
65
|
+
|
data/packager.yml
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
|
2
|
+
name: my_package_name$pg_version
|
3
|
+
summary: This is a summary of the package
|
4
|
+
description: Optional longer description of the package
|
5
|
+
version: 1.2.3
|
6
|
+
release: $pg_version.$perm
|
7
|
+
packager: null
|
8
|
+
requires:
|
9
|
+
- ruby
|
10
|
+
- apache
|
11
|
+
- postgres$pg_version
|
12
|
+
|
13
|
+
pg_version: 13
|
14
|
+
perm: 755
|
15
|
+
root: example
|
16
|
+
|
17
|
+
bindir:
|
18
|
+
- $root/bin/a_file
|
19
|
+
- $root/bin/another_file
|
20
|
+
- name: an_alias
|
21
|
+
file: $root/bin/a_file
|
22
|
+
|
23
|
+
sbindir:
|
24
|
+
- link: /bin/a_file
|
25
|
+
|
26
|
+
pcksharedir:
|
27
|
+
- $root/share/some_data
|
28
|
+
|
29
|
+
vardir:
|
30
|
+
- $root/share/some_other_data
|
31
|
+
|
32
|
+
|
data/program.sh
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
#!/usr/bin/bash
|
2
|
+
|
3
|
+
# Ref. http://aerostitch.github.io/linux_and_unix/RedHat/build_sample_rpm.html
|
4
|
+
|
5
|
+
PKG_NAME=dummy_package
|
6
|
+
PKG_DIR=/tmp/${PKG_NAME}
|
7
|
+
mkdir -p ${PKG_DIR}
|
8
|
+
|
9
|
+
cat << __EOF__ > ${PKG_DIR}/hello_world.c
|
10
|
+
#include <stdio.h>
|
11
|
+
int main(){
|
12
|
+
printf("Hello world!\n");
|
13
|
+
return 0;
|
14
|
+
}
|
15
|
+
__EOF__
|
16
|
+
|
17
|
+
pushd ${PKG_DIR}/..
|
18
|
+
tar czvf ${PKG_NAME}.tar.gz ${PKG_NAME}
|
19
|
+
popd
|
data/qrpm.gemspec
ADDED
@@ -0,0 +1,47 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "lib/qrpm/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |spec|
|
6
|
+
spec.name = "qrpm"
|
7
|
+
spec.version = Qrpm::VERSION
|
8
|
+
spec.authors = ["Claus Rasmussen"]
|
9
|
+
spec.email = ["claus.l.rasmussen@gmail.com"]
|
10
|
+
|
11
|
+
spec.summary = "Gem qrpm"
|
12
|
+
spec.description = "Gem qrpm"
|
13
|
+
spec.homepage = "http://www.nowhere.com/"
|
14
|
+
spec.required_ruby_version = ">= 2.4.0"
|
15
|
+
|
16
|
+
|
17
|
+
spec.metadata["homepage_uri"] = spec.homepage
|
18
|
+
|
19
|
+
# Specify which files should be added to the gem when it is released.
|
20
|
+
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
21
|
+
spec.files = Dir.chdir(File.expand_path(__dir__)) do
|
22
|
+
`git ls-files -z`.split("\x0").reject do |f|
|
23
|
+
(f == __FILE__) || f.match(%r{\A(?:(?:test|spec|features)/|\.(?:git|travis|circleci)|appveyor)})
|
24
|
+
end
|
25
|
+
end
|
26
|
+
spec.bindir = "exe"
|
27
|
+
spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
|
28
|
+
spec.require_paths = ["lib"]
|
29
|
+
|
30
|
+
spec.add_dependency "shellopts", "~> 2.0.0"
|
31
|
+
spec.add_dependency "indented_io"
|
32
|
+
|
33
|
+
# Uncomment to register a new dependency of your gem
|
34
|
+
# spec.add_dependency "example-gem", "~> 1.0"
|
35
|
+
|
36
|
+
# For more information and examples about making a new gem, checkout our
|
37
|
+
# guide at: https://bundler.io/guides/creating_gem.html
|
38
|
+
|
39
|
+
# Add your production dependencies here
|
40
|
+
# spec.add_dependency GEM [, VERSION]
|
41
|
+
|
42
|
+
# Add your development dependencies here
|
43
|
+
# spec.add_development_dependency GEM [, VERSION]
|
44
|
+
|
45
|
+
# Also un-comment in spec/spec_helper to use simplecov
|
46
|
+
# spec.add_development_dependency "simplecov"
|
47
|
+
end
|
metadata
ADDED
@@ -0,0 +1,100 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: qrpm
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Claus Rasmussen
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2022-05-03 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: shellopts
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 2.0.0
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 2.0.0
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: indented_io
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
description: Gem qrpm
|
42
|
+
email:
|
43
|
+
- claus.l.rasmussen@gmail.com
|
44
|
+
executables:
|
45
|
+
- qrpm
|
46
|
+
extensions: []
|
47
|
+
extra_rdoc_files: []
|
48
|
+
files:
|
49
|
+
- ".rspec"
|
50
|
+
- ".ruby-version"
|
51
|
+
- Gemfile
|
52
|
+
- README.md
|
53
|
+
- Rakefile
|
54
|
+
- bin/console
|
55
|
+
- bin/setup
|
56
|
+
- clean
|
57
|
+
- cmd
|
58
|
+
- example/bin/a_file
|
59
|
+
- example/bin/another_file
|
60
|
+
- example/qrpm.yml
|
61
|
+
- example/share/some_data
|
62
|
+
- example/share/some_other_data
|
63
|
+
- exe/qrpm
|
64
|
+
- lib/qrpm.rb
|
65
|
+
- lib/qrpm/node.rb
|
66
|
+
- lib/qrpm/parser.rb
|
67
|
+
- lib/qrpm/qrpm.rb
|
68
|
+
- lib/qrpm/render.rb
|
69
|
+
- lib/qrpm/rpm.rb
|
70
|
+
- lib/qrpm/template.erb
|
71
|
+
- lib/qrpm/template.yml
|
72
|
+
- lib/qrpm/version.rb
|
73
|
+
- packager.sh
|
74
|
+
- packager.yml
|
75
|
+
- program.sh
|
76
|
+
- qrpm.gemspec
|
77
|
+
homepage: http://www.nowhere.com/
|
78
|
+
licenses: []
|
79
|
+
metadata:
|
80
|
+
homepage_uri: http://www.nowhere.com/
|
81
|
+
post_install_message:
|
82
|
+
rdoc_options: []
|
83
|
+
require_paths:
|
84
|
+
- lib
|
85
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: 2.4.0
|
90
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
91
|
+
requirements:
|
92
|
+
- - ">="
|
93
|
+
- !ruby/object:Gem::Version
|
94
|
+
version: '0'
|
95
|
+
requirements: []
|
96
|
+
rubygems_version: 3.1.4
|
97
|
+
signing_key:
|
98
|
+
specification_version: 4
|
99
|
+
summary: Gem qrpm
|
100
|
+
test_files: []
|