Module: Fir::Tasks

Defined in:
lib/fir/tasks.rb

Defined Under Namespace

Classes: Rsyncer

Class Method Summary collapse

Class Method Details

.defineObject



3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
# File 'lib/fir/tasks.rb', line 3

def self.define
  namespace :users do
    desc 'Add a user for the content management API. If the user already exists, the password is overwritten. ' +
      'You must restart your server for the change to take effect. Usage: rake add_user user=username pass=password'
    task :add do
      require 'fir'
      require 'active_support/secure_random'
      unless (ENV.has_key?('user') or ENV.has_key?('USER')) and (ENV.has_key?('pass') or ENV.has_key?('PASS'))
        puts 'usage: rake users:add user=username pass=password'
        exit
      end
      user = ENV['user'] || ENV['USER']
      pass = ENV['pass'] || ENV['PASS']
      
      if File.exists?('users.yml')
        pairs = YAML::load(File.read('users.yml')) || {}
      else
        pairs = {}
      end
      
      salt = ActiveSupport::SecureRandom.hex(13)
      pairs[user] = {'crypted_password' => Fir.encrypt_password(pass, salt), 'salt' => salt}
      
      File.open('users.yml', 'w') do |file|
        file.write(YAML::dump(pairs))
      end
    end
  end
  desc 'Export the site to static HTML. (For web hosts that don\'t support Rack. Creates an .htaccess file for pretty URLs. mod_rewrite must be enabled!) ' +
    'Usage: rake export dir=path_to_export_to'
  task :export do
    require 'fileutils'
    
    if !ENV.has_key?('dir') or ENV['dir'].empty?
      puts 'Usage: rake export dir=path_to_export_to'
      exit
    end
    
    copy_to = ENV['dir']
    unless ENV['force'] or !File.exists?(copy_to) or Dir.entries(copy_to).length == 2
      puts 'Directory is not empty. Export aborted. Use "rake export dir=path force=1" to override. This will delete everything in the directory!'
      exit
    end
    
    page_config = YAML.load(File.read(File.join(FIR_ROOT, 'pages.yml')))
    path_mappings = page_config.inject({}) do |mappings, (page, configs)|
      mappings[configs['path']] = page if configs['path']
      mappings
    end
    inverted_path_mappings = path_mappings.invert
    
    pages_dir = File.join(FIR_ROOT, 'pages')
    # Get all the page files without extensions
    paths = Dir.glob(pages_dir + '/**/**').inject([]) do |result, file|
      file.gsub!(pages_dir + '/', '')
      is_erb = !!file.match(/\.erb$/)
      file.sub!(/#{File.extname(file)}$/, '')
      if is_erb
        # This was something like .html.erb, so we need to remove two extensions
        file.sub!(/#{File.extname(file)}$/, '')
      end
      # If this is a directory index, then we'll already get it when the directory is picked up in the glob.
      if !file.match(/index$/)
        unless inverted_path_mappings.has_key?(file)
          result << file
        end
      end
      result
    end + path_mappings.keys
    paths << '' # Get the home page
    
    puts "Exporting to #{copy_to}..."
    
    Fir.config.force_caching = true
    require File.expand_path(File.join(FIR_ROOT, 'config.rb'))
    builder = Rack::Builder.new(&Fir.boot_proc)
    
    puts 'Getting each page to generate the cache...'       
    paths.each do |path|
      puts '  GET ' + path
      builder.call({'PATH_INFO' => '/' + path})
    end
    
    copy_from = File.join(FIR_ROOT, 'public', '.')
    if File.exists?(copy_to)
      FileUtils.rm_rf(copy_to)
    end
    Dir.mkdir(copy_to)
    FileUtils.cp_r(copy_from, copy_to)
    FileUtils.cp_r(File.join(copy_to, 'cache', '.'), copy_to)
    FileUtils.rm_rf(File.join(copy_to, 'cache'))
    ['.htaccess', 'dispatch.cgi'].each do |file|
      path = File.join(copy_to, file)
      if File.exists?(path)
        File.delete(path)
      end
    end
    # Create a simple .htaccess file to enable pretty URLs
    htaccess =
    "DirectoryIndex index.html\n" +
    "RewriteEngine On\n" +
    "RewriteCond %{REQUEST_FILENAME} !-f\n" +
    "RewriteCond %{REQUEST_FILENAME} !-d\n" +
    "RewriteRule (.*) $1.html"
    File.open(File.join(copy_to, '.htaccess'), 'w') do |f|
      f.write(htaccess)
    end
  end
  
  desc "Export the site to static HTML and transfer it to the server using rsync and SSH. (For web hosts that don't support Rack. " +
    "Creates an .htaccess file for pretty URLs. mod_rewrite must be enabled!) " +
    "Example usage: rake export_to_server [email protected]:/home/username/public_html\n\n" +
    "Obviously, dest should be set to the correct rsync destination for your deploy environment. " +
    "Note that dest is NOT a URI, even though it sort of looks like one. It's a destination string in the form that rsync accepts."
  task :export_to_server do
    begin
      ENV['dir'] = '.server_export_tmp'
      Rake::Task['export'].execute
      if ENV['dest']
        dest = ENV['dest']
      elsif File.exists?(File.join(FIR_ROOT, 'deploy.yml'))
        yaml = YAML.load(File.read(File.join(FIR_ROOT, 'deploy.yml')))
        ['host', 'user', 'path'].each do |param|
          unless yaml.has_key?(param)
            puts "deploy.yml must specify #{param}"
            exit
          end
        end
        dest = "#{yaml['user']}@#{yaml['host']}:#{yaml['path']}"
      else
        puts "Example usage: rake export_to_server [email protected]/home:/username/public_html"
        exit
      end
      Rsyncer.new.run(dest)
    ensure
      FileUtils.rm_rf '.server_export_tmp'
    end
  end
end