Cross package maker. DEB/RPM generation or conversion. Derived from jordansissel/fpm.

⌈⌋ ⎇ branch:  cross package maker


Check-in [d3f725a8ea]

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:- previous commit missed some files; adding features to allow generating multiple files from 'specfile' phase.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: d3f725a8eac39af226cbb13f1e0e9ca71fc5f8cd
User & Date: jls@semicomplete.com 2011-06-21 02:33:27
Context
2011-06-21
06:00
- some code cleanup - source rpm => target puppet works now check-in: 1f0b1d1b50 user: jls@semicomplete.com tags: trunk
02:33
- previous commit missed some files; adding features to allow generating multiple files from 'specfile' phase. check-in: d3f725a8ea user: jls@semicomplete.com tags: trunk
02:26
- refactor to allow package targets to override generate_specfile so puppet target can write multiple files (::package class and anticlass). check-in: 31f554b9ca user: jls@semicomplete.com tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to lib/fpm/builder.rb.

159
160
161
162
163
164
165
166
167
168
169
170
171
172


173
174
175
176
177
178
179
  def cleanup!
    return [] if garbage.empty?
    FileUtils.rm_rf(garbage) && garbage.clear
  end

  private
  def generate_specfile
    File.open(@package.specfile(builddir), "w") do |f|
      f.puts @package.render_spec
    end
  end

  private
  def edit_specfile


    editor = ENV['FPM_EDITOR'] || ENV['EDITOR'] || 'vi'
    system("#{editor} '#{package.specfile(builddir)}'")
    unless File.size? package.specfile(builddir)
      puts "Empty specfile.  Aborting."
      exit 1
    end
  end







|
<
<




>
>







159
160
161
162
163
164
165
166


167
168
169
170
171
172
173
174
175
176
177
178
179
  def cleanup!
    return [] if garbage.empty?
    FileUtils.rm_rf(garbage) && garbage.clear
  end

  private
  def generate_specfile
    @package.generate_specfile(builddir)


  end

  private
  def edit_specfile
    # TODO(sissel): support editing multiple files for targets like
    # puppet which generate multiple manifests.
    editor = ENV['FPM_EDITOR'] || ENV['EDITOR'] || 'vi'
    system("#{editor} '#{package.specfile(builddir)}'")
    unless File.size? package.specfile(builddir)
      puts "Empty specfile.  Aborting."
      exit 1
    end
  end

Changes to lib/fpm/package.rb.

103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132

133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149








150
151
152
153
154
155
156
    @architecture = source[:architecture]
    @description = source[:description] || "no description given"
    @provides = source[:provides] || []
    @replaces = source[:replaces] || []
    @scripts = source[:scripts]
  end # def initialize

  # TODO(sissel): not needed anymore
  #def generate_specfile(builddir, paths)
    #spec = template.result(binding)
    #File.open(specfile(builddir), "w") { |f| f.puts spec }
  #end # def generate_specfile

  # nobody needs md5sums by default.
  def needs_md5sums
    false
  end # def needs_md5sums

  #def generate_md5sums(builddir, paths)
    #md5sums = self.checksum(paths)
    #File.open("#{builddir}/md5sums", "w") { |f| f.puts md5sums }
    #md5sums
  #end # def generate_md5sums

  # TODO [Jay]: make this better...?
  def type
    self.class.name.split(':').last.downcase
  end # def type

  def template

    @template ||= begin
      tpl = File.read(
        "#{FPM::DIRS[:templates]}/#{type}.erb"
      )
      ERB.new(tpl, nil, "-")
    end
  end # def template

  def render_spec
    # find all files in paths given.
    paths = []
    @source.paths.each do |path|
      Find.find(path) { |p| paths << p }
    end
    #@logger.info(:paths => paths.sort)
    template.result(binding)
  end # def render_spec









  def default_output
    if iteration
      "#{name}-#{version}-#{iteration}.#{architecture}.#{type}"
    else
      "#{name}-#{version}.#{architecture}.#{type}"
    end







<
<
<
<
<
<





<
<
<
<
<
<





|
>

|
<
<













>
>
>
>
>
>
>
>







103
104
105
106
107
108
109






110
111
112
113
114






115
116
117
118
119
120
121
122
123


124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
    @architecture = source[:architecture]
    @description = source[:description] || "no description given"
    @provides = source[:provides] || []
    @replaces = source[:replaces] || []
    @scripts = source[:scripts]
  end # def initialize







  # nobody needs md5sums by default.
  def needs_md5sums
    false
  end # def needs_md5sums







  # TODO [Jay]: make this better...?
  def type
    self.class.name.split(':').last.downcase
  end # def type

  def template(path=nil)
    path ||= "#{type}.erb"
    @template ||= begin
      tpl = File.read("#{FPM::DIRS[:templates]}/#{path}")


      ERB.new(tpl, nil, "-")
    end
  end # def template

  def render_spec
    # find all files in paths given.
    paths = []
    @source.paths.each do |path|
      Find.find(path) { |p| paths << p }
    end
    #@logger.info(:paths => paths.sort)
    template.result(binding)
  end # def render_spec

  # Default specfile generator just makes one specfile, whatever that is for
  # this package.
  def generate_specfile(builddir)
    File.open(specfile(builddir), "w") do |f|
      f.puts render_spec
    end
  end # def generate_specfile

  def default_output
    if iteration
      "#{name}-#{version}-#{iteration}.#{architecture}.#{type}"
    else
      "#{name}-#{version}.#{architecture}.#{type}"
    end

