
    p:i                         d dl m Z  d dlZd dlZd dlmZ d dlmZ d dlmZm	Z	m
Z
mZmZ d dlmZmZmZ d dlmZmZmZ d dlmZmZ d d	lmZmZmZ d d
lmZ d dlmZm Z m!Z!m"Z"m#Z#m$Z$m%Z%m&Z&m'Z' d dl(m)Z)m*Z*m+Z+ d dl,m-Z- d dl.m/Z/ d dl0m1Z1 d dl2m3Z3  G d de*          Z4 G d de+          Z5d Z6d Z7d Z8dZ9d Z:d Z; G d de          Z< G d de          Z= G d d e!          Z> G d! d"e           Z? G d# d$e          Z@ G d% d&e          ZAdS )'    )datetimeN)ISystemInfoProvider)cached)
BoolOption	IntOption
ListOption
PathOptionOption)	Component	TracError
implements)FixedOffsetto_timestampformat_datetime)Markuptag)exception_to_unicodeshorten_line
to_unicode_)		ChangesetNode
RepositoryIRepositoryConnectorInvalidRepositoryNoSuchChangeset
NoSuchNodeRepositoryManagerIRepositoryProvider)CACHE_YOUNGEST_REVCachedRepositoryCachedChangeset)IPropertyRenderer)Chrome)IWikiSyntaxProvider)PyGITc                   D    e Zd ZdZd Zd Zd Zd Zd Zd Z	d Z
ddZd	S )GitCachedRepositoryzGit-specific cached repository.c                 ,    |                      |          S N	short_revselfrevs     Y/var/www/html/trac/venv/lib/python3.11/site-packages/tracopt/versioncontrol/git/git_fs.pydisplay_revzGitCachedRepository.display_rev+       ~~c"""    c                 6    | j                             |          S r+   )reposr-   r/   paths     r1   r-   zGitCachedRepository.short_rev.   s    z##D)))r4   c                     |s|                                  S | j        j                            |          }|t	          |          |S r+   )get_youngest_revr6   git	verifyrevr   r/   r0   normrevs      r1   normalize_revz!GitCachedRepository.normalize_rev1   sK     	+((****.**3//?!#&&&r4   c                 .    t          j        |           pd S r+   )r"   r:   r/   s    r1   r:   z$GitCachedRepository.get_youngest_rev9   s    066>$>r4   c                 6    | j                             |          S r+   )r6   
child_revsr.   s     r1   rC   zGitCachedRepository.child_revs=   s    z$$S)))r4   c              #   Z   K   t          j        t          j         ||          d           D ]z\  }}t	          |          }t          |          dk    r|d         V  2d |D             r: fdD             }t          |          D ]}                    |          V  :{d S )Nc                     | j         S r+   )date)csets    r1   <lambda>z4GitCachedRepository.get_changesets.<locals>.<lambda>C   s     r4   )key   r   c                     i | ]
}|j         |S  )r0   ).0rG   s     r1   
<dictcomp>z6GitCachedRepository.get_changesets.<locals>.<dictcomp>H   s    :::D4:::r4   c                 z    g | ]7}t          fd j                            |          D                       5|8S )c              3       K   | ]}|v V  	d S r+   rL   )rM   r	rev_csetss     r1   	<genexpr>z@GitCachedRepository.get_changesets.<locals>.<listcomp>.<genexpr>K   sC       'L 'L+, ()I~ 'L 'L 'L 'L 'L 'Lr4   )anyr6   rC   )rM   r0   rR   r/   s     r1   
<listcomp>z6GitCachedRepository.get_changesets.<locals>.<listcomp>J   s}     M M M#& 'L 'L 'L 'L04
0E0Ec0J0J'L 'L 'L $L $LM M M Mr4   )	itertoolsgroupbyr"   get_changesetslistlensortedpop)r/   startstoprI   csetsrevsr0   rR   s   `      @r1   rX   z"GitCachedRepository.get_changesets@   s     #+ /eTBB**, , , 	- 	-JC KKE5zzQAh::E:::I -M M M M My M M M "$<< - -C#--,,,,,,  -	- 	-r4   c                 T    t          | |                     |          | j                  S r+   )GitCachedChangesetr?   envr.   s     r1   get_changesetz!GitCachedRepository.get_changesetP   s$    !$(:(:3(?(?JJJr4   NFc                 (   	
 |r                                    j        }                     |           |                    t          d          } j        
 fd	
 fd}	
fd
 fd} j        j        5  	 
                                  |            r |            r*
j	        pd}||k    r? j        j
        5 } |d| j        t          f            `d d d            n# 1 swxY w Y   	 d d d            d S # 1 swxY w Y   d S )N c                 d    j                             dj        | f          D ]\  }|dk    c S dS )Nza
                    SELECT COUNT(*) FROM revision WHERE repos=%s AND rev=%s
                    r   F)rc   db_queryid)r0   countr/   s     r1   	is_syncedz+GitCachedRepository.sync.<locals>.is_synced\   sK    (++ -'3) ) ! ! qy   5r4   c                     d} t          t          d 	j                                        D                                 }| dz
  }t	          dt          |          |          D ]}||||z            }d                    dt          |          z            }
j        g}|                    |           d|z  }
j	        
                    ||          D ]\  }|t          |          k     r  dS d	S )
Ni  c              3       K   | ]	\  }}|V  
d S r+   rL   )rM   refnamer0   s      r1   rS   z?GitCachedRepository.sync.<locals>.needs_sync.<locals>.<genexpr>e   s&      KKlgscKKKKKKr4   rJ   r   ,)z%szXSELECT COUNT(*) FROM revision
                           WHERE repos=%%s AND rev IN (%s)TF)r[   setr;   get_refsrangerZ   joinri   extendrc   rh   )max_holdersr`   stepidxrevs_holdersargsqueryrj   r6   r/   s            r1   
needs_syncz,GitCachedRepository.sync.<locals>.needs_syncc   s   K#KKei6H6H6J6JKKKKKLLD?DQD		400 	$ 	$St^,((7SZZ#788yE""">@GH"h//t<< $ $FEs5zz))#ttt *$ 5r4   c                    g }g }	 | |v rn|                     |             |           rnu|                    |                                |           }|snH|d         } t          |          dk    r,|                    t          |          |dd          f           t	          |          D ]\  }}|D ]}  | |          |||<   |S )NTr   rJ   )addappendparent_revsrZ   reversed)	r0   seenr`   
merge_revsr   rw   rk   r6   traverses	         r1   r   z*GitCachedRepository.sync.<locals>.traverses   s   DJD$;;9S>> C   #//44" !!n{##a''%%s4yy+abb/&BCCCD %-Z$8$8 8 8 [& 8 8C$,HS$$7$7DSMM8Kr4   c                     d} t                      }j                                        D ]}                    |          r 	||          }|r|                                }j                            d|                               |          }	                     ||           d} n=# j	        j
        j        $ r&}j                            d||           Y d }~d }~ww xY wr |           || S )NFzTrying to sync revision [%s]TzRevision %s already cached: %r)rp   r;   all_revsrC   r\   loginford   insert_changesetrc   db_excIntegrityError)
