o xa;$@snddlZddlZddlmZddlmZddlmZddlmZddlmZGdddej Z e d e dS) N)backend)BackendException)log)config)utilc@seZdZdZddZddZddZdd Zd d Zd d Z ddZ ddZ ddZ ddZ ddZddZddZddZdS) Par2BackendzThis 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 Cstj||zddlaWntyw||_ztj|_Wn t y+d|_Ynwztj |_ Wn t y>d|_ Ynwztj d|_ Wn t ySd|_ Ynwt|j|_dD]}t|j|rrt||t||ddq]|j|_dS)Nr z -q -qz-q -q) _get_put_list_delete _delete_list_query _query_list_retry_cleanup _error_code_move_close)rBackend__init__pexpect ImportError parsed_urlrpar2_redundancy redundancyAttributeError par2_volumesvolumes par2_optionscommon_optionsget_backend_object url_stringwrapped_backendhasattrsetattrgetattr delete_listr)selfrattrr*@/usr/lib/python3/dist-packages/duplicity/backends/par2backend.pyr$s8            zPar2Backend.__init__c CsP|}|||}|}tj|s#tjt t |}t ||| t dd|j|j|jt|f}t|dd\}} | rrt dd|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_dirmkdirappend get_canonicalospathisabsjoinrfsencodegetcwdsymlinksetdatarInforrr fsdecoderrunWarndeletelistdirError get_filenamedeltree) r(method source_pathremote_filenamepar2tempsource_symlink source_target par2createout returncodefiles_to_transferfiler*r*r+transferIsB            zPar2Backend.transfercC||jj||dSN)rLr#r r(localremoter*r*r+putvzPar2Backend.putcCrMrN)rLr#rrOr*r*r+moveyrSzPar2Backend.movec s|}|||}|j||zz||d}|j||d|jt| t| f}t |dd\}}|rt d|td|fdd|jD} | D]} || } |j| | qad |jt| t| f} t | dd\}}|rt d |nt d |Wn tyYn 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).0fcr*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;recompiledecoder r>rrenamer@) r(rC local_pathrDlocal_path_temppar2file par2verifyrHrI par2volumesfilenamerK par2repairr*rXr+get|sN             zPar2Backend.getcCsX|j||}tdt|}|D]}|t|r)|jt|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|}|ddD]}tdt|}|D]}|t|r(|d|qq t|jdr6|j |S|D]}|j |q8dS)zKdelete given filename_list and all .par2 files that belong to them Nrgrr) rhr[r\rr9rUinsertr$r#rr )r( filename_listrirdrYrCr*r*r+r's   zPar2Backend.delete_listcCs@|j}td}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+lists   zPar2Backend.listcCs |jSrN)r#r r(r*r*r+rhs zPar2Backend.unfiltered_listcC|jdSrN)r#rrnr*r*r+ retry_cleanupzPar2Backend.retry_cleanupcCs|j||SrN)r#r)r( operationer*r*r+ error_coderqzPar2Backend.error_codecC |j|SrNr#r)r(rdr*r*r+query zPar2Backend.querycCrurNrv)r(rkr*r*r+ query_listrxzPar2Backend.query_listcCrorN)r#rrnr*r*r+closerqzPar2Backend.closeN)__name__ __module__ __qualname____doc__rrLrRrTrfr<r'rmrhrprtrwryrzr*r*r*r+rs %-1  rpar2) r0r[ duplicityrduplicity.errorsrrrrrrregister_backend_prefixr*r*r*r+s     P