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

⌈⌋ branch:  cross package maker


Check-in [1151192533]

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

Overview
SHA1 Hash:1151192533245dbb55cd7a22353f5e6f751bfb62
Date: 2011-07-08 07:14:40
User: jls
Comment:Merge branch 'master' of github.com:jordansissel/fpm
Tags And Properties
  • sym-trunk inherited from [2b439be7d6]
Context
2011-07-08
07:14
[059075a03f] - lots of small fixes and cleanup by tmm1, version bump it. (user: jls, tags: trunk)
07:14
[1151192533] Merge branch 'master' of github.com:jordansissel/fpm (user: jls, tags: trunk)
07:13
[79cfa3398b] - deb packages let you specify 'or' in deps (pipe, '|'). Let it work. (user: jls, tags: trunk)
05:55
[2c687d20de] Merge pull request #69 from tmm1/whitespace Removed a bunch of trailing whitespace (user: jls, tags: trunk)
Changes

Changes to CHANGELIST.

18
19
20
21
22
23
24
25
26
27
    python and easy_install tools to use when building. Default is simply
    'python' and 'easy_install' respectively.
  - Add support for ~/.fpmrc - The format of this file is the same as the flags.
    One flag per line. https://github.com/jordansissel/fpm/issues/38
    Example:
      --python-bin=/usr/bin/python2.7
      --python-easyinstall=/usr/bin/easy_install2.7
    
0.2.26 and earlier
  No changelist tracked. My bad, yo.







|


18
19
20
21
22
23
24
25
26
27
    python and easy_install tools to use when building. Default is simply
    'python' and 'easy_install' respectively.
  - Add support for ~/.fpmrc - The format of this file is the same as the flags.
    One flag per line. https://github.com/jordansissel/fpm/issues/38
    Example:
      --python-bin=/usr/bin/python2.7
      --python-easyinstall=/usr/bin/easy_install2.7

0.2.26 and earlier
  No changelist tracked. My bad, yo.

Changes to NOTES.md.

44
45
46
47
48
49
50
51
52
53
(I hope) Debian had good reason.

So, I'm going to try working on a howto for recommended ways to build python
packages with fpm in debian. It will likely require a one-time addition to
site.py (/usr/lib/python2.6/site.py) or some other PYTHONPATH hackery, though
I don't know just yet.

It will also require special setup.py invocations as Debian has patched distutils to 
install python packages, by default, to a place that requires again the
python-central/support tools to run to make them work.







|


44
45
46
47
48
49
50
51
52
53
(I hope) Debian had good reason.

So, I'm going to try working on a howto for recommended ways to build python
packages with fpm in debian. It will likely require a one-time addition to
site.py (/usr/lib/python2.6/site.py) or some other PYTHONPATH hackery, though
I don't know just yet.

It will also require special setup.py invocations as Debian has patched distutils to
install python packages, by default, to a place that requires again the
python-central/support tools to run to make them work.

Changes to bin/fpm-npm.

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
  # Load the package.json and glean any information from it, then invoke pkg.rb
  package = JSON.parse(File.new("#{path}/package/package.json").read())

  # TODO(sissel): Ideally we want to say any version with the same 'release' number, like
  # So we'll specify deps of {v}-1 <= x <= {v}-999999....
  depends = Dir.glob("#{path}/dependson/*@*") \
    .collect { |p| PACKAGEPREFIX + File.basename(p) } \
    .collect { |p| n,v = p.split("@"); 
      ["#{n} (>= #{v}-1)", "#{n} (<= #{v}-99999999999999)"] 
  }.flatten

  if package["author"]
    maintainer = package["author"]
  else
    m = package["maintainers"][0] \
      rescue { "name" => "missing upstream author", "email" => ENV["USER"] }
    maintainer = "#{m["name"]} <#{m["email"]}>"
  end

  pkgcmd = [ "fpm", 
    "-n", "#{PACKAGEPREFIX}#{package["name"]}",
    "-v", package["version"],
    "-m", maintainer,
    "-a", "all",
  ]

  depends.each do |dep|







|
|










|







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
  # Load the package.json and glean any information from it, then invoke pkg.rb
  package = JSON.parse(File.new("#{path}/package/package.json").read())

  # TODO(sissel): Ideally we want to say any version with the same 'release' number, like
  # So we'll specify deps of {v}-1 <= x <= {v}-999999....
  depends = Dir.glob("#{path}/dependson/*@*") \
    .collect { |p| PACKAGEPREFIX + File.basename(p) } \
    .collect { |p| n,v = p.split("@");
      ["#{n} (>= #{v}-1)", "#{n} (<= #{v}-99999999999999)"]
  }.flatten

  if package["author"]
    maintainer = package["author"]
  else
    m = package["maintainers"][0] \
      rescue { "name" => "missing upstream author", "email" => ENV["USER"] }
    maintainer = "#{m["name"]} <#{m["email"]}>"
  end

  pkgcmd = [ "fpm",
    "-n", "#{PACKAGEPREFIX}#{package["name"]}",
    "-v", package["version"],
    "-m", maintainer,
    "-a", "all",
  ]

  depends.each do |dep|

Changes to examples/fpm/README.md.

12
13
14
15
16
17
18
19

Should make the package. Try installing:

    $ sudo dpkg -i fpm-0.2.30.x86.deb

Now try it:

    $ /opt/fpm/bin/fpm --help 







|
12
13
14
15
16
17
18
19

Should make the package. Try installing:

    $ sudo dpkg -i fpm-0.2.30.x86.deb

Now try it:

    $ /opt/fpm/bin/fpm --help

Changes to examples/jruby/Makefile.

11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
package: deb

.PHONY: clean
clean:
	rm -f $(NAME)-* $(NAME)_* || true
	rm -fr $(TARDIR) || true
	rm -f *.deb
        rm -f *.rpm

$(TARBALL):
	wget "$(DOWNLOAD)"

$(TARDIR): $(TARBALL)
	tar -zxf $(TARBALL)








|







11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
package: deb

