Ë
    -Œ:j!°  ã            &       óÞ  — d Z ddlZddlZddlZddlZddlZddlZddlZddlm	Z	 ddl
mZmZ ddlmZmZ ddlmZ ddlmZmZmZ dd	lmZmZ dd
lmZ ddlmZmZmZmZmZm Z m!Z! ddl"m#Z# erddl$m%Z%  ejL                  e'«      Z(dZ)dZ*e G d„ d«      «       Z+e G d„ d«      «       Z,e G d„ d«      «       Z-e G d„ d«      «       Z. ed¬«       G d„ d«      «       Z/e G d„ d«      «       Z0e G d„ d«      «       Z1e G d „ d!«      «       Z2d"e3d#efd$„Z4d"e3d#e5fd%„Z6e G d&„ d'«      «       Z7e G d(„ d)«      «       Z8 G d*„ d+«      Z9d,e3d#e:e;e3e3f      fd-„Z<d"e3d#e;e=e>f   dz  fd.„Z?d/e3d#e	e;e3e=e>f      fd0„Z@d1d2d3e3d4e3d#e	e;e3e=e>ef      fd5„ZAd6e>d#e3fd7„ZBdd8œd"e3d9ed:   d;e=d<e>d=e=d>e>d?e3d@e3dAe5dBe5dCe5dDedz  d#e7fdE„ZC	 	 	 	 	 	 	 d_dGe3dHe3d1d2dIe5dBe5dAe5dJe5dCe5dKe9dz  dLedz  d#e8fdM„ZDdNe8d#dfdO„ZEdNe8dPe3d#dfdQ„ZFdPe3d#e8fdR„ZGd`dNe8d1d2dSe5dLedz  d#df
dT„ZHdNe8d#dfdU„ZI	 	 dadFdFdFdFdFddddddFdFdFddVœdGe3dz  dHe3dz  d1d2dIe5dBe5dAe5dJe5dCe5dWe:e3   dz  dXe:e3   dz  dYe3dz  dNe3dz  dZe3dz  d[e5dSe5d\e5d]e5e3z  dz  d#e8f$d^„ZJy)bzzShared logic for bucket operations.

This module contains the core buckets logic used by both the CLI and the Python API.
é    N)ÚIterator)Ú	dataclassÚfield)ÚdatetimeÚtimezone)ÚPath)ÚTYPE_CHECKINGÚAnyÚLiteralé   )Ú	constantsÚlogging)ÚBucketNotFoundError)ÚHfUriÚ
StatusLineÚXetFileDataÚdisable_progress_barsÚenable_progress_barsÚparse_datetimeÚparse_hf_uri)Ú_looks_like_hf_url©ÚHfApizhf://buckets/éè  c                   óJ   — e Zd ZU dZeed<   eed<   eed<   eed<   eed<   d„ Z	y)	Ú
BucketInfoaß  
    Contains information about a bucket on the Hub. This object is returned by [`bucket_info`] and [`list_buckets`].

    Attributes:
        id (`str`):
            ID of the bucket.
        private (`bool`):
            Is the bucket private.
        created_at (`datetime`):
            Date of creation of the bucket on the Hub.
        size (`int`):
            Size of the bucket in bytes.
        total_files (`int`):
            Total number of files in the bucket.
    ÚidÚprivateÚ
created_atÚsizeÚtotal_filesc                 ó*  — |j                  d«      | _        |j                  d«      | _        t        |j                  d«      «      | _        |j                  d«      | _        |j                  d«      | _         | j                  j                  di |¤Ž y )Nr   r   Ú	createdAtr    Ú
totalFiles© )	Úpopr   r   r   r   r    r!   Ú__dict__Úupdate)ÚselfÚkwargss     úZ/var/www/html/tokenscope/api/venv/lib/python3.12/site-packages/huggingface_hub/_buckets.pyÚ__init__zBucketInfo.__init__V   so   € Ø—*‘*˜TÓ"ˆŒØ—z‘z )Ó,ˆŒÜ(¨¯©°KÓ)@ÓAˆŒØ—J‘J˜vÓ&ˆŒ	Ø!Ÿ:™: lÓ3ˆÔØˆ�‰×ÑÑ&˜vÓ&ó    N)
Ú__name__Ú
__module__Ú__qualname__Ú__doc__ÚstrÚ__annotations__Úboolr   Úintr,   r%   r-   r+   r   r   >   s)   … ñð  	ƒGØƒMØÓØ
ƒIØÓó'r-   r   c                   ó¸   — e Zd ZU eez  ez  ed<   eed<    ed¬«      Zedz  ed<    ed¬«      Z	e
dz  ed<    ed¬«      Ze
ed	<    ed¬«      Zedz  ed
<   dd„Zy)Ú_BucketAddFileÚsourceÚdestinationN©ÚdefaultÚxet_hashr    F©ÚinitÚmtimeÚcontent_typec                 óð  — d | _         t        | j                  t        t        f«      r't        j                  | j                  «      d   | _         | j                   €'t        j                  | j                  «      d   | _         t        t        | j                  t        «      s6t        j                  j                  | j                  «      dz  «      | _        y t        j                  «       dz  «      | _        y ©Nr   r   )r@   Ú
isinstancer8   r2   r   Ú	mimetypesÚ
guess_typer9   r5   ÚbytesÚosÚpathÚgetmtimeÚtimer?   ©r)   s    r+   Ú__post_init__z_BucketAddFile.__post_init__i   s²   € Ø ˆÔÜ�d—k‘k¤C¬ ;Ô/Ü )× 4Ñ 4°T·[±[Ó AÀ!Ñ DˆDÔØ×ÑÐ$Ü )× 4Ñ 4°T×5EÑ5EÓ FÀqÑ IˆDÔäÜ8BÀ4Ç;Á;ÔPUÔ8VŒB�G‰G×Ñ˜TŸ[™[Ó)¨DÑ0ó
ˆ�
Ü\`×\eÑ\eÓ\gÐjnÑ\nó
ˆ�
r-   ©ÚreturnN)r.   r/   r0   r2   r   rF   r3   r   r<   r    r5   r?   r@   rL   r%   r-   r+   r7   r7   _   sd   … à�$‰J˜ÑÓØÓá ¨Ô.€Hˆc�D‰jÓ.Ù TÔ*€Dˆ#�‰*Ó*Ù˜EÔ"€Eˆ3Ó"Ù$¨%Ô0€L�#˜‘*Ó0ô	
r-   r7   c                   óž   — e Zd ZU eed<   eed<   eed<   eed<    ed¬«      Zedz  ed<    ed¬	«      Zeed
<    ed¬	«      Z	edz  ed<   dd„Z
y)Ú_BucketCopyFiler9   r<   Úsource_repo_typeÚsource_repo_idNr:   r    Fr=   r?   r@   c                 óœ   — t        j                  | j                  «      d   | _        t	        t        j
                  «       dz  «      | _        y rB   )rD   rE   r9   r@   r5   rJ   r?   rK   s    r+   rL   z_BucketCopyFile.__post_init__   s7   € Ü%×0Ñ0°×1AÑ1AÓBÀ1ÑEˆÔÜœŸ™› tÑ+Ó,ˆ�
r-   rM   )r.   r/   r0   r2   r3   r   r    r5   r?   r@   rL   r%   r-   r+   rP   rP   u   sS   … àÓØƒMØÓØÓÙ TÔ*€Dˆ#�‰*Ó*Ù˜EÔ"€Eˆ3Ó"Ù$¨%Ô0€L�#˜‘*Ó0ô-r-   rP   c                   ó   — e Zd ZU eed<   y)Ú_BucketDeleteFilerH   N)r.   r/   r0   r2   r3   r%   r-   r+   rU   rU   „   s   … à
„Ir-   rU   T)Úfrozenc                   ó&   — e Zd ZU dZeed<   eed<   y)ÚBucketFileMetadataa%  Data structure containing information about a file in a bucket.

    Returned by [`get_bucket_file_metadata`].

    Args:
        size (`int`):
            Size of the file in bytes.
        xet_file_data (`XetFileData`):
            Xet information for the file (hash and refresh route).
    r    Úxet_file_dataN)r.   r/   r0   r1   r5   r3   r   r%   r-   r+   rX   rX   ‰   s   … ñ	ð ƒIØÔr-   rX   c                   ó†   — e Zd ZU dZeed<   dZeed<    ed¬«      Zeed<    ed¬«      Z	eed<    ed¬«      Z
eed	<   dd„Zy
)Ú	BucketUrla½  Describes a bucket URL on the Hub.

    `BucketUrl` is returned by [`create_bucket`]. At initialization, the URL is parsed to populate properties:
    - endpoint (`str`)
    - namespace (`str`)
    - bucket_id (`str`)
    - url (`str`)
    - uri (`HfUri`)

    Args:
        url (`str`):
            String value of the bucket url.
        endpoint (`str`, *optional*):
            Endpoint of the Hub. Defaults to <https://huggingface.co>.
    ÚurlÚ ÚendpointFr=   Ú	namespaceÚ	bucket_idÚuriNc                 óÆ  — | j                   xs t        j                  | _         | j                  j	                  | j                   d«      j                  d«      }|j                  d«      r|t        d«      d  }t        |«      }|j                  rt        d| j                  › �«      ‚|j                  j                  d«      d   | _        |j                  | _        || _        y )Nr]   ú/zbuckets/zUnable to parse bucket URL: r   )r^   r   ÚENDPOINTr\   ÚreplaceÚstripÚ
startswithÚlenÚ_parse_bucket_uriÚpath_in_repoÚ
ValueErrorr   Úsplitr_   r`   ra   )r)   Úurl_pathÚparseds      r+   rL   zBucketUrl.__post_init__²   s³   € ØŸ™Ò;¬×);Ñ);ˆŒð —8‘8×#Ñ# D§M¡M°2Ó6×<Ñ<¸SÓAˆà×Ñ˜zÔ*Ø¤ J£Ð 1Ð2ˆHÜ" 8Ó,ˆØ×ÒÜÐ;¸D¿H¹H¸:ÐFÓGÐGØŸ™Ÿ™¨Ó-¨aÑ0ˆŒØŸ™ˆŒØˆ�r-   rM   )r.   r/   r0   r1   r2   r3   r^   r   r_   r`   ra   r   rL   r%   r-   r+   r[   r[   š   sJ   … ñð  
ƒHØ€HˆcÓÙ Ô&€IˆsÓ&Ù Ô&€IˆsÓ&Ù˜EÔ"€CˆÓ"ôr-   r[   c                   óf   — e Zd ZU dZed   ed<   eed<   eed<   eed<   edz  ed<   edz  ed	<   d
„ Z	y)Ú
BucketFilez«
    Contains information about a file in a bucket on the Hub. This object is returned by [`list_bucket_tree`].

    Similar to [`RepoFile`] but for files in buckets.
    ÚfileÚtyperH   r    r<   Nr?   Úuploaded_atc                 óX  — |j                  d«      | _        |j                  d«      | _        |j                  d«      | _        |j                  d«      | _        |j                  dd «      }|rt        |«      nd | _        |j                  dd «      }|rt        |«      | _        y d | _        y )Nrr   rH   r    ÚxetHashr?   Ú
