
    `gjb                       d Z ddlmZ ddlZddlZddlZddlZddlZddlm	Z	 dZ
dZdZdZdZd	Zd
ZdZe
dd7dZd8dZd9dZd:dZd;dZd<dZd=dZd>dZd?dZd?dZd@dZdAdZdBdZdCdZdDdZ dEdZ!dFdZ"dGdZ#dHdZ$dHd Z%dHd!Z&dId"Z'dJd#Z(dKd$Z)dLd%Z*dLd&Z+dMd'Z,dLd(Z-dLd)Z.dNd*Z/dOd+Z0dPd,Z1dQd-Z2dQd.Z3dPd/Z4dKd0Z5dRd1Z6dSd2Z7dTd3Z8dOd4Z9dUd5Z:dOd6Z;y)Vuw  Backend git operations for the desktop coding rail + Codex-style review pane.

The desktop's git affordances (coding-rail status, worktree lanes, review pane,
branch switch) run as Electron-local git on the user's machine. On a *remote*
gateway those would operate on the wrong filesystem, so this module mirrors them
over the dashboard's authenticated REST surface — the same pattern as ``/api/fs``.

Everything shells out to the system ``git`` (and ``gh`` for ship info / PRs).
Reads degrade to ``None`` / empty on a non-repo; mutations raise so the renderer
can surface a toast. Callers pass an already path-hardened ``cwd``.
    )annotationsN)Path   i   i   i  i P   )mainmaster)timeoutc                   	 t        j                  dg|| dd|      }|j                  |j
                  |j                  fS # t        t         j                  f$ r Y yw xY w)zRun ``git`` in ``cwd``. Returns (returncode, stdout, stderr); never raises
    on a non-zero exit (callers decide what an error means).gitTcwdcapture_outputtextr	   )    zgit invocation failed)
subprocessrunOSErrorSubprocessError
returncodestdoutstderr)r   argsr	   procs       E/root/.hermes/venv/lib/python3.12/site-packages/hermes_cli/web_git.py_gitr       sd    	.~~NTN
 ??DKK44 Z//0 .-.s   A AAc                4    t        | |      \  }}}|dk(  r|S dS )z.stdout of a git command, or "" on any failure.r   r   r   )r   r   codeout_s        r   _git_outr"   0   s$    T?LD#q!)3##    c                    t        | |      \  }}}|dk7  r0t        |j                         xs ddj                  |       d      y)z@Run a git mutation, raising RuntimeError with stderr on failure.r   zgit  z failedN)r   RuntimeErrorstripjoin)r   r   r   r!   errs        r   _git_okr*   6   sG    T?LD!Sqy399;HD$0@*HII r#   c                T    	 t        |       j                         S # t        $ r Y yw xY w)NF)r   is_dirr   r   s    r   _is_dirr.   =   s,    Cy!! s    	''c                F   t        | xs d      j                         }d|vr|S |j                  d      \  }}}|rFd|v rB|j                  d      \  }}}|j                  d      \  }}}| | | j                  dd      S |j	                  d      d   j                         S )ur   ``old => new`` (and ``dir/{old => new}/f``) → the NEW path, so a row
    addresses the real file for diff/stage.r   z => {}z///)strr'   	partitionreplacesplit)rawpathheadr!   tailinnersuffixtos           r   resolve_rename_pathr?   G   s     syb>!DTNN3'MD!Tt>>#.q&??6*1btF8$,,T377::fb!''))r#   c                *   t        | ddg|      }i }|j                         D ]m  }|j                  d      }t        |      dk  r#|d   dk(  rdnt	        |d   xs d      }|d   dk(  rdnt	        |d   xs d      }||f|t        |d         <   o |S )	uP   ``git diff --numstat`` → {path: (added, removed)}; binary files (``-``) → 0.diffz	--numstat	   r   -r      )r"   
splitlinesr7   lenintr?   )r   r   r    countslinepartsaddedremoveds           r   _numstatrN   U   s    
34t4
5C)+F  A

4 u:>1X_#eAhm!*<Qx3!CaA,>160@"58,-A Mr#   c                D   	 t        |       |z  }|j                         }t        j                  j	                  |      r|j
                  t        kD  ry|j                         }d|v ry|j                  d      }|r|j                  d      s|dz   S |S # t        $ r Y yw xY w)u   Line count of an untracked file (newlines + a final unterminated line),
    so the review tree can show +N for new files. Binary / oversized → 0.r          
r   )r   statosr9   isfilest_size_UNTRACKED_LINE_MAX_BYTES
read_bytescountendswithr   )r   reltargetstdataliness         r   _untracked_insertionsr_   c   s    cS[[]ww~~f%6O)O  "D=

5! u)=uqyH5H s$   AB B ((B B 	BBc                l    |D ]/  }|d   dk(  s|d   dk(  s|d   dk(  st        | |d         |d<   1 y )Nstatus?rL   r   rM   r9   r_   )r   filesfiles      r   _fill_untracked_countsrf   t   sI     E>S T']a%7DOq<P1#tF|DDMEr#   c                    g }t        | g d      j                         }|r|j                  |       |g dz  }|D ]%  }t        | dd|g      j                         }|s#|c S  y)zCMerge-base with the remote default branch for "all branch changes".	rev-parse--abbrev-reforigin/HEAD)zorigin/mainzorigin/masterr   r   z
merge-baseHEADN)r"   r'   append)r   
candidatesr:   refbases        r   _branch_baserq   z   sq    JCEFLLND$DDJ lFC89??AK r#   c                    t        | g d      j                         }|r|dk7  r|j                  dd      d   S dD ]1  }t        | ddd	|g      \  }}}|d
k(  s|j                  d      d   c S  y)uD   The repo's trunk name ("main"/"master"/…), preferring origin/HEAD.rh   rk   r2   r   r3   )zrefs/heads/mainzrefs/heads/masterzrefs/remotes/origin/mainzrefs/remotes/origin/masterri   --verify--quietr   N)r"   r'   r7   r   )r   r:   ro   r   r!   s        r   _default_branch_nameru      s    CEFLLND%zz#q!"%% & #ZCHI
a1999S>"%%& r#   c              #    K   | j                  d      }d}|t        |      k  r||   }|r|d   nd}|dk(  rdd|dd f n|dk(  r-d|j                  d	      d
   |j                  d	d      d   f na|dv r]|j                  d	      d
   }|dk(  r|j                  d	d      d   n|j                  d	d      d   }|dk(  r|d
z  }||t        |      f |d
z  }|t        |      k  ryyw)zYield (tag, xy, path) per changed file from ``git status --porcelain=v2 -z``,
    skipping branch headers and the rename/copy origin-path records. One walker
    feeds the rail, the review list, and the commit flow. r   r   rb   ??rE   Nur%   r   
   r3   12r|      	   r}   )r7   rG   r?   )r8   recordsirectagxyr9   s          r   _walk_entriesr      s     iioG	A
c'l
ajc!f#:tSW$$CZsyy~a(#))C*<R*@@@J3"B,/3J399S!$R(CIIc1<Mb<QDczQr.t444	Q c'l
s   C&C+)C+c                    | dv xr |d   dvS )z1A tracked entry whose index (staged) code is set.r{   r   .rb    )r   r   s     r   _entry_stagedr      s    *8Aj!88r#   c                z    t        |      dkD  r|d   nd}|t        | |      | dk(  xs
 | dv xr |dv| dk(  | dk(  dS )Nr   r   rb   r{   r   ry   )r9   stagedunstaged	untracked
conflicted)rG   r   )r   r   r9   ys       r   	_classifyr      sW    R11#AR(3JM3*#4#L*9LCZSj r#   c                    | dv r| dk(  r| j                         S dS |d   dk7  r|d   nt        |      dkD  r|d   nd}|dk7  r|j                         S dj                         S )N)rb   ry   ry   rb   r   r   r   M)upperrG   )r   r   r   s      r   _status_letterr      si    
j!Sjsyy{1c1qESL2a5B!r!uDCKD//11S//11r#   c                    t               syt         g d      \  }}}|dk7  ryd}d}dx}}|j                  d      D ]  }|j                  d      r|t	        d      d }	|	dk(  }|rdn|	}.|j                  d      s@|j                         d	d D ]J  }
|
j                  d
      rt        |
dd xs d      }'|
j                  d      s9t        |
dd xs d      }L  t        |      D cg c]  \  }}}t        |||       }}}}dx}}t         dg      j                         D ]  \  }}||z  }||z  } |t         fd|dt         D              z  }|t               |||t        d |D              t        d |D              t        d |D              t        d |D              t	        |      |||dd dS c c}}}w )zDCompact working-tree status for the coding rail. None on a non-repo.N)ra   --porcelain=v2z--branch-zr   Frw   z# branch.head z
(detached)z# branch.ab rE   +r   rD   rl   c              3  H   K   | ]  }|d    s	t        |d           yw)r   r9   Nrc   ).0fr   s     r   	<genexpr>zrepo_status.<locals>.<genexpr>   s&     n1_`al_m&sAfI6ns   
""c              3  &   K   | ]	  }|d      yw)r   Nr   r   r   s     r   r   zrepo_status.<locals>.<genexpr>   s     1aak1   c              3  &   K   | ]	  }|d      yw)r   Nr   r   s     r   r   zrepo_status.<locals>.<genexpr>   s     5!*5r   c              3  &   K   | ]	  }|d      yw)r   Nr   r   s     r   r   zrepo_status.<locals>.<genexpr>   s     7A;7r   c              3  &   K   | ]	  }|d      yw)r   Nr   r   s     r   r   zrepo_status.<locals>.<genexpr>   s     9a!L/9r      )branchdefaultBranchdetachedaheadbehindr   r   r   r   changedrL   rM   rd   )r.   r   r7   
startswithrG   rH   r   r   rN   valuessum_UNTRACKED_SCAN_CAPru   )r   r   r8   r!   r   r   r   r   r   r:   tokr   r   r9   rd   rL   rM   ars   `                  r   repo_statusr      s   3<KLLD#qqyFHEFyy 
/>>*+s+,./D|+H%T4F^^N+yy{12 />>#&AB1-E^^C( QRA.F	/
/ <I;MNN-#r4YsB%NEN EGvh'..0 1
1 
SnFZGZ@[nnnE -c215115u557779599u:t  Os   0G c                   t        |       sg ddS |dv r|dk(  rt        |       n|}|sg ddS |dk(  r| dn|}t        | |g      j                         D cg c]  \  }\  }}|||ddd }}}}|d	k(  rW|D 	ch c]  }	|	d
   	 }
}	t	        | g d      \  }}}|t        |      D cg c]  \  }}}|dk(  r||
vr|ddddd c}}}z  }|j                  d        t        | |       ||dS t	        | g d      \  }}}|dk7  rg ddS t        | dg      }t        | g       }g }t        |      D ]a  \  }}}|j                  |d      \  }}|j                  |d      \  }}|j                  |||z   ||z   t        ||      t        ||      d       c |j                  d        t        | |       |ddS c c}}}w c c}	w c c}}}w )zBChanged files for a scope. Mirrors the Electron reviewList shapes.N)rd   rp   )r   lastTurnr   ...HEADr   F)r9   rL   rM   ra   r   r   r9   ra   r   r   rb   r   c                    | d   S Nr9   r   r   s    r   <lambda>zreview_list.<locals>.<lambda>  s
    6 r#   )key--cached)r   r   c                    | d   S r   r   r   s    r   r   zreview_list.<locals>.<lambda>/  s
    QvY r#   )r.   rq   rN   itemsr   r   sortrf   getrm   r   r   )r   scopebase_refrp   rngr9   r   r   rd   r   seenr!   r8   r   _xyr   r   r   r   sasruaurs                          r   review_listr     s2   3<T**&&$)X$5|C 8.."'8"3g !)se 4 : : <
 
fq! A!seT
 
 J',-!AfI-D-S"DEIAsA&3C&8 "Cd#:$d"2 a3RWX E
 	

*
+sE*--?@LD#qqyT**cJ<(FR HE&s+ 
RD&)BdF+Bb7(b1'R0	

 
JJ&J'3&D))K

 .s   F<;G+G
c                J   t        |       sy|dk(  r"t        |       }|rt        | d| dd|g      S dS |dk(  r|rt        | d|d|g      S dS |rt        | ddd|g      S t        | dd|g      }|j                         r|S t	        | dddt
        j                  |g      \  }}}|S )	Nr   r   rA   r   --r   r   
--no-index)r.   rq   r"   r'   r   rS   devnull)	r   	file_pathr   r   r   rp   worktreer!   r    s	            r   review_diffr   4  s    3<C MQxfg&6iHIYWYY
EMxfhi@AUSUUfj$	BCCfdI67H~~S6<rzz9MNIAsAJr#   c                   t        |       syt        | ddd|g      }|j                         r|S t        | ddd|g      }|j                         j                  d      syt	        | dddt
        j                  |g      \  }}}|S )	zWorking-tree-vs-HEAD diff for one file (the preview's diff view). Unlike
    review_diff, never all-adds a clean tracked file; only a genuinely untracked one.r   rA   rl   r   ra   --porcelainrx   r   )r.   r"   r'   r   r   rS   r   )r   r   r:   ra   r!   r    s         r   file_diff_vs_headr   F  s     3<C&&$	:;Dzz|cHmT9EFF<<>$$T*S6<rzz9MNIAsAJr#   c                4    t        | |rdd|gnddg       ddiS )Naddr   -AokTr*   r   r   s     r   review_stager   U  s%    CY%y)UDMJ$<r#   c                8    t        | |rdddd|gng d       ddiS )Nreset-qrl   r   )r   r   rl   r   Tr   r   s     r   review_unstager   Z  s&    CY'4y9Lcd$<r#   c                ^    |rd|gnddg}t        | ddg|       t        | ddg|       ddiS )	zPDiscard changes back to the committed state (restore tracked, remove untracked).r   r   checkoutrl   cleanz-fdr   Tr   )r   r   r[   s      r   review_revertr   _  sF    "+dI$Fz6+F+,w''($<r#   c                N    t        | d|xs dg      j                         }|xs d S )Nri   rl   )r"   r'   )r   ro   r    s      r   review_rev_parser   g  s*    
3cmV4
5
;
;
=C;$r#   c                    t        | g d      \  }}}t        d t        |      D              st        | ddg       t        | dd|g       |rt	        |        ddiS )	zGCommit the working tree; stage everything first when nothing is staged.r   c              3  <   K   | ]  \  }}}t        ||        y wNr   r   r   r   r!   s       r   r   z review_commit.<locals>.<genexpr>o  s     K*#r1}S"%K   r   r   commit-mr   T)r   anyr   r*   _review_push)r   messagepushr!   r8   s        r   review_commitr   l  s\    S<=IAsAKc8JKKeT]#C(D'*+S$<r#   c                    t        | g d      j                         }|rt        | dg       y t        | g d      j                         }|r|dk7  rt        | ddd|g       y y y )N)ri   rj   z--symbolic-full-namez@{u}r   )ri   rj   rl   rl   z-uorigin)r"   r'   r*   )r   upstreamr   s      r   r   r   w  sd    Z[aacHfXc@AGGIF&F"fdHf56 #vr#   c                     t        |        ddiS )Nr   T)r   r-   s    r   review_pushr     s    $<r#   c                   t        |       sdddS t        | g d      \  }}}|dk7  rdddS t        t        |            }t	        d |D              }|rt        | ddg      nt        | ddg      }t        |      t        kD  r!t        |      t        z
  }|d	t          d
| d}|D 	
cg c]  \  }}	}
|dk(  s|
 }}	}}
|rc|d	t         }ddj                  d |D              z   }t        |      t        |      kD  r|dt        |      t        |      z
   dz  }|r| | n|}|xs dt        | g d      j                         dS c c}
}	}w )zJDiff of what WILL commit + recent subjects, for drafting a commit message.r   )rA   recentr   r   c              3  <   K   | ]  \  }}}t        ||        y wr   r   r   s       r   r   z(review_commit_context.<locals>.<genexpr>  s     F
R]3+Fr   rA   r   rl   Nz
# diff truncated: z chars omitted
rb   z
# New (untracked) files:
c              3  (   K   | ]
  }d | d  yw)z#   
Nr   )r   ps     r   r   z(review_commit_context.<locals>.<genexpr>  s     7V$qc7Vs   z#   ... z more omitted
)logz-n10z--pretty=format:%s)r.   r   listr   r   r"   rG   _COMMIT_CONTEXT_DIFF_MAX_CHARS_COMMIT_CONTEXT_UNTRACKED_MAXr(   r'   )r   r   r8   r!   entries
has_stagedrA   omittedr   r   r9   r   visiblenotes                 r   review_commit_contextr    si   3<b))?@LD#qqyb))=%&GFgFFJ2<8C&*-.(3QWY_P`BaD
4y11d)<<66788LWIUef,3BB.#sDsczBIB::;-7Vg7V0VVy>CL(hs9~G<=_MMD"&$vDJB(38a*b*h*h*jkk Cs   *E	9E	c                    t        j                  d      sy	 t        j                  dg|| ddt              }|j                  dk(  |j                  xs dfS # t
        t        j                  f$ r Y yw xY w)Ngh)Fr   Tr   r   r   )	shutilwhichr   r   _GH_TIMEOUTr   r   r   r   )r   r   r   s      r   _ghr    ss    <<~~MDMs4dK

 ??a!222 Z//0 s   !A A43A4c                n   t        |       sdddS t        | ddg      \  }}|sdddS t        | g d      \  }}|sdddS 	 t        j                  |      }|r;|j                  d      r*d|d   |j                  d	      |j                  d
      ddS dddS # t        j                  $ r dddcY S w xY w)zPgh availability/auth + this branch's PR. ghReady false when gh missing/unauthed.FN)ghReadyprauthra   )r  viewz--jsonzurl,state,numberTurlstatenumber)r  r  r  )r.   r  jsonloadsJSONDecodeErrorr   )r   auth_okr!   view_okr    r  s         r   review_ship_infor    s    3< --S68,-JGQ --sHILGSt,,-ZZ_ 
