tmsu_file_db 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 87c86606a333c58a62d8d6c1d6db1cdee4da35dc
4
+ data.tar.gz: fbae0484413b490c0e1c98f5a415b95e7ef46b0f
5
+ SHA512:
6
+ metadata.gz: 220887318854f6a1a9037bf265edc70f547384f8acc44b4d75b7b3a5f00026fdf0c75c913e453c7d6800446f857cb357ac40d9ed2526817b185a42f7f39f6d11
7
+ data.tar.gz: f5fc16da123e6a2c8eb1eec9f476905e7d4a85193125298efac7e42119f41d2b33ea762da7902a8fbffaf1519599b83d22ce87a76c02c374beefe109b418aa5a
data/bin/tmsu_file_db ADDED
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env ruby
2
+ require 'tmsu_file_db'
3
+ class TmsuFileDb::CLI < Thor
4
+ desc "test", "run tests"
5
+ def test
6
+ puts "No tests have been wrritten"
7
+ exit
8
+ end
9
+ end
10
+ TmsuFileDb::CLI.start ARGV
@@ -0,0 +1,270 @@
1
+ require 'securerandom'
2
+ require 'gemmy'
3
+
4
+ module TmsuFileDb
5
+ def self.start
6
+ ::TmsuRuby.start
7
+ end
8
+ end
9
+
10
+ class TmsuModel
11
+ Config = { root_path: "." }
12
+ Validations = Hash.new { |h,k| h[k] = [] }
13
+ Callbacks = {}
14
+
15
+ def self.query_glob
16
+ "#{Config[:root_path] || "."}/*"
17
+ end
18
+
19
+ def self.configure(root_path:)
20
+ Config[:root_path] = root_path || "./db".tap do |path|
21
+ `mkdir #{path}`
22
+ end
23
+ end
24
+
25
+ def self.validate(attribute=nil, &blk)
26
+ if attribute
27
+ Validations[:generic] << blk
28
+ else
29
+ Validations[attribute] << blk
30
+ end
31
+ end
32
+
33
+ def self.add_callback name, &blk
34
+ Callbacks[name] = blk
35
+ end
36
+
37
+ def self.opts_to_query opts
38
+ case opts
39
+ when Array
40
+ opts.join " "
41
+ when Hash
42
+ opts.map { |k,v| "#{k}={v}" }.join(" ")
43
+ end
44
+ end
45
+
46
+ def self.find_by opts
47
+ where(opts).first
48
+ end
49
+
50
+ def self.where opts={}
51
+ query opts_to_query opts
52
+ end
53
+
54
+ def self.query string
55
+ TmsuFile.new(query_glob).paths_query(query)
56
+ end
57
+
58
+ def self.update_all opts={}
59
+ Dir.glob(query_glob).each { |path| new(path).update(opts) }
60
+ end
61
+
62
+ def self.destroy_all opts={}
63
+ Dir.glob(query_glob).each { |path| `rm #{path}` }
64
+ end
65
+
66
+ attr_reader :attributes, :errors, :path
67
+
68
+ def initialize(attrs={})
69
+ attrs = attrs.with_indifferent_access
70
+ @path = build_id(attrs.delete :id)
71
+ @attributes = attrs
72
+ @persisted = File.exists? @path
73
+ @errors = []
74
+ end
75
+
76
+ def build_id(given=nil)
77
+ rand_id = given || SecureRandom.urlsafe_base64
78
+ prefix = "#{self.class::Config[:root_path]}"
79
+ if prefix
80
+ "#{prefix}/#{rand_id}"
81
+ else
82
+ "#{rand_id}"
83
+ end
84
+ end
85
+
86
+ def []=(k,v)
87
+ attributes[k] = v
88
+ end
89
+
90
+ def [](k)
91
+ attributes[k]
92
+ end
93
+
94
+ def method_missing(sym, *arguments, &blk)
95
+ if attributes.keys.include? sym
96
+ attributes[sym]
97
+ else
98
+ super
99
+ end
100
+ end
101
+
102
+ def write(text, append: false)
103
+ return unless text
104
+ File.open(path, "w#{"a" if append}") { |f| f.write text }
105
+ self
106
+ end
107
+
108
+ def append(text)
109
+ write(text, append: true)
110
+ self
111
+ end
112
+
113
+ def valid?
114
+ @errors = []
115
+ Validations.each do |type, procs|
116
+ procs.each do |proc|
117
+ some_errors = if type.eql?(:generic)
118
+ proc.call self
119
+ else
120
+ proc.call self[type], self
121
+ end
122
+ raise(
123
+ ArgumentError, "validations must return arrays"
124
+ ) unless some_errors.is_a?(Array)
125
+ @errors.concat some_errors
126
+ end
127
+ end
128
+ @errors.empty?
129
+ end
130
+
131
+ def persisted?
132
+ !!@persisted
133
+ end
134
+
135
+ def ensure_persisted
136
+ `touch #{path}` unless persisted?
137
+ end
138
+
139
+ def save
140
+ ensure_persisted
141
+ tag attributes
142
+ self
143
+ end
144
+
145
+ def update attrs={}
146
+ attrs.each_key { |k| self[k] = attrs[k] }
147
+ save
148
+ self
149
+ end
150
+
151
+ def destroy
152
+ `rm #{path}`
153
+ self
154
+ end
155
+
156
+ end
157
+
158
+ module SystemPatch
159
+ refine Object do
160
+ def system string
161
+ `#{string}`.tap &method(:puts)
162
+ end
163
+ end
164
+ end
165
+
166
+ module TmsuRubyInitializer
167
+ using SystemPatch
168
+ def start
169
+ init_tmsu
170
+ end
171
+ def init_tmsu
172
+ puts "initializing tmsu"
173
+ puts system "tmsu init"
174
+ puts "making vfs_path #{vfs_path}"
175
+ puts system "mkdir #{vfs_path}"
176
+ puts "mounting vfs path"
177
+ puts system "tmsu mount #{vfs_path}"
178
+ end
179
+ def vfs_path
180
+ "/home/max/tmsu_vfs"
181
+ end
182
+ end
183
+
184
+ module TmsuFileAPI
185
+
186
+ using SystemPatch
187
+
188
+ def tags
189
+ ensure_persisted
190
+ system("tmsu tags #{path}").split(" ")[1..-1].reduce({}) do |res, tag|
191
+ key, val = tag.split("=")
192
+ res.tap { res[key] = val }
193
+ end
194
+ end
195
+
196
+ def paths_query(query)
197
+ query_root = "#{vfs_path}/queries/#{query}"
198
+ system("ls #{query_root}").split("\n").map do |filename|
199
+ system("readlink #{query_root}/#{filename}").chomp
200
+ end
201
+ end
202
+
203
+ def untag tag_list
204
+ `touch #{path}` unless persisted?
205
+ attributes.delete
206
+ system "tmsu untag #{path} #{tag_list}"
207
+ tags
208
+ end
209
+
210
+ def tag tag_obj
211
+ `touch #{path}` unless persisted?
212
+ system "tmsu tag #{path} #{build_tag_arg tag_obj}"
213
+ tags
214
+ end
215
+
216
+ def build_tag_arg obj
217
+ case obj
218
+ when String
219
+ obj
220
+ when Array
221
+ obj.join " "
222
+ when Hash
223
+ obj.map {|k,v| "#{k}=#{v}" }.join " "
224
+ else
225
+ obj
226
+ end
227
+ end
228
+
229
+ def tag_selector(tag_obj)
230
+ system "tmsu tag --tags '#{build_tag_arg tag_obj}' #{path}"
231
+ files tag_obj
232
+ end
233
+
234
+ def merge_tag(source, dest)
235
+ source_files = files source
236
+ dest_files = files dest
237
+ raise(ArgumentError, "#{source} tag not found") if source_files.empty?
238
+ raise(ArgumentError, "#{dest} tag not found") if dest_files.empty?
239
+ system("tmsu merge #{source} #{dest}")
240
+ source_files
241
+ end
242
+
243
+ def files(tag_obj)
244
+ system("tmsu files #{build_tag_arg tag_obj }").split("\n")
245
+ end
246
+
247
+ end
248
+
249
+ class TmsuRuby
250
+ extend TmsuRubyInitializer
251
+
252
+ def self.file(path=nil)
253
+ TmsuRuby::TmsuFile.new path, vfs_path
254
+ end
255
+
256
+ def self.model(path=nil)
257
+ record = TmsuModel.new id: path
258
+ end
259
+
260
+ class TmsuFile
261
+ include TmsuFileAPI
262
+ attr_reader :path, :vfs_path
263
+ def initialize path, vfs_path
264
+ @path = path
265
+ @vfs_path = vfs_path
266
+ end
267
+ end
268
+ end
269
+
270
+ TmsuModel.include TmsuFileAPI
data/lib/version.rb ADDED
@@ -0,0 +1,3 @@
1
+ module TmsuFileDb
2
+ VERSION = '0.0.1'
3
+ end
metadata ADDED
@@ -0,0 +1,61 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: tmsu_file_db
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - maxpleaner
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2017-01-08 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: gemmyrb
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ description: ''
28
+ email: maxpleaner@gmail.com
29
+ executables:
30
+ - tmsu_file_db
31
+ extensions: []
32
+ extra_rdoc_files: []
33
+ files:
34
+ - bin/tmsu_file_db
35
+ - lib/tmsu_file_db.rb
36
+ - lib/version.rb
37
+ homepage: http://github.com/maxpleaner/tmsu_file_db
38
+ licenses:
39
+ - MIT
40
+ metadata: {}
41
+ post_install_message:
42
+ rdoc_options: []
43
+ require_paths:
44
+ - lib
45
+ required_ruby_version: !ruby/object:Gem::Requirement
46
+ requirements:
47
+ - - "~>"
48
+ - !ruby/object:Gem::Version
49
+ version: '2.3'
50
+ required_rubygems_version: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: 2.5.1
55
+ requirements: []
56
+ rubyforge_project:
57
+ rubygems_version: 2.5.1
58
+ signing_key:
59
+ specification_version: 4
60
+ summary: a 'database' using TMSU file tagging system
61
+ test_files: []