-
Notifications
You must be signed in to change notification settings - Fork 0
/
camtagger.rb
executable file
·158 lines (132 loc) · 2.63 KB
/
camtagger.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
#!/usr/bin/env ruby
# encoding: utf-8
#
# See LICENSE.txt for licensing information.
require 'json'
require 'set'
def usage
puts "Usage: #{$0} add|del tag,tag... -- file file..."
exit(1)
end
usage if ARGV.length < 4
usage if ARGV[2] != '--'
MODE = ARGV.shift.downcase
usage unless %w{add del}.member? MODE
tags = ARGV.shift.split(',')
usage if tags.empty?
TAGS = Set.new(tags)
ARGV.shift # remove the '--'
CMDS = {
:search => {
:string => 'camtool search -',
:mode => :pipe,
:out => :json,
},
:describe => {
:string => 'camtool describe %s',
:mode => :simple,
:out => :json,
},
:attr_mod => {
:string => 'camput attr %s %s %s %s',
:mode => :simple,
:out => :blob,
},
}
def ask(command, query)
cmd = CMDS[command]
res = nil
case cmd[:mode]
when :pipe
res = IO.popen(cmd[:string], 'r+') do |p|
p.puts JSON.generate(query)
p.close_write
p.read
end
when :simple
res = `#{cmd[:string] % query}`
end
case cmd[:out]
when :json
JSON.parse(res, :symbolize_names => true)
when :blob
res
end
end
def find_blobs(name, size)
query = {
:file => {
:filename => {
:equals => name,
},
:filesize => {
:min => size,
:max => size,
},
},
}
res = ask(:search, query)
return nil unless res[:blobs]
res[:blobs].collect {|e| e[:blob] }
end
def find_permanodes(blob)
query = {
:permanode => {
:attr => 'camliContent',
:value => blob,
},
}
res = ask(:search, query)
return nil unless res[:blobs]
res[:blobs].collect {|e| e[:blob] }
end
def get_attrs(node)
res = ask(:describe, node)
return nil if res[:meta].empty?
res[:meta][node.to_sym][:permanode][:attr]
end
ARGV.each do |arg|
print arg, ' '
unless File.exists? arg
puts 'NON-EXISTENT'
next
end
if File.directory? arg
puts 'DIRECTORY'
next
end
name = File.basename(arg)
size = File.size(arg)
nodes = find_blobs(name, size).compact \
.collect{|b| find_permanodes(b) }.compact.flatten
if nodes.length != 1
puts "#{nodes.length} NODES"
next
end
permanode = nodes.first
print permanode, ' '
attrs = get_attrs(permanode)
unless attrs
puts 'NO ATTRS'
next
end
if attrs.has_key? :tag
tags = Set.new(attrs[:tag])
else
tags = Set.new
end
if MODE == 'add'
tags = TAGS - tags
else
tags = TAGS.intersection(tags)
end
if tags.empty?
puts MODE == 'add' ? 'ALL TAGS PRESENT' : 'NO TAGS TO REMOVE'
else
tags.each do |tag|
print tag, ' '
res = ask(:attr_mod, ["--#{MODE}", permanode, 'tag', tag])
end
puts
end
end