odisk 0.2.1 → 0.2.2
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +6 -6
- data/bin/odisk +2 -30
- data/bin/odisk_forget +122 -0
- data/lib/odisk.rb +35 -0
- data/lib/odisk/version.rb +1 -1
- metadata +6 -5
data/README.md
CHANGED
@@ -25,9 +25,9 @@ which utilizes an alternative approach to dealing with multiple threads.
|
|
25
25
|
|
26
26
|
## <a name="release">Release Notes</a>
|
27
27
|
|
28
|
-
### Release 0.2.
|
28
|
+
### Release 0.2.2
|
29
29
|
|
30
|
-
-
|
30
|
+
- Added odisk_forget which removes remote entries causing a file or directory to look like a new file or directory.
|
31
31
|
|
32
32
|
# Plans and Notes
|
33
33
|
|
@@ -40,10 +40,10 @@ files has not been implemented yet and changing ownership or mode only take
|
|
40
40
|
effect if the file is touched as well. Feel free to give it a try and let me
|
41
41
|
know when you run into bugs.
|
42
42
|
|
43
|
-
- Support
|
44
|
-
- specify on command line and create .odisk/
|
43
|
+
- Support ignore of file and directories
|
44
|
+
- specify on command line and create .odisk/ignore file
|
45
45
|
- use ::File.fnmatch(pattern, path, ::File::FNM_DOTMATCH)
|
46
|
-
- pass array of
|
46
|
+
- pass array of ignores to digest creation
|
47
47
|
- loosen up current restriction on any file that begins with .
|
48
48
|
|
49
49
|
- Support file removal
|
@@ -54,7 +54,7 @@ know when you run into bugs.
|
|
54
54
|
|
55
55
|
- Handle changes in mode, owner, and group
|
56
56
|
- Compare to previous digest to detect changes
|
57
|
-
- File modification times are not
|
57
|
+
- File modification times are not changed by mode, owner, or group changes
|
58
58
|
- Note conflicts if modifications are more recent than remote
|
59
59
|
- Use a script to pick change or keep local version
|
60
60
|
|
data/bin/odisk
CHANGED
@@ -67,39 +67,11 @@ if 1 != dirs.size
|
|
67
67
|
end
|
68
68
|
$local_top = ::File.expand_path(dirs[0])
|
69
69
|
|
70
|
-
|
71
|
-
# in that directory. If the directory does not exist then stop the walk. If
|
72
|
-
# not found check the ~/.odisk/remotes.json file for a matching top.
|
73
|
-
top = $local_top
|
74
|
-
if $ruser.nil? || $rhost.nil? || $rtop.nil?
|
75
|
-
while ::File.directory?(::File.join(top, '.odisk'))
|
76
|
-
rfile = ::File.join(top, '.odisk', 'remote')
|
77
|
-
if ::File.file?(rfile)
|
78
|
-
rstr = ::File.read(rfile).strip()
|
79
|
-
#$remote.pass_file = ::File.expand_path($remote.pass_file) unless $remote.pass_file.nil? || $remote.pass_file.empty?
|
80
|
-
orig_pass_file = $remote.pass_file
|
81
|
-
$remote.update(rstr)
|
82
|
-
$remote.pass_file = ::File.expand_path($remote.pass_file) unless $remote.pass_file.nil? || $remote.pass_file.empty?
|
83
|
-
if !$remote.dir.nil? && !$remote.dir.empty? && top != $local_top
|
84
|
-
$remote.dir = $remote.dir + $local_top[top.size..-1]
|
85
|
-
end
|
86
|
-
if $remote.pass_file != orig_pass_file && !::File.file?($remote.pass_file)
|
87
|
-
$remote.pass_file = ::File.join(top, '.odisk', $remote.pass_file)
|
88
|
-
end
|
89
|
-
break
|
90
|
-
end
|
91
|
-
top = ::File.dirname(top)
|
92
|
-
end
|
93
|
-
end
|
94
|
-
|
95
|
-
ODisk.info_from_remotes($local_top, $remote) unless $remote.complete?
|
96
|
-
$remote.user = ENV['USER'] if $remote.user.nil?
|
97
|
-
$remote.pass_file = nil if $plain
|
98
|
-
unless $remote.okay?
|
99
|
-
puts "*** user@host:top_dir not specified on command line, in local .odisk/remote file, or in ~/.odisk/remotes"
|
70
|
+
unless ODisk.gather_remote_info($local_top, $remote)
|
100
71
|
puts opts.help
|
101
72
|
Process.exit!(0)
|
102
73
|
end
|
74
|
+
$remote.pass_file = nil if $plain
|
103
75
|
|
104
76
|
Thread.current[:name] = 'main'
|
105
77
|
::Opee::Env.logger.formatter = proc { |s,t,p,m|
|
data/bin/odisk_forget
ADDED
@@ -0,0 +1,122 @@
|
|
1
|
+
#!/usr/bin/env ruby -wW1
|
2
|
+
# encoding: UTF-8
|
3
|
+
|
4
|
+
while (i = ARGV.index('-I'))
|
5
|
+
x,path = ARGV.slice!(i, 2)
|
6
|
+
$: << path
|
7
|
+
end
|
8
|
+
|
9
|
+
# TBD tmp for testing
|
10
|
+
$: << ::File.join(::File.dirname(__FILE__), "../../oj/lib")
|
11
|
+
$: << ::File.join(::File.dirname(__FILE__), "../../oj/ext")
|
12
|
+
$: << ::File.join(::File.dirname(__FILE__), "../../opee/lib")
|
13
|
+
$: << ::File.join(::File.dirname(__FILE__), "../lib")
|
14
|
+
|
15
|
+
require 'optparse'
|
16
|
+
begin
|
17
|
+
v = $VERBOSE
|
18
|
+
$VERBOSE = false
|
19
|
+
require 'net/ssh'
|
20
|
+
require 'net/sftp'
|
21
|
+
$VERBOSE = v
|
22
|
+
end
|
23
|
+
require 'opee'
|
24
|
+
require 'oj'
|
25
|
+
require 'odisk'
|
26
|
+
|
27
|
+
$verbose = Logger::WARN
|
28
|
+
$dry_run = false
|
29
|
+
$dir = '.'
|
30
|
+
$master = nil
|
31
|
+
$remote = ::ODisk::Remote.new()
|
32
|
+
|
33
|
+
opts = OptionParser.new(%{Usage: odisk_forget [options] <local_directory> <relative_forget_path>
|
34
|
+
|
35
|
+
Will remove data for the file or directory specified on the remote server. The local file or directory
|
36
|
+
will not be removed but the local digest will no longer includes that entry. This make the file or
|
37
|
+
directory look new as far as oDisk is concerned.
|
38
|
+
})
|
39
|
+
opts.on('-s', 'decrease verbosity') { $verbose += 1 unless 5 == $verbose }
|
40
|
+
opts.on('-v', 'increase verbosity') { $verbose -= 1 unless 0 == $verbose }
|
41
|
+
opts.on('-n', 'dry run / no modifications') { $dry_run = true }
|
42
|
+
opts.on('-r', '--remote [user@host:dir:pass_file]',
|
43
|
+
String, 'remote user, host, directory, passphrase file for gpg') { |r|
|
44
|
+
$remote.update(r)
|
45
|
+
}
|
46
|
+
opts.on('-h', '--help', 'Show this display') { puts opts.help; Process.exit!(0) }
|
47
|
+
dirs = opts.parse(ARGV)
|
48
|
+
|
49
|
+
if 2 != dirs.size
|
50
|
+
puts opts.help
|
51
|
+
Process.exit!(0)
|
52
|
+
end
|
53
|
+
$local_top = ::File.expand_path(dirs[0])
|
54
|
+
$forget_me = dirs[1] # relative path from top
|
55
|
+
|
56
|
+
unless ODisk.gather_remote_info($local_top, $remote)
|
57
|
+
puts opts.help
|
58
|
+
Process.exit!(0)
|
59
|
+
end
|
60
|
+
$remote.pass_file = nil if $plain
|
61
|
+
|
62
|
+
Thread.current[:name] = 'main'
|
63
|
+
::Opee::Env.logger.formatter = proc { |s,t,p,m|
|
64
|
+
s = '' if s.nil?
|
65
|
+
"#{s[0]} [#{t.strftime('%Y-%m-%dT%H:%M:%S.%6N')} ##{p}]: #{m}\n"
|
66
|
+
}
|
67
|
+
::Opee::Env.logger.severity = $verbose
|
68
|
+
|
69
|
+
if Logger::INFO >= $verbose
|
70
|
+
if $digests_only
|
71
|
+
::Opee::Env.info(%{
|
72
|
+
Generate Local Digests
|
73
|
+
local directory: #{::File.expand_path($local_top)}
|
74
|
+
})
|
75
|
+
else
|
76
|
+
::Opee::Env.info(%{
|
77
|
+
Forget "#{$forget_me}"
|
78
|
+
remote host: #{$remote.host}
|
79
|
+
remote user: #{$remote.user}
|
80
|
+
remote directory: #{$remote.dir}
|
81
|
+
local: #{::File.expand_path($local_top)}
|
82
|
+
dry run: #{$dry_run}
|
83
|
+
})
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
# If $local_top/.odisk/remote does not exist or is different that what is in $remote, replace it.
|
88
|
+
remote_str = $remote.to_s
|
89
|
+
top_remote_path = ::File.join($local_top, '.odisk', 'remote')
|
90
|
+
if !::File.file?(top_remote_path) || ::File.read(top_remote_path).strip() != remote_str
|
91
|
+
::Opee::Env.info("Writing #{top_remote_path}")
|
92
|
+
unless $dry_run
|
93
|
+
`mkdir -p #{::File.join($local_top, '.odisk')}`
|
94
|
+
::File.open(top_remote_path, 'w') { |f| f.write(remote_str + "\n") }
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
path = ::File.join($local_top, $forget_me)
|
99
|
+
local_digest_path = ::File.join(::File.dirname(path), '.odisk', 'digest.json')
|
100
|
+
forget_name = ::File.basename(path)
|
101
|
+
remote_path = ::File.join($remote.dir, $forget_me)
|
102
|
+
remote_digest_path = ::File.join(::File.dirname(remote_path), '.odisk', 'digest.json')
|
103
|
+
|
104
|
+
# Remove forget_me from local digest.
|
105
|
+
digest = Oj.load_file(local_digest_path, mode: :object)
|
106
|
+
digest.delete(forget_name)
|
107
|
+
Oj.to_file(local_digest_path, digest, indent: 2) unless $dry_run
|
108
|
+
|
109
|
+
# Remove forget_me from remote digest
|
110
|
+
Net::SSH.start($remote.host, $remote.user) do |ssh|
|
111
|
+
ssh.exec!(%{rm -rf "#{remote_path}.gpg"})
|
112
|
+
ssh.exec!(%{rm -rf "#{remote_path}"})
|
113
|
+
end
|
114
|
+
|
115
|
+
# Update the remote digest by removing the forget_me entry.
|
116
|
+
Net::SFTP.start($remote.host, $remote.user) do |ftp|
|
117
|
+
json = ftp.download!(remote_digest_path)
|
118
|
+
digest = Oj.load(json, mode: :object)
|
119
|
+
digest.delete(forget_name)
|
120
|
+
json = Oj.dump(digest, indent: 2)
|
121
|
+
ftp.open!(remote_digest_path, 'w') { |res| ftp.write!(res[:handle], 0, json) }
|
122
|
+
end
|
data/lib/odisk.rb
CHANGED
@@ -1,6 +1,41 @@
|
|
1
1
|
|
2
2
|
module ODisk
|
3
3
|
|
4
|
+
# Walk up the directory tree looking for .odisk directories and a
|
5
|
+
# remote.json in that directory. If the directory does not exist then stop
|
6
|
+
# the walk. If not found check the ~/.odisk/remotes.json file for a matching
|
7
|
+
# top.
|
8
|
+
def self.gather_remote_info(local_dir, remote)
|
9
|
+
top = local_dir
|
10
|
+
if remote.user.nil? || remote.host.nil? || remote.dir.nil?
|
11
|
+
while ::File.directory?(::File.join(top, '.odisk'))
|
12
|
+
rfile = ::File.join(top, '.odisk', 'remote')
|
13
|
+
if ::File.file?(rfile)
|
14
|
+
rstr = ::File.read(rfile).strip()
|
15
|
+
#remote.pass_file = ::File.expand_path(remote.pass_file) unless remote.pass_file.nil? || remote.pass_file.empty?
|
16
|
+
orig_pass_file = remote.pass_file
|
17
|
+
remote.update(rstr)
|
18
|
+
remote.pass_file = ::File.expand_path(remote.pass_file) unless remote.pass_file.nil? || remote.pass_file.empty?
|
19
|
+
if !remote.dir.nil? && !remote.dir.empty? && top != $local_top
|
20
|
+
remote.dir = remote.dir + local_dir[top.size..-1]
|
21
|
+
end
|
22
|
+
if remote.pass_file != orig_pass_file && !::File.file?(remote.pass_file)
|
23
|
+
remote.pass_file = ::File.join(top, '.odisk', remote.pass_file)
|
24
|
+
end
|
25
|
+
break
|
26
|
+
end
|
27
|
+
top = ::File.dirname(top)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
info_from_remotes(local_dir, remote) unless remote.complete?
|
31
|
+
remote.user = ENV['USER'] if remote.user.nil?
|
32
|
+
unless remote.okay?
|
33
|
+
puts "*** user@host:top_dir not specified on command line, in local .odisk/remote file, or in ~/.odisk/remotes"
|
34
|
+
return false
|
35
|
+
end
|
36
|
+
true
|
37
|
+
end
|
38
|
+
|
4
39
|
def self.info_from_remotes(local_dir, remote)
|
5
40
|
orig_pass_file = remote.pass_file
|
6
41
|
local_dir = ::File.expand_path(local_dir)
|
data/lib/odisk/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: odisk
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.2
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-08-
|
12
|
+
date: 2012-08-16 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: opee
|
@@ -79,6 +79,7 @@ description: Remote Encrypted File Synchronization, oDisk
|
|
79
79
|
email: peter@ohler.com
|
80
80
|
executables:
|
81
81
|
- odisk
|
82
|
+
- odisk_forget
|
82
83
|
extensions: []
|
83
84
|
extra_rdoc_files:
|
84
85
|
- README.md
|
@@ -104,8 +105,8 @@ files:
|
|
104
105
|
- lib/odisk.rb
|
105
106
|
- LICENSE
|
106
107
|
- README.md
|
107
|
-
-
|
108
|
-
|
108
|
+
- bin/odisk
|
109
|
+
- bin/odisk_forget
|
109
110
|
homepage: http://www.ohler.com/odisk
|
110
111
|
licenses: []
|
111
112
|
post_install_message:
|
@@ -128,7 +129,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
128
129
|
version: '0'
|
129
130
|
requirements: []
|
130
131
|
rubyforge_project: odisk
|
131
|
-
rubygems_version: 1.8.
|
132
|
+
rubygems_version: 1.8.23
|
132
133
|
signing_key:
|
133
134
|
specification_version: 3
|
134
135
|
summary: Remote Encrypted File Synchronization, oDisk
|