bffUmr%y266'?^`^d^dem^n'opp4((	  -t,,-s   B B43B4c                    	 t        |        t        | g d      \  }}|st        d      t        d t	        |j                         j                               D        d      }d|iS # t        $ r Y ew xY w)zLCreate a PR for the current branch (push first), letting gh fill title/body.)r  createz--fillz8gh pr create failed (is gh installed and authenticated?)c              3  B   K   | ]  }|j                         s|  y wr   r'   r   rJ   s     r   r   z#review_create_pr.<locals>.<genexpr>  s     Ttzz|Ts   r   r  )r   r&   r  nextreversedr'   rF   )r   createdr    r  s       r   review_create_prr%    sv    S s67LGSUVV
T#))+*@*@*B!CTVX
YC3<  s   A' '	A32A3c                   g }d }| j                  d      D ]  }|j                  d      r-|r|j                  |       |dd  j                         d dddd}A|D|j                  d      r(|dd  j                         j	                  dd	d
      |d<   }|dk(  rd|d<   |dk(  rd|d<   |j                  d      sd|d<    |r|j                  |       |S )Nr   z	worktree r   F)r9   r   r   barelockedzbranch    refs/heads/r   r   r   r   Tr'  r(  )r7   r   rm   r'   r6   )r    treescurrJ   s       r   _parse_worktreesr-    s    EC		$ !??;'S!8>>+tX]inoC[__Y' HNN,44]BJCMZ"C