uploadedAt)r&   rr   rH   r    r<   r   r?   rs   )r)   r*   r?   rs   s       r+   r,   zBucketFile.__init__Ñ   sˆ   € Ø—J‘J˜vÓ&ˆŒ	Ø—J‘J˜vÓ&ˆŒ	Ø—J‘J˜vÓ&ˆŒ	ØŸ
™
 9Ó-ˆŒØ—
‘
˜7 DÓ)ˆÙ.3”^ EÔ*¸ˆŒ
Ø—j‘j ¨tÓ4ˆÙ:Eœ>¨+Ó6ˆÕÈ4ˆÕr-   )
r.   r/   r0   r1   r   r3   r2   r5   r   r,   r%   r-   r+   rp   rp   Â   s<   … ñð �&‰/ÓØ
ƒIØ
ƒIØƒMØ�d‰?ÓØ˜D‘Ó óPr-   rp   c                   óB   — e Zd ZU dZed   ed<   eed<   edz  ed<   d„ Zy)ÚBucketFolderz¸
    Contains information about a directory in a bucket on the Hub. This object is returned by [`list_bucket_tree`].

    Similar to [`RepoFolder`] but for directories in buckets.
    Ú	directoryrr   rH   Nrs   c                 ó  — |j                  d«      | _        |j                  d«      | _        |j                  dd «      xs |j                  dd «      }|r)t        |t        «      r|| _        y t        |«      | _        y d | _        y )Nrr   rH   rv   rs   )r&   rr   rH   rC   r   r   rs   )r)   r*   rs   s      r+   r,   zBucketFolder.__init__è   s|   € Ø—J‘J˜vÓ&ˆŒ	Ø—J‘J˜vÓ&ˆŒ	Ø—j‘j ¨tÓ4ÒW¸¿
¹
À=ÐRVÓ8Wˆñ ô ' {´HÔ=ˆ[ð 	ÕÜCQÐR]ÓC^ð 	Õð ð 	Õr-   )	r.   r/   r0   r1   r   r3   r2   r   r,   r%   r-   r+   rx   rx   Ü   s(   … ñð �+Ñ
ÓØ
ƒIØ˜D‘Ó ó
r-   rx   rH   rN   c                 óv  — | j                  t        j                  «      st        | «      r(t	        | «      }|j
                  st        d| › d�«      ‚|S | j                  dd«      }t        |«      dk  s