updatedr   r0   r`   rG   efeedbackr6   r/   r   s
         r1   	sync_revsz+GitCachedRepository.sync.<locals>.sync_revs   s,   G55Dy))++ & &##C(( xT** &((**CHMM"@#FFF ..s33D!--c4888"&8?9 ! ! !&FQOOO !   &   & Ns   B//C)C$$C)Tz
                            UPDATE repository SET value=%s
                            WHERE id=%s AND name=%s
                            )remove_cachemetadatasave_metadatagetr!   r6   rc   rh   syncyoungest_revdb_transactionri   )r/   r   cleanr   meta_youngestr|   r   repos_youngestdbrk   r6   r   s   ``       @@@r1   r   zGitCachedRepository.syncS   s&    	 =8$$$ %7<<
	 	 	 	 		 	 	 	 	 	 	 	 	 	 	 	 	*	 	 	 	 	 	 	 	0 X 	 	

:<< IIKK !&!3!9r N220 *B   #1$';M!NP P P !M* * * * * * * * * * * * * * * 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	s7    ADC."D.C2	2D5C2	6DDD)NF)__name__
__module____qualname____doc__r2   r-   r?   r:   rC   rX   rd   r   rL   r4   r1   r)   r)   (   s        ))# # #* * *  ? ? ?* * *- - - K K KZ Z Z Z Z Zr4   r)   c                       e Zd ZdZd Zd ZdS )rb   zGit-specific cached changeset.c                 v    | j         fd| j        j        j                            d          D             S )Nc                 &    g | ]\  }}||k    fS rL   rL   rM   kv_revs      r1   rU   z3GitCachedChangeset.get_branches.<locals>.<listcomp>   s7     O O O41aAI O O Or4   Tresolver0   r6   r;   get_branch_containsr/   r   s    @r1   get_brancheszGitCachedChangeset.get_branches   sX    xO O O O!%99$9MMO O O 	Or4   c                 T    | j         j         j                            | j                  S r+   r6   r;   get_tagsr0   rA   s    r1   r   zGitCachedChangeset.get_tags   s     z#,,TX666r4   N)r   r   r   r   r   r   rL   r4   r1   rb   rb      s;        ((O O O7 7 7 7 7r4   rb   c              #      K   t          |           }	 t          |          }n# t          $ r Y dS w xY w|D ]
}d|fV  |}d|fV  dS )z/helper for detecting last iteration in for-loopNFT)iternextStopIteration)iterableir   nextvs       r1   _last_iterabler      sy      XAGG     Qh
'MMMMMs   # 
11c              #   H   K   t          |          D ]\  }}|r| V  |V  dS )zThe 'intersperse' generator takes an element and an iterable and
    intersperses that element between the elements of the iterable.

    inspired by Haskell's ``Data.List.intersperse``
    N)	enumerate)sepr   r   items       r1   intersperser      sE       X&&  4Ciii



 r4   c                     |                      dd          \  }}}t          t          |          dz  dz  |          }t          j        t          |          |          }||fS )zgParse author or committer attribute lines and return
    corresponding ``(user, timestamp)`` pair.
    N      
   )rsplitr   intr   fromtimestampfloat)susertimetz_strtzs        r1   _parse_user_timer      s^    
 $**D$	c&kkAo",f	5	5B!%++r22D:r4   i   c                 "    | dS | t           z  dv S )NF)i @     _file_type_maskmodes    r1   _is_dirr      s    |u?"';;;r4   c                 &    | dS | t           z  dk    S )NFr   r   r   s    r1   _is_submoduler      s    |u?"x//r4   c                   N   e Zd Z eeee           d Zd Zd Z	d Z
d Z edddd	          Z edd
dd          Z edddd          Z edddd          Z edddd          Z edddd          Z edddd          Z edddd          Z edddd          Zd Zd Zd S )!GitConnectorc                    d | _         	 t          j                            | j                  | _         n7# t          j        $ r%}| j                            d|           Y d }~nd }~ww xY w| j         rg| j                            d| j         d                    | j         d         s6| j                            d| j         d         | j         d                    d S d S d S )N)git_binzGitError: %szdetected GIT version %sv_strv_compatiblez3GIT version %s installed not compatible(need >= %s)	v_min_str)	_versionr'   Storagegit_versionr   GitErrorr   errorr   )r/   r   s     r1   __init__zGitConnector.__init__   s    	.!M55dl5KKDMM~ 	. 	. 	.HNN>1--------	. = 	;HMM3T]75KLLL=0 ;  ./3}W/E#}[9; ; ; ; ;	; 	;; ;s   *4 A(A##A(c              #   >   K   | j         rd| j         d         fV  d S d S )NGITr   )r   rA   s    r1   get_system_infozGitConnector.get_system_info  s8      = 	0w///////	0 	0r4   c           	      >   d}|j         }|r)|j        j        dv r|j        j        j        }n	|j        }|)	 t          | j                                      |          }|st          d|z            |	                    |          }|
                    |          }t          j        |dt          |j                  |j                            ||j                            S # t          $ r/}t          j        |dt%          |          d          cY d }~S d }~ww xY w)	Nrf   )source	changesetzRepository '%s' not foundr   class_titlehrefmissing changesetnofollowr   r   rel)contextresourcerealmparentri   r   rc   get_repository	Exceptionr?   rd   r   ar   messager   r   reponamer   )	r/   	formattershalabelr   r   r6   r   r   s	            r1   _format_sha_linkzGitConnector._format_sha_link
  s[    # 	%%)@@@"+25nG	  	%	>%dh//>>xHHE H ;h FGGG%%c**C++C00I5{+I,=>>'n66sENKKM M M M  	> 	> 	>5':)!}}*> > > > > > > > >	>s   B,C# #
D-$DDDc              #   .    K   d j         z   fdfV  d S )Nz(?:\b|!)r?[0-9a-fA-F]{%d,40}\bc                 p                         | |                    d          r
|dd          p||          S )NrQ   rJ   )r   
startswith)fmtr   matchr/   s      r1   rH   z.GitConnector.get_wiki_syntax.<locals>.<lambda>'  sG    ))#s~~c/B/B 06.1!""g0=9<cC C r4   )wiki_shortrev_lenrA   s   `r1   get_wiki_syntaxzGitConnector.get_wiki_syntax%  sN      043IIC C C CD 	D 	D 	D 	D 	Dr4   c              #        K   dd fd	fV  d S )Nr   c                 2                         | ||          S r+   )r   )r   r   r   r   r   r/   s        r1   rH   z1GitConnector.get_link_resolvers.<locals>.<lambda>,  s    --c3>> r4   r+   rL   rA   s   `r1   get_link_resolverszGitConnector.get_link_resolvers+  sG       ? ? ? ? ? @ 	@ 	@ 	@ 	@ 	@r4   r;   persistent_cachefalsez)Enable persistent caching of commit tree.cached_repositoryz+Wrap `GitRepository` in `CachedRepository`.shortrev_len   zTThe length at which a sha1 is abbreviated (must be >= 4
        and <= 40).
        wikishortrev_len(   zThe minimum length at which a hex-string in wiki content
        is formatted as a changeset TracLink (must be >= 4 and <= 40).
        trac_user_rlookupa  Enable reverse mapping of git email addresses to trac user ids.
        Performance will be reduced if there are many users and the
        `cached_repository` option is `disabled`.

        A repository resync is required after changing the value of this
        option.
        use_committer_idtruezbUse git-committer id instead of git-author id for the
        changeset ''Author'' field.
        use_committer_timezsUse git-committer timestamp instead of git-author timestamp
        for the changeset ''Timestamp'' field.
        git_fs_encodingutf-8z9Define charset encoding of paths within git repositories.r   zPath to the git executable.c              #      K   dV  d S )N)r;      rL   rA   s    r1   get_supported_typesz GitConnector.get_supported_types[  s      r4   c                      |dk    sJ d j         cxk    rdk    s n t          t          dd                    d j        cxk    rdk    s n t          t          dd                     j        st          t          d                     j        d	         s5t          t          d
 j        d          j        d                              j        r fd}nd }t           j        || j         j	         j
         j         j         | j         j                  } j        r7t           j        | j                  } j                            d|           n j                            d|           |S )zGitRepository factory methodr;      r  z'%(option)s must be in the range [4..40]z[git] shortrev_len)optionz[git] wikishortrev_lenzGIT backend not availabler   zFGIT version %(hasver)s installed not compatible (need >= %(needsver)s)r   r   )hasverneedsverc                 T   	 |                      dd          \  }} |                     dd          \  } }|                                 } n# t          $ r Y dS w xY wj                                        D ]3\  }}}	 | |                                k    r|c S $# t          $ r Y 0w xY wdS )zReverse map 'real name <user@domain.tld>' addresses to trac
                user ids.

                :return: `None` if lookup failed
                <rJ   >N)r   splitlowerr   rc   get_known_users)emailr   _uid_name_emailr/   s        r1   rlookup_uidz0GitConnector.get_repository.<locals>.rlookup_uids  s     $||C33HAu${{322HE1!KKMMEE       44  ,08+C+C+E+E ! !'D%! FLLNN22#'KKK 3$ ! ! ! !	! !s$   AA
 

AA;B
B%$B%c                     d S r+   rL   r   s    r1   r$  z0GitConnector.get_repository.<locals>.rlookup_uid  s    tr4   )r  r   r  r  r$  r  r  z!enabled CachedRepository for '%s'z"disabled CachedRepository for '%s')r  r   r   r   r   r  GitRepositoryrc   r   r  r   r  r  r  r  r)   debug)r/   typedirparamsr$  r6   s   `     r1   r   zGitConnector.get_repository^  s   u}}}}T&,,,,",,,,AG%9; ; ; < < < T+1111r1111AG%=? ? ? @ @ @ } 	DA9::;;;~. 	DA B%)]7%;'+}['AC C C D D D
 ! 	! ! ! ! ! !,   dhVTX/3/D&*l.2.B+/+<*5/3/D151H      ! 	F'%BBEHNN>DDDDHNN?EEEr4   N)r   r   r   r   r   r   r&   r   r   r   r  r  r   r  r  r   r  r   r  r  r  r
   r  r   r  r   rL   r4   r1   r   r      s       J#%8:MNNN; ; ;"0 0 0> > >6D D D@ @ @ "z%);W79 9 #