.PHONY: clean
clean:
	rm -f $(NAME)-* $(NAME)_* || true
	rm -fr $(TARDIR) || true
	rm -f *.deb
	rm -f *.rpm

$(TARBALL):
	wget "$(DOWNLOAD)"

$(TARDIR): $(TARBALL)
	tar -zxf $(TARBALL)

Changes to examples/jruby/README.md.

4
5
6
7
8
9
10
11
12
13
14
15
16
17

Should make the package. Try installing:

    sudo dpkg -i jruby-1.6.0.RC2-1.all.deb

Now try it:

    % /opt/jruby/bin/jirb 
    >> require "java"
    => true
    >> java.lang.System.out.println("Hello")
    Hello
    => nil








|






4
5
6
7
8
9
10
11
12
13
14
15
16
17

Should make the package. Try installing:

    sudo dpkg -i jruby-1.6.0.RC2-1.all.deb

Now try it:

    % /opt/jruby/bin/jirb
    >> require "java"
    => true
    >> java.lang.System.out.println("Hello")
    Hello
    => nil

Changes to examples/python/twisted/Makefile.

4
5
6
7
8
9
10
11
12
13
14
15
twisted:
	easy_install --editable --build-directory . "$(NAME)==$(VERSION)"

usr: twisted
	cd twisted; python setup.py bdist
	tar -zxf twisted/dist/Twisted-$(VERSION).linux-$(shell uname -m).tar.gz

package: usr 
	fpm -s dir -t deb -n $(NAME) -v $(VERSION) \
		-p python-$(NAME)-VERSION_ARCH.deb -d "python" \
		usr








|




4
5
6
7
8
9
10
11
12
13
14
15
twisted:
	easy_install --editable --build-directory . "$(NAME)==$(VERSION)"

usr: twisted
	cd twisted; python setup.py bdist
	tar -zxf twisted/dist/Twisted-$(VERSION).linux-$(shell uname -m).tar.gz

package: usr
	fpm -s dir -t deb -n $(NAME) -v $(VERSION) \
		-p python-$(NAME)-VERSION_ARCH.deb -d "python" \
		usr

Changes to lib/fpm/builder.rb.

9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
..
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

  # where the package goes
  def output
    @output ||= begin
      o = @package.default_output
      if o[0,1] == "/"
        o
      else 
        File.join(@working_dir, o)
      end
    end
  end

  # things to clean up afterwards
  def garbage
................................................................................
      :url => settings.url,
      :settings => settings.source
    )

    @edit = !!settings.edit

    @paths = paths
    @package = package_class_for(settings.package_type).new(@source, 
			:settings => settings.target
		)
    # Append dependencies given from settings (-d flag for fpm)
    @package.dependencies += settings.dependencies if settings.dependencies
    # Append provides given from settings (--provides flag for fpm)
    @package.provides += settings.provides if settings.provides
    @package.replaces += settings.replaces if settings.replaces
    @package.architecture = settings.architecture if settings.architecture
    @package.scripts = settings.scripts

    @output = settings.package_path
    @recurse_dependencies = settings.recurse_dependencies
  end # def initialize
  
  def tar_path
    @tar_path ||= "#{builddir}/data.tar"
  end

  # Assemble the package
  def assemble!
    version_a = [ @source[:version], @package.iteration ].compact







|







 







|













|







9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
..
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

  # where the package goes
  def output
    @output ||= begin
      o = @package.default_output
      if o[0,1] == "/"
        o
      else
        File.join(@working_dir, o)
      end
    end
  end

  # things to clean up afterwards
  def garbage
................................................................................
      :url => settings.url,
      :settings => settings.source
    )

    @edit = !!settings.edit

    @paths = paths
    @package = package_class_for(settings.package_type).new(@source,
			:settings => settings.target
		)
    # Append dependencies given from settings (-d flag for fpm)
    @package.dependencies += settings.dependencies if settings.dependencies
    # Append provides given from settings (--provides flag for fpm)
    @package.provides += settings.provides if settings.provides
    @package.replaces += settings.replaces if settings.replaces
    @package.architecture = settings.architecture if settings.architecture
    @package.scripts = settings.scripts

    @output = settings.package_path
    @recurse_dependencies = settings.recurse_dependencies
  end # def initialize

  def tar_path
    @tar_path ||= "#{builddir}/data.tar"
  end

  # Assemble the package
  def assemble!
    version_a = [ @source[:version], @package.iteration ].compact

Changes to lib/fpm/flags.rb.

6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
    @flag_prefix = flag_prefix
    @help_prefix = help_prefix
  end # def initialize

  def on(*args, &block)
    fixed_args = args.collect do |arg|
      if arg =~ /^--/
        "--#{@flag_prefix}-#{arg.gsub(/^--/, "")}" 
      else
        "(#{@help_prefix}) #{arg}"
      end
    end
    @opts.on(*fixed_args, &block)
  end # def on
end # class FPM::Flags







|







6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
    @flag_prefix = flag_prefix
    @help_prefix = help_prefix
  end # def initialize

  def on(*args, &block)
    fixed_args = args.collect do |arg|
      if arg =~ /^--/
        "--#{@flag_prefix}-#{arg.gsub(/^--/, "")}"
      else
        "(#{@help_prefix}) #{arg}"
      end
    end
    @opts.on(*fixed_args, &block)
  end # def on
end # class FPM::Flags

Changes to lib/fpm/package.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
..
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
...
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
...
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
require "fpm/namespace"
require "socket" # for Socket.gethostname
require "logger"
require "find" # for Find.find (directory walking)

class FPM::Package 
  # The name of this package
  attr_accessor :name

  # The version of this package (the upstream version)
  attr_accessor :version

  # The epoch version of this package
................................................................................
  # This is used most when an upstream package changes it's versioning
  # style so standard comparisions wouldn't work.
  attr_accessor :epoch

  # The iteration of this package.
  #   Debian calls this 'release' and is the last '-NUMBER' in the version
  #   RedHat has this as 'Release' in the .spec file
  #   FreeBSD calls this 'PORTREVISION' 
  # If left unpicked, it defaults to 1.
  attr_accessor :iteration

  # Who maintains this package? This could be the upstream author
  # or the package maintainer. You pick.
  attr_accessor :maintainer

