Ë
    Z²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! erddl"m#Z#  ejH                  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«      «       Z.e G d„ d«      «       Z/e G d„ d «      «       Z0d!e1d"efd#„Z2d!e1d"e3fd$„Z4e G d%„ d&«      «       Z5e G d'„ d(«      «       Z6 G d)„ d*«      Z7d+e1d"e8e9e1e1f      fd,„Z:d!e1d"e9e;e<f   dz  fd-„Z=d.e1d"e	e9e1e;e<f      fd/„Z>d0d1d2e1d3e1d"e	e9e1e;e<ef      fd4„Z?d5e<d"e1fd6„Z@dd7œd!e1d8ed9   d:e;d;e<d<e;d=e<d>e1d?e1d@e3dAe3dBe3dCedz  d"e5fdD„ZA	 	 	 	 	 	 	 d^dFe1dGe1d0d1dHe3dAe3d@e3dIe3dBe3dJe7dz  dKedz  d"e6fdL„ZBdMe6d"dfdN„ZCdMe6dOe1d"dfdP„ZDdOe1d"e6fdQ„ZEd_dMe6d0d1dRe3dKedz  d"df
dS„ZFdMe6d"dfdT„ZG	 	 d`dEdEdEdEdEddddddEdEdEddUœdFe1dz  dGe1dz  d0d1dHe3dAe3d@e3dIe3dBe3dVe8e1   dz  dWe8e1   dz  dXe1dz  dMe1dz  dYe1dz  dZe3dRe3d[e3d\e3e1z  dz  d"e6f$d]„ZHy)azzShared 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©Ú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     úW/var/www/html/ia-enhanced/venv/lib/python3.12/site-packages/huggingface_hub/_buckets.pyÚ__init__zBucketInfo.__init__U   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?   Ú
isinstancer7   r1   r   Ú	mimetypesÚ
guess_typer8   r4   ÚbytesÚosÚpathÚgetmtimeÚtimer>   ©r(   s    r*   Ú__post_init__z_BucketAddFile.__post_init__h   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.   r/   r1   r   rE   r2   r   r;   r   r4   r>   r?   rK   r$   r,   r*   r6   r6   ^   sd   … à�$‰J˜ÑÓØÓá ¨Ô.€Hˆc�D‰jÓ.Ù TÔ*€Dˆ#�‰*Ó*Ù˜EÔ"€Eˆ3Ó"Ù$¨%Ô0€L�#˜‘*Ó0ô	
r,   r6   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)Ú_BucketCopyFiler8   r;   Úsource_repo_typeÚsource_repo_idNr9   r   Fr<   r>   r?   c                 óœ   — t        j                  | j                  «      d   | _        t	        t        j
                  «       dz  «      | _        y rA   )rC   rD   r8   r?   r4   rI   r>   rJ   s    r*   rK   z_BucketCopyFile.__post_init__~   s7   € Ü%×0Ñ0°×1AÑ1AÓBÀ1ÑEˆÔÜœŸ™› tÑ+Ó,ˆ�
