HEX
Server: Apache
System: Linux pdx1-shared-a1-38 6.6.104-grsec-jammy+ #3 SMP Tue Sep 16 00:28:11 UTC 2025 x86_64
User: mmickelson (3396398)
PHP: 8.1.31
Disabled: NONE
Upload Files
File: //usr/lib/python3/dist-packages/trac/versioncontrol/web_ui/__pycache__/browser.cpython-310.pyc
o

�k�`��@s�ddlZddlmZmZddlmZddlmZmZmZddl	Tddl
mZmZm
Z
ddlmZmZddlmZmZdd	lmZmZdd
lmZmZmZmZddlmZmZmZddl m!Z!m"Z"dd
l#m$Z$m%Z%ddl&m'Z'm(Z(ddl)Tddl*m+Z+m,Z,ddl-m.Z.m/Z/m0Z0m1Z1m2Z2m3Z3m4Z4m5Z5ddl6m7Z7m8Z8m9Z9ddl:m;Z;m<Z<dZ=Gdd�de>�Z?Gdd�de@�ZAGdd�deB�ZCGdd�deB�ZDGdd�de@�ZEGdd�deB�ZFGd d!�d!e@�ZGdS)"�N)�datetime�	timedelta��fnmatchcase)�
BoolOption�
ListOption�Option)�*)�IHTMLPreviewAnnotator�Mimeview�	is_binary)�IPermissionRequestor�PermissionError)�Resource�ResourceNotFound)�as_bool�embedded_numbers)�datetime_now�	http_date�to_datetime�utc)�Markup�escape�tag)�exception_to_unicode�shorten_line)�_�	cleandoc_)�NoSuchChangeset�RepositoryManager)�IRequestHandler�RequestDone)�Chrome�INavigationContributor�add_ctxtnav�add_link�
add_script�add_stylesheet�prevnext_nav�web_context)�IWikiMacroProvider�IWikiSyntaxProvider�
parse_args)�format_to_html�format_to_onelineric@s eZdZdZdd�Zdd�ZdS)�IPropertyRendererz>Render node properties in TracBrowser and TracChangeset views.cC�dS)aIndicate whether this renderer can treat the given property

        `mode` is the current rendering context, which can be:
         - 'browser' rendered in the browser view
         - 'changeset' rendered in the changeset view as a node property
         - 'revprop' rendered in the changeset view as a revision property

        Other identifiers might be used by plugins, so it's advised to simply
        ignore unknown modes.

        Returns a quality number, ranging from 0 (unsupported) to 9
        (''perfect'' match).
        N�)�name�moder1r1�D/usr/lib/python3/dist-packages/trac/versioncontrol/web_ui/browser.py�match_property0�z IPropertyRenderer.match_propertycCr0)a�Render the given property.

        `name` is the property name as given to `match()`,
        `mode` is the same as for `match_property`,
        `context` is the context for the node being render
        (useful when the rendering depends on the node kind) and
        `props` is the collection of the corresponding properties
        (i.e. the `node.get_properties()`).

        The rendered result can be one of the following:
         - `None`: the property will be skipped
         - a `str` value: the property will be displayed as text
         - a `RenderedProperty` instance: the property will only be displayed
           using the instance's `content` attribute, and the other attributes
           will also be used in some display contexts (like `revprop`)
         - `Markup` or `Fragment`: the property will be displayed
           normally, using that content as a block-level markup
        Nr1)r2r3�context�propsr1r1r4�render_property?r6z!IPropertyRenderer.render_propertyN)�__name__�
__module__�__qualname__�__doc__r5r9r1r1r1r4r/-sr/c@seZdZ		ddd�ZdS)�RenderedPropertyNcCs||_||_||_||_dS�N)r2�name_attributes�content�content_attributes)�selfr2r@rArBr1r1r4�__init__Us
zRenderedProperty.__init__)NNNN)r:r;r<rDr1r1r1r4r>Ts�r>c@s(eZdZdZee�dd�Zdd�ZdS)�DefaultPropertyRendererz*Default version control property renderer.cCr0)N�r1�rCr2r3r1r1r4r5b�z&DefaultPropertyRenderer.match_propertycCs6||}|rd|vrtd�dd�|�d�D���}|S)N�
�css�|]	}dt|�VqdS)z<br />%sN)r��.0�vr1r1r4�	<genexpr>is��z:DefaultPropertyRenderer.render_property.<locals>.<genexpr>)r�join�split)rCr2r3r7r8�valuer1r1r4r9es
�z'DefaultPropertyRenderer.render_propertyN)r:r;r<r=�
implementsr/r5r9r1r1r1r4rE]s
rEc@sHeZdZdZee�eddddd�Zedddd	d�Zd
d�Z	dd
�Z
dS)�WikiPropertyRendererzWiki text property renderer.�browser�wiki_propertiesztrac:descriptionzxComma-separated list of version control properties to render
        as wiki content in the repository browser.
        ��doc�oneliner_propertiesztrac:summaryz�Comma-separated list of version control properties to render
        as oneliner wiki content in the repository browser.
        cCs||jvs
||jvrdSdS)N�r)rUrXrGr1r1r4r5s


��z#WikiPropertyRenderer.match_propertycCs.||jvrt|j|||�St|j|||�Sr?)rUr-�envr.)rCr2r3r7r8r1r1r4r9�s
z$WikiPropertyRenderer.render_propertyN)r:r;r<r=rRr/rrUrXr5r9r1r1r1r4rSns��rSc	@sReZdZeddddddde�Zdd�Zdd�Zdd�Zd	d
�Z	dd�Z
d
d�ZdS)�	TimeRangerFrcCs||_|_d|_dSr?)�oldest�newest�_total)rC�baser1r1r4rD�s
zTimeRange.__init__cCs||}|jdd|jS)N�i)�days�seconds)rC�dt1�dt2�deltar1r1r4�seconds_between�szTimeRange.seconds_betweencCs|�|tj�Sr?)rfr[�min)rC�dtr1r1r4�
to_seconds��zTimeRange.to_secondscCstjtt|d��S)Ni�Q)r[rgr�divmod)rC�secsr1r1r4�from_seconds�szTimeRange.from_secondscCsB|jdurt|�|j|j��|_d}|jr|�||j�|j}|S�Ng�?)r^�floatrfr]r\)rCr�ager1r1r4�relative�s
zTimeRange.relativecCs&d|_t|j|�|_t|j|�|_dSr?)r^rgr\�maxr])rCrr1r1r4�insert�szTimeRange.insertN)r:r;r<rrrgrDrfrirmrqrsr1r1r1r4r[�sr[c@s�eZdZeeeeeee	�e
e�Ze
jZeddddd�Zeddddd�Zd	Zedd
ee�dd�ZdZedd
ee�dd�Zeddddd�Zeddddd�Zedddd�Zeddddd�Zdd�Zdd�Zdd�Z d d!�Z!d"d#�Z"d$d%�Z#d&d'�Z$d(d)�Z%d*d+�Z&dPd-d.�Z'dPd/d0�Z(d1d2�Z)d3d4�Z*d5d6�Z+d7d8�Z,d9d:�Z-d;d<�Z.d=d>�Z/d?d@�Z0e1�2dA�Z3dBdC�Z4dDdE�Z5dFdG�Z6dHdI�Z7dJdK�Z8dLdM�Z9dNdO�Z:d,S)Q�
BrowserModulerT�downloadable_pathsz/trunk, /branches/*, /tags/*aDList of repository paths that can be downloaded.

        Leave this option empty if you want to disable all downloads, otherwise
        set it to a comma-separated list of authorized paths (those paths are
        glob patterns, i.e. "*" can be used as a wild card). In a
        multi-repository environment, the path must be qualified with the
        repository name if the path does not point to the default repository
        (e.g. /reponame/trunk). Note that a simple prefix matching is
        performed on the paths, so aliases won't get automatically resolved.
        rV�color_scaleTz�Enable colorization of the ''age'' column.

        This uses the same color scale as the source code annotation:
        blue is older, red is newer.
        )��rx�newest_colorz�(r,g,b) color triple to use for the color corresponding
        to the newest color, for the color scale used in ''blame'' or
        the browser ''age'' column if `color_scale` is enabled.
        )rxrxrw�oldest_colorz�(r,g,b) color triple to use for the color corresponding
        to the oldest color, for the color scale used in ''blame'' or
        the browser ''age'' column if `color_scale` is enabled.
        �intermediate_pointrJz�If set to a value between 0 and 1 (exclusive), this will be the
        point chosen to set the `intermediate_color` for interpolating
        the color value.
        �intermediate_colora,(r,g,b) color triple to use for the color corresponding
        to the intermediate color, if two linear interpolations are used
        for the color scale (see `intermediate_point`).
        If not set, the intermediate color between `oldest_color` and
        `newest_color` will be used.
        �render_unsafe_content�falsea�Whether raw files should be rendered in the browser, or only made
        downloadable.

        Pretty much any file may be interpreted as HTML by the browser,
        which allows a malicious user to create a file containing cross-site
        scripting attacks.

        For open repositories where anyone can check-in a file, it is
        recommended to leave this option disabled.�hide_propertiesz	svk:mergezhComma-separated list of version control properties to hide from
        the repository browser.
        cs�dd��dd�}||j|j��||j|j��zt|j��Wnty(d�Ynw�rK||jd���s?tdd�t	���D��������fdd	�}|S���fd
d	�}|S)z?Returns a converter for values from [0.0, 1.0] to a RGB triple.cst�fdd�t||�D��S)Ncs$g|]\}}t|||���qSr1��int�rL�a�b�rQr1r4�
<listcomp>s$zKBrowserModule.get_custom_colorizer.<locals>.interpolate.<locals>.<listcomp>)�tuple�zip)�old�newrQr1r�r4�interpolate�sz7BrowserModule.get_custom_colorizer.<locals>.interpolatecSsTztdd�t�d|�ddd�D��}t|�dkr|WS|WSty)|YSw)NcSsg|]}t|��qSr1r�rKr1r1r4r�szKBrowserModule.get_custom_colorizer.<locals>.parse_color.<locals>.<listcomp>z(\d+)rF��)r��rerP�len�
ValueError)�rgb�default�tr1r1r4�parse_colors$�z7BrowserModule.get_custom_colorizer.<locals>.parse_colorNcSsg|]
\}}||d�qS)r�r1r�r1r1r4r�sz6BrowserModule.get_custom_colorizer.<locals>.<listcomp>cs8|�kr|�}���|�S|�d�}���|�Srnr1r���intermediater|r�ryrzr1r4�	colorizers
z5BrowserModule.get_custom_colorizer.<locals>.colorizercs���|�Sr?r1r�)r�ryrzr1r4r�s)
ry�NEWEST_COLORrz�OLDEST_COLORror{r�r|r�r�)rCr�r�r1r�r4�get_custom_colorizer�s&��
�z"BrowserModule.get_custom_colorizercCr0)NrTr1)rC�reqr1r1r4�get_active_navigation_item#rHz(BrowserModule.get_active_navigation_itemc#sN�t|j�}t�fdd�|��D��r%ddtjtd��j��d�fVdSdS)Nc3s�|]	}|��j�VqdSr?��is_viewable�perm)rL�repos�r�r1r4rN(s�z5BrowserModule.get_navigation_items.<locals>.<genexpr>�mainnavrTz
Browse Source��href)	rrZ�any�get_real_repositoriesrr�rr�rT)rCr��rmr1r�r4�get_navigation_items&s�
�
��z"BrowserModule.get_navigation_itemscCsddgS)N�BROWSER_VIEW�	FILE_VIEWr1�rCr1r1r4�get_permission_actions/sz$BrowserModule.get_permission_actionscCs�t�d|j�}|r[|��\}}|dkr8|r7d|vr7|�dd�}t|�dkr'dS|d}|d|jd<d	|jd
<n|dkrR|j|jj	||j�
d�|j�
d
�d�d
d�|pUd|jd<d
SdS)Nz/(export|browser|file)(/.*)?$�export�/r�r�FrF�rev�raw�format�file�r�r�T)�	permanent�path)r��match�	path_info�groupsrPr��args�redirectr�rT�get)rCr�r�r3r��	path_eltsr1r1r4�
match_request4s*
�
���zBrowserModule.match_requestc 
Cs|j�d�}|r|d�|j��d�r|�|�|j�dd�}|j�dd�}|��dvr/d}|j�d�}|j�dd	���}d
|jv}t|j�}|�	�}	|�
|�\}
}}|
oZ|dk}|rp|rpt|	d�d��sn|�|j
�spd}|s||
r|ttd|
d
���|
r�|
|jkr�|j}
|�|j�|jp�d|�|
r�d|
nd�|r�|jnd}
t|�}d}d}dd�}|r�z|r�|�|�}|p�|j}t||||�}Wnty�}zt|td��|�d}~ww|r�z|�|j�}Wn	ty�Ynw|�|jj|j||d��}|j}t|j|
||||�}d}}}|�r|�||	||�}|�r[|�|j
��s1t|j �r*dnd|j|j��|j �rN|dv�rC|�!|||||�|�"||||||�}n
|j#�r[|�$|||||�}|�s}|�rf|d�s}|j
�%d�|�ruttd���ttd|d���d}}|�r�|j&�s�|�'d||�(��}t)|�*|��}id|�d|
�d|�d|	�|
�p�d��d|�d|�o�|j�d|�d |�d!|�d"|�o�|j+�d#|�o�|j,�d$|�d%|�d|�d
|�r�d&nd�d'|�d(|�|||j-d!�.d)�d*��}|j&�r�d+|fS|�s�|�rt/|d,�t/|d-�|�r|j#�rt|j0|j,|j+d.�}|�r2|jj|
|j+|d/�}t1|d0|td1||�d2��|du�rCt1|d3|j�|
|j+��|j2|j,|j+d.�}|�rf|jj|
|j+|d/�}t1|d4|td1||�d2��t3|td5�td6�td7��n&|dk�r�t1|d3|d8d9td:��t4|t5j6td;�|j�7|j,|
|j+�d<��|j#�r�|d=d>}|�r�t4|td?�td@�|jj|
|j+|d/�dA�|dBk�r�t4|tdC�tdD�|jj|
|j+|dBdE�dA�t4|tdF�|jj8|
||d/�d<�|�9||�}|�r|�dG��r�|j:dH|}t4|tdI�|d<�t;|dJ�dK|fS)LN�preselectedr�r�r�rJ)rJ�headr��orderr2�desc�hiddenzRepository '%(repo)s' not found��repo�?cSs|Sr?r1�r�r1r1r4�<lambda>mr6z/BrowserModule.process_request.<locals>.<lambda>zInvalid changeset number)�versionr�r�)r��repositorieszNo viewable repositorieszNo node %(path)s�r�rTr7�reponamer��repoinfo�	stickyrev�display_rev�	changeset�created_path�created_rev�
properties�
path_linksrFr��dir�wiki_format_messages)r��quickjump_entriesr�zdir_entries.htmlzcommon/js/expand_dir.jszcommon/js/keyboard_nav.js)r�r�r��prevzRevision %(num)s)�num�up�nextzPrevious Revisionz
Next RevisionzLatest Revision���r�zParent directoryzLast Changer�r��annotate�NormalzView file without annotations��titler��blame�BlamezQAnnotate each line with the last changed revision (this can be time consuming...))r�r�zRevision Logz//�:zRepository URL�common/css/browser.csszbrowser.html)<r�r��
startswithr�rTr��lowerrrZ�get_all_repositories�get_repository_by_pathrr�r�rrr��query_stringr)�
normalize_rev�youngest_rev�get_existing_noder�
get_changesetr��child�resource�realmr��get_path_links�_render_repository_indexr�isdir�_render_zip�_render_dir�isfile�_render_file�require�is_xhr�render_properties�get_properties�list�get_quickjump_entriesr�r��config�getboolr&�previous_revr%�next_revr(r$rr�r��log�get_path_url�schemer') rCr��preselr�r�r�r�r�r��all_repositoriesr�r��
show_index�qsr7�noder�r��
rev_or_latest�er��	repo_data�dir_data�	file_data�quickjump_data�properties_data�data�prev_revr�rr��path_urlr1r1r4�process_requestGs�



���

������
�

��������������	�	�
�
�
�

���
�����
���
��

��
�
zBrowserModule.process_requestcCs�d}}|jr|��}t|j�}g}|��D]�\}	}
|	r#t|
�d��r$qz|�|	�}WntyG}z|	|
ddt	|�df}
WYd}~nOd}~ww|r�|�
|j�sQqz|�|j
�}Wntydd}Ynw|jrx|rx|srt|j�}n|�|j�|�|j|dd�}|	|
||d|f}
n|	|
ddddf}
|
ddur�td|	��|jd�}d|�|�vr�q|�|
�q|dkr�dd	�}n
|d
kr�dd	�}ndd	�}t|||d
�}|||d�S)Nr�u–rY�
repositoryr�r��datecSs.|\}}}}}}|r
|jntd�t|���fS�Nr)rrrr��r�r�r�r��youngest�errr�r1r1r4�
repo_order"�
�z:BrowserModule._render_repository_index.<locals>.repo_order�authorcSs.|\}}}}}}|r|j��ndt|���fS)NrJ)rr�rrr1r1r4r'rcSs|\}}}}}}t|���Sr?)rr�rr1r1r4r,s��key�reverse)r��	timerange�colorize_age)rvr�rrZ�itemsrr��get_repository�	TracErrorrr�r�r�r�rr[rrs�_get_download_hrefr�rr�r��append�sorted)rCr7rr�r�r �custom_colorizerr�r�r�r�r�r�entryr�raw_href�rootrr1r1r4r��sb
����

�
�

�z&BrowserModule._render_repository_indexcs���|j��d�|j�G�����fdd�dt����fdd�|��D�}t�dd�|D�|j���r;����j	}nt
�j�}d�}	|jr{t
|���j�d�}
�j�d�}�fd	d�|
|fD�}d
d����D�}
|
|D]}��|�qo|��}	|dkr��fdd
��n|dkr�dd
��n|dkr��fdd
��ndd
��|r�dnd���fdd�}t|||d�}|��j�|��}|r�t�d|td�dd�|��|	�oӈ��j��oڈ��j�d�S)Nr�cs2eZdZd��ZedgZ�����fdd�ZdS)z(BrowserModule._render_dir.<locals>.entryz3name rev created_rev kind isdir path content_lengthr*cs4�jD]}t||t||��q��j�|��|_dSr?)�_copy�setattr�getattrr�r*)rCr�f��
download_hrefr)r�r�r�r1r4rD?s
z1BrowserModule._render_dir.<locals>.entry.__init__N)r:r;r<rPr,�	__slots__rDr1r0r1r4r):s�
r)cs g|]}|��j�r�|��qSr1r�)rL�n)r)r�r1r4r�Ds
�z-BrowserModule._render_dir.<locals>.<listcomp>cSsg|]}|j�qSr1)r�)rL�ir1r1r4r�Fs�range_max_secs�range_min_secscsg|]}|r��t|���qSr1)rmr�)rL�s)r r1r4r�Ts�cSsg|]}|r|j�qSr1)r)rL�cr1r1r4r�Vsrcs�|jjt|j���fSr?)r�rrr2r��r���changesr1r4�
file_order]s
�z-BrowserModule._render_dir.<locals>.file_order�sizecSs|jt|j���fSr?)�content_lengthrr2r�r9r1r1r4r<as�rcs�|jj��t|j���fSr?)r�rr�rr2r9r:r1r4r<es�cSst|j���Sr?)rr2r�r9r1r1r4r<irjrF���cs|jr�nd�|�fSr)r�r9)�	dir_orderr<r1r4�browse_ordernsz/BrowserModule._render_dir.<locals>.browse_orderr�	alternatezZip Archivezapplication/zipr�)�entriesr;r r!r5r6)r�r�r�r%�object�get_entries�get_changesrr�rr�tzrvr[r�r��valuesrsr�r'r�r%rrir]r\)rCr�r�rr�r�r�rCr]r(�max_s�min_s�parent_range�
this_rangerhrA�zip_hrefr1)	r;r@r1r)r<r�r�r�r r4r�5sX
�

�
�

�zBrowserModule._render_dirccsH�|g}|r"|��}|V|jr|�t|��dd�dd��|sdSdS)NcSs|jSr?)r2)�xr1r1r4r��sz+BrowserModule._iter_nodes.<locals>.<lambda>Tr)�popr��extendr'rE)rCr�stackr1r1r4�_iter_nodes�s���zBrowserModule._iter_nodesNc	Csr|�||j�s
ttd���|�|j��d�|j�d�}|r"|j}n|j	p&d}d||j
f}t|||||j�dS)NzPath not available for downloadr�r�rz	%s-%s.zip)
�is_path_downloadabler�r$rr�r�r��rstripr2r�r��
render_ziprR)	rCr�r7r��	root_noder��	root_path�archive_name�filenamer1r1r4r��s
zBrowserModule._render_zipcCsH|�|j��d�t|j�}t|����x}|�t�}|j	}	|	r#|	dkr.|�
|j|�p-|	p-d}	|j�
d�}
|
dvr�|�d�|�d|
dkrFdn|	�|�d	t|j��|durh|�d
d�|�dd�|�d
d�|jsq|�dd�|��|r�|�|�|�t�}|swt�Wd�n1s�wY|�|j�}t|�s�|	dkr�|jj|jp�d|j|dd�}t|d|td�d�|j�|p�|j |jp�d|j�}
t|d|
td�|	�|j!�"d|j||	�t#|d�dg}|j�
d�}|r�|�$d|�t|����}|j%|||�&�|	|j'|
|t(|�d�}Wd�n	1�swY||j)||d�S)Nr�zapplication/octet-streamz
text/plainr�)r��txt��zContent-TyperZz
Last-Modified�Pragmazno-cachez
Cache-Control�ExpireszFri, 01 Jan 1999 00:00:00 GMTzContent-Disposition�
attachmentr�rBz
Plain TextzOriginal Formatz1Rendering preview of node %s@%s with mime-type %szcommon/css/code.css�linenor�r)�annotations�force_source)r�r=�previewr�)*r�r�r�rrZ�content_closing�get_processed_content�read�
CHUNK_SIZE�content_type�get_mimetyper2r�r��
send_response�send_headerr�
last_modifiedr}�end_headers�writer!r�r�rr�rTr�r�r%rr�r�r�debugr'rs�preview_data�get_content_lengthr��boolr>)rCr�r7r�rr��mimeviewrA�chunk�	mime_typer�r��
plain_hrefr*r`r�ror1r1r4r��s�

��
�

���!�����
���zBrowserModule._render_filecCsn|dur|jr|�|pd|jpd|j�S|durdn|j�d�}|�||�r5|j|jp,d||p1|jdd�SdS)z?Return the URL for downloading a file, or a directory as a ZIP.N�HEADrJr�r�r�)r�r�r�r��striprSrTr�)rCr�r�rr�r�r1r1r4r%�s�
��z BrowserModule._get_download_hrefcs,|jr
|jd��t�fdd�|jD��S)Nr�c3s �|]}t�|�d��VqdS)r�N)rrw)rL�dpr�r1r4rN�s��z5BrowserModule.is_path_downloadable.<locals>.<genexpr>)r�r�ru)rCr�r�r1r�r4rS�s
�z"BrowserModule.is_path_downloadablecs&ttd����fdd�t��D���S)z0Prepare rendering of a collection of properties.Ncsg|]
}��|�����qSr1)r9)rLr2�r7r3r8rCr1r4r��s�z3BrowserModule.render_properties.<locals>.<listcomp>)r��filterr')rCr3r7r8r1ryr4r��s
��zBrowserModule.render_propertiesc
Cs�||jvrdSg}|jD]}|�||�}|dkr|�||f�q|jdd�|D]L\}}z'|�||||�}|s<|WSt|t�rE|j}	n|}	d}||	|d�}
|
WSt	yt}z|j
�d||jj
t|dd��WYd}~q(d}~wwdS)z Renders a node property to HTML.NrT�r)r2rQ�renderedz5Rendering failed for property %s with renderer %s: %s)�	traceback)�hidden_properties�property_renderersr5r&�sortr9�
isinstancer>rA�	Exceptionr�warning�	__class__r:r)rCr2r3r7r8�
candidates�renderer�qualityr|rQ�propr
r1r1r4r9�s:

�



����zBrowserModule.render_propertycCsgSr?r1r�r1r1r4�get_wiki_syntaxrHzBrowserModule.get_wiki_syntaxcCs$d|jfd|jfd|jfd|jfgS)a TracBrowser link resolvers.

        `source:` and `browser:`
         * simple paths (/dir/file)
         * paths at a given revision (/dir/file@234)
         * paths with line number marks (/dir/file@234:10,20-30)
         * paths with line number anchor (/dir/file@234#L100)

        Marks and anchor can be combined.
        The revision must be present when specifying line numbers.
        In the few cases where it would be redundant (e.g. for tags), the
        revision number itself can be omitted: /tags/v10/file@100-110#L99
        r�r��sourcerT)�_format_browser_link�_format_export_linkr�r1r1r4�get_link_resolverss
�z BrowserModule.get_link_resolverscCs�|�|�\}}}d|vr|�dd�\}}nd|vr"|�dd�\}}nd|}}|�|||j|j�\}	}
}|
rAtj|d|
||d�Stj|dd�S)Nr�rF�@r�)�class_r�r�zmissing export�r�)�
split_linkrP�_get_link_infor�r�rr�)rC�	formatter�nsr��label�query�fragmentr�r�rr*r�r1r1r4r�0s

��z!BrowserModule._format_export_linkcCs�|�|�\}}}d}}|j�|�}	|	r|	��\}}}|j}
|
j|||d�||}|�|||j|j�\}}
}|s@tj	|dd�Stj	|d|d�}|
r]t|tj	d|
|||j
rXdndd	��}|S)
N)r��markszmissing sourcer�r�)r�r�u​ztrac-rawlinkztrac-ziplink)r�r�r�)r��PATH_LINK_REr�r�r�rTr�r�rr�r�)rCr�r�r�r�r�r�r�r�r�r��src_hrefrr*r��linkr1r1r4r�?s(
�
�z"BrowserModule._format_browser_linkz<([^@#:]*)[@:]([^#:]+)?(?::(\d+(?:-\d+)?(?:,\d+(?:-\d+)?)*))?cCs�t|j�}d}}}z(|�|�\}	}
}t|
|||�}|dur2|�||
||�}|jr.td�ntd�}Wn	ty<Ynw|||fS)N�DownloadzDownload as Zip archive)rrZr��get_allowed_noder%r�rr$)rCr�r�r�r�r�rr*r�r�r��npathr1r1r4r�Xs
���
zBrowserModule._get_link_infocCsdtd�td�fS)Nr��Revz"Revision in which the line changed)rr�r1r1r4�get_annotation_typehsz!BrowserModule.get_annotation_typecCst|j|�S)z9Cache the annotation data corresponding to each revision.)�BlameAnnotatorrZ)rCr7r1r1r4�get_annotation_dataksz!BrowserModule.get_annotation_datacCs|�||�dSr?)r�)rCr7�rowr_�line�blame_annotatorr1r1r4�annotate_rowoszBrowserModule.annotate_rowccs�dVdS)N�RepositoryIndexr1r�r1r1r4�
get_macrosts�
zBrowserModule.get_macroscCstd�}d|fS)Na

        Display the list of available repositories.

        Can be given the following named arguments:

          ''format''::
            Select the rendering format:
            - ''compact'' produces a comma-separated list of repository prefix
              names (default)
            - ''list'' produces a description list of repository prefix names
            - ''table'' produces a table view, similar to the one visible in
              the ''Browse View'' page
          ''glob''::
            Do a glob-style filtering on the repository names (defaults to '*')
          ''order''::
            Order repositories by the given column (one of "name", "date" or
            "author")
          ''desc''::
            When set to 1, order by descending order
        �messages)r)rCr2�descriptionr1r1r4�get_macro_descriptionwsz#BrowserModule.get_macro_descriptionc