................................................................................
    # Default version is 1.0 in case nobody told us a specific version.
    @version = source[:version] || "1.0"
    @epoch = source[:epoch]

    @dependencies = source[:dependencies] || []
    # Iteration can be nil. If nil, the fpm package implementation is expected
    # to handle any default value that should be instead.
    @iteration = source[:iteration] 
    @url = source[:url] || "http://nourlgiven.example.com/no/url/given"
    @category = source[:category] || "default"
    @license = source[:license] || "unknown"
    #@maintainer = source[:maintainer] || "<#{ENV["USER"]}@#{Socket.gethostname}>"
    @maintainer = source[:maintainer]

    # Default maintainer if none given.
................................................................................
    # Another special includes "native" which will be the current platform's arch.
    @architecture = source[:architecture]
    @description = source[:description] || "no description given"
    @provides = source[:provides] || []
    @replaces = source[:replaces] || []
    @scripts = source[:scripts]

		# Target-specific settings, mirrors :settings metadata in FPM::Source
		@settings = params[:settings] || {}
  end # def initialize

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

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

  def fixpath(path)
    if path[0,1] != "/" 
      path = File.join(@source.root, path)
    end
    return path if File.symlink?(path)
    @logger.info(:fixpath => path)
    realpath = Pathname.new(path).realpath.to_s
    re = Regexp.new("^#{Regexp.escape(@source.root)}")
    realpath.gsub!(re, "")
    @logger.info(:fixpath_result => realpath)
    return realpath
  end # def fixpath
end # class FPM::Package





|







 







|







 







|







 







|
|







 







|











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
..
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
...
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
...
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
require "fpm/namespace"
require "socket" # for Socket.gethostname
require "logger"
require "find" # for Find.find (directory walking)

class FPM::Package
  # The name of this package
  attr_accessor :name

  # The version of this package (the upstream version)
  attr_accessor :version

  # The epoch version of this package
................................................................................
  # This is used most when an upstream package changes it's versioning
  # style so standard comparisions wouldn't work.
  attr_accessor :epoch

  # The iteration of this package.
  #   Debian calls this 'release' and is the last '-NUMBER' in the version
  #   RedHat has this as 'Release' in the .spec file
  #   FreeBSD calls this 'PORTREVISION'
  # If left unpicked, it defaults to 1.
  attr_accessor :iteration

  # Who maintains this package? This could be the upstream author
  # or the package maintainer. You pick.
  attr_accessor :maintainer

................................................................................
    # Default version is 1.0 in case nobody told us a specific version.
    @version = source[:version] || "1.0"
    @epoch = source[:epoch]

    @dependencies = source[:dependencies] || []
    # Iteration can be nil. If nil, the fpm package implementation is expected
    # to handle any default value that should be instead.
    @iteration = source[:iteration]
    @url = source[:url] || "http://nourlgiven.example.com/no/url/given"
    @category = source[:category] || "default"
    @license = source[:license] || "unknown"
    #@maintainer = source[:maintainer] || "<#{ENV["USER"]}@#{Socket.gethostname}>"
    @maintainer = source[:maintainer]

    # Default maintainer if none given.
................................................................................
    # Another special includes "native" which will be the current platform's arch.
    @architecture = source[:architecture]
    @description = source[:description] || "no description given"
    @provides = source[:provides] || []
    @replaces = source[:replaces] || []
    @scripts = source[:scripts]

    # Target-specific settings, mirrors :settings metadata in FPM::Source
    @settings = params[:settings] || {}
  end # def initialize

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

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

  def fixpath(path)
    if path[0,1] != "/"
      path = File.join(@source.root, path)
    end
    return path if File.symlink?(path)
    @logger.info(:fixpath => path)
    realpath = Pathname.new(path).realpath.to_s
    re = Regexp.new("^#{Regexp.escape(@source.root)}")
    realpath.gsub!(re, "")
    @logger.info(:fixpath_result => realpath)
    return realpath
  end # def fixpath
end # class FPM::Package

Changes to lib/fpm/program.rb.

14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
..
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
..
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
...
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
...
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
    @settings.exclude = []  # Paths to exclude in packaging
    @settings.provides = []
    @settings.replaces = []
    @settings.source = {}   # source settings
    @settings.target = {}   # target settings

    # Maintainer scripts - https://github.com/jordansissel/fpm/issues/18
    @settings.scripts ||= {} 

    @help = nil
  end # def initialize

  def run(args)
    $: << File.expand_path(File.join(File.dirname(__FILE__), "..", "lib"))
    paths = options(args)
................................................................................
    if @settings.source_type.nil?
      $stderr.puts "Missing package source type (no -s flag?)"
      ok = false
    end

    if !ok
      $stderr.puts "There were errors; see above."
      $stderr.puts 
      $stderr.puts @help
      return 1
    end

    builder = FPM::Builder.new(@settings, paths)
    builder.assemble!
    puts "Created #{builder.output}"
................................................................................
    opts = OptionParser.new
    default_options(opts)

    # Add extra flags from plugins
    FPM::Source::Gem.flags(FPM::Flags.new(opts, "gem", "gem source only"), @settings)
    FPM::Source::Python.flags(FPM::Flags.new(opts, "python", "python source only"),
                              @settings)
		FPM::Target::Deb.flags(FPM::Flags.new(opts, "deb", "deb target only"), @settings)  
  
    # Process fpmrc first
    fpmrc(opts)

    # Proces normal flags now.
    remaining = opts.parse(args)
    
    # need to print help in a different scope
    @help = opts.help

    return remaining
  end # def options

  def fpmrc(options)
    # Skip if we have no HOME environment variable.
    return if !ENV.include?("HOME")
    rcpath = File.expand_path("~/.fpmrc")
    return if !File.exists?(rcpath)
    
    # fpmrc exists, read it as flags, one per line.
    File.new(rcpath, "r").each do |line|
      flag = line.chomp
      begin
        options.parse([flag])
      rescue => e
        $stderr.puts "Error parsing fpmrc (#{rcpath})"
