dropbox-folder-sync 0.0.1

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/.gitignore ADDED
@@ -0,0 +1,16 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ InstalledFiles
7
+ _yardoc
8
+ coverage
9
+ doc/
10
+ lib/bundler/man
11
+ pkg
12
+ rdoc
13
+ spec/reports
14
+ test/tmp
15
+ test/version_tmp
16
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,10 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in dropbox-folder-sync.gemspec
4
+ gemspec
5
+ gem "rake"
6
+ gem "thor"
7
+ gem "dropbox-sdk"
8
+ gem "launchy"
9
+ gem "keystorage"
10
+
data/Gemfile.lock ADDED
@@ -0,0 +1,28 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ dropbox-folder-sync (0.0.1)
5
+
6
+ GEM
7
+ remote: https://rubygems.org/
8
+ specs:
9
+ addressable (2.2.7)
10
+ dropbox-sdk (1.3)
11
+ json
12
+ json (1.6.5)
13
+ keystorage (0.4.7)
14
+ launchy (2.0.5)
15
+ addressable (~> 2.2.6)
16
+ rake (0.9.2.2)
17
+ thor (0.14.6)
18
+
19
+ PLATFORMS
20
+ ruby
21
+
22
+ DEPENDENCIES
23
+ dropbox-folder-sync!
24
+ dropbox-sdk
25
+ keystorage
26
+ launchy
27
+ rake
28
+ thor
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2012 Yoshihiro TAKAHARA
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,60 @@
1
+ DropboxFolderSync
2
+ =================
3
+
4
+ Sync Dropbox Folder with Local directory via Dropbox API.
5
+
6
+ ## Installation
7
+
8
+ Add this line to your application's Gemfile:
9
+
10
+ gem 'dropbox-folder-sync'
11
+
12
+ And then execute:
13
+
14
+ $ bundle
15
+
16
+ Or install it yourself as:
17
+
18
+ $ gem install dropbox-folder-sync
19
+
20
+ ## Usage
21
+
22
+ ### Register your own app
23
+
24
+ > https://www.dropbox.com/developers/apps
25
+
26
+ and set env vars.
27
+
28
+ export DROPBOX_FOLDER_SYNC_APP_KEY='app-key-form-dropbox'
29
+ export DROPBOX_FOLDER_SYNC_APP_SECRET='secret key here'
30
+
31
+
32
+ ### Login and link with Dropbox
33
+
34
+ Usage:
35
+ $ dropbox-folder login [NAME]
36
+
37
+ *NAME* is identifer of Dropbox account. Please name your own easy to understand. *default* is used as name if not specified.
38
+
39
+ ### Synchronize
40
+
41
+ Usage:
42
+ $ dropbox-folder sync [NAME:]/PATH/TO/REMOTE /PATH/TO/LOCAL
43
+
44
+ Options:
45
+ -i, [--interval=sec] # sync interval (seconds) , default = 1
46
+
47
+
48
+ ### Logout and unlink from Dropbox
49
+
50
+ Usage:
51
+ $ dropbox-folder logout [NAME]
52
+
53
+
54
+ ## Contributing
55
+
56
+ 1. Fork it
57
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
58
+ 3. Commit your changes (`git commit -am 'Added some feature'`)
59
+ 4. Push to the branch (`git push origin my-new-feature`)
60
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+ # -*- coding: utf-8 -*-
3
+ $:.unshift(File.expand_path(File.join(File.dirname(__FILE__),'..','lib')))
4
+ require 'dropbox-folder-sync'
5
+ DropboxFolderSync::CLI.start
@@ -0,0 +1,17 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path('../lib/dropbox-folder-sync/version', __FILE__)
3
+
4
+ Gem::Specification.new do |gem|
5
+ gem.authors = ["Yoshihiro TAKAHARA"]
6
+ gem.email = ["y.takahara@gmail.com"]
7
+ gem.description = %q{Sync Dropbox folder with local directory}
8
+ gem.summary = %q{Sync Dropbox folder with local directory }
9
+ gem.homepage = ""
10
+
11
+ gem.files = `git ls-files`.split($\)
12
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
13
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
14
+ gem.name = "dropbox-folder-sync"
15
+ gem.require_paths = ["lib"]
16
+ gem.version = DropboxFolderSync::VERSION
17
+ end
@@ -0,0 +1,7 @@
1
+ require 'rubygems'
2
+ require 'bundler/setup'
3
+
4
+ module DropboxFolderSync
5
+ autoload :VERSION, "dropbox-folder-sync/version"
6
+ autoload :CLI, "dropbox-folder-sync/cli"
7
+ end
@@ -0,0 +1,189 @@
1
+ #!/usr/bin/env ruby
2
+ # -*- coding: utf-8 -*-
3
+ # $:.unshift(File.expand_path(File.join(File.dirname(__FILE__),'..')))
4
+ require 'dropbox_sdk'
5
+ require 'launchy'
6
+ require 'keystorage'
7
+
8
+ class DropboxFolderSync::App
9
+ APP_KEY = ENV['DROPBOX_FOLDER_SYNC_APP_KEY']
10
+ APP_SECRET = ENV['DROPBOX_FOLDER_SYNC_APP_SECRET']
11
+
12
+ def initialize
13
+ unless (APP_KEY and APP_SECRET)
14
+ raise "set env vars 'DROPBOX_FOLDER_SYNC_APP_KEY' and 'DROPBOX_FOLDER_SYNC_APP_SECRET'"
15
+ end
16
+ @session = DropboxSession.new(APP_KEY, APP_SECRET)
17
+ end
18
+
19
+ def login name
20
+ key = Keystorage.get("DROPBOX_APP_"+APP_KEY+"_USER_KEY",name)
21
+ secret = Keystorage.get("DROPBOX_APP_"+APP_KEY+"_USER_SECRET",name)
22
+ if key and secret
23
+ @session.set_access_token(key,secret)
24
+ @session.get_access_token rescue {}
25
+ return true if @session.authorized?
26
+ end
27
+
28
+ @session.get_request_token
29
+ authorize_url = @session.get_authorize_url
30
+ puts "Login: [#{name}] ---> #{authorize_url}"
31
+ Launchy.open authorize_url
32
+ while 1
33
+ @session.get_access_token rescue {}
34
+ break if @session.authorized?
35
+ sleep 1
36
+ end
37
+ Keystorage.set("DROPBOX_APP_"+APP_KEY+"_USER_KEY",name,@session.access_token.key.to_s)
38
+ Keystorage.set("DROPBOX_APP_"+APP_KEY+"_USER_SECRET",name,@session.access_token.secret.to_s)
39
+ true
40
+ end
41
+
42
+ def logout name
43
+ Keystorage.delete("DROPBOX_APP_"+APP_KEY+"_USER_KEY",name)
44
+ Keystorage.delete("DROPBOX_APP_"+APP_KEY+"_USER_SECRET",name)
45
+ true
46
+ end
47
+
48
+ def log(message)
49
+ puts message
50
+ end
51
+
52
+ def local_file_meta(path)
53
+ { :path => path,
54
+ :modified => File.mtime(path),
55
+ :id_dir => File.directory?(path)}
56
+ end
57
+
58
+ def remote_path local
59
+ @remote_root+local[@local_root.length..-1]
60
+ end
61
+
62
+ def local_path remote
63
+ @local_root+remote[@remote_root.length..-1]
64
+ end
65
+
66
+ def remote_delta cur
67
+ delta = @client.delta(cur)
68
+ cur = delta["cursor"]
69
+
70
+ if delta["reset"] == "true"
71
+ @local_files = {}
72
+ Dir::glob(@local_root + "/**/*").each { |path|
73
+ @local_files[path] = local_file_meta(path)
74
+ }
75
+ end
76
+
77
+ delta["entries"].each { |path,meta|
78
+ local = local_path(path)
79
+ if path == @remote_root or /^#{@remote_root}\// =~ path
80
+ unless meta
81
+ if File.exists?(local)
82
+ log "remove #{local}"
83
+ FileUtils.remove_entry(local)
84
+ @local_files.reject! { |k,v| k == local }
85
+ if File.directory?(local)
86
+ @local_files.reject! { |k,v| /^#{local}\/.*/ =~ k }
87
+ end
88
+ end
89
+ next
90
+ end
91
+
92
+ if meta["is_dir"] #dir
93
+ log "----> #{local}"
94
+ FileUtils.mkdir_p local unless File.exists?(local)
95
+ else #file
96
+ out = @client.get_file(path)
97
+ open(local, 'w'){|f| f.puts out }
98
+ log "----> #{local}"
99
+ end
100
+ @local_files[local] = local_file_meta(local)
101
+ end
102
+ } # delta
103
+ cur
104
+ end
105
+
106
+ def check_local_modified
107
+ # check local modified
108
+ Dir::glob(@local_root + "/**/*").each { |path|
109
+ remote = remote_path(path)
110
+ # new file
111
+ unless @local_files.include?(path)
112
+ @local_files[path] = local_file_meta(path)
113
+ log "<---- #{path}"
114
+ if File.file?(path)
115
+ @client.put_file(remote, open(path))
116
+ elsif File.directory?(path)
117
+ @client.file_create_folder(remote)
118
+ end
119
+ next
120
+ end
121
+
122
+ # modified
123
+ if File.file?(path) and File.mtime(path) > @local_files[path][:modified]
124
+ @local_files[path] = local_file_meta(path)
125
+ @client.put_file(remote, open(path))
126
+ end
127
+ }
128
+ end
129
+
130
+ def check_local_removed
131
+ # check removed
132
+ @local_files.each { |path,v|
133
+ unless File.exists?(path)
134
+ log "remote delete #{path}"
135
+ @local_files.reject! { |k,v| k == path }
136
+ @client.file_delete(remote_path(path))
137
+ end
138
+ }
139
+ end
140
+
141
+ def sync(remote,local,options)
142
+ name,@remote_root = parse_remote(remote)
143
+ @local_root = path_normalize(File.expand_path(local))
144
+ login(name) unless @session.authorized?
145
+ @client = DropboxClient.new(@session, :dropbox)
146
+ log "#{@remote_root} <---> #{@local_root}"
147
+ @local_files = {}
148
+ cur = nil
149
+ while true
150
+ cur = remote_delta(cur)
151
+ check_local_modified
152
+ check_local_removed
153
+ sleep options[:interval]
154
+ end
155
+ end
156
+
157
+ def path_normalize path
158
+ path = "/" + path if path[0,1] != "/"
159
+ path = path[0,path.length - 1] if path[-1,1] == "/"
160
+ path
161
+ end
162
+
163
+ def parse_remote remote
164
+ name = "default"
165
+ if /^([^\/]+):(.*)/ =~ remote
166
+ name = $1
167
+ remote = $2
168
+ end
169
+ [name,path_normalize(remote)]
170
+ end
171
+
172
+ class << self
173
+ def sync remote,local,options
174
+ new.sync(remote,local,options)
175
+ end
176
+ def login name
177
+ new.login(name)
178
+ end
179
+ def logout name
180
+ new.logout(name)
181
+ end
182
+ end
183
+
184
+ end
185
+
186
+ if $0 == __FILE__
187
+
188
+ end
189
+
@@ -0,0 +1,28 @@
1
+ #!/usr/bin/env ruby
2
+ # -*- coding: utf-8 -*-
3
+ # $:.unshift(File.expand_path(File.join(File.dirname(__FILE__),'..')))
4
+ require 'thor'
5
+ require 'dropbox-folder-sync/app'
6
+ class DropboxFolderSync::CLI < Thor
7
+
8
+ desc 'login [NAME]', "Login and Link with Dropbox account."
9
+ def login name="default"
10
+ DropboxFolderSync::App.login(name)
11
+ end
12
+
13
+ desc 'logout [NAME]', "Logout and unink from Dropbox account."
14
+ def logout name="default"
15
+ DropboxFolderSync::App.logout(name)
16
+ end
17
+
18
+ desc 'sync [NAME:]/PATH/TO/DROPBOX /PATH/TO/REMOTE', "Sync local directory with Dropbox"
19
+ method_option :interval, :type => :numeric, :aliases => "-i", :desc => "Sync interval (sec)", :default => 1
20
+ def sync remote,local
21
+ DropboxFolderSync::App.sync(remote,local,options)
22
+ end
23
+ end
24
+
25
+ if $0 == __FILE__
26
+
27
+ end
28
+
@@ -0,0 +1,3 @@
1
+ module DropboxFolderSync
2
+ VERSION = "0.0.1"
3
+ end
metadata ADDED
@@ -0,0 +1,77 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: dropbox-folder-sync
3
+ version: !ruby/object:Gem::Version
4
+ hash: 29
5
+ prerelease:
6
+ segments:
7
+ - 0
8
+ - 0
9
+ - 1
10
+ version: 0.0.1
11
+ platform: ruby
12
+ authors:
13
+ - Yoshihiro TAKAHARA
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2012-04-01 00:00:00 Z
19
+ dependencies: []
20
+
21
+ description: Sync Dropbox folder with local directory
22
+ email:
23
+ - y.takahara@gmail.com
24
+ executables:
25
+ - dropbox-folder
26
+ extensions: []
27
+
28
+ extra_rdoc_files: []
29
+
30
+ files:
31
+ - .gitignore
32
+ - Gemfile
33
+ - Gemfile.lock
34
+ - LICENSE
35
+ - README.md
36
+ - Rakefile
37
+ - bin/dropbox-folder
38
+ - dropbox-folder-sync.gemspec
39
+ - lib/dropbox-folder-sync.rb
40
+ - lib/dropbox-folder-sync/app.rb
41
+ - lib/dropbox-folder-sync/cli.rb
42
+ - lib/dropbox-folder-sync/version.rb
43
+ homepage: ""
44
+ licenses: []
45
+
46
+ post_install_message:
47
+ rdoc_options: []
48
+
49
+ require_paths:
50
+ - lib
51
+ required_ruby_version: !ruby/object:Gem::Requirement
52
+ none: false
53
+ requirements:
54
+ - - ">="
55
+ - !ruby/object:Gem::Version
56
+ hash: 3
57
+ segments:
58
+ - 0
59
+ version: "0"
60
+ required_rubygems_version: !ruby/object:Gem::Requirement
61
+ none: false
62
+ requirements:
63
+ - - ">="
64
+ - !ruby/object:Gem::Version
65
+ hash: 3
66
+ segments:
67
+ - 0
68
+ version: "0"
69
+ requirements: []
70
+
71
+ rubyforge_project:
72
+ rubygems_version: 1.8.12
73
+ signing_key:
74
+ specification_version: 3
75
+ summary: Sync Dropbox folder with local directory
76
+ test_files: []
77
+