rails 1.0.0 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of rails might be problematic. Click here for more details.
- data/CHANGELOG +152 -10
- data/README +30 -5
- data/Rakefile +18 -13
- data/bin/rails +1 -11
- data/{lib/rails_info.rb → builtin/rails_info/rails/info.rb} +25 -8
- data/builtin/{controllers/rails_info_controller.rb → rails_info/rails/info_controller.rb} +2 -2
- data/configs/databases/mysql.yml +47 -0
- data/configs/databases/oracle.yml +30 -0
- data/configs/databases/postgresql.yml +44 -0
- data/configs/databases/sqlite2.yml +16 -0
- data/configs/databases/sqlite3.yml +16 -0
- data/configs/lighttpd.conf +11 -5
- data/configs/routes.rb +5 -2
- data/environments/development.rb +3 -2
- data/environments/environment.rb +5 -8
- data/environments/production.rb +1 -2
- data/environments/test.rb +1 -1
- data/fresh_rakefile +2 -2
- data/html/500.html +1 -1
- data/html/index.html +3 -3
- data/html/javascripts/application.js +2 -0
- data/html/javascripts/controls.js +95 -30
- data/html/javascripts/dragdrop.js +161 -21
- data/html/javascripts/effects.js +310 -211
- data/html/javascripts/prototype.js +228 -28
- data/lib/code_statistics.rb +1 -1
- data/lib/commands/console.rb +3 -1
- data/lib/commands/plugin.rb +113 -70
- data/lib/commands/process/reaper.rb +1 -1
- data/lib/commands/process/spawner.rb +33 -4
- data/lib/commands/runner.rb +1 -1
- data/lib/commands/server.rb +3 -1
- data/lib/commands/servers/lighttpd.rb +41 -9
- data/lib/console_app.rb +27 -0
- data/lib/console_with_helpers.rb +23 -0
- data/lib/dispatcher.rb +8 -8
- data/lib/fcgi_handler.rb +22 -4
- data/lib/initializer.rb +107 -38
- data/lib/rails_generator/commands.rb +17 -7
- data/lib/rails_generator/generators/applications/app/app_generator.rb +30 -18
- data/lib/rails_generator/generators/components/integration_test/USAGE +14 -0
- data/lib/rails_generator/generators/components/integration_test/integration_test_generator.rb +16 -0
- data/lib/rails_generator/generators/components/integration_test/templates/integration_test.rb +10 -0
- data/lib/rails_generator/generators/components/mailer/USAGE +1 -1
- data/lib/rails_generator/generators/components/migration/USAGE +1 -1
- data/lib/rails_generator/generators/components/model/USAGE +3 -1
- data/lib/rails_generator/generators/components/model/model_generator.rb +16 -0
- data/lib/rails_generator/generators/components/model/templates/migration.rb +11 -0
- data/lib/rails_generator/generators/components/model/templates/unit_test.rb +1 -1
- data/lib/rails_generator/generators/components/plugin/USAGE +3 -1
- data/lib/rails_generator/generators/components/plugin/plugin_generator.rb +1 -0
- data/lib/rails_generator/generators/components/plugin/templates/Rakefile +1 -1
- data/lib/rails_generator/generators/components/plugin/templates/install.rb +1 -0
- data/lib/rails_generator/generators/components/scaffold/scaffold_generator.rb +1 -1
- data/lib/rails_generator/generators/components/scaffold/templates/controller.rb +4 -0
- data/lib/rails_generator/generators/components/scaffold/templates/style.css +4 -4
- data/lib/rails_generator/generators/components/scaffold/templates/view_list.rhtml +1 -1
- data/lib/rails_generator/generators/components/session_migration/USAGE +1 -1
- data/lib/rails_generator/options.rb +2 -2
- data/lib/rails_version.rb +1 -1
- data/lib/ruby_version_check.rb +17 -0
- data/lib/tasks/databases.rake +141 -139
- data/lib/tasks/documentation.rake +73 -68
- data/lib/tasks/framework.rake +86 -58
- data/lib/tasks/log.rake +9 -0
- data/lib/tasks/misc.rake +2 -17
- data/lib/tasks/pre_namespace_aliases.rake +46 -0
- data/lib/tasks/statistics.rake +9 -8
- data/lib/tasks/testing.rake +81 -29
- data/lib/tasks/tmp.rake +30 -0
- data/lib/test_help.rb +1 -0
- data/lib/webrick_server.rb +6 -8
- metadata +284 -271
- data/bin/process/spinner +0 -3
- data/configs/database.yml +0 -85
- data/lib/tasks/javascripts.rake +0 -6
@@ -1,17 +1,13 @@
|
|
1
|
-
/* Prototype JavaScript framework, version 1.
|
1
|
+
/* Prototype JavaScript framework, version 1.5.0_pre1
|
2
2
|
* (c) 2005 Sam Stephenson <sam@conio.net>
|
3
3
|
*
|
4
|
-
* THIS FILE IS AUTOMATICALLY GENERATED. When sending patches, please diff
|
5
|
-
* against the source tree, available from the Prototype darcs repository.
|
6
|
-
*
|
7
4
|
* Prototype is freely distributable under the terms of an MIT-style license.
|
8
|
-
*
|
9
5
|
* For details, see the Prototype web site: http://prototype.conio.net/
|
10
6
|
*
|
11
7
|
/*--------------------------------------------------------------------------*/
|
12
8
|
|
13
9
|
var Prototype = {
|
14
|
-
Version: '1.
|
10
|
+
Version: '1.5.0_pre1',
|
15
11
|
ScriptFragment: '(?:<script.*?>)((\n|\r|.)*?)(?:<\/script>)',
|
16
12
|
|
17
13
|
emptyFunction: function() {},
|
@@ -120,26 +116,49 @@ PeriodicalExecuter.prototype = {
|
|
120
116
|
}
|
121
117
|
}
|
122
118
|
}
|
119
|
+
Object.extend(String.prototype, {
|
120
|
+
gsub: function(pattern, replacement) {
|
121
|
+
var result = '', source = this, match;
|
122
|
+
replacement = arguments.callee.prepareReplacement(replacement);
|
123
|
+
|
124
|
+
while (source.length > 0) {
|
125
|
+
if (match = source.match(pattern)) {
|
126
|
+
result += source.slice(0, match.index);
|
127
|
+
result += (replacement(match) || '').toString();
|
128
|
+
source = source.slice(match.index + match[0].length);
|
129
|
+
} else {
|
130
|
+
result += source, source = '';
|
131
|
+
}
|
132
|
+
}
|
133
|
+
return result;
|
134
|
+
},
|
123
135
|
|
124
|
-
|
136
|
+
sub: function(pattern, replacement, count) {
|
137
|
+
replacement = this.gsub.prepareReplacement(replacement);
|
138
|
+
count = count === undefined ? 1 : count;
|
125
139
|
|
126
|
-
|
127
|
-
|
140
|
+
return this.gsub(pattern, function(match) {
|
141
|
+
if (--count < 0) return match[0];
|
142
|
+
return replacement(match);
|
143
|
+
});
|
144
|
+
},
|
128
145
|
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
146
|
+
scan: function(pattern, iterator) {
|
147
|
+
this.gsub(pattern, iterator);
|
148
|
+
return this;
|
149
|
+
},
|
133
150
|
|
134
|
-
|
135
|
-
|
151
|
+
truncate: function(length, truncation) {
|
152
|
+
length = length || 30;
|
153
|
+
truncation = truncation === undefined ? '...' : truncation;
|
154
|
+
return this.length > length ?
|
155
|
+
this.slice(0, length - truncation.length) + truncation : this;
|
156
|
+
},
|
136
157
|
|
137
|
-
|
138
|
-
|
158
|
+
strip: function() {
|
159
|
+
return this.replace(/^\s+/, '').replace(/\s+$/, '');
|
160
|
+
},
|
139
161
|
|
140
|
-
return elements;
|
141
|
-
}
|
142
|
-
Object.extend(String.prototype, {
|
143
162
|
stripTags: function() {
|
144
163
|
return this.replace(/<\/?[^>]+>/gi, '');
|
145
164
|
},
|
@@ -203,12 +222,35 @@ Object.extend(String.prototype, {
|
|
203
222
|
},
|
204
223
|
|
205
224
|
inspect: function() {
|
206
|
-
return "'" + this.replace(
|
225
|
+
return "'" + this.replace(/\\/g, '\\\\').replace(/'/g, '\\\'') + "'";
|
207
226
|
}
|
208
227
|
});
|
209
228
|
|
229
|
+
String.prototype.gsub.prepareReplacement = function(replacement) {
|
230
|
+
if (typeof replacement == 'function') return replacement;
|
231
|
+
var template = new Template(replacement);
|
232
|
+
return function(match) { return template.evaluate(match) };
|
233
|
+
}
|
234
|
+
|
210
235
|
String.prototype.parseQuery = String.prototype.toQueryParams;
|
211
236
|
|
237
|
+
var Template = Class.create();
|
238
|
+
Template.Pattern = /(^|.|\r|\n)(#\{(.*?)\})/;
|
239
|
+
Template.prototype = {
|
240
|
+
initialize: function(template, pattern) {
|
241
|
+
this.template = template.toString();
|
242
|
+
this.pattern = pattern || Template.Pattern;
|
243
|
+
},
|
244
|
+
|
245
|
+
evaluate: function(object) {
|
246
|
+
return this.template.gsub(this.pattern, function(match) {
|
247
|
+
var before = match[1];
|
248
|
+
if (before == '\\') return match[2];
|
249
|
+
return before + (object[match[3]] || '').toString();
|
250
|
+
});
|
251
|
+
}
|
252
|
+
}
|
253
|
+
|
212
254
|
var $break = new Object();
|
213
255
|
var $continue = new Object();
|
214
256
|
|
@@ -375,8 +417,7 @@ var Enumerable = {
|
|
375
417
|
|
376
418
|
var collections = [this].concat(args).map($A);
|
377
419
|
return this.map(function(value, index) {
|
378
|
-
iterator(
|
379
|
-
return value;
|
420
|
+
return iterator(collections.pluck(index));
|
380
421
|
});
|
381
422
|
},
|
382
423
|
|
@@ -662,7 +703,8 @@ Ajax.Request.prototype = Object.extend(new Ajax.Base(), {
|
|
662
703
|
setRequestHeaders: function() {
|
663
704
|
var requestHeaders =
|
664
705
|
['X-Requested-With', 'XMLHttpRequest',
|
665
|
-
'X-Prototype-Version', Prototype.Version
|
706
|
+
'X-Prototype-Version', Prototype.Version,
|
707
|
+
'Accept', 'text/javascript, text/html, application/xml, text/xml, */*'];
|
666
708
|
|
667
709
|
if (this.options.method == 'post') {
|
668
710
|
requestHeaders.push('Content-type',
|
@@ -831,22 +873,48 @@ Ajax.PeriodicalUpdater.prototype = Object.extend(new Ajax.Base(), {
|
|
831
873
|
this.updater = new Ajax.Updater(this.container, this.url, this.options);
|
832
874
|
}
|
833
875
|
});
|
876
|
+
function $() {
|
877
|
+
var results = [], element;
|
878
|
+
for (var i = 0; i < arguments.length; i++) {
|
879
|
+
element = arguments[i];
|
880
|
+
if (typeof element == 'string')
|
881
|
+
element = document.getElementById(element);
|
882
|
+
results.push(Element.extend(element));
|
883
|
+
}
|
884
|
+
return results.length < 2 ? results[0] : results;
|
885
|
+
}
|
886
|
+
|
834
887
|
document.getElementsByClassName = function(className, parentElement) {
|
835
888
|
var children = ($(parentElement) || document.body).getElementsByTagName('*');
|
836
889
|
return $A(children).inject([], function(elements, child) {
|
837
890
|
if (child.className.match(new RegExp("(^|\\s)" + className + "(\\s|$)")))
|
838
|
-
elements.push(child);
|
891
|
+
elements.push(Element.extend(child));
|
839
892
|
return elements;
|
840
893
|
});
|
841
894
|
}
|
842
895
|
|
843
896
|
/*--------------------------------------------------------------------------*/
|
844
897
|
|
845
|
-
if (!window.Element)
|
898
|
+
if (!window.Element)
|
846
899
|
var Element = new Object();
|
900
|
+
|
901
|
+
Element.extend = function(element) {
|
902
|
+
if (!element) return;
|
903
|
+
|
904
|
+
if (!element._extended && element.tagName && element != window) {
|
905
|
+
var methods = Element.Methods;
|
906
|
+
for (property in methods) {
|
907
|
+
var value = methods[property];
|
908
|
+
if (typeof value == 'function')
|
909
|
+
element[property] = value.bind(null, element);
|
910
|
+
}
|
911
|
+
}
|
912
|
+
|
913
|
+
element._extended = true;
|
914
|
+
return element;
|
847
915
|
}
|
848
916
|
|
849
|
-
|
917
|
+
Element.Methods = {
|
850
918
|
visible: function(element) {
|
851
919
|
return $(element).style.display != 'none';
|
852
920
|
},
|
@@ -882,6 +950,19 @@ Object.extend(Element, {
|
|
882
950
|
setTimeout(function() {html.evalScripts()}, 10);
|
883
951
|
},
|
884
952
|
|
953
|
+
replace: function(element, html) {
|
954
|
+
element = $(element);
|
955
|
+
if (element.outerHTML) {
|
956
|
+
element.outerHTML = html.stripScripts();
|
957
|
+
} else {
|
958
|
+
var range = element.ownerDocument.createRange();
|
959
|
+
range.selectNodeContents(element);
|
960
|
+
element.parentNode.replaceChild(
|
961
|
+
range.createContextualFragment(html.stripScripts()), element);
|
962
|
+
}
|
963
|
+
setTimeout(function() {html.evalScripts()}, 10);
|
964
|
+
},
|
965
|
+
|
885
966
|
getHeight: function(element) {
|
886
967
|
element = $(element);
|
887
968
|
return element.offsetHeight;
|
@@ -920,6 +1001,13 @@ Object.extend(Element, {
|
|
920
1001
|
return $(element).innerHTML.match(/^\s*$/);
|
921
1002
|
},
|
922
1003
|
|
1004
|
+
childOf: function(element, ancestor) {
|
1005
|
+
element = $(element), ancestor = $(ancestor);
|
1006
|
+
while (element = element.parentNode)
|
1007
|
+
if (element == ancestor) return true;
|
1008
|
+
return false;
|
1009
|
+
},
|
1010
|
+
|
923
1011
|
scrollTo: function(element) {
|
924
1012
|
element = $(element);
|
925
1013
|
var x = element.x ? element.x : element.offsetLeft,
|
@@ -1013,7 +1101,9 @@ Object.extend(Element, {
|
|
1013
1101
|
element.style.overflow = element._overflow;
|
1014
1102
|
element._overflow = undefined;
|
1015
1103
|
}
|
1016
|
-
}
|
1104
|
+
}
|
1105
|
+
|
1106
|
+
Object.extend(Element, Element.Methods);
|
1017
1107
|
|
1018
1108
|
var Toggle = new Object();
|
1019
1109
|
Toggle.display = Element.toggle;
|
@@ -1148,6 +1238,116 @@ Element.ClassNames.prototype = {
|
|
1148
1238
|
}
|
1149
1239
|
|
1150
1240
|
Object.extend(Element.ClassNames.prototype, Enumerable);
|
1241
|
+
var Selector = Class.create();
|
1242
|
+
Selector.prototype = {
|
1243
|
+
initialize: function(expression) {
|
1244
|
+
this.params = {classNames: []};
|
1245
|
+
this.expression = expression.toString().strip();
|
1246
|
+
this.parseExpression();
|
1247
|
+
this.compileMatcher();
|
1248
|
+
},
|
1249
|
+
|
1250
|
+
parseExpression: function() {
|
1251
|
+
function abort(message) { throw 'Parse error in selector: ' + message; }
|
1252
|
+
|
1253
|
+
if (this.expression == '') abort('empty expression');
|
1254
|
+
|
1255
|
+
var params = this.params, expr = this.expression, match, modifier, clause, rest;
|
1256
|
+
while (match = expr.match(/^(.*)\[([a-z0-9_:-]+?)(?:([~\|!]?=)(?:"([^"]*)"|([^\]\s]*)))?\]$/i)) {
|
1257
|
+
params.attributes = params.attributes || [];
|
1258
|
+
params.attributes.push({name: match[2], operator: match[3], value: match[4] || match[5] || ''});
|
1259
|
+
expr = match[1];
|
1260
|
+
}
|
1261
|
+
|
1262
|
+
if (expr == '*') return this.params.wildcard = true;
|
1263
|
+
|
1264
|
+
while (match = expr.match(/^([^a-z0-9_-])?([a-z0-9_-]+)(.*)/i)) {
|
1265
|
+
modifier = match[1], clause = match[2], rest = match[3];
|
1266
|
+
switch (modifier) {
|
1267
|
+
case '#': params.id = clause; break;
|
1268
|
+
case '.': params.classNames.push(clause); break;
|
1269
|
+
case '':
|
1270
|
+
case undefined: params.tagName = clause.toUpperCase(); break;
|
1271
|
+
default: abort(expr.inspect());
|
1272
|
+
}
|
1273
|
+
expr = rest;
|
1274
|
+
}
|
1275
|
+
|
1276
|
+
if (expr.length > 0) abort(expr.inspect());
|
1277
|
+
},
|
1278
|
+
|
1279
|
+
buildMatchExpression: function() {
|
1280
|
+
var params = this.params, conditions = [], clause;
|
1281
|
+
|
1282
|
+
if (params.wildcard)
|
1283
|
+
conditions.push('true');
|
1284
|
+
if (clause = params.id)
|
1285
|
+
conditions.push('element.id == ' + clause.inspect());
|
1286
|
+
if (clause = params.tagName)
|
1287
|
+
conditions.push('element.tagName.toUpperCase() == ' + clause.inspect());
|
1288
|
+
if ((clause = params.classNames).length > 0)
|
1289
|
+
for (var i = 0; i < clause.length; i++)
|
1290
|
+
conditions.push('Element.hasClassName(element, ' + clause[i].inspect() + ')');
|
1291
|
+
if (clause = params.attributes) {
|
1292
|
+
clause.each(function(attribute) {
|
1293
|
+
var value = 'element.getAttribute(' + attribute.name.inspect() + ')';
|
1294
|
+
var splitValueBy = function(delimiter) {
|
1295
|
+
return value + ' && ' + value + '.split(' + delimiter.inspect() + ')';
|
1296
|
+
}
|
1297
|
+
|
1298
|
+
switch (attribute.operator) {
|
1299
|
+
case '=': conditions.push(value + ' == ' + attribute.value.inspect()); break;
|
1300
|
+
case '~=': conditions.push(splitValueBy(' ') + '.include(' + attribute.value.inspect() + ')'); break;
|
1301
|
+
case '|=': conditions.push(
|
1302
|
+
splitValueBy('-') + '.first().toUpperCase() == ' + attribute.value.toUpperCase().inspect()
|
1303
|
+
); break;
|
1304
|
+
case '!=': conditions.push(value + ' != ' + attribute.value.inspect()); break;
|
1305
|
+
case '':
|
1306
|
+
case undefined: conditions.push(value + ' != null'); break;
|
1307
|
+
default: throw 'Unknown operator ' + attribute.operator + ' in selector';
|
1308
|
+
}
|
1309
|
+
});
|
1310
|
+
}
|
1311
|
+
|
1312
|
+
return conditions.join(' && ');
|
1313
|
+
},
|
1314
|
+
|
1315
|
+
compileMatcher: function() {
|
1316
|
+
this.match = new Function('element', 'if (!element.tagName) return false; \
|
1317
|
+
return ' + this.buildMatchExpression());
|
1318
|
+
},
|
1319
|
+
|
1320
|
+
findElements: function(scope) {
|
1321
|
+
var element;
|
1322
|
+
|
1323
|
+
if (element = $(this.params.id))
|
1324
|
+
if (this.match(element))
|
1325
|
+
if (!scope || Element.childOf(element, scope))
|
1326
|
+
return [element];
|
1327
|
+
|
1328
|
+
scope = (scope || document).getElementsByTagName(this.params.tagName || '*');
|
1329
|
+
|
1330
|
+
var results = [];
|
1331
|
+
for (var i = 0; i < scope.length; i++)
|
1332
|
+
if (this.match(element = scope[i]))
|
1333
|
+
results.push(Element.extend(element));
|
1334
|
+
|
1335
|
+
return results;
|
1336
|
+
},
|
1337
|
+
|
1338
|
+
toString: function() {
|
1339
|
+
return this.expression;
|
1340
|
+
}
|
1341
|
+
}
|
1342
|
+
|
1343
|
+
function $$() {
|
1344
|
+
return $A(arguments).map(function(expression) {
|
1345
|
+
return expression.strip().split(/\s+/).inject([null], function(results, expr) {
|
1346
|
+
var selector = new Selector(expr);
|
1347
|
+
return results.map(selector.findElements.bind(selector)).flatten();
|
1348
|
+
});
|
1349
|
+
}).flatten();
|
1350
|
+
}
|
1151
1351
|
var Field = {
|
1152
1352
|
clear: function() {
|
1153
1353
|
for (var i = 0; i < arguments.length; i++)
|
data/lib/code_statistics.rb
CHANGED
data/lib/commands/console.rb
CHANGED
@@ -11,9 +11,11 @@ end
|
|
11
11
|
|
12
12
|
libs = " -r irb/completion"
|
13
13
|
libs << " -r #{RAILS_ROOT}/config/environment"
|
14
|
+
libs << " -r console_app"
|
14
15
|
libs << " -r console_sandbox" if options[:sandbox]
|
16
|
+
libs << " -r console_with_helpers"
|
15
17
|
|
16
|
-
ENV['RAILS_ENV'] = ARGV.first || 'development'
|
18
|
+
ENV['RAILS_ENV'] = ARGV.first || ENV['RAILS_ENV'] || 'development'
|
17
19
|
if options[:sandbox]
|
18
20
|
puts "Loading #{ENV['RAILS_ENV']} environment in sandbox."
|
19
21
|
puts "Any modifications you make will be rolled back on exit."
|
data/lib/commands/plugin.rb
CHANGED
@@ -31,10 +31,13 @@
|
|
31
31
|
# look like subversion repositories with plugins:
|
32
32
|
# http://wiki.rubyonrails.org/rails/pages/Plugins
|
33
33
|
#
|
34
|
+
# * Unless you specify that you want to use svn, script/plugin uses plain ole
|
35
|
+
# HTTP for downloads. The following bullets are true if you specify
|
36
|
+
# that you want to use svn.
|
37
|
+
#
|
34
38
|
# * If `vendor/plugins` is under subversion control, the script will
|
35
39
|
# modify the svn:externals property and perform an update. You can
|
36
|
-
# use normal subversion commands to keep the plugins up to date
|
37
|
-
# you can use the built in update command.
|
40
|
+
# use normal subversion commands to keep the plugins up to date.
|
38
41
|
#
|
39
42
|
# * Or, if `vendor/plugins` is not under subversion control, the
|
40
43
|
# plugin is pulled via `svn checkout` or `svn export` but looks
|
@@ -58,7 +61,7 @@ class RailsEnvironment
|
|
58
61
|
def initialize(dir)
|
59
62
|
@root = dir
|
60
63
|
end
|
61
|
-
|
64
|
+
|
62
65
|
def self.find(dir=nil)
|
63
66
|
dir ||= pwd
|
64
67
|
while dir.length > 1
|
@@ -93,21 +96,22 @@ class RailsEnvironment
|
|
93
96
|
end
|
94
97
|
|
95
98
|
def use_svn?
|
96
|
-
|
99
|
+
require 'active_support/core_ext/kernel'
|
100
|
+
silence_stderr {`svn --version` rescue nil}
|
97
101
|
!$?.nil? && $?.success?
|
98
102
|
end
|
99
103
|
|
100
104
|
def use_externals?
|
101
|
-
File.directory?("#{root}/vendor/plugins/.svn")
|
105
|
+
use_svn? && File.directory?("#{root}/vendor/plugins/.svn")
|
102
106
|
end
|
103
|
-
|
107
|
+
|
104
108
|
def use_checkout?
|
105
109
|
# this is a bit of a guess. we assume that if the rails environment
|
106
110
|
# is under subversion than they probably want the plugin checked out
|
107
111
|
# instead of exported. This can be overridden on the command line
|
108
112
|
File.directory?("#{root}/.svn")
|
109
113
|
end
|
110
|
-
|
114
|
+
|
111
115
|
def best_install_method
|
112
116
|
return :http unless use_svn?
|
113
117
|
case
|
@@ -119,12 +123,12 @@ class RailsEnvironment
|
|
119
123
|
|
120
124
|
def externals
|
121
125
|
return [] unless use_externals?
|
122
|
-
ext = `svn propget svn:externals #{root}/vendor/plugins`
|
126
|
+
ext = `svn propget svn:externals "#{root}/vendor/plugins"`
|
123
127
|
ext.reject{ |line| line.strip == '' }.map do |line|
|
124
128
|
line.strip.split(/\s+/, 2)
|
125
129
|
end
|
126
130
|
end
|
127
|
-
|
131
|
+
|
128
132
|
def externals=(items)
|
129
133
|
unless items.is_a? String
|
130
134
|
items = items.map{|name,uri| "#{name.ljust(29)} #{uri.chomp('/')}"}.join("\n")
|
@@ -132,7 +136,7 @@ class RailsEnvironment
|
|
132
136
|
Tempfile.open("svn-set-prop") do |file|
|
133
137
|
file.write(items)
|
134
138
|
file.flush
|
135
|
-
system("svn propset -q svn:externals -F #{file.path} #{root}/vendor/plugins")
|
139
|
+
system("svn propset -q svn:externals -F #{file.path} \"#{root}/vendor/plugins\"")
|
136
140
|
end
|
137
141
|
end
|
138
142
|
|
@@ -155,40 +159,73 @@ class Plugin
|
|
155
159
|
or rails_env.externals.detect{ |name, repo| self.uri == repo }
|
156
160
|
end
|
157
161
|
|
158
|
-
def install(method=nil)
|
162
|
+
def install(method=nil, options = {})
|
159
163
|
method ||= rails_env.best_install_method?
|
164
|
+
|
165
|
+
uninstall if installed? and options[:force]
|
166
|
+
|
160
167
|
unless installed?
|
161
|
-
send("install_using_#{method}")
|
168
|
+
send("install_using_#{method}", options)
|
169
|
+
run_install_hook
|
162
170
|
else
|
163
|
-
puts "already installed: #{name} (#{uri})"
|
171
|
+
puts "already installed: #{name} (#{uri}). pass --force to reinstall"
|
164
172
|
end
|
165
173
|
end
|
166
|
-
|
174
|
+
|
175
|
+
def uninstall
|
176
|
+
path = "#{rails_env.root}/vendor/plugins/#{name}"
|
177
|
+
if File.directory?(path)
|
178
|
+
puts "Removing 'vendor/plugins/#{name}'" if $verbose
|
179
|
+
rm_r path
|
180
|
+
else
|
181
|
+
puts "Plugin doesn't exist: #{path}"
|
182
|
+
end
|
183
|
+
# clean up svn:externals
|
184
|
+
externals = rails_env.externals
|
185
|
+
externals.reject!{|n,u| name == n or name == u}
|
186
|
+
rails_env.externals = externals
|
187
|
+
end
|
188
|
+
|
167
189
|
private
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
190
|
+
|
191
|
+
def run_install_hook
|
192
|
+
install_hook_file = "#{rails_env.root}/vendor/plugins/#{name}/install.rb"
|
193
|
+
load install_hook_file if File.exists? install_hook_file
|
194
|
+
end
|
195
|
+
|
196
|
+
def install_using_export(options = {})
|
197
|
+
svn_command :export, options
|
172
198
|
end
|
173
199
|
|
174
|
-
def install_using_checkout
|
175
|
-
|
176
|
-
mkdir_p "#{root}/vendor/plugins"
|
177
|
-
system("svn checkout #{uri} #{root}/vendor/plugins/#{name}")
|
200
|
+
def install_using_checkout(options = {})
|
201
|
+
svn_command :checkout, options
|
178
202
|
end
|
179
203
|
|
180
|
-
def install_using_externals
|
204
|
+
def install_using_externals(options = {})
|
181
205
|
externals = rails_env.externals
|
182
206
|
externals.push([@name, uri])
|
183
207
|
rails_env.externals = externals
|
184
|
-
install_using_checkout
|
208
|
+
install_using_checkout(options)
|
185
209
|
end
|
186
210
|
|
187
|
-
def install_using_http
|
211
|
+
def install_using_http(options = {})
|
188
212
|
root = rails_env.root
|
189
213
|
mkdir_p "#{root}/vendor/plugins"
|
190
214
|
Dir.chdir "#{root}/vendor/plugins"
|
191
|
-
|
215
|
+
puts "fetching from '#{uri}'" if $verbose
|
216
|
+
fetcher = RecursiveHTTPFetcher.new(uri)
|
217
|
+
fetcher.quiet = true if options[:quiet]
|
218
|
+
fetcher.fetch
|
219
|
+
end
|
220
|
+
|
221
|
+
def svn_command(cmd, options = {})
|
222
|
+
root = rails_env.root
|
223
|
+
mkdir_p "#{root}/vendor/plugins"
|
224
|
+
base_cmd = "svn #{cmd} #{uri} \"#{root}/vendor/plugins/#{name}\""
|
225
|
+
base_cmd += ' -q' if options[:quiet] and not $verbose
|
226
|
+
base_cmd += " -r #{options[:revision]}" if options[:revision]
|
227
|
+
puts base_cmd if $verbose
|
228
|
+
system(base_cmd)
|
192
229
|
end
|
193
230
|
|
194
231
|
def guess_name(url)
|
@@ -239,7 +276,6 @@ class Repositories
|
|
239
276
|
return plugin if plugin.name == name
|
240
277
|
end
|
241
278
|
end
|
242
|
-
|
243
279
|
return nil
|
244
280
|
end
|
245
281
|
|
@@ -298,8 +334,7 @@ class Repository
|
|
298
334
|
attr_reader :uri, :plugins
|
299
335
|
|
300
336
|
def initialize(uri)
|
301
|
-
uri << "/"
|
302
|
-
@uri = uri
|
337
|
+
@uri = uri.chomp('/') << "/"
|
303
338
|
@plugins = nil
|
304
339
|
end
|
305
340
|
|
@@ -310,7 +345,7 @@ class Repository
|
|
310
345
|
puts index
|
311
346
|
end
|
312
347
|
|
313
|
-
@plugins = index.
|
348
|
+
@plugins = index.reject{ |line| line !~ /\/$/ }
|
314
349
|
@plugins.map! { |name| Plugin.new(File.join(@uri, name), name) }
|
315
350
|
end
|
316
351
|
|
@@ -323,7 +358,7 @@ class Repository
|
|
323
358
|
|
324
359
|
private
|
325
360
|
def index
|
326
|
-
@index ||=
|
361
|
+
@index ||= RecursiveHTTPFetcher.new(@uri).ls
|
327
362
|
end
|
328
363
|
end
|
329
364
|
|
@@ -411,7 +446,7 @@ module Commands
|
|
411
446
|
command.parse!(sub)
|
412
447
|
else
|
413
448
|
puts "Unknown command: #{command}"
|
414
|
-
puts
|
449
|
+
puts options
|
415
450
|
exit 1
|
416
451
|
end
|
417
452
|
end
|
@@ -435,7 +470,6 @@ module Commands
|
|
435
470
|
@sources = []
|
436
471
|
@local = false
|
437
472
|
@remote = true
|
438
|
-
@details = false
|
439
473
|
end
|
440
474
|
|
441
475
|
def options
|
@@ -453,8 +487,6 @@ module Commands
|
|
453
487
|
o.on( "--remote",
|
454
488
|
"List remotely availabled plugins. This is the default behavior",
|
455
489
|
"unless --local is provided.") {|@remote|}
|
456
|
-
o.on( "-l", "--long",
|
457
|
-
"Long listing / details about each plugin.") {|@details|}
|
458
490
|
end
|
459
491
|
end
|
460
492
|
|
@@ -469,14 +501,12 @@ module Commands
|
|
469
501
|
@sources.map{|r| r.plugins}.flatten.each do |plugin|
|
470
502
|
if @local or !plugin.installed?
|
471
503
|
puts plugin.to_s
|
472
|
-
system "svn info #{plugin.uri}" if @details
|
473
504
|
end
|
474
505
|
end
|
475
506
|
else
|
476
507
|
cd "#{@base_command.environment.root}/vendor/plugins"
|
477
508
|
Dir["*"].select{|p| File.directory?(p)}.each do |name|
|
478
509
|
puts name
|
479
|
-
system "svn info #{name}" if @details
|
480
510
|
end
|
481
511
|
end
|
482
512
|
end
|
@@ -644,7 +674,8 @@ module Commands
|
|
644
674
|
class Install
|
645
675
|
def initialize(base_command)
|
646
676
|
@base_command = base_command
|
647
|
-
@method = :
|
677
|
+
@method = :http
|
678
|
+
@options = { :quiet => false, :revision => nil, :force => false }
|
648
679
|
end
|
649
680
|
|
650
681
|
def options
|
@@ -660,6 +691,14 @@ module Commands
|
|
660
691
|
o.on( "-o", "--checkout",
|
661
692
|
"Use svn checkout to grab the plugin.",
|
662
693
|
"Enables updating but does not add a svn:externals entry.") { |v| @method = :checkout }
|
694
|
+
o.on( "-q", "--quiet",
|
695
|
+
"Suppresses the output from installation.",
|
696
|
+
"Ignored if -v is passed (./script/plugin -v install ...)") { |v| @options[:quiet] = true }
|
697
|
+
o.on( "-r REVISION", "--revision REVISION",
|
698
|
+
"Checks out the given revision from subversion.",
|
699
|
+
"Ignored if subversion is not used.") { |v| @options[:revision] = v }
|
700
|
+
o.on( "-f", "--force",
|
701
|
+
"Reinstalls a plugin if it's already installed.") { |v| @options[:force] = true }
|
663
702
|
o.separator ""
|
664
703
|
o.separator "You can specify plugin names as given in 'plugin list' output or absolute URLs to "
|
665
704
|
o.separator "a plugin repository."
|
@@ -672,8 +711,8 @@ module Commands
|
|
672
711
|
case
|
673
712
|
when (best == :http and @method != :http)
|
674
713
|
msg = "Cannot install using subversion because `svn' cannot be found in your PATH"
|
675
|
-
when (best == :export and (@method != :export and method != :http))
|
676
|
-
msg = "Cannot install using #{
|
714
|
+
when (best == :export and (@method != :export and @method != :http))
|
715
|
+
msg = "Cannot install using #{@method} because this project is not under subversion."
|
677
716
|
when (best != :externals and @method == :externals)
|
678
717
|
msg = "Cannot install using externals because vendor/plugins is not under subversion."
|
679
718
|
end
|
@@ -691,11 +730,11 @@ module Commands
|
|
691
730
|
puts "Plugins will be installed using #{install_method}" if $verbose
|
692
731
|
args.each do |name|
|
693
732
|
if name =~ /\// then
|
694
|
-
::Plugin.new(name).install(install_method)
|
733
|
+
::Plugin.new(name).install(install_method, @options)
|
695
734
|
else
|
696
735
|
plugin = Repositories.instance.find_plugin(name)
|
697
736
|
unless plugin.nil?
|
698
|
-
plugin.install(install_method)
|
737
|
+
plugin.install(install_method, @options)
|
699
738
|
else
|
700
739
|
puts "Plugin not found: #{name}"
|
701
740
|
exit 1
|
@@ -705,39 +744,42 @@ module Commands
|
|
705
744
|
end
|
706
745
|
end
|
707
746
|
|
708
|
-
|
709
|
-
class Remove
|
747
|
+
class Update
|
710
748
|
def initialize(base_command)
|
711
749
|
@base_command = base_command
|
712
750
|
end
|
713
|
-
|
751
|
+
|
714
752
|
def options
|
715
753
|
OptionParser.new do |o|
|
716
754
|
o.set_summary_indent(' ')
|
717
|
-
o.banner = "Usage: #{@base_command.script_name}
|
718
|
-
o.
|
755
|
+
o.banner = "Usage: #{@base_command.script_name} update [name [name]...]"
|
756
|
+
o.on( "-r REVISION", "--revision REVISION",
|
757
|
+
"Checks out the given revision from subversion.",
|
758
|
+
"Ignored if subversion is not used.") { |v| @revision = v }
|
759
|
+
o.define_head "Update plugins."
|
719
760
|
end
|
720
761
|
end
|
721
|
-
|
762
|
+
|
722
763
|
def parse!(args)
|
723
764
|
options.parse!(args)
|
724
765
|
root = @base_command.environment.root
|
766
|
+
cd root
|
767
|
+
args = Dir["vendor/plugins/*"].map do |f|
|
768
|
+
File.directory?("#{f}/.svn") ? File.basename(f) : nil
|
769
|
+
end.compact if args.empty?
|
770
|
+
cd "vendor/plugins"
|
725
771
|
args.each do |name|
|
726
|
-
|
727
|
-
|
728
|
-
|
772
|
+
if File.directory?(name)
|
773
|
+
puts "Updating plugin: #{name}"
|
774
|
+
system("svn #{$verbose ? '' : '-q'} up \"#{name}\" #{@revision ? "-r #{@revision}" : ''}")
|
729
775
|
else
|
730
|
-
puts "Plugin doesn't exist: #{
|
776
|
+
puts "Plugin doesn't exist: #{name}"
|
731
777
|
end
|
732
|
-
# clean up svn:externals
|
733
|
-
externals = @base_command.environment.externals
|
734
|
-
externals.reject!{|n,u| name == n or name == u}
|
735
|
-
@base_command.environment.externals = externals
|
736
778
|
end
|
737
779
|
end
|
738
780
|
end
|
739
781
|
|
740
|
-
class
|
782
|
+
class Remove
|
741
783
|
def initialize(base_command)
|
742
784
|
@base_command = base_command
|
743
785
|
end
|
@@ -745,25 +787,16 @@ module Commands
|
|
745
787
|
def options
|
746
788
|
OptionParser.new do |o|
|
747
789
|
o.set_summary_indent(' ')
|
748
|
-
o.banner = "Usage: #{@base_command.script_name}
|
749
|
-
o.define_head "
|
790
|
+
o.banner = "Usage: #{@base_command.script_name} remove name [name]..."
|
791
|
+
o.define_head "Remove plugins."
|
750
792
|
end
|
751
793
|
end
|
752
794
|
|
753
795
|
def parse!(args)
|
754
796
|
options.parse!(args)
|
755
797
|
root = @base_command.environment.root
|
756
|
-
args = Dir["#{root}/vendor/plugins/*"].map do |f|
|
757
|
-
File.directory?("#{f}/.svn") ? File.basename(f) : nil
|
758
|
-
end.compact if args.empty?
|
759
|
-
cd "#{root}/vendor/plugins"
|
760
798
|
args.each do |name|
|
761
|
-
|
762
|
-
puts "Updating plugin: #{name}"
|
763
|
-
system("svn #{$verbose ? '' : '-q'} up #{name}")
|
764
|
-
else
|
765
|
-
puts "Plugin doesn't exist: #{name}"
|
766
|
-
end
|
799
|
+
::Plugin.new(name).uninstall
|
767
800
|
end
|
768
801
|
end
|
769
802
|
end
|
@@ -771,9 +804,19 @@ module Commands
|
|
771
804
|
end
|
772
805
|
|
773
806
|
class RecursiveHTTPFetcher
|
807
|
+
attr_accessor :quiet
|
774
808
|
def initialize(urls_to_fetch, cwd = ".")
|
775
809
|
@cwd = cwd
|
776
810
|
@urls_to_fetch = urls_to_fetch.to_a
|
811
|
+
@quiet = false
|
812
|
+
end
|
813
|
+
|
814
|
+
def ls
|
815
|
+
@urls_to_fetch.collect do |url|
|
816
|
+
open(url) do |stream|
|
817
|
+
links("", stream.read)
|
818
|
+
end rescue nil
|
819
|
+
end.flatten
|
777
820
|
end
|
778
821
|
|
779
822
|
def push_d(dir)
|
@@ -796,7 +839,7 @@ class RecursiveHTTPFetcher
|
|
796
839
|
end
|
797
840
|
|
798
841
|
def download(link)
|
799
|
-
puts "+ #{File.join(@cwd, File.basename(link))}"
|
842
|
+
puts "+ #{File.join(@cwd, File.basename(link))}" unless @quiet
|
800
843
|
open(link) do |stream|
|
801
844
|
File.open(File.join(@cwd, File.basename(link)), "wb") do |file|
|
802
845
|
file.write(stream.read)
|