Ë ÿ(6‰¼è ãóF—ddlZddlmZddlmZmZej d«ZdZdZ ejd«Z ejd«Z ee jk(sJ‚e e jk(sJ‚d Zd „Zd „Zd „Zej$Gd „d««Zd„Zd„Zd„Zd„Zd„Zy)éNé)Úattr)ÚerrorÚpolicyÚparsersé,z >LLLLL4s20sz>LHHLHLLLLHllli có\—tj|«\}}}}}} } t|||||«y)a:parse a full v2-dirstate from a binary data into dictionaries: - map: a {path: entry} mapping that will be filled - copy_map: a {path: copy-source} mapping that will be filled - data: a binary blob contains v2 nodes data - tree_metadata:: a binary blob of the top level node (from the docket) N)Ú TREE_METADATAÚunpackÚ parse_nodes) ÚmapÚcopy_mapÚdataÚ tree_metadataÚroot_nodes_startÚroot_nodes_lenÚ_nodes_with_entry_countÚ_nodes_with_copy_source_countÚ_unreachable_bytesÚ_unusedÚ_ignore_patterns_hashs ú>usr/lib/python3.12/site-packages/mercurial/dirstateutils/v2.pyÚparse_dirstater>s=€ô ×ј]Ó+ñØØØØ%ØØØä��X˜tÐ%5°~ÕFócój—t|«D]¥}|t|zz}t||t«}tj |«\ }} } } } } }}}}}}}t |||| |«t jj||||«}|jsŒ�t||| «}|||<| sŒ–t|| | «||<Œ§y)aparse nodes from starting at offset This is used by parse_dirstate to recursively fill `map` and `copy_map`. All directory specific information is ignored and do not need any processing (DIRECTORY, ALL_UNKNOWN_RECORDED, ALL_IGNORED_RECORDED) N) ÚrangeÚ NODE_SIZEÚslice_with_lenÚNODEr r rÚ DirstateItemÚ from_v2_dataÚ any_tracked)r rrÚstartÚlenÚiÚ node_startÚ node_bytesÚ path_startÚpath_lenÚ_basename_startÚcopy_source_startÚcopy_source_lenÚchildren_startÚchildren_countÚ_descendants_with_entry_countÚ_tracked_descendants_countÚflagsÚsizeÚmtime_sÚmtime_nsÚitemÚpaths rr r RsÒ€ô�3ŽZˆØœY¨™]Ñ*ˆ Ü# D¨*´iÓ@ˆ ô �K‰K˜ Ó #ñ Ø Ø Ø Ø Ø Ø Ø Ø )Ø &Ø Ø Ø Ø ô �C˜ 4¨¸ÔHä×#Ñ#×0Ñ0°¸¸gÀxÓPˆØ×ÒØ ܘd J°Ó9ˆØˆˆD‰ Ú Ü+ØÐ'¨óˆH�TŠNñ9rcó—||||zS©N©)rr#r$s rrr{s€Ø �˜ ™ Ð $Ð$rcó—eZdZej«Zej«Zejd¬«Zejd¬«Zejd¬«Z ejd¬«Z ejd¬«Z d„Z y)ÚNodeN)Údefaultrcó°—|j}|j|«}|j}|}t|«}|j d«dz}|�|t|«z} t|«} nd} d} |�|j «\} } } }n t } d} d} d}tj|||| | |j|j|j|j| | | |« S)Nó/ér) r6ÚgetÚentryr$ÚrfindÚv2_dataÚDIRSTATE_V2_DIRECTORYrÚpackÚchildren_offsetr.Údescendants_with_entryÚtracked_descendants)ÚselfrÚ paths_offsetr6ÚcopyrAr(r)Úbasename_startr+r,r1r2r3r4s rrEz Node.pack‰sì€Ø�y‰yˆØ�|‰|˜DÓ!ˆØ— ‘ ˆà!ˆ Ü�t“9ˆØŸ™ DÓ)¨AÑ-ˆØ Ð Ø ,¬s°4«yÑ 8Ð Ü! $›i‰Oà !Р؈OØ Ð Ø-2¯]©]«_Ñ *ˆE�4˜¡(ô*ˆE؈D؈G؈HÜ�y‰yØ Ø Ø Ø Ø Ø × Ñ Ø × Ñ Ø × 'Ñ 'Ø × $Ñ $Ø Ø Ø Ø ó ð r) Ú__name__Ú __module__Ú __qualname__rÚibr6rAÚparentr.rFrGrHrEr9rrr;r;ss„à ˆ4�7‰7‹9€DØ ˆD�G‰G‹I€EØ ˆT�W‰W˜TÔ "€FØ�T—W‘W QÔ'€NØ�d—g‘g aÔ(€OØ$˜TŸW™W¨QÔ/ÐØ!˜$Ÿ'™'¨!Ô,Ðó$ rr;c ó¢—t«}d}d}d}d}d}d}d} t|«dk(rtj||||||| «} || fSt |j «d„¬«} g} t dd«} | j| «t| d«D�]?\}\}}|dz }||vr|dz }t|«}t|| | «} | xjdz c_ |jr| xjdz c_ | xjdz c_| jt ||| ««d }d}|t| «kr| |d}t||« }|sŒÁt!| ||| «| sŒÒ| j"dk7sŒâ| j$}|duxr"t|t| d j"««}|�|r�Œt!|||| «|} | s�Œ0| j"dk7rŒ^�ŒB| j'«} | j"dk(sJ| j"«‚t| «dk(sJt| ««‚tj| j(| j||||| «} || fS) a5 Pack `map` and `copy_map` into the dirstate v2 binary format and return the tuple of (data, metadata) bytearrays. The on-disk format expects a tree-like structure where the leaves are written first (and sorted per-directory), going up levels until the root node and writing that one to the docket. See more details on the on-disk format in `mercurial/helptext/internals/dirstate-v2`. Since both `map` and `copy_map` are flat dicts we need to figure out the hierarchy. This algorithm does so without having to build the entire tree in-memory: it only keeps the minimum number of nodes around to satisfy the format. # Algorithm explanation This explanation does not talk about the different counters for tracked descendants and storing the copies, but that work is pretty simple once this algorithm is in place. ## Building a subtree First, sort `map`: this makes it so the leaves of the tree are contiguous per directory (i.e. a/b/c and a/b/d will be next to each other in the list), and enables us to use the ordering of folders to have a "cursor" of the current folder we're in without ever going twice in the same branch of the tree. The cursor is a node that remembers its parent and any information relevant to the format (see the `Node` class), building the relevant part of the tree lazily. Then, for each file in `map`, move the cursor into the tree to the corresponding folder of the file: for example, if the very first file is "a/b/c", we start from `Node[""]`, create `Node["a"]` which points to its parent `Node[""]`, then create `Node["a/b"]`, which points to its parent `Node["a"]`. These nodes are kept around in a stack. If the next file in `map` is in the same subtree ("a/b/d" or "a/b/e/f"), we add it to the stack and keep looping with the same logic of creating the tree nodes as needed. If however the next file in `map` is *not* in the same subtree ("a/other", if we're still in the "a/b" folder), then we know that the subtree we're in is complete. ## Writing the subtree We have the entire subtree in the stack, so we start writing it to disk folder by folder. The way we write a folder is to pop the stack into a list until the folder changes, revert this list of direct children (to satisfy the format requirement that children be sorted). This process repeats until we hit the "other" subtree. An example: a dir1/b dir1/c dir2/dir3/d dir2/dir3/e dir2/f Would have us: - add to the stack until "dir2/dir3/e" - realize that "dir2/f" is in a different subtree - pop "dir2/dir3/e", "dir2/dir3/d", reverse them so they're sorted and pack them since the next entry is "dir2/dir3" - go back up to "dir2" - add "dir2/f" to the stack - realize we're done with the map - pop "dir2/f", "dir2/dir3" from the stack, reverse and pack them - go up to the root node, do the same to write "a", "dir1" and "dir2" in that order ## Special case for the root node The root node is not serialized in the format, but its information is written to the docket. Again, see more details on the on-disk format in `mercurial/helptext/internals/dirstate-v2`. rsscó*—|djd«S)Nrr>)Úsplit)Úxs rÚzpack_dirstate..s€°1°Q±4·:±:¸dÔ3Cr)ÚkeyrNr?Téÿÿÿÿ)Ú bytearrayr$r rEÚsortedÚitemsr;ÚappendÚ enumerateÚ get_folderÚmove_to_correct_node_in_treer.ÚtrackedrHrGÚ is_ancestorÚpack_directory_childrenr6rQÚpoprF)r rrrrÚnodes_with_entry_countÚnodes_with_copy_source_countÚunreachable_bytesÚunusedÚignore_patterns_hashrÚ sorted_mapÚstackÚ current_nodeÚindexr6rAÚcurrent_folderÚ should_packÚ next_pathrQÚin_ancestor_of_next_paths rÚ pack_dirstaterq°s‹€ôV ‹;€DØÐØ€NØÐØ#$Ð ðÐØ €Fà'Ðä ˆ3ƒx�1‚}Ü%×*Ñ*Ø Ø Ø "Ø (Ø Ø Ø ó ˆ ð�]Ð"Ð"䘟 ™ › Ñ)CÔD€Jð €Eܘ˜T“?€LØ ‡L�L�Ôä )¨*°a× 8ш‰}��eØ !Ñ#ÐØ �8Ñ Ø (¨AÑ -Ð (Ü# DÓ)ˆÜ3Ø ˜L¨%ó ˆ ð ×#Ò# qÑ(Õ#à �=Š=Ø × ,Ò ,°Ñ 1Õ ,Ø×+Ò+¨qÑ0Õ+Ø � ‰ ”T˜$  |Ó4Ô5àˆ Øˆ Ø ”3�z“?Ò "ð# 5Ñ)¨!Ñ,ˆIÜ)¨)°^ÓDÐDˆKÚ Ü # L°(¸DÀ%Ô HÚ˜L×-Ñ-°Ó4ð&×,Ñ,�Ø+4¸DÐ+@ò,Ü  ¬:°e¸B±i·n±nÓ+EÓFð)ð�>Ñ%=ÙÜ'¨°¸$ÀÔFØ%� ó˜L×-Ñ-°Õ4ð3!9ðN—9‘9“;€LØ × Ñ  Ò #Ð6 \×%6Ñ%6Ó6Ð #Ü ˆu‹:˜Š?Ð&œC ›JÓ&ˆ?ä!×&Ñ&Ø×$Ñ$Ø×#Ñ#ØØ$ØØØó€Mð �Ð Ðrcó8—d|vr|jdd«dSdS)zU Return the folder of the path that's given, an empty string for root paths. r>r?rr)Úrsplit)r6s rr^r^Ss%€ð'+¨d¡lˆ4�;‰;�t˜QÓ  Ñ "Ð;¸Ð;rcó–—|dk(ry||kry|jd«}|jd«}td„t||«D««S)aReturns whether `maybe_ancestor` is an ancestor of `path`. >>> is_ancestor(b"a", b"") True >>> is_ancestor(b"a/b/c", b"a/b/c") False >>> is_ancestor(b"hgext3rd/__init__.py", b"hgext") False >>> is_ancestor(b"hgext3rd/__init__.py", b"hgext3rd") True rTFr>c3ó,K—|] \}}||k(–—Œy­wr8r9)Ú.0ÚcÚos rÚ zis_ancestor..lsèø€ÐLÑ"K™$˜!˜Qˆq�A�vÑ"Kùs‚)rTÚallÚzip)r6Úmaybe_ancestorÚpath_componentsÚancestor_componentss rraraZsR€ð˜ÒØØ ˆ~ÒØØ—j‘j Ó&€OØ(×.Ñ.¨tÓ4ÐÜ ÑL¤# oÐ7JÔ"KÓLÓ LÐLrcóØ—||jk7rÚt||j«r¨|t|j«djd«}|j dd«d}|jr|jdz|z}n|}|d}|j|k(r|}n@|xj dz c_t |d|«}|j|«n |j}||jk7rŒÚ|S)z’ Move inside the dirstate node tree to the node corresponding to `target_folder`, creating the missing nodes along the way if needed. Nr>r?rrX) r6rar$ÚlstriprTr.r;r\rQ)Ú target_folderrkrjÚprefixÚsubfolder_nameÚsubfolder_pathÚ next_nodes rr_r_osé€ð ˜<×,Ñ,Ò ,Ü �} l×&7Ñ&7Ô 8à"¤3 |×'8Ñ'8Ó#9Ð#;Ð<×CÑCÀDÓIˆFØ#Ÿ\™\¨$°Ó2°1Ñ5ˆNØ× Ò Ø!-×!2Ñ!2°TÑ!9¸NÑ!J‘à!/�ؘb™ ˆIØ�~‰~ Ò.ð )‘ à×+Ò+¨qÑ0Õ+Ü# N°D¸,ÓG� Ø— ‘ ˜\Õ*ð(×.Ñ.ˆLð) ˜<×,Ñ,Ó ,ð* ÐrcóR—g}|djdk7r|t|dj«|jk(rW|j|j««|djdk7r&t|dj«|jk(rŒW|s"t j d|jz«‚|j «t«}|D]³}|j|t|«¬«}|j|«|j|j«|j|j|jd««|xj|jz c_ |xj|jz c_ Œµt|«|_|j|«y)z_ Write the binary representation of the direct sorted children of `node` to `data` rXrsno direct children for %r)rrJN)r6r^r\rcrÚProgrammingErrorÚreverserYrEr$Úextendr@rHrGrF)ÚnoderrrjÚdirect_childrenÚpacked_childrenÚchildÚpackeds rrbrbŒsC€ð €Oà �‰)�.‰.˜CÒ ¤J¨u°R©y¯~©~Ó$>À$Ç)Á)Ò$KØ×јuŸy™y›{Ô+ð �‰)�.‰.˜CÒ ¤J¨u°R©y¯~©~Ó$>À$Ç)Á)Ó$Ká Ü×$Ñ$Ð%AÀDÇIÁIÑ%MÓNÐNð×ÑÔÜ“k€O㠈ؗ‘ X¼CÀ»I�ÓFˆØ×јvÔ&Ø � ‰ �E—J‘JÔØ � ‰ �H—L‘L §¡¨SÓ1Ô2Ø × Ò  E×$=Ñ$=Ñ=Õ Ø ×#Ò# u×'CÑ'CÑCÖ#ð !ô˜t›9€DÔØ‡K�K�Õ r)ÚstructÚ thirdpartyrÚrrÚ importmodrÚTREE_METADATA_SIZErÚStructr rr2rDrr rÚsr;rqr^rar_rbr9rrÚr–sÏðóåßà ˆ&× Ñ ˜9Ó %€ð ÐØ € ð�— ‘ ˜mÓ,€ ð&€v‡}�}Ð%Ó&€ð˜]×/Ñ/Ò/Ð/Ð/Ø�D—I‘IÒÐÐð ÐòGò(&òR%ð‡�÷- ð- óð- ò``òF<òMò*ó:!r