|
|
dossier - dossier - console collection manager |
|
|
 |
Log |
|
|
 |
Files |
|
|
 |
Refs |
|
|
 |
Tags |
|
|
 |
README |
|
|
 |
LICENSE |
|
|
|
--- |
|
|
|
dossier (7949B) |
|
|
|
--- |
|
|
|
1 #!/bin/sh |
|
|
|
2 |
|
|
|
3 REPOSITORY="${HOME}/.collections" |
|
|
|
4 mkdir -p "$REPOSITORY" |
|
|
|
5 test -f "${REPOSITORY}/current" && . "${REPOSITORY}/current" |
|
|
|
6 |
|
|
|
7 if [ -n "$CONTEXT" ] |
|
|
|
8 then |
|
|
|
9 REPO="${REPOSITORY}/${CONTEXT}/" |
|
|
|
10 cd "$REPO" |
|
|
|
11 test ! -d ".git" && git init |
|
|
|
12 else |
|
|
|
13 printf 'No current collection in use\n' |
|
|
|
14 fi |
|
|
|
15 |
|
|
|
16 # return if an item exists |
|
|
|
17 # $1 identifier |
|
|
|
18 exists() { |
|
|
|
19 cd "$REPO" |
|
|
|
20 ls */"$1" >/dev/null 2>&1 |
|
|
|
21 return $? |
|
|
|
22 } |
|
|
|
23 |
|
|
|
24 # displays the values of an identifier |
|
|
|
25 # $1 identifier |
|
|
|
26 show() { |
|
|
|
27 cd "$REPO" |
|
|
|
28 if exists "$1" |
|
|
|
29 then |
|
|
|
30 SEEN=0 |
|
|
|
31 for attribute in * |
|
|
|
32 do |
|
|
|
33 if [ -f "${attribute}/${1}" ] |
|
|
|
34 then |
|
|
|
35 if [ "$SEEN" -eq 0 ] |
|
|
|
36 then |
|
|
|
37 printf "%s:\n" "$1" |
|
|
|
38 SEEN=1 |
|
|
|
39 fi |
|
|
|
40 printf "%15s: %s\n" "$attribute" "$(cat "${attribute}/${1}")" |
|
|
|
41 fi |
|
|
|
42 done |
|
|
|
43 exit 0 |
|
|
|
44 else |
|
|
|
45 printf '%s is not in the library.\n' "$1" |
|
|
|
46 exit 1 |
|
|
|
47 fi |
|
|
|
48 } |
|
|
|
49 |
|
|
|
50 # displays the list of values per attributes |
|
|
|
51 show_attributes_values() { |
|
|
|
52 cd "$REPO" |
|
|
|
53 for attribute in * |
|
|
|
54 do |
|
|
|
55 printf "%s:\n" "$attribute" |
|
|
|
56 awk '{ print }' "${attribute}"/* | sort | uniq | sed 's/^/ /' |
|
|
|
57 done |
|
|
|
58 exit 0 |
|
|
|
59 } |
|
|
|
60 |
|
|
|
61 # import data from a csv |
|
|
|
62 # $1 is the file to import |
|
|
|
63 import_csv() { |
|
|
|
64 git tag "Importing CSV" |
|
|
|
65 awk -F "," '{ |
|
|
|
66 if(NR==1) { |
|
|
|
67 for(i=1;i<=NF;i=i+1) { |
|
|
|
68 headers[i] = $i |
|
|
|
69 } |
|
|
|
70 } else { |
|
|
|
71 out = $1; |
|
|
|
72 for(i=2;i<=NF;i=i+1) { |
|
|
|
73 if(! match($i,/^""$/) && $i !="") { |
|
|
|
74 out = out " "headers[i]" "$i; |
|
|
|
75 } |
|
|
|
76 } |
|
|
|
77 if(out==$1) { |
|
|
|
78 print "empty" |
|
|
|
79 } else { |
|
|
|
80 out=out "\n" |
|
|
|
81 print out |
|
|
|
82 system("dossier "out) |
|
|
|
83 } |
|
|
|
84 } |
|
|
|
85 }' "$1" |
|
|
|
86 } |
|
|
|
87 |
|
|
|
88 # export the data in csv format "data","data","data" |
|
|
|
89 # we assume it'll works with the dataset |
|
|
|
90 export_csv() { |
|
|
|
91 cd "$REPO" |
|
|
|
92 |
|
|
|
93 # display header |
|
|
|
94 printf '"identifier"' |
|
|
|
95 find . -name '.git' -prune -o -type f -print | cut -d '/' -f 2 | sort | uniq | while read attr |
|
|
|
96 do |
|
|
|
97 printf ',"%s"' $attr |
|
|
|
98 done |
|
|
|
99 printf '\n' |
|
|
|
100 |
|
|
|
101 # print database |
|
|
|
102 find . -name '.git' -prune -o -type f -print | cut -d '/' -f 3 | sort | uniq | while read id |
|
|
|
103 do |
|
|
|
104 printf '"%s",' "$id" |
|
|
|
105 FIRST=0 |
|
|
|
106 find . -name '.git' -prune -o -type f -print | cut -d '/' -f 2 | sort | uniq | while read attr |
|
|
|
107 do |
|
|
|
108 if [ "$FIRST" -eq 0 ] |
|
|
|
109 then |
|
|
|
110 FIRST=1 |
|
|
|
111 else |
|
|
|
112 printf "," |
|
|
|
113 fi |
|
|
|
114 # for faster processing, we do not check existence of file before |
|
|
|
115 awk '{ printf "\"%s\"",$0}' "${attr}/${id}" 2>/dev/null \ |
|
|
|
116 || printf '""' |
|
|
|
117 done |
|
|
|
118 printf '\n' |
|
|
|
119 done |
|
|
|
120 IFS=$OLDIFS |
|
|
|
121 exit 0 |
|
|
|
122 } |
|
|
|
123 |
|
|
|
124 # delete identifier from attributes |
|
|
|
125 # $1 identifier |
|
|
|
126 delete() { |
|
|
|
127 cd "$REPO" |
|
|
|
128 SEEN=0 |
|
|
|
129 for attribute in * |
|
|
|
130 do |
|
|
|
131 if [ -f "${attribute}/${1}" ] |
|
|
|
132 then |
|
|
|
133 git rm "${attribute}/${1}" |
|
|
|
134 git commit -m "Delete ${attribute} ${1}" "${attribute}/${1}" |
|
|
|
135 rmdir "$attribute" 2> /dev/null |
|
|
|
136 SEEN=1 |
|
|
|
137 fi |
|
|
|
138 done |
|
|
|
139 |
|
|
|
140 # did we find it? |
|
|
|
141 if [ "$SEEN" -eq 0 ] |
|
|
|
142 then |
|
|
|
143 printf "%s is not in the library!\n" "$1" |
|
|
|
144 exit 1 |
|
|
|
145 else |
|
|
|
146 exit 0 |
|
|
|
147 fi |
|
|
|
148 } |
|
|
|
149 |
|
|
|
150 # displays list of identifiers |
|
|
|
151 show_list() { |
|
|
|
152 cd "$REPO" |
|
|
|
153 find . -name '.git' -prune -o -type f -print | cut -d '/' -f 3 | sort | uniq -c | \ |
|
|
|
154 awk '{ for(i=2;i<=NF;i=i+1) { printf "%s ", $i } |
|
|
|
155 printf "(%i)\n", $1 |
|
|
|
156 }' |
|
|
|
157 exit 0 |
|
|
|
158 } |
|
|
|
159 |
|
|
|
160 # displays attributes used |
|
|
|
161 show_attributes() { |
|
|
|
162 cd "$REPO" |
|
|
|
163 find . -name '.git' -prune -o -type f -print | cut -d '/' -f 2 | sort | uniq -c | \ |
|
|
|
164 awk '{ for(i=2;i<=NF;i=i+1) { printf "%s ", $i } |
|
|
|
165 printf "(%i)\n", $1 |
|
|
|
166 }' |
|
|
|
167 exit 0 |
|
|
|
168 } |
|
|
|
169 |
|
|
|
170 # add/modify a value |
|
|
|
171 # $@ identifier / attr / value / attr / value / .... |
|
|
|
172 # shift to have attr / value again and again |
|
|
|
173 add_value() { |
|
|
|
174 cd "$REPO" |
|
|
|
175 ID="$1" |
|
|
|
176 shift |
|
|
|
177 |
|
|
|
178 while [ "$#" -gt 1 ] |
|
|
|
179 do |
|
|
|
180 ATTRIBUTE="$1" |
|
|
|
181 VALUE="$2" |
|
|
|
182 shift 2 |
|
|
|
183 |
|
|
|
184 mkdir -p "$ATTRIBUTE" |
|
|
|
185 printf '%s' "$VALUE" > "${ATTRIBUTE}/${ID}" |
|
|
|
186 git add "${ATTRIBUTE}/${ID}" |
|
|
|
187 git commit -m "Modify ${ATTRIBUTE} on ${ID}" "${ATTRIBUTE}/${ID}" |
|
|
|
188 done |
|
|
|
189 exit 0 |
|
|
|
190 } |
|
|
|
191 |
|
|
|
192 # returns identifiers having attribute=value |
|
|
|
193 # $1 attribute |
|
|
|
194 # $2 value |
|
|
|
195 search_value() { |
|
|
|
196 cd "$REPO" |
|
|
|
197 shift |
|
|
|
198 |
|
|
|
199 RESULT=$(mktemp /tmp/dossier.XXXXXXXXXXXX) |
|
|
|
200 COUNT=0 |
|
|
|
201 if [ -f "$RESULT" ] |
|
|
|
202 then |
|
|
|
203 while [ "$#" -gt 1 ] |
|
|
|
204 do |
|
|
|
205 ATTRIBUTE="$1" |
|
|
|
206 NEGATE="" |
|
|
|
207 if [ "${ATTRIBUTE#!}" -ne "${ATTRIBUTE}" ] |
|
|
|
208 then |
|
|
|
209 ATTRIBUTE="${ATTRIBUTE#!}" |
|
|
|
210 NEGATE=v |
|
|
|
211 fi |
|
|
|
212 VALUE="$2" |
|
|
|
213 shift 2 |
|
|
|
214 if [ ! -d "$ATTRIBUTE" ] |
|
|
|
215 then |
|
|
|
216 printf 'The attribute %s do not exists\n' "$ATTRIBUTE" |
|
|
|
217 exit 5 |
|
|
|
218 fi |
|
|
|
219 grep "-rl${NEGATE}" "$VALUE" "$ATTRIBUTE" | cut -d '/' -f 2 >> "$RESULT" |
|
|
|
220 COUNT=$(( COUNT + 1 )) |
|
|
|
221 done |
|
|
|
222 sort "$RESULT" | uniq -c | \ |
|
|
|
223 awk -v count=$COUNT \ |
|
|
|
224 '{ if($1==count) { |
|
|
|
225 $1="" # remove uniq result |
|
|
|
226 gsub(/^[ ]+/,"",$0) # remove leading space due to uniq |
|
|
|
227 print |
|
|
|
228 }}' |
|
|
|
229 else |
|
|
|
230 printf 'Cannot create a temporary file in /tmp\n' |
|
|
|
231 exit 6 |
|
|
|
232 fi |
|
|
|
233 |
|
|
|
234 exit 0 |
|
|
|
235 } |
|
|
|
236 |
|
|
|
237 # returns list of identifiers in a attribute |
|
|
|
238 # $1 attribute |
|
|
|
239 list() { |
|
|
|
240 cd "$REPO" |
|
|
|
241 grep -r . "$1" | cut -d '/' -f 2- | sort |
|
|
|
242 exit 0 |
|
|
|
243 } |
|
|
|
244 |
|
|
|
245 # displays usage |
|
|
|
246 usage() { |
|
|
|
247 printf '%s\n' \ |
|
|
|
248 "Get help" \ |
|
|
|
249 ": dossier help" \ |
|
|
|
250 "" \ |
|
|
|
251 "Export data as CSV" \ |
|
|
|
252 ": dossier export" \ |
|
|
|
253 "" \ |
|
|
|
254 "Import data from CSV" \ |
|
|
|
255 ": dossier import file.csv" \ |
|
|
|
256 "" \ |
|
|
|
257 "Show collections, register collections, switch current collection" \ |
|
|
|
258 ": dossier collections [register path name] [name]" \ |
|
|
|
259 "" \ |
|
|
|
260 "Show items and display informations about an item" \ |
|
|
|
261 ": dossier show [attributes] [identifier]" \ |
|
|
|
262 "" \ |
|
|
|
263 "Look at attributes, search items having some values" \ |
|
|
|
264 ": dossier search [attribute [value]] ... [attribute [value]] ..." \ |
|
|
|
265 "" \ |
|
|
|
266 "Add / Modify attributes values on an item" \ |
|
|
|
267 ": dossier identifier attribute value ... attribute value ..." |
|
|
|
268 exit 0 |
|
|
|
269 } |
|
|
|
270 |
|
|
|
271 switch() { |
|
|
|
272 if [ ! -L "${REPOSITORY}/${1}" ] |
|
|
|
273 then |
|
|
|
274 printf 'Collection %s is not registered\n' "$1" |
|
|
|
275 exit 9 |
|
|
|
276 else |
|
|
|
277 printf 'Switching to collection %s\n' "$1" |
|
|
|
278 printf 'CONTEXT=%s\n' $1 > "${REPOSITORY}/current" |
|
|
|
279 exit $? |
|
|
|
280 fi |
|
|
|
281 } |
|
|
|
282 |
|
|
|
283 collections() { |
|
|
|
284 ls "$REPOSITORY" | grep -v 'current' | sed "s/^${CONTEXT}$/& */" |
|
|
|
285 exit 0 |
|
|
|
286 } |
|
|
|
287 |
|
|
|
288 # create symlink to register a collection |
|
|
|
289 # $1 absolute path to collection |
|
|
|
290 # $2 name of collection |
|
|
|
291 register() { |
|
|
|
292 if [ -d "$1" ] |
|
|
|
293 then |
|
|
|
294 if ! expr "$1" : '^/' >/dev/null |
|
|
|
295 then |
|
|
|
296 printf 'Aborting, the path of the collection must be an absolute path. %s is not valid\n' "$1" |
|
|
|
297 fi |
|
|
|
298 test -L "${REPOSITORY}/${2}" && rm "${REPOSITORY}/${2}" |
|
|
|
299 ln -s "$1" "${REPOSITORY}/${2}" |
|
|
|
300 printf "%s registered. Use it as default with\n\t%s collections %s\n" "$2" "$0" "$2" |
|
|
|
301 exit 0 |
|
|
|
302 else |
|
|
|
303 printf 'Aborting, %s is not a directory\n' "$2" |
|
|
|
304 exit 8 |
|
|
|
305 fi |
|
|
|
306 } |
|
|
|
307 |
|
|
|
308 |
|
|
|
309 # commands not requiring a repository set |
|
|
|
310 if [ "$1" = "help" ] ; then usage ; fi |
|
|
|
311 |
|
|
|
312 if [ "$1" = "collections" ]; then |
|
|
|
313 if [ "$#" -eq 1 ]; then collections ; fi |
|
|
|
314 if [ "$#" -eq 2 ]; then switch "$2" ; fi |
|
|
|
315 if [ "$2" = "register" ] && [ "$#" -eq 4 ]; then register "$3" "$4" ; fi |
|
|
|
316 fi |
|
|
|
317 |
|
|
|
318 # quit if CONTEXT is not set |
|
|
|
319 test -n "$CONTEXT" || exit 10 |
|
|
|
320 |
|
|
|
321 |
|
|
|
322 if [ "$1" = "import" ] && [ -f "${OLDPWD}/${2}" ]; then import_csv "${OLDPWD}/${2}" ; fi |
|
|
|
323 if [ "$1" = "export" ] ; then export_csv ; fi |
|
|
|
324 if [ "$1" = "rm" ] && [ "$#" -eq 2 ] ; then delete "$2" ; fi |
|
|
|
325 |
|
|
|
326 # dealing with identifiers |
|
|
|
327 if [ "$1" = "show" ] |
|
|
|
328 then |
|
|
|
329 if [ "$#" -eq 1 ]; then show_list ; fi |
|
|
|
330 if [ "$#" -eq 2 ]; then |
|
|
|
331 if [ "$2" = "attributes" ] |
|
|
|
332 then |
|
|
|
333 show_attributes_values |
|
|
|
334 else |
|
|
|
335 show "$2" |
|
|
|
336 fi |
|
|
|
337 fi |
|
|
|
338 fi |
|
|
|
339 |
|
|
|
340 # dealing with attributes |
|
|
|
341 if [ "$1" = "search" ]; |
|
|
|
342 then |
|
|
|
343 if [ "$#" -eq 1 ]; then show_attributes ; fi |
|
|
|
344 if [ "$#" -eq 2 ]; then list "$2" ; fi |
|
|
|
345 if [ "$#" -ge 3 ]; then search_value "$@" ; fi |
|
|
|
346 fi |
|
|
|
347 |
|
|
|
348 if [ "$#" -ge 3 ]; then add_value "$@" ; fi |
|
|
|
349 |
|
|
|
350 # no command, maybe it's an item, try it |
|
|
|
351 if [ "$#" -eq 1 ] && exists "$1" ; then show "$1" ; fi |
|
|
|
352 |
|
|
|
353 usage |
|