From 846763e97bb04fdb192a96662839f060d66403cb Mon Sep 17 00:00:00 2001 From: =?utf8?q?Franti=C5=A1ek=20Dvo=C5=99=C3=A1k?= Date: Sun, 23 Mar 2014 22:52:57 +0100 Subject: [PATCH] rubygems-tasks - initial gem2deb package. --- ruby-rubygems-tasks/.document | 5 + ruby-rubygems-tasks/.gitignore | 3 + ruby-rubygems-tasks/.rspec | 1 + ruby-rubygems-tasks/.yardopts | 1 + ruby-rubygems-tasks/ChangeLog.md | 115 +++++++++++++ ruby-rubygems-tasks/LICENSE.txt | 20 +++ ruby-rubygems-tasks/README.md | 117 ++++++++++++++ ruby-rubygems-tasks/Rakefile | 79 +++++++++ ruby-rubygems-tasks/debian/changelog | 5 + ruby-rubygems-tasks/debian/compat | 1 + ruby-rubygems-tasks/debian/control | 19 +++ ruby-rubygems-tasks/debian/copyright | 35 ++++ .../debian/ruby-rubygems-tasks.docs | 2 + ruby-rubygems-tasks/debian/ruby-test-files.yaml | 10 ++ ruby-rubygems-tasks/debian/rules | 15 ++ ruby-rubygems-tasks/debian/source/format | 1 + ruby-rubygems-tasks/debian/watch | 2 + ruby-rubygems-tasks/gemspec.yml | 14 ++ ruby-rubygems-tasks/lib/rubygems/tasks.rb | 9 ++ ruby-rubygems-tasks/lib/rubygems/tasks/build.rb | 3 + .../lib/rubygems/tasks/build/gem.rb | 67 ++++++++ .../lib/rubygems/tasks/build/tar.rb | 51 ++++++ .../lib/rubygems/tasks/build/task.rb | 67 ++++++++ .../lib/rubygems/tasks/build/zip.rb | 49 ++++++ ruby-rubygems-tasks/lib/rubygems/tasks/console.rb | 99 ++++++++++++ ruby-rubygems-tasks/lib/rubygems/tasks/install.rb | 62 +++++++ ruby-rubygems-tasks/lib/rubygems/tasks/printing.rb | 98 +++++++++++ ruby-rubygems-tasks/lib/rubygems/tasks/project.rb | 145 +++++++++++++++++ ruby-rubygems-tasks/lib/rubygems/tasks/push.rb | 79 +++++++++ ruby-rubygems-tasks/lib/rubygems/tasks/release.rb | 49 ++++++ ruby-rubygems-tasks/lib/rubygems/tasks/scm.rb | 3 + ruby-rubygems-tasks/lib/rubygems/tasks/scm/push.rb | 64 ++++++++ .../lib/rubygems/tasks/scm/status.rb | 80 +++++++++ ruby-rubygems-tasks/lib/rubygems/tasks/scm/tag.rb | 179 +++++++++++++++++++++ ruby-rubygems-tasks/lib/rubygems/tasks/sign.rb | 2 + .../lib/rubygems/tasks/sign/checksum.rb | 113 +++++++++++++ ruby-rubygems-tasks/lib/rubygems/tasks/sign/pgp.rb | 50 ++++++ .../lib/rubygems/tasks/sign/task.rb | 58 +++++++ ruby-rubygems-tasks/lib/rubygems/tasks/task.rb | 153 ++++++++++++++++++ ruby-rubygems-tasks/lib/rubygems/tasks/tasks.rb | 147 +++++++++++++++++ ruby-rubygems-tasks/metadata.yml | 146 +++++++++++++++++ ruby-rubygems-tasks/rubygems-tasks.gemspec | 109 +++++++++++++ ruby-rubygems-tasks/spec/console_spec.rb | 78 +++++++++ ruby-rubygems-tasks/spec/install_spec.rb | 16 ++ ruby-rubygems-tasks/spec/project_spec.rb | 159 ++++++++++++++++++ ruby-rubygems-tasks/spec/push_spec.rb | 32 ++++ ruby-rubygems-tasks/spec/rake_context.rb | 10 ++ ruby-rubygems-tasks/spec/scm/push_spec.rb | 35 ++++ ruby-rubygems-tasks/spec/scm/status_spec.rb | 50 ++++++ ruby-rubygems-tasks/spec/scm/tag_spec.rb | 116 +++++++++++++ ruby-rubygems-tasks/spec/sign/pgp_spec.rb | 20 +++ ruby-rubygems-tasks/spec/spec_helper.rb | 12 ++ ruby-rubygems-tasks/spec/tasks_spec.rb | 127 +++++++++++++++ 53 files changed, 2982 insertions(+) create mode 100644 ruby-rubygems-tasks/.document create mode 100644 ruby-rubygems-tasks/.gitignore create mode 100644 ruby-rubygems-tasks/.rspec create mode 100644 ruby-rubygems-tasks/.yardopts create mode 100644 ruby-rubygems-tasks/ChangeLog.md create mode 100644 ruby-rubygems-tasks/LICENSE.txt create mode 100644 ruby-rubygems-tasks/README.md create mode 100644 ruby-rubygems-tasks/Rakefile create mode 100644 ruby-rubygems-tasks/debian/changelog create mode 100644 ruby-rubygems-tasks/debian/compat create mode 100644 ruby-rubygems-tasks/debian/control create mode 100644 ruby-rubygems-tasks/debian/copyright create mode 100644 ruby-rubygems-tasks/debian/ruby-rubygems-tasks.docs create mode 100644 ruby-rubygems-tasks/debian/ruby-test-files.yaml create mode 100755 ruby-rubygems-tasks/debian/rules create mode 100644 ruby-rubygems-tasks/debian/source/format create mode 100644 ruby-rubygems-tasks/debian/watch create mode 100644 ruby-rubygems-tasks/gemspec.yml create mode 100644 ruby-rubygems-tasks/lib/rubygems/tasks.rb create mode 100644 ruby-rubygems-tasks/lib/rubygems/tasks/build.rb create mode 100644 ruby-rubygems-tasks/lib/rubygems/tasks/build/gem.rb create mode 100644 ruby-rubygems-tasks/lib/rubygems/tasks/build/tar.rb create mode 100644 ruby-rubygems-tasks/lib/rubygems/tasks/build/task.rb create mode 100644 ruby-rubygems-tasks/lib/rubygems/tasks/build/zip.rb create mode 100644 ruby-rubygems-tasks/lib/rubygems/tasks/console.rb create mode 100644 ruby-rubygems-tasks/lib/rubygems/tasks/install.rb create mode 100644 ruby-rubygems-tasks/lib/rubygems/tasks/printing.rb create mode 100644 ruby-rubygems-tasks/lib/rubygems/tasks/project.rb create mode 100644 ruby-rubygems-tasks/lib/rubygems/tasks/push.rb create mode 100644 ruby-rubygems-tasks/lib/rubygems/tasks/release.rb create mode 100644 ruby-rubygems-tasks/lib/rubygems/tasks/scm.rb create mode 100644 ruby-rubygems-tasks/lib/rubygems/tasks/scm/push.rb create mode 100644 ruby-rubygems-tasks/lib/rubygems/tasks/scm/status.rb create mode 100644 ruby-rubygems-tasks/lib/rubygems/tasks/scm/tag.rb create mode 100644 ruby-rubygems-tasks/lib/rubygems/tasks/sign.rb create mode 100644 ruby-rubygems-tasks/lib/rubygems/tasks/sign/checksum.rb create mode 100644 ruby-rubygems-tasks/lib/rubygems/tasks/sign/pgp.rb create mode 100644 ruby-rubygems-tasks/lib/rubygems/tasks/sign/task.rb create mode 100644 ruby-rubygems-tasks/lib/rubygems/tasks/task.rb create mode 100644 ruby-rubygems-tasks/lib/rubygems/tasks/tasks.rb create mode 100644 ruby-rubygems-tasks/metadata.yml create mode 100644 ruby-rubygems-tasks/rubygems-tasks.gemspec create mode 100644 ruby-rubygems-tasks/spec/console_spec.rb create mode 100644 ruby-rubygems-tasks/spec/install_spec.rb create mode 100644 ruby-rubygems-tasks/spec/project_spec.rb create mode 100644 ruby-rubygems-tasks/spec/push_spec.rb create mode 100644 ruby-rubygems-tasks/spec/rake_context.rb create mode 100644 ruby-rubygems-tasks/spec/scm/push_spec.rb create mode 100644 ruby-rubygems-tasks/spec/scm/status_spec.rb create mode 100644 ruby-rubygems-tasks/spec/scm/tag_spec.rb create mode 100644 ruby-rubygems-tasks/spec/sign/pgp_spec.rb create mode 100644 ruby-rubygems-tasks/spec/spec_helper.rb create mode 100644 ruby-rubygems-tasks/spec/tasks_spec.rb diff --git a/ruby-rubygems-tasks/.document b/ruby-rubygems-tasks/.document new file mode 100644 index 0000000..bf7d6f2 --- /dev/null +++ b/ruby-rubygems-tasks/.document @@ -0,0 +1,5 @@ +lib/**/*.rb +bin/* +- +ChangeLog.* +LICENSE.txt diff --git a/ruby-rubygems-tasks/.gitignore b/ruby-rubygems-tasks/.gitignore new file mode 100644 index 0000000..4603547 --- /dev/null +++ b/ruby-rubygems-tasks/.gitignore @@ -0,0 +1,3 @@ +doc/ +pkg/ +data/projects/ diff --git a/ruby-rubygems-tasks/.rspec b/ruby-rubygems-tasks/.rspec new file mode 100644 index 0000000..660778b --- /dev/null +++ b/ruby-rubygems-tasks/.rspec @@ -0,0 +1 @@ +--colour --format documentation diff --git a/ruby-rubygems-tasks/.yardopts b/ruby-rubygems-tasks/.yardopts new file mode 100644 index 0000000..1e589cd --- /dev/null +++ b/ruby-rubygems-tasks/.yardopts @@ -0,0 +1 @@ +--markup markdown --title "Gem::Tasks Documentation" --protected diff --git a/ruby-rubygems-tasks/ChangeLog.md b/ruby-rubygems-tasks/ChangeLog.md new file mode 100644 index 0000000..df865d5 --- /dev/null +++ b/ruby-rubygems-tasks/ChangeLog.md @@ -0,0 +1,115 @@ +### 0.2.4 / 2013-04-8 + +* Use the new `Gem::Package` class when running under Ruby 2.0.0. +* Fix `hg showconfig extensions hgext gpg` empty test by ignoring the trailing + new-line (thanks @wrzasa). + +### 0.2.3 / 2012-04-30 + +* {Gem::Tasks::Printing#status} and {Gem::Tasks::Printing#debug} will not + produce output if `Rake.verbose` is false. +* Added specs for {Gem::Tasks::Sign::PGP}. + +#### sign:pgp + +* Generate detached PGP signatures using `--detach-sign`. + +### 0.2.2 / 2012-04-29 + +* Added {Gem::Tasks::Task#invoke}. + +#### build:* + +* Explicitly invoke the `validate` task from within package file tasks. + This prevents package file tasks from always being triggered, due to the + dependency on `validate`. + +### 0.2.1 / 2012-04-29 + +* Overrode the `FileUtils.fu_output_message` to call + {Gem::Tasks::Printing#debug}. +* Added `@api semipublic` tags to mark the semi-public API. +* Fixed a spelling error. + +#### console + +* Infer the primary file to require from the gemspec name. +* No longer run `bundle console`, since it is not the same as running + `bundle exec irb -Ilib -rfoo/bar`. + +#### scm:status + +* Will display the human-readable status, if the repository is dirty. +* Hooks into the `validate` task. + +#### scm:push + +* Depends on the `validate` task. + +#### scm:tag + +* Depends on the `validate` task. + +#### build:* + +* All `build:*` tasks now depend on the `validate` task. + +#### push + +* Depends on the `validate` task. + +### 0.2.0 / 2012-04-27 + +* Removed `Gem::Tasks::Task.task_name`. + +#### scm:status + +* Now ignores untracked files. +* Will prevent any packages from being built, if the repository is dirty. + +#### scm:tag + +* Now create `v` prefixed version tags by default. +* Now supports creating PGP signed Git/Mercurial tags. +* {Gem::Tasks::SCM::Tag#initialize} now accepts the `:sign` option, + for enabling/disabling tag signing on a per-project basis. +* Added {Gem::Tasks::SCM::Tag#sign?} and {Gem::Tasks::SCM::Tag#sign=}. + +### 0.1.2 / 2012-04-26 + +#### scm:push + +* Now runs `git push` then `git push --tags`. + +### 0.1.1 / 2012-04-26 + +#### console + +* require `rubygems` on Ruby 1.8. +* require the first `lib/` file to load the project. + +#### sign:pgp + +* Now creates ASCII armored signatures. + +### 0.1.0 / 2012-04-24 + +* Initial release: + * Added {Gem::Tasks::Project}. + * Added {Gem::Tasks::Printing}. + * Added {Gem::Tasks::Task}. + * Added {Gem::Tasks::Build::Task}. + * Added {Gem::Tasks::Build::Gem}. + * Added {Gem::Tasks::Build::Tar}. + * Added {Gem::Tasks::Build::Zip}. + * Added {Gem::Tasks::SCM::Push}. + * Added {Gem::Tasks::SCM::Status}. + * Added {Gem::Tasks::SCM::Tag}. + * Added {Gem::Tasks::Sign::Task}. + * Added {Gem::Tasks::Sign::Checksum}. + * Added {Gem::Tasks::Sign::PGP}. + * Added {Gem::Tasks::Console}. + * Added {Gem::Tasks::Install}. + * Added {Gem::Tasks::Push}. + * Added {Gem::Tasks::Release}. + * Added {Gem::Tasks}. diff --git a/ruby-rubygems-tasks/LICENSE.txt b/ruby-rubygems-tasks/LICENSE.txt new file mode 100644 index 0000000..9988fd3 --- /dev/null +++ b/ruby-rubygems-tasks/LICENSE.txt @@ -0,0 +1,20 @@ +Copyright (c) 2011-2013 Hal Brodigan + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/ruby-rubygems-tasks/README.md b/ruby-rubygems-tasks/README.md new file mode 100644 index 0000000..dd0b1e2 --- /dev/null +++ b/ruby-rubygems-tasks/README.md @@ -0,0 +1,117 @@ +# rubygems-tasks + +* [Source](https://github.com/postmodern/rubygems-tasks) +* [Issues](https://github.com/postmodern/rubygems-tasks/issues) +* [Email](mailto:postmodern.mod3 at gmail.com) + +## Description + +rubygems-tasks provides agnostic and unobtrusive Rake tasks for building, +installing and releasing Ruby Gems. + + require 'rubygems/tasks' + Gem::Tasks.new + +## Philosophy + +The Rake tasks which you use to manage a Ruby project should not be coupled +to the project generator which you used to create the project. +Project generators have nothing to do with the Rake tasks used to build, +install and release a Ruby project. + +Recently, many Ruby Developers began creating Ruby projects by hand, +building/releasing RubyGems using `gem build` / `gem push`. Sometimes this +resulted in RubyGems being released with uncommitted changes, or the developer +forgetting to tag the release. Ruby Developers should have access to +**agnostic** and **unobtrusive** Rake tasks, to **automate** the release +process. + +This is what rubygems-tasks seeks to provide. + +## Features + +* Provides tasks to build, install and push gems to [rubygems.org]. + * Loads all project metadata from the `.gemspec` file. + * Supports loading multiple `.gemspec` files. + * Supports pushing gems to alternate [Gemcutter] servers. +* Supports optionally building `.tar.gz` and `.zip` archives. + * `build:tar` + * `build:zip` +* Supports [Git], [Mercurial] and [SubVersion] Source-Code-Managers + (SCMs). + * Supports creating PGP signed Git/Mercurial tags. +* Provides optional `sign` tasks for package integrity: + * `sign:checksum` + * `sign:pgp` +* Provides a `console` task, for jumping right into your code. +* Defines task aliases for users coming from [Jeweler] or [Hoe]. +* ANSI coloured messages! + +## Anti-Features + +* **Does not** parse project metadata from the README or the ChangeLog. +* **Does not** generate or modify code. +* **Does not** automatically commit changes. +* **Does not** inject dependencies into gems. +* **Zero** dependencies. + +## Install + + $ gem install rubygems-tasks + +## Examples + +Specifying an alternate Ruby Console to run: + + Gem::Tasks.new do |tasks| + tasks.console.command = 'pry' + end + +Enable pushing gems to an in-house [Gemcutter] server: + + Gem::Tasks.new do |tasks| + tasks.push.host = 'gems.company.com' + end + +Disable the `push` task: + + Gem::Tasks.new(:push => false) + +Enable building `.tar.gz` and `.zip` archives: + + Gem::Tasks.new(:build => {:tar => true, :zip => true}) + +Enable Checksums and PGP signatures for built packages: + + Gem::Tasks.new(:sign => {:checksum => true, :pgp => true}) + +Selectively defining tasks: + + Gem::Build::Tar.new + Gem::SCM::Status.new + Gem::SCM::Tag.new(:format => 'REL-%s') + Gem::Sign::Checksum.new + Gem::Console.new + +## Synopsis + + rake build # Builds all packages + rake console # Spawns an Interactive Ruby Console + rake install # Installs all built gem packages + rake release # Performs a release + +## Copyright + +Copyright (c) 2011-2013 Hal Brodigan + +See {file:LICENSE.txt} for details. + +[Git]: http://git-scm.com/ +[Mercurial]: http://mercurial.selenic.com/ +[SubVersion]: http://subversion.tigris.org/ + +[Jeweler]: https://github.com/technicalpickles/jeweler#readme +[Hoe]: https://github.com/seattlerb/hoe#readme + +[rubygems.org]: https://rubygems.org/ +[Gemcutter]: https://github.com/rubygems/rubygems.org#readme diff --git a/ruby-rubygems-tasks/Rakefile b/ruby-rubygems-tasks/Rakefile new file mode 100644 index 0000000..0edb5e3 --- /dev/null +++ b/ruby-rubygems-tasks/Rakefile @@ -0,0 +1,79 @@ +require 'rubygems' +require 'rake' + +lib_dir = File.expand_path('lib',File.dirname(__FILE__)) +$LOAD_PATH << lib_dir unless $LOAD_PATH.include?(lib_dir) + +require 'rubygems/tasks' +Gem::Tasks.new( + :build => {:gem => true, :tar => true}, + :sign => {:checksum => true, :pgp => true} +) + +begin + gem 'rspec', '~> 2.4' + require 'rspec/core/rake_task' + + RSpec::Core::RakeTask.new +rescue LoadError + task :spec do + abort "Please run `gem install rspec` to install RSpec." + end +end +task :test => :spec +task :default => :spec + +begin + gem 'yard', '~> 0.7' + require 'yard' + + YARD::Rake::YardocTask.new +rescue LoadError => e + task :yard do + abort 'Please run `gem install yard` to install YARD.' + end +end + +require 'net/https' +require 'uri' + +DOWNLOAD_URI = 'http://cloud.github.com/downloads/postmodern/rubygems-tasks/' +PROJECTS_DIR = File.join('data','projects') +PROJECTS = %w[rubygems-project rubygems-multi-project bundler-project] + +directory PROJECTS_DIR + +PROJECTS.each do |project| + project_file = "#{project}.tar.gz" + project_path = File.join(PROJECTS_DIR,project_file) + project_dir = File.join(PROJECTS_DIR,project) + + file project_path => PROJECTS_DIR do + Net::HTTP.get_response(URI(DOWNLOAD_URI + project_file)) do |response| + size, total = 0, response.header['Content-Length'].to_i + + puts ">>> Downloading to #{project_file} to #{project_path} ..." + + File.open(project_path,"wb") do |file| + response.read_body do |chunk| + file.write(chunk) + + size += chunk.size + printf "\r>>> [%d / %d] %d%% ...", size, total, ((size * 100) / total) + end + end + + puts + end + end + + task project_dir => project_path do + unless File.directory?(project_dir) + sh 'tar', 'xzf', project_path, '-C', PROJECTS_DIR + end + end + + task 'data:projects' => project_dir +end + +task :spec => 'data:projects' diff --git a/ruby-rubygems-tasks/debian/changelog b/ruby-rubygems-tasks/debian/changelog new file mode 100644 index 0000000..89596a4 --- /dev/null +++ b/ruby-rubygems-tasks/debian/changelog @@ -0,0 +1,5 @@ +ruby-rubygems-tasks (0.2.4-1) UNRELEASED; urgency=medium + + * Initial release (Closes: #nnnn) + + -- František Dvořák Sun, 23 Mar 2014 22:50:41 +0100 diff --git a/ruby-rubygems-tasks/debian/compat b/ruby-rubygems-tasks/debian/compat new file mode 100644 index 0000000..7f8f011 --- /dev/null +++ b/ruby-rubygems-tasks/debian/compat @@ -0,0 +1 @@ +7 diff --git a/ruby-rubygems-tasks/debian/control b/ruby-rubygems-tasks/debian/control new file mode 100644 index 0000000..5933b8e --- /dev/null +++ b/ruby-rubygems-tasks/debian/control @@ -0,0 +1,19 @@ +Source: ruby-rubygems-tasks +Section: ruby +Priority: optional +Maintainer: Debian Ruby Extras Maintainers +Uploaders: František Dvořák +Build-Depends: debhelper (>= 7.0.50~), gem2deb (>= 0.6.1~) +Standards-Version: 3.9.4 +#Vcs-Git: git://anonscm.debian.org/pkg-ruby-extras/ruby-rubygems-tasks.git +#Vcs-Browser: http://anonscm.debian.org/gitweb/?p=pkg-ruby-extras/ruby-rubygems-tasks.git;a=summary +Homepage: https://github.com/postmodern/rubygems-tasks#readme +XS-Ruby-Versions: all + +Package: ruby-rubygems-tasks +Architecture: all +XB-Ruby-Versions: ${ruby:Versions} +Depends: ${shlibs:Depends}, ${misc:Depends}, ruby | ruby-interpreter +# rspec (~> 2.4, development), yard (~> 0.7, development) +Description: Rake tasks for managing and releasing Ruby Gems. + Agnostic and unobtrusive Rake tasks for managing and releasing Ruby Gems. diff --git a/ruby-rubygems-tasks/debian/copyright b/ruby-rubygems-tasks/debian/copyright new file mode 100644 index 0000000..c2e9b7d --- /dev/null +++ b/ruby-rubygems-tasks/debian/copyright @@ -0,0 +1,35 @@ +Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ +Upstream-Name: rubygems-tasks +Source: FIXME + +Files: * +Copyright: + +License: GPL-2+ (FIXME) + +Files: debian/* +Copyright: 2014 František Dvořák +License: GPL-2+ (FIXME) +Comment: the Debian packaging is licensed under the same terms as the original package. + +License: GPL-2+ (FIXME) + This program is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later + version. + . + This program is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied + warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the GNU General Public License for more + details. + . + You should have received a copy of the GNU General Public + License along with this package; if not, write to the Free + Software Foundation, Inc., 51 Franklin St, Fifth Floor, + Boston, MA 02110-1301 USA + . + On Debian systems, the full text of the GNU General Public + License version 2 can be found in the file + `/usr/share/common-licenses/GPL-2'. diff --git a/ruby-rubygems-tasks/debian/ruby-rubygems-tasks.docs b/ruby-rubygems-tasks/debian/ruby-rubygems-tasks.docs new file mode 100644 index 0000000..07b3c9e --- /dev/null +++ b/ruby-rubygems-tasks/debian/ruby-rubygems-tasks.docs @@ -0,0 +1,2 @@ +# FIXME: READMEs found +# README.md diff --git a/ruby-rubygems-tasks/debian/ruby-test-files.yaml b/ruby-rubygems-tasks/debian/ruby-test-files.yaml new file mode 100644 index 0000000..8de9577 --- /dev/null +++ b/ruby-rubygems-tasks/debian/ruby-test-files.yaml @@ -0,0 +1,10 @@ +--- +- spec/console_spec.rb +- spec/install_spec.rb +- spec/project_spec.rb +- spec/push_spec.rb +- spec/scm/push_spec.rb +- spec/scm/status_spec.rb +- spec/scm/tag_spec.rb +- spec/sign/pgp_spec.rb +- spec/tasks_spec.rb diff --git a/ruby-rubygems-tasks/debian/rules b/ruby-rubygems-tasks/debian/rules new file mode 100755 index 0000000..82ddc0c --- /dev/null +++ b/ruby-rubygems-tasks/debian/rules @@ -0,0 +1,15 @@ +#!/usr/bin/make -f +#export DH_VERBOSE=1 +# +# Uncomment to ignore all test failures (but the tests will run anyway) +#export DH_RUBY_IGNORE_TESTS=all +# +# Uncomment to ignore some test failures (but the tests will run anyway). +# Valid values: +#export DH_RUBY_IGNORE_TESTS=ruby1.9.1 ruby2.0 require-rubygems +# +# If you need to specify the .gemspec (eg there is more than one) +#export DH_RUBY_GEMSPEC=gem.gemspec + +%: + dh $@ --buildsystem=ruby --with ruby diff --git a/ruby-rubygems-tasks/debian/source/format b/ruby-rubygems-tasks/debian/source/format new file mode 100644 index 0000000..163aaf8 --- /dev/null +++ b/ruby-rubygems-tasks/debian/source/format @@ -0,0 +1 @@ +3.0 (quilt) diff --git a/ruby-rubygems-tasks/debian/watch b/ruby-rubygems-tasks/debian/watch new file mode 100644 index 0000000..61d78d7 --- /dev/null +++ b/ruby-rubygems-tasks/debian/watch @@ -0,0 +1,2 @@ +version=3 +http://pkg-ruby-extras.alioth.debian.org/cgi-bin/gemwatch/rubygems-tasks .*/rubygems-tasks-(.*).tar.gz diff --git a/ruby-rubygems-tasks/gemspec.yml b/ruby-rubygems-tasks/gemspec.yml new file mode 100644 index 0000000..7cb9b18 --- /dev/null +++ b/ruby-rubygems-tasks/gemspec.yml @@ -0,0 +1,14 @@ +name: rubygems-tasks +version: 0.2.4 +summary: Rake tasks for managing and releasing Ruby Gems. +description: + Agnostic and unobtrusive Rake tasks for managing and releasing Ruby Gems. + +authors: Postmodern +email: postmodern.mod3@gmail.com +homepage: https://github.com/postmodern/rubygems-tasks#readme +has_yard: true + +development_dependencies: + rspec: ~> 2.4 + yard: ~> 0.7 diff --git a/ruby-rubygems-tasks/lib/rubygems/tasks.rb b/ruby-rubygems-tasks/lib/rubygems/tasks.rb new file mode 100644 index 0000000..29e5a82 --- /dev/null +++ b/ruby-rubygems-tasks/lib/rubygems/tasks.rb @@ -0,0 +1,9 @@ +require 'rubygems/tasks/console' +require 'rubygems/tasks/build' +require 'rubygems/tasks/install' +require 'rubygems/tasks/scm' +require 'rubygems/tasks/scm' +require 'rubygems/tasks/push' +require 'rubygems/tasks/release' +require 'rubygems/tasks/sign' +require 'rubygems/tasks/tasks' diff --git a/ruby-rubygems-tasks/lib/rubygems/tasks/build.rb b/ruby-rubygems-tasks/lib/rubygems/tasks/build.rb new file mode 100644 index 0000000..21f29bc --- /dev/null +++ b/ruby-rubygems-tasks/lib/rubygems/tasks/build.rb @@ -0,0 +1,3 @@ +require 'rubygems/tasks/build/tar' +require 'rubygems/tasks/build/gem' +require 'rubygems/tasks/build/zip' diff --git a/ruby-rubygems-tasks/lib/rubygems/tasks/build/gem.rb b/ruby-rubygems-tasks/lib/rubygems/tasks/build/gem.rb new file mode 100644 index 0000000..c399122 --- /dev/null +++ b/ruby-rubygems-tasks/lib/rubygems/tasks/build/gem.rb @@ -0,0 +1,67 @@ +require 'rubygems/tasks/build/task' + +require 'fileutils' + +if Gem::VERSION > '2.' then require 'rubygems/package' +else require 'rubygems/builder' +end + +module Gem + class Tasks + module Build + # + # The `build:gem` task. + # + class Gem < Task + + # + # Initializes the `build:gem` task. + # + # @param [Hash] options + # Additional options. + # + def initialize(options={}) + super() + + yield self if block_given? + define + end + + # + # Defines the `build:gem` task. + # + def define + build_task :gem + + # backwards compatibility for Gem::PackageTask + task :gem => 'build:gem' + + # backwards compatibility for Hoe + task :package => 'build:gem' + end + + # + # Builds the `.gem` package. + # + # @param [String] path + # The path for the `.gem` package. + # + # @param [Gem::Specification] gemspec + # The gemspec to build the `.gem` package from. + # + # @api semipublic + # + def build(path,gemspec) + gem = if ::Gem::VERSION > '2.' + ::Gem::Package.build(gemspec) + else + ::Gem::Builder.new(gemspec).build + end + + mv gem, Project::PKG_DIR + end + + end + end + end +end diff --git a/ruby-rubygems-tasks/lib/rubygems/tasks/build/tar.rb b/ruby-rubygems-tasks/lib/rubygems/tasks/build/tar.rb new file mode 100644 index 0000000..47414b0 --- /dev/null +++ b/ruby-rubygems-tasks/lib/rubygems/tasks/build/tar.rb @@ -0,0 +1,51 @@ +require 'rubygems/tasks/build/task' + +require 'set' + +module Gem + class Tasks + module Build + # + # The `build:tar` task. + # + class Tar < Task + + # + # Initializes the `build:tar` task. + # + # @param [Hash] options + # Additional options. + # + def initialize(options={}) + super() + + yield self if block_given? + define + end + + # + # Defines the `build:tar` task. + # + def define + build_task :tar, 'tar.gz' + end + + # + # Builds a `.tar.gz` archive. + # + # @param [String] path + # The path for the `.tar.gz` archive. + # + # @param [Gem::Specification] gemspec + # The gemspec to generate the archive from. + # + # @api semipublic + # + def build(path,gemspec) + run 'tar', 'czf', path, *gemspec.files + end + + end + end + end +end diff --git a/ruby-rubygems-tasks/lib/rubygems/tasks/build/task.rb b/ruby-rubygems-tasks/lib/rubygems/tasks/build/task.rb new file mode 100644 index 0000000..0ab4184 --- /dev/null +++ b/ruby-rubygems-tasks/lib/rubygems/tasks/build/task.rb @@ -0,0 +1,67 @@ +require 'rubygems/tasks/task' + +module Gem + class Tasks + module Build + class Task < Tasks::Task + + # + # @param [String] path + # + # @param [Gem::Specification] gemspec + # + # @abstract + # + def build(path,gemspec) + end + + protected + + # + # Defines build task(s) for file type. + # + # @param [Symbol] name + # The name for the task(s). + # + # @param [String, Symbol] extname + # The file extension for the resulting files. + # + # @api semipublic + # + def build_task(name,extname=name) + directory Project::PKG_DIR + + task :validate + + @project.builds.each do |build,packages| + namespace :build do + namespace name do + gemspec = @project.gemspecs[build] + path = packages[extname] + + # define file tasks, so the packages are not needless re-built + file(path => [Project::PKG_DIR, *gemspec.files]) do + invoke :validate + + status "Building #{File.basename(path)} ..." + + build(path,gemspec) + end + + task build => path + end + end + + task "build:#{build}" => "build:#{name}:#{build}" + end + + gemspec_tasks "build:#{name}" + + desc "Builds all packages" unless task?(:build) + task :build => "build:#{name}" + end + + end + end + end +end diff --git a/ruby-rubygems-tasks/lib/rubygems/tasks/build/zip.rb b/ruby-rubygems-tasks/lib/rubygems/tasks/build/zip.rb new file mode 100644 index 0000000..e5f9a00 --- /dev/null +++ b/ruby-rubygems-tasks/lib/rubygems/tasks/build/zip.rb @@ -0,0 +1,49 @@ +require 'rubygems/tasks/build/task' + +module Gem + class Tasks + module Build + # + # The `build:zip` task. + # + class Zip < Task + + # + # Initializes the `build:zip` task. + # + # @param [Hash] options + # Additional options. + # + def initialize(options={}) + super() + + yield self if block_given? + define + end + + # + # Defines the `build:zip` task. + # + def define + build_task :zip + end + + # + # Builds the `.zip` archive. + # + # @param [String] path + # The path for the `.zip` archive. + # + # @param [Gem::Specification] gemspec + # The gemspec to build the archive from. + # + # @api semipublic + # + def build(path,gemspec) + run 'zip', '-q', path, *gemspec.files + end + + end + end + end +end diff --git a/ruby-rubygems-tasks/lib/rubygems/tasks/console.rb b/ruby-rubygems-tasks/lib/rubygems/tasks/console.rb new file mode 100644 index 0000000..3283e5b --- /dev/null +++ b/ruby-rubygems-tasks/lib/rubygems/tasks/console.rb @@ -0,0 +1,99 @@ +require 'rubygems/tasks/task' + +module Gem + class Tasks + # + # The `console` task. + # + class Console < Task + + # The default Interactive Ruby Console + DEFAULT_CONSOLE = 'irb' + + # The default command to run + DEFAULT_COMMAND = (ENV['RUBYCONSOLE'] || DEFAULT_CONSOLE) + + # The Ruby Console command + attr_accessor :command + + # Additional options for the Ruby Console + attr_accessor :options + + # + # Initializes the `console` task. + # + # @param [Hash] options + # Additional options. + # + # @option options [String] :command (DEFAULT_COMMAND) + # The Ruby Console command to run. + # + # @option options [Array] :options + # Additional options for the Ruby Console. + # + def initialize(options={}) + super() + + @command = options.fetch(:command,DEFAULT_COMMAND) + @options = Array(options[:options]) + + yield self if block_given? + define + end + + # + # Defines the `console` task. + # + def define + @project.gemspecs.each_key do |name| + namespace :console do + task(name) { console(name) } + end + end + + desc "Spawns an Interactive Ruby Console" + task :console => "console:#{@project.primary_gemspec}" + end + + # + # Builds the complete arguments for the console command. + # + # @param [Symbol, String] name + # The name of the gemspec to load. + # + # @return [Array] + # The arguments for the console command. + # + # @api semipublic + # + def console(name=nil) + gemspec = @project.gemspec(name) + + require_paths = gemspec.require_paths + require_file = gemspec.name.gsub('-',File::SEPARATOR) + + arguments = [@command] + + # add -I options for lib/ or ext/ directories + arguments.push(*require_paths.map { |dir| "-I#{dir}" }) + + # add a -rrubygems to explicitly load rubygems on Ruby 1.8 + arguments.push('-rrubygems') if RUBY_VERSION < '1.9' + + # add an -r option to require the library + arguments.push('-r' + require_file) + + # push on additional options + arguments.push(*@options) + + if @project.bundler? + # run under `bundle exec` + arguments.unshift('bundle', 'exec') + end + + return run(*arguments) + end + + end + end +end diff --git a/ruby-rubygems-tasks/lib/rubygems/tasks/install.rb b/ruby-rubygems-tasks/lib/rubygems/tasks/install.rb new file mode 100644 index 0000000..e4c3107 --- /dev/null +++ b/ruby-rubygems-tasks/lib/rubygems/tasks/install.rb @@ -0,0 +1,62 @@ +require 'rubygems/tasks/task' + +module Gem + class Tasks + # + # The `install` task. + # + class Install < Task + + # + # Initializes the `install` task. + # + # @param [Hash] options + # Additional options. + # + def initialize(options={}) + super() + + yield self if block_given? + define + end + + # + # Defines the `install` task. + # + def define + namespace :install do + @project.builds.each do |build,packages| + path = packages[:gem] + + task build => path do + status "Installing #{File.basename(path)} ..." + + install(path) + end + end + end + + desc "Installs all built gem packages" + gemspec_tasks :install + + task :install_gem => :install # backwards compatibility with Hoe + end + + # + # Pushes the gem by running `gem install`. + # + # @param [String] path + # The path to the `.gem` file. + # + # @return [Boolean] + # Specifies whether `gem install` was successful or not. + # + # @api semipublic + # + def install(path) + run 'gem', 'install', '-q', path + end + + end + end +end diff --git a/ruby-rubygems-tasks/lib/rubygems/tasks/printing.rb b/ruby-rubygems-tasks/lib/rubygems/tasks/printing.rb new file mode 100644 index 0000000..cb918c8 --- /dev/null +++ b/ruby-rubygems-tasks/lib/rubygems/tasks/printing.rb @@ -0,0 +1,98 @@ +module Gem + class Tasks + # + # Provides helper methods for printing messages. + # + # @api semipublic + # + module Printing + + # ANSI 'bright' color code + ANSI_BRIGHT = "\e[1m" + + # ANSI 'clear' color code + ANSI_CLEAR = "\e[0m" + + # ANSI 'green' color code + ANSI_GREEN = "\e[32m" + + # ANSI 'yellow' color code + ANSI_YELLOW = "\e[33m" + + # ANSI 'red' color code + ANSI_RED = "\e[31m" + + # Prefix for all status messages + STATUS_PREFIX = if $stdout.tty? + "#{ANSI_GREEN}#{ANSI_BRIGHT}>>>#{ANSI_CLEAR}" + else + ">>>" + end + + # Prefix for all debugging messages + DEBUG_PREFIX = if $stderr.tty? + "#{ANSI_YELLOW}#{ANSI_BRIGHT}>>>#{ANSI_CLEAR}" + else + ">>>" + end + + # Prefix for all error messages + ERROR_PREFIX = if $stderr.tty? + "#{ANSI_RED}#{ANSI_BRIGHT}!!!#{ANSI_CLEAR}" + else + "!!!" + end + + protected + + # + # Prints a status message. + # + # @param [String] message + # The message to print. + # + def status(message) + if Rake.verbose + $stdout.puts "#{STATUS_PREFIX} #{message}" + end + end + + # + # Prints a debugging message. + # + # @param [String] message + # The message to print. + # + def debug(message) + if (Rake.verbose && Rake.application.options.trace) + $stderr.puts "#{DEBUG_PREFIX} #{message}" + end + end + + # + # Prints an error message and exits. + # + # @param [String] message + # The message to print. + # + def error(message) + $stderr.puts "#{ERROR_PREFIX} #{message}" + end + + private + + # + # The FileUtils output method. + # + # @param [String] message + # The FileUtils message to print. + # + # @since 0.2.1 + # + def fu_output_message(message) + debug(message) + end + + end + end +end diff --git a/ruby-rubygems-tasks/lib/rubygems/tasks/project.rb b/ruby-rubygems-tasks/lib/rubygems/tasks/project.rb new file mode 100644 index 0000000..ffc4b7f --- /dev/null +++ b/ruby-rubygems-tasks/lib/rubygems/tasks/project.rb @@ -0,0 +1,145 @@ +require 'set' + +module Gem + class Tasks + # + # @api semipublic + # + class Project + + # Supported SCMs and their control directories. + SCM_DIRS = { + :git => '.git', + :hg => '.hg', + :svn => '.svn' + } + + # The `pkg/` directory. + PKG_DIR = 'pkg' + + # + # The project directory. + # + # @return [String] + # The path to the project. + # + attr_reader :root + + # + # The name of the project. + # + # @return [String] + # The project name. + # + attr_reader :name + + # + # @return [Symbol, nil] + # The SCM the project is using. + # + attr_reader :scm + + # + # The builds and gemspecs of the project. + # + # @return [Hash{String => Gem::Specification}] + # The hash of builds and their gemspecs. + # + attr_reader :gemspecs + + # + # The builds and their packages. + # + # @return [Hash{String => Hash{String => String}}] + # The hash of builds and their respective packages. + # + attr_reader :builds + + # + # The name of the primary gemspec. + # + # @return [String] + # The gemspec name. + # + attr_reader :primary_gemspec + + # + # Initializes the project. + # + # @param [String] root + # The root directory of the project. + # + def initialize(root=Dir.pwd) + @root = root + @name = File.basename(@root) + + @scm, _ = SCM_DIRS.find do |scm,dir| + File.directory?(File.join(@root,dir)) + end + + Dir.chdir(@root) do + @gemspecs = Hash[Dir['*.gemspec'].map { |path| + [File.basename(path,'.gemspec'), Specification.load(path)] + }] + end + + @primary_gemspec = if @gemspecs.has_key?(@name) + @name + else + @gemspecs.keys.sort.first + end + + @builds = {} + + @gemspecs.each do |name,gemspec| + @builds[name] = Hash.new do |packages,format| + packages[format] = File.join(PKG_DIR,"#{gemspec.full_name}.#{format}") + end + end + + @bundler = File.file?(File.join(@root,'Gemfile')) + end + + # + # Retrieves a gemspec for the project. + # + # @param [String] name (@primary_gemspec) + # The gemspec name to retrieve. + # + # @return [Gem::Specification] + # The requested gemspec. + # + def gemspec(name=nil) + name ||= @primary_gemspec + + unless @gemspecs.has_key?(name) + raise(ArgumentError,"unknown gemspec: #{name}") + end + + return @gemspecs[name] + end + + # + # Maps project directories to projects. + # + # @return [Hash{String => Project}] + # Project directories and project objects. + # + def self.directories + @@directories ||= Hash.new do |hash,key| + hash[key] = new(key) + end + end + + # + # Specifies whether the project uses Bundler. + # + # @return [Boolean] + # + def bundler? + @bundler + end + + end + end +end diff --git a/ruby-rubygems-tasks/lib/rubygems/tasks/push.rb b/ruby-rubygems-tasks/lib/rubygems/tasks/push.rb new file mode 100644 index 0000000..ed760cd --- /dev/null +++ b/ruby-rubygems-tasks/lib/rubygems/tasks/push.rb @@ -0,0 +1,79 @@ +require 'rubygems/tasks/task' + +module Gem + class Tasks + # + # The `push` task. + # + class Push < Task + + # The Gemcutter host to push gems to. + attr_accessor :host + + # + # Initializes the `push` task. + # + # @param [Hash] options + # Additional options. + # + # @option options [String] :host + # The Gemcutter host to push gems to. + # + def initialize(options={}) + super() + + @host = options[:host] + + yield self if block_given? + define + end + + # + # Defines the `push` task. + # + def define + task :validate + + namespace :push do + @project.builds.each do |build,packages| + path = packages[:gem] + + task build => [:validate, path] do + if @host + status "Pushing #{File.basename(path)} to #{@host} ..." + else + status "Pushing #{File.basename(path)} ..." + end + + push(path) + end + end + end + + gemspec_tasks :push + + # backwards compatibility for Hoe + task :publish => :push + end + + # + # Pushes the gem by running `gem push`. + # + # @param [String] path + # The path to the `.gem` file. + # + # @return [Boolean] + # Specifies whether `gem push` was successful or not. + # + # @api semipublic + # + def push(path) + arguments = ['gem', 'push', path] + arguments.push('--host', @host) if @host + + return run(*arguments) + end + + end + end +end diff --git a/ruby-rubygems-tasks/lib/rubygems/tasks/release.rb b/ruby-rubygems-tasks/lib/rubygems/tasks/release.rb new file mode 100644 index 0000000..588f93e --- /dev/null +++ b/ruby-rubygems-tasks/lib/rubygems/tasks/release.rb @@ -0,0 +1,49 @@ +require 'rubygems/tasks/task' + +module Gem + class Tasks + # + # The `release` task. + # + class Release < Task + + # + # Initializes the `release` task. + # + # @param [Hash] options + # Additional options for the `release` task. + # + def initialize(options={}) + super() + + yield self if block_given? + define + end + + # + # Defines the `release` task. + # + def define + @project.gemspecs.each_key do |name| + task :release => [ + "build:#{name}", + 'scm:tag', + 'scm:push', + "push:#{name}", + "sign:#{name}" + ].select { |name| task?(name) } + end + + desc "Performs a release" + task :release => [ + :build, + 'scm:tag', + 'scm:push', + :push, + :sign + ].select { |name| task?(name) } + end + + end + end +end diff --git a/ruby-rubygems-tasks/lib/rubygems/tasks/scm.rb b/ruby-rubygems-tasks/lib/rubygems/tasks/scm.rb new file mode 100644 index 0000000..4c3c655 --- /dev/null +++ b/ruby-rubygems-tasks/lib/rubygems/tasks/scm.rb @@ -0,0 +1,3 @@ +require 'rubygems/tasks/scm/status' +require 'rubygems/tasks/scm/tag' +require 'rubygems/tasks/scm/push' diff --git a/ruby-rubygems-tasks/lib/rubygems/tasks/scm/push.rb b/ruby-rubygems-tasks/lib/rubygems/tasks/scm/push.rb new file mode 100644 index 0000000..af4048e --- /dev/null +++ b/ruby-rubygems-tasks/lib/rubygems/tasks/scm/push.rb @@ -0,0 +1,64 @@ +require 'rubygems/tasks/task' + +module Gem + class Tasks + module SCM + # + # The `scm:push` task. + # + class Push < Task + + # + # Initializes the `scm:push` task. + # + # @param [Hash] options + # Additional options. + # + def initialize(options={}) + super() + + yield self if block_given? + define + end + + # + # Defines the `scm:push` task. + # + def define + task :validate + + namespace :scm do + task :push => :validate do + status "Pushing commits ..." + + unless push! + error "Could not push commits" + end + end + end + end + + # + # Pushes commits. + # + # @return [Boolean] + # Specifies whether the commits were successfully pushed. + # + # @api semipublic + # + def push! + case @project.scm + when :git + run 'git', 'push' + run 'git', 'push', '--tags' + when :hg + run 'hg', 'push' + else + true + end + end + + end + end + end +end diff --git a/ruby-rubygems-tasks/lib/rubygems/tasks/scm/status.rb b/ruby-rubygems-tasks/lib/rubygems/tasks/scm/status.rb new file mode 100644 index 0000000..3c5361f --- /dev/null +++ b/ruby-rubygems-tasks/lib/rubygems/tasks/scm/status.rb @@ -0,0 +1,80 @@ +require 'rubygems/tasks/task' + +module Gem + class Tasks + module SCM + # + # The `scm:status` task. + # + class Status < Task + + # + # Initializes the `status` task. + # + # @param [Hash] options + # Additional options. + # + def initialize(options={}) + super() + + yield self if block_given? + define + end + + # + # Defines the `status` task. + # + def define + namespace :scm do + task :status do + if dirty? + error "Project has uncommitted changes!" + + status + abort + end + end + end + + # alias the `validate` task to scm:status + task :validate => 'scm:status' + end + + # + # Checks the status of the project repository. + # + # @return [Boolean] + # Specifies whether the repository is dirty. + # + # @api semipublic + # + # @since 0.2.1 + # + def dirty? + status = case @project.scm + when :git then `git status --porcelain --untracked-files=no` + when :hg then `hg status --quiet` + when :svn then `svn status --quiet` + else '' + end + + return !status.chomp.empty? + end + + # + # Displays the status of the project repository. + # + # @api semipublic + # + def status + case @project.scm + when :git then run 'git', 'status', '--untracked-files=no' + when :hg then run 'hg', 'status', '--quiet' + when :svn then run 'svn', 'status', '--quiet' + end + end + + end + end + end +end diff --git a/ruby-rubygems-tasks/lib/rubygems/tasks/scm/tag.rb b/ruby-rubygems-tasks/lib/rubygems/tasks/scm/tag.rb new file mode 100644 index 0000000..51bab3c --- /dev/null +++ b/ruby-rubygems-tasks/lib/rubygems/tasks/scm/tag.rb @@ -0,0 +1,179 @@ +require 'rubygems/tasks/task' + +module Gem + class Tasks + module SCM + # + # The `scm:tag` task. + # + class Tag < Task + + # Default format for versions + DEFAULT_FORMAT = 'v%s' + + # The format for version tags. + # + # @return [String, Proc] + # The format String or Proc. + # + attr_accessor :format + + # Enables or disables PGP signing of tags. + # + # @param [Boolean] value + # The new value. + # + # @since 0.2.0 + # + attr_writer :sign + + # + # Initializes the `scm:tag` task. + # + # @param [Hash] options + # Additional options. + # + # @option options [String, Proc] :format (DEFAULT_FORMAT) + # The format String or Proc for version tags. + # + # @option options [Boolean] :sign + # Enables PGP signing of tags. + # + def initialize(options={}) + super() + + @format = options.fetch(:format,DEFAULT_FORMAT) + @sign = options[:sign] + + yield self if block_given? + define + end + + # + # Defines the `scm:tag` task. + # + def define + task :validate + + namespace :scm do + task :tag, [:name] => :validate do |t,args| + tag = (args.name || version_tag(@project.gemspec.version)) + + status "Tagging #{tag} ..." + + unless tag!(tag) + error "Could not create tag #{tag}" + end + end + end + end + + # + # Formats the version into a version tag. + # + # @param [String] version + # The version to be formatted. + # + # @return [String] + # The tag for the version. + # + # @raise [TypeError] + # {#format} was not a String or a Proc. + # + # @api semipublic + # + def version_tag(version) + case @format + when String + (@format % version) + when Proc + @format[version] + else + raise(TypeError,"tag format must be a String or Proc") + end + end + + # + # Indicates whether new tags will be signed. + # + # @return [Boolean] + # Specifies whether new tags will be signed. + # + # @note + # If {#sign=} has not been set, {#sign?} will determine if tag signing + # has been enabled globally by calling the following commands: + # + # * Git: `git config user.signingkey` + # * Mercurial: `hg showconfig extensions hgext gpg` + # + # @api semipublic + # + # @since 0.2.0 + # + def sign? + if @sign.nil? + @sign = case @project.scm + when :git + !`git config user.signingkey`.chomp.empty? + when :hg + !`hg showconfig extensions.hgext.gpg`.empty? + else + false + end + end + + return @sign + end + + # + # Creates a tag. + # + # @param [String] name + # The name of the tag. + # + # @return [Boolean] + # Specifies whether the tag was successfully created. + # + # @api semipublic + # + def tag!(name) + message = "Tagging #{name}" + + case @project.scm + when :git then + arguments = ['-m', message] + arguments << '-s' if sign? + arguments << name + + run 'git', 'tag', *arguments + when :hg then + if sign? + # sign the change-set, then tag the release + run 'hg', 'sign', '-m', "Signing #{name}" + end + + run 'hg', 'tag', '-m', message, name + when :svn + branch = File.basename(@project.root) + tags_dir = if branch == 'trunk' + # we are in trunk/ + File.join('..','tags') + else + # must be within branches/$name/ + File.join('..','..','tags') + end + + tag_dir = File.join(tag_dirs,name) + + run 'svn', 'mkdir', '--parents', tag_dir + run 'svn', 'cp', '*', tag_dir + run 'svn', 'commit', '-m', message, tag_dir + else + true + end + end + + end + end + end +end diff --git a/ruby-rubygems-tasks/lib/rubygems/tasks/sign.rb b/ruby-rubygems-tasks/lib/rubygems/tasks/sign.rb new file mode 100644 index 0000000..75abcf5 --- /dev/null +++ b/ruby-rubygems-tasks/lib/rubygems/tasks/sign.rb @@ -0,0 +1,2 @@ +require 'rubygems/tasks/sign/checksum' +require 'rubygems/tasks/sign/pgp' diff --git a/ruby-rubygems-tasks/lib/rubygems/tasks/sign/checksum.rb b/ruby-rubygems-tasks/lib/rubygems/tasks/sign/checksum.rb new file mode 100644 index 0000000..a045f5a --- /dev/null +++ b/ruby-rubygems-tasks/lib/rubygems/tasks/sign/checksum.rb @@ -0,0 +1,113 @@ +require 'rubygems/tasks/sign/task' + +require 'digest' + +module Gem + class Tasks + module Sign + # + # The `sign:checksum` task. + # + class Checksum < Task + + # Enables or disables MD5 checksums. + attr_writer :md5 + + # Enables or disables SHA1 checksums. + attr_writer :sha1 + + # Enables or disables SHA2 checksums. + attr_writer :sha2 + + # Enables or disables SHA512 checksums. + attr_writer :sha512 + + # + # Initializes the `sign:checksum` task. + # + # @param [Hash] options + # Digest options. + # + # @option options [Boolean] :md5 (true) + # Specifies whether MD5 checksums are enabled. + # + # @option options [Boolean] :sha1 (true) + # Specifies whether SHA1 checksums are enabled. + # + # @option options [Boolean] :sha2 (false) + # Specifies whether SHA2 checksums are enabled. + # + # @option options [Boolean] :sha512 (false) + # Specifies whether SHA512 checksums are enabled. + # + def initialize(options={}) + super() + + @md5 = options.fetch(:md5, true) + @sha1 = options.fetch(:sha1, true) + @sha2 = options.fetch(:sha2, false) + @sha512 = options.fetch(:sha512,false) + + yield self if block_given? + define + end + + # + # Specifies whether MD5 checksums are enabled. + # + # @return [Boolean] + # + def md5?; @md5; end + + # + # Specifies whether SHA1 checksums are enabled. + # + # @return [Boolean] + # + def sha1?; @sha1; end + + # + # Specifies whether SHA2 checksums are enabled. + # + # @return [Boolean] + # + def sha2?; @sha2; end + + # + # Specifies whether SHA512 checksums are enabled. + # + # @return [Boolean] + # + def sha512?; @sha512; end + + # + # Defines the `sign:checksum` tasks. + # + def define + sign_task :checksum + task :checksum => 'sign:checksum' + end + + # + # Prints the checksums of a package. + # + # @param [String] path + # The path to the package. + # + # @api semipublic + # + def sign(path) + status "Checksums for #{File.basename(path)}:" + + puts + puts " md5: #{Digest::MD5.file(path)}" if @md5 + puts " sha1: #{Digest::SHA1.file(path)}" if @sha1 + puts " sha2: #{Digest::SHA2.file(path)}" if @sha2 + puts " sha512: #{Digest::SHA512.file(path)}" if @sha512 + puts + end + + end + end + end +end diff --git a/ruby-rubygems-tasks/lib/rubygems/tasks/sign/pgp.rb b/ruby-rubygems-tasks/lib/rubygems/tasks/sign/pgp.rb new file mode 100644 index 0000000..66fa111 --- /dev/null +++ b/ruby-rubygems-tasks/lib/rubygems/tasks/sign/pgp.rb @@ -0,0 +1,50 @@ +require 'rubygems/tasks/sign/task' + +module Gem + class Tasks + module Sign + # + # The `sign:pgp` task. + # + class PGP < Task + + # + # Initializes the `sign` task. + # + # @param [Hash] options + # Digest options. + # + def initialize(options={}) + super() + + yield self if block_given? + define + end + + # + # Defines the `sign:pgp` task. + # + def define + sign_task :pgp + + task :pgp => 'sign:pgp' + end + + # + # PGP signs a package. + # + # @param [String] path + # The path to the package. + # + # @api semipublic + # + def sign(path) + status "Signing #{File.basename(path)} ..." + + run 'gpg', '--sign', '--detach-sign', '--armor', path + end + + end + end + end +end diff --git a/ruby-rubygems-tasks/lib/rubygems/tasks/sign/task.rb b/ruby-rubygems-tasks/lib/rubygems/tasks/sign/task.rb new file mode 100644 index 0000000..2f33d9b --- /dev/null +++ b/ruby-rubygems-tasks/lib/rubygems/tasks/sign/task.rb @@ -0,0 +1,58 @@ +require 'rubygems/tasks/task' + +require 'digest' + +module Gem + class Tasks + module Sign + class Task < Tasks::Task + + # + # Signs a package. + # + # @param [String] path + # The path to the package. + # + # @abstract + # + def sign(path) + end + + protected + + # + # Defines signing tasks for the various packages. + # + # @param [Symbol] name + # The name for the `sign:` task. + # + # @api semipublic + # + def sign_task(name) + @project.builds.each do |build,packages| + packages.each do |format,path| + namespace :sign do + namespace name do + namespace build do + task format => path do + sign(path) + end + end + end + end + end + + multi_task "sign:#{name}:#{build}", packages.keys + + task "sign:#{name}" => "sign:#{name}:#{build}" + task "sign:#{build}" => "sign:#{name}:#{build}" + + desc "Signs all packages" unless task?(:sign) + task :sign => "sign:#{name}:#{build}" + end + end + + end + end + end +end diff --git a/ruby-rubygems-tasks/lib/rubygems/tasks/task.rb b/ruby-rubygems-tasks/lib/rubygems/tasks/task.rb new file mode 100644 index 0000000..0c63e2c --- /dev/null +++ b/ruby-rubygems-tasks/lib/rubygems/tasks/task.rb @@ -0,0 +1,153 @@ +require 'rubygems/tasks/project' +require 'rubygems/tasks/printing' + +require 'rake/tasklib' + +module Gem + class Tasks + class Task < Rake::TaskLib + + include Printing + + # + # Project metadata. + # + # @return [Project] + # + attr_reader :project + + # + # Initializes the task. + # + def initialize + @project = Project.directories[Dir.pwd] + end + + protected + + # + # Runs a command. + # + # @param [String] command + # The command to run. + # + # @param [Array] arguments + # Additional arguments for the command. + # + # @return [Boolean] + # Specifies whether the command was successful. + # + # @api semipublic + # + def run(command,*arguments) + show_command = [command, *arguments].join(' ') + + debug show_command + + unless system(command,*arguments) + error "Command failed: #{show_command}" + abort + end + + return true + end + + # + # Runs a `gem` command. + # + # @param [String] command + # The `gem` command to run. + # + # @param [Array] arguments + # Additional arguments for the command. + # + # @return [Boolean] + # Specifies whether the command was successful. + # + # @api semipublic + # + def gem(command,*arguments) + run 'gem', command, *arguments + end + + # + # Runs a `bundle` command. + # + # @param [String] command + # The `bundle` command to run. + # + # @param [Array] arguments + # Additional arguments for the command. + # + # @return [Boolean] + # Specifies whether the command was successful. + # + # @api semipublic + # + def bundle(command,*arguments) + run 'bundler', command, *arguments + end + + # + # Determines if a task was defined. + # + # @param [Symbol, String] name + # The task name to search for. + # + # @return [Boolean] + # Specifies whether the task was defined. + # + # @api semipublic + # + def task?(name) + Rake::Task.task_defined?(name) + end + + # + # Explicitly invokes a task. + # + # @param [Symbol, String] name + # The name of the task. + # + # @api semipublic + # + # @since 0.2.2 + # + def invoke(name) + Rake.application[name].invoke + end + + # + # Defines a task that will invoke one or all of the specifies tasks + # within the namespace. + # + # @param [String] prefix + # The namespace of the sub-tasks to call. + # + # @param [Array] names + # The names of the sub-tasks. + # + # @example + # gemspec_tasks 'pkg:tar' + # + # @api semipublic + # + def multi_task(prefix,names) + task prefix => names.map { |name| "#{prefix}:#{name}" } + end + + # + # Defines a task that will execute tasks for each gemspec. + # + # @param [Symbol, String] name + # The name for the task. + # + # @api semipublic + # + def gemspec_tasks(name) + multi_task name, @project.gemspecs.keys + end + + end + end +end diff --git a/ruby-rubygems-tasks/lib/rubygems/tasks/tasks.rb b/ruby-rubygems-tasks/lib/rubygems/tasks/tasks.rb new file mode 100644 index 0000000..55e3709 --- /dev/null +++ b/ruby-rubygems-tasks/lib/rubygems/tasks/tasks.rb @@ -0,0 +1,147 @@ +require 'rubygems/tasks/console' +require 'rubygems/tasks/build' +require 'rubygems/tasks/install' +require 'rubygems/tasks/scm' +require 'rubygems/tasks/push' +require 'rubygems/tasks/release' +require 'rubygems/tasks/sign' + +require 'rake/tasklib' +require 'ostruct' + +module Gem + # + # Defines basic Rake tasks for managing and releasing projects: + # + # * {Build::Gem build:gem} + # * {Build::Tar build:tar} + # * {Build::Zip build:zip} + # * {SCM::Status scm:status} + # * {SCM::Push scm:push} + # * {SCM::Tag scm:tag} + # * {Console console} + # * {Install install} + # * {Push push} + # * {Release release} + # * {Sign::Checksum sign:checksum} + # * {Sign::PGP sign:pgp} + # + class Tasks + + # + # The `build` tasks. + # + # @return [OpenStruct] + # The collection of `build` tasks. + # + attr_reader :build + + # + # The `scm` tasks. + # + # @return [OpenStruct] + # The collection of `scm` tasks. + # + attr_reader :scm + + # + # The `sign` tasks. + # + # @return [OpenStruct] + # The collection of `sign` tasks. + # + attr_reader :sign + + # The {Console console} task. + attr_reader :console + + # The {Install install} task. + attr_reader :install + + # The {Push push} task. + attr_reader :push + + # The {Release release} task. + attr_reader :release + + # + # Initializes the project tasks. + # + # @param [Hash{Symbol => Hash}] options + # Enables or disables individual tasks. + # + # @option options [Hash{Symbol => Boolean}] :build + # Enables or disables the `build` tasks. + # + # @option options [Hash{Symbol => Boolean}] :scm + # Enables or disables the `scm` tasks. + # + # @option options [Boolean] :console (true) + # Enables or disables the {Console console} task. + # + # @option options [Boolean] :install (true) + # Enables or disables the {Install install} task. + # + # @option options [Boolean] :push (true) + # Enables or disables the {Push push} task. + # + # @option options [Boolean] :release (true) + # Enables or disables the {Release release} task. + # + # @option options [Hash{Symbol => Boolean}] :sign + # Enables or disables the `sign` tasks. + # + # @yield [tasks] + # If a block is given, it will be passed the newly created tasks, + # before they are fully defined. + # + # @yieldparam [Tasks] tasks + # The newly created tasks. + # + # @example Enables building of `.gem` and `.tar.gz` packages: + # Gem::Tasks.new(:build => {:gem => true, :tar => true}) + # + # @example Disables pushing `.gem` packages to [rubygems.org](rubygems.org): + # Gem::Tasks.new(:push => false) + # + # @example Configures the version tag format: + # Gem::Tasks.new do |tasks| + # tasks.scm.tag.format = "release-%s" + # end + # + def initialize(options={}) + build_options = options.fetch(:build,{}) + scm_options = options.fetch(:scm,{}) + sign_options = options.fetch(:sign,{}) + + @scm = OpenStruct.new + @build = OpenStruct.new + @sign = OpenStruct.new + + if build_options + @build.gem = (Build::Gem.new if build_options.fetch(:gem,true)) + @build.tar = (Build::Tar.new if build_options[:tar]) + @build.zip = (Build::Zip.new if build_options[:zip]) + end + + if scm_options + @scm.status = (SCM::Status.new if scm_options.fetch(:status,true)) + @scm.tag = (SCM::Tag.new if scm_options.fetch(:tag,true)) + @scm.push = (SCM::Push.new if scm_options.fetch(:push,true)) + end + + if sign_options + @sign.checksum = (Sign::Checksum.new if sign_options[:checksum]) + @sign.pgp = (Sign::PGP.new if sign_options[:pgp]) + end + + @console = (Console.new if options.fetch(:console,true)) + @install = (Install.new if options.fetch(:install,true)) + @push = (Push.new if options.fetch(:push,true)) + @release = (Release.new if options.fetch(:release,true)) + + yield self if block_given? + end + + end +end diff --git a/ruby-rubygems-tasks/metadata.yml b/ruby-rubygems-tasks/metadata.yml new file mode 100644 index 0000000..3cec9ae --- /dev/null +++ b/ruby-rubygems-tasks/metadata.yml @@ -0,0 +1,146 @@ +--- !ruby/object:Gem::Specification +name: rubygems-tasks +version: !ruby/object:Gem::Version + hash: 31 + prerelease: + segments: + - 0 + - 2 + - 4 + version: 0.2.4 +platform: ruby +authors: +- Postmodern +autorequire: +bindir: bin +cert_chain: [] + +date: 2013-04-08 00:00:00 Z +dependencies: +- !ruby/object:Gem::Dependency + name: rspec + prerelease: false + requirement: &id001 !ruby/object:Gem::Requirement + none: false + requirements: + - - ~> + - !ruby/object:Gem::Version + hash: 11 + segments: + - 2 + - 4 + version: "2.4" + type: :development + version_requirements: *id001 +- !ruby/object:Gem::Dependency + name: yard + prerelease: false + requirement: &id002 !ruby/object:Gem::Requirement + none: false + requirements: + - - ~> + - !ruby/object:Gem::Version + hash: 5 + segments: + - 0 + - 7 + version: "0.7" + type: :development + version_requirements: *id002 +description: Agnostic and unobtrusive Rake tasks for managing and releasing Ruby Gems. +email: postmodern.mod3@gmail.com +executables: [] + +extensions: [] + +extra_rdoc_files: +- ChangeLog.md +- LICENSE.txt +- README.md +files: +- .document +- .gitignore +- .rspec +- .yardopts +- ChangeLog.md +- LICENSE.txt +- README.md +- Rakefile +- gemspec.yml +- lib/rubygems/tasks.rb +- lib/rubygems/tasks/build.rb +- lib/rubygems/tasks/build/gem.rb +- lib/rubygems/tasks/build/tar.rb +- lib/rubygems/tasks/build/task.rb +- lib/rubygems/tasks/build/zip.rb +- lib/rubygems/tasks/console.rb +- lib/rubygems/tasks/install.rb +- lib/rubygems/tasks/printing.rb +- lib/rubygems/tasks/project.rb +- lib/rubygems/tasks/push.rb +- lib/rubygems/tasks/release.rb +- lib/rubygems/tasks/scm.rb +- lib/rubygems/tasks/scm/push.rb +- lib/rubygems/tasks/scm/status.rb +- lib/rubygems/tasks/scm/tag.rb +- lib/rubygems/tasks/sign.rb +- lib/rubygems/tasks/sign/checksum.rb +- lib/rubygems/tasks/sign/pgp.rb +- lib/rubygems/tasks/sign/task.rb +- lib/rubygems/tasks/task.rb +- lib/rubygems/tasks/tasks.rb +- rubygems-tasks.gemspec +- spec/console_spec.rb +- spec/install_spec.rb +- spec/project_spec.rb +- spec/push_spec.rb +- spec/rake_context.rb +- spec/scm/push_spec.rb +- spec/scm/status_spec.rb +- spec/scm/tag_spec.rb +- spec/sign/pgp_spec.rb +- spec/spec_helper.rb +- spec/tasks_spec.rb +homepage: https://github.com/postmodern/rubygems-tasks#readme +licenses: [] + +post_install_message: +rdoc_options: [] + +require_paths: +- lib +required_ruby_version: !ruby/object:Gem::Requirement + none: false + requirements: + - - ">=" + - !ruby/object:Gem::Version + hash: 3 + segments: + - 0 + version: "0" +required_rubygems_version: !ruby/object:Gem::Requirement + none: false + requirements: + - - ">=" + - !ruby/object:Gem::Version + hash: 3 + segments: + - 0 + version: "0" +requirements: [] + +rubyforge_project: +rubygems_version: 1.8.24 +signing_key: +specification_version: 3 +summary: Rake tasks for managing and releasing Ruby Gems. +test_files: +- spec/console_spec.rb +- spec/install_spec.rb +- spec/project_spec.rb +- spec/push_spec.rb +- spec/scm/push_spec.rb +- spec/scm/status_spec.rb +- spec/scm/tag_spec.rb +- spec/sign/pgp_spec.rb +- spec/tasks_spec.rb diff --git a/ruby-rubygems-tasks/rubygems-tasks.gemspec b/ruby-rubygems-tasks/rubygems-tasks.gemspec new file mode 100644 index 0000000..28880d8 --- /dev/null +++ b/ruby-rubygems-tasks/rubygems-tasks.gemspec @@ -0,0 +1,109 @@ +# encoding: utf-8 + +require 'yaml' + +Gem::Specification.new do |gemspec| + files = if File.directory?('.git') + `git ls-files`.split($/) + elsif File.directory?('.hg') + `hg manifest`.split($/) + elsif File.directory?('.svn') + `svn ls -R`.split($/).select { |path| File.file?(path) } + else + Dir['{**/}{.*,*}'].select { |path| File.file?(path) } + end + + filter_files = lambda { |paths| + case paths + when Array + (files & paths) + when String + (files & Dir[paths]) + end + } + + version = { + :file => 'lib/rubygems/tasks/version.rb', + :constant => 'Gem::Tasks::VERSION' + } + + defaults = { + 'name' => File.basename(File.dirname(__FILE__)), + 'files' => files, + 'require_paths' => ['ext', 'lib'].select { |dir| File.directory?(dir) }, + 'executables' => filter_files['bin/*'].map { |path| File.basename(path) }, + 'test_files' => filter_files['{test/{**/}*_test.rb,spec/{**/}*_spec.rb}'], + 'extra_doc_files' => filter_files['*.{txt,rdoc,md,markdown,tt,textile}'] + } + + metadata = defaults.merge(YAML.load_file('gemspec.yml')) + + gemspec.name = metadata['name'] + gemspec.version = if metadata['version'] + metadata['version'] + else + $LOAD_PATH << lib_dir unless $LOAD_PATH.include?(lib_dir) + + require version[:file] + eval(version[:constant]) + end + + gemspec.summary = metadata.fetch('summary',metadata['description']) + gemspec.description = metadata.fetch('description',metadata['summary']) + + gemspec.licenses = Array(metadata['license']) + gemspec.authors = Array(metadata['authors']) + + gemspec.email = metadata['email'] + gemspec.homepage = metadata['homepage'] + + gemspec.require_paths = Array(metadata['require_paths']) + gemspec.files = filter_files[metadata['files']] + gemspec.executables = metadata['executables'] + gemspec.extensions = metadata['extensions'] + + if Gem::VERSION < '1.7.' + gemspec.default_executable = gemspec.executables.first + end + + gemspec.test_files = filter_files[metadata['test_files']] + gemspec.extra_rdoc_files = Array(metadata['extra_doc_files']) + + gemspec.post_install_message = metadata['post_install_message'] + gemspec.requirements = metadata['requirements'] + + if gemspec.respond_to?(:required_ruby_version=) + gemspec.required_ruby_version = metadata['required_ruby_version'] + end + + if gemspec.respond_to?(:required_rubygems_version=) + gemspec.required_rubygems_version = metadata['required_ruby_version'] + end + + parse_versions = lambda { |versions| + case versions + when Array + versions.map { |v| v.to_s } + when String + versions.split(/,\s*/) + end + } + + if metadata['dependencies'] + metadata['dependencies'].each do |name,versions| + gemspec.add_dependency(name,parse_versions[versions]) + end + end + + if metadata['runtime_dependencies'] + metadata['runtime_dependencies'].each do |name,versions| + gemspec.add_runtime_dependency(name,parse_versions[versions]) + end + end + + if metadata['development_dependencies'] + metadata['development_dependencies'].each do |name,versions| + gemspec.add_development_dependency(name,parse_versions[versions]) + end + end +end diff --git a/ruby-rubygems-tasks/spec/console_spec.rb b/ruby-rubygems-tasks/spec/console_spec.rb new file mode 100644 index 0000000..76cb8da --- /dev/null +++ b/ruby-rubygems-tasks/spec/console_spec.rb @@ -0,0 +1,78 @@ +require 'spec_helper' +require 'rake_context' + +require 'rubygems/tasks/console' + +describe Gem::Tasks::Console do + describe "#console" do + include_context "rake" + + if RUBY_VERSION < '1.9' + let(:default_options) { %w[-Ilib -rrubygems -rrubygems/tasks] } + else + let(:default_options) { %w[-Ilib -rrubygems/tasks] } + end + + let(:custom_command) { 'ripl' } + let(:custom_options) { %w[-Ivendor -rfoo] } + + context "defaults" do + it "should run `irb`" do + subject.should_receive(:run).with('irb',*default_options) + + subject.console + end + + context "when project.bundler? == true" do + it "should use `bundle exec`" do + subject.project.stub!(:bundler?).and_return(true) + subject.should_receive(:run).with( + 'bundle', 'exec', 'irb', *default_options + ) + + subject.console + end + end + end + + context "with custom command" do + subject { described_class.new(:command => custom_command) } + + it "should run the custom console" do + subject.should_receive(:run).with(custom_command,*default_options) + + subject.console + end + + context "when project.bundler? == true" do + it "should use `bundle exec`" do + subject.project.stub!(:bundler?).and_return(true) + subject.should_receive(:run).with( + 'bundle', 'exec', custom_command, *default_options + ) + + subject.console + end + end + end + + context "with custom options" do + subject { described_class.new(:options => custom_options) } + + it "should pass custom options to `irb`" do + subject.should_receive(:run).with('irb', *(default_options + custom_options)) + + subject.console + end + + context "when project.bundler? == true" do + it "should use `bundle exec ...`" do + subject.project.stub!(:bundler?).and_return(true) + subject.should_receive(:run).with('bundle', 'exec', 'irb', *(default_options + custom_options)) + + subject.console + end + end + end + end +end diff --git a/ruby-rubygems-tasks/spec/install_spec.rb b/ruby-rubygems-tasks/spec/install_spec.rb new file mode 100644 index 0000000..803c3ef --- /dev/null +++ b/ruby-rubygems-tasks/spec/install_spec.rb @@ -0,0 +1,16 @@ +require 'spec_helper' +require 'rake_context' + +require 'rubygems/tasks/install' + +describe Gem::Tasks::Install do + describe "#install" do + let(:path) { 'pkg/foo-1.2.3.gem' } + + it "should use `gem install -q`" do + subject.should_receive(:run).with('gem', 'install', '-q', path) + + subject.install(path) + end + end +end diff --git a/ruby-rubygems-tasks/spec/project_spec.rb b/ruby-rubygems-tasks/spec/project_spec.rb new file mode 100644 index 0000000..6e71878 --- /dev/null +++ b/ruby-rubygems-tasks/spec/project_spec.rb @@ -0,0 +1,159 @@ +require 'spec_helper' +require 'rubygems/tasks/project' + +describe Gem::Tasks::Project do + let(:rubygems_project) do + described_class.new(PROJECT_DIRS['rubygems-project']) + end + + let(:rubygems_multi_project) do + described_class.new(PROJECT_DIRS['rubygems-multi-project']) + end + + let(:bundler_project) do + described_class.new(PROJECT_DIRS['bundler-project']) + end + + describe "directories" do + it "should map paths to #{described_class} instances" do + directory = PROJECT_DIRS['rubygems-project'] + project = described_class.directories[directory] + + project.root.should == directory + end + end + + describe "#name" do + subject { rubygems_project } + + it "should use the name of the directory" do + subject.name.should == 'rubygems-project' + end + end + + describe "#scm" do + subject { bundler_project } + + it "should detect the SCM used" do + subject.scm.should == :git + end + end + + describe "#gemspecs" do + context "with single-gemspec project" do + subject { rubygems_project } + + it "should load the single-gemspec" do + subject.gemspecs.values.map(&:name).should == %w[rubygems-project] + end + end + + context "with multi-gemspec project" do + subject { rubygems_multi_project } + + it "should load all gemspecs" do + subject.gemspecs.values.map(&:name).should =~ %w[ + rubygems-project + rubygems-project-lite + ] + end + end + end + + describe "#primary_gemspec" do + context "with single-gemspec project" do + subject { rubygems_project } + + it "should match the directory name to the gemspec" do + subject.primary_gemspec.should == subject.name + end + end + + context "with multi-gemspec project" do + subject { rubygems_multi_project } + + it "should pick the first gemspec" do + subject.primary_gemspec.should == 'rubygems-project' + end + end + end + + describe "#gemspec" do + context "with single-gemspec project" do + subject { rubygems_project } + + it "should default the directory name to the gemspec" do + subject.gemspec.name.should == subject.name + end + + it "should raise an ArgumentError for unknown gemspec names" do + lambda { subject.gemspec('foo') }.should raise_error(ArgumentError) + end + end + + context "with multi-gemspec project" do + subject { rubygems_multi_project } + + it "should default the first gemspec" do + subject.gemspec.name.should == 'rubygems-project' + end + + it "should allow accessing alternate gemspecs" do + alternate = 'rubygems-project-lite' + + subject.gemspec(alternate).name.should == alternate + end + end + end + + describe "#builds" do + subject { rubygems_multi_project } + + it "should group builds by gemspec name" do + subject.builds.keys.should =~ subject.gemspecs.keys + end + + it "should map a package format to a pkg/ path" do + packages = subject.builds['rubygems-project'] + + packages['tar.gz'].should == 'pkg/rubygems-project-1.2.3.tar.gz' + end + + context "with single-gemspec project" do + subject { rubygems_project } + + it "should only have a key for the single-gemspec" do + subject.builds.keys.should == %w[rubygems-project] + end + end + + context "with multi-gemspec project" do + subject { rubygems_multi_project } + + it "should have keys for each gemspec" do + subject.builds.keys.should =~ %w[ + rubygems-project + rubygems-project-lite + ] + end + end + end + + describe "#bundler?" do + context "with Bundler" do + subject { bundler_project } + + it "should detect the 'Gemfile' file" do + subject.bundler?.should be_true + end + end + + context "without Bundler" do + subject { rubygems_project } + + it "should be false" do + subject.bundler?.should be_false + end + end + end +end diff --git a/ruby-rubygems-tasks/spec/push_spec.rb b/ruby-rubygems-tasks/spec/push_spec.rb new file mode 100644 index 0000000..69ec268 --- /dev/null +++ b/ruby-rubygems-tasks/spec/push_spec.rb @@ -0,0 +1,32 @@ +require 'spec_helper' +require 'rake_context' + +require 'rubygems/tasks/push' + +describe Gem::Tasks::Push do + describe "#push" do + include_context "rake" + + let(:path) { 'pkg/foo-1.2.3.gem' } + + context "defaults" do + it "should use `gem push`" do + subject.should_receive(:run).with('gem', 'push', path) + + subject.push(path) + end + end + + context "with custom :host" do + let(:host) { 'internal.company.com' } + + subject { described_class.new(:host => host) } + + it "should include the --host option" do + subject.should_receive(:run).with('gem', 'push', path, '--host', host) + + subject.push(path) + end + end + end +end diff --git a/ruby-rubygems-tasks/spec/rake_context.rb b/ruby-rubygems-tasks/spec/rake_context.rb new file mode 100644 index 0000000..a36691b --- /dev/null +++ b/ruby-rubygems-tasks/spec/rake_context.rb @@ -0,0 +1,10 @@ +require 'rake' + +shared_context "rake" do + let(:rake) { Rake::Application.new } + + before(:all) do + Rake.verbose(false) + Rake.application = rake + end +end diff --git a/ruby-rubygems-tasks/spec/scm/push_spec.rb b/ruby-rubygems-tasks/spec/scm/push_spec.rb new file mode 100644 index 0000000..b445df4 --- /dev/null +++ b/ruby-rubygems-tasks/spec/scm/push_spec.rb @@ -0,0 +1,35 @@ +require 'spec_helper' +require 'rake_context' + +require 'rubygems/tasks/scm/push' + +describe Gem::Tasks::SCM::Push do + describe "#push!" do + context "git" do + it "should run `git push --tags`" do + subject.project.stub!(:scm).and_return(:git) + subject.should_receive(:run).with('git', 'push') + subject.should_receive(:run).with('git', 'push', '--tags') + + subject.push! + end + end + + context "hg" do + it "should run `hg push`" do + subject.project.stub!(:scm).and_return(:hg) + subject.should_receive(:run).with('hg', 'push') + + subject.push! + end + end + + context "otherwise" do + it "should return true" do + subject.project.stub!(:scm).and_return(:svn) + + subject.push!.should == true + end + end + end +end diff --git a/ruby-rubygems-tasks/spec/scm/status_spec.rb b/ruby-rubygems-tasks/spec/scm/status_spec.rb new file mode 100644 index 0000000..d521235 --- /dev/null +++ b/ruby-rubygems-tasks/spec/scm/status_spec.rb @@ -0,0 +1,50 @@ +require 'spec_helper' +require 'rake_context' + +require 'rubygems/tasks/scm/status' + +describe Gem::Tasks::SCM::Status do + describe "#status" do + context "git" do + include_context "rake" + + it "should run `git status --untracked-files=no`" do + subject.project.stub!(:scm).and_return(:git) + + subject.should_receive(:run).with( + 'git', 'status', '--untracked-files=no' + ) + + subject.status + end + end + + context "hg" do + include_context "rake" + + it "should run `hg status --quiet`" do + subject.project.stub!(:scm).and_return(:hg) + + subject.should_receive(:run).with( + 'hg', 'status', '--quiet' + ) + + subject.status + end + end + + context "svn" do + include_context "rake" + + it "should run `svn status --quiet`" do + subject.project.stub!(:scm).and_return(:svn) + + subject.should_receive(:run).with( + 'svn', 'status', '--quiet' + ) + + subject.status + end + end + end +end diff --git a/ruby-rubygems-tasks/spec/scm/tag_spec.rb b/ruby-rubygems-tasks/spec/scm/tag_spec.rb new file mode 100644 index 0000000..8cb2995 --- /dev/null +++ b/ruby-rubygems-tasks/spec/scm/tag_spec.rb @@ -0,0 +1,116 @@ +require 'spec_helper' +require 'rake_context' + +require 'rubygems/tasks/scm/tag' + +describe Gem::Tasks::SCM::Tag do + let(:version) { '1.2.3' } + + describe "#version_tag" do + context "defaults" do + include_context "rake" + + it "should have a 'v' prefix" do + subject.version_tag(version).should == "v#{version}" + end + end + + context "with format String" do + include_context "rake" + + let(:format) { 'release-%s' } + + subject { described_class.new(:format => format) } + + it "should apply the format String to the version" do + subject.version_tag(version).should == "release-#{version}" + end + end + + context "with format Proc" do + let(:format) { proc { |ver| "REL_" + ver.tr('.','_') } } + + subject { described_class.new(:format => format) } + + it "should call the format Proc with the version" do + subject.version_tag(version).should == "REL_1_2_3" + end + end + end + + describe "#tag!" do + let(:name) { "v#{version}" } + let(:message) { "Tagging #{name}" } + + context "git" do + context "without signing" do + include_context "rake" + + subject { described_class.new(:sign => false) } + + it "should run `git tag`" do + subject.project.stub!(:scm).and_return(:git) + + subject.should_receive(:run).with( + 'git', 'tag', '-m', message, name + ) + + subject.tag!(name) + end + end + + context "signing" do + include_context "rake" + + subject { described_class.new(:sign => true) } + + it "should run `git tag -s`" do + subject.project.stub!(:scm).and_return(:git) + + subject.should_receive(:run).with( + 'git', 'tag', '-m', message, '-s', name + ) + + subject.tag!(name) + end + end + end + + context "hg" do + context "without signing" do + include_context "rake" + + subject { described_class.new(:sign => false) } + + it "should run `hg tag`" do + subject.project.stub!(:scm).and_return(:hg) + + subject.should_receive(:run).with( + 'hg', 'tag', '-m', message, name + ) + + subject.tag!(name) + end + end + + context "with signing" do + include_context "rake" + + subject { described_class.new(:sign => true) } + + it "should run `hg sign` then `hg tag`" do + subject.project.stub!(:scm).and_return(:hg) + + subject.should_receive(:run).with( + 'hg', 'sign', '-m', "Signing #{name}" + ) + subject.should_receive(:run).with( + 'hg', 'tag', '-m', message, name + ) + + subject.tag!(name) + end + end + end + end +end diff --git a/ruby-rubygems-tasks/spec/sign/pgp_spec.rb b/ruby-rubygems-tasks/spec/sign/pgp_spec.rb new file mode 100644 index 0000000..28b15ad --- /dev/null +++ b/ruby-rubygems-tasks/spec/sign/pgp_spec.rb @@ -0,0 +1,20 @@ +require 'spec_helper' +require 'rake_context' + +require 'rubygems/tasks/sign/pgp' + +describe Gem::Tasks::Sign::PGP do + describe "#sign" do + include_context "rake" + + let(:path) { File.join('pkg','foo-1.2.3.gem') } + + it "should run `gpg --sign --detach-sign --armor ...`" do + subject.should_receive(:run).with( + 'gpg', '--sign', '--detach-sign', '--armor', path + ) + + subject.sign(path) + end + end +end diff --git a/ruby-rubygems-tasks/spec/spec_helper.rb b/ruby-rubygems-tasks/spec/spec_helper.rb new file mode 100644 index 0000000..e94e172 --- /dev/null +++ b/ruby-rubygems-tasks/spec/spec_helper.rb @@ -0,0 +1,12 @@ +gem 'rspec', '~> 2.4' +require 'rspec' + +PROJECTS_DIR = File.join('data','projects') +PROJECT_DIRS = lambda { |name| File.join(PROJECTS_DIR,name) } + +unless File.directory?(PROJECTS_DIR) + abort "Please run `rake data:projects` before running the specs!" +end + +# clear the $RUBYCONSOLE env variable +ENV['RUBYCONSOLE'] = nil diff --git a/ruby-rubygems-tasks/spec/tasks_spec.rb b/ruby-rubygems-tasks/spec/tasks_spec.rb new file mode 100644 index 0000000..c66eb5a --- /dev/null +++ b/ruby-rubygems-tasks/spec/tasks_spec.rb @@ -0,0 +1,127 @@ +require 'spec_helper' +require 'rake_context' + +require 'rubygems/tasks/tasks' + +describe Gem::Tasks do + describe "#initialize" do + context "default options" do + include_context "rake" + + its(:build) { should be_kind_of(OpenStruct) } + its('build.gem') { should be_kind_of(Gem::Tasks::Build::Gem) } + its('build.tar') { should be_nil } + its('build.zip') { should be_nil } + + its(:scm) { should be_kind_of(OpenStruct) } + its('scm.status') { should be_kind_of(Gem::Tasks::SCM::Status) } + its('scm.push') { should be_kind_of(Gem::Tasks::SCM::Push) } + its('scm.tag') { should be_kind_of(Gem::Tasks::SCM::Tag) } + + its(:sign) { should be_kind_of(OpenStruct) } + its('sign.checksum') { should be_nil } + its('sign.pgp') { should be_nil } + + its(:console) { should be_kind_of(Gem::Tasks::Console) } + its(:install) { should be_kind_of(Gem::Tasks::Install) } + its(:push) { should be_kind_of(Gem::Tasks::Push) } + its(:release) { should be_kind_of(Gem::Tasks::Release) } + end + + context ":build => {:gem => false}" do + include_context "rake" + + subject { described_class.new(:build => {:gem => false}) } + + its('build.gem') { should be_nil } + end + + context ":build => {:tar => true}" do + include_context "rake" + + subject { described_class.new(:build => {:tar => true}) } + + its('build.tar') { should be_kind_of(Gem::Tasks::Build::Tar) } + end + + context ":build => {:zip => true}" do + include_context "rake" + + subject { described_class.new(:build => {:zip => true}) } + + its('build.zip') { should be_kind_of(Gem::Tasks::Build::Zip) } + end + + context ":scm => {:status => false}" do + include_context "rake" + + subject { described_class.new(:scm => {:status => false}) } + + its('scm.status') { should be_nil } + end + + context ":scm => {:push => false}" do + include_context "rake" + + subject { described_class.new(:scm => {:push => false}) } + + its('scm.push') { should be_nil } + end + + context ":scm => {:tag => false}" do + include_context "rake" + + subject { described_class.new(:scm => {:tag => false}) } + + its('scm.tag') { should be_nil } + end + + context ":sign => {:checksum => true}" do + include_context "rake" + + subject { described_class.new(:sign => {:checksum => true}) } + + its('sign.checksum') { should be_kind_of(Gem::Tasks::Sign::Checksum) } + end + + context ":sign => {:pgp => true}" do + include_context "rake" + + subject { described_class.new(:sign => {:pgp => true}) } + + its('sign.pgp') { should be_kind_of(Gem::Tasks::Sign::PGP) } + end + + context ":console => false" do + include_context "rake" + + subject { described_class.new(:console => false) } + + its(:console) { should be_nil } + end + + context ":install => false" do + include_context "rake" + + subject { described_class.new(:install => false) } + + its(:install) { should be_nil } + end + + context ":push => false" do + include_context "rake" + + subject { described_class.new(:push => false) } + + its(:push) { should be_nil } + end + + context ":release => false" do + include_context "rake" + + subject { described_class.new(:release => false) } + + its(:release) { should be_nil } + end + end +end -- 1.8.2.3