commit 4441325aa6ee9e6f9e9b982ca7032d7501c3e99f
parent 483b0da4d14b2fada3e58b3e5dbf2450b194cd0a
Author: Jaromil <jaromil@dyne.org>
Date: Sun, 17 Jun 2012 14:57:22 +0200
search and backup improvements (intuitive args) and better stats
Diffstat:
M | src/jaro | | | 263 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------------- |
1 file changed, 219 insertions(+), 44 deletions(-)
diff --git a/src/jaro b/src/jaro
@@ -448,6 +448,25 @@ option_value() {
#First argument, the option (something like "-s")
<<< ${opts[$1]}
}
+
+# checks if its a maildir
+# returns 0 (success) if yes
+# no in all other cases
+maildircheck() {
+ { test -r $1 } || {
+ error "Maildir not existing: $1"
+ return 1 }
+ { test -w $1 } || {
+ error "Directory not writable: $1"
+ return 1 }
+ { test -r $1/cur } \
+ && { test -r $1/new } \
+ && { test -r $1/tmp } \
+ && { return 0 } # Yes is a maildir
+ func "Not a maildir: $1"
+ return 1
+}
+
maildirmake() {
if [ -z $1 ]; then
@@ -816,8 +835,26 @@ EOF
}
stats() {
- mailstat -k $WORKDIR/log/procmail.log
- return $?
+ # make index of all maildirs
+ notice "Maildirs status"
+ typeset -alU ml
+ typeset -al empty
+ for i in `ls $MAILDIRS`; do
+ { maildircheck $MAILDIRS/${i} } || { continue }
+ cur=`ls $MAILDIRS/$i/cur | wc -l`
+ new=`ls $MAILDIRS/$i/cur | wc -l`
+ tot=$(( $cur + $new ))
+ ml+=("$tot\t:: $i\t ($cur/$new)")
+ done
+ for m in ${ml}; do
+ { test ${m[1]} = "0" } && {
+ empty+=${m}
+ continue }
+ act "$m"
+ done
+ { test ${#empty} != 0 } && { emptystr="(${#empty} are empty)" }
+ notice "Total maildirs: ${#ml} $emptystr"
+ return 0
}
######
@@ -1326,17 +1363,90 @@ search() {
{ which mairix > /dev/null } || { return 1 }
id=$RANDOM
rc=$TMPDIR/search.conf.$id
+ typeset -al expr
+ typeset -al fold
+ # intelligent parse of args, position independent
+ # check if its a folder, if not is an expression
+ mlstr="all folders"; ml=""; c=0
+ basedir=$MAILDIRS
+ # check if the name of a maildir is among params
+ for p in ${PARAM}; do
+ c=$(( $c + 1 ))
+ func "checking param: ${p}"
+ if [ -r ${p} ]; then
+
+ { maildircheck ${p} } && {
+ fold+=(${p})
+ { test ${#fold} = 1 } && {
+ # base path is the dir of the first folder
+ pushd `dirname ${p}`
+ basedir=`pwd`
+ popd }
+ }
+
+ elif [ -r ${MAILDIRS}/${p} ]; then
+
+ { maildircheck ${MAILDIRS}/${p} } && { fold+=(${MAILDIRS}/${p}) }
+
+ else # not a folder, add it to expressions array
+ expr+=(${p})
+ fi
+ done
+
+
+ # now fold is an array of specified folders
+ # expr is an array of specified search expressions
+
+ # to search only one maildir then we need to index it
+ # separate from the rest of the maildirs
+ if [ ${#fold} != 0 ]; then
+ { test ${#expr} = 0 } && {
+ error "no search expression given for folders ${fold[@]}"
+ return 1 }
+ # forge the folder string for mairix conf
+ folders=""; for f in ${fold}; do folders="$folders`basename $f`:"; done
+ cat <<EOF > $rc
+base=$basedir
+database=$TMPDIR/search.db.$id
+maildir=${folders}
+mfolder=$TMPDIR/search.result.$id
+mformat=maildir
+EOF
+
+ exitcode=1
+ act "Indexing ${folders}"
+ mairix -F -f $rc 2> /dev/null
+ { test $? = 0 } && {
+ act "Searching for: ${expr}"
+ found=`mairix -F -f $rc ${=expr} 2> /dev/null | awk '{ print $2}'`
+ if [ $found != 0 ]; then
+ mutt -F $MUTTDIR/rc -R -f $TMPDIR/search.result.$id
+ notice "Found $found matches looking for '$expr' in $folders"
+ find $TMPDIR/search.result.$id
+ cat $rc
+ exitcode=0
+ else error "No matches found."; fi
+ }
+
+
+ rm -f $rc
+ rm -f $TMPDIR/search.db.$id
+# rm -rf $TMPDIR/search.result.$id
+ return $exitcode
+
+
+ ####################################################
+ else # no folder specified on commandline, search all
# make index if no params given
- ml=""; c=0
- for i in `ls $MAILDIRS`; do
+ c=0
+ for i in `ls $MAILDIRS`; do
# is it a maildir?
- { test -r $MAILDIRS/${i}/cur } \
- && { test -r $MAILDIRS/${i}/new } \
- && { test -r $MAILDIRS/${i}/tmp } \
- && { c=`expr $c + 1`; ml="$ml:$i" }
- done
- func "searching maildirs: $ml"
+ { maildircheck $MAILDIRS/${i} } && {
+ c=`expr $c + 1`; ml="$ml:$i" }
+ done
+ fi
+
cat <<EOF > $rc
base=$MAILDIRS
database=$WORKDIR/search.db
@@ -1351,14 +1461,20 @@ EOF
mairix -F -f $rc
rm -f $rc
exitcode=$?
- { test $exitcode = 0 } && { notice "Done." } || { error "Error, indexing aborted." }
+ if [ $exitcode = 0 ]; then notice "Done."
+ else error "Error, indexing aborted."; fi
+ rm -f $rc
return $exitcode
}
- act "Searching maildirs for: $PARAM"
- act -n ""
- mairix -F -f $rc ${=PARAM} 2> /dev/null
- { test $? = 0 } && { mutt -F $MUTTDIR/rc -R -f $TMPDIR/search.result.$id }
- rm -rf $TMPDIR/search.result.$id
+ act "Searching $mlstr for: ${expr}"
+ exitcode=1
+ found=`mairix -F -f $rc ${=expr} 2> /dev/null | awk '{print $2}'`
+ if [ $found != 0 ]; then
+ mutt -F $MUTTDIR/rc -R -f $TMPDIR/search.result.$id
+ notice "Found $found matches looking for '$expr' in all mail folders"
+ exitcode=0
+ else error "Nothing found matching '$expr'"; fi
+ rm -rf $TMPDIR/search.*.$id
rm -f $rc
}
##############
@@ -1379,41 +1495,100 @@ open_file() {
######################
# Maildir manipulation
backup() {
- src=${PARAM[1]}
- dst=${PARAM[2]}
- expire=${PARAM[3]}
- if ! [ -r ${src}/cur ]; then
- error "No maildir found in $src"
+ id=$RANDOM
+ rc=$TMPDIR/backup.conf.$id
+ typeset -al expr
+ typeset -al fold
+
+ src=""; dst=""
+ basedir=$MAILDIRS
+ # check if the name of a maildir is among params
+ # we need at least 2 maildirs, the second is the destination
+ for p in ${PARAM}; do
+ c=$(( $c + 1 ))
+
+ if [ $c = ${#PARAM} ]; then
+ # last one is always the destination
+ func "destination is ${p}"
+ fold+=(${p})
+
+ elif [ -r ${p} ]; then
+
+ { maildircheck ${p} } && {
+ func "param ${p} is a maildir"
+ fold+=(${p})
+ { test ${#fold} = 1 } && {
+ # base path is the dir of the first folder
+ pushd `dirname ${p}`
+ basedir=`pwd`
+ popd }
+ }
+
+ elif [ -r ${MAILDIRS}/${p} ]; then
+
+ { maildircheck ${MAILDIRS}/${p} } && {
+ func "param ${p} is a jaro maildir"
+ fold+=(${MAILDIRS}/${p})
+ }
+
+ else # not a folder, add it to expressions array
+ func "param ${p} is an expression"
+ expr+=(${p})
+ fi
+ done
+
+ { test ${#fold} -lt 2 } && {
+ error "Not enough folders specified for backup: minimum is 2"
+ act "When specifying more than 2, the last one is the destination"
return 1
- fi
- if ! [ -r ${dst}/cur ]; then
- maildirmake "${dst}"
- fi
- if [ -z $expire ]; then
- error "No expiration date set for backup, please indicate how many days old"
+ }
+
+ dst=${fold[${#fold}]}
+ { test -r $dst } && {
+ error "Backup destination already exists: $dst"
+ return 1 }
+
+ maildirmake "${dst}"
+
+ { test ${#expr} = 0 } && {
+ error "No expression set for backup, please indicate what you want to backup"
+ act "For example: d:10y-2y (all mails older than 1 year up to 10 years ago"
+ act "Or a simple search string, all expressions can be verified using search."
return 1
- fi
- notice "Backup of all read mails older than $expire days"
- oldread=`find $src/cur -type f | wc -l`
- oldunread=`find $src/new -type f | wc -l`
+ }
- newread=`find $src/cur -type f -mtime +$expire | wc -l`
- newunread=`find $src/new -type f -mtime +$expire | wc -l`
+ # forge the folder string for mairix conf
+ folders=""
+ for f in ${fold}; do
+ { test $f = $dst } || {
+ folders="$folders`basename $f`:" }
+ done
- act "from: (${oldread}/${oldunread} read/unread) maildir $src"
- if [ $newunread != 0 ]; then # use some highlight to signal long due unread
- act "to: ($fg[red]${newread}/${newunread} read/unread$fg[white]) maildir $fg_bold[white]$dst$fg_no_bold[white]"
- else
- act "to: (${newread}/${newunread} read/unread) maildir $dst"
- fi
+ notice "Backup of all mails in '$folders' matching expression '$expr'"
- if [ $DRYRUN = 1 ]; then return 0; fi
+ act "Indexing folders"
+ cat <<EOF > $rc
+base=$basedir
+database=$TMPDIR/backup.db.$id
+maildir=${folders}
+mfolder=$dst
+mformat=maildir
+EOF
+ mairix -F -f $rc 2> /dev/null
+ act "Copying matches to $dst"
+ pushd `dirname $dst`; basedir=`pwd`; popd
+ rm -f $rc; cat <<EOF > $rc
+base=$basedir
+database=$TMPDIR/backup.db.$id
+maildir=${folders}
+mfolder=$dst
+mformat=maildir
+EOF
+ found=`mairix -F -f $rc -H ${expr} 2> /dev/null | awk '{print $2}'`
+ notice "$found matches found, destination folder size is `du -hs $basedir/$dst | awk '{print $1}'`"
- find $src/cur -mtime +$expire -type f -exec mv {} $dst/cur/ \;
- find $src/new -mtime +$expire -type f -exec mv {} $dst/new/ \;
+ # TODO: remove matched messages from source folders using rmdupes
- notice "Operation completed, current maildir sizes:"
- du -hs $src $dst
}
rmdupes() {