5*=w9; ; 9UNA	 L
 "	%);R	 
 #
5*=w	  "z%);V	 
 $E+?	 
 fU$5wGI IO fUIu)+ +G  > > > > >r4   r   c                   0    e Zd Z ee           d Zd ZdS )CsetPropertyRendererc                     |dv r|dk    rdpdS )N)ParentsChildrenBranchesgit-committer
git-authorrevpropr  r   rL   )r/   namer   s      r1   match_propertyz#CsetPropertyRenderer.match_property  s7       1
  $y08
 78=
 <=	=r4   c                     d fd	|dk    r+||         }t          t          dfd|D                        S |dv r ||         }|dk    rt          |          dk    rډj        j        j        j        j        t          dfd|D                       }t          t          |          t          j                    t          j        t          t          d	                    d
          t          j                    t          j        t          t          d                    d
                    S t          t          dt          |                     S |dv rf||         \  }}	t           j                                      j        |          dt!          |	j        j                  d}
t%          |
          S t'          t          d                    )Nc           	         	 j         j        j        }t          j                                      |          }|                    |           }||                    |           }t          j	        |dt          |j                  j                            | |j                            S # t          $ r/}t          j	        | dt!          |          d          cY d }~S d }~ww xY w)Nr   r   r   r   r   )r   r   ri   r   rc   r   rd   r2   r   r   r   r   r   r   r   r   r   )r   r   r   r6   rG   r   r   r/   s         r1   sha_linkz6CsetPropertyRenderer.render_property.<locals>.sha_link  s   B"+25)$(33BB8LL**3//=!--c22EuU;#/#=#="),"8"8en"M"MO O O O  B B BuS)<#-a==jB B B B B B B B BBs   B+B/ /
