kindlefs 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,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