guard-autoupload 0.3.4
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.
- 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: []
|