
    i                         d Z ddlZddlZddlZddlmZ ddlmZ 	 ddlmZ n# e	$ r dZY nw xY wddddZ
 ej                    Zda ej                    ZdZdd
Zd Zd ZddZd Zd ZdS )aJ  
Hermes Web UI -- Self-update checker.

Checks if the webui and hermes-agent git repos are behind their upstream
branches. Results are cached server-side (30-min TTL) so git fetch runs
at most twice per hour regardless of client count.

Skips repos that are not git checkouts (e.g. Docker baked images where
.git does not exist).
    N)Path)	REPO_ROOT)
_AGENT_DIR)webuiagent
checked_atFi  
   c                     	 t          j        dg| z   t          |          dd|          }|j                                        |j        dk    fS # t           j        t          t          f$ r Y dS w xY w)z*Run a git command and return (stdout, ok).gitT)cwdcapture_outputtexttimeoutr   ) F)	
subprocessrunstrstdoutstrip
returncodeTimeoutExpiredFileNotFoundErrorOSError)argsr   r   rs       (/home/ubuntu/hermes-webui/api/updates.py_run_gitr      s    NGdNCw
 
 
 x~~!222%'8'B   yys   AA A0/A0c                     t          ddg|           \  }}|r|r|                    d          d         S dD ]!}t          ddd| g|           \  }}|r|c S "d	S )
z2Detect the remote default branch (master or main).zsymbolic-refzrefs/remotes/origin/HEAD/)mastermain	rev-parsez--verifyorigin/r!   )r   split)pathoutokbranch_s        r   _detect_default_branchr+   +   s    (BCTJJGC	 "c "yy~~b!!$  +z3EV3E3EFMM2 	MMM	8    c                    | | dz                                   sdS t          g d| d          \  }}|s|dddS t          |           }t          d	d
d| g|           \  }}|r#|                                rt	          |          nd}t          g d|           \  }}t          ddd| g|           \  }	}||||	|dS )zACheck if a git repo is behind its upstream. Returns dict or None.N.git)fetchoriginz--quiet   r   r   zfetch failed)namebehinderrorzrev-listz--countzHEAD..origin/)r#   --shortHEADr#   r6   r$   )r3   r4   current_sha
latest_shar)   )existsr   r+   isdigitint)
r&   r3   r*   fetch_okr)   r'   r(   r4   currentlatests
             r   _check_repor@   9   s   |D6M1133|t 9994LLLKAx DNCCC#D))F 
I/Gv/G/GH$OOGC44SXXX1F :::DAAJGQ+y2DF2D2DEtLLIFA   r,   c                 `   t           5  | sJt          j                    t          d         z
  t          k     r t	          t                    cddd           S t
          r t	          t                    cddd           S daddd           n# 1 swxY w Y   	 t          t          d          }t          t          d          }t           5  |t          d<   |t          d<   t          j                    t          d<   t	          t                    cddd           daS # 1 swxY w Y   	 dadS # daw xY w)z6Return cached update status for webui and agent repos.r   NTr   r   F)	_cache_locktime_update_cache	CACHE_TTLdict_check_in_progressr@   r   r   )force
webui_info
agent_infos      r   check_for_updatesrK   V   s    
 " " 	'}\'BBYNN&&" " " " " " " "  	'&&	" " " " " " " "
 "" " " " " " " " " " " " " " "# G44
 W55
 	' 	'%/M'"%/M'"*.)++M,'&&		' 	' 	' 	' 	' 	' 	' #	' 	' 	' 	' 	' 	' 	' 	' 	' #U""""sO   A B
B
<B

BB1D) AD
D) DD)  D!D) )D-c                     t                               d          sdddS 	 t          |           t                                            S # t                                            w xY w)z5Stash, pull --ff-only, pop for the given target repo.F)blockingzUpdate already in progressr(   message)_apply_lockacquire_apply_update_innerrelease)targets    r   apply_updaterU   n   sh    .. F(DEEE"6**s   A
 
A%c                 0   | dk    rt           }n| dk    rt          }ndd|  dS ||dz                                  sdddS t          |          }t	          d	d
g|          \  }}d}|rt	          dg|          \  }}|sdddS d}t	          ddd|g|d          \  }}|s$|rt	          ddg|           dd|dd          dS |rt	          ddg|          \  }}	|	sddddS t
          5  dt          d<   ddd           n# 1 swxY w Y   d|  d| dS )z?Inner implementation of apply_update, called under _apply_lock.r   r   FzUnknown target: rN   Nr.   zNot a git repositorystatusz--porcelainstashzFailed to stash local changesTpullz	--ff-onlyr0      r2   popzPull failed:    z3Updated but stash pop failed -- manual merge needed)r(   rO   stash_conflictr   r   z updated successfully)r(   rO   rT   )r   r   r:   r+   r   rB   rD   )
rT   r&   r)   
status_outr*   stashedr(   pull_outpull_okpop_oks
             r   rR   rR   x   s   	7		(C6(C(CDDD|D6M1133|(>???#D))F h6==MJG 'D))2 	M,KLLL !&+x!H$XZ[[[Hg J 	-gu%t,,,(H#(H(HIII  gu-t44	6 	P"&   
 ( (&'l#( ( ( ( ( ( ( ( ( ( ( ( ( ( ( f#C#C#CvVVVs   -DDD)r	   )F)__doc__r   	threadingrC   pathlibr   
api.configr   r   ImportErrorrD   LockrB   rG   rP   rE   r   r+   r@   rK   rU   rR    r,   r   <module>rj      sA  	 	                           %%%%%%%   JJJ Q??in in		 	 	 	    :# # # #0  ,W ,W ,W ,W ,Ws   # --