webmake 1.1.0
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/lib/ftp.rb +175 -0
- data/lib/wake.rb +149 -0
- data/sample/Wakefile +20 -0
- data/wake +15 -0
- metadata +105 -0
data/lib/ftp.rb
ADDED
@@ -0,0 +1,175 @@
|
|
1
|
+
require 'net/ftp'
|
2
|
+
require 'net/sftp'
|
3
|
+
|
4
|
+
class Ftp
|
5
|
+
|
6
|
+
def initialize(config)
|
7
|
+
@config = config
|
8
|
+
connect
|
9
|
+
end
|
10
|
+
|
11
|
+
def connect
|
12
|
+
if @config["sftp"]
|
13
|
+
@connection = Net::SFTP.start(@config["host"], @config["username"], :password => @config["password"])
|
14
|
+
else
|
15
|
+
@connection = Net::FTP.new(@config["host"])
|
16
|
+
@connection.login(@config["username"], @config["password"])
|
17
|
+
end
|
18
|
+
|
19
|
+
true
|
20
|
+
rescue
|
21
|
+
false
|
22
|
+
end
|
23
|
+
|
24
|
+
def close
|
25
|
+
@connection.close unless @config["sftp"]
|
26
|
+
true
|
27
|
+
end
|
28
|
+
|
29
|
+
def connected?
|
30
|
+
! @connection.nil?
|
31
|
+
end
|
32
|
+
|
33
|
+
def list(dir)
|
34
|
+
if @config["sftp"]
|
35
|
+
files = []
|
36
|
+
@connection.dir.foreach(dir) do |entry|
|
37
|
+
permissions = entry.longname.split(" ")[0]
|
38
|
+
files << [entry.name, !entry.longname.starts_with("d"), permissions_from_string(permissions)] unless [".", ".."].include? entry.name
|
39
|
+
end
|
40
|
+
files
|
41
|
+
else
|
42
|
+
@connection.chdir(dir)
|
43
|
+
list = []
|
44
|
+
@connection.ls("-a").each do |file|
|
45
|
+
if file.size() > 8
|
46
|
+
filename = ""
|
47
|
+
filehold = file.split(" ")[8..-1] # get filename or directory name
|
48
|
+
filehold.each {|name_segment| filename += " #{name_segment}" }
|
49
|
+
filename.lstrip!
|
50
|
+
|
51
|
+
# if this is a directory a d or ASCII 100 will be the first character
|
52
|
+
# 45 means its just a file
|
53
|
+
# anything else is garbage
|
54
|
+
unless [".", ".."].include? filename
|
55
|
+
if file[0] == 45
|
56
|
+
list << [filename, true]
|
57
|
+
elsif file[0] == 100
|
58
|
+
list << [filename, false]
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
list
|
65
|
+
end
|
66
|
+
rescue
|
67
|
+
[]
|
68
|
+
end
|
69
|
+
|
70
|
+
def publish(path, create_dirs_on_failure = true)
|
71
|
+
remote_path = prepare_remote_path(path)
|
72
|
+
|
73
|
+
if @config["sftp"]
|
74
|
+
@connection.upload!(path, remote_path)
|
75
|
+
else
|
76
|
+
@connection.put(path, remote_path)
|
77
|
+
end
|
78
|
+
|
79
|
+
true
|
80
|
+
rescue
|
81
|
+
if create_dirs_on_failure
|
82
|
+
create_directories(remote_path)
|
83
|
+
return publish(path, false)
|
84
|
+
end
|
85
|
+
|
86
|
+
false
|
87
|
+
end
|
88
|
+
|
89
|
+
def create_directories(path)
|
90
|
+
segments = File.dirname(path).gsub(/^\/?(.+?)\/?$/, "\\1").split("/")
|
91
|
+
|
92
|
+
dir = ""
|
93
|
+
dir = "/" if path[0, 1] == "/"
|
94
|
+
|
95
|
+
segments.each do |segment|
|
96
|
+
dir << "#{segment}/"
|
97
|
+
|
98
|
+
begin
|
99
|
+
@connection.mkdir(dir)
|
100
|
+
rescue
|
101
|
+
# This dir already exist, move on.
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
def create_dir(path)
|
107
|
+
path = prepare_remote_path(path)
|
108
|
+
|
109
|
+
create_directories(path)
|
110
|
+
@connection.mkdir(path)
|
111
|
+
true
|
112
|
+
rescue
|
113
|
+
false
|
114
|
+
end
|
115
|
+
|
116
|
+
def delete_file(path)
|
117
|
+
path = prepare_remote_path(path) unless path.match(/^#{Regexp.escape(@config["root"])}/)
|
118
|
+
|
119
|
+
if @config["sftp"]
|
120
|
+
@connection.remove!(path)
|
121
|
+
true
|
122
|
+
else
|
123
|
+
@connection.delete(path)
|
124
|
+
true
|
125
|
+
end
|
126
|
+
rescue
|
127
|
+
false
|
128
|
+
end
|
129
|
+
|
130
|
+
def delete_dir(path)
|
131
|
+
path = prepare_remote_path(path) unless path.match(/^#{Regexp.escape(@config["root"])}/)
|
132
|
+
|
133
|
+
if @config["sftp"]
|
134
|
+
@connection.dir.entries(path).each do |entry|
|
135
|
+
next if entry.name == '.' or entry.name == '..'
|
136
|
+
|
137
|
+
child_path = File.join(path, entry.name)
|
138
|
+
|
139
|
+
if @connection.stat!(child_path).directory?
|
140
|
+
delete_dir(child_path)
|
141
|
+
else
|
142
|
+
delete_file(child_path)
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
@connection.rmdir!(path)
|
147
|
+
true
|
148
|
+
else
|
149
|
+
file_list = list(path)
|
150
|
+
|
151
|
+
file_list.each do |thefile|
|
152
|
+
filename = thefile[0]
|
153
|
+
# Files are True
|
154
|
+
if thefile[1]
|
155
|
+
delete_file(File.join(path, filename))
|
156
|
+
else
|
157
|
+
if filename != "." and filename != ".."
|
158
|
+
delete_dir(File.join(path, filename))
|
159
|
+
end
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
@connection.rmdir(path)
|
164
|
+
true
|
165
|
+
end
|
166
|
+
rescue
|
167
|
+
false
|
168
|
+
end
|
169
|
+
|
170
|
+
def prepare_remote_path(local_path)
|
171
|
+
path = local_path.gsub(/^#{Regexp.escape(Dir.pwd)}\//, "")
|
172
|
+
File.join(@config["root"], path)
|
173
|
+
end
|
174
|
+
|
175
|
+
end
|
data/lib/wake.rb
ADDED
@@ -0,0 +1,149 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'find'
|
3
|
+
require 'yaml'
|
4
|
+
require "#{File.expand_path("..", __FILE__)}/ftp"
|
5
|
+
require 'fileutils'
|
6
|
+
|
7
|
+
module Wake
|
8
|
+
|
9
|
+
def self.public_methods
|
10
|
+
['help', 'init', 'sync', 'set_synced']
|
11
|
+
end
|
12
|
+
|
13
|
+
# ----------------------------------------------------------------------
|
14
|
+
# Callable methods
|
15
|
+
# ----------------------------------------------------------------------
|
16
|
+
|
17
|
+
def self.help(e = nil)
|
18
|
+
puts "Wake only has three basic commands."
|
19
|
+
puts " init - Initializes a new Wake project and creates a sample Wakefile."
|
20
|
+
puts " sync - Publishes any changes in the filetree (including deletes)."
|
21
|
+
puts " set_synced - Set the project as synchronized without publishing changes."
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.init(e = nil)
|
25
|
+
config_file = File.join(Dir.pwd, "Wakefile")
|
26
|
+
release_dir = File.join(Dir.pwd, ".wake")
|
27
|
+
|
28
|
+
FileUtils.mkdir release_dir unless File.exists? release_dir
|
29
|
+
|
30
|
+
unless File.exists? config_file
|
31
|
+
wakefile_sample = File.expand_path("..", __FILE__)+"/../sample/Wakefile"
|
32
|
+
FileUtils.cp wakefile_sample, Dir.pwd
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def self.set_synced(environment = "development")
|
37
|
+
self.get_tree_diff(environment)
|
38
|
+
puts "Environment #{environment} is now set as synced."
|
39
|
+
end
|
40
|
+
|
41
|
+
def self.sync(environment = "development")
|
42
|
+
config_file = File.join(Dir.pwd, "Wakefile")
|
43
|
+
|
44
|
+
unless File.exists? config_file
|
45
|
+
puts "This project has no Wakefile."
|
46
|
+
return
|
47
|
+
end
|
48
|
+
|
49
|
+
config = YAML::load(File.open(config_file).read)
|
50
|
+
|
51
|
+
unless config.has_key? environment
|
52
|
+
puts "#{environment.capitalize} environment is not defined in Wakefile."
|
53
|
+
end
|
54
|
+
|
55
|
+
synchronize(environment, config[environment])
|
56
|
+
end
|
57
|
+
|
58
|
+
def self.synchronize(environment, config)
|
59
|
+
diff_tree = self.get_tree_diff(environment)
|
60
|
+
|
61
|
+
ftp = Ftp.new(config)
|
62
|
+
diff_tree.each do |filename, stats|
|
63
|
+
if stats[:is_dir]
|
64
|
+
ftp.delete_dir(filename) if stats[:status] == :delete
|
65
|
+
ftp.create_dir(filename) if stats[:status] == :publish
|
66
|
+
else
|
67
|
+
ftp.delete_file(filename) if stats[:status] == :delete
|
68
|
+
ftp.publish(filename) if stats[:status] == :publish
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
# ----------------------------------------------------------------------
|
74
|
+
# "Private" methods
|
75
|
+
# ----------------------------------------------------------------------
|
76
|
+
|
77
|
+
def self.get_tree_diff(environment)
|
78
|
+
old_tree = self.get_old_tree(environment)
|
79
|
+
current_tree = self.get_current_tree
|
80
|
+
|
81
|
+
last_release = self.get_last_release_date(environment)
|
82
|
+
|
83
|
+
diff_tree = {}
|
84
|
+
|
85
|
+
# Find out if any files have been added or updated since the last release.
|
86
|
+
current_tree.each do |filename, is_dir|
|
87
|
+
if File.ctime(filename) > last_release
|
88
|
+
diff_tree[filename] = {
|
89
|
+
:is_dir => is_dir,
|
90
|
+
:status => :publish
|
91
|
+
}
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
# Find out if any files have been removed since the last release.
|
96
|
+
old_tree.each do |filename, is_dir|
|
97
|
+
unless current_tree.has_key? filename
|
98
|
+
diff_tree[filename] = {
|
99
|
+
:is_dir => is_dir,
|
100
|
+
:status => :delete
|
101
|
+
}
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
self.write_tree(environment, current_tree)
|
106
|
+
|
107
|
+
diff_tree
|
108
|
+
end
|
109
|
+
|
110
|
+
def self.get_last_release_date(environment)
|
111
|
+
tree_file = File.join(Dir.pwd, ".wake/#{environment}")
|
112
|
+
|
113
|
+
if File.exists? tree_file
|
114
|
+
return File.ctime tree_file
|
115
|
+
end
|
116
|
+
|
117
|
+
Time.at(0)
|
118
|
+
end
|
119
|
+
|
120
|
+
def self.get_old_tree(environment)
|
121
|
+
tree = {}
|
122
|
+
|
123
|
+
tree_file = File.join(Dir.pwd, ".wake/#{environment}")
|
124
|
+
if File.exists? tree_file
|
125
|
+
tree = YAML::load(File.open(tree_file).read)
|
126
|
+
end
|
127
|
+
|
128
|
+
tree
|
129
|
+
end
|
130
|
+
|
131
|
+
def self.get_current_tree
|
132
|
+
tree = {}
|
133
|
+
|
134
|
+
path = Dir.pwd
|
135
|
+
Find.find(path) do |file|
|
136
|
+
tree[file] = File.directory? file unless (file == path or file.match(/(Wakefile|\.wake)/))
|
137
|
+
end
|
138
|
+
|
139
|
+
tree
|
140
|
+
end
|
141
|
+
|
142
|
+
def self.write_tree(environment, tree)
|
143
|
+
tree_file = File.join(Dir.pwd, ".wake/#{environment}")
|
144
|
+
File.open(tree_file, 'w') do |f|
|
145
|
+
f.write YAML::dump(tree)
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
end
|
data/sample/Wakefile
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
development:
|
2
|
+
sftp: false
|
3
|
+
host: "ftp.example.com"
|
4
|
+
username: "dev"
|
5
|
+
password: "dev"
|
6
|
+
root: "/var/www/dev/"
|
7
|
+
|
8
|
+
test:
|
9
|
+
sftp: false
|
10
|
+
host: "ftp.example.com"
|
11
|
+
username: "test"
|
12
|
+
password: "test"
|
13
|
+
root: "/var/www/test/"
|
14
|
+
|
15
|
+
production:
|
16
|
+
sftp: true
|
17
|
+
host: "sftp.example.com"
|
18
|
+
username: "prod"
|
19
|
+
password: "prod"
|
20
|
+
root: "/var/www/production/"
|
data/wake
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require "#{File.expand_path("..", __FILE__)}/lib/wake"
|
3
|
+
|
4
|
+
unless ARGV[0].nil?
|
5
|
+
command = ARGV[0]
|
6
|
+
|
7
|
+
if Wake.public_methods.include? command
|
8
|
+
environment = "development"
|
9
|
+
environment = ARGV[1] if ["development", "test", "production"].include? ARGV[1]
|
10
|
+
|
11
|
+
Wake.send(command, environment)
|
12
|
+
else
|
13
|
+
puts "Wake does not respond to \"#{command}\". Run \"wake help\" for more information."
|
14
|
+
end
|
15
|
+
end
|
metadata
ADDED
@@ -0,0 +1,105 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: webmake
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 19
|
5
|
+
prerelease:
|
6
|
+
segments:
|
7
|
+
- 1
|
8
|
+
- 1
|
9
|
+
- 0
|
10
|
+
version: 1.1.0
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- Christoffer Lejdborg
|
14
|
+
autorequire:
|
15
|
+
bindir: .
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2011-01-21 00:00:00 +01:00
|
19
|
+
default_executable: wake
|
20
|
+
dependencies:
|
21
|
+
- !ruby/object:Gem::Dependency
|
22
|
+
name: net-ssh
|
23
|
+
prerelease: false
|
24
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ">="
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
hash: 11
|
30
|
+
segments:
|
31
|
+
- 2
|
32
|
+
- 1
|
33
|
+
- 0
|
34
|
+
version: 2.1.0
|
35
|
+
type: :runtime
|
36
|
+
version_requirements: *id001
|
37
|
+
- !ruby/object:Gem::Dependency
|
38
|
+
name: net-sftp
|
39
|
+
prerelease: false
|
40
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ">="
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
hash: 5
|
46
|
+
segments:
|
47
|
+
- 2
|
48
|
+
- 0
|
49
|
+
- 5
|
50
|
+
version: 2.0.5
|
51
|
+
type: :runtime
|
52
|
+
version_requirements: *id002
|
53
|
+
description: Wake is a very simplistic synchronisation tool for web applications. You can set up three envioronments (test, development and production) and use wither FTP or SFTP to sync your sites.
|
54
|
+
email: hello@9muses.se
|
55
|
+
executables:
|
56
|
+
- wake
|
57
|
+
extensions: []
|
58
|
+
|
59
|
+
extra_rdoc_files: []
|
60
|
+
|
61
|
+
files:
|
62
|
+
- lib/ftp.rb
|
63
|
+
- lib/wake.rb
|
64
|
+
- sample/Wakefile
|
65
|
+
- ./wake
|
66
|
+
has_rdoc: true
|
67
|
+
homepage: http://github.com/Lejdborg/Wake
|
68
|
+
licenses: []
|
69
|
+
|
70
|
+
post_install_message:
|
71
|
+
rdoc_options: []
|
72
|
+
|
73
|
+
require_paths:
|
74
|
+
- lib
|
75
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
76
|
+
none: false
|
77
|
+
requirements:
|
78
|
+
- - ">="
|
79
|
+
- !ruby/object:Gem::Version
|
80
|
+
hash: 57
|
81
|
+
segments:
|
82
|
+
- 1
|
83
|
+
- 8
|
84
|
+
- 7
|
85
|
+
version: 1.8.7
|
86
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
87
|
+
none: false
|
88
|
+
requirements:
|
89
|
+
- - ">="
|
90
|
+
- !ruby/object:Gem::Version
|
91
|
+
hash: 23
|
92
|
+
segments:
|
93
|
+
- 1
|
94
|
+
- 3
|
95
|
+
- 6
|
96
|
+
version: 1.3.6
|
97
|
+
requirements: []
|
98
|
+
|
99
|
+
rubyforge_project:
|
100
|
+
rubygems_version: 1.4.2
|
101
|
+
signing_key:
|
102
|
+
specification_version: 3
|
103
|
+
summary: FTP/SFTP sync tool.
|
104
|
+
test_files: []
|
105
|
+
|