sPt|�\}}|�dd�}|�dd��|�d�}t|�dd��}t|j��t�fdd	������D��}	|d
krh|��j	|	||�}
t
�jd�|jd�
d
�}|
||rTdndddd|d�}t|j���j	jd|�S�fdd���fdd�|	D�}	t�fdd	�|	D�|d�}	�fdd��|dkr�t��fdd�|	D��Std���fdd	�|	D��S)Nr��compact�globr	r�r�rc3s"�|]}t|d��r|VqdS)rNr)rL�rdata)r�r1r4rN�s��z-BrowserModule.expand_macro.<locals>.<genexpr>�tabler�r�r�rFr�)r�r�r�r�r�r�r�zrepository_index.htmlcs"z��|�WStyYdSwr?)r#r$)r�)r�r1r4r#�s
�z2BrowserModule.expand_macro.<locals>.get_repositorycsg|]}|�|�f�qSr1r1)rLr�)r#r1r4r��s�z.BrowserModule.expand_macro.<locals>.<listcomp>c3s<�|]\}}|rt|j�d��s|��j�r||fVqdS)r�N)r�paramsr�r�r��rLr�r��r�r1r4rN�s�
��
�r{cs6|ptd�}ttj|td|d��j�|jpd�d��S)Nz	(default)zView repository %(repo)sr�r�)rrrr�r�rTr�)r�r�r�r�r1r4�repolink�s

