ó
    pyüic¯  ã            &       ó$  • S r SSKrSSKrSSKrSSKrSSKrSSKrSSKrSSKJ	r	  SSK
JrJr  SSKJrJr  SSKJr  SSKJrJrJr  SS	KJrJr  SS
KJr  SSKJrJrJrJr  SSKJ r   \(       a  SSK!J"r"  \RF                  " \$5      r%Sr&Sr'S\(S\)\(\(4   4S jr*\ " S S5      5       r+\ " S S5      5       r,\ " S S5      5       r-\ " S S5      5       r.\" SS9 " S S5      5       r/\ " S S 5      5       r0\ " S! S"5      5       r1\ " S# S$5      5       r2S\(S\)\(\(4   4S% jr3S\(S\44S& jr5\ " S' S(5      5       r6\ " S) S*5      5       r7 " S+ S,5      r8S-\(S\9\)\(\(4      4S. jr:S\(S\)\;\<4   S-  4S/ jr=S0\(S\	\)\(\;\<4      4S1 jr>S2S3S4\(S5\(S\	\)\(\;\<\4      4S6 jr?S7\<S\(4S8 jr@SS9.S\(S:\S;   S<\;S=\<S>\;S?\<S@\(SA\(SB\4SC\4SD\4SE\S-  S\64SF jjrA       S`SH\(SI\(S2S3SJ\4SC\4SB\4SK\4SD\4SL\8S-  SM\S-  S\74SN jjrBSO\7SS4SP jrCSO\7SQ\(SS4SR jrDSQ\(S\74SS jrESaSO\7S2S3ST\4SM\S-  SS4
SU jjrFSO\7SS4SV jrG  SbSGSGSGSGSGSSSSSSGSGSGSSW.SH\(S-  SI\(S-  S2S3SJ\4SC\4SB\4SK\4SD\4SX\9\(   S-  SY\9\(   S-  SZ\(S-  SO\(S-  S[\(S-  S\\4ST\4S]\4S^\4\(-  S-  S\74$S_ jjjrHg)czzShared 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)ÚXetFileDataÚdisable_progress_barsÚenable_progress_barsÚparse_datetime)Ú
StatusLine©ÚHfApiúhf://buckets/éè  ÚpathÚreturnc                 óÖ   • U R                  SS5      n[        U5      S:  d  US   (       a
  US   (       d  [        SU  S35      eUS    SUS    3n[        U5      S:”  a  US   OSnX#4$ )zÎSplit 'namespace/name(/optional/prefix)' into ('namespace/name', 'prefix').

Returns (bucket_id, prefix) where prefix may be empty string.
Raises ValueError if path doesn't contain at least namespace/name.
Ú/é   r   r   zInvalid bucket path: 'z)'. Expected format: namespace/bucket_nameÚ )ÚsplitÚlenÚ
ValueError)r   ÚpartsÚ	bucket_idÚprefixs       ÚU/home/mande/repo/quber/.venv/lib/python3.13/site-packages/huggingface_hub/_buckets.pyÚ_split_bucket_id_and_prefixr&   6   sw   € ð �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Ü˜U› a›ˆU�1ŠX¨R€FØÐÐó    c                   óR   • \ rS rSr% Sr\\S'   \\S'   \\S'   \	\S'   \	\S'   S r
S	rg
)Ú
BucketInfoéD   a«  
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                 ó*  • UR                  S5      U l        UR                  S5      U l        [        UR                  S5      5      U l        UR                  S5      U l        UR                  S5      U l        U R                  R                  " S0 UD6  g )Nr+   r,   Ú	createdAtr.   Ú
totalFiles© )	Úpopr+   r,   r   r-   r.   r/   Ú__dict__Úupdate)ÚselfÚkwargss     r%   Ú__init__ÚBucketInfo.__init__\   sm   € Ø—*‘*˜TÓ"ˆŒØ—z‘z )Ó,ˆŒÜ(¨¯©°KÓ)@ÓAˆŒØ—J‘J˜vÓ&ˆŒ	Ø!Ÿ:™: lÓ3ˆÔØ�‰×ÒÑ&˜vÓ&r'   )r-   r+   r,   r.   r/   N)Ú__name__Ú
__module__Ú__qualname__Ú__firstlineno__Ú__doc__ÚstrÚ__annotations__Úboolr   Úintr9   Ú__static_attributes__r3   r'   r%   r)   r)   D   s)   ‡ ñð  	ƒGØƒMØÓØ
ƒIØÓõ'r'   r)   c                   óª   • \ rS rSr% \\-  \-  \S'   \\S'   \" SS9r	\S-  \S'   \" SS9r
\S-  \S'   \" SS	9r\\S
'   \" SS	9r\S-  \S'   SS jrSrg)Ú_BucketAddFileée   ÚsourceÚdestinationN©ÚdefaultÚxet_hashr.   F©ÚinitÚmtimeÚcontent_typec                 óø  • S U l         [        U R                  [        [        45      (       a(  [
        R                  " U R                  5      S   U l         U R                   c(  [
        R                  " U R                  5      S   U l         [        [        U R                  [        5      (       d,  [        R                  R                  U R                  5      S-  O[        R                  " 5       S-  5      U l        g ©Nr   r   )rP   Ú
isinstancerH   r@   r   Ú	mimetypesÚ
guess_typerI   rC   ÚbytesÚosr   ÚgetmtimeÚtimerO   ©r7   s    r%   Ú__post_init__Ú_BucketAddFile.__post_init__o   s¯   € Ø ˆÔÜ�d—k‘k¤C¬ ;×/Ñ/Ü )× 4Ò 4°T·[±[Ó AÀ!Ñ DˆDÔØ×ÑÑ$Ü )× 4Ò 4°T×5EÑ5EÓ FÀqÑ IˆDÔäÜ8BÀ4Ç;Á;ÔPU×8VÑ8VŒB�G‰G×Ñ˜TŸ[™[Ó)¨DÒ0Ô\`×\eÒ\eÓ\gÐjnÑ\nó
ˆ�
r'   ©rP   rO   ©r   N)r;   r<   r=   r>   r@   r   rV   rA   r   rL   r.   rC   rO   rP   r[   rD   r3   r'   r%   rF   rF   e   sd   ‡ à�$‰J˜ÑÓØÓá ¨Ñ.€Hˆc�D‰jÓ.Ù TÑ*€Dˆ#�‰*Ó*Ù˜EÑ"€Eˆ3Ó"Ù$¨%Ñ0€L�#˜‘*Ó0÷	
r'   rF   c                   ó–   • \ rS rSr% \\S'   \\S'   \\S'   \\S'   \" SS9r\S-  \S'   \" S	S
9r	\\S'   \" S	S
9r
\S-  \S'   SS jrSrg)Ú_BucketCopyFileé{   rI   rL   Úsource_repo_typeÚsource_repo_idNrJ   r.   FrM   rO   rP   c                 ó    • [         R                  " U R                  5      S   U l        [	        [
        R
                  " 5       S-  5      U l        g rR   )rT   rU   rI   rP   rC   rY   rO   rZ   s    r%   r[   Ú_BucketCopyFile.__post_init__…   s7   € Ü%×0Ò0°×1AÑ1AÓBÀ1ÑEˆÔÜœŸš› tÑ+Ó,ˆ�
r'   r]   r^   )r;   r<   r=   r>   r@   rA   r   r.   rC   rO   rP   r[   rD   r3   r'   r%   r`   r`   {   sS   ‡ àÓØƒMØÓØÓÙ TÑ*€Dˆ#�‰*Ó*Ù˜EÑ"€Eˆ3Ó"Ù$¨%Ñ0€L�#˜‘*Ó0÷-r'   r`   c                   ó    • \ rS rSr% \\S'   Srg)Ú_BucketDeleteFileéŠ   r   r3   N)r;   r<   r=   r>   r@   rA   rD   r3   r'   r%   rg   rg   Š   s   ‡ à
†Ir'   rg   T)Úfrozenc                   ó.   • \ rS rSr% Sr\\S'   \\S'   Srg)ÚBucketFileMetadataé�   a	  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_datar3   N)	r;   r<   r=   r>   r?   rC   rA   r   rD   r3   r'   r%   rk   rk   �   s   ‡ ñ	ð ƒIØÖr'   rk   c                   ó~   • \ rS rSr% Sr\\S'   Sr\\S'   \" SS9r	\\S'   \" SS9r
\\S	'   \" SS9r\\S
'   SS jrSrg)Ú	BucketUrlé    aŽ  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`)
- handle (`str`)

Args:
    url (`str`):
        String value of the bucket url.
    endpoint (`str`, *optional*):
        Endpoint of the Hub. Defaults to <https://huggingface.co>.
Úurlr   ÚendpointFrM   Ú	namespacer#   ÚhandleNc                 óÄ  • U R                   =(       d    [        R                  U l         U R                  R	                  U R                   S5      R                  S5      nUR                  S5      (       a  U[        S5      S  n[        U5      u  p#U(       a  [        SU R                   35      eUR                  S5      S   U l        X l        SU R                   3U l        g )Nr   r   zbuckets/zUnable to parse bucket URL: r   r   )rr   r   ÚENDPOINTrq   ÚreplaceÚstripÚ
startswithr    r&   r!   r   rs   r#   rt   )r7   Úurl_pathr#   r$   s       r%   r[   ÚBucketUrl.__post_init__¸   sµ   € ØŸ™×;¬×);Ñ);ˆŒð —8‘8×#Ñ# D§M¡M°2Ó6×<Ñ<¸SÓAˆà×Ñ˜z×*Ñ*Ø¤ J£Ð 1Ð2ˆHÜ7¸ÓAÑˆ	ÞÜÐ;¸D¿H¹H¸:ÐFÓGÐGØ"Ÿ™¨Ó-¨aÑ0ˆŒØ"Œà% d§n¡nÐ%5Ð6ˆ�r'   )r#   rr   rt   rs   r^   )r;   r<   r=   r>   r?   r@   rA   rr   r   rs   r#   rt   r[   rD   r3   r'   r%   ro   ro       sJ   ‡ ñð  
ƒHØ€HˆcÓÙ Ñ&€IˆsÓ&Ù Ñ&€IˆsÓ&Ù˜UÑ#€FˆCÓ#÷7r'   ro   c                   ón   • \ rS rSr% Sr\S   \S'   \\S'   \\S'   \\S'   \	S-  \S	'   \	S-  \S
'   S r
Srg)Ú
BucketFileéÉ   zŸ
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Útyper   r.   rL   NrO   Úuploaded_atc                 ól  • UR                  S5      U l        UR                  S5      U l        UR                  S5      U l        UR                  S5      U l        UR                  SS 5      nU(       a  [        U5      OS U l        UR                  SS 5      nU(       a  [        U5      U l        g S U l        g )Nr€   r   r.   ÚxetHashrO   Ú
uploadedAt)r4   r€   r   r.   rL   r   rO   r�   )r7   r8   rO   r�   s       r%   r9   Ú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'   )rO   r   r.   r€   r�   rL   )r;   r<   r=   r>   r?   r   rA   r@   rC   r   r9   rD   r3   r'   r%   r}   r}   É   s<   ‡ ñð �&‰/ÓØ
ƒIØ
ƒIØƒMØ�d‰?ÓØ˜D‘Ó õPr'   r}   c                   óJ   • \ rS rSr% Sr\S   \S'   \\S'   \S-  \S'   S r	S	r
g)
ÚBucketFolderéã   z¬
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.
Ú	directoryr€   r   Nr�   c                 ó,  • UR                  S5      U l        UR                  S5      U l        UR                  SS 5      =(       d    UR                  SS 5      nU(       a/  [        U[        5      (       a  UU l        g [        U5       U l        g S U l        g )Nr€   r   r„   r�   )r4   r€   r   rS   r   r   r�   )r7   r8   r�   s      r%   r9   ÚBucketFolder.__init__ï   s   € Ø—J‘J˜vÓ&ˆŒ	Ø—J‘J˜vÓ&ˆŒ	Ø—j‘j ¨tÓ4×W¸¿
¹
À=ÐRVÓ8Wˆö ô ' {´H×=Ñ=ˆ[ð 	ÕÜCQÐR]ÔC^ð 	Õð ð 	Õr'   )r   r€   r�   )r;   r<   r=   r>   r?   r   rA   r@   r   r9   rD   r3   r'   r%   r‡   r‡   ã   s(   ‡ ñð �+Ñ
ÓØ
ƒIØ˜D‘Ó õ
r'   r‡   c                 óœ   • U R                  [        5      (       d  [        SU  S[         35      e[        U R	                  [        5      5      $ )zÑParse a bucket path like hf://buckets/namespace/bucket_name/prefix into (bucket_id, prefix).

Returns:
    tuple: (bucket_id, prefix) where bucket_id is "namespace/bucket_name" and prefix may be empty string.
zInvalid bucket path: z. Must start with )ry   ÚBUCKET_PREFIXr!   r&   Úremoveprefix©r   s    r%   Ú_parse_bucket_pathr�   ÿ   sC   € ð �?‰?œ=×)Ñ)ÜÐ0°°Ð6HÌÈÐXÓYÐYÜ& t×'8Ñ'8¼Ó'GÓHÐHr'   c                 ó,   • U R                  [        5      $ )z!Check if a path is a bucket path.)ry   r�   r�   s    r%   Ú_is_bucket_pathr’   
  s   € à�?‰?œ=Ó)Ð)r'   c                   ó’   • \ rS rSr% Sr\S   \S'   \\S'   Sr\	S-  \S'   Sr
\\S	'   Sr\S-  \S
'   Sr\S-  \S'   Sr\S-  \S'   Srg)ÚSyncOperationi  z,Represents a sync operation to be performed.)ÚuploadÚdownloadÚdeleteÚskipÚactionr   Nr.   r   ÚreasonÚlocal_mtimeÚremote_mtimeÚbucket_filer3   )r;   r<   r=   r>   r?   r   rA   r@   r.   rC   rš   r›   rœ   r�   r}   rD   r3   r'   r%   r”   r”     sY   ‡ á6àÐ:Ñ;Ó;Ø
ƒIØ€Dˆ#�‰*ÓØ€FˆCÓØ"€K��t‘Ó"Ø#€L�#˜‘*Ó#Ø%)€K�˜dÑ"Ö)r'   r”   c                   ór   • \ rS rSr% Sr\\S'   \\S'   \\S'   \" \S9r	\\
   \S'   S\\\\-  4   4S	 jrS
rg)ÚSyncPlani!  z Represents a complete sync plan.rH   ÚdestÚ	timestamp)Údefault_factoryÚ
operationsr   c                 ó*  • [        S U R                   5       5      n[        S U R                   5       5      n[        S U R                   5       5      n[        S U R                   5       5      n[        S U R                   5       5      nUUUUUS.$ )Nc              3   óH   #   • U  H  oR                   S :X  d  M  Sv •  M     g7f)r•   r   N©r™   ©Ú.0Úops     r%   Ú	<genexpr>Ú#SyncPlan.summary.<locals>.<genexpr>+  ó   é € ÐK¢/˜B·Y±YÀ(Ñ5J—a‘a¢/ùó   ‚"™	"c              3   óH   #   • U  H  oR                   S :X  d  M  Sv •  M     g7f)r–   r   Nr¦   r§   s     r%   rª   r«   ,  s   é € ÐO¢O˜b·y±yÀJÑ7NŸ™¢Oùr­   c              3   óH   #   • U  H  oR                   S :X  d  M  Sv •  M     g7f)r—   r   Nr¦   r§   s     r%   rª   r«   -  r¬   r­   c              3   óH   #   • U  H  oR                   S :X  d  M  Sv •  M     g7f)r˜   r   Nr¦   r§   s     r%   rª   r«   .  s   é € ÐG¢˜"·9±9ÀÑ3F—A‘A¢ùr­   c              3   ón   #   • U  H+  oR                   S ;   d  M  UR                  =(       d    Sv •  M-     g7f)©r•   r–   r   N)r™   r.   r§   s     r%   rª   r«   /  s&   é € Ðg²¨"Ç9Á9ÐPfÑCf›˜Ÿ™Ÿ Aœ²ùs   ‚5™5)ÚuploadsÚ	downloadsÚdeletesÚskipsÚ
total_size)Úsumr£   )r7   r³   r´   rµ   r¶   r·   s         r%   ÚsummaryÚSyncPlan.summary*  s   € ÜÑK $§/¢/ÓKÓKˆÜÑO D§O¢OÓOÓOˆ	ÜÑK $§/¢/ÓKÓKˆÜÑG §¢ÓGÓGˆÜÑg°·²ÓgÓgˆ
àØ"ØØØ$ñ
ð 	
r'   r3   N)r;   r<   r=   r>   r?   r@   rA   r   Úlistr£   r”   ÚdictrC   r¹   rD   r3   r'   r%   rŸ   rŸ   !  sA   ‡ á*àƒKØ
ƒIØƒNÙ&+¸DÑ&A€J��]Ñ#ÓAð
˜˜c 3¨¡9˜nÑ-÷ 
r'   rŸ   c            
       óx   • \ rS rSrSr   SS\\   S-  S\\   S-  S\\\\4      S-  4S jjrS\S	\	4S
 jr
Srg)ÚFilterMatcheri>  z4Matches file paths against include/exclude patterns.NÚinclude_patternsÚexclude_patternsÚfilter_rulesc                 ód   • U=(       d    / U l         U=(       d    / U l        U=(       d    / U l        g)zê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Á   )r7   r¿   rÀ   rÁ   s       r%   r9   ÚFilterMatcher.__init__A  s+   € ð !1× 6°BˆÔØ 0× 6°BˆÔØ(×.¨BˆÕr'   r   r   c                 óV  • U R                    H'  u  p#[        R                  " X5      (       d  M"  US:H  s  $    U R                   H   n[        R                  " X5      (       d  M     g   U R                   H   n[        R                  " X5      (       d  M     g   U R                  (       a  gg)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¿   )r7   r   ÚsignÚpatterns       r%   ÚmatchesÚFilterMatcher.matchesR  sŠ   € ð "×.Ô.‰MˆDÜ�Š˜t×-Ó-Ø˜s‘{Ò"ñ /ð
 ×,Ô,ˆGÜ�Š˜t×-Ó-Ùñ -ð ×,Ô,ˆGÜ�Š˜t×-Ó-Ùñ -ð
 × × Øð r'   )rÀ   rÁ   r¿   )NNN)r;   r<   r=   r>   r?   r»   r@   Útupler9   rB   rÊ   rD   r3   r'   r%   r¾   r¾   >  sh   † Ù>ð .2Ø-1Ø59ñ	/à˜s™) dÑ*ð/ð ˜s™) dÑ*ð/ð ˜5  c ™?Ñ+¨dÑ2õ	/ð"˜Cð  D÷ r'   r¾   Úfilter_filec                 óÜ  • / n[        U 5       nU H½  nUR                  5       nU(       a  UR                  S5      (       a  M2  UR                  S5      (       a&  UR                  SUSS R                  5       45        Mn  UR                  S5      (       a&  UR                  SUSS R                  5       45        Mª  UR                  SU45        M¿     SSS5        U$ ! , (       d  f       U$ = f)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Ú-)Úopenrx   ry   Úappend)rÍ   ÚrulesÚfÚlines       r%   Ú_parse_filter_filerÖ   o  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   ŽCCÃ
