commit 178c5e4636f5d2168423f2d51115a615609e4952
parent 74b03fbe5279a5bc7fac35e5d357dbbb203258e5
Author: Jaromil <jaromil@dyne.org>
Date: Tue, 6 Jan 2015 12:51:31 +0100
backup function now uses notmuch search. also cleaned up merge and using safer refile() to move files
Diffstat:
5 files changed, 96 insertions(+), 132 deletions(-)
diff --git a/src/jaro b/src/jaro
@@ -699,7 +699,6 @@ main()
index) CLEANEXIT=0;
nm_index
- nm compact
;;
search) CLEANEXIT=0; search ${PARAM} ;;
diff --git a/src/zlibs/addressbook b/src/zlibs/addressbook
@@ -70,7 +70,7 @@ insert_address() {
}
remove_address() {
- warning "remove_address() TODO in abook branch"
+ error "remove_address() TODO in abook branch"
return 0
}
@@ -213,7 +213,7 @@ learn() {
}
forget() {
- warning "forget() TODO in abook branch"
+ error "forget() TODO in abook branch"
return 0
# func "forget sender from mail in stdin"
diff --git a/src/zlibs/helpers b/src/zlibs/helpers
@@ -73,6 +73,34 @@ s/"/\"/g
'
}
+# move an email file from a maildir to another
+# keeping cur/new/tmp positioning
+refile() {
+ src="$1"
+ dst="$2"
+
+ [[ "$2" = "" ]] && {
+ error "refile() needs 2 args: source file and destination maildir"
+ return 1
+ }
+
+ [[ -r "$1" ]] || {
+ error "refile origin file not existing: $1"
+ return 1
+ }
+
+ # weak destination check, called should use maildircheck anyway
+ [[ -d "$2"/new ]] || {
+ error "refile destination not a maildir: $2"
+ return 1
+ }
+
+ srcarr=( ${=src//\// } )
+ srcnum=${#srcarr}
+ pos=${srcarr[$(( $srcnum - 1 ))]}
+ func "mv $src ${dst}/${pos}/"
+ [[ $DRYRUN = 0 ]] && mv $src ${dst}/${pos}/
+}
autostart() {
diff --git a/src/zlibs/maildirs b/src/zlibs/maildirs
@@ -147,63 +147,50 @@ rmdupes() {
}
merge() {
- src=${1}
- dst=${2}
+ _src=${1}
+ _dst=${2}
- { test "$src" = "$dst" } && {
- error "Cannot merge same directory in itself: $src = $dst"
- return 1 }
-
- { maildircheck "$src" } || {
- error "Source is not a maildir: $src"
- return 1 }
+ [[ "$_src" = "$_dst" ]] && {
+ error "Cannot merge same directory in itself: $_src = $_dst"
+ return 1 }
- { maildircheck "$dst" } || {
- error "Destination is not a maildir: $dst"
- return 1 }
+ maildircheck "$_src"
+ [[ $? = 0 ]] || {
+ error "Source is not a maildir: $_src"
+ return 1
+ }
+
+ maildircheck "$_dst"
+ [[ $? = 0 ]] || {
+ error "Destination is not a maildir: $_dst"
+ return 1
+ }
# merge does not uses deliver() because
# the new-flag and read-flags must be kept intact.
# it will abort on any single error on moving each file.
- notice "Merging maildir ${src} into ${dst}"
- c=0
- fr=`${=find} ${src}/cur -type f`
+ notice "Merging maildir ${_src} into ${_dst}"
+ fr=`${=find} ${_src} -type f`
- # TODO: preserve timestamps using cp hardlinks
- # cp -p -r -l source/date target/
- # rm -rf source/data
- for i in ${(f)fr}; do
- mv "$i" "${dst}/cur/"; c=$(($c + 1))
- { test $? = 0 } || {
- error "error moving file: $i"
- error "merge aborted."
- return 1 }
- done
- fr=`${=find} ${src}/new -type f`
- for i in ${(f)fr}; do
- mv "$i" "${dst}/new/"; c=$(($c + 1))
- { test $? = 0 } || {
- error "error moving file: $i"
- error "merge aborted."
- return 1 }
- done
- fr=`${=find} ${src}/tmp -type f`
+ c=0
for i in ${(f)fr}; do
- mv "$i" "${dst}/tmp/"; c=$(($c + 1))
- { test $? = 0 } || {
- error "error moving file: $i"
- error "merge aborted."
- return 1 }
+ refile "$i" "$_dst"
+ [[ $? = 0 ]] || {
+ # bail out on every single error
+ error "Error refiling emails to destination maildir"
+ error "Operation aborted, $c files moved."
+ return 1
+ }
+ c=$(($c + 1))
done
notice "$c mails succesfully moved"
- act "Removing source directory ${src}"
- ${=rm} -r "${src}"
-
- act "Purging duplicates in destination"
- rmdupes "${dst}"
-
- act "Done. All mails merged into ${dst}"
+ [[ $DRYRUN = 0 ]] && {
+ act "Removing source directory ${_src}"
+ ${=rm} -r "${_src}"
+ }
+
+ act "Done. All mails merged into ${_dst}"
}
diff --git a/src/zlibs/search b/src/zlibs/search
@@ -235,98 +235,48 @@ search() {
backup() {
id=$datestamp.$RANDOM
- mairixrc=$TMPDIR/backup.rc.$id
- mairixdb=$TMPDIR/backup.db.$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
+ c=0
+
+ dst=${PARAM[1]}
+ shift 1 PARAM
+ expr=${PARAM}
+
+ notice "Backup of mails matched by search expression"
+ act "expression: $expr"
+ act "destination folder: $dst"
+ [[ $DRYRUN = 1 ]] && act "Dryrun mode enabled"
+
+ [[ $DRYRUN = 0 ]] && {
+ maildircheck "$dst"
+ [[ $? = 0 ]] || {
+ error "First argument of backup command must be an existing maildir"
+ return 1
+ }
}
- dst=${fold[${#fold}]}
- { test -r "$dst" } || { maildirmake "${dst}" }
-
- { test ${#expr} = 0 } && {
+ [[ "$expr" = "" ]] && {
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
}
- # forge the folder string for mairix conf
- folders=""
- for f in ${=fold}; do
- { test $f = $dst } || {
- folders="$folders`basename $f`:" }
- done
-
- notice "Backup of all mails in '$folders' matching expression '$expr'"
+ read_account
+ nm_setup
- act "Indexing folders"
- cat <<EOF > ${mairixrc}
-base=$basedir
-database=$mairixdb
-maildir=${folders}
-mformat=maildir
-EOF
- mairix -F -f ${mairixrc} 2> /dev/null
- tempdst="bck.`basename $dst`"
- notice "Backup of $dst"
- rm -f ${mairixrc}; cat <<EOF > ${mairixrc}
-base=$basedir
-database=$mairixdb
-maildir=${folders}
-mfolder=$tempdst
-mformat=maildir
-EOF
- mairix -F -f ${mairixrc} -t -M ${expr}
- { test -r $basedir/$tempdst } && {
- merge $basedir/$tempdst $dst
- notice "Destination folder size is `du -hs $dst | awk '{print $1}'`"
+ _res=`nm_search ${=expr}`
+
+ [[ $DRYRUN = 0 ]] && {
+ for i in ${(f)_res}; do
+ refile $i $dst
+ [[ $? = 0 ]] || {
+ # bail out on every single error
+ error "Error refiling emails to destination maildir"
+ error "Operation aborted"
+ return 1
+ }
+ done
}
+
- ${=rm} ${mairixrc}
- ${=rm} ${mairixdb}
-
- act "Backup completed to destination: $dst"
}