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

⌈⌋ ⎇ branch:  cross package maker


Check-in [1e5dbadf47]

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

Overview
Comment:- start major refactoring. Design first, this time. With tests.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 1e5dbadf476425f8858217a8803dadea4850b8f2
User & Date: jls@semicomplete.com 2012-02-23 07:59:31
Context
2012-02-24
07:43
- move older minitest tests away until they can be refactored to the new api check-in: 40571c6988 user: jls@semicomplete.com tags: trunk
2012-02-23
07:59
- start major refactoring. Design first, this time. With tests. check-in: 1e5dbadf47 user: jls@semicomplete.com tags: trunk
2012-02-22
23:10
- update changelist for 0.3.12 check-in: 35ee49c8a5 user: jls@semicomplete.com tags: trunk, v0.3.12
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Added Gemfile.







>
>
>
1
2
3
source :rubygems

gemspec

Changes to fpm.gemspec.

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
Gem::Specification.new do |spec|
  files = []
  dirs = %w{lib bin templates}
  dirs.each do |dir|
    files += Dir["#{dir}/**/*"]
  end

  files << "LICENSE"
  files << "CONTRIBUTORS"
  files << "CHANGELIST"

  spec.name = "fpm"
  spec.version = "0.3.12"
  spec.summary = "fpm - package building and mangling"
  spec.description = "Convert directories, rpms, python eggs, rubygems, and more to rpms, debs, solaris packages and more. Win at package management without wasting pointless hours debugging bad rpm specs!"
  spec.add_dependency("json")


  spec.files = files
  spec.require_paths << "lib"
  spec.bindir = "bin"
  spec.executables << "fpm"
  spec.executables << "fpm-npm"

  spec.author = "Jordan Sissel"
  spec.email = "jls@semicomplete.com"
  spec.homepage = "https://github.com/jordansissel/fpm"
end













|



>
>











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
Gem::Specification.new do |spec|
  files = []
  dirs = %w{lib bin templates}
  dirs.each do |dir|
    files += Dir["#{dir}/**/*"]
  end

  files << "LICENSE"
  files << "CONTRIBUTORS"
  files << "CHANGELIST"

  spec.name = "fpm"
  spec.version = "0.4.0"
  spec.summary = "fpm - package building and mangling"
  spec.description = "Convert directories, rpms, python eggs, rubygems, and more to rpms, debs, solaris packages and more. Win at package management without wasting pointless hours debugging bad rpm specs!"
  spec.add_dependency("json")
  spec.add_dependency("backports", "2.3.0")
  spec.add_development_dependency("rush")
  spec.files = files
  spec.require_paths << "lib"
  spec.bindir = "bin"
  spec.executables << "fpm"
  spec.executables << "fpm-npm"

  spec.author = "Jordan Sissel"
  spec.email = "jls@semicomplete.com"
  spec.homepage = "https://github.com/jordansissel/fpm"
end

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
29
30
31
32
33
34
35
36
37
38
39
40
41
42

43
44
45
46
47
48
49
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

  # URL for this package.
  # Could be the homepage. Could be the download url. You pick.
  attr_accessor :url

  # The category of this package.
  # RedHat calls this 'Group'
  # Debian calls this 'Section'
  # FreeBSD would put this in /usr/ports/<category>/...
  attr_accessor :category

  # A identifier representing the license. Any string is fine.
  attr_accessor :license

  # A identifier representing the vendor. Any string is fine.

  attr_accessor :vendor

  # What architecture is this package for?
  attr_accessor :architecture

  # Array of dependencies.
  attr_accessor :dependencies



|

















>
>
|




