OV^CK__X& CM! SLr#   c           
         t        | g d      }|sg S t        t        |            D cg c]  \  }}|d   |d   |dk(  |d   |d   d c}}S c c}}w )N)r   r   r   r9   r   r   r   r(  )r9   r   isMainr   r(  )r"   	enumerater-  )r   r    indextrees       r   worktree_listr3    sp    
3;
<C	 %%5c%:;	 E4 L8nqjZ(8n	
	 	 	s   !Ac                >    t        |       D ]  }|d   s	|d   c S  | S )Nr/  r9   )r3  )r   r2  s     r   
_main_rootr5    s.    c"  ><  Jr#   c                4   t        | xs d      }t        j                  dd|      }t        j                  dd|      }t        j                  dd|      }t        j                  dd|      }t        j                  dd	|      }t        j                  d
d|      S )Nr   z\s+rD   z[^\w./-]z-{2,}z/{2,}r2   z\.{2,}r   z^[-./]+|[-./]+$)r4   resub)namevalues     r   _sanitize_branchr;     s}    
OEFF63&EFF;E*EFF8S%(EFF8S%(EFF9c5)E66$b%00r#   c                    t        j                  ddt        | xs d      j                         j	                               }t        j                  dd|      d d j                  d      }|xs dS )Nz
[^a-z0-9]+rD   r   z^-+|-+$(   work)r7  r8  r4   r'   lowerrstrip)r9  slugs     r   _slugifyrB  
  s\    66-c$*"o&;&;&=&C&C&EFD66*b$',33C8D>6r#   c                   t        | g d      j                         j                  ddd      }|r|S t        | g d      j                         }|r|S t        D ]&  }t        | ddd| g      j                         s$|c S  y)	Nzsymbolic-refrt   z--shortzrefs/remotes/origin/HEADorigin/r   r   )configz--getzinit.defaultBranchzshow-refrs   r*  )r"   r'   r6   _TRUNK_BRANCHES)r   remote
configuredr   s       r   _default_branchrJ    s    OegggiQ'  #HIOOQJ! C*jKx2HIJPPRM r#   c                    t        | ddg      j                         }d}|dk7  rt        | dg       d}nt        | g d      \  }}}|dk7  }|rt        | g d	       y
y
)zA new project folder may not be a repo (or has no commit to branch from);
    init it with a root commit so worktrees just work. No-op for a committed repo.ri   z--is-inside-work-treeFtrueinitT)ri   rs   rl   r   )-czuser.email=hermes@localhostrN  zuser.name=Hermesr   z--allow-emptyr   zInitial commitN)r"   r'   r*   r   )r   inside
