drupal.rb 0.0.12

Sign up to get free protection for your applications and to get access to all the features.
Files changed (40) hide show
  1. data/History.txt +53 -0
  2. data/Manifest.txt +23 -0
  3. data/README.txt +108 -0
  4. data/Rakefile +21 -0
  5. data/bin/drupal +4 -0
  6. data/drupal.rb.gemspec +59 -0
  7. data/lib/drupal/create_module.rb +276 -0
  8. data/lib/drupal/install.rb +143 -0
  9. data/lib/drupal/templates/5.x/base/info +6 -0
  10. data/lib/drupal/templates/5.x/comments/file +9 -0
  11. data/lib/drupal/templates/5.x/comments/large +6 -0
  12. data/lib/drupal/templates/5.x/hooks/block +44 -0
  13. data/lib/drupal/templates/5.x/hooks/cron +7 -0
  14. data/lib/drupal/templates/5.x/hooks/form_alter +14 -0
  15. data/lib/drupal/templates/5.x/hooks/init +7 -0
  16. data/lib/drupal/templates/5.x/hooks/install +15 -0
  17. data/lib/drupal/templates/5.x/hooks/menu +24 -0
  18. data/lib/drupal/templates/5.x/hooks/perm +7 -0
  19. data/lib/drupal/templates/5.x/txt/changelog +9 -0
  20. data/lib/drupal/templates/5.x/txt/readme +36 -0
  21. data/lib/drupal/templates/6.x/base/info +6 -0
  22. data/lib/drupal/templates/6.x/comments/file +9 -0
  23. data/lib/drupal/templates/6.x/comments/large +6 -0
  24. data/lib/drupal/templates/6.x/hooks/block +45 -0
  25. data/lib/drupal/templates/6.x/hooks/boot +7 -0
  26. data/lib/drupal/templates/6.x/hooks/cron +7 -0
  27. data/lib/drupal/templates/6.x/hooks/form_alter +11 -0
  28. data/lib/drupal/templates/6.x/hooks/init +8 -0
  29. data/lib/drupal/templates/6.x/hooks/menu +17 -0
  30. data/lib/drupal/templates/6.x/hooks/perm +7 -0
  31. data/lib/drupal/templates/6.x/hooks/theme +11 -0
  32. data/lib/drupal/templates/6.x/txt/changelog +9 -0
  33. data/lib/drupal/templates/6.x/txt/readme +36 -0
  34. data/lib/drupal/todo_list.rb +72 -0
  35. data/lib/drupal.rb +156 -0
  36. data/test/test_create_module.rb +1 -0
  37. data/test/test_drupal.rb +6 -0
  38. data/test/test_install.rb +23 -0
  39. data/test/test_todo_list.rb +0 -0
  40. metadata +145 -0
