+
    „WÝj�  ã                  ó†  € R t ^ RIHt ^ RIt^ RIt^ RIt^ RIt^ RIt^ RIt^ RI	t	^ RI
t
^ RIt^ RIHt Rt]R,           tR"t^t]! ]P&                  ]P(                  04      tR R ltR R	 ltR
 R ltR R ltR R ltR R ltR R lt]P:                  R R l4       tRR/R R lltR R lt R R lt!R R lt"R  R! lt#R# )#aæ  Scratch entries the prune cannot delete as this user: remembered once, skipped until fixed.

A container that ran as root and wrote into a bind mount under scratch (the Docker terminal
backend without ``docker_run_as_host_user``, a test or review lane's ``docker run -v``) leaves
files this user cannot unlink, or directories it cannot even read. ``rmtree(ignore_errors=True)``
removes what it can, the entry stays idle, and every hourly pass re-walked the whole subtree and
logged the same "could not fully remove" line again (218 times per entry on one host). Here such
an entry is recorded with the directories that refused access, the user gets ONE line naming the
command that clears it, and later passes skip it before walking it. A record is dropped (and
the entry judged normally again) when the entry is gone or its top directory changed, when
every recorded blocking directory is accessible now (``chown``/``chmod`` of a nested dir), when
it was made by another uid, or after :data:`RECHECK_AFTER_SECONDS` in any case. Nothing is
escalated or shelled out to: the hint is for the user to run.

POSIX only: without ``os.getuid`` (Windows) a PermissionError is usually a transient open
handle, so the prune keeps retrying there exactly as before.
)ÚannotationsN)ÚPathz.prune_stuck.jsonz.lockc               ó   € V ^8„  d   QhRR/# )é   ÚreturnÚbool© )Úformats   "ÚRC:\Users\johnn\AppData\Local\hermes\hermes-agent\hermes_constants_scratch_stuck.pyÚ__annotate__r   )   s   € ÷ 9ñ 9˜Dñ 9ó    c                 óX   € \         P                  R 8H  ;'       d    \        \         R4      # )ÚposixÚgeteuid)ÚosÚnameÚhasattrr   r   r
   Útracking_supportedr   )   s    € Ü�7‰7�gÑ×8Ð8¤'¬"¨iÓ"8Ð8r   c               ó    € V ^8„  d   QhRRRR/# )r   ÚexcÚBaseExceptionr   r   r   )r	   s   "r
   r   r   -   s   € ÷ Hñ H˜]ð H¨tñ Hr   c                óX   € \        V \        4      ;'       d    V P                  \        9   # ©N)Ú
isinstanceÚOSErrorÚerrnoÚ_PERMISSION_ERRNOS)r   s   &r
   Úis_permission_errorr   -   s!   € Ü�cœ7Ó#×GÐG¨¯	©	Ô5GÑ(GÐGr   c               ó    € V ^8„  d   QhRRRR/# )r   Úentryr   r   zlist[int] | Noner   )r	   s   "r
   r   r   1   s   € ÷ 7ñ 7˜ð 7Ð!1ñ 7r   c                óš   €  \         P                  ! V 4      pTP                  TP                  TP
                  .#   \         d     R # i ; ir   )r   Úlstatr   Úst_inoÚst_mtime_nsÚst_ctime_ns)r   Ústs   & r
   Ú_fingerprintr&   1   sC   € ðÜ�XŠX�e‹_ˆð �I‰I�r—~‘~ r§~¡~Ð6Ð6øô ô Úðús   ‚; »A
