Skip to content

Commit

Permalink
First commit
Browse files Browse the repository at this point in the history
  • Loading branch information
genki committed Feb 13, 2009
0 parents commit 4fdb99f
Show file tree
Hide file tree
Showing 16 changed files with 2,603 additions and 0 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG
@@ -0,0 +1,2 @@

v0.2.3. Signed gem.
504 changes: 504 additions & 0 deletions COPYING

Large diffs are not rendered by default.

55 changes: 55 additions & 0 deletions LICENSE
@@ -0,0 +1,55 @@
GemPlugin is copyrighted free software by Zed A. Shaw
<zedshaw at zedshaw dot com> You can redistribute it and/or modify it under
either the terms of the GPL or the conditions below:

1. You may make and give away verbatim copies of the source form of the
software without restriction, provided that you duplicate all of the
original copyright notices and associated disclaimers.

2. You may modify your copy of the software in any way, provided that
you do at least ONE of the following:

a) place your modifications in the Public Domain or otherwise make them
Freely Available, such as by posting said modifications to Usenet or an
equivalent medium, or by allowing the author to include your
modifications in the software.

b) use the modified software only within your corporation or
organization.

c) rename any non-standard executables so the names do not conflict with
standard executables, which must also be provided.

d) make other distribution arrangements with the author.

3. You may distribute the software in object code or executable
form, provided that you do at least ONE of the following:

a) distribute the executables and library files of the software,
together with instructions (in the manual page or equivalent) on where
to get the original distribution.

b) accompany the distribution with the machine-readable source of the
software.

c) give non-standard executables non-standard names, with
instructions on where to get the original software distribution.

d) make other distribution arrangements with the author.

4. You may modify and include the part of the software into any other
software (possibly commercial). But some files in the distribution
are not written by the author, so that they are not under this terms.

5. The scripts and library files supplied as input to or produced as
output from the software do not automatically fall under the
copyright of the software, but belong to whomever generated them,
and may be sold commercially, and may be aggregated with this
software.

6. THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE.


15 changes: 15 additions & 0 deletions Manifest
@@ -0,0 +1,15 @@
test/test_plugins.rb
setup.rb
resources/resources/defaults.yaml
resources/README
resources/Rakefile
resources/LICENSE
resources/lib/project/init.rb
resources/COPYING
README
Manifest
LICENSE
lib/gem_plugin.rb
COPYING
CHANGELOG
bin/gpgen
115 changes: 115 additions & 0 deletions README
@@ -0,0 +1,115 @@
= GemPlugin: Gem Based Plugin System

