o k`'@sddlmZddlmZddlZddlZddlZddlmZm Z m Z ddl Tddl m Z ddlmZddlmZdd lmZmZmZdd lmZdd lmZmZmZmZdd lmZmZdd l m!Z!ddl"m#Z#ddl$m%Z%m&Z&m'Z'm(Z(m)Z)ddl*m+Z+m,Z,m-Z-ddl.m/Z/m0Z0m1Z1m2Z2ddl3m4Z4m5Z5m6Z6ddl7m8Z8ddl9m:Z:m;Z;ddlZ>ddl?m@Z@mAZAmBZBmCZCmDZDmEZEmFZFmGZGddlHmIZImJZJddlKmLZLGdddeMZNGdddeOZPGdddeOZQGdd d eOZRd!d"ZSdS)#)partial)groupbyN) BoolOption IntOptionOption)*)Mimeview)IPermissionRequestor)ResourceNotFound) ISearchSource search_to_sqlshorten_result)ITimelineEventProvider)as_boolcontent_dispositionembedded_numberspathjoin)from_utimestamppretty_timedelta)tag)to_json)CRLFexception_to_unicode shorten_line to_unicodeunicode_urlencode)_ngettexttag_) ChangesetNoSuchChangesetNodeRepositoryManager) diff_blocksget_diff_options unified_diff) BrowserModule)content_closing render_zip)IRequestHandler RequestDone)ChromeINavigationContributor add_ctxtnavadd_link add_scriptadd_stylesheet prevnext_nav web_context)IWikiSyntaxProvider WikiParser) format_toc@s eZdZdZddZddZdS)IPropertyDiffRendererz>Render node properties in TracBrowser and TracChangeset views.cCdS)zIndicate whether this renderer can treat the given property diffs Returns a quality number, ranging from 0 (unsupported) to 9 (''perfect'' match). Nnamer8r8F/usr/lib/python3/dist-packages/trac/versioncontrol/web_ui/changeset.pymatch_property_diff:z)IPropertyDiffRenderer.match_property_diffcCr7)aRender the given diff of property to HTML. `name` is the property name as given to `match_property_diff()`, `old_context` corresponds to the old node being render (useful when the rendering depends on the node kind) and `old_props` is the corresponding collection of all properties. Same for `new_node` and `new_props`. `options` are the current diffs options. The rendered result can be one of the following: - `None`: the property change will be shown the normal way (''changed from `old` to `new`'') - an `str` value: the change will be shown as textual content - `Markup` or `Fragment`: the change will shown as block markup Nr8)r: old_context old_props new_context new_propsoptionsr8r8r;render_property_diffAr=z*IPropertyDiffRenderer.render_property_diffN)__name__ __module__ __qualname____doc__r<rCr8r8r8r;r67s r6c@s(eZdZdZeeddZddZdS)DefaultPropertyDiffRendererz5Default version control property difference renderer.cCr7)Nr8)selfr:r8r8r;r<Yz/DefaultPropertyDiffRenderer.match_property_diffc Csv||||}}d|vrd|vrdSddt|||dd} ttdt|dt|j  |d| S)N z --- +++ contextlineszProperty %(name)sr9z text/x-diff) joinr% splitlinesgetrlirstrongrenvrender) rJr:r>r?r@rArBoldnewunidiffr8r8r;rC\s z0DefaultPropertyDiffRenderer.render_property_diffN)rDrErFrG implementsr6r<rCr8r8r8r;rHTs  rHc@sNeZdZdZeeeeee e e e Z ejZeddddZeddddZedd dd Zed d d dZed dddZed dddZddZddZddZedZddZ ddZ!d d!Z"d"d#Z#d$d%Z$d&d'Z%d(d)Z&d*d+Z'd,d-Z(d.d/Z)d0d1Z*d2d3Z+d4d5Z,d6d7Z-d8Z.d9d:Z/d;d<Z0 =dFd>d?Z1d@dAZ2dBdCZ3dDdEZ4d=S)GChangesetModuleaMRenderer providing flexible functionality for showing sets of differences. If the differences shown are coming from a specific changeset, then that changeset information can be shown too. In addition, it is possible to show only a subset of the changeset: Only the changes affecting a given path will be shown. This is called the ''restricted'' changeset. But the differences can also be computed in a more general way, between two arbitrary paths and/or between two arbitrary revisions. In that case, there's no changeset information displayed. timelinechangeset_show_files0zNumber of files to show (`-1` for unlimited, `0` to disable). This can also be `location`, for showing the common prefix for the changed files. changeset_long_messagesfalseaWhether wiki-formatted changeset messages should be multiline or not. If this option is not specified or is false and `wiki_format_messages` is set to true, changeset messages will be single line only, losing some formatting (bullet points, etc).changeset_collapse_eventszWhether consecutive changesets from the same author having exactly the same message should be presented as one event. That event will link to the range of changesets in the log view. changesetmax_diff_filesrzmMaximum number of modified files for which the changeset view will attempt to show the diffs inlined.max_diff_bytesizMaximum total size in bytes of the modified files (their old size plus their new size) for which the changeset view will attempt to show the diffs inlined.wiki_format_messagestruezWhether wiki formatting should be applied to changeset messages. If this option is disabled, changeset messages will be rendered as pre-formatted text.cCr7)Nbrowserr8rJreqr8r8r;get_active_navigation_itemrKz*ChangesetModule.get_active_navigation_itemcCsgSNr8rgr8r8r;get_navigation_itemsrKz$ChangesetModule.get_navigation_itemscCsdgS)NCHANGESET_VIEWr8rJr8r8r;get_permission_actionssz&ChangesetModule.get_permission_actionsz/changeset(?:/([^/]+)(/.*)?)?$cCsDt|j|j}|r |\}}|r||jd<|r||jd<dSdS)NrWnew_pathT)rematch _request_re path_infogroupsargs)rJrhrqrWror8r8r; match_requests   zChangesetModule.match_requestcCs:|jd|jd}|jd}|jd}|jd}|jd}|r2d|vr2|dd\}}|r@d|vr@|dd\}}t|j}|rM||}n||\}}}|rl||\} } }| |krlt t d | |d |s|sv|r|d krt t d |p| d d t t dz| |}| |p|}Wnt y} zt| t d| d} ~ ww||}||p|}d t|j|} d t|j|} ||kr||krd}}t|\}}}|d}| o|du}|r|dv}n||k}d|jvs||jkr9|dpd}|jpd}|r*|r||jj||||dn||jj|||dn||jj||||| |d|r`|||}|rP|dd\}}n|||}}||||d}n|sg|j}n|sm|j}|durt|}||||d}|||jpd||jd|r||}||jd||j|d ||j!|d|d|"||j|j#|j$t%|jddg |jd}|dvr|&d d}|r|rd ||f}nd!|}n|rd"|||f}n d#|&d d|||f}|d$kr|'||||n|d%krt(||d&|dt)|j*||||+||||||r-d'|}n t,| || |d(}t-|d)d*|t d+d,d$t-|d)d-|t d.d/d%t.|d0t/|d1t/|d2t/|d3|r|rxt0|t d4t d5d;|fSt0|t d6t d7d;|fS|jj|| || d8}t1|t d9|d:d;|fS).get_changescs&|}r td|dStd|dS)NzChangeset %(id)s for %(path)sidrChangeset %(id)srrr)rrrr8r;_changeset_titles  z6ChangesetModule._render_html.._changeset_titlera)parentcontextrevprop propertiesrfirstrrrwrlastnextc3s4jdddddD]}|VqdS)Nrorrwrrorrwr)r)d)rrr8r;rs   Ftitle BROWSER_VIEWcsNjj|j|j|r dndd}td|jd}|j|j|j||dS)Nblame)rannotatez-Show revision %(rev)s of this file in browserr)rrshortrevrr)rrf created_path created_revrrr short_rev)node annotatedrr)rrxrrhr8r; node_infos   z/ChangesetModule._render_html..node_inforrBc s|}|}t|j}t|j}g}||krt|D]C\}}d} } } ||vr1|} n"|||krS|||||} | sS|d||} |d||} | sY| sY| rc||| | | dq t|D]\}}||vr|d||} | dur||| ddqj|S)Nra)r:rVrWr)r:rWrV)get_propertiesr2rsorteditemsrCrender_propertyappend) rrr?rAold_ctxnew_ctxchanged_propertieskvrWrVr)rfrBrhrJr8r; _prop_changessJ      z3ChangesetModule._render_html.._prop_changescSs|}|}||Srj)get_content_length)rrold_sizenew_sizer8r8r;_estimate_changessz7ChangesetModule._render_html.._estimate_changesc stj}||j|jrdS||j|jrdSt|}|j|dr%dSt|}|j|dr1dS|||j}|||j}||krzdd}|dksRdrTd}j ddd }d }d }d } t | | ||||| d SgS)zReturns the list of differences. The list is empty when no differences between comparable files are detected, but the return value is None for non-comparable files. NcontentrMrNrr mimeviewer tab_widthignoreblanklines ignorecaseignorewhitespaceignore_blank_lines ignore_caseignore_space_changes) rrT is_binary content_typer _read_contentrrQconfiggetintr#rP) rrmview old_content new_contentrtabwidthrr ignore_space)rBrJr8r;_content_changess:       z6ChangesetModule._render_html.._content_changesrrrIT)rrVrWpropsdiffsr~z0Show the changeset %(id)s restricted to %(path)srrz5Show the %(range)s differences restricted to %(path)sz[%s:%s])rangerr hide_diffRevisionr) has_diffs show_diffs diff_files diff_bytesrbrcchanges filestatsrfileslocationlongcolshortcolzchangeset_content.html)0rr&rTrxr2realmrrrrender_properties oldest_revrrrrar.rrrstrnext_revhas_nodetitle_for_diffrlistrrrurQrcrbr DIFF_CHANGESr!FILE is_viewable_prepare_filestatsEDITrrrrrr_get_parent_locationr+generate_fragmentsend)-rJrhrrrrrrrrrevpropsrrrr prev_hrefrr next_hrefrrrr  diff_changesrrrrrrrrrrrrr r show_oldshow_new show_entry show_diffinforstreamr8) rfrrrrBrrxrrhrrrJr;r{sz                '              zChangesetModule._render_htmlcCsdd||||D}t|jjrd}n d|}t|}|d|dd|dtd |d |dur>|d || | |t ) zRaw Unified Diff versioncss(|]}t|tr|dn|VqdS)zutf-8N) isinstancerencode).0liner8r8r; s z/ChangesetModule._render_diff..Nr~z Content-Typeztext/x-patch;charset=utf-8zContent-Disposition attachmentz.diffzContent-Length) _iter_diff_linesr+rTuse_chunked_encodingrOlen send_response send_headerr end_headerswriter*)rJrhrrroutputlengthr8r8r;rs"        zChangesetModule._render_diffc cst|j}|j|d|d|d|ddD]\}}}}|tjkr#qd} } d} } |rU||js4q||j|j r=qt |} |j| drHq|j |j f} | | |j} |r||js^q||j|j rgqt |} |j| drrq|j |j f} |j } | | |j} n| |j }| |d}t|d|t|d d} | | kr|d d }|d d }|dks|drd }|d}|d}|d}| ds| } d| tVdtVd| tVd| tVt| | ||||dD]}|tVqqdS)Nrorrwrrr~)r~r~rrIrrBrMrNrrrrrzIndex: zC===================================================================z--- %s (revision %s)z+++ %s (revision %s)r)rrTrr! DIRECTORYr$rrrrrrrrrr=rQrr%rP)rJrhrrmimeviewrrrrrr new_node_info old_node_inforo old_node_path diff_old_pathrBrrrrr7r8r8r;r;s~                  z ChangesetModule._iter_diff_linesc csb|j|d|d|d|ddD]\}}}}|tjtjfvr.|tjkr.||jr.|VqdS)z;Node iterator yielding all the added and/or modified files.rorrwrrN)rr!r#rDrrr$r) rJrhrr root_noderrrrr8r8r;rs    zChangesetModule._zip_iter_nodescCsrtd}|d|dkr td|dp||dp||dpddStd |dp'd|dp,||dp1d|dp6|d S) Nlatestrorwz+Diff [%(old_rev)s:%(new_rev)s] for %(path)srrrz)rrrz>Diff from %(old_path)s@%(old_rev)s to %(new_path)s@%(new_rev)srr)rJrrKr8r8r;r  s       zChangesetModule.title_for_diffc Cs|t|jjvr dSg}|jD]}||} | dkr!|| |fq|jdd|D]2\} }z |||||||WSty\} z|j d||j j t | ddWYd} ~ q*d} ~ wwdS)z)Renders diffs of a node property to HTML.NrT)reversez:Diff rendering failed for property %s with renderer %s: %s) traceback)r&rThidden_propertiesproperty_diff_renderersr<rsortrC Exceptionlogwarning __class__rDr) rJr:rr?rrArB candidatesrendererqualityrr8r8r;rCs0       z$ChangesetModule.render_property_diffcCs0t|dkr |dSdtjdd|DS)z|Return the deepest common path for the given files. If all the files are actually the same, return that location.rIrrzcSsg|]}|dqS)rzrr6fr8r8r; 7sz1ChangesetModule._get_location..)r=rOosr commonprefix)rJrr8r8r; _get_location1s  zChangesetModule._get_locationcCs@|r||d}|ddD] }||kr||SqdS)zaOnly get a location when there are different files, otherwise return the empty string.rrINr~)rPr^)rJrrrZr8r8r;r':sz$ChangesetModule._get_parent_locationcCsi}tjD]}d||<q|S)Nr)r ALL_CHANGES)rJrchgr8r8r;r%Es  z"ChangesetModule._prepare_filestatscszdjvr;g}t|j}|}t|dkr-fdd|D}|tdtd}ntd}|dd |f|SgS) NrlrIcsDg|]}t|jds|jrd|jd|jptdfqS)hiddenrepo-u  -  (default))rparamsrQr$rrxrr6rrhr8r;r[Us z8ChangesetModule.get_timeline_filters..z common/js/timeline_multirepos.jszChangesets in all repositorieszRepository changesetsrra) rr"rTget_real_repositoriesr=rPr/rinsert)rJrhfiltersr repositorieschangeset_labelr8rfr;get_timeline_filtersMs      z$ChangesetModule.get_timeline_filtersc #sd|v}dd|D}|s|r|jdkdvrdn r'tnd|jr1dd nd d ifd d }t|j}t|d d dD]7} |s]d| j|vrz || D]} | VqbWqRt y} z|j d| jt | WYd} ~ qRd} ~ wwqRdSdS)NracSsh|] }|dr|qS)rb)rrYr8r8r; gsz6ChangesetModule.get_timeline_events..r)z-1 unlimitedrcSs |j|jfSrj)authorrcr8r8r;ss z5ChangesetModule.get_timeline_events..cS|jSrjrrqr8r8r;rsuc3st|dD]K\}}g}|D].}|jrA|jg}||j}|r8|vr4||jq||<|||j|fq|rV|dd}d|j |j |ffVq dS)Nkeyrorra) rget_changesetsr$rrxget_changeset_uidrrrrrp)rr changesetsviewable_changesetscset repos_for_uiduidcollapse_changesetsrh show_files show_locationstartstop uids_seenr8r;generate_changesetsxs6      z@ChangesetModule.get_timeline_events..generate_changesetscSrtrj)rx)rr8r8r;rsrurvrbz6Timeline event provider for repository '%s' failed: %r) timeline_show_filesisdigitinttimeline_collapser"rTrrgrxrrRerrorr) rJrhrrri all_repos repo_filtersrrreventrr8rr;get_timeline_eventsesD      'z#ChangesetModule.get_timeline_eventsc s|d\}}}|d\}}} |dd} |jpd} |jj} |j| j} }|dkr@|| kr5|j|| p3dS|jj| p;d| |dS|dkrH|jrYd}|jrX| }|j dd d n| }d} d |j vr6g}|r| |D]3\}}}| D])}|jj d |dpd |j}d| |vrqv|dd7<||dqvqmfddtjD}tjt|dt||pd |dd}nu|r6t}|D]=\}}}| D]3}|jj d |dpd |j}d| |vrqd|krt|krnnn ||d|dfqqddt|D}d|krt|kr,nn |d|tdg}ttj|dd|}| rF|t|jd| || 7}|S|| k}| dsWtd| d<| sat| dkrrtdd|ridndd| d}n tdd|rzdnd}| j !|}|rt|t"d|}n|j !| }t|t"d ||f}|d!krg}|#D]"\}}|s|d"vrqd#}|r|d$7}|tj$||dq|%D] }|tj$|d%dq|&D] }|tj$|d&dq|s|St||S|d'kr t'd(|t(| d)SdS)*NrNrror~url)rstop_rev descriptionhtmlT) wiki_flavorpreserve_newlinesrsourcerz FILE_VIEWrrIc sNg|]#}|}|rtj|dt|d|dkr!|dkrdp |dp"|fqS)class_ rIcopycopiess)rdivspan)r6rcountrr8r;r[s  z9ChangesetModule.render_timeline_event..z in rrcSs(g|]\}}ttj|d|pdqS)rrz)rrRr)r6rmodr8r8r;r[su…rczChangeset in %(repo)s zChangesets in %(repo)s z, r|z Changeset z Changesets z[%s]z[%s-%s]r)defaultmasterbranchz headrz trac-bookmarksummaryz%(title)s: %(message)s)rr))rrrrrrarRrdtimeline_long_messageschild set_hintsrr%rrrrr_rulrRrSr^setr=addrr5rTrrrOrrem get_branchesrget_tags get_bookmarksrr) rJrfieldrrzrrr| cset_resourcer} older_csetrrxrev_brev_amarkuprrrr repos_for_cr`rstats unique_filessinglerdrev_adrev_blabelsr:headrr8rr;render_timeline_events                      z%ChangesetModule.render_timeline_eventz(?:[0-9]+|[a-fA-F0-9]{8,})c#s,dtjdjdfddfVdS)Nz!?\[(?P%s\s*)z*%s(?:/[^\]]*)?(?:\?[^\]]*)?(?:#[^\]]*)?\]|z1(?:\b|!)r[0-9]+\b(?!:[0-9])(?:/[a-zA-Z0-9_/+-]+)?cs8|d|ddkr|dd||S|dd||S)NrarrrIro)_format_changeset_link)xyzrmr8r;rss z1ChangesetModule.get_wiki_syntax..)r4INTERTRAC_SCHEME CHANGESET_IDrmr8rmr;get_wiki_syntaxs  zChangesetModule.get_wiki_syntaxccsd|jfVd|jfVdS)Nrar)r_format_diff_linkrmr8r8r;get_link_resolverss z"ChangesetModule.get_link_resolversNc Csn|||||}|r |St|j}||\}}} |d} | dkr0|d| || d} } n|d} } zc|| \} }} | sO||j} | durO|| }| dkrUd} |r| | }| |j r~|j | |jpjd| }tj|dt|j||| dWStd| | ptdd}n | rtd| d }ntd }Wnty}z t|}WYd}~nd}~wwtj|d |d S) Nrzrrarrrz4No permission to view changeset %(rev)s on %(repos)src)rrr{r|zNo default repository definedzmissing changeset)rr)shorthand_intertrac_helperr"rT split_linkfindrget_default_repositoryrrrr$rrrarxrarrrrr)rJ formatternsrlabel fullmatch intertracrrdfragmentseprrrxrrarerrmsgrr8r8r;rsV          z&ChangesetModule._format_changeset_linkcCs ||\}}}dd}d|vr1|dd\} } || || } } | d| d| d| dd} n||\}}d}|rGd|vrG|dd\}}||||d} || }d}t| r}|red|dd}|jj| d pmd| d | d pud| d d |}tj|d||dS)NcSsd|vr |ddS|dfS)NryrIrX)rr8r8r;pathrevGs z2ChangesetModule._format_diff_link..pathrevz//rIrr:&rorrwrrrar) rrr anyvaluesrrarr)rJrrtargetrrdqueryrrp1p2rVrWrrwrrrrr8r8r;rEs8       z!ChangesetModule._format_diff_linkccs"d|jvrdtdfVdSdS)Nrlra Changesets)rrrgr8r8r;get_search_filtersgs z"ChangesetModule.get_search_filtersc cs>d|vrdSt|j}dd|D}t}|jjy}t|gd|\}} |d|| D]^\} } } } }|| }|s=q.z || } || }Wn t yRYq.w| | }||vr]q.|j |j | }d||vr|||j| |jpydd|t|ft| | t||fVq.WddS1swYdS)NracSsi|]}|jd|qSr)rdrer8r8r; osz6ChangesetModule.get_search_results..)rrrpzf SELECT repos, rev, time, author, message FROM revision WHERE rlz[%s]: %s)r"rTrgrdb_queryr rQrrr ryrrrrrrrarxrrr )rJrhtermsrirrjrdbsqlrurrtsrprRrdrevr~r|r8r8r;get_search_resultsksL       "z"ChangesetModule.get_search_resultsrj)5rDrErFrGrYr,r r)rr3r ExtensionPointr6rOr"changeset_realmrrrrrrrrbrcrdrirkrnrpcompilerrrvrrrr;rr rCr^r'r%rlrrrrrrrrrr8r8r8r;rZjsr    90A   5j -" rZc@s$eZdZeeddZddZdS) AnyDiffModulecCs |jdkS)Nz/diff)rsrgr8r8r;rvs zAnyDiffModule.match_requestcst|j}jratjd\}||\}}dd}g}r9| fdd | D|sI| fdd| Dfddt ||d D}t|} | d d jd } jd } jd} jd} || \}}} || \}}} i}|r|jdt|j| || dn |jjd | d|r|jdt|j| || dn |jjd| dt|jtdd|fS)NtermcSs|d t|dfS)NrrI)r)entryr8r8r; kind_ordersz1AnyDiffModule.process_request..kind_orderc3s8|]}|jr|j|jdtj|jfVqdS)rzN)r$risdirr:rrxr)r6r)rrhr8r;r8s   z0AnyDiffModule.process_request..c3s.|]}|jrd|jd|jfVqdS)TrzN)r$rrxrerfr8r;r8s  cs8g|]\}}}|r||rdnd||dqS)rzr~)rvaluer)lowerr)r6rr:r)prefixr8r;r[s   z1AnyDiffModule.process_request..rvzapplication/jsonr9rorrwrrz)ror)rwrrzdiff_form.html)r"rTr posixpathrrurQrrextendr get_entriesrgrrr)rrrxrr+ add_jquery_uir0)rJrhrdirnamerxrrentriespathsrrorrwr new_reponame new_reposrrrr8)rrrhr;rsT         zAnyDiffModule.process_requestN)rDrErFrYr)rvrr8r8r8r;rs rcCs8t| }|WdS1swYdSrj)r' get_contentread)rrr8r8r;rs$r)T functoolsr itertoolsrr\rrp trac.configrrr trac.coretrac.mimeview.apir trac.permr trac.resourcer trac.searchr r r trac.timeline.apir trac.utilrrrrtrac.util.datefmtrrtrac.util.htmlrtrac.util.presentationrtrac.util.textrrrrrtrac.util.translationrrrtrac.versioncontrol.apirr r!r"trac.versioncontrol.diffr#r$r%"trac.versioncontrol.web_ui.browserr&trac.versioncontrol.web_ui.utilr'r(trac.webr)r*trac.web.chromer+r,r-r.r/r0r1r2 trac.wiki.apir3r4trac.wiki.formatterr5 Interfacer6 ComponentrHrZrrr8r8r8r;sN         ( ) D