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

⌈⌋ ⎇ branch:  cross package maker


Check-in [8e40379d3b]

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

Overview
Comment:- style and docs
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 8e40379d3bffc76bd2718c7106fac36c81dcb788
User & Date: jls@semicomplete.com 2012-03-02 09:20:49
Context
2012-03-02
09:20
don't sleep check-in: b7e0fa71df user: jls@semicomplete.com tags: trunk
09:20
- style and docs check-in: 8e40379d3b user: jls@semicomplete.com tags: trunk
09:11
- remove old flags helper, won't need it soon. check-in: 413326f3bd user: jls@semicomplete.com tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to lib/fpm/command.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
require "rubygems"
require "fpm/namespace"
require "clamp"
require "ostruct"
require "fpm"


class FPM::Command < Clamp::Command
  option "-t", "OUTPUT_TYPE",
    "the type of package you want to create (deb, rpm, solaris, etc)",
    :attribute_name => :output_type
  option "-s", "INPUT_TYPE",
    "the package type to use as input (gem, rpm, python, etc)",
    :attribute_name => :input_type
  option "-C", "CHDIR",
    "Change directory to here before searching for files", :attribute_name => :chdir
  option "--prefix", "PREFIX",
    "A path to prefix files with when building the target package. This may " \
    "be necessary for all input packages. For example, the 'gem' type will" \
    "prefix with your gem directory automatically."

  option ["-p", "--package"], "OUTPUT",
    "The package file path to output.", :default => "NAME-FULLVERSION.ARCH.TYPE"
  option ["-n", "--name"], "NAME",
    "The name to give to the package"
  option "--verbose", :flag, "Enable verbose output"
  option "--debug", :flag, "Enable debug output"
  option ["-v", "--version"], "VERSION",
    "The version to give to the package", :default => "1.0"
  option "--iteration", "ITERATION",
    "The iteration to give to the package. RPM calls this the 'release'. " \
    "FreeBSD calls it 'PORTREVISION'. Debian calls this 'debian_revision'",
    :default => "1"
  option "--epoch", "EPOCH",
    "The epoch value for this package. RPM and Debian calls this 'epoch'. " \
    "FreeBSD calls this 'PORTEPOCH'",
    :default => "1"
  option "--license", "LICENSE",
    "(optional) license name for this package", :default => "not given"
  option "--vendor", "VENDOR",
    "(optional) vendor name for this package", :default => "not given"
  option "--category", "CATEGORY",
    "(optional) category this package belongs to", :default => "none"
  option ["-d", "--depends"], "DEPENDENCY",






>













<


|
<










|
<







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
require "rubygems"
require "fpm/namespace"
require "clamp"
require "ostruct"
require "fpm"