................................................................................
    opts.on("-n PACKAGENAME", "--name PACKAGENAME",
            "What name to give to the package") do |name|
      @settings.package_name = name
    end # --name

    opts.on("-v VERSION", "--version VERSION",
            "version to give the package") do |version|
      @settings.version = version 
    end # --version

    opts.on("--iteration ITERATION",
            "(optional) Set the iteration value for this package.") do |iteration|
      @settings.iteration = iteration
    end # --iteration

................................................................................

    opts.on("-t PACKAGE_TYPE", "the type of package you want to create") do |type|
      @settings.package_type = type
    end # -t

    opts.on("-s SOURCE_TYPE", "what to build the package from") do |st|
      @settings.source_type = st
    end # -s 

    opts.on("-S PACKAGE_SUFFIX", "which suffix to append to package and dependencies") do |sfx|
      @settings.suffix = sfx
    end # -S

    opts.on("--prefix PREFIX",
            "A path to prefix files with when building the target package. This may not be necessary for all source types. For example, the 'gem' type will prefix with your gem directory (gem env | grep -A1 PATHS:)") do |prefix|







|







 







|







 







|
|





|











|







 







|







 







|







14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
..
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
..
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
...
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
...
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
    @settings.exclude = []  # Paths to exclude in packaging
    @settings.provides = []
    @settings.replaces = []
    @settings.source = {}   # source settings
    @settings.target = {}   # target settings

    # Maintainer scripts - https://github.com/jordansissel/fpm/issues/18
    @settings.scripts ||= {}

    @help = nil
  end # def initialize

  def run(args)
    $: << File.expand_path(File.join(File.dirname(__FILE__), "..", "lib"))
    paths = options(args)
................................................................................
    if @settings.source_type.nil?
      $stderr.puts "Missing package source type (no -s flag?)"
      ok = false
    end

    if !ok
      $stderr.puts "There were errors; see above."
      $stderr.puts
      $stderr.puts @help
      return 1
    end

    builder = FPM::Builder.new(@settings, paths)
    builder.assemble!
    puts "Created #{builder.output}"
................................................................................
    opts = OptionParser.new
    default_options(opts)

    # Add extra flags from plugins
    FPM::Source::Gem.flags(FPM::Flags.new(opts, "gem", "gem source only"), @settings)
    FPM::Source::Python.flags(FPM::Flags.new(opts, "python", "python source only"),
                              @settings)
    FPM::Target::Deb.flags(FPM::Flags.new(opts, "deb", "deb target only"), @settings)

    # Process fpmrc first
    fpmrc(opts)

    # Proces normal flags now.
    remaining = opts.parse(args)

    # need to print help in a different scope
    @help = opts.help

    return remaining
  end # def options

  def fpmrc(options)
    # Skip if we have no HOME environment variable.
    return if !ENV.include?("HOME")
    rcpath = File.expand_path("~/.fpmrc")
    return if !File.exists?(rcpath)

    # fpmrc exists, read it as flags, one per line.
    File.new(rcpath, "r").each do |line|
      flag = line.chomp
      begin
        options.parse([flag])
      rescue => e
        $stderr.puts "Error parsing fpmrc (#{rcpath})"
................................................................................
    opts.on("-n PACKAGENAME", "--name PACKAGENAME",
            "What name to give to the package") do |name|
      @settings.package_name = name
    end # --name

    opts.on("-v VERSION", "--version VERSION",
            "version to give the package") do |version|
      @settings.version = version
    end # --version

    opts.on("--iteration ITERATION",
            "(optional) Set the iteration value for this package.") do |iteration|
      @settings.iteration = iteration
    end # --iteration

................................................................................

    opts.on("-t PACKAGE_TYPE", "the type of package you want to create") do |type|
      @settings.package_type = type
    end # -t

    opts.on("-s SOURCE_TYPE", "what to build the package from") do |st|
      @settings.source_type = st
    end # -s

    opts.on("-S PACKAGE_SUFFIX", "which suffix to append to package and dependencies") do |sfx|
      @settings.suffix = sfx
    end # -S

    opts.on("--prefix PREFIX",
            "A path to prefix files with when building the target package. This may not be necessary for all source types. For example, the 'gem' type will prefix with your gem directory (gem env | grep -A1 PATHS:)") do |prefix|

Changes to lib/fpm/source.rb.

83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
...
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
  def tar(output, paths, chdir=".")
    dirs = []

    # Include all directory entries at the top of the tarball
    paths = [ paths ] if paths.is_a? String
    paths.each do |path|
      while path != "/" and path != "."
        dirs << path if !dirs.include?(path) 
        path = File.dirname(path)
      end
    end # paths.each
    
    # Want directories to be sorted thusly: [ "/usr", "/usr/bin" ]
    # Why? tar and some package managers sometimes fail if the tar is created
    # like: [ "/opt/fizz", "/opt" ]
    # dpkg -i will fail if /opt doesn't exist, sorting it by length ensures
    # /opt is created before /opt/fizz.
    dirs.sort! { |a,b| a.size <=> b.size }
    paths.sort! { |a,b| a.size <=> b.size }
................................................................................
                + [ "--owner=root", "--group=root", "-rf", output ] \
                + paths
    ::Dir.chdir(chdir) do
      system(*files_tar)
    end
  end # def tar

  def tar_cmd 
    # Rely on gnu tar for solaris.
    case %x{uname -s}.chomp
    when "SunOS"
      return "gtar"
    else
      return "tar"
    end
  end # def tar_cmd
end # class FPM::Source







|



|







 







|









83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
...
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
  def tar(output, paths, chdir=".")
    dirs = []

    # Include all directory entries at the top of the tarball
    paths = [ paths ] if paths.is_a? String
    paths.each do |path|
      while path != "/" and path != "."
        dirs << path if !dirs.include?(path)
        path = File.dirname(path)
      end
    end # paths.each

    # Want directories to be sorted thusly: [ "/usr", "/usr/bin" ]
    # Why? tar and some package managers sometimes fail if the tar is created
    # like: [ "/opt/fizz", "/opt" ]
    # dpkg -i will fail if /opt doesn't exist, sorting it by length ensures
    # /opt is created before /opt/fizz.
    dirs.sort! { |a,b| a.size <=> b.size }
    paths.sort! { |a,b| a.size <=> b.size }