Á	A
c               ó    € V ^8„  d   QhRRRR/# )r   ÚpathÚstrr   r   r   )r	   s   "r
   r   r   :   s   € ÷ >ñ >�cð >˜dñ >r   c                óB  € \         P                  P                  V 4      '       g   R# \         P                  \         P                  9   d   RR/M/ p\         P                  ! V \         P
                  \         P                  ,          \         P                  ,          3/ VB # )zJTrue when this user can now list and delete inside *path* (or it is gone).TÚeffective_ids)r   r(   ÚlexistsÚaccessÚsupports_effective_idsÚR_OKÚW_OKÚX_OK)r(   Úkws   & r
   Ú_accessibler3   :   sb   € ä�7‰7�?‰?˜4× Ò ÙÜ$&§I¡I´×1JÑ1JÔ$Jˆ/˜4Ñ	 ÐPR€BÜ�9Š9�Tœ2Ÿ7™7¤R§W¡WÕ,¬r¯w©wÕ6Ñ=¸"Ñ=Ð=r   c          
     ó,   € V ^8„  d   QhRRRRRRRRR	R
/# )r   Úrootr   r   r)   ÚrecÚdictÚnowÚfloatr   r   r   )r	   s   "r
   r   r   B   s/   € ÷ ñ �tð  3ð ¨Tð ¸ð À$ñ r   c                ó  € VP                  R 4      pVP                  R4      \        P                  ! 4       8H  ;'       dÊ    T\        VP                  R4      ;'       g    ^ 4      ,
          \        8  ;'       d�    VP                  R4      \        W,          4      8H  ;'       de    \        V\        4      ;'       dM    \        V4      ;'       d:    \        ;QJ d    R V 4       F  '       d   K   RM	  RM! R V 4       4      '       * # )ÚblockersÚuidÚsinceÚfpc              3  óh   "  € T F(  p\        V\        4      '       g   K  \        V4      x € K*  	  R # 5ir   )r   r)   r3   )Ú.0Úbs   & r
   Ú	<genexpr>Ú_still_stuck.<locals>.<genexpr>I   s!   é € ÐK©H q¼
À1Äc×8J”N”K —N�N«Hùs   ‚2Ÿ2FT)
Úgetr   r   r9   ÚRECHECK_AFTER_SECONDSr&   r   Úlistr   Úall)r5   r   r6   r8   r;   s   &&&& r
   Ú_still_stuckrH   B   sÚ   € Ø�w‰w�zÓ"€Hà�‰�‹œ"Ÿ*š*›,Ñ&÷ 	Lð 	LØ”%˜Ÿ™ Ó(×-Ð-¨AÓ.Õ.Ô1FÑF÷	Lð 	Là�G‰G�D‹Mœ\¨$­+Ó6Ñ6÷	Lð 	Lô �x¤Ó&÷	Lð 	Lô ,0°«>÷	Lð 	L÷ “ÑK©HÓK——’ÑK©HÓKÓKÔKðr   c               ó    € V ^8„  d   QhRRRR/# )r   r5   r   r   údict[str, dict]r   )r	   s   "r
   r   r   M   s   € ÷ dñ d�ð d˜ñ dr   c                óL  €  \         P                  ! V \        ,          P                  R R7      4      p\        T\        4      '       d=   TP                  4        UUu/ uF  w  r#\        T\        4      '       g   K  Y#bK!  	  upp# / #   \        \
        3 d    / u # i ; iu uppi )z	utf-8-sig©Úencoding)	ÚjsonÚloadsÚSTUCK_STATE_NAMEÚ	read_textr   Ú
ValueErrorr   r7   Úitems)r5   ÚdataÚkÚvs   &   r
   Ú_readrW   M   sˆ   € ðÜ�zŠz˜4Ô"2Õ2×=Ñ=À{Ð=ÓSÓTˆô FPÐPTÔVZ×E[ÒE[˜TŸZ™Zœ\ÔA™\‘T�Q¬Z¸¼4×-@ŒDˆAŠD™\ÒAÐcÐacÐcøô ”ZÐ ô ØŠ	ðüãAs   ‚1B ÁB Á;B ÂBÂBc               ó$   € V ^8„  d   QhRRRRRR/# )r   r5   r   ÚstaterJ   r   ÚNoner   )r	   s   "r
   r   r   V   s!   € ÷ ñ �ð ˜oð °$ñ r   c           	     óò  € V \         ,          pV'       g@   \        P                  ! \        4      ;_uu_ 4        VP	                  RR7       RRR4       R#  \
        P                  ! V \         R,           RR7      w  r4 \        P                  ! TRRR	7      ;_uu_ 4       p\        P                  ! Y^RR
