gpm 0.0.2 → 0.1.3
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.
- data/bin/correct_permissions +4 -0
- data/lib/gpm/cli.rb +18 -10
- data/lib/gpm/file_path_and_permissions.rb +16 -11
- data/lib/gpm/io_helpers.rb +26 -0
- data/lib/gpm/packaging_task.rb +15 -6
- data/lib/gpm/source.rb +9 -6
- data/lib/gpm/source/bundler.rb +22 -51
- data/lib/gpm/source/files_providers/composite_files_provider.rb +23 -0
- data/lib/gpm/source/files_providers/files_from_bundler_directory_provider.rb +36 -0
- data/lib/gpm/source/files_providers/files_from_directory_provider.rb +16 -0
- data/lib/gpm/source/files_providers/files_from_gem_directory_provider.rb +13 -0
- data/lib/gpm/source/files_providers/files_provider.rb +10 -0
- data/lib/gpm/source/files_providers/overrides_permissions.rb +37 -0
- data/lib/gpm/source/files_providers/vendored_gems_installer.rb +36 -0
- data/lib/gpm/source/gem.rb +22 -27
- data/lib/gpm/target.rb +11 -20
- data/lib/gpm/target/deb.rb +44 -36
- data/lib/gpm/target/generate_from_templates.rb +1 -1
- data/lib/gpm/target/step_plugin.rb +7 -6
- data/lib/gpm/target/zip_directories.rb +1 -1
- data/templates/deb/control.tar.gz.dir/control.erb +1 -1
- data/templates/deb/control.tar.gz.dir/postinst.erb +5 -0
- data/templates/deb/control.tar.gz.dir/prerm.erb +4 -0
- data/templates/deb/data.tar.gz.dir/usr/share/doc/__name__/{changelog.gz.erb → changelog.Debian.gz.erb} +0 -0
- metadata +59 -26
data/lib/gpm/cli.rb
CHANGED
@@ -1,23 +1,31 @@
|
|
1
1
|
require 'thor'
|
2
2
|
require_relative 'packaging_task'
|
3
3
|
class GpmCli < Thor
|
4
|
-
|
4
|
+
def self.supported_sources
|
5
|
+
["gem","bundler"]
|
6
|
+
end
|
7
|
+
def self.supported_targets
|
8
|
+
["deb"]
|
9
|
+
end
|
5
10
|
# gpm package -s <source type> -t <target type> [options]
|
6
|
-
desc "package APP_DIRECTORY_OR_FILE", "
|
7
|
-
method_option :source, :type => :string, :aliases => "-s"
|
8
|
-
method_option :target, :type => :string, :aliases => "-t"
|
9
|
-
method_option :workdir, :type => :string, :aliases => "-wd"
|
10
|
-
method_option :destination, :type => :string, :aliases => "-d"
|
11
|
+
desc "package APP_DIRECTORY_OR_FILE", "Packages the app given in a specified source format to a desired target format"
|
12
|
+
method_option :source, :type => :string, :aliases => "-s", :desc => "The input for creating the package (Currently supported: #{supported_sources.join(', ')})", :required => true
|
13
|
+
method_option :target, :type => :string, :aliases => "-t", :desc => "The desired output format for the package (Currently supported: #{supported_targets.join(', ')})", :required => true
|
14
|
+
method_option :workdir, :type => :string, :aliases => "-wd", :desc => "A directory in which temporary files can be placed"
|
15
|
+
method_option :destination, :type => :string, :aliases => "-d", :desc => "The destination path where the application shall be installed to", :required => true
|
16
|
+
method_option :owner, :type => :string, :aliases => "-o", :desc => "The owning user for the destination path", :default => "root"
|
17
|
+
method_option :group, :type => :string, :aliases => "-g", :desc => "The owning group for the destination path", :default => "root"
|
18
|
+
method_option :buildnumber, :type => :string, :aliases => "-b", :desc => "The build number that is appended to the version", :required => false
|
11
19
|
|
12
20
|
def package(file_or_directory)
|
13
|
-
raise "Only gem or bundler source at the moment" unless
|
14
|
-
raise "Only deb target at the moment" unless options.target
|
21
|
+
raise "Only gem or bundler source at the moment" unless self.class.supported_sources.include? options.source
|
22
|
+
raise "Only deb target at the moment" unless self.class.supported_targets.include? options.target
|
15
23
|
package_options = {}
|
16
|
-
{:workdir => :work_dir , :destination => :destination}.each do |in_field, out_field|
|
24
|
+
{:workdir => :work_dir , :destination => :destination, :owner => :owner, :group => :group, :buildnumber => :build_number}.each do |in_field, out_field|
|
17
25
|
package_options[out_field] = options[in_field] if options[in_field]
|
18
26
|
end
|
19
27
|
|
20
28
|
PackagingTask.create(file_or_directory, options.source, options.target, package_options).run
|
21
29
|
end
|
22
30
|
|
23
|
-
end
|
31
|
+
end
|
@@ -1,19 +1,24 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
1
|
+
require 'delegate'
|
2
|
+
class FilePathAndPermissions < SimpleDelegator
|
3
|
+
attr_reader :permissions, :path
|
4
|
+
def initialize(path, permissions = 0444)
|
5
|
+
@path = path.to_s
|
6
|
+
super(@path)
|
5
7
|
@permissions = permissions
|
6
8
|
end
|
7
9
|
|
8
|
-
def
|
9
|
-
@path
|
10
|
+
def eql?(other)
|
11
|
+
return @path == other if other.is_a? String
|
12
|
+
return @path == other.path if other.is_a? FilePathAndPermissions
|
13
|
+
super
|
10
14
|
end
|
11
15
|
|
12
|
-
def
|
13
|
-
|
16
|
+
def inspect
|
17
|
+
vars = instance_variables.collect { |v| v.to_s << "=#{instance_variable_get(v).inspect}"}.join(", ")
|
18
|
+
"#<#{self.class}:#{vars}>"
|
14
19
|
end
|
15
20
|
|
16
|
-
def
|
17
|
-
@path
|
21
|
+
def hash
|
22
|
+
@path.hash
|
18
23
|
end
|
19
|
-
end
|
24
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require_relative 'file_path_and_permissions'
|
2
|
+
def write_file_contents(file_contents)
|
3
|
+
file_contents.each do |file_name, content|
|
4
|
+
FileUtils.mkdir_p(File.dirname(file_name))
|
5
|
+
File.open(file_name,"w") do |file|
|
6
|
+
file.print content
|
7
|
+
end
|
8
|
+
File.chmod(file_name.permissions, file_name.to_s) if file_name.is_a? FilePathAndPermissions
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
def write_file_contents_in_directory(file_contents,directory)
|
13
|
+
FileUtils.mkdir_p directory
|
14
|
+
Dir.chdir(directory) do
|
15
|
+
write_file_contents(file_contents)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
def read_file_contents(files,base_directory)
|
19
|
+
file_contents = {}
|
20
|
+
files.each do |f|
|
21
|
+
path = File.join(base_directory,f)
|
22
|
+
permissions = File.lstat(path).mode % 4096
|
23
|
+
file_contents[FilePathAndPermissions.new(f,permissions)] = File.read(path) if File.file?(path)
|
24
|
+
end
|
25
|
+
file_contents
|
26
|
+
end
|
data/lib/gpm/packaging_task.rb
CHANGED
@@ -1,14 +1,23 @@
|
|
1
1
|
class PackagingTask
|
2
|
-
|
3
|
-
|
2
|
+
|
3
|
+
def self.class_for_source(source_name)
|
4
4
|
require_relative "source"
|
5
5
|
require_relative "source/#{source_name}"
|
6
|
-
|
7
|
-
|
6
|
+
Kernel.const_get("Source").const_get(source_name.capitalize)
|
7
|
+
end
|
8
8
|
|
9
|
+
def self.class_for_target(target_name)
|
9
10
|
require_relative "target"
|
10
11
|
require_relative "target/#{target_name}"
|
11
|
-
|
12
|
+
Kernel.const_get("Target").const_get(target_name.capitalize)
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.create(file_or_directory, source_name, target_name, options = {})
|
16
|
+
options[:work_dir] ||= Dir.mktmpdir
|
17
|
+
source_class = class_for_source(source_name)
|
18
|
+
source = source_class.create(file_or_directory, options)
|
19
|
+
|
20
|
+
target_class = class_for_target(target_name)
|
12
21
|
target = target_class.new(options[:work_dir], options)
|
13
22
|
new(source,target)
|
14
23
|
end
|
@@ -22,4 +31,4 @@ class PackagingTask
|
|
22
31
|
@target.create_package(@source)
|
23
32
|
end
|
24
33
|
|
25
|
-
end
|
34
|
+
end
|
data/lib/gpm/source.rb
CHANGED
@@ -1,9 +1,12 @@
|
|
1
|
+
require 'pathname'
|
2
|
+
require_relative 'file_path_and_permissions'
|
3
|
+
|
1
4
|
module Source
|
2
5
|
class Base
|
3
6
|
DEFAULTS = {
|
4
7
|
# Default version is 1.0 in case nobody told us a specific version.
|
5
8
|
:version => "1.0",
|
6
|
-
:
|
9
|
+
:build_number => nil,
|
7
10
|
:epoch => nil,
|
8
11
|
# If architecture is nil, the target package should provide a default.
|
9
12
|
# Special 'architecture' values include "all" (aka rpm's noarch, debian's all)
|
@@ -46,10 +49,10 @@ module Source
|
|
46
49
|
end
|
47
50
|
end
|
48
51
|
end
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
file_contents.
|
52
|
+
|
53
|
+
def contains_file?(file_name)
|
54
|
+
file_name = FilePathAndPermissions.new(file_name) unless file_name.kind_of? FilePathAndPermissions
|
55
|
+
file_contents.include? file_name
|
53
56
|
end
|
54
57
|
end
|
55
|
-
end
|
58
|
+
end
|
data/lib/gpm/source/bundler.rb
CHANGED
@@ -1,55 +1,26 @@
|
|
1
1
|
require_relative 'gem'
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
2
|
+
require_relative 'files_providers/files_from_bundler_directory_provider'
|
3
|
+
module Source
|
4
|
+
class Bundler < Source::Gem
|
5
|
+
def self.create(gemfile, options = {})
|
6
|
+
directory = File.absolute_path(File.dirname(gemfile))
|
7
|
+
gemspec = Dir[File.join(directory,'*.gemspec')].first
|
8
|
+
metadata = read_metadata(gemspec)
|
9
|
+
|
10
|
+
bundler_provider = FilesFromBundlerDirectoryProvider.new(File.expand_path(gemfile), gemspec)
|
11
|
+
package_path = File.join(directory, '_package_')
|
12
|
+
package_scripts_provider = Source::FilesFromDirectoryProvider.new(package_path, directory)
|
13
|
+
new(metadata, Source::CompositeFilesProvider.new(bundler_provider, package_scripts_provider), options)
|
14
14
|
end
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
ENV["PWD"] = directory
|
25
|
-
backup_fields.each {|f| ENV[f] = old_env[f]}
|
26
|
-
FileUtils.rm_rf('.bundle')
|
27
|
-
["bundle install","bundle install --deployment --verbose"].each do |c| # --standalone
|
28
|
-
puts c,`#{c}`
|
29
|
-
end
|
30
|
-
end
|
31
|
-
bundled_files = Dir["vendor/bundle/**/*"]
|
32
|
-
end
|
33
|
-
old_env.each {|k,v| ENV[k] = v}
|
34
|
-
super_contents = super.merge(read_file_contents(bundled_files+[File.basename(gemfile),File.basename(gemspec),'Gemfile.lock'], directory))
|
35
|
-
super_contents
|
15
|
+
|
16
|
+
def initialize(*args)
|
17
|
+
super
|
18
|
+
end
|
19
|
+
def architecture
|
20
|
+
"native"
|
21
|
+
end
|
22
|
+
def dependencies
|
23
|
+
["libc6", "ruby"]
|
36
24
|
end
|
37
25
|
end
|
38
|
-
|
39
|
-
def self.create(gemfile)
|
40
|
-
gemspec = Dir[File.join(File.dirname(gemfile),'*.gemspec')].first
|
41
|
-
metadata = read_metadata(gemspec)
|
42
|
-
|
43
|
-
new(metadata,FilesFromBundlerDirectoryProvider.new(File.expand_path(gemfile), gemspec))
|
44
|
-
end
|
45
|
-
|
46
|
-
def initialize(*args)
|
47
|
-
super
|
48
|
-
end
|
49
|
-
def architecture
|
50
|
-
"native"
|
51
|
-
end
|
52
|
-
def dependencies
|
53
|
-
["libc6"]
|
54
|
-
end
|
55
|
-
end
|
26
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Source
|
2
|
+
class CompositeFilesProvider
|
3
|
+
def initialize(*file_providers)
|
4
|
+
@file_providers = file_providers
|
5
|
+
end
|
6
|
+
|
7
|
+
def files
|
8
|
+
@file_providers.inject([]) do |merged, file_provider|
|
9
|
+
files = file_provider.files
|
10
|
+
raise "duplicate filename found in different file providers" unless (merged & files).empty?
|
11
|
+
merged + files
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def file_contents
|
16
|
+
@file_providers.inject({}) do |merged, file_provider|
|
17
|
+
contents = file_provider.file_contents
|
18
|
+
raise "duplicate filename found in different file providers: #{(merged.keys & contents.keys)}" unless (merged.keys & contents.keys).empty?
|
19
|
+
merged.merge contents
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require_relative 'files_from_directory_provider'
|
2
|
+
require_relative 'composite_files_provider'
|
3
|
+
require_relative 'files_from_gem_directory_provider'
|
4
|
+
require_relative 'vendored_gems_installer'
|
5
|
+
require_relative '../gem'
|
6
|
+
require 'bundler'
|
7
|
+
|
8
|
+
module Source
|
9
|
+
class FilesFromBundlerDirectoryProvider < FilesFromGemDirectoryProvider
|
10
|
+
attr_reader :gemfile,:gemspec
|
11
|
+
def initialize(gemfile,gemspec,vendored_gems_installer = nil)
|
12
|
+
raise "Must give me a Gemfile, not #{gemfile.inspect}" unless File.basename(gemfile)=="Gemfile"
|
13
|
+
metadata = Source::Gem.read_metadata(gemspec)
|
14
|
+
super(File.dirname(gemfile),metadata.files)
|
15
|
+
@gemfile = gemfile
|
16
|
+
@gemspec = gemspec
|
17
|
+
@vendored_gems_installer = vendored_gems_installer || Source::VendoredGemsInstaller.new(gemfile)
|
18
|
+
end
|
19
|
+
|
20
|
+
def bundled_files
|
21
|
+
files = nil
|
22
|
+
Dir.chdir(File.dirname(@gemfile)) do
|
23
|
+
files = Dir["vendor/bundle/**/*"]
|
24
|
+
end
|
25
|
+
files
|
26
|
+
end
|
27
|
+
|
28
|
+
def file_contents
|
29
|
+
@vendored_gems_installer.install!
|
30
|
+
super_contents = super.merge(read_file_contents(bundled_files+[File.basename(gemfile),File.basename(gemspec),'Gemfile.lock','.bundle/config'], directory))
|
31
|
+
super_contents
|
32
|
+
end
|
33
|
+
|
34
|
+
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require_relative 'files_provider'
|
2
|
+
|
3
|
+
module Source
|
4
|
+
class FilesFromDirectoryProvider < FilesProvider
|
5
|
+
def initialize(directory=".", base_directory=nil)
|
6
|
+
@directory = directory
|
7
|
+
@base_directory = base_directory || directory
|
8
|
+
end
|
9
|
+
|
10
|
+
def file_contents
|
11
|
+
base_path = Pathname.new(@base_directory)
|
12
|
+
files = Dir[File.join(@directory, '**', '*')].collect {|file| Pathname.new(file).relative_path_from(base_path).to_s }
|
13
|
+
read_file_contents(files, @base_directory)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require_relative 'files_provider'
|
2
|
+
module Source
|
3
|
+
class FilesFromGemDirectoryProvider < FilesProvider
|
4
|
+
attr_reader :directory
|
5
|
+
def initialize(directory,files)
|
6
|
+
@directory = directory
|
7
|
+
@files = files
|
8
|
+
end
|
9
|
+
def file_contents
|
10
|
+
read_file_contents @files, @directory
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require_relative '../../file_path_and_permissions'
|
2
|
+
|
3
|
+
#This module is intended as a mixin, you still need to implement
|
4
|
+
# the respective methods, i.e.
|
5
|
+
# base_provider and permission_overrides
|
6
|
+
module OverridesPermissions
|
7
|
+
def file_contents
|
8
|
+
#Beware: Deep magic here.
|
9
|
+
result = base_provider.file_contents.map do |file_with_permissions,content|
|
10
|
+
_,override = permission_overrides.map do |condition,permission|
|
11
|
+
# Find the length of the longest match for the current regexp.
|
12
|
+
longest = file_with_permissions.scan(condition).map do |match|
|
13
|
+
match = match.join if match.kind_of? Array
|
14
|
+
match.length
|
15
|
+
end.max
|
16
|
+
# return the length of the longest match and the associated permission
|
17
|
+
# or nil if there was no match
|
18
|
+
[longest,permission] if longest
|
19
|
+
end.compact.max_by(&:first) #Get the Array with the greatest length in the first component.
|
20
|
+
file_with_permissions = FilePathAndPermissions.new(file_with_permissions,override) if override
|
21
|
+
[file_with_permissions,content]
|
22
|
+
end
|
23
|
+
Hash[*result.flatten]
|
24
|
+
end
|
25
|
+
|
26
|
+
def files
|
27
|
+
file_contents.keys
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
def base_provider
|
32
|
+
raise "Not implemented here. Override this method in the class that includes this module."
|
33
|
+
end
|
34
|
+
def permission_overrides
|
35
|
+
raise "Not implemented here. Override this method in the class that includes this module."
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require_relative 'files_provider'
|
2
|
+
|
3
|
+
module Source
|
4
|
+
class VendoredGemsInstaller
|
5
|
+
attr_reader :gemfile
|
6
|
+
def initialize(gemfile)
|
7
|
+
@gemfile = gemfile
|
8
|
+
@installed = false
|
9
|
+
end
|
10
|
+
def directory
|
11
|
+
File.dirname(@gemfile)
|
12
|
+
end
|
13
|
+
def install!
|
14
|
+
return if @installed
|
15
|
+
backup_fields = ["PATH","GEM_PATH"]
|
16
|
+
bundled_files = []
|
17
|
+
|
18
|
+
old_env = ENV.to_hash
|
19
|
+
Dir.chdir(directory) do
|
20
|
+
::Bundler.with_clean_env do
|
21
|
+
old_env.each {|k,_| ENV.delete k}
|
22
|
+
ENV["BUNDLE_GEMFILE"] = gemfile
|
23
|
+
ENV["PWD"] = directory
|
24
|
+
backup_fields.each {|f| ENV[f] = old_env[f]}
|
25
|
+
FileUtils.rm_rf('.bundle')
|
26
|
+
["bundle install","bundle install --deployment --verbose"].each do |c| # --standalone
|
27
|
+
command_result = `#{c}`
|
28
|
+
raise "#{c.inspect} failed:\n#{command_result}" unless $?.success?
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
old_env.each {|k,v| ENV[k] = v}
|
33
|
+
@installed = true
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
data/lib/gpm/source/gem.rb
CHANGED
@@ -1,9 +1,11 @@
|
|
1
1
|
require_relative '../source'
|
2
|
+
require_relative 'files_providers/files_from_gem_directory_provider'
|
2
3
|
require "rubygems/package"
|
3
4
|
require "rubygems"
|
4
5
|
require 'zlib'
|
5
6
|
|
6
|
-
|
7
|
+
module Source
|
8
|
+
class Gem < Base
|
7
9
|
class FilesFromGemProvider < Source::FilesProvider
|
8
10
|
def initialize(contents)
|
9
11
|
@gem_file_contents = contents
|
@@ -17,7 +19,7 @@ class Source::Gem < Source::Base
|
|
17
19
|
contents
|
18
20
|
end
|
19
21
|
def tar_files(io)
|
20
|
-
tar_reader = Gem::Package::TarReader.new(io)
|
22
|
+
tar_reader = ::Gem::Package::TarReader.new(io)
|
21
23
|
tar_files = {}
|
22
24
|
tar_reader.each do |entry|
|
23
25
|
tar_files[entry.full_name] = entry.read
|
@@ -27,24 +29,6 @@ class Source::Gem < Source::Base
|
|
27
29
|
end
|
28
30
|
end
|
29
31
|
|
30
|
-
class FilesFromGemDirectoryProvider < Source::FilesProvider
|
31
|
-
attr_reader :directory
|
32
|
-
def initialize(directory,files)
|
33
|
-
@directory = directory
|
34
|
-
@files = files
|
35
|
-
end
|
36
|
-
def file_contents
|
37
|
-
read_file_contents @files, @directory
|
38
|
-
end
|
39
|
-
def read_file_contents(files,base_directory)
|
40
|
-
file_contents = {}
|
41
|
-
files.each do |f|
|
42
|
-
path = File.join(base_directory,f)
|
43
|
-
file_contents[f] = File.read(path) if File.file?(path)
|
44
|
-
end
|
45
|
-
file_contents
|
46
|
-
end
|
47
|
-
end
|
48
32
|
|
49
33
|
def self.read_metadata(gem_file)
|
50
34
|
metadata = nil
|
@@ -58,13 +42,16 @@ class Source::Gem < Source::Base
|
|
58
42
|
end
|
59
43
|
end
|
60
44
|
elsif gem_file.end_with?('.gemspec')
|
61
|
-
metadata = Gem::Specification.load(gem_file)
|
45
|
+
metadata = ::Gem::Specification.load(gem_file)
|
46
|
+
else
|
47
|
+
raise "Unknown file type of #{gem_file}. Need a .gem or .gemspec file"
|
62
48
|
end
|
63
49
|
end
|
50
|
+
raise "Could not read metadata for #{gem_file.inspect}" unless metadata
|
64
51
|
metadata
|
65
52
|
end
|
66
53
|
|
67
|
-
def self.create(gem_file)
|
54
|
+
def self.create(gem_file, options = {})
|
68
55
|
metadata = self.read_metadata(gem_file)
|
69
56
|
|
70
57
|
files_provider = nil
|
@@ -77,13 +64,14 @@ class Source::Gem < Source::Base
|
|
77
64
|
files_provider = FilesFromGemDirectoryProvider.new(File.expand_path(File.dirname(gem_file)), metadata.files+[File.basename(gem_file)])
|
78
65
|
end
|
79
66
|
end
|
80
|
-
new(metadata, files_provider)
|
67
|
+
new(metadata, files_provider, options)
|
81
68
|
end
|
82
69
|
|
83
70
|
attr_reader :metadata, :files_provider
|
84
|
-
def initialize(metadata, files_provider = nil)
|
71
|
+
def initialize(metadata, files_provider = nil, options = {})
|
85
72
|
@metadata = metadata
|
86
73
|
@files_provider = files_provider
|
74
|
+
@options = options
|
87
75
|
end
|
88
76
|
|
89
77
|
%w(description license summary version email).each do |method|
|
@@ -91,6 +79,12 @@ class Source::Gem < Source::Base
|
|
91
79
|
metadata.send(method)
|
92
80
|
end
|
93
81
|
end
|
82
|
+
|
83
|
+
%w(owner group destination build_number).each do |method|
|
84
|
+
define_method method do
|
85
|
+
@options[method.to_sym]
|
86
|
+
end
|
87
|
+
end
|
94
88
|
{:maintainer => :author, :url => :homepage}.each do |out_field, in_field|
|
95
89
|
define_method out_field do
|
96
90
|
metadata.send(in_field)
|
@@ -132,12 +126,13 @@ class Source::Gem < Source::Base
|
|
132
126
|
dependencies << "#{name(dep)} #{req}"
|
133
127
|
end
|
134
128
|
end
|
135
|
-
dependencies
|
129
|
+
return dependencies + ["libc6", "ruby"]
|
136
130
|
end
|
137
131
|
def file_contents
|
138
|
-
|
132
|
+
files_provider.nil? ? {} : files_provider.file_contents
|
139
133
|
end
|
140
134
|
def files
|
141
|
-
|
135
|
+
files_provider.files
|
142
136
|
end
|
137
|
+
end
|
143
138
|
end
|
data/lib/gpm/target.rb
CHANGED
@@ -7,6 +7,7 @@ require_relative 'file_path_and_permissions'
|
|
7
7
|
|
8
8
|
require_relative 'target/generate_from_templates'
|
9
9
|
require_relative 'target/zip_directories'
|
10
|
+
require_relative 'io_helpers'
|
10
11
|
module Target
|
11
12
|
class Base
|
12
13
|
PHASES = [:file_creation, :packaging]
|
@@ -19,6 +20,9 @@ module Target
|
|
19
20
|
def self.steps_for_phase(phase)
|
20
21
|
self.send(field_name_for_steps(phase))
|
21
22
|
end
|
23
|
+
def self.add_step_for_phase(phase, block, description = nil)
|
24
|
+
steps_for_phase(phase) << [block, description]
|
25
|
+
end
|
22
26
|
class_inheritable_array *phase_steps_names
|
23
27
|
phase_steps_names.each {|p| self.send("#{p}=".to_sym,[])}
|
24
28
|
|
@@ -28,6 +32,7 @@ module Target
|
|
28
32
|
def initialize(work_dir, options = {})
|
29
33
|
@work_dir = work_dir
|
30
34
|
@logger = ::Logger.new(STDERR)
|
35
|
+
@logger.level = ::Logger::INFO
|
31
36
|
@options = options
|
32
37
|
end
|
33
38
|
|
@@ -43,30 +48,16 @@ module Target
|
|
43
48
|
@origin_dir = Dir.getwd
|
44
49
|
FileUtils.mkdir_p package_dir
|
45
50
|
::Dir.chdir(package_dir) do
|
46
|
-
self.class.phase_steps_names.each do |
|
47
|
-
self.class.send(
|
51
|
+
self.class.phase_steps_names.each do |phase_name|
|
52
|
+
steps_for_phase = self.class.send(phase_name)
|
53
|
+
steps_for_phase.each do |step, description|
|
54
|
+
@logger.info description if description
|
48
55
|
instance_exec source, &step
|
49
56
|
end
|
50
57
|
end
|
51
58
|
end
|
52
59
|
end
|
53
60
|
|
54
|
-
def write_file_contents(file_contents)
|
55
|
-
file_contents.each do |file_name, content|
|
56
|
-
FileUtils.mkdir_p(File.dirname(file_name))
|
57
|
-
File.open(file_name,"w") do |file|
|
58
|
-
file.print content
|
59
|
-
end
|
60
|
-
File.chmod(file_name.permissions, file_name.to_s) if file_name.is_a? FilePathAndPermissions
|
61
|
-
end
|
62
|
-
end
|
63
|
-
|
64
|
-
def write_file_contents_in_directory(file_contents,directory)
|
65
|
-
FileUtils.mkdir_p directory
|
66
|
-
Dir.chdir(directory) do
|
67
|
-
write_file_contents(file_contents)
|
68
|
-
end
|
69
|
-
end
|
70
61
|
|
71
62
|
def tar_directory(directory, options = {})
|
72
63
|
FileUtils.mkdir_p(directory)
|
@@ -80,9 +71,9 @@ module Target
|
|
80
71
|
end
|
81
72
|
|
82
73
|
def exec(*args)
|
83
|
-
|
74
|
+
@logger.debug args.join(" ")
|
84
75
|
success = system(*args)
|
85
|
-
|
76
|
+
@logger.error "#{args.join(" ")} did not complete successfully!" unless success
|
86
77
|
end
|
87
78
|
end
|
88
79
|
end
|
data/lib/gpm/target/deb.rb
CHANGED
@@ -1,23 +1,47 @@
|
|
1
1
|
require_relative '../target'
|
2
|
+
require_relative '../source'
|
3
|
+
require_relative '../source/files_providers/overrides_permissions'
|
2
4
|
require 'erb'
|
3
5
|
require 'delegate'
|
4
6
|
require_relative 'step_plugin'
|
5
7
|
|
6
8
|
class Target::Deb < Target::Base
|
7
9
|
include StepPlugin
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
10
|
+
POST_INST_FILES = /^_package_\/postinst.*$/
|
11
|
+
PRE_RM_FILES = /^_package_\/prerm.*$/
|
12
|
+
SCRIPT_PERMISSIONS = 0750
|
13
|
+
|
14
|
+
def self.architecture(architecture=nil)
|
15
|
+
if architecture.nil? or architecture == "native"
|
16
|
+
# Default architecture should be 'native' which we'll need
|
17
|
+
# to ask the system about.
|
18
|
+
arch = %x{dpkg --print-architecture}.chomp
|
19
|
+
if $?.exitstatus != 0
|
20
|
+
arch = %x{uname -m}.chomp
|
21
|
+
@logger.warn("Can't find 'dpkg' tool (need it to get default " \
|
22
|
+
"architecture!). Please specificy --architecture " \
|
23
|
+
"specifically. (Defaulting now to #{arch})")
|
24
|
+
end
|
25
|
+
arch
|
26
|
+
elsif architecture == "x86_64"
|
27
|
+
# Debian calls x86_64 "amd64"
|
28
|
+
"amd64"
|
29
|
+
else
|
30
|
+
architecture
|
13
31
|
end
|
32
|
+
end
|
14
33
|
|
15
|
-
|
16
|
-
|
34
|
+
class DebianSourceWrapper < SimpleDelegator
|
35
|
+
include OverridesPermissions
|
36
|
+
alias :base_provider :__getobj__
|
37
|
+
def initialize(source)
|
38
|
+
raise("nil source") unless source
|
39
|
+
super(source)
|
40
|
+
@logger = ::Logger.new(STDERR)
|
17
41
|
end
|
18
42
|
|
19
|
-
def
|
20
|
-
|
43
|
+
def permission_overrides
|
44
|
+
{ Regexp.union(POST_INST_FILES, PRE_RM_FILES) => SCRIPT_PERMISSIONS }
|
21
45
|
end
|
22
46
|
|
23
47
|
def name
|
@@ -33,7 +57,7 @@ class Target::Deb < Target::Base
|
|
33
57
|
end
|
34
58
|
|
35
59
|
if name.include?("_")
|
36
|
-
@logger.
|
60
|
+
@logger.debug("Package name '#{name}' includes underscores, converting" \
|
37
61
|
" to dashes")
|
38
62
|
name = name.gsub(/[_]/, "-")
|
39
63
|
end
|
@@ -41,31 +65,14 @@ class Target::Deb < Target::Base
|
|
41
65
|
return name
|
42
66
|
end
|
43
67
|
def architecture
|
44
|
-
architecture
|
45
|
-
if architecture.nil? or architecture == "native"
|
46
|
-
# Default architecture should be 'native' which we'll need
|
47
|
-
# to ask the system about.
|
48
|
-
arch = %x{dpkg --print-architecture}.chomp
|
49
|
-
if $?.exitstatus != 0
|
50
|
-
arch = %x{uname -m}.chomp
|
51
|
-
@logger.warn("Can't find 'dpkg' tool (need it to get default " \
|
52
|
-
"architecture!). Please specificy --architecture " \
|
53
|
-
"specifically. (Defaulting now to #{arch})")
|
54
|
-
end
|
55
|
-
arch
|
56
|
-
elsif architecture == "x86_64"
|
57
|
-
# Debian calls x86_64 "amd64"
|
58
|
-
"amd64"
|
59
|
-
else
|
60
|
-
architecture
|
61
|
-
end
|
68
|
+
Target::Deb.architecture(__getobj__.architecture)
|
62
69
|
end # def architecture
|
63
70
|
|
64
71
|
def default_output
|
65
72
|
name_and_version = "#{name}_#{version}"
|
66
73
|
architecture_and_type = "#{architecture}.#{type}"
|
67
|
-
if
|
68
|
-
"#{name_and_version}
|
74
|
+
if build_number
|
75
|
+
"#{name_and_version}-b#{build_number}_#{architecture_and_type}"
|
69
76
|
else
|
70
77
|
"#{name_and_version}_#{architecture_and_type}"
|
71
78
|
end
|
@@ -95,8 +102,8 @@ class Target::Deb < Target::Base
|
|
95
102
|
nextversion[l-1] = 0
|
96
103
|
nextversion = nextversion.join(".")
|
97
104
|
return ["#{name} (>= #{version})", "#{name} (<< #{nextversion})"]
|
98
|
-
# ignore
|
99
|
-
elsif (m = dep.match(/(\S+)\s+\(= (.+)\)/)) && self.settings[:
|
105
|
+
# ignore build_numbers for = dependencies if flag specified
|
106
|
+
elsif (m = dep.match(/(\S+)\s+\(= (.+)\)/)) && self.settings[:ignore_build_numbers]
|
100
107
|
name, version = m[1..2]
|
101
108
|
nextversion = version.split('.').collect { |v| v.to_i }
|
102
109
|
nextversion[-1] += 1
|
@@ -115,10 +122,11 @@ class Target::Deb < Target::Base
|
|
115
122
|
Dir["**/*.so"]
|
116
123
|
end
|
117
124
|
|
118
|
-
in_phase(:file_creation) { exec("strip --strip-unneeded #{all_binaries.join(' ')}") unless all_binaries.empty? }
|
119
|
-
in_phase(:file_creation) { exec("chrpath --delete #{all_binaries.join(' ')}") unless all_binaries.empty? }
|
120
|
-
in_phase(:
|
121
|
-
in_phase(:packaging) {|source|
|
125
|
+
in_phase(:file_creation, "Stripping links from binaries...") { exec("strip --strip-unneeded #{all_binaries.join(' ')}") unless all_binaries.empty? }
|
126
|
+
in_phase(:file_creation, "Removing absolute paths from binaries...") { exec("chrpath --delete #{all_binaries.join(' ')}") unless all_binaries.empty? }
|
127
|
+
in_phase(:file_creation, "Making files unwriteable by group and others...") { exec("chmod -R go-w *") }
|
128
|
+
in_phase(:packaging, "Packaging metafiles and files into .deb package...") {|source| exec("ar -qc ../#{source.default_output} debian-binary control.tar.gz data.tar.gz") }
|
129
|
+
in_phase(:packaging, "Copying .deb package to output directory...") {|source| FileUtils.cp("../#{source.default_output}",@origin_dir) }
|
122
130
|
|
123
131
|
def create_package(source)
|
124
132
|
super(DebianSourceWrapper.new(source))
|
@@ -2,7 +2,7 @@ require_relative 'step_plugin'
|
|
2
2
|
require_relative '../file_path_and_permissions'
|
3
3
|
module GenerateFromTemplates
|
4
4
|
include StepPlugin
|
5
|
-
in_phase(:file_creation) { |source| write_files_to_package_dir(source) }
|
5
|
+
in_phase(:file_creation, "Expanding templates...") { |source| write_files_to_package_dir(source) }
|
6
6
|
|
7
7
|
def template_paths
|
8
8
|
@template_paths ||= Dir["#{template_dir}/**/*.erb"]
|
@@ -1,19 +1,20 @@
|
|
1
1
|
module StepPlugin
|
2
2
|
def self.included(base)
|
3
3
|
if base.is_a? Class
|
4
|
-
def base.in_phase(phase, &block)
|
5
|
-
self.
|
4
|
+
def base.in_phase(phase, description=nil, &block)
|
5
|
+
self.add_step_for_phase(phase,block,description)
|
6
6
|
end
|
7
7
|
elsif base.is_a? Module
|
8
|
-
def base.in_phase(phase, &block)
|
8
|
+
def base.in_phase(phase, description=nil, &block)
|
9
9
|
@phase_blocks||= {}
|
10
10
|
@phase_blocks[phase] ||= []
|
11
|
-
@phase_blocks[phase] << block
|
11
|
+
@phase_blocks[phase] << [block, description]
|
12
12
|
end
|
13
13
|
def base.included(clazz)
|
14
14
|
@phase_blocks.each do |phase, blocks|
|
15
|
-
blocks.each do |
|
16
|
-
|
15
|
+
blocks.each do |block_and_description|
|
16
|
+
block, description = block_and_description
|
17
|
+
clazz.add_step_for_phase(phase,block,description)
|
17
18
|
end
|
18
19
|
end
|
19
20
|
end
|
@@ -1,5 +1,5 @@
|
|
1
1
|
Package: <%= name %>
|
2
|
-
Version: <%= "#{epoch}:" if epoch %><%= version %><%=
|
2
|
+
Version: <%= "#{epoch}:" if epoch %><%= version %><%= build_number && '-b'+build_number.to_s %>
|
3
3
|
Architecture: <%= architecture %>
|
4
4
|
Maintainer: <%= maintainer or "<unknown>" %><%= " <#{email}>".gsub(" <>","") %>
|
5
5
|
<% if !dependencies.empty? -%>
|
File without changes
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: gpm
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.1.3
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,11 +9,11 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2011-
|
12
|
+
date: 2011-09-14 00:00:00.000000000Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: json
|
16
|
-
requirement: &
|
16
|
+
requirement: &75731240 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ! '>='
|
@@ -21,10 +21,10 @@ dependencies:
|
|
21
21
|
version: '0'
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
24
|
+
version_requirements: *75731240
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: thor
|
27
|
-
requirement: &
|
27
|
+
requirement: &75730810 !ruby/object:Gem::Requirement
|
28
28
|
none: false
|
29
29
|
requirements:
|
30
30
|
- - ~>
|
@@ -32,10 +32,10 @@ dependencies:
|
|
32
32
|
version: 0.14.6
|
33
33
|
type: :runtime
|
34
34
|
prerelease: false
|
35
|
-
version_requirements: *
|
35
|
+
version_requirements: *75730810
|
36
36
|
- !ruby/object:Gem::Dependency
|
37
37
|
name: activesupport
|
38
|
-
requirement: &
|
38
|
+
requirement: &75730540 !ruby/object:Gem::Requirement
|
39
39
|
none: false
|
40
40
|
requirements:
|
41
41
|
- - ! '>='
|
@@ -43,10 +43,10 @@ dependencies:
|
|
43
43
|
version: '0'
|
44
44
|
type: :runtime
|
45
45
|
prerelease: false
|
46
|
-
version_requirements: *
|
46
|
+
version_requirements: *75730540
|
47
47
|
- !ruby/object:Gem::Dependency
|
48
48
|
name: i18n
|
49
|
-
requirement: &
|
49
|
+
requirement: &75730250 !ruby/object:Gem::Requirement
|
50
50
|
none: false
|
51
51
|
requirements:
|
52
52
|
- - ! '>='
|
@@ -54,10 +54,10 @@ dependencies:
|
|
54
54
|
version: '0'
|
55
55
|
type: :runtime
|
56
56
|
prerelease: false
|
57
|
-
version_requirements: *
|
57
|
+
version_requirements: *75730250
|
58
58
|
- !ruby/object:Gem::Dependency
|
59
59
|
name: cucumber
|
60
|
-
requirement: &
|
60
|
+
requirement: &75729940 !ruby/object:Gem::Requirement
|
61
61
|
none: false
|
62
62
|
requirements:
|
63
63
|
- - ~>
|
@@ -65,10 +65,10 @@ dependencies:
|
|
65
65
|
version: 1.0.2
|
66
66
|
type: :development
|
67
67
|
prerelease: false
|
68
|
-
version_requirements: *
|
68
|
+
version_requirements: *75729940
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
70
|
name: aruba
|
71
|
-
requirement: &
|
71
|
+
requirement: &75729620 !ruby/object:Gem::Requirement
|
72
72
|
none: false
|
73
73
|
requirements:
|
74
74
|
- - ~>
|
@@ -76,32 +76,32 @@ dependencies:
|
|
76
76
|
version: 0.4.3
|
77
77
|
type: :development
|
78
78
|
prerelease: false
|
79
|
-
version_requirements: *
|
79
|
+
version_requirements: *75729620
|
80
80
|
- !ruby/object:Gem::Dependency
|
81
81
|
name: guard
|
82
|
-
requirement: &
|
82
|
+
requirement: &75729360 !ruby/object:Gem::Requirement
|
83
83
|
none: false
|
84
84
|
requirements:
|
85
85
|
- - ~>
|
86
86
|
- !ruby/object:Gem::Version
|
87
|
-
version: 0.
|
87
|
+
version: 0.7.0
|
88
88
|
type: :development
|
89
89
|
prerelease: false
|
90
|
-
version_requirements: *
|
90
|
+
version_requirements: *75729360
|
91
91
|
- !ruby/object:Gem::Dependency
|
92
92
|
name: guard-cucumber
|
93
|
-
requirement: &
|
93
|
+
requirement: &75729110 !ruby/object:Gem::Requirement
|
94
94
|
none: false
|
95
95
|
requirements:
|
96
96
|
- - ~>
|
97
97
|
- !ruby/object:Gem::Version
|
98
|
-
version: 0.
|
98
|
+
version: 0.6.3
|
99
99
|
type: :development
|
100
100
|
prerelease: false
|
101
|
-
version_requirements: *
|
101
|
+
version_requirements: *75729110
|
102
102
|
- !ruby/object:Gem::Dependency
|
103
103
|
name: guard-bundler
|
104
|
-
requirement: &
|
104
|
+
requirement: &75728810 !ruby/object:Gem::Requirement
|
105
105
|
none: false
|
106
106
|
requirements:
|
107
107
|
- - ~>
|
@@ -109,18 +109,40 @@ dependencies:
|
|
109
109
|
version: 0.1.3
|
110
110
|
type: :development
|
111
111
|
prerelease: false
|
112
|
-
version_requirements: *
|
112
|
+
version_requirements: *75728810
|
113
113
|
- !ruby/object:Gem::Dependency
|
114
114
|
name: guard-rspec
|
115
|
-
requirement: &
|
115
|
+
requirement: &75728460 !ruby/object:Gem::Requirement
|
116
116
|
none: false
|
117
117
|
requirements:
|
118
118
|
- - ~>
|
119
119
|
- !ruby/object:Gem::Version
|
120
|
-
version: 0.4.
|
120
|
+
version: 0.4.5
|
121
121
|
type: :development
|
122
122
|
prerelease: false
|
123
|
-
version_requirements: *
|
123
|
+
version_requirements: *75728460
|
124
|
+
- !ruby/object:Gem::Dependency
|
125
|
+
name: fakefs
|
126
|
+
requirement: &75728070 !ruby/object:Gem::Requirement
|
127
|
+
none: false
|
128
|
+
requirements:
|
129
|
+
- - ~>
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: 0.3.2
|
132
|
+
type: :development
|
133
|
+
prerelease: false
|
134
|
+
version_requirements: *75728070
|
135
|
+
- !ruby/object:Gem::Dependency
|
136
|
+
name: simplecov
|
137
|
+
requirement: &75727760 !ruby/object:Gem::Requirement
|
138
|
+
none: false
|
139
|
+
requirements:
|
140
|
+
- - ~>
|
141
|
+
- !ruby/object:Gem::Version
|
142
|
+
version: 0.4.2
|
143
|
+
type: :development
|
144
|
+
prerelease: false
|
145
|
+
version_requirements: *75727760
|
124
146
|
description: Convert directories, rpms, python eggs, rubygems, and more to rpms, debs,
|
125
147
|
solaris packages and more. Win at package management without wasting pointless hours
|
126
148
|
debugging bad rpm specs!
|
@@ -131,21 +153,32 @@ extensions: []
|
|
131
153
|
extra_rdoc_files: []
|
132
154
|
files:
|
133
155
|
- lib/gpm/cli.rb
|
156
|
+
- lib/gpm/source/files_providers/composite_files_provider.rb
|
157
|
+
- lib/gpm/source/files_providers/files_from_gem_directory_provider.rb
|
158
|
+
- lib/gpm/source/files_providers/overrides_permissions.rb
|
159
|
+
- lib/gpm/source/files_providers/vendored_gems_installer.rb
|
160
|
+
- lib/gpm/source/files_providers/files_from_bundler_directory_provider.rb
|
161
|
+
- lib/gpm/source/files_providers/files_from_directory_provider.rb
|
162
|
+
- lib/gpm/source/files_providers/files_provider.rb
|
134
163
|
- lib/gpm/source/bundler.rb
|
135
164
|
- lib/gpm/source/gem.rb
|
136
165
|
- lib/gpm/packaging_task.rb
|
137
166
|
- lib/gpm/file_path_and_permissions.rb
|
138
167
|
- lib/gpm/target.rb
|
139
168
|
- lib/gpm/source.rb
|
169
|
+
- lib/gpm/io_helpers.rb
|
140
170
|
- lib/gpm/target/generate_from_templates.rb
|
141
171
|
- lib/gpm/target/deb.rb
|
142
172
|
- lib/gpm/target/zip_directories.rb
|
143
173
|
- lib/gpm/target/step_plugin.rb
|
174
|
+
- bin/correct_permissions
|
144
175
|
- bin/gpm
|
145
176
|
- templates/deb/data.tar.gz.dir/usr/share/doc/__name__/copyright.erb
|
146
|
-
- templates/deb/data.tar.gz.dir/usr/share/doc/__name__/changelog.gz.erb
|
177
|
+
- templates/deb/data.tar.gz.dir/usr/share/doc/__name__/changelog.Debian.gz.erb
|
147
178
|
- templates/deb/control.tar.gz.dir/md5sums.erb
|
179
|
+
- templates/deb/control.tar.gz.dir/postinst.erb
|
148
180
|
- templates/deb/control.tar.gz.dir/control.erb
|
181
|
+
- templates/deb/control.tar.gz.dir/prerm.erb
|
149
182
|
- templates/deb/debian-binary.erb
|
150
183
|
homepage: https://github.com/crealytics/gpm
|
151
184
|
licenses: []
|