data/History.txt ADDED
@@ -0,0 +1,53 @@
1
+ === 0.0.11 / 2010-02-14
2
+ * Database scaffolding initial. Adds CRUD database includefile and schema in install.
3
+
4
+ === 0.0.8 / 2009-08-06
5
+
6
+ * 1 Internal rewrite, 2 new features, 1 bugfix
7
+ * Added commandline option to allow selection of Drupal version for installation.
8
+
9
+ * Rewrote install system by parsing the drupal release XML rather then scraping HTML.
10
+ * Added defaults.yml config option. When this file is present, we parse the contents and
11
+ present them as defaults in interactive mode. Quicker module-building!
12
+ * If hook "install" was chose, the .install file was not created. Fixed.
13
+
14
+ === 0.0.7 / 2009-05-02
15
+
16
+ * Cleanup and rename to drupal.rb
17
+ * Implemented ability to override global templates in a ~/.drupal.rb directory.
18
+
19
+ === 0.0.6 / 2008-10-16
20
+
21
+ * 1 Minor Feature:
22
+
23
+ * Added hook_install() support
24
+
25
+ === 0.0.5 / 2008-10-06
26
+
27
+ * 1 Minor Fix:
28
+
29
+ * Todo list was not parsing items starting with '@' in @todo
30
+
31
+ === 0.0.4 / 2008-10-03
32
+
33
+ * 1 Major Feature:
34
+
35
+ * Installer allows lists of projects 'err,ac,devel'
36
+
37
+ === 0.0.3 / 2008-10-03
38
+
39
+ * 1 Major Feature:
40
+
41
+ * Installer for Drupal projects
42
+
43
+ === 0.0.2 / 2008-10-02
44
+
45
+ * 2 Bug Fixes:
46
+
47
+ * Executable
48
+ * Fixed template filepath errors
49
+
50
+ === 0.0.1 / 2008-09-27
51
+
52
+ * Initial release
53
+
data/Manifest.txt ADDED
@@ -0,0 +1,23 @@
1
+ History.txt
2
+ Manifest.txt
3
+ README.txt
4
+ Rakefile
5
+ bin/drupal
6
+ lib/drupal.rb
7
+ lib/drupal/todo_list.rb
8
+ lib/drupal/create_module.rb
9
+ lib/drupal/install.rb
10
+ lib/drupal/templates/comments/file
11
+ lib/drupal/templates/comments/large
12
+ lib/drupal/templates/hooks/block
13
+ lib/drupal/templates/hooks/boot
14
+ lib/drupal/templates/hooks/install
15
+ lib/drupal/templates/hooks/cron
16
+ lib/drupal/templates/hooks/form_alter
17
+ lib/drupal/templates/hooks/init
18
+ lib/drupal/templates/hooks/menu
19
+ lib/drupal/templates/hooks/perm
20
+ lib/drupal/templates/hooks/schema
21
+ lib/drupal/templates/hooks/theme
22
+ lib/drupal/templates/txt/changelog
23
+ lib/drupal/templates/txt/readme
data/README.txt ADDED
@@ -0,0 +1,108 @@
1
+ = drupal.rb
2
+
3
+ http://berkes.github.com/drupal.rb/
4
+
5
+ == DESCRIPTION:
6
+
7
+ Drupal is an open source Ruby development tool allowing developers
8
+ to quickly generate and manage Drupal modules.
9
+
10
+ == SYNOPSIS:
11
+
12
+ drupal [options] [arguments]
13
+
14
+ == REQUIREMENTS:
15
+
16
+ none
17
+
18
+ == ARGUMENTS:
19
+
20
+ create module <module_name> Generates a module skeleton from an interactive wizard.
21
+ todo list [total] Displays list of todo items or a total.
22
+ install <core | project> [dir] [5.x|6.x|7.x]
23
+ Install a Drupal project or core itself to [dir] (defaults to curent dir) for version (defaults to 6.x)
24
+
25
+ == OPTIONS:
26
+
27
+ -h, --help Display this help information.
28
+ -V, --version Display version of the Drupal development tool.
29
+
30
+ == EXAMPLES:
31
+
32
+ Create a new module in the current directory.
33
+ drupal create module my_module
34
+
35
+ Create a new module in a specific directory.
36
+ drupal create module my_module ./sites/all/modules
37
+
38
+ View todo list for current directory.
39
+ drupal todo list
40
+
41
+ View todo list for multiple files or directories.
42
+ drupal todo list ./sites/all/modules/mymodule
43
+
44
+ View total todo items only.
45
+ drupal todo list total ./sites/all/modules
46
+
47
+ Install drupal core to the current directory.
48
+ drupal install core
49
+
50
+ Install a 5.x module when in the 'modules directory
51
+ drupal install devel . 5.x
52
+
53
+ Install a module to the modules folder in my new installation (from drupal root)
54
+ drupal install devel ./sites/all/modules
55
+
56
+ Install a module when in the 'modules directory
57
+ drupal install devel
58
+
59
+ == LOCAL TEMPLATES
60
+
61
+ Create .drupal.rb/templates/ directories in your home-directory and put your
62
+ own templates there. Drupal.rb will pick these, instead of the global ones.
63
+
64
+ e.g. $ mkdir ~/.drupal.rb/
65
+ $ cp -r /path/to/gems/berkes-drupal.rb-0.0.7/var/lib/drupal/templates/ \
66
+ ~/.drupal.rb/templates/
67
+
68
+ == DEFAULTS
69
+ Create a file in ~/.drupal.rb/ named defaults.yml. The variables in there will
70
+ be used as defaults on the prompt when creating a module.
71
+ Alternatively you can copy the example from the doc dir in the package.
72
+
73
+ == AUTHOR:
74
+
75
+ Original:
76
+ TJ Holowaychuk
77
+ tj@vision-media.ca
78
+ http://vision-media.ca
79
+
80
+ Current Maintainer:
81
+ Bèr Kessels
82
+ ber@webschuur.com
83
+ http://webschuur.com
84
+
85
+ == LICENSE:
86
+
87
+ (The MIT License)
88
+
89
+ Copyright (c) 2008 FIX
90
+
91
+ Permission is hereby granted, free of charge, to any person obtaining
92
+ a copy of this software and associated documentation files (the
93
+ 'Software'), to deal in the Software without restriction, including
94
+ without limitation the rights to use, copy, modify, merge, publish,
95
+ distribute, sublicense, and/or sell copies of the Software, and to
96
+ permit persons to whom the Software is furnished to do so, subject to
97
+ the following conditions:
98
+
99
+ The above copyright notice and this permission notice shall be
100
+ included in all copies or substantial portions of the Software.
101
+
102
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
103
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
104
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
105
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
106
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
107
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
108
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Rakefile ADDED
@@ -0,0 +1,21 @@
1
+ # -*- ruby -*-
2
+
3
+ require 'rubygems'
4
+ require File.dirname(__FILE__) + '/lib/drupal'
5
+
6
+ desc 'Build and install ruby gem.'
7
+ task :build do
8
+ sh "sudo gem build ./drupal.gemspec"
9
+ sh "sudo gem install drupal-#{Drupal::VERSION}.gem"
10
+ end
11
+
12
+ desc 'Remove ruby gem build data.'
13
+ task :remove do
14
+ sh "sudo gem uninstall drupal"
15
+ sh "sudo rm drupal-#{Drupal::VERSION}.gem"
16
+ end
17
+
18
+ desc 'Run tests.'
19
+ task :test do
20
+ sh "ruby " + File.dirname(__FILE__) + '/test/test_drupal.rb' + ' -r tk'
21
+ end
data/bin/drupal ADDED
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'drupal'
4
+ Drupal.new.run(ARGV)
data/drupal.rb.gemspec ADDED
@@ -0,0 +1,59 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = "drupal.rb"
3
+ s.version = "0.0.12"
4
+ s.date = "2010-02-14"
5
+ s.summary = "Drupal development kit"
6
+ s.email = "ber@webschuur.com"
7
+ s.homepage = "http://berkes.github.com/drupal.rb/"
8
+ s.description = "Drupal is an open source Ruby development tool allowing developers to quickly generate and manage Drupal modules."
9
+ s.has_rdoc = true
10
+ s.require_path = "lib"
11
+ s.authors = ["tj@vision-media.ca", "ber@webschuur.com"]
12
+ s.add_dependency("archive-tar-minitar", ">0.5.0")
13
+ s.add_dependency("active_support", ">0.0.0")
14
+ s.requirements = [
15
+ "A POSIX compliant environment (Mac, Unix, Linux, and for Windows Cygwin)",
16
+ "Minitar Gem version 0.5.0 or greater. http://raa.ruby-lang.org/project/minitar",
17
+ "Pluralize, as found in active_support, for database scaffolding." ]
18
+ s.files = ["History.txt",
19
+ "Manifest.txt",
20
+ "README.txt",
21
+ "Rakefile",
22
+ "drupal.rb.gemspec",
23
+ "lib/drupal.rb",
24
+ "lib/drupal/create_module.rb",
25
+ "lib/drupal/todo_list.rb",
26
+ "lib/drupal/install.rb",
27
+ "lib/drupal/templates/6.x/comments/file",
28
+ "lib/drupal/templates/6.x/comments/large",
29
+ "lib/drupal/templates/6.x/hooks/block",
30
+ "lib/drupal/templates/6.x/hooks/boot",
31
+ "lib/drupal/templates/6.x/hooks/cron",
32
+ "lib/drupal/templates/6.x/hooks/form_alter",
33
+ "lib/drupal/templates/6.x/hooks/init",
34
+ "lib/drupal/templates/6.x/hooks/menu",
35
+ "lib/drupal/templates/6.x/hooks/perm",
36
+ "lib/drupal/templates/6.x/hooks/theme",
37
+ "lib/drupal/templates/6.x/txt/changelog",
38
+ "lib/drupal/templates/6.x/txt/readme",
39
+ "lib/drupal/templates/6.x/base/info",
40
+
41
+ "lib/drupal/templates/5.x/comments/file",
42
+ "lib/drupal/templates/5.x/comments/large",
43
+ "lib/drupal/templates/5.x/hooks/block",
44
+ "lib/drupal/templates/5.x/hooks/install",
45
+ "lib/drupal/templates/5.x/hooks/cron",
46
+ "lib/drupal/templates/5.x/hooks/form_alter",
47
+ "lib/drupal/templates/5.x/hooks/init",
48
+ "lib/drupal/templates/5.x/hooks/menu",
49
+ "lib/drupal/templates/5.x/hooks/perm",
50
+ "lib/drupal/templates/5.x/txt/changelog",
51
+ "lib/drupal/templates/5.x/txt/readme",
52
+ "lib/drupal/templates/5.x/base/info",
53
+
54
+ "bin/drupal"]
55
+ s.executables = ["drupal"]
56
+ s.test_files = ["test/test_drupal.rb", "test/test_install.rb", "test/test_create_module.rb", "test/test_todo_list.rb"]
57
+ s.rdoc_options = ["--main", "README.txt"]
58
+ s.extra_rdoc_files = ["History.txt", "Manifest.txt", "README.txt"]
59
+ end
@@ -0,0 +1,276 @@
1
+ require 'yaml'
2
+ require 'active_support'
3
+
4
+ class Drupal
5
+ class Create_Module
6
+
7
+ # Create a module using the module builing wizard.
8
+ def run(arguments)
9
+ @arguments = arguments
10
+ @dir = @arguments[1] || '.' # TODO remove trailing slash, check validity, and existance
11
+ self.check_module_name
12
+ self.run_wizard
13
+ end
14
+
15
+ # Ensure module name is supplied and that it is
16
+ # formatted correctly as module names must be alphanumeric
17
+ # and must begin with a letter.
18
+ def check_module_name
19
+ case
20
+ when @arguments.empty?; puts 'Module name required.'; exit 3
21
+ when !@arguments[0].match(/^[a-z][\w]+/); puts 'Invalid module name.'; exit 4
22
+ else @module = @arguments[0]
23
+ end
24
+ end
25
+
26
+ # Run module generation wizard.
27
+ def run_wizard
28
+ # TODO create self.log() with padding to even output
29
+ defaults = get_defaults
30
+
31
+ # TODO make each ask have a commandline-option equivalent.
32
+ @version = self.ask('What drupal version to scaffold for?:', defaults[:version])
33
+ @author = self.ask('What is your name?:', defaults[:author])
34
+ @link = self.ask('What is the URI to your companies website?:', defaults[:link])
35
+ @email = self.ask('What is your email?:', defaults[:email])
36
+ @module_name = self.ask('Enter a human readable name for your module:', defaults[:module_name])
37
+ @table = self.ask('Database table name for your module. Without the modulename. A table name "pirates" on the module "cool_people" we would give us a table "cool_people_pirates" Leave empty for no database-scaffolding.')
38
+ @module_description = self.ask('Enter a short description of your module:', defaults[:module_description])
39
+ @module_dependencies = self.ask('Enter a list of dependencies for your module:', defaults[:module_dependencies], true)
40
+ # Hooks
41
+ puts self.list_templates('Hooks:', 'hooks')
42
+ @hooks = self.ask('Which hooks would you like to implement?:', '', true)
43
+ # Files
44
+ puts self.list_templates('Files:', 'txt')
45
+ @files = self.ask('Which additional files would you like to include?:', '', true)
46
+ # Dirs
47
+ puts "\nCommon directories:"
48
+ puts ['js', 'images', 'css'].collect{ |d| " - " << d }
49
+ @dirs = self.ask('Which directories would you like to create?:', '', true)
50
+ # Finish
51
+ self.create_tokens
52
+ self.create_hook_weights
53
+ self.create_module
54
+ end
55
+
56
+ # Create global tokens.
57
+ def create_tokens
58
+ if not @table.nil?
59
+ @record = @table.singularize
60
+ else
61
+ @record = ''
62
+ end
63
+
64
+ @tokens = {
65
+ :module => @module,
66
+ :link => @link,
67
+ :email => @email,
68
+ :author => @author,
69
+ :module_name => @module_name,
70
+ :module_description => @module_description,
71
+ :module_dependencies => @module_dependencies,
72
+ :table => @table,
73
+ :record => @record,
74
+ }
75
+ end
76
+
77
+ # Register hook weights
78
+ def create_hook_weights
79
+ @hook_weights = [
80
+ 'perm',
81
+ 'cron',
82
+ 'boot',
83
+ 'init',
84
+ 'menu',
85
+ 'theme',
86
+ 'form_alter',
87
+ 'block',
88
+ ]
89
+ end
90
+
91
+ # Create module from wizard results.
92
+ def create_module
93
+ puts "\n... Creating module '#{@module}' in '#{@dir}'"
94
+ # Base directory
95
+ create_dir("#{@module}")
96
+ self.create_module_dirs
97
+ self.create_module_files
98
+ self.create_module_file
99
+ self.create_module_database_files
100
+ self.create_module_info_file
101
+ puts 'Module created :)'
102
+ end
103
+
104
+ # Create directories.
105
+ def create_module_dirs
106
+ @dirs.each{ |dir| create_dir("#{@module}/#{dir}") }
107
+ end
108
+
109
+ # Create file templates.
110
+ def create_module_files
111
+ @files.each do |file|
112
+ filepath = "#{file.upcase}.txt"
113
+ create_file(filepath)
114
+ append_template(filepath, "txt/#{file}", @tokens)
115
+ end
116
+ end
117
+
118
+ # Create .module file.
119
+ def create_module_file
120
+ create_file("#{@module}.module", "<?php\n")
121
+ append_template("#{@module}.module", 'comments/file', @tokens)
122
+ append_template("#{@module}.module", 'comments/large', {'title' => 'Hook Implementations'})
123
+ for hook in @hook_weights
124
+ if @hooks.include?(hook)
125
+ append_template("#{@module}.module", "hooks/#{hook}", @tokens)
126
+ end
127
+ end
128
+ end
129
+
130
+ # Create .install file, database includes and schema..
131
+ def create_module_database_files
132
+ if not @table.empty?
133
+ create_file("#{@module}.install", "<?php\n")
134
+ append_template("#{@module}.install", 'comments/file', @tokens)
135
+ ['install', 'schema'].each do |hook|
136
+ append_template("#{@module}.install", "incs/#{hook}", @tokens)
137
+ end
138
+
139
+ create_file("#{@module}_db.inc", "<?php\n")
140
+ append_template("#{@module}_db.inc", 'comments/file_db', @tokens)
141
+ append_template("#{@module}_db.inc", "incs/module_db", @tokens)
142
+
143
+ append_template("#{@module}.module", "hooks/init", @tokens) unless @hooks.include('init')
144
+ end
145
+ end
146
+
147
+ # Create info file.
148
+ def create_module_info_file
149
+ tokens = {
150
+ 'module_name' => @module_name,
151
+ 'module_description' => @module_description,
152
+ 'version' => @version,
153
+ }
154
+
155
+ if !@module_dependencies.nil?
156
+ #In 6.x each dep has a new line. In 5.x they are on a single line.
157
+ if (@version == '6.x')
158
+ @module_dependencies.each do |dependency|
159
+ tokens['dependencies_chunk'] = "\ndependencies[] = #{dependency}"
160
+ end
161
+ elsif (@version == '5.x')
162
+ tokens['dependencies_chunk'] = "dependencies = " + @module_dependencies.join(',')
163
+ end
164
+ end
165
+
166
+ filepath = "#{@module}.info"
167
+ create_file(filepath)
168
+ append_template(filepath, "base/info", tokens)
169
+ end
170
+
171
+ # Create a new directory.
172
+ def create_dir(dir)
173
+ dir = "#{@dir}/#{dir}"
174
+ puts "... Creating directory '#{dir}'"
175
+ Dir.mkdir(dir)
176
+ end
177
+
178
+ # Create a new file.
179
+ def create_file(filepath, contents = '')
180
+ filepath = "#{@dir}/#{@module}/#{filepath}"
181
+ puts "... Creating file '#{filepath}'"
182
+ File.open(filepath, 'w') do |f|
183
+ f.write contents
184
+ end
185
+ end
186
+
187
+ # Append a tokenized template template to a file.
188
+ def append_template(filepath, template, tokens = {})
189
+ # TODO: ensure template exists
190
+ # TODO: is \n included with STDIN?
191
+ _template = template
192
+ filepath = "#{@dir}/#{@module}/#{filepath}"
193
+ template = get_template_location << template
194
+ puts "... Adding template '#{_template}' to '#{filepath}'"
195
+ contents = File.read(template)
196
+ tokens.each_pair do |token, value|
197
+ if value.class == String && contents.include?("[#{token}]")
198
+ contents.gsub!(/\[#{token}\]/, value)
199
+ end
200
+ end
201
+ File.open(filepath, 'a') do |f|
202
+ f.write contents
203
+ end
204
+ end
205
+
206
+ # Prompt user for input
207
+ def ask(question, default = '', list = false)
208
+ if not default.to_s.empty? then question = question << " (#{default})" end
209
+ puts "\n" << question
210
+
211
+ # TODO: support 'all'
212
+ # TODO: why is gets not working?
213
+ # TODO: not catching exception when CTRL+C ?
214
+ begin
215
+ case list
216
+ when true; input = STDIN.gets.split
217
+ when false; input = STDIN.gets.gsub!(/\n/, '')
218
+ end
219
+ rescue => e
220
+ puts ':)'
221
+ end
222
+
223
+ if input.empty?
224
+ return default
225
+ else
226
+ return input
227
+ end
228
+ end
229
+
230
+ # List templates available of a certain type.
231
+ def list_templates(title, type)
232
+ "\n" << title << self.get_templates(type).collect{ |t| "\n - " << File.basename(t) }.join
233
+ end
234
+
235
+ # Get array of templates of a certain type.
236
+ def get_templates(type)
237
+ Dir[get_template_location << type << '/*']
238
+ end
239
+
240
+
241
+ private
242
+ def get_template_location
243
+ location = File.expand_path "~/.drupal.rb/templates/#{@version}"
244
+
245
+ unless File.directory? location
246
+ location = File.dirname(__FILE__) + "/templates/#{@version}"
247
+ end
248
+
249
+ return location + '/'
250
+ end
251
+
252
+ # @TODO: implement defaults that can be altered for list of hooks and files
253
+ def get_defaults
254
+ defaults = {}
255
+ location = File.expand_path '~/.drupal.rb/defaults.yml'
256
+ if File.readable? location
257
+ defaults_yml = File.open( location ) { |yf| YAML::load( yf ) }
258
+
259
+ # @TODO: There is most probably a much nicer Rubyism for this nested looping.
260
+ # If you know Ruby better then I do, please chime in and change this.
261
+ create_tokens().each do |token|
262
+ defaults_yml.each do |d|
263
+ if (d.has_key? token.first.to_s)
264
+ defaults[token.first] = d[token.first.to_s]
265
+ end
266
+ end
267
+ end
268
+ else
269
+ defaults = create_tokens
270
+ end
271
+
272
+ return defaults
273
+ end
274
+ end
275
+ end
276
+
@@ -0,0 +1,143 @@
1
+ require 'rubygems'
2
+ require 'net/http'
3
+ require 'rexml/document'
4
+ require 'zlib'
5
+ require 'archive/tar/minitar'
6
+
7
+ class Drupal
8
+ class Install
9
+ include REXML
10
+ # Attempt to download core installation or module.
11
+ def run(arguments)
12
+ @project = arguments[0]
13
+ @dest = arguments[1] || '.'
14
+ @version = arguments[2] || '6.x'
15
+ abort "Destination #{@dest} is not a directory." unless File.directory?(@dest)
16
+ abort 'Project name required (core | <project>).' if arguments.empty?
17
+ install_projects
18
+ end
19
+
20
+ def debug(message)
21
+ puts '... ' + message
22
+ end
23
+
24
+ # Install single project or iterate lists.
25
+ def install_projects
26
+ if @project.include? ','
27
+ projects = @project.split ','
28
+ projects.each do |p|
29
+ @project = p
30
+ check_core
31
+ install_project
32
+ puts
33
+ end
34
+ else
35
+ check_core
36
+ install_project
37
+ end
38
+ end
39
+
40
+ # Check if the destination is empty.
41
+ def destination_empty?
42
+ Dir['*'].length == 0
43
+ end
44
+
45
+ # Allow users to type 'core' instead of 'drupal install drupal'
46
+ def check_core
47
+ @project = 'drupal' if @project =~ /^core|drupal$/
48
+ end
49
+
50
+ # Check if a uri is available.
51
+ def uri_available?(uri)
52
+ open(uri) rescue false
53
+ end
54
+
55
+ # Install project.
56
+ # @TODO move all the updates.drupal.org xml parsing into a separate Class
57
+ def install_project
58
+ xmldoc = get_xml(@project, @version)
59
+ release = get_release(xmldoc, 'latest')
60
+ @tarpath = get_tarball(release)
61
+
62
+ # Extract tarball
63
+ tgz = Zlib::GzipReader.new(File.open(@tarpath, 'rb'))
64
+ Archive::Tar::Minitar.unpack(tgz, @dest) rescue abort "Failed to extract #{@tarpath} to #{@dest}"
65
+
66
+ # Remove tarball
67
+ File.delete(@tarpath) rescue abort "Failed to remove #{@tarpath}"
68
+
69
+ # Installation complete
70
+ debug "Project #{@project} installed to #{File.dirname(@tarpath)}" unless @dest == '.'
71
+ debug 'Installation complete'
72
+ end
73
+
74
+ def get_xml project, version='6.x'
75
+ debug "Locating #{project} page for version #{version}"
76
+ # Locate tarball from project page
77
+ begin
78
+ response = Net::HTTP.get_response(URI.parse("http://updates.drupal.org/release-history/#{project}/#{version}"))
79
+ # TODO: unhardcode the dependency on Drupal 6, make this an environment or static var.
80
+ # TODO: check 404, 403 etc.
81
+ xmldoc = Document.new response.body
82
+ if xmldoc.root.name == 'error' #TODO: better error handling here.
83
+ message = xmldoc.root.text
84
+ raise message
85
+ end
86
+ rescue
87
+ abort "Could not fetch #{project}. Error: #{message}"
88
+ end
89
+
90
+ return xmldoc
91
+ end
92
+
93
+ def get_releases(xmldoc)
94
+ releases = Hash.new
95
+
96
+ xmldoc.root.each_element('//release') do |release|
97
+ releases[release.text('version')] = release
98
+ end
99
+
100
+ return releases
101
+ end
102
+
103
+ # returns the release with releasenumber 'which' from xmldoc.
104
+ # use 'latest' for which, if you want the latest stable release
105
+ def get_release(xmldoc, which)
106
+ releases = get_releases(xmldoc)
107
+
108
+ ordered = releases.keys.sort_by {|k| k.to_s.split(/\.|-/).map {|v| v.to_i} }
109
+
110
+ if ( which == 'latest' )
111
+ release = releases[ordered.last]
112
+ elsif ordered.include? which
113
+ release = releases[which]
114
+ else
115
+ raise "Failed to find requested release #{which}"
116
+ end
117
+
118
+ return release
119
+ end
120
+
121
+ def get_tarball(release)
122
+ tarball = release.elements['//download_link'].text
123
+ tarpath = File.basename(tarball)
124
+
125
+ abort "Failed to find Drupal 6 tar of #{@project}" if tarball.nil?
126
+ debug "Found tarball #{tarball}"
127
+
128
+ # Fetch tarball
129
+ begin
130
+ response = Net::HTTP.get_response(URI.parse(tarball))
131
+ puts tarpath
132
+ File.open(tarpath, 'w') do |f|
133
+ f.write response.body
134
+ end
135
+ debug "Copied tarball to #{tarpath}"
136
+ rescue
137
+ abort "Failed to copy remote tarball #{tarball} to #{tarpath}"
138
+ end
139
+
140
+ return tarpath
141
+ end
142
+ end
143
+ end
@@ -0,0 +1,6 @@
1
+ ; $Id$'
2
+
3
+ name = [module_name]
4
+ description = [module_description]
5
+ core = [version]
6
+ [dependencies_chunk]