o ´xa;$ã@snddlZddlZddlmZddlmZddlmZddlmZddlmZGdd„dej ƒZ e  d e ¡dS) éN)Úbackend)ÚBackendException)Úlog)Úconfig)Úutilc@s€eZdZdZdd„Zdd„Zdd„Zdd „Zd d „Zd d „Z dd„Z dd„Z dd„Z dd„Z dd„Zdd„Zdd„Zdd„ZdS)Ú Par2BackendzãThis backend wrap around other backends and create Par2 recovery files before the file and the Par2 files are transfered with the wrapped backend. If a received file is corrupt it will try to repair it on the fly. c Csòtj ||¡zddlaWnty‚w||_ztj|_Wn t y+d|_Ynwztj |_ Wn t y>d|_ Ynwztj d|_ Wn t ySd|_ Ynwt |j¡|_dD]}t|j|ƒrrt||t||dd…ƒƒq]|j|_dS)Nré éz -q -qz-q -q) Ú_getÚ_putÚ_listÚ_deleteÚ _delete_listÚ_queryÚ _query_listÚ_retry_cleanupÚ _error_codeÚ_moveÚ_close)rÚBackendÚ__init__ÚpexpectÚ ImportErrorÚ parsed_urlrÚpar2_redundancyÚ redundancyÚAttributeErrorÚ par2_volumesÚvolumesÚ par2_optionsÚcommon_optionsÚget_backend_objectÚ url_stringÚwrapped_backendÚhasattrÚsetattrÚgetattrÚ delete_listr)ÚselfrÚattr©r*ú@/usr/lib/python3/dist-packages/duplicity/backends/par2backend.pyr$s8  ÿ   ÿ   ÿ  ÿ € zPar2Backend.__init__c CsP| ¡}| ¡| |¡}| ¡}tj |¡s#tj t  t  ¡¡|¡}t  || ¡¡|  ¡t  d¡d|j|j|jt | ¡¡f}t |dd¡\}} | rrt  d¡d|j|jt | ¡¡f}t |dd¡\}} | srt  d¡| ¡g} | sŠ| ¡D] } |  | | ¡¡q~nt  d| ¡|||ƒ| D] } || |  ¡ƒq˜| ¡dS) a3create Par2 files and transfer the given file and the Par2 files with the wrapped backend. Par2 must run on the real filename or it would restore the temp-filename later on. So first of all create a tempdir and symlink the soure_path with remote_filename into this. zCreate Par2 recovery fileszpar2 c -r%d -n%d %s "%s"NTzDFailed to create par2 file with requested options, retrying with -n1zpar2 c -r%d -n1 %s "%s"z'Successfully created par2 file with -n1z-FAILED to create par2 file with returncode %d)Úget_temp_in_same_dirÚmkdirÚappendÚ get_canonicalÚosÚpathÚisabsÚjoinrÚfsencodeÚgetcwdÚsymlinkÚsetdatarÚInforrr ÚfsdecoderÚrunÚWarnÚdeleteÚlistdirÚErrorÚ get_filenameÚdeltree) r(ÚmethodÚ source_pathÚremote_filenameÚpar2tempÚsource_symlinkÚ source_targetÚ par2createÚoutÚ returncodeÚfiles_to_transferÚfiler*r*r+ÚtransferIsB     þ   ÿ  ÿ  zPar2Backend.transfercCó| |jj||¡dS©N)rLr#r ©r(ÚlocalÚremoter*r*r+ÚputvózPar2Backend.putcCrMrN)rLr#rrOr*r*r+ÚmoveyrSzPar2Backend.movec s’| ¡}| ¡| |¡}|j ||¡zªzˆ| |d¡}|j | ¡|¡d|jt |  ¡¡t |  ¡¡f}t   |dd¡\}}|rœt   d|¡t d| ¡¡‰‡fdd„|j ¡Dƒ} | D]} | | ¡} |j | | ¡qad |jt |  ¡¡t |  ¡¡f} t   | dd¡\}}|r•t  d |¡nt   d |¡Wn ty¦Yn wW| |¡| ¡dSW| |¡| ¡dS| |¡| ¡w) atransfer remote_filename and the related .par2 file into a temp-dir. remote_filename will be renamed into local_path before finishing. If "par2 verify" detect an error transfer the Par2-volumes into the temp-dir and try to repair. s.par2zpar2 v %s %s "%s"NTz!File is corrupt. Try to repair %sz%s\.vol[\d+]*\.par2cs g|] }ˆ t |¡¡r|‘qSr*)Úmatchrr9)Ú.0Úf©Úcr*r+Ú —s z#Par2Backend.get..zpar2 r %s %s "%s"zFailed to repair %szRepair successful %s)r,r-r.r#r r?r rr9r/rr:rr;ÚreÚcompileÚdecoder r>rÚrenamer@) r(rCÚ local_pathrDÚlocal_path_tempÚpar2fileÚ par2verifyrHrIÚ par2volumesÚfilenamerKÚ par2repairr*rXr+Úget|sN    þ   þ€ þ€  ý   ÿ zPar2Backend.getcCsX|j |¡| ¡}t dt |¡¡}|D]}| t |¡¡r)|j t |¡¡qdS)z2delete given filename and its .par2 files ú%s(?:\.vol[\d+]*)?\.par2N) r#r Úunfiltered_listr[r\rr9rUr4)r(rdÚ remote_listrYrCr*r*r+r<­s €þzPar2Backend.deletecCs†| ¡}|dd…D]}t dt |¡¡}|D]}| t |¡¡r(| d|¡qq t|jdƒr6|j  |¡S|D]}|j  |¡q8dS)zKdelete given filename_list and all .par2 files that belong to them Nrgrr) rhr[r\rr9rUÚinsertr$r#rr )r(Ú filename_listrirdrYrCr*r*r+r'¹s €ý  ÿzPar2Backend.delete_listcCs@|j ¡}t d¡}g}|D]}| t |¡¡r| |¡q|S)z Return list of filenames (byte strings) present in backend Files ending with ".par2" will be excluded from the list. z (?!.*\.par2$))r#r r[r\rUrr9r.)r(rirYÚ filtered_listrdr*r*r+ÚlistËs   €zPar2Backend.listcCs |j ¡SrN)r#r ©r(r*r*r+rhÚs zPar2Backend.unfiltered_listcCó|j ¡dSrN)r#rrnr*r*r+Ú retry_cleanupÝózPar2Backend.retry_cleanupcCs|j ||¡SrN)r#r)r(Ú operationÚer*r*r+Ú error_codeàrqzPar2Backend.error_codecCó |j |¡SrN©r#r)r(rdr*r*r+Úqueryãó zPar2Backend.querycCrurNrv)r(rkr*r*r+Ú query_listærxzPar2Backend.query_listcCrorN)r#rrnr*r*r+ÚcloseérqzPar2Backend.closeN)Ú__name__Ú __module__Ú __qualname__Ú__doc__rrLrRrTrfr<r'rmrhrprtrwryrzr*r*r*r+rs %-1  rÚpar2) r0r[Ú duplicityrÚduplicity.errorsrrrrrrÚregister_backend_prefixr*r*r*r+Ús     P