>







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
require "fpm/namespace"
require "socket" # for Socket.gethostname
require "logger"
require "tmpdir"

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'
  #
  # Iteration can be nil. If nil, the fpm package implementation is expected
  # to handle any default value that should be instead.
  attr_accessor :iteration

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

  # URL for this package.
  # Could be the homepage. Could be the download url. You pick.
  attr_accessor :url

  # The category of this package.
  # RedHat calls this 'Group'
  # Debian calls this 'Section'
  # FreeBSD would put this in /usr/ports/<category>/...
  attr_accessor :category

  # A identifier representing the license. Any string is fine.
  attr_accessor :license

  # A identifier representing the vendor. Any string is fine.
  # This is usually who produced the software.
  attr_accessor :vendor

  # What architecture is this package for?
  attr_accessor :architecture

  # Array of dependencies.
  attr_accessor :dependencies
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

  # hash of paths for maintainer/package scripts (postinstall, etc)
  attr_accessor :scripts

  # Array of configuration files
  attr_accessor :config_files

  # Package path prefix

  attr_accessor :prefix

	# target-specific settings
	attr_accessor :settings

  def initialize(source, params={})
    @source = source
    @logger = Logger.new(STDERR)
    @logger.level = $DEBUG ? Logger::DEBUG : Logger::WARN

    @name = source[:name] # || fail

    # 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"
    @vendor = source[:vendor] || "none"
    #@maintainer = source[:maintainer] || "<#{ENV["USER"]}@#{Socket.gethostname}>"

    @maintainer = source[:maintainer]

    # Default maintainer if none given.
    if @maintainer.nil? or @maintainer.empty?
      # Reference
      # http://www.debian.org/doc/manuals/maint-guide/first.en.html
      # http://wiki.debian.org/DeveloperConfiguration
      # https://github.com/jordansissel/fpm/issues/37
      if ENV.include?("DEBEMAIL") and ENV.include?("DEBFULLNAME")
        # Use DEBEMAIL and DEBFULLNAME as the default maintainer if available.
        @maintainer = "#{ENV["DEBFULLNAME"]} <#{ENV["DEBEMAIL"]}>"
      else
        # TODO(sissel): Maybe support using 'git config' for a default as well?
        # git config --get user.name, etc can be useful.
        #
        # Otherwise default to user@currenthost
        @maintainer = "<#{ENV["USER"]}@#{Socket.gethostname}>"
      end
    end

    # If @architecture is nil, the target package should provide a default.
    # Special 'architecture' values include "all" (aka rpm's noarch, debian's all)
    # 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] || []
    @conflicts = source[:conflicts] || []
    @scripts = source[:scripts]
    @config_files = source[:config_files] || []
    @prefix = source[:prefix] || "/"


    # 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

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


  def template(path=nil)
    path ||= "#{type}.erb"
    @logger.info("Reading template: #{path}")
    tpl = File.read("#{FPM::DIRS[:templates]}/#{path}")
    return ERB.new(tpl, nil, "-")
  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
  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







|
>
|

<
|

|
<



<
<

|
|
<
|
<
<
|
|
|
|
|
|
>
|

<
<
|
|
|
|
|
|
|
|
|
|
|
|
|
<





|
|
|
>
|
|
|
|
|
>

|
<
>
>
|
|
<
>
>
>
>
>
>
>
>
|
|
|






>
|
<
<
<
|
<
>

|
<
|
<
<
<
<
<
<
>
>
>
|
<
<
<
|
<
>

>
>
|

|
<
<
|
<
<
|