|d   r|d   st        d| › d�«      ‚|d   › d|d   › �}dj                  |dd	 «      }t        d
||¬«      S )a  Parse a bucket path into a HfUri.

    Accepts:
    - `hf://buckets/namespace/name(/path/in/repo)` URIs,
    - Hugging Face web URLs such as `https://huggingface.co/buckets/namespace/name(/tree/path)`,
    - plain `namespace/name(/path/in/repo)` paths.
    zInvalid bucket path: z*. Must be a bucket URI (hf://buckets/...).rc   é   r   r   zInvalid bucket path: 'z)'. Expected format: namespace/bucket_nameNÚbucket)rr   r   rj   )rg   r   ÚHF_PROTOCOLr   r   Ú	is_bucketrk   rl   rh   Újoinr   )rH   rn   Úpartsr`   Úprefixs        r+   ri   ri   ø   sÄ   € ð ‡�”y×,Ñ,Ô-Ô1CÀDÔ1Iä˜dÓ#ˆØ×ÒÜÐ4°T°FÐ:dÐeÓfÐfØˆØ�J‰J�s˜AÓ€EÜ
ˆ5ƒz�A‚~˜U 1šX¨U°1ªXÜÐ1°$°Ð7`ÐaÓbÐbØ˜‘8�*˜A˜e A™h˜ZÐ(€IØ�X‰X�e˜A˜B�iÓ €FÜ�h 9¸6ÔBÐBr-   c                 ól   — | j                  t        j                  «      syt        | «      j                  S )z›Check if a path is a bucket path.

    Do not raise if the path is not a hf:// URI.
    Raise if the path is a hf:// URI but with an incorrect format.
    F)rg   r   r~   r   r   )rH   s    r+   Ú_is_bucket_pathr„     s*   € ð �?‰?œ9×0Ñ0Ô1ØÜ˜Ó×'Ñ'Ð'r-   c                   óŠ   — e Zd ZU dZed   ed<   eed<   dZedz  ed<   dZ	eed<   dZ
edz  ed	<   dZedz  ed
<   dZedz  ed<   y)ÚSyncOperationz,Represents a sync operation to be performed.)ÚuploadÚdownloadÚdeleteÚskipÚactionrH   Nr    r]   ÚreasonÚlocal_mtimeÚremote_mtimeÚbucket_file)r.   r/   r0   r1   r   r3   r2   r    r5   rŒ   r�   rŽ   r�   rp   r%   r-   r+   r†   r†     sY   … á6àÐ:Ñ;Ó;Ø
ƒIØ€Dˆ#�‰*ÓØ€FˆCÓØ"€K��t‘Ó"Ø#€L�#˜‘*Ó#Ø%)€K�˜dÑ"Ô)r-   r†   c                   ón   — e Zd ZU dZeed<   eed<   eed<    ee¬«      Zee	   ed<   de
eeez  f   fd„Zy	)
ÚSyncPlanz Represents a complete sync plan.r8   ÚdestÚ	timestamp)Údefault_factoryÚ
operationsrN   c                 ó*  — t        d„ | j                  D «       «      }t        d„ | j                  D «       «      }t        d„ | j                  D «       «      }t        d„ | j                  D «       «      }t        d„ | j                  D «       «      }|||||dœS )Nc              3   ó@   K  — | ]  }|j                   d k(  sŒd–— Œ y­w)r‡   r   N©r‹   ©Ú.0Úops     r+   ú	<genexpr>z#SyncPlan.summary.<locals>.<genexpr>5  ó   è ø€ ÒK˜B°R·Y±YÀ(Ó5J”aÑKùó   ‚—c              3   ó@   K  — | ]  }|j                   d k(  sŒd–— Œ y­w)rˆ   r   Nr˜   r™   s     r+   rœ   z#SyncPlan.summary.<locals>.<genexpr>6  s   è ø€ ÒO˜b°r·y±yÀJÓ7NœÑOùrž   c              3   ó@   K  — | ]  }|j                   d k(  sŒd–— Œ y­w)r‰   r   Nr˜   r™   s     r+   rœ   z#SyncPlan.summary.<locals>.<genexpr>7  r�   rž   c              3   ó@   K  — | ]  }|j                   d k(  sŒd–— Œ y­w)rŠ   r   Nr˜   r™   s     r+   rœ   z#SyncPlan.summary.<locals>.<genexpr>8  s   è ø€ ÒG˜"°2·9±9ÀÓ3F”AÑGùrž   c              3   óZ   K  — | ]#  }|j                   d v sŒ|j                  xs d–— Œ% y­w)©r‡   rˆ   r   N)r‹   r    r™   s     r+   rœ   z#SyncPlan.summary.<locals>.<genexpr>9  s&   è ø€ Òg¨"À2Ç9Á9ÐPfÒCf˜Ÿ™š A›Ñgùs   ‚+–+)ÚuploadsÚ	downloadsÚdeletesÚskipsÚ
total_size)Úsumr•   )r)   r¤   r¥   r¦   r§   r¨   s         r+   ÚsummaryzSyncPlan.summary4  s   € ÜÑK $§/¡/ÔKÓKˆÜÑO D§O¡OÔOÓOˆ	ÜÑK $§/¡/ÔKÓKˆÜÑG §¡ÔGÓGˆÜÑg°·±ÔgÓgˆ
àØ"ØØØ$ñ
ð 	
r-   N)r.   r/   r0   r1   r2   r3   r   Úlistr•   r†   Údictr5   rª   r%   r-   r+   r‘   r‘   +  sA   … á*àƒKØ
ƒIØƒNÙ&+¸DÔ&A€J��]Ñ#ÓAð
˜˜c 3¨¡9˜nÑ-ô 
r-   r‘   c            
       ój   — e Zd ZdZ	 	 	 d
dee   dz  dee   dz  deeeef      dz  fd„Zdedefd	„Z	y)ÚFilterMatcherz4Matches file paths against include/exclude patterns.NÚinclude_patternsÚexclude_patternsÚfilter_rulesc                 óF   — |xs g | _         |xs g | _        |xs g | _        y)a  Initialize the filter matcher.

        Args:
            include_patterns: Patterns to include (from --include)
            exclude_patterns: Patterns to exclude (from --exclude)
            filter_rules: Rules from filter file as list of ("+"/"-", pattern) tuples
        N©r¯   r°   r±   )r)   r¯   r°   r±   s       r+   r,   zFilterMatcher.__init__K  s+   € ð !1Ò 6°BˆÔØ 0Ò 6°BˆÔØ(Ò.¨BˆÕr-   rH   rN   c                 ó$  — | j                   D ]"  \  }}t        j                  ||«      sŒ|dk(  c S  | j                  D ]  }t        j                  ||«      sŒ y | j                  D ]  }t        j                  ||«      sŒ y | j                  ryy)zþCheck if a path should be included based on the filter rules.

        Filtering rules:
        - Filters are evaluated in order, first matching rule decides
        - If no rules match, include by default (unless include patterns are specified)
        ú+FT)r±   Úfnmatchr°   r¯   )r)   rH   ÚsignÚpatterns       r+   ÚmatcheszFilterMatcher.matches\  s˜   € ð "×.Ñ.ò 	#‰MˆD�'Ü�‰˜t WÕ-Ø˜s‘{Ò"ð	#ð
 ×,Ñ,ò 	ˆGÜ�‰˜t WÕ-Ùð	ð ×,Ñ,ò 	ˆGÜ�‰˜t WÕ-Ùð	ð
 × Ò Øð r-   )NNN)
r.   r/   r0   r1   r«   r2   Útupler,   r4   r¹   r%   r-   r+   r®   r®   H  sh   „ Ù>ð .2Ø-1Ø59ñ	/à˜s™) dÑ*ð/ð ˜s™) dÑ*ð/ð ˜5  c ™?Ñ+¨dÑ2ó	/ð"˜Cð  Dô r-   r®   Úfilter_filec                 ó¢  — g }t        | «      5 }|D ]¥  }|j                  «       }|r|j                  d«      rŒ'|j                  d«      r%|j                  d|dd j                  «       f«       Œ]|j                  d«      r%|j                  d|dd j                  «       f«       Œ“|j                  d|f«       Œ§ 	 ddd«       |S # 1 sw Y   |S xY w)zþParse a filter file and return a list of (sign, pattern) tuples.

    Filter file format:
    - Lines starting with "+" are include patterns
    - Lines starting with "-" are exclude patterns
    - Empty lines and lines starting with "#" are ignored
    ú#rµ   r   Nú-)Úopenrf   rg   Úappend)r»   ÚrulesÚfÚlines       r+   Ú_parse_filter_filerÄ   y  sÂ   € ð €EÜ	ˆkÓ	ð *˜aØò 
	*ˆDØ—:‘:“<ˆDÙ˜4Ÿ?™?¨3Ô/ØØ�‰˜sÔ#Ø—‘˜c 4¨¨ 8§>¡>Ó#3Ð4Õ5Ø—‘ Ô%Ø—‘˜c 4¨¨ 8§>¡>Ó#3Ð4Õ5ð —‘˜c 4˜[Õ)ñ
	*÷*ð €L÷*ð €Lús   ŽB+CÃCc                 óÂ   — 	 t        j                  | «      }t        j                  |j                  «      ry|j
                  |j                  dz  fS # t        $ r Y yw xY w)zÇStat a local file and return (size, mtime_ms).

    Returns None if the path is missing or is a directory. Uses a single
    ``os.stat`` call so callers don't pay for multiple syscalls per file.
    Nr   )rG   ÚstatÚOSErrorÚS_ISDIRÚst_modeÚst_sizeÚst_mtime)rH   Ústs     r+   Ú_stat_localrÍ   –  sU   € ðÜ�W‰W�T‹]ˆô ‡|�|�B—J‘JÔØØ�:‰:�r—{‘{ TÑ)Ð)Ð)øô	 ò Ùðús   ‚A Á	AÁAÚ
local_pathc              #   óä  K  — t         j                  j                  | «      } t         j                  j                  | «      st	        d| › �«      ‚t        j
                  | «      D ]ˆ  \  }}}|D ]}  }t         j                  j                  ||«      }t        |«      }|€Œ1t         j                  j                  || «      }|j                  t         j                  d«      }||d   |d   f–— Œ ŒŠ y­w)zsList all files in a local directory.

    Yields:
        tuple: (relative_path, size, mtime_ms) for each file
    z Local path must be a directory: Nrc   r   r   )rG   rH   ÚabspathÚisdirrk   Úwalkr€   rÍ   Úrelpathre   Úsep)rÎ   ÚrootÚ_ÚfilesÚfilenameÚ	full_pathÚ	stat_infoÚrel_paths           r+   Ú_list_local_filesrÜ   ¥  sÐ   è ø€ ô —‘—‘ Ó,€JÜ�7‰7�=‰=˜Ô$ÜÐ;¸J¸<ÐHÓIÐIäŸ'™' *Ó-ò 	7‰ˆˆa�Øò 	7ˆHÜŸ™Ÿ™ T¨8Ó4ˆIÜ# IÓ.ˆIØÐ ØÜ—w‘w—‘ y°*Ó=ˆHà×'Ñ'¬¯©°Ó4ˆHØ˜I a™L¨)°A©,Ð6Ó6ñ	7ñ	7ùs   ‚C.C0Úapir   r`   r‚   c              #   ó’  K  — | j                  ||xs dd¬«      D ]¨  }t        |t        «      rŒ|j                  }|rH|j	                  |dz   «      r|t        |«      dz   d }n$||k(  rd|v r|j                  dd«      d   n|}nŒj|}|j                  r|j                  j                  «       dz  nd}||j                  ||f–— Œª y­w)	zÔList all files in a bucket with a given prefix.

    Yields:
        tuple: (relative_path, size, mtime_ms, bucket_file) for each file.
            bucket_file is the BucketFile object from list_bucket_tree.
    NT)r‚   Ú	recursiverc   r   éÿÿÿÿr   r   )