C(9$C#C(#C(r0  z, c              3   6   K   | ]\  }} ||          V  d S r+   rL   )rM   r   r0   r8  s      r1   rS   z7CsetPropertyRenderer.render_property.<locals>.<genexpr>  sO       +G +G/9uc ,48C+?+? +G +G +G +G +G +Gr4   )r.  r/  r.  rJ   c              3      K   | ]]} |          d t          j        t          d          t          d          j                            |                    dfV  ^dS ) (diffzIDiff against this parent (show the changes merged from the other parents))old)r   r   )N)r   r   r   r   r   )rM   r0   r   current_shar   r8  s     r1   rS   z7CsetPropertyRenderer.render_property.<locals>.<genexpr>  s       ,& ,&  .6Xc]]eAfII"# %M #N #N!(!7!7X<? "8 "A "AB B B
 - ,& ,& ,& ,& ,& ,&r4   zmNote: this is a <strong>merge</strong> changeset, the changes displayed below correspond to the merge itself.hint)r   zWUse the <code>(diff)</code> links above to see all the changes relative to each parent.)r1  r2  r;  )tzinfor>  Internal errorr+   )r   r   rZ   r   ri   r   rY   brspanr   r   mapr%   rc   format_authorreqr   r   strr   )r/   r4  r   r   propsbranchesr`   parent_linksuser_time__strr?  r   r8  s   `  `       @@@r1   render_propertyz$CsetPropertyRenderer.render_property  si   	B 	B 	B 	B 	B 	B 	B" :T{H D +G +G +G +G=E+G +G +G H H I I ,,,;Dy  SYY]]%.1"+25*4,& ,& ,& ,& ,& ,& ,& !%,& ,& ,&	 ' 	 ' 4--6888F1 .7 ,8 ,8 %9 %9
 ,23 3 3 6888F1 .7 ,8 ,8 %9 %9 ,2	3 3 34 4 4  D#h*=*=>>??444 ;LE5tx  ..w{EBBBBgkn=====?D t99*++,,,r4   N)r   r   r   r   r$   r5  rO  rL   r4   r1   r,  r,    sH        J !!!= = =F- F- F- F- F-r4   r,  c                      e Zd ZdZddddd ddfdZd Zed	             Z ed
          d             Z	d Z
d%dZd Zd Zd Zd Zd Zd&dZd%dZd Zd Zd Zd Zd Z	 d'dZd(dZd(dZd  Zd! Zd" Zd&d#Zd%d$ZdS ))r&  zGit repositoryFr;   r  r	  c                     d S r+   rL   r   s    r1   rH   zGitRepository.<lambda>  s    t r4   c           	      n   || _         || _        || _        || _        || _        t          dt          |d                    | _        |	| _        || _	        |
| _
        	 t          j        ||| ||          }|                                | _        nl# t          j        $ rZ}|                    t#          |                     t%          t'          d|                    d          pd                    d }~ww xY wt+          j        | d|z   | j        |           t/          | j                  | _        d S )	Nr  r  )r   r  z3"%(name)s" is not readable or not a Git repository.r4  z	(default))r4  zgit:)rc   loggergitrepor*  r  maxminr  r$  r  r  r'   StorageFactorygetInstance_gitr   r   r   r   r   r   r   r   rH  ri   _cached_git_id)r/   rc   r8   r*  r   r  r   r  r  r$  r  r  factoryr   s                 r1   r   zGitRepository.__init__  sN     03|R#8#899&"4 0		;*4:J6J3:;JL L LG  ++--DII~ 	; 	; 	;II*1--...#Gzz&))8[: : :; ; ;	; 	D&4-cBBB!$'lls   3B C: AC55C:c                     d | _         d S r+   )rY  rA   s    r1   closezGitRepository.close  s    			r4   c                 ,    | j         r| j        S | j        S r+   )r  _cached_gitrY  rA   s    r1   r;   zGitRepository.git  s      	##9r4   rZ  c                 B    | j                                          | j         S r+   )rY  invalidate_rev_cacherA   s    r1   r_  zGitRepository._cached_git%  s    	&&(((yr4   c                 4    | j                                         S r+   )r;   r   rA   s    r1   r:   zGitRepository.get_youngest_rev*  s    x$$&&&r4   Nc                 :    t          t          d                    )Nz(Unsupported "Show only adds and deletes")r   r   )r/   r8   r0   limits       r1   get_path_historyzGitRepository.get_path_history-  s    FGGHHHr4   c                 4    | j                                         S r+   )r;   
oldest_revrA   s    r1   get_oldest_revzGitRepository.get_oldest_rev0  s    x""$$$r4   c                 4    |r|                     d          pdS )N/)stripr7   s     r1   normalize_pathzGitRepository.normalize_path3  s    '

3.3.r4   c                     |s|                                  S | j                            |          }|t          |          |S r+   )r:   r;   r<   r   r=   s      r1   r?   zGitRepository.normalize_rev6  sI     	+((***($$S))?!#&&&r4   c                 ,    |                      |          S r+   r,   r.   s     r1   r2   zGitRepository.display_rev>  r3   r4   c                 j    | j                             |                     |          | j                  S )N)min_len)r;   shortrevr?   r  r.   s     r1   r-   zGitRepository.short_revA  s7    x  !3!3C!8!8)-): ! < < 	<r4   c                 .    |                      ||          S r+   )	_get_noder/   r8   r0   s      r1   get_nodezGitRepository.get_nodeE  s    ~~dC(((r4   c                 4    t          | ||| j        ||          S r+   )GitNoder   )r/   r8   r0   ls_tree_info	historians        r1   rs  zGitRepository._get_nodeH  s    tT3,	JJJr4   c              #      K   | j                                         D ]\  }}d|d|fV  | j                                         D ]
}d|d|fV  d S )NrJ  rj  tags)r;   r   r   )r/   r0   bnamebshats        r1   get_quickjump_entriesz#GitRepository.get_quickjump_entriesK  s~      80022 	/ 	/KE4eS$.....""$$ 	$ 	$A!S!#####	$ 	$r4   c                 6    | j                             d          S )Nurl)r*  r   rt  s      r1   get_path_urlzGitRepository.get_path_urlQ  s    {u%%%r4   c              #      K   | j                             t          |          t          |                    D ]}|                     |          V  d S r+   )r;   history_timeranger   rd   )r/   r]   r^   r0   s       r1   rX   zGitRepository.get_changesetsT  se      8--l5.A.A.:4.@.@B B 	* 	*C$$S))))))	* 	*r4   c                 "    t          | |          S )zGitChangeset factory method)GitChangesetr.   s     r1   rd   zGitRepository.get_changesetY  s    D#&&&r4   c                 ,    |                      |          S r+   )r?   r.   s     r1   get_changeset_uidzGitRepository.get_changeset_uid]  s    !!#&&&r4   r   c              #   &   K                         |          }                      |          }||k    rt          t          d                                         |          }                     |          }||k    rd S  fd}|                    d           ||          } ||          } j                            |          5 }	 j                            |          5 }
 j                            ||          D ]}|\  }}}}}}}t          |          st          |          rt          j
        nt          j        }t          j        |         }|t          j        k    r,                     |||                    |d          |	          nd }|t          j        k    r,                     |||                    |d          |
          nd }||||fV  	 d d d            n# 1 swxY w Y   d d d            d S # 1 swxY w Y   d S )NzNot supported in git_fsc                 V    j                             | d          }d |D             S )NT)	recursivec                      i | ]}|d          |S )r  rL   )rM   results     r1   rN   z?GitRepository.get_changes.<locals>.get_tree.<locals>.<dictcomp>o  s    <<<&F1Iv<<<r4   )r;   ls_tree)r0   resultsr/   target_paths     r1   get_treez+GitRepository.get_changes.<locals>.get_treem  s3    h&&sK4&HHG<<G<<<<r4   rj  F)rl  r   r   r?   rk  r;   get_historian	diff_treer   r   	DIRECTORYFILEr  
action_mapr   ADDrs  r   DELETE)r/   old_pathold_revnew_pathnew_revignore_ancestryr  old_treenew_treeold_historiannew_historianchgmode1mode2obj1obj2actionr8   path2kindchangeold_nodenew_noder  s   `                      @r1   get_changeszGitRepository.get_changes`  s      &&x00&&x00xA788999$$W--$$W--gF	= 	= 	= 	= 	= 	= nnS))8G$$8G$$X##G[99 	;]''== ;8--gwLL ; ;CDGAE5$fdE%enn*07*4>> $	  *4V<F #)IM"9"9  $~~dG.6ll4.G.G.; =  =  = @D  #)I,<"<"<  $~~dG.6ll4.G.G.; =  =  = CG 
 #HdF:::::!;; ; ; ; ; ; ; ; ; ; ; ; ; ; ;	; 	; 	; 	; 	; 	; 	; 	; 	; 	; 	; 	; 	; 	; 	; 	; 	; 	;s7   H+C6G."H.G2	2H5G2	6HH
H
rf   c                 6    | j                             |          S r+   )r;   hist_next_revisionr/   r0   r8   s      r1   next_revzGitRepository.next_rev      x**3///r4   c                 6    | j                             |          S r+   )r;   hist_prev_revisionr  s      r1   previous_revzGitRepository.previous_rev  r  r4   c                 6    | j                             |          S r+   )r;   parentsr.   s     r1   r   zGitRepository.parent_revs  s    x$$$r4   c                 6    | j                             |          S r+   )r;   childrenr.   s     r1   rC   zGitRepository.child_revs  s    x  %%%r4   c                     | j                             |                     |          |                     |                    S r+   )r;   rev_is_anchestor_ofr?   )r/   rev1rev2s      r1   rev_older_thanzGitRepository.rev_older_than  s@    x++D,>,>t,D,D,0,>,>t,D,DF F 	Fr4   c                 .    |                                   d S r+   )r   )r/   r   s     r1   clearzGitRepository.clear  s    		r4   c                    |r&t          | j                                                  }| j        r| `| j                                        sd S |r9t          | j                                                  |z
  }|D ]} ||           d S d S r+   )rp   r;   r   r  r_  r   )r/   rev_callbackr   r`   r0   s        r1   r   zGitRepository.sync  s     	,tx((**++D  	! x}} 	4 	"tx((**++d2D " "S!!!!	" 	"" "r4   NNr+   )r   )rf   ) r   r   r   r   r   r]  propertyr;   r   r_  r:   re  rh  rl  r?   r2   r-   ru  rs  r  r  rX   rd   r  r  r  r  r   rC   r  r  r   rL   r4   r1   r&  r&    s        #(!(+^"'$) +  +  +  +D     X V  ' ' 'I I I I% % %/ / /  # # #< < <) ) ) )K K K K$ $ $& & &* * *
' ' '' ' ' %&'; '; '; ';R0 0 0 00 0 0 0% % %& & &F F F   " " " " " "r4   r&  c                   R    e Zd Z	 	 ddZd Zd Zd Zd Zd Zd Z	d	 Z
dd
Zd ZdS )rw  Nc                 n   || _         || _        d | _        d | _        d | _        d | _        |r#|                    t          |                    }n|j        }|}t          j
        }|                    d          }	|	r|st          ||          |%|j                            ||	          }|r|d         }|st          ||          |\  | _        | _        | _        | _        }
|j                            ||	|          }| j        dk    rt          j
        }nw| j        dk    rt          j        }n_t#          | j                  rt          j
        }n>| j                             d|           t'          t)          d| j                            || _        || _        t          j        | ||||           d S )Nrj  r   treeblobzGot unexpected object %rz6Internal error (got unexpected object kind '%(kind)s'))r  )r   r6   fs_shafs_permfs_typefs_sizer?   r   r   r   r  rk  r   r;   r  last_changer  r   warningr   r   created_pathcreated_revr   )r/   r6   r8   r0   r   rx  ry  r  r  pfnames              r1   r   zGitNode.__init__  s   
 	%%%joo66CC$C~JJsOO 	J , s+++#$y00a88 3#/?L , s+++ IDL$,T\5  )//Q	BBK|v%%~''yt|,, J ~  !;\JJJ #5;?<!I !I !I J J J !&dE4d33333r4   c                     | j                             d          }| j        r|sJ |S | j        r|o|dz   S t	          t          d                    )z return path as expected by PyGITrj  rB  )r8   rk  isfileisdirr   r   )r/   r  s     r1   
__git_pathzGitNode.__git_path  s\    IOOC  ; 	HHHH: 	#?!c'"*++,,,r4   c                 \    | j         sd S | j        j                            | j                  S r+   )r  r6   r;   get_filer  rA   s    r1   get_contentzGitNode.get_content  s+    { 	4z~&&t{333r4   c                 l    | j         i S dd| j         z  i}t          | j                   r
| j        |d<   |S )Nr   z%06ocommit)r  r   r  )r/   rI  s     r1   get_propertieszGitNode.get_properties  sB    <I$,./&& 	*"kE(Or4   c                     | j         sd S d | j        j                            | j        |                                           D             S )Nc                     g | ]\  }}|S rL   rL   )rM   r0   linenos      r1   rU   z+GitNode.get_annotations.<locals>.<listcomp>   s.     B B BV B B Br4   )r  r6   r;   blamer0   _GitNode__git_pathrA   s    r1   get_annotationszGitNode.get_annotations  sX    { 	FB B
$$TXdoo.?.?@@B B B 	Br4   c           
   #     K   | j         sd S | j        sd S t          | j                  rd S | j        j                            | j         | j                            d                    5 }| j        j        	                    | j         | 
                                          D ]-}t          | j        |d         | j         | j        ||          V  .	 d d d            d S # 1 swxY w Y   d S )Nrj  )r0   r  r   r  r6   r;   r  r8   rk  r  r  rw  r   )r/   ry  ents      r1   get_entrieszGitNode.get_entries  s:     x 	Fz 	F&& 	FZ^))$(*.)//#*>*>@ @ 	)CLz~--dh8I8IJJ ) )dj#b'48TXs') ) ) ) ) ))	) 	) 	) 	) 	) 	) 	) 	) 	) 	) 	) 	) 	) 	) 	) 	) 	) 	)s   (A&CC #C c                     | j         rd S dS )Nrf   )r  rA   s    r1   get_content_typezGitNode.get_content_type  s    : 	4rr4   c                     | j         sd S | j        )| j        j                            | j                  | _        | j        S r+   )r  r  r6   r;   get_obj_sizer  rA   s    r1   get_content_lengthzGitNode.get_content_length  s<    { 	4<:>66t{CCDL|r4   c              #      K   | j         sd S t          | j        j                            | j         |                                 |                    D ])\  }}| j        ||st          j        nt          j	        fV  *d S r+   )
r0   r   r6   r;   historyr  r8   r   EDITr  )r/   rd  is_lastr0   s       r1   get_historyzGitNode.get_history   s      x 	F*4:>+A+A$(040A0A5,J ,J K K 	2 	2LGS9c $19>>#,=2 2 2 2 2	2 	2r4   c                     | j         sd S 	 | j        j                            | j                  \  }}t          |d         d                   \  }}n(#  | j                            d| j                   Y d S xY w|S )N	committerr   z9internal error (could not get timestamp from commit '%s'))r  r6   r;   read_commitr0   r   r   r   )r/   msgrI  r   tss        r1   get_last_modifiedzGitNode.get_last_modified)  s    { 	4	33DH==JC'k(:1(=>>HD""	HNN *+/85 5 544	s   AA "A6r  r+   )r   r   r   r   r  r  r  r  r  r  r  r  r  rL   r4   r1   rw  rw    s        ;?/4 /4 /4 /4b	- 	- 	-4 4 4
  B B B) ) )    2 2 2 2    r4   rw  c                       e Zd ZdZej        ej        ej        ej        ej        ej	        dZ
d Zd Zd Zd Zd Zd Zd	S )
r  zRA Git changeset in the Git repository.

    Corresponds to a Git commit blob.
    )AMTDRCc                 P   |t          |          	 |j                            |          \  }}n"# t          j        $ r t          |          w xY w|| _        d|vsJ t          |j                            |                    }|r||d<   |                                 \  }}d x}x}	x}
}|rt          |          \  }}
|rt          |          \  }	}|j
        r|
p|}n|p|
}|j        r|p|	}n|	p|}|                    |          p|}t          j        | |||||           d S )Nr  )r0   r   authorrF   )r   r;   r  r'   GitErrorSharI  rY   r  _get_committer_and_authorr   r  r  r$  r   r   )r/   r6   r   r  rI  	_childrenr  r  c_usera_userc_timea_timer   r   s                 r1   r   zGitChangeset.__init__G  s   ;!#&&&	'..s33JC  	' 	' 	'!#&&&	' 
&&&&++C0011	 	* )E* ::<<	6,0000&6 	9-i88NFF 	6-f55NFF# 	$#VDD#VD! 	$#VDD#VD   &&.$4CT $	& 	& 	& 	& 	& 	&s	   1 Ac                     d x}}d| j         v r| j         d         d         }d| j         v r| j         d         d         }||fS )Nr  r   r  )rI  )r/   r  r  s      r1   r  z&GitChangeset._get_committer_and_authoro  sS    !!	F$*$$
;/2Itz!!Z)!,F&  r4   c                 d   i }d| j         v r| j         d         |d<   d| j         v r| j         d         |d<   |                                 \  }}||k    r$t          |          |d<   t          |          |d<   t          | j        j                            | j        d                    }|r||d	<   |S )
Nr   r.  r  r/  r1  r2  Tr   r0  )rI  r  r   rY   r6   r;   r   r0   )r/   
propertiesr  r  rJ  s        r1   r  zGitChangeset.get_propertiesw  s    
tz!!$(Jx$8Jy!##%)Z
%;Jz" ::<<	6Y*:9*E*EJ''7'?'?J|$
::48CG ; I I J J 	.%-Jz"r4   c              #     K   | j                             d          }|r|d         nd }| j        j                            || j                  }|D ]w\  }}}}}}}	|	p|}
||}}t          |          st          |          rt          j        nt          j	        }t          j        |         }|t          j        k    rd x}}|
||||fV  xd S )Nr   r   )rI  r   r6   r;   r  r0   r   r   r  r  r  r  r   r  )r/   r   changesr  r  r  r  r  path1r  r8   p_pathp_revr  s                 r1   r  zGitChangeset.get_changes  s      ))$.$*.,,VTX>>>E 	4 	4:E5$feU>ED!6EF enn(/4>>9  ",V4F&&!%%ffe33333	4 	4r4   c                 l    | j         fd| j        j                            d          D             S )Nc                 &    g | ]\  }}||k    fS rL   rL   r   s      r1   rU   z-GitChangeset.get_branches.<locals>.<listcomp>  s;     N N NAq AI N N Nr4   Tr   r   r   s    @r1   r   zGitChangeset.get_branches  s]    xN N N N JN>>tGK ? M MN N N 	Nr4   c                 J    | j         j                            | j                  S r+   r   rA   s    r1   r   zGitChangeset.get_tags  s    z~&&tx000r4   N)r   r   r   r   r   r  r  r  MOVECOPYr  r   r  r  r  r   r   rL   r4   r1   r  r  8  s          ]^^^^
 
J&& && &&P! ! !  *4 4 4*N N N1 1 1 1 1r4   r  c                       e Zd Z ee            eddd          Z eddd          Z eddd          Z	 e
dd	d
d          Zd ZdS ) GitwebProjectsRepositoryProviderzgitweb-repositoriesprojects_listz(Path to a gitweb-formatted projects.list)docprojects_basez%Path to the base of your git projectsprojects_urlzKTemplate for project URLs. `%s` will be replaced with the repo
        namesync_per_requestrf   z@Repositories to sync on every request
        (not recommended).c              #   f  K   | j         sdS t          j                            | j                   s"| j                            d| j                    dS t          | j         dd          5 }|D ]*}|                                                                }|r|d         }|	                    d          }t          j        
                    | j        |          || j        v dd	}t          j        
                    |d
         d          }t          j                            |          rSt          |dd          5 }|                                                                |d<   ddd           n# 1 swxY w Y   | j        r| j        |z  |d<   ||fV  ,	 ddd           dS # 1 swxY w Y   dS )z:Retrieve repositories specified in a `projects_list` file.Nz2The [git] projects_list file was not found at '%s'rQ   r  )encodingr   z.gitr;   )r)  r  r(  r)  descriptionr  )r  osr8   existsr   r  openrk  r  rstriprs   r  r  readr  )	r/   fplineentriesr4  r   r   description_pathfds	            r1   get_repositoriesz1GitwebProjectsRepositoryProvider.get_repositories  sS     ! 	Fw~~d011 	H $%)%79 9 9F$$cG<<< 	) ) )**,,,,.. )"1:D#{{622H!w||D,>EE,48M,M % D T%[-@@ %w~~&677 D!"2C+24 4 4 D7924''))//2C2CD/D D D D D D D D D D D D D D D ( C&*&7(&BU"D.(((%)	) 	) 	) 	) 	) 	) 	) 	) 	) 	) 	) 	) 	) 	) 	) 	) 	) 	)s7   )CF&;*E1%F&1E55F&8E59F&&F*-F*N)r   r   r   r   r    r	   r  r  r
   r  r   r  r(  rL   r4   r1   r  r    s        J"###J4o68 8 8M J4o35 5 5M 6/	  L "z"7B %  ) ) ) ) )r4   r  )Br   rV   r  trac.apir   
trac.cacher   trac.configr   r   r   r	   r
   	trac.corer   r   r   trac.util.datefmtr   r   r   trac.util.htmlr   r   trac.util.textr   r   r   trac.util.translationr   trac.versioncontrol.apir   r   r   r   r   r   r   r   r    trac.versioncontrol.cacher!   r"   r#   trac.versioncontrol.web_uir$   trac.web.chromer%   	trac.wikir&   tracopt.versioncontrol.gitr'   r)   rb   r   r   r   r   r   r   r   r,  r&  rw  r  r  rL   r4   r1   <module>r7     s             				 ( ( ( ( ( (       M M M M M M M M M M M M M M 6 6 6 6 6 6 6 6 6 6 H H H H H H H H H H & & & & & & & & I I I I I I I I I I # # # # # #K K K K K K K K K K K K K K K K K K K K K K6 6 6 6 6 6 6 6 6 6 8 8 8 8 8 8 " " " " " " ) ) ) ) ) ) , , , , , ,E E E E E* E E EP
7 
7 
7 
7 
7 
7 
7 
7
 
 
	 	 	   < < <0 0 0m m m m m9 m m m`T- T- T- T- T-9 T- T- T-nx" x" x" x" x"J x" x" x"vD D D D Dd D D DNq1 q1 q1 q1 q19 q1 q1 q1h/) /) /) /) /)y /) /) /) /) /)r4   