# HG changeset patch # User Christian Ebert # Date 1166280825 -3600 # Node ID 536c1797202d57efb77bea098e10968ff01602ce # Parent 6dc2b42689208e3d41e7a52111b49e819bb507e3 Implement $Hg$ scheme with update hook The pivotal line for update hook is: repo.dirstate.update(kwupdates, 'n') This forces hg to consider the freshly written files as not modified. Thanks to wfile(), this keeps executable bits etc. Still needs more testing. No need to check for basename/filename in keyword trigger. update hook does not need re. TODO: Walk back in history, if last change of file didn't happen in 1 of the provided changesets (update/merge?)? diff -r 6dc2b4268920 -r 536c1797202d hgkw/kwexpander.py --- a/hgkw/kwexpander.py Sat Dec 16 15:42:27 2006 +0100 +++ b/hgkw/kwexpander.py Sat Dec 16 15:53:45 2006 +0100 @@ -1,56 +1,68 @@ -# $Hg: kwexpander.py,v$ +# $Hg$ -from mercurial.i18n import gettext as _ -from mercurial.demandload import demandload -demandload(globals(), 'mercurial:util') -demandload(globals(), 'os.path re sys') +from mercurial import demandimport +demandimport.enable() + +from mercurial.i18n import _ +import mercurial.util, re # name of keyword encode filter: kwencodefilter = 'hgkwencode' +# look for Hg +kwtrigger = '%sHg$' % '$' -def expandkw(ui, repo, parent1, node, candidates): +def wwritekw(ui, repo, f, text): + '''Writes text with kwupdates keywords to f in working directory.''' + ui.note(_('expanding keywords in %s\n' % f)) +# # backup file (?) +# absfile = repo.wjoin(f) +# mercurial.util.copyfile(absfile, absfile+'.kwbak') + repo.wfile(f, 'w').write(text) + +def expandkw(ui, repo, node, cid, candidates, update=False): '''Important: returns False on success, True on failure.''' + # only check files that have hgkwencode assigned as encode filter files = [] for pat, cmd in repo.ui.configitems('encode'): if cmd.endswith(kwencodefilter): - mf = util.matcher(repo.root, '', [pat], [], [])[1] + mf = mercurial.util.matcher(repo.root, '', [pat], [], [])[1] for candidate in candidates: if mf(candidate): + # check again that there really are no duplicates + # if candidate not in files ??? files.append(candidate) if not files: # nothing to do return False - user, date = repo.changelog.read(parent1)[1:3] - user = util.shortuser(user) - date = util.datestr(date=date, format=util.defaultdateformats[2]) - # %Y-%m-%d %H:%M - re_kwcheck = re.compile(r'[$]Hg: (.*?),v.*?\$') + user, date = repo.changelog.read(node)[1:3] + user = mercurial.util.shortuser(user) + date = mercurial.util.datestr(date=date, + format=mercurial.util.defaultdateformats[2]) + # %Y-%m-%d %H:%M - for fn in files: + # collect filenames that were changed by hg update + kwupdates = [] - data = repo.wopener(fn, 'rb').read() - bn = os.path.basename(fn) + for f in files: + + text = repo.wfile(f).read() + kwrepl = '%sHg: %s,v %s %s %s $' % ('$', f, cid, date, user) - # check for keywords with incorrect basename - # eg. if you forgot to update basename manually after "hg mv" - failures = [m for m in map(str, re_kwcheck.findall(data)) if m != bn] - if failures: - failures = ['%sHg: %s,v$' % ('$', nobn) for nobn in failures] - ui.warn(_('%d incorrect basenames in file %s:\n' - '%s\nplease correct to %sHg: %s,v$\n' - % (len(failures), fn, ', '.join(failures), '$', bn))) - return True + if update and text.find(kwtrigger) > -1: + text = text.replace(kwtrigger, kwrepl) + wwritekw(ui, repo, f, text) + kwupdates.append(f) + + elif not update: + re_kw = re.compile(r'[$]Hg(: %s,v [a-z0-9]{12} [^$]+? )?\$' % f) + text, kwct = re_kw.subn(kwrepl, text) + if kwct: + wwritekw(ui, repo, f, text) - # substitute (Hg|Id): ,v.* - re_kw = re.compile(r'([$]Hg: %s,v).*?\$' % bn) - data, kwct = re_kw.subn(r'\1 %s %s %s $' % (node, date, user), data) - - if kwct: - # backup file and write with expanded keyword - ui.note(_('expanding keywords in %s\n' % fn)) - util.copyfile(fn, fn+'~') - repo.wopener(fn, 'wb').write(data) + if kwupdates: + # cheat hg to believe that updated files were not modified + repo.dirstate.update(kwupdates, 'n') return False