
    Jj                       S r SSKJ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
r
SSKrSSKJr  SSKJr  SSKJr  SSKJrJr  SSKJr  SS	KJr  SS
KJr  \" S5      r\ " S S5      5       rSrSrSrSr Sr!\\4SS jjr"\RF                  " S5      r$SS jr%SS jr&S S jr'Sr(S!S jr)S"S jr*S#S jr+S$S%S jjr,S#S jr-g)&a^  Update check foundation.

v1 only DETECTS and REPORTS whether a newer version is available on the
configured channel. It does NOT download, swap, or restart anything. The
production update pipeline is sketched below as no-op stubs with TODOs so the
structure is ready: download -> verify checksum -> stage -> atomic swap ->
health check -> rollback.
    )annotationsN)Path)	dataclass)Any)	ApiClientApiError)Config)load_agent_token)
get_loggerupdatec                  z    \ rS rSr% S\S'   S\S'   S\S'   SrS\S	'   SrS\S
'   SrS\S'   SrS\S'   Sr	S\S'   Sr
g)
UpdateInfo!   strcurrentlatestboolupdate_availableNz
str | Noneurlsha256	signaturechannelz
int | None
size_bytes )__name__
__module____qualname____firstlineno____annotations__r   r   r   r   r   __static_attributes__r       0D:\Programs\laragon\www\wolf\agent\src\update.pyr   r   !   sD    LKCFJ Iz GZ!J
!r!   r   l   ehm>?fKq"0aw
pplkQPo3?%?!yP[{0g<M.9`>s~Ncva -\R!nV5o_W;BtJzAwP9(zDukJVK{gI	s x
s^SAK9qiU1RD# \tO^skrSW @\47H*@AJj]e QRMz	Xey+? ))kRcxNu
n}vFbXqu.? i  l   I`2}zkR9t>mt@a%Ax}]}iG[_/oB|s>+8Y3	f+R{fpxQw|wB	w{KGodxXzmQNFvX:hdN[a)MQRj>GG2q!RUDy9#-`t`h"u:]3)ZYdWiG\Q'1yy.ZSaz:{gEr<H/oYE:Wu0!;S j.VP'>S_H$xVS0Ys~?Ny2v l   zP9WJ(pC@I]HLM9yHAG)Eq%U=;'.YubXnP:vLsK"pd2%$0N- 4(;n0~S,s4
zg	D_<XUik.q`*Q	]r)YcvsGpE*T9y4\s?	u+@LM{`m/0u|H#)R;?SBV74c\:^oY|ID[\xdsFPZ[9,[mFd!T=J&_	 c                J    U(       d  g[         R                  U5      n[        U5      S:w  a  g[        R	                  US5      n[        XSU5      nUR                  SS5      n[        R                  " U 5      R                  5       nSn	SU	-   U-   n
Xz:H  $ ! [         a     gf = f)zVerify standard RSASSA-PKCS1-v1_5 signature using the given public key.

Defaults to the production public key; pass n=TEST_PUBLIC_KEY_N,
e=TEST_PUBLIC_KEY_E to verify a mock/test signature instead.
F   big   010	`He       )bytesfromhexlenint
from_bytespowto_byteshashlibr   digest	Exception)datasignature_hexne	sig_bytessm	decryptedsha256_hashasn1_prefixexpecteds              r"   verify_signaturer=   G   s    MM-0	y>S NN9e,aLJJsE*	nnT*113e8;FT$$ s   B $B A%B 
B"!B"z^(?P<major>0|[1-9]\d*)\.(?P<minor>0|[1-9]\d*)\.(?P<patch>0|[1-9]\d*)(?:-(?P<prerelease>[0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*))?(?:\+[0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*)?$c                2   [         R                  U =(       d    SR                  5       5      nU(       d  [        SU < 35      e[	        US   5      [	        US   5      [	        US   5      pCnUS   (       a  [        US   R                  S5      5      OSnX#XE4$ )	zIParse a semver.org version string into (major, minor, patch, prerelease). zinvalid semantic version: majorminorpatch
prerelease.N)
_SEMVER_REmatchstrip
ValueErrorr+   tuplesplit)versionr8   r@   rA   rB   rC   s         r"   parse_semverrL   h   s    '-R..01A5g[ABBaj/3qz?C'
O%E67oq,,S124J**r!   c                N    U R                  5       (       a  S[        U 5      4$ SU 4$ )Nr      )isdigitr+   )idents    r"   _prerelease_identifier_keyrQ   r   s'     }}3u:u:r!   c                ~   [        U 5      u  p#pE[        U5      u  pgpX&4X74XH44 H  u  pX:w  d  M  X:  a  Ss  $ Ss  $    Uc  U	c  gUc  gU	c  g[        XY5       H,  u  p[        U
5      [        U5      pX:w  d  M!  X:  a  Ss  $ Ss  $    [        U5      [        U	5      :w  a  [        U5      [        U	5      :  a  S$ S$ g)aa  Return -1, 0, or 1 comparing semver strings a and b per semver.org precedence.

Core versions compare numerically field-by-field; a version with a
pre-release always has lower precedence than the same core version
without one (e.g. 1.2.0-rc.1 < 1.2.0); pre-release identifiers compare
left-to-right per semver.org rule 11 (e.g. beta.1 < beta.2 < rc.1).
rN   r   )rL   ziprQ   r*   )aba_majora_minora_patcha_preb_majorb_minorb_patchb_prexykxkys                 r"   compare_semverrc   {   s     (4A$Gg'3A$Gg#g%7'9KL62%A% M }}}E!+A.0J10MB82'a' " 5zSZZ#e*,r3!3r!   )rN   c                b    UR                  U R                  5      nUR                  S5      nU[        ;  a  [        R                  SU[        5        gUR                  S5      nXPR                  :w  a"  [        R                  SU R                  U5        gUR                  SS5      n [        X`R                  5      S	:  nUR                  S5      nU(       d  U R                  (       a  SnUR                  S5      n	Sn
U	(       aC  [        R                  R                  SS5      R                  S5      nU SU R                   SU	 3n
[!        U R                  UUU
UR                  S5      UUUR                  S5      S9nU(       a-  [        R#                  SUR$                  UR&                  5        U$ [        R#                  SUR$                  5        U$ ! [         a   n[        R	                  SU5         SnAgSnAff = f! [         a   n[        R                  S
U5         SnAgSnAff = f)zCFetch the channel manifest and compare against the running version.zupdate check failed: %sNmanifest_versionzCrejecting manifest: unsupported manifest_version %r (supported: %s)r   zNrejecting manifest: channel mismatch (agent is on '%s', manifest reports '%s')rK   r?   r   zrejecting manifest: %sr   mock_signaturefileWOLFPANEL_RELEASE_BASEzhttps://downloads.wolfpanel.net/r   r   )r   r   r   r   r   r   r   r   zupdate available: %s -> %szagent is up to date (%s))fetch_manifestmanifest_urlr   logwarningget_SUPPORTED_MANIFEST_VERSIONSerrorrelease_channelrc   agent_versionrH   api_mockosenvironrstripr   infor   r   )config
api_clientmanifestexcre   manifest_channelr   	availablesigmanifest_filedownload_urlrelease_baserw   s                r"   checkr      s   #-#<#<V=P=P#Q
  ||$67;;		Q:	
 ||I.111		\""$4	
 \\)R(F"6+?+?@1D	
 ,,{
#C6??LL(MLzz~~&>@abiijmn&q)?)?(@-Q$$"||H% <<-	D -t||T[[I K 	+T\\:Ke  -s3.  		*C0s/   G )H 
H!G<<H
H.H))H.c                   [        [        S5      (       a   UR                  UR                   S3-  nUR	                  5       (       d  UR                  5       (       a  UR                  5         [        R                  " X5        [        R                  " X!5        g UR	                  5       (       d  UR                  5       (       a<  UR                  5       (       a  UR                  5         O[        R                  " U5        [        R                  " X5        g ! [         a   n[        R                  SU5         S nANS nAff = f)Nsymlink_tempz<Symlink creation failed (%s), falling back to directory swap)hasattrrt   parentnameexists
is_symlinkunlinkr   replaceOSErrorrl   rm   shutilrmtreecopytree)src_dir	dest_link	temp_linkr5   s       r"   swap_directories_atomicr      s    r9	[!((inn-=U+CCI!!Y%9%9%;%;  "JJw*JJy, Y1133!!MM)$
OOG'  	[KKVXYZZ	[s   BD 
E!D<<Ec                    [        U SS5      nU R                  S-  nUR                  5       (       d  gU R                  S-  nSnUR                  5       (       a  UR	                  5       R
                  n/ nUR                  5        H  nUR                  5       (       d  M  UR
                  R                  S5      (       a  M<  U(       a  UR
                  U:X  a  MU  UR
                  U R                  :X  a  Mq  UR                  XfR                  5       R                  45        M     UR                  S S9  [        U5      U:  a=  USU*   H2  u  pg [        R                   " U5        ["        R%                  S	U5        M4     gg! [&         a!  n["        R)                  S
Xh5         SnAM^  SnAff = f! [&         a   n	["        R)                  SU	5         Sn	A	gSn	A	ff = f)z?Clean up old extracted version directories under opt/versions/.update_retention   versionsNr   .backupc                    U S   $ )NrN   r   )r_   s    r"   <lambda>$clean_old_versions.<locals>.<lambda>  s    !r!   )keyz$Cleaned up old version directory: %sz-Failed to remove old version directory %s: %sz.Failed to clean up old version directories: %s)getattropt_dirr   r   readlinkr   iterdiris_direndswithrr   appendstatst_mtimesortr*   r   r   rl   rw   r1   rm   )
rx   	retentionversions_dircurrent_symlinkcurrent_targetdirsp_r5   r{   s
             r"   clean_old_versionsr      s   %KF$6:	~~
2""$$ ..94%%'',557<<N %%'Axxzz66??9--!aff&>66V111Q 1 123 ( 			n	% t9y [yj)WMM!$HHCQG * !
 ! WKK OQRVVW KDcJJKsN   1F0 A(F0  B/F0 ,F<F0 
F-F("F0 (F--F0 0
G:GGc                   SSK n[        R                  SU5        UR                  R	                  U SS0S9nUR                  R                  XBS9 n[        US5       nUR                  S	5      =n(       a+  UR                  U5        UR                  S	5      =n(       a  M+  SSS5        SSS5        g! , (       d  f       N= f! , (       d  f       g= f)
zBDownload a file from url to dest_path with a timeout using urllib.r   Nz$Downloading file with timeout %ds...z
User-Agentwolfpanel-agent)headers)timeoutwb    )	urllib.requestrl   rw   requestRequesturlopenopenreadwrite)r   	dest_pathr   urllibreqresponsefchunks           r"   download_with_timeoutr     s    HH3W=
..
 
 |=N.O
 
PC					5)T"a#==..%. $==..%. # 
6	5"" 
6	5s%   CAB2!C2
C 	<C
Cc           
     \'   SnSnSn[        U5      S:  a  US   n[        U[        5      (       a  UnOUn[        U5      S:  a  US   nU(       a  UR                  S5      OSnU(       a  [	        U 5      OSnU(       a6  U(       a/   [
        R                  SU5        UR                  USSS	0S
.U5        U(       d=  U(       d  SSK
Jn
  U
" U 5      n[	        U 5      n[        X5      nU(       d  [        S5      eUR                  (       a~  UR                  U R                  :w  ad  SU R                   SUR                   S3n[
        R                  U5        U(       a   U(       a   UR                  USSU0S
.U5        [        U5      eU R                   (       a  U(       a  UR"                  (       d  SUl        UR$                  (       a"  UR&                  (       a  UR"                  (       dI  Sn[
        R                  U5        U(       a   U(       a   UR                  USSU0S
.U5        [        U5      eUR(                  (       dX  [
        R                  SUR*                  5        U(       a0  U(       a)   UR                  USSSUR*                   S3S.S
.U5        ggU R,                  S-  n UR/                  5       (       a  [0        R2                  " U5        UR5                  SSS9  US-  n[
        R                  SUR$                  U5        U R                   (       Ga  US -  nUR5                  SSS9  US!-  R5                  SSS9  US!-  S"-  R7                  S#S$S%9  US&-  R7                  UR8                  S$S%9  US'-  R7                  S(S$S%9  US)-  R5                  SSS9  US)-  S*-  R7                  S(S$S%9  [:        R<                  " US+5       nUR?                  US!-  S!S,9  UR?                  US&-  S&S,9  UR?                  US'-  S'S,9  UR?                  US)-  S)S,9  SSS5        [=        US-5       nURA                  5       nSSS5        [B        R&                  " 5       nURE                  W5        URG                  5       Ul        [        U5      Ul$        URK                  5       nS.nS/U-   U-   n[L        RO                  US05      n[Q        U[R        [T        5      nURW                  S1S05      RY                  5       Ul        O%[[        U S2S35      n[]        UR$                  UU5          UR_                  5       R`                  nURH                  b+  UURH                  :w  a  [        S5URH                   S6U 35      e[B        R&                  " 5       n[=        US-5       nURA                  S75      =n(       a+  URE                  U5        URA                  S75      =n(       a  M+  SSS5        URG                  5       nUUR&                  :w  a  [        S8UR&                   S9U 35      e[
        R                  S:5        [=        US-5       nURA                  5       nSSS5        U R                   (       a  [c        WUR"                  [T        [d        S;9nO[c        WUR"                  5      nU(       d  [        S<5      e[
        R                  S=5        U Rf                  S?-  nU Rf                  S@-  U Rh                   SA3-  nSn  UR/                  5       (       a  [0        R2                  " U5        URk                  5       (       aC  URm                  5       n U Ro                  5       (       d  U Rf                  U -  Rq                  5       n O%UR/                  5       (       a  URq                  5       n [
        R                  SBU U5        U (       a,  U R/                  5       (       a  [0        Rr                  " U U5        U Rf                  S@-  UR8                  -  n! U!R/                  5       (       a  [0        R2                  " U!5        U!R5                  SSS9  [
        R                  SDU!5        [:        R<                  " USE5       nURu                  U!SF9  SSS5        U!S&-  n"U"Rw                  5       (       d  [        SG5      eU"Ry                  S$S%9R{                  5       n#U#UR8                  :w  a  [        SHUR8                   SIU# SJ35      e[
        R                  SKU#5        UR/                  5       (       a  [0        R2                  " U5        U!SL-  n$U$R7                  SM[|        R~                   SN3S$S%9  U$R                  SO5        [
        R                  SPU!5        [        U 5        U R                  SR-  n%SSn&[        R                  R                  ST5      (       a  Sn&O9 [        R                  " / SUQSSSV9n'U'R                  R{                  5       SW:X  a  Sn&U[        U5      [        U5      U Rh                  UR8                  [        U5      U R                  UU&SX.	n( [=        U%SY5       n[        R                  " U(U5        SSS5        [
        R                  SZU(5        SSKLn)U)R                  Gb  [
        R                  S\5        SU)R                  lN        [        R                  " 5       n*[[        U S]S^5      S_-
  n+U+S_:  a  S3n+[        R                  " 5       U*-
  U+:  a  U)R                  R                     U)R                  R                   V,s/ sH  n,U,U:w  d  M  U,PM     n-n,SSS5        W-(       d  OJ[
        R                  S`U-5        [        R                  " Sa5        [        R                  " 5       U*-
  U+:  a  M  [
        R                  Sb5         [        U!U5        Sdn.[|        R~                  SeU.[        U%5      [        U R                  5      /n/SSn0U&(       a  [0        R                  " Sf5      (       a  SgU=(       d    Sh Si[M        [        R                  " 5       5       3n1 [
        R                  SjU15        [        R                  " SfSkU1SlSmSn/U/Q[        R                  [        R                  So9  Sn0U0(       dI   [
        R                  Sq5        [        R                  " U/S[        R                  [        R                  Sr9  St[|        R                  ;   a;  [
        R                  Su5        U%Rw                  5       (       a  U%R                  5         gU&(       aD  [
        R                  Sv5         [        R                  " / SwQ5        [|        R                  " S5        U&(       dc  [
        R                  Sy5         [        R                  " [|        R~                  [        US!-  S"-  5      Sz/5        [|        R                  " S5        gg! [         a!  n	[
        R                  SU	5         Sn	A	GNdSn	A	ff = f! [         a     GNf = f! [         a     GNf = f! [         a   n	[
        R                  SU	5         Sn	A	gSn	A	ff = f! , (       d  f       G
N\= f! , (       d  f       G
NI= f! [         ay  n	UR/                  5       (       a  [0        R2                  " U5        U(       a4  U(       a-   UR                  USSS4U	 30S
.U5        O! [         a     Of = f[        S4U	 35      eSn	A	ff = f! , (       d  f       G	NF= f! , (       d  f       GN= f! [         ay  n	UR/                  5       (       a  [0        R2                  " U5        U(       a4  U(       a-   UR                  USSS>U	 30S
.U5        O! [         a     Of = f[        S>U	 35      eSn	A	ff = f! [         ay  n	UR/                  5       (       a  [0        R2                  " U5        U(       a4  U(       a-   UR                  USSSCU	 30S
.U5        O! [         a     Of = f[        SCU	 35      eSn	A	ff = f! , (       d  f       GN= f! [         a  n	UR/                  5       (       a  [0        R2                  " U5        U!R/                  5       (       a  [0        R2                  " U!5        UR/                  5       (       a  [0        R2                  " U5        U(       a4  U(       a-   UR                  USSSQU	 30S
.U5        O! [         a     Of = f[        SQU	 35      eSn	A	ff = f! [         a     GNGf = f! , (       d  f       GN= f! [         a  n	U!R/                  5       (       a  [0        R2                  " U!5        UR/                  5       (       a  [0        R2                  " U5        U(       a4  U(       a-   UR                  USSS[U	 30S
.U5        O! [         a     Of = f[        S[U	 35      eSn	A	ff = fs  sn,f ! , (       d  f       GN= f! [         a  n	U!R/                  5       (       a  [0        R2                  " U!5        UR/                  5       (       a  [0        R2                  " U5        U%Rw                  5       (       a  U%R                  5         U(       a4  U(       a-   UR                  USSScU	 30S
.U5        O! [         a     Of = f[        ScU	 35      eSn	A	ff = f! [         a!  n	[
        R                  SpU	5         Sn	A	GNSn	A	ff = f! [         a!  n	[
        R                  SsU	5         Sn	A	GN_Sn	A	ff = f! [         a#  n	[
        R                  SxU	5        SSn& Sn	A	GNSn	A	ff = f! [         a  n	[
        R                  S{U	5        U	eSn	A	ff = f)|z!Perform self-update of the agent.NrN   r      job_idz3Reporting status 'running' to backend for job_id=%srunningmessagezUpdate in progress...)statusresultz#Failed to report running status: %s)get_api_clientzManifest check returned no infoz'channel mismatch: agent is on channel 'z' but manifest is for channel 'z'; refusing to updatefailedrp   rf   z5Manifest missing download_url, checksum, or signaturez!Agent is already up to date (v%s)	succeededTzAgent is up to date (v))successr   z#Failed to report success status: %szwolfpanel-agent-update)parentsexist_okzagent.tar.gzz(Downloading update archive from %s to %smock_agent_srcsrczmain.pyz
import os, sys
flag_file = os.environ.get("WOLFPANEL_UPDATE_FLAG_FILE")
if flag_file:
    with open(flag_file, "w") as f:
        f.write("OK")
zutf-8)encodingVERSIONz	README.mdmocksystemdzwolfpanel-agent.servicezw:gz)arcnamerbr&   r'   r%   r$   download_timeout   zDownload failed: zSize mismatch: expected z bytes, got r   zChecksum mismatch: expected z, got zChecksum verified successfully)r4   r5   zDSignature verification failed: release package signature is invalid!z'Release signature verified successfullyzVerification failed: r   r   r   z(Backing up current version from %s to %szFailed to create backup: zExtracting update to %szr:gz)pathz*staged package is missing its VERSION filez(package VERSION mismatch: manifest says z but extracted package is z; refusing to activate itz+staged package VERSION matches manifest: %sr   z#!/usr/bin/env bash
exec z$ "$(dirname "$0")/src/main.py" "$@"
i  zStaged new version files at %szFailed to stage new files: zupdate_state.jsonFINVOCATION_ID)	systemctlz	is-activer   )capture_outputtextactive)	r   
backup_dirr   rollback_versionupdating_to_versiontemp_dirapi_urltokenr   wzWrote update_state.json: %szFailed to write update state: zCSelf-update initiated: pausing new command polling and execution...update_timeout<   
   z0Waiting for other running commands to finish: %sg      ?z1Swapping current directory path to new version...zFailed to swap symlink: a  
import os, sys, time, json, shutil, urllib.request
from pathlib import Path

state_file_path = sys.argv[1]
timeout = int(sys.argv[2]) if len(sys.argv) > 2 else 60
time.sleep(timeout)

if not os.path.exists(state_file_path):
    sys.exit(0)

try:
    with open(state_file_path, "r") as f:
        state = json.load(f)
except Exception:
    sys.exit(1)

job_id = state.get("job_id")
backup_dir = Path(state.get("backup_dir"))
current_symlink = Path(state.get("current_symlink"))
temp_dir = Path(state.get("temp_dir"))
api_url = state.get("api_url")
token = state.get("token")
use_systemd = state.get("systemd")

print("Timeout/failure detected. Restoring backup...", flush=True)
try:
    if backup_dir.exists():
        if current_symlink.is_symlink():
            current_symlink.unlink()
        elif current_symlink.exists():
            if current_symlink.is_dir():
                shutil.rmtree(current_symlink)
            else:
                current_symlink.unlink()
        
        try:
            os.symlink(backup_dir, current_symlink)
        except Exception:
            shutil.copytree(backup_dir, current_symlink)
except Exception as e:
    print(f"Failed to restore backup: {e}", flush=True)

try:
    if temp_dir.exists():
        shutil.rmtree(temp_dir)
except Exception:
    pass

try:
    os.unlink(state_file_path)
except Exception:
    pass

if api_url and job_id:
    try:
        url = f"{api_url}/api/v1/agent/commands/{job_id}/result"
        headers = {"Content-Type": "application/json", "User-Agent": "wolfpanel-agent"}
        if token:
            headers["X-Agent-Token"] = token
        payload = {"status": "failed", "result": {"error": "new version failed to connect"}}
        req = urllib.request.Request(url, data=json.dumps(payload).encode("utf-8"), headers=headers, method="POST")
        with urllib.request.urlopen(req, timeout=15) as res:
            pass
    except Exception as e:
        print(f"Failed to report failure to backend: {e}", flush=True)

if use_systemd:
    os.system("systemctl restart wolfpanel-agent")
else:
    os.spawnv(os.P_NOWAIT, sys.executable, [sys.executable, str(current_symlink / "src" / "main.py"), "run"])
z-czsystemd-runzwolfpanel-agent-rollback-r   -z;Spawning rollback watcher as independent systemd unit %s...z--unitz	--collectz--quietz--)stdoutstderrz+Failed to spawn watcher via systemd-run: %sz-Spawning detached rollback watcher process...)start_new_sessionr   r   z$Failed to spawn detached watcher: %spytestz7Running under pytest; skipping reload and process exit.zERunning under systemd. Executing systemctl restart wolfpanel-agent...)r   restartr   zFFailed to run systemctl restart: %s. Falling back to standalone spawn.z3Running standalone. Spawning new version process...runz*Failed to spawn new standalone process: %s)[r*   
isinstancer   rn   r
   rl   rw   post_command_resultr1   rm   ry   r   r   r   rq   rp   rs   r   r   r   r   r   	cache_dirr   r   r   mkdir
write_textr   tarfiler   addr   r/   r   	hexdigestr   r0   r+   r,   r-   TEST_PRIVATE_KEY_DTEST_PUBLIC_KEY_Nr.   hexr   r   r   st_sizer=   TEST_PUBLIC_KEY_Er   rr   r   r   is_absoluteresolver   
extractallis_file	read_textrG   sys
executablechmodr   var_dirrt   ru   
subprocessr   r   r   r   jsondumpcommand_runner_worker_managerupdatingtimelockactive_commandssleepr   r   r   whichPopenDEVNULLmodulesexit)2rx   argskwargsrw   ry   payloadfirstr   r   r{   r   msgr   temp_tarmock_srctarr   	tar_bytesr   r:   r;   paddedr8   sig_intr   actual_sizer   actual_checksumtar_datasig_okr   r   r   new_version_dirpackage_version_filepackage_versionwrapper_path
state_fileuse_systemdresupdate_stater  
start_waitmax_waitcidother_activewatcher_codewatcher_argvwatcher_spawned	unit_names2                                                     r"   self_updater7    s   DJG
4yA~QeZ((DJ
4yA~q'&-W[["4F(2V$E f	DHHJFS**$<S0TU 1'/J$V,EV(=>>
 ||(>(>>5f6L6L5M N,,0LL>9NP 	 			#&..v(W^`cVd7eglm n4)884;;dnnE		#&..v(W^`cVd7eglm n   4dllC&H..*$UklplxlxkyyzS{6|} 	 "::H@3??MM(#td3n,;TXXxP???"22HNN4$N7$$TD$A 	)55 7  6  	!--dkkG-L#///I	!(((E	!$==II&[bIch/35(%89,i@;.D9,i@	 0 h%FFH	 & ^^%FMM)$ **,DK!)nDO
 !--/KiK:[H;VFvu-A!/1BCG$--c59==?DN&v/A2F!$((H6FG '7mmo--??&;$//+I6t6G|T_S`abb!(D!Q66$<'%'e$ 66$<'%' " !**,dkk):4;;-voM^_``12
 (D!QvvxH "??%hBSWhiF%h?Fbcc:;  nny0O*,&2F2F1Gw/OOJN;MM*%%%'',557N!--//"(..>"A!J!J!L##%%,446N;^ZXn3355OONJ7  nnz1DKK?O5=!!##MM/*dT:*O<\\(F+sNNN0 ,  /:#++--HII.88'8JPPRdkk):4;;- H((7'88QS  	>P ??MM(#&):: %	nn ! 	  	 	5!1?C6"( "55JK	zz~~o&&	..!N_cjnoCzz!X-"
 *o/"00#{{M>>
L@*c"aIIlA& #.=" %%1VW26&&/ YY[
6#3R82=b=HiikJ&1//44/=/M/M/]/]o/]adhnan/]o 5HHGVJJsO iikJ&1 HH@A:A(GLP NND,JVMbMbIcdLOv||M22 00B(/C1SEUDVW			LHHRT]^)[)TaT`a!))!))
 #O 		EHHDE"&!))!))	 3;;JK XY	 HIHHQK
 FG	cnnc/E2II2U.VX]^_HHQK	 e  	DKK=sCC	D2      HA3GGHB 0/ &%(  3??MM(#&..'G?PQTPU=V3WX
  +C51223* "! "!  7??MM(#&..'G?TUXTY=Z3[\
  /u5667B  ;??MM(#&..'G?XY\X]=^3_`
  3C59::;, ,+>  =??MM(#!!##MM/*MM*%&..'G?Z[^Z_=`3ab
  5cU;<<!=:  		  #"  @!!##MM/*MM*%&..'G?]^a]b=c3de
  8>??@8  p 54  :!!##MM/*MM*%&..'G?WX[W\=]3^_
  23%899!:^  	LKKEsKK	L  	EKK>DD	E  	 II^`cdK	   	IIBCHI	sv  .w2 $x  x1 3'y ,D!z Ay/z .z?B=z =$z #A3|= A|A$|= >|+A5|= 5C2 A(AA ,AA	<DAA 8AD7 AE AE'AE AH5	AHAHAH:AH" AAK8 %AAL& .AM $AAN 2
x<xx 
x.-x.1
x?>x?
y,y''y,/
y>9z 
zz 
|9|{32|3
| =|?|  ||
|(#|= +
|:5|= =
 9~;~~;
~*'~;)~**~;; 
AA9AA@A@#@"AA@#
A@0@-AA@/A@0@0AAAAAA	
AAAAA A
AD4A%BAD/C5ADDAD/D
ADDAD/DADDAD/D/AD4D7
AEEAEE
AEEAE E
AHE$A$AHG	AG%G$AHG%
AG2G/AHG1AG2G2AHHAHHAHH
AHH"
AK5H,B	AK0J6AKKAK0K
AKKAK0KAKKAK0K0AK5K8
AL#LALLAL#L&
AML0AMMAMM
ANMAM<M<ANN
AN+NAN&N&AN+)
r2   r(   r3   r   r4   r+   r5   r+   returnr   )rK   r   r8  z,tuple[int, int, int, tuple[str, ...] | None])rP   r   r8  ztuple[int, Any])rU   r   rV   r   r8  r+   )rx   r	   ry   r   r8  zUpdateInfo | None)r   r   r   r   )rx   r	   r8  None)r   )r   r   r   r   r   r+   r8  r9  ).__doc__
__future__r   rt   rer  r  r
  r   r   r/   r	  pathlibr   dataclassesr   typingr   ry   r   r   rx   r	   identityr
   loggerr   rl   r   PUBLIC_KEY_NPUBLIC_KEY_Er   r   r   r=   compilerE   rL   rQ   rc   ro   r   r   r   r   r7  r   r!   r"   <module>rE     s    # 	 	 
        !  *  %  " " ", y	 ~	   ~	  @LVb 4 ZZ1
+>  $ 6r(('KTur!   