qrpm 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- 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: []
|