o La=@s~ddlmZddlZddlZddlmZddlmZddlmZddl ZGdddej j Z ej de ej jdgdS) )strN)log)util)BackendExceptionc@s`eZdZdZdZdZddZddZdd Zd d Z d d Z ddZ ddZ ddZ ddZdS) GDriveBackendz1Connect to remote store using Google Drive API V3diPc Cstjj||zddlm}ddlm}Wnty*}zt dt |d}~wwi|_ i|_ i|_ i|_d|_d|jvrYddi|_ d|jddi|_ d d i|_ d d i|_n!d |jvrvdd i|_ d d i|_ d d i|_|jd d|_nt d|jdur|jd|j}n|j}dtjvr|tjd}|j|krt d|j|fndtjvrLdtjvrLddlm}ddlm}d}tjtjdrttjdd } t| }Wdn1swY|r|j s<|r|j!r|j"r|#|n!|$tjddg} | j%d|krt d| j%d|f| &}ttjdd} t'|| Wdn 1s7wY|j(|krKt d|j(|fnt d|dd|d|_)|j rb|j d} n |jrj|j} nd} |j*d } | D]a} | s{qtd!| d"| d#}|j)+j,d,|d$d%d&|j |j |j |j-}|.d'g}t/|dkr| d(| gd)}|0|j |j)+j1d,|d*d+|j-}n|d}|d*} qt| |_2i|_3dS)-Nr)build) CredentialszpGDrive backend requires Google API client installation. Please read the manpage for setup details. Exception: %sdriveIDcorporadrivedriveIdincludeItemsFromAllDrivesTsupportsAllDrivesmyDriveFolderIDuserzVgdrive: backend requires a query paramater should either be driveID or myDriveFolderID@GOOGLE_SERVICE_JSON_FILEzGService account email in the JSON file (%s) does not match the URL (%s)GOOGLE_CLIENT_SECRET_JSON_FILEGOOGLE_CREDENTIALS_FILE)InstalledAppFlow)Requestrbz*https://www.googleapis.com/auth/drive.file client_idz;Client ID in the JSON file (%s) does not match the URL (%s)wbzBClient ID in the credentials file (%s) does not match the URL (%s)zxGOOGLE_SERVICE_JSON_FILE or GOOGLE_CLIENT_SECRET_JSON_FILE environment variable not set. Please read the manpage to fix.v3) credentialsroot/zname = 'z' and 'zR' in parents and mimeType = 'application/vnd.google-apps.folder' and trashed=falsefiles(name,id),nextPageToken)qpageSizefieldsfilesz"application/vnd.google-apps.folder)namemimeTypeparentsid)bodyr#)4 duplicitybackendBackend__init__googleapiclient.discoveryrgoogle.oauth2.service_accountr ImportErrorrrshared_drive_corporashared_drive_idshared_drive_flags_includeshared_drive_flags_supportshared_root_folder_id query_argsusernamehostnameosenvironfrom_service_account_fileservice_account_emailgoogle_auth_oauthlib.flowrgoogle.auth.transport.requestsrpathexistsopenpickleloadvalidexpired refresh_tokenrefreshfrom_client_secrets_file client_config run_consoledumprr splitr$listexecutegetlenupdatecreatefolderid_cache)self parsed_urlrr errrrtokenflowparent_folder_id folder_names folder_namer!results file_list file_metadatarTr*r*B/usr/lib/python3/dist-packages/duplicity/backends/gdrivebackend.pyr.%s                        zGDriveBackend.__init__c Csddlm}t|}||jvrs|j|}z7|jjd|dd|j }|d|krK|dsK|dD]}||j krJt d||f|WSq5Wn|ye}z |j jd kr[WYd}~nd}~wwt d ||f|j|=d ||j f}|jjd|d d d|j|j|j|j }|dg} t| dkrt d|fn"t| dkr| dd}| dd|j|<t d||f| dSt d|fdS)Nr HttpErrorzid,size,name,parents,trashed)fileIdr#r%trashedr'z6GDrive backend: found file '%s' with id %s in ID cacheizBGDrive backend: invalidating '%s' (previously ID %s) from ID cachez3name = '%s' and '%s' in parents and trashed = falsez!files(name,id,size),nextPageToken)r!r#r"r$rz+GDrive backend: multiple files called '%s'.r(zEGDrive backend: found file '%s' with id %s on server, adding to cachez9GDrive backend: file '%s' not found in cache or on serverr*)googleapiclient.errorsrcrfsdecoderUr r$rPr5rOrTrInforespstatusrNr2r3r4rQ FatalError) rVfilenamercfile_id drive_fileparenterrorr!r^r_r*r*ra file_by_namesv             zGDriveBackend.file_by_namecCs||}|dur dS|dS)Nr()rr)rVrmror*r*ra id_by_names zGDriveBackend.id_by_namec Csddlm}t|}||}|drd}nd}tj|j }||j kr+d}d}nd}d}||j ||d } |durd||j gd } | |j td |f|jjd| | d |jj|d }n td||df|jj d| |dd|jj|d }|d|j|<dS)Nr)MediaFileUploadz.gpgzapplication/pgp-encryptedz text/plainTF)mimetype resumable)r%r'z&GDrive backend: creating new file '%s')r) media_body) num_retriesz9GDrive backend: replacing existing file '%s' with id '%s'r()ryrdr*)googleapiclient.httprurrhrrendswithr:r@getsizer%MIN_RESUMABLE_UPLOADrTrRr3rrir r$rSr5rOrU) rV source_pathremote_filenameruro mime_type file_sizerxrzmediar`r*r*ra_putsJ        zGDriveBackend._putc Csddlm}||}|jjdd|di|j}tt |j d&}d}|||}|durB| \} }|dus0WddSWddS1sMwYdS)Nr)MediaIoBaseDownloadrdr(rFr*) r{rrrr r$ get_mediar5rBrrhr% next_chunk) rVr local_pathrrorequestfhdone downloaderrkr*r*ra_gets     "zGDriveBackend._getcCsd}g} |jjd d|jd|jd|d|j|j|j|j }|| dg7}| dd}|dur:nqt dd |D}t|j D]}||vr]||dur]||qKt|S) NT'z' in parents and trashed=falser )r!r"r# pageTokenr$ nextPageTokencss|]}|dVqdS)r%Nr*).0itemr*r*ra 1sz&GDriveBackend._list..r*)r r$rNrT PAGE_SIZEr2r3r4r5rOrPsetrUkeysrradd)rV page_token drive_filesresponse filenamesrmr*r*ra_lists<    zGDriveBackend._listcCsP||}|dkrtdt|fdS|jjdd|i|j dS)Nrsz2File '%s' does not exist while trying to delete itrdr*) rtrWarnrrhr r$deleter5rO)rVrmrnr*r*ra_delete;s  zGDriveBackend._deletecCs2||}|durd}d|iSt|d}d|iS)Nsize)rrint)rVrmrorr*r*ra_queryCs  zGDriveBackend._querycCsDddlm}ddlm}t||rtjjSt||rtjjStjj S)Nr) RefreshErrorrb) google.auth.exceptionsrrgrc isinstancer ErrorCodebackend_not_foundbackend_permission_denied backend_error)rV operationrqrrcr*r*ra _error_codeKs    zGDriveBackend._error_codeN)__name__ __module__ __qualname____doc__rr~r.rrrtrrrrrrr*r*r*rars 3&  rgdrive)builtinsrr:rCr+rrduplicity.errorsrduplicity.backendr,r-rregister_backend uses_netlocextendr*r*r*ras    8