needs_rootr   r!   s        r   _ensure_reporQ    sq     cK)@ABHHJFJfX
#@A
aQY
		
 r#   c                    | }d}t         j                  j                  |      r,|dz  }|  d| }t         j                  j                  |      r,|S )Nr   rD   )rS   r9   exists)rp   	candidatens      r   _unique_dirrV  :  sN    I	A
''..
#	QfAaSM	 ''..
# r#   c           	     2   t        |        t        |       }|xs i }t        |j                  d      xs d      }|j                  d      rx|st	        d      |t        |      k(  rt        |d|g       |||dS t        t        j                  j                  |dt        |                  }t        |dd||g       |||dS t        |j                  d	      xs& d
t        j                  d      j                                }t        |j                  d      xs d      xs d| }t        t        j                  j                  |d|            }ddd||g}|j                  d      rMt        |d         }|j                  d      r|t!        d      d  }	t#        |dd|	g       |j%                  |       t#        ||      \  }
}}|
dk7  rDd|xs dj'                         v rt        |dd||g       nt	        |j)                         xs d      |||dS )NexistingBranchr   Branch name is required.switch)r9   r   repoRootz
.worktreesr   r   r9  zwork-   r   zhermes/z-brp   rE  fetchr   r   zalready existszgit worktree add failed)rQ  r5  r;  r   r&   rJ  r*   rV  rS   r9   r(   rB  urandomhexr4   r   rG   r   rm   r?  r'   )r   optionsrootexistingr[   rA  r   r   rp   remote_branchr   r!   r)   s                r   worktree_addrd  C  s   c?DmG,< = CDH{{#$9::t,,D8X./ H$GGRWW\\$hx>PQRz5&(;<(EEGKK'HU2::a=3D3D3F2G+HIDgkk(39r:Nv>NFdL$?@FtVV4D{{676?#
 ??9% Y1M=9:Dd#LD!Sqy	r0022D:uff=>syy{G.GHHf$??r#   c                    t        |       }ddg}|r|j                  d       |j                  |       t        ||       d|iS )Nr   removez--forcerM   )r5  rm   r*   )r   worktree_pathforcera  r   s        r   worktree_removeri  j  sE    c?D!DIKKD$}%%r#   c           	     :   t        | g d      }|sg S t        |       }|D ci c]  }|d   s	|d   |d    }}t        |       }d |j                  d      D        D cg c],  }|r(|||v t	        |xr ||k(        |j                  |      d. c}S c c}w c c}w )N)for-each-refz--format=%(refname:short)--sort=-committerdate
refs/headsr   r9   c              3  <   K   | ]  }|j                           y wr   r   r!  s     r   r   zbranch_list.<locals>.<genexpr>  s     >dTZZ\>r   r   )r9  
checkedOut	isDefaultworktreePath)r"   r3  rJ  r7   boolr   )r   r    r+  tpath_by_branchtrunkr9  s          r   branch_listrv  t  s    
aC 	#E6;Kq{ak1V9,KNKC E ?ciio>	  .0e56*..t4		
	 	 L	s   
