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: |
1e5dbadf476425f8858217a8803dadea |
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
Added Gemfile.
> > > | 1 2 3 | source :rubygems gemspec |
Changes to fpm.gemspec.
1 2 3 4 5 6 7 8 9 10 11 12 | 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" | | > > | 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 | require "fpm/namespace" require "socket" # for Socket.gethostname require "logger" | | > > | > | 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 | # hash of paths for maintainer/package scripts (postinstall, etc) attr_accessor :scripts # Array of configuration files attr_accessor :config_files | | > | < | | < < < | | < | < < | | | | | | > | < < | | | | | | | | | | | | | < | | | > | | | | | > | < > > | | < > > > > > > > > | | | > | < < < | < > | < | < < < < < < > > > | < < < | < > > > | | < < | < < | | < | | | < < < > | < | | > > | 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 | vendor ).each do |attr| attr = :"#{attr}" define_method(attr) { self[attr] } define_method(:"#{attr}=") { |v| self[attr] = v} end | < < < < < < < | < < < < < < < < < < < < < < < < < < < < | < < < < < | < < < < | | < < | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | | 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.
|
| < < < < < < < < < < < |
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.
|
| < < |
Deleted test/dir-deb-with-debconf.test.
|
| < < < < < < < < < < < < < < < < < |
Deleted test/dir-deb-with-prefix.out.
|
| < < < < < < < < < < < < < < < < < < < |
Deleted test/dir-deb-with-prefix.test.
|
| < < < < < < < < < < < < < < < < < |
Deleted test/dir-deb.out.template.
|
| < < < < < < < < < < < < < < < < < |
Deleted test/dir-deb.test.
|
| < < < < < < < < < < < < < < < < < < < < < < < |
Deleted test/dir-rpm-with-prefix.out.
|
| < < < < < < < < < < < < < < < < |
Deleted test/dir-rpm-with-prefix.test.
|
| < < < < < < < < < < < < < < < |
Deleted test/dir-rpm.out.template.
|
| < < < < < < < < < < < < < < < < |
Deleted test/dir-rpm.test.
|
| < < < < < < < < < < < < < < < < < < < < |
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.
|
| < < < < < < < < < < < < < < < < |
Deleted test/gem-deb.test.
|
| < < < < < < < < < < < < < < < < < |
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 |