Check-in [aa9ee22bad]
Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Comment: | Pass other scripts through |
---|---|
Downloads: | Tarball | ZIP archive | SQL archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
aa9ee22badfc1871fe633e109333fc98 |
User & Date: | djhaskin987@gmail.com 2014-09-19 13:10:51 |
2014-09-19
| ||
13:23 | Merge into scriptmap in the name of elegance check-in: 7c35c9bf18 user: djhaskin987@gmail.com tags: trunk | |
13:10 | Pass other scripts through check-in: aa9ee22bad user: djhaskin987@gmail.com tags: trunk | |
12:53 | Grammar, contributions check-in: 7934760d27 user: djhaskin987@gmail.com tags: trunk | |
2014-09-18
| ||
17:44 | Merge pull request #694 from vStone/bugfix/fix-python-tests-python3 Fixes 2 python issues within the tests check-in: 8d82a3922e user: jls@semicomplete.com tags: trunk | |
Changes to .travis.yml.
1 2 3 4 5 6 7 8 9 10 | language: ruby rvm: - 1.8.7 - 1.9.2 - 1.9.3 - 2.0.0 script: rspec before_install: - sudo apt-get update -qq - sudo apt-get install -qq rpm | > | 1 2 3 4 5 6 7 8 9 10 11 | language: ruby rvm: - 1.8.7 - 1.9.2 - 1.9.3 - 2.0.0 script: rspec before_install: - sudo apt-get update -qq - sudo apt-get install -qq rpm - sudo apt-get install -qq lintian |
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 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 | 1.2.0 (July 25, 2014) - rpm: Add --rpm-verifyscript for adding a custom rpm verify script to your package. (Remi Hakim) - Allow the -p flag to target a directory for writing the output package (#656, Jordan Sissel) - Add --debug-workspace which skips any workspace cleanup to let users debug things if they break. (#720, #734; Jordan Sissel) - rpm: Add --rpm-attr for controlling attribute settings per file. This setting will likely be removed in the future once rpmbuild is no longer needed. (#719) - deb: Add --deb-meta-file to add arbitrary files to the control dir (#599, Dan Brown) - deb: Add --deb-interest and --deb-activate for adding package triggers (#595, Dan Brown) - cpan: Fix small bug in handling empty metadata fields (#712, Mathias Lafeldt) - rpm: Fix bug when specifying both --architecture and --rpm-os (#707, #716; Alan Ivey) - gem: Fix bug where --gem-version-bins is given but package has no bins (#688, Jan Vansteenkiste) - deb: Set permissions correct on the package's internals. Makes lintian happier. (Jan Vansteenkiste) - rpm: rpmbuild's _tmppath now respects --workdir (#714, Jordan Sissel) - gem/rpm: Add --rpm-verbatim-gem-dependencies to use old-style (fpm 0.4.x) rpm gem dependencies (#724, Jordan Sissel) - gem/rpm: Fix bug for gem pessimistic constraints when converting to rpm (Tom Duckering) - python: Fix small bug with pip invocations (#727, Dane Knecht) 1.1.0 (April 23, 2014) - New package type: zip, for converting to and from zip files (Jordan Sissel) - New package type: sh, a self-extracting package installation shell archive. (#651, Chris Gerber) - 'fpm --version' will now emit the version of fpm. - rpm: supports packaging fifo files (Adam Stephens) - deb: Add --deb-use-file-permissions (Adam Stephens) - cpan: Improve how fpm tries to find cpan artifacts for download (#614, Tim Nicholas) - gem: Add --gem-disable-dependency for removing one or more specific rubygem dependencies from the automatically-generated list (#598, Derek Olsen) - python: Add --python-scripts-executable for setting a custom interpreter to use for the hashbang line at the top of may python package scripts. (#628, Vladimir Rutsky) - Allow absolute paths with --directories even when --prefix is used (Vladimir Rutsky) - dir: Now correctly identifies hardlinked files and creates a package correctly with that knowledge (#365, #623, #659; Vladimir Rutsky) - rpm: Add --rpm-auto-add-exclude-directories for excluding directories from the --rpm-auto-add-directories behavior (#640, Vladimir Rutsky) - general: --config-files now accepts directories and will recursively mark any files within as config files inside the package (#642, Vladimir Rutsky) - general: If you specify a --config-files path that doesn't exist, you will now get an error. (#654, Alan Franzoni) - python: Support --python-pypi when using --python-pip (#652, David Lindquist) - deb: Tests now try to make packages ensure we don't upset lintian (#648, Sam Crang) - rpm: Fix architecture targeting (#676, Rob Kinyon) - rpm: Allow --rpm-user and --rpm-group to override the user/group even if --rpm-use-file-permissions is enabled. (#679, Jordan Sissel) - gem: Add --gem-version-bins for appending the gem version to the file name of executable scripts a rubygem may install. (Jan Vansteenkiste) - python: Attempt to provide better error messages for known issues in python environments (#664, Jordan Sissel) 1.0.2 (January 10, 2013) - rpm: No longer converts - to _ in dependency strings (#603, Bulat Shakirzyanov) - Handle Darwin/OSX tar invocations (now tries 'gnutar' and 'gtar'). (Jordan Sissel) - Process $HOME/.fpm, and $PWD/.fpm in the correct order and allow CLI flags to override fpm config file settings. (#615, Jordan Sissel) - Don't leave empty gem bin paths in packages that don't need them (#612, Jordan Sissel) - deb: Make --deb-compression=gz work correctly (#616, #617; Evan Krall, Jason Yan) 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 README.md.
|
| | | 1 2 3 4 5 6 7 8 | # Effing Package Management ## Preface Package maintainers work hard and take a lot of shit. You can't please everyone. So, if you're a maintainer: Thanks for maintaining packages! ## What is fpm? |
︙ | ︙ | |||
58 59 60 61 62 63 64 65 66 67 68 69 70 71 | The goal of FPM is to be able to easily build platform-native packages. * Creating packages easily (deb, rpm, etc) * Tweaking existing packages (removing files, changing metadata/dependencies) * Stripping pre/post/maintainer scripts from packages ## Get with the download You can install fpm with gem: gem install fpm Building a package named "awesome" might look something like this: | > > > > > > > > > | 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 | The goal of FPM is to be able to easily build platform-native packages. * Creating packages easily (deb, rpm, etc) * Tweaking existing packages (removing files, changing metadata/dependencies) * Stripping pre/post/maintainer scripts from packages ## System packages You will need the ruby-dev and gcc packages for your system. These can be installed with the below apt-get install ruby-dev gcc yum install ruby-devel gcc Additional packages will be required depending on the source and target package types (rpmbuild for rpm, etc.). FPM will show the commands that are required which you must map to your distribution's package names. ## Get with the download You can install fpm with gem: gem install fpm Building a package named "awesome" might look something like this: |
︙ | ︙ | |||
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 | > | 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 | 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) | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 | 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. ##Problems running bundle install? If you are installing on Mac OS 10.9 (Mavericks) you will need to make sure that you have the standalone command line tools seperate from Xcode: $ xcode-select --install Finally, click the install button on the prompt that appears. ## More Documentation [See the wiki for more docs](https://github.com/jordansissel/fpm/wiki) |
Changes to Vagrantfile.
1 2 3 4 5 6 7 8 9 10 | # -*- mode: ruby -*- # vi: set ft=ruby : Vagrant.configure("2") do |config| # All Vagrant configuration is done here. The most common configuration # options are documented and commented below. For a complete reference, # please see the online documentation at vagrantup.com. config.vm.define "centos6" do |centos6| centos6.vm.box = "centos6" | | | | > > | > > > > > > > > < < < | < < | 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 | # -*- mode: ruby -*- # vi: set ft=ruby : Vagrant.configure("2") do |config| # All Vagrant configuration is done here. The most common configuration # options are documented and commented below. For a complete reference, # please see the online documentation at vagrantup.com. config.vm.define "centos6" do |centos6| centos6.vm.box = "centos6" centos6.vm.box_url = "http://puppet-vagrant-boxes.puppetlabs.com/centos-65-x64-virtualbox-puppet.box" end config.vm.define "debian6" do |debian6| debian6.vm.box = "debian6" debian6.vm.box_url = "http://puppet-vagrant-boxes.puppetlabs.com/debian-607-x64-vbox4210.box" end config.vm.define "debian7" do |debian7| debian7.vm.box = "debian7" debian7.vm.box_url = "http://puppet-vagrant-boxes.puppetlabs.com/debian-73-x64-virtualbox-puppet.box" 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 config.vm.provision :puppet do |puppet| puppet.manifests_path = "test" puppet.manifest_file = "vagrant.pp" end end |
Added examples/fpm-with-system-ruby/Makefile.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 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 | # # feel free to change these to whatever makes sense # # debian package we rely on RUBY_PACKAGE=ruby # and the executable that comes from it RUBY_BIN=/usr/bin/ruby # the version we name the deb VERSION=1.1.0 # where to get the sauce GIT_URL=https://github.com/jordansissel/fpm.git # the tag we checkout to build from TAG_SPEC=refs/tags/v$(VERSION) CHECKOUT_DIR=fpm-checkout BUILD_DIR=build LIB_DIR=$(BUILD_DIR)/usr/lib/fpm BIN_DIR=$(BUILD_DIR)/usr/bin GEM_PATH:=$(shell readlink -f .)/build/gem FPM_BIN=$(BIN_DIR)/fpm BUNDLE_BIN=$(GEM_PATH)/bin/bundle BUNDLE_CMD=$(RUBY_CMD) $(BUNDLE_BIN) FPM_CMD=$(FPM_BIN) GEM_CMD=$(RUBY_BIN) -S gem .PHONY: clean clean: rm -rf $(CHECKOUT_DIR) rm -rf $(BUILD_DIR) rm -f fpm*.deb $(CHECKOUT_DIR): rm -rf $(CHECKOUT_DIR) git clone $(GIT_URL) $(CHECKOUT_DIR) --depth 1 cd $(CHECKOUT_DIR) && git fetch && git checkout $(TAG_SPEC) $(BUNDLE_BIN): $(GEM_CMD) install bundler --install-dir=$(GEM_PATH) --no-ri --no-rdoc $(FPM_BIN): mkdir --parents $(BIN_DIR) # Couldn't think of a nice way to do this, so here is this code turd echo "#! $(RUBY_BIN)" > $(FPM_BIN) echo 'load File.dirname($$0) + "/../lib/fpm/bundle/bundler/setup.rb"' >> $(FPM_BIN) echo 'require "fpm"' >> $(FPM_BIN) echo 'require "fpm/command"' >> $(FPM_BIN) echo 'exit(FPM::Command.run || 0)' >> $(FPM_BIN) chmod +x $(FPM_BIN) .PHONY: install install: $(CHECKOUT_DIR) $(BUNDLE_BIN) $(FPM_BIN) mkdir --parents $(LIB_DIR) cd $(CHECKOUT_DIR) && GEM_PATH=$(GEM_PATH) $(BUNDLE_CMD) install --without=development --standalone cd $(CHECKOUT_DIR) && gem build fpm.gemspec tar -xf $(CHECKOUT_DIR)/fpm*gem -C $(BUILD_DIR) tar --touch -xf $(BUILD_DIR)/data.tar.gz -C $(LIB_DIR) cp -r $(CHECKOUT_DIR)/bundle $(LIB_DIR)/bundle .PHONY: package package: install $(FPM_BIN) -s dir -t deb -n fpm -d $(RUBY_PACKAGE) -v $(VERSION) -C $(BUILD_DIR) usr |
Added examples/fpm-with-system-ruby/README.md.
> > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | # About - build and install dependency on a ruby1.9 of some kind - does not need root to package - has its own GEM_DIR to keep its dependencies isolated - installation does not install any gems in to your ruby environment - installs in to standard locations /usr/{bin,lib}/fpm - doesn't depend on having fpm installed for packaging to work # Dependencies - build-essential (perhaps more, but basically the standard packages you need for deb packaging) - ruby and ruby-dev # Usage - $ cd examples/fpm-with-system-ruby && make package |
Changes to fpm.gemspec.
︙ | ︙ | |||
27 28 29 30 31 32 33 | spec.add_dependency("cabin", ">= 0.6.0") # license: Apache 2 # For backports to older rubies # https://github.com/marcandre/backports spec.add_dependency("backports", ">= 2.6.2") # license: MIT # For reading and writing rpms | | < < < | < | 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 | spec.add_dependency("cabin", ">= 0.6.0") # license: Apache 2 # For backports to older rubies # https://github.com/marcandre/backports spec.add_dependency("backports", ">= 2.6.2") # license: MIT # For reading and writing rpms spec.add_dependency("arr-pm", "~> 0.0.9") # license: Apache 2 # For command-line flag support # https://github.com/mdub/clamp/blob/master/README.markdown spec.add_dependency("clamp", "~> 0.6") # license: MIT # For starting external processes across various ruby interpreters spec.add_dependency("childprocess") # license: ??? # For calling functions in dynamic libraries spec.add_dependency("ffi") # license: GPL3/LGPL3 spec.add_development_dependency("rspec", "~> 3.0.0") # license: MIT (according to wikipedia) spec.add_development_dependency("insist", "~> 0.0.5") # license: ??? spec.add_development_dependency("pry") spec.add_development_dependency("stud") spec.files = files spec.require_paths << "lib" spec.bindir = "bin" spec.executables << "fpm" spec.author = "Jordan Sissel" spec.email = "jls@semicomplete.com" spec.homepage = "https://github.com/jordansissel/fpm" end |
Changes to lib/fpm/command.rb.
︙ | ︙ | |||
56 57 58 59 60 61 62 63 64 65 66 67 68 69 | "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" option ["-v", "--version"], "VERSION", "The version to give to the package", :default => 1.0 option "--iteration", "ITERATION", "The iteration to give to the package. RPM calls this the 'release'. " \ "FreeBSD calls it 'PORTREVISION'. Debian calls this 'debian_revision'" option "--epoch", "EPOCH", "The epoch value for this package. RPM and Debian calls this 'epoch'. " \ | > > > | 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 | "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" option "--debug-workspace", :flag, "Keep any file workspaces around for " \ "debugging. This will disable automatic cleanup of package staging and " \ "build paths. It will also print which directories are available." option ["-v", "--version"], "VERSION", "The version to give to the package", :default => 1.0 option "--iteration", "ITERATION", "The iteration to give to the package. RPM calls this the 'release'. " \ "FreeBSD calls it 'PORTREVISION'. Debian calls this 'debian_revision'" option "--epoch", "EPOCH", "The epoch value for this package. RPM and Debian calls this 'epoch'. " \ |
︙ | ︙ | |||
97 98 99 100 101 102 103 | "Other packages/versions this package replaces. This flag can be " \ "specified multiple times.", :multivalued => true, :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 " \ | | > | | 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 | "Other packages/versions this package replaces. This flag can be " \ "specified multiple times.", :multivalued => true, :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. If argument is " \ "directory all files inside it will be recursively marked as config files.", :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.", |
︙ | ︙ | |||
203 204 205 206 207 208 209 | "the provided value. Implies --template-scripts", :multivalued => true do |kv| @template_scripts = true next kv.split("=", 2) end option "--workdir", "WORKDIR", | | | | 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 | "the provided value. Implies --template-scripts", :multivalued => true do |kv| @template_scripts = true next kv.split("=", 2) end option "--workdir", "WORKDIR", "The directory you want fpm to do its work in, where 'work' is any file " \ "copying, downloading, etc. Roughly any scratch space fpm needs to build " \ "your package.", :default => Dir.tmpdir parameter "[ARGS] ...", "Inputs to the source package type. For the 'dir' type, this is the files" \ " and directories you want to include in the package. For others, like " \ "'gem', it specifies the packages to download and use as the gem input", :attribute_name => :args |
︙ | ︙ | |||
230 231 232 233 234 235 236 237 238 239 240 241 242 243 | @dependencies = [] @config_files = [] @directories = [] end # def initialize # Execute this command. See Clamp::Command#execute and Clamp's documentation def execute @logger.level = :warn if (stray_flags = args.grep(/^-/); stray_flags.any?) @logger.warn("All flags should be before the first argument " \ "(stray flags found: #{stray_flags}") end | > > > > > > | 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 | @dependencies = [] @config_files = [] @directories = [] end # def initialize # Execute this command. See Clamp::Command#execute and Clamp's documentation def execute # Short-circuit if someone simply runs `fpm --version` if ARGV == [ "--version" ] puts FPM::VERSION return 0 end @logger.level = :warn if (stray_flags = args.grep(/^-/); stray_flags.any?) @logger.warn("All flags should be before the first argument " \ "(stray flags found: #{stray_flags}") end |
︙ | ︙ | |||
352 353 354 355 356 357 358 359 360 361 362 363 364 365 | input.conflicts += conflicts input.dependencies += dependencies input.provides += provides input.replaces += replaces input.config_files += config_files input.directories += directories script_errors = [] setscript = proc do |scriptname| # 'self.send(scriptname) == self.before_install == --before-install # Gets the path to the script path = self.send(scriptname) # Skip scripts not set | > > > > > > > > > > | 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 | input.conflicts += conflicts input.dependencies += dependencies input.provides += provides input.replaces += replaces input.config_files += config_files input.directories += directories h = {} attrs.each do | e | s = e.split(':', 2) h[s.last] = s.first end input.attrs = h script_errors = [] setscript = proc do |scriptname| # 'self.send(scriptname) == self.before_install == --before-install # Gets the path to the script path = self.send(scriptname) # Skip scripts not set |
︙ | ︙ | |||
400 401 402 403 404 405 406 407 | template_value_list.each do |key, value| (class << output; self; end).send(:define_method, key) { value } end end # Write the output somewhere, package can be nil if no --package is specified, # and that's OK. begin | > > > > > > > > > | > > > > > > > > > > > > | | > | > > | > > | | 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 | template_value_list.each do |key, value| (class << output; self; end).send(:define_method, key) { value } end end # Write the output somewhere, package can be nil if no --package is specified, # and that's OK. # If the package output (-p flag) is a directory, write to the default file name # but inside that directory. if ! package.nil? && File.directory?(package) package_file = File.join(package, output.to_s) else package_file = output.to_s(package) end begin output.output(package_file) rescue FPM::Package::FileAlreadyExists => e @logger.fatal(e.message) return 1 rescue FPM::Package::ParentDirectoryMissing => e @logger.fatal(e.message) return 1 end @logger.log("Created package", :path => package_file) return 0 rescue FPM::Util::ExecutableNotFound => e @logger.error("Need executable '#{e}' to convert #{input_type} to #{output_type}") return 1 rescue FPM::InvalidPackageConfiguration => e @logger.error("Invalid package configuration: #{e}") return 1 rescue FPM::Package::InvalidArgument => e @logger.error("Invalid package argument: #{e}") return 1 rescue FPM::Util::ProcessFailed => e @logger.error("Process failed: #{e}") return 1 ensure if debug_workspace? # only emit them if they have files [input, output].each do |plugin| next if plugin.nil? [:staging_path, :build_path].each do |pathtype| path = plugin.send(pathtype) next unless Dir.open(path).to_a.size > 2 @logger.log("plugin directory", :plugin => plugin.type, :pathtype => pathtype, :path => path) end end else input.cleanup unless input.nil? output.cleanup unless output.nil? end end # def execute 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.
︙ | ︙ | |||
107 108 109 110 111 112 113 114 115 116 117 118 119 120 | attr_accessor :directories # 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 = Cabin::Channel.get # Attributes for this specific package @attributes = {} | > > | 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 | attr_accessor :directories # Any other attributes specific to this package. # This is where you'd put rpm, deb, or other specific attributes. attr_accessor :attributes attr_accessor :attrs private def initialize @logger = Cabin::Channel.get # Attributes for this specific package @attributes = {} |
︙ | ︙ | |||
168 169 170 171 172 173 174 175 176 177 178 179 180 181 | @provides = [] @conflicts = [] @replaces = [] @dependencies = [] @scripts = {} @config_files = [] @directories = [] staging_path build_path end # def initialize # Get the 'type' for this instance. # | > | 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 | @provides = [] @conflicts = [] @replaces = [] @dependencies = [] @scripts = {} @config_files = [] @directories = [] @attrs = {} staging_path build_path end # def initialize # Get the 'type' for this instance. # |
︙ | ︙ | |||
194 195 196 197 198 199 200 | 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, | | | 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 | 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, :@attrs ] 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 |
︙ | ︙ | |||
367 368 369 370 371 372 373 | if @attributes.include?(:prefix) installdir = staging_path(@attributes[:prefix]) else installdir = staging_path end Find.find(installdir) do |path| | | | 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 | 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) |
︙ | ︙ | |||
515 516 517 518 519 520 521 | # General public API public(:type, :initialize, :convert, :input, :output, :to_s, :cleanup, :files, :version, :script, :provides=) # Package internal public api public(:cleanup_staging, :cleanup_build, :staging_path, :converted_from, | | | 518 519 520 521 522 523 524 525 526 | # General public API public(:type, :initialize, :convert, :input, :output, :to_s, :cleanup, :files, :version, :script, :provides=) # Package internal public api public(:cleanup_staging, :cleanup_build, :staging_path, :converted_from, :edit_file, :build_path) end # class FPM::Package |
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 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 | #"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"] self.license = case metadata["license"] when Array; metadata["license"].first when nil; "unknown" else; metadata["license"] end unless metadata["distribution"].nil? @logger.info("Setting package name from 'distribution'", :distribution => metadata["distribution"]) self.name = fix_name(metadata["distribution"]) else @logger.info("Setting package name from 'name'", :name => metadata["name"]) self.name = fix_name(metadata["name"]) end # author is not always set or it may be a string instead of an array self.vendor = case metadata["author"] when String; metadata["author"] when Array; metadata["author"].join(", ") else raise FPM::InvalidPackageConfiguration, "Unexpected CPAN 'author' field type: #{metadata["author"].class}. This is a bug." end if metadata.include?("author") self.url = metadata["resources"]["homepage"] rescue "unknown" # TODO(sissel): figure out if this perl module compiles anything # and set the architecture appropriately. self.architecture = "all" # Install any build/configure dependencies with cpanm. # We'll install to a temporary directory. @logger.info("Installing any build or configure dependencies") cpanm_flags = ["-L", build_path("cpan"), moduledir] cpanm_flags += ["-n"] if attributes[:cpan_test?] cpanm_flags += ["--mirror", "#{attributes[:cpan_mirror]}"] if !attributes[:cpan_mirror].nil? cpanm_flags += ["--mirror-only"] if attributes[:cpan_mirror_only?] && !attributes[:cpan_mirror].nil? safesystem(attributes[:cpan_cpanm_bin], *cpanm_flags) if !attributes[:no_auto_depends?] unless metadata["requires"].nil? metadata["requires"].each do |dep_name, version| # Special case for representing perl core as a version. if dep_name == "perl" self.dependencies << "#{dep_name} >= #{version}" next end dep = search(dep_name) |
︙ | ︙ | |||
229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 | safesystem("tar", *args) return directory end def download(metadata, cpan_version=nil) distribution = metadata["distribution"] author = metadata["author"] @logger.info("Downloading perl module", :distribution => distribution, :version => cpan_version) # default to latest versionunless we specify one if cpan_version.nil? self.version = metadata["version"] else if metadata["version"] =~ /^v\d/ self.version = "v#{cpan_version}" else self.version = cpan_version end end | > | > > > > > > > > > > > > > > > > > > | | 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 | safesystem("tar", *args) return directory end def download(metadata, cpan_version=nil) distribution = metadata["distribution"] author = metadata["author"] @logger.info("Downloading perl module", :distribution => distribution, :version => cpan_version) # default to latest versionunless we specify one if cpan_version.nil? self.version = metadata["version"] else if metadata["version"] =~ /^v\d/ self.version = "v#{cpan_version}" else self.version = cpan_version end end metacpan_release_url = "http://api.metacpan.org/v0/release/#{author}/#{distribution}-#{self.version}" begin release_response = httpfetch(metacpan_release_url) rescue Net::HTTPServerException => e @logger.error("metacpan release query failed.", :error => e.message, :module => package, :url => metacpan_release_url) raise FPM::InvalidPackageConfiguration, "metacpan release query failed" end data = release_response.body release_metadata = JSON.parse(data) archive = release_metadata["archive"] # should probably be basepathed from the url tarball = File.basename(archive) url_base = "http://www.cpan.org/" url_base = "#{attributes[:cpan_mirror]}" if !attributes[:cpan_mirror].nil? #url = "http://www.cpan.org/CPAN/authors/id/#{author[0,1]}/#{author[0,2]}/#{author}/#{tarball}" url = "#{url_base}/authors/id/#{author[0,1]}/#{author[0,2]}/#{author}/#{archive}" @logger.debug("Fetching perl module", :url => url) begin response = httpfetch(url) rescue Net::HTTPServerException => e #@logger.error("Download failed", :error => response.status_line, #:url => url) |
︙ | ︙ |
Changes to lib/fpm/package/deb.rb.
︙ | ︙ | |||
37 38 39 40 41 42 43 | option "--pre-depends", "DEPENDENCY", "Add DEPENDENCY as a Pre-Depends" do |dep| @pre_depends ||= [] @pre_depends << dep end option "--compression", "COMPRESSION", "The compression type to use, must " \ | | | 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 | option "--pre-depends", "DEPENDENCY", "Add DEPENDENCY as a Pre-Depends" do |dep| @pre_depends ||= [] @pre_depends << dep end option "--compression", "COMPRESSION", "The compression type to use, must " \ "be one of #{COMPRESSION_TYPES.join(", ")}.", :default => "gz" do |value| if !COMPRESSION_TYPES.include?(value) raise ArgumentError, "deb compression value of '#{value}' is invalid. " \ "Must be one of #{COMPRESSION_TYPES.join(", ")}" end value end |
︙ | ︙ | |||
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 | "automatically" do |value| value.to_i end option "--priority", "PRIORITY", "The debian package 'priority' value.", :default => "extra" option "--user", "USER", "The owner of files in this package", :default => 'root' option "--group", "GROUP", "The group owner of files in this package", :default => 'root' option "--changelog", "FILEPATH", "Add FILEPATH as debian changelog" do |file| File.expand_path(file) end option "--recommends", "PACKAGE", "Add PACKAGE to Recommends" do |pkg| @recommends ||= [] @recommends << pkg next @recommends end option "--suggests", "PACKAGE", "Add PACKAGE to Suggests" do |pkg| @suggests ||= [] @suggests << pkg next @suggests end option "--field", "'FIELD: VALUE'", "Add custom field to the control file" do |fv| @custom_fields ||= {} field, value = fv.split(/: */, 2) @custom_fields[field] = value next @custom_fields end | > > > > > > > > > > > > > > > > > > > > > | 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 | "automatically" do |value| value.to_i end option "--priority", "PRIORITY", "The debian package 'priority' value.", :default => "extra" option "--use-file-permissions", :flag, "Use existing file permissions when defining ownership and modes" option "--user", "USER", "The owner of files in this package", :default => 'root' option "--group", "GROUP", "The group owner of files in this package", :default => 'root' option "--changelog", "FILEPATH", "Add FILEPATH as debian changelog" do |file| File.expand_path(file) end option "--recommends", "PACKAGE", "Add PACKAGE to Recommends" do |pkg| @recommends ||= [] @recommends << pkg next @recommends end option "--suggests", "PACKAGE", "Add PACKAGE to Suggests" do |pkg| @suggests ||= [] @suggests << pkg next @suggests end option "--meta-file", "FILEPATH", "Add FILEPATH to DEBIAN directory" do |file| @meta_files ||= [] @meta_files << File.expand_path(file) next @meta_files end option "--interest", "EVENT", "Package is interested in EVENT trigger" do |event| @interested_triggers ||= [] @interested_triggers << event next @interested_triggers end option "--activate", "EVENT", "Package activates EVENT trigger" do |event| @activated_triggers ||= [] @activated_triggers << event next @activated_triggers end option "--field", "'FIELD: VALUE'", "Add custom field to the control file" do |fv| @custom_fields ||= {} field, value = fv.split(/: */, 2) @custom_fields[field] = value next @custom_fields end |
︙ | ︙ | |||
221 222 223 224 225 226 227 | 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 | | > > > | 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 | 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(/^\.$/, "") |
︙ | ︙ | |||
293 294 295 296 297 298 299 300 301 302 303 304 305 306 | # 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 | > | 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 | # 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 |
︙ | ︙ | |||
335 336 337 338 339 340 341 | end end write_control_tarball # Tar up the staging_path into data.tar.{compression type} case self.attributes[:deb_compression] | | < < < < < < < < < < < < < < < < < | 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 | end end write_control_tarball # Tar up the staging_path into data.tar.{compression type} case self.attributes[:deb_compression] when "gz", nil datatar = build_path("data.tar.gz") compression = "-z" when "bzip2" datatar = build_path("data.tar.bz2") compression = "-j" when "xz" datatar = build_path("data.tar.xz") compression = "-J" else raise FPM::InvalidPackageConfiguration, "Unknown compression type '#{self.attributes[:deb_compression]}'" end if attributes[:deb_changelog] dest_changelog = File.join(staging_path, "usr/share/doc/#{name}/changelog.Debian") FileUtils.mkdir_p(File.dirname(dest_changelog)) FileUtils.cp attributes[:deb_changelog], dest_changelog File.chmod(0644, dest_changelog) safesystem("gzip", dest_changelog) end |
︙ | ︙ | |||
403 404 405 406 407 408 409 | # Install an init.d shim that calls upstart dest_init = staging_path("/etc/init.d/#{name}") FileUtils.mkdir_p(File.dirname(dest_init)) FileUtils.ln_s("/lib/init/upstart-job", dest_init) end | | < > > > > | 411 412 413 414 415 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 442 443 444 | # Install an init.d shim that calls upstart dest_init = staging_path("/etc/init.d/#{name}") FileUtils.mkdir_p(File.dirname(dest_init)) FileUtils.ln_s("/lib/init/upstart-job", dest_init) end args = [ tar_cmd, "-C", staging_path, compression ] + data_tar_flags + [ "-cf", datatar, "." ] safesystem(*args) # pack up the .deb, which is just an 'ar' archive with 3 files # the 'debian-binary' file has to be first with(File.expand_path(output_path)) do |output_path| ::Dir.chdir(build_path) do safesystem("ar", "-qc", output_path, "debian-binary", "control.tar.gz", datatar) end end 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 |
︙ | ︙ | |||
451 452 453 454 455 456 457 | 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?("_") | | | 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 | 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] |
︙ | ︙ | |||
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 517 518 519 520 | 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 else return File.join(@control_path, path) end end # def control_path def write_control_tarball # Use custom Debian control file when given ... write_control # write the control file write_shlibs # write optional shlibs file write_scripts # write the maintainer scripts write_conffiles # write the conffiles write_debconf # write the debconf files write_md5sums # write the md5sums file # Make the control.tar.gz with(build_path("control.tar.gz")) do |controltar| @logger.info("Creating", :path => controltar, :from => control_path) args = [ tar_cmd, "-C", control_path, "-zcf", controltar, | > > > > > > > > > > > > > > > > > > > | 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 | 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 else return File.join(@control_path, path) end end # def control_path def write_control_tarball # Use custom Debian control file when given ... write_control # write the control file write_shlibs # write optional shlibs file write_scripts # write the maintainer scripts write_conffiles # write the conffiles write_debconf # write the debconf files write_meta_files # write additional meta files write_triggers # write trigger config to 'triggers' file write_md5sums # write the md5sums file # Make the control.tar.gz with(build_path("control.tar.gz")) do |controltar| @logger.info("Creating", :path => controltar, :from => control_path) args = [ tar_cmd, "-C", control_path, "-zcf", controltar, |
︙ | ︙ | |||
554 555 556 557 558 559 560 561 562 563 564 565 566 567 | else @logger.debug("Using 'deb.erb' template for the control file") control_data = template("deb.erb").result(binding) end @logger.debug("Writing control file", :path => control) File.write(control, control_data) edit_file(control) if attributes[:edit?] end end # def write_control # Write out the maintainer scripts # # SCRIPT_MAP is a map from the package ':after_install' to debian | > | 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 | else @logger.debug("Using 'deb.erb' template for the control file") control_data = template("deb.erb").result(binding) end @logger.debug("Writing control file", :path => control) File.write(control, control_data) File.chmod(0644, control) edit_file(control) if attributes[:edit?] end end # def write_control # Write out the maintainer scripts # # SCRIPT_MAP is a map from the package ':after_install' to debian |
︙ | ︙ | |||
581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 | 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, "Error trying to use '#{cfg_path}' as a config file in the package. Does it exist?" end end allconfigs.sort!.uniq! | > > | > | | | > > > > > | 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 | 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, "Error trying to use '#{cfg_path}' as a config file in the package. Does it exist?" end end allconfigs.sort!.uniq! with(control_path("conffiles")) do |conffiles| File.open(conffiles, "w") do |out| # 'config_files' comes from FPM::Package and is usually set with # FPM::Command's --config-files flag allconfigs.each do |cf| # We need to put the leading / back. Stops lintian relative-conffile error. out.puts("/" + cf) end end File.chmod(0644, conffiles) end end # def write_conffiles def write_shlibs return unless attributes[:deb_shlibs] @logger.info("Adding shlibs", :content => attributes[:deb_shlibs]) File.open(control_path("shlibs"), "w") do |out| |
︙ | ︙ | |||
619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 | end if attributes[:deb_templates] FileUtils.cp(attributes[:deb_templates], control_path("templates")) File.chmod(0755, control_path("templates")) end end # def write_debconf def write_md5sums md5_sums = {} Find.find(staging_path) do |path| if File.file?(path) && !File.symlink?(path) md5 = Digest::MD5.file(path).hexdigest md5_path = path.gsub("#{staging_path}/", "") md5_sums[md5_path] = md5 end end 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 | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | | 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 | end if attributes[:deb_templates] FileUtils.cp(attributes[:deb_templates], control_path("templates")) File.chmod(0755, control_path("templates")) end end # def write_debconf def write_meta_files files = attributes[:deb_meta_files] return unless files files.each do |fn| dest = control_path(File.basename(fn)) FileUtils.cp(fn, dest) File.chmod(0644, dest) end end def write_triggers lines = [['interest', :deb_interest], ['activate', :deb_activate]].map { |label, attr| (attributes[attr] || []).map { |e| "#{label} #{e}\n" } }.flatten.join('') if lines.size > 0 File.open(control_path("triggers"), 'a') do |f| f.write "\n" if f.size > 0 f.write lines end end end def write_md5sums md5_sums = {} Find.find(staging_path) do |path| if File.file?(path) && !File.symlink?(path) md5 = Digest::MD5.file(path).hexdigest md5_path = path.gsub("#{staging_path}/", "") md5_sums[md5_path] = md5 end end 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 def data_tar_flags data_tar_flags = [] if attributes[:deb_use_file_permissions?].nil? if !attributes[:deb_user].nil? if attributes[:deb_user] == 'root' data_tar_flags += [ "--numeric-owner", "--owner", "0" ] else data_tar_flags += [ "--owner", attributes[:deb_user] ] end end if !attributes[:deb_group].nil? if attributes[:deb_group] == 'root' data_tar_flags += [ "--numeric-owner", "--group", "0" ] else data_tar_flags += [ "--group", attributes[:deb_group] ] end end end return data_tar_flags end # def data_tar_flags public(:input, :output, :architecture, :name, :prefix, :converted_from, :to_s, :data_tar_flags) 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) |
︙ | ︙ | |||
67 68 69 70 71 72 73 | @logger["method"] = "input" begin ::Dir.chdir(chdir) do begin clone(source, destination) rescue Errno::ENOENT => e raise FPM::InvalidPackageConfiguration, | | | 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 | @logger["method"] = "input" begin ::Dir.chdir(chdir) do begin clone(source, destination) rescue Errno::ENOENT => e raise FPM::InvalidPackageConfiguration, "Cannot package the path '#{File.join(chdir, source)}', does it exist?" end end rescue Errno::ENOENT => e raise FPM::InvalidPackageConfiguration, "Cannot chdir to '#{chdir}'. Does it exist?" end |
︙ | ︙ |
Changes to lib/fpm/package/gem.rb.
︙ | ︙ | |||
34 35 36 37 38 39 40 41 42 43 44 45 46 47 | :default => true option "--fix-dependencies", :flag, "Should the package dependencies be " \ "prefixed?", :default => true option "--env-shebang", :flag, "Should the target package have the " \ "shebang rewritten to use env?", :default => true option "--prerelease", :flag, "Allow prerelease versions of a gem", :default => false def input(gem) # 'arg' is the name of the rubygem we should unpack. path_to_gem = download_if_necessary(gem, version) # Got a good gem now (downloaded or otherwise) # | > > > > > | 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 | :default => true option "--fix-dependencies", :flag, "Should the package dependencies be " \ "prefixed?", :default => true option "--env-shebang", :flag, "Should the target package have the " \ "shebang rewritten to use env?", :default => true option "--prerelease", :flag, "Allow prerelease versions of a gem", :default => false option "--disable-dependency", "gem_name", "The gem name to remove from dependency list", :multivalued => true, :attribute_name => :gem_disable_dependencies option "--version-bins", :flag, "Append the version to the bins", :default => false def input(gem) # 'arg' is the name of the rubygem we should unpack. path_to_gem = download_if_necessary(gem, version) # Got a good gem now (downloaded or otherwise) # |
︙ | ︙ | |||
143 144 145 146 147 148 149 150 151 152 153 154 155 156 | reqs = dep.requirement.to_s else reqs = dep.version_requirements end # Some reqs can be ">= a, < b" versions, let's handle that. reqs.to_s.split(/, */).each do |req| if attributes[:gem_fix_dependencies?] name = fix_name(dep.name) else name = dep.name end self.dependencies << "#{name} #{req}" end | > > > > | 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 | reqs = dep.requirement.to_s else reqs = dep.version_requirements end # Some reqs can be ">= a, < b" versions, let's handle that. reqs.to_s.split(/, */).each do |req| if attributes[:gem_disable_dependencies] next if attributes[:gem_disable_dependencies].include?(dep.name) end if attributes[:gem_fix_dependencies?] name = fix_name(dep.name) else name = dep.name end self.dependencies << "#{name} #{req}" end |
︙ | ︙ | |||
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 | > > > > > > > > > > > > > > > > > | 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 | 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 if attributes[:gem_version_bins?] and File.directory?(bin_path) (::Dir.entries(bin_path) - ['.','..']).each do |bin| FileUtils.mv("#{bin_path}/#{bin}", "#{bin_path}/#{bin}-#{self.version}") end 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 |
Changes to lib/fpm/package/python.rb.
︙ | ︙ | |||
59 60 61 62 63 64 65 66 67 68 69 70 71 72 | "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. # # The 'package' can be any of: # | > > > > > > | 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 | "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 option "--scripts-executable", "PYTHON_EXECUTABLE", "Set custom python " \ "interpreter in installing scripts. By default distutils will replace " \ "python interpreter in installing scripts (specified by shebang) with " \ "current python interpreter (sys.executable). This option is equivalent " \ "to appending 'build_scripts --executable PYTHON_EXECUTABLE' arguments " \ "to 'setup.py install' command." private # Input a package. # # The 'package' can be any of: # |
︙ | ︙ | |||
117 118 119 120 121 122 123 | # no pip, use easy_install @logger.debug("no pip, defaulting to easy_install", :easy_install => attributes[:python_easyinstall]) safesystem(attributes[:python_easyinstall], "-i", attributes[:python_pypi], "--editable", "-U", "--build-directory", target, want_pkg) else @logger.debug("using pip", :pip => attributes[:python_pip]) | | < > > > > > > > > > > > > > > > > > > > > | 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 | # no pip, use easy_install @logger.debug("no pip, defaulting to easy_install", :easy_install => attributes[:python_easyinstall]) safesystem(attributes[:python_easyinstall], "-i", attributes[:python_pypi], "--editable", "-U", "--build-directory", target, want_pkg) else @logger.debug("using pip", :pip => attributes[:python_pip]) safesystem(attributes[:python_pip], "install", "--no-deps", "--no-install", "-i", attributes[:python_pypi], "-U", "--build", target, want_pkg) end # easy_install will put stuff in @tmpdir/packagename/, so find that: # @tmpdir/somepackage/setup.py dirs = ::Dir.glob(File.join(target, "*")) if dirs.length != 1 raise "Unexpected directory layout after easy_install. Maybe file a bug? The directory is #{build_path}" end return dirs.first end # def download # Load the package information like name, version, dependencies. def load_package_info(setup_py) if !attributes[:python_package_prefix].nil? attributes[:python_package_name_prefix] = attributes[:python_package_prefix] end begin json_test_code = [ "try:", " import json", "except ImportError:", " import simplejson as json" ].join("\n") safesystem("#{attributes[:python_bin]} -c '#{json_test_code}'") rescue FPM::Util::ProcessFailed => e @logger.error("Your python environment is missing json support (either json or simplejson python module). I cannot continue without this.", :python => attributes[:python_bin], :error => e) raise FPM::Util::ProcessFailed, "Python (#{attributes[:python_bin]}) is missing simplejson or json modules." end begin safesystem("#{attributes[:python_bin]} -c 'import pkg_resources'") rescue FPM::Util::ProcessFailed => e @logger.error("Your python environment is missing a working setuptools module. I tried to find the 'pkg_resources' module but failed.", :python => attributes[:python_bin], :error => e) raise FPM::Util::ProcessFailed, "Python (#{attributes[:python_bin]}) is missing pkg_resources module." end # Add ./pyfpm/ to the python library path pylib = File.expand_path(File.dirname(__FILE__)) # chdir to the directory holding setup.py because some python setup.py's assume that you are # in the same directory. setup_dir = File.dirname(setup_py) |
︙ | ︙ | |||
267 268 269 270 271 272 273 274 275 276 277 278 279 280 | if !attributes[:python_install_bin].nil? flags += [ "--install-scripts", File.join(prefix, attributes[:python_install_bin]) ] elsif !attributes[:prefix].nil? # prefix given, but not python_install_bin, assume PREFIX/bin flags += [ "--install-scripts", File.join(prefix, "bin") ] end safesystem(attributes[:python_bin], "setup.py", "install", *flags) end end # def install_to_staging public(:input) end # class FPM::Package::Python | > > > > > | 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 | if !attributes[:python_install_bin].nil? flags += [ "--install-scripts", File.join(prefix, attributes[:python_install_bin]) ] elsif !attributes[:prefix].nil? # prefix given, but not python_install_bin, assume PREFIX/bin flags += [ "--install-scripts", File.join(prefix, "bin") ] end if !attributes[:python_scripts_executable].nil? # Overwrite installed python scripts shebang binary with provided executable flags += [ "build_scripts", "--executable", attributes[:python_scripts_executable] ] end safesystem(attributes[:python_bin], "setup.py", "install", *flags) end end # def install_to_staging public(:input) end # class FPM::Package::Python |
Changes to lib/fpm/package/rpm.rb.
︙ | ︙ | |||
26 27 28 29 30 31 32 | "none" => "w0.gzdio", "xz" => "w2.xzdio", "gzip" => "w9.gzdio", "bzip2" => "w9.bzdio" } unless defined?(COMPRESSION_MAP) option "--use-file-permissions", :flag, | | < | < < < < | < < < | 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 | "none" => "w0.gzdio", "xz" => "w2.xzdio", "gzip" => "w9.gzdio", "bzip2" => "w9.bzdio" } unless defined?(COMPRESSION_MAP) option "--use-file-permissions", :flag, "Use existing file permissions when defining ownership and modes." option "--user", "USER", "Set the user to USER in the %files section. Overrides the user when used with use-file-permissions setting." option "--group", "GROUP", "Set the group to GROUP in the %files section. Overrides the group when used with use-file-permissions setting." option "--defattrfile", "ATTR", "Set the default file mode (%defattr).", :default => '-' do |value| value end |
︙ | ︙ | |||
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 | option "--changelog", "FILEPATH", "Add changelog from FILEPATH contents" do |file| File.read(File.expand_path(file)) end option "--sign", :flag, "Pass --sign to rpmbuild" option "--auto-add-directories", :flag, "Auto add directories not part of filesystem" option "--autoreqprov", :flag, "Enable RPM's AutoReqProv option" option "--autoreq", :flag, "Enable RPM's AutoReq option" option "--autoprov", :flag, "Enable RPM's AutoProv option" rpmbuild_filter_from_provides = [] option "--filter-from-provides", "REGEX", "Set %filter_from_provides to the supplied REGEX." do |filter_from_provides| rpmbuild_filter_from_provides << filter_from_provides next rpmbuild_filter_from_provides end rpmbuild_filter_from_requires = [] option "--filter-from-requires", "REGEX", "Set %filter_from_requires to the supplied REGEX." do |filter_from_requires| rpmbuild_filter_from_requires << filter_from_requires next rpmbuild_filter_from_requires end option "--ignore-iteration-in-dependencies", :flag, "For '=' (equal) dependencies, allow iterations on the specified " \ "version. Default is to be specific. This option allows the same " \ "version of a package but any iteration is permitted" private # Fix path name # Replace [ with [\[] to make rpm not use globs # Replace * with [*] to make rpm not use globs # Replace ? with [?] to make rpm not use globs # Replace % with [%] to make rpm not expand macros def rpm_fix_name(name) name = "\"#{name}\"" if name[/\s/] 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) | > > > > > > > > > > > > > > > > > > > > > > > > > > | > > > > > > > > > > > > | | | 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 | option "--changelog", "FILEPATH", "Add changelog from FILEPATH contents" do |file| File.read(File.expand_path(file)) end option "--sign", :flag, "Pass --sign to rpmbuild" option "--auto-add-directories", :flag, "Auto add directories not part of filesystem" option "--auto-add-exclude-directories", "DIRECTORIES", "Additional directories ignored by '--rpm-auto-add-directories' flag", :multivalued => true, :attribute_name => :auto_add_exclude_directories option "--autoreqprov", :flag, "Enable RPM's AutoReqProv option" option "--autoreq", :flag, "Enable RPM's AutoReq option" option "--autoprov", :flag, "Enable RPM's AutoProv option" option "--attr", "ATTRFILE", "Set the attribute for a file (%attr).", :multivalued => true, :attribute_name => :attrs rpmbuild_filter_from_provides = [] option "--filter-from-provides", "REGEX", "Set %filter_from_provides to the supplied REGEX." do |filter_from_provides| rpmbuild_filter_from_provides << filter_from_provides next rpmbuild_filter_from_provides end rpmbuild_filter_from_requires = [] option "--filter-from-requires", "REGEX", "Set %filter_from_requires to the supplied REGEX." do |filter_from_requires| rpmbuild_filter_from_requires << filter_from_requires next rpmbuild_filter_from_requires end option "--ignore-iteration-in-dependencies", :flag, "For '=' (equal) dependencies, allow iterations on the specified " \ "version. Default is to be specific. This option allows the same " \ "version of a package but any iteration is permitted" option "--verbatim-gem-dependencies", :flag, "When converting from a gem, leave the old (fpm 0.4.x) style " \ "dependency names. This flag will use the old 'rubygem-foo' " \ "names in rpm requires instead of the redhat style " \ "rubygem(foo).", :default => false option "--verifyscript", "FILE", "a script to be run on verification" do |val| File.expand_path(val) # Get the full path to the script end # --verifyscript option "--pretrans", "FILE", "pretrans script" do |val| File.expand_path(val) # Get the full path to the script end # --pretrans option "--posttrans", "FILE", "posttrans script" do |val| File.expand_path(val) # Get the full path to the script end # --posttrans private # Fix path name # Replace [ with [\[] to make rpm not use globs # Replace * with [*] to make rpm not use globs # Replace ? with [?] to make rpm not use globs # Replace % with [%] to make rpm not expand macros def rpm_fix_name(name) name = "\"#{name}\"" if name[/\s/] 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) if !attributes[:rpm_use_file_permissions?] if attrs[file].nil? return file else return sprintf("%%attr(%s) %s\n", attrs[file], file) end end return sprintf("%%attr(%s) %s\n", attrs[file], file) unless attrs[file].nil? # Stat the original filename in the relative staging path ::Dir.chdir(staging_path) do stat = File.stat(original_file.gsub(/\"/, '').sub(/^\//,'')) # rpm_user and rpm_group attribute should override file ownership # otherwise use the current file user/group by name. user = attributes[:rpm_user] || Etc.getpwuid(stat.uid).name group = attributes[:rpm_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. |
︙ | ︙ | |||
172 173 174 175 176 177 178 | def iteration return @iteration ? @iteration : 1 end # def iteration # See FPM::Package#converted_from def converted_from(origin) if origin == FPM::Package::Gem | < < < < < < < > | < < | < | > | > | < | | > | | | | | < > < < < < < < < < < < < < < > > > > > > > > > > > > > > > | 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 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 | def iteration return @iteration ? @iteration : 1 end # def iteration # See FPM::Package#converted_from def converted_from(origin) if origin == FPM::Package::Gem fixed_deps = [] self.dependencies.collect do |dep| # Gem dependency operator "~>" is not compatible with rpm. Translate any found. fixed_deps = fixed_deps + expand_pessimistic_constraints(dep) 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 if !self.attributes[:rpm_verbatim_gem_dependencies?] 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 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 } nextversion[-1] += 1 nextversion = nextversion.join(".") @logger.warn("Converting dependency #{dep} to #{name} >= #{version}, #{name} < #{nextversion}") ["#{name} >= #{version}", "#{name} < #{nextversion}"] else dep end end.flatten end setscript = proc do |scriptname| script_path = self.attributes[scriptname] # Skip scripts not set next if script_path.nil? if !File.exists?(script_path) @logger.error("No such file (for #{scriptname.to_s}): #{script_path.inspect}") script_errors << script_path end # Load the script into memory. scripts[scriptname] = File.read(script_path) end setscript.call(:rpm_verifyscript) setscript.call(:rpm_posttrans) setscript.call(:rpm_pretrans) end # def converted def input(path) rpm = ::RPM::File.new(path) tags = {} rpm.header.tags.each do |tag| |
︙ | ︙ | |||
277 278 279 280 281 282 283 284 285 286 287 288 289 290 | self.vendor = tags[:vendor] self.version = tags[:version] self.scripts[:before_install] = tags[:prein] self.scripts[:after_install] = tags[:postin] self.scripts[:before_remove] = tags[:preun] self.scripts[:after_remove] = tags[:postun] # TODO(sissel): prefix these scripts above with a shebang line if there isn't one? # Also taking into account the value of tags[preinprog] etc, something like: # #!#{tags[:preinprog]} # #{tags[prein]} # TODO(sissel): put 'trigger scripts' stuff into attributes if !attributes[:no_auto_depends?] | > > > | 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 | self.vendor = tags[:vendor] self.version = tags[:version] self.scripts[:before_install] = tags[:prein] self.scripts[:after_install] = tags[:postin] self.scripts[:before_remove] = tags[:preun] self.scripts[:after_remove] = tags[:postun] self.scripts[:rpm_verifyscript] = tags[:verifyscript] self.scripts[:rpm_posttrans] = tags[:posttrans] self.scripts[:rpm_pretrans] = tags[:pretrans] # TODO(sissel): prefix these scripts above with a shebang line if there isn't one? # Also taking into account the value of tags[preinprog] etc, something like: # #!#{tags[:preinprog]} # #{tags[prein]} # TODO(sissel): put 'trigger scripts' stuff into attributes if !attributes[:no_auto_depends?] |
︙ | ︙ | |||
312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 | # this feature #self.directories += rpm.directories # Extract to the staging directory rpm.extract(staging_path) end # def input def output(output_path) output_check(output_path) %w(BUILD RPMS SRPMS SOURCES SPECS).each { |d| FileUtils.mkdir_p(build_path(d)) } args = ["rpmbuild", "-bb"] # issue #309 if !attributes[:rpm_os].nil? rpm_target = "#{architecture}-unknown-#{attributes[:rpm_os]}" args += ["--target", rpm_target] end args += [ "--define", "buildroot #{build_path}/BUILD", "--define", "_topdir #{build_path}", "--define", "_sourcedir #{build_path}", "--define", "_rpmdir #{build_path}/RPMS", ] args += ["--sign"] if attributes[:rpm_sign?] if attributes[:rpm_auto_add_directories?] fs_dirs_list = File.join(template_dir, "rpm", "filesystem_list") fs_dirs = File.readlines(fs_dirs_list).reject { |x| x =~ /^\s*#/}.map { |x| x.chomp } Find.find(staging_path) do |path| next if path == staging_path if File.directory? path and !File.symlink? path add_path = path.gsub(/^#{staging_path}/,'') self.directories << add_path if not fs_dirs.include? add_path end end else | > > > > > > > > > > > > > > | | > | | 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 | # this feature #self.directories += rpm.directories # Extract to the staging directory rpm.extract(staging_path) end # def input def prefixed_path(path) Pathname.new(path).absolute?() ? path : File.join(self.prefix, path) end # def prefixed_path def output(output_path) output_check(output_path) %w(BUILD RPMS SRPMS SOURCES SPECS).each { |d| FileUtils.mkdir_p(build_path(d)) } args = ["rpmbuild", "-bb"] if %x{uname -m}.chomp != self.architecture rpm_target = self.architecture end # issue #309 if !attributes[:rpm_os].nil? rpm_target = "#{architecture}-unknown-#{attributes[:rpm_os]}" end # issue #707 if !rpm_target.nil? args += ["--target", rpm_target] end args += [ "--define", "buildroot #{build_path}/BUILD", "--define", "_topdir #{build_path}", "--define", "_sourcedir #{build_path}", "--define", "_rpmdir #{build_path}/RPMS", "--define", "_tmppath #{attributes[:workdir]}" ] args += ["--sign"] if attributes[:rpm_sign?] if attributes[:rpm_auto_add_directories?] fs_dirs_list = File.join(template_dir, "rpm", "filesystem_list") fs_dirs = File.readlines(fs_dirs_list).reject { |x| x =~ /^\s*#/}.map { |x| x.chomp } fs_dirs.concat((attributes[:auto_add_exclude_directories] or [])) Find.find(staging_path) do |path| next if path == staging_path if File.directory? path and !File.symlink? path add_path = path.gsub(/^#{staging_path}/,'') self.directories << add_path if not fs_dirs.include? add_path end end else self.directories = self.directories.map { |x| self.prefixed_path(x) } alldirs = [] self.directories.each do |path| Find.find(File.join(staging_path, path)) do |subpath| if File.directory? subpath and !File.symlink? subpath alldirs << subpath.gsub(/^#{staging_path}/, '') end end end self.directories = alldirs end # scan all conf file paths for files and add them allconfigs = [] self.config_files.each do |path| cfg_path = File.join(staging_path, path) raise "Config file path #{cfg_path} does not exist" unless File.exist?(cfg_path) Find.find(cfg_path) do |p| allconfigs << p.gsub("#{staging_path}/", '') if File.file? p end end allconfigs.sort!.uniq! self.config_files = allconfigs.map { |x| File.join("/", x) } (attributes[:rpm_rpmbuild_define] or []).each do |define| args += ["--define", define] end # copy all files from staging to BUILD dir Find.find(staging_path) do |path| |
︙ | ︙ | |||
394 395 396 397 398 399 400 | @logger.info("Running rpmbuild", :args => args) safesystem(*args) ::Dir["#{build_path}/RPMS/**/*.rpm"].each do |rpmpath| # This should only output one rpm, should we verify this? FileUtils.cp(rpmpath, output_path) end | < < | | 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 | @logger.info("Running rpmbuild", :args => args) safesystem(*args) ::Dir["#{build_path}/RPMS/**/*.rpm"].each do |rpmpath| # This should only output one rpm, should we verify this? FileUtils.cp(rpmpath, output_path) end end # def output def prefix return (attributes[:prefix] or "/") end # def prefix def build_sub_dir return "BUILD" #return File.join("BUILD", prefix) end # def build_sub_dir def version if @version.kind_of?(String) and @version.include?("-") @logger.warn("Package version '#{@version}' includes dashes, converting" \ " to underscores") @version = @version.gsub(/-/, "_") end |
︙ | ︙ | |||
444 445 446 447 448 449 450 | def digest_algorithm return DIGEST_ALGORITHM_MAP[attributes[:rpm_digest]] end # def digest_algorithm public(:input, :output, :converted_from, :architecture, :to_s, :iteration, :payload_compression, :digest_algorithm, :prefix, :build_sub_dir, | | | 485 486 487 488 489 490 491 492 493 | def digest_algorithm return DIGEST_ALGORITHM_MAP[attributes[:rpm_digest]] end # def digest_algorithm public(:input, :output, :converted_from, :architecture, :to_s, :iteration, :payload_compression, :digest_algorithm, :prefix, :build_sub_dir, :epoch, :version, :prefixed_path) end # class FPM::Package::RPM |
Added lib/fpm/package/sh.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 | require "erb" require "fpm/namespace" require "fpm/package" require "fpm/errors" require "fpm/util" require "backports" require "fileutils" require "digest" # Support for self extracting sh files (.sh files) # # This class only supports output of packages. # # The sh package is a single sh file with a bzipped tar payload concatenated to the end. # The script can unpack the tarball to install it and call optional post install scripts. class FPM::Package::Sh < FPM::Package def output(output_path) create_scripts # Make one file. The installscript can unpack itself. `cat #{install_script} #{payload} > #{output_path}` FileUtils.chmod("+x", output_path) end def create_scripts if script?(:before_install) # the scripts are kept in the payload so what would before install be if we've already # unpacked the payload? raise "sh package does not support before install scripts." end if script?(:after_install) File.write(File.join(fpm_meta_path, "after_install"), script(:after_install)) end end def install_script path = build_path("installer.sh") File.open(path, "w") do |file| file.write template("sh.erb").result(binding) end path end # Returns the path to the tar file containing the packed up staging directory def payload payload_tar = build_path("payload.tar") @logger.info("Creating payload tar ", :path => payload_tar) args = [ tar_cmd, "-C", staging_path, "-cf", payload_tar, "--owner=0", "--group=0", "--numeric-owner", "." ] unless safesystem(*args) raise "Command failed while creating payload tar: #{args}" end payload_tar end # Where we keep metadata and post install scripts and such def fpm_meta_path @fpm_meta_path ||= begin path = File.join(staging_path, ".fpm") FileUtils.mkdir_p(path) path end end end |
Added lib/fpm/package/zip.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 | require "backports" # gem backports require "fpm/package" require "fpm/util" require "fileutils" require "fpm/package/dir" # Use a zip as a package. # # This provides no metadata. Both input and output are supported. class FPM::Package::Zip < FPM::Package # Input a zipfile. def input(input_path) # use part of the filename as the package name self.name = File.extname(input_path)[1..-1] realpath = Pathname.new(input_path).realpath.to_s ::Dir.chdir(build_path) do safesystem("unzip", realpath) end # use dir to set stuff up properly, mainly so I don't have to reimplement # the chdir/prefix stuff special for zip. dir = convert(FPM::Package::Dir) if attributes[:chdir] dir.attributes[:chdir] = File.join(build_path, attributes[:chdir]) else dir.attributes[:chdir] = build_path end cleanup_staging # Tell 'dir' to input "." and chdir/prefix will help it figure out the # rest. dir.input(".") @staging_path = dir.staging_path dir.cleanup_build end # def input # Output a tarball. # # If the output path ends predictably (like in .tar.gz) it will try to obey # the compression type. def output(output_path) output_check(output_path) files = Find.find(staging_path).to_a safesystem("zip", output_path, *files) end # def output # Generate the proper tar flags based on the path name. def tar_compression_flag(path) case path when /\.tar\.bz2$/ return "-j" when /\.tar\.gz$|\.tgz$/ return "-z" when /\.tar\.xz$/ return "-J" else return nil end end # def tar_compression_flag end # class FPM::Package::Tar |
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 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 | 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 # Is the given program in the system's PATH? def program_in_path?(program) # Scan path to find the executable # Do this to help the user get a better error message. envpath = ENV["PATH"].split(":") return envpath.select { |p| File.executable?(File.join(p, program)) }.any? end # def program_in_path def program_exists?(program) # Scan path to find the executable # Do this to help the user get a better error message. return program_in_path?(program) if !program.include?("/") return File.executable?(program) end # def program_exists? def default_shell shell = ENV["SHELL"] return "/bin/sh" if shell.nil? || shell.empty? return shell end # Run a command safely in a way that gets reports useful errors. def safesystem(*args) # ChildProcess isn't smart enough to run a $SHELL if there's # spaces in the first arg and there's only 1 arg. if args.size == 1 args = [ default_shell, "-c", args[0] ] end program = args[0] if !program_exists?(program) raise ExecutableNotFound.new(program) end @logger.debug("Running command", :args => args) # Create a pair of pipes to connect the # invoked process to the cabin logger |
︙ | ︙ | |||
67 68 69 70 71 72 73 | if !success raise ProcessFailed.new("#{program} failed (exit code #{process.exit_code})" \ ". Full command was:#{args.inspect}") end return success end # def safesystem | | | 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 | if !success raise ProcessFailed.new("#{program} failed (exit code #{process.exit_code})" \ ". Full command was:#{args.inspect}") end return success end # def safesystem # Run a command safely in a way that captures output and status. def safesystemout(*args) if args.size == 1 args = [ ENV["SHELL"], "-c", args[0] ] end program = args[0] if !program.include?("/") and !program_in_path?(program) |
︙ | ︙ | |||
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" | > | > > > > > > > > > > > > > > > > | < < < | > > > > > > > > > | > | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | > > > > > > > > > > > > > > > | 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 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 | # 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 # if the file with the same dev and inode has been copied already - # hard link it's copy to `dst`, otherwise make an actual copy st = File.lstat(src) known_entry = copied_entries[[st.dev, st.ino]] if known_entry FileUtils.ln(known_entry, dst) else FileUtils.copy_entry(src, dst) copied_entries[[st.dev, st.ino]] = dst end end # else... end # def copy_entry def copied_entries # TODO(sissel): I wonder that this entry-copy knowledge needs to be put # into a separate class/module. As is, calling copy_entry the same way # in slightly different contexts will result in weird or bad behavior. # What I mean is if we do: # pkg = FPM::Package::Dir... # pkg.output()... # pkg.output()... # The 2nd output call will fail or behave weirdly because @copied_entries # is already populated. even though this is anew round of copying. return @copied_entries ||= {} end # def copied_entries def expand_pessimistic_constraints(constraint) name, op, version = constraint.split(/\s+/) if op == '~>' new_lower_constraint = "#{name} >= #{version}" version_components = version.split('.').collect { |v| v.to_i } version_prefix = version_components[0..-3].join('.') portion_to_work_with = version_components.last(2) prefix = '' unless version_prefix.empty? prefix = version_prefix + '.' end one_to_increment = portion_to_work_with[0].to_i incremented = one_to_increment + 1 new_version = ''+ incremented.to_s + '.0' upper_version = prefix + new_version new_upper_constraint = "#{name} < #{upper_version}" return [new_lower_constraint,new_upper_constraint] else return [constraint] end end #def expand_pesimistic_constraints end # module FPM::Util |
Changes to lib/fpm/version.rb.
1 | module FPM | | | 1 2 3 | module FPM VERSION = "1.2.0" end |
Added spec/fixtures/deb/meta_test.
> | 1 | asdf |
Added spec/fixtures/deb/staging/etc/init.d/test.
> > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 | start() { } stop() { } restart() { } force-reload() { } |
Added spec/fixtures/deb/triggers.
> | 1 | interest from-meta-file |
Added spec/fixtures/gem/example/bin/example.
> | 1 | #!/usr/bin/env ruby |
Changes to spec/fixtures/gem/example/example-1.0.gem.
cannot compute difference between binary files
Changes to spec/fixtures/gem/example/example.gemspec.
1 2 3 4 5 6 7 8 9 10 | Gem::Specification.new do |spec| spec.name = "example" spec.version = "1.0" spec.summary = "sample summary" spec.description = "sample description" spec.add_dependency("dependency1") # license: Ruby License spec.add_dependency("dependency2") #spec.files = ["hello.txt"] | | > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | Gem::Specification.new do |spec| spec.name = "example" spec.version = "1.0" spec.summary = "sample summary" spec.description = "sample description" spec.add_dependency("dependency1") # license: Ruby License spec.add_dependency("dependency2") #spec.files = ["hello.txt"] spec.files = [ "bin/example" ] spec.executables = "example" spec.bindir = "bin" #spec.require_paths << "lib" spec.author = "sample author" spec.email = "sample email" spec.homepage = "http://sample-url/" end |
Changes to spec/fpm/command_spec.rb.
1 2 3 4 5 6 7 8 | require "spec_setup" require "fpm" # local require "fpm/command" # local describe FPM::Command do describe "--prefix" describe "-C" describe "-p / --package" | > | 1 2 3 4 5 6 7 8 9 | require "spec_setup" require "stud/temporary" require "fpm" # local require "fpm/command" # local describe FPM::Command do describe "--prefix" describe "-C" describe "-p / --package" |
︙ | ︙ | |||
18 19 20 21 22 23 24 | describe "--no-depends" describe "--provides" describe "--conflicts" describe "--replaces" describe "--config-files" describe "--directories" describe "-a | --architecture" | > > > > > > > > > > > | > > > > > > > > > > > > > > > > > > | 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 | describe "--no-depends" describe "--provides" describe "--conflicts" describe "--replaces" describe "--config-files" describe "--directories" describe "-a | --architecture" describe "-p | --package" do context "when given a directory" do it "should write the package to the given directory." do Stud::Temporary.directory do |path| cmd = FPM::Command.new("fpm") cmd.run(["-s", "empty", "-t", "deb", "-n", "example", "-p", path]) files = Dir.new(path).to_a - [".", ".."] insist { files.size } == 1 insist { files[0] } =~ /^example_/ end end end context "when not set" do it "should write the package to the current directory." do Stud::Temporary.directory do |path| Dir.chdir(path) do cmd = FPM::Command.new("fpm") cmd.run(["-s", "empty", "-t", "deb", "-n", "example"]) end files = Dir.new(path).to_a - ['.', '..'] insist { files.size } == 1 insist { files[0] } =~ /example_/ end end end end end |
Changes to spec/fpm/package/cpan_spec.rb.
1 2 3 4 | require "spec_setup" require "fpm" # local require "fpm/package/cpan" # local | | | 1 2 3 4 5 6 7 8 9 10 11 12 | require "spec_setup" require "fpm" # local require "fpm/package/cpan" # local have_cpanm = program_exists?("cpanm") if !have_cpanm Cabin::Channel.get("rspec") \ .warn("Skipping CPAN#input tests because 'cpanm' isn't in your PATH") end describe FPM::Package::CPAN, :if => have_cpanm do subject { FPM::Package::CPAN.new } |
︙ | ︙ |
Changes to spec/fpm/package/deb_spec.rb.
1 2 3 4 5 6 | require "spec_setup" require "fpm" # local require "fpm/package/deb" # local require "fpm/package/dir" # local describe FPM::Package::Deb do | > | | > > > > > > | | 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 | require "spec_setup" require 'fileutils' require "fpm" # local require "fpm/package/deb" # local require "fpm/package/dir" # local describe FPM::Package::Deb do # dpkg-deb lets us query deb package files. # Comes with debian and ubuntu systems. have_dpkg_deb = program_exists?("dpkg-deb") if !have_dpkg_deb Cabin::Channel.get("rspec") \ .warn("Skipping some deb tests because 'dpkg-deb' isn't in your PATH") end have_lintian = program_exists?("lintian") if !have_lintian Cabin::Channel.get("rspec") \ .warn("Skipping some deb tests because 'lintian' isn't in your PATH") end after :each do subject.cleanup end describe "#architecture" do it "should convert x86_64 to amd64" do subject.architecture = "x86_64" insist { subject.architecture } == "amd64" end it "should convert noarch to all" do subject.architecture = "noarch" insist { subject.architecture } == "all" end it "should default to native" do expected = "" if program_exists?("dpkg") expected = %x{dpkg --print-architecture}.chomp end if expected.empty? # dpkg was missing, failed, or emitted nothing. expected = %x{uname -m}.chomp end |
︙ | ︙ | |||
57 58 59 60 61 62 63 64 65 66 67 68 69 70 | end describe "priority" do it "should default to 'extra'" do insist { subject.attributes[:deb_priority] } == "extra" end end describe "#to_s" do it "should have a default output usable as a filename" do subject.name = "name" subject.version = "123" subject.architecture = "all" subject.iteration = "100" | > > > > > > | 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 | end describe "priority" do it "should default to 'extra'" do insist { subject.attributes[:deb_priority] } == "extra" end end describe "use-file-permissions" do it "should be nil by default" do insist { subject.attributes[:deb_use_file_permissions?] }.nil? end end describe "#to_s" do it "should have a default output usable as a filename" do subject.name = "name" subject.version = "123" subject.architecture = "all" subject.iteration = "100" |
︙ | ︙ | |||
98 99 100 101 102 103 104 | end it "should replace underscores with dashes in the package name" do reject { subject.name }.include?("_") end end | | | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 | end it "should replace underscores with dashes in the package name" do reject { subject.name }.include?("_") end end describe "#output" do before :all do # output a package, use it as the input, set the subject to that input # package. This helps ensure that we can write and read packages # properly. tmpfile = Tempfile.new("fpm-test-deb") @target = tmpfile.path # The target file must not exist. tmpfile.unlink @original = FPM::Package::Deb.new @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' @original.attributes[:deb_build_depends] << 'something-else < 1.0.0' @original.attributes[:deb_priority] = "fizzle" @original.attributes[:deb_field_given?] = true @original.attributes[:deb_field] = { "foo" => "bar" } @original.attributes[:deb_meta_files] = %w[meta_test triggers].map { |fn| File.expand_path("../../../fixtures/deb/#{fn}", __FILE__) } @original.attributes[:deb_interest] = ['asdf', 'hjkl'] @original.attributes[:deb_activate] = ['qwer', 'uiop'] @original.output(@target) @input = FPM::Package::Deb.new @input.input(@target) end after :all do @original.cleanup @input.cleanup end # after context "when the deb's control section is extracted" do before :all do tmp_control = Tempfile.new("fpm-test-deb-control") @control_extracted = tmp_control.path tmp_control.unlink system("dpkg-deb -e '#{@target}' '#{@control_extracted}'") or \ raise "couldn't extract test deb" end it "should have the requested meta file in the control archive" do File.open(File.join(@control_extracted, 'meta_test')) do |f| insist { f.read.chomp } == "asdf" end end it "should have the requested triggers in the triggers file" do triggers = File.open(File.join(@control_extracted, 'triggers')) do |f| f.read end reject { triggers =~ /^interest from-meta-file$/ }.nil? reject { triggers =~ /^interest asdf$/ }.nil? reject { triggers =~ /^interest hjkl$/ }.nil? reject { triggers =~ /^activate qwer$/ }.nil? reject { triggers =~ /^activate uiop$/ }.nil? insist { triggers[-1] } == ?\n end after :all do FileUtils.rm_rf @control_extracted end end context "package attributes" do it "should have the correct name" do insist { @input.name } == @original.name end it "should have the correct version" do |
︙ | ︙ | |||
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' | | > > > > | 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 | @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 |
︙ | ︙ | |||
199 200 201 202 203 204 205 | it "should have the correct build dependency list" do insist { dpkg_field("Build-Depends") } == "something-else (>> 0.0.0), something-else (<< 1.0.0)" end it "should have a custom field 'foo: bar'" do insist { dpkg_field("foo") } == "bar" end | | | | 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 | it "should have the correct build dependency list" do insist { dpkg_field("Build-Depends") } == "something-else (>> 0.0.0), something-else (<< 1.0.0)" end it "should have a custom field 'foo: bar'" do insist { dpkg_field("foo") } == "bar" end it "should have the correct Conflicts" do insist { dpkg_field("Conflicts") } == "foo (<< 123)" end it "should have the correct Breaks" do insist { dpkg_field("Breaks") } == "baz (<< 123)" end end end # #output describe "#output with no depends" do before :all do # output a package, use it as the input, set the subject to that input # package. This helps ensure that we can write and read packages # properly. tmpfile = Tempfile.new("fpm-test-deb") @target = tmpfile.path # The target file must not exist. |
︙ | ︙ | |||
244 245 246 247 248 249 250 251 | @input.cleanup end # after it "should have no dependencies" do insist { @input.dependencies }.empty? end end # #output with no dependencies end # describe FPM::Package::Deb | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 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 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 | @input.cleanup end # after it "should have no dependencies" do insist { @input.dependencies }.empty? end end # #output with no dependencies describe "#tar_flags" do before :each do tmpfile = Tempfile.new("fpm-test-deb") @target = tmpfile.path # The target file must not exist. tmpfile.unlink @package = FPM::Package::Deb.new @package.name = "name" end after :each do @package.cleanup end # after it "should set the user for the package's data files" do @package.attributes[:deb_user] = "nobody" # output a package so that @data_tar_flags is computed insist { @package.data_tar_flags } == ["--owner", "nobody", "--numeric-owner", "--group", "0"] end it "should set the group for the package's data files" do @package.attributes[:deb_group] = "nogroup" # output a package so that @data_tar_flags is computed insist { @package.data_tar_flags } == ["--numeric-owner", "--owner", "0", "--group", "nogroup"] end it "should not set the user or group for the package's data files if :deb_use_file_permissions? is not nil" do @package.attributes[:deb_use_file_permissions?] = true # output a package so that @data_tar_flags is computed @package.output(@target) insist { @package.data_tar_flags } == [] end end # #tar_flags describe "#output with lintian" do before :all do @staging_path = Dir.mktmpdir tmpfile = Tempfile.new(["fpm-test-deb", ".deb"]) @target = tmpfile.path # The target file must not exist. tmpfile.unlink FileUtils.cp_r(Dir['spec/fixtures/deb/staging/*'], @staging_path) @deb = FPM::Package::Deb.new @deb.name = "name" @deb.version = "0.0.1" @deb.maintainer = "Jordan Sissel <jls@semicomplete.com>" @deb.description = "Test package\nExtended description." @deb.attributes[:deb_user] = "root" @deb.attributes[:deb_group] = "root" @deb.instance_variable_set(:@config_files, ["/etc/init.d/test"]) @deb.instance_variable_set(:@staging_path, @staging_path) @deb.output(@target) end after :all do @deb.cleanup FileUtils.rm_r @staging_path if File.exists? @staging_path end # after context "when run against lintian", :if => have_lintian do lintian_errors_to_ignore = [ "no-copyright-file", "init.d-script-missing-lsb-section", "non-standard-file-permissions-for-etc-init.d-script" ] it "should return no errors" do lintian_output = %x{lintian #{@target} --suppress-tags #{lintian_errors_to_ignore.join(",")}} expect($?).to eq(0), lintian_output end end end end # describe FPM::Package::Deb |
Changes to spec/fpm/package/dir_spec.rb.
1 2 3 4 5 6 7 8 9 10 11 | require "spec_setup" require "fpm" # local require "fpm/package/dir" # local require "stud/temporary" describe FPM::Package::Dir do let(:tmpdir) { Stud::Temporary.directory("tmpdir") } let(:output) { Stud::Temporary.directory("output") } #let(:tmpdir) { ::Dir.mkdir("/tmp/tmpdir"); "/tmp/tmpdir" } #let(:output) { ::Dir.mkdir("/tmp/output"); "/tmp/output" } | > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | require "spec_setup" require "fpm" # local require "fpm/package/dir" # local require "stud/temporary" if RUBY_VERSION =~ /^1\.8/ # The following method copied from ruby 1.9.3 module SecureRandom def self.uuid ary = self.random_bytes(16).unpack("NnnnnN") ary[2] = (ary[2] & 0x0fff) | 0x4000 ary[3] = (ary[3] & 0x3fff) | 0x8000 "%08x-%04x-%04x-%04x-%04x%08x" % ary end end end describe FPM::Package::Dir do let(:tmpdir) { Stud::Temporary.directory("tmpdir") } let(:output) { Stud::Temporary.directory("output") } #let(:tmpdir) { ::Dir.mkdir("/tmp/tmpdir"); "/tmp/tmpdir" } #let(:output) { ::Dir.mkdir("/tmp/output"); "/tmp/output" } |
︙ | ︙ | |||
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 | > > > > > > | > > > > > > > > > > > | 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 | 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/gem_spec.rb.
1 2 3 4 | require "spec_setup" require "fpm" # local require "fpm/package/gem" # local | | | > > > > > > > > > > > > > > > > > > > > > > > > > | 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 | require "spec_setup" require "fpm" # local require "fpm/package/gem" # local have_gem = program_exists?("gem") if !have_gem Cabin::Channel.get("rspec") \ .warn("Skipping Gem#input tests because 'gem' isn't in your PATH") end describe FPM::Package::Gem, :if => have_gem do let (:example_gem) do File.expand_path("../../fixtures/gem/example/example-1.0.gem", File.dirname(__FILE__)) end after :each do subject.cleanup end context "when :gem_version_bins? is true" do before :each do subject.attributes[:gem_version_bins?] = true subject.attributes[:gem_bin_path] = '/usr/bin' end it "it should append the version to binaries" do subject.input(example_gem) insist { ::Dir.entries(File.join(subject.staging_path, "/usr/bin")) }.include?("example-1.0.0") end end context "when :gem_version_bins? is false" do before :each do subject.attributes[:gem_version_bins?] = false subject.attributes[:gem_bin_path] = '/usr/bin' end it "it should not append the version to binaries" do subject.input(example_gem) insist { ::Dir.entries(File.join(subject.staging_path, "/usr/bin")) }.include?("example") end end context "when :gem_fix_name? is true" do before :each do subject.attributes[:gem_fix_name?] = true end context "and :gem_package_name_prefix is nil/default" do it "should prefix the package with 'gem-'" do |
︙ | ︙ |
Changes to spec/fpm/package/python_spec.rb.
1 2 3 4 5 | require "spec_setup" require "fpm" # local require "fpm/package/python" # local def python_usable? | > | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 | require "spec_setup" require "fpm" # local require "fpm/package/python" # local require "find" # stdlib def python_usable? return program_exists?("python") && program_exists?("easy_install") end if !python_usable? Cabin::Channel.get("rspec").warn("Skipping Python#input tests because " \ "'python' and/or 'easy_install' isn't in your PATH") end |
︙ | ︙ | |||
122 123 124 125 126 127 128 129 | it "it should load requirements.txt" do subject.input(example_dir) insist { subject.dependencies.sort } == ["rtxt-dep1 > 0.1", "rtxt-dep2 = 0.1"] end end end end # describe FPM::Package::Python | > > > > > > > > > > > > > > > > > > > > | 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 | it "it should load requirements.txt" do subject.input(example_dir) insist { subject.dependencies.sort } == ["rtxt-dep1 > 0.1", "rtxt-dep2 = 0.1"] end end end context "python_scripts_executable is set" do it "should have scripts with a custom hashbang line" do subject.attributes[:python_install_bin] = '/usr/bin' subject.attributes[:python_scripts_executable] = "fancypants" subject.input("django") # Get the default scripts install directory and use it to find django-admin.py from Django # Then let's make sure the scripts executable setting worked! python_bindir = %x{python -c 'from distutils.sysconfig import get_config_var; print(get_config_var("BINDIR"))'}.chomp path = subject.staging_path(File.join(python_bindir, "django-admin.py")) # Read the first line (the hashbang line) of the django-admin.py script fd = File.new(path, "r") topline = fd.readline fd.close insist { topline.chomp } == "#!fancypants" end end end # describe FPM::Package::Python |
Changes to spec/fpm/package/rpm_spec.rb.
1 2 3 4 5 6 | require "spec_setup" require "fpm" # local require "fpm/package/rpm" # local require "fpm/package/dir" # local require "arr-pm/file" # gem 'arr-pm' | > | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | require "spec_setup" require "fpm" # local require "fpm/package/rpm" # local require "fpm/package/dir" # local require "arr-pm/file" # gem 'arr-pm' require "stud/temporary" # gem 'stud' if !program_exists?("rpmbuild") Cabin::Channel.get("rspec") \ .warn("Skipping RPM#output tests because 'rpmbuild' isn't in your PATH") end describe FPM::Package::RPM do after :each do subject.cleanup |
︙ | ︙ | |||
76 77 78 79 80 81 82 | end after :each do subject.cleanup end it "should set the user and group of each file in the RPM" do | | | 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 | end after :each do subject.cleanup end it "should set the user and group of each file in the RPM" do expect(subject.rpmspec).to include('%defattr(-,root,root,-') end end # context context "non-default user and group" do before :each do subject.attributes[:rpm_user] = "some_user" subject.attributes[:rpm_group] = "some_group" |
︙ | ︙ | |||
100 101 102 103 104 105 106 | end after :each do subject.cleanup end it "should set the user and group of each file in the RPM" do | | | > > > > > > > > > > > > > > > > > | < > > > > | 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 | end after :each do subject.cleanup end it "should set the user and group of each file in the RPM" do expect(subject.rpmspec).to include('%defattr(-,some_user,some_group,-') end end # context end describe "#output", :if => program_exists?("rpmbuild") do context "architecture" do it "can be basically anything" do subject.name = "example" subject.architecture = "fancypants" subject.version = "1.0" target = Stud::Temporary.pathname # Should not fail. subject.output(target) # Verify the arch tag. rpm = ::RPM::File.new(target) insist { rpm.tags[:arch] } == subject.architecture File.unlink(target) end end context "package attributes" do before :each do @target = Stud::Temporary.pathname subject.name = "name" subject.version = "123" subject.architecture = "all" subject.iteration = "100" subject.epoch = "5" subject.dependencies << "something > 10" subject.dependencies << "hello >= 20" subject.conflicts << "bad < 2" subject.attributes[:rpm_os] = "fancypants" # Make sure multi-line licenses are hacked to work in rpm (#252) subject.license = "this\nis\nan\example" subject.provides << "bacon = 1.0" # TODO(sissel): This api sucks, yo. subject.scripts[:before_install] = "example before_install" subject.scripts[:after_install] = "example after_install" subject.scripts[:before_remove] = "example before_remove" subject.scripts[:after_remove] = "example after_remove" subject.scripts[:rpm_verifyscript] = "example rpm_verifyscript" subject.scripts[:rpm_posttrans] = "example rpm_posttrans" subject.scripts[:rpm_pretrans] = "example rpm_pretrans" # Write the rpm out subject.output(@target) # Read the rpm @rpm = ::RPM::File.new(@target) |
︙ | ︙ | |||
210 211 212 213 214 215 216 217 218 219 220 221 222 223 | insist { @rpm.tags[:preunprog] } == "/bin/sh" end it "should have the correct 'postun' script" do insist { @rpm.tags[:postun] } == "example after_remove" insist { @rpm.tags[:postunprog] } == "/bin/sh" end it "should have the correct 'prein' script" do insist { @rpm.tags[:prein] } == "example before_install" insist { @rpm.tags[:preinprog] } == "/bin/sh" end it "should have the correct 'postin' script" do | > > > > > > > > > > > > > > > | 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 | insist { @rpm.tags[:preunprog] } == "/bin/sh" end it "should have the correct 'postun' script" do insist { @rpm.tags[:postun] } == "example after_remove" insist { @rpm.tags[:postunprog] } == "/bin/sh" end it "should have the correct 'verify' script" do insist { @rpm.tags[:verifyscript] } == "example rpm_verifyscript" insist { @rpm.tags[:verifyscriptprog] } == "/bin/sh" end it "should have the correct 'pretrans' script" do insist { @rpm.tags[:pretrans] } == "example rpm_pretrans" insist { @rpm.tags[:pretransprog] } == "/bin/sh" end it "should have the correct 'posttrans' script" do insist { @rpm.tags[:posttrans] } == "example rpm_posttrans" insist { @rpm.tags[:posttransprog] } == "/bin/sh" end it "should have the correct 'prein' script" do insist { @rpm.tags[:prein] } == "example before_install" insist { @rpm.tags[:preinprog] } == "/bin/sh" end it "should have the correct 'postin' script" do |
︙ | ︙ | |||
238 239 240 241 242 243 244 | insist { [nil, FPM::Package::RPM::DIGEST_ALGORITHM_MAP["md5"]] } \ .include?((@rpmtags[:filedigestalgo].first rescue nil)) end end # package attributes context "package default attributes" do before :each do | | < | 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 | insist { [nil, FPM::Package::RPM::DIGEST_ALGORITHM_MAP["md5"]] } \ .include?((@rpmtags[:filedigestalgo].first rescue nil)) end end # package attributes context "package default attributes" do before :each do @target = Stud::Temporary.pathname subject.name = "name" subject.version = "123" # Write the rpm out subject.output(@target) # Read the rpm @rpm = ::RPM::File.new(@target) |
︙ | ︙ | |||
309 310 311 312 313 314 315 | subject.provides.each do |dep| insist { provides }.include?(dep) end end end # package attributes end # #output | | | | | 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 | subject.provides.each do |dep| insist { provides }.include?(dep) end end end # package attributes end # #output describe "regressions should not occur", :if => program_exists?("rpmbuild") do before :each do @tempfile_handle = @target = Stud::Temporary.pathname subject.name = "name" subject.version = "1.23" end after :each do subject.cleanup File.delete(@target) rescue nil |
︙ | ︙ | |||
389 390 391 392 393 394 395 | insist { rpmtags[:epoch] } == nil # Default release must be '1' insist { rpmtags[:release] } == "1" end end # regression stuff | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | | < | 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 | insist { rpmtags[:epoch] } == nil # Default release must be '1' insist { rpmtags[:release] } == "1" end end # regression stuff describe "rpm_use_file_permissions" do let(:target) { Stud::Temporary.pathname } let(:rpm) { ::RPM::File.new(target) } let(:path) { "hello.txt" } let(:path_stat) { File.lstat(subject.staging_path(path)) } before :each do File.write(subject.staging_path(path), "Hello world") subject.name = "example" subject.version = "1.0" end after :each do subject.cleanup File.delete(target) rescue nil end it "should respect file user and group ownership", :if => program_exists?("rpmbuild") do subject.attributes[:rpm_use_file_permissions?] = true subject.output(target) insist { rpm.tags[:fileusername].first } == Etc.getpwuid(path_stat.uid).name insist { rpm.tags[:filegroupname].first } == Etc.getgrgid(path_stat.gid).name end it "rpm_group should override rpm_use_file_permissions-derived owner", :if => program_exists?("rpmbuild") do subject.attributes[:rpm_use_file_permissions?] = true subject.attributes[:rpm_user] = "hello" subject.attributes[:rpm_group] = "world" subject.output(target) insist { rpm.tags[:fileusername].first } == subject.attributes[:rpm_user] insist { rpm.tags[:filegroupname].first } == subject.attributes[:rpm_group] end end describe "#output with digest and compression settings", :if => program_exists?("rpmbuild") do context "bzip2/sha1" do before :each do @target = Stud::Temporary.pathname subject.name = "name" subject.version = "123" subject.architecture = "all" subject.iteration = "100" subject.epoch = "5" subject.attributes[:rpm_compression] = "bzip2" subject.attributes[:rpm_digest] = "sha1" |
︙ | ︙ |
Changes to spec/fpm/package_convert_spec.rb.
1 2 3 4 5 | require "spec_setup" require "fpm" # local describe "FPM::Package#convert" do | | | | | | > > > | | | | | | | | > > > | > | 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 |
Added spec/fpm/util_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 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 | require "spec_setup" require "fpm" # local require "fpm/util" # local require "stud/temporary" describe FPM::Util do subject do Class.new do include FPM::Util def initialize @logger = Cabin::Channel.new end end.new end context "#copy_entry" do context "when given files that are hardlinks" do it "should keep those files as hardlinks" do Stud::Temporary.directory do |path| a = File.join(path, "a") b = File.join(path, "b") File.write(a, "hello") File.link(a, b) Stud::Temporary.directory do |target| ta = File.join(target, "a") tb = File.join(target, "b") subject.copy_entry(a, ta) subject.copy_entry(b, tb) # This seems to work to compare file stat calls. # target 'a' and 'b' should have the same stat result because # they are linked to the same file. insist { File.lstat(ta) } == File.lstat(tb) end end end end end # #copy_entry describe "#safesystem" do context "with a missing $SHELL" do before do @orig_shell = ENV["SHELL"] ENV.delete("SHELL") end after do ENV["SHELL"] = @orig_shell unless @orig_shell.nil? end it "should assume /bin/sh" do insist { subject.default_shell } == "/bin/sh" end it "should still run commands correctly" do # This will raise an exception if we can't run it at all. subject.safesystem("true") end end context "with $SHELL set to an empty string" do before do @orig_shell = ENV["SHELL"] ENV["SHELL"] = "" end after do ENV["SHELL"] = @orig_shell unless @orig_shell.nil? end it "should assume /bin/sh" do insist { subject.default_shell } == "/bin/sh" end it "should still run commands correctly" do # This will raise an exception if we can't run it at all. subject.safesystem("true") end end end describe "#expand_pessimistic_constraints" do it 'convert 2 piece versions' do constraint = 'bundle ~> 1.2' expected_lower = 'bundle >= 1.2' expected_upper = 'bundle < 2.0' derived_constraint = subject.expand_pessimistic_constraints(constraint) expect(derived_constraint).to include expected_lower expect(derived_constraint).to include expected_upper end it 'convert 3 piece versions' do constraint = 'zippy ~> 1.2.3' expected_lower = 'zippy >= 1.2.3' expected_upper = 'zippy < 1.3.0' derived_constraint = subject.expand_pessimistic_constraints(constraint) expect(derived_constraint).to include expected_lower expect(derived_constraint).to include expected_upper end it 'does not convert where not needed when the operator is > ' do constraint = 'zippy > 1.2.3' derived_constraint = subject.expand_pessimistic_constraints(constraint) expect(derived_constraint).to include constraint end it 'does not convert where not needed when when the operator is < ' do constraint = 'zippy < 1.2.3' derived_constraint = subject.expand_pessimistic_constraints(constraint) expect(derived_constraint).to include constraint end it 'does not convert where not needed when when the operator is <= ' do constraint = 'zippy <= 1.2.3' derived_constraint = subject.expand_pessimistic_constraints(constraint) expect(derived_constraint).to include constraint end it 'does not convert where not needed when when the operator is >= ' do constraint = 'zippy >= 1.2.3' derived_constraint = subject.expand_pessimistic_constraints(constraint) expect(derived_constraint).to include constraint end end end |
Changes to spec/spec_setup.rb.
1 2 3 4 5 6 7 8 9 10 | require "rubygems" # for ruby 1.8 require "insist" # gem "insist" require "cabin" # gem "cabin" require "tmpdir" # stdlib require "tempfile" # stdlib require "fileutils" # stdlib # put "lib" in RUBYLIB $: << File.join(File.dirname(File.dirname(__FILE__)), "lib") | | > > > > > > > | > > > | | 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 | require "rubygems" # for ruby 1.8 require "insist" # gem "insist" require "cabin" # gem "cabin" require "tmpdir" # stdlib require "tempfile" # stdlib require "fileutils" # stdlib # put "lib" in RUBYLIB $: << File.join(File.dirname(File.dirname(__FILE__)), "lib") # for method "program_exists?" etc require "fpm/util" include FPM::Util # Enable debug logs if requested. if $DEBUG or ENV["DEBUG"] Cabin::Channel.get.level = :debug Cabin::Channel.get.subscribe(STDOUT) else class << Cabin::Channel.get alias_method :subscribe_, :subscribe def subscribe(io) return if io == STDOUT subscribe_(io) #puts caller.join("\n") end end end Cabin::Channel.get.level = :error spec_logger = Cabin::Channel.get("rspec") spec_logger.subscribe(STDOUT) spec_logger.level = :error # Quiet the output of all system() calls module Kernel alias_method :orig_system, :system def system(*args) old_stdout = $stdout.clone old_stderr = $stderr.clone |
︙ | ︙ |
Changes to templates/rpm.erb.
︙ | ︙ | |||
37 38 39 40 41 42 43 | Version: <%= version %> <% if epoch -%> Epoch: <%= epoch %> <% end -%> Release: <%= iteration or 1 %> <%# use the first line of the description as the summary -%> Summary: <%= description.split("\n").first.empty? ? "_" : description.split("\n").first %> | < | 37 38 39 40 41 42 43 44 45 46 47 48 49 50 | Version: <%= version %> <% if epoch -%> Epoch: <%= epoch %> <% end -%> Release: <%= iteration or 1 %> <%# use the first line of the description as the summary -%> Summary: <%= description.split("\n").first.empty? ? "_" : description.split("\n").first %> <% if !attributes[:rpm_autoreqprov?] -%> AutoReqProv: no <% else -%> AutoReqProv: yes <% end -%> <% if attributes[:rpm_autoreq?] -%> AutoReq: yes |
︙ | ︙ | |||
105 106 107 108 109 110 111 | %install # noop %clean # noop | | | 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 | %install # noop %clean # noop <%# This next section puts any %pre, %post, %preun, %postun, %verifyscript, %pretrans or %posttrans scripts %> <% if script?(:before_upgrade) or script?(:after_upgrade) -%> <% if script?(:before_upgrade) or script?(:before_install) -%> %pre upgrade() { <% if script?(:before_upgrade) -%> <%= script(:before_upgrade) %> <% end -%> |
︙ | ︙ | |||
163 164 165 166 167 168 169 170 171 | <% if script?(:after_remove) -%> %postun if [ "${1}" -eq 0 ] then <%= script(:after_remove) %> fi <% end -%> <% else -%> <% | > > > > > > > > > > > > > | | | | | > > > | | > | | 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 | <% if script?(:after_remove) -%> %postun if [ "${1}" -eq 0 ] then <%= script(:after_remove) %> fi <% end -%> <% scriptmap = { :rpm_verifyscript => "verifyscript", :rpm_posttrans => "posttrans", :rpm_pretrans => "pretrans" } scriptmap.each do |name, rpmname| -%> <% if script?(name) -%> %<%= rpmname %> <%= script(name) %> <% end -%> <% end -%> <% else -%> <% scriptmap = { :before_install => "pre", :after_install => "post", :before_remove => "preun", :after_remove => "postun", :rpm_verifyscript => "verifyscript", :rpm_posttrans => "posttrans", :rpm_pretrans => "pretrans" } scriptmap.each do |name, rpmname| -%> <% if script?(name) -%> %<%= rpmname %> <%= script(name) %> <% end -%> <% end -%> <% end -%> %files %defattr(<%= attributes[:rpm_defattrfile] %>,<%= attributes[:rpm_user] || "root" %>,<%= attributes[:rpm_group] || "root" %>,<%= attributes[:rpm_defattrdir] %>) <%# Output config files and then regular files. -%> <% config_files.each do |path| -%> %config(noreplace) <%= rpm_file_entry(path) %> <% end -%> <%# list directories %> <% directories.each do |path| -%> %dir <%= rpm_file_entry(path) %> |
︙ | ︙ |
Added templates/sh.erb.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 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 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 | #!/bin/bash # bail out if any part of this fails set -e # This is the self-extracting installer script for an FPM shell installer package. # It contains the logic to unpack a tar archive appended to the end of this script # and, optionally, to run post install logic. # Run the package file with -h to see a usage message or look at the print_usage method. # # The post install scripts are called with INSTALL_ROOT, INSTALL_DIR and VERBOSE exported # into the environment for their use. # # INSTALL_ROOT = the path passed in with -i or a relative directory of the name of the package # file with no extension # INSTALL_DIR = the same as INSTALL_ROOT unless -c (capistrano release directory) argumetn # is used. Then it is $INSTALL_ROOT/releases/<datestamp> # CURRENT_DIR = if -c argument is used, this is set to the $INSTALL_ROOT/current which is # symlinked to INSTALL_DIR # VERBOSE = is set if the package was called with -v for verbose output function main() { set_install_dir create_pid wait_for_others kill_others set_owner unpack_payload if [ "$UNPACK_ONLY" == "1" ] ; then echo "Unpacking complete, not moving symlinks or restarting because unpack only was specified." else create_symlinks set +e # don't exit on errors to allow us to clean up if ! run_post_install ; then revert_symlinks log "Installation failed." exit 1 else clean_out_old_releases log "Installation complete." fi fi } # deletes the PID file for this installation function delete_pid(){ rm -f ${INSTALL_ROOT}/$$.pid 2> /dev/null } # creates a PID file for this installation function create_pid(){ trap "delete_pid" EXIT echo $$> ${INSTALL_ROOT}/$$.pid } # checks for other PID files and sleeps for a grace period if found function wait_for_others(){ local count=`ls ${INSTALL_ROOT}/*.pid | wc -l` if [ $count -gt 1 ] ; then sleep 10 fi } # kills other running installations function kill_others(){ for PID_FILE in $(ls ${INSTALL_ROOT}/*.pid) ; do local p=`cat ${PID_FILE}` if ! [ $p == $$ ] ; then kill -9 $p rm -f $PID_FILE 2> /dev/null fi done } # echos metadata file. A function so that we can have it change after we set INSTALL_ROOT function fpm_metadata_file(){ echo "${INSTALL_ROOT}/.install-metadata" } # if this package was installed at this location already we will find a metadata file with the details # about the installation that we left here. Load from that if available but allow command line args to trump function load_environment(){ local METADATA=$(fpm_metadata_file) if [ -r "${METADATA}" ] ; then log "Found existing metadata file '${METADATA}'. Loading previous install details. Env vars in current environment will take precedence over saved values." local TMP="/tmp/$(basename $0).$$.tmp" # save existing environment, load saved environment from previous run from install-metadata and then # overlay current environment so that anything set currencly will take precedence # but missing values will be loaded from previous runs. save_environment "$TMP" source "${METADATA}" source $TMP rm "$TMP" fi } # write out metadata for future installs function save_environment(){ local METADATA=$1 echo -n "" > ${METADATA} # empty file # just piping env to a file doesn't quote the variables. This does # filter out multiline junk and _. _ is a readonly variable env | egrep "^[^ ]+=.*" | grep -v "^_=" | while read ENVVAR ; do local NAME=${ENVVAR%%=*} # sed is to preserve variable values with dollars (for escaped variables or $() style command replacement), # and command replacement backticks # Escaped parens captures backward reference \1 which gets replaced with backslash and \1 to esape them in the saved # variable value local VALUE=$(eval echo '$'$NAME | sed 's/\([$`]\)/\\\1/g') echo "export $NAME=\"$VALUE\"" >> ${METADATA} done if [ -n "${OWNER}" ] ; then chown ${OWNER} ${METADATA} fi } function set_install_dir(){ # if INSTALL_ROOT isn't set by parsed args, use basename of package file with no extension DEFAULT_DIR=$(echo $(basename $0) | sed -e 's/\.[^\.]*$//') INSTALL_DIR=${INSTALL_ROOT:-$DEFAULT_DIR} DATESTAMP=$(date +%Y%m%d%H%M%S) if [ -z "$USE_FLAT_RELEASE_DIRECTORY" ] ; then <%= "RELEASE_ID=#{release_id}" if respond_to?(:release_id) %> INSTALL_DIR="${RELEASES_DIR}/${RELEASE_ID:-$DATESTAMP}" fi mkdir -p "$INSTALL_DIR" || die "Unable to create install directory $INSTALL_DIR" export INSTALL_DIR log "Installing package to '$INSTALL_DIR'" } function set_owner(){ export OWNER=${OWNER:-$USER} log "Installing as user $OWNER" } function unpack_payload(){ if [ "$FORCE" == "1" ] || [ ! "$(ls -A $INSTALL_DIR)" ] ; then log "Unpacking payload . . ." local archive_line=$(grep -a -n -m1 '__ARCHIVE__$' $0 | sed 's/:.*//') tail -n +$((archive_line + 1)) $0 | tar -C $INSTALL_DIR -xf - > /dev/null || die "Failed to unpack payload from the end of '$0' into '$INSTALL_DIR'" else # Files are already here, just move symlinks log "Directory already exists and has contents ($INSTALL_DIR). Not unpacking payload." fi } function run_post_install(){ local AFTER_INSTALL=$INSTALL_DIR/.fpm/after_install if [ -r $AFTER_INSTALL ] ; then chmod +x $AFTER_INSTALL log "Running post install script" output=$($AFTER_INSTALL 2>&1) errorlevel=$? log $output return $errorlevel fi return 0 } function create_symlinks(){ [ -n "$USE_FLAT_RELEASE_DIRECTORY" ] && return export CURRENT_DIR="$INSTALL_ROOT/current" if [ -e "$CURRENT_DIR" ] ; then OLD_CURRENT_TARGET=$(readlink $CURRENT_DIR) rm "$CURRENT_DIR" fi ln -s "$INSTALL_DIR" "$CURRENT_DIR" log "Symlinked '$INSTALL_DIR' to '$CURRENT_DIR'" } # in case post install fails we may have to back out switching the symlink to current # We can't switch the symlink after because post install may assume that it is in the # exact state of being installed (services looking to current for their latest code) function revert_symlinks(){ if [ -n "$OLD_CURRENT_TARGET" ] ; then log "Putting current symlink back to '$OLD_CURRENT_TARGET'" if [ -e "$CURRENT_DIR" ] ; then rm "$CURRENT_DIR" fi ln -s "$OLD_CURRENT_TARGET" "$CURRENT_DIR" fi } function clean_out_old_releases(){ [ -n "$USE_FLAT_RELEASE_DIRECTORY" ] && return if [ -n "$OLD_CURRENT_TARGET" ] ; then # exclude old 'current' from deletions while [ $(ls -tr "${RELEASES_DIR}" | grep -v ^$(basename "${OLD_CURRENT_TARGET}")$ | wc -l) -gt 2 ] ; do OLDEST_RELEASE=$(ls -tr "${RELEASES_DIR}" | grep -v ^$(basename "${OLD_CURRENT_TARGET}")$ | head -1) log "Deleting old release '${OLDEST_RELEASE}'" rm -rf "${RELEASES_DIR}/${OLDEST_RELEASE}" done else while [ $(ls -tr "${RELEASES_DIR}" | wc -l) -gt 2 ] ; do OLDEST_RELEASE=$(ls -tr "${RELEASES_DIR}" | head -1) log "Deleting old release '${OLDEST_RELEASE}'" rm -rf "${RELEASES_DIR}/${OLDEST_RELEASE}" done fi } function print_usage(){ echo "Usage: `basename $0` [options]" echo "Install this package" echo " -i <DIRECTORY> : install_root - an optional directory to install to." echo " Default is package file name without file extension" echo " -o <USER> : owner - the name of the user that will own the files installed" echo " by the package. Defaults to current user" echo " -r: disable capistrano style release directories - Default behavior is to create a releases directory inside" echo " install_root and unpack contents into a date stamped (or build time id named) directory under the release" echo " directory. Then create a 'current' symlink under install_root to the unpacked" echo " directory once installation is complete replacing the symlink if it already " echo " exists. If this flag is set just install into install_root directly" echo " -u: Unpack the package, but do not install and symlink the payload" echo " -f: force - Always overwrite existing installations" echo " -y: yes - Don't prompt to clobber existing installations" echo " -v: verbose - More output on installation" echo " -h: help - Display this message" } function die () { local message=$* echo "Error: $message : $!" exit 1 } function log(){ local message=$* if [ -n "$VERBOSE" ] ; then echo "$*" fi } function parse_args() { args=`getopt i:o:rfuyvh $*` if [ $? != 0 ] ; then print_usage exit 2 fi set -- $args for i do case "$i" in -r) USE_FLAT_RELEASE_DIRECTORY=1 shift;; -i) shift; export INSTALL_ROOT="$1" export RELEASES_DIR="${INSTALL_ROOT}/releases" shift;; -o) shift; export OWNER="$1" shift;; -v) export VERBOSE=1 shift;; -u) UNPACK_ONLY=1 shift;; -f) FORCE=1 shift;; -y) CONFIRM="y" shift;; -h) print_usage exit 0 shift;; --) shift; break;; esac done } # parse args first to get install root parse_args $* # load environment from previous installations so we get defaults from that load_environment # reparse args so they can override any settings from previous installations if provided on the command line parse_args $* main save_environment $(fpm_metadata_file) exit 0 __ARCHIVE__ |
Changes to test/vagrant.pp.
1 | case $operatingsystem { | | > > > < < < < < < | | 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 | case $operatingsystem { centos, redhat, fedora: { $pkgupdate = "yum clean all" $devsuffix = "devel" } debian, ubuntu: { $pkgupdate = "apt-get update" $devsuffix = "dev" package { "lintian": ensure => latest } } } exec { "update-packages": command => $pkgupdate, path => [ "/bin", "/usr/bin", "/sbin", "/usr/sbin" ]; } package { "git": ensure => latest; "bundler": provider => "gem", ensure => latest; "ruby-$devsuffix": ensure => latest; } Exec["update-packages"] -> Package <| |> |