google_drive_companion 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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