# The main fpm command entry point.
class FPM::Command < Clamp::Command
  option "-t", "OUTPUT_TYPE",
    "the type of package you want to create (deb, rpm, solaris, etc)",
    :attribute_name => :output_type
  option "-s", "INPUT_TYPE",
    "the package type to use as input (gem, rpm, python, etc)",
    :attribute_name => :input_type
  option "-C", "CHDIR",
    "Change directory to here before searching for files", :attribute_name => :chdir
  option "--prefix", "PREFIX",
    "A path to prefix files with when building the target package. This may " \
    "be necessary for all input packages. For example, the 'gem' type will" \
    "prefix with your gem directory automatically."

  option ["-p", "--package"], "OUTPUT",
    "The package file path to output.", :default => "NAME-FULLVERSION.ARCH.TYPE"
  option ["-n", "--name"], "NAME", "The name to give to the package"

  option "--verbose", :flag, "Enable verbose output"
  option "--debug", :flag, "Enable debug output"
  option ["-v", "--version"], "VERSION",
    "The version to give to the package", :default => "1.0"
  option "--iteration", "ITERATION",
    "The iteration to give to the package. RPM calls this the 'release'. " \
    "FreeBSD calls it 'PORTREVISION'. Debian calls this 'debian_revision'",
    :default => "1"
  option "--epoch", "EPOCH",
    "The epoch value for this package. RPM and Debian calls this 'epoch'. " \
    "FreeBSD calls this 'PORTEPOCH'", :default => "1"

  option "--license", "LICENSE",
    "(optional) license name for this package", :default => "not given"
  option "--vendor", "VENDOR",
    "(optional) vendor name for this package", :default => "not given"
  option "--category", "CATEGORY",
    "(optional) category this package belongs to", :default => "none"
  option ["-d", "--depends"], "DEPENDENCY",
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
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
  option ["-e", "--edit"], :flag,
    "Edit the package spec before building."
  option ["-x", "--exclude"], "EXCLUDE_PATTERN",
    "Exclude paths matching pattern (shell wildcard globs valid here)" do |val|
    @exclude_pattern ||= []
    @exclude_pattern << val
  end # -x / --exclude

  option "--post-install", "FILE",
    "a script to be run after package installation" do |val|
    File.expand_path(val) # Get the full path to the script
  end # --post-install

  option "--pre-install", "FILE",
    "a script to be run before package installation" do |val|
    File.expand_path(val) # Get the full path to the script
  end # --pre-install

  # TODO(sissel): Name the flag --post-remove for clarity
  option "--post-uninstall", "FILE",
    "a script to be run after package removal",
    :attribute_name => :post_remove do |val|
    File.expand_path(val) # Get the full path to the script
  end # --post-uninstall

  # TODO(sissel): Name the flag --pre-remove for clarity
  option "--pre-uninstall", "FILE",
    "a script to be run before package removal",
    :attribute_name => :pre_remove do |val|
    File.expand_path(val) # Get the full path to the script
  end # --pre-uninstall

  option "--description", "DESCRIPTION",
    "Add a description for this package.",
    :default => "no description"

  option "--url", "URI",
    "Add a url for this package.",
    :default => "http://example.com/no-uri-given"

  option "--inputs", "INPUTS_PATH",
    "The path to a file containing a newline-separated list of " \
    "files and dirs to use as input."

  parameter "[ARGS] ...",
    "Inputs to the source package type. For the 'dir' type, this is the files" \
    " and directories you want to include in the package. For others, like " \
    "'gem', it specifies the packages to download and use as the gem input",
    :attribute_name => :args




  # Add extra flags from plugins
  #FPM::Package::Gem.flags(FPM::Flags.new(opts, "gem", "gem only"), @settings)
  #FPM::Package::Python.flags(FPM::Flags.new(opts, "python", "python only"),
                            #@settings)
  #FPM::Package::Deb.flags(FPM::Flags.new(opts, "deb", "deb only"), @settings)
  #FPM::Package::Rpm.flags(FPM::Flags.new(opts, "rpm", "rpm only"), @settings)
  

  def initialize(*args)
    super(*args)
    @conflicts = []
    @replaces = []
    @provides = []
    @dependencies = []
    @config_files = []
  end # def initialize


  def execute
    @logger = Cabin::Channel.get
    @logger.subscribe(STDOUT)
    @logger.level = :warn
    validator = Validator.new(self)
    if !validator.ok?
      validator.messages.each do |message|







<




<




<






<






<
|
<

<
|
<

<



<






>
>
>







>









>







80
81
82
83
84
85
86

87
88
89
90

91
92
93
94

95
96
97
98
99
100

101
102
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
  option ["-e", "--edit"], :flag,
    "Edit the package spec before building."
  option ["-x", "--exclude"], "EXCLUDE_PATTERN",
    "Exclude paths matching pattern (shell wildcard globs valid here)" do |val|
    @exclude_pattern ||= []
    @exclude_pattern << val
  end # -x / --exclude

  option "--post-install", "FILE",
    "a script to be run after package installation" do |val|
    File.expand_path(val) # Get the full path to the script
  end # --post-install

  option "--pre-install", "FILE",
    "a script to be run before package installation" do |val|
    File.expand_path(val) # Get the full path to the script
  end # --pre-install

  # TODO(sissel): Name the flag --post-remove for clarity
  option "--post-uninstall", "FILE",
    "a script to be run after package removal",
    :attribute_name => :post_remove do |val|
    File.expand_path(val) # Get the full path to the script
  end # --post-uninstall

  # TODO(sissel): Name the flag --pre-remove for clarity
  option "--pre-uninstall", "FILE",
    "a script to be run before package removal",
    :attribute_name => :pre_remove do |val|
    File.expand_path(val) # Get the full path to the script
  end # --pre-uninstall

  option "--description", "DESCRIPTION", "Add a description for this package.",

    :default => "no description"

  option "--url", "URI", "Add a url for this package.",

    :default => "http://example.com/no-uri-given"

  option "--inputs", "INPUTS_PATH",
    "The path to a file containing a newline-separated list of " \
    "files and dirs to use as input."

  parameter "[ARGS] ...",
    "Inputs to the source package type. For the 'dir' type, this is the files" \
    " and directories you want to include in the package. For others, like " \
    "'gem', it specifies the packages to download and use as the gem input",
    :attribute_name => :args

  # TODO(sissel): expose 'option' and 'parameter' junk to FPM::Package and subclasses.
  # Apply those things to this command.
  #
  # Add extra flags from plugins
  #FPM::Package::Gem.flags(FPM::Flags.new(opts, "gem", "gem only"), @settings)
  #FPM::Package::Python.flags(FPM::Flags.new(opts, "python", "python only"),
                            #@settings)
  #FPM::Package::Deb.flags(FPM::Flags.new(opts, "deb", "deb only"), @settings)
  #FPM::Package::Rpm.flags(FPM::Flags.new(opts, "rpm", "rpm only"), @settings)
  
  # A new FPM::Command
  def initialize(*args)
    super(*args)
    @conflicts = []
    @replaces = []
    @provides = []
    @dependencies = []
    @config_files = []
  end # def initialize

  # Execute this command. See Clamp::Command#execute and Clamp's documentation
  def execute
    @logger = Cabin::Channel.get
    @logger.subscribe(STDOUT)
    @logger.level = :warn
    validator = Validator.new(self)
    if !validator.ok?
      validator.messages.each do |message|