................................................................................
                + [ "--owner=root", "--group=root", "-rf", output ] \
                + paths
    ::Dir.chdir(chdir) do
      system(*files_tar)
    end
  end # def tar

  def tar_cmd
    # Rely on gnu tar for solaris.
    case %x{uname -s}.chomp
    when "SunOS"
      return "gtar"
    else
      return "tar"
    end
  end # def tar_cmd
end # class FPM::Source

Changes to lib/fpm/source/dir.rb.

12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
      # Trim leading '/' from prefix
      self[:prefix] = self[:prefix][1..-1] if self[:prefix] =~ /^\//

      # Prefix all files with a path if given.
      @paths.each do |path|
        # Trim @root (--chdir)
        if @root != "." and path.start_with?(@root)
          path = path[@root.size .. -1] 
        end

        # Copy to self[:prefix] (aka --prefix)
        if File.directory?(path)
          # Turn 'path' into 'path/' so rsync copies it properly.
          path = "#{path}/" if path[-1,1] != "/"
          dest = "#{builddir}/tarbuild/#{self[:prefix]}/#{path}"







|







12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
      # Trim leading '/' from prefix
      self[:prefix] = self[:prefix][1..-1] if self[:prefix] =~ /^\//

      # Prefix all files with a path if given.
      @paths.each do |path|
        # Trim @root (--chdir)
        if @root != "." and path.start_with?(@root)
          path = path[@root.size .. -1]
        end

        # Copy to self[:prefix] (aka --prefix)
        if File.directory?(path)
          # Turn 'path' into 'path/' so rsync copies it properly.
          path = "#{path}/" if path[-1,1] != "/"
          dest = "#{builddir}/tarbuild/#{self[:prefix]}/#{path}"

Changes to lib/fpm/source/pyfpm/get_metadata.py.

46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
    # end if

    dependencies = None
    try:
      dependencies = self.distribution.install_requires
    except:
      pass
    
    # In some cases (Mysql-Python) 'dependencies' is none, not empty.
    if dependencies is None:
      dependencies = []

    # Some cases (like paramiko) dependencies is actually just a string, not a
    # list
    if isinstance(dependencies, str):







|







46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
    # end if

    dependencies = None
    try:
      dependencies = self.distribution.install_requires
    except:
      pass

    # In some cases (Mysql-Python) 'dependencies' is none, not empty.
    if dependencies is None:
      dependencies = []

    # Some cases (like paramiko) dependencies is actually just a string, not a
    # list
    if isinstance(dependencies, str):

Changes to lib/fpm/source/python.rb.

26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
    package = @paths.first
    if ["setup.py", "."].include?(package)
      # Assume we're building from an existing python package.
      # Source already acquired, nothing to do!
      return
    end

    if !File.exists?(package) 
      download(package, params[:version])
    else
      @paths = [ File.expand_path(package) ]
    end
  end # def get_source

  def download(package, version=nil)







|







26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
    package = @paths.first
    if ["setup.py", "."].include?(package)
      # Assume we're building from an existing python package.
      # Source already acquired, nothing to do!
      return
    end

    if !File.exists?(package)
      download(package, params[:version])
    else
      @paths = [ File.expand_path(package) ]
    end
  end # def get_source

  def download(package, version=nil)

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

30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
..
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
...
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
...
145
146
147
148
149
150
151
152
                     "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

................................................................................
          control_files << "prerm"
        when "post-uninstall"
          system("cp #{path} ./postrm")
          control_files << "postrm"
        else raise "Unsupported script name '#{name}' (path: #{path})"
      end # case name
    end # self.scripts.each
    
    # Make the control
    system("tar -zcf control.tar.gz #{control_files.join(" ")}")

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

    # pack up the .deb
................................................................................
      if da.size == 1
        da += [">=", "0"]
      end
      dep = "#{da[0]} (#{da[1]} #{da[2]})"
    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 =~ /_/
................................................................................
      nextversion = nextversion.join(".")
      return ["#{name} (>= #{version})", "#{name} (<< #{nextversion})"]
    else
      return dep
    end
  end # def fix_dependency
end # class FPM::Target::Deb








|







 







|







 







|







 







<
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
..
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
...
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
...
145
146
147
148
149
150
151

                     "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

................................................................................
          control_files << "prerm"
        when "post-uninstall"
          system("cp #{path} ./postrm")
          control_files << "postrm"
        else raise "Unsupported script name '#{name}' (path: #{path})"
      end # case name
    end # self.scripts.each

    # Make the control
    system("tar -zcf control.tar.gz #{control_files.join(" ")}")

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

    # pack up the .deb
................................................................................
      if da.size == 1
        da += [">=", "0"]
      end
      dep = "#{da[0]} (#{da[1]} #{da[2]})"
    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 =~ /_/
................................................................................
      nextversion = nextversion.join(".")
      return ["#{name} (>= #{version})", "#{name} (<< #{nextversion})"]
    else
      return dep
    end
  end # def fix_dependency
end # class FPM::Target::Deb

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

32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
    manifests = %w{package.pp package/remove.pp}

    ::Dir.mkdir(File.join(builddir, "manifests"))
    manifests.each do |manifest|
      dir = File.join(builddir, "manifests", File.dirname(manifest))
      @logger.info("manifests targeting: #{dir}")
      ::Dir.mkdir(dir) if !File.directory?(dir)
      
      File.open(File.join(builddir, "manifests", manifest), "w") do |f|
        @logger.info("manifest: #{f.path}")
        template = template(File.join("puppet", "#{manifest}.erb"))
        ::Dir.chdir(fileroot) do
          f.puts template.result(binding)
        end
      end







|