|
<
|
|
|
<
<
<
>
|
<
|
|
>
>

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

  # hash of paths for maintainer/package scripts (postinstall, etc)
  attr_accessor :scripts

  # Array of configuration files
  attr_accessor :config_files

  # Any other attributes specific to this package.
  # This is where you'd put rpm, deb, or other specific attributes.
  attr_accessor :attributes


  private

  def initialize

    @logger = Logger.new(STDERR)
    @logger.level = $DEBUG ? Logger::DEBUG : Logger::WARN



    # Default version is 1.0 in case nobody told us a specific version.
    @version = 1.0
    @epoch = 1

    @dependencies = []


    @iteration = nil
    @url = nil
    @category = "default"
    @license = "unknown"
    @vendor = "none"

    # Attributes for this specific package 
    @attributes = {}



    # Reference
    # http://www.debian.org/doc/manuals/maint-guide/first.en.html
    # http://wiki.debian.org/DeveloperConfiguration
    # https://github.com/jordansissel/fpm/issues/37
    if ENV.include?("DEBEMAIL") and ENV.include?("DEBFULLNAME")
      # Use DEBEMAIL and DEBFULLNAME as the default maintainer if available.
      @maintainer = "#{ENV["DEBFULLNAME"]} <#{ENV["DEBEMAIL"]}>"
    else
      # TODO(sissel): Maybe support using 'git config' for a default as well?
      # git config --get user.name, etc can be useful.
      #
      # Otherwise default to user@currenthost
      @maintainer = "<#{ENV["USER"]}@#{Socket.gethostname}>"

    end

    # If @architecture is nil, the target package should provide a default.
    # Special 'architecture' values include "all" (aka rpm's noarch, debian's all)
    # Another special includes "native" which will be the current platform's arch.
    @architecture = "all"
    @description = "no description given"

    # TODO(sissel): Implement provides, requires, conflicts, etc later.
    #@provides = []
    #@conflicts = source[:conflicts] || []
    #@scripts = source[:scripts]
    #@config_files = source[:config_files] || []
    #@prefix = source[:prefix] || "/"
  end # def initialize

  # Add a new source to this package.

  # The exact behavior depends on the kind of package being managed.
  #
  # For instance: 
  #

  # * for FPM::Package::Dir, << expects a path to a directory or files.
  # * for FPM::Package::RPM, << expects a path to an rpm.
  #
  # The idea is that you can keep pumping in new things to a package
  # for later conversion or output.
  #
  # Implementations are expected to put files relevant to the 'input' in the
  # staging_path
  def <<(input)
    raise NotImplementedError.new
  end # def <<

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

  # Convert this package to a new package type
  def convert(klass)



    pkg = klass.new

    pkg.instance_variable_set(:@staging_path, staging_path)

    # copy other bits

    ivars = [






      :architecture, :attributes, :category, :config_files, :conflicts,
      :dependencies, :description, :epoch, :iteration, :license, :maintainer,
      :name, :provides, :replaces, :scripts, :url, :vendor, :version
    ]



    ivars.each do |ivar|

      pkg.instance_variable_set(ivar, instance_variable_get(ivar))
    end

    return pkg
  end # def convert

  def output(path)


    raise NotImplementedError.new("This must be implemented by FPM::Package subclasses")


  end # def output

  def staging_path

    @staging_path ||= ::Dir.mktmpdir(File.join(::Dir.pwd, "package-#{type}-staging"))
  end # def staging_path




  # Clean up any temporary storage used by this class.
  def cleanup

    FileUtils.rm_r(staging_path)
  end # def cleanup

  public(:type, :initialize, :convert, :output, :<<, :cleanup, :staging_path)
end # class FPM::Package

Added lib/fpm/package/dir.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
require "fpm/package"
require "backports"
require "fileutils"
require "find"

class FPM::Package::Dir < FPM::Package
  private

  def <<(path)
    @paths ||= []
    @paths << path

    clone(path, staging_path)
  end # def <<

  def output(dir)
    dir = File.expand_path(dir)
    @paths.each do |path|
      ::Dir.chdir(staging_path) do
        clone(path, dir)
      end
    end
  end

  private
  # Copy a file or directory to a destination
  #
  # This is special because it respects the full path of the source.
  # Aditionally, hardlinks will be used instead of copies.
  #
  # Example:
  #
  #     clone("/tmp/hello/world", "/tmp/example")
  #
  # The above will copy, recursively, /tmp/hello/world into
  # /tmp/example/hello/world
  def clone(source, destination)
    # Copy all files from 'path' into staging_path

    ::Dir.chdir(@attributes[:chdir] || ".") do
      p :chdir => ::Dir.pwd, :source => source
      Find.find(source).each do |file|
        next if source == file # ignore the directory itself
        # Translate file paths with attributes like 'prefix' and 'chdir'
        if @attributes[:prefix]
          target = File.join(destination, @attributes[:prefix], file)
        else
          target = File.join(destination, file)
        end

        copy(file, target)
      end
    end
  end # def clone

  def copy(source, destination)
    directory = File.dirname(destination)
    if !File.directory?(directory)
      FileUtils.mkdir_p(directory)
    end

    # Create a directory if this path is a directory
    if File.directory?(source)
      FileUtils.mkdir(destination)
    else
      # Otherwise try copying the file.
      begin
        File.link(source, destination)
      rescue Errno::EXDEV
        # Hardlink attempt failed, copy it instead
        FileUtils.copy(source, destination)
      end
    end
  end # def copy

  public(:<<, :output)
end # class FPM::Package::Dir

