comparison hgext/releasenotes.py @ 33571:9a944e908ecf

releasenotes: add custom admonitions support for release notes By default, the extension has default sections like fix, feature, perf etc.. This patch allow user to add support for custom admonition. In order to add a custom admonition, one needs to have a .hgreleasenotes file inside the repository. All the custom directive with name specified under the tag [sections] will be usable by the extension. One important thing to keep in mind is if there exists any custom admonitions with same key as default then they will override the default ones.
author Rishabh Madan <rishabhmadan96@gmail.com>
date Tue, 18 Jul 2017 23:04:08 +0530
parents 5814db57941c
children 3748098d072a
comparison
equal deleted inserted replaced
33570:e470f12d7d05 33571:9a944e908ecf
18 import sys 18 import sys
19 import textwrap 19 import textwrap
20 20
21 from mercurial.i18n import _ 21 from mercurial.i18n import _
22 from mercurial import ( 22 from mercurial import (
23 config,
23 error, 24 error,
24 minirst, 25 minirst,
25 registrar, 26 registrar,
26 scmutil, 27 scmutil,
28 util,
27 ) 29 )
28 30
29 cmdtable = {} 31 cmdtable = {}
30 command = registrar.command(cmdtable) 32 command = registrar.command(cmdtable)
31 33
109 # TODO perform similarily comparison and try to match against 111 # TODO perform similarily comparison and try to match against
110 # existing. 112 # existing.
111 self.addnontitleditem(section, paragraphs) 113 self.addnontitleditem(section, paragraphs)
112 114
113 class releasenotessections(object): 115 class releasenotessections(object):
114 def __init__(self, ui): 116 def __init__(self, ui, repo=None):
115 # TODO support defining custom sections from config. 117 if repo:
116 self._sections = list(DEFAULT_SECTIONS) 118 sections = util.sortdict(DEFAULT_SECTIONS)
119 custom_sections = getcustomadmonitions(repo)
120 if custom_sections:
121 sections.update(custom_sections)
122 self._sections = list(sections.iteritems())
123 else:
124 self._sections = list(DEFAULT_SECTIONS)
117 125
118 def __iter__(self): 126 def __iter__(self):
119 return iter(self._sections) 127 return iter(self._sections)
120 128
121 def names(self): 129 def names(self):
125 for name, value in self._sections: 133 for name, value in self._sections:
126 if value == title: 134 if value == title:
127 return name 135 return name
128 136
129 return None 137 return None
138
139 def getcustomadmonitions(repo):
140 ctx = repo['.']
141 p = config.config()
142
143 def read(f, sections=None, remap=None):
144 if f in ctx:
145 data = ctx[f].data()
146 p.parse(f, data, sections, remap, read)
147 else:
148 raise error.Abort(_(".hgreleasenotes file \'%s\' not found") %
149 repo.pathto(f))
150
151 if '.hgreleasenotes' in ctx:
152 read('.hgreleasenotes')
153 return p['sections']
130 154
131 def parsenotesfromrevisions(repo, directives, revs): 155 def parsenotesfromrevisions(repo, directives, revs):
132 notes = parsedreleasenotes() 156 notes = parsedreleasenotes()
133 157
134 for rev in revs: 158 for rev in revs:
394 This means that the release notes file can be updated independently from 418 This means that the release notes file can be updated independently from
395 this command and changes should not be lost when running this command on 419 this command and changes should not be lost when running this command on
396 that file. A particular use case for this is to tweak the wording of a 420 that file. A particular use case for this is to tweak the wording of a
397 release note after it has been added to the release notes file. 421 release note after it has been added to the release notes file.
398 """ 422 """
399 sections = releasenotessections(ui) 423 sections = releasenotessections(ui, repo)
400 424
401 revs = scmutil.revrange(repo, [rev or 'not public()']) 425 revs = scmutil.revrange(repo, [rev or 'not public()'])
402 incoming = parsenotesfromrevisions(repo, sections.names(), revs) 426 incoming = parsenotesfromrevisions(repo, sections.names(), revs)
403 427
404 try: 428 try:
414 438
415 with open(file_, 'wb') as fh: 439 with open(file_, 'wb') as fh:
416 fh.write(serializenotes(sections, notes)) 440 fh.write(serializenotes(sections, notes))
417 441
418 @command('debugparsereleasenotes', norepo=True) 442 @command('debugparsereleasenotes', norepo=True)
419 def debugparsereleasenotes(ui, path): 443 def debugparsereleasenotes(ui, path, repo=None):
420 """parse release notes and print resulting data structure""" 444 """parse release notes and print resulting data structure"""
421 if path == '-': 445 if path == '-':
422 text = sys.stdin.read() 446 text = sys.stdin.read()
423 else: 447 else:
424 with open(path, 'rb') as fh: 448 with open(path, 'rb') as fh:
425 text = fh.read() 449 text = fh.read()
426 450
427 sections = releasenotessections(ui) 451 sections = releasenotessections(ui, repo)
428 452
429 notes = parsereleasenotesfile(sections, text) 453 notes = parsereleasenotesfile(sections, text)
430 454
431 for section in notes: 455 for section in notes:
432 ui.write(_('section: %s\n') % section) 456 ui.write(_('section: %s\n') % section)