fpm 1.3.3 → 1.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELIST +32 -0
- data/CONTRIBUTORS +1 -1
- data/lib/fpm.rb +1 -0
- data/lib/fpm/command.rb +43 -18
- data/lib/fpm/package.rb +13 -13
- data/lib/fpm/package/cpan.rb +29 -17
- data/lib/fpm/package/deb.rb +59 -23
- data/lib/fpm/package/dir.rb +13 -26
- data/lib/fpm/package/empty.rb +6 -0
- data/lib/fpm/package/gem.rb +4 -4
- data/lib/fpm/package/npm.rb +2 -2
- data/lib/fpm/package/osxpkg.rb +3 -3
- data/lib/fpm/package/p5p.rb +124 -0
- data/lib/fpm/package/pyfpm/get_metadata.py +9 -1
- data/lib/fpm/package/python.rb +16 -9
- data/lib/fpm/package/rpm.rb +17 -10
- data/lib/fpm/package/sh.rb +1 -7
- data/lib/fpm/package/solaris.rb +1 -1
- data/lib/fpm/package/virtualenv.rb +136 -0
- data/lib/fpm/package/zip.rb +1 -1
- data/lib/fpm/util.rb +31 -5
- data/lib/fpm/version.rb +1 -1
- data/templates/deb/postinst_upgrade.sh.erb +14 -2
- data/templates/deb/postrm_upgrade.sh.erb +10 -1
- data/templates/deb/preinst_upgrade.sh.erb +11 -2
- data/templates/deb/prerm_upgrade.sh.erb +7 -2
- data/templates/p5p_metadata.erb +12 -0
- data/templates/rpm.erb +34 -5
- data/templates/sh.erb +22 -1
- metadata +8 -7
- data/lib/fpm/package/pyfpm/__init__.pyc +0 -0
- data/lib/fpm/package/pyfpm/get_metadata.pyc +0 -0
@@ -90,7 +90,15 @@ class get_metadata(Command):
|
|
90
90
|
|
91
91
|
output = open(self.output, "w")
|
92
92
|
if hasattr(json, 'dumps'):
|
93
|
-
|
93
|
+
def default_to_str(obj):
|
94
|
+
""" Fall back to using __str__ if possible """
|
95
|
+
# This checks if the class of obj defines __str__ itself,
|
96
|
+
# so we don't fall back to an inherited __str__ method.
|
97
|
+
if "__str__" in type(obj).__dict__:
|
98
|
+
return str(obj)
|
99
|
+
return json.JSONEncoder.default(self, obj)
|
100
|
+
|
101
|
+
output.write(json.dumps(data, indent=2, default=default_to_str))
|
94
102
|
else:
|
95
103
|
# For Python 2.5 and Debian's python-json
|
96
104
|
output.write(json.write(data))
|
data/lib/fpm/package/python.rb
CHANGED
@@ -7,7 +7,7 @@ require "fileutils"
|
|
7
7
|
require "tmpdir"
|
8
8
|
require "json"
|
9
9
|
|
10
|
-
# Support for python packages.
|
10
|
+
# Support for python packages.
|
11
11
|
#
|
12
12
|
# This supports input, but not output.
|
13
13
|
#
|
@@ -28,7 +28,7 @@ class FPM::Package::Python < FPM::Package
|
|
28
28
|
"is used instead", :default => nil
|
29
29
|
option "--pypi", "PYPI_URL",
|
30
30
|
"PyPi Server uri for retrieving packages.",
|
31
|
-
:default => "
|
31
|
+
:default => "https://pypi.python.org/simple"
|
32
32
|
option "--package-prefix", "NAMEPREFIX",
|
33
33
|
"(DEPRECATED, use --package-name-prefix) Name to prefix the package " \
|
34
34
|
"name with." do |value|
|
@@ -69,6 +69,10 @@ class FPM::Package::Python < FPM::Package
|
|
69
69
|
"current python interpreter (sys.executable). This option is equivalent " \
|
70
70
|
"to appending 'build_scripts --executable PYTHON_EXECUTABLE' arguments " \
|
71
71
|
"to 'setup.py install' command."
|
72
|
+
option "--disable-dependency", "python_package_name",
|
73
|
+
"The python package name to remove from dependency list",
|
74
|
+
:multivalued => true, :attribute_name => :python_disable_dependency,
|
75
|
+
:default => []
|
72
76
|
|
73
77
|
private
|
74
78
|
|
@@ -88,7 +92,7 @@ class FPM::Package::Python < FPM::Package
|
|
88
92
|
setup_py = path_to_package
|
89
93
|
end
|
90
94
|
|
91
|
-
if !File.
|
95
|
+
if !File.exist?(setup_py)
|
92
96
|
logger.error("Could not find 'setup.py'", :path => setup_py)
|
93
97
|
raise "Unable to find python package; tried #{setup_py}"
|
94
98
|
end
|
@@ -104,7 +108,7 @@ class FPM::Package::Python < FPM::Package
|
|
104
108
|
# part should go elsewhere.
|
105
109
|
path = package
|
106
110
|
# If it's a path, assume local build.
|
107
|
-
if File.directory?(path) or (File.
|
111
|
+
if File.directory?(path) or (File.exist?(path) and File.basename(path) == "setup.py")
|
108
112
|
return path
|
109
113
|
end
|
110
114
|
|
@@ -127,7 +131,7 @@ class FPM::Package::Python < FPM::Package
|
|
127
131
|
"--build-directory", target, want_pkg)
|
128
132
|
else
|
129
133
|
logger.debug("using pip", :pip => attributes[:python_pip])
|
130
|
-
safesystem(attributes[:python_pip], "install", "--no-deps", "--no-install", "-i", attributes[:python_pypi], "-U", "--build", target, want_pkg)
|
134
|
+
safesystem(attributes[:python_pip], "install", "--no-deps", "--no-install", "--no-use-wheel", "-i", attributes[:python_pypi], "-U", "--build", target, want_pkg)
|
131
135
|
end
|
132
136
|
|
133
137
|
# easy_install will put stuff in @tmpdir/packagename/, so find that:
|
@@ -145,7 +149,7 @@ class FPM::Package::Python < FPM::Package
|
|
145
149
|
attributes[:python_package_name_prefix] = attributes[:python_package_prefix]
|
146
150
|
end
|
147
151
|
|
148
|
-
begin
|
152
|
+
begin
|
149
153
|
json_test_code = [
|
150
154
|
"try:",
|
151
155
|
" import json",
|
@@ -219,7 +223,7 @@ class FPM::Package::Python < FPM::Package
|
|
219
223
|
self.name = self.name.downcase if attributes[:python_downcase_name?]
|
220
224
|
|
221
225
|
if !attributes[:no_auto_depends?] and attributes[:python_dependencies?]
|
222
|
-
|
226
|
+
metadata["dependencies"].each do |dep|
|
223
227
|
dep_re = /^([^<>!= ]+)\s*(?:([<>!=]{1,2})\s*(.*))?$/
|
224
228
|
match = dep_re.match(dep)
|
225
229
|
if match.nil?
|
@@ -228,6 +232,8 @@ class FPM::Package::Python < FPM::Package
|
|
228
232
|
end
|
229
233
|
name, cmp, version = match.captures
|
230
234
|
|
235
|
+
next if attributes[:python_disable_dependency].include?(name)
|
236
|
+
|
231
237
|
# convert == to =
|
232
238
|
if cmp == "=="
|
233
239
|
logger.info("Converting == dependency requirement to =", :dependency => dep )
|
@@ -241,7 +247,8 @@ class FPM::Package::Python < FPM::Package
|
|
241
247
|
|
242
248
|
# convert dependencies from python-Foo to python-foo
|
243
249
|
name = name.downcase if attributes[:python_downcase_dependencies?]
|
244
|
-
|
250
|
+
|
251
|
+
self.dependencies << "#{name} #{cmp} #{version}"
|
245
252
|
end
|
246
253
|
end # if attributes[:python_dependencies?]
|
247
254
|
end # def load_package_info
|
@@ -267,7 +274,7 @@ class FPM::Package::Python < FPM::Package
|
|
267
274
|
|
268
275
|
prefix = "/"
|
269
276
|
prefix = attributes[:prefix] unless attributes[:prefix].nil?
|
270
|
-
|
277
|
+
|
271
278
|
# Some setup.py's assume $PWD == current directory of setup.py, so let's
|
272
279
|
# chdir first.
|
273
280
|
::Dir.chdir(project_dir) do
|
data/lib/fpm/package/rpm.rb
CHANGED
@@ -29,7 +29,7 @@ class FPM::Package::RPM < FPM::Package
|
|
29
29
|
"bzip2" => "w9.bzdio"
|
30
30
|
} unless defined?(COMPRESSION_MAP)
|
31
31
|
|
32
|
-
option "--use-file-permissions", :flag,
|
32
|
+
option "--use-file-permissions", :flag,
|
33
33
|
"Use existing file permissions when defining ownership and modes."
|
34
34
|
|
35
35
|
option "--user", "USER", "Set the user to USER in the %files section. Overrides the user when used with use-file-permissions setting."
|
@@ -55,6 +55,8 @@ class FPM::Package::RPM < FPM::Package
|
|
55
55
|
next rpmbuild_define
|
56
56
|
end
|
57
57
|
|
58
|
+
option "--dist", "DIST-TAG", "Set the rpm distribution."
|
59
|
+
|
58
60
|
option "--digest", DIGEST_ALGORITHM_MAP.keys.join("|"),
|
59
61
|
"Select a digest algorithm. md5 works on the most platforms.",
|
60
62
|
:default => "md5" do |value|
|
@@ -98,7 +100,7 @@ class FPM::Package::RPM < FPM::Package
|
|
98
100
|
option "--attr", "ATTRFILE",
|
99
101
|
"Set the attribute for a file (%attr).",
|
100
102
|
:multivalued => true, :attribute_name => :attrs
|
101
|
-
|
103
|
+
|
102
104
|
option "--init", "FILEPATH", "Add FILEPATH as an init script",
|
103
105
|
:multivalued => true do |file|
|
104
106
|
next File.expand_path(file)
|
@@ -149,14 +151,14 @@ class FPM::Package::RPM < FPM::Package
|
|
149
151
|
match = trigger.match(/^(\[.*\]|)(.*): (.*)$/)
|
150
152
|
@logger.fatal("Trigger '#{trigger_type}' definition can't be parsed ('#{trigger}')") unless match
|
151
153
|
opt, pkg, file = match.captures
|
152
|
-
@logger.fatal("File given for --trigger-#{trigger_type} does not exist (#{file})") unless File.
|
154
|
+
@logger.fatal("File given for --trigger-#{trigger_type} does not exist (#{file})") unless File.exist?(file)
|
153
155
|
rpm_trigger << [pkg, File.read(file), opt.tr('[]','')]
|
154
156
|
next rpm_trigger
|
155
157
|
end
|
156
158
|
end
|
157
|
-
|
159
|
+
|
158
160
|
private
|
159
|
-
|
161
|
+
|
160
162
|
# Fix path name
|
161
163
|
# Replace [ with [\[] to make rpm not use globs
|
162
164
|
# Replace * with [*] to make rpm not use globs
|
@@ -289,7 +291,7 @@ class FPM::Package::RPM < FPM::Package
|
|
289
291
|
script_path = self.attributes[scriptname]
|
290
292
|
# Skip scripts not set
|
291
293
|
next if script_path.nil?
|
292
|
-
if !File.
|
294
|
+
if !File.exist?(script_path)
|
293
295
|
logger.error("No such file (for #{scriptname.to_s}): #{script_path.inspect}")
|
294
296
|
script_errors << script_path
|
295
297
|
end
|
@@ -303,7 +305,6 @@ class FPM::Package::RPM < FPM::Package
|
|
303
305
|
end # def converted
|
304
306
|
|
305
307
|
def rpm_get_trigger_type(flag)
|
306
|
-
puts "#{flag.to_s(2)}"
|
307
308
|
if (flag & (1 << 25)) == (1 << 25)
|
308
309
|
:rpm_trigger_before_install
|
309
310
|
elsif (flag & (1 << 16)) == (1 << 16)
|
@@ -375,13 +376,13 @@ class FPM::Package::RPM < FPM::Package
|
|
375
376
|
[name, operator, version].join(" ")
|
376
377
|
end
|
377
378
|
#input.replaces += replaces
|
378
|
-
|
379
|
+
|
379
380
|
self.config_files += rpm.config_files
|
380
381
|
|
381
382
|
# rpms support '%dir' things for specifying empty directories to package,
|
382
383
|
# but the rpm header itself doesn't actually record this information.
|
383
384
|
# so there's no 'directories' to copy, so don't try to merge in the
|
384
|
-
# 'directories' feature.
|
385
|
+
# 'directories' feature.
|
385
386
|
# TODO(sissel): If you want this feature, we'll have to find scan
|
386
387
|
# the extracted rpm for empty directories. I'll wait until someone asks for
|
387
388
|
# this feature
|
@@ -414,6 +415,9 @@ class FPM::Package::RPM < FPM::Package
|
|
414
415
|
args += ["--target", rpm_target]
|
415
416
|
end
|
416
417
|
|
418
|
+
# set the rpm dist tag
|
419
|
+
args += ["--define", "dist .#{attributes[:rpm_dist]}"] if attributes[:rpm_dist]
|
420
|
+
|
417
421
|
args += [
|
418
422
|
"--define", "buildroot #{build_path}/BUILD",
|
419
423
|
"--define", "_topdir #{build_path}",
|
@@ -531,7 +535,10 @@ class FPM::Package::RPM < FPM::Package
|
|
531
535
|
end # def epoch
|
532
536
|
|
533
537
|
def to_s(format=nil)
|
534
|
-
|
538
|
+
if format.nil?
|
539
|
+
return super("NAME-VERSION-ITERATION.DIST.ARCH.TYPE").gsub('DIST', attributes[:rpm_dist]) if attributes[:rpm_dist]
|
540
|
+
return super("NAME-VERSION-ITERATION.ARCH.TYPE")
|
541
|
+
end
|
535
542
|
return super(format)
|
536
543
|
end # def to_s
|
537
544
|
|
data/lib/fpm/package/sh.rb
CHANGED
@@ -11,7 +11,7 @@ require "digest"
|
|
11
11
|
#
|
12
12
|
# This class only supports output of packages.
|
13
13
|
#
|
14
|
-
# The sh package is a single sh file with a
|
14
|
+
# The sh package is a single sh file with a tar payload concatenated to the end.
|
15
15
|
# The script can unpack the tarball to install it and call optional post install scripts.
|
16
16
|
class FPM::Package::Sh < FPM::Package
|
17
17
|
|
@@ -24,12 +24,6 @@ class FPM::Package::Sh < FPM::Package
|
|
24
24
|
end
|
25
25
|
|
26
26
|
def create_scripts
|
27
|
-
if script?(:before_install)
|
28
|
-
# the scripts are kept in the payload so what would before install be if we've already
|
29
|
-
# unpacked the payload?
|
30
|
-
raise "sh package does not support before install scripts."
|
31
|
-
end
|
32
|
-
|
33
27
|
if script?(:after_install)
|
34
28
|
File.write(File.join(fpm_meta_path, "after_install"), script(:after_install))
|
35
29
|
end
|
data/lib/fpm/package/solaris.rb
CHANGED
@@ -75,7 +75,7 @@ class FPM::Package::Solaris < FPM::Package
|
|
75
75
|
# Should create a package directory named by the package name.
|
76
76
|
safesystem("pkgmk", "-o", "-f", "#{build_path}/Prototype", "-d", build_path)
|
77
77
|
end
|
78
|
-
|
78
|
+
|
79
79
|
|
80
80
|
# Convert the 'package directory' built above to a real solaris package.
|
81
81
|
safesystem("pkgtrans", "-s", build_path, output_path, name)
|
@@ -0,0 +1,136 @@
|
|
1
|
+
require "fpm/namespace"
|
2
|
+
require "fpm/package"
|
3
|
+
require "fpm/util"
|
4
|
+
|
5
|
+
# Support for python virtualenv packages.
|
6
|
+
#
|
7
|
+
# This supports input, but not output.
|
8
|
+
#
|
9
|
+
class FPM::Package::Virtualenv < FPM::Package
|
10
|
+
# Flags '--foo' will be accessable as attributes[:virtualenv_foo]
|
11
|
+
|
12
|
+
option "--pypi", "PYPI_URL",
|
13
|
+
"PyPi Server uri for retrieving packages.",
|
14
|
+
:default => "https://pypi.python.org/simple"
|
15
|
+
option "--package-name-prefix", "PREFIX", "Name to prefix the package " \
|
16
|
+
"name with.", :default => "virtualenv"
|
17
|
+
|
18
|
+
option "--install-location", "DIRECTORY", "Location to which to " \
|
19
|
+
"install the virtualenv by default.", :default => "/usr/share/python" do |path|
|
20
|
+
File.expand_path(path)
|
21
|
+
end
|
22
|
+
|
23
|
+
option "--fix-name", :flag, "Should the target package name be prefixed?",
|
24
|
+
:default => true
|
25
|
+
option "--other-files-dir", "DIRECTORY", "Optionally, the contents of the " \
|
26
|
+
"specified directory may be added to the package. This is useful if the " \
|
27
|
+
"virtualenv needs configuration files, etc.", :default => nil
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
# Input a package.
|
32
|
+
#
|
33
|
+
# `package` can look like `psutil==2.2.1` or `psutil`.
|
34
|
+
def input(package)
|
35
|
+
installdir = attributes[:virtualenv_install_location]
|
36
|
+
m = /^([^=]+)==([^=]+)$/.match(package)
|
37
|
+
package_version = nil
|
38
|
+
|
39
|
+
if m
|
40
|
+
package_name = m[1]
|
41
|
+
package_version = m[2]
|
42
|
+
self.version ||= package_version
|
43
|
+
else
|
44
|
+
package_name = package
|
45
|
+
package_version = nil
|
46
|
+
end
|
47
|
+
|
48
|
+
virtualenv_name = package_name
|
49
|
+
|
50
|
+
self.name ||= package_name
|
51
|
+
|
52
|
+
if self.attributes[:virtualenv_fix_name?]
|
53
|
+
self.name = [self.attributes[:virtualenv_package_name_prefix],
|
54
|
+
self.name].join("-")
|
55
|
+
end
|
56
|
+
|
57
|
+
virtualenv_folder =
|
58
|
+
File.join(installdir,
|
59
|
+
virtualenv_name)
|
60
|
+
|
61
|
+
virtualenv_build_folder = build_path(virtualenv_folder)
|
62
|
+
|
63
|
+
::FileUtils.mkdir_p(virtualenv_build_folder)
|
64
|
+
|
65
|
+
safesystem("virtualenv", virtualenv_build_folder)
|
66
|
+
pip_exe = File.join(virtualenv_build_folder, "bin", "pip")
|
67
|
+
python_exe = File.join(virtualenv_build_folder, "bin", "python")
|
68
|
+
|
69
|
+
# Why is this hack here? It looks important, so I'll keep it in.
|
70
|
+
safesystem(pip_exe, "install", "-U", "-i",
|
71
|
+
attributes[:virtualenv_pypi],
|
72
|
+
"pip", "distribute")
|
73
|
+
safesystem(pip_exe, "uninstall", "-y", "distribute")
|
74
|
+
|
75
|
+
safesystem(pip_exe, "install", "-i",
|
76
|
+
attributes[:virtualenv_pypi],
|
77
|
+
package)
|
78
|
+
|
79
|
+
if package_version.nil?
|
80
|
+
frozen = safesystemout(pip_exe, "freeze")
|
81
|
+
package_version = frozen[/#{package}==[^=]+$/].split("==")[1].chomp!
|
82
|
+
self.version ||= package_version
|
83
|
+
end
|
84
|
+
|
85
|
+
::Dir[build_path + "/**/*"].each do |f|
|
86
|
+
if ! File.world_readable? f
|
87
|
+
File.lchmod(File.stat(f).mode | 444)
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
::Dir.chdir(virtualenv_build_folder) do
|
92
|
+
safesystem("virtualenv-tools", "--update-path", virtualenv_folder)
|
93
|
+
end
|
94
|
+
|
95
|
+
if !attributes[:virtualenv_other_files_dir].nil?
|
96
|
+
# Copy all files from other dir to build_path
|
97
|
+
Find.find(attributes[:virtualenv_other_files_dir]) do |path|
|
98
|
+
src = path.gsub(/^#{attributes[:virtualenv_other_files_dir]}/, '')
|
99
|
+
dst = File.join(build_path, src)
|
100
|
+
copy_entry(path, dst, preserve=true, remove_destination=true)
|
101
|
+
copy_metadata(path, dst)
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
remove_python_compiled_files virtualenv_build_folder
|
106
|
+
|
107
|
+
# use dir to set stuff up properly, mainly so I don't have to reimplement
|
108
|
+
# the chdir/prefix stuff special for tar.
|
109
|
+
dir = convert(FPM::Package::Dir)
|
110
|
+
|
111
|
+
if attributes[:chdir]
|
112
|
+
dir.attributes[:chdir] = File.join(build_path, attributes[:chdir])
|
113
|
+
else
|
114
|
+
dir.attributes[:chdir] = build_path
|
115
|
+
end
|
116
|
+
|
117
|
+
cleanup_staging
|
118
|
+
# Tell 'dir' to input "." and chdir/prefix will help it figure out the
|
119
|
+
# rest.
|
120
|
+
dir.input(".")
|
121
|
+
@staging_path = dir.staging_path
|
122
|
+
dir.cleanup_build
|
123
|
+
|
124
|
+
end # def input
|
125
|
+
|
126
|
+
# Delete python precompiled files found in a given folder.
|
127
|
+
def remove_python_compiled_files path
|
128
|
+
logger.debug("Now removing python object and compiled files from the virtualenv")
|
129
|
+
Find.find(path) do |path|
|
130
|
+
if path.end_with? '.pyc' or path.end_with? '.pyo'
|
131
|
+
FileUtils.rm path
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
135
|
+
public(:input)
|
136
|
+
end # class FPM::Package::Virtualenv
|
data/lib/fpm/package/zip.rb
CHANGED
data/lib/fpm/util.rb
CHANGED
@@ -24,6 +24,8 @@ module FPM::Util
|
|
24
24
|
|
25
25
|
# Is the given program in the system's PATH?
|
26
26
|
def program_in_path?(program)
|
27
|
+
# return false if path is not set
|
28
|
+
return false unless ENV['PATH']
|
27
29
|
# Scan path to find the executable
|
28
30
|
# Do this to help the user get a better error message.
|
29
31
|
envpath = ENV["PATH"].split(":")
|
@@ -33,12 +35,12 @@ module FPM::Util
|
|
33
35
|
def program_exists?(program)
|
34
36
|
# Scan path to find the executable
|
35
37
|
# Do this to help the user get a better error message.
|
36
|
-
return program_in_path?(program) if !program.include?("/")
|
38
|
+
return program_in_path?(program) if !program.include?("/")
|
37
39
|
return File.executable?(program)
|
38
40
|
end # def program_exists?
|
39
41
|
|
40
42
|
def default_shell
|
41
|
-
shell = ENV["SHELL"]
|
43
|
+
shell = ENV["SHELL"]
|
42
44
|
return "/bin/sh" if shell.nil? || shell.empty?
|
43
45
|
return shell
|
44
46
|
end
|
@@ -139,7 +141,7 @@ module FPM::Util
|
|
139
141
|
end # def tar_cmd
|
140
142
|
|
141
143
|
# Run a block with a value.
|
142
|
-
# Useful in lieu of assigning variables
|
144
|
+
# Useful in lieu of assigning variables
|
143
145
|
def with(value, &block)
|
144
146
|
block.call(value)
|
145
147
|
end # def with
|
@@ -157,7 +159,30 @@ module FPM::Util
|
|
157
159
|
rc
|
158
160
|
end
|
159
161
|
|
160
|
-
def
|
162
|
+
def copy_metadata(source, destination)
|
163
|
+
source_stat = File::lstat(source)
|
164
|
+
dest_stat = File::lstat(destination)
|
165
|
+
|
166
|
+
# If this is a hard-link, there's no metadata to copy.
|
167
|
+
# If this is a symlink, what it points to hasn't been copied yet.
|
168
|
+
return if source_stat.ino == dest_stat.ino || dest_stat.symlink?
|
169
|
+
|
170
|
+
File.utime(source_stat.atime, source_stat.mtime, destination)
|
171
|
+
mode = source_stat.mode
|
172
|
+
begin
|
173
|
+
File.lchown(source_stat.uid, source_stat.gid, destination)
|
174
|
+
rescue Errno::EPERM
|
175
|
+
# clear setuid/setgid
|
176
|
+
mode &= 01777
|
177
|
+
end
|
178
|
+
|
179
|
+
unless source_stat.symlink?
|
180
|
+
File.chmod(mode, destination)
|
181
|
+
end
|
182
|
+
end # def copy_metadata
|
183
|
+
|
184
|
+
|
185
|
+
def copy_entry(src, dst, preserve=false, remove_destination=false)
|
161
186
|
case File.ftype(src)
|
162
187
|
when 'fifo', 'characterSpecial', 'blockSpecial', 'socket'
|
163
188
|
st = File.stat(src)
|
@@ -173,7 +198,8 @@ module FPM::Util
|
|
173
198
|
if known_entry
|
174
199
|
FileUtils.ln(known_entry, dst)
|
175
200
|
else
|
176
|
-
FileUtils.copy_entry(src, dst
|
201
|
+
FileUtils.copy_entry(src, dst, preserve=preserve,
|
202
|
+
remove_destination=remove_destination)
|
177
203
|
copied_entries[[st.dev, st.ino]] = dst
|
178
204
|
end
|
179
205
|
end # else...
|