32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
    manifests = %w{package.pp package/remove.pp}

    ::Dir.mkdir(File.join(builddir, "manifests"))
    manifests.each do |manifest|
      dir = File.join(builddir, "manifests", File.dirname(manifest))
      @logger.info("manifests targeting: #{dir}")
      ::Dir.mkdir(dir) if !File.directory?(dir)

      File.open(File.join(builddir, "manifests", manifest), "w") do |f|
        @logger.info("manifest: #{f.path}")
        template = template(File.join("puppet", "#{manifest}.erb"))
        ::Dir.chdir(fileroot) do
          f.puts template.result(binding)
        end
      end

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

6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
..
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
      when nil
        return %x{uname -m}.chomp   # default to current arch
      when "native"
        return %x{uname -m}.chomp   # 'native' is current arch
      when "all"
        # Translate fpm "all" arch to what it means in RPM.
        return "noarch"
      else 
        return @architecture
    end
  end # def architecture

  def specfile(builddir)
    "#{builddir}/#{name}.spec"
  end
................................................................................
    if !replaces.empty?
      $stderr.puts "Warning: RPM does not support 'replaces'"
      $stderr.puts "If you have suggstions as to what --replaces means to RPM"
      $stderr.puts "Please let me know: https://github.com/jordansissel/fpm/issues"
    end

    %w(BUILD RPMS SRPMS SOURCES SPECS).each { |d| Dir.mkdir(d) }
    args = ["rpmbuild", "-ba", 
           "--define", "buildroot #{Dir.pwd}/BUILD",
           "--define", "_topdir #{Dir.pwd}",
           "--define", "_sourcedir #{Dir.pwd}",
           "--define", "_rpmdir #{Dir.pwd}/RPMS",
           "#{name}.spec"]
    ret = system(*args)
    if !ret







|







 







|







6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
..
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
      when nil
        return %x{uname -m}.chomp   # default to current arch
      when "native"
        return %x{uname -m}.chomp   # 'native' is current arch
      when "all"
        # Translate fpm "all" arch to what it means in RPM.
        return "noarch"
      else
        return @architecture
    end
  end # def architecture

  def specfile(builddir)
    "#{builddir}/#{name}.spec"
  end
................................................................................
    if !replaces.empty?
      $stderr.puts "Warning: RPM does not support 'replaces'"
      $stderr.puts "If you have suggstions as to what --replaces means to RPM"
      $stderr.puts "Please let me know: https://github.com/jordansissel/fpm/issues"
    end

    %w(BUILD RPMS SRPMS SOURCES SPECS).each { |d| Dir.mkdir(d) }
    args = ["rpmbuild", "-ba",
           "--define", "buildroot #{Dir.pwd}/BUILD",
           "--define", "_topdir #{Dir.pwd}",
           "--define", "_sourcedir #{Dir.pwd}",
           "--define", "_rpmdir #{Dir.pwd}/RPMS",
           "#{name}.spec"]
    ret = system(*args)
    if !ret

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

7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# IIRC this has to be done as a 'checkinstall' step.
class FPM::Target::Solaris < FPM::Package
  def architecture
    case @architecture
    when nil, "native"
      @architecture = %x{uname -p}.chomp
    end
    # "all" is a valid arch according to 
    # http://www.bolthole.com/solaris/makeapackage.html

    return @architecture
  end # def architecture

  def specfile(builddir)
    "#{builddir}/pkginfo"







|







7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# IIRC this has to be done as a 'checkinstall' step.
class FPM::Target::Solaris < FPM::Package
  def architecture
    case @architecture
    when nil, "native"
      @architecture = %x{uname -p}.chomp
    end
    # "all" is a valid arch according to
    # http://www.bolthole.com/solaris/makeapackage.html

    return @architecture
  end # def architecture

  def specfile(builddir)
    "#{builddir}/pkginfo"

Changes to lib/rpm/header.rb.

19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
..
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

  def read
    # TODO(sissel): update the comments here to reflect learnings about rpm
    # internals
    # At this point assume we've read and consumed the lead and signature.
    #len = @rpm.signature.index_length + @rpm.signature
    #
    # header size is 
    #     ( @rpm.signature.index_length * size of a header entry )
    #     + @rpm.signature.data_length
    #
    # header 'entries' are an 
    #   int32 (tag id), int32 (tag type), int32  (offset), uint32 (count)
    #
    # See rpm's header.c, the headerLoad method function for reference.

    # Header always starts with HEADER_MAGIC + index_count(2bytes) +
    # data_length(2bytes)
    data = @rpm.file.read(16).unpack("a8NN")
................................................................................
    @magic, @index_count, @data_length = data
    validate

    entry_size = 16 # tag id, type, offset, count == 16 bytes
    @index_size = @index_count * entry_size
    tag_data = @rpm.file.read(@index_size)
    data = @rpm.file.read(@data_length)
    
    #ap :data => data

    (0 ... @index_count).each do |i|
      offset = i * entry_size
      entry_data = tag_data[i * entry_size, entry_size]
      entry = entry_data.unpack("NNNN")
      entry << data
      tag = ::RPMFile::Tag.new(*entry)
      @tags << tag

      #ap tag.tag => {
        #:type => tag.type, 
        #:offset => tag.offset,
        #:count => tag.count,
        #:value => (tag.value rescue "???"),
      #}
    end # each index
    @length = @magic.size + @index_size + @data_length
  end # def read







|



|







 







|











|







19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
..
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

  def read
    # TODO(sissel): update the comments here to reflect learnings about rpm
    # internals
    # At this point assume we've read and consumed the lead and signature.
    #len = @rpm.signature.index_length + @rpm.signature
    #
    # header size is
    #     ( @rpm.signature.index_length * size of a header entry )
    #     + @rpm.signature.data_length
    #
    # header 'entries' are an
    #   int32 (tag id), int32 (tag type), int32  (offset), uint32 (count)
    #
    # See rpm's header.c, the headerLoad method function for reference.

    # Header always starts with HEADER_MAGIC + index_count(2bytes) +
    # data_length(2bytes)
    data = @rpm.file.read(16).unpack("a8NN")