�z,BrowserModule.expand_macro.<locals>.repolinkr�c	s4g|]\}}tt��||��t�|j�d����qS)r�)rrh�ddr�r�r��r�r1r4r��s���z, c3s�|]
\}}�||�VqdSr?r1r�r�r1r4rN�s��)r,r�rrrZ�dictr�r"r�r7r'r�r�r�r"�render_fragmentr'r�dlrrO)
rCr�r2rAr��kwargsr�r�r��	all_reposr�r�rr1)r�r#r�r�r�r4�expand_macro�sL


����
����zBrowserModule.expand_macror?);r:r;r<rRr#r
r r+r
r*�ExtensionPointr/rr�source_realmr�rrurrvr�r�reprryr�rzr{r|r}r~r�r�r�r�r�rr�r�rRr�r�r%rSr�r9r�r�r�r�r��compiler�r�r�r�r�r�r�r�r1r1r1r4rt�s~��
�������)	1>K


N
rtc@s$eZdZdd�Zdd�Zdd�ZdS)r�cCsx||_||_t|j�}|�|jjj�|_|jj|_|jj	|_
d|_i|_t
|jd�t|jd�t|jd�|��dS)Nzcommon/js/blame.jszcommon/css/changeset.csszcommon/css/diff.css)rZr7rr#r��parent�idr�r�r�r��prev_chgset�chgset_datar&r�r'�reset)rCrZr7r�r1r1r4rD�s


