o k`m$@sddlmZddlmZmZddlmZddlmZm Z ddl m Z ddl m Z ddlmZmZddlmZmZmZdd lmZgd ZGd d d eZdddZdddZddZddZddZddZd S)) TemporaryFile)ZipFile ZIP_DEFLATED)ResourceNotFound)content_dispositioncreate_zipinfo) http_date)tag)tag__)EmptyChangesetNoSuchChangeset NoSuchNode) RequestDone)content_closing get_changesget_path_linksget_existing_nodeget_allowed_nodemake_log_graph render_zipc@s$eZdZddZddZddZdS)rcCs ||_dSNcontent)selfrrA/usr/lib/python3/dist-packages/trac/versioncontrol/web_ui/util.py__init__&s zcontent_closing.__init__cCs|jSrr)rrrr __enter__)szcontent_closing.__enter__cGst|jdr |jdSdS)Nclose)hasattrrr)rexc_inforrr__exit__,s zcontent_closing.__exit__N)__name__ __module__ __qualname__rrr"rrrrr$s rNc Csli}|D]/}||vr qz||}Wnty.t||}|dur,|d||jp*dYnw|||<q|S)Nz"Unable to get changeset [%s] in %sz (default)) get_changesetr r warningreponame)reposrevslogchangesrev changesetrrrr1s    rc Cs|pd}d|j|dkr |nd||ddg}|r'|||j||||ddd}dd|dDD]}||d7}|||j|pCd||||ddq3|S)Nzsource:)r-orderdesc)namehrefcSsg|]}|r|qSrr.0prrr Ksz"get_path_links../)browserappendsplit) r3r(pathr-r0r1links partial_pathpartrrrrAs*  rc Csvz|||WSty:}z'tjtd|jj|jpd||ddd}tttj |ddt t d|dd}~ww) Nsearch path_history)r-mode)r3message)class_z^You can %(search)s in the repository history to see if that path existed but was later removed)r@) get_noderr ar r3r+r(rr6r )reqr)r<r-esearch_arrrrUs   rc CsH|dur z|||}Wn ttfyYdSw||r"|SdSdSr)rErr is_viewable)r)r<r-permnoderrrrds rcsg}g}d}t|}dd}zt|}dgg} |}|vr7|dtgg||d|t|t}||||ft|}dd} t||} fdd| D} | | d <tt |D]H\} \} }| | vr||| | d qx| |kr| r| | d| | d| D]}|| dkr|d| g||| |d qqx| s|=n%t|}| fd d t t| d D||d|d d <| d 7qt yYnw|||fS) aGenerate graph information for the given revisions. Returns a tuple `(threads, vertices, columns)`, where: * `threads`: List of paint command lists `[(type, column, line)]`, where `type` is either 0 for "move to" or 1 for "line to", and `column` and `line` are coordinates. * `vertices`: List of `(column, thread_index)` tuples, where the `i`th item specifies the column in which to draw the dot in line `i` and the corresponding thread. * `columns`: Maximum width of the graph. rcSsP|r|dddd|gkr|dd|kr||dd<dS|d||gdS)N)r:)threadcolumnlinerrradd_edgesz make_log_graph..add_edgeTrMNcsg|]}|vr|qSrrr4)activerrr7sz"make_log_graph..rOc3s(|]}dd|dggVqdS)rrONr)r5i)rRrSrr s z!make_log_graph..)iternextr:lenmaxindexlist parent_revs enumeratezipremoveextendrange StopIteration)r)r*threadsverticescolumnsrTnext_rev active_threadr- next_revsparents new_parentscolrrQparentbaser)rUrRrSrrnsd      + rc sddddtd||r&dt|j|jd}nd}|r4|d7}|jd}nd}t|} fd d }d } t d d d} t | dt } ||D]} | |ur_qX| j d} | |slJ|| |d} d| ji}d}| jrt| jdd }|}Wdn1swY| }d|vr|dr|dd}d|d<d|vrd|d<n | jr| rd|d<d}|dur| t| fi|||| | } qXWdn1swY|| | Wdt1swYt)aSend a ZIP file containing the data corresponding to the `nodes` iterable. :type root_node: `~trac.versioncontrol.api.Node` :param root_node: optional ancestor for all the *nodes* :param iter_nodes: callable taking the optional *root_node* as input and generating the `~trac.versioncontrol.api.Node` for which the content should be added into the zip. z Content-Typezapplication/zipzContent-Dispositioninlinez Last-Modifiedr8r/csb|}||d||}|dkr)|t|d}||t|8}|dks||d|S)Nri)tellseekreadminwriterZ)fileobjstartend remainingchunkrGrr write_partials    z!render_zip..write_partialrztrac-z.zip)prefixsuffixwNmtimeCRLF)eol_hintz svn:specialzlink Tsymlinkzsvn:executable executabledir) send_response send_headerrr last_modifiedr<rstripr2rZ end_headersrrrstrip startswithisfilerget_processed_contentruget_propertiesisdirwritestrrr)rGfilenamer) root_node iter_nodes root_path root_nameroot_lenr~posrxzipfilerLr<kwargsdatarpropsrr}rrsn              rr)NN) tempfilerrrr trac.resourcer trac.utilrrtrac.util.datefmtrtrac.util.htmlr trac.util.translationr r trac.versioncontrol.apir r r trac.web.apir__all__objectrrrrrrrrrrrs"       N