................................................................................
    @magic, @index_count, @data_length = data
    validate

    entry_size = 16 # tag id, type, offset, count == 16 bytes
    @index_size = @index_count * entry_size
    tag_data = @rpm.file.read(@index_size)
    data = @rpm.file.read(@data_length)

    #ap :data => data

    (0 ... @index_count).each do |i|
      offset = i * entry_size
      entry_data = tag_data[i * entry_size, entry_size]
      entry = entry_data.unpack("NNNN")
      entry << data
      tag = ::RPMFile::Tag.new(*entry)
      @tags << tag

      #ap tag.tag => {
        #:type => tag.type,
        #:offset => tag.offset,
        #:count => tag.count,
        #:value => (tag.value rescue "???"),
      #}
    end # each index
    @length = @magic.size + @index_size + @data_length
  end # def read

Changes to lib/rpm/lead.rb.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
..
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
require File.join(File.dirname(__FILE__), "namespace")

class RPMFile::Lead
  #struct rpmlead {
  attr_accessor :magic #unsigned char magic[4]; 
  attr_accessor :major #unsigned char major;
  attr_accessor :minor #unsigned char minor;
  attr_accessor :type  #short type;
  attr_accessor :archnum #short archnum;
  attr_accessor :name #char name[66];
  attr_accessor :osnum #short osnum;
  attr_accessor :signature_type #short signature_type;
  attr_accessor :reserved #char reserved[16];
  #}
  
  attr_accessor :length

  def initialize(rpm)
    @rpm = rpm
  end

  def type
................................................................................
      return :binary
    when 1
      return :source
    else
      raise "Unknown package 'type' value #{@type}"
    end
  end # def type
  
  def read
    # Use 'A' here instead of 'a' to trim nulls.
    @length = 96
    data = @rpm.file.read(@length).unpack("A4CCnnA66nnA16")
    @magic, @major, @minor, @type, @archnum, @name, \
      @osnum, @signature_type, @reserved = data





|









|







 







|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
..
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
require File.join(File.dirname(__FILE__), "namespace")

class RPMFile::Lead
  #struct rpmlead {
  attr_accessor :magic #unsigned char magic[4];
  attr_accessor :major #unsigned char major;
  attr_accessor :minor #unsigned char minor;
  attr_accessor :type  #short type;
  attr_accessor :archnum #short archnum;
  attr_accessor :name #char name[66];
  attr_accessor :osnum #short osnum;
  attr_accessor :signature_type #short signature_type;
  attr_accessor :reserved #char reserved[16];
  #}

  attr_accessor :length

  def initialize(rpm)
    @rpm = rpm
  end

  def type
................................................................................
      return :binary
    when 1
      return :source
    else
      raise "Unknown package 'type' value #{@type}"
    end
  end # def type

  def read
    # Use 'A' here instead of 'a' to trim nulls.
    @length = 96
    data = @rpm.file.read(@length).unpack("A4CCnnA66nnA16")
    @magic, @major, @minor, @type, @archnum, @name, \
      @osnum, @signature_type, @reserved = data

Changes to lib/rpm/rpmfile.rb.

4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
require File.join(File.dirname(__FILE__), "lead")
require File.join(File.dirname(__FILE__), "tag")

# Much of the code here is derived from knowledge gained by reading the rpm
# source code, but mostly it started making more sense after reading this site:
# http://www.rpm.org/max-rpm/s1-rpm-file-format-rpm-file-format.html

class RPMFile 
  attr_reader :file

  def initialize(file)
    if file.is_a?(String)
      file = File.new(file, "r")
    end
    @file = file







|







4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
require File.join(File.dirname(__FILE__), "lead")
require File.join(File.dirname(__FILE__), "tag")

# Much of the code here is derived from knowledge gained by reading the rpm
# source code, but mostly it started making more sense after reading this site:
# http://www.rpm.org/max-rpm/s1-rpm-file-format-rpm-file-format.html

class RPMFile
  attr_reader :file

  def initialize(file)
    if file.is_a?(String)
      file = File.new(file, "r")
    end
    @file = file

Changes to misc/pkgsrc.sh.

7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
..
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
  exit 1
fi

if [ ! -f "build/usr/local/bin/bmake" ] ; then
  # TODO(sissel): Maybe bootstrap ourselves.
  echo "This script requires pkgsrc to be bootstrapped in a specific way."
  echo "I expected to find file: build/usr/local/bin/bmake and did not"
  echo 
  echo "Bootstrap with:"
  echo "SH=/bin/bash ./bootstrap/bootstrap --unprivileged --prefix $PWD/build/usr/local --pkgdbdir $PWD/pkgdb"
  exit 1
fi

# TODO(sissel): put some flags.

................................................................................

TARGETS="$*"

for target in $TARGETS; do
  set --

  eval "$(bmake -C $target show-vars-eval VARS="PKGNAME PKGVERSION")"
  name="$(echo "$PKGNAME" | sed -e "s/-$PKGVERSION\$//")" 
  orig_version=${PKGVERSION}
  version=${PKGVERSION}-pkgsrc

  # Purge old package
  rm packages/All/$PKGNAME.tgz

  pkg_delete $name > /dev/null 2>&1
................................................................................

  bmake -C $target clean || exit 1
  bmake -C $target USE_DESTDIR=yes LOCALBASE=$LOCALBASE PREFIX=$LOCALBASE \
    DESTDIR=$DESTDIR SKIP_DEPENDS=yes \
    clean package || exit 1

  # Start building fpm args
  set -- -n "$name" -v "$version" --prefix $LOCALBASE 
  
  # Skip the pkgsrc package metadata files
  set -- "$@" --exclude '+*'

  # Handle deps
  for dep in $(bmake -C $target show-depends-pkgpaths) ; do
    eval "$(bmake -C $dep show-vars-eval VARS="PKGNAME PKGVERSION")"
    PKGNAME="$(echo "$PKGNAME" | sed -e "s/-$PKGVERSION\$//")"
    set -- "$@" -d "$PKGNAME (= $PKGVERSION-pkgsrc)"
  done

  set -- -s tar -t deb "$@" 
  set -- "$@" packages/All/$name-$orig_version.tgz 
  fpm "$@" 
