gpm 0.0.1
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/gpm +8 -0
- data/lib/gpm/cli.rb +23 -0
- data/lib/gpm/file_path_and_permissions.rb +19 -0
- data/lib/gpm/packaging_task.rb +25 -0
- data/lib/gpm/source.rb +55 -0
- data/lib/gpm/source/bundler.rb +55 -0
- data/lib/gpm/source/gem.rb +143 -0
- data/lib/gpm/target.rb +88 -0
- data/lib/gpm/target/deb.rb +131 -0
- data/lib/gpm/target/generate_from_templates.rb +56 -0
- data/lib/gpm/target/step_plugin.rb +22 -0
- data/lib/gpm/target/zip_directories.rb +9 -0
- data/templates/deb/control.tar.gz.dir/control.erb +28 -0
- data/templates/deb/control.tar.gz.dir/md5sums.erb +0 -0
- data/templates/deb/data.tar.gz.dir/usr/share/doc/__name__/changelog.gz.erb +1 -0
- data/templates/deb/data.tar.gz.dir/usr/share/doc/__name__/copyright.erb +1 -0
- data/templates/deb/debian-binary.erb +1 -0
- metadata +175 -0
data/bin/gpm
ADDED
data/lib/gpm/cli.rb
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'thor'
|
2
|
+
require_relative 'packaging_task'
|
3
|
+
class GpmCli < Thor
|
4
|
+
|
5
|
+
# gpm package -s <source type> -t <target type> [options]
|
6
|
+
desc "package APP_DIRECTORY_OR_FILE", "package the given app"
|
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
|
+
|
12
|
+
def package(file_or_directory)
|
13
|
+
raise "Only gem or bundler source at the moment" unless ["gem","bundler"].include? options.source
|
14
|
+
raise "Only deb target at the moment" unless options.target == "deb"
|
15
|
+
package_options = {}
|
16
|
+
{:workdir => :work_dir , :destination => :destination}.each do |in_field, out_field|
|
17
|
+
package_options[out_field] = options[in_field] if options[in_field]
|
18
|
+
end
|
19
|
+
|
20
|
+
PackagingTask.create(file_or_directory, options.source, options.target, package_options).run
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
class FilePathAndPermissions < Delegator
|
2
|
+
attr_reader :permissions
|
3
|
+
def initialize(path, permissions = "0444")
|
4
|
+
@path = path
|
5
|
+
@permissions = permissions
|
6
|
+
end
|
7
|
+
|
8
|
+
def to_s
|
9
|
+
@path
|
10
|
+
end
|
11
|
+
|
12
|
+
def __getobj__
|
13
|
+
@path
|
14
|
+
end
|
15
|
+
|
16
|
+
def __setobj__(path)
|
17
|
+
@path = path
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
class PackagingTask
|
2
|
+
def self.create(file_or_directory, source_name, target_name, options = {})
|
3
|
+
options[:work_dir] ||= Dir.mktmpdir
|
4
|
+
require_relative "source"
|
5
|
+
require_relative "source/#{source_name}"
|
6
|
+
source_class = Kernel.const_get("Source").const_get(source_name.capitalize)
|
7
|
+
source = source_class.create(file_or_directory)
|
8
|
+
|
9
|
+
require_relative "target"
|
10
|
+
require_relative "target/#{target_name}"
|
11
|
+
target_class = Kernel.const_get("Target").const_get(target_name.capitalize)
|
12
|
+
target = target_class.new(options[:work_dir], options)
|
13
|
+
new(source,target)
|
14
|
+
end
|
15
|
+
|
16
|
+
def initialize(source,target)
|
17
|
+
@source = source
|
18
|
+
@target = target
|
19
|
+
end
|
20
|
+
|
21
|
+
def run
|
22
|
+
@target.create_package(@source)
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
data/lib/gpm/source.rb
ADDED
@@ -0,0 +1,55 @@
|
|
1
|
+
module Source
|
2
|
+
class Base
|
3
|
+
DEFAULTS = {
|
4
|
+
# Default version is 1.0 in case nobody told us a specific version.
|
5
|
+
:version => "1.0",
|
6
|
+
:iteration => nil,
|
7
|
+
:epoch => nil,
|
8
|
+
# If architecture is nil, the target package should provide a default.
|
9
|
+
# Special 'architecture' values include "all" (aka rpm's noarch, debian's all)
|
10
|
+
# Another special includes "native" which will be the current platform's arch.
|
11
|
+
:architecture => nil,
|
12
|
+
:dependencies => [],
|
13
|
+
:provides => [],
|
14
|
+
:replaces => [],
|
15
|
+
:conflicts => [],
|
16
|
+
:scripts => [],
|
17
|
+
:config_files => [],
|
18
|
+
:settings => {},
|
19
|
+
:url => "http://nourlgiven.example.com/no/url/given",
|
20
|
+
:category => "default",
|
21
|
+
:license => "unknown",
|
22
|
+
:maintainer => nil,
|
23
|
+
:description => "no description given"
|
24
|
+
}
|
25
|
+
DEFAULTS.each do |field, default_value|
|
26
|
+
define_method field do
|
27
|
+
default_value
|
28
|
+
end
|
29
|
+
end
|
30
|
+
def maintainer
|
31
|
+
# Default maintainer if none given.
|
32
|
+
if @maintainer.nil? or @maintainer.empty?
|
33
|
+
# Reference
|
34
|
+
# http://www.debian.org/doc/manuals/maint-guide/first.en.html
|
35
|
+
# http://wiki.debian.org/DeveloperConfiguration
|
36
|
+
# https://github.com/jordansissel/fpm/issues/37
|
37
|
+
if ENV.include?("DEBEMAIL") and ENV.include?("DEBFULLNAME")
|
38
|
+
# Use DEBEMAIL and DEBFULLNAME as the default maintainer if available.
|
39
|
+
@maintainer = "#{ENV["DEBFULLNAME"]} <#{ENV["DEBEMAIL"]}>"
|
40
|
+
else
|
41
|
+
# TODO(sissel): Maybe support using 'git config' for a default as well?
|
42
|
+
# git config --get user.name, etc can be useful.
|
43
|
+
#
|
44
|
+
# Otherwise default to user@currenthost
|
45
|
+
@maintainer = "<#{ENV["USER"]}@#{Socket.gethostname}>"
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
class FilesProvider
|
51
|
+
def files
|
52
|
+
file_contents.keys
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
require_relative 'gem'
|
2
|
+
require 'bundler'
|
3
|
+
|
4
|
+
|
5
|
+
class Source::Bundler < Source::Gem
|
6
|
+
|
7
|
+
class FilesFromBundlerDirectoryProvider < Source::Gem::FilesFromGemDirectoryProvider
|
8
|
+
|
9
|
+
attr_reader :gemfile,:gemspec
|
10
|
+
def initialize(gemfile,gemspec)
|
11
|
+
super(File.dirname(gemfile),Source::Gem.read_metadata(gemspec).files)
|
12
|
+
@gemfile = gemfile
|
13
|
+
@gemspec = gemspec
|
14
|
+
end
|
15
|
+
def file_contents
|
16
|
+
backup_fields = ["PATH","GEM_PATH"]
|
17
|
+
bundled_files = []
|
18
|
+
directory = File.dirname(@gemfile)
|
19
|
+
old_env = ENV.to_hash
|
20
|
+
Dir.chdir(directory) do
|
21
|
+
Bundler.with_clean_env do
|
22
|
+
old_env.each {|k,_| ENV.delete k}
|
23
|
+
ENV["BUNDLE_GEMFILE"] = @gemfile
|
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
|
36
|
+
end
|
37
|
+
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
|
@@ -0,0 +1,143 @@
|
|
1
|
+
require_relative '../source'
|
2
|
+
require "rubygems/package"
|
3
|
+
require "rubygems"
|
4
|
+
require 'zlib'
|
5
|
+
|
6
|
+
class Source::Gem < Source::Base
|
7
|
+
class FilesFromGemProvider < Source::FilesProvider
|
8
|
+
def initialize(contents)
|
9
|
+
@gem_file_contents = contents
|
10
|
+
end
|
11
|
+
def file_contents
|
12
|
+
return {} unless @gem_file_contents
|
13
|
+
tar_files = tar_files(StringIO.new(@gem_file_contents))
|
14
|
+
reader = Zlib::GzipReader.new(StringIO.new(tar_files["data.tar.gz"]))
|
15
|
+
contents = tar_files(reader)
|
16
|
+
reader.close
|
17
|
+
contents
|
18
|
+
end
|
19
|
+
def tar_files(io)
|
20
|
+
tar_reader = Gem::Package::TarReader.new(io)
|
21
|
+
tar_files = {}
|
22
|
+
tar_reader.each do |entry|
|
23
|
+
tar_files[entry.full_name] = entry.read
|
24
|
+
end
|
25
|
+
tar_reader.close
|
26
|
+
tar_files
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
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
|
+
|
49
|
+
def self.read_metadata(gem_file)
|
50
|
+
metadata = nil
|
51
|
+
|
52
|
+
Dir.chdir(File.dirname(gem_file)) do
|
53
|
+
if gem_file.end_with?('.gem')
|
54
|
+
contents = nil
|
55
|
+
File.open(gem_file, 'r') do |f|
|
56
|
+
::Gem::Package.open(f, 'r') do |gem|
|
57
|
+
metadata = gem.metadata
|
58
|
+
end
|
59
|
+
end
|
60
|
+
elsif gem_file.end_with?('.gemspec')
|
61
|
+
metadata = Gem::Specification.load(gem_file)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
metadata
|
65
|
+
end
|
66
|
+
|
67
|
+
def self.create(gem_file)
|
68
|
+
metadata = self.read_metadata(gem_file)
|
69
|
+
|
70
|
+
files_provider = nil
|
71
|
+
Dir.chdir(File.dirname(gem_file)) do
|
72
|
+
if gem_file.end_with?('.gem')
|
73
|
+
File.open(gem_file, 'r') do |f|
|
74
|
+
files_provider = FilesFromGemProvider.new(f.read)
|
75
|
+
end
|
76
|
+
elsif gem_file.end_with?('.gemspec')
|
77
|
+
files_provider = FilesFromGemDirectoryProvider.new(File.expand_path(File.dirname(gem_file)), metadata.files+[File.basename(gem_file)])
|
78
|
+
end
|
79
|
+
end
|
80
|
+
new(metadata, files_provider)
|
81
|
+
end
|
82
|
+
|
83
|
+
attr_reader :metadata, :files_provider
|
84
|
+
def initialize(metadata, files_provider = nil)
|
85
|
+
@metadata = metadata
|
86
|
+
@files_provider = files_provider
|
87
|
+
end
|
88
|
+
|
89
|
+
%w(description license summary version email).each do |method|
|
90
|
+
define_method method do
|
91
|
+
metadata.send(method)
|
92
|
+
end
|
93
|
+
end
|
94
|
+
{:maintainer => :author, :url => :homepage}.each do |out_field, in_field|
|
95
|
+
define_method out_field do
|
96
|
+
metadata.send(in_field)
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
def name(name_provider=nil)
|
101
|
+
name_provider ||= metadata
|
102
|
+
"rubygem-#{name_provider.name}"
|
103
|
+
end
|
104
|
+
|
105
|
+
def category
|
106
|
+
# TODO: this will be different for different
|
107
|
+
# package managers. Need to decide how to handle this.
|
108
|
+
'Languages/Development/Ruby'
|
109
|
+
end
|
110
|
+
|
111
|
+
def architecture
|
112
|
+
# if the gemspec has extensions defined, then this should be a 'native' arch.
|
113
|
+
if !metadata.extensions.empty?
|
114
|
+
"native"
|
115
|
+
else
|
116
|
+
"all"
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
def dependencies
|
121
|
+
dependencies = []
|
122
|
+
metadata.runtime_dependencies.map do |dep|
|
123
|
+
# rubygems 1.3.5 doesn't have 'Gem::Dependency#requirement'
|
124
|
+
if dep.respond_to?(:requirement)
|
125
|
+
reqs = dep.requirement.to_s.gsub(/,/, '')
|
126
|
+
else
|
127
|
+
reqs = dep.version_requirements
|
128
|
+
end
|
129
|
+
|
130
|
+
# Some reqs can be ">= a, < b" versions, let's handle that.
|
131
|
+
reqs.to_s.split(/, */).each do |req|
|
132
|
+
dependencies << "#{name(dep)} #{req}"
|
133
|
+
end
|
134
|
+
end
|
135
|
+
dependencies
|
136
|
+
end
|
137
|
+
def file_contents
|
138
|
+
@files_provider.nil? ? {} : @files_provider.file_contents
|
139
|
+
end
|
140
|
+
def files
|
141
|
+
@files_provider.files
|
142
|
+
end
|
143
|
+
end
|
data/lib/gpm/target.rb
ADDED
@@ -0,0 +1,88 @@
|
|
1
|
+
require 'tmpdir'
|
2
|
+
require 'fileutils'
|
3
|
+
require 'logger'
|
4
|
+
require 'active_support/core_ext/array'
|
5
|
+
require 'active_support/core_ext/class'
|
6
|
+
require_relative 'file_path_and_permissions'
|
7
|
+
|
8
|
+
require_relative 'target/generate_from_templates'
|
9
|
+
require_relative 'target/zip_directories'
|
10
|
+
module Target
|
11
|
+
class Base
|
12
|
+
PHASES = [:file_creation, :packaging]
|
13
|
+
def self.phase_steps_names
|
14
|
+
PHASES.collect {|p| field_name_for_steps p }
|
15
|
+
end
|
16
|
+
def self.field_name_for_steps(phase)
|
17
|
+
"#{phase}_steps".to_sym
|
18
|
+
end
|
19
|
+
def self.steps_for_phase(phase)
|
20
|
+
self.send(field_name_for_steps(phase))
|
21
|
+
end
|
22
|
+
class_inheritable_array *phase_steps_names
|
23
|
+
phase_steps_names.each {|p| self.send("#{p}=".to_sym,[])}
|
24
|
+
|
25
|
+
include GenerateFromTemplates
|
26
|
+
include ZipDirectories
|
27
|
+
attr_reader :work_dir, :options
|
28
|
+
def initialize(work_dir, options = {})
|
29
|
+
@work_dir = work_dir
|
30
|
+
@logger = ::Logger.new(STDERR)
|
31
|
+
@options = options
|
32
|
+
end
|
33
|
+
|
34
|
+
def type
|
35
|
+
self.class.name.downcase.gsub("target::","")
|
36
|
+
end
|
37
|
+
|
38
|
+
def package_dir
|
39
|
+
File.join(work_dir,'package_files')
|
40
|
+
end
|
41
|
+
|
42
|
+
def create_package(source)
|
43
|
+
@origin_dir = Dir.getwd
|
44
|
+
FileUtils.mkdir_p package_dir
|
45
|
+
::Dir.chdir(package_dir) do
|
46
|
+
self.class.phase_steps_names.each do |steps|
|
47
|
+
self.class.send(steps).each do |step|
|
48
|
+
instance_exec *([source][0,step.parameters.size]), &step
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
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
|
+
|
71
|
+
def tar_directory(directory, options = {})
|
72
|
+
FileUtils.mkdir_p(directory)
|
73
|
+
::Dir.chdir(directory) do
|
74
|
+
tar(File.join('..',directory.gsub('.dir','')),[''], options)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def tar(output, files, options={})
|
79
|
+
exec("tar -zcf #{output} #{files.map{ |f| "./#{f}" }.join(" ")} "+options.collect {|k,v| "--#{k}=#{v}"}.join(" "))
|
80
|
+
end
|
81
|
+
|
82
|
+
def exec(*args)
|
83
|
+
puts args.join(" ")
|
84
|
+
success = system(*args)
|
85
|
+
puts "#{args.join(" ")} did not complete successfully!" unless success
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
@@ -0,0 +1,131 @@
|
|
1
|
+
require_relative '../target'
|
2
|
+
require 'erb'
|
3
|
+
require 'delegate'
|
4
|
+
require_relative 'step_plugin'
|
5
|
+
|
6
|
+
class Target::Deb < Target::Base
|
7
|
+
include StepPlugin
|
8
|
+
class DebianSourceWrapper < Delegator
|
9
|
+
def initialize(source)
|
10
|
+
super
|
11
|
+
@delegate_sd_obj = source || raise("nil source")
|
12
|
+
@logger = ::Logger.new(STDERR)
|
13
|
+
end
|
14
|
+
|
15
|
+
def __getobj__
|
16
|
+
@delegate_sd_obj # return object we are delegating to, required
|
17
|
+
end
|
18
|
+
|
19
|
+
def __setobj__(source)
|
20
|
+
@delegate_sd_obj = source # change delegation object, a feature we're providing
|
21
|
+
end
|
22
|
+
|
23
|
+
def name
|
24
|
+
clean_package_name(__getobj__.name)
|
25
|
+
end
|
26
|
+
def clean_package_name(name)
|
27
|
+
if name =~ /[A-Z]/
|
28
|
+
@logger.warn("Debian tools (dpkg/apt) don't do well with packages " \
|
29
|
+
"that use capital letters in the name. In some cases it will " \
|
30
|
+
"automatically downcase them, in others it will not. It is confusing." \
|
31
|
+
"Best to not use any capital letters at all.")
|
32
|
+
name = name.downcase
|
33
|
+
end
|
34
|
+
|
35
|
+
if name.include?("_")
|
36
|
+
@logger.info("Package name '#{name}' includes underscores, converting" \
|
37
|
+
" to dashes")
|
38
|
+
name = name.gsub(/[_]/, "-")
|
39
|
+
end
|
40
|
+
|
41
|
+
return name
|
42
|
+
end
|
43
|
+
def architecture
|
44
|
+
architecture = __getobj__.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
|
62
|
+
end # def architecture
|
63
|
+
|
64
|
+
def default_output
|
65
|
+
name_and_version = "#{name}_#{version}"
|
66
|
+
architecture_and_type = "#{architecture}.#{type}"
|
67
|
+
if iteration
|
68
|
+
"#{name_and_version}-#{iteration}_#{architecture_and_type}"
|
69
|
+
else
|
70
|
+
"#{name_and_version}_#{architecture_and_type}"
|
71
|
+
end
|
72
|
+
end # def default_output
|
73
|
+
def fix_dependency(dep)
|
74
|
+
if dep =~ /[\(,\|]/
|
75
|
+
# Don't "fix" ones that could appear well formed already.
|
76
|
+
else
|
77
|
+
da = dep.split(/ +/)
|
78
|
+
if da.size > 1
|
79
|
+
# Convert strings 'foo >= bar' to 'foo (>= bar)'
|
80
|
+
dep = "#{da[0]} (#{da[1]} #{da[2]})"
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
name_re = /^[^ \(]+/
|
85
|
+
name = dep[name_re]
|
86
|
+
name = clean_package_name(name)
|
87
|
+
|
88
|
+
|
89
|
+
# Convert gem ~> X.Y.Z to '>= X.Y.Z' and << X.Y+1.0
|
90
|
+
if dep =~ /\(~>/
|
91
|
+
name, version = dep.gsub(/[()~>]/, "").split(/ +/)[0..1]
|
92
|
+
nextversion = version.split(".").collect { |v| v.to_i }
|
93
|
+
l = nextversion.length
|
94
|
+
nextversion[l-2] += 1
|
95
|
+
nextversion[l-1] = 0
|
96
|
+
nextversion = nextversion.join(".")
|
97
|
+
return ["#{name} (>= #{version})", "#{name} (<< #{nextversion})"]
|
98
|
+
# ignore iterations for = dependencies if flag specified
|
99
|
+
elsif (m = dep.match(/(\S+)\s+\(= (.+)\)/)) && self.settings[:ignore_iteration]
|
100
|
+
name, version = m[1..2]
|
101
|
+
nextversion = version.split('.').collect { |v| v.to_i }
|
102
|
+
nextversion[-1] += 1
|
103
|
+
nextversion = nextversion.join(".")
|
104
|
+
return ["#{name} (>= #{version})", "#{name} (<< #{nextversion})"]
|
105
|
+
else
|
106
|
+
return dep
|
107
|
+
end
|
108
|
+
end
|
109
|
+
def type
|
110
|
+
"deb"
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
def all_binaries
|
115
|
+
Dir["**/*.so"]
|
116
|
+
end
|
117
|
+
|
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(:packaging) {|source| exec("ar -qc ../#{source.default_output} debian-binary control.tar.gz data.tar.gz") }
|
121
|
+
in_phase(:packaging) {|source| FileUtils.cp("../#{source.default_output}",@origin_dir) }
|
122
|
+
|
123
|
+
def create_package(source)
|
124
|
+
super(DebianSourceWrapper.new(source))
|
125
|
+
end
|
126
|
+
def write_files_to_package_dir(source)
|
127
|
+
super
|
128
|
+
write_file_contents_in_directory source.file_contents, File.join("data.tar.gz.dir",options[:destination] || "")
|
129
|
+
end
|
130
|
+
|
131
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
require_relative 'step_plugin'
|
2
|
+
require_relative '../file_path_and_permissions'
|
3
|
+
module GenerateFromTemplates
|
4
|
+
include StepPlugin
|
5
|
+
in_phase(:file_creation) { |source| write_files_to_package_dir(source) }
|
6
|
+
|
7
|
+
def template_paths
|
8
|
+
@template_paths ||= Dir["#{template_dir}/**/*.erb"]
|
9
|
+
end
|
10
|
+
|
11
|
+
def template_dir
|
12
|
+
File.expand_path("../../../templates/#{type}/", File.dirname(__FILE__))
|
13
|
+
end
|
14
|
+
|
15
|
+
def template_files
|
16
|
+
template_paths.map {|tp| tp.gsub(/#{template_dir}\//,"")}
|
17
|
+
end
|
18
|
+
|
19
|
+
def templates
|
20
|
+
Hash[*template_paths.map {|file| FilePathAndPermissions.new(file.gsub(/#{template_dir}\//,"").gsub(".erb",""),File.new(file).lstat.mode)}.zip(template_paths.map do |template_file|
|
21
|
+
tpl = File.read(template_file)
|
22
|
+
::ERB.new(tpl, nil, "-")
|
23
|
+
end).flatten]
|
24
|
+
end
|
25
|
+
|
26
|
+
def file_contents_from_templates(source)
|
27
|
+
Hash[*templates.map {|file,template| [packaged_file_name(file,source),file_content(template, source, file)]}.flatten]
|
28
|
+
end
|
29
|
+
|
30
|
+
def write_files_to_package_dir(source)
|
31
|
+
write_file_contents_in_directory file_contents_from_templates(source), '.'
|
32
|
+
end
|
33
|
+
|
34
|
+
REPLACEMENT_REGEXP = /__(\w+)__/
|
35
|
+
def packaged_file_name(file_name,source)
|
36
|
+
to_replace = file_name.scan(REPLACEMENT_REGEXP).flatten
|
37
|
+
to_replace.each do |replace|
|
38
|
+
file_name = file_name.gsub("__#{replace}__",source.send(replace.to_sym))
|
39
|
+
end
|
40
|
+
file_name
|
41
|
+
end
|
42
|
+
|
43
|
+
def file_content(template, source, file)
|
44
|
+
contents = template.result(source.instance_eval{ binding() })
|
45
|
+
basename = File.basename(file)
|
46
|
+
if file.end_with?(".gz")
|
47
|
+
zipped = ""
|
48
|
+
gz = Zlib::GzipWriter.new(StringIO.new(zipped))
|
49
|
+
gz.write contents
|
50
|
+
gz.close
|
51
|
+
contents = zipped
|
52
|
+
end
|
53
|
+
contents
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module StepPlugin
|
2
|
+
def self.included(base)
|
3
|
+
if base.is_a? Class
|
4
|
+
def base.in_phase(phase, &block)
|
5
|
+
self.steps_for_phase(phase) << block
|
6
|
+
end
|
7
|
+
elsif base.is_a? Module
|
8
|
+
def base.in_phase(phase, &block)
|
9
|
+
@phase_blocks||= {}
|
10
|
+
@phase_blocks[phase] ||= []
|
11
|
+
@phase_blocks[phase] << block
|
12
|
+
end
|
13
|
+
def base.included(clazz)
|
14
|
+
@phase_blocks.each do |phase, blocks|
|
15
|
+
blocks.each do |block|
|
16
|
+
clazz.steps_for_phase(phase) << block
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
Package: <%= name %>
|
2
|
+
Version: <%= "#{epoch}:" if epoch %><%= version %><%= iteration && '-'+iteration.to_s %>
|
3
|
+
Architecture: <%= architecture %>
|
4
|
+
Maintainer: <%= maintainer or "<unknown>" %><%= " <#{email}>".gsub(" <>","") %>
|
5
|
+
<% if !dependencies.empty? -%>
|
6
|
+
<% properdeps = dependencies.collect { |d| fix_dependency(d) }.flatten -%>
|
7
|
+
Depends: <%= properdeps.flatten.join(", ") %>
|
8
|
+
<% end -%>
|
9
|
+
<% if !conflicts.empty? -%>
|
10
|
+
Conflicts: <%= conflicts.join(", ") %>
|
11
|
+
<% end -%>
|
12
|
+
<% if !provides.empty? -%>
|
13
|
+
Provides: <%= provides.join(", ") %>
|
14
|
+
<% end -%>
|
15
|
+
<% if !replaces.empty? -%>
|
16
|
+
<% properrepl = replaces.collect { |d| fix_dependency(d) }.flatten -%>
|
17
|
+
Replaces: <%= properrepl.flatten.join(", ") %>
|
18
|
+
<% end -%>
|
19
|
+
Standards-Version: 3.9.1
|
20
|
+
Section: <%= category or "unknown" %>
|
21
|
+
Priority: extra
|
22
|
+
Homepage: <%= url or "http://nourlgiven.example.com/" %>
|
23
|
+
<% lines = (description or "no description given").split("\n") -%>
|
24
|
+
<% firstline, *remainder = lines -%>
|
25
|
+
Description: <%= firstline %>
|
26
|
+
<% if remainder.any? -%>
|
27
|
+
<%= remainder.collect { |l| l =~ /^ *$/ ? " ." : " #{l}" }.join("\n") %>
|
28
|
+
<% end -%>
|
File without changes
|
@@ -0,0 +1 @@
|
|
1
|
+
<%= name %> (<%= version %>) unstable; urgency=low
|
@@ -0,0 +1 @@
|
|
1
|
+
<%= license %>
|
@@ -0,0 +1 @@
|
|
1
|
+
2.0
|
metadata
ADDED
@@ -0,0 +1,175 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: gpm
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Martin Mauch
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2011-08-16 00:00:00.000000000Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: json
|
16
|
+
requirement: &76126640 !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: *76126640
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: thor
|
27
|
+
requirement: &76124890 !ruby/object:Gem::Requirement
|
28
|
+
none: false
|
29
|
+
requirements:
|
30
|
+
- - ~>
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: 0.14.6
|
33
|
+
type: :runtime
|
34
|
+
prerelease: false
|
35
|
+
version_requirements: *76124890
|
36
|
+
- !ruby/object:Gem::Dependency
|
37
|
+
name: activesupport
|
38
|
+
requirement: &76124160 !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - ! '>='
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: '0'
|
44
|
+
type: :runtime
|
45
|
+
prerelease: false
|
46
|
+
version_requirements: *76124160
|
47
|
+
- !ruby/object:Gem::Dependency
|
48
|
+
name: i18n
|
49
|
+
requirement: &76115690 !ruby/object:Gem::Requirement
|
50
|
+
none: false
|
51
|
+
requirements:
|
52
|
+
- - ! '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
type: :runtime
|
56
|
+
prerelease: false
|
57
|
+
version_requirements: *76115690
|
58
|
+
- !ruby/object:Gem::Dependency
|
59
|
+
name: cucumber
|
60
|
+
requirement: &76115270 !ruby/object:Gem::Requirement
|
61
|
+
none: false
|
62
|
+
requirements:
|
63
|
+
- - ~>
|
64
|
+
- !ruby/object:Gem::Version
|
65
|
+
version: 1.0.2
|
66
|
+
type: :development
|
67
|
+
prerelease: false
|
68
|
+
version_requirements: *76115270
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: aruba
|
71
|
+
requirement: &76114730 !ruby/object:Gem::Requirement
|
72
|
+
none: false
|
73
|
+
requirements:
|
74
|
+
- - ~>
|
75
|
+
- !ruby/object:Gem::Version
|
76
|
+
version: 0.4.3
|
77
|
+
type: :development
|
78
|
+
prerelease: false
|
79
|
+
version_requirements: *76114730
|
80
|
+
- !ruby/object:Gem::Dependency
|
81
|
+
name: guard
|
82
|
+
requirement: &76114270 !ruby/object:Gem::Requirement
|
83
|
+
none: false
|
84
|
+
requirements:
|
85
|
+
- - ~>
|
86
|
+
- !ruby/object:Gem::Version
|
87
|
+
version: 0.5.1
|
88
|
+
type: :development
|
89
|
+
prerelease: false
|
90
|
+
version_requirements: *76114270
|
91
|
+
- !ruby/object:Gem::Dependency
|
92
|
+
name: guard-cucumber
|
93
|
+
requirement: &76113790 !ruby/object:Gem::Requirement
|
94
|
+
none: false
|
95
|
+
requirements:
|
96
|
+
- - ~>
|
97
|
+
- !ruby/object:Gem::Version
|
98
|
+
version: 0.5.2
|
99
|
+
type: :development
|
100
|
+
prerelease: false
|
101
|
+
version_requirements: *76113790
|
102
|
+
- !ruby/object:Gem::Dependency
|
103
|
+
name: guard-bundler
|
104
|
+
requirement: &76113160 !ruby/object:Gem::Requirement
|
105
|
+
none: false
|
106
|
+
requirements:
|
107
|
+
- - ~>
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: 0.1.3
|
110
|
+
type: :development
|
111
|
+
prerelease: false
|
112
|
+
version_requirements: *76113160
|
113
|
+
- !ruby/object:Gem::Dependency
|
114
|
+
name: guard-rspec
|
115
|
+
requirement: &76112590 !ruby/object:Gem::Requirement
|
116
|
+
none: false
|
117
|
+
requirements:
|
118
|
+
- - ~>
|
119
|
+
- !ruby/object:Gem::Version
|
120
|
+
version: 0.4.0
|
121
|
+
type: :development
|
122
|
+
prerelease: false
|
123
|
+
version_requirements: *76112590
|
124
|
+
description: Convert directories, rpms, python eggs, rubygems, and more to rpms, debs,
|
125
|
+
solaris packages and more. Win at package management without wasting pointless hours
|
126
|
+
debugging bad rpm specs!
|
127
|
+
email: mauch@crealytics.de
|
128
|
+
executables:
|
129
|
+
- gpm
|
130
|
+
extensions: []
|
131
|
+
extra_rdoc_files: []
|
132
|
+
files:
|
133
|
+
- lib/gpm/cli.rb
|
134
|
+
- lib/gpm/source/bundler.rb
|
135
|
+
- lib/gpm/source/gem.rb
|
136
|
+
- lib/gpm/packaging_task.rb
|
137
|
+
- lib/gpm/file_path_and_permissions.rb
|
138
|
+
- lib/gpm/target.rb
|
139
|
+
- lib/gpm/source.rb
|
140
|
+
- lib/gpm/target/generate_from_templates.rb
|
141
|
+
- lib/gpm/target/deb.rb
|
142
|
+
- lib/gpm/target/zip_directories.rb
|
143
|
+
- lib/gpm/target/step_plugin.rb
|
144
|
+
- bin/gpm
|
145
|
+
- 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
|
147
|
+
- templates/deb/control.tar.gz.dir/md5sums.erb
|
148
|
+
- templates/deb/control.tar.gz.dir/control.erb
|
149
|
+
- templates/deb/debian-binary.erb
|
150
|
+
homepage: https://github.com/crealytics/gpm
|
151
|
+
licenses: []
|
152
|
+
post_install_message:
|
153
|
+
rdoc_options: []
|
154
|
+
require_paths:
|
155
|
+
- lib
|
156
|
+
- lib
|
157
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
158
|
+
none: false
|
159
|
+
requirements:
|
160
|
+
- - ! '>='
|
161
|
+
- !ruby/object:Gem::Version
|
162
|
+
version: '0'
|
163
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
164
|
+
none: false
|
165
|
+
requirements:
|
166
|
+
- - ! '>='
|
167
|
+
- !ruby/object:Gem::Version
|
168
|
+
version: '0'
|
169
|
+
requirements: []
|
170
|
+
rubyforge_project:
|
171
|
+
rubygems_version: 1.8.7
|
172
|
+
signing_key:
|
173
|
+
specification_version: 3
|
174
|
+
summary: gpm - Grand Package Manager
|
175
|
+
test_files: []
|