google_drive_companion 0.1.0

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.
@@ -0,0 +1,20 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ coverage
6
+ InstalledFiles
7
+ lib/bundler/man
8
+ pkg
9
+ rdoc
10
+ spec/reports
11
+ test/tmp
12
+ test/version_tmp
13
+ tmp
14
+ Gemfile.lock
15
+
16
+ # YARD artifacts
17
+ .yardoc
18
+ _yardoc
19
+ doc/
20
+
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in google_drive_companion.gemspec
4
+ gemspec
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2012 Edward Price
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.
@@ -0,0 +1,82 @@
1
+ # GoogleDriveCompanion
2
+
3
+ I was playing with the "google-drive-ruby" gem and thought it was awesome.
4
+
5
+ I don't like leaving the terminal, so I thought, meh, I am going to write a gem that allows me to push from the command line.
6
+
7
+ Then, I figured: "Yo!" The handshake takes to long, so why not set of a unix server socket to run as a daemon, listening for my google drive commands so that it will go faster.
8
+
9
+ Sweetness!
10
+
11
+ ## Installation
12
+
13
+ Add this line to your application's Gemfile:
14
+
15
+ gem 'google_drive_companion'
16
+
17
+ And then execute:
18
+
19
+ $ bundle
20
+
21
+ Or install it yourself as:
22
+
23
+ $ gem install google_drive_companion
24
+
25
+ ## Usage
26
+
27
+ Get help
28
+
29
+ gdrive help
30
+
31
+ Start the server using environment variables
32
+
33
+ username=AzureDiamond@gmail.com password=hunter2 gdrive start
34
+
35
+ Or create a file in your ~/.google_drive/conf.yaml:
36
+
37
+ username: AzureDiamond@gmail.com
38
+ password: hunter2
39
+
40
+ Toggle the foreground/daemon flag when you start the server (def. as a daemon):
41
+
42
+ gdrive start [run_in_foreground]
43
+
44
+ Upload a file:
45
+
46
+ gdpush /path/to/file.txt
47
+
48
+ Upload a file from the current dir:
49
+
50
+ gdpush this.txt
51
+
52
+ Upload a file from the current dir, to a remote location:
53
+
54
+ gdpush this.txt remote/path/to/that.txt
55
+
56
+ Move a remote file to another remote folder:
57
+
58
+ gdmv /path/to/file.txt /another/path
59
+
60
+ Download the new file:
61
+
62
+ gdpull /another/path/file.txt
63
+
64
+ Trash the file:
65
+
66
+ gddel /another/path/file.txt
67
+
68
+ Trash whole folders, with reckless abandon!
69
+
70
+ gddel another
71
+
72
+ Kill the server:
73
+
74
+ gdrive stop
75
+
76
+ ## Contributing
77
+
78
+ 1. Fork it
79
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
80
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
81
+ 4. Push to the branch (`git push origin my-new-feature`)
82
+ 5. Create new Pull Request
@@ -0,0 +1,12 @@
1
+ require "bundler/gem_tasks"
2
+
3
+ require 'rake/testtask'
4
+
5
+ Rake::TestTask.new do |t|
6
+ t.libs << "test"
7
+ $foo = t.test_files = FileList['test/**/*_test.rb']
8
+ t.verbose = true
9
+ # t.warning = true
10
+ end
11
+
12
+ task default: "test"
@@ -0,0 +1,13 @@
1
+ #!/usr/bin/env ruby
2
+ require "google_drive_companion"
3
+
4
+ begin
5
+ res = GoogleDriveCompanion::Socket.instance
6
+ $stdout.puts res.digest(["del"] + ARGV)
7
+
8
+ rescue Errno::ECONNREFUSED, Errno::ENOENT
9
+ $stdout.puts <<EOS
10
+ Error connecting to server, please try again after running:
11
+ $ gdrive start
12
+ EOS
13
+ end
@@ -0,0 +1,13 @@
1
+ #!/usr/bin/env ruby
2
+ require "google_drive_companion"
3
+
4
+ begin
5
+ res = GoogleDriveCompanion::Socket.instance
6
+ $stdout.puts res.digest(["mv"] + ARGV)
7
+
8
+ rescue Errno::ECONNREFUSED, Errno::ENOENT
9
+ $stdout.puts <<EOS
10
+ Error connecting to server, please try again after running:
11
+ $ gdrive start
12
+ EOS
13
+ end
@@ -0,0 +1,20 @@
1
+ #!/usr/bin/env ruby
2
+ require "google_drive_companion"
3
+
4
+ begin
5
+ res = GoogleDriveCompanion::Socket.instance
6
+
7
+ # If it ain't an absolute path, make it so!
8
+ ARGV[1] ||= GoogleDriveCompanion::Session.split_file(ARGV[0]).last
9
+ unless ARGV[1][/^\//]
10
+ ARGV[1] = File.join(Dir.pwd, ARGV[1])
11
+ end
12
+
13
+ $stdout.puts res.digest(["pull"] + ARGV)
14
+
15
+ rescue Errno::ECONNREFUSED, Errno::ENOENT
16
+ $stdout.puts <<EOS
17
+ Error connecting to server, please try again after running:
18
+ $ gdrive start
19
+ EOS
20
+ end
@@ -0,0 +1,19 @@
1
+ #!/usr/bin/env ruby
2
+ require "google_drive_companion"
3
+
4
+ begin
5
+ res = GoogleDriveCompanion::Socket.instance
6
+
7
+ # If it ain't an absolute path, make it so!
8
+ unless ARGV[0][/^\//]
9
+ ARGV[0] = File.join(Dir.pwd, ARGV[0])
10
+ end
11
+
12
+ $stdout.puts res.digest(["push"] + ARGV)
13
+
14
+ rescue Errno::ECONNREFUSED, Errno::ENOENT
15
+ $stdout.puts <<EOS
16
+ Error connecting to server, please try again after running:
17
+ $ gdrive start
18
+ EOS
19
+ end
@@ -0,0 +1,18 @@
1
+ #!/usr/bin/env ruby
2
+ require "google_drive_companion"
3
+
4
+ case ARGV[0].downcase
5
+ when "start"
6
+ GoogleDriveCompanion::Server.instance.run! ARGV[1]
7
+ else
8
+ begin
9
+ instance = GoogleDriveCompanion::Socket.instance
10
+ puts instance.digest(ARGV)
11
+ instance.close
12
+ rescue Errno::ECONNREFUSED, Errno::ENOENT
13
+ $stdout.puts <<EOS
14
+ Error connecting to server, please try again after running:
15
+ $ gdrive start
16
+ EOS
17
+ end
18
+ end
@@ -0,0 +1,23 @@
1
+ # -*- encoding: utf-8 -*-
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'google_drive_companion/version'
5
+
6
+ Gem::Specification.new do |gem|
7
+ gem.name = "google_drive_companion"
8
+ gem.version = GoogleDriveCompanion::VERSION
9
+ gem.authors = ["Edward Price"]
10
+ gem.email = ["ted.price+github@gmail.com"]
11
+ gem.description = %q{Interface with google drive from tha matrix}
12
+ gem.summary = %q{Interface with google drive from tha matrix}
13
+ gem.homepage = "https://github.com/pricees/google-drive-companion"
14
+
15
+ gem.files = `git ls-files`.split($/)
16
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
17
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
18
+ gem.require_paths = ["lib"]
19
+
20
+ gem.add_dependency("google_drive")
21
+ gem.add_development_dependency("minitest")
22
+ gem.add_development_dependency("mocha")
23
+ end
@@ -0,0 +1,15 @@
1
+ require "socket"
2
+ require "singleton"
3
+ require "fileutils"
4
+ require "yaml"
5
+ require "google_drive"
6
+ require "json"
7
+
8
+ module GoogleDriveCompanion
9
+ # Your code goes here...
10
+ end
11
+
12
+ require_relative "google_drive_companion/version"
13
+ require_relative "google_drive_companion/server"
14
+ require_relative "google_drive_companion/session"
15
+ require_relative "google_drive_companion/socket"
@@ -0,0 +1,96 @@
1
+ # This module sets up a unix socket daemon process to listen out for commands
2
+ module GoogleDriveCompanion
3
+ class Server
4
+ include Singleton
5
+
6
+ def socket_file
7
+ ENV["gdc_socket"] || File.join("", "tmp", "gdc_socket.sock")
8
+ end
9
+
10
+ def pid_file
11
+ ENV["gdc_pid"] || File.join("", "tmp", "gdc.pid")
12
+ end
13
+
14
+ def check_if_running!
15
+ if File.exists?(socket_file)
16
+ puts "Socket file #{socket_file} in use"
17
+ leave = true
18
+ end
19
+
20
+ if File.exists?(pid_file)
21
+ pid = File.read(pid_file)
22
+ puts "Server may be running on #{pid}\n**************\n"
23
+ leave ||= true
24
+ end
25
+ leave && exit(1)
26
+ end
27
+
28
+ def server
29
+ @server ||= begin
30
+ check_if_running!
31
+ write(Process.pid, pid_file)
32
+ UNIXServer.new(socket_file)
33
+ end
34
+ end
35
+
36
+ def close
37
+ server.close
38
+ end
39
+
40
+ def close!
41
+ close
42
+ File.exists?(socket_file) && FileUtils.rm(socket_file)
43
+ File.exists?(pid_file) && FileUtils.rm(pid_file)
44
+ Process.kill 9, Process.pid
45
+ end
46
+
47
+ # Attempts to write the pid of the forked process to the pid file.
48
+ # Kills process if write unsuccesfull.
49
+ def write(pid, pidfile)
50
+ File.open pidfile, "w" do |f|
51
+ f.write pid
52
+ f.close
53
+ end
54
+ $stdout.puts "Daemon running with pid: #{pid}"
55
+ rescue ::Exception => e
56
+ raise "While writing the PID to file, unexpected #{e.class}: #{e}"
57
+ end
58
+
59
+ def run!(arg = nil)
60
+ server
61
+ Process.daemon unless arg
62
+ msg_pump.join
63
+ end
64
+
65
+ def respond(s, msg)
66
+ s.send(msg, 0)
67
+ rescue Errno::EPIPE
68
+ $stderr.puts "Socket closed, meh"
69
+ end
70
+
71
+ def msg_pump
72
+ loop do
73
+ begin
74
+ s = server.accept
75
+ while (cmd = s.recv(1000))
76
+ cmd = JSON.parse(cmd)
77
+ case cmd.first
78
+ when "stop"
79
+ close!
80
+ when "help"
81
+ help_file = File.join(File.dirname(__FILE__), "..", "help.txt")
82
+ respond(s, File.read(help_file))
83
+ else
84
+ GoogleDriveCompanion::Session.handle_msg(cmd)
85
+ respond(s, "[#{cmd.first}] Success!")
86
+ end
87
+ end
88
+ rescue Exception => bang
89
+ tmp = "Server error: #{bang}"
90
+ $stderr.puts tmp
91
+ respond(s, tmp)
92
+ end
93
+ end
94
+ end
95
+ end
96
+ end
@@ -0,0 +1,202 @@
1
+ module GoogleDriveCompanion
2
+
3
+ module Session
4
+ extend self
5
+
6
+ # Set authentication creditials in ~/.google_drive/conf.yaml
7
+ #
8
+ # ~/.google_drive/conf.yaml:
9
+ #
10
+ # username: AzureDiamond@gmail.com
11
+ # password: hunter2
12
+ #
13
+ # OR at the env level:
14
+ #
15
+ # username=AzureDiamond@gmail.com password=hunter2 [cmd] [arg1, ... ]
16
+ #
17
+ def configs
18
+ @configs ||= begin
19
+ fn = File.join(Dir.home, ".google_drive", "conf.yaml")
20
+ configs = File.exists?(fn) ? YAML::load(File.open(fn)) : ENV
21
+ end
22
+ end
23
+
24
+ # Public: Split filename into array by separator
25
+ #
26
+ # name - Name of file
27
+ # sep - Seperator (def. system separator)
28
+ #
29
+ # Examples
30
+ #
31
+ # split_file("/path/to/file.txt")
32
+ # # => ["path", "to", "file.txt")
33
+ #
34
+ # split_file("-path-to-file.txt----", "-")
35
+ # res.must_equal(exp)
36
+ #
37
+ # Returns array
38
+ def split_file(name = "", sep = File::SEPARATOR)
39
+ name.gsub(/^#{sep}+/, '').split(sep)
40
+ end
41
+
42
+ # Public: Return the top level folder of the accounts google drive
43
+ #
44
+ # Returns GoogleDrive::Collection
45
+ def root
46
+ session.root_collection
47
+ end
48
+
49
+ # Public: Call methods, check against whitelist
50
+ #
51
+ #
52
+ # Returns [something]
53
+ PROTECTED_METHODS = %w[push pull mv del]
54
+ def send_protected(ary)
55
+ if PROTECTED_METHODS.include?(ary.first)
56
+ send(ary.shift.to_sym, *ary)
57
+ end
58
+ end
59
+
60
+ # Public: Takes an array of names of gdrive folders and traverss them. If name is erroneous, it stops at last leaf; if forced, creates the subcollection
61
+ #
62
+ # Examples
63
+ #
64
+ # traverse(["foo", "bar"])
65
+ # # => <collection "bar">
66
+ #
67
+ # traverse(["foo", "bar", "baz"]) NOTE: bar doesn't exist
68
+ # # => <collection "foo">
69
+ #
70
+ # traverse(["foo", "bar", "baz"], :force) NOTE: bar doesn't exist
71
+ # # => <collection "baz">
72
+ #
73
+ # Returns a GoogleDrive::Collection
74
+ def traverse(collections, force = false)
75
+ node = root
76
+ collections.each do |subcollection|
77
+ new_node = node.subcollection_by_title(subcollection)
78
+
79
+ if new_node
80
+ node = new_node
81
+ elsif force
82
+ node = node.create_subcollection(subcollection)
83
+ else
84
+ break
85
+ end
86
+ end
87
+
88
+ node
89
+ end
90
+
91
+ # Public: Get a file from Google Drive
92
+ #
93
+ # ary - Array of collections, last element is title of file
94
+ #
95
+ # Example
96
+ #
97
+ # get_file(["foo", "bar", "faz.rb"])
98
+ # # => <GoogleDrive::File faz.rb>
99
+ #
100
+ # Returns a GoogleDrive::File
101
+ def get_file(ary)
102
+ title = ary.pop
103
+ traverse(ary).
104
+ files({ "title" => title, "title-exact" => "true" })[0]
105
+ end
106
+
107
+ # Public: Move file from one remote location to another
108
+ #
109
+ # src - Source remote path to file
110
+ # dest - Destination remote path for file
111
+ # force - Make destination folder path if not already (def. true)
112
+ # Examples
113
+ #
114
+ # mv("/old/path/to/file.txt", "/new/path/")
115
+ # # => mil;
116
+ #
117
+ # Raise RuntimeError is remote file doesn't exist
118
+ # Returns nil
119
+ def mv(src, dest, force = true)
120
+ src_ary = split_file(src)
121
+ src_node = traverse(src_ary[0...-1])
122
+ file = get_file(src_ary)
123
+
124
+ if file
125
+ traverse(split_file(dest), force).add(file)
126
+ src_node.remove(file)
127
+ else
128
+ raise "Remote file: #{file} doesn't exist yo!"
129
+ end
130
+
131
+ nil
132
+ end
133
+
134
+ # Public: Uploads local file to remote local
135
+ #
136
+ # remote_file - Remote file path, File::SEPARATOR delimited
137
+ # local_file - Local file path, File::SEPARATOR delimited
138
+ #
139
+ # Examples
140
+ #
141
+ # push("/tmp/text.txt")
142
+ # # => [ remote file /tmp/text.txt ]
143
+ #
144
+ # push("/tmp/text.txt", "/remote/path/to/text.txt")
145
+ # # => [ remote file /remote/path/to/text.txt ]
146
+ #
147
+ # Returns GoogleDrive::File
148
+ def push(local_file, remote_file = nil, force = true)
149
+
150
+ remote_file ||= local_file
151
+ ary = split_file(remote_file)
152
+ remote_fn = ary.pop
153
+ file = session.upload_from_file(local_file, remote_fn)
154
+
155
+ unless ary.empty?
156
+ traverse(ary, force).add(file)
157
+ root.remove(file)
158
+ end
159
+ file
160
+ end
161
+
162
+ # Public: Downloads remote file
163
+ #
164
+ # remote_file - Remote file path, File::SEPARATOR delimited
165
+ # local_file - Local file path, File::SEPARATOR delimited
166
+ #
167
+ # Examples
168
+ #
169
+ # pull("/remote/path/to/text.txt", "/tmp/text.txt")
170
+ # # => [ file /tmp/text.txt ]
171
+ #
172
+ # Returns an integer
173
+ def pull(remote_file, local_file = nil)
174
+
175
+ remote_ary = split_file(remote_file)
176
+ local_file ||= remote_ary.last
177
+
178
+ get_file(remote_ary).download_to_file(local_file)
179
+ rescue
180
+ raise "problem locating remote file: #{remote_file}"
181
+ end
182
+
183
+ # Public: Deletes remote folder
184
+ #
185
+ # file - Remote file path, File::SEPARATOR delimited
186
+ # permanent - Delete permantantly? (or just put in trash) (def. false)
187
+ #
188
+ # Returns boolean
189
+ def del(file, permanently = false)
190
+ get_file(split_file(file)).delete(permanently)
191
+ permanently
192
+ end
193
+
194
+ def handle_msg(cmd)
195
+ send_protected(cmd) || "bad command!"
196
+ end
197
+
198
+ def session
199
+ @session = GoogleDrive.login(configs["username"], configs["password"])
200
+ end
201
+ end
202
+ end
@@ -0,0 +1,27 @@
1
+ # Class: The class connects to the UNIX socket and pushes the command line as quickly as possible
2
+ #
3
+ # NOTE: I didn't comment this section, because the code is so amazing, sometimes I just cry looking at it.
4
+ #
5
+ # Oops there it goes, a tear drop right in my Portillo's Italian Sausage.
6
+ module GoogleDriveCompanion
7
+ class Socket
8
+ include Singleton
9
+
10
+ def socket_file
11
+ ENV["gdc_socket"] || File.join("", "tmp", "gdc_socket.sock")
12
+ end
13
+
14
+ def socket
15
+ @socket ||= UNIXSocket.open(socket_file)
16
+ end
17
+
18
+ def close
19
+ socket.close
20
+ end
21
+
22
+ def digest(msg)
23
+ socket.send(msg.to_json, 0)
24
+ socket.recv(10_000)
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,3 @@
1
+ module GoogleDriveCompanion
2
+ VERSION = "0.1.0"
3
+ end
@@ -0,0 +1,23 @@
1
+ ======================
2
+ Google Drive Companion
3
+ ======================
4
+
5
+ gdriver s # start server
6
+
7
+ == Upload Files ==
8
+ gdpush [local file] [remote file]
9
+ gdpush /tmp/foo remote/path/bar # push local file /tmp/foo -> remote/path/bar
10
+ gdpush /tmp/foo [remote file] # push local file /tmp/foo -> remote /tmp/foo
11
+ gdpush relative.txt [remote file] # push file in current directory, will retain directory structure if remote file unspecified, beware!
12
+
13
+ == Download Files ==
14
+ gdpull /remote/path/bar.txt # Download to the relative path (./bar.txt)
15
+ gdpull /remote/path/bar.txt /tmp/foo.txt # Download to absoltute path and filename
16
+
17
+ == Move Files ==
18
+ gdmv /foo/bar.txt /new/path # push remote file to different directory (/foo/bar.txt - > new/path/bar.txt)
19
+
20
+ == Remove Remote Files ==
21
+ gddel /new/path/bar.txt # Delete a file
22
+ gddel /new/ # Delete the whole directory (AHHHHHHHHHH!)
23
+
@@ -0,0 +1,102 @@
1
+ require_relative "test_helper.rb"
2
+
3
+ describe GoogleDriveCompanion::Server do
4
+
5
+ before do
6
+ @instance = GoogleDriveCompanion::Server.instance
7
+ end
8
+
9
+ it "returns socket filename" do
10
+ @instance.socket_file.must_equal "/tmp/gdc_socket.sock"
11
+
12
+ ENV["gdc_socket"] = "/foo"
13
+ @instance.socket_file.must_equal "/foo"
14
+ end
15
+
16
+ it "returns pid filename" do
17
+ @instance.pid_file.must_equal "/tmp/gdc.pid"
18
+
19
+ ENV["gdc_pid"] = "/foo"
20
+ @instance.pid_file.must_equal "/foo"
21
+ end
22
+
23
+ describe "checks if the server is running" do
24
+
25
+ it "may be running because of the unix socket file" do
26
+ @instance.expects(:socket_file).times(2).returns(:foo)
27
+ @instance.expects(:pid_file).returns(:bar)
28
+
29
+ File.expects(:exists?).with(:foo).returns(true)
30
+ File.expects(:exists?).with(:bar).returns(false)
31
+
32
+ @instance.expects(:exit).with(1)
33
+ refute @instance.check_if_running!
34
+ end
35
+
36
+ it "may be running because of the pidfile" do
37
+ @instance.expects(:socket_file).returns(:foo)
38
+ @instance.expects(:pid_file).times(2).returns(:bar)
39
+
40
+ File.expects(:exists?).with(:foo).returns(false)
41
+ File.expects(:exists?).with(:bar).returns(true)
42
+ File.expects(:read).with(:bar)
43
+
44
+ @instance.expects(:exit).with(1)
45
+ refute @instance.check_if_running!
46
+ end
47
+
48
+ it "isn't running" do
49
+ @instance.expects(:socket_file).returns(:foo)
50
+ @instance.expects(:pid_file).returns(:bar)
51
+
52
+ File.expects(:exists?).with(:foo).returns(false)
53
+ File.expects(:exists?).with(:bar).returns(false)
54
+
55
+ @instance.expects(:exit).times(0)
56
+ refute @instance.check_if_running!
57
+ end
58
+ end
59
+
60
+ it "grabs a new unix socket it appropriate" do
61
+ @instance.expects(:check_if_running!)
62
+ @instance.expects(:write)
63
+ @instance.expects(:socket_file).returns(:socket!)
64
+ UNIXServer.expects(:new).with(:socket!).returns(:success!)
65
+
66
+ @instance.server.must_equal(:success!)
67
+ end
68
+
69
+ it "closes its socket" do
70
+ @instance.expects(:server).returns(mock(close: :success!))
71
+ @instance.close.must_equal(:success!)
72
+ end
73
+
74
+ it "kills the server" do
75
+ @instance.expects(:close)
76
+ @instance.expects(:socket_file).times(2).returns(:yar!)
77
+ @instance.expects(:pid_file).times(2).returns(:she_blows!)
78
+
79
+ File.expects(:exists?).with(:yar!).returns(true)
80
+ File.expects(:exists?).with(:she_blows!).returns(true)
81
+ FileUtils.expects(:rm).times(2)
82
+ Process.expects(:kill)
83
+
84
+ @instance.close!
85
+ end
86
+
87
+ describe "runs the server" do
88
+ it "as a daemon process" do
89
+ @instance.expects(:server)
90
+ Process.expects(:daemon).times(1)
91
+ @instance.expects(:msg_pump).returns []
92
+ @instance.run!
93
+ end
94
+
95
+ it "in the foreground" do
96
+ @instance.expects(:server)
97
+ Process.expects(:daemon).times(0)
98
+ @instance.expects(:msg_pump).returns []
99
+ @instance.run! :foo!
100
+ end
101
+ end
102
+ end
@@ -0,0 +1,165 @@
1
+ require_relative "test_helper.rb"
2
+
3
+ describe GoogleDriveCompanion::Session do
4
+
5
+ before do
6
+ @module = GoogleDriveCompanion::Session
7
+ end
8
+
9
+ describe "has a config" do
10
+
11
+ it "gets from a file" do
12
+ end
13
+
14
+ it "gets from env" do
15
+ end
16
+ end
17
+
18
+ it "has a session" do
19
+ hsh = { "username" => "foo", "password" => "bar" }
20
+ @module.expects(:configs).times(2).returns(hsh)
21
+ GoogleDrive.expects(:login).with("foo", "bar").returns(:jeah)
22
+ @module.session.must_equal(:jeah)
23
+ end
24
+
25
+ it "sends methods" do
26
+ ary = %w[mv bar baz]
27
+ @module.expects(:send).with(:mv, "bar", "baz")
28
+ @module.send_protected(ary)
29
+ end
30
+
31
+ it "handles message" do
32
+ hsh = { "foo" => "bar" }
33
+ @module.expects(:send_protected).with(hsh)
34
+ @module.handle_msg(hsh)
35
+ end
36
+
37
+ describe "handles files" do
38
+
39
+ it "seperates files by separator" do
40
+ exp = %w(path to file.txt)
41
+ res = @module.split_file("path/to/file.txt")
42
+ res.must_equal(exp)
43
+
44
+ res = @module.split_file("/path/to/file.txt")
45
+ res.must_equal(exp)
46
+
47
+ res = @module.split_file("/path/to/file.txt////")
48
+ res.must_equal(exp)
49
+
50
+ res = @module.split_file("-path-to-file.txt----", "-")
51
+ res.must_equal(exp)
52
+ end
53
+ end
54
+
55
+ describe "collections" do
56
+
57
+ it "traverses a full collection tree" do
58
+ root = mock
59
+ foo = mock
60
+ bar = mock
61
+ root.expects(:subcollection_by_title).with("foo").returns(foo)
62
+ foo.expects(:subcollection_by_title).with("bar").returns(bar)
63
+ bar.expects(:subcollection_by_title).with("baz").returns(:success!)
64
+ @module.expects(:root).returns(root)
65
+ @module.traverse(%w(foo bar baz)).must_equal(:success!)
66
+ end
67
+
68
+ it "stops at leaf" do
69
+ root = mock
70
+ foo = mock
71
+ bar = mock
72
+ root.expects(:subcollection_by_title).with("foo").returns(foo)
73
+ foo.expects(:subcollection_by_title).with("bar").returns(nil)
74
+ @module.expects(:root).returns(root)
75
+ @module.traverse(%w(foo bar baz)).must_equal(foo)
76
+ end
77
+
78
+ it "traverses a known collection tree" do
79
+ root = mock
80
+ foo = mock
81
+ bar = mock
82
+ root.expects(:subcollection_by_title).with("foo").returns(foo)
83
+ foo.expects(:subcollection_by_title).with("bar").returns(nil)
84
+ foo.expects(:create_subcollection).with("bar").returns(:success!)
85
+
86
+ @module.expects(:root).returns(root)
87
+ @module.traverse(%w(foo bar), :force).must_equal(:success!)
88
+ end
89
+ end
90
+
91
+ it "gets the root 'directory' of the gdrive" do
92
+
93
+ @module.expects(:session).returns(mock(root_collection: :success!))
94
+ @module.root.must_equal :success!
95
+ end
96
+
97
+
98
+ describe "handles files on gdrive" do
99
+
100
+ it "pushes a file" do
101
+ m = mock
102
+ m.expects(:upload_from_file).with("baz.rb", "baz.rb")
103
+ @module.expects(:session).returns(m)
104
+
105
+ ary = %w(baz.rb)
106
+ @module.push(ary.join("/"))
107
+ end
108
+
109
+ it "pushes a file with collection" do
110
+ m = mock
111
+ m.expects(:upload_from_file).with("foo/bar/test.rb", "test.rb").returns(:remote_file)
112
+ @module.expects(:session).returns(m)
113
+
114
+ ary = %w(foo bar test.rb)
115
+ col = mock
116
+ col.expects(:add).with(:remote_file)
117
+ @module.expects(:traverse).with(["baz"], :force).returns(col)
118
+ @module.expects(:root).returns(mock(:remove))
119
+ @module.push(ary.join("/"), "baz/test.rb", :force).must_equal :remote_file
120
+ end
121
+
122
+ end
123
+
124
+ describe "downloading files" do
125
+ it "pulls file to local file" do
126
+ m = mock
127
+ m.expects(:download_to_file).with("/tmp/out")
128
+ @module.expects(:get_file).with(%w(foo bar baz.txt)).returns(m)
129
+ @module.pull("foo/bar/baz.txt", "/tmp/out")
130
+ end
131
+
132
+ it "pulls file to local defaults" do
133
+ m = mock
134
+ m.expects(:download_to_file).with("baz.txt")
135
+ @module.expects(:get_file).with(%w(foo bar baz.txt)).returns(m)
136
+ @module.pull("foo/bar/baz.txt")
137
+ end
138
+ end
139
+
140
+ it "deletes files" do
141
+ path = "/path/to/txt"
142
+
143
+ m = mock
144
+ m.expects(:delete).with(:blah).returns(:blah)
145
+
146
+ @module.expects(:get_file).with(%w[path to txt]).returns(m)
147
+
148
+ @module.del(path, :blah).must_equal(:blah)
149
+ end
150
+
151
+ it "moves files" do
152
+ old_path = "/old/path/to/txt"
153
+ new_path = "/new/path/txt"
154
+
155
+ m = mock
156
+ n = mock
157
+ n.expects(:add).with(m).returns(:success)
158
+
159
+ @module.expects(:traverse).with(%w[old path to]).returns(mock(remove: true))
160
+ @module.expects(:get_file).with(%w[old path to txt]).returns(m)
161
+ @module.expects(:traverse).with(%w[new path txt], true).returns(n)
162
+
163
+ @module.mv(old_path, new_path).must_be :nil?
164
+ end
165
+ end
@@ -0,0 +1,38 @@
1
+ require_relative "test_helper.rb"
2
+
3
+ describe GoogleDriveCompanion::Socket do
4
+
5
+ before do
6
+ @instance = GoogleDriveCompanion::Socket.instance
7
+ end
8
+
9
+ it "returns socket filename" do
10
+ ENV.delete("gdc_socket")
11
+
12
+ @instance.socket_file.must_equal "/tmp/gdc_socket.sock"
13
+
14
+ ENV["gdc_socket"] = "/foo"
15
+ @instance.socket_file.must_equal "/foo"
16
+ end
17
+
18
+ it "returns a socket" do
19
+ UNIXSocket.expects(:open).returns(:success!)
20
+ @instance.socket.must_equal(:success!)
21
+ end
22
+
23
+ it "closes its socket" do
24
+ @instance.expects(:socket).returns(mock(close: :success!))
25
+ @instance.close.must_equal(:success!)
26
+ end
27
+
28
+ it "sends a json string to the socket" do
29
+ ary = %w[push /path/to/file]
30
+
31
+ socket = mock
32
+ socket.expects(:send).with(ary.to_json, 0)
33
+ socket.expects(:recv).with(10_000).returns(:success!)
34
+
35
+ @instance.expects(:socket).times(2).returns(socket)
36
+ @instance.digest(ary).must_equal(:success!)
37
+ end
38
+ end
@@ -0,0 +1,5 @@
1
+ require "minitest/autorun"
2
+ require "minitest/reporters"
3
+ require "mocha/setup"
4
+ require_relative "../lib/google_drive_companion.rb"
5
+ Minitest::Reporters.use!
metadata ADDED
@@ -0,0 +1,123 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: google_drive_companion
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Edward Price
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-01-03 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: google_drive
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
30
+ - !ruby/object:Gem::Dependency
31
+ name: minitest
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ type: :development
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ - !ruby/object:Gem::Dependency
47
+ name: mocha
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ description: Interface with google drive from tha matrix
63
+ email:
64
+ - ted.price+github@gmail.com
65
+ executables:
66
+ - gddel
67
+ - gdmv
68
+ - gdpull
69
+ - gdpush
70
+ - gdrive
71
+ extensions: []
72
+ extra_rdoc_files: []
73
+ files:
74
+ - .gitignore
75
+ - Gemfile
76
+ - LICENSE.txt
77
+ - README.md
78
+ - Rakefile
79
+ - bin/gddel
80
+ - bin/gdmv
81
+ - bin/gdpull
82
+ - bin/gdpush
83
+ - bin/gdrive
84
+ - google_drive_companion.gemspec
85
+ - lib/google_drive_companion.rb
86
+ - lib/google_drive_companion/server.rb
87
+ - lib/google_drive_companion/session.rb
88
+ - lib/google_drive_companion/socket.rb
89
+ - lib/google_drive_companion/version.rb
90
+ - lib/help.txt
91
+ - test/server_test.rb
92
+ - test/session_test.rb
93
+ - test/socket_test.rb
94
+ - test/test_helper.rb
95
+ homepage: https://github.com/pricees/google-drive-companion
96
+ licenses: []
97
+ post_install_message:
98
+ rdoc_options: []
99
+ require_paths:
100
+ - lib
101
+ required_ruby_version: !ruby/object:Gem::Requirement
102
+ none: false
103
+ requirements:
104
+ - - ! '>='
105
+ - !ruby/object:Gem::Version
106
+ version: '0'
107
+ required_rubygems_version: !ruby/object:Gem::Requirement
108
+ none: false
109
+ requirements:
110
+ - - ! '>='
111
+ - !ruby/object:Gem::Version
112
+ version: '0'
113
+ requirements: []
114
+ rubyforge_project:
115
+ rubygems_version: 1.8.24
116
+ signing_key:
117
+ specification_version: 3
118
+ summary: Interface with google drive from tha matrix
119
+ test_files:
120
+ - test/server_test.rb
121
+ - test/session_test.rb
122
+ - test/socket_test.rb
123
+ - test/test_helper.rb