done
  








|







 







|







 







|
|










|
|
|

|

7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
..
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
  exit 1
fi

if [ ! -f "build/usr/local/bin/bmake" ] ; then
  # TODO(sissel): Maybe bootstrap ourselves.
  echo "This script requires pkgsrc to be bootstrapped in a specific way."
  echo "I expected to find file: build/usr/local/bin/bmake and did not"
  echo
  echo "Bootstrap with:"
  echo "SH=/bin/bash ./bootstrap/bootstrap --unprivileged --prefix $PWD/build/usr/local --pkgdbdir $PWD/pkgdb"
  exit 1
fi

# TODO(sissel): put some flags.

................................................................................

TARGETS="$*"

for target in $TARGETS; do
  set --

  eval "$(bmake -C $target show-vars-eval VARS="PKGNAME PKGVERSION")"
  name="$(echo "$PKGNAME" | sed -e "s/-$PKGVERSION\$//")"
  orig_version=${PKGVERSION}
  version=${PKGVERSION}-pkgsrc

  # Purge old package
  rm packages/All/$PKGNAME.tgz

  pkg_delete $name > /dev/null 2>&1
................................................................................

  bmake -C $target clean || exit 1
  bmake -C $target USE_DESTDIR=yes LOCALBASE=$LOCALBASE PREFIX=$LOCALBASE \
    DESTDIR=$DESTDIR SKIP_DEPENDS=yes \
    clean package || exit 1

  # Start building fpm args
  set -- -n "$name" -v "$version" --prefix $LOCALBASE

  # Skip the pkgsrc package metadata files
  set -- "$@" --exclude '+*'

  # Handle deps
  for dep in $(bmake -C $target show-depends-pkgpaths) ; do
    eval "$(bmake -C $dep show-vars-eval VARS="PKGNAME PKGVERSION")"
    PKGNAME="$(echo "$PKGNAME" | sed -e "s/-$PKGVERSION\$//")"
    set -- "$@" -d "$PKGNAME (= $PKGVERSION-pkgsrc)"
  done

  set -- -s tar -t deb "$@"
  set -- "$@" packages/All/$name-$orig_version.tgz
  fpm "$@"
done


Changes to templates/deb.erb.

10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
Provides: <%= provides.join(", ") -%>
<% end -%>
<% if !replaces.empty? -%>
<%   properrepl = replaces.collect { |d| fix_dependency(d) }.flatten -%>
Replaces: <%= properrepl.flatten.join(", ") %>
<% end -%>
Standards-Version: 3.9.1
Section: <%= category or "unknown" %> 
Priority: extra
Homepage: <%= url or "http://nourlgiven.example.com/" %>
Description: <%= name %> (FPM-generated package)
<% max_len = 74 -%>
<% if description -%>
<%= description.gsub(/^$/, ".").gsub(/(.{1,#{max_len}})( +|$)\n?|(.{#{max_len}})/,"  \\1\\3\n") -%>
<% else -%>
<%= "no description given" %>
<% end -%>







|









10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
Provides: <%= provides.join(", ") -%>
<% end -%>
<% if !replaces.empty? -%>
<%   properrepl = replaces.collect { |d| fix_dependency(d) }.flatten -%>
Replaces: <%= properrepl.flatten.join(", ") %>
<% end -%>
Standards-Version: 3.9.1
Section: <%= category or "unknown" %>
Priority: extra
Homepage: <%= url or "http://nourlgiven.example.com/" %>
Description: <%= name %> (FPM-generated package)
<% max_len = 74 -%>
<% if description -%>
<%= description.gsub(/^$/, ".").gsub(/(.{1,#{max_len}})( +|$)\n?|(.{#{max_len}})/,"  \\1\\3\n") -%>
<% else -%>
<%= "no description given" %>
<% end -%>

Changes to templates/rpm.erb.

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
AutoReqProv: no

Group: <%= category %>
<%#
TODO: [Jay] rpms require a license
let's detect it intelligently
-%>
License: <%= license %> 
URL: <%= url or "http://nourlgiven.example.com/" %>
Source0:  %{_sourcedir}/data.tar.gz
BuildRoot: %(mktemp -ud %{_tmppath}/%{name}-%{version}-%{release}-XXXXXX)

<% if !dependencies.empty? -%>
<%
  properdeps = dependencies.collect do |d|
    # Convert gem ~> X.Y.Z to '>= X.Y.Z' and < X.Y+1.0
    if d =~ /\~>/
      name, version = d.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(".")
      ["#{name} >= #{version}", "#{name} < #{nextversion}"]
    # Convert gem >= A.B.C <= X.Y.Z to '>= A.B.C' and '<= X.Y.Z'
    elsif d =~ /\d [<>]=? \d/
      puts d
      # split out version numbers with their equality sign
      name, lower_version, upper_version = d.scan(/([\w-]+) ([<>]=? [\d\.]+) ([<>]=? [\d\.]+)/)[0]







|













|







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
AutoReqProv: no

Group: <%= category %>
<%#
TODO: [Jay] rpms require a license
let's detect it intelligently
-%>
License: <%= license %>
URL: <%= url or "http://nourlgiven.example.com/" %>
Source0:  %{_sourcedir}/data.tar.gz
BuildRoot: %(mktemp -ud %{_tmppath}/%{name}-%{version}-%{release}-XXXXXX)

<% if !dependencies.empty? -%>
<%
  properdeps = dependencies.collect do |d|
    # Convert gem ~> X.Y.Z to '>= X.Y.Z' and < X.Y+1.0
    if d =~ /\~>/
      name, version = d.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(".")
      ["#{name} >= #{version}", "#{name} < #{nextversion}"]
    # Convert gem >= A.B.C <= X.Y.Z to '>= A.B.C' and '<= X.Y.Z'
    elsif d =~ /\d [<>]=? \d/
      puts d
      # split out version numbers with their equality sign
      name, lower_version, upper_version = d.scan(/([\w-]+) ([<>]=? [\d\.]+) ([<>]=? [\d\.]+)/)[0]