zBlameAnnotator.__init__c	Cs�|j}|j�|j|�}|��|_g|_|j�|�}||i}t|j	�|_
tt|j��D]%}|j|}|�
|�}|sI|j�|�}|||<|j
�|j	�|j�|�q*i|_|��D]
\}}}||j|<qWt|j�}|��|_dSr?)r�r��get_noder��get_annotationsr`�
changesetsr�r[rr �ranger�r�rsr&�paths�get_historyrtrZr�r!)	rCr�r�chgset�chgsets�idxr��chgrTr1r1r4r��s(



zBlameAnnotator.resetc
Csl|t|j�kr|�t���dS|j|d}|j|d}|j�|�}||jvrl|j	j
�||jj
p3d|�}|j�dd�d}td||jf�}tjd|j�|�||d�}	|�|j�|j��}
d|
}|	|f|j|<n|j|\}	}|j|kr{||_|r�||jkr�d}|j}|t|j�kr�|j||kr�|d	7}tj|d
|d�}|j|kr�|�|	�||_|�|�dS)NrF� rz%s: %sz[%s]r�z"background-color: rgb(%d, %d, %d);rJz border-bottom: none;z	blame r%s)�styler�)r�r`r&r�thr�r�r�r�r7r�r�r�r�rrPr�messager��	short_revr!r rqrr��
prev_styler�)
rCr�r_r�r�r��chgset_href�short_authorr��anchor�colorr��	blame_colr1r1r4r��s@
���


zBlameAnnotator.annotateN)r:r;r<rDr�r�r1r1r1r4r��s r�)Hr�rr�fnmatchr�trac.configrrr�	trac.core�trac.mimeview.apir
rr�	trac.permr
r�
trac.resourcerr�	trac.utilrr�trac.util.datefmtrrrr�trac.util.htmlrrr�trac.util.textrr�trac.util.translationrr�trac.versioncontrol.apirr�trac.versioncontrol.web_ui.util�trac.web.apir r!�trac.web.chromer"r#r$r%r&r'r(r)�
trac.wiki.apir*r+r,�trac.wiki.formatterr-r.rf�	Interfacer/rDr>�	ComponentrErSr[rtr�r1r1r1r4�<module>sB('	!!