C+c                 óÒ   •  [         R                  " U 5      n[        R                  " UR                  5      (       a  gUR
                  UR                  S-  4$ ! [         a     gf = f)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   )rW   ÚstatÚOSErrorÚS_ISDIRÚst_modeÚst_sizeÚst_mtime)r   Ústs     r%   Ú_stat_localrß   Œ  sX   € ðÜ�WŠW�T‹]ˆô ‡|‚|�B—J‘J×ÑØØ�:‰:�r—{‘{ TÑ)Ð)Ð)øô	 ó Ùðús   ‚A Á
A&Á%A&Ú
local_pathc              #   óô  #   • [         R                  R                  U 5      n [         R                  R                  U 5      (       d  [	        SU  35      e[         R
                  " U 5       H‰  u  pnU H}  n[         R                  R                  X5      n[        U5      nUc  M2  [         R                  R                  XP5      nUR                  [         R                  S5      nXvS   US   4v •  M     M‹     g7f)zgList all files in a local directory.

Yields:
    tuple: (relative_path, size, mtime_ms) for each file
z Local path must be a directory: Nr   r   r   )rW   r   ÚabspathÚisdirr!   ÚwalkÚjoinrß   Úrelpathrw   Úsep)rà   ÚrootÚ_ÚfilesÚfilenameÚ	full_pathÚ	stat_infoÚrel_paths           r%   Ú_list_local_filesrï   ›  sÀ   é € ô —‘—‘ Ó,€JÜ�7‰7�=‰=˜×$Ñ$ÜÐ;¸J¸<ÐHÓIÐIäŸ'š' *Ö-‰ˆ�ÛˆHÜŸ™Ÿ™ TÓ4ˆIÜ# IÓ.ˆIØÑ ÙÜ—w‘w—‘ yÓ=ˆHà×'Ñ'¬¯©°Ó4ˆHØ a™L¨)°A©,Ð6Ô6ó ò .ùs   ‚C6C8Úapir   r#   r$   c              #   óÄ  #   • U R                  X=(       d    SSS9 H¿  n[        U[        5      (       a  M  UR                  nU(       aP  UR	                  US-   5      (       a  U[        U5      S-   S nO'XB:X  a  SU;   a  UR                  SS5      S   OUnOM}  UnUR                  (       a  UR                  R                  5       S-  OSnXSR                  Xc4v •  MÁ     g7f)	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$   Ú	recursiver   r   éÿÿÿÿr   r   )
Úlist_bucket_treerS   r‡   r   ry   r    ÚrsplitrO   r¡   r.   )rð   r#   r$   Úitemr   rî   Úmtime_mss          r%   Ú_list_remote_filesrø   ±  sÇ   é € ð ×$Ñ$ Y·~ÀÐQUÐ$ÓVˆÜ�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Ð1Ô1ò' Wùs   ‚CC r÷   c                 ój   • [         R                  " U S-  [        R                  S9R	                  5       $ )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                 óæ  • [        US:X  a  UOU5      n[        US:X  a  UOU5      nU UUUS.nU
(       a  [        SSSS.UD6$ X$:g  nX5-
  [        :„  nU(       a9  U(       a  [        SXUS.UD6$ XS-
  [        :„  nU(       a  UOSn[        SSUS.UD6$ U	(       a$  U(       a  [        SUSUS.UD6$ [        SSS	S.UD6$ U(       d  U(       a  U(       a  SOUn[        SUUUS.UD6$ [        SSS
S.UD6$ )aS  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•   )r   r.   r›   rœ   r˜   z&exists on receiver (--ignore-existing))r™   rš   )r™   rš   r�   z
same mtimezsize differsz	same sizeÚ	identicalr3   )rþ   r”   Ú_SYNC_TIME_WINDOW_MS)r   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  Ø  s-  € ô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¨Ð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'   FrH   r    r—   ÚexistingÚfilter_matcherÚstatusc
                 ó
  • U=(       d
    [        5       n[        U 5      (       + =(       a    [        U5      n
[        U 5      =(       a    [        U5      (       + nU
(       d  U(       d  [        S5      e[        U U[        R
                  " [        R                  5      R                  5       S9nSnU
(       Ga>  [        R                  R                  U 5      n[        U5      u  nn[        R                  R                  U5      (       d  [        SU 35      e0 n[        U5       HK  u  nnnUR                  U5      (       a  UU4UU'   U	(       d  M-  U	R!                  S[#        U5       S35        MM     U	(       a  U	R%                  S[#        U5       S35        0 nU	(       a   UR'                  U5      R(                  n [-        X/U5       HX  u  nnnnUR                  U5      (       a  UU4UU'   U	(       d  M.  Ub  SU 3OSnU	R!                  S	[#        U5       U S35        MZ     U	(       a  U	R%                  S	[#        U5       S35        [5        UR7                  5       5      [5        UR7                  5       5      -  nU	(       a  U	R%                  S[#        U5       S35        [9        U5       GHA  nUR;                  U5      nUR;                  U5      nU(       a|  U(       du  U(       a7  UR<                  R?                  [A        SUUS   S[C        US   5      S95        Mr  UR<                  R?                  [A        SUUS   S[C        US   5      S95        M©  U(       a?  U(       a8  Uu  nnUu  nnUR<                  R?                  [E        USUUUUSSUUUS95        Mï  U(       a  Mø  U(       d  GM  U(       d  GM  UR<                  R?                  [A        SUUS   S[C        US   5      S95        GMD     U$ [        U 5      u  nn[        R                  R                  U5      n0 n0 n U	(       a   UR'                  U5      R(                  n[-        X/U5       H]  u  nnnn!UR                  U5      (       a  UU4UU'   U!U U'   U	(       d  M3  Ub  SU 3OSnU	R!                  S	[#        U5       U S35        M_     U	(       a  U	R%                  S	[#        U5       S35        0 n[        R                  R                  U5      (       aÇ  U(       a[  [        U5       HK  u  nnnUR                  U5      (       a  UU4UU'   U	(       d  M-  U	R!                  S[#        U5       S35        MM     OeU H_  n[        R                  RG                  UU5      n"[I        U"5      n#U#c  M3  U#UU'   U	(       d  MA  U	R!                  S[#        U5       S35        Ma     U	(       a  U	R%                  S[#        U5       S35        [5        UR7                  5       5      [5        UR7                  5       5      -  nU	(       a  U	R%                  S[#        U5       S35        [9        U5       GHc  nUR;                  U5      nUR;                  U5      nU(       aŒ  U(       d…  U(       a7  UR<                  R?                  [A        SUUS   S[C        US   5      S95        Mr  UR<                  R?                  [A        SUUS   S[C        US   5      U R;                  U5      S95        M¹  U(       aP  U(       aI  Uu  nnUu  nnUR<                  R?                  [E        USUUUUSSUUUU R;                  U5      S95        GM  U(       a  GM  U(       d  GM$  U(       d  GM.  UR<                  R?                  [A        SUUS   S[C        US   5      S95        GMf     U$ ! [*         a     GNf = f! [.         a    [0        R3                  S
U S35         GNÌf = f! [*         a     GN¹f = f)zvCompute 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.©rH   r    r¡   NzSource must be a directory: zScanning local directory (z files)r   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™   r   r.   rš   r›   r•   znew filezlocal newerzremote newer)r   r™   rÿ   r   r  r  r  r  r  r  r  r—   znot in source (--delete))r™   r   r.   rš   rœ   r–   )r™   r   r.   rš   rœ   r�   )r   r™   rÿ   r   r  r  r  r  r  r  r  r�   )%r¾   r’   r!   rŸ   r   Únowr   rü   rý   rW   r   râ   r�   rã   rï   rÊ   r6   r    ÚdoneÚbucket_infor/   Ú	Exceptionrø   r   ÚloggerÚdebugÚsetÚkeysÚsortedÚgetr£   rÒ   r”   rþ   r  rå   rß   )$rH   r    rð   r—   r  r  r  r  r  r  Ú	is_uploadÚis_downloadÚplanÚremote_totalrà   r#   r$   Úlocal_filesrî   r.   r÷   Úremote_filesré   Ú	total_strÚ	all_pathsr   Ú
local_infoÚremote_infoÚ
local_sizer›   Úremote_sizerœ   Úbucket_file_mapr�   Ú
local_filerí   s$                                       r%   Ú_compute_sync_planr0     ss  € ð" $×6¤}£€NÜ# FÓ+Ô+×E´ÀÓ0E€IÜ! &Ó)×G´/À$Ó2GÔ.G€Kæž[ÜÐvÓwÐwäØØÜ—,’,œxŸ|™|Ó,×6Ñ6Ó8ñ€Dð  $€Lßä—W‘W—_‘_ VÓ,ˆ
Ü.¨tÓ4Ñˆ	�6ä�w‰w�}‰}˜Z×(Ñ(ÜÐ;¸J¸<ÐHÓIÐIð ˆÜ(9¸*Ö(EÑ$ˆH�d˜HØ×%Ñ% h×/Ñ/Ø)-¨xÐ(8�˜HÑ%ßˆvØ—‘Ð :¼3¸{Ó;KÐ:LÈGÐTÖUñ	 )Fö
 Ø�K‰KÐ4´S¸Ó5EÐ4FÀgÐNÔOàˆÞðØ"Ÿ™¨yÓ9×EÑE�ð		PÜ/AÀ#ÐRXÖ/YÑ+�˜$ ¨!Ø!×)Ñ)¨(×3Ñ3Ø.2°HÐ-=�L Ñ*ß�6Ø6BÑ6N ! L >Ñ 2ÐTV�IØ—M‘MÐ$<¼SÀÓ=NÐ<OÐPYÈ{ÐZaÐ"bÖcñ 0Zö Ø�K‰KÐ2´3°|Ó3DÐ2EÀWÐMÔNô ˜×(Ñ(Ó*Ó+¬c°,×2CÑ2CÓ2EÓ.FÑFˆ	ÞØ�K‰KÐ+¬C°	«NÐ+;¸7ÐCÔDÜ˜9×%ˆ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ñö÷  �Z§K¡K·F±Fà—‘×&Ñ&Ü!Ø'Ø!Ø(¨™^Ø9Ü%2°;¸q±>Ó%Bñ÷ña &ðT €Kô] /¨vÓ6Ñˆ	�6Ü—W‘W—_‘_ TÓ*ˆ
ð ˆØ*,ˆÞðØ"Ÿ™¨yÓ9×EÑE�ô 6HÈÐX^Ö5_Ñ1ˆH�d˜H kØ×%Ñ% h×/Ñ/Ø*.°Ð)9�˜XÑ&Ø,7� Ñ)ßˆvØ2>Ñ2J˜a ˜~Ñ.ÐPR�	Ø—‘Ð 8¼¸\Ó9JÐ8KÈIÈ;ÐV]Ð^Ö_ñ 6`ö Ø�K‰KÐ2´3°|Ó3DÐ2EÀWÐMÔNàˆÜ�7‰7�=‰=˜×$Ñ$Þä0AÀ*Ö0MÑ,�H˜d HØ%×-Ñ-¨h×7Ñ7Ø15°xÐ0@˜ HÑ-ß�vØŸ™Ð(BÄ3À{ÓCSÐBTÐT[Ð&\Ö]ò	 1Nó !-�HÜ!#§¡§¡¨j¸(Ó!C�JÜ +¨JÓ 7�IØ Ñ(Ù Ø,5�K Ñ)ß�vØŸ™Ð(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¡Z·F±Fà—‘×&Ñ&Ü!Ø'Ø!Ø'¨™]Ø9Ü$1°*¸Q±-Ó$@ñ÷ñe &ðx €Køô{ ó Úðûô #ó 	Pä�L‰L˜8 I ;Ð.MÐN×Oð	Pûô^ ó Úðús<   Æ ^9 Æ<6_
 Ç6._
 Ð-_4 Þ9
_ß_ß
#_1ß0_1ß4
`à`r$  c                 ó$  • SU R                   U R                  U R                  U R                  5       S.nUR	                  [
        R                  " U5      S-   5        U R                   H¤  nSUR                  UR                  UR                  S.nUR                  b  UR                  US'   UR                  b  UR                  US'   UR                  b  UR                  US	'   UR	                  [
        R                  " U5      S-   5        M¦     g)
z1Write a sync plan as JSONL to a file-like object.Úheader)r€   rH   r    r¡   r¹   Ú
Ú	operation)r€   r™   r   rš   Nr.   r›   rœ   )rH   r    r¡   r¹   ÚwriteÚjsonÚdumpsr£   r™   r   rš   r.   r›   rœ   )r$  rÔ   r2  r©   Úop_dicts        r%   Ú_write_planr9    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                 óf   • [        US5       n[        X5        SSS5        g! , (       d  f       g= f)z!Save a sync plan to a JSONL file.ÚwN)rÑ   r9  )r$  r:  rÔ   s      r%   Ú
_save_planr=  7  s"   € ä	ˆi˜Ô	 Ü�DÔ÷ 
×	Ö	ús   �"¢
0c                 ó|  • [        U 5       nUR                  5       nSSS5        W(       d  [        SU  35      e[        R                  " US   5      nUR                  S5      S:w  a  [        S5      e[        US   US   US	   S
9nUSS  Hš  n[        R                  " U5      nUR                  S5      S:w  a  M0  UR                  R                  [        US   US   UR                  S5      UR                  SS5      UR                  S5      UR                  S5      S95        Mœ     U$ ! , (       d  f       GN= f)z#Load a sync plan from a JSONL file.NzEmpty plan file: r   r€   r2  z0Invalid plan file: expected header as first linerH   r    r¡   r  r   r4  r™   r   r.   rš   r   r›   rœ   )r™   r   r.   rš   r›   rœ   )
rÑ   Ú	readlinesr!   r6  Úloadsr!  rŸ   r£   rÒ   r”   )r:  rÔ   Úlinesr2  r$  rÕ   r8  s          r%   Ú
_load_planrB  =  s$  € ä	ˆ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,Ä,
D;Úverbosec                 óŒ  • [        U R                  5      (       + =(       a    [        U R                  5      n[        U R                  5      =(       a    [        U R                  5      (       + nU(       Gab  [        R                  R                  U R                  5      n[        U R                  5      u  pxUR                  S5      n/ n	/ n
U R                   GHH  nUR                  =S:X  a�    [        R                  R                  XkR                  5      nU(       a  U SUR                   3OUR                  nU(       a&  [        SUR                   SUR                   S35        U	R                  XÍ45        M¤  =S:X  af    U(       a  U SUR                   3OUR                  nU(       a&  [        SUR                   SUR                   S35        U
R                  U5        GM  S:X  d  GM  U(       d  GM"  [        S	UR                   SUR                   S35        GMK     U	(       d  U
(       a¥  U(       az  / nU	(       a  UR                  S
[        U	5       S35        U
(       a  UR                  S[        U
5       S35        UR                  SR                  U5      R!                  5       5        UR#                  UU	=(       d    SU
=(       d    SS9  ggU(       GaU  [        U R                  5      u  pxUR                  S5      n[        R                  R                  U R                  5      n[        R$                  " USS9  / n/ nU R                   GH¾  nUR                  S:X  aí  [        R                  R                  XkR                  5      n[        R$                  " [        R                  R'                  U5      SS9  U(       a&  [        SUR                   SUR                   S35        UR(                  b  UR                  UR(                  U45        MÈ  U(       a  U SUR                   3OUR                  nUR                  XÜ45        GM  UR                  S:X  aj  [        R                  R                  XkR                  5      nU(       a&  [        SUR                   SUR                   S35        UR                  U5        GM{  UR                  S:X  d  GMŽ  U(       d  GM˜  [        S	UR                   SUR                   S35        GMÁ     [        U5      S:”  a6  U(       a  UR                  S[        U5       S35        UR+                  X5        U(       a%  U(       a  UR                  S[        U5       S35        U H¤  n[        R                  R-                  U5      (       d  M)  [        R.                  " U5        [        R                  R'                  U5      nUU:w  d  Mf   [        R0                  " U5        [        R                  R'                  U5      nUU:w  a  M>  M¦     gg! [2         a     M·  f = f)zExecute a sync plan.r   r•   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’   rH   r    rW   r   râ   r�   Úrstripr£   r™   rå   Úprintrš   rÒ   r    r  Ú
capitalizeÚbatch_bucket_filesÚmakedirsÚdirnamer�   Údownload_bucket_filesÚexistsÚremoveÚrmdirrÙ   )r$  rð   rC  r  r"  r#  rà   r#   r$   Ú	add_filesÚdelete_pathsr©   r/  Úremote_pathr"   Údownload_filesÚdelete_filesÚ	file_pathÚparents                      r%   Ú_execute_planrY  h  s…  € ä# D§K¡KÓ0Ô0×O´_ÀTÇYÁYÓ5O€IÜ! $§+¡+Ó.×Q´ÀtÇyÁyÓ7QÔ3Q€KçÜ—W‘W—_‘_ T§[¡[Ó1ˆ
Ü.¨t¯y©yÓ9Ñˆ	Ø—‘˜sÓ#ˆð ;=ˆ	Ø"$ˆà—/•/ˆ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™wÜ˜L¨¯©¨	°°B·I±I°;¸aÐ@×Añ "ö" žÞØ�ÞØ—L‘L :¬c°)«nÐ-=¸VÐ!DÔEÞØ—L‘L 9¬S°Ó->Ð,?¸vÐ!FÔGØ—‘˜DŸI™I eÓ,×7Ñ7Ó9Ô:Ø×"Ñ"ØØ×% Ø#×+ tð #ò ð %÷ 
Ü.¨t¯{©{Ó;Ñˆ	Ø—‘˜sÓ#ˆÜ—W‘W—_‘_ T§Y¡YÓ/ˆ
ô 	�Š�J¨Ò.ð EGˆØ"$ˆà—/•/ˆBØ�y‰y˜JÓ&ÜŸW™WŸ\™\¨*·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Ÿ\™\¨*·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   ×25X5Ø5
YÙYc                 óö   • U R                  5       n[        SU R                   SU R                   35        [        SUS    35        [        SUS    35        [        SUS    35        [        S	US
    35        g)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¹   rI  rH   r    )r$  r¹   s     r%   Ú_print_plan_summaryr[  Ì  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_runrC  ÚquietÚtokenr\  r]  r^  r_  r`  ra  rb  c                ó  • Ub  SSK Jn  U" US9nU(       GaA  U (       d  U(       a  [        S5      eUb  [        S5      eU(       a  [        S5      eU(       a  [        S5      eU(       a  [        S	5      eU(       a  [        S
5      eU	(       a  [        S5      eU
(       a  [        S5      eU(       a  [        S5      eU(       a  [        S5      eU(       a  [        S5      e[        U5      n[	        U(       + S9nU(       d  [        U5        [        S5        U(       a
  [        5          [        UX.US9  U(       a
  [        5         U(       d  [        S5        U$ U (       a  U(       d  [        S5      e[        U 5      n[        U5      nU(       a  U(       a  [        S5      eU(       d  U(       d  [        S5      eU(       a  U(       a  [        S5      eU(       a  U(       a  [        S5      eU(       a  U(       a  [        S5      eU(       aW  [        R                  R                  U5      (       a2  [        R                  R                  U5      (       d  [        SU 35      eO2[        R                  R                  U 5      (       d  [        SU  35      eSnU
(       a  [        U
5      n[!        UU	US9n[	        U(       + =(       a    U(       + S9n[#        U UUUUUUUUUS9
nU(       a  [%        U[&        R(                  5        U$ U(       a.  [+        UU5        U(       d  [        U5        [        SU 35        U$ U(       d  [        U5        UR-                  5       nUS   S :X  a&  US!   S :X  a  US"   S :X  a  U(       d  [        S#5        U$ U(       d  [        S$5        U(       a
  [        5          [        UX.US9  U(       a
  [        5         U(       d  [        S5        U$ ! U(       a  [        5         f f = f! U(       a  [        5         f f = f)%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   )rb  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...)rC  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Ã   )
rH   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   r!   rB  r   r[  rI  r   rY  r   r’   rW   r   rO  rã   rÖ   r¾   r0  r9  ÚsysÚstdoutr=  r¹   )rH   r    rð   r—   r  r  r  r  r\  r]  r^  r$  r_  r`  rC  ra  rb  r   Ú	sync_planr  Úsource_is_bucketÚdest_is_bucketrÁ   r  r¹   s                            r%   Úsync_bucket_internalrk  Û  sg  € ð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 ¸fÒEæÜ Ô"æÜÐÔ àÐøöG Ü$Õ&ð ûöz Ü Õ"ð ús   Ä)O Î/O6 ÏO3Ï6P
)FFFFFNN)FN)NN)Ir?   rÇ   r6  rT   rW   rØ   rf  rY   Úcollections.abcr   Údataclassesr   r   r   r   Úpathlibr   Útypingr	   r
   r   r   r   r   Úerrorsr   Úutilsr   r   r   r   Úutils._terminalr   re  r   Ú
get_loggerr;   r  r�   r
  r@   rÌ   r&   r)   rF   r`   rg   rk   ro   r}   r‡   r�   rB   r’   r”   rŸ   r¾   r»   rÖ   rC   Úfloatrß   rï   rø   rþ   r  r0  r9  r=  rB  rY  r[  rk  r3   r'   r%   Ú<module>ru     s~  ðñó
 Û Û Û 	Û Û 
Û Ý $ß (ß 'Ý ß .Ñ .ç  Ý 'ß [Ó [Ý 'ö Ýð 
×	Ò	˜HÓ	%€ð  €ØÐ ð cð ¨e°C¸°H©oô ð ÷'ð 'ó ð'ð@ ÷
ð 
ó ð
ð* ÷-ð -ó ð-ð ÷ð ó ðñ �$Ñ÷ð ó ðð  ÷%7ð %7ó ð%7ðP ÷Pð Pó ðPð2 ÷
ð 
ó ð
ð6I˜Sð I U¨3°¨8¡_ô Ið*˜#ð * $ô *ð ÷	*ð 	*ó ð	*ð ÷
ð 
ó ð
÷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 ØØØØ!Ø+/ØñrØðrà
ðrð 
ðrð ð	rð
 ðrð ðrð ðrð ðrð " DÑ(ðrð �$‰Jðrð õrðt,�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'   