Changes to lib/fpm/source.rb.

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
    vendor
  ).each do |attr|
    attr = :"#{attr}"
    define_method(attr) { self[attr] }
    define_method(:"#{attr}=") { |v| self[attr] = v}
  end

  def dependencies
    self[:dependencies] ||= []
  end

  attr_reader :paths
  attr_accessor :root

  def initialize(paths, root, params={})
    @logger = Logger.new(STDERR)
    @logger.level = $DEBUG ? Logger::DEBUG : Logger::WARN

    @paths = paths
    @root = root

    self[:suffix] = params[:suffix]
    self[:settings] = params[:settings]

    get_source(params)
    get_metadata

    # override the inferred data with the passed-in data
    params.each do |k,v|
      self[k] = v if v != nil
    end
  end # def initialize

  # this method should take the paths and root and infer as much
  # about the package as it can.
  def get_metadata
    raise NoMethodError,
      "Please subclass FPM::Source and define get_metadata"
  end # def get_metadata

  # This method should be overridden by package sources that need to do any
  # kind of fetching.
  def get_source(params)
    # noop by default
  end # def get_source

  def make_tarball!(tar_path, builddir)
    raise NoMethodError,
      "Please subclass FPM::Source and define make_tarball!(tar_path)"
  end

  def metadata
    @metadata ||= {}
  end

  def [](key)
    metadata[key.to_sym]
  end

  def []=(key,val)
    metadata[key.to_sym] = val
  end

  # MySourceClass.new('/tmp/build').package(FPM::Deb).assemble(params)
  def package(pkg_cls)
    pkg_cls.new(self)
  end

  private
  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 }


    # Solaris's tar is pretty neutered, so implement --exclude and such
    # ourselves.
    # TODO(sissel): May need to implement our own tar file generator
    # so we can enforce file ownership. Again, solaris' tar doesn't support
    # --owner, etc.
    #paths = []
    #dirs.each do |dir|
      #Dir.glob(File.join(dir, "**", "*")).each do |path|
        #next if excludesFile.fnmatch?(
      #end
    #end

    excludes = self[:exclude].map { |e| ["--exclude", e] }.flatten

    # TODO(sissel): To properly implement excludes as regexps, we
    # will need to find files ourselves. That may be more work
    # than it is worth. For now, rely on tar's --exclude.
    dir_tar = [tar_cmd, "--owner=0", "--group=0" ] \
              + excludes \
              + ["-cf", output, "--no-recursion" ]

    # Only if directories and paths do not have duplicates ...
    dirs -= paths

    if dirs.any?
      ::Dir.chdir(chdir) do
        safesystem *(dir_tar += dirs)
      end
    end

    files_tar = [ tar_cmd ] \
                + excludes \
                + [ "--owner=0", "--group=0", "-rf", output ] \
                + paths
    ::Dir.chdir(chdir) do
      safesystem(*files_tar)
    end
  end # def tar

end # class FPM::Source







<
<
<
<
<
<
<
|


<
<
<
<
<
<
<
<
<
<
<
<
<
<


<
<
<
<
<
<
|
<
<
<
<
<
|
<
<
<
<
|
|
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|


17
18
19
20
21
22
23







24
25
26














27
28






29





30




31
32


33








































































34
35
36
    vendor
  ).each do |attr|
    attr = :"#{attr}"
    define_method(attr) { self[attr] }
    define_method(:"#{attr}=") { |v| self[attr] = v}
  end








  def initialize
    @logger = Logger.new(STDERR)
    @logger.level = $DEBUG ? Logger::DEBUG : Logger::WARN














  end # def initialize







  # Add a new argument to this source





  # The effect of this is specific to the source's implementation,




  # but in general this means you are adding something to this source.
  def <<(arg)


    raise NotImplementedError.new








































































  end # def <<

end # class FPM::Source

Deleted test/Makefile.

1
2
3
4
5
6
7
8
9
10
11
TESTS=$(shell git ls-files '*.test')

.PHONY: test
test: $(TESTS)

.PHONY: $(TESTS)
$(TESTS):
	@bash test.sh $@

clean:
	rm *.deb *.rpm *.gem
<
<
<
<
<
<
<
<
<
<
<






















Added test/all.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
require "rubygems"
require "minitest/spec"
require "minitest/autorun"

# Get coverage report
require "simplecov"
SimpleCov.start

