source: branches/locker-dev/locker/deploy/bin/rails @ 2261

Last change on this file since 2261 was 2261, checked in by glasgall, 12 years ago
Properly find the name of the application class for Rails apps The previous method was a hack that broke on apps with hyphens in the name. Actually read it out of config/application.rb now.
  • Property svn:executable set to *
File size: 7.6 KB
RevLine 
[1295]1#!/usr/bin/perl
2use strict;
3use FindBin qw($Bin);
4use lib $Bin;
5use onserver;
6use Tie::File;
[2149]7use Cwd;
[1295]8
9setup();
10
11sub make_db {
12    my($type) = @_;
13    print "\nCreating $type SQL database for $sname...\n";
14    open GETPWD, '-|', "/mit/scripts/sql/bin$scriptsdev/get-password";
15    ($sqlhost, $sqluser, $sqlpass) = split(/\s/, <GETPWD>);
16    close GETPWD;
17    open SQLDB, '-|', "/mit/scripts/sql/bin$scriptsdev/get-next-database", "${addrlast}_${type}";
18    $sqldb = <SQLDB>;
19    close SQLDB;
20    open SQLDB, '-|', "/mit/scripts/sql/bin$scriptsdev/create-database", $sqldb;
21    $sqldb = <SQLDB>;
22    close SQLDB;
23    if($sqldb eq "") {
24        print "\nERROR:\n";
25        print "Your SQL account failed to create a SQL database.\n";
26        print "You should log in at http://sql.mit.edu to check whether\n";
27        print "your SQL account is at its database limit or its storage limit.\n";
28        print "If you cannot determine the cause of the problem, please\n";
29        print "feel free to contact sql\@mit.edu for assistance.\n";
30        open FAILED, ">.failed";
31        close FAILED;
32        exit 1;
33    }
34    return $sqldb;
35}
36
37my $dev_db = make_db("development");
38my $test_db = make_db("test");
39my $prod_db = make_db("production");
40
[2149]41my $cwd = getcwd;
42system("rails", "new", $cwd ,"-d", "mysql");
43my $appdir = `basename $cwd`;
44chomp $appdir;
[1295]45
[2261]46open APPLICATION_RB, "config/application.rb";
47my $appclass;
48while(<APPLICATION_RB>) {
49    if (/module (\w+)\n/) {
50        $appclass = $1;
51        last;
52    }
53}
54close APPLICATION_RB;
55if (!$appclass) {
56    open FAILED, ">.failed";
57    close FAILED;
58    die "Couldn't find application class name - plase email scripts\@mit.edu with the names of your locker and the application you tried to create. Sorry!";
59}
60
[1295]61open PUBLIC_HTACCESS, ">public/.htaccess";
62print PUBLIC_HTACCESS <<EOF;
63# General Apache options
64Options +FollowSymLinks +ExecCGI
65
66# If you don't want Rails to look in certain directories,
67# use the following rewrite rules so that Apache won't rewrite certain requests
68#
69# Example:
70#   RewriteCond %{REQUEST_URI} ^/notrails.*
71#   RewriteRule .* - [L]
72
73# Redirect all requests not available on the filesystem to Rails
74# By default the cgi dispatcher is used which is very slow
75#
76# For better performance replace the dispatcher with the fastcgi one
77#
78# Example:
79#   RewriteRule ^(.*)\$ dispatch.fcgi [QSA,L]
80RewriteEngine On
81
82# If your Rails application is accessed via an Alias directive,
83# then you MUST also set the RewriteBase in this htaccess file.
84#
85# Example:
86#   Alias /myrailsapp /path/to/myrailsapp/public
87#   RewriteBase /myrailsapp
88
89RewriteRule ^\$ index.html [QSA]
90RewriteRule ^([^.]+)\$ \$1.html [QSA]
91RewriteCond %{REQUEST_FILENAME} !-f
92RewriteRule ^(.*)\$ dispatch.fcgi [QSA,L]
93
94# In case Rails experiences terminal errors
95# Instead of displaying this message you can supply a file here which will be rendered instead
96#
97# Example:
98#   ErrorDocument 500 /500.html
99
100EOF
101
102open HTACCESS, ">.htaccess";
103print HTACCESS <<EOF;
104RewriteEngine On
105RewriteRule ^(.*)\$ public/\$1 [QSA,L]
[2260]106
[1295]107EOF
108
109tie my @railsenv, 'Tie::File', 'config/environment.rb';
[1407]110unshift @railsenv, "# ENV['RAILS_ENV'] ||= 'production'";
111unshift @railsenv, "# Uncomment below to put Rails into production mode";
112unshift @railsenv, "";
[1295]113unshift @railsenv, "ENV['RAILS_RELATIVE_URL_ROOT'] = \"/$addrend\"";
114untie @railsenv;
115
116tie my @railsdb, 'Tie::File', 'config/database.yml';
117for (@railsdb) {
118    s/username:.*$/username: $sqluser/;
119    s/password:.*$/password: $sqlpass/;
120    s/host:.*$/host: $sqlhost/;
121    s/database:.*_development.*/database: $dev_db/;
122    s/database:.*_test.*/database: $test_db/;
123    s/database:.*_production.*/database: $prod_db/;
124}
125untie @railsdb;
126
[1297]127tie my @railswelcome, 'Tie::File', 'public/index.html';
128for (@railswelcome) {
129    s/Create your database/Sync your database/;
130    s/to create your database\..*/to create tables in your database.<\/p>/;
131}
132untie @railswelcome;
133
[1408]134tie my @railsfcgi, 'Tie::File', 'public/dispatch.fcgi';
135for (@railsfcgi) {
136    s/^[^#]*RailsFCGIHandler/## Commented out by scripts.mit.edu autoinstaller\n## RailsFCGIHandler/;
137}
138untie @railsfcgi;
139open RAILSFCGI, ">>public/dispatch.fcgi";
[2149]140print RAILSFCGI "#!/usr/bin/ruby\n";
[1408]141print RAILSFCGI <<EOF;
[2149]142require File.join(File.dirname(__FILE__), '../config/environment')       
143require 'rack'
[1408]144
145## Added by scripts.mit.edu autoinstaller to reload when app code changes
146Thread.abort_on_exception = true
147
[2149]148class Rack::PathInfoRewriter
149  def initialize(app)
150    \@app = app
151  end
152
153  def call(env)
154    env["SCRIPT_NAME"] = ""
155    parts = env['REQUEST_URI'].split('?')
156    env['PATH_INFO'] = parts[0]
157    env['QUERY_STRING'] = parts[1].to_s
158    \@app.call(env)
159  end
160end
161
162
[1408]163t1 = Thread.new do
[2149]164  dispatch_logger = Logger.new(File.join(Rails.root,'log/dispatcher.log'))
165
166  begin
[2260]167    Rack::Handler::FastCGI.run Rack::PathInfoRewriter.new(Rack::URLMap.new("/$appdir" => ${appclass}::Application,
168                                                                           "/" => ${appclass}::Application))
[2149]169  rescue => e
170   dispatch_logger.error(e)
171   raise e
172  end
[1408]173end
174t2 = Thread.new do
[1469]175   # List of directories to watch for changes before reload.
176   # You may want to also watch public or vendor, depending on your needs.
177   Thread.current[:watched_dirs] = ['app', 'config', 'db', 'lib']
[1484]178
179   # List of specific files to watch for changes.
180   Thread.current[:watched_files] = ['public/dispatch.fcgi',
181                                     'public/.htaccess']
[1411]182   # Sample filter: /(\.rb|\.erb)\$/.  Default filter: watch all files
[1408]183   Thread.current[:watched_extensions] = //
[1410]184   # Iterations since last reload
185   Thread.current[:iterations] = 0
[1408]186
187   def modified(file)
[1410]188     begin
189       mtime = File.stat(file).mtime
190     rescue
191       false
192     else
193       if Thread.current[:iterations] == 0
194         Thread.current[:modifications][file] = mtime
195       end
196       Thread.current[:modifications][file] != mtime
197     end
[1408]198   end
199
[1410]200   # Don't symlink yourself into a loop.  Please.  Things will still work
201   # (Linux limits your symlink depth) but you will be sad
[1408]202   def modified_dir(dir)
203     Dir.new(dir).each do |file|
204       absfile = File.join(dir, file)
205       if FileTest.directory? absfile
206         next if file == '.' or file == '..'
207         return true if modified_dir(absfile)
208       else
209         return true if Thread.current[:watched_extensions] =~ absfile &&
[1410]210           modified(absfile)
[1408]211       end
212     end
213     false
214   end
215
216   def reload
217     Thread.current[:modifications] = {}
[1410]218     Thread.current[:iterations] = 0
[1486]219     # This is a kludge, but at the same time it works.
220     # Will kill the current FCGI process so that it is reloaded
221     # at next request.
222     raise RuntimeError
[1408]223   end
224
225   Thread.current[:modifications] = {}
226   # Wait until the modify time changes, then reload.
227   while true
[1484]228     dir_modified = Thread.current[:watched_dirs].inject(false) {|z, dir| z || modified_dir(File.join(File.dirname(__FILE__), '..', dir))}
229     file_modified = Thread.current[:watched_files].inject(false) {|z, file| z || modified(File.join(File.dirname(__FILE__), '..', file))}
230     reload if dir_modified || file_modified
[1410]231     Thread.current[:iterations] += 1
[1408]232     sleep 1
233   end
234end
235
236t1.join
237t2.join
238## End of scripts.mit.edu autoinstaller additions
239EOF
[2149]240chmod 0755,'public/dispatch.fcgi';
[1408]241
[2149]242# have to explicitly take a dependency on fcgi
[2259]243# ruby1.9 means we need to take a dependency on minitest
244# for rails console to work
[2149]245open GEMFILE, ">>Gemfile";
246print GEMFILE "gem 'fcgi'\n";
[2259]247print GEMFILE "gem 'minitest'\n";
[2149]248close GEMFILE;
249
[1297]250print "Your application is located in:\n";
251print "  /mit/$USER/web_scripts/$addrend/\n";
252print "To run programs like rake or script/generate, run\n";
253print "  'ssh -k $USER\@scripts' and cd to the above directory.\n\n";
254press_enter;
255
[1295]256exit 0;
Note: See TracBrowser for help on using the repository browser.