BB1Bc                V    t        |      }|st        d      t        | d|g       d|iS )NrY  rZ  r   )r;  r&   r*   )r   r   r[   s      r   branch_switchrx    s5    f%F566C(F#$fr#   c           	        t        | g d      }|sg S t        | g d      j                         }|st        |       nd}g }|j                  d      D ]m  }|j                         }|s|j                  d      d   }|j	                  ||j                  d      t        |xr ||k(  xs | xr	 |xr ||k(        d       o |S )	zLocal heads + remote-tracking refs for the base-branch picker.

    The remote default (origin/HEAD) is flagged so the UI can preselect it.
    )rk  z.--format=%(refname:short)	%(committerdate:iso)rl  rm  zrefs/remotesrD  r   r   rB   r   rE  )r9  isRemoterp  )r"   r'   rJ  r7   rm   r   rr  )r   r    remote_defaultlocal_defaultresultrJ   r9  s          r   base_branch_listr~    s    
 	
	C 	Oeg  1?OC(BMF		$ 
zz|zz$" OOI6 "#>(> X**V}VAV
	

$ Mr#   )r   r4   r   	list[str]r	   rH   returnztuple[int, str, str])r   r4   r   r  r  r4   )r   r4   r   r  r  None)r   r4   r  rr  )r8   r4   r  r4   )r   r4   r   r  r  zdict[str, tuple[int, int]])r   r4   rZ   r4   r  rH   )r   r4   rd   
list[dict]r  r  )r   r4   r  
str | None)r8   r4   )r   r4   r   r4   r  rr  )r   r4   r   r4   r9   r4   r  dict)r   r4   r   r4   r  r4   )r   r4   r  zdict | None)r   r4   r   r4   r   r  r  r  )r   r4   r   r4   r   r4   r   r  r   rr  r  r4   )r   r4   r   r4   r  r4   )r   r4   r   r  r  r  )r   r4   ro   r  r  r  )r   r4   r   r4   r   rr  r  r  )r   r4   r  r  )r   r4   r  r  )r   r4   r   r  r  ztuple[bool, str])r    r4   r  r  )r   r4   r  r  )r   r4   r  r4   )r9  r4   r  r4   )rp   r4   r  r4   )r   r4   r`  r  r  r  )r   r4   rg  r4   rh  rr  r  r  )r   r4   r   r4   r  r  )<__doc__
__future__r   r  rS   r7  r  r   pathlibr   _GIT_TIMEOUTr  _MAX_BUFFERrV   r   r  r  rG  r   r"   r*   r.   r?   rN   r_   rf   rq   ru   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r  r  r  r%  r-  r3  r5  r;  rB  rJ  rQ  rV  rd  ri  rv  rx  r~  r   r#   r   <module>r     s,  
 #  	 	   '  !(  " $ 7C 5 $J*"E(,9
20l/*d$


7
l:	3)&
 . 1
6$@N&*(r#   