# Add '../lib' to the require path.
$: << File.join(File.dirname(__FILE__), "..", "lib")

def use(path)
  puts "Loading tests from #{path}"
  require File.expand_path(path)
end

dirname = File.dirname(__FILE__)
use File.join(dirname, "docs.rb")

# Load tests from ./*/**/*.rb (usually ./libraryname/....)
glob = File.join(dirname, "*", "**", "*.rb")
Dir.glob(glob).each do |path|
  use path
end

Deleted test/dir-deb-with-debconf.out.

1
2
       0 bytes,     0 lines   *  config               
       0 bytes,     0 lines      templates            
<
<




Deleted test/dir-deb-with-debconf.test.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#!/bin/bash

run() {
  mkdir -p $tmpdir/prefix
  touch $tmpdir/config
  touch $tmpdir/templates

  fpm -s dir -t deb -n testing -a all \
  --deb-config $tmpdir/config \
  --deb-templates $tmpdir/templates \
  $tmpdir/prefix

  file=testing_1.0_all.deb
  dpkg -I $file | grep "\(config\)\|\(templates\)" > $output

  rm $file
}
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<


































Deleted test/dir-deb-with-prefix.out.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
./
./opt/
./opt/foo/
./opt/foo/bar/
./opt/foo/bar/a/
./opt/foo/bar/a/d/
./opt/foo/bar/a/d/hello
./opt/foo/bar/a/e/
./opt/foo/bar/a/f/
./opt/foo/bar/a/hello
./opt/foo/bar/b/
./opt/foo/bar/b/d/
./opt/foo/bar/b/e/
./opt/foo/bar/b/f/
./opt/foo/bar/c/
./opt/foo/bar/c/d/
./opt/foo/bar/c/d/hello
./opt/foo/bar/c/e/
./opt/foo/bar/c/f/
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<






































Deleted test/dir-deb-with-prefix.test.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#!/bin/bash

run() {
  mkdir -p $tmpdir/{a,b,c}/{d,e,f}
  touch $tmpdir/a/hello
  touch $tmpdir/a/d/hello
  touch $tmpdir/c/d/hello

  prefix=/opt/foo/bar

  fpm -s dir -t deb -n testing -a all --prefix $prefix -C $tmpdir 

  file=testing_1.0_all.deb
  dpkg -c $file | awk '{$1=$2=$3=$4=$5="";print}' | sed -e 's/^ *//' | sort > $output

  rm $file
}
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<


































Deleted test/dir-deb.out.template.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
tmp/
tmp/TMPDIR/
tmp/TMPDIR/a/
tmp/TMPDIR/a/d/
tmp/TMPDIR/a/d/hello
tmp/TMPDIR/a/e/
tmp/TMPDIR/a/f/
tmp/TMPDIR/a/hello
tmp/TMPDIR/b/
tmp/TMPDIR/b/d/
tmp/TMPDIR/b/e/
tmp/TMPDIR/b/f/
tmp/TMPDIR/c/
tmp/TMPDIR/c/d/
tmp/TMPDIR/c/d/hello
tmp/TMPDIR/c/e/
tmp/TMPDIR/c/f/
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<


































Deleted test/dir-deb.test.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#!/bin/bash

run() {
  mkdir -p $tmpdir/{a,b,c}/{d,e,f}
  touch $tmpdir/a/hello
  touch $tmpdir/a/d/hello
  touch $tmpdir/c/d/hello

  prefix=/opt/foo/bar

  fpm -s dir -t deb -n testing -a all $tmpdir

  file=testing_1.0_all.deb
  dpkg -c $file | awk '{$1=$2=$3=$4=$5="";print}' | sed -e 's/^ *//' | sort > $output
  #ar p $file data.tar.gz | tar -ztf - | sort > $output
  sed -e "s,TMPDIR,$(basename $tmpdir)," $expected.template > $expected

  rm $file
}

clean() {
  rm $expected
}
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<














































Deleted test/dir-rpm-with-prefix.out.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/opt/foo/bar
/opt/foo/bar/a
/opt/foo/bar/a/d
/opt/foo/bar/a/d/hello
/opt/foo/bar/a/e
/opt/foo/bar/a/f
/opt/foo/bar/a/hello
/opt/foo/bar/b
/opt/foo/bar/b/d
/opt/foo/bar/b/e
/opt/foo/bar/b/f
/opt/foo/bar/c
/opt/foo/bar/c/d
/opt/foo/bar/c/d/hello
/opt/foo/bar/c/e
/opt/foo/bar/c/f
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
































