groundwork 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/bin/groundwork ADDED
@@ -0,0 +1,26 @@
1
+ #!/usr/bin/ruby
2
+
3
+ require File.join(File.dirname(__FILE__),"..","lib","groundwork.rb")
4
+
5
+ begin
6
+ options = Groundwork::parse_options
7
+
8
+ case options[:command]
9
+ when "generate"
10
+ generate_opts = Trollop::options(options[:remainder]) do
11
+ opt :force, :default=>false
12
+ end
13
+
14
+ name = options[:remainder].shift || "Recipe"
15
+
16
+ if File.exists?(name+".recipe") && !generate_opts[:force]
17
+ raise RuntimeError.new("File already exists: #{name}.recipe")
18
+ end
19
+
20
+ recipe = Groundwork::Recipe.generate
21
+ File.open(name+".recipe","w"){|f| f.print recipe}
22
+ else
23
+ end
24
+ rescue
25
+ puts $!.to_s
26
+ end
data/lib/groundwork.rb ADDED
@@ -0,0 +1,175 @@
1
+ require "rubygems"
2
+ require "trollop"
3
+ require "erb"
4
+ require "pathname"
5
+ require File.join(File.dirname(__FILE__), "options.rb")
6
+ require File.join(File.dirname(__FILE__), "tar_wrapper.rb")
7
+
8
+ module Groundwork
9
+ class Recipe
10
+ def initialize &block
11
+ if block_given?
12
+ instance_eval &block
13
+ end
14
+ end
15
+
16
+ def tar= data
17
+ @tar = TarWrapper.new(data)
18
+ end
19
+
20
+ # Creates a directory. If a block is passed,
21
+ # the block will be run inside that directory
22
+ def directory *name, &block
23
+ FileUtils.mkdir_p File.join(name)
24
+ if block_given?
25
+ FileUtils.cd File.join(name), &block
26
+ end
27
+ end
28
+
29
+ # If opts is a string, it's the contents of the file, verbatim
30
+ # If opts is a hash, it must contain either:
31
+ # * :from, copies the text of the given filename verbatim
32
+ # * :from_erb, uses the text of the filename as an erb template
33
+ # * :erb, uses the given string as an erb template
34
+ def file name, opts = nil
35
+ name = File.join(name)
36
+ File.open(File.join(name),"w") do |file|
37
+ if opts.is_a? String
38
+ file.print opts
39
+ elsif opts.is_a? Hash
40
+ file.print( if opts[:from]
41
+ read_file opts[:from]
42
+ elsif opts[:from_erb]
43
+ ERB.new(read_file(opts[:from_erb])).result(binding)
44
+ elsif opts[:erb]
45
+ ERB.new(opts[:erb]).result(binding)
46
+ end )
47
+ elsif opts.nil?
48
+ # write nothing
49
+ else
50
+ raise ArgumentError.new
51
+ end
52
+ end
53
+ end
54
+
55
+ # When you compile a recipe, it runs it to determine which files to bake in.
56
+ # If you have a file that might not be generated by running your script with
57
+ # no options, you can call possible on it to ensure it gets baked into
58
+ # the script. This function only has an effect during compilation, it does
59
+ # nothing when the script is actually run.
60
+ def possible name ; end
61
+
62
+ # Takes a block and lists the files that that block will require as templates.
63
+ # See Groundwork::Recipe#possible
64
+ def self.required_files &block
65
+ dummy = Object.new
66
+ files = []
67
+
68
+ class << dummy
69
+ attr_reader :files
70
+
71
+ def directory *args
72
+ yield if block_given?
73
+ end
74
+
75
+ def file name, opts=nil
76
+ @files << opts[:from] if opts[:from]
77
+ @files << opts[:from_erb] if opts[:from_erb]
78
+ end
79
+
80
+ def possible name
81
+ @files << name
82
+ end
83
+
84
+ def method_missing *args ; end
85
+ end
86
+
87
+ dummy.instance_variable_set "@files", []
88
+ dummy.instance_eval &block
89
+
90
+ dummy.files
91
+ end
92
+
93
+ # Takes a script file, finds the files it requires (paths relative to the script file),
94
+ # reads/tars them and returns a string containing the script and the TAR blob, ready
95
+ # to write to a file
96
+ def self.compile script_file
97
+ script = File.read(script_file)
98
+ out = StringIO.new
99
+ data = nil
100
+
101
+ FileUtils.cd(File.dirname(script_file)) do
102
+ files = required_files do
103
+ eval script
104
+ end
105
+
106
+ data = TarWrapper.compress files
107
+ end
108
+
109
+ out.puts "if $0==__FILE__"
110
+ out.puts " require 'rubygems'"
111
+ out.puts " require 'kickstart'"
112
+ out.puts "end"
113
+ out.puts ""
114
+ out.puts script
115
+ out.puts ""
116
+ out.puts "__END__"
117
+ out.puts data
118
+
119
+ out.string
120
+ end
121
+
122
+ # Takes a filename and runs the script contained in it. The file should be
123
+ # the results of Groundwork::Recipe#compile
124
+ def self.run script_file
125
+ (script, data) = File.read(script_file).split("\n__END__\n")
126
+
127
+ Groundwork::Recipe.new do
128
+ self.tar = data
129
+ eval script
130
+ end
131
+ end
132
+
133
+ # Generate a tree of file and directory calls that would create the given
134
+ # directory
135
+ def self.generate dir = FileUtils.pwd
136
+ base = Pathname.new dir
137
+
138
+ handle_dir = lambda do |d, output, indent|
139
+ FileUtils.cd d do
140
+ Dir["*"].each do |file|
141
+ if File.directory? file
142
+ if Dir[File.join(file,"*")].empty?
143
+ output.puts((" "*indent)+"directory \"#{file}\"")
144
+ else
145
+ output.puts("")
146
+ output.puts((" "*indent)+"directory \"#{file}\" do")
147
+ handle_dir[file, output, indent+2]
148
+ output.puts((" "*indent)+"end")
149
+ output.puts("")
150
+ end
151
+ else
152
+ rel = Pathname.new(File.join(FileUtils.pwd,file))
153
+ relpath = rel.relative_path_from(base).to_s
154
+ output.puts((" "*indent)+"file \"#{file}\", :from => \"#{relpath}\"")
155
+ end
156
+ end
157
+ end
158
+ end
159
+
160
+ str = StringIO.new
161
+ handle_dir[dir, str, 0]
162
+ str.string.gsub(/\n\n+/,"\n\n") # Collapse adjacent blank lines
163
+ end
164
+
165
+ private
166
+
167
+ def read_file name
168
+ if @tar
169
+ @tar[name]
170
+ else
171
+ File.read(name)
172
+ end
173
+ end
174
+ end
175
+ end
data/lib/options.rb ADDED
@@ -0,0 +1,32 @@
1
+ require "abbrev"
2
+
3
+ module Groundwork
4
+ def self.parse_options opts=ARGV
5
+ global_opts = Trollop::options(opts) do
6
+ banner "Groundwork"
7
+ version "0.0.1"
8
+ stop_on_unknown
9
+ end
10
+
11
+ cmd=short_for(opts.shift)
12
+
13
+ return({ :options=>global_opts,
14
+ :command=>cmd,
15
+ :remainder=>opts
16
+ })
17
+ end
18
+
19
+ def self.short_for cmd_start, all_commands=["generate"]
20
+ return cmd_start unless cmd_start
21
+ return cmd_start if all_commands.index(cmd_start)
22
+
23
+ completions = all_commands.abbrev(cmd_start)
24
+ if completions[cmd_start]
25
+ completions[cmd_start]
26
+ elsif completions.values.uniq.empty?
27
+ raise RuntimeError.new("Unknown command \"#{cmd_start}\".")
28
+ else
29
+ raise RuntimeError.new("\"#{cmd_start}\" is ambiguous. Which did you mean:\n\t"+cmd_poss.join("\n\t"))
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,33 @@
1
+ require "rubygems"
2
+ require "archive/tar/minitar"
3
+ require "base64"
4
+
5
+ class Groundwork::TarWrapper
6
+ include Archive::Tar
7
+
8
+ # Takes a base64-encoded, tarred string
9
+ def initialize encoded
10
+ tar = Base64.decode64(encoded)
11
+ @files = {}
12
+ Minitar::Reader.new(StringIO.new(tar)).each do |entry|
13
+ next unless entry.file?
14
+ @files[entry.full_name] = entry.read
15
+ end
16
+ end
17
+
18
+ def [] name
19
+ @files[name]
20
+ end
21
+
22
+ def self.compress files
23
+ string = StringIO.new
24
+ output = Minitar::Output.new(string)
25
+
26
+ files.each do |file|
27
+ Minitar.pack_file(file, output)
28
+ end
29
+
30
+ output.close
31
+ Base64.encode64 string.string
32
+ end
33
+ end
metadata ADDED
@@ -0,0 +1,91 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: groundwork
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 0
8
+ - 1
9
+ version: 0.0.1
10
+ platform: ruby
11
+ authors:
12
+ - Andrews, Ross
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2010-02-23 00:00:00 -06:00
18
+ default_executable:
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ name: trollop
22
+ prerelease: false
23
+ requirement: &id001 !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - ">="
26
+ - !ruby/object:Gem::Version
27
+ segments:
28
+ - 1
29
+ - 10
30
+ - 2
31
+ version: 1.10.2
32
+ type: :runtime
33
+ version_requirements: *id001
34
+ - !ruby/object:Gem::Dependency
35
+ name: archive-tar-minitar
36
+ prerelease: false
37
+ requirement: &id002 !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - ">="
40
+ - !ruby/object:Gem::Version
41
+ segments:
42
+ - 0
43
+ - 5
44
+ - 2
45
+ version: 0.5.2
46
+ type: :runtime
47
+ version_requirements: *id002
48
+ description: Create scripts that describe the groundwork for laying out your projects, and generate project frameworks
49
+ email: randrews@geekfu.org
50
+ executables:
51
+ - groundwork
52
+ extensions: []
53
+
54
+ extra_rdoc_files: []
55
+
56
+ files:
57
+ - lib/groundwork.rb
58
+ - lib/tar_wrapper.rb
59
+ - lib/options.rb
60
+ has_rdoc: true
61
+ homepage: https://github.com/randrews/groundwork
62
+ licenses: []
63
+
64
+ post_install_message:
65
+ rdoc_options: []
66
+
67
+ require_paths:
68
+ - lib
69
+ required_ruby_version: !ruby/object:Gem::Requirement
70
+ requirements:
71
+ - - ">="
72
+ - !ruby/object:Gem::Version
73
+ segments:
74
+ - 0
75
+ version: "0"
76
+ required_rubygems_version: !ruby/object:Gem::Requirement
77
+ requirements:
78
+ - - ">="
79
+ - !ruby/object:Gem::Version
80
+ segments:
81
+ - 0
82
+ version: "0"
83
+ requirements: []
84
+
85
+ rubyforge_project: groundwork
86
+ rubygems_version: 1.3.6
87
+ signing_key:
88
+ specification_version: 3
89
+ summary: A project scaffolding generator
90
+ test_files: []
91
+