Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 16 additions & 5 deletions lib/fpm/command.rb
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,9 @@ def help(*args)
option ["-s", "--input-type"], "INPUT_TYPE",
"the package type to use as input (gem, rpm, python, etc)",
:attribute_name => :input_type
option ["-r", "--recipe"], "RECIPE_FILE",
"path to recipe file used for building a source based package",
:attribute_name => :recipe_file
option ["-C", "--chdir"], "CHDIR",
"Change directory to here before searching for files",
:attribute_name => :chdir
Expand Down Expand Up @@ -311,7 +314,7 @@ def execute
return 1
end
input_class = FPM::Package.types[input_type]
output_class = FPM::Package.types[output_type]
output_class = FPM::Package.types[output_type] || FPM::SourcePackage.types[output_type]

input = input_class.new

Expand Down Expand Up @@ -470,7 +473,7 @@ def execute
end

# Convert to the output type
output = input.convert(output_class)
output = input.convert(output_class, recipe_file)

# Provide any template values as methods on the package.
if template_scripts?
Expand Down Expand Up @@ -685,21 +688,29 @@ def validate
"Missing required -t flag. What package output did you want?")

# Verify the types requested are valid
types = FPM::Package.types.keys.sort
types = FPM::Package.types.keys.concat(FPM::SourcePackage.types.keys).sort
@command.input_type.tap do |val|
next if val.nil?
mandatory(FPM::Package.types.include?(val),
mandatory(types.include?(val),
"Invalid input package -s flag) type #{val.inspect}. " \
"Expected one of: #{types.join(", ")}")
end

@command.output_type.tap do |val|
next if val.nil?
mandatory(FPM::Package.types.include?(val),
mandatory(types.include?(val),
"Invalid output package (-t flag) type #{val.inspect}. " \
"Expected one of: #{types.join(", ")}")
end

# we cannot output a source based package without a recipe
@command.recipe_file.tap do |val|
is_source_package = FPM::SourcePackage.types.keys.include?(@command.output_type)
mandatory(is_source_package ? val : true,
"source based package output type #{@command.output_type} " \
"requires a recipe file (via -r flag).")
end

@command.dependencies.tap do |dependencies|
# Verify dependencies don't include commas (#257)
dependencies.each do |dep|
Expand Down
8 changes: 5 additions & 3 deletions lib/fpm/package.rb
Original file line number Diff line number Diff line change
Expand Up @@ -191,12 +191,12 @@ def type
end # def type

# Convert this package to a new package type
def convert(klass)
def convert(klass, recipe_file)
logger.info("Converting #{self.type} to #{klass.type}")

exclude

pkg = klass.new
pkg = recipe_file ? klass.new(recipe_file) : klass.new
pkg.cleanup_staging # purge any directories that may have been created by klass.new

# copy other bits
Expand Down Expand Up @@ -414,7 +414,9 @@ class << self
# Lets us track all known FPM::Package subclasses
def inherited(klass)
@subclasses ||= {}
@subclasses[klass.name.gsub(/.*:/, "").downcase] = klass
unless klass.name == 'FPM::SourcePackage'
@subclasses[klass.name.gsub(/.*:/, "").downcase] = klass
end
end # def self.inherited

# Get a list of all known package subclasses
Expand Down
64 changes: 64 additions & 0 deletions lib/fpm/package/srpm.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
require "fpm/source_package"
require "fileutils"

class FPM::Package::SRPM < FPM::SourcePackage

def output(output_path)
output_check(output_path)

%w(BUILD RPMS SRPMS SOURCES SPECS).each { |d| FileUtils.mkdir_p(build_path(d)) }

spec_file = staging_path("#{name}.spec")
# puts "spec_file = #{spec_file}"

File.open(spec_file, "w+") do |file|

if name = name()
file.write("Name: #{name}\n")
end

if version = version()
file.write("Version: #{version}\n")
end

if license = license()
file.write("License: #{license}\n")
end

if release = iteration()
file.write("Release: #{release}\n")
else
file.write("Release: 1\n")
end

if download_url = recipe.download
download_source(download_url.chomp, build_path("SOURCES"))
file.write("Url: #{download_url}\n")
file.write("Source0: #{download_url}\n")
end

if summary = description()
file.write("Summary: #{summary}\n")
file.write("%description\n#{summary}\n\n")
end

if prebuild_instructions = recipe.prebuild
file.write("%prep\n#{prebuild_instructions}\n\n")
end

if build_instructions = recipe.build
file.write("%build\n#{build_instructions}\n\n")
end

if install_instructions = recipe.install
file.write("%install\n#{install_instructions}\n\n")
end
end

safesystem("rpmbuild", "-bs", "--define", "_topdir #{build_path}", spec_file)

::Dir["#{build_path}/SRPMS/*.src.rpm"].each do |srpm|
FileUtils.cp(srpm, output_path)
end
end
end
50 changes: 50 additions & 0 deletions lib/fpm/recipe.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
require "fpm/util"

class FPM::Recipe

RECIPE_SECTIONS = [ :download,
:prebuild,
:build,
:install,
]

attr_accessor(*RECIPE_SECTIONS)

def initialize(recipe_file)
recipe_file = File.expand_path(recipe_file)

unless File.file?(recipe_file)
STDERR.puts "recipe file #{recipe_file} does not exist"
exit 1
end

# parse recipe_file
cur_section = nil
cur_val = nil
File.foreach(recipe_file) do |line|
line.gsub!(/ *#.*| +$/, '')
next if line =~ /^$/
if section_name = section_tag?(line)
if !cur_section # this is the first section tag we have seen.
cur_section = section_name
cur_val = ""
else
instance_variable_set("@#{cur_section}", cur_val)
cur_section = section_name
cur_val = ""
end
else # this line is not a section
cur_val += line
end
end
if cur_section and cur_val
self.instance_variable_set("@#{cur_section}", cur_val)
end
end

private
def section_tag?(line)
# Note that no trimming of +line+ happens here
line[/^\[(#{RECIPE_SECTIONS.join("|")})\]$/, 1]
end
end
29 changes: 29 additions & 0 deletions lib/fpm/source_package.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
require "fpm/package"
require "fpm/recipe"

# This class is the parent of all source based packages.
# If you want to implement a source based FPM package type, you'll inherit from
# this.
class FPM::SourcePackage < FPM::Package
attr_reader :recipe

def initialize(recipe_file)
super()
@recipe = FPM::Recipe.new(recipe_file)
end

def download_source(url, dir)
safesystem("wget", "-P", dir, url)
end

class << self
def inherited(klass)
@subclasses ||= {}
@subclasses[klass.name.gsub(/.*:/, "").downcase] = klass
end

def types
return @subclasses
end
end
end