\x89\x50\x4E\x47\x0D\x0A\x1A\x0A PNG  \x89\x50\x4E\x47\x0D\x0A\x1A\x0A  13\c @@sdZddlmZddlZddlZddlZddlmZddlm Z m Z m Z m Z m Z mZmZmZddlmZiZejeZyddljZejWnek rdZnXdZded fd ed fd ed fdedfdedfgZejdZdZedZde fdYZ!de fdYZ"dZ#dZ$dZ%dZ&dZ'dZ(dZ)d Z*d!Z+d"Z,d#Z-d$Z.ed%d&d'd(ed)ed*fd+d,e/ed-ed*fd.d/e/ed0dfged1d2ej0dd3Z1ed4d5e2dd6Z3dS(7s/generate release notes from commit messages (EXPERIMENTAL) It is common to maintain files detailing changes in a project between releases. Maintaining these files can be difficult and time consuming. The :hg:`releasenotes` command provided by this extension makes the process simpler by automating it. i(tabsolute_importN(t_(tconfigterrortminirsttnodetpycompatt registrartscmutiltutil(t stringutilsships-with-hg-coretfeatures New FeaturestbcsBackwards Compatibility Changestfixs Bug FixestperfsPerformance Improvementstapis API Changess#^\.\. ([a-zA-Z0-9_]+)::\s*([^$]+)?$s\bissue ?[0-9]{4,6}(?![0-9])\bs Other ChangestparsedreleasenotescB@sYeZdZdZdZdZdZdZdZdZ dZ RS( cC@s i|_dS(N(tsections(tself((s8/usr/lib64/python2.7/site-packages/hgext/releasenotes.pyt__init__@scC@s ||jkS(N(R(Rtsection((s8/usr/lib64/python2.7/site-packages/hgext/releasenotes.pyt __contains__CscC@stt|jS(N(titertsortedR(R((s8/usr/lib64/python2.7/site-packages/hgext/releasenotes.pyt__iter__FscC@s;|jj|ggf|j|dj||fdS(s Add a titled release note entry.iN(Rt setdefaulttappend(RRttitlet paragraphs((s8/usr/lib64/python2.7/site-packages/hgext/releasenotes.pyt addtitleditemIscC@s5|jj|ggf|j|dj|dS(s[Adds a non-titled release note entry. Will be rendered as a bullet point. iN(RRR(RRR((s8/usr/lib64/python2.7/site-packages/hgext/releasenotes.pytaddnontitleditemNscC@s|jj|ggfdS(s|Returns titled entries in a section. Returns a list of (title, paragraphs) tuples describing sub-sections. i(Rtget(RR((s8/usr/lib64/python2.7/site-packages/hgext/releasenotes.pyttitledforsectionVscC@s|jj|ggfdS(s5Returns non-titled, bulleted paragraphs in a section.i(RR(RR((s8/usr/lib64/python2.7/site-packages/hgext/releasenotes.pytnontitledforsection]sc@s#tfd|j|DS(Nc3@s|]}|dkVqdS(iN((t.0tt(R(s8/usr/lib64/python2.7/site-packages/hgext/releasenotes.pys bs(tanyR (RRR((Rs8/usr/lib64/python2.7/site-packages/hgext/releasenotes.pythastitledinsectionasc C@sts|jtdnx|D]}t|j|t|j|}x|j|D]\}}|j||r|jtd||fqant||fgd}|dkrt |}|rt |||rqaqqnt |||rqan|j |||qaWx|j|D]}||j|krWq6nt|gd}|dkrt |}|rt |||rq6qqnt |||rq6n|j ||q6Wq#WdS(s{Merge another instance into this one. This is used to combine multiple sources of release notes together. sKmodule 'fuzzywuzzy' not found, merging of similar releasenotes is disabled s*%s already exists in %s section; ignoring iR N(tfuzztwarnRt converttitledR tconvertnontitledR!R%twritet getissuenumt findissuetsimilarRR( RtuitotherRt existingnotesRRt incoming_strtissue((s8/usr/lib64/python2.7/site-packages/hgext/releasenotes.pytmergeds>       ( t__name__t __module__RRRRRR R!R%R3(((s8/usr/lib64/python2.7/site-packages/hgext/releasenotes.pyR?s        treleasenotessectionscB@s/eZddZdZdZdZRS(cC@sb|rOtjt}t|}|r7|j|nt|j|_ntt|_dS(N(R tsortdicttDEFAULT_SECTIONStgetcustomadmonitionstupdatetlistt iteritemst _sections(RR.trepoRtcustom_sections((s8/usr/lib64/python2.7/site-packages/hgext/releasenotes.pyRs cC@s t|jS(N(RR=(R((s8/usr/lib64/python2.7/site-packages/hgext/releasenotes.pyRscC@sg|jD]}|d^q S(Ni(R=(RR#((s8/usr/lib64/python2.7/site-packages/hgext/releasenotes.pytnamesscC@s.x'|jD]\}}||kr |Sq WdS(N(R=tNone(RRtnametvalue((s8/usr/lib64/python2.7/site-packages/hgext/releasenotes.pytsectionfromtitles N(R4R5RARRR@RD(((s8/usr/lib64/python2.7/site-packages/hgext/releasenotes.pyR6s  cC@s[g}xN|D]F\}}g}x|D]}|j|q&W|jdj|q W|S(s. Convert titled paragraphs to strings t (textendRtjoin(ttitledparagraphst string_listRRtlinestpara((s8/usr/lib64/python2.7/site-packages/hgext/releasenotes.pyR(s cC@sUg}xH|D]@}g}x|D]}|j|q W|jdj|q W|S(s/ Convert non-titled bullets to strings RE(RFRRG(tnontitledparagraphsRIRRJRK((s8/usr/lib64/python2.7/site-packages/hgext/releasenotes.pyR)s  cC@s1tjt|tj}|r-|j}n|S(sD Returns issue number from the incoming string if it exists (tretsearchtRE_ISSUEt IGNORECASEtgroup(R1R2((s8/usr/lib64/python2.7/site-packages/hgext/releasenotes.pyR+sc@s?tfd|Dr7|jtdtStSdS(s? Returns true if issue number already exists in notes. c3@s|]}|kVqdS(N((R"ts(R2(s8/usr/lib64/python2.7/site-packages/hgext/releasenotes.pys ss'"%s" already exists in notes; ignoring N(R$R*RtTruetFalse(R.texistingR2((R2s8/usr/lib64/python2.7/site-packages/hgext/releasenotes.pyR,scC@sWt|jdkrOt||}|sH|jtd|tStSntSdS(s? Returns true if similar note found in existing notes. i s,"%s" already exists in notes file; ignoring N(tlentsplittsimilaritycheckR*RRSRT(R.RUR1R3((s8/usr/lib64/python2.7/site-packages/hgext/releasenotes.pyR-scC@sMts tSt}x6|D].}tj||}|dkrt}PqqW|S(sK Returns false when note fragment can be merged to existing notes. iK(R&RSttoken_set_ratioRT(R1R0R3tbullettscore((s8/usr/lib64/python2.7/site-packages/hgext/releasenotes.pyRXs  c@sUdtjddfddkrMdndS(Nt.c@s^|kr8|j}j||||n"tjtdj|dS(Ns#.hgreleasenotes file '%s' not found(tdatatparseRtAbortRtpathto(tfRtremapR](tctxtptreadR>(s8/usr/lib64/python2.7/site-packages/hgext/releasenotes.pyRes  s.hgreleasenotesR(RRA(R>((RcRdReR>s8/usr/lib64/python2.7/site-packages/hgext/releasenotes.pyR9s     c @s*x#|D]}||}tjt|jrjd|krPqq"|jtdjd|jd ffd}g|D]}||dkr|^q}t|dkr|jtd|dq"|r"dj t |} |jtd | q"qqWd S( s` Checks the commit messages for admonitions and their validity. .. abcd:: First paragraph under this admonition For this commit message, using `hg releasenotes -r . --check` returns: Invalid admonition 'abcd' present in changeset 3ea92981e103 As admonition 'abcd' is neither present in default nor custom admonitions is0Invalid admonition '%s' present in changeset %s i c@s"tjdjd|jS(Ni(tdifflibtSequenceMatcherRARQtratio(tx(t admonition(s8/usr/lib64/python2.7/site-packages/hgext/releasenotes.pyts g333333?s(did you mean %s?) is, s(did you mean one of %s?) N( RMRNt RE_DIRECTIVEt descriptionRQR*RthexRVRGR( R.R>t directivestrevstrevRctsimRRR-tss((Rjs8/usr/lib64/python2.7/site-packages/hgext/releasenotes.pytcheckadmonitionss  !+cC@s4x-|D]%}|jd|d|dfqWdS(Ns%s: %s ii(R*(R.RR((s8/usr/lib64/python2.7/site-packages/hgext/releasenotes.pyt_getadmonitionlist&s cC@st}x|D]}||}tj|jd|\}}xt|D]\}} | ddkrpqNn| d} | dr| ddjnd} |dt|krtj t d|| fng} xt |dt|D]} || }|dd krqn|ddkr0Pn|dd krc|j j t d || fn|d dkr| j|dqPqW| s|j j t d tj|jn| r|j| | | qN|j| | qNWqW|S(Nt admonitionsttypeRjtadmonitiontitleRJiis6changeset %s: release notes directive %s lacks contenttmargint paragraphs=changeset %s: unexpected block in release notes directive %s tindents.error parsing releasenotes for revision: '%s' (RRR^Rmt enumeratetstripRARVRR_RtrangeR.R'RRRnRR(R>RoRptnotesRqRctblockstprunedtitblockt directiveRRtjtpblock((s8/usr/lib64/python2.7/site-packages/hgext/releasenotes.pytparsenotesfromrevisions*sB    $  c @st}tj|dtfd}d }xHtD]:\}}|ddkrcqAn|dd}|ddkr|j|}|stjt d|n|}||} | r{x!| D]} |j || qWq{qA|dd krb|t kr=||} xC| D]} |j || q Wq{||t } |j ||| qAtjt d |qAW|S( s6Parse text content containing generated release notes.ic@sg}xt|dtD]}|}|ddkrFq nJ|ddkrZPn6|ddkr`|ddkrtjtdn|rg|d D]}|dj^q}|j|q qg|d D]}|dj^qg}xN|dD]>}|dd kr%Pn|dd kr |j|d q q W|j|q n0|dd krtjtd |dn|r |j|d q q W|S( NiRwRyRRZR{is#indented bullet lists not supportedRJRzs*unexpected block type in release notes: %s(RZR(R~RVRR_RR}R(toffsetRt notefragmentRRtlRJ(R(s8/usr/lib64/python2.7/site-packages/hgext/releasenotes.pytgatherparagraphsbulletses8  ' * RwRRJt underlinet=s!unknown release notes section: %st-sunsupported section type for %sN(RRR^RTRAR|RDRR_RRtBULLET_SECTIONRSR( RttextRRtcurrentsectionRRRRBt bullet_pointsRKR((Rs8/usr/lib64/python2.7/site-packages/hgext/releasenotes.pytparsereleasenotesfile_s6 #      c C@sSg}x|D]\}}||kr+q n|j||jdt||jdx|j|D]\}}|j||jdt||jdx[t|D]M\}}|r|jdn|jtjdj|ddjqW|jdqlW|j |} |j|rp| rp|jt |jdtt |jdnx| D]}|jtjdj|ddddd d d jxV|d D]J}|jd|jtjdj|dddd d d jqW|jdqwWq W|rF|d rF|jdndj|S(sSerialize release notes from parsed fragments and notes. This function essentially takes the output of ``parsenotesfromrevisions()`` and ``parserelnotesfile()`` and produces output combining the 2. RtRREtwidthiNit initindents* t hangindents iis ( RRVR R|RFR twrapRGt splitlinesR!R( RRRJt sectionnamet sectiontitleRRRRKt nontitled((s8/usr/lib64/python2.7/site-packages/hgext/releasenotes.pytserializenotessJ        t releasenotestrRqRs&revisions to process for release notestREVtctchecks+checks for validity of admonitions (if any)RR;s/list the available admonitions with their titles"hg releasenotes [-r REV] [-c] FILEt helpcategoryc K@stj|}t||}|jd}|rZ|jdrZtjtdn|r|jdrtjtdn|rt||S|jd}tj ||pdg}|jdrt |||j |St ||j |}|d kr3|jd|jt||Sy1t|d} t|| j} Wd QXWn4tk r} | jtjkrnt} nX| j||t|d } | jt|| Wd QXd S( s parse release notes from commit messages into an output file Given an output file and set of revisions, this command will parse commit messages for release notes then add them to the output file. Release notes are defined in commit messages as ReStructuredText directives. These have the form:: .. directive:: title content Each ``directive`` maps to an output section in a generated release notes file, which itself is ReStructuredText. For example, the ``.. feature::`` directive would map to a ``New Features`` section. Release note directives can be either short-form or long-form. In short- form, ``title`` is omitted and the release note is rendered as a bullet list. In long form, a sub-section with the title ``title`` is added to the section. The ``FILE`` argument controls the output file to write gathered release notes to. The format of the file is:: Section 1 ========= ... Section 2 ========= ... Only sections with defined release notes are emitted. If a section only has short-form notes, it will consist of bullet list:: Section ======= * Release note 1 * Release note 2 If a section has long-form notes, sub-sections will be emitted:: Section ======= Note 1 Title ------------ Description of the first long-form note. Note 2 Title ------------ Description of the second long-form note. If the ``FILE`` argument points to an existing file, that file will be parsed for release notes having the format that would be generated by this command. The notes from the processed commit messages will be *merged* into this parsed set. During release notes merging: * Duplicate items are automatically ignored * Items that are different are automatically ignored if the similarity is greater than a threshold. This means that the release notes file can be updated independently from this command and changes should not be lost when running this command on that file. A particular use case for this is to tweak the wording of a release note after it has been added to the release notes file. The -c/--check option checks the commit message for invalid admonitions. The -l/--list option, presents the user with a list of existing available admonitions along with their title. This also includes the custom admonitions (if any). R;Rqs$cannot use both '--list' and '--rev'Rs&cannot use both '--list' and '--check's not public()RtrbNtwb(Rt byteskwargsR6RRR_RRuRtrevrangeRtR@RRAtpagerR*RtopenRRetIOErrorterrnotENOENTRR3( R.R>tfile_toptsRtlistflagRqRptincomingtfhRte((s8/usr/lib64/python2.7/site-packages/hgext/releasenotes.pyRs6[    tdebugparsereleasenotestnorepoc C@sR|dkrtjj}n$t|d}|j}WdQXt||}t||}x|D]}|jtd|xe|j|D]T\}} |jtd|x.| D]&} |jtddj | qWqWx[|j |D]J} |jtdx.| D]&} |jtddj | qWqWqgWdS( s6parse release notes and print resulting data structureRRNs section: %s s subsection: %s s paragraph: %s REs bullet point: ( RtstdinReRR6RR*RR RGR!( R.tpathR>RRRRRRRRK((s8/usr/lib64/python2.7/site-packages/hgext/releasenotes.pyRjs    ( (4t__doc__t __future__RRfRRMtmercurial.i18nRt mercurialRRRRRRRR tmercurial.utilsR tcmdtabletcommandtfuzzywuzzy.fuzzR&RYt ImportErrorRAt testedwithR8tcompileRlRORtobjectRR6R(R)R+R,R-RXR9RtRuRRRRTtCATEGORY_CHANGE_NAVIGATIONRRSR(((s8/usr/lib64/python2.7/site-packages/hgext/releasenotes.pyt s`   :     U     5 K ?    y