kindlefs 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --format progress
data/.rvmrc ADDED
@@ -0,0 +1 @@
1
+ rvm use --create --install 1.9.3@kindlefs
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in kindlefs.gemspec
4
+ gemspec
@@ -0,0 +1,19 @@
1
+ # A sample Guardfile
2
+ # More info at https://github.com/guard/guard#readme
3
+
4
+ guard 'rspec', :version => 2 do
5
+ watch(%r{^spec/.+_spec\.rb$})
6
+ watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
7
+ watch('spec/spec_helper.rb') { "spec" }
8
+
9
+ # Rails example
10
+ watch(%r{^app/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
11
+ watch(%r{^app/(.*)(\.erb|\.haml)$}) { |m| "spec/#{m[1]}#{m[2]}_spec.rb" }
12
+ watch(%r{^app/controllers/(.+)_(controller)\.rb$}) { |m| ["spec/routing/#{m[1]}_routing_spec.rb", "spec/#{m[2]}s/#{m[1]}_#{m[2]}_spec.rb", "spec/acceptance/#{m[1]}_spec.rb"] }
13
+ watch(%r{^spec/support/(.+)\.rb$}) { "spec" }
14
+ watch('config/routes.rb') { "spec/routing" }
15
+ watch('app/controllers/application_controller.rb') { "spec/controllers" }
16
+ # Capybara request specs
17
+ watch(%r{^app/views/(.+)/.*\.(erb|haml)$}) { |m| "spec/requests/#{m[1]}_spec.rb" }
18
+ end
19
+
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2012 Arthur Andersen
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,32 @@
1
+ # KindleFS
2
+
3
+ KindleFS is a FuseFS that mounts a Kindles data via Rindle and allows
4
+ the management of the kindles collection information via filesystem tools.
5
+
6
+ ## Installation
7
+
8
+ Add this line to your application's Gemfile:
9
+
10
+ gem 'kindlefs'
11
+
12
+ And then execute:
13
+
14
+ $ bundle
15
+
16
+ Or install it yourself as:
17
+
18
+ $ gem install kindlefs
19
+
20
+ ## Usage
21
+
22
+ Just mount the kindle into some folder.
23
+
24
+ $ kindlefs /path/to/kindle/root /path/to/mountpoint
25
+
26
+ ## Contributing
27
+
28
+ 1. Fork it
29
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
30
+ 3. Commit your changes (`git commit -am 'Added some feature'`)
31
+ 4. Push to the branch (`git push origin my-new-feature`)
32
+ 5. Create new Pull Request
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
@@ -0,0 +1,28 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'rubygems'
4
+ require 'fusefs'
5
+ require 'rindle'
6
+ require 'kindlefs'
7
+
8
+ if ARGV.length < 1
9
+ puts "usage: kindlefs <kindle_root> <mount_point>"
10
+ exit 1
11
+ end
12
+
13
+ trap("INT") do
14
+ puts "exiting kindlefs ..."
15
+ FuseFS.exit
16
+ FuseFS.unmount
17
+ exit
18
+ end
19
+
20
+ kindle_root = ARGV.shift.sub(/#{Regexp.escape(File::SEPARATOR)}$/, '')
21
+ mount_path = ARGV.shift.sub(/#{Regexp.escape(File::SEPARATOR)}$/, '')
22
+
23
+ Rindle::load(kindle_root)
24
+
25
+ kindle = KindleFS::Filesystem.new
26
+ FuseFS.set_root kindle
27
+ FuseFS.mount_under mount_path
28
+ FuseFS.run
@@ -0,0 +1,23 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path('../lib/kindlefs/version', __FILE__)
3
+
4
+ Gem::Specification.new do |gem|
5
+ gem.authors = ["Arthur Andersen"]
6
+ gem.email = ["leoc.git@gmail.com"]
7
+ gem.description = %q{KindleFS mounts the collection information of a Kindle device as file system in user space via the Rindle gem.}
8
+ gem.summary = %q{Mount Kindle via Rindle.}
9
+ gem.homepage = "https://github.com/leoc/kindlefs"
10
+
11
+ gem.files = `git ls-files`.split("\n")
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 = "kindlefs"
15
+ gem.require_paths = ["lib"]
16
+ gem.version = KindleFS::VERSION
17
+
18
+ gem.add_development_dependency 'guard-rspec'
19
+ gem.add_development_dependency 'rake'
20
+ gem.add_development_dependency 'rspec'
21
+ gem.add_dependency 'rfusefs'
22
+ gem.add_dependency 'rindle'
23
+ end
@@ -0,0 +1,4 @@
1
+ require "kindlefs/version"
2
+ require "kindlefs/filesystem"
3
+
4
+ module KindleFS; end
@@ -0,0 +1,219 @@
1
+ require 'fusefs'
2
+ require 'rindle/mixins/regexp'
3
+
4
+ module KindleFS
5
+ class Filesystem < FuseFS::FuseDir
6
+ ROOT_PATH = /^\/$/
7
+ COLLECTIONS_PATH = /^\/collections$/.freeze
8
+ DOCUMENTS_PATH = /^\/documents$/.freeze
9
+ PICTURES_PATH = /^\/pictures$/.freeze
10
+ COLLECTION_NAME = /([A-Za-z0-9_\-\s'"\.]+)/i.freeze
11
+ COLLECTION_PATH = /^#{COLLECTIONS_PATH.strip}\/#{COLLECTION_NAME.strip}$/.freeze
12
+ DOCUMENT_NAME = /([A-Za-z0-9_\s\-]+\.(mobi|epub|rtf|pdf|azw|azw1)+)/i.freeze
13
+ COLLECTION_DOCUMENT_PATH = /^#{COLLECTIONS_PATH.strip}\/#{COLLECTION_NAME.strip}\/#{DOCUMENT_NAME.strip}$/.freeze
14
+ UNASSOCIATED_DOCUMENT_PATH = /^#{COLLECTIONS_PATH.strip}\/#{DOCUMENT_NAME.strip}$/.freeze
15
+ DOCUMENT_PATH = /^#{DOCUMENTS_PATH.strip}\/#{DOCUMENT_NAME.strip}$/.freeze
16
+
17
+ def contents path
18
+ case path
19
+ when ROOT_PATH
20
+ [ 'collections', 'documents', 'pictures' ]
21
+ when COLLECTIONS_PATH
22
+ Rindle::Collection.all.map(&:name) + Rindle::Document.unassociated.map(&:filename)
23
+ when DOCUMENTS_PATH
24
+ Rindle::Document.all.map(&:filename)
25
+ when COLLECTION_PATH
26
+ collection = Rindle::Collection.first :named => $1
27
+ collection.documents.map(&:filename)
28
+ else
29
+ []
30
+ end
31
+ end
32
+
33
+ def file?(path)
34
+ case path
35
+ when DOCUMENT_PATH
36
+ return true
37
+ when COLLECTION_DOCUMENT_PATH
38
+ col = Rindle::Collection.find_by_name $1
39
+ doc = Rindle::Document.find_by_name $2
40
+ return doc && col.include?(doc)
41
+ when UNASSOCIATED_DOCUMENT_PATH
42
+ doc = Rindle::Document.find_by_name $1
43
+ return doc.collections.empty? if doc
44
+ end
45
+ false
46
+ end
47
+
48
+ def directory?(path)
49
+ case path
50
+ when COLLECTIONS_PATH, DOCUMENTS_PATH, PICTURES_PATH
51
+ true
52
+ when COLLECTION_PATH
53
+ Rindle::Collection.exists?(:named => $1)
54
+ else
55
+ false
56
+ end
57
+ end
58
+
59
+ def executable? path
60
+ false
61
+ end
62
+
63
+ def size path
64
+ doc = Rindle::Document.find_by_name File.basename(path)
65
+ File.size File.join(Rindle.root_path, doc.path)
66
+ end
67
+
68
+ def can_delete?(path)
69
+ case path
70
+ when DOCUMENTS_PATH, PICTURES_PATH, COLLECTIONS_PATH
71
+ false
72
+ else
73
+ true
74
+ end
75
+ end
76
+
77
+ def can_write?(path)
78
+ if path !~ ROOT_PATH
79
+ true
80
+ else
81
+ false
82
+ end
83
+ end
84
+
85
+ def can_mkdir?(path)
86
+ case path
87
+ when COLLECTION_PATH
88
+ true
89
+ else
90
+ false
91
+ end
92
+ end
93
+
94
+ def can_rmdir?(path)
95
+ case path
96
+ when COLLECTION_PATH
97
+ true
98
+ else
99
+ false
100
+ end
101
+ end
102
+
103
+ def touch(path, val = 0)
104
+ filename = File.basename(path)
105
+ case path
106
+ when UNASSOCIATED_DOCUMENT_PATH, DOCUMENT_PATH
107
+ doc = Rindle::Document.find_by_name $1
108
+ doc = Rindle::Document.create $1 unless doc
109
+ FileUtils.touch(File.join(Rindle.root_path, doc.path))
110
+ Rindle.save
111
+ true
112
+ else
113
+ false
114
+ end
115
+ end
116
+
117
+ def mkdir(path)
118
+ if path =~ COLLECTION_PATH
119
+ col = Rindle::Collection.find_by_name $1
120
+ Rindle::Collection.create($1) if col.nil?
121
+ Rindle.save
122
+ true
123
+ else
124
+ false
125
+ end
126
+ end
127
+
128
+ def rmdir(path)
129
+ if path =~ COLLECTION_PATH
130
+ collection = Rindle::Collection.first :named => $1
131
+ return false unless collection
132
+ collection.destroy!
133
+ else
134
+ return false
135
+ end
136
+ Rindle.save
137
+ true
138
+ end
139
+
140
+ def delete path
141
+ case path
142
+ when COLLECTION_DOCUMENT_PATH
143
+ col = Rindle::Collection.find_by_name $1
144
+ doc = Rindle::Document.find_by_name $2
145
+ col.remove doc
146
+ when DOCUMENT_PATH, UNASSOCIATED_DOCUMENT_PATH
147
+ doc = Rindle::Document.find_by_name $1
148
+ doc.delete!
149
+ end
150
+ Rindle.save
151
+ true
152
+ end
153
+
154
+ def rename old, new
155
+ case old
156
+ when UNASSOCIATED_DOCUMENT_PATH
157
+ doc = Rindle::Document.find_by_name $1
158
+ if new =~ COLLECTION_DOCUMENT_PATH
159
+ col = Rindle::Collection.find_by_name $1
160
+ col.add doc
161
+ end
162
+ if doc and !doc.amazon?
163
+ doc.rename! File.basename(new)
164
+ else
165
+ return false
166
+ end
167
+ when COLLECTION_DOCUMENT_PATH
168
+ old_col = Rindle::Collection.find_by_name $1
169
+ doc = Rindle::Document.find_by_name $2
170
+ if new =~ COLLECTION_DOCUMENT_PATH
171
+ new_col = Rindle::Collection.find_by_name $1
172
+ unless old_col == new_col
173
+ old_col.remove doc
174
+ new_col.add doc
175
+ end
176
+ doc.rename! File.basename(new)
177
+ else
178
+ return false
179
+ end
180
+ when COLLECTION_PATH
181
+ collection = Rindle::Collection.find_by_name $1
182
+ if new =~ COLLECTION_PATH
183
+ collection.rename! File.basename(new)
184
+ else
185
+ return false
186
+ end
187
+ else
188
+ return false
189
+ end
190
+ Rindle.save
191
+ true
192
+ end
193
+
194
+ def write_to path, body
195
+ doc = Rindle::Document.find_by_name File.basename(path)
196
+ if doc
197
+ if path =~ COLLECTION_DOCUMENT_PATH
198
+ col = Rindle::Collection.find_by_name $1
199
+ col.add doc
200
+ end
201
+ else
202
+ doc = Rindle::Document.create File.basename(path)
203
+ File.open(File.join(Rindle.root_path, doc.path), 'w+') do |f|
204
+ f.write body
205
+ end
206
+ if path =~ COLLECTION_DOCUMENT_PATH
207
+ Rindle::Collection.find_by_name($1).add doc
208
+ end
209
+ end
210
+ Rindle.save
211
+ true
212
+ end
213
+
214
+ def read_file path
215
+ doc = Rindle::Document.find_by_name File.basename(path)
216
+ File.read File.join(Rindle.root_path, doc.path)
217
+ end
218
+ end
219
+ end
@@ -0,0 +1,3 @@
1
+ module KindleFS
2
+ VERSION = "0.1.0"
3
+ end
@@ -0,0 +1 @@
1
+ This directory contains dummy data for the specs.
@@ -0,0 +1 @@
1
+ Some dummy data
@@ -0,0 +1 @@
1
+ Some dummy data
@@ -0,0 +1 @@
1
+ {"collection2@en-US":{"items":["*440f49b58ae78d34f4b8ad3233f04f6b8f5490c2","*5c4dc5c9e385385cbcaf1beedef7690c165a39ca"],"lastAccess":1298745909918},"amazon books@en-US":{"items":["#B001UQ5HVA^EBSP","#B000JQU1VS^EBOK"],"lastAccess":1298745909917},"test collection@en-US":{"items":[],"lastAccess":0},"collection1@en-US":{"items":["*0849dd9b85fc341d10104f56985e423b3848e1f3","*18be6fcd5d5df39c1a96cd22596bbe7fe01db9b7"],"lastAccess":1298745909919}}
@@ -0,0 +1,459 @@
1
+ require "spec_helper"
2
+
3
+ describe KindleFS::Filesystem do
4
+ before(:all) do
5
+ Rindle.load(kindle_root)
6
+ @fs = KindleFS::Filesystem.new
7
+ end
8
+
9
+ context ' regular expressions' do
10
+ it 'should match root path correctly' do
11
+ '/'.should match(KindleFS::Filesystem::ROOT_PATH)
12
+ '/collections'.should_not match(KindleFS::Filesystem::ROOT_PATH)
13
+ end
14
+
15
+ it 'should match the documents path correctly' do
16
+ '/documents'.should match(KindleFS::Filesystem::DOCUMENTS_PATH)
17
+ '/collections'.should_not match(KindleFS::Filesystem::DOCUMENTS_PATH)
18
+ '/documents/dummy'.should_not match(KindleFS::Filesystem::DOCUMENTS_PATH)
19
+ end
20
+
21
+ it 'should match the collections path correctly' do
22
+ '/collections'.should match(KindleFS::Filesystem::COLLECTIONS_PATH)
23
+ '/documents'.should_not match(KindleFS::Filesystem::COLLECTIONS_PATH)
24
+ '/collections/dummy'.should_not match(KindleFS::Filesystem::COLLECTIONS_PATH)
25
+ end
26
+ end
27
+
28
+ describe '#contents' do
29
+ it 'lists view options' do
30
+ list = @fs.contents('/')
31
+ list.should =~ [ 'collections', 'documents', 'pictures' ]
32
+ end
33
+ it 'lists all documents' do
34
+ list = @fs.contents '/documents'
35
+ list.should =~ [
36
+ 'A book in another collection.mobi',
37
+ 'A test aswell.mobi',
38
+ 'Definitely a Test.pdf',
39
+ 'Salvia Divinorum Shamanic Plant-asin_B001UQ5HVA-type_EBSP-v_0.azw',
40
+ 'The Adventures of Sherlock Holme-asin_B000JQU1VS-type_EBOK-v_0.azw',
41
+ 'This is a test document.rtf'
42
+ ]
43
+ end
44
+ it 'lists collections and unassociated documents' do
45
+ list = @fs.contents('/collections')
46
+ list.should =~ [ 'collection1', 'collection2', 'amazon books',
47
+ "This is a test document.rtf" ]
48
+ end
49
+ it 'lists documents in a collection' do
50
+ list = @fs.contents('/collections/collection1')
51
+ list.should =~ [ 'A test aswell.mobi', 'Definitely a Test.pdf' ]
52
+ end
53
+
54
+ end
55
+
56
+ describe '#file?' do
57
+ it 'returns true if path to a collections document given' do
58
+ @fs.file?('/collections/collection1/A test aswell.mobi').should == true
59
+ end
60
+
61
+ it 'returns false if path to collection given' do
62
+ @fs.file?('/collections/collection1').should == false
63
+ end
64
+ end
65
+
66
+ describe '#directory?' do
67
+ it 'returns true if path to root folders given' do
68
+ @fs.directory?('/collections').should == true
69
+ @fs.directory?('/documents').should == true
70
+ @fs.directory?('/pictures').should == true
71
+ end
72
+
73
+ it 'returns true if path to collection given' do
74
+ @fs.directory?('/collections/collection1').should == true
75
+ end
76
+
77
+ it 'returns false if path to collections document given' do
78
+ @fs.directory?('/collections/collection1/A test aswell.mobi').should == false
79
+ end
80
+
81
+ it 'returns false if path to unassociated document given' do
82
+ @fs.directory?('/collections/test.mobi').should == false
83
+ end
84
+
85
+ it 'returns false if path to document given' do
86
+ @fs.directory?('/documents/test.mobi').should == false
87
+ end
88
+ end
89
+
90
+ describe '#executable?' do
91
+ it 'should return false' do
92
+ @fs.executable?('/some/path').should == false
93
+ end
94
+ end
95
+
96
+ describe '#can_delete?' do
97
+ it 'should return false for documents path' do
98
+ @fs.can_delete?('/documents').should == false
99
+ end
100
+
101
+ it 'should return false for pictures path' do
102
+ @fs.can_delete?('/pictures').should == false
103
+ end
104
+
105
+ it 'should return false for collections path' do
106
+ @fs.can_delete?('/collections').should == false
107
+ end
108
+
109
+ it 'should return true for document path' do
110
+ @fs.can_delete?('/documents/abc.pdf').should == true
111
+ end
112
+
113
+ it 'should return true for collection document path' do
114
+ @fs.can_delete?('/collections/abc/my_document.pdf').should == true
115
+ end
116
+
117
+ it 'should return true for unasssociated document path' do
118
+ @fs.can_delete?('/collections/my_document.pdf').should == true
119
+ end
120
+ end
121
+
122
+ describe '#can_write?' do
123
+ it 'should return false for root path' do
124
+ @fs.can_write?('/').should == false
125
+ end
126
+ end
127
+
128
+ describe '#can_mkdir?' do
129
+ it 'should return false for root path' do
130
+ @fs.can_mkdir?('/').should == false
131
+ end
132
+
133
+ it 'should return false for documents path' do
134
+ @fs.can_mkdir?('/documents').should == false
135
+ end
136
+
137
+ it 'should return false for pictures path' do
138
+ @fs.can_mkdir?('/pictures').should == false
139
+ end
140
+
141
+ it 'should return false for collections path' do
142
+ @fs.can_mkdir?('/collections').should == false
143
+ end
144
+
145
+ it 'should return true for collection path' do
146
+ @fs.can_mkdir?('/collections/collection').should == true
147
+ end
148
+
149
+ it 'should return false for collection document path' do
150
+ @fs.can_mkdir?('/collections/collection/document.pdf').should == false
151
+ end
152
+
153
+ it 'should return false for document path' do
154
+ @fs.can_mkdir?('/documents/document.pdf').should == false
155
+ end
156
+ end
157
+
158
+ describe '#can_rmdir?' do
159
+ it 'should return false for root path' do
160
+ @fs.can_rmdir?('/').should == false
161
+ end
162
+
163
+ it 'should return false for documents path' do
164
+ @fs.can_rmdir?('/documents').should == false
165
+ end
166
+
167
+ it 'should return false for pictures path' do
168
+ @fs.can_rmdir?('/pictures').should == false
169
+ end
170
+
171
+ it 'should return false for collections path' do
172
+ @fs.can_rmdir?('/collections').should == false
173
+ end
174
+
175
+ it 'should return true for collection path' do
176
+ @fs.can_rmdir?('/collections/collection').should == true
177
+ end
178
+
179
+ it 'should return false for collection document path' do
180
+ @fs.can_rmdir?('/collections/collection/document.pdf').should == false
181
+ end
182
+
183
+ it 'should return false for document path' do
184
+ @fs.can_rmdir?('/documents/document.pdf').should == false
185
+ end
186
+ end
187
+
188
+ describe '#touch' do
189
+ before :all do
190
+ @fs.touch '/collections/abc.rtf'
191
+ end
192
+
193
+ after :all do
194
+ FileUtils.rm_f File.join(Rindle.root_path, '/documents/abc.rtf')
195
+ end
196
+
197
+ it 'should create an empty file for given path' do
198
+ File.should exist File.join(Rindle.root_path, '/documents/abc.rtf')
199
+ end
200
+ end
201
+
202
+ describe '#mkdir' do
203
+ context 'given collection path' do
204
+ it 'should create a new collection if non-existent' do
205
+ @fs.mkdir '/collections/test collection'
206
+ Rindle.collections.should have_key 'test collection'
207
+ end
208
+ end
209
+
210
+ context 'given another path' do
211
+ it 'should return false' do
212
+ @fs.mkdir('/collections/test collection/something').should == false
213
+ end
214
+ end
215
+ end
216
+
217
+ describe '#rmdir' do
218
+ context 'given collection path' do
219
+ before :all do
220
+ Rindle::Collection.create 'some collection'
221
+ end
222
+
223
+ context 'with existing collection' do
224
+ it 'should delete the collection' do
225
+ @fs.rmdir '/collections/some collection'
226
+ Rindle.collections.should_not have_key 'some collection'
227
+ end
228
+ end
229
+
230
+ context 'with non-existing collection' do
231
+ it 'should return false' do
232
+ ret = @fs.rmdir '/collections/some collection'
233
+ ret.should == false
234
+ end
235
+ end
236
+ end
237
+
238
+ context 'given another path' do
239
+ it 'should return false' do
240
+ ret = @fs.rmdir '/collections/some collection/something'
241
+ ret.should == false
242
+ end
243
+ end
244
+ end
245
+
246
+ describe '#delete' do
247
+ context 'given a collection document path' do
248
+ before :all do
249
+ @fs.delete '/collections/collection1/A test aswell.mobi'
250
+ end
251
+
252
+ it 'should remove the document from the collection' do
253
+ Rindle.collections['collection1'].
254
+ include?('*18be6fcd5d5df39c1a96cd22596bbe7fe01db9b7').
255
+ should == false
256
+ end
257
+ end
258
+
259
+ context 'given a document path' do
260
+ before :all do
261
+ @fs.delete '/documents/A test aswell.mobi'
262
+ end
263
+
264
+ after :all do
265
+ doc = Rindle::Document.create 'A test aswell.mobi', :data => 'Some dummy data'
266
+ Rindle.collections['collection1'].add doc
267
+ end
268
+
269
+ it 'should remove the document from index' do
270
+ Rindle.index.should_not have_key '*18be6fcd5d5df39c1a96cd22596bbe7fe01db9b7'
271
+ end
272
+
273
+ it 'should remove all references in collections' do
274
+ Rindle.collections['collection1'].indices.
275
+ should_not include '*18be6fcd5d5df39c1a96cd22596bbe7fe01db9b7'
276
+ end
277
+
278
+ it 'should delete the document file' do
279
+ File.should_not exist File.join(Rindle.root_path, '/documents/A test aswell.mobi')
280
+ end
281
+ end
282
+
283
+ context 'given an unassociated document path' do
284
+ before :all do
285
+ @fs.delete '/collections/This is a test document.rtf'
286
+ end
287
+
288
+ after :all do
289
+ doc = Rindle::Document.create 'This is a test document.rtf', :data => 'Some dummy data'
290
+ end
291
+
292
+ it 'should remove the document from index' do
293
+ Rindle.index.should_not have_key '*3a102b4032d485025650409b2f7753a1158b199d'
294
+ end
295
+
296
+ it 'should delete the document file' do
297
+ File.should_not exist File.join(Rindle.root_path, '/documents/This is a test document.rtf')
298
+ end
299
+ end
300
+ end
301
+
302
+ describe '#rename' do
303
+ context 'given an unassociated document path as `old` and a collection document path as `new`' do
304
+ before :all do
305
+ @doc = Rindle::Document.find_by_name 'This is a test document.rtf'
306
+ @fs.rename '/collections/This is a test document.rtf', '/collections/collection1/Test.rtf'
307
+ end
308
+
309
+ after :all do
310
+ Rindle.collections['collection1'].remove @doc
311
+ @doc.rename! 'This is a test document.rtf'
312
+ end
313
+
314
+ it 'should rename the document' do
315
+ @doc.filename.should == 'Test.rtf'
316
+ File.should_not exist File.join(Rindle.root_path, '/documents/This is a test document.rtf')
317
+ File.should exist File.join(Rindle.root_path, '/documents/Test.rtf')
318
+ end
319
+
320
+ it 'should add the document to the given collection' do
321
+ Rindle.collections['collection1'].include?(@doc).should == true
322
+ end
323
+ end
324
+
325
+ context 'given a collection document path as `old`' do
326
+ context 'and a collection document path as `new`' do
327
+ context 'is equal to the `old` one' do
328
+ before :all do
329
+ @doc = Rindle::Document.find_by_name 'A test aswell.mobi'
330
+ @fs.rename '/collections/collection1/A test aswell.mobi',
331
+ '/collections/collection1/test aswell.mobi'
332
+ end
333
+
334
+ after :all do
335
+ @doc.rename! 'A test aswell.mobi'
336
+ end
337
+
338
+ it 'should rename the document' do
339
+ File.should exist File.join(Rindle.root_path, '/documents/test aswell.mobi')
340
+ end
341
+ end
342
+
343
+ context 'is not equal to the `old` one' do
344
+ before :all do
345
+ @doc = Rindle::Document.find_by_name 'A test aswell.mobi'
346
+ @fs.rename '/collections/collection1/A test aswell.mobi',
347
+ '/collections/collection2/A test aswell.mobi'
348
+ end
349
+
350
+ after :all do
351
+ Rindle.collections['collection2'].remove @doc
352
+ Rindle.collections['collection1'].add @doc
353
+ end
354
+
355
+ it 'should remove the document from the old collection' do
356
+ @doc.collections.map(&:name).should_not include 'collection1'
357
+ end
358
+
359
+ it 'should add the document to the new collection' do
360
+ @doc.collections.map(&:name).should include 'collection2'
361
+ end
362
+ end
363
+ end
364
+ end
365
+
366
+ context 'given a collection path as `old`' do
367
+ context 'and a collection path as `new`' do
368
+ before :all do
369
+ @col = Rindle::Collection.find_by_name 'collection1'
370
+ @fs.rename '/collections/collection1',
371
+ '/collections/collection_renamed'
372
+ end
373
+
374
+ after :all do
375
+ @col.rename! 'collection1'
376
+ end
377
+
378
+ it 'should rename the collection' do
379
+ @col.name.should == 'collection_renamed'
380
+ end
381
+ end
382
+ end
383
+ end
384
+
385
+ describe '#write_to' do
386
+ context 'given document exists' do
387
+ context 'and in collection document path' do
388
+ before :all do
389
+ @doc = Rindle::Document.find_by_name 'A test aswell.mobi'
390
+ @fs.write_to '/collections/collection2/A test aswell.mobi',
391
+ 'Some dummy data'
392
+ end
393
+
394
+ after :all do
395
+ Rindle.collections['collection2'].remove @doc
396
+ end
397
+
398
+ it 'should add the document to the collection' do
399
+ Rindle.collections['collection2'].include?(@doc).should == true
400
+ end
401
+ end
402
+ end
403
+
404
+ context 'given document does not exist' do
405
+ before :all do
406
+ @fs.write_to '/collections/My test.mobi',
407
+ 'Some dummy data'
408
+ @doc = Rindle::Document.find_by_name 'My test.mobi'
409
+ end
410
+
411
+ after :all do
412
+ @doc.delete!
413
+ end
414
+
415
+ it 'should write the file to `documents` folder' do
416
+ File.read(File.join(Rindle.root_path, @doc.path)).
417
+ should == 'Some dummy data'
418
+ end
419
+
420
+ it 'should add the document to the index' do
421
+ Rindle.index['*5c4dc5c9e385385cbcaf1beedef7690c165a39ca'].should == @doc
422
+ end
423
+ end
424
+
425
+ context 'given document does not exist and in collection document path' do
426
+ before :all do
427
+ @fs.write_to '/collections/collection2/My test.mobi',
428
+ 'Some dummy data'
429
+ @doc = Rindle::Document.find_by_name 'My test.mobi'
430
+ end
431
+
432
+ after :all do
433
+ @doc.delete!
434
+ end
435
+
436
+ it 'should write the file to `documents` folder' do
437
+ File.read(File.join(Rindle.root_path, @doc.path)).
438
+ should == 'Some dummy data'
439
+ end
440
+
441
+ it 'should add the document to the index' do
442
+ Rindle.index['*5c4dc5c9e385385cbcaf1beedef7690c165a39ca'].should == @doc
443
+ end
444
+
445
+ it 'should add the new document to the collection' do
446
+ Rindle.collections['collection2'].
447
+ include?('*5c4dc5c9e385385cbcaf1beedef7690c165a39ca').
448
+ should == true
449
+ end
450
+ end
451
+ end
452
+
453
+ describe '#read_file' do
454
+ it 'should return the file data' do
455
+ data = @fs.read_file '/collections/collection1/A test aswell.mobi'
456
+ data.should == 'Some dummy data'
457
+ end
458
+ end
459
+ end
File without changes
@@ -0,0 +1,52 @@
1
+ require 'rindle'
2
+ require 'kindlefs'
3
+
4
+ def kindle_root; File.join(File.dirname(__FILE__), 'data', 'kindle'); end
5
+
6
+ File.open 'spec/data/kindle/system/collections.json', 'w+' do |f|
7
+ f.write <<JSON
8
+ {
9
+ "collection1@en-US":{
10
+ "items":["*18be6fcd5d5df39c1a96cd22596bbe7fe01db9b7", "*0849dd9b85fc341d10104f56985e423b3848e1f3"],
11
+ "lastAccess": 1298745909919
12
+ },
13
+ "collection2@en-US":{
14
+ "items":["*440f49b58ae78d34f4b8ad3233f04f6b8f5490c2"],
15
+ "lastAccess": 1298745909918
16
+ },
17
+ "amazon books@en-US":{
18
+ "items":["#B001UQ5HVA^EBSP","#B000JQU1VS^EBOK"],
19
+ "lastAccess": 1298745909917
20
+ }
21
+ }
22
+ JSON
23
+ end
24
+
25
+ system 'rm -rf spec/data/kindle/documents/*'
26
+
27
+ [ 'A book in another collection.mobi',
28
+ 'A test aswell.mobi',
29
+ 'Definitely a Test.pdf',
30
+ 'Salvia Divinorum Shamanic Plant-asin_B001UQ5HVA-type_EBSP-v_0.azw',
31
+ 'The Adventures of Sherlock Holme-asin_B000JQU1VS-type_EBOK-v_0.azw',
32
+ 'This is a test document.rtf' ].each do |filename|
33
+ File.open File.join('spec/data/kindle/documents', filename), 'w+' do |f|
34
+ f.write 'Some dummy data'
35
+ end
36
+ end
37
+
38
+ # this is to reset the Singleton'ish nature of the Kindle module
39
+ class Rindle
40
+ def self.reset
41
+ self.class_variables.each do |var|
42
+ eval "#{var} = nil"
43
+ end
44
+ end
45
+ end
46
+
47
+ # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
48
+ RSpec.configure do |config|
49
+ config.treat_symbols_as_metadata_keys_with_true_values = true
50
+ config.run_all_when_everything_filtered = true
51
+ config.filter_run :focus
52
+ end
metadata ADDED
@@ -0,0 +1,143 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: kindlefs
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Arthur Andersen
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-05-20 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: guard-rspec
16
+ requirement: &11542360 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :development
23
+ prerelease: false
24
+ version_requirements: *11542360
25
+ - !ruby/object:Gem::Dependency
26
+ name: rake
27
+ requirement: &11445000 !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
30
+ - - ! '>='
31
+ - !ruby/object:Gem::Version
32
+ version: '0'
33
+ type: :development
34
+ prerelease: false
35
+ version_requirements: *11445000
36
+ - !ruby/object:Gem::Dependency
37
+ name: rspec
38
+ requirement: &11058220 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ! '>='
42
+ - !ruby/object:Gem::Version
43
+ version: '0'
44
+ type: :development
45
+ prerelease: false
46
+ version_requirements: *11058220
47
+ - !ruby/object:Gem::Dependency
48
+ name: rfusefs
49
+ requirement: &9408900 !ruby/object:Gem::Requirement
50
+ none: false
51
+ requirements:
52
+ - - ! '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ type: :runtime
56
+ prerelease: false
57
+ version_requirements: *9408900
58
+ - !ruby/object:Gem::Dependency
59
+ name: rindle
60
+ requirement: &8717100 !ruby/object:Gem::Requirement
61
+ none: false
62
+ requirements:
63
+ - - ! '>='
64
+ - !ruby/object:Gem::Version
65
+ version: '0'
66
+ type: :runtime
67
+ prerelease: false
68
+ version_requirements: *8717100
69
+ description: KindleFS mounts the collection information of a Kindle device as file
70
+ system in user space via the Rindle gem.
71
+ email:
72
+ - leoc.git@gmail.com
73
+ executables:
74
+ - kindlefs
75
+ extensions: []
76
+ extra_rdoc_files: []
77
+ files:
78
+ - .gitignore
79
+ - .rspec
80
+ - .rvmrc
81
+ - Gemfile
82
+ - Guardfile
83
+ - LICENSE
84
+ - README.md
85
+ - Rakefile
86
+ - bin/kindlefs
87
+ - kindlefs.gemspec
88
+ - lib/kindlefs.rb
89
+ - lib/kindlefs/filesystem.rb
90
+ - lib/kindlefs/version.rb
91
+ - spec/data/README.md
92
+ - spec/data/kindle/documents/A book in another collection.mobi
93
+ - spec/data/kindle/documents/A test aswell.mobi
94
+ - spec/data/kindle/documents/Definitely a Test.pdf
95
+ - spec/data/kindle/documents/Salvia Divinorum Shamanic Plant-asin_B001UQ5HVA-type_EBSP-v_0.azw
96
+ - spec/data/kindle/documents/The Adventures of Sherlock Holme-asin_B000JQU1VS-type_EBOK-v_0.azw
97
+ - spec/data/kindle/documents/This is a test document.rtf
98
+ - spec/data/kindle/system/collections.json
99
+ - spec/kindlefs/filesystem_spec.rb
100
+ - spec/kindlefs_spec.rb
101
+ - spec/spec_helper.rb
102
+ homepage: https://github.com/leoc/kindlefs
103
+ licenses: []
104
+ post_install_message:
105
+ rdoc_options: []
106
+ require_paths:
107
+ - lib
108
+ required_ruby_version: !ruby/object:Gem::Requirement
109
+ none: false
110
+ requirements:
111
+ - - ! '>='
112
+ - !ruby/object:Gem::Version
113
+ version: '0'
114
+ segments:
115
+ - 0
116
+ hash: -3452657948332476179
117
+ required_rubygems_version: !ruby/object:Gem::Requirement
118
+ none: false
119
+ requirements:
120
+ - - ! '>='
121
+ - !ruby/object:Gem::Version
122
+ version: '0'
123
+ segments:
124
+ - 0
125
+ hash: -3452657948332476179
126
+ requirements: []
127
+ rubyforge_project:
128
+ rubygems_version: 1.8.17
129
+ signing_key:
130
+ specification_version: 3
131
+ summary: Mount Kindle via Rindle.
132
+ test_files:
133
+ - spec/data/README.md
134
+ - spec/data/kindle/documents/A book in another collection.mobi
135
+ - spec/data/kindle/documents/A test aswell.mobi
136
+ - spec/data/kindle/documents/Definitely a Test.pdf
137
+ - spec/data/kindle/documents/Salvia Divinorum Shamanic Plant-asin_B001UQ5HVA-type_EBSP-v_0.azw
138
+ - spec/data/kindle/documents/The Adventures of Sherlock Holme-asin_B000JQU1VS-type_EBOK-v_0.azw
139
+ - spec/data/kindle/documents/This is a test document.rtf
140
+ - spec/data/kindle/system/collections.json
141
+ - spec/kindlefs/filesystem_spec.rb
142
+ - spec/kindlefs_spec.rb
143
+ - spec/spec_helper.rb