GemPlugin is a system that lets your users install gems and lets you load
them as additional features to use in your software. It originated from the
Mongrel (http://mongrel.rubyforge.org) project but proved useful enough to
break out into a separate project.

GemPlugin works by listing the gems installed, and doing a require_gem on
any that have the right dependencies. For example, if a gem depends on
"gem_plugin" and "mongrel" then it'll load as a Mongrel plugin. This
makes it so that users of the plugins only need to gem install (and maybe
config a bit), and plugin authors only need to make gems.


== Implementers

To use GemPlugin in your system you only have to require 'gem_plugin' and
then use the GemPlugin::Manager.create, GemPlugin::Manager.load, and
GemPlugin::Manager.available methods to work with them.

* GemPlugin::Manager.load -- Takes a "depend include/exclude map" and loads plugins based on it.
* GemPlugin::Manager.create -- Takes a URI style name and some options then creates one for you.
* GemPlugin::Manager.available -- Lets you inspect and mess with the internal plugin registry.

=== Loading Plugins

As an example from Mongrel it's necessary to load plugins that depend on rails after
the Rails system is configured, but load other plugins right when Mongrel is ready.
To do this we very first do:

GemPlugin::Manager.instance.load "mongrel" => GemPlugin::INCLUDE, "rails" => GemPlugin::EXCLUDE

Later, when it's ready to load Rails plugins as well we do this:

GemPlugin::Manager.instance.load "mongrel" => GemPlugin::INCLUDE

This simply loads any plugins that remain and are ready for use in Rails.

=== Creating Plugins

Creating a plugin is cake:

plug = GemPlugin::Manager.instance.create("/commands/snazzy", "something" => "yeah")

In this case we're making the snazzy command and passing a couple fake options.

=== Finding Available Plugins

Finding plugins is also very easy, you just call GemPlugin::Manager.instance.available
and you get a Hash that maps categories to name => class. For example, if I had
the "/commands/snazzy" plugin registered above, then I'd get the following:

puts GemPlugin::Manager.instance.available["/commands"].inspect
-> { "/snazzy" => Snazzy}


=== Plugins Inside Modules

Plugins that are placed in modules are also lowercased when registered but
still retain their module. So, if Snazzy was actually MyModule::Snazzy, then
it'd be registered as "/commands/mymodule::snazzy".


== Plugin Authors

People who wish to write gem plugins have a faily easy time of it, but need
to know the particular rules for the target system. To keep this example
concrete we'll assume you want to write a Mongrel command plugin.

First thing is create your project like normal and setup Rake to make
your gem. Your plugin then needs to be created like so:

class Snazzy < GemPlugin::Plugin "/commands"
...
end

And place this code in a file you will have RubyGems autorequire (I use lib/init.rb).

Next you need to add the following to whatever Rakefile code you use to create
your gem:

spec.add_dependency('gem_plugin', '>= 0.1')
spec.add_dependency('mongrel', '>= 0.3.9')
spec.autorequire = 'init.rb'

This does three things:

* Tells GemPlugins::Manager.load that this is a GemPlugin.
* Tells Mongrel that this is a Mongrel specific GemPlugin.
* Tells RubyGems to run init.rb when the gem is required, just hooking up your plugin.

Now, all the users of your plugin have to do is gem install it and then
they get the plugin automagically.

People writing GemPlugins for other systems would have to check the
documentation from that project to get an idea of what extra
requirements might be needed. For example, you'd probably have to
depend on another project other that *mongrel* and most likely have
a few more things to configure in your init.rb.

== Plugin Users

Plugin users have it the easiest of all. They simply do:

gem install mongrel_command_snazzy

And that's it. When they run mongrel_rails (given the above example)
this snazzy command get loaded automatically without any intervention.

The only thing missing in this release is a way for end users to configure
such a plugin. I really think this is the job of the implementers to define.

== Contact

E-mail zedshaw at zedshaw.com and I'll help. Comments about the API are welcome.
60 changes: 60 additions & 0 deletions bin/gpgen
@@ -0,0 +1,60 @@
require 'erb'
require 'fileutils'
include FileUtils

if ARGV.length != 1
STDERR.puts "ERROR: You must give a name for your plugin and directory."
STDERR.puts "usage: gpgen name"
STDERR.puts "example: gpgen mygemplugin"
exit 1
end

# setup the required binding variables for erb processing later
project = ARGV.shift
gem_plugin_base = File.expand_path(File.join(File.dirname(__FILE__), ".."))
resources = File.join(gem_plugin_base, "resources")
gem_plugin_version = gem_plugin_base[gem_plugin_base.rindex("-")+1 .. -1]


# make the dir if it don't exist
if not File.exist? project
puts "Creating directory #{project}"
mkdir project
else
puts "Directory #{project} exists, skipping."
end


# go through all the resource files, erb them, and write them verbatim to output
# do not overwrite if exists already

Dir.glob("#{resources}/**/*") do |infile|
outfile = File.join(project, infile[resources.length .. -1])
if File.exist? outfile
puts "File #{outfile} exists, skipping."
else
if File.directory? infile
puts "Creating directory #{outfile}"
mkdir_p outfile
elsif File.file? infile
puts "Creating file #{outfile}"
open(infile) do |content|
template = ERB.new(content.read)
open(outfile,"w") {|f| f.write(template.result(binding)) }
end
else
puts "!!! Resources contains something not a file or directory."
puts "Skipping #{infile}."
end
end
end

# Finally, move the base init.rb to the right dir
init_file = File.join(project,"lib",project)
if File.exist? init_file
puts "File init.rb already exists, skipping."
puts "WARNING: There might be a junk '#{project}/lib/project/init.rb' file you can delete."
else
puts "Creating proper '#{project}/lib/#{project}/init.rb' file"
mv File.join(project,"lib","project"), init_file
end
53 changes: 53 additions & 0 deletions gem_plugin.gemspec
@@ -0,0 +1,53 @@

# Gem::Specification for Gem_plugin-0.2.3
# Originally generated by Echoe

Gem::Specification.new do |s|
s.name = %q{gem_plugin}
s.version = "0.2.3"

s.specification_version = 2 if s.respond_to? :specification_version=

s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
s.authors = ["Zed A. Shaw"]
s.date = %q{2007-10-26}
s.default_executable = %q{gpgen}
s.description = %q{A plugin system based on rubygems that uses dependencies only}
s.email = %q{}
s.executables = ["gpgen"]
s.files = ["test/test_plugins.rb", "setup.rb", "resources/resources/defaults.yaml", "resources/README", "resources/Rakefile", "resources/LICENSE", "resources/lib/project/init.rb", "resources/COPYING", "README", "Manifest", "LICENSE", "lib/gem_plugin.rb", "COPYING", "CHANGELOG", "bin/gpgen", "gem_plugin.gemspec"]
s.has_rdoc = true
s.homepage = %q{}
s.require_paths = ["lib"]
s.rubyforge_project = %q{mongrel}
s.rubygems_version = %q{0.9.4.6}
s.summary = %q{A plugin system based on rubygems that uses dependencies only}
s.test_files = ["test/test_plugins.rb"]
end


# # Original Rakefile source (requires the Echoe gem):
#
#
# require 'echoe'
#
# Echoe.new("gem_plugin") do |p|
# p.author="Zed A. Shaw"
# p.project = "mongrel"
# p.summary = "A plugin system based on rubygems that uses dependencies only"
#
# p.need_tar_gz = false
# p.need_tgz = true
# p.require_signed = true
#
# p.test_pattern = "test/test_plugins.rb"
# p.clean_pattern += ["pkg", "lib/*.bundle", "*.gem", ".config"]
# p.rdoc_pattern = ['README', 'LICENSE', 'COPYING', 'lib/**/*.rb', 'doc/**/*.rdoc']
# end
#
# # The default Echoe rdoc location should be good enough, but it's not what we currently use.
# # It would be: rubyforge.org:/var/www/gforge-projects/mongrel/gem_plugin/
# #
# # task :site => [:redocs] do
# # sh %{ rsync -r doc/* rubyforge.org:/var/www/gforge-projects/mongrel/gem_plugin_rdoc/ }
# # end

0 comments on commit 4fdb99f

Please sign in to comment.