7       RRR4       \        P                  ! YB4       R#   + '       g   i     R# ; i  \         d     R# i ; i  + '       g   i     LN; i  \         d[    \        P                  ! \        4      ;_uu_ 4        \        P                  ! T4       RRR4        R#   + '       g   i      R# ; ii ; i)z^Publish *state* via a unique temp file + ``os.replace``: a reader sees old or new, never torn.T)Ú
missing_okNÚ.z.tmp)ÚdirÚprefixÚsuffixÚwzutf-8rL   )ÚindentÚ	sort_keys)rP   Ú
contextlibÚsuppressr   ÚunlinkÚtempfileÚmkstempr   ÚfdopenrN   ÚdumpÚreplace)r5   rY   r(   ÚfdÚtmpÚfs   &&    r
   Ú_writero   V   s÷   € àÔ"Õ"€DßÜ× Ò ¤×)Õ)Ø�K‰K 4ˆKÔ(÷ *áðÜ×"Ò" tÔ4DÀsÕ4JÐSYÔZ‰ˆðÜ�YŠY�r˜3¨×1Õ1°QÜ�IŠI�e q°DÕ9÷ 2ä
�
Š
�3Ö÷ *Ö)áûô ô Úðú÷ 2×1ûô ô Ü× Ò ¤×)Õ)Ü�IŠI�cŒN÷ *×)×)Ô)úðús_   ¸CÁ&C, Á=!D ÂC>Â8D ÃC)	Ã,C;Ã:C;Ã>D	Ä	D Ä-E6Ä>E ÅE6Å E2Å+E6Å2E6c               ó   € V ^8„  d   QhRR/# )r   r5   r   r   )r	   s   "r
   r   r   k   s   € ÷ ñ �$ñ r   c              #  óD  "  € ^ RI p\        P                  ! V \        ,          \        P                  \        P
                  ,          R4      p VP                  W!P                  4       Rx € \        P                  ! V4       R#   \        P                  ! T4       i ; i5i)a  Exclusive cross-process lock around a read-merge-write of the state file. Two pruners of
one home (separate processes past the ``.last_prune`` throttle together) otherwise overwrite
each other's records from stale snapshots. POSIX only, like the tracking itself.Ni€  )	Úfcntlr   ÚopenÚSTUCK_LOCK_NAMEÚO_RDWRÚO_CREATÚflockÚLOCK_EXÚclose)r5   rr   rl   s   &  r
   Ú_lockedrz   j   s\   é € ó
 ä	�Š�œÕ'¬¯©´R·Z±ZÕ)?ÀÓ	G€BðØ�‰�BŸ™Ô&Ûä
�Š�ŽøŒ�Š��üs   ‚AB ÁB Á-B ÂBÂB ÚpersistTc               ó$   € V ^8„  d   QhRRRRRR/# )r   r5   r   r{   r   r   zfrozenset[str]r   )r	   s   "r
   r   r   y   s!   € ÷ ñ �Tð  tð °~ñ r   c               óv  a a€ \        4       '       d"   S \        ,          P                  4       '       g   \        4       # \        P                  ! 4       oV'       g0   \        S 4      p\        VV 3R lVP                  4        4       4      #  \        S 4      ;_uu_ 4        \        S 4      pVP                  4        UUu/ uF  w  r4\        S W4S4      '       g   K  W4bK  	  pppWR8w  d   \        S V4       RRR4       \        X4      # u uppi   + '       g   i     L!; i  \         d    \        4       u # i ; i)zzNames to skip this pass. Records that no longer hold (see module doc) are dropped, so