Úlist_bucket_treerC   rx   rH   rg   rh   Úrsplitr?   r“   r    )rÝ   r`   r‚   ÚitemrH   rÛ   Úmtime_mss          r+   Ú_list_remote_filesrå   »  sÎ   è ø€ ð ×$Ñ$ Y°v²~ÀÐQUÐ$ÓVò 2ˆÜ�dœLÔ)ØØ�y‰yˆñ Ø�‰˜v¨™|Ô,Ø¤ F£¨a¡Ð 1Ð2‘Ø˜’à69¸T±k˜4Ÿ;™; s¨AÓ.¨rÒ2Àt‘ð àˆHØ48·J²J�4—:‘:×'Ñ'Ó)¨DÒ0ÀAˆØ˜Ÿ	™	 8¨TÐ1Ó1ñ'2ùs   ‚CCrä   c                 ón   — t        j                  | dz  t        j                  ¬«      j	                  «       S )z3Convert mtime in milliseconds to ISO format string.r   )Útz)r   Úfromtimestampr   ÚutcÚ	isoformat)rä   s    r+   Ú_mtime_to_isorë   Ý  s&   € ä×!Ñ! (¨T¡/´h·l±lÔC×MÑMÓOÐOr-   )r�   r‹   r£   Úsource_sizeÚsource_mtimeÚ	dest_sizeÚ
dest_mtimeÚsource_newer_labelÚdest_newer_labelÚignore_sizesÚignore_timesÚignore_existingr�   c                 ó�  — t        |dk(  r|n|«      }t        |dk(  r|n|«      }| |||dœ}|
rt        ddddœ|¤ŽS ||k7  }||z
  t        kD  }|r1|rt        d|||dœ|¤ŽS ||z
  t        kD  }|r|nd}t        dd|dœ|¤ŽS |	r|rt        d|d|dœ|¤ŽS t        ddd	dœ|¤ŽS |s|r|rdn|}t        d|||dœ|¤ŽS t        ddd
dœ|¤ŽS )a—  Compare source and dest files and return the appropriate sync operation.

    This is a unified helper for both upload and download directions.

    Args:
        path: Relative file path
        action: "upload" or "download"
        source_size: Size of the source file (bytes)
        source_mtime: Mtime of the source file (milliseconds)
        dest_size: Size of the destination file (bytes)
        dest_mtime: Mtime of the destination file (milliseconds)
        source_newer_label: Label when source is newer (e.g., "local newer" or "remote newer")
        dest_newer_label: Label when dest is newer (e.g., "remote newer" or "local newer")
        ignore_sizes: Only compare mtime
        ignore_times: Only compare size
        ignore_existing: Skip files that exist on receiver
        bucket_file: BucketFile object (for downloads only)

    Returns:
        SyncOperation describing the action to take
    r‡   )rH   r    r�   rŽ   rŠ   z&exists on receiver (--ignore-existing))r‹   rŒ   )r‹   rŒ   r�   z
same mtimezsize differsz	same sizeÚ	identicalr%   )rë   r†   Ú_SYNC_TIME_WINDOW_MS)rH   r‹   rì   rí   rî   rï   rð   rñ   rò   ró   rô   r�   Úlocal_mtime_isoÚremote_mtime_isoÚbase_kwargsÚsize_differsÚsource_newerÚ
dest_newerÚskip_reasonrŒ   s                       r+   Ú_compare_files_for_syncrÿ   â  s6  € ôH $°F¸hÒ4F¡LÈJÓW€OÜ$°6¸XÒ3E¡ZÈ<ÓXÐð ØØ&Ø(ñ	#€Kñ ÜÐk FÐ3[ÑkÐ_jÑkÐkà )Ñ+€LØ  :Ñ-Ô1EÑE€LáÙÜ Ðr¨Ð7IÐWbÑrÐfqÑrÐrà$ |Ñ3Ô7KÑKˆJÙ.8Ñ*¸lˆKÜ ÐR¨°{ÑRÀkÑRÐRÙ	ÙÜ Ðn¨°~ÐS^ÑnÐbmÑnÐnä ÐR¨°{ÑRÀkÑRÐRá™<Ù'3‘^Ð9KˆFÜ Ðf¨°vÈ;ÑfÐZeÑfÐfä ÐR¨°{ÑRÀkÑRÐRr-   Fr8   r’   r‰   ÚexistingÚfilter_matcherÚstatusc
                 ó�  — |xs
 t        «       }t        | «       xr t        |«      }
t        | «      xr t        |«       }|
s|st        d«      ‚t        | |t	        j
                  t        j                  «      j                  «       ¬«      }d}|
�rût        j                  j                  | «      }t        |«      }|j                  |j                  }}t        j                  j                  |«      st        d|› �«      ‚i }t!        |«      D ]?  \  }}}|j#                  |«      r||f||<   |	sŒ"|	j%                  dt'        |«      › d�«       ŒA |	r|	j)                  dt'        |«      › d�«       i }|	r	 |j+                  |«      j,                  }	 t1        |||«      D ]K  \  }}}}|j#                  |«      r||f||<   |	sŒ#|�d|› �nd}|	j%                  d	t'        |«      › |› d�«       ŒM 	 |	r|	j)                  d	t'        |«      › d�«       t9        |j;                  «       «      t9        |j;                  «       «      z  }|	r|	j)                  dt'        |«      › d�«       t=        |«      D �]  }|j?                  |«      }|j?                  |«      }|rv|st|r9|j@                  jC                  tE        d||d   dtG        |d   «      ¬«      «       Œe|j@                  jC                  tE        d||d   dtG        |d   «      ¬«      «       Œž|r<|r:|\  }}|\  }} |j@                  jC                  tI        |d|||| dd|||¬«      «       ŒÜ|rŒß|sŒâ|sŒå|j@                  jC                  tE        d||d   dtG        |d   «      ¬«      «       �Œ |S t        | «      }|j                  |j                  }}t        j                  j                  |«      }i }i }!|	r	 |j+                  |«      j,                  }t1        |||«      D ]P  \  }}}}"|j#                  |«      r||f||<   |"|!|<   |	sŒ(|�d|› �nd}|	j%                  d	t'        |«      › |› d�«       ŒR |	r|	j)                  d	t'        |«      › d�«       i }t        j                  j                  |«      r«|rNt!        |«      D ]?  \  }}}|j#                  |«      r||f||<   |	sŒ"|	j%                  dt'        |«      › d�«       ŒA n[|D ]V  }t        j                  jK                  ||«      }#tM        |#«      }$|$€Œ1|$||<   |	sŒ9|	j%                  dt'        |«      › d�«       ŒX |	r|	j)                  dt'        |«      › d�«       t9        |j;                  «       «      t9        |j;                  «       «      z  }|	r|	j)                  dt'        |«      › d�«       t=        |«      D �]>  }|j?                  |«      }|j?                  |«      }|r†|s„|r9|j@                  jC                  tE        d||d   dtG        |d   «      ¬«      «       Œe|j@                  jC                  tE        d||d   dtG        |d   «      |!j?                  |«      ¬«      «       Œ®|rL|rJ|\  }} |\  }}|j@                  jC                  tI        |d|| ||dd||||!j?                  |«      ¬«      «       Œü|rŒÿ|s�Œ|s�Œ|j@                  jC                  tE        d||d   dtG        |d   «      ¬«      «       �ŒA |S # t.        $ r Y �Œ{w xY w# t2        $ r t4        j7                  d
|› d�«       Y �ŒGw xY w# t.        $ r Y �ŒSw xY w)z‚Compute the sync plan by comparing source and destination.

    Returns:
        SyncPlan with all operations to be performed
    z[One of source or dest must be a bucket path (hf://buckets/...) and the other must be local.©r8   r’   r“   NzSource must be a directory: zScanning local directory (z files)rc   r]   zScanning remote bucket (zBucket 'z' not found, treating as empty.zComparing files (z paths)rŠ   r   znew file (--existing)r   )r‹   rH   r    rŒ   r�   r‡   znew filezlocal newerzremote newer)rH   r‹   rì   rí   rî   rï   rð   rñ   rò   ró   rô   r‰   znot in source (--delete))r‹   rH   r    rŒ   rŽ   rˆ   )r‹   rH   r    rŒ   rŽ   r�   )rH   r‹   rì   rí   rî   rï   rð   rñ   rò   ró   rô   r�   )'r®   r„   rk   r‘   r   Únowr   ré   rê   rG   rH   rÐ   ri   r   rj   rÑ   rÜ   r¹   r(   rh   ÚdoneÚbucket_infor!   Ú	Exceptionrå   r   ÚloggerÚdebugÚsetÚkeysÚsortedÚgetr•   rÀ   r†   rë   rÿ   r€   rÍ   )%r8   r’   rÝ   r‰   ró   rò   r   rô   r  r  Ú	is_uploadÚis_downloadÚplanÚremote_totalrÎ   rn   r`   r‚   Úlocal_filesrÛ   r    rä   Úremote_filesrÖ   Ú	total_strÚ	all_pathsrH   Ú