r,   rL   )r-   r.   r/   r1   r2   r   r   r4   r>   r?   rK   r$   r,   r*   rO   rO   t   sS   … àÓØƒMØÓØÓÙ TÔ*€Dˆ#�‰*Ó*Ù˜EÔ"€Eˆ3Ó"Ù$¨%Ô0€L�#˜‘*Ó0ô-r,   rO   c                   ó   — e Zd ZU eed<   y)Ú_BucketDeleteFilerG   N)r-   r.   r/   r1   r2   r$   r,   r*   rT   rT   ƒ   s   … à
„Ir,   rT   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.   r/   r0   r4   r2   r   r$   r,   r*   rW   rW   ˆ   s   … ñ	ð ƒIØÔr,   rW   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_   r`   )r(   Úurl_pathÚparseds      r*   rK   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,   rL   )r-   r.   r/   r0   r1   r2   r]   r   r^   r_   r`   r   rK   r$   r,   r*   rZ   rZ   ™   sJ   … ñð  
ƒHØ€HˆcÓÙ Ô&€IˆsÓ&Ù Ô&€IˆsÓ&Ù˜EÔ"€CˆÓ"ôr,   rZ   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ÚtyperG   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 )Nrq   rG   r   ÚxetHashr>   Ú
uploadedAt)r%   rq   rG   r   r;   r   r>   rr   )r(   r)   r>   rr   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.   r/   r0   r   r2   r1   r4   r   r+   r$   r,   r*   ro   ro   Á   s<   … ñð �&‰/ÓØ
ƒIØ
ƒIØƒMØ�d‰?ÓØ˜D‘Ó óPr,   ro   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.
    Ú	directoryrq   rG   Nrr   c                 ó  — |j                  d«      | _        |j                  d«      | _        |j                  dd «      xs |j                  dd «      }|r)t        |t        «      r|| _        y t        |«      | _        y d | _        y )Nrq   rG   ru   rr   )r%   rq   rG   rB   r   r   rr   )r(   r)   rr   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.   r/   r0   r   r2   r1   r   r+   r$   r,   r*   rw   rw   Û   s(   … ñð �+Ñ
ÓØ
ƒIØ˜D‘Ó ó
r,   rw   rG   rM   c                 ó`  — | j                  t        j                  «      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 )z�Parse a bucket path into a HfUri.

    Accepts both `hf://buckets/namespace/name(/path/in/repo)` and plain `namespace/name(/path/in/repo)`.
    zInvalid bucket path: z*. Must be a bucket URI (hf://buckets/...).rb   é   r   r   zInvalid bucket path: 'z)'. Expected format: namespace/bucket_nameNÚbucket)rq   r   ri   )
rf   r   ÚHF_PROTOCOLr   Ú	is_bucketrj   rk   rg   Újoinr   )rG   rm   Úpartsr_   Úprefixs        r*   rh   rh   ÷   s¼   € ð
 ‡�”y×,Ñ,Ô-Ü˜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)rf   r   r}   r   r~   )rG   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ÚactionrG   Nr   r\   ÚreasonÚlocal_mtimeÚremote_mtimeÚbucket_file)r-   r.   r/   r0   r   r2   r1   r   r4   r‹   rŒ   r�   rŽ   ro   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.r7   ÚdestÚ	timestamp)Údefault_factoryÚ
operationsrM   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>0  ó   è ø€ Ò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>1  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>2  rœ   r�   c              3   ó@   K  — | ]  }|j                   d k(  sŒd–— Œ y­w)r‰   r   Nr—   r˜   s     r*   r›   z#SyncPlan.summary.<locals>.<genexpr>3  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>4  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.summary/  s   € ÜÑK $§/¡/ÔKÓKˆÜÑO D§O¡OÔOÓOˆ	ÜÑK $§/¡/ÔKÓKˆÜÑG §¡ÔGÓGˆÜÑg°·±ÔgÓgˆ
àØ"ØØØ$ñ
ð 	
r,   N)r-   r.   r/   r0   r1   r2   r   Úlistr”   r…   Údictr4   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__F  s+   € ð !1Ò 6°BˆÔØ 0Ò 6°BˆÔØ(Ò.¨BˆÕr,   rG   rM   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(   rG   ÚsignÚpatterns       r*   ÚmatcheszFilterMatcher.matchesW  s˜   € ð "×.Ñ.ò 	#‰MˆD�'Ü�‰˜t WÕ-Ø˜s‘{Ò"ð	#ð
 ×,Ñ,ò 	ˆGÜ�‰˜t WÕ-Ùð	ð ×,Ñ,ò 	ˆGÜ�‰˜t WÕ-Ùð	ð
 × Ò Øð r,   )NNN)
