frank 1.0.9 → 1.0.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/Gemfile.lock +21 -20
- data/Rakefile +7 -0
- data/frank.gemspec +6 -4
- data/lib/frank/base.rb +0 -9
- data/lib/frank/cli.rb +1 -1
- data/lib/frank/middleware/statik.rb +8 -8
- data/lib/frank/publish.rb +50 -42
- data/lib/frank/publish/base.rb +94 -0
- data/lib/frank/publish/ftp.rb +80 -0
- data/lib/frank/publish/ftptls.rb +80 -0
- data/lib/frank/publish/scp.rb +37 -0
- data/lib/frank/publish/sftp.rb +37 -0
- data/lib/frank/publish/shell_scp.rb +29 -0
- data/lib/frank/settings.rb +1 -0
- data/lib/frank/version.rb +1 -1
- data/lib/template/setup.rb +4 -1
- data/spec/base_spec.rb +5 -5
- data/spec/compile_spec.rb +3 -1
- data/spec/publish/base_spec.rb +125 -0
- data/spec/publish/ftp_spec.rb +143 -0
- data/spec/publish/ftptls_spec.rb +143 -0
- data/spec/publish/scp_spec.rb +62 -0
- data/spec/publish/sftp_spec.rb +62 -0
- data/spec/publish_spec.rb +60 -10
- data/spec/render_spec.rb +2 -2
- data/spec/{helper.rb → spec_helper.rb} +28 -10
- data/spec/template/setup.rb +4 -3
- data/spec/template_helpers_spec.rb +4 -4
- metadata +185 -231
data/Gemfile.lock
CHANGED
@@ -1,3 +1,13 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
frank (1.0.9)
|
5
|
+
haml (~> 3.0)
|
6
|
+
mongrel (~> 1.2.0.pre2)
|
7
|
+
net-ssh (~> 2.0)
|
8
|
+
rack (~> 1.1)
|
9
|
+
tilt (~> 1.3)
|
10
|
+
|
1
11
|
GEM
|
2
12
|
remote: http://rubygems.org/
|
3
13
|
specs:
|
@@ -10,7 +20,6 @@ GEM
|
|
10
20
|
coffee-script-source (1.1.2)
|
11
21
|
compass (0.10.2)
|
12
22
|
haml (>= 3.0.4)
|
13
|
-
contest (0.1.2)
|
14
23
|
daemons (1.0.10)
|
15
24
|
diff-lcs (1.1.2)
|
16
25
|
erubis (2.6.6)
|
@@ -18,26 +27,24 @@ GEM
|
|
18
27
|
execjs (1.2.4)
|
19
28
|
multi_json (~> 1.0)
|
20
29
|
gem_plugin (0.2.3)
|
21
|
-
gemcutter (0.6.1)
|
22
|
-
git (1.2.5)
|
23
30
|
haml (3.0.13)
|
24
|
-
jeweler (1.4.0)
|
25
|
-
gemcutter (>= 0.1.0)
|
26
|
-
git (>= 1.2.5)
|
27
|
-
rubyforge (>= 2.0.0)
|
28
|
-
json_pure (1.4.3)
|
29
31
|
less (1.2.21)
|
30
32
|
mutter (>= 0.4.2)
|
31
33
|
treetop (>= 1.4.2)
|
32
34
|
liquid (2.1.2)
|
35
|
+
metaclass (0.0.1)
|
36
|
+
mocha (0.10.5)
|
37
|
+
metaclass (~> 0.0.1)
|
33
38
|
mongrel (1.2.0.pre2)
|
34
39
|
daemons (~> 1.0.10)
|
35
40
|
gem_plugin (~> 0.2.3)
|
36
41
|
multi_json (1.0.3)
|
37
42
|
mutter (0.5.3)
|
38
|
-
net-scp (1.0.
|
43
|
+
net-scp (1.0.4)
|
39
44
|
net-ssh (>= 1.99.1)
|
40
|
-
net-
|
45
|
+
net-sftp (2.0.5)
|
46
|
+
net-ssh (>= 2.0.9)
|
47
|
+
net-ssh (2.3.0)
|
41
48
|
polyglot (0.3.1)
|
42
49
|
rack (1.2.1)
|
43
50
|
rack-test (0.5.4)
|
@@ -52,8 +59,6 @@ GEM
|
|
52
59
|
rspec-expectations (2.6.0)
|
53
60
|
diff-lcs (~> 1.1.2)
|
54
61
|
rspec-mocks (2.6.0)
|
55
|
-
rubyforge (2.0.4)
|
56
|
-
json_pure (>= 1.1.7)
|
57
62
|
tilt (1.3.3)
|
58
63
|
treetop (1.4.8)
|
59
64
|
polyglot (>= 0.3.1)
|
@@ -66,18 +71,14 @@ DEPENDENCIES
|
|
66
71
|
builder
|
67
72
|
coffee-script (~> 2.2.0)
|
68
73
|
compass (~> 0.10.2)
|
69
|
-
contest
|
70
74
|
erubis
|
71
|
-
|
72
|
-
jeweler
|
75
|
+
frank!
|
73
76
|
less
|
74
77
|
liquid
|
75
|
-
|
76
|
-
net-scp
|
77
|
-
net-
|
78
|
-
rack (~> 1.1)
|
78
|
+
mocha
|
79
|
+
net-scp
|
80
|
+
net-sftp
|
79
81
|
rack-test (~> 0.5)
|
80
82
|
rake
|
81
83
|
rdiscount
|
82
84
|
rspec (~> 2.6.0)
|
83
|
-
tilt (~> 1.3)
|
data/Rakefile
CHANGED
data/frank.gemspec
CHANGED
@@ -16,18 +16,18 @@ Gem::Specification.new do |s|
|
|
16
16
|
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
17
17
|
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
18
18
|
s.require_paths = ["lib"]
|
19
|
-
|
19
|
+
|
20
20
|
s.add_runtime_dependency 'rack', '~> 1.1'
|
21
21
|
s.add_runtime_dependency 'mongrel', '~> 1.2.0.pre2'
|
22
22
|
s.add_runtime_dependency 'haml', '~> 3.0'
|
23
23
|
s.add_runtime_dependency 'tilt', '~> 1.3'
|
24
24
|
s.add_runtime_dependency 'net-ssh', '~> 2.0'
|
25
|
-
|
26
|
-
|
25
|
+
|
27
26
|
s.add_development_dependency 'rspec', '~> 2.6.0'
|
28
27
|
s.add_development_dependency 'rack-test', '~> 0.5'
|
29
28
|
s.add_development_dependency 'rake'
|
30
29
|
s.add_development_dependency 'builder'
|
30
|
+
s.add_development_dependency 'mocha'
|
31
31
|
s.add_development_dependency 'erubis'
|
32
32
|
s.add_development_dependency 'compass', '~> 0.10.2'
|
33
33
|
s.add_development_dependency 'rdiscount'
|
@@ -35,4 +35,6 @@ Gem::Specification.new do |s|
|
|
35
35
|
s.add_development_dependency 'less'
|
36
36
|
s.add_development_dependency 'coffee-script', '~> 2.2.0'
|
37
37
|
s.add_development_dependency 'RedCloth'
|
38
|
-
|
38
|
+
s.add_development_dependency 'net-scp'
|
39
|
+
s.add_development_dependency 'net-sftp'
|
40
|
+
end
|
data/lib/frank/base.rb
CHANGED
@@ -223,15 +223,6 @@ module Frank
|
|
223
223
|
Frank.reset
|
224
224
|
Frank.root = new_root if new_root
|
225
225
|
|
226
|
-
if %w[publish p].include? ARGV.first
|
227
|
-
begin
|
228
|
-
require 'net/ssh'
|
229
|
-
require 'net/scp'
|
230
|
-
rescue LoadError
|
231
|
-
puts "\033[31mpublish requires the 'net-scp' gem. `gem install net-scp'\033[0m"
|
232
|
-
exit!
|
233
|
-
end
|
234
|
-
end
|
235
226
|
|
236
227
|
# setup compass
|
237
228
|
begin
|
data/lib/frank/cli.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
module Frank
|
2
2
|
module Middleware
|
3
3
|
class Statik
|
4
|
-
|
4
|
+
|
5
5
|
def initialize(app, options={})
|
6
6
|
@app = app
|
7
7
|
frank_root = File.expand_path(File.dirname(File.dirname(__FILE__))) + '/templates'
|
@@ -9,13 +9,13 @@ module Frank
|
|
9
9
|
@frank_server = Rack::File.new(frank_root)
|
10
10
|
@static_server = Rack::File.new(root)
|
11
11
|
end
|
12
|
-
|
12
|
+
|
13
13
|
# handles serving from __frank__
|
14
14
|
# looks for static access, if not found,
|
15
15
|
# passes request to frank
|
16
16
|
def call(env)
|
17
17
|
path = env['PATH_INFO'].dup
|
18
|
-
|
18
|
+
|
19
19
|
if path.include? '__frank__'
|
20
20
|
env['PATH_INFO'].gsub!('/__frank__', '')
|
21
21
|
result = @frank_server.call(env)
|
@@ -24,18 +24,18 @@ module Frank
|
|
24
24
|
env['PATH_INFO'] << 'index.html' if path[-1..-1] == '/'
|
25
25
|
result = @static_server.call(env)
|
26
26
|
end
|
27
|
-
|
27
|
+
|
28
28
|
# return if static assets found
|
29
29
|
# else reset the path and pass to frank
|
30
|
-
if result[0] == 200
|
30
|
+
if result[0] == 200 || result[0] == 304
|
31
31
|
result
|
32
32
|
else
|
33
33
|
env['PATH_INFO'] = path
|
34
34
|
@app.call(env)
|
35
35
|
end
|
36
|
-
|
36
|
+
|
37
37
|
end
|
38
|
-
|
38
|
+
|
39
39
|
end
|
40
40
|
end
|
41
|
-
end
|
41
|
+
end
|
data/lib/frank/publish.rb
CHANGED
@@ -1,68 +1,76 @@
|
|
1
1
|
module Frank
|
2
2
|
module Publish
|
3
3
|
|
4
|
-
class SCP
|
5
|
-
def self.execute!
|
6
|
-
exit_unless_configured
|
7
4
|
|
8
|
-
|
9
|
-
|
10
|
-
puts " - \033[32mExporting templates\033[0m"
|
11
|
-
end
|
5
|
+
def self.execute!
|
6
|
+
protocol = exit_unless_configured.to_s
|
12
7
|
|
13
|
-
|
8
|
+
ok_message "", "\nFrank is..."
|
9
|
+
ok_message "Exporting templates", " - "
|
14
10
|
|
15
|
-
|
16
|
-
|
11
|
+
# upload the files and report progress
|
12
|
+
ok_message "Publishing to: `#{Frank.publish.host}:#{Frank.publish.path}' via #{protocol}", " - "
|
17
13
|
|
18
|
-
# dump the project in production mode to tmp folder
|
19
|
-
Frank.export.path = tmp_folder
|
20
|
-
Frank.export.silent = true
|
21
|
-
Frank::Compile.export!
|
22
14
|
|
23
|
-
|
15
|
+
req = "frank/publish/#{protocol.downcase}"
|
16
|
+
rescue_load_error protocol do
|
17
|
+
require req
|
18
|
+
clazz = Frank::Publish.const_get(protocol.upcase)
|
19
|
+
publisher = clazz.new(Frank.publish)
|
20
|
+
publisher.perform!
|
21
|
+
end
|
24
22
|
|
25
|
-
|
26
|
-
|
27
|
-
:port => Frank.publish.port
|
28
|
-
}
|
23
|
+
ok_message "\nPublish complete!"
|
24
|
+
end
|
29
25
|
|
30
|
-
|
26
|
+
def self.exit_unless_configured
|
27
|
+
required_settings = {:host => Frank.publish.host, :path => Frank.publish.path, :username => Frank.publish.username}
|
31
28
|
|
32
|
-
|
33
|
-
|
34
|
-
ssh.scp.upload!("#{tmp_folder}/", Frank.publish.path, :recursive => true, :chunk_size => 2048) do |ch, name, sent, total|
|
29
|
+
should_exit = false
|
30
|
+
message = ""
|
35
31
|
|
36
|
-
|
32
|
+
protocol = Frank.publish.mode || :scp
|
33
|
+
unless [:ftp, :ftptls, :sftp, :scp].include?(protocol.to_sym)
|
34
|
+
message << "Frank.publish.mode = #{protocol} is not supported. Supported publish modes are 'ftp', 'ftptls', 'sftp' or 'scp' (default)\n"
|
35
|
+
should_exit = true
|
36
|
+
end
|
37
37
|
|
38
|
-
|
39
|
-
|
38
|
+
required_settings.each do |name, value|
|
39
|
+
if value.nil?
|
40
|
+
message << "Frank.publish.#{name} is required to publish. You can configure it in setup.rb\n"
|
41
|
+
should_exit = true
|
40
42
|
end
|
43
|
+
end
|
41
44
|
|
42
|
-
# cleanup by removing tmp folder
|
43
|
-
FileUtils.rm_rf(tmp_folder)
|
44
45
|
|
45
|
-
|
46
|
+
if should_exit
|
47
|
+
err_message message
|
48
|
+
exit!
|
46
49
|
end
|
47
50
|
|
48
|
-
|
49
|
-
|
50
|
-
should_exit = false
|
51
|
-
message = "\033[31m"
|
51
|
+
protocol
|
52
|
+
end
|
52
53
|
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
54
|
+
def self.rescue_load_error protocol, &blk
|
55
|
+
gem = "net-#{protocol}"
|
56
|
+
begin
|
57
|
+
yield
|
58
|
+
rescue LoadError
|
59
|
+
err_message "Publishing via #{protocol} requires the '#{gem}' gem. `gem install #{gem}'"
|
60
|
+
exit!
|
61
|
+
end
|
62
|
+
end
|
59
63
|
|
60
|
-
message << "\033[0m"
|
61
64
|
|
62
|
-
|
63
|
-
|
65
|
+
def self.ok_message str, prefix = ''
|
66
|
+
puts "#{prefix}\033[32m#{str}\033[0m"
|
67
|
+
end
|
64
68
|
|
69
|
+
def self.err_message str, prefix = ''
|
70
|
+
puts "#{prefix}\033[31m#{str}\033[0m"
|
65
71
|
end
|
66
72
|
|
73
|
+
|
67
74
|
end
|
75
|
+
|
68
76
|
end
|
@@ -0,0 +1,94 @@
|
|
1
|
+
module Frank
|
2
|
+
module Publish
|
3
|
+
class Base
|
4
|
+
|
5
|
+
attr_accessor :username, :password
|
6
|
+
attr_accessor :hostname, :port
|
7
|
+
attr_accessor :remote_path
|
8
|
+
attr_accessor :local_path
|
9
|
+
|
10
|
+
|
11
|
+
def initialize(options)
|
12
|
+
@username = options.user || options.username
|
13
|
+
@password = options.password
|
14
|
+
@hostname = options.host
|
15
|
+
@remote_path = options.path
|
16
|
+
@port = options.port
|
17
|
+
@local_path = "/tmp/frank-publish-#{Frank.proj_name}-#{Time.now.to_i}"
|
18
|
+
end
|
19
|
+
|
20
|
+
##
|
21
|
+
# Performs the backup transfer
|
22
|
+
def perform!
|
23
|
+
export!
|
24
|
+
begin
|
25
|
+
transfer!
|
26
|
+
rescue SocketError
|
27
|
+
err_message "Transfer failed. SocketError. Do you have internet?"
|
28
|
+
end
|
29
|
+
cleanup!
|
30
|
+
end
|
31
|
+
|
32
|
+
|
33
|
+
private
|
34
|
+
|
35
|
+
def export!
|
36
|
+
# remove stale folder if it exists
|
37
|
+
FileUtils.rm_rf(local_path) if File.exist?(local_path)
|
38
|
+
|
39
|
+
# dump the project in production mode to tmp folder
|
40
|
+
Frank.export.path = @local_path
|
41
|
+
Frank.export.silent = true
|
42
|
+
Frank::Compile.export!
|
43
|
+
end
|
44
|
+
|
45
|
+
|
46
|
+
##
|
47
|
+
# returns a local_path relative list of all files to transfer for this export
|
48
|
+
def files_to_transfer
|
49
|
+
list = []
|
50
|
+
return list unless File.exist?(local_path)
|
51
|
+
|
52
|
+
Dir.chdir(local_path) do
|
53
|
+
list = Dir.glob("**/*").map do |f|
|
54
|
+
f unless File.directory? f
|
55
|
+
end.compact!
|
56
|
+
end
|
57
|
+
|
58
|
+
list
|
59
|
+
end
|
60
|
+
|
61
|
+
##
|
62
|
+
# returns a local_path relative list of all directories to export
|
63
|
+
def directories
|
64
|
+
list = []
|
65
|
+
return list unless File.exist?(local_path)
|
66
|
+
|
67
|
+
Dir.chdir(local_path) do
|
68
|
+
list = Dir.glob("**/*").map do |f|
|
69
|
+
f if File.directory? f
|
70
|
+
end.compact!
|
71
|
+
end
|
72
|
+
|
73
|
+
list
|
74
|
+
end
|
75
|
+
|
76
|
+
def cleanup!
|
77
|
+
FileUtils.rm_rf(@local_path)
|
78
|
+
end
|
79
|
+
|
80
|
+
# ZOMG, we a need a Logger or sth.
|
81
|
+
def ok_message *args
|
82
|
+
Frank::Publish.ok_message *args
|
83
|
+
end
|
84
|
+
|
85
|
+
def err_message *args
|
86
|
+
Frank::Publish.err_message *args
|
87
|
+
end
|
88
|
+
|
89
|
+
|
90
|
+
end
|
91
|
+
|
92
|
+
|
93
|
+
end
|
94
|
+
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
require 'frank/publish/base'
|
2
|
+
require 'net/ftp'
|
3
|
+
|
4
|
+
module Frank
|
5
|
+
module Publish
|
6
|
+
|
7
|
+
class FTP < Base
|
8
|
+
|
9
|
+
def initialize(options, &block)
|
10
|
+
super(options)
|
11
|
+
instance_eval(&block) if block_given?
|
12
|
+
|
13
|
+
@port ||= 21
|
14
|
+
@remote_path = remote_path.sub(/^\~\//, '').sub(/^\//, '')
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
##
|
20
|
+
# Establishes a connection to the remote server
|
21
|
+
#
|
22
|
+
# Note:
|
23
|
+
# Since the FTP port is defined as a constant in the Net::FTP class, and
|
24
|
+
# might be required to change by the user, we dynamically remove and
|
25
|
+
# re-add the constant with the provided port value
|
26
|
+
def connection
|
27
|
+
if Net::FTP.const_defined?(:FTP_PORT)
|
28
|
+
Net::FTP.send(:remove_const, :FTP_PORT)
|
29
|
+
end; Net::FTP.send(:const_set, :FTP_PORT, port)
|
30
|
+
|
31
|
+
Net::FTP.open(hostname, username, password) do |ftp|
|
32
|
+
ftp.passive = true
|
33
|
+
yield ftp
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
##
|
38
|
+
# Transfers the archived file to the specified remote server
|
39
|
+
def transfer!
|
40
|
+
connection do |ftp|
|
41
|
+
directories.each do |dir|
|
42
|
+
create_remote_path(File.join(remote_path, dir), ftp)
|
43
|
+
end
|
44
|
+
|
45
|
+
files_to_transfer.each do |file|
|
46
|
+
ok_message "Uploading #{file}", " - "
|
47
|
+
ftp.put(
|
48
|
+
File.join(local_path, file),
|
49
|
+
File.join(remote_path, file)
|
50
|
+
)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
##
|
56
|
+
# Creates (if they don't exist yet) all the directories on the remote
|
57
|
+
# server in order to upload the backup file. Net::FTP does not support
|
58
|
+
# paths to directories that don't yet exist when creating new
|
59
|
+
# directories. Instead, we split the parts up in to an array (for each
|
60
|
+
# '/') and loop through that to create the directories one by one.
|
61
|
+
# Net::FTP raises an exception when the directory it's trying to create
|
62
|
+
# already exists, so we have rescue it
|
63
|
+
def create_remote_path(remote_path, ftp)
|
64
|
+
path_parts = []
|
65
|
+
remote_path.split('/').each do |path_part|
|
66
|
+
path_parts << path_part
|
67
|
+
begin
|
68
|
+
dir = path_parts.join('/')
|
69
|
+
ftp.mkdir(dir) unless dir.empty?
|
70
|
+
rescue Net::FTPPermError;
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
|
76
|
+
end
|
77
|
+
|
78
|
+
|
79
|
+
end
|
80
|
+
end
|