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

⌈⌋ ⎇ branch:  cross package maker


Check-in [445280c9eb]

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

Overview
Comment:- purge old deb source (that was actually just a copy of the deb target?)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 445280c9ebba0c9b23a8bfd63c25eb03d0eac116
User & Date: jls@semicomplete.com 2012-03-02 10:17:11
Context
2012-03-02
10:44
use new options goodness check-in: a48642e336 user: jls@semicomplete.com tags: trunk
10:17
- purge old deb source (that was actually just a copy of the deb target?) check-in: 445280c9eb user: jls@semicomplete.com tags: trunk
10:16
- add deb work in progress check-in: cec703c311 user: jls@semicomplete.com tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Deleted lib/fpm/source/deb.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
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
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
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
require "erb"
require "fpm/namespace"
require "fpm/package"
require "fpm/errors"
require "fpm/util"

class FPM::Target::Deb < FPM::Package

  # Supported Debian control files
  CONTROL_FILES = {
    "pre-install"       => [:script, "preinst"],
    "post-install"      => [:script, "postinst"],
    "pre-uninstall"     => [:script, "prerm"],
    "post-uninstall"    => [:script, "postrm"],
    "debconf-config"    => [:script, "config"],
    "debconf-templates" => [:text,   "templates"]
  }

  def self.flags(opts, settings)
    settings.target[:deb] = "deb"

    opts.on("--ignore-iteration-in-dependencies",
            "For = dependencies, allow iterations on the specified version.  Default is to be specific.") do |x|
      settings.target[:ignore_iteration] = true
    end

    opts.on("--pre-depends DEPENDENCY", "Add DEPENDENCY as Pre-Depends.") do |dep|
      (settings.target[:pre_depends] ||= []) << dep
    end

    # Take care about the case when we want custom control file but still use fpm ...
    opts.on("--custom-control FILEPATH",
            "Custom version of the Debian control file.") do |control|
      settings.target[:control] = File.expand_path(control)
    end
    
    # Add custom debconf config file
    opts.on("--config SCRIPTPATH",
            "Add SCRIPTPATH as debconf config file.") do |config|
      settings.scripts["debconf-config"] = File.expand_path(config)
    end
    
    # Add custom debconf templates file
    opts.on("--templates FILEPATH",
            "Add FILEPATH as debconf templates file.") do |templates|
      settings.scripts["debconf-templates"] = File.expand_path(templates)
    end
  end

  def needs_md5sums
    case %x{uname -s}.chomp
    when "Darwin"
      return false
    else
      return true
    end
  end # def needs_md5sums

  def architecture
    if @architecture.nil? or @architecture == "native"
      # Default architecture should be 'native' which we'll need
      # to ask the system about.
      arch = %x{dpkg --print-architecture 2> /dev/null}.chomp
      if $?.exitstatus != 0
        arch = %x{uname -m}.chomp
        @logger.warn("Can't find 'dpkg' tool (need it to get default " \
                     "architecture!). Please specificy --architecture " \
                     "specifically. (Defaulting now to #{arch})")
      end
      @architecture = arch
    elsif @architecture == "x86_64"
      # Debian calls x86_64 "amd64"
      @architecture = "amd64"
    end

    return @architecture
  end # def architecture

  def specfile(builddir)
    "#{builddir}/control"
  end

  def name
    if @name =~ /[A-Z]/
      @logger.warn("Debian tools (dpkg/apt) don't do well with packages " \
        "that use capital letters in the name. In some cases it will " \
        "automatically downcase them, in others it will not. It is confusing." \
        "Best to not use any capital letters at all.")
      @name = @name.downcase
    end

    if @name.include?("_")
      @logger.info("Package name '#{@name}' includes underscores, converting" \
                   " to dashes")
      @name = @name.gsub(/[_]/, "-")
    end

    return @name
  end

  def build!(params)
    control_files = [ "control" ]
    if File.exists? "./md5sums"
      control_files << "md5sums"
    end

    # Use custom Debian control file when given ...
    if self.settings[:control]
      %x{cp #{self.settings[:control]} ./control 2> /dev/null 2>&1}
      @logger.warn("Unable to process custom Debian control file (exit " \
                   "code: #{$?.exitstatus}). Falling back to default " \
                   "template.") unless $?.exitstatus == 0
    end

    # place the control files
    self.scripts.each do |name, path|
      ctrl_type, ctrl_file = CONTROL_FILES[name]
      if ctrl_file
        safesystem("cp",  path, "./#{ctrl_file}")
        safesystem("chmod", "a+x", "./#{ctrl_file}") if ctrl_type == :script
        control_files << ctrl_file
      else
        raise "Unsupported script name '#{name}' (path: #{path})"
      end
    end # self.scripts.each

    if self.config_files.any?
      File.open('conffiles', 'w'){ |f| f.puts(config_files.join("\n")) }
      control_files << 'conffiles'
    end

    # Make the control
    safesystem(tar_cmd, "--numeric-owner", "--owner=0", "--group=0",
               "-zcf", "control.tar.gz", *control_files)

    # create debian-binary
    File.open("debian-binary", "w") { |f| f.puts "2.0" }

    # pack up the .deb
    safesystem("ar", "-qc", "#{params[:output]}", "debian-binary", "control.tar.gz", "data.tar.gz")
  end # def build

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

  def fix_dependency(dep)
    if dep =~ /[\(,\|]/
      # Don't "fix" ones that could appear well formed already.
    else
      da = dep.split(/ +/)
      if da.size > 1
        # Convert strings 'foo >= bar' to 'foo (>= bar)'
        dep = "#{da[0]} (#{da[1]} #{da[2]})"
      end
    end

    name_re = /^[^ \(]+/
    name = dep[name_re]
    if name =~ /[A-Z]/
      @logger.warn("Downcasing dependency '#{name}' because deb packages " \
                   " don't work so good with uppercase names")
      dep.gsub!(name_re) { |n| n.downcase }
    end

    if dep =~ /_/
      @logger.warn("Replacing underscores with dashes in '#{dep}' because " \
                   "debs don't like underscores")
      dep.gsub!("_", "-")
    end

    # Convert gem ~> X.Y.Z to '>= X.Y.Z' and << X.Y+1.0
    if dep =~ /\(~>/
      name, version = dep.gsub(/[()~>]/, "").split(/ +/)[0..1]
      nextversion = version.split(".").collect { |v| v.to_i }
      l = nextversion.length
      nextversion[l-2] += 1
      nextversion[l-1] = 0
      nextversion = nextversion.join(".")
      return ["#{name} (>= #{version})", "#{name} (<< #{nextversion})"]
    # ignore iterations for = dependencies if flag specified
    elsif (m = dep.match(/(\S+)\s+\(= (.+)\)/)) && self.settings[:ignore_iteration]
      name, version = m[1..2]
      nextversion = version.split('.').collect { |v| v.to_i }
      nextversion[-1] += 1
      nextversion = nextversion.join(".")
      return ["#{name} (>= #{version})", "#{name} (<< #{nextversion})"]
    else
      return dep
    end
  end # def fix_dependency

  def pre_dependencies
    self.settings[:pre_depends] || []
  end # def pre_dependencies
end # class FPM::Target::Deb
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<