200
201
202
203
204
205
206




207
208
209
210
211
212
213
    output.output(output.to_s(package))
    return 0
  ensure
    input.cleanup
    output.cleanup unless output.nil?
  end # def execute





  class Validator
    private

    def initialize(command)
      @command = command
      @valid = true
      @messages = []







>
>
>
>







193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
    output.output(output.to_s(package))
    return 0
  ensure
    input.cleanup
    output.cleanup unless output.nil?
  end # def execute

  # A simple flag validator
  #
  # The goal of this class is to ensure the flags and arguments given
  # are a valid configuration.
  class Validator
    private

    def initialize(command)
      @command = command
      @valid = true
      @messages = []

Changes to lib/fpm/errors.rb.

1
2

3
require "fpm/namespace"


class FPM::InvalidPackageConfiguration < StandardError; end


>

1
2
3
4
require "fpm/namespace"

# Raised if a package is configured in an unsupported way
class FPM::InvalidPackageConfiguration < StandardError; end

Changes to lib/fpm/namespace.rb.


1
2
3
4
5
6
7
8
9
10
11
12
13

module FPM
  module Target; end # TODO(sissel): Make this the 'package' ?
  DIRS = {
    :templates => File.expand_path(
      File.join(
        File.dirname(__FILE__),
        '..',
        '..',
        'templates'
      )
    )
  }
end
>

<
<
<
<
<
<
<
|
<
<
<

1
2







3



4
# The FPM namespace
module FPM







  class Package; end



end

Changes to lib/fpm/util.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
require "fpm/namespace"


module FPM::Util







  def safesystem(*args)
    program = args[0]
    # TODO(sissel): Search PATH for program, abort if we can't find it









    success = system(*args)
    if !success
      raise "#{args.first} failed with exit code #{$?.exitstatus}. Full command was: #{args.inspect}"

    end
    return success
  end # def safesystem


  def tar_cmd
    # Rely on gnu tar for solaris and OSX.
    case %x{uname -s}.chomp
    when "SunOS"
      return "gtar"
    when "Darwin"
      return "gnutar"
    else
      return "tar"
    end
  end # def tar_cmd
end # module FPM::Util


>

>
>
>
>
>
>
>


|
>
>
>
>
>
>
>
>



|
>




>












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 "fpm/namespace"

# Some utility functions
module FPM::Util
  # Raised if safesystem cannot find the program to run.
  class ExecutableNotFound < StandardError; end

  # Raised if a safesystem program exits nonzero
  class ProcessFailed < StandardError; end

  # Run a command safely in a way that gets reports useful errors.
  def safesystem(*args)
    program = args[0]

    # Scan path to find the executable
    # Do this to help the user get a better error message.
    if !program.include("/")
      envpath = ENV["PATH"].split(":")
      if envpath.select { |p| File.executable?(File.join(p, program)) }.empty?
        raise ExecutableNotFound.new(program)
      end
    end

    success = system(*args)
    if !success
      raise ProcessFailed.new("#{program} failed (exit code #{$?.exitstatus})" \
                              ". Full command was:#{args.inspect}")
    end
    return success
  end # def safesystem

  # Get the recommended 'tar' command for this platform.
  def tar_cmd
    # Rely on gnu tar for solaris and OSX.
    case %x{uname -s}.chomp
    when "SunOS"
      return "gtar"
    when "Darwin"
      return "gnutar"
    else
      return "tar"
    end
  end # def tar_cmd
end # module FPM::Util