fpm-aeppert 1.6.2

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.
Files changed (61) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELIST +661 -0
  3. data/CONTRIBUTORS +26 -0
  4. data/LICENSE +21 -0
  5. data/bin/fpm +8 -0
  6. data/lib/fpm.rb +20 -0
  7. data/lib/fpm/command.rb +648 -0
  8. data/lib/fpm/errors.rb +4 -0
  9. data/lib/fpm/namespace.rb +4 -0
  10. data/lib/fpm/package.rb +539 -0
  11. data/lib/fpm/package/apk.rb +510 -0
  12. data/lib/fpm/package/cpan.rb +405 -0
  13. data/lib/fpm/package/deb.rb +935 -0
  14. data/lib/fpm/package/dir.rb +221 -0
  15. data/lib/fpm/package/empty.rb +13 -0
  16. data/lib/fpm/package/freebsd.rb +147 -0
  17. data/lib/fpm/package/gem.rb +243 -0
  18. data/lib/fpm/package/npm.rb +120 -0
  19. data/lib/fpm/package/osxpkg.rb +165 -0
  20. data/lib/fpm/package/p5p.rb +124 -0
  21. data/lib/fpm/package/pacman.rb +403 -0
  22. data/lib/fpm/package/pear.rb +117 -0
  23. data/lib/fpm/package/pkgin.rb +35 -0
  24. data/lib/fpm/package/pleaserun.rb +63 -0
  25. data/lib/fpm/package/puppet.rb +120 -0
  26. data/lib/fpm/package/pyfpm/__init__.py +1 -0
  27. data/lib/fpm/package/pyfpm/get_metadata.py +104 -0
  28. data/lib/fpm/package/python.rb +318 -0
  29. data/lib/fpm/package/rpm.rb +593 -0
  30. data/lib/fpm/package/sh.rb +69 -0
  31. data/lib/fpm/package/solaris.rb +95 -0
  32. data/lib/fpm/package/tar.rb +86 -0
  33. data/lib/fpm/package/virtualenv.rb +164 -0
  34. data/lib/fpm/package/zip.rb +63 -0
  35. data/lib/fpm/rake_task.rb +60 -0
  36. data/lib/fpm/util.rb +358 -0
  37. data/lib/fpm/util/tar_writer.rb +80 -0
  38. data/lib/fpm/version.rb +3 -0
  39. data/templates/deb.erb +52 -0
  40. data/templates/deb/changelog.erb +5 -0
  41. data/templates/deb/ldconfig.sh.erb +13 -0
  42. data/templates/deb/postinst_upgrade.sh.erb +62 -0
  43. data/templates/deb/postrm_upgrade.sh.erb +46 -0
  44. data/templates/deb/preinst_upgrade.sh.erb +41 -0
  45. data/templates/deb/prerm_upgrade.sh.erb +39 -0
  46. data/templates/osxpkg.erb +11 -0
  47. data/templates/p5p_metadata.erb +12 -0
  48. data/templates/pacman.erb +47 -0
  49. data/templates/pacman/INSTALL.erb +41 -0
  50. data/templates/pleaserun/generate-cleanup.sh +17 -0
  51. data/templates/pleaserun/install-path.sh +17 -0
  52. data/templates/pleaserun/install.sh +117 -0
  53. data/templates/pleaserun/scripts/after-install.sh +4 -0
  54. data/templates/pleaserun/scripts/before-remove.sh +12 -0
  55. data/templates/puppet/package.pp.erb +34 -0
  56. data/templates/puppet/package/remove.pp.erb +13 -0
  57. data/templates/rpm.erb +260 -0
  58. data/templates/rpm/filesystem_list +14514 -0
  59. data/templates/sh.erb +369 -0
  60. data/templates/solaris.erb +15 -0
  61. metadata +322 -0
