fpm 1.4.0 → 1.5.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/CHANGELIST +32 -1
- data/lib/fpm.rb +1 -0
- data/lib/fpm/command.rb +49 -30
- data/lib/fpm/package.rb +4 -4
- data/lib/fpm/package/cpan.rb +20 -7
- data/lib/fpm/package/deb.rb +160 -32
- data/lib/fpm/package/dir.rb +2 -2
- data/lib/fpm/package/freebsd.rb +165 -0
- data/lib/fpm/package/osxpkg.rb +2 -2
- data/lib/fpm/package/pacman.rb +398 -0
- data/lib/fpm/package/pyfpm/__init__.pyc +0 -0
- data/lib/fpm/package/pyfpm/get_metadata.pyc +0 -0
- data/lib/fpm/package/rpm.rb +33 -7
- data/lib/fpm/package/tar.rb +2 -2
- data/lib/fpm/package/virtualenv.rb +12 -3
- data/lib/fpm/rake_task.rb +59 -0
- data/lib/fpm/util.rb +3 -6
- data/lib/fpm/version.rb +1 -1
- data/templates/deb/postinst_upgrade.sh.erb +19 -0
- data/templates/deb/prerm_upgrade.sh.erb +7 -0
- data/templates/pacman.erb +47 -0
- data/templates/pacman/INSTALL.erb +41 -0
- data/templates/rpm.erb +4 -1
- data/templates/sh.erb +16 -2
- metadata +67 -4
data/lib/fpm/package/dir.rb
CHANGED
@@ -128,7 +128,7 @@ class FPM::Package::Dir < FPM::Package
|
|
128
128
|
"to stage files during packaging, so this setting would have " \
|
129
129
|
"caused fpm to loop creating staging directories and copying " \
|
130
130
|
"them into your package! Oops! If you are confused, maybe you could " \
|
131
|
-
"check your TMPDIR or
|
131
|
+
"check your TMPDIR, TMP, or TEMP environment variables?"
|
132
132
|
end
|
133
133
|
|
134
134
|
# For single file copies, permit file destinations
|
@@ -160,7 +160,7 @@ class FPM::Package::Dir < FPM::Package
|
|
160
160
|
# lstat to follow symlinks
|
161
161
|
dstat = File.stat(directory) rescue nil
|
162
162
|
if dstat.nil?
|
163
|
-
FileUtils.mkdir_p(directory)
|
163
|
+
FileUtils.mkdir_p(directory, :mode => 0755)
|
164
164
|
elsif dstat.directory?
|
165
165
|
# do nothing, it's already a directory!
|
166
166
|
else
|
@@ -0,0 +1,165 @@
|
|
1
|
+
require "backports" # gem backports
|
2
|
+
require "fpm/package"
|
3
|
+
require "fpm/util"
|
4
|
+
require "digest"
|
5
|
+
require "fileutils"
|
6
|
+
require "rubygems/package"
|
7
|
+
require "xz"
|
8
|
+
require "corefines"
|
9
|
+
|
10
|
+
class FPM::Package::FreeBSD < FPM::Package
|
11
|
+
SCRIPT_MAP = {
|
12
|
+
:before_install => "pre-install",
|
13
|
+
:after_install => "post-install",
|
14
|
+
:before_remove => "pre-deinstall",
|
15
|
+
:after_remove => "post-deinstall",
|
16
|
+
} unless defined?(SCRIPT_MAP)
|
17
|
+
|
18
|
+
def self.default_abi
|
19
|
+
abi_name = %x{uname -s}.chomp
|
20
|
+
abi_version = %x{uname -r}.chomp.split(".")[0]
|
21
|
+
abi_arch = %x{uname -m}.chomp
|
22
|
+
|
23
|
+
[abi_name, abi_version, abi_arch].join(":")
|
24
|
+
end
|
25
|
+
|
26
|
+
option "--abi", "ABI",
|
27
|
+
"Sets the FreeBSD abi pkg field to specify binary compatibility.",
|
28
|
+
:default => default_abi
|
29
|
+
|
30
|
+
option "--origin", "ABI",
|
31
|
+
"Sets the FreeBSD 'origin' pkg field",
|
32
|
+
:default => "fpm/<name>"
|
33
|
+
|
34
|
+
def output(output_path)
|
35
|
+
output_check(output_path)
|
36
|
+
|
37
|
+
# Build the packaging metadata files.
|
38
|
+
checksums = {}
|
39
|
+
self.files.each do |f|
|
40
|
+
path = staging_path(f)
|
41
|
+
if File.symlink?(path)
|
42
|
+
checksums[f] = "-"
|
43
|
+
elsif File.file?(path)
|
44
|
+
checksums[f] = Digest::SHA256.file(path).hexdigest
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
pkg_origin = attributes[:freebsd_origin]
|
49
|
+
if pkg_origin == "fpm/<name>" # fill in default
|
50
|
+
pkg_origin = "fpm/#{name}"
|
51
|
+
end
|
52
|
+
|
53
|
+
pkg_version = "#{version}-#{iteration || 1}"
|
54
|
+
|
55
|
+
pkgdata = {
|
56
|
+
"abi" => attributes[:freebsd_abi],
|
57
|
+
"name" => name,
|
58
|
+
"version" => pkg_version,
|
59
|
+
"comment" => description,
|
60
|
+
"desc" => description,
|
61
|
+
"origin" => pkg_origin,
|
62
|
+
"maintainer" => maintainer,
|
63
|
+
"www" => url,
|
64
|
+
# prefix is required, but it doesn't seem to matter
|
65
|
+
"prefix" => "/",
|
66
|
+
}
|
67
|
+
|
68
|
+
# Write +COMPACT_MANIFEST, without the "files" section.
|
69
|
+
File.open(staging_path("+COMPACT_MANIFEST"), "w+") do |file|
|
70
|
+
file.write(pkgdata.to_json + "\n")
|
71
|
+
end
|
72
|
+
|
73
|
+
# Populate files + checksums, then write +MANIFEST.
|
74
|
+
pkgdata["files"] = {}
|
75
|
+
checksums.each do |f, shasum|
|
76
|
+
# pkg expands % URL-style escapes, so make sure to escape % as %25
|
77
|
+
pkgdata["files"]["/" + f.gsub("%", "%25")] = shasum
|
78
|
+
end
|
79
|
+
|
80
|
+
# Populate scripts
|
81
|
+
pkgdata["scripts"] = {}
|
82
|
+
scripts.each do |name, data|
|
83
|
+
pkgdata["scripts"][SCRIPT_MAP[name]] = data
|
84
|
+
end
|
85
|
+
|
86
|
+
File.open(staging_path("+MANIFEST"), "w+") do |file|
|
87
|
+
file.write(pkgdata.to_json + "\n")
|
88
|
+
end
|
89
|
+
|
90
|
+
# Create the .txz package archive from the files in staging_path.
|
91
|
+
File.open(output_path, "wb") do |file|
|
92
|
+
XZ::StreamWriter.new(file) do |xz|
|
93
|
+
::Gem::Package::TarWriter.new(xz) do |tar|
|
94
|
+
# The manifests must come first for pkg.
|
95
|
+
add_path(tar, "+COMPACT_MANIFEST",
|
96
|
+
File.join(staging_path, "+COMPACT_MANIFEST"))
|
97
|
+
add_path(tar, "+MANIFEST",
|
98
|
+
File.join(staging_path, "+MANIFEST"))
|
99
|
+
|
100
|
+
checksums.keys.each do |path|
|
101
|
+
add_path(tar, "/" + path, File.join(staging_path, path))
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end # def output
|
107
|
+
|
108
|
+
def add_path(tar, tar_path, path)
|
109
|
+
stat = File.lstat(path)
|
110
|
+
if stat.directory?
|
111
|
+
tar.mkdir(tar_path, stat.mode)
|
112
|
+
elsif stat.symlink?
|
113
|
+
tar.add_symlink(tar_path, File.readlink(path), stat.mode)
|
114
|
+
else
|
115
|
+
tar.add_file_simple(tar_path, stat.mode, stat.size) do |io|
|
116
|
+
File.open(path) do |fd|
|
117
|
+
chunk = nil
|
118
|
+
size = 0
|
119
|
+
while chunk = fd.read(16384) do
|
120
|
+
size += io.write(chunk)
|
121
|
+
end
|
122
|
+
if size != stat.size
|
123
|
+
raise "Failed to add #{path} to the archive; expected to " +
|
124
|
+
"write #{stat.size} bytes, only wrote #{size}"
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end # tar.tar.add_file_simple
|
128
|
+
end
|
129
|
+
end # def add_path
|
130
|
+
|
131
|
+
def to_s(format=nil)
|
132
|
+
return "#{name}-#{version}_#{iteration || 1}.txz"
|
133
|
+
return super(format)
|
134
|
+
end # def to_s
|
135
|
+
end # class FPM::Package::FreeBSD
|
136
|
+
|
137
|
+
# Backport Symlink Support to TarWriter
|
138
|
+
# https://github.com/rubygems/rubygems/blob/4a778c9c2489745e37bcc2d0a8f12c601a9c517f/lib/rubygems/package/tar_writer.rb#L239-L253
|
139
|
+
module TarWriterAddSymlink
|
140
|
+
refine Gem::Package::TarWriter do
|
141
|
+
def add_symlink(name, target, mode)
|
142
|
+
check_closed
|
143
|
+
|
144
|
+
name, prefix = split_name name
|
145
|
+
|
146
|
+
header = Gem::Package::TarHeader.new(:name => name, :mode => mode,
|
147
|
+
:size => 0, :typeflag => "2",
|
148
|
+
:linkname => target,
|
149
|
+
:prefix => prefix,
|
150
|
+
:mtime => Time.now).to_s
|
151
|
+
|
152
|
+
@io.write header
|
153
|
+
|
154
|
+
self
|
155
|
+
end # def add_symlink
|
156
|
+
end # refine Gem::Package::TarWriter
|
157
|
+
end # module TarWriterAddSymlink
|
158
|
+
|
159
|
+
module Util
|
160
|
+
module Tar
|
161
|
+
unless Gem::Package::TarWriter.public_instance_methods.include? :add_symlink
|
162
|
+
using TarWriterAddSymlink
|
163
|
+
end
|
164
|
+
end # module Tar
|
165
|
+
end # module Util
|
data/lib/fpm/package/osxpkg.rb
CHANGED
@@ -81,7 +81,7 @@ class FPM::Package::OSXpkg < FPM::Package
|
|
81
81
|
SCRIPT_MAP.each do |scriptname, filename|
|
82
82
|
next unless script?(scriptname)
|
83
83
|
|
84
|
-
|
84
|
+
scripts_path(filename).tap do |pkgscript|
|
85
85
|
logger.info("Writing pkg script", :source => filename, :target => pkgscript)
|
86
86
|
File.write(pkgscript, script(scriptname))
|
87
87
|
# scripts are required to be executable
|
@@ -103,7 +103,7 @@ class FPM::Package::OSXpkg < FPM::Package
|
|
103
103
|
|
104
104
|
# Extract name and version from PackageInfo XML
|
105
105
|
def extract_info(package)
|
106
|
-
|
106
|
+
build_path("expand").tap do |path|
|
107
107
|
doc = REXML::Document.new File.open(File.join(path, "PackageInfo"))
|
108
108
|
pkginfo_elem = doc.elements["pkg-info"]
|
109
109
|
identifier = pkginfo_elem.attribute("identifier").value
|
@@ -0,0 +1,398 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
require "fpm/package"
|
3
|
+
require "fpm/util"
|
4
|
+
require "backports"
|
5
|
+
require "fileutils"
|
6
|
+
require "find"
|
7
|
+
|
8
|
+
class FPM::Package::Pacman < FPM::Package
|
9
|
+
|
10
|
+
option "--optional-depends", "PACKAGE",
|
11
|
+
"Add an optional dependency to the pacman package.", :multivalued => true
|
12
|
+
|
13
|
+
option "--use-file-permissions", :flag,
|
14
|
+
"Use existing file permissions when defining ownership and modes"
|
15
|
+
|
16
|
+
option "--user", "USER", "The owner of files in this package", :default => 'root'
|
17
|
+
|
18
|
+
option "--group", "GROUP", "The group owner of files in this package", :default => 'root'
|
19
|
+
|
20
|
+
# The list of supported compression types. Default is xz (LZMA2)
|
21
|
+
COMPRESSION_TYPES = [ "gz", "bzip2", "xz", "none" ]
|
22
|
+
|
23
|
+
option "--compression", "COMPRESSION", "The compression type to use, must " \
|
24
|
+
"be one of #{COMPRESSION_TYPES.join(", ")}.", :default => "xz" do |value|
|
25
|
+
if !COMPRESSION_TYPES.include?(value)
|
26
|
+
raise ArgumentError, "Pacman compression value of '#{value}' is invalid. " \
|
27
|
+
"Must be one of #{COMPRESSION_TYPES.join(", ")}"
|
28
|
+
end
|
29
|
+
value
|
30
|
+
end
|
31
|
+
|
32
|
+
def initialize(*args)
|
33
|
+
super(*args)
|
34
|
+
attributes[:pacman_optional_depends] = []
|
35
|
+
end # def initialize
|
36
|
+
|
37
|
+
def architecture
|
38
|
+
case @architecture
|
39
|
+
when nil
|
40
|
+
return %x{uname -m}.chomp # default to current arch
|
41
|
+
when "amd64" # debian and pacman disagree on architecture names
|
42
|
+
return "x86_64"
|
43
|
+
when "native"
|
44
|
+
return %x{uname -m}.chomp # 'native' is current arch
|
45
|
+
when "all", "any", "noarch"
|
46
|
+
return "any"
|
47
|
+
else
|
48
|
+
return @architecture
|
49
|
+
end
|
50
|
+
end # def architecture
|
51
|
+
|
52
|
+
def iteration
|
53
|
+
return @iteration || 1
|
54
|
+
end # def iteration
|
55
|
+
|
56
|
+
def config_files
|
57
|
+
return @config_files || []
|
58
|
+
end # def config_files
|
59
|
+
|
60
|
+
def dependencies
|
61
|
+
bogus_regex = /[^\sA-Za-z0-9><=-]/
|
62
|
+
# Actually modifies depencies if they are not right
|
63
|
+
bogus_dependencies = @dependencies.grep bogus_regex
|
64
|
+
if bogus_dependencies.any?
|
65
|
+
@dependencies.reject! { |a| a =~ bogus_regex }
|
66
|
+
logger.warn("Some of the dependencies looked like they weren't package " \
|
67
|
+
"names. Such dependency entries only serve to confuse arch. " \
|
68
|
+
"I am removing them.",
|
69
|
+
:removed_dependencies => bogus_dependencies,
|
70
|
+
:fixed_dependencies => @dependencies)
|
71
|
+
end
|
72
|
+
return @dependencies
|
73
|
+
end
|
74
|
+
|
75
|
+
|
76
|
+
# This method is invoked on a package when it has been converted to a new
|
77
|
+
# package format. The purpose of this method is to do any extra conversion
|
78
|
+
# steps, like translating dependency conditions, etc.
|
79
|
+
#def converted_from(origin)
|
80
|
+
# nothing to do by default. Subclasses may implement this.
|
81
|
+
# See the RPM package class for an example.
|
82
|
+
#end # def converted_from
|
83
|
+
|
84
|
+
# Add a new source to this package.
|
85
|
+
# The exact behavior depends on the kind of package being managed.
|
86
|
+
#
|
87
|
+
# For instance:
|
88
|
+
#
|
89
|
+
# * for FPM::Package::Dir, << expects a path to a directory or files.
|
90
|
+
# * for FPM::Package::RPM, << expects a path to an rpm.
|
91
|
+
#
|
92
|
+
# The idea is that you can keep pumping in new things to a package
|
93
|
+
# for later conversion or output.
|
94
|
+
#
|
95
|
+
# Implementations are expected to put files relevant to the 'input' in the
|
96
|
+
# staging_path
|
97
|
+
def input(pacman_pkg_path)
|
98
|
+
control = {}
|
99
|
+
# Unpack the control tarball
|
100
|
+
safesystem(tar_cmd, "-C", staging_path, "-xf", pacman_pkg_path)
|
101
|
+
pkginfo = staging_path(".PKGINFO")
|
102
|
+
mtree = staging_path(".MTREE")
|
103
|
+
install = staging_path(".INSTALL")
|
104
|
+
|
105
|
+
control_contents = File.read(pkginfo)
|
106
|
+
FileUtils.rm(pkginfo)
|
107
|
+
FileUtils.rm(mtree)
|
108
|
+
|
109
|
+
|
110
|
+
control_lines = control_contents.split("\n")
|
111
|
+
control_lines.each do |line|
|
112
|
+
key, val = line.split(/ += +/, 2)
|
113
|
+
if control.has_key? key
|
114
|
+
control[key].push(val)
|
115
|
+
else
|
116
|
+
control[key] = [val]
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
self.name = control["pkgname"][0]
|
121
|
+
|
122
|
+
# Parse 'epoch:version-iteration' in the version string
|
123
|
+
version_re = /^(?:([0-9]+):)?(.+?)(?:-(.*))?$/
|
124
|
+
m = version_re.match(control["pkgver"][0])
|
125
|
+
if !m
|
126
|
+
raise "Unsupported version string '#{control["pkgver"][0]}'"
|
127
|
+
end
|
128
|
+
self.epoch, self.version, self.iteration = m.captures
|
129
|
+
|
130
|
+
self.maintainer = control["packager"][0]
|
131
|
+
|
132
|
+
# Arch has no notion of vendor, so...
|
133
|
+
#self.vendor =
|
134
|
+
|
135
|
+
self.url = control["url"][0]
|
136
|
+
# Groups could include more than one.
|
137
|
+
# Speaking of just taking the first entry of the field:
|
138
|
+
# A crude thing to do, but I suppose it's better than nothing.
|
139
|
+
# -- Daniel Haskin, 3/24/2015
|
140
|
+
self.category = control["group"][0] || self.category
|
141
|
+
|
142
|
+
# Licenses could include more than one.
|
143
|
+
# Speaking of just taking the first entry of the field:
|
144
|
+
# A crude thing to do, but I suppose it's better than nothing.
|
145
|
+
# -- Daniel Haskin, 3/24/2015
|
146
|
+
self.license = control["license"][0] || self.license
|
147
|
+
|
148
|
+
self.architecture = control["arch"][0]
|
149
|
+
|
150
|
+
self.dependencies = control["depend"] || self.dependencies
|
151
|
+
|
152
|
+
self.provides = control["provides"] || self.provides
|
153
|
+
|
154
|
+
self.conflicts = control["conflict"] || self.conflicts
|
155
|
+
|
156
|
+
self.replaces = control["replaces"] || self.replaces
|
157
|
+
|
158
|
+
self.description = control["pkgdesc"][0]
|
159
|
+
|
160
|
+
if control.include? "backup"
|
161
|
+
self.config_files = control["backup"].map{|file| "/" + file}
|
162
|
+
else
|
163
|
+
self.config_files = []
|
164
|
+
end
|
165
|
+
|
166
|
+
self.dependencies = control["depend"] || self.dependencies
|
167
|
+
|
168
|
+
self.attributes[:pacman_optional_depends] = control["optdepend"] || []
|
169
|
+
# There are other available attributes, but I didn't include them because:
|
170
|
+
# - makedepend: deps needed to make the arch package. But it's already
|
171
|
+
# made. It just needs to be converted at this point
|
172
|
+
# - checkdepend: See above
|
173
|
+
# - makepkgopt: See above
|
174
|
+
# - size: can be dynamically generated
|
175
|
+
# - builddate: Should be changed to time of package conversion in the new
|
176
|
+
# package, so this value should be thrown away.
|
177
|
+
|
178
|
+
if File.exist?(install)
|
179
|
+
functions = parse_install_script(install)
|
180
|
+
if functions.include?("pre_install")
|
181
|
+
self.scripts[:before_install] = functions["pre_install"].join("\n")
|
182
|
+
end
|
183
|
+
if functions.include?("post_install")
|
184
|
+
self.scripts[:after_install] = functions["post_install"].join("\n")
|
185
|
+
end
|
186
|
+
if functions.include?("pre_upgrade")
|
187
|
+
self.scripts[:before_upgrade] = functions["pre_upgrade"].join("\n")
|
188
|
+
end
|
189
|
+
if functions.include?("post_upgrade")
|
190
|
+
self.scripts[:after_upgrade] = functions["post_upgrade"].join("\n")
|
191
|
+
end
|
192
|
+
if functions.include?("pre_remove")
|
193
|
+
self.scripts[:before_remove] = functions["pre_remove"].join("\n")
|
194
|
+
end
|
195
|
+
if functions.include?("post_remove")
|
196
|
+
self.scripts[:after_remove] = functions["post_remove"].join("\n")
|
197
|
+
end
|
198
|
+
FileUtils.rm(install)
|
199
|
+
end
|
200
|
+
|
201
|
+
# Note: didn't use `self.directories`.
|
202
|
+
# Pacman doesn't really record that information, to my knowledge.
|
203
|
+
|
204
|
+
end # def input
|
205
|
+
|
206
|
+
def compression_option
|
207
|
+
case self.attributes[:pacman_compression]
|
208
|
+
when nil, "xz"
|
209
|
+
return "--xz"
|
210
|
+
when "none"
|
211
|
+
return ""
|
212
|
+
when "gz"
|
213
|
+
return "-z"
|
214
|
+
when "bzip2"
|
215
|
+
return "-j"
|
216
|
+
else
|
217
|
+
return "--xz"
|
218
|
+
end
|
219
|
+
end
|
220
|
+
|
221
|
+
def compression_ending
|
222
|
+
case self.attributes[:pacman_compression]
|
223
|
+
when nil, "xz"
|
224
|
+
return ".xz"
|
225
|
+
when "none"
|
226
|
+
return ""
|
227
|
+
when "gz"
|
228
|
+
return ".gz"
|
229
|
+
when "bzip2"
|
230
|
+
return ".bz2"
|
231
|
+
else
|
232
|
+
return ".xz"
|
233
|
+
end
|
234
|
+
end
|
235
|
+
|
236
|
+
# Output this package to the given path.
|
237
|
+
def output(output_path)
|
238
|
+
output_check(output_path)
|
239
|
+
|
240
|
+
# Copy all files from staging to BUILD dir
|
241
|
+
Find.find(staging_path) do |path|
|
242
|
+
src = path.gsub(/^#{staging_path}/, '')
|
243
|
+
dst = build_path(src)
|
244
|
+
copy_entry(path, dst, preserve=true, remove_destination=true)
|
245
|
+
copy_metadata(path, dst)
|
246
|
+
end
|
247
|
+
|
248
|
+
# This value is used later in the template for PKGINFO
|
249
|
+
size = safesystemout("du", "-sk", build_path).split(/\s+/)[0].to_i * 1024
|
250
|
+
builddate = Time.new.to_i
|
251
|
+
|
252
|
+
pkginfo = template("pacman.erb").result(binding)
|
253
|
+
pkginfo_file = build_path(".PKGINFO")
|
254
|
+
File.write(pkginfo_file, pkginfo)
|
255
|
+
|
256
|
+
if script?(:before_install) or script?(:after_install) or \
|
257
|
+
script?(:before_upgrade) or script?(:after_upgrade) or \
|
258
|
+
script?(:before_remove) or script?(:after_remove)
|
259
|
+
install_script = template("pacman/INSTALL.erb").result(binding)
|
260
|
+
install_script_file = build_path(".INSTALL")
|
261
|
+
File.write(install_script_file, install_script)
|
262
|
+
end
|
263
|
+
|
264
|
+
generate_mtree
|
265
|
+
|
266
|
+
File.expand_path(output_path).tap do |path|
|
267
|
+
::Dir.chdir(build_path) do
|
268
|
+
safesystem(*([tar_cmd,
|
269
|
+
compression_option,
|
270
|
+
"-cf",
|
271
|
+
path] + data_tar_flags + \
|
272
|
+
::Dir.entries(".").reject{|entry| entry =~ /^\.{1,2}$/ }))
|
273
|
+
end
|
274
|
+
end
|
275
|
+
end # def output
|
276
|
+
|
277
|
+
def data_tar_flags
|
278
|
+
data_tar_flags = []
|
279
|
+
if attributes[:pacman_use_file_permissions?].nil?
|
280
|
+
if !attributes[:pacman_user].nil?
|
281
|
+
if attributes[:pacman_user] == 'root'
|
282
|
+
data_tar_flags += [ "--numeric-owner", "--owner", "0" ]
|
283
|
+
else
|
284
|
+
data_tar_flags += [ "--owner", attributes[:deb_user] ]
|
285
|
+
end
|
286
|
+
end
|
287
|
+
|
288
|
+
if !attributes[:pacman_group].nil?
|
289
|
+
if attributes[:pacman_group] == 'root'
|
290
|
+
data_tar_flags += [ "--numeric-owner", "--group", "0" ]
|
291
|
+
else
|
292
|
+
data_tar_flags += [ "--group", attributes[:deb_group] ]
|
293
|
+
end
|
294
|
+
end
|
295
|
+
end
|
296
|
+
return data_tar_flags
|
297
|
+
end # def data_tar_flags
|
298
|
+
|
299
|
+
def default_output
|
300
|
+
v = version
|
301
|
+
v = "#{epoch}:#{v}" if epoch
|
302
|
+
if iteration
|
303
|
+
"#{name}_#{v}-#{iteration}_#{architecture}.#{type}"
|
304
|
+
else
|
305
|
+
"#{name}_#{v}_#{architecture}.#{type}"
|
306
|
+
end
|
307
|
+
end # def default_output
|
308
|
+
|
309
|
+
def to_s(format=nil)
|
310
|
+
# Default format if nil
|
311
|
+
# git_1.7.9.3-1_amd64.deb
|
312
|
+
return super("NAME-FULLVERSION-ARCH.pkg.tar#{compression_ending}") if format.nil?
|
313
|
+
return super(format)
|
314
|
+
end # def to_s
|
315
|
+
|
316
|
+
private
|
317
|
+
|
318
|
+
def generate_mtree
|
319
|
+
::Dir.chdir(build_path) do
|
320
|
+
cmd = "LANG=C bsdtar "
|
321
|
+
cmd += "-czf .MTREE "
|
322
|
+
cmd += "--format=mtree "
|
323
|
+
cmd += "--options='!all,use-set,type,uid,gid,mode,time,size,md5,sha256,link' "
|
324
|
+
cmd += ::Dir.entries(".").reject{|entry| entry =~ /^\.{1,2}$/ }.join(" ")
|
325
|
+
safesystem(cmd)
|
326
|
+
end
|
327
|
+
end # def generate_mtree
|
328
|
+
|
329
|
+
# KNOWN ISSUE:
|
330
|
+
# If an un-matched bracket is used in valid bash, as in
|
331
|
+
# `echo "{"`, this function will choke.
|
332
|
+
# However, to cover this case basically
|
333
|
+
# requires writing almost half a bash parser,
|
334
|
+
# and it is a very small corner case.
|
335
|
+
# Otherwise, this approach is very robust.
|
336
|
+
def gobble_function(cons,prod)
|
337
|
+
level = 1
|
338
|
+
while level > 0
|
339
|
+
line = cons.next
|
340
|
+
# Not the best, but pretty good
|
341
|
+
# short of writing an *actual* sh
|
342
|
+
# parser
|
343
|
+
level += line.count "{"
|
344
|
+
level -= line.count "}"
|
345
|
+
if level > 0
|
346
|
+
prod.push(line.rstrip())
|
347
|
+
else
|
348
|
+
fine = line.sub(/\s*[}]\s*$/, "")
|
349
|
+
if !(fine =~ /^\s*$/)
|
350
|
+
prod.push(fine.rstrip())
|
351
|
+
end
|
352
|
+
end
|
353
|
+
end
|
354
|
+
end # def gobble_function
|
355
|
+
|
356
|
+
FIND_SCRIPT_FUNCTION_LINE =
|
357
|
+
/^\s*(\w+)\s*\(\s*\)\s*\{\s*([^}]+?)?\s*(\})?\s*$/
|
358
|
+
|
359
|
+
def parse_install_script(path)
|
360
|
+
global_lines = []
|
361
|
+
look_for = Set.new(["pre_install", "post_install",
|
362
|
+
"pre_upgrade", "post_upgrade",
|
363
|
+
"pre_remove", "post_remove"])
|
364
|
+
functions = {}
|
365
|
+
look_for.each do |fname|
|
366
|
+
functions[fname] = []
|
367
|
+
end
|
368
|
+
|
369
|
+
open(path, "r") do |iscript|
|
370
|
+
lines = iscript.each
|
371
|
+
begin
|
372
|
+
while true
|
373
|
+
line = lines.next
|
374
|
+
# This regex picks up beginning names of posix shell
|
375
|
+
# functions
|
376
|
+
# Examples:
|
377
|
+
# fname() {
|
378
|
+
# fname() { echo hi }
|
379
|
+
m = FIND_SCRIPT_FUNCTION_LINE.match(line)
|
380
|
+
if not m.nil? and look_for.include? m[1]
|
381
|
+
if not m[2].nil?
|
382
|
+
functions[m[1]].push(m[2].rstrip())
|
383
|
+
end
|
384
|
+
gobble_function(lines, functions[m[1]])
|
385
|
+
else
|
386
|
+
global_lines.push(line.rstrip())
|
387
|
+
end
|
388
|
+
end
|
389
|
+
rescue StopIteration
|
390
|
+
end
|
391
|
+
end
|
392
|
+
look_for.each do |name|
|
393
|
+
# Add global lines to each function to preserve global variables, etc.
|
394
|
+
functions[name] = global_lines + functions[name]
|
395
|
+
end
|
396
|
+
return functions
|
397
|
+
end # def parse_install_script
|
398
|
+
end # class FPM::Package::Pacman
|