synqa 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile CHANGED
@@ -3,6 +3,9 @@ source "http://rubygems.org"
3
3
  # Example:
4
4
  # gem "activesupport", ">= 2.3.5"
5
5
 
6
+ gem "net-ssh", ">= 2.0"
7
+ gem "net-scp", ">= 1.0"
8
+
6
9
  # Add dependencies to develop your gem here.
7
10
  # Include everything needed to run rake, tests, features, etc.
8
11
  group :development do
data/Gemfile.lock CHANGED
@@ -6,6 +6,9 @@ GEM
6
6
  bundler (~> 1.0.0)
7
7
  git (>= 1.2.5)
8
8
  rake
9
+ net-scp (1.0.4)
10
+ net-ssh (>= 1.99.1)
11
+ net-ssh (2.1.4)
9
12
  rake (0.8.7)
10
13
  rcov (0.9.9)
11
14
  shoulda (2.11.3)
@@ -16,5 +19,7 @@ PLATFORMS
16
19
  DEPENDENCIES
17
20
  bundler (~> 1.0.0)
18
21
  jeweler (~> 1.5.2)
22
+ net-scp (>= 1.0)
23
+ net-ssh (>= 2.0)
19
24
  rcov
20
25
  shoulda
data/README.rdoc CHANGED
@@ -1,7 +1,7 @@
1
1
  = synqa
2
2
 
3
3
  *Synqa* is a simple file syncing tool that works over SSH, and is designed
4
- primarily for maintaining static websites. It uses a hash function to
4
+ primarily for maintaining static websites. It uses a secure hash function to
5
5
  determine which files don't need to be copied because the destination copy
6
6
  is already identical to the source copy.
7
7
 
@@ -20,8 +20,11 @@ I wrote *synqa* for two main reasons:
20
20
  == Dependencies of *synqa* are:
21
21
 
22
22
  * Ruby 1.9.2
23
- * An SSH client. I use *plink*.
24
- * An SCP client. I use *pscp*.
23
+ * Ruby gems *net-ssh* and *net-scp*
24
+
25
+ Optionally:
26
+ * An external SSH client. I use *plink*.
27
+ * An external SCP client. I use *pscp*.
25
28
 
26
29
  For some sample code, see <b>examples/synga-useage.rb</b> and <b>examples/sample-rakefile</b>.
27
30
 
@@ -35,3 +38,6 @@ Synqa is licensed under the GNU General Public License version 3.
35
38
  containing whitespace or non-ASCII characters. Typically this doesn't matter for
36
39
  many static websites, but it will reduce the tool's usefulness as a general purpose
37
40
  backup tool.
41
+
42
+ * Currently *Synqa* does not provide authentication options, on the assumption that you
43
+ will use Pageant (which automagically provides "presented" keys for specified user/host combinations).
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.0
1
+ 0.2.0
@@ -1,4 +1,4 @@
1
- require 'based-directory'
1
+ require 'based'
2
2
  require 'synqa'
3
3
  require 'digest/sha2'
4
4
 
@@ -19,7 +19,7 @@ task :default => [:uploaddry] do |t|
19
19
  end
20
20
 
21
21
  REMOTE_HOST = SshContentHost.new("yourusername@yourhostname.example.com",
22
- Sha256Command.new(), "plink", "pscp")
22
+ Sha256Command.new())
23
23
 
