codger 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/.gitignore ADDED
@@ -0,0 +1,4 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/*
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in codger.gemspec
4
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2012 Jacob Williams
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,63 @@
1
+ # codger
2
+
3
+ Goals:
4
+
5
+ * Provide a simple way to define and run project skeletons and other code generators.
6
+ * Help integrate later changes to the generators into a project.
7
+
8
+ ## Creating Skeletons
9
+
10
+ Put the skeleton in a git repo. Before testing it, make sure to at least `git add` the files. Then:
11
+
12
+ codger skeleton path/to/your-repo-name --test
13
+
14
+ Now, to generate code inside the current working directory, do
15
+
16
+ codger gen your-repo-name
17
+
18
+ Here's how the skeleton repo will be used:
19
+
20
+ 1. If there is a script named `generate.rb` in the root directory, it will be run.
21
+ 2. Files ending in `.erb` will be [interpolated](http://ruby-doc.org/stdlib-1.9.3/libdoc/erb/rdoc/ERB.html) and written to the target directory.
22
+ 3. Other files will be copied directly to the target directory. (Exceptions: README, README.md, README.markdown)
23
+
24
+ ### Parameters
25
+
26
+ In the templates or generate.rb, use the method `param :parameter_name` to request values to configure the skeleton. The first time a particular parameter is requested, the user will be prompted for a value.
27
+
28
+ The first time a prompt is given, the skeleton repo's README will be printed (if it exists).
29
+
30
+ ### Helpers
31
+
32
+ * In a template, you can use `<%- rename "relative_path" -%>` to override the output file name.
33
+ * Use `copy "path1", "path2"` to copy files "path1" and "path2" (relative the skeleton repo's root directory) into the target directory directly. Use `copy "path1" => "newpath1"` to override the destination path in the target directory.
34
+ * Use `interpolate "path1", "path2"` to interpolate ERB files "path1" and "path2" into the target directory. As with `copy` you can use a hash to override the destination paths.
35
+ * Use `ignore "path1", "path2"` to prevent automatic copying or interpolation of files.
36
+
37
+ ## Using Skeletons
38
+
39
+ Register a skeleton:
40
+
41
+ codger skeleton git://example.com/boilerplate.git
42
+
43
+ Run it in a new folder:
44
+
45
+ codger create boilerplate monumental-endeavor
46
+
47
+ Or run it in the current working directory:
48
+
49
+ codger gen boilerplate
50
+
51
+ In either case the parameters used will be recorded in a file named `.codger`, so that later, after the project or the skeleton have changed, you can use
52
+
53
+ codger diff
54
+
55
+ to compare the current state of your project with the output of the current version of the skeleton. The command used for diffing can be changed:
56
+
57
+ codger config diff "diff -ur %SOURCE %DEST"
58
+
59
+ ## TODO
60
+
61
+ * Better documentation; examples
62
+ * I'm hopeful that more useful diffing can be done through git integration, but I haven't worked on it much yet.
63
+ * Code generators shouldn't be restricted to whatever dependencies happen to be pulled in by codger.
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
data/bin/codger ADDED
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'codger'
4
+ Codger::CLI.start
data/codger.gemspec ADDED
@@ -0,0 +1,28 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "codger/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "codger"
7
+ s.version = Codger::VERSION
8
+ s.authors = ["Jacob Williams"]
9
+ s.email = ["jacobaw@gmail.com"]
10
+ s.homepage = ""
11
+ s.summary = %q{Manages invocation of code generators.}
12
+ s.description = %q{Manages invocation of code generators.}
13
+
14
+ s.rubyforge_project = "codger"
15
+
16
+ s.files = `git ls-files`.split("\n")
17
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
18
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
19
+ s.require_paths = ["lib"]
20
+
21
+ # specify any dependencies here; for example:
22
+ # s.add_development_dependency "rspec"
23
+ # s.add_runtime_dependency "rest-client"
24
+ s.add_runtime_dependency 'activesupport', '~> 3.2.1'
25
+ s.add_runtime_dependency 'deep_merge', '~> 1.0.0'
26
+ s.add_runtime_dependency 'git', '~> 1.2.5'
27
+ s.add_runtime_dependency 'thor', '~> 0.14.6'
28
+ end
data/lib/codger/cli.rb ADDED
@@ -0,0 +1,100 @@
1
+ require 'fileutils'
2
+ require 'git'
3
+ require 'thor'
4
+ require 'tmpdir'
5
+ require 'yaml'
6
+
7
+ module Codger
8
+ class CLI < Thor
9
+ desc 'config [NAME [VALUE]]', 'lists, shows, or alters configuration'
10
+ def config(name = nil, value = nil)
11
+ if name
12
+ if value
13
+ Manager.default.global_settings[:config][name] = value
14
+ Manager.default.save_globals
15
+ else
16
+ puts Manager.default.settings[:config][name]
17
+ end
18
+ else
19
+ puts YAML.dump(Manager.default.settings[:config]).lines.drop(1).join
20
+ end
21
+ end
22
+
23
+ desc 'available', 'lists registered code generators'
24
+ def available
25
+ Manager.default.settings[:generators].each do |name, info|
26
+ puts "#{name}\t#{info.inspect}"
27
+ end
28
+ end
29
+
30
+ desc 'skeleton LOCATION', 'register a git repository as a code generator, creating a clone from the given location'
31
+ method_option :name, desc: 'Name you wish to refer to the skeleton by.'
32
+ method_option :test, desc: 'Prevent cloning or pulling of the repository. Location should be a path on the file system.'
33
+ def skeleton(location)
34
+ info = {}
35
+ if options[:test]
36
+ location = File.expand_path(location)
37
+ info[:test] = true
38
+ end
39
+ info[:git] = location
40
+ Manager.default.register options[:name], info
41
+ end
42
+
43
+ desc 'create NAME PATH', 'run the named generator in a new folder at the given path'
44
+ def create(name, path)
45
+ FileUtils.mkdir path
46
+ Git.init File.expand_path(path)
47
+ manager = Manager.new(File.join(path, '.codger'))
48
+ generator = manager.generator(manager.settings[:generators][name])
49
+ generator.run path, project_name: path.split('/').last
50
+ manager.record_run generator
51
+ end
52
+
53
+ desc 'gen NAME', 'run the named generator'
54
+ def gen(name)
55
+ generator = Manager.default.generator(Manager.default.settings[:generators][name])
56
+ generator.run(Dir.pwd)
57
+ Manager.default.record_run(generator)
58
+ end
59
+
60
+ desc 'history', 'show the actions recorded for this directory'
61
+ def history
62
+ Manager.default.settings[:runs].each do |info|
63
+ puts "#{info[:generator]} [#{info[:tags].join(' ')}]"
64
+ puts Generator.format_params(info[:params])
65
+ puts
66
+ end
67
+ end
68
+
69
+ desc 'diff [TAGS...]', 'run part or all of the history in a temp directory and display a diff'
70
+ def diff(*tags)
71
+ Dir.mktmpdir do |dir|
72
+ Manager.default.settings[:runs].each do |info|
73
+ if tags.empty? or (tags & info[:tags]).any?
74
+ generator = Manager.default.generator(info[:generator])
75
+ generator.run dir, info[:params]
76
+ end
77
+ end
78
+ system Manager.default.diff_command(dir, Dir.pwd)
79
+ end
80
+ end
81
+
82
+ desc 'repeat [TAGS...]', 're-run part or all of the history'
83
+ def repeat(*tags)
84
+ Manager.default.settings[:runs].each do |info|
85
+ if tags.empty? or (tags & info[:tags]).any?
86
+ puts "Running #{info[:generator]} [#{info[:tags].join(' ')}]"
87
+ puts Generator.format_params(info[:params])
88
+ puts
89
+ generator = Manager.default.generator(info[:generator])
90
+ generator.run Dir.pwd, info[:params]
91
+ end
92
+ end
93
+ end
94
+
95
+ desc 'unregister NAME', 'unregister a code generator and delete its clone'
96
+ def unregister(name)
97
+ Manager.default.unregister name
98
+ end
99
+ end
100
+ end
@@ -0,0 +1,84 @@
1
+ require 'yaml'
2
+
3
+ module Codger
4
+ # A code generator. The #run method is called to perform code generation;
5
+ # the parameters used (which may have been specified interactively during #run)
6
+ # can be determined afterwards using #params.
7
+ #
8
+ # Subclasses must implement:
9
+ # * a #generate method which will perform the code generation
10
+ # * a #help method which returns help text
11
+ #
12
+ # Methods for use by subclasses:
13
+ # * #dest_path
14
+ # * #ensure_folder
15
+ # * #param
16
+ # * #tags
17
+ class Generator
18
+ class << self
19
+ # Given a params map, print one param per line, indented.
20
+ def format_params(params)
21
+ YAML.dump(params).lines.drop(1).map do |line|
22
+ "\t#{line}"
23
+ end.join
24
+ end
25
+ end
26
+
27
+ # The map of parameters used during the last call to #run.
28
+ attr_reader :params
29
+ # The output directory used during the last call to #run.
30
+ attr_reader :target
31
+
32
+ # Perform code generation in the given directory. Any parameters
33
+ # already known (e.g., if we're repeating a previous run) can be
34
+ # specified; any other parameters needed will be determined interactively.
35
+ def run(target, params = {})
36
+ @showed_help = false
37
+ @target = target
38
+ @params = params.with_indifferent_access
39
+
40
+ generate
41
+ end
42
+
43
+ # Given a path relative to the output directory root, returns the full path.
44
+ def dest_path(path)
45
+ File.join(target, path)
46
+ end
47
+
48
+ # Given a path relative to the output directory root, creates a folder
49
+ # at that location if one does not yet exist.
50
+ def ensure_folder(path)
51
+ FileUtils.mkdir_p(File.join(target, File.dirname(path)))
52
+ end
53
+
54
+ # Returns the value from the params map for the given name. If there
55
+ # is none, asks the user for a value. #help is called the first time
56
+ # the user is asked for a value.
57
+ # The parameter will also be saved in an instance variable of the same name.
58
+ def param(name)
59
+ until params[name]
60
+ unless @showed_help
61
+ puts help
62
+ puts
63
+ @showed_help = true
64
+ end
65
+ print "Specify #{name}: "
66
+ value = STDIN.gets.chomp
67
+ params[name] = value unless value.empty?
68
+ end
69
+ instance_variable_set("@#{name}", params[name])
70
+ params[name]
71
+ end
72
+
73
+ # Sets (with parameters) or returns (without parameters) tags for
74
+ # this generator. The tags will be associated to recorded runs.
75
+ # (This may be useless, we'll see.)
76
+ def tags(*tags)
77
+ if tags == []
78
+ @tags || []
79
+ else
80
+ @tags = tags.flatten
81
+ end
82
+ end
83
+ end
84
+ end
@@ -0,0 +1,134 @@
1
+ require 'fileutils'
2
+ require 'git'
3
+ require 'yaml'
4
+
5
+ module Codger
6
+ # Responsible for:
7
+ # * Reading, writing, and to some degree interpreting configuration files.
8
+ # * Looking up code generators from their identifiers.
9
+ class Manager
10
+ class << self
11
+ # Return an instance using any settings in the .codger
12
+ # file (if one exists) of the working directory.
13
+ def default
14
+ @config ||= Manager.new(File.join(Dir.pwd, '.codger'))
15
+ end
16
+ end
17
+
18
+ # The global settings map (i.e. from ~/.codger/codger.yaml)
19
+ attr_reader :global_settings
20
+ # The project settings map (i.e. from .codger)
21
+ attr_reader :project_settings
22
+
23
+ # Create an instance with project-level settings stored at the specified path
24
+ # (does not need to exist yet, and will not be created unless necessary).
25
+ def initialize(path)
26
+ @project_path = path
27
+ @project_settings = {
28
+ runs: []
29
+ }.with_indifferent_access
30
+ if File.exists?(@project_path)
31
+ @project_settings.merge! YAML.load(File.read(@project_path))
32
+ end
33
+
34
+ @global_settings = {
35
+ config: {
36
+ diff: 'diff -ur %SOURCE %DEST'
37
+ },
38
+ clones: {},
39
+ generators: {}
40
+ }.with_indifferent_access
41
+ if File.exists?(globals_path)
42
+ @global_settings.merge! YAML.load(File.read(globals_path))
43
+ end
44
+ end
45
+
46
+ # Creates a Generator, currently always a Skeleton.
47
+ # info should contain :git, the path/URI of the repository.
48
+ # Unless it contains :test, the repository will be cloned to #clones_base
49
+ # (if it has not been already).
50
+ def generator(info)
51
+ if location = info[:git]
52
+ if info[:test]
53
+ clone = location
54
+ elsif !(clone = settings[:clones][location] and File.exists?(clone))
55
+ FileUtils.mkdir_p clones_base
56
+ next_id = Dir.entries(clones_base).map(&:to_i).max + 1
57
+ clone = File.join(clones_base, next_id.to_s)
58
+ Git.clone location, clone
59
+ @global_settings[:clones][location] = clone
60
+ save_globals
61
+ end
62
+ Skeleton.new clone, info
63
+ end
64
+ end
65
+
66
+ # Load a generator for the given attributes and register it
67
+ # in the global configuration under the given name, or its default
68
+ # name if name is nil.
69
+ def register(name, info)
70
+ gen = generator(info)
71
+ @global_settings[:generators][name || gen.name] = gen.info
72
+ save_globals
73
+ end
74
+
75
+ # Given a generator name, removes it from the config, and delete its
76
+ # local clone if one exists.
77
+ def unregister(name)
78
+ info = @global_settings[:generators].delete name # TODO graciously handle it not existing
79
+ clone = @global_settings[:clones].delete info[:git]
80
+ if clone and clone.start_with? clones_base # sanity check before rm_rf
81
+ FileUtils.rm_rf clone
82
+ end
83
+ save_globals
84
+ end
85
+
86
+ # Saves the tags, identifier, and params from the last run of the given generator instance
87
+ # in the project settings file.
88
+ def record_run(generator)
89
+ @project_settings[:runs] << {
90
+ tags: [generator.name] + generator.tags,
91
+ generator: generator.info,
92
+ params: generator.params
93
+ }.with_indifferent_access
94
+ save_project
95
+ end
96
+
97
+ # Save #project_settings.
98
+ def save_project
99
+ File.write @project_path, @project_settings.to_yaml
100
+ end
101
+
102
+ # Save #global_settings.
103
+ def save_globals
104
+ FileUtils.mkdir_p codger_home
105
+ File.write globals_path, @global_settings.to_yaml
106
+ end
107
+
108
+ # Return the folder where global settings and other resources can be saved.
109
+ # By default ~/.codger but this can be overridden using 'codger_home' in #project_settings.
110
+ def codger_home
111
+ @project_settings[:codger_home] || File.join(Dir.home, '.codger')
112
+ end
113
+
114
+ # Return the file where global settings should be saved - 'codger.yaml' in #codger_home.
115
+ def globals_path
116
+ File.join(codger_home, 'codger.yaml')
117
+ end
118
+
119
+ # Return the folder where skeleton clones can be saved - 'clones' in #codger_home.
120
+ def clones_base
121
+ File.join(codger_home, 'clones')
122
+ end
123
+
124
+ # Return a merged map of #global_settings and #project_settings.
125
+ def settings
126
+ @global_settings.deep_merge @project_settings
127
+ end
128
+
129
+ # Return the command to use for diffing two folders.
130
+ def diff_command(source, dest)
131
+ settings[:config][:diff].gsub('%SOURCE', source).gsub('%DEST', dest)
132
+ end
133
+ end
134
+ end
@@ -0,0 +1,137 @@
1
+ require 'erb'
2
+ require 'fileutils'
3
+ require 'git'
4
+
5
+ module Codger
6
+ # A generator that produces code by using a git repository as a template.
7
+ #
8
+ # By default:
9
+ # * README, README.md, README.markdown will be ignored, except to
10
+ # be printed as documentation if user input is required for the
11
+ # value of a param
12
+ # * generate.rb (if it exists) will be executed in the context of
13
+ # the Skeleton instance
14
+ # * Files ending in .erb will be interpolated in the context of
15
+ # the Skeleton instance
16
+ # * All other files will be copied directly
17
+ #
18
+ # Methods for use in generate.rb and templates:
19
+ # * #src_path
20
+ # * #copy
21
+ # * #interpolate
22
+ # * #ignore
23
+ # * #rename
24
+ class Skeleton < Generator
25
+ # Returns a (non-unique) name for the generator. For
26
+ # skeletons this is based on the last segment of the origin
27
+ # URI or of the clone's path.
28
+ attr_reader :name
29
+ # Returns the attributes used in creating this instance.
30
+ attr_reader :info
31
+
32
+ # Create an instance reading from the git repository at the specified
33
+ # path. Options for info:
34
+ # git:: Canonical source for the repo; required.
35
+ # test:: Unless truthy, an attempt will be made to perform a 'pull' for the repository.
36
+ def initialize(repo, info)
37
+ @info = info
38
+ @git = Git.open(repo)
39
+ # https://github.com/schacon/ruby-git/issues/32
40
+ @git.lib.send(:command, 'pull') unless info[:test] # TODO needs to be OK if this fails
41
+ @name = info[:git].split('/').last.sub(/\.git\z/,'')
42
+ end
43
+
44
+ # Perform code generation using the process outlined in the class documentation.
45
+ def generate
46
+ @to_copy = @git.ls_files.keys - ['README', 'README.md', 'README.markdown', 'generate.rb']
47
+
48
+ code_path = src_path('generate.rb')
49
+ if File.exists?(code_path)
50
+ eval(File.read(code_path), binding, code_path)
51
+ end
52
+
53
+ interpolate(@to_copy.select {|path| path =~ /\.erb\z/})
54
+ copy @to_copy
55
+ end
56
+
57
+ # Return the full path to the given file in the repo.
58
+ def src_path(path)
59
+ File.join(@git.dir.to_s, path)
60
+ end
61
+
62
+ # For each path or array of paths, copy the
63
+ # corresponding files directly from the repository to
64
+ # the target directory.
65
+ # Alternatively, a hash of paths may be given, in which
66
+ # keys specify the name in the source repository and
67
+ # values specify the desired name in the target directory.
68
+ def copy(*paths)
69
+ paths = paths.flatten
70
+ mappings = {}
71
+ paths.each do |path|
72
+ if path.is_a? Hash
73
+ mappings.merge! path
74
+ else
75
+ mappings[path] = path
76
+ end
77
+ end
78
+
79
+ mappings.each do |src, dest|
80
+ ensure_folder dest
81
+ FileUtils.cp src_path(src), dest_path(dest)
82
+ @to_copy.delete src
83
+ end
84
+ end
85
+
86
+ # For each path or array of paths, interpolate (in the
87
+ # context of this object) the corresponding files and
88
+ # write the output to the target directory, stripping
89
+ # .erb from the filename.
90
+ # Alternatively, a hash of paths may be given, in which
91
+ # keys specify the name in the source repository and
92
+ # values specify the desired name in the target directory.
93
+ #
94
+ # Note that calls to #rename may override the destination path.
95
+ def interpolate(*paths)
96
+ paths = paths.flatten
97
+ mappings = {}
98
+ paths.each do |path|
99
+ if path.is_a? Hash
100
+ mappings.merge! path
101
+ else
102
+ mappings[path] = path.sub(/\.erb\z/, '')
103
+ end
104
+ end
105
+
106
+ mappings.each do |src, dest|
107
+ @current_template_src = src
108
+ @current_template_dest = dest
109
+ template = ERB.new(File.read(src_path(src)), nil, '-')
110
+ ensure_folder @current_template_dest
111
+ result = template.result(binding)
112
+ File.write dest_path(@current_template_dest), result
113
+ @to_copy.delete src
114
+ end
115
+ end
116
+
117
+ # Should only be called from within a file being interpolated.
118
+ # The output path will be changed to dest, which should be
119
+ # relative to the template's folder.
120
+ def rename(dest)
121
+ @current_template_dest = File.join(File.dirname(@current_template_src), dest)
122
+ end
123
+
124
+ # For each path or array of paths, disable implicit copying.
125
+ def ignore(*paths)
126
+ @to_copy -= paths.flatten
127
+ end
128
+
129
+ # Returns the text of the README, README.md or README.markdown file, if any.
130
+ def help
131
+ path = Dir[src_path('README')].first || Dir[src_path('README.md')].first || Dir[src_path('README.markdown')].first
132
+ if path
133
+ File.read path
134
+ end
135
+ end
136
+ end
137
+ end
@@ -0,0 +1,3 @@
1
+ module Codger
2
+ VERSION = "0.0.1"
3
+ end
data/lib/codger.rb ADDED
@@ -0,0 +1,8 @@
1
+ require 'active_support/core_ext'
2
+ require 'deep_merge/rails_compat'
3
+
4
+ require 'codger/cli'
5
+ require 'codger/generator'
6
+ require 'codger/manager'
7
+ require 'codger/skeleton'
8
+ require 'codger/version'
metadata ADDED
@@ -0,0 +1,103 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: codger
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Jacob Williams
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-03-05 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: activesupport
16
+ requirement: &70337635384820 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ~>
20
+ - !ruby/object:Gem::Version
21
+ version: 3.2.1
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: *70337635384820
25
+ - !ruby/object:Gem::Dependency
26
+ name: deep_merge
27
+ requirement: &70337635384160 !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
30
+ - - ~>
31
+ - !ruby/object:Gem::Version
32
+ version: 1.0.0
33
+ type: :runtime
34
+ prerelease: false
35
+ version_requirements: *70337635384160
36
+ - !ruby/object:Gem::Dependency
37
+ name: git
38
+ requirement: &70337635383500 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ~>
42
+ - !ruby/object:Gem::Version
43
+ version: 1.2.5
44
+ type: :runtime
45
+ prerelease: false
46
+ version_requirements: *70337635383500
47
+ - !ruby/object:Gem::Dependency
48
+ name: thor
49
+ requirement: &70337635382820 !ruby/object:Gem::Requirement
50
+ none: false
51
+ requirements:
52
+ - - ~>
53
+ - !ruby/object:Gem::Version
54
+ version: 0.14.6
55
+ type: :runtime
56
+ prerelease: false
57
+ version_requirements: *70337635382820
58
+ description: Manages invocation of code generators.
59
+ email:
60
+ - jacobaw@gmail.com
61
+ executables:
62
+ - codger
63
+ extensions: []
64
+ extra_rdoc_files: []
65
+ files:
66
+ - .gitignore
67
+ - Gemfile
68
+ - LICENSE
69
+ - README.md
70
+ - Rakefile
71
+ - bin/codger
72
+ - codger.gemspec
73
+ - lib/codger.rb
74
+ - lib/codger/cli.rb
75
+ - lib/codger/generator.rb
76
+ - lib/codger/manager.rb
77
+ - lib/codger/skeleton.rb
78
+ - lib/codger/version.rb
79
+ homepage: ''
80
+ licenses: []
81
+ post_install_message:
82
+ rdoc_options: []
83
+ require_paths:
84
+ - lib
85
+ required_ruby_version: !ruby/object:Gem::Requirement
86
+ none: false
87
+ requirements:
88
+ - - ! '>='
89
+ - !ruby/object:Gem::Version
90
+ version: '0'
91
+ required_rubygems_version: !ruby/object:Gem::Requirement
92
+ none: false
93
+ requirements:
94
+ - - ! '>='
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ requirements: []
98
+ rubyforge_project: codger
99
+ rubygems_version: 1.8.6
100
+ signing_key:
101
+ specification_version: 3
102
+ summary: Manages invocation of code generators.
103
+ test_files: []