that entry is judged normally again.c              3  óV   <"  € T F  w  r\        SWS4      '       g   K  Vx € K   	  R # 5ir   )rH   )r@   Únr6   r8   r5   s   &  €€r
   rB   Úload_skips.<locals>.<genexpr>�   s!   øé € ÐZ©™v˜q¼,ÀtÈQÐUX×:YŸš«ùs   ƒ)Ÿ
)N)r   rP   ÚexistsÚ	frozensetÚtimerW   rS   rz   rH   ro   r   )r5   r{   rY   r   r6   Úliver8   s   f$    @r
   Ú
load_skipsr…   y   sá   ù€ ô ×Ò¨Ô/?Õ(?×'GÑ'G×'IÒ'IÜ‹{ÐÜ
�)Š)‹+€CßÜ�d“ˆÜÕZ¨¯©¬ÓZÓZÐZðÜ�T�]�]Ü˜$“KˆEØ).¯©¬ÔZ©™v˜q¼,ÀtÈQÐUX×:Y”F�A’F©ˆDÑZØŒ}Ü�t˜TÔ"÷	 ô �T‹?Ðùó [÷ �]ûô
 ô Ü‹{ÒðúsH   ÂD  ÂDÂ=D
ÃD
ÃDÃ4D  ÄDÄD	ÄD  ÄD  Ä D8Ä7D8c               ó    € V ^8„  d   QhRRRR/# )r   r   r   r   ú	list[str]r   )r	   s   "r
   r   r   �   s   € ÷ ñ ¨tð ¸	ñ r   c                ó°   aa€ . oV3R lo\         P                  R8¼  d   \        P                  ! V SR7       S# \        P                  ! V V3R lR7       S# )z¤``rmtree`` that keeps going past errors (like ``ignore_errors=True``) and returns the
directories that refused access with EACCES/EPERM (empty: nothing was denied).c                ó  <€ \        V4      '       dr   V \        P                  \        P                  \        P                  39   d   TM\        P
                  P                  V4      pVS9  d   SP                  V4       R # R # R # r   )r   r   Úscandirrs   r!   r(   ÚdirnameÚappend)Úfuncr(   r   Úblockerr;   s   &&& €r
   Ú_onexcÚ3rmtree_collecting_permission_errors.<locals>._onexc’   s[   ø€ Ü˜s×#Ò#à"¤r§z¡z´2·7±7¼B¿H¹HÐ&EÔE‘dÌ2Ï7É7Ï?É?Ð[_ÓK`ˆGØ˜hÔ&Ø—‘ Ö(ñ 'ñ $r   )Úonexcc                ó$   <€ S! WV^,          4      # )é   r   )rn   ÚpÚinfor�   s   &&&€r
   Ú<lambda>Ú5rmtree_collecting_permission_errors.<locals>.<lambda>œ   s   ø€ ¹¸qÀTÈ!ÅWÔ8Mr   )Úonerror)é   é   )ÚsysÚversion_infoÚshutilÚrmtree)r   r�   r;   s   &@@r
   Ú#rmtree_collecting_permission_errorsrŸ   �   sJ   ù€ ð €Hõ)ô ×Ñ˜7Ô"Ü�Š�e 6Õ*ð €Oô 	�Š�eÔ%MÕNØ€Or   c               ó    € V ^8„  d   QhRRRR/# )r   r   r   r   r)   r   )r	   s   "r
   r   r       s   € ÷ 	ñ 	˜ð 	 ñ 	r   c                óx  € ^ RI Hp R\        P                  ! \        P
                  ! V 4      4       2pV! R4      P                  '       do   VR\        P                  ! \        P
                  ! V P                  4      R,           4       R\        P                  ! RV P                  ,           4       R2,          pV# )	é    )Úlocate_commandzsudo rm -rf Údockerz'  (or without sudo: docker run --rm -v z:/sz alpine rm -rf z/s/Ú))	Úhermes_platform.resolverr£   ÚshlexÚquoter   ÚfspathÚcommandÚparentr   )r   r£   Úhints   &  r
   Úremoval_hintr­       sŒ   € Ý7àœ%Ÿ+š+¤b§i¢i°Ó&6Ó7Ð8Ð9€DÙ�hÓ×'×'Ð'ØØ5´e·k²kÄ"Ç)Â)ÈEÏLÉLÓBYÐ\aÕBaÓ6bÐ5cØœeŸkšk¨%°%·*±*Õ*<Ó=Ð>¸aðAõ	
