Check-in [c436022fd2]
Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Comment: | Merge remote-tracking branch 'upstream/master' |
---|---|
Downloads: | Tarball | ZIP archive | SQL archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
c436022fd2426206d7959fb06f9b6dbc |
User & Date: | ben@tisdall.org.uk 2014-01-09 20:17:07 |
2014-01-20
| ||
11:34 | Merge remote-tracking branch 'upstream/master' check-in: 039c34b96e user: ben@tisdall.org.uk tags: trunk | |
2014-01-09
| ||
20:17 | Merge remote-tracking branch 'upstream/master' check-in: c436022fd2 user: ben@tisdall.org.uk tags: trunk | |
2014-01-08
| ||
20:08 | Don't put gem_bin_path in packages if there's no need. This should fix #612. check-in: b7ecd0fed7 user: jls@semicomplete.com tags: trunk | |
2013-09-25
| ||
14:07 | Merge remote-tracking branch 'upstream/master' Conflicts: templates/rpm.erb check-in: ce682e6ea9 user: astephens@drh.net tags: trunk | |
Changes to CHANGELIST.
|
| > > | > > > > > | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 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 | 1.0.1 (December 7, 2013) - deb: Correctly handle --config-files given with a leading / (Jordan Sissel) 1.0.0 (December 5, 2013) - Config file of flags is now supported. Searches for $HOME/.fpm and $PWD/.fpm. If both exist, $HOME is loaded first so $PWD can override. (Pranay Kanwar) - pkgin: Basic support for SmartOS/pkgsrc's pkgin format. (#567, Brian Akins) - cpan: catch more cases of perllocal.pod and delete them (#510, Jordan Sissel) - cpan: Correctly support module version selection (#518, Matt Sharpe) - cpan: include builddeps in PERL5LIB when running cpan tests (#500, Matt Sharpe) - cpan: Avoid old system perl modules when doing module builds (#442, #513; Matt Sharpe) - python: safer gathering of python module dependencies. - python: better handling of unicode strings in python package metadata (#575, Bruno Renié) - cpan: Support 'http_proxy' env var. (#491, Patrick Cable) - deb: --deb-user and --deb-group both default to 'root' now (#504, Pranay Kanwar) - deb: convert '>' to '>>' in deb version constraints (#503, #439, Pranay Kanwar) - deb: Warn if epoch is set. Just so you know what's going on, since the default filename doesn't include the epoch. (#502, Pranay Kanwar) - deb,rpm: --config-files is now recursive if you give it a directory. This seems to be the most expected behavior by users. (#171, #506; Pranay Kanwar) - dir: Respect -C when using path mapping (#498, #507; Pranay Kanwar) - rpm: Add --rpm-ignore-iteration-in-dependencies to let you to depend on any release (aka iteration) of the same version of a package. (#364, #508; Pranay Kanwar) - dir: Handle copying of special files when possible (#347, #511, #539, #561; Pranay Kanwar) - rpm: Don't mistake symlinks as actual directories (#521, Nathan Huff) - npm: Choose an alternate npm registry with --npm-registry (#445, #524; Matt Sharpe) - cpan: Choose an alternate cpan server with --cpan-mirror. Additionally, you can use --cpan-mirror-only to only use this mirror for metadata queries. (#524, Matt Sharpe) - deb: Fix broken --deb-changelog flag (#543, #544; Tray Torrance) - deb: When --deb-upstart is given, automatically create an upstart-sysv symlink /etc/init.d/<name> to /lib/init/upstart-job (#545, Igor Galić) - rpm: Fix bug when generating spec file listings on files with strange characters in the names. (#547, Chris Chandler) - dir: Fix bug where the new directory mapping feature would cause you not to be able to select files with '=' in the name for packaging. (#556, #554; Pranay Kanwar) - python: Fix some unicode string issues in package metadata (#575, Bruno Renié) - gem-rpm: Now respects the --gem-package-name-prefix when generating the 'rubygem(name)' provides statement (#585, Stepan Stipl) - deb: Downcase and replace underscores with dashes in 'provides' list. (#591, Eric Connell) - deb: Fix a lintian complaint about md5sums permissions (#593, Sam Crang) - cpan: Modules with 'MYMETA' files are now supported (#573, Michael Donlon) 0.4.42 (July 23, 2013) - dir: make source=destination mappings behave the same way 'rsync -a' does with respect to source and destination paths. 0.4.41 (July 17, 2013) - cpan: handle cases where modules don't specify a license |
︙ | ︙ |
Changes to Makefile.
1 2 3 4 5 6 7 8 | GEMSPEC=$(shell ls *.gemspec) VERSION=$(shell awk -F\" '/VERSION =/ { print $$2 }' lib/fpm/version.rb) NAME=$(shell awk -F\" '/spec.name/ { print $$2 }' $(GEMSPEC)) GEM=$(NAME)-$(VERSION).gem .PHONY: test test: rm -rf .yardoc | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | GEMSPEC=$(shell ls *.gemspec) VERSION=$(shell awk -F\" '/VERSION =/ { print $$2 }' lib/fpm/version.rb) NAME=$(shell awk -F\" '/spec.name/ { print $$2 }' $(GEMSPEC)) GEM=$(NAME)-$(VERSION).gem .PHONY: test test: rm -rf .yardoc sh notify-failure.sh rspec .PHONY: testloop testloop: while true; do \ $(MAKE) test; \ $(MAKE) wait-for-changes; \ done |
︙ | ︙ |
Changes to README.md.
︙ | ︙ | |||
91 92 93 94 95 96 97 98 99 100 101 102 103 104 | Sources: * gem (even autodownloaded for you) * python modules (autodownload for you) * pear (also downloads for you) * directories * rpm * deb * node packages (npm) Targets: * deb | > | 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 | Sources: * gem (even autodownloaded for you) * python modules (autodownload for you) * pear (also downloads for you) * directories * tar(.gz) archives * rpm * deb * node packages (npm) Targets: * deb |
︙ | ︙ | |||
131 132 133 134 135 136 137 138 139 140 141 142 | the [mailing list](http://groups.google.com/group/fpm-users). * If you want to send patches, best way is to fork this repo and send me a pull request. If you don't know git, I also accept diff(1) formatted patches - whatever is most comfortable for you. * Want to lurk about and see what others are doing? IRC (#fpm on irc.freenode.org) is a good place for this as is the [mailing list](http://groups.google.com/group/fpm-users) ## More Documentation [See the wiki for more docs](https://github.com/jordansissel/fpm/wiki) | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 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 | the [mailing list](http://groups.google.com/group/fpm-users). * If you want to send patches, best way is to fork this repo and send me a pull request. If you don't know git, I also accept diff(1) formatted patches - whatever is most comfortable for you. * Want to lurk about and see what others are doing? IRC (#fpm on irc.freenode.org) is a good place for this as is the [mailing list](http://groups.google.com/group/fpm-users) ### Contributing by forking from GitHub First, create a github account if you do not already have one. Log in to github and go to [the main fpm github page](https://github.com/jordansissel/fpm). At the top right, click on the button labeled "Fork". This will put a forked copy of the main fpm repo into your account. Next, clone your account's github repo of fpm. For example: $ git clone git@github.com:yourusername/fpm.git If you don't already have the bundler gem installed, install it now: $ gem install bundler Now change to the root of the fpm repo and run: $ bundle install This will install all of the dependencies required for running fpm from source. Most importantly, you should see the following output from the bundle command when it lists the fpm gem: ... Using json (1.8.1) Using fpm (0.4.42) from source at . Using hitimes (1.2.1) ... Next, run make in root of the fpm repo. If there are any problems (such as missing dependencies) you should receive an error At this point, the fpm command should run directly from the code in your cloned repo. Now simply make whatever changes you want, commit the code, and push your commit back to master. If you think your changes are ready to be merged back to the main fpm repo, you can generate a pull request on the github website for your repo and send it in for review. ## More Documentation [See the wiki for more docs](https://github.com/jordansissel/fpm/wiki) |
Changes to Vagrantfile.
︙ | ︙ | |||
16 17 18 19 20 21 22 | centos6.vm.box_url = "http://vagrant-jls.objects.dreamhost.com/Debian-6.0.7-amd64-netboot.box" end config.vm.provision :puppet do |puppet| puppet.manifests_path = "test" puppet.manifest_file = "vagrant.pp" end | > > > > | > > | 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | centos6.vm.box_url = "http://vagrant-jls.objects.dreamhost.com/Debian-6.0.7-amd64-netboot.box" end config.vm.provision :puppet do |puppet| puppet.manifests_path = "test" puppet.manifest_file = "vagrant.pp" end config.vm.define :smartos do |smartos| smartos.vm.box = "smartos-base1310-64-virtualbox-20130806.box" smartos.vm.box_url = "http://dlc-int.openindiana.org/aszeszo/vagrant/smartos-base1310-64-virtualbox-20130806.box" end end |
Changes to lib/fpm.rb.
︙ | ︙ | |||
10 11 12 13 14 15 16 | require "fpm/package/cpan" require "fpm/package/pear" require "fpm/package/empty" require "fpm/package/puppet" require "fpm/package/python" require "fpm/package/osxpkg" require "fpm/package/solaris" | > | 10 11 12 13 14 15 16 17 | require "fpm/package/cpan" require "fpm/package/pear" require "fpm/package/empty" require "fpm/package/puppet" require "fpm/package/python" require "fpm/package/osxpkg" require "fpm/package/solaris" require "fpm/package/pkgin" |
Changes to lib/fpm/command.rb.
︙ | ︙ | |||
48 49 50 51 52 53 54 | "the package type to use as input (gem, rpm, python, etc)", :attribute_name => :input_type option "-C", "CHDIR", "Change directory to here before searching for files", :attribute_name => :chdir option "--prefix", "PREFIX", "A path to prefix files with when building the target package. This may " \ | | | 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 | "the package type to use as input (gem, rpm, python, etc)", :attribute_name => :input_type option "-C", "CHDIR", "Change directory to here before searching for files", :attribute_name => :chdir option "--prefix", "PREFIX", "A path to prefix files with when building the target package. This may " \ "be necessary for all input packages. For example, the 'gem' type will " \ "prefix with your gem directory automatically." option ["-p", "--package"], "OUTPUT", "The package file path to output." option ["-f", "--force"], :flag, "Force output even if it will overwrite an " \ "existing file", :default => false option ["-n", "--name"], "NAME", "The name to give to the package" option "--verbose", :flag, "Enable verbose output" option "--debug", :flag, "Enable debug output" |
︙ | ︙ | |||
99 100 101 102 103 104 105 | :attribute_name => :replaces option "--config-files", "CONFIG_FILES", "Mark a file in the package as being a config file. This uses 'conffiles'" \ " in debs and %config in rpm. If you have multiple files to mark as " \ "configuration files, specify this flag multiple times.", :multivalued => true, :attribute_name => :config_files | | | 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 | :attribute_name => :replaces option "--config-files", "CONFIG_FILES", "Mark a file in the package as being a config file. This uses 'conffiles'" \ " in debs and %config in rpm. If you have multiple files to mark as " \ "configuration files, specify this flag multiple times.", :multivalued => true, :attribute_name => :config_files option "--directories", "DIRECTORIES", "Recursively mark a directory as being owned " \ "by the package", :multivalued => true, :attribute_name => :directories option ["-a", "--architecture"], "ARCHITECTURE", "The architecture name. Usually matches 'uname -m'. For automatic values," \ " you can use '-a all' or '-a native'. These two strings will be " \ "translated into the correct value for your platform and target package type." option ["-m", "--maintainer"], "MAINTAINER", "The maintainer of this package.", |
︙ | ︙ | |||
416 417 418 419 420 421 422 | def run(*args) @logger = Cabin::Channel.get @logger.subscribe(STDOUT) # fpm initialization files, note the order of the following array is # important, try .fpm in users home directory first and then the current # directory | | > > | > > | | 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 | def run(*args) @logger = Cabin::Channel.get @logger.subscribe(STDOUT) # fpm initialization files, note the order of the following array is # important, try .fpm in users home directory first and then the current # directory rc_files = [ ".fpm" ] rc_files << File.join(ENV["HOME"], ".fpm") if ENV["HOME"] rc_files.each do |rc_file| if File.readable? rc_file @logger.warn("Loading flags from rc file #{rc_file}") File.readlines(rc_file).each do |line| # reverse becasue 'unshift' pushes onto the left side of the array. Shellwords.shellsplit(line).reverse.each do |arg| # Put '.fpm'-file flags *before* the command line flags # so that we the CLI can override the .fpm flags ARGV.unshift(arg) end end end end super(*args) end # def run |
︙ | ︙ |
Changes to lib/fpm/package.rb.
︙ | ︙ | |||
191 192 193 194 195 196 197 | exclude pkg = klass.new pkg.cleanup_staging # purge any directories that may have been created by klass.new # copy other bits ivars = [ | | > > > > > | 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 | exclude pkg = klass.new pkg.cleanup_staging # purge any directories that may have been created by klass.new # copy other bits ivars = [ :@architecture, :@category, :@config_files, :@conflicts, :@dependencies, :@description, :@epoch, :@iteration, :@license, :@maintainer, :@name, :@provides, :@replaces, :@scripts, :@url, :@vendor, :@version, :@directories, :@staging_path ] ivars.each do |ivar| #@logger.debug("Copying ivar", :ivar => ivar, :value => instance_variable_get(ivar), #:from => self.type, :to => pkg.type) pkg.instance_variable_set(ivar, instance_variable_get(ivar)) end # Attributes are special! We do not want to remove the default values of # the destination package type unless their value is specified on the # source package object. pkg.attributes.merge!(self.attributes) pkg.converted_from(self.class) return pkg end # def convert # This method is invoked on a package when it has been covered to a new # package format. The purpose of this method is to do any extra conversion |
︙ | ︙ | |||
362 363 364 365 366 367 368 | if @attributes.include?(:prefix) installdir = staging_path(@attributes[:prefix]) else installdir = staging_path end Find.find(installdir) do |path| | | | 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 | if @attributes.include?(:prefix) installdir = staging_path(@attributes[:prefix]) else installdir = staging_path end Find.find(installdir) do |path| match_path = path.sub("#{installdir.chomp('/')}/", '') attributes[:excludes].each do |wildcard| @logger.debug("Checking path against wildcard", :path => match_path, :wildcard => wildcard) if File.fnmatch(wildcard, match_path) @logger.info("Removing excluded path", :path => match_path, :matches => wildcard) FileUtils.remove_entry_secure(path) |
︙ | ︙ |
Changes to lib/fpm/package/cpan.rb.
︙ | ︙ | |||
36 37 38 39 40 41 42 | #"me know by filing an issue: " \ #"https://github.com/jordansissel/fpm/issues" #end #require "ftw" # for http access require "net/http" require "json" | > > > | | | > > > > > > | 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 | #"me know by filing an issue: " \ #"https://github.com/jordansissel/fpm/issues" #end #require "ftw" # for http access require "net/http" require "json" if (attributes[:cpan_local_module?]) moduledir = package else result = search(package) tarball = download(result, version) moduledir = unpack(tarball) end # Read package metadata (name, version, etc) if File.exists?(File.join(moduledir, "META.json")) metadata = JSON.parse(File.read(File.join(moduledir, ("META.json")))) elsif File.exists?(File.join(moduledir, ("META.yml"))) require "yaml" metadata = YAML.load_file(File.join(moduledir, ("META.yml"))) elsif File.exists?(File.join(moduledir, "MYMETA.json")) metadata = JSON.parse(File.read(File.join(moduledir, ("MYMETA.json")))) elsif File.exists?(File.join(moduledir, ("MYMETA.yml"))) require "yaml" metadata = YAML.load_file(File.join(moduledir, ("MYMETA.yml"))) else raise FPM::InvalidPackageConfiguration, "Could not find package metadata. Checked for META.json and META.yml" end self.version = metadata["version"] self.description = metadata["abstract"] |
︙ | ︙ |
Changes to lib/fpm/package/deb.rb.
︙ | ︙ | |||
224 225 226 227 228 229 230 | self.architecture = parse.call("Architecture") self.category = parse.call("Section") self.license = parse.call("License") || self.license self.maintainer = parse.call("Maintainer") self.name = parse.call("Package") self.url = parse.call("Homepage") self.vendor = parse.call("Vendor") || self.vendor | | > > > | 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 | self.architecture = parse.call("Architecture") self.category = parse.call("Section") self.license = parse.call("License") || self.license self.maintainer = parse.call("Maintainer") self.name = parse.call("Package") self.url = parse.call("Homepage") self.vendor = parse.call("Vendor") || self.vendor with(parse.call("Provides")) do |provides_str| next if provides_str.nil? self.provides = provides_str.split(/\s*,\s*/) end # The description field is a special flower, parse it that way. # The description is the first line as a normal Description field, but also continues # on future lines indented by one space, until the end of the file. Blank # lines are marked as ' .' description = control[/^Description: .*/m].split(": ", 2).last self.description = description.gsub(/^ /, "").gsub(/^\.$/, "") |
︙ | ︙ | |||
296 297 298 299 300 301 302 303 304 305 306 307 308 309 | # unpack the data.tar.{gz,bz2,xz} from the deb package into staging_path safesystem("ar p #{package} #{datatar} " \ "| tar #{compression} -xf - -C #{staging_path}") end # def extract_files def output(output_path) output_check(output_path) # Abort if the target path already exists. # create 'debian-binary' file, required to make a valid debian package File.write(build_path("debian-binary"), "2.0\n") # If we are given --deb-shlibs but no --after-install script, we | > | 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 | # unpack the data.tar.{gz,bz2,xz} from the deb package into staging_path safesystem("ar p #{package} #{datatar} " \ "| tar #{compression} -xf - -C #{staging_path}") end # def extract_files def output(output_path) self.provides = self.provides.collect { |p| fix_provides(p) } output_check(output_path) # Abort if the target path already exists. # create 'debian-binary' file, required to make a valid debian package File.write(build_path("debian-binary"), "2.0\n") # If we are given --deb-shlibs but no --after-install script, we |
︙ | ︙ | |||
410 411 412 413 414 415 416 417 418 419 420 421 422 423 | @logger.log("Created deb package", :path => output_path) end # def output def converted_from(origin) self.dependencies = self.dependencies.collect do |dep| fix_dependency(dep) end.flatten end # def converted_from def debianize_op(op) # Operators in debian packaging are <<, <=, =, >= and >> # So any operator like < or > must be replaced {:< => "<<", :> => ">>"}[op.to_sym] or op end | > > > > | 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 | @logger.log("Created deb package", :path => output_path) end # def output def converted_from(origin) self.dependencies = self.dependencies.collect do |dep| fix_dependency(dep) end.flatten self.provides = self.provides.collect do |provides| fix_provides(provides) end.flatten end # def converted_from def debianize_op(op) # Operators in debian packaging are <<, <=, =, >= and >> # So any operator like < or > must be replaced {:< => "<<", :> => ">>"}[op.to_sym] or op end |
︙ | ︙ | |||
441 442 443 444 445 446 447 | if name =~ /[A-Z]/ @logger.warn("Downcasing dependency '#{name}' because deb packages " \ " don't work so good with uppercase names") dep = dep.gsub(name_re) { |n| n.downcase } end if dep.include?("_") | | | 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 | if name =~ /[A-Z]/ @logger.warn("Downcasing dependency '#{name}' because deb packages " \ " don't work so good with uppercase names") dep = dep.gsub(name_re) { |n| n.downcase } end if dep.include?("_") @logger.warn("Replacing dependency underscores with dashes in '#{dep}' because " \ "debs don't like underscores") dep = dep.gsub("_", "-") end # Convert gem ~> X.Y.Z to '>= X.Y.Z' and << X.Y+1.0 if dep =~ /\(~>/ name, version = dep.gsub(/[()~>]/, "").split(/ +/)[0..1] |
︙ | ︙ | |||
478 479 480 481 482 483 484 485 486 487 488 489 490 491 | name, version = m[1..2] return ["#{name} (>> #{version})"] else # otherwise the dep is probably fine return dep.rstrip end end # def fix_dependency def control_path(path=nil) @control_path ||= build_path("control") FileUtils.mkdir(@control_path) if !File.directory?(@control_path) if path.nil? return @control_path | > > > > > > > > > > > > > > > > > | 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 | name, version = m[1..2] return ["#{name} (>> #{version})"] else # otherwise the dep is probably fine return dep.rstrip end end # def fix_dependency def fix_provides(provides) name_re = /^[^ \(]+/ name = provides[name_re] if name =~ /[A-Z]/ @logger.warn("Downcasing provides '#{name}' because deb packages " \ " don't work so good with uppercase names") provides = provides.gsub(name_re) { |n| n.downcase } end if provides.include?("_") @logger.warn("Replacing 'provides' underscores with dashes in '#{provides}' because " \ "debs don't like underscores") provides = provides.gsub("_", "-") end return provides.rstrip end def control_path(path=nil) @control_path ||= build_path("control") FileUtils.mkdir(@control_path) if !File.directory?(@control_path) if path.nil? return @control_path |
︙ | ︙ | |||
571 572 573 574 575 576 577 578 579 580 581 582 583 584 | def write_conffiles return unless config_files.any? # scan all conf file paths for files and add them allconfigs = [] config_files.each do |path| cfg_path = File.expand_path(path, staging_path) begin Find.find(cfg_path) do |p| allconfigs << p.gsub("#{staging_path}/", '') if File.file? p end rescue Errno::ENOENT => e raise FPM::InvalidPackageConfiguration, | > > | 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 | def write_conffiles return unless config_files.any? # scan all conf file paths for files and add them allconfigs = [] config_files.each do |path| # Strip leading / path = path[1..-1] if path[0,1] == "/" cfg_path = File.expand_path(path, staging_path) begin Find.find(cfg_path) do |p| allconfigs << p.gsub("#{staging_path}/", '') if File.file? p end rescue Errno::ENOENT => e raise FPM::InvalidPackageConfiguration, |
︙ | ︙ | |||
627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 | if not md5_sums.empty? File.open(control_path("md5sums"), "w") do |out| md5_sums.each do |path, md5| out.puts "#{md5} #{path}" end end end end # def write_md5sums def to_s(format=nil) # Default format if nil # git_1.7.9.3-1_amd64.deb return super("NAME_FULLVERSION_ARCH.TYPE") if format.nil? return super(format) end # def to_s public(:input, :output, :architecture, :name, :prefix, :converted_from, :to_s) end # class FPM::Target::Deb | > | 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 | if not md5_sums.empty? File.open(control_path("md5sums"), "w") do |out| md5_sums.each do |path, md5| out.puts "#{md5} #{path}" end end File.chmod(0644, control_path("md5sums")) end end # def write_md5sums def to_s(format=nil) # Default format if nil # git_1.7.9.3-1_amd64.deb return super("NAME_FULLVERSION_ARCH.TYPE") if format.nil? return super(format) end # def to_s public(:input, :output, :architecture, :name, :prefix, :converted_from, :to_s) end # class FPM::Target::Deb |
Changes to lib/fpm/package/dir.rb.
︙ | ︙ | |||
39 40 41 42 43 44 45 | def input(path) chdir = attributes[:chdir] || "." # Support mapping source=dest # This mapping should work the same way 'rsync -a' does # Meaning 'rsync -a source dest' # and 'source=dest' in fpm work the same as the above rsync | | | 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 | def input(path) chdir = attributes[:chdir] || "." # Support mapping source=dest # This mapping should work the same way 'rsync -a' does # Meaning 'rsync -a source dest' # and 'source=dest' in fpm work the same as the above rsync if path =~ /.=./ && !File.exists?(chdir == '.' ? path : File.join(chdir, path)) origin, destination = path.split("=", 2) if File.directory?(origin) && origin[-1,1] == "/" chdir = chdir == '.' ? origin : File.join(chdir, origin) source = "." else origin_dir = File.dirname(origin) |
︙ | ︙ |
Changes to lib/fpm/package/gem.rb.
︙ | ︙ | |||
182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 | bin_path = File.join(staging_path, gem_bin) end args += ["--bindir", bin_path] ::FileUtils.mkdir_p(bin_path) args << gem_path safesystem(*args) end # def install_to_staging # Sanitize package name. # This prefixes the package name with 'rubygem' (but depends on the attribute # :gem_package_name_prefix def fix_name(name) return [attributes[:gem_package_name_prefix], name].join("-") end # def fix_name public(:input, :output) end # class FPM::Package::Gem | > > > > > > > > > > > > | 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 | bin_path = File.join(staging_path, gem_bin) end args += ["--bindir", bin_path] ::FileUtils.mkdir_p(bin_path) args << gem_path safesystem(*args) # Delete bin_path if it's empty, and any empty parents (#612) # Above, we mkdir_p bin_path because rubygems aborts if the parent # directory doesn't exist, for example: # ERROR: While executing gem ... (Errno::ENOENT) # No such file or directory - /tmp/something/weird/bin tmp = bin_path while ::Dir.entries(tmp).size == 2 || tmp == "/" # just [ "..", "." ] is an empty directory @logger.info("Deleting empty bin_path", :path => tmp) ::Dir.rmdir(tmp) tmp = File.dirname(tmp) end end # def install_to_staging # Sanitize package name. # This prefixes the package name with 'rubygem' (but depends on the attribute # :gem_package_name_prefix def fix_name(name) return [attributes[:gem_package_name_prefix], name].join("-") end # def fix_name public(:input, :output) end # class FPM::Package::Gem |
Changes to lib/fpm/package/pear.rb.
︙ | ︙ | |||
102 103 104 105 106 107 108 | delete_these = [".depdb", ".depdblock", ".filemap", ".lock", ".channel", "cache", "temp", "download", ".channels", ".registry"] Find.find(staging_path) do |path| if File.file?(path) @logger.info("replacing staging_path in file", :replace_in => path, :staging_path => staging_path) begin content = File.read(path).gsub(/#{Regexp.escape(staging_path)}/, "") File.write(path, content) | | | | 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 | delete_these = [".depdb", ".depdblock", ".filemap", ".lock", ".channel", "cache", "temp", "download", ".channels", ".registry"] Find.find(staging_path) do |path| if File.file?(path) @logger.info("replacing staging_path in file", :replace_in => path, :staging_path => staging_path) begin content = File.read(path).gsub(/#{Regexp.escape(staging_path)}/, "") File.write(path, content) rescue ArgumentError => e @logger.warn("error replacing staging_path in file", :replace_in => path, :error => e) end end FileUtils.rm_r(path) if delete_these.include?(File.basename(path)) end end # def input end # class FPM::Package::PEAR |
Added lib/fpm/package/pkgin.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 | class FPM::Package::Pkgin < FPM::Package def output(output_path) output_check(output_path) File.write(build_path("build-info"), `pkg_info -X pkg_install | egrep '^(MACHINE_ARCH|OPSYS|OS_VERSION|PKGTOOLS_VERSION)'`) cwd = ::Dir.pwd ::Dir.chdir(staging_path) files = [] Find.find(".") do |path| stat = File.lstat(path) next unless stat.symlink? or stat.file? files << path end ::Dir.chdir(cwd) File.write(build_path("packlist"), files.sort.join("\n")) File.write(build_path("comment"), self.description + "\n") File.write(build_path("description"), self.description + "\n") args = [ "-B", build_path("build-info"), "-c", build_path("comment"), "-d", build_path("description"), "-f", build_path("packlist"), "-I", "/opt/local", "-p", staging_path, "-U", "#{cwd}/#{name}-#{self.version}-#{iteration}.tgz" ] safesystem("pkg_create", *args) end def iteration return @iteration ? @iteration : 1 end end |
Changes to lib/fpm/package/pyfpm/get_metadata.py.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | from distutils.core import Command import os import pkg_resources try: import json except ImportError: import simplejson as json # Note, the last time I coded python daily was at Google, so it's entirely # possible some of my techniques below are outdated or bad. # If you have fixes, let me know. class get_metadata(Command): | > > > > > > > > > > > > | 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 | from distutils.core import Command import os import sys import pkg_resources try: import json except ImportError: import simplejson as json PY3 = sys.version_info[0] == 3 if PY3: def u(s): return s else: def u(s): if isinstance(u, unicode): return u return s.decode('utf-8') # Note, the last time I coded python daily was at Google, so it's entirely # possible some of my techniques below are outdated or bad. # If you have fixes, let me know. class get_metadata(Command): |
︙ | ︙ | |||
44 45 46 47 48 49 50 | return deps def run(self): data = { "name": self.distribution.get_name(), "version": self.distribution.get_version(), | | | | | 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 | return deps def run(self): data = { "name": self.distribution.get_name(), "version": self.distribution.get_version(), "author": u("%s <%s>") % ( u(self.distribution.get_author()), u(self.distribution.get_author_email()), ), "description": self.distribution.get_description(), "license": self.distribution.get_license(), "url": self.distribution.get_url(), } if self.distribution.has_ext_modules(): |
︙ | ︙ |
Changes to lib/fpm/package/python.rb.
︙ | ︙ | |||
51 52 53 54 55 56 57 | option "--install-bin", "BIN_PATH", "The path to where python scripts " \ "should be installed to." option "--install-lib", "LIB_PATH", "The path to where python libs " \ "should be installed to (default depends on your python installation). " \ "Want to what your target platform is using? Run this: " \ "python -c 'from distutils.sysconfig import get_python_lib; " \ "print get_python_lib()'" | | | | 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 | option "--install-bin", "BIN_PATH", "The path to where python scripts " \ "should be installed to." option "--install-lib", "LIB_PATH", "The path to where python libs " \ "should be installed to (default depends on your python installation). " \ "Want to what your target platform is using? Run this: " \ "python -c 'from distutils.sysconfig import get_python_lib; " \ "print get_python_lib()'" option "--install-data", "DATA_PATH", "The path to where data should be " \ "installed to. This is equivalent to 'python setup.py --install-data " \ "DATA_PATH" option "--dependencies", :flag, "Include requirements defined in setup.py" \ " as dependencies.", :default => true option "--obey-requirements-txt", :flag, "Use a requirements.txt file " \ "in the top-level directory of the python package for dependency " \ "detection.", :default => false private # Input a package. # |
︙ | ︙ |
Changes to lib/fpm/package/rpm.rb.
︙ | ︙ | |||
130 131 132 133 134 135 136 137 138 139 | name = name.gsub("[", "[\\[]") name = name.gsub("*", "[*]") name = name.gsub("?", "[?]") name = name.gsub("%", "[%]") end def rpm_file_entry(file) file = rpm_fix_name(file) return file unless attributes[:rpm_use_file_permissions?] | > > > | | | | | > | 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 | name = name.gsub("[", "[\\[]") name = name.gsub("*", "[*]") name = name.gsub("?", "[?]") name = name.gsub("%", "[%]") end def rpm_file_entry(file) original_file = file file = rpm_fix_name(file) return file unless attributes[:rpm_use_file_permissions?] # Stat the original filename in the relative staging path ::Dir.chdir(staging_path) do stat = File.stat(original_file.gsub(/\"/, '').sub(/^\//,'')) user = Etc.getpwuid(stat.uid).name group = Etc.getgrgid(stat.gid).name mode = stat.mode return sprintf("%%attr(%o, %s, %s) %s\n", mode & 4095 , user, group, file) end end # Handle any architecture naming conversions. # For example, debian calls amd64 what redhat calls x86_64, this # method fixes those types of things. def architecture |
︙ | ︙ | |||
185 186 187 188 189 190 191 | end end self.dependencies = fixed_deps # Convert 'rubygem-foo' provides values to 'rubygem(foo)' # since that's what most rpm packagers seem to do. self.provides = self.provides.collect do |provides| | < | < | > | | | | | < < < < < < < < < < < < < < | 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 | end end self.dependencies = fixed_deps # Convert 'rubygem-foo' provides values to 'rubygem(foo)' # since that's what most rpm packagers seem to do. self.provides = self.provides.collect do |provides| # Tries to match rubygem_prefix [1], gem_name [2] and version [3] if present # and return it in rubygem_prefix(gem_name) form if name=/^(#{attributes[:gem_package_name_prefix]})-([^\s]+)\s*(.*)$/.match(provides) "#{name[1]}(#{name[2]})#{name[3] ? " #{name[3]}" : ""}" else provides end end self.dependencies = self.dependencies.collect do |dependency| # Tries to match rubygem_prefix [1], gem_name [2] and version [3] if present # and return it in rubygem_prefix(gem_name) form if name=/^(#{attributes[:gem_package_name_prefix]})-([^\s]+)\s*(.*)$/.match(dependency) "#{name[1]}(#{name[2]})#{name[3] ? " #{name[3]}" : ""}" else dependency end end end # Convert != dependency as Conflict =, as rpm doesn't understand != self.dependencies = self.dependencies.select do |dep| name, op, version = dep.split(/\s+/) dep_ok = true if op == '!=' self.conflicts << "#{name} = #{version}" dep_ok = false end dep_ok end # if --ignore-iteration-in-dependencies is true convert foo = X, to # foo >= X , foo < X+1 if self.attributes[:rpm_ignore_iteration_in_dependencies?] self.dependencies = self.dependencies.collect do |dep| name, op, version = dep.split(/\s+/) if op == '=' nextversion = version.split('.').collect { |v| v.to_i } |
︙ | ︙ |
Changes to lib/fpm/util.rb.
1 2 3 4 5 6 7 8 9 | require "fpm/namespace" require "childprocess" require "ffi" # Some utility functions module FPM::Util extend FFI::Library ffi_lib FFI::Library::LIBC | | > | > | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | require "fpm/namespace" require "childprocess" require "ffi" # Some utility functions module FPM::Util extend FFI::Library ffi_lib FFI::Library::LIBC # mknod is __xmknod in glibc a wrapper around mknod to handle # various stat struct formats. See bits/stat.h in glibc source begin attach_function :mknod, :mknod, [:string, :uint, :ulong], :int rescue FFI::NotFoundError # glibc/io/xmknod.c int __xmknod (int vers, const char *path, mode_t mode, dev_t *dev) attach_function :xmknod, :__xmknod, [:int, :string, :uint, :pointer], :int end # Raised if safesystem cannot find the program to run. class ExecutableNotFound < StandardError; end # Raised if a safesystem program exits nonzero class ProcessFailed < StandardError; end |
︙ | ︙ | |||
111 112 113 114 115 116 117 | # Get the recommended 'tar' command for this platform. def tar_cmd # Rely on gnu tar for solaris and OSX. case %x{uname -s}.chomp when "SunOS" return "gtar" when "Darwin" | > | > > > > > > > > > > > > > > > > | < < < | > > | 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 | # Get the recommended 'tar' command for this platform. def tar_cmd # Rely on gnu tar for solaris and OSX. case %x{uname -s}.chomp when "SunOS" return "gtar" when "Darwin" # Try running gnutar, it was renamed(??) in homebrew to 'gtar' at some point, I guess? I don't know. ["gnutar", "gtar"].each do |tar| system("#{tar} > /dev/null 2> /dev/null") return tar unless $?.exitstatus == 127 end else return "tar" end end # def tar_cmd # Run a block with a value. # Useful in lieu of assigning variables def with(value, &block) block.call(value) end # def with # wrapper around mknod ffi calls def mknod_w(path, mode, dev) rc = -1 case %x{uname -s}.chomp when 'Linux' # bits/stat.h #define _MKNOD_VER_LINUX 0 rc = xmknod(0, path, mode, FFI::MemoryPointer.new(dev)) else rc = mknod(path, mode, dev) end rc end def copy_entry(src, dst) case File.ftype(src) when 'fifo', 'characterSpecial', 'blockSpecial', 'socket' st = File.stat(src) rc = mknod_w(dst, st.mode, st.dev) raise SystemCallError.new("mknod error", FFI.errno) if rc == -1 when 'directory' FileUtils.mkdir(dst) unless File.exists? dst else FileUtils.copy_entry(src, dst) end end end # module FPM::Util |
Changes to lib/fpm/version.rb.
1 | module FPM | | | 1 2 3 | module FPM VERSION = "1.0.1" end |
Changes to spec/fpm/package/deb_spec.rb.
︙ | ︙ | |||
116 117 118 119 120 121 122 | @original.name = "name" @original.version = "123" @original.iteration = "100" @original.epoch = "5" @original.architecture = "all" @original.dependencies << "something > 10" @original.dependencies << "hello >= 20" | | > > > | 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 | @original.name = "name" @original.version = "123" @original.iteration = "100" @original.epoch = "5" @original.architecture = "all" @original.dependencies << "something > 10" @original.dependencies << "hello >= 20" @original.provides << "#{@original.name} = #{@original.version}" # Test to cover PR#591 (fix provides names) @original.provides << "Some-SILLY_name" @original.conflicts = ["foo < 123"] @original.attributes[:deb_breaks] = ["baz < 123"] @original.attributes[:deb_build_depends_given?] = true @original.attributes[:deb_build_depends] ||= [] @original.attributes[:deb_build_depends] << 'something-else > 0.0.0' |
︙ | ︙ | |||
165 166 167 168 169 170 171 | @original.dependencies.each do |dep| insist { @input.dependencies }.include?(dep) end end it "should ignore versions and conditions in 'provides' (#280)" do # Provides is an array because rpm supports multiple 'provides' | | > > > > | 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 | @original.dependencies.each do |dep| insist { @input.dependencies }.include?(dep) end end it "should ignore versions and conditions in 'provides' (#280)" do # Provides is an array because rpm supports multiple 'provides' insist { @input.provides }.include?(@original.name) end it "should fix capitalization and underscores-to-dashes (#591)" do insist { @input.provides }.include?("some-silly-name") end end # package attributes # This section mainly just verifies that 'dpkg-deb' can parse the package. context "when read with dpkg", :if => have_dpkg_deb do def dpkg_field(field) return %x{dpkg-deb -f #{@target} #{field}}.chomp |
︙ | ︙ |
Changes to spec/fpm/package/dir_spec.rb.
︙ | ︙ | |||
93 94 95 96 97 98 99 | Dir.mkdir(File.join(tmpdir, "a")) File.write(File.join(tmpdir, "a", "b"), "hello world") subject.input(File.join(tmpdir, input)) subject.output(output) insist { File }.exist?(File.join(output, expected_file)) end end | > > > > > > | > > > > > > > > > > > | 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 | Dir.mkdir(File.join(tmpdir, "a")) File.write(File.join(tmpdir, "a", "b"), "hello world") subject.input(File.join(tmpdir, input)) subject.output(output) insist { File }.exist?(File.join(output, expected_file)) end end it "should not map existing paths with = in them" do File.write(File.join(tmpdir, "a=b"), "hello world") subject.input(File.join(tmpdir, "a=b")) subject.output(output) insist { File }.exist?(File.join(output, tmpdir, "a=b")) end it "should not map existing paths with = in them and obey :chdir and :prefix attributes" do Dir.mkdir(File.join(tmpdir, "a")) File.write(File.join(tmpdir,"a", "a=b"), "hello world") subject.attributes[:chdir] = tmpdir subject.attributes[:prefix] = "/foo" subject.input(File.join("a", "a=b")) subject.output(output) insist { File }.exist?(File.join(output, "foo", "a", "a=b")) end end end # describe FPM::Package::Dir |
Changes to spec/fpm/package/rpm_spec.rb.
︙ | ︙ | |||
330 331 332 333 334 335 336 337 338 339 340 341 342 343 | Dir.mkdir(subject.staging_path("/example")) File.write(subject.staging_path("/example/%name%"), "Hello") subject.output(@target) rpm = ::RPM::File.new(@target) insist { rpm.files } == [ "/example/%name%" ] end it "should permit spaces in filenames (issue #164)" do File.write(subject.staging_path("file with space"), "Hello") # This will raise an exception if rpmbuild fails. subject.output(@target) rpm = ::RPM::File.new(@target) | > > > > > > > > > > > > | 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 | Dir.mkdir(subject.staging_path("/example")) File.write(subject.staging_path("/example/%name%"), "Hello") subject.output(@target) rpm = ::RPM::File.new(@target) insist { rpm.files } == [ "/example/%name%" ] end it "should escape '%' characters in filenames while preserving permissions" do Dir.mkdir(subject.staging_path("/example")) File.write(subject.staging_path("/example/%name%"), "Hello") File.chmod(01777,subject.staging_path("/example/%name%")) subject.attributes[:rpm_use_file_permissions?] = true subject.output(@target) rpm = ::RPM::File.new(@target) insist { rpm.files } == [ "/example/%name%" ] insist { `rpm -qlv -p #{@target}`.chomp.split.first } == "-rwxrwxrwt" end it "should permit spaces in filenames (issue #164)" do File.write(subject.staging_path("file with space"), "Hello") # This will raise an exception if rpmbuild fails. subject.output(@target) rpm = ::RPM::File.new(@target) |
︙ | ︙ |
Added spec/fpm/package_convert_spec.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 | require "spec_setup" require "fpm" # local describe "FPM::Package#convert" do let(:gem_package_name_prefix) { 'rubygem19' } let(:default_rpm_compression) { 'gzip' } subject do source = FPM::Package::Gem.new prefix = source.attributes[:gem_package_name_prefix ] = 'rubygem19' name = source.name = "whatever" version = source.version = "1.0" source.provides << "#{prefix}-#{name} = #{version}" source.convert(FPM::Package::RPM) end it "applies the default attributes for target format" do insist { subject.attributes[:rpm_compression] } == default_rpm_compression end it "remembers attributes applied to source" do insist { subject.attributes[:gem_package_name_prefix] } == gem_package_name_prefix end it "should list provides matching the gem_package_name_prefix (#585)" do insist { subject.provides }.include?("rubygem19(whatever) = 1.0") end end |
Changes to templates/rpm.erb.
1 2 | # Hello packaging friend! # | | | 1 2 3 4 5 6 7 8 9 10 | # Hello packaging friend! # # If you find yourself using this 'fpm --edit' feature frequently, it is # a sign that fpm is missing a feature! I welcome your feature requests! # Please visit the following URL and ask for a feature that helps you never # need to edit this file again! :) # https://github.com/jordansissel/fpm/issues # ------------------------------------------------------------------------ # Disable the stupid stuff rpm distros include in the build process by default: |
︙ | ︙ |