@@ -0,0 +1,117 @@
1
+ require "fpm/namespace"
2
+ require "fpm/package"
3
+ require "fileutils"
4
+ require "fpm/util"
5
+
6
+ # This provides PHP PEAR package support.
7
+ #
8
+ # This provides input support, but not output support.
9
+ class FPM::Package::PEAR < FPM::Package
10
+ option "--package-name-prefix", "PREFIX",
11
+ "Name prefix for pear package", :default => "php-pear"
12
+
13
+ option "--channel", "CHANNEL_URL",
14
+ "The pear channel url to use instead of the default."
15
+
16
+ option "--channel-update", :flag,
17
+ "call 'pear channel-update' prior to installation"
18
+
19
+ option "--bin-dir", "BIN_DIR",
20
+ "Directory to put binaries in"
21
+
22
+ option "--php-bin", "PHP_BIN",
23
+ "Specify php executable path if differs from the os used for packaging"
24
+
25
+ option "--php-dir", "PHP_DIR",
26
+ "Specify php dir relative to prefix if differs from pear default (pear/php)"
27
+
28
+ option "--data-dir", "DATA_DIR",
29
+ "Specify php dir relative to prefix if differs from pear default (pear/data)"
30
+
31
+ # Input a PEAR package.
32
+ #
33
+ # The parameter is a PHP PEAR package name.
34
+ #
35
+ # Attributes that affect behavior here:
36
+ # * :prefix - changes the install root, default is /usr/share
37
+ # * :pear_package_name_prefix - changes the
38
+ def input(input_package)
39
+ if !program_in_path?("pear")
40
+ raise ExecutableNotFound.new("pear")
41
+ end
42
+
43
+ # Create a temporary config file
44
+ logger.debug("Creating pear config file")
45
+ config = File.expand_path(build_path("pear.config"))
46
+ installroot = attributes[:prefix] || "/usr/share"
47
+ safesystem("pear", "config-create", staging_path(installroot), config)
48
+
49
+ if attributes[:pear_php_dir]
50
+ logger.info("Setting php_dir", :php_dir => attributes[:pear_php_dir])
51
+ safesystem("pear", "-c", config, "config-set", "php_dir", "#{staging_path(installroot)}/#{attributes[:pear_php_dir]}")
52
+ end
53
+
54
+ if attributes[:pear_data_dir]
55
+ logger.info("Setting data_dir", :data_dir => attributes[:pear_data_dir])
56
+ safesystem("pear", "-c", config, "config-set", "data_dir", "#{staging_path(installroot)}/#{attributes[:pear_data_dir]}")
57
+ end
58
+
59
+ bin_dir = attributes[:pear_bin_dir] || "usr/bin"
60
+ logger.info("Setting bin_dir", :bin_dir => bin_dir)
61
+ safesystem("pear", "-c", config, "config-set", "bin_dir", bin_dir)
62
+
63
+ php_bin = attributes[:pear_php_bin] || "/usr/bin/php"
64
+ logger.info("Setting php_bin", :php_bin => php_bin)
65
+ safesystem("pear", "-c", config, "config-set", "php_bin", php_bin)
66
+
67
+ # do channel-discover if required
68
+ if !attributes[:pear_channel].nil?
69
+ logger.info("Custom channel specified", :channel => attributes[:pear_channel])
70
+ channel_list = safesystemout("pear", "-c", config, "list-channels")
71
+ if channel_list !~ /#{Regexp.quote(attributes[:pear_channel])}/
72
+ logger.info("Discovering new channel", :channel => attributes[:pear_channel])
73
+ safesystem("pear", "-c", config, "channel-discover", attributes[:pear_channel])
74
+ end
75
+ input_package = "#{attributes[:pear_channel]}/#{input_package}"
76
+ logger.info("Prefixing package name with channel", :package => input_package)
77
+ end
78
+
79
+ # do channel-update if requested
80
+ if attributes[:pear_channel_update?]
81
+ channel = attributes[:pear_channel] || "pear"
82
+ logger.info("Updating the channel", :channel => channel)
83
+ safesystem("pear", "-c", config, "channel-update", channel)
84
+ end
85
+
86
+ logger.info("Installing pear package", :package => input_package,
87
+ :directory => staging_path)
88
+ ::Dir.chdir(staging_path) do
89
+ safesystem("pear", "-c", config, "install", "-n", "-f", input_package)
90
+ end
91
+
92
+ pear_cmd = "pear -c #{config} remote-info #{input_package}"
93
+ logger.info("Fetching package information", :package => input_package, :command => pear_cmd)
94
+ name = %x{#{pear_cmd} | sed -ne '/^Package\s*/s/^Package\s*//p'}.chomp
95
+ self.name = "#{attributes[:pear_package_name_prefix]}-#{name}"
96
+ self.version = %x{#{pear_cmd} | sed -ne '/^Installed\s*/s/^Installed\s*//p'}.chomp
97
+ self.description = %x{#{pear_cmd} | sed -ne '/^Summary\s*/s/^Summary\s*//p'}.chomp
98
+ logger.debug("Package info", :name => self.name, :version => self.version,
99
+ :description => self.description)
100
+
101
+ # Remove the stuff we don't want
102
+ delete_these = [".depdb", ".depdblock", ".filemap", ".lock", ".channel", "cache", "temp", "download", ".channels", ".registry"]
103
+ Find.find(staging_path) do |path|
104
+ if File.file?(path)
105
+ logger.info("replacing staging_path in file", :replace_in => path, :staging_path => staging_path)
106
+ begin
107
+ content = File.read(path).gsub(/#{Regexp.escape(staging_path)}/, "")
108
+ File.write(path, content)
109
+ rescue ArgumentError => e
110
+ logger.warn("error replacing staging_path in file", :replace_in => path, :error => e)
111
+ end
112
+ end
113
+ FileUtils.rm_r(path) if delete_these.include?(File.basename(path))
114
+ end
115
+
116
+ end # def input
117
+ end # class FPM::Package::PEAR
@@ -0,0 +1,35 @@
1
+ class FPM::Package::Pkgin < FPM::Package
2
+
3
+ def output(output_path)
4
+ output_check(output_path)
5
+
6
+ File.write(build_path("build-info"), `pkg_info -X pkg_install | egrep '^(MACHINE_ARCH|OPSYS|OS_VERSION|PKGTOOLS_VERSION)'`)
7
+
8
+ cwd = ::Dir.pwd
9
+ ::Dir.chdir(staging_path)
10
+
11
+ files = []
12
+ Find.find(".") do |path|
13
+ stat = File.lstat(path)
14
+ next unless stat.symlink? or stat.file?
15
+ files << path
16
+ end
17
+ ::Dir.chdir(cwd)
18
+
19
+ File.write(build_path("packlist"), files.sort.join("\n"))
20
+
21
+ File.write(build_path("comment"), self.description + "\n")
22
+
23
+ File.write(build_path("description"), self.description + "\n")
24
+
25
+ args = [ "-B", build_path("build-info"), "-c", build_path("comment"), "-d", build_path("description"), "-f", build_path("packlist"), "-I", "/opt/local", "-p", staging_path, "-U", "#{cwd}/#{name}-#{self.version}-#{iteration}.tgz" ]
26
+ safesystem("pkg_create", *args)
27
+
28
+ end
29
+
30
+ def iteration
31
+ return @iteration ? @iteration : 1
32
+ end
33
+
34
+ end
35
+
@@ -0,0 +1,63 @@
1
+ require "fpm/namespace"
2
+ require "fpm/package"
3
+ require "fpm/util"
4
+ require "fileutils"
5
+
6
+ require "pleaserun/cli"
7
+
8
+ # A pleaserun package.
9
+ #
10
+ # This does not currently support 'output'
11
+ class FPM::Package::PleaseRun < FPM::Package
12
+ # TODO(sissel): Implement flags.
13
+
14
+ require "pleaserun/platform/systemd"
15
+ require "pleaserun/platform/upstart"
16
+ require "pleaserun/platform/launchd"
17
+ require "pleaserun/platform/sysv"
18
+
19
+ option "--name", "SERVICE_NAME", "The name of the service you are creating"
20
+
21
+ private
22
+ def input(command)
23
+ platforms = [
24
+ ::PleaseRun::Platform::Systemd.new("default"), # RHEL 7, Fedora 19+, Debian 8, Ubuntu 16.04
25
+ ::PleaseRun::Platform::Upstart.new("1.5"), # Recent Ubuntus
26
+ ::PleaseRun::Platform::Upstart.new("0.6.5"), # CentOS 6
27
+ ::PleaseRun::Platform::Launchd.new("10.9"), # OS X
28
+ ::PleaseRun::Platform::SYSV.new("lsb-3.1") # Ancient stuff
29
+ ]
30
+
31
+ attributes[:pleaserun_name] ||= File.basename(command.first)
32
+ attributes[:prefix] ||= "/usr/share/pleaserun/#{attributes[:pleaserun_name]}"
33
+
34
+ platforms.each do |platform|
35
+ logger.info("Generating service manifest.", :platform => platform.class.name)
36
+ platform.program = command.first
37
+ platform.name = attributes[:pleaserun_name]
38
+ platform.args = command[1..-1]
39
+ platform.description = if attributes[:description_given?]
40
+ attributes[:description]
41
+ else
42
+ platform.name
43
+ end
44
+ base = staging_path(File.join(attributes[:prefix], "#{platform.platform}/#{platform.target_version || "default"}"))
45
+ target = File.join(base, "files")
46
+ actions_script = File.join(base, "install_actions.sh")
47
+ ::PleaseRun::Installer.install_files(platform, target, false)
48
+ ::PleaseRun::Installer.write_actions(platform, actions_script)
49
+ end
50
+
51
+ libs = [ "install.sh", "install-path.sh", "generate-cleanup.sh" ]
52
+ libs.each do |file|
53
+ base = staging_path(File.join(attributes[:prefix]))
54
+ File.write(File.join(base, file), template(File.join("pleaserun", file)).result(binding))
55
+ File.chmod(0755, File.join(base, file))
56
+ end
57
+
58
+ scripts[:after_install] = template(File.join("pleaserun", "scripts", "after-install.sh")).result(binding)
59
+ scripts[:before_remove] = template(File.join("pleaserun", "scripts", "before-remove.sh")).result(binding)
60
+ end # def input
61
+
62
+ public(:input)
63
+ end # class FPM::Package::PleaseRun
@@ -0,0 +1,120 @@
1
+ require "erb"
2
+ require "fpm/namespace"
3
+ require "fpm/package"
4
+ require "fpm/errors"
5
+ require "etc"
6
+ require "fileutils"
7
+
8
+ class FPM::Package::Puppet < FPM::Package
9
+ def architecture
10
+ case @architecture
11
+ when nil, "native"
12
+ @architecture = %x{uname -m}.chomp
13
+ end
14
+ return @architecture
15
+ end # def architecture
16
+
17
+ # Default specfile generator just makes one specfile, whatever that is for
18
+ # this package.
19
+ def generate_specfile(builddir)
20
+ paths = []
21
+ logger.info("PWD: #{File.join(builddir, unpack_data_to)}")
22
+ fileroot = File.join(builddir, unpack_data_to)
23
+ Dir.chdir(fileroot) do
24
+ Find.find(".") do |p|
25
+ next if p == "."
26
+ paths << p
27
+ end
28
+ end
29
+ logger.info(paths[-1])
30
+ manifests = %w{package.pp package/remove.pp}
31
+
32
+ ::Dir.mkdir(File.join(builddir, "manifests"))
33
+ manifests.each do |manifest|
34
+ dir = File.join(builddir, "manifests", File.dirname(manifest))
35
+ logger.info("manifests targeting: #{dir}")
36
+ ::Dir.mkdir(dir) if !File.directory?(dir)
37
+
38
+ File.open(File.join(builddir, "manifests", manifest), "w") do |f|
39
+ logger.info("manifest: #{f.path}")
40
+ template = template(File.join("puppet", "#{manifest}.erb"))
41
+ ::Dir.chdir(fileroot) do
42
+ f.puts template.result(binding)
43
+ end
44
+ end
45
+ end
46
+ end # def generate_specfile
47
+
48
+ def unpack_data_to
49
+ "files"
50
+ end
51
+
52
+ def build!(params)
53
+ # TODO(sissel): Support these somehow, perhaps with execs and files.
54
+ self.scripts.each do |name, path|
55
+ case name
56
+ when "pre-install"
57
+ when "post-install"
58
+ when "pre-uninstall"
59
+ when "post-uninstall"
60
+ end # case name
61
+ end # self.scripts.each
62
+
63
+ if File.exists?(params[:output])
64
+ # TODO(sissel): Allow folks to choose output?
65
+ logger.error("Puppet module directory '#{params[:output]}' already " \
66
+ "exists. Delete it or choose another output (-p flag)")
67
+ end
68
+
69
+ ::Dir.mkdir(params[:output])
70
+ builddir = ::Dir.pwd
71
+
72
+ # Copy 'files' from builddir to :output/files
73
+ Find.find("files", "manifests") do |path|
74
+ logger.info("Copying path: #{path}")
75
+ if File.directory?(path)
76
+ ::Dir.mkdir(File.join(params[:output], path))
77
+ else
78
+ FileUtils.cp(path, File.join(params[:output], path))
79
+ end
80
+ end
81
+ end # def build!
82
+
83
+ # The directory we create should just be the name of the package as the
84
+ # module name
85
+ def default_output
86
+ name
87
+ end # def default_output
88
+
89
+ # This method is used by the puppet manifest template
90
+ def puppetsort(hash)
91
+ # TODO(sissel): Implement sorting that follows the puppet style guide
92
+ # Such as, 'ensure' goes first, etc.
93
+ return hash.to_a
94
+ end # def puppetsort
95
+
96
+ # Helper for user lookup
97
+ def uid2user(uid)
98
+ begin
99
+ pwent = Etc.getpwuid(uid)
100
+ return pwent.name
101
+ rescue ArgumentError => e
102
+ # Invalid user id? No user? Return the uid.
103
+ logger.warn("Failed to find username for uid #{uid}")
104
+ return uid.to_s
105
+ end
106
+ end # def uid2user
107
+
108
+ # Helper for group lookup
109
+ def gid2group(gid)
110
+ begin
111
+ grent = Etc.getgrgid(gid)
112
+ return grent.name
113
+ rescue ArgumentError => e
114
+ # Invalid user id? No user? Return the uid.
115
+ logger.warn("Failed to find group for gid #{gid}")
116
+ return gid.to_s
117
+ end
118
+ end # def uid2user
119
+ end # class FPM::Target::Puppet
120
+
@@ -0,0 +1 @@
1
+ __all__ = [ "get_metadata" ]
@@ -0,0 +1,104 @@
1
+ from distutils.core import Command
2
+ import os
3
+ import sys
4
+ import pkg_resources
5
+ try:
6
+ import json
7
+ except ImportError:
8
+ import simplejson as json
9
+
10
+ PY3 = sys.version_info[0] == 3
11
+
12
+ if PY3:
13
+ def u(s):
14
+ return s
15
+ else:
16
+ def u(s):
17
+ if isinstance(u, unicode):
18
+ return u
19
+ return s.decode('utf-8')
20
+
21
+
22
+ # Note, the last time I coded python daily was at Google, so it's entirely
23
+ # possible some of my techniques below are outdated or bad.
24
+ # If you have fixes, let me know.
25
+
26
+
27
+ class get_metadata(Command):
28
+ description = "get package metadata"
29
+ user_options = [
30
+ ('load-requirements-txt', 'l',
31
+ "load dependencies from requirements.txt"),
32
+ ("output=", "o", "output destination for metadata json")
33
+ ]
34
+ boolean_options = ['load-requirements-txt']
35
+
36
+ def initialize_options(self):
37
+ self.load_requirements_txt = False
38
+ self.cwd = None
39
+ self.output = None
40
+
41
+ def finalize_options(self):
42
+ self.cwd = os.getcwd()
43
+ self.requirements_txt = os.path.join(self.cwd, "requirements.txt")
44
+ # make sure we have a requirements.txt
45
+ if self.load_requirements_txt:
46
+ self.load_requirements_txt = os.path.exists(self.requirements_txt)
47
+
48
+ def process_dep(self, dep):
49
+ deps = []
50
+ if dep.specs:
51
+ for operator, version in dep.specs:
52
+ deps.append("%s %s %s" % (dep.project_name,
53
+ operator, version))
54
+ else:
55
+ deps.append(dep.project_name)
56
+
57
+ return deps
58
+
59
+ def run(self):
60
+ data = {
61
+ "name": self.distribution.get_name(),
62
+ "version": self.distribution.get_version(),
63
+ "author": u("%s <%s>") % (
64
+ u(self.distribution.get_author()),
65
+ u(self.distribution.get_author_email()),
66
+ ),
67
+ "description": self.distribution.get_description(),
68
+ "license": self.distribution.get_license(),
69
+ "url": self.distribution.get_url(),
70
+ }
71
+
72
+ if self.distribution.has_ext_modules():
73
+ data["architecture"] = "native"
74
+ else:
75
+ data["architecture"] = "all"
76
+
77
+ final_deps = []
78
+
79
+ if self.load_requirements_txt:
80
+ requirement = open(self.requirements_txt).readlines()
81
+ for dep in pkg_resources.parse_requirements(requirement):
82
+ final_deps.extend(self.process_dep(dep))
83
+ else:
84
+ if getattr(self.distribution, 'install_requires', None):
85
+ for dep in pkg_resources.parse_requirements(
86
+ self.distribution.install_requires):
87
+ final_deps.extend(self.process_dep(dep))
88
+
89
+ data["dependencies"] = final_deps
90
+
91
+ output = open(self.output, "w")
92
+ if hasattr(json, 'dumps'):
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))
102
+ else:
103
+ # For Python 2.5 and Debian's python-json
104
+ output.write(json.write(data))