Deleted test/dir-rpm-with-prefix.test.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#!/bin/bash

run() {
  mkdir -p $tmpdir/{a,b,c}/{d,e,f}
  touch $tmpdir/a/hello
  touch $tmpdir/a/d/hello
  touch $tmpdir/c/d/hello

  prefix=/opt/foo/bar

  fpm -s dir -t rpm -n testing -a all --prefix $prefix -C $tmpdir 

  rpm -qlp testing-1.0-1.noarch.rpm > $output
  rm testing-1.0-1.noarch.rpm
}
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<






























Deleted test/dir-rpm.out.template.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/tmp/TMPDIR
/tmp/TMPDIR/a
/tmp/TMPDIR/a/d
/tmp/TMPDIR/a/d/hello
/tmp/TMPDIR/a/e
/tmp/TMPDIR/a/f
/tmp/TMPDIR/a/hello
/tmp/TMPDIR/b
/tmp/TMPDIR/b/d
/tmp/TMPDIR/b/e
/tmp/TMPDIR/b/f
/tmp/TMPDIR/c
/tmp/TMPDIR/c/d
/tmp/TMPDIR/c/d/hello
/tmp/TMPDIR/c/e
/tmp/TMPDIR/c/f
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
































Deleted test/dir-rpm.test.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#!/bin/bash

run() {
  mkdir -p $tmpdir/{a,b,c}/{d,e,f}
  touch $tmpdir/a/hello
  touch $tmpdir/a/d/hello
  touch $tmpdir/c/d/hello

  fpm -s dir -t rpm -n testing -a all $tmpdir

  file=testing-1.0-1.noarch.rpm
  rpm -qlp $file > $output
  sed -e "s,TMPDIR,$(basename $tmpdir)," $expected.template > $expected

  rm $file
}

clean() {
  rm $expected
}
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<








































Added test/docs.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
require "rubygems"                                                                                               
require "yard"                                                                                                   
require File.join(File.expand_path(File.dirname(__FILE__)), "testing")
require "minitest/autorun"

describe "documentation tests" do
  before do
    # Use YARD to parse all ruby files found in '../lib'
    libdir = File.join(File.dirname(__FILE__), "..", "lib")
    YARD::Registry.load(Dir.glob(File.join(libdir, "**", "*.rb")))
    @registry = YARD::Registry.all
  end

  test "All classes, methods, modules, and constants must be documented" do
    # Note, the 'find the undocumented things' code here is 
    # copied mostly from: YARD 0.7.5's lib/yard/cli/stats.rb
    #
    # Find all undocumented classes, modules, and constants
    undocumented = @registry.select do |o| 
      [:class, :module, :constant].include?(o.type) && o.docstring.blank?
    end

    # Find all undocumented methods
    methods = @registry.select { |m| m.type == :method }
    methods.reject! { |m| m.is_alias? || !m.is_explicit? }
    undocumented += methods.select do |m| 
      m.docstring.blank? && !m.overridden_method
    end

    if (undocumented.length > 0)
      message = ["The following are not documented"]
      undocumented.each do |o|
        message << "* #{o.type.to_s} #{o.to_s} <#{o.file}:#{o.line}>"
      end

      flunk(message.join("\n"))
    else
      pass
    end
  end
end

Added test/fpm/package/dir.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
require "rubygems"
require File.join(File.dirname(File.expand_path(__FILE__)), "..", "..", "testing")
$: << File.join(File.dirname(File.expand_path(__FILE__)), "..", "..", "..", "lib")
require "minitest/autorun"
require "tmpdir"
require "fileutils"
require "fpm/package/dir"
require "rush" # for simple file stuff

