Mercurial > public > mercurial-scm > hg-stable
diff mercurial/cmdutil.py @ 33438:8056481caa81
codemod: simplify nested withs
This is the result of running:
python codemod_nestedwith.py **/*.py
where codemod_nestedwith.py looks like this:
#!/usr/bin/env python
# codemod_nestedwith.py - codemod tool to rewrite nested with
#
# Copyright 2017 Facebook, Inc.
#
# This software may be used and distributed according to the terms of the
# GNU General Public License version 2 or any later version.
from __future__ import absolute_import, print_function
import sys
import redbaron
def readpath(path):
with open(path) as f:
return f.read()
def writepath(path, content):
with open(path, 'w') as f:
f.write(content)
def main(argv):
if not argv:
print('Usage: codemod_nestedwith.py FILES')
for i, path in enumerate(argv):
print('(%d/%d) scanning %s' % (i + 1, len(argv), path))
changed = False
red = redbaron.RedBaron(readpath(path))
processed = set()
for node in red.find_all('with'):
if node in processed or node.type != 'with':
continue
top = node
child = top[0]
while True:
if len(top) > 1 or child.type != 'with':
break
# estimate line length after merging two "with"s
new = '%swith %s:' % (top.indentation, top.contexts.dumps())
new += ', %s' % child.contexts.dumps()
# only do the rewrite if the end result is within 80 chars
if len(new) > 80:
break
processed.add(child)
top.contexts.extend(child.contexts)
top.value = child.value
top.value.decrease_indentation(4)
child = child[0]
changed = True
if changed:
print('updating %s' % path)
writepath(path, red.dumps())
if __name__ == "__main__":
sys.exit(main(sys.argv[1:]))
Differential Revision: https://phab.mercurial-scm.org/D77
author | Jun Wu <quark@fb.com> |
---|---|
date | Thu, 13 Jul 2017 18:31:35 -0700 |
parents | e48fb90f80c8 |
children | 0407a51b9d8c |
line wrap: on
line diff
--- a/mercurial/cmdutil.py Mon Aug 08 18:14:42 2016 +0200 +++ b/mercurial/cmdutil.py Thu Jul 13 18:31:35 2017 -0700 @@ -2750,148 +2750,147 @@ base = old.p1() newid = None - with repo.wlock(), repo.lock(): - with repo.transaction('amend') as tr: - # See if we got a message from -m or -l, if not, open the editor - # with the message of the changeset to amend - message = logmessage(ui, opts) - # ensure logfile does not conflict with later enforcement of the - # message. potential logfile content has been processed by - # `logmessage` anyway. - opts.pop('logfile') - # First, do a regular commit to record all changes in the working - # directory (if there are any) - ui.callhooks = False - activebookmark = repo._bookmarks.active - try: - repo._bookmarks.active = None - opts['message'] = 'temporary amend commit for %s' % old - node = commit(ui, repo, commitfunc, pats, opts) - finally: - repo._bookmarks.active = activebookmark - repo._bookmarks.recordchange(tr) - ui.callhooks = True - ctx = repo[node] - - # Participating changesets: + with repo.wlock(), repo.lock(), repo.transaction('amend') as tr: + # See if we got a message from -m or -l, if not, open the editor + # with the message of the changeset to amend + message = logmessage(ui, opts) + # ensure logfile does not conflict with later enforcement of the + # message. potential logfile content has been processed by + # `logmessage` anyway. + opts.pop('logfile') + # First, do a regular commit to record all changes in the working + # directory (if there are any) + ui.callhooks = False + activebookmark = repo._bookmarks.active + try: + repo._bookmarks.active = None + opts['message'] = 'temporary amend commit for %s' % old + node = commit(ui, repo, commitfunc, pats, opts) + finally: + repo._bookmarks.active = activebookmark + repo._bookmarks.recordchange(tr) + ui.callhooks = True + ctx = repo[node] + + # Participating changesets: + # + # node/ctx o - new (intermediate) commit that contains changes + # | from working dir to go into amending commit + # | (or a workingctx if there were no changes) + # | + # old o - changeset to amend + # | + # base o - parent of amending changeset + + # Update extra dict from amended commit (e.g. to preserve graft + # source) + extra.update(old.extra()) + + # Also update it from the intermediate commit or from the wctx + extra.update(ctx.extra()) + + if len(old.parents()) > 1: + # ctx.files() isn't reliable for merges, so fall back to the + # slower repo.status() method + files = set([fn for st in repo.status(base, old)[:3] + for fn in st]) + else: + files = set(old.files()) + + # Second, we use either the commit we just did, or if there were no + # changes the parent of the working directory as the version of the + # files in the final amend commit + if node: + ui.note(_('copying changeset %s to %s\n') % (ctx, base)) + + user = ctx.user() + date = ctx.date() + # Recompute copies (avoid recording a -> b -> a) + copied = copies.pathcopies(base, ctx) + if old.p2: + copied.update(copies.pathcopies(old.p2(), ctx)) + + # Prune files which were reverted by the updates: if old + # introduced file X and our intermediate commit, node, + # renamed that file, then those two files are the same and + # we can discard X from our list of files. Likewise if X + # was deleted, it's no longer relevant + files.update(ctx.files()) + files = [f for f in files if not samefile(f, ctx, base)] + + def filectxfn(repo, ctx_, path): + try: + fctx = ctx[path] + flags = fctx.flags() + mctx = context.memfilectx(repo, + fctx.path(), fctx.data(), + islink='l' in flags, + isexec='x' in flags, + copied=copied.get(path)) + return mctx + except KeyError: + return None + else: + ui.note(_('copying changeset %s to %s\n') % (old, base)) + + # Use version of files as in the old cset + def filectxfn(repo, ctx_, path): + try: + return old.filectx(path) + except KeyError: + return None + + user = opts.get('user') or old.user() + date = opts.get('date') or old.date() + editform = mergeeditform(old, 'commit.amend') + editor = getcommiteditor(editform=editform, + **pycompat.strkwargs(opts)) + if not message: + editor = getcommiteditor(edit=True, editform=editform) + message = old.description() + + pureextra = extra.copy() + extra['amend_source'] = old.hex() + + new = context.memctx(repo, + parents=[base.node(), old.p2().node()], + text=message, + files=files, + filectxfn=filectxfn, + user=user, + date=date, + extra=extra, + editor=editor) + + newdesc = changelog.stripdesc(new.description()) + if ((not node) + and newdesc == old.description() + and user == old.user() + and date == old.date() + and pureextra == old.extra()): + # nothing changed. continuing here would create a new node + # anyway because of the amend_source noise. # - # node/ctx o - new (intermediate) commit that contains changes - # | from working dir to go into amending commit - # | (or a workingctx if there were no changes) - # | - # old o - changeset to amend - # | - # base o - parent of amending changeset - - # Update extra dict from amended commit (e.g. to preserve graft - # source) - extra.update(old.extra()) - - # Also update it from the intermediate commit or from the wctx - extra.update(ctx.extra()) - - if len(old.parents()) > 1: - # ctx.files() isn't reliable for merges, so fall back to the - # slower repo.status() method - files = set([fn for st in repo.status(base, old)[:3] - for fn in st]) + # This not what we expect from amend. + return old.node() + + ph = repo.ui.config('phases', 'new-commit', phases.draft) + try: + if opts.get('secret'): + commitphase = 'secret' else: - files = set(old.files()) - - # Second, we use either the commit we just did, or if there were no - # changes the parent of the working directory as the version of the - # files in the final amend commit + commitphase = old.phase() + repo.ui.setconfig('phases', 'new-commit', commitphase, 'amend') + newid = repo.commitctx(new) + finally: + repo.ui.setconfig('phases', 'new-commit', ph, 'amend') + if newid != old.node(): + # Reroute the working copy parent to the new changeset + repo.setparents(newid, nullid) + mapping = {old.node(): (newid,)} if node: - ui.note(_('copying changeset %s to %s\n') % (ctx, base)) - - user = ctx.user() - date = ctx.date() - # Recompute copies (avoid recording a -> b -> a) - copied = copies.pathcopies(base, ctx) - if old.p2: - copied.update(copies.pathcopies(old.p2(), ctx)) - - # Prune files which were reverted by the updates: if old - # introduced file X and our intermediate commit, node, - # renamed that file, then those two files are the same and - # we can discard X from our list of files. Likewise if X - # was deleted, it's no longer relevant - files.update(ctx.files()) - files = [f for f in files if not samefile(f, ctx, base)] - - def filectxfn(repo, ctx_, path): - try: - fctx = ctx[path] - flags = fctx.flags() - mctx = context.memfilectx(repo, - fctx.path(), fctx.data(), - islink='l' in flags, - isexec='x' in flags, - copied=copied.get(path)) - return mctx - except KeyError: - return None - else: - ui.note(_('copying changeset %s to %s\n') % (old, base)) - - # Use version of files as in the old cset - def filectxfn(repo, ctx_, path): - try: - return old.filectx(path) - except KeyError: - return None - - user = opts.get('user') or old.user() - date = opts.get('date') or old.date() - editform = mergeeditform(old, 'commit.amend') - editor = getcommiteditor(editform=editform, - **pycompat.strkwargs(opts)) - if not message: - editor = getcommiteditor(edit=True, editform=editform) - message = old.description() - - pureextra = extra.copy() - extra['amend_source'] = old.hex() - - new = context.memctx(repo, - parents=[base.node(), old.p2().node()], - text=message, - files=files, - filectxfn=filectxfn, - user=user, - date=date, - extra=extra, - editor=editor) - - newdesc = changelog.stripdesc(new.description()) - if ((not node) - and newdesc == old.description() - and user == old.user() - and date == old.date() - and pureextra == old.extra()): - # nothing changed. continuing here would create a new node - # anyway because of the amend_source noise. - # - # This not what we expect from amend. - return old.node() - - ph = repo.ui.config('phases', 'new-commit', phases.draft) - try: - if opts.get('secret'): - commitphase = 'secret' - else: - commitphase = old.phase() - repo.ui.setconfig('phases', 'new-commit', commitphase, 'amend') - newid = repo.commitctx(new) - finally: - repo.ui.setconfig('phases', 'new-commit', ph, 'amend') - if newid != old.node(): - # Reroute the working copy parent to the new changeset - repo.setparents(newid, nullid) - mapping = {old.node(): (newid,)} - if node: - mapping[node] = () - scmutil.cleanupnodes(repo, mapping, 'amend') + mapping[node] = () + scmutil.cleanupnodes(repo, mapping, 'amend') return newid def commiteditor(repo, ctx, subs, editform=''):