r-   r.   r/   r0   rª   r1   Útupler+   r3   r¸   r$   r,   r*   r­   r­   C  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ú-)Úopenre   rf   Úappend)rº   ÚrulesÚfÚlines       r*   Ú_parse_filter_filerÃ   t  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   )rF   ÚstatÚOSErrorÚS_ISDIRÚst_modeÚst_sizeÚst_mtime)rG   Ú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: Nrb   r   r   )rF   rG   ÚabspathÚisdirrj   Úwalkr   rÌ   Úrelpathrd   Ú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�   Ú	recursiverb   r   éÿÿÿÿr   r   )
Úlist_bucket_treerB   rw   rG   rf   rg   Úrsplitr>   r’   r   )rÜ   r_   r�   ÚitemrG   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†   )rG   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)rG   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,   Fr7   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.©r7   r‘   r’   NzSource must be a directory: zScanning local directory (z files)rb   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Š   rG   r   r‹   rŒ   r†   znew filezlocal newerzremote newer)rG   rŠ   rë   rì   rí   rî   rï   rð   rñ   rò   ró   rˆ   znot in source (--delete))rŠ   rG   r   r‹   r�   r‡   )rŠ   rG   r   r‹   r�   rŽ   )rG   rŠ   rë   rì   rí   rî   rï   rð   rñ   rò   ró   rŽ   )'r­   rƒ   rj   r�   r   Únowr   rè   ré   rF   rG   rÏ   rh   r   ri   rÐ   rÛ   r¸   r'   rg   ÚdoneÚbucket_infor    Ú	Exceptionrä   r   ÚloggerÚdebugÚsetÚkeysÚsortedÚgetr”   r¿   r…   rê   rþ   r   rÌ   )%r7   r‘   rÜ   rˆ   rò   rñ   rÿ   ró   r   r  Ú	is_uploadÚis_downloadÚplanÚremote_totalrÍ   rm   r_   r�   Úlocal_filesrÚ   r   rã   Úremote_filesrÕ   Ú	total_strÚ	all_pathsrG   Ú
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)rq   r7   r‘   r’   r©   ú
Ú	operation)rq   rŠ   rG   r‹   Nr   rŒ   r�   )r7   r‘   r’   r©   ÚwriteÚjsonÚdumpsr”   rŠ   rG   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)  >  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   rq   r  z0Invalid plan file: expected header as first liner7   r‘   r’   r  r   r   rŠ   rG   r   r‹   r\   rŒ   r�   )rŠ   rG   r   r‹   rŒ   r�   )
r¾   Ú	readlinesrj   r"  Úloadsr  r�   r”   r¿   r…   )r&  rÁ   Úlinesr  r  rÂ   r$  s          r*   Ú
_load_planr.  D  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†   rb   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ƒ   r7   r‘   rF   rG   rÏ   rh   r   ri   r”   rŠ   r   Úprintr‹   r¿   rg   r  Ú
capitalizeÚbatch_bucket_filesÚmakedirsÚdirnamerŽ   Údownload_bucket_filesÚexistsÚremoveÚrmdirrÆ   )r  rÜ   r/  r  r  r  rÍ   rm   r_   r�   Ú	add_filesÚdelete_pathsrš   r  Úremote_pathr€   Údownload_filesÚdelete_filesÚ	file_pathÚparents                       r*   Ú_execute_planrD  o  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©   r4  r7   r‘   )r  r©   s     r*   Ú_print_plan_summaryrF  Ó  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_runr/  ÚquietÚtokenrG  rH  rI  rJ  rK  rL  rM  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   )rM  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...)r/  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²   )
r7   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   rj   r.  r   rF  r4  r   rD  r   rƒ   rF   rG   r:  rÐ   rÃ   r­   r  r%  ÚsysÚstdoutr)  r©   )r7   r‘   rÜ   rˆ   rò   rñ   rÿ   ró   rG  rH  rI  r  rJ  rK  r/  rL  rM  r   Ú	sync_planr  Úsource_is_bucketÚdest_is_bucketr°   r   r©   s                            r*   Úsync_bucket_internalrV  â  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)Ir0   rµ   r"  rC   rF   rÅ   rQ  rI   Úcollections.abcr   Údataclassesr   r   r   r   Úpathlibr   Útypingr	   r
   r   r\   r   r   Úerrorsr   Úutilsr   r   r   r   r   r   r   rP  r   Ú
get_loggerr-   r  ÚBUCKET_PREFIXrö   r   r6   rO   rT   rW   rZ   ro   rw   r1   rh   r3   rƒ   r…   r�   r­   rª   r¹   rÃ   r4   ÚfloatrÌ   rÛ   rä   rê   rþ   r  r%  r)  r.  rD  rF  rV  r$   r,   r*   ú<module>r`     sc  ðñó
 Û Û Û 	Û Û 
Û Ý $ß (ß 'Ý ß .Ñ .ç  Ý '÷÷ ñ ñ Ýð 
ˆ×	Ñ	˜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,   