ˆð €Kr   c               ó(   € V ^8„  d   QhRRRRRRRR/# )r   r5   r   r   r;   r‡   r   rZ   r   )r	   s   "r
   r   r   ¬   s(   € ÷ ñ �ð ˜dð ¨ið À4ñ r   c           
     ó8  € \        V4      pVe	   V'       g   R# RVR\        P                  ! 4       R\        P                  ! 4       RVR\         /p\
        P                  ! \        4      ;_uu_ 4        \        V 4      ;_uu_ 4        \        V 4      pWVVP                  &   \        W4       RRR4       RRR4       VP                  R\        P                  ! V4      VR,          \        V4      4       R#   + '       g   i     LR; i  + '       g   i     L]; i)zORemember *entry* as not removable by this user and log the one actionable line.Nr>   r=   r<   r;   zÓscratch prune: cannot remove %r: it holds files this user (uid %d) may not read or delete, usually root-owned output of a Docker container; skipping it until that is fixed (re-checked weekly). Remove it with: %s)r&   rƒ   r   r   Ú_MAX_BLOCKERSrd   re   r   rz   rW   r   ro   r•   r©   r­   )r5   r   r;   Úauditr>   r6   rY   s   &&&&   r
   Úrecordr²   ¬   s¼   € ä	�eÓ	€BØ	‚zŸÙØ��WœdŸiši›k¨5´"·*²*³,À
ÈHÐUcÔVcÐLdÐ
e€CÜ	×	Ò	œW×	%Õ	%¤w¨t§}¥}Ü�d“ˆØˆe�j‰jÑÜˆtÔ÷ (5×	%ð 
‡J�Jð	8ô 	�	Š	�%Ó˜#˜e�*¤l°5Ó&9ö	÷	 (5§}ú×	%×	%ús$   Á3D	Â%C6	Â,D	Ã6DÄD	Ä	D	c               ó    € V ^8„  d   QhRRRR/# )r   r5   r   r   z
list[Path]r   )r	   s   "r
   r   r   ¾   s   € ÷ Mñ M˜ð M ñ Mr   c                ód   € \        \        V RR7      4       Uu. uF  qV,          NK  	  up# u upi )zQEntries the prune is currently skipping as not removable (for ``hermes doctor``).F)r{   )Úsortedr…   )r5   r   s   & r
   Ústuck_entriesr¶   ¾   s,   € ä$*¬:°dÀEÔ+JÔ$KÓLÑ$K˜D�4�KˆKÑ$KÑLÐLùÒLs   ™-i€:	 )$Ú__doc__Ú
__future__r   rd   r   rN   r   r§   r�   r›   rg   rƒ   Úpathlibr   rP   rt   rE   r°   r‚   ÚEACCESÚEPERMr   r   r   r&   r3   rH   rW   ro   Úcontextmanagerrz   r…   rŸ   r­   r²   r¶   r   r   r
   Ú<module>r½      sÂ   ðñõ" #ã Û Û Û 	Û Û Û 
Û Û Ý à&Ð Ø" WÕ,€ð &Ð à€Ù §¡¨e¯k©kÐ:Ó;Ð õ9õHõ7õ>õõdõð( ×Ñôó ðð¨d÷ õ(õ&	õ÷$Mr   