guard-autoupload 0.3.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitattributes +22 -0
- data/.gitignore +166 -0
- data/Gemfile +0 -0
- data/README.md +56 -0
- data/Rakefile +2 -0
- data/guard-autoupload.gemspec +23 -0
- data/lib/guard/autoupload/ftpsession.rb +45 -0
- data/lib/guard/autoupload/scpsession.rb +108 -0
- data/lib/guard/autoupload/sftpsession.rb +61 -0
- data/lib/guard/autoupload/templates/Guardfile +20 -0
- data/lib/guard/autoupload.rb +133 -0
- metadata +96 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 6e16faa42eba0a9ffb386ddb02c5139554cba0ad
|
4
|
+
data.tar.gz: 89652a63835b3d2869b979423c512e0248bfcecd
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: a8206ff9cddcb9bc16e0651362d11aa95ff8501eaf8a06a7319b330e0a9f320c77923596967a45c9dbeebbcd0e392360fce7c74968d9576f6b9f869d88844afa
|
7
|
+
data.tar.gz: 71655bc8a80248a5fafe4aa7011e14de66d88c01f7fad686d0635a5b4d54c32364d7e4b38911795defcdbb5f0361bda9bbe682ae25cea769a91f12f313b2b0ae
|
data/.gitattributes
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
# Auto detect text files and perform LF normalization
|
2
|
+
* text=auto
|
3
|
+
|
4
|
+
# Custom for Visual Studio
|
5
|
+
*.cs diff=csharp
|
6
|
+
*.sln merge=union
|
7
|
+
*.csproj merge=union
|
8
|
+
*.vbproj merge=union
|
9
|
+
*.fsproj merge=union
|
10
|
+
*.dbproj merge=union
|
11
|
+
|
12
|
+
# Standard to msysgit
|
13
|
+
*.doc diff=astextplain
|
14
|
+
*.DOC diff=astextplain
|
15
|
+
*.docx diff=astextplain
|
16
|
+
*.DOCX diff=astextplain
|
17
|
+
*.dot diff=astextplain
|
18
|
+
*.DOT diff=astextplain
|
19
|
+
*.pdf diff=astextplain
|
20
|
+
*.PDF diff=astextplain
|
21
|
+
*.rtf diff=astextplain
|
22
|
+
*.RTF diff=astextplain
|
data/.gitignore
ADDED
@@ -0,0 +1,166 @@
|
|
1
|
+
#################
|
2
|
+
## Eclipse
|
3
|
+
#################
|
4
|
+
|
5
|
+
*.pydevproject
|
6
|
+
.project
|
7
|
+
.metadata
|
8
|
+
bin/
|
9
|
+
tmp/
|
10
|
+
*.tmp
|
11
|
+
*.bak
|
12
|
+
*.swp
|
13
|
+
*~.nib
|
14
|
+
local.properties
|
15
|
+
.classpath
|
16
|
+
.settings/
|
17
|
+
.loadpath
|
18
|
+
|
19
|
+
# External tool builders
|
20
|
+
.externalToolBuilders/
|
21
|
+
|
22
|
+
# Locally stored "Eclipse launch configurations"
|
23
|
+
*.launch
|
24
|
+
|
25
|
+
# CDT-specific
|
26
|
+
.cproject
|
27
|
+
|
28
|
+
# PDT-specific
|
29
|
+
.buildpath
|
30
|
+
|
31
|
+
|
32
|
+
#################
|
33
|
+
## Visual Studio
|
34
|
+
#################
|
35
|
+
|
36
|
+
## Ignore Visual Studio temporary files, build results, and
|
37
|
+
## files generated by popular Visual Studio add-ons.
|
38
|
+
|
39
|
+
# User-specific files
|
40
|
+
*.suo
|
41
|
+
*.user
|
42
|
+
*.sln.docstates
|
43
|
+
|
44
|
+
# Build results
|
45
|
+
[Dd]ebug/
|
46
|
+
[Rr]elease/
|
47
|
+
*_i.c
|
48
|
+
*_p.c
|
49
|
+
*.ilk
|
50
|
+
*.meta
|
51
|
+
*.obj
|
52
|
+
*.pch
|
53
|
+
*.pdb
|
54
|
+
*.pgc
|
55
|
+
*.pgd
|
56
|
+
*.rsp
|
57
|
+
*.sbr
|
58
|
+
*.tlb
|
59
|
+
*.tli
|
60
|
+
*.tlh
|
61
|
+
*.tmp
|
62
|
+
*.vspscc
|
63
|
+
.builds
|
64
|
+
*.dotCover
|
65
|
+
|
66
|
+
## TODO: If you have NuGet Package Restore enabled, uncomment this
|
67
|
+
#packages/
|
68
|
+
|
69
|
+
# Visual C++ cache files
|
70
|
+
ipch/
|
71
|
+
*.aps
|
72
|
+
*.ncb
|
73
|
+
*.opensdf
|
74
|
+
*.sdf
|
75
|
+
|
76
|
+
# Visual Studio profiler
|
77
|
+
*.psess
|
78
|
+
*.vsp
|
79
|
+
|
80
|
+
# ReSharper is a .NET coding add-in
|
81
|
+
_ReSharper*
|
82
|
+
|
83
|
+
# Installshield output folder
|
84
|
+
[Ee]xpress
|
85
|
+
|
86
|
+
# DocProject is a documentation generator add-in
|
87
|
+
DocProject/buildhelp/
|
88
|
+
DocProject/Help/*.HxT
|
89
|
+
DocProject/Help/*.HxC
|
90
|
+
DocProject/Help/*.hhc
|
91
|
+
DocProject/Help/*.hhk
|
92
|
+
DocProject/Help/*.hhp
|
93
|
+
DocProject/Help/Html2
|
94
|
+
DocProject/Help/html
|
95
|
+
|
96
|
+
# Click-Once directory
|
97
|
+
publish
|
98
|
+
|
99
|
+
# Others
|
100
|
+
[Bb]in
|
101
|
+
[Oo]bj
|
102
|
+
sql
|
103
|
+
TestResults
|
104
|
+
*.Cache
|
105
|
+
ClientBin
|
106
|
+
stylecop.*
|
107
|
+
~$*
|
108
|
+
*.dbmdl
|
109
|
+
Generated_Code #added for RIA/Silverlight projects
|
110
|
+
|
111
|
+
# Backup & report files from converting an old project file to a newer
|
112
|
+
# Visual Studio version. Backup files are not needed, because we have git ;-)
|
113
|
+
_UpgradeReport_Files/
|
114
|
+
Backup*/
|
115
|
+
UpgradeLog*.XML
|
116
|
+
|
117
|
+
|
118
|
+
|
119
|
+
############
|
120
|
+
## Windows
|
121
|
+
############
|
122
|
+
|
123
|
+
# Windows image file caches
|
124
|
+
Thumbs.db
|
125
|
+
|
126
|
+
# Folder config file
|
127
|
+
Desktop.ini
|
128
|
+
|
129
|
+
|
130
|
+
#############
|
131
|
+
## Python
|
132
|
+
#############
|
133
|
+
|
134
|
+
*.py[co]
|
135
|
+
|
136
|
+
# Packages
|
137
|
+
*.egg
|
138
|
+
*.egg-info
|
139
|
+
dist
|
140
|
+
build
|
141
|
+
eggs
|
142
|
+
parts
|
143
|
+
bin
|
144
|
+
var
|
145
|
+
sdist
|
146
|
+
develop-eggs
|
147
|
+
.installed.cfg
|
148
|
+
|
149
|
+
# Installer logs
|
150
|
+
pip-log.txt
|
151
|
+
|
152
|
+
# Unit test / coverage reports
|
153
|
+
.coverage
|
154
|
+
.tox
|
155
|
+
|
156
|
+
#Translations
|
157
|
+
*.mo
|
158
|
+
|
159
|
+
#Mr Developer
|
160
|
+
.mr.developer.cfg
|
161
|
+
|
162
|
+
# Mac crap
|
163
|
+
.DS_Store
|
164
|
+
|
165
|
+
# Ignore built gems
|
166
|
+
*.gem
|
data/Gemfile
ADDED
File without changes
|
data/README.md
ADDED
@@ -0,0 +1,56 @@
|
|
1
|
+
guard-autoupload
|
2
|
+
================
|
3
|
+
|
4
|
+
Autoupload plugin used for uploading all local changes to remote host.
|
5
|
+
Uses either SFTP or FTP.
|
6
|
+
|
7
|
+
Usage
|
8
|
+
-----
|
9
|
+
|
10
|
+
Sample guardfile:
|
11
|
+
|
12
|
+
opts = {
|
13
|
+
:protocol => :scp, # Protocol used to connect to remote host.
|
14
|
+
# Possible values are :scp, :sftp and :ftp.
|
15
|
+
# Of these :scp is the preferred one for
|
16
|
+
# its stability.
|
17
|
+
:host => "remote_host",
|
18
|
+
:user => "username",
|
19
|
+
:password => "password",
|
20
|
+
:remote => "remote_path",
|
21
|
+
:verbose => false, # if true you get all outputs
|
22
|
+
:quiet => false # if true outputs only on exceptions.
|
23
|
+
}
|
24
|
+
|
25
|
+
guard :autoupload, opts do
|
26
|
+
watch(/^((?!Guardfile$).)*$/)
|
27
|
+
# Matches every other file but Guardfile. This way we don't
|
28
|
+
# accidentally upload the credentials.
|
29
|
+
end
|
30
|
+
|
31
|
+
Dependencies
|
32
|
+
------------
|
33
|
+
|
34
|
+
- guard
|
35
|
+
- Net::SFTP
|
36
|
+
- Net::SSH::Simple
|
37
|
+
|
38
|
+
Installation
|
39
|
+
------------
|
40
|
+
|
41
|
+
For now you need to install `guard-autoupload` by building the gem manually
|
42
|
+
and installing from that:
|
43
|
+
|
44
|
+
gem build guard-autoupload.gemspec
|
45
|
+
gem install guard-autoupload-0.3.4.gem
|
46
|
+
|
47
|
+
Author
|
48
|
+
------
|
49
|
+
|
50
|
+
This guard plugin was written by Jyrki Lilja and is used at FocusFlow.
|
51
|
+
The code is hevily based on [vincenthu's guard-flopbox][gsftp] and
|
52
|
+
[bgarret's guard-ftpsync][gftp].
|
53
|
+
|
54
|
+
[gsftp]: https://github.com/vincentchu/guard-flopbox
|
55
|
+
[gftp]: https://github.com/bgarret/guard-ftpsync
|
56
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
|
4
|
+
Gem::Specification.new do |s|
|
5
|
+
s.name = "guard-autoupload"
|
6
|
+
s.version = "0.3.4"
|
7
|
+
s.authors = ["Jyrki Lilja"]
|
8
|
+
s.email = ["jyrki dot lilja at outlook dot com"]
|
9
|
+
s.homepage = "https://github.com/jyrkij/guard-autosync"
|
10
|
+
s.summary = %q{Autoupload plugin - uploads local changes to remote host.}
|
11
|
+
s.description = %q{Uses either SFTP or FTP.}
|
12
|
+
|
13
|
+
s.rubyforge_project = "guard-autoupload"
|
14
|
+
|
15
|
+
s.files = `git ls-files`.split("\n")
|
16
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
17
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map { |f| File.basename(f) }
|
18
|
+
s.require_paths = ["lib"]
|
19
|
+
|
20
|
+
s.add_dependency('guard')
|
21
|
+
s.add_dependency('net-sftp')
|
22
|
+
s.add_dependency('net-ssh-simple')
|
23
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require 'net/ftp'
|
2
|
+
|
3
|
+
class FTPSession
|
4
|
+
RESPAWN_INTERVAL = 60 # in seconds
|
5
|
+
|
6
|
+
def initialize(host, user, password)
|
7
|
+
@session = Net::FTP.new
|
8
|
+
@host = host
|
9
|
+
@user = user
|
10
|
+
@password = password
|
11
|
+
@last_timestamp = Time.new(0)
|
12
|
+
@session.connect(@host)
|
13
|
+
@session.login(@user, @password)
|
14
|
+
end
|
15
|
+
|
16
|
+
def upload!(local, remote)
|
17
|
+
remote { @session.putbinaryfile(local, remote) }
|
18
|
+
end
|
19
|
+
|
20
|
+
def mkdir!(dir)
|
21
|
+
remote { @session.mkdir(dir) }
|
22
|
+
end
|
23
|
+
|
24
|
+
def remove!(remote)
|
25
|
+
remote { @session.delete(remote) }
|
26
|
+
end
|
27
|
+
|
28
|
+
def rmdir!(dir)
|
29
|
+
remote { @session.rmdir(dir) }
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
def remote
|
35
|
+
command_start_timestamp = Time.now
|
36
|
+
if (command_start_timestamp - @last_timestamp > RESPAWN_INTERVAL)
|
37
|
+
@session.close unless @session.last_response == nil
|
38
|
+
@session.connect(@host)
|
39
|
+
@session.login(@user, @password)
|
40
|
+
end
|
41
|
+
ret = yield
|
42
|
+
@last_timestamp = Time.now
|
43
|
+
ret
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,108 @@
|
|
1
|
+
require 'net/ssh/simple'
|
2
|
+
|
3
|
+
class SCPSession
|
4
|
+
def initialize(host, user, password, caller_ref)
|
5
|
+
@host = host
|
6
|
+
@user = user
|
7
|
+
@password = password.clone
|
8
|
+
@caller = caller_ref
|
9
|
+
@retry_count = 0
|
10
|
+
@max_retries = 1
|
11
|
+
end
|
12
|
+
|
13
|
+
def ss
|
14
|
+
Thread.current[:simplessh] ||= Net::SSH::Simple.new({:user => @user, :password => @password.clone})
|
15
|
+
end
|
16
|
+
|
17
|
+
def upload!(local, remote)
|
18
|
+
begin
|
19
|
+
ss.scp_put "#{@host}", "#{local}", "#{remote}"
|
20
|
+
# This shouldn't be run if we get an exception
|
21
|
+
@retry_count = 0
|
22
|
+
rescue Net::SSH::Simple::Error => e
|
23
|
+
case e.wrapped
|
24
|
+
when Errno::ECONNRESET, Net::SSH::Disconnect
|
25
|
+
raise e if @retry_count >= @max_retries
|
26
|
+
@retry_count += 1
|
27
|
+
@caller.log "Failed uploading and will try again."
|
28
|
+
@caller.log "The reason was #{e}" unless @caller.quiet?
|
29
|
+
close
|
30
|
+
retry
|
31
|
+
else
|
32
|
+
raise e
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def mkdir!(dir)
|
38
|
+
begin
|
39
|
+
check_exists = ss.ssh "#{@host}", "ls -ld #{dir}"
|
40
|
+
ss.ssh "#{@host}", "mkdir #{dir}" if check_exists.exit_code
|
41
|
+
# This shouldn't be run if we get an exception
|
42
|
+
@retry_count = 0
|
43
|
+
rescue Net::SSH::Simple::Error => e
|
44
|
+
case e.wrapped
|
45
|
+
when Errno::ECONNRESET, Net::SSH::Disconnect
|
46
|
+
raise e if @retry_count >= @max_retries
|
47
|
+
@retry_count += 1
|
48
|
+
@caller.log "Failed making directory and will try again."
|
49
|
+
@caller.log "The reason was #{e}" unless @caller.quiet?
|
50
|
+
close
|
51
|
+
retry
|
52
|
+
else
|
53
|
+
raise e
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def remove!(remote)
|
59
|
+
begin
|
60
|
+
ss.ssh @host, "rm #{remote}"
|
61
|
+
# This shouldn't be run if we get an exception
|
62
|
+
@retry_count = 0
|
63
|
+
rescue Net::SSH::Simple::Error => e
|
64
|
+
case e.wrapped
|
65
|
+
when Errno::ECONNRESET, Net::SSH::Disconnect
|
66
|
+
raise e if @retry_count >= @max_retries
|
67
|
+
@retry_count += 1
|
68
|
+
@caller.log "Failed removing file and will try again."
|
69
|
+
@caller.log "The reason was #{e}" unless @caller.quiet?
|
70
|
+
close
|
71
|
+
retry
|
72
|
+
else
|
73
|
+
raise e
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def rmdir!(dir)
|
79
|
+
throw NotImplementedError
|
80
|
+
end
|
81
|
+
|
82
|
+
def ls!(dir)
|
83
|
+
begin
|
84
|
+
ss.ssh @host, "ls #{dir}"
|
85
|
+
# This shouldn't be run if we get an exception
|
86
|
+
@retry_count = 0
|
87
|
+
rescue Net::SSH::Simple::Error => e
|
88
|
+
case e.wrapped
|
89
|
+
when Errno::ECONNRESET, Net::SSH::Disconnect
|
90
|
+
raise e if @retry_count >= @max_retries
|
91
|
+
puts @password
|
92
|
+
exit
|
93
|
+
@retry_count += 1
|
94
|
+
@caller.log "Failed listing directory contents and will try again."
|
95
|
+
@caller.log "The reason was #{e}" unless @caller.quiet?
|
96
|
+
close
|
97
|
+
retry
|
98
|
+
else
|
99
|
+
raise e
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
def close
|
105
|
+
ss.close
|
106
|
+
Thread.current[:simplessh] = nil
|
107
|
+
end
|
108
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
require 'net/sftp'
|
2
|
+
|
3
|
+
class SFTPSession
|
4
|
+
def initialize(host, user, password, caller_ref)
|
5
|
+
@host = host
|
6
|
+
@user = user
|
7
|
+
@password = password
|
8
|
+
@session = Net::SFTP.start(
|
9
|
+
@host,
|
10
|
+
@user,
|
11
|
+
:password => @password
|
12
|
+
)
|
13
|
+
@caller = caller_ref
|
14
|
+
end
|
15
|
+
|
16
|
+
def upload!(local, remote)
|
17
|
+
remote { @session.upload!(local, remote) }
|
18
|
+
end
|
19
|
+
|
20
|
+
def mkdir!(dir)
|
21
|
+
begin
|
22
|
+
remote { @session.lstat!(dir) }
|
23
|
+
exists = true
|
24
|
+
rescue Net::SFTP::StatusException
|
25
|
+
exists = false
|
26
|
+
end
|
27
|
+
remote { @session.mkdir!(dir) } unless exists
|
28
|
+
end
|
29
|
+
|
30
|
+
def remove!(remote)
|
31
|
+
stat = remote { @session.lstat!(remote) }
|
32
|
+
remote { @session.remove!(remote) } if stat.file?
|
33
|
+
remote { @session.rmdir!(remote) } if stat.directory?
|
34
|
+
end
|
35
|
+
|
36
|
+
def rmdir!(dir)
|
37
|
+
remote { @session.rmdir!(dir) }
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
41
|
+
|
42
|
+
def remote
|
43
|
+
begin
|
44
|
+
ret = yield
|
45
|
+
rescue => e
|
46
|
+
case e
|
47
|
+
when Errno::ECONNRESET
|
48
|
+
@caller.log "Connection resetted by remote. Reconnecting." unless @caller.quiet?
|
49
|
+
@session = Net::SFTP.start(
|
50
|
+
@host,
|
51
|
+
@user,
|
52
|
+
:password => @password
|
53
|
+
)
|
54
|
+
ret = yield
|
55
|
+
else
|
56
|
+
raise
|
57
|
+
end
|
58
|
+
end
|
59
|
+
ret
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# Configuartion Options for guard-autoupload
|
2
|
+
|
3
|
+
opts = {
|
4
|
+
:protocol => :scp, # Protocol used to connect to remote host.
|
5
|
+
# Possible values are :scp, :sftp and :ftp.
|
6
|
+
# Of these :scp is the preferred one for
|
7
|
+
# its stability.
|
8
|
+
:host => "remote_host",
|
9
|
+
:user => "username",
|
10
|
+
:password => "password",
|
11
|
+
:remote => "remote_path",
|
12
|
+
:verbose => false, # if true you get all outputs
|
13
|
+
:quiet => false # if true outputs only on exceptions.
|
14
|
+
}
|
15
|
+
|
16
|
+
guard :autoupload, opts do
|
17
|
+
watch(/^((?!Guardfile$).)*$/)
|
18
|
+
# Matches every other file but Guardfile. This way we don't
|
19
|
+
# accidentally upload the credentials.
|
20
|
+
end
|
@@ -0,0 +1,133 @@
|
|
1
|
+
$LOAD_PATH.unshift File.dirname(__FILE__)
|
2
|
+
|
3
|
+
require 'guard'
|
4
|
+
require 'guard/guard'
|
5
|
+
require 'autoupload/scpsession.rb'
|
6
|
+
require 'autoupload/sftpsession.rb'
|
7
|
+
require 'autoupload/ftpsession.rb'
|
8
|
+
|
9
|
+
module Guard
|
10
|
+
class Autoupload < Guard
|
11
|
+
def initialize(watchers = [], options = {})
|
12
|
+
super
|
13
|
+
|
14
|
+
@instance = self
|
15
|
+
if options[:protocol] == :scp
|
16
|
+
@session = SCPSession.new(
|
17
|
+
options[:host],
|
18
|
+
options[:user],
|
19
|
+
options[:password],
|
20
|
+
self
|
21
|
+
)
|
22
|
+
elsif options[:protocol] == :sftp
|
23
|
+
@session = SFTPSession.new(
|
24
|
+
options[:host],
|
25
|
+
options[:user],
|
26
|
+
options[:password],
|
27
|
+
@instance
|
28
|
+
)
|
29
|
+
elsif options[:protocol] == :ftp
|
30
|
+
@session = FTPSession.new(
|
31
|
+
options[:host],
|
32
|
+
options[:user],
|
33
|
+
options[:password]
|
34
|
+
)
|
35
|
+
else
|
36
|
+
throw :task_has_failed
|
37
|
+
end
|
38
|
+
|
39
|
+
@remote = options[:remote]
|
40
|
+
@local = Dir.pwd
|
41
|
+
@verbose = options[:verbose]
|
42
|
+
@quiet = options[:quiet] unless verbose?
|
43
|
+
|
44
|
+
options[:password].gsub!(/./, '*') if options.include? :password
|
45
|
+
log "Initialized with watchers #{watchers.inspect}" if verbose?
|
46
|
+
log "Initialized with options #{options.inspect}" unless quiet?
|
47
|
+
end
|
48
|
+
|
49
|
+
def run_on_change(paths)
|
50
|
+
paths.each do |path|
|
51
|
+
local_file = File.join(@local, path)
|
52
|
+
remote_file = File.join(@remote, path)
|
53
|
+
|
54
|
+
attempts = 0
|
55
|
+
|
56
|
+
begin
|
57
|
+
log "Upload #{local_file} => #{remote_file}" if verbose?
|
58
|
+
@session.upload!(local_file, remote_file)
|
59
|
+
log "Uploaded #{path}" unless quiet?
|
60
|
+
rescue => ex
|
61
|
+
log "Exception on uploading #{path}\n#{ex.inspect}"
|
62
|
+
log ex.backtrace.join("\n") if verbose?
|
63
|
+
attempts += 1
|
64
|
+
remote_dir = File.dirname(remote_file)
|
65
|
+
recursively_create_dirs(remote_dir)
|
66
|
+
retry if attempts < 3
|
67
|
+
log "Exceeded 3 attempts to upload #{path}"
|
68
|
+
throw :task_has_failed
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
msg = "Uploaded:\n#{paths.join("\n")}"
|
73
|
+
::Guard::Notifier.notify msg, :title => "Uploaded"
|
74
|
+
end
|
75
|
+
|
76
|
+
def run_on_removals(paths)
|
77
|
+
paths.each do |path|
|
78
|
+
remote_file = File.join(@remote, path)
|
79
|
+
|
80
|
+
begin
|
81
|
+
log "Delete #{remote_file}" if verbose?
|
82
|
+
@session.remove!(remote_file)
|
83
|
+
rescue => ex
|
84
|
+
log "Exception on deleting #{path}\n#{ex.inspect}"
|
85
|
+
log ex.backtrace.join("\n") if verbose?
|
86
|
+
end
|
87
|
+
|
88
|
+
log "Deleted #{path}" unless quiet?
|
89
|
+
end
|
90
|
+
|
91
|
+
msg = "Deleted:\n#{paths.join("\n")}"
|
92
|
+
::Guard::Notifier.notify msg, :title => "Deleted"
|
93
|
+
end
|
94
|
+
|
95
|
+
def verbose?
|
96
|
+
@verbose || false
|
97
|
+
end
|
98
|
+
|
99
|
+
def quiet?
|
100
|
+
@quiet || false
|
101
|
+
end
|
102
|
+
|
103
|
+
def log(message)
|
104
|
+
puts "[#{Time.now}] #{message}"
|
105
|
+
end
|
106
|
+
|
107
|
+
def stop
|
108
|
+
log "Tearing down connections" unless quiet?
|
109
|
+
if @session.is_a? SCPSession
|
110
|
+
@session.close
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
private
|
115
|
+
|
116
|
+
def recursively_create_dirs(remote_dir)
|
117
|
+
new_dir = @remote
|
118
|
+
remote_dir.gsub(@remote, "").split("/").each do |dir|
|
119
|
+
new_dir = File.join(new_dir, dir)
|
120
|
+
|
121
|
+
begin
|
122
|
+
log "Creating #{new_dir}" if verbose?
|
123
|
+
@session.mkdir!(new_dir)
|
124
|
+
rescue => ex
|
125
|
+
log "Cannot create directory #{new_dir}\n#{ex.inspect}"
|
126
|
+
log ex.backtrace.join("\n") if verbose?
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
log "Created directory #{remote_dir}" unless quiet?
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
metadata
ADDED
@@ -0,0 +1,96 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: guard-autoupload
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.3.4
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Jyrki Lilja
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2013-04-12 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: guard
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - '>='
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - '>='
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: net-sftp
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - '>='
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - '>='
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: net-ssh-simple
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - '>='
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
description: Uses either SFTP or FTP.
|
56
|
+
email:
|
57
|
+
- jyrki dot lilja at outlook dot com
|
58
|
+
executables: []
|
59
|
+
extensions: []
|
60
|
+
extra_rdoc_files: []
|
61
|
+
files:
|
62
|
+
- .gitattributes
|
63
|
+
- .gitignore
|
64
|
+
- Gemfile
|
65
|
+
- README.md
|
66
|
+
- Rakefile
|
67
|
+
- guard-autoupload.gemspec
|
68
|
+
- lib/guard/autoupload.rb
|
69
|
+
- lib/guard/autoupload/ftpsession.rb
|
70
|
+
- lib/guard/autoupload/scpsession.rb
|
71
|
+
- lib/guard/autoupload/sftpsession.rb
|
72
|
+
- lib/guard/autoupload/templates/Guardfile
|
73
|
+
homepage: https://github.com/jyrkij/guard-autosync
|
74
|
+
licenses: []
|
75
|
+
metadata: {}
|
76
|
+
post_install_message:
|
77
|
+
rdoc_options: []
|
78
|
+
require_paths:
|
79
|
+
- lib
|
80
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
81
|
+
requirements:
|
82
|
+
- - '>='
|
83
|
+
- !ruby/object:Gem::Version
|
84
|
+
version: '0'
|
85
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - '>='
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
requirements: []
|
91
|
+
rubyforge_project: guard-autoupload
|
92
|
+
rubygems_version: 2.0.3
|
93
|
+
signing_key:
|
94
|
+
specification_version: 4
|
95
|
+
summary: Autoupload plugin - uploads local changes to remote host.
|
96
|
+
test_files: []
|