24
24
  REMOTE_SITE = RemoteContentLocation.new(REMOTE_HOST,
25
25
  "/home/username/public",
@@ -29,22 +29,27 @@ LOCAL_SITE = LocalContentLocation.new(UPLOAD_DIR,
29
29
  Digest::SHA256,
30
30
  File.join(SYNQA_DIR, "localContent.txt"))
31
31
 
32
+ # Ensure that directory for cached content files exists
32
33
  task :init do |t|
33
34
  ensureDirectoryExists(SYNQA_DIR)
34
35
  end
35
36
 
37
+ # Delete the cached content files
36
38
  task :clean => [:init] do |t|
37
39
  SyncOperation.new(LOCAL_SITE, REMOTE_SITE).clearCachedContentFiles()
38
40
  end
39
41
 
42
+ # List the files and directories in the remote directory
40
43
  task :list do |t|
41
44
  REMOTE_SITE.listFiles()
42
45
  end
43
-
46
+
47
+ # Dry run for uploading (i.e. syncing) files to remote site
44
48
  task :uploaddry => [:init] do |t|
45
49
  SyncOperation.new(LOCAL_SITE, REMOTE_SITE).doSync(:dryRun => true)
46
50
  end
47
51
 
52
+ # Upload (i.e. sync) files to remote site
48
53
  task :upload => [:init] do |t|
49
54
  SyncOperation.new(LOCAL_SITE, REMOTE_SITE).doSync()
50
55
  end
@@ -1,7 +1,7 @@
1
1
  # Sample code for synqa useage -- you will need to fill in your own details
2
2
 
3
3
  require 'synqa.rb'
4
- require 'based-directory'
4
+ require 'based'
5
5
  require 'digest/sha2'
6
6
 
7
7
  STDOUT.sync = true
@@ -10,12 +10,18 @@ include Synqa
10
10
  sha256Sum = Sha256SumCommand.new() # sha256sum (with 2 characters between hash and file name)
11
11
  sha256 = Sha256Command.new() # sha256 -r (with 1 space between hash and file name)
12
12
 
13
+ # Default is use Ruby net-ssh & net-scp gems, the following line defines external SSH/SCP applications
14
+ # plinkAndPscp = ExternalSshScp.new("plink", "pscp")
15
+
13
16
  localContentLocation = LocalContentLocation.new(Based::BaseDirectory.new("c:/dev/src/project"),
14
17
  Digest::SHA256,
15
18
  "c:/temp/synqa/local.project.content.cache.txt")
19
+ # Default uses Ruby net-ssh & net-scp gems
20
+ remoteHost = SshContentHost.new("username@host.example.com", sha256)
21
+
22
+ # Alternative uses plink & pscp
23
+ #remoteHost = SshContentHost.new("username@host.example.com", sha256, ExternalSshScp)
16
24
 
17
- remoteHost = SshContentHost.new("username@host.example.com",
18
- sha256, "plink", "pscp")
19
25
 
20
26
  # Note: the specification of plink & pscp assumes that keys are managed with Pageant, and therefore
21
27
  # do not need to be specified on the command line.
File without changes
data/lib/synqa.rb CHANGED
@@ -1,4 +1,6 @@
1
1
  require 'time'
2
+ require 'net/ssh'
3
+ require 'net/scp'
2
4
 
3
5
  module Synqa
4
6
 
@@ -13,6 +15,12 @@ module Synqa
13
15
  end
14
16
  end
15
17
 
18
+ # Return the enumerated lines of the command's output
19
+ def getCommandOutput(command)
20
+ puts "#{command.inspect} ..."
21
+ return IO.popen(command)
22
+ end
23
+
16
24
  # Check if the last executed process exited with status 0, if not, raise an exception
17
25
  def checkProcessStatus(description)
18
26
  processStatus = $?
@@ -161,12 +169,6 @@ module Synqa
161
169
  return fileHashes
162
170
  end
163
171
 
164
- # Return the enumerated lines of the command's output
165
- def getCommandOutput(command)
166
- puts "#{command.inspect} ..."
167
- return IO.popen(command)
168
- end
169
-
170
172
  # Construct the ContentTree for the given base directory
171
173
  def getContentTree(baseDir)
172
174
  contentTree = ContentTree.new()
@@ -181,64 +183,167 @@ module Synqa
181
183
  end
182
184
  end
183
185
 
184
- # Representation of a remote system accessible via SSH
185
- class SshContentHost<DirContentHost
186
+ # Execute a (local) command, or, if dryRun, just pretend to execute it.
187
+ # Raise an exception if the process exit status is not 0.
188
+ def executeCommand(command, dryRun)
189
+ puts "EXECUTE: #{command}"
190
+ if not dryRun
191
+ system(command)
192
+ checkProcessStatus(command)
193
+ end
194
+ end
195
+
196
+ # Base SSH/SCP implementation
197
+ class BaseSshScp
186
198
 
199
+ # delete remote directory (if dryRun is false) using "rm -r"
200
+ def deleteDirectory(userAtHost, dirPath, dryRun)
201
+ ssh(userAtHost, "rm -r #{dirPath}", dryRun)
202
+ end
203
+
204
+ # delete remote file (if dryRun is false) using "rm"
205
+ def deleteFile(userAtHost, filePath, dryRun)
206
+ ssh(userAtHost, "rm #{filePath}", dryRun)
207
+ end
208
+ end
209
+
210
+ # SSH/SCP using Ruby Net::SSH & Net::SCP
211
+ class InternalSshScp<BaseSshScp
212
+
213
+ # execute command on remote host (if dryRun is false), yielding lines of output
214
+ def ssh(userAtHost, commandString, dryRun)
215
+ user, host = userAtHost.split("@")
216
+ description = "SSH #{user}@#{host}: executing #{commandString}"
217
+ puts description
218
+ if not dryRun
219
+ Net::SSH.start(host, user) do |ssh|
220
+ outputText = ssh.exec!(commandString)
221
+ if outputText != nil then
222
+ for line in outputText.split("\n") do
223
+ yield line
224
+ end
225
+ end
226
+ end
227
+ end
228
+ end
229
+
230
+ # copy a local directory to a remote directory (if dryRun is false)
231
+ def copyLocalToRemoteDirectory(userAtHost, sourcePath, destinationPath, dryRun)
232
+ user, host = userAtHost.split("@")
233
+ description = "SCP: copy directory #{sourcePath} to #{user}@#{host}:#{destinationPath}"
234
+ puts description
235
+ if not dryRun
236
+ Net::SCP.upload!(host, user, sourcePath, destinationPath, :recursive => true)
237
+ end
238
+ end
239
+
240
+ # copy a local file to a remote directory (if dryRun is false)
241
+ def copyLocalFileToRemoteDirectory(userAtHost, sourcePath, destinationPath, dryRun)
242
+ user, host = userAtHost.split("@")
243
+ description = "SCP: copy file #{sourcePath} to #{user}@#{host}:#{destinationPath}"
244
+ puts description
245
+ if not dryRun
246
+ Net::SCP.upload!(host, user, sourcePath, destinationPath)
247
+ end
248
+ end
249
+
250
+ end
251
+
252
+ # SSH/SCP using external commands, such as "plink" and "pscp"
253
+ class ExternalSshScp<BaseSshScp
187
254
  # The SSH client, e.g. ["ssh"] or ["plink","-pw","mysecretpassword"] (i.e. command + args as an array)
188
255
  attr_reader :shell
189
256
 
190
257
  # The SCP client, e.g. ["scp"] or ["pscp","-pw","mysecretpassword"] (i.e. command + args as an array)
191
258
  attr_reader :scpProgram
192
-
193
- # The remote host, e.g. "username@host.example.com"
194
- attr_reader :host
195
-
259
+
196
260
  # The SCP command as a string
197
261
  attr_reader :scpCommandString
198
-
199
- def initialize(host, hashCommand, shell, scpProgram)
200
- super(hashCommand)
201
- @host = host
262
+
263
+ def initialize(shell, scpProgram)
202
264
  @shell = shell.is_a?(String) ? [shell] : shell
203
265
  @scpProgram = scpProgram.is_a?(String) ? [scpProgram] : scpProgram
204
266
  @scpCommandString = @scpProgram.join(" ")
205
267
  end
206
268
 
207
- # Return readable description of base directory on remote system
208
- def locationDescriptor(baseDir)
209
- baseDir = normalisedDir(baseDir)
210
- return "#{host}:#{baseDir} (connect = #{shell}/#{scpProgram}, hashCommand = #{hashCommand})"
211
- end
212
-
213
- # execute an SSH command on the remote system, yielding lines of output
214
- # (or don't actually execute, if dryRun is true)
215
- def executeRemoteCommand(commandString, dryRun = false)
216
- puts "SSH #{host} (#{shell.join(" ")}): executing #{commandString}"
269
+ # execute command on remote host (if dryRun is false), yielding lines of output
270
+ def ssh(userAtHost, commandString, dryRun)
271
+ puts "SSH #{userAtHost} (#{shell.join(" ")}): executing #{commandString}"
217
272
  if not dryRun
218
- output = getCommandOutput(shell + [host, commandString])
273
+ output = getCommandOutput(shell + [userAtHost, commandString])
219
274
  while (line = output.gets)
220
275
  yield line.chomp
221
276
  end
222
277
  output.close()
223
- checkProcessStatus("SSH #{host} #{commandString}")
278
+ checkProcessStatus("SSH #{userAtHost} #{commandString}")
224
279
  end
225
280
  end
226
281
 
227
- # execute an SSH command on the remote system, displaying output to stdout,
228
- # (or don't actually execute, if dryRun is true)
282
+ # copy a local directory to a remote directory (if dryRun is false)
283
+ def copyLocalToRemoteDirectory(userAtHost, sourcePath, destinationPath, dryRun)
284
+ executeCommand("#{@scpCommandString} -r #{sourcePath} #{userAtHost}:#{destinationPath}", dryRun)
285
+ end
286
+
287
+ # copy a local file to a remote directory (if dryRun is false)
288
+ def copyLocalFileToRemoteDirectory(userAtHost, sourcePath, destinationPath, dryRun)
289
+ executeCommand("#{@scpCommandString} #{sourcePath} #{userAtHost}:#{destinationPath}", dryRun)
290
+ end
291
+
292
+ end
293
+
294
+ # Representation of a remote system accessible via SSH
295
+ class SshContentHost<DirContentHost
296
+
297
+ # The remote userAtHost, e.g. "username@host.example.com"
298
+ attr_reader :userAtHost, :sshAndScp
299
+
300
+ def initialize(userAtHost, hashCommand, sshAndScp = nil)
301
+ super(hashCommand)
302
+ @sshAndScp = sshAndScp != nil ? sshAndScp : InternalSshScp.new()
303
+ @userAtHost = userAtHost
304
+ end
305
+
306
+ # Return readable description of base directory on remote system
307
+ def locationDescriptor(baseDir)
308
+ baseDir = normalisedDir(baseDir)
309
+ return "#{userAtHost}:#{baseDir} (connect = #{shell}/#{scpProgram}, hashCommand = #{hashCommand})"
310
+ end
311
+
312
+ # execute an SSH command on the remote system, yielding lines of output
313
+ # (or don't actually execute, if dryRun is false)
229
314
  def ssh(commandString, dryRun = false)
230
- executeRemoteCommand(commandString, dryRun) do |line|
231
- puts line
315
+ sshAndScp.ssh(userAtHost, commandString, dryRun) do |line|
316
+ yield line
232
317
  end
233
318
  end
234
319
 
320
+ # delete a remote directory, if dryRun is false
321
+ def deleteDirectory(dirPath, dryRun)
322
+ sshAndScp.deleteDirectory(userAtHost, dirPath, dryRun)
323
+ end
324
+
325
+ # delete a remote file, if dryRun is false
326
+ def deleteFile(filePath, dryRun)
327
+ sshAndScp.deleteFile(userAtHost, filePath, dryRun)
328
+ end
329
+
330
+ # copy a local directory to a remote directory, if dryRun is false
331
+ def copyLocalToRemoteDirectory(sourcePath, destinationPath, dryRun)
332
+ sshAndScp.copyLocalToRemoteDirectory(userAtHost, sourcePath, destinationPath, dryRun)
333
+ end
334
+
335
+ # copy a local file to a remote directory, if dryRun is false
336
+ def copyLocalFileToRemoteDirectory(sourcePath, destinationPath, dryRun)
337
+ sshAndScp.copyLocalFileToRemoteDirectory(userAtHost, sourcePath, destinationPath, dryRun)
338
+ end
339
+
235
340
  # Return a list of all subdirectories of the base directory (as paths relative to the base directory)
236
341
  def listDirectories(baseDir)
237
342
  baseDir = normalisedDir(baseDir)
238
343
  puts "Listing directories ..."
239
344
  directories = []
240
345
  baseDirLen = baseDir.length
241
- executeRemoteCommand(findDirectoriesCommand(baseDir).join(" ")) do |line|
346
+ ssh(findDirectoriesCommand(baseDir).join(" ")) do |line|
242
347
  puts " #{line}"
243
348
  if line.start_with?(baseDir)
244
349
  directories << line[baseDirLen..-1]
@@ -254,7 +359,7 @@ module Synqa
254
359
  def listFileHashLines(baseDir)
255
360
  baseDir = normalisedDir(baseDir)
256
361
  remoteFileHashLinesCommand = findFilesCommand(baseDir) + ["|", "xargs", "-r"] + @hashCommand.command
257
- executeRemoteCommand(remoteFileHashLinesCommand.join(" ")) do |line|
362
+ ssh(remoteFileHashLinesCommand.join(" ")) do |line|
258
363
  puts " #{line}"
259
364
  yield line
260
365
  end
@@ -263,15 +368,11 @@ module Synqa
263
368
  # List all files within the base directory to stdout
264
369
  def listFiles(baseDir)
265
370
  baseDir = normalisedDir(baseDir)
266
- executeRemoteCommand(findFilesCommand(baseDir).join(" ")) do |line|
371
+ ssh(findFilesCommand(baseDir).join(" ")) do |line|
267
372
  puts " #{line}"
268
373
  end
269
374
  end
270
375
 
271
- # Get the remote path of the directory or file on the host, in the format required by SCP
272
- def getScpPath(path)
273
- return host + ":" + path
274
- end
275
376
  end
276
377
 
277
378
  # An object representing the content of a file within a ContentTree.
@@ -315,8 +416,8 @@ module Synqa
315
416
  return "#{name} (#{hash})"
316
417
  end
317
418
 
318
- # The full (relative) name of this file in the content tree
319
- def fullPath
419
+ # The relative name of this file in the content tree (relative to the base dir)
420
+ def relativePath
320
421
  return (parentPathElements + [name]).join("/")
321
422
  end
322
423
  end
@@ -376,8 +477,8 @@ module Synqa
376
477
  @toBeDeleted = true
377
478
  end
378
479
 
379
- # the full path of the directory that this content tree represents (relative to the base directory)
380
- def fullPath
480
+ # the path of the directory that this content tree represents, relative to the base directory
481
+ def relativePath
381
482
  return @pathElements.join("/")
382
483
  end
383
484
 
@@ -446,7 +547,7 @@ module Synqa
446
547
  puts "#{currentIndent}#{name}"
447
548
  end
448
549
  if copyDestination != nil
449
- puts "#{currentIndent} [COPY to #{copyDestination.fullPath}]"
550
+ puts "#{currentIndent} [COPY to #{copyDestination.relativePath}]"
450
551
  end
451
552
  if toBeDeleted
452
553
  puts "#{currentIndent} [DELETE]"
@@ -458,7 +559,7 @@ module Synqa
458
559
  for file in files
459
560
  puts "#{nextIndent}#{file.name} - #{file.hash}"
460
561
  if file.copyDestination != nil
461
- puts "#{nextIndent} [COPY to #{file.copyDestination.fullPath}]"
562
+ puts "#{nextIndent} [COPY to #{file.copyDestination.relativePath}]"
462
563
  end
463
564
  if file.toBeDeleted
464
565
  puts "#{nextIndent} [DELETE]"
@@ -677,11 +778,6 @@ module Synqa
677
778
  @hashClass = hashClass
678
779
  end
679
780
 
680
- # get the path as required for an SCP command
681
- def getScpPath(relativePath)
682
- return getFullPath(relativePath)
683
- end
684
-
685
781
  # get the full path of a relative path (i.e. of a file/directory within the base directory)
686
782
  def getFullPath(relativePath)
687
783
  return @baseDirectory.fullPath + relativePath
@@ -722,25 +818,25 @@ module Synqa
722
818
  # A directory of files on a remote system
723
819
  class RemoteContentLocation<ContentLocation
724
820
  # the remote username@host value
725
- attr_reader :host
821
+ attr_reader :userAtHost
726
822
 
727
823
  # the base directory on the remote system
728
824
  attr_reader :baseDir
729
825
 
730
- def initialize(host, baseDir, cachedContentFile = nil)
826
+ def initialize(userAtHost, baseDir, cachedContentFile = nil)
731
827
  super(cachedContentFile)
732
- @host = host
828
+ @userAtHost = userAtHost
733
829
  @baseDir = normalisedDir(baseDir)
734
830
  end
735
831
 
736
- # list files within the base directory on the remote host
832
+ # list files within the base directory on the remote userAtHost
737
833
  def listFiles()
738
- host.listFiles(baseDir)
834
+ userAtHost.listFiles(baseDir)
739
835
  end
740
836
 
741
- # the command string required to execute SCP (e.g. "scp" or "pscp", possibly with extra args)
742
- def scpCommandString
743
- return host.scpCommandString
837
+ # object required to execute SCP (e.g. "scp" or "pscp", possibly with extra args)
838
+ def sshAndScp
839
+ return userAtHost.sshAndScp
744
840
  end
745
841
 
746
842
  # get the full path of a relative path
@@ -748,28 +844,23 @@ module Synqa
748
844
  return baseDir + relativePath
749
845
  end
750
846
 
751
- # get the full path of a file as required in an SCP command (i.e. with username@host prepended)
752
- def getScpPath(relativePath)
753
- return host.getScpPath(getFullPath(relativePath))
754
- end
755
-
756
847
  # execute an SSH command on the remote host (or just pretend, if dryRun is true)
757
848
  def ssh(commandString, dryRun = false)
758
- host.ssh(commandString, dryRun)
849
+ userAtHost.sshAndScp.ssh(commandString, dryRun)
759
850
  end
760
851
 
761
852
  # list all sub-directories of the base directory on the remote host
762
853
  def listDirectories
763
- return host.listDirectories(baseDir)
854
+ return userAtHost.listDirectories(baseDir)
764
855
  end
765
856
 
766
857
  # list all the file hashes of the files within the base directory
767
858
  def listFileHashes
768
- return host.listFileHashes(baseDir)
859
+ return userAtHost.listFileHashes(baseDir)
769
860
  end
770
861
 
771
862
  def to_s
772
- return host.locationDescriptor(baseDir)
863
+ return userAtHost.locationDescriptor(baseDir)
773
864
  end
774
865
 
775
866
  # Get the content tree, from the cached content file if it exists,
@@ -780,7 +871,7 @@ module Synqa
780
871
  if cachedContentFile and File.exists?(cachedContentFile)
781
872
  return ContentTree.readFromFile(cachedContentFile)
782
873
  else
783
- contentTree = host.getContentTree(baseDir)
874
+ contentTree = userAtHost.getContentTree(baseDir)
784
875
  contentTree.sort!
785
876
  if cachedContentFile != nil
786
877
  contentTree.writeToFile(cachedContentFile)
@@ -845,7 +936,7 @@ module Synqa
845
936
  end
846
937
  doAllCopyOperations(dryRun)
847
938
  doAllDeleteOperations(dryRun)
848
- if (@destinationLocation.cachedContentFile and @sourceLocation.cachedContentFile and
939
+ if (not dryRun and @destinationLocation.cachedContentFile and @sourceLocation.cachedContentFile and
849
940
  File.exists?(@sourceLocation.cachedContentFile))
850
941
  FileUtils::Verbose.cp(@sourceLocation.cachedContentFile, @destinationLocation.cachedContentFile)
851
942
  end
@@ -876,18 +967,18 @@ module Synqa
876
967
  def doCopyOperations(sourceContent, destinationContent, dryRun)
877
968
  for dir in sourceContent.dirs
878
969
  if dir.copyDestination != nil
879
- sourcePath = sourceLocation.getScpPath(dir.fullPath)
880
- destinationPath = destinationLocation.getScpPath(dir.copyDestination.fullPath)
881
- executeCommand("#{destinationLocation.scpCommandString} -r #{sourcePath} #{destinationPath}", dryRun)
970
+ sourcePath = sourceLocation.getFullPath(dir.relativePath)
971
+ destinationPath = destinationLocation.getFullPath(dir.copyDestination.relativePath)
972
+ destinationLocation.userAtHost.copyLocalToRemoteDirectory(sourcePath, destinationPath, dryRun)
882
973
  else
883
974
  doCopyOperations(dir, destinationContent.getDir(dir.name), dryRun)
884
975
  end
885
976
  end
886
977
  for file in sourceContent.files
887
978
  if file.copyDestination != nil
888
- sourcePath = sourceLocation.getScpPath(file.fullPath)
889
- destinationPath = destinationLocation.getScpPath(file.copyDestination.fullPath)
890
- executeCommand("#{destinationLocation.scpCommandString} #{sourcePath} #{destinationPath}", dryRun)
979
+ sourcePath = sourceLocation.getFullPath(file.relativePath)
980
+ destinationPath = destinationLocation.getFullPath(file.copyDestination.relativePath)
981
+ destinationLocation.userAtHost.copyLocalFileToRemoteDirectory(sourcePath, destinationPath, dryRun)
891
982
  end
892
983
  end
893
984
  end
@@ -897,16 +988,16 @@ module Synqa
897
988
  def doDeleteOperations(destinationContent, dryRun)
898
989
  for dir in destinationContent.dirs
899
990
  if dir.toBeDeleted
900
- dirPath = destinationLocation.getFullPath(dir.fullPath)
901
- destinationLocation.ssh("rm -r #{dirPath}", dryRun)
991
+ dirPath = destinationLocation.getFullPath(dir.relativePath)
992
+ destinationLocation.userAtHost.deleteDirectory(dirPath, dryRun)
902
993
  else
903
994
  doDeleteOperations(dir, dryRun)
904
995
  end
905
996
  end
906
997
  for file in destinationContent.files
907
998
  if file.toBeDeleted
908
- filePath = destinationLocation.getFullPath(file.fullPath)
909
- destinationLocation.ssh("rm #{filePath}", dryRun)
999
+ filePath = destinationLocation.getFullPath(file.relativePath)
1000
+ destinationLocation.userAtHost.deleteFile(filePath, dryRun)
910
1001
  end
911
1002
  end
912
1003
  end
@@ -1,6 +1,6 @@
1
1
  require 'helper'
2
2
 
3
- require 'based-directory'
3
+ require 'based'
4
4
 
5
5
  module Based
6
6
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: synqa
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,12 +9,34 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2011-03-19 00:00:00.000000000 +13:00
12
+ date: 2011-04-19 00:00:00.000000000 +12:00
13
13
  default_executable:
14
14
  dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: net-ssh
17
+ requirement: &25189860 !ruby/object:Gem::Requirement
18
+ none: false
19
+ requirements:
20
+ - - ! '>='
21
+ - !ruby/object:Gem::Version
22
+ version: '2.0'
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: *25189860
26
+ - !ruby/object:Gem::Dependency
27
+ name: net-scp
28
+ requirement: &25189176 !ruby/object:Gem::Requirement
29
+ none: false
30
+ requirements:
31
+ - - ! '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '1.0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: *25189176
15
37
  - !ruby/object:Gem::Dependency
16
38
  name: shoulda
17
- requirement: &24879420 !ruby/object:Gem::Requirement
39
+ requirement: &25188444 !ruby/object:Gem::Requirement
18
40
  none: false
19
41
  requirements:
20
42
  - - ! '>='
@@ -22,10 +44,10 @@ dependencies:
22
44
  version: '0'
23
45
  type: :development
24
46
  prerelease: false
25
- version_requirements: *24879420
47
+ version_requirements: *25188444
26
48
  - !ruby/object:Gem::Dependency
27
49
  name: bundler
28
- requirement: &24878820 !ruby/object:Gem::Requirement
50
+ requirement: &25187796 !ruby/object:Gem::Requirement
29
51
  none: false
30
52
  requirements:
31
53
  - - ~>
@@ -33,10 +55,10 @@ dependencies:
33
55
  version: 1.0.0
34
56
  type: :development
35
57
  prerelease: false
36
- version_requirements: *24878820
58
+ version_requirements: *25187796
37
59
  - !ruby/object:Gem::Dependency
38
60
  name: jeweler
39
- requirement: &24878220 !ruby/object:Gem::Requirement
61
+ requirement: &25180356 !ruby/object:Gem::Requirement
40
62
  none: false
41
63
  requirements:
42
64
  - - ~>
@@ -44,10 +66,10 @@ dependencies:
44
66
  version: 1.5.2
45
67
  type: :development
46
68
  prerelease: false
47
- version_requirements: *24878220
69
+ version_requirements: *25180356
48
70
  - !ruby/object:Gem::Dependency
49
71
  name: rcov
50
- requirement: &24877560 !ruby/object:Gem::Requirement
72
+ requirement: &25179864 !ruby/object:Gem::Requirement
51
73
  none: false
52
74
  requirements:
53
75
  - - ! '>='
@@ -55,7 +77,7 @@ dependencies:
55
77
  version: '0'
56
78
  type: :development
57
79
  prerelease: false
58
- version_requirements: *24877560
80
+ version_requirements: *25179864
59
81
  description: Sync files from a local directory to a remote directory via SSH/SCP
60
82
  email: http://www.1729.com/email.html
61
83
  executables: []
@@ -74,7 +96,7 @@ files:
74
96
  - _project.el
75
97
  - examples/sample-rakefile
76
98
  - examples/synqa-useage.rb
77
- - lib/based-directory.rb
99
+ - lib/based.rb
78
100
  - lib/synqa.rb
79
101
  - test/data/dir1/dir2/dir4/dir5/file6.text
80
102
  - test/data/dir1/dir2/dir4/file5.text
@@ -83,7 +105,7 @@ files:
83
105
  - test/data/dir1/file1.txt
84
106
  - test/data/dir1/file2.txt
85
107
  - test/helper.rb
86
- - test/test_based_directory.rb
108
+ - test/test_based.rb
87
109
  - test/test_synqa.rb
88
110
  has_rdoc: true
89
111
  homepage: http://www.1729.com/software/synqa/
@@ -101,7 +123,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
101
123
  version: '0'
102
124
  segments:
103
125
  - 0
104
- hash: 537622927
126
+ hash: 874582639
105
127
  required_rubygems_version: !ruby/object:Gem::Requirement
106
128
  none: false
107
129
  requirements:
@@ -117,5 +139,5 @@ summary: Sync files from a local directory to a remote directory via SSH/SCP
117
139
  test_files:
118
140
  - examples/synqa-useage.rb
119
141
  - test/helper.rb
120
- - test/test_based_directory.rb
142
+ - test/test_based.rb
121
143
  - test/test_synqa.rb