describe FPM::Package::Dir do
  before do
    @source = FPM::Package::Dir.new
    @rush = Rush::Box.new("localhost")
    @tmpdir = @rush[::Dir.mktmpdir("package-test-tmpdir")]
    @output = @rush[::Dir.mktmpdir("package-test-output")]
  end # before

  after do
    @source.cleanup
    FileUtils.rm_r(@tmpdir.full_path)
    FileUtils.rm_r(@output.full_path)
  end # after

  test "adding a single file" do
    file = @tmpdir["hello"]
    file.write "Hello world"
    @source << @tmpdir.full_path

    @source.output(@output.full_path)
    assert_equal(@output[File.join(".", file.full_path)].contents,
                 file.contents, "The file #{@tmpdir["hello"].full_path} should appear in the output")
  end

  test "single file in a directory" do
    dir = @tmpdir.create_dir("a/b/c")
    file = dir.create_file("hello")
    file.write "Hello world"
    @source << @tmpdir.full_path

    @source.output(@output.full_path)
    assert_equal(@output[File.join(".", file.full_path)].contents,
                 file.contents, "The file #{@tmpdir["a/b/c/hello"].full_path} should appear in the output")
  end

  test "multiple files" do
    dir = @tmpdir.create_dir("a/b/c")
    files = rand(50).times.collect do |i|
      dir.create_file("hello-#{i}")
    end
    files.each { |f| f.write(rand(1000)) }

    @source << @tmpdir.full_path
    @source.output(@output.full_path)

    files.each do |file|
      assert_equal(@output[File.join(".", file.full_path)].contents,
                   file.contents, "The file #{file.full_path} should appear in the output")
    end
  end

  test "single file with prefix" do
    prefix = @source.attributes[:prefix] = "/usr/local"
    file = @tmpdir["hello"]
    file.write "Hello world"
    @source << @tmpdir.full_path

    @source.output(@output.full_path)

    expected_path = File.join(".", prefix, file.full_path)
    assert_equal(@output[expected_path].contents,
                 file.contents, "The file #{@tmpdir["hello"].full_path} should appear in the output")
  end

  test "single file with prefix and chdir" do
    prefix = @source.attributes[:prefix] = "/usr/local"
    chdir = @source.attributes[:chdir] = @tmpdir.full_path
    file = @tmpdir["hello"]
    file.write "Hello world"
    @source << "." # since we chdir, copy the entire root

    @source.output(@output.full_path)

    # path relative to the @output directory.
    expected_path = File.join(".", prefix, file.name)
    assert_equal(@output[expected_path].contents,
                 file.contents, "The file #{@tmpdir["hello"].full_path} should appear in the output")
  end

end # describe FPM::Package::Dir

Deleted test/gem-deb.out.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
./usr/
./usr/lib/
./usr/lib/ruby/
./usr/lib/ruby/gems/
./usr/lib/ruby/gems/1.8/
./usr/lib/ruby/gems/1.8/bin/
./usr/lib/ruby/gems/1.8/bin/rails
./usr/lib/ruby/gems/1.8/cache/
./usr/lib/ruby/gems/1.8/cache/rails-3.1.0.gem
./usr/lib/ruby/gems/1.8/doc/
./usr/lib/ruby/gems/1.8/gems/
./usr/lib/ruby/gems/1.8/gems/rails-3.1.0/
./usr/lib/ruby/gems/1.8/gems/rails-3.1.0/bin/
./usr/lib/ruby/gems/1.8/gems/rails-3.1.0/bin/rails
./usr/lib/ruby/gems/1.8/specifications/
./usr/lib/ruby/gems/1.8/specifications/rails-3.1.0.gemspec
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
































Deleted test/gem-deb.test.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#!/bin/bash
RAILS_VERSION=3.1.0

run() {
  # Force the gem installation path to match the one of the expected output
  export GEM_HOME=/usr/lib/ruby/gems/1.8
  
  fpm -s gem -t deb -v $RAILS_VERSION rails

  file=rubygem-rails_${RAILS_VERSION}_all.deb
  dpkg -c $file | awk '{$1=$2=$3=$4=$5="";print}' | sed -e 's/^ *//' | sort > $output
  rm $file
}

clean() {
  rm rails-${RAILS_VERSION}.gem
}
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<


































Added test/testing.rb.





























>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
require "rubygems"
require "minitest/spec"

# Add '../lib' to the require path.
$: << File.join(File.dirname(__FILE__), "..", "lib")

# I don't really like monkeypatching, but whatever, this is probably better
# than overriding the 'describe' method.
class MiniTest::Spec
  class << self
    # 'it' sounds wrong, call it 'test'
    alias :test :it
  end
end