local_infoÚremote_infoÚ
local_sizer�   Úremote_sizerŽ   Úbucket_file_mapr�   Ú
local_filerÚ   s%                                        r+   Ú_compute_sync_planr  *  s”  € ð" $Ò6¤}£€NÜ# FÓ+Ð+ÒE´ÀÓ0E€IÜ! &Ó)ÒG´/À$Ó2GÐ.G€Ká™[ÜÐvÓwÐwäØØÜ—,‘,œxŸ|™|Ó,×6Ñ6Ó8ô€Dð  $€LÚä—W‘W—_‘_ VÓ,ˆ
Ü" 4Ó(ˆØ"ŸI™I v×':Ñ':�6ˆ	ä�w‰w�}‰}˜ZÔ(ÜÐ;¸J¸<ÐHÓIÐIð ˆÜ(9¸*Ó(Eò 	VÑ$ˆH�d˜HØ×%Ñ% hÔ/Ø)-¨xÐ(8�˜HÑ%ÚØ—‘Ð :¼3¸{Ó;KÐ:LÈGÐTÕUð		Vñ
 Ø�K‰KÐ4´S¸Ó5EÐ4FÀgÐNÔOàˆÙðØ"Ÿ™¨yÓ9×EÑE�ð		PÜ/AÀ#ÀyÐRXÓ/Yò dÑ+�˜$ ¨!Ø!×)Ñ)¨(Ô3Ø.2°HÐ-=�L Ñ*ÚØ6BÐ6N ! L >Ñ 2ÐTV�IØ—M‘MÐ$<¼SÀÓ=NÐ<OÐPYÈ{ÐZaÐ"bÕcñdñ Ø�K‰KÐ2´3°|Ó3DÐ2EÀWÐMÔNô ˜×(Ñ(Ó*Ó+¬c°,×2CÑ2CÓ2EÓ.FÑFˆ	ÙØ�K‰KÐ+¬C°	«NÐ+;¸7ÐCÔDÜ˜9Ó%ó 8	ˆDØ$Ÿ™¨Ó.ˆJØ&×*Ñ*¨4Ó0ˆKá¡+áà—O‘O×*Ñ*Ü%Ø#)Ø!%Ø!+¨A¡Ø#:Ü(5°jÀ±mÓ(Dôõð —O‘O×*Ñ*Ü%Ø#+Ø!%Ø!+¨A¡Ø#-Ü(5°jÀ±mÓ(Dôõñ ¡à*4Ñ'�
˜KØ,7Ñ)�˜\Ø—‘×&Ñ&Ü+Ø!Ø'Ø$.Ø%0Ø"-Ø#/Ø+8Ø)7Ø%1Ø%1Ø(7ôõò  ¢K²Fà—‘×&Ñ&Ü!Ø'Ø!Ø(¨™^Ø9Ü%2°;¸q±>Ó%Bôöða8	ðV €Kô_ # 6Ó*ˆØ"ŸI™I v×':Ñ':�6ˆ	Ü—W‘W—_‘_ TÓ*ˆ
ð ˆØ*,ˆÙðØ"Ÿ™¨yÓ9×EÑE�ô 6HÈÈYÐX^Ó5_ò 	`Ñ1ˆH�d˜H kØ×%Ñ% hÔ/Ø*.°Ð)9�˜XÑ&Ø,7� Ñ)ÚØ2>Ð2J˜a ˜~Ñ.ÐPR�	Ø—‘Ð 8¼¸\Ó9JÐ8KÈIÈ;ÐV]Ð^Õ_ð	`ñ Ø�K‰KÐ2´3°|Ó3DÐ2EÀWÐMÔNàˆÜ�7‰7�=‰=˜Ô$Ùä0AÀ*Ó0Mò ^Ñ,�H˜d HØ%×-Ñ-¨hÔ7Ø15°xÐ0@˜ HÑ-ÚØŸ™Ð(BÄ3À{ÓCSÐBTÐT[Ð&\Õ]ñ	^ð !-ò ^�HÜ!#§¡§¡¨j¸(Ó!C�JÜ +¨JÓ 7�IØ Ð(Ø Ø,5�K Ñ)ÚØŸ™Ð(BÄ3À{ÓCSÐBTÐT[Ð&\Õ]ð^ñ Ø�K‰KÐ4´S¸Ó5EÐ4FÀgÐNÔOô ˜×)Ñ)Ó+Ó,¬s°;×3CÑ3CÓ3EÓ/FÑFˆ	ÙØ�K‰KÐ+¬C°	«NÐ+;¸7ÐCÔDÜ˜9Ó%ó :	ˆDØ&×*Ñ*¨4Ó0ˆKØ$Ÿ™¨Ó.ˆJá¡:áà—O‘O×*Ñ*Ü%Ø#)Ø!%Ø!,¨Q¡Ø#:Ü)6°{À1±~Ó)Fôõð —O‘O×*Ñ*Ü%Ø#-Ø!%Ø!,¨Q¡Ø#-Ü)6°{À1±~Ó)FØ(7×(;Ñ(;¸DÓ(Aôõ	ñ ¡à,7Ñ)�˜\Ø*4Ñ'�
˜KØ—‘×&Ñ&Ü+Ø!Ø)Ø$/Ø%1Ø",Ø#.Ø+9Ø)6Ø%1Ø%1Ø(7Ø$3×$7Ñ$7¸Ó$=ôõò  !£Z³Fà—‘×&Ñ&Ü!Ø'Ø!Ø'¨™]Ø9Ü$1°*¸Q±-Ó$@ôöðe:	ðx €Køô} ò Úðûô #ò 	Pä�L‰L˜8 I ;Ð.MÐN×Oð	Pûô` ò Úðús<   Å5[? Æ/\ Ç+\ Ï\8 Û?	\Ü\Ü"\5Ü4\5Ü8	]Ý]r  c                 ó  — d| j                   | j                  | j                  | j                  «       dœ}|j	                  t        j                  |«      dz   «       | j                  D ]Ÿ  }d|j                  |j                  |j                  dœ}|j                  �|j                  |d<   |j                  �|j                  |d<   |j                  �|j                  |d	<   |j	                  t        j                  |«      dz   «       Œ¡ y)
z1Write a sync plan as JSONL to a file-like object.Úheader)rr   r8   r’   r“   rª   ú
Ú	operation)rr   r‹   rH   rŒ   Nr    r�   rŽ   )r8   r’   r“   rª   ÚwriteÚjsonÚdumpsr•   r‹   rH   rŒ   r    r�   rŽ   )r  rÂ   r  r›   Úop_dicts        r+   Ú_write_planr&  &  sß   € ð Ø—+‘+Ø—	‘	Ø—^‘^Ø—<‘<“>ñ€Fð ‡G�GŒD�J‰J�vÓ Ñ%Ô&ð �o‰oò ,ˆàØ—i‘iØ—G‘GØ—i‘iñ	#
ˆð �7‰7ÐØ Ÿg™gˆG�F‰OØ�>‰>Ð%Ø%'§^¡^ˆG�MÑ"Ø�?‰?Ð&Ø&(§o¡oˆG�NÑ#Ø	�‰”—
‘
˜7Ó# dÑ*Õ+ñ,r-   Ú	plan_filec                 ó^   — t        |d«      5 }t        | |«       ddd«       y# 1 sw Y   yxY w)z!Save a sync plan to a JSONL file.ÚwN)r¿   r&  )r  r'  rÂ   s      r+   Ú
_save_planr*  C  s-   € ä	ˆi˜Ó	ð  Ü�D˜!Ô÷÷ ñ ús   �#£,c                 óf  — t        | «      5 }|j                  «       }ddd«       st        d| › �«      ‚t        j                  |d   «      }|j                  d«      dk7  rt        d«      ‚t        |d   |d   |d	   ¬
«      }|dd D ]™  }t        j                  |«      }|j                  d«      dk7  rŒ-|j                  j                  t        |d   |d   |j                  d«      |j                  dd«      |j                  d«      |j                  d«      ¬«      «       Œ› |S # 1 sw Y   �ŒxY w)z#Load a sync plan from a JSONL file.NzEmpty plan file: r   rr   r  z0Invalid plan file: expected header as first liner8   r’   r“   r  r   r!  r‹   rH   r    rŒ   r]   r�   rŽ   )r‹   rH   r    rŒ   r�   rŽ   )
r¿   Ú	readlinesrk   r#  Úloadsr  r‘   r•   rÀ   r†   )r'  rÂ   Úlinesr  r  rÃ   r%  s          r+   Ú
_load_planr/  I  s1  € ä	ˆi‹ð ˜AØ—‘“ˆ÷ñ ÜÐ,¨Y¨KÐ8Ó9Ð9ô �Z‰Z˜˜a™Ó!€FØ‡z�z�&Ó˜XÒ%ÜÐKÓLÐLäØ�hÑØ�F‰^Ø˜Ñ%ô€Dð �a�b�	ò 
ˆÜ—*‘*˜TÓ"ˆØ�;‰;�vÓ +Ò-ØØ�‰×ÑÜØ˜xÑ(Ø˜V‘_Ø—[‘[ Ó(Ø—{‘{ 8¨RÓ0Ø#ŸK™K¨Ó6Ø$Ÿ[™[¨Ó8ôõ		
ð	
ð €K÷Cñ ús   ŒD&Ä&D0Úverbosec                 ót  — t        | j                  «       xr t        | j                  «      }t        | j                  «      xr t        | j                  «       }|�r%t        j                  j                  | j                  «      }t        | j                  «      }|j                  |j                  }	}g }
g }| j                  D �]'  }|j                  xdk(  r† t        j                  j                  ||j                  «      }|	r|	› d|j                  › �n|j                  }|r&t        d|j                  › d|j                  › d�«       |
j                  ||f«       Œšxdk(  rZ |	r|	› d|j                  › �n|j                  }|r&t        d|j                  › d|j                  › d�«       |j                  |«       Œùdk(  sŒþ|s�Œt        d	|j                  › d|j                  › d�«       �Œ* |
s|r�|rpg }|
r|j                  d
t        |
«      › d�«       |r|j                  dt        |«      › d�«       |j!                  dj                  |«      j#                  «       «       |j%                  ||
xs d|xs d¬«       yy|�r$t        | j                  «      }|j                  |j                  }	}t        j                  j                  | j                  «      }t        j&                  |d¬«       g }g }| j                  D �]¤  }|j                  dk(  rãt        j                  j                  ||j                  «      }t        j&                  t        j                  j)                  |«      d¬«       |r&t        d|j                  › d|j                  › d�«       |j*                  �|j                  |j*                  |f«       ŒÃ|	r|	› d|j                  › �n|j                  }|j                  ||f«       Œö|j                  dk(  ret        j                  j                  ||j                  «      }|r&t        d|j                  › d|j                  › d�«       |j                  |«       �Œj|j                  dk(  s�Œ{|s�Œt        d	|j                  › d|j                  › d�«       �Œ§ t        |«      dkD  r2|r|j!                  dt        |«      › d�«       |j-                  ||«       |r |r|j!                  dt        |«      › d�«       |D ]—  }t        j                  j/                  |«      sŒ#t        j0                  |«       t        j                  j)                  |«      }||k7  sŒ]	 t        j2                  |«       t        j                  j)                  |«      }||k7  rŒ;Œ™ yy# t4        $ r Y Œ§w xY w)zExecute a sync plan.r‡   rc   z  Uploading: z (ú)r‰   z  Deleting: rŠ   z  Skipping: z
uploading z filesz	deleting z, N)Úaddr‰   T)Úexist_okrˆ   z  Downloading: r   zDownloading z	Deleting z local files)r„   r8   r’   rG   rH   rÐ   ri   r   rj   r•   r‹   r€   ÚprintrŒ   rÀ   rh   r  Ú
capitalizeÚbatch_bucket_filesÚmakedirsÚdirnamer�   Údownload_bucket_filesÚexistsÚremoveÚrmdirrÇ   )r  rÝ   r0  r  r  r  rÎ   rn   r`   r‚   Ú	add_filesÚdelete_pathsr›   r  Úremote_pathr�   Údownload_filesÚdelete_filesÚ	file_pathÚparents                       r+   Ú_execute_planrE  t  sŸ  € ä# D§K¡KÓ0Ð0ÒO´_ÀTÇYÁYÓ5O€IÜ! $§+¡+Ó.ÒQ´ÀtÇyÁyÓ7QÐ3Q€KâÜ—W‘W—_‘_ T§[¡[Ó1ˆ
Ü" 4§9¡9Ó-ˆØ"ŸI™I v×':Ñ':�6ˆ	ð ;=ˆ	Ø"$ˆà—/‘/ó 	BˆBØ—)‘)ÝÜ!#§¡§¡¨j¸"¿'¹'Ó!B�JÙ;A V H¨A¨b¯g©g¨YÑ"7ÀrÇwÁw�KÙÜ ¨b¯g©g¨Y°b¸¿¹¸À1ÐEÔFØ×$Ñ$ j°+Ð%>Õ?ÝÙ;A V H¨A¨b¯g©g¨YÑ"7ÀrÇwÁw�KÙÜ ¨R¯W©W¨I°R¸¿	¹	°{À!ÐDÔEØ ×'Ñ'¨Õ4Ü›wÜ˜L¨¯©¨	°°B·I±I°;¸aÐ@ÖAð	Bñ" ™ÙØ�ÙØ—L‘L :¬c°)«nÐ-=¸VÐ!DÔEÙØ—L‘L 9¬S°Ó->Ð,?¸vÐ!FÔGØ—‘˜DŸI™I eÓ,×7Ñ7Ó9Ô:Ø×"Ñ"ØØÒ% Ø#Ò+ tð #õ ð %ò 
Ü" 4§;¡;Ó/ˆØ"ŸI™I v×':Ñ':�6ˆ	Ü—W‘W—_‘_ T§Y¡YÓ/ˆ
ô 	�‰�J¨Õ.ð EGˆØ"$ˆà—/‘/ó 	>ˆBØ�y‰y˜JÒ&ÜŸW™WŸ\™\¨*°b·g±gÓ>�
ä—‘œBŸG™GŸO™O¨JÓ7À$ÕGÙÜ˜O¨B¯G©G¨9°B°r·y±y°kÀÐCÔDà—>‘>Ð-Ø"×)Ñ)¨2¯>©>¸:Ð*FÕGá;A V H¨A¨b¯g©g¨YÑ"7ÀrÇwÁw�KØ"×)Ñ)¨;¸
Ð*CÕDØ—‘˜hÒ&ÜŸW™WŸ\™\¨*°b·g±gÓ>�
ÙÜ˜L¨¯©¨	°°B·I±I°;¸aÐ@ÔAØ×#Ñ# JÖ/Ø—‘˜fÔ$«Ü˜ R§W¡W I¨R°·	±	¨{¸!Ð<Ö=ð'	>ô, ˆ~Ó Ò"ÙØ—‘˜l¬3¨~Ó+>Ð*?¸vÐFÔGØ×%Ñ% i°Ô@ñ ‘lØ�K‰K˜)¤C¨Ó$5Ð#6°lÐCÔDØ%ò 
	ˆIÜ�w‰w�~‰~˜iÕ(Ü—	‘	˜)Ô$äŸ™Ÿ™¨Ó3�Ø 
Ó*ðÜŸ™ Ô(Ü!#§¡§¡°Ó!8˜ð  
Ô*ñ
	ðU 
øôf #ò Ùðús   Õ-4V+Ö+	V7Ö6V7c                 óö   — | j                  «       }t        d| j                  › d| j                  › �«       t        d|d   › �«       t        d|d   › �«       t        d|d   › �«       t        d	|d
   › �«       y)z!Print a summary of the sync plan.zSync plan: z -> z  Uploads: r¤   z  Downloads: r¥   z  Deletes: r¦   z	  Skips: r§   N)rª   r5  r8   r’   )r  rª   s     r+   Ú_print_plan_summaryrG  Ø  s~   € à�l‰l‹n€GÜ	ˆK˜Ÿ™�} D¨¯©¨Ð
4Ô5Ü	ˆK˜ 	Ñ*Ð+Ð
,Ô-Ü	ˆM˜' +Ñ.Ð/Ð
0Ô1Ü	ˆK˜ 	Ñ*Ð+Ð
,Ô-Ü	ˆI�g˜gÑ&Ð'Ð
(Õ)r-   )r‰   ró   rò   r   rô   ÚincludeÚexcludeÚfilter_fromr  ÚapplyÚdry_runr0  ÚquietÚtokenrH  rI  rJ  rK  rL  rM  rN  c                ód  — |�ddl m}  ||¬«      }|rù| s|rt        d«      ‚|�t        d«      ‚|rt        d«      ‚|rt        d«      ‚|rt        d	«      ‚|rt        d
«      ‚|	rt        d«      ‚|
rt        d«      ‚|rt        d«      ‚|rt        d«      ‚|rt        d«      ‚t        |«      }t	        | ¬«      }|st        |«       t        d«       |r
t        «        	 t        ||||¬«       |rt        «        	 |st        d«       |S | r|st        d«      ‚t        | «      }t        |«      }|r|rt        d«      ‚|s|st        d«      ‚|r|rt        d«      ‚|r|rt        d«      ‚|r|rt        d«      ‚|rLt        j                  j                  |«      rZt        j                  j                  |«      s;t        d|› �«      ‚t        j                  j                  | «      st        d| › �«      ‚d}|
rt        |
«      }t!        ||	|¬«      }t	        | xr | ¬«      }t#        | |||||||||¬«
      }|rt%        |t&        j(                  «       |S |r)t+        ||«       |st        |«       t        d|› �«       |S |st        |«       |j-                  «       }|d   d k(  r|d!   d k(  r|d"   d k(  r|st        d#«       |S |st        d$«       |r
t        «        	 t        ||||¬«       |rt        «        	 |st        d«       |S # |rt        «        w w xY w# |rt        «        w w xY w)%a  Sync files between a local directory and a bucket.

    This is equivalent to the ``hf buckets sync`` CLI command. One of ``source`` or ``dest`` must be a bucket path
    (``hf://buckets/...``) and the other must be a local directory path.

    Args:
        source (`str`, *optional*):
            Source path: local directory or ``hf://buckets/namespace/bucket_name(/prefix)``.
            Required unless using ``apply``.
        dest (`str`, *optional*):
            Destination path: local directory or ``hf://buckets/namespace/bucket_name(/prefix)``.
            Required unless using ``apply``.
        api ([`HfApi`]):
            The HfApi instance to use for API calls.
        delete (`bool`, *optional*, defaults to `False`):
            Delete destination files not present in source.
        ignore_times (`bool`, *optional*, defaults to `False`):
            Skip files only based on size, ignoring modification times.
        ignore_sizes (`bool`, *optional*, defaults to `False`):
            Skip files only based on modification times, ignoring sizes.
        existing (`bool`, *optional*, defaults to `False`):
            Skip creating new files on receiver (only update existing files).
        ignore_existing (`bool`, *optional*, defaults to `False`):
            Skip updating files that exist on receiver (only create new files).
        include (`list[str]`, *optional*):
            Include files matching patterns (fnmatch-style).
        exclude (`list[str]`, *optional*):
            Exclude files matching patterns (fnmatch-style).
        filter_from (`str`, *optional*):
            Path to a filter file with include/exclude rules.
        plan (`str`, *optional*):
            Save sync plan to this JSONL file instead of executing.
        apply (`str`, *optional*):
            Apply a previously saved plan file. When set, ``source`` and ``dest`` are not needed.
        dry_run (`bool`, *optional*, defaults to `False`):
            Print sync plan to stdout as JSONL without executing.
        verbose (`bool`, *optional*, defaults to `False`):
            Show detailed per-file operations.
        quiet (`bool`, *optional*, defaults to `False`):
            Suppress all output and progress bars.
        token (Union[bool, str, None], optional):
            A valid user access token. If not provided, the locally saved token will be used.

    Returns:
        [`SyncPlan`]: The computed (or loaded) sync plan.

    Raises:
        `ValueError`: If arguments are invalid (e.g., both paths are remote, conflicting options).

    Example:
        ```python
        >>> from huggingface_hub import HfApi
        >>> api = HfApi()

        # Upload local directory to bucket
        >>> api.sync_bucket("./data", "hf://buckets/username/my-bucket")

        # Download bucket to local directory
        >>> api.sync_bucket("hf://buckets/username/my-bucket", "./data")

        # Sync with delete and filtering
        >>> api.sync_bucket(
        ...     "./data",
        ...     "hf://buckets/username/my-bucket",
        ...     delete=True,
        ...     include=["*.safetensors"],
        ... )

        # Dry run: preview what would be synced
        >>> plan = api.sync_bucket("./data", "hf://buckets/username/my-bucket", dry_run=True)
        >>> plan.summary()
        {'uploads': 3, 'downloads': 0, 'deletes': 0, 'skips': 1, 'total_size': 4096}

        # Save plan for review, then apply
        >>> api.sync_bucket("./data", "hf://buckets/username/my-bucket", plan="sync-plan.jsonl")
        >>> api.sync_bucket(apply="sync-plan.jsonl")
        ```
    Nr   r   )rN  z,Cannot specify source/dest when using apply.z#Cannot specify both plan and apply.z'Cannot specify delete when using apply.z-Cannot specify ignore_times when using apply.z-Cannot specify ignore_sizes when using apply.z(Cannot specify include when using apply.z(Cannot specify exclude when using apply.z,Cannot specify filter_from when using apply.z)Cannot specify existing when using apply.z0Cannot specify ignore_existing when using apply.z(Cannot specify dry_run when using apply.)ÚenabledzExecuting plan...)r0  r  zSync completed.z7Both source and dest are required (unless using apply).z?Remote to remote sync is not supported. One path must be local.z?One of source or dest must be a bucket path (hf://buckets/...).z2Cannot specify both ignore_times and ignore_sizes.z1Cannot specify both existing and ignore_existing.z%Cannot specify both dry_run and plan.z!Destination must be a directory: z&Source must be an existing directory: r³   )
r8   r’   rÝ   r‰   ró   rò   r   rô   r  r  zPlan saved to: r¤   r   r¥   r¦   zNothing to sync.z
Syncing...)Úhf_apir   rk   r/  r   rG  r5  r   rE  r   r„   rG   rH   r;  rÑ   rÄ   r®   r  r&  ÚsysÚstdoutr*  rª   )r8   r’   rÝ   r‰   ró   rò   r   rô   rH  rI  rJ  r  rK  rL  r0  rM  rN  r   Ú	sync_planr  Úsource_is_bucketÚdest_is_bucketr±   r  rª   s                            r+   Úsync_bucket_internalrW  ç  sa  € ðF ÐÝ!á˜%Ô ˆáÙ‘TÜÐKÓLÐLØÐÜÐBÓCÐCÙÜÐFÓGÐGÙÜÐLÓMÐMÙÜÐLÓMÐMÙÜÐGÓHÐHÙÜÐGÓHÐHÙÜÐKÓLÐLÙÜÐHÓIÐIÙÜÐOÓPÐPÙÜÐGÓHÐHä˜uÓ%ˆ	Ü¨ IÔ.ˆÙÜ 	Ô*ÜÐ%Ô&áÜ!Ô#ð	'Ü˜) S°'À&ÕIáÜ$Õ&áÜÐ#Ô$àÐñ ™ÜÐRÓSÐSä& vÓ.ÐÜ$ TÓ*€Ná™NÜÐZÓ[Ð[á¡NÜÐZÓ[Ð[á™ÜÐMÓNÐNá‘OÜÐLÓMÐMá‘4ÜÐ@ÓAÐAñ Ü�7‰7�>‰>˜$Ô¬¯©¯©°dÔ(;ÜÐ@ÀÀÐGÓHÐHä�w‰w�}‰}˜VÔ$ÜÐEÀfÀXÐNÓOÐOð €LÙÜ)¨+Ó6ˆä"Ø Ø Ø!ô€Nô  E 	Ò 9°'¨kÔ:€FÜ"ØØØØØ!Ø!ØØ'Ø%Øô€Iñ Ü�IœsŸz™zÔ*ØÐáÜ�9˜dÔ#ÙÜ 	Ô*Ü�O D 6Ð*Ô+ØÐñ Ü˜IÔ&à×ÑÓ!€GØˆyÑ˜QÒ 7¨;Ñ#7¸1Ò#<ÀÈÑASÐWXÒAXÙÜÐ$Ô%ØÐáÜˆlÔáÜÔð#Ü�i ¨g¸fÕEáÜ Õ"áÜÐÔ àÐøñG Ü$Õ&ð ûñz Ü Õ"ð ús   Ã"L Ë#L  ÌLÌ L/)FFFFFNN)FN)NN)Kr1   r¶   r#  rD   rG   rÆ   rR  rJ   Úcollections.abcr   Údataclassesr   r   r   r   Úpathlibr   Útypingr	   r
   r   r]   r   r   Úerrorsr   Úutilsr   r   r   r   r   r   r   Úutils._hf_urisr   rQ  r   Ú
get_loggerr.   r	  ÚBUCKET_PREFIXr÷   r   r7   rP   rU   rX   r[   rp   rx   r2   ri   r4   r„   r†   r‘   r®   r«   rº   rÄ   r5   ÚfloatrÍ   rÜ   rå   rë   rÿ   r  r&  r*  r/  rE  rG  rW  r%   r-   r+   ú<module>rb     sh  ðñó
 Û Û Û 	Û Û 
Û Ý $ß (ß 'Ý ß .Ñ .ç  Ý '÷÷ ñ õ /ñ Ýð 
ˆ×	Ñ	˜HÓ	%€ð  €ØÐ ð ÷'ð 'ó ð'ð@ ÷
ð 
ó ð
ð* ÷-ð -ó ð-ð ÷ð ó ðñ �$Ô÷ð ó ðð  ÷$ð $ó ð$ðN ÷Pð Pó ðPð2 ÷
ð 
ó ð
ð6C˜Cð C Eó Cð,(˜#ð ( $ó (ð  ÷	*ð 	*ó ð	*ð ÷
ð 
ó ð
÷8.ñ .ðb Cð ¨D°°s¸C°x±Ñ,Aó ð:*�cð *˜e C¨ JÑ/°$Ñ6ó *ð7 #ð 7¨(°5¸¸cÀ5¸Ñ3IÑ*Jó 7ð,2˜Gð 2°ð 2¸Sð 2ÀXÈeÐTWÐY\Ð^cÐehÐThÑNiÑEjó 2ðDP˜Eð P có Pð$ #òESà
ðESð Ð(Ñ)ðESð ð	ESð
 ðESð ðESð ðESð ðESð ðESð ðESð ðESð ðESð �t‘ðESð óESðX ØØØØ!Ø+/ØñtØðtà
ðtð 
ðtð ð	tð
 ðtð ðtð ðtð ðtð " DÑ(ðtð �$‰Jðtð ótðx,�hð , dó ,ð:�Xð ¨#ð °$ó ð#˜#ð # (ó #ñVa˜ð a wð a¸ð aÈsÐUYÉzð aÐeió aðH*˜hð *¨4ó *ð  Øðnð
 ØØØØ!Ø $Ø $Ø"ØØØØØØ#ò%nØ�$‰Jðnà
�‰*ðnð 
ð	nð
 ðnð ðnð ðnð ðnð ðnð �#‰Y˜Ñðnð �#‰Y˜Ñðnð �t‘ðnð �‰*ðnð �‰:ðnð ðnð  ð!nð" ð#nð$ �#‰:˜Ñð%nð& ô'nr-   