Changes to lib/fpm/target/puppet.rb.

1
2
3
4
5











6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23































24
25
26
27
28
29
30
31
32
33
34
35
36
37






38
39
40
41
42
43
44
require "erb"
require "fpm/namespace"
require "fpm/package"
require "fpm/errors"
require "etc"












require "fileutils" # for FileUtils

# TODO(sissel): Add dependency checking support.
# IIRC this has to be done as a 'checkinstall' step.
class FPM::Target::Puppet < FPM::Package
  def architecture
    case @architecture
    when nil, "native"
      @architecture = %x{uname -m}.chomp
    end
    return @architecture
  end # def architecture

  def specfile(builddir)
    "#{builddir}/package.pp"
  end # def specfile
































  def unpack_data_to
    "files"
  end

  def build!(params)
    # TODO(sissel): Support these somehow, perhaps with execs and files.
    self.scripts.each do |name, path|
      case name
        when "pre-install"
        when "post-install"
        when "pre-uninstall"
        when "post-uninstall"
      end # case name
    end # self.scripts.each







    Dir.mkdir(params[:output])
    builddir = Dir.pwd

    Dir.chdir(params[:output]) do
      Dir.mkdir("manifests")
      FileUtils.cp(specfile(builddir), "manifests")





>
>
>
>
>
>
>
>
>
>
>

















|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>














>
>
>
>
>
>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
require "erb"
require "fpm/namespace"
require "fpm/package"
require "fpm/errors"
require "etc"

class ::Dir
  class << self
    alias :orig_mkdir :mkdir

    def mkdir(*args)
      p :mkdir => { :args => args, :caller => caller }
      orig_mkdir(*args)
    end
  end
end

require "fileutils" # for FileUtils

# TODO(sissel): Add dependency checking support.
# IIRC this has to be done as a 'checkinstall' step.
class FPM::Target::Puppet < FPM::Package
  def architecture
    case @architecture
    when nil, "native"
      @architecture = %x{uname -m}.chomp
    end
    return @architecture
  end # def architecture

  def specfile(builddir)
    "#{builddir}/package.pp"
  end # def specfile
  
  # Default specfile generator just makes one specfile, whatever that is for
  # this package.
  def generate_specfile(builddir)
    paths = []
    @source.paths.each do |path|
      Find.find(path) { |p| paths << p }
    end
    manifests = %w{package.pp package/remove.pp}
    manifests.each do |name|
      dir = File.join(builddir, File.dirname(name))
      @logger.info("manifests targeting: #{dir}")
      Dir.mkdir(dir) if !File.directory?(dir)
      
      @logger.info("Generating #{name}")
      File.open(File.join(builddir, name), "w") do |f|
        f.puts template(File.join("puppet", "#{name}.erb")).result(binding)
      end
    end
  end # def generate_specfile

  # Override render_spec so we can generate multiple files for puppet.
  # The package.pp, package/remove.pp, 
  def render_spec
    # find all files in paths given.
    paths = []
    @source.paths.each do |path|
      Find.find(path) { |p| paths << p }
    end
    #@logger.info(:paths => paths.sort)
    template.result(binding)
  end # def render_spec
  def unpack_data_to
    "files"
  end

  def build!(params)
    # TODO(sissel): Support these somehow, perhaps with execs and files.
    self.scripts.each do |name, path|
      case name
        when "pre-install"
        when "post-install"
        when "pre-uninstall"
        when "post-uninstall"
      end # case name
    end # self.scripts.each

    if File.exists?(params[:output])
      # TODO(sissel): Allow folks to choose output?
      @logger.error("Puppet module directory '#{params[:output]}' already " \
                    "exists. Delete it or choose another output (-p flag)")
    end

    Dir.mkdir(params[:output])
    builddir = Dir.pwd

    Dir.chdir(params[:output]) do
      Dir.mkdir("manifests")
      FileUtils.cp(specfile(builddir), "manifests")

Deleted templates/puppet.erb.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
# TODO(sissel): implement 'anti' class for this package.
class <%= name %>::package {
  $version = "<%= version %>"
  $iteration = "<%= iteration %>"

  file {
<% paths.each do |path|
     stat = File.lstat(path)
     params = {}
     if stat.directory?
       params[:ensure] = "directory"
     elsif stat.symlink?
       params[:ensure] = "link"
       params[:target] = File.readlink(path)
       stat = File.stat(path)
     else
       params[:ensure] = "file"
       params[:source] = "puppet:///modules/#{name}/#{path}"
     end

     if params[:ensure] != "link"
       params[:owner] = uid2user(stat.uid)
       params[:group] = gid2group(stat.gid)
       params[:mode] = sprintf("%04o", stat.mode & 0777)
     end

     settings = puppetsort(params).collect { |k,v| "#{k} => \"#{v}\"" }.join(",\n      ")
-%>
    # <%= stat.inspect %>
    "<%= fixpath(path) %>":
      <%= settings %>;
<% end # paths.each -%>
  }
}
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<