URI: 
       dossier - dossier - console collection manager
   DIR Log
   DIR Files
   DIR Refs
   DIR Tags
   DIR README
   DIR 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