a +bW @sFdZddlmZddlZddlZddlZddlmZddlm Z ddl m Z ddl m Z mZmZmZmZmZmZmZddlmZmZiZeeZzXddlZe4ejd d ed d ddlmZej Wdn1s0YWne!ydZYn0d Z"dedfdedfdedfdedfdedfgZ#e$dZ%dZ&edZ'Gddde(Z)Gddde(Z*dd Z+d!d"Z,d#d$Z-d%d&Z.d'd(Z/d)d*Z0d+d,Z1d-d.Z2d/d0Z3d1d2Z4d3d4Z5d5d6Z6ed7d8d9d:ed;ed<fd=d>d?ed@ed<fdAdBd?edCdfgedDej7dEdMdFdGZ8edHdIdJdNdKdLZ9dS)Oa/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. )absolute_importN)_)open)hex)cmdutilconfigerror logcmdutilminirstpycompat registrarutil)procutil stringutilignorez.*python-Levenshtein.*zfuzzywuzzy.fuzz)actionmessagecategorymodulesships-with-hg-coresfeatures New FeaturessbcsBackwards Compatibility Changesfixs Bug FixessperfsPerformance Improvementssapis API Changess#^\.\. ([a-zA-Z0-9_]+)::\s*([^$]+)?$s\bissue ?[0-9]{4,6}(?![0-9])\bs Other Changesc@sTeZdZddZddZddZddZd d Zd d Zd dZ ddZ ddZ dS)parsedreleasenotescCs i|_dSNsectionsselfr8/usr/lib64/python3.9/site-packages/hgext/releasenotes.py__init__Rszparsedreleasenotes.__init__cCs ||jvSrrrsectionrrr __contains__Uszparsedreleasenotes.__contains__cCstt|jSr)itersortedrrrrr__iter__Xszparsedreleasenotes.__iter__cCs.|j|ggf|j|d||fdS)z Add a titled release note entry.rNr setdefaultappend)rr title paragraphsrrr addtitleditem[sz parsedreleasenotes.addtitleditemcCs*|j|ggf|j|d|dS)z[Adds a non-titled release note entry. Will be rendered as a bullet point. Nr%)rr r)rrraddnontitleditem`sz#parsedreleasenotes.addnontitleditemcCs|j|ggfdS)z|Returns titled entries in a section. Returns a list of (title, paragraphs) tuples describing sub-sections. rrgetrrrrtitledforsectionhsz#parsedreleasenotes.titledforsectioncCs|j|ggfdS)z5Returns non-titled, bulleted paragraphs in a section.r+r-rrrrnontitledforsectionosz&parsedreleasenotes.nontitledforsectioncstfdd||DS)Nc3s|]}|dkVqdS)rNr.0tr(rr tz8parsedreleasenotes.hastitledinsection..)anyr/)rr r(rr4rhastitledinsectionssz%parsedreleasenotes.hastitledinsectionc Cs8ts|td|D]}t||t||}||D]|\}}|||rn|td||fqBt||fgd}|dkrt |}|rt |||rqBt |||rqB| |||qB||D]f}|||vrqt|gd}|dkrt |}|rt |||rqt |||r$q| ||qqdS)z{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 rrN)fuzzwarnr converttitledr/convertnontitledr0r8write getissuenum findissuesimilarr*r,) ruiotherr existingnotesr(r) incoming_strissuerrrmergevsR      zparsedreleasenotes.mergeN) __name__ __module__ __qualname__rr!r$r*r,r/r0r8rFrrrrrQsrc@s.eZdZd ddZddZddZdd ZdS) releasenotessectionsNcCsD|r6tt}t|}|r$||tt||_n tt|_dSr) r ZsortdictDEFAULT_SECTIONSgetcustomadmonitionsupdatelistr Z iteritems _sections)rrAreporZcustom_sectionsrrrrs  zreleasenotessections.__init__cCs t|jSr)r"rOrrrrr$szreleasenotessections.__iter__cCsdd|jDS)NcSsg|] }|dqS)rrr1rrr r6z.releasenotessections.names..rOrrrrnamesszreleasenotessections.namescCs$|jD]\}}||kr|SqdSrrR)rr(namevaluerrrsectionfromtitles z%releasenotessections.sectionfromtitle)N)rGrHrIrr$rSrVrrrrrJs rJcCs>g}|D]0\}}g}|D]}||q|d|q|S)z. Convert titled paragraphs to strings  extendr'join)Ztitledparagraphs string_listr(r)linespararrrr;s  r;cCs:g}|D],}g}|D]}||q|d|q|S)z/ Convert non-titled bullets to strings rWrX)Znontitledparagraphsr[r)r\r]rrrr<s r<cCs tt|tj}|r|}|S)zD Returns issue number from the incoming string if it exists )researchRE_ISSUE IGNORECASEgroup)rDrErrrr>sr>cs4tfdd|Dr,|tddSdSdS)z? Returns true if issue number already exists in notes. c3s|]}|vVqdSrrr2srErrr5r6zfindissue..s'"%s" already exists in notes; ignoring TFN)r7r=r)rAexistingrErrerr?sr?cCsBt|dkr:t||}|s4|td|dSdSndSdS)z? Returns true if similar note found in existing notes. s,"%s" already exists in notes file; ignoring TFN)lensplitsimilaritycheckr=r)rArfrDrFrrrr@s r@cCs6tsdSd}|D] }t||}|dkrd}q2q|S)zK Returns false when note fragment can be merged to existing notes. TKF)r9token_set_ratio)rDrCrFZbulletZscorerrrrjs rjcs>dtdfdd dvr4ddS)N.csD|vr(|}||||nttd|dS)Ns#.hgreleasenotes file '%s' not found)dataparserAbortrZpathto)frZremaprnctxpreadrPrrrus  z"getcustomadmonitions..reads.hgreleasenotesssections)NN)ritems)rPrrrrrLs  rLcs|D]}||}tt|rd|vr6qq|tdd|ddffddfdd|D}t|dkr|td |d q|rd t |}|td |qdS) a` 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 r+s0Invalid admonition '%s' present in changeset %s N cstdd|S)Nr+)difflibZSequenceMatcherrbZratio)x) admonitionrrCs z"checkadmonitions..csg|]}|dkr|qS)g333333?rrc)simrrrQGr6z$checkadmonitions..s(did you mean %s?) rs, s(did you mean one of %s?) ) r^r_ RE_DIRECTIVE descriptionrbr=rrrhrZr#)rArP directivesrevsrevrsr@ssr)rzr|rcheckadmonitions+s$   rcCs(|D]}|d|d|dfqdS)Ns%s: %s rr+)r=)rArr rrr_getadmonitionlistOsrcCspt}|D]^}||}tj||d\}}t|D]0\}} | ddkrNq6| d} | drn| ddnd} |dt|krtt d|| fg} t |dt|D]t} || }|dd krq|ddkrq$|dd kr|j t d || f|d dkr| |dqq$q| sF|j t d t|| r\|| | | q6|| | q6q |S)N)Z admonitionstypes admonitionsadmonitiontitlelinesrr+s6changeset %s: release notes directive %s lacks contentmargin paragraphs=changeset %s: unexpected block in release notes directive %s indents.error parsing releasenotes for revision: '%s' )rr ror~ enumeratestriprhrrprrangerAr:r'rZnoder*r,)rPrrnotesrrsblocksZprunediblockZ directiver(r)jZpblockrrrparsenotesfromrevisionsTs^        rc s t}t|ddfdd }d}tD]\}}|ddkrDq.|dd}|d d kr||}|s|ttd ||}||} | r| D]} ||| qq.|d d kr|t kr||} | D]} ||| qn||d } | ||| q.ttd|q.|S)z6Parse text content containing generated release notes.rFcs0g}t|dtD]}|}|ddkr4qn|ddkrHq,n|ddkr|ddkrnttd|rd d |d D}||qn`d d |d Dg}|ddD].}|dd vrq|ddkr||d q||qn$|ddkrttd|d|r||d q|S)Nr+rrsectionbulletrrs#indented bullet lists not supportedcSsg|]}|ddqSr+Nrr2lrrrrQr6zJparsereleasenotesfile..gatherparagraphsbullets..rcSsg|]}|ddqSrrrrrrrQr6)rrrs*unexpected block type in release notes: %s)rrhrrprr')offsetr(Z notefragmentrrr\rrrgatherparagraphsbulletss>        z6parsereleasenotesfile..gatherparagraphsbulletsNrrrs underline=s!unknown release notes section: %s-Tsunsupported section type for %s)F) rr rorrVrrprr,BULLET_SECTIONr*) rtextrrZcurrentsectionrrr(rTZ bullet_pointsr]r)rrrparsereleasenotesfiles8%       rc Csg}|D]x\}}||vrq|||dt||d||D]v\}}|||dt||dt|D]4\}}|r|d|tjd|ddq|dqL| |} ||r| r|t |dtt |d| D]v}|tjd|dddd d |d d D]2}|d|tjd|dd d d q@|dq q|r|d r|dd|S)zSerialize release notes from parsed fragments and notes. This function essentially takes the output of ``parsenotesfromrevisions()`` and ``parserelnotesfile()`` and produces output combining the 2. rr6rrWN)widthrs* s )rZ initindentZ hangindentr+N ) r'rhr/rrYrwraprZ splitlinesr0r) rrr\Z sectionnameZ sectiontitler(r)rr]Z nontitledrrrserializenotess\              r releasenotesrrevr6s&revisions to process for release notessREVccheckFs+checks for validity of admonitions (if any)llists/list the available admonitions with their titles"hg releasenotes [-r REV] [-c] FILE)Z helpcategoryc Ksjt|}t||}t|dddg|dr:t||S|d}t||pPdg}|drrt ||| |St || |}|dur| d| t||Szr?r@rjrLrrrrrZCATEGORY_CHANGE_NAVIGATIONrrrrrrs    (    (       ]    $COI u