Mercurial > public > mercurial-scm > hg
comparison 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 |
comparison
equal
deleted
inserted
replaced
33437:0720e6265c8a | 33438:8056481caa81 |
---|---|
2748 | 2748 |
2749 ui.note(_('amending changeset %s\n') % old) | 2749 ui.note(_('amending changeset %s\n') % old) |
2750 base = old.p1() | 2750 base = old.p1() |
2751 | 2751 |
2752 newid = None | 2752 newid = None |
2753 with repo.wlock(), repo.lock(): | 2753 with repo.wlock(), repo.lock(), repo.transaction('amend') as tr: |
2754 with repo.transaction('amend') as tr: | 2754 # See if we got a message from -m or -l, if not, open the editor |
2755 # See if we got a message from -m or -l, if not, open the editor | 2755 # with the message of the changeset to amend |
2756 # with the message of the changeset to amend | 2756 message = logmessage(ui, opts) |
2757 message = logmessage(ui, opts) | 2757 # ensure logfile does not conflict with later enforcement of the |
2758 # ensure logfile does not conflict with later enforcement of the | 2758 # message. potential logfile content has been processed by |
2759 # message. potential logfile content has been processed by | 2759 # `logmessage` anyway. |
2760 # `logmessage` anyway. | 2760 opts.pop('logfile') |
2761 opts.pop('logfile') | 2761 # First, do a regular commit to record all changes in the working |
2762 # First, do a regular commit to record all changes in the working | 2762 # directory (if there are any) |
2763 # directory (if there are any) | 2763 ui.callhooks = False |
2764 ui.callhooks = False | 2764 activebookmark = repo._bookmarks.active |
2765 activebookmark = repo._bookmarks.active | 2765 try: |
2766 try: | 2766 repo._bookmarks.active = None |
2767 repo._bookmarks.active = None | 2767 opts['message'] = 'temporary amend commit for %s' % old |
2768 opts['message'] = 'temporary amend commit for %s' % old | 2768 node = commit(ui, repo, commitfunc, pats, opts) |
2769 node = commit(ui, repo, commitfunc, pats, opts) | 2769 finally: |
2770 finally: | 2770 repo._bookmarks.active = activebookmark |
2771 repo._bookmarks.active = activebookmark | 2771 repo._bookmarks.recordchange(tr) |
2772 repo._bookmarks.recordchange(tr) | 2772 ui.callhooks = True |
2773 ui.callhooks = True | 2773 ctx = repo[node] |
2774 ctx = repo[node] | 2774 |
2775 | 2775 # Participating changesets: |
2776 # Participating changesets: | 2776 # |
2777 # node/ctx o - new (intermediate) commit that contains changes | |
2778 # | from working dir to go into amending commit | |
2779 # | (or a workingctx if there were no changes) | |
2780 # | | |
2781 # old o - changeset to amend | |
2782 # | | |
2783 # base o - parent of amending changeset | |
2784 | |
2785 # Update extra dict from amended commit (e.g. to preserve graft | |
2786 # source) | |
2787 extra.update(old.extra()) | |
2788 | |
2789 # Also update it from the intermediate commit or from the wctx | |
2790 extra.update(ctx.extra()) | |
2791 | |
2792 if len(old.parents()) > 1: | |
2793 # ctx.files() isn't reliable for merges, so fall back to the | |
2794 # slower repo.status() method | |
2795 files = set([fn for st in repo.status(base, old)[:3] | |
2796 for fn in st]) | |
2797 else: | |
2798 files = set(old.files()) | |
2799 | |
2800 # Second, we use either the commit we just did, or if there were no | |
2801 # changes the parent of the working directory as the version of the | |
2802 # files in the final amend commit | |
2803 if node: | |
2804 ui.note(_('copying changeset %s to %s\n') % (ctx, base)) | |
2805 | |
2806 user = ctx.user() | |
2807 date = ctx.date() | |
2808 # Recompute copies (avoid recording a -> b -> a) | |
2809 copied = copies.pathcopies(base, ctx) | |
2810 if old.p2: | |
2811 copied.update(copies.pathcopies(old.p2(), ctx)) | |
2812 | |
2813 # Prune files which were reverted by the updates: if old | |
2814 # introduced file X and our intermediate commit, node, | |
2815 # renamed that file, then those two files are the same and | |
2816 # we can discard X from our list of files. Likewise if X | |
2817 # was deleted, it's no longer relevant | |
2818 files.update(ctx.files()) | |
2819 files = [f for f in files if not samefile(f, ctx, base)] | |
2820 | |
2821 def filectxfn(repo, ctx_, path): | |
2822 try: | |
2823 fctx = ctx[path] | |
2824 flags = fctx.flags() | |
2825 mctx = context.memfilectx(repo, | |
2826 fctx.path(), fctx.data(), | |
2827 islink='l' in flags, | |
2828 isexec='x' in flags, | |
2829 copied=copied.get(path)) | |
2830 return mctx | |
2831 except KeyError: | |
2832 return None | |
2833 else: | |
2834 ui.note(_('copying changeset %s to %s\n') % (old, base)) | |
2835 | |
2836 # Use version of files as in the old cset | |
2837 def filectxfn(repo, ctx_, path): | |
2838 try: | |
2839 return old.filectx(path) | |
2840 except KeyError: | |
2841 return None | |
2842 | |
2843 user = opts.get('user') or old.user() | |
2844 date = opts.get('date') or old.date() | |
2845 editform = mergeeditform(old, 'commit.amend') | |
2846 editor = getcommiteditor(editform=editform, | |
2847 **pycompat.strkwargs(opts)) | |
2848 if not message: | |
2849 editor = getcommiteditor(edit=True, editform=editform) | |
2850 message = old.description() | |
2851 | |
2852 pureextra = extra.copy() | |
2853 extra['amend_source'] = old.hex() | |
2854 | |
2855 new = context.memctx(repo, | |
2856 parents=[base.node(), old.p2().node()], | |
2857 text=message, | |
2858 files=files, | |
2859 filectxfn=filectxfn, | |
2860 user=user, | |
2861 date=date, | |
2862 extra=extra, | |
2863 editor=editor) | |
2864 | |
2865 newdesc = changelog.stripdesc(new.description()) | |
2866 if ((not node) | |
2867 and newdesc == old.description() | |
2868 and user == old.user() | |
2869 and date == old.date() | |
2870 and pureextra == old.extra()): | |
2871 # nothing changed. continuing here would create a new node | |
2872 # anyway because of the amend_source noise. | |
2777 # | 2873 # |
2778 # node/ctx o - new (intermediate) commit that contains changes | 2874 # This not what we expect from amend. |
2779 # | from working dir to go into amending commit | 2875 return old.node() |
2780 # | (or a workingctx if there were no changes) | 2876 |
2781 # | | 2877 ph = repo.ui.config('phases', 'new-commit', phases.draft) |
2782 # old o - changeset to amend | 2878 try: |
2783 # | | 2879 if opts.get('secret'): |
2784 # base o - parent of amending changeset | 2880 commitphase = 'secret' |
2785 | |
2786 # Update extra dict from amended commit (e.g. to preserve graft | |
2787 # source) | |
2788 extra.update(old.extra()) | |
2789 | |
2790 # Also update it from the intermediate commit or from the wctx | |
2791 extra.update(ctx.extra()) | |
2792 | |
2793 if len(old.parents()) > 1: | |
2794 # ctx.files() isn't reliable for merges, so fall back to the | |
2795 # slower repo.status() method | |
2796 files = set([fn for st in repo.status(base, old)[:3] | |
2797 for fn in st]) | |
2798 else: | 2881 else: |
2799 files = set(old.files()) | 2882 commitphase = old.phase() |
2800 | 2883 repo.ui.setconfig('phases', 'new-commit', commitphase, 'amend') |
2801 # Second, we use either the commit we just did, or if there were no | 2884 newid = repo.commitctx(new) |
2802 # changes the parent of the working directory as the version of the | 2885 finally: |
2803 # files in the final amend commit | 2886 repo.ui.setconfig('phases', 'new-commit', ph, 'amend') |
2887 if newid != old.node(): | |
2888 # Reroute the working copy parent to the new changeset | |
2889 repo.setparents(newid, nullid) | |
2890 mapping = {old.node(): (newid,)} | |
2804 if node: | 2891 if node: |
2805 ui.note(_('copying changeset %s to %s\n') % (ctx, base)) | 2892 mapping[node] = () |
2806 | 2893 scmutil.cleanupnodes(repo, mapping, 'amend') |
2807 user = ctx.user() | |
2808 date = ctx.date() | |
2809 # Recompute copies (avoid recording a -> b -> a) | |
2810 copied = copies.pathcopies(base, ctx) | |
2811 if old.p2: | |
2812 copied.update(copies.pathcopies(old.p2(), ctx)) | |
2813 | |
2814 # Prune files which were reverted by the updates: if old | |
2815 # introduced file X and our intermediate commit, node, | |
2816 # renamed that file, then those two files are the same and | |
2817 # we can discard X from our list of files. Likewise if X | |
2818 # was deleted, it's no longer relevant | |
2819 files.update(ctx.files()) | |
2820 files = [f for f in files if not samefile(f, ctx, base)] | |
2821 | |
2822 def filectxfn(repo, ctx_, path): | |
2823 try: | |
2824 fctx = ctx[path] | |
2825 flags = fctx.flags() | |
2826 mctx = context.memfilectx(repo, | |
2827 fctx.path(), fctx.data(), | |
2828 islink='l' in flags, | |
2829 isexec='x' in flags, | |
2830 copied=copied.get(path)) | |
2831 return mctx | |
2832 except KeyError: | |
2833 return None | |
2834 else: | |
2835 ui.note(_('copying changeset %s to %s\n') % (old, base)) | |
2836 | |
2837 # Use version of files as in the old cset | |
2838 def filectxfn(repo, ctx_, path): | |
2839 try: | |
2840 return old.filectx(path) | |
2841 except KeyError: | |
2842 return None | |
2843 | |
2844 user = opts.get('user') or old.user() | |
2845 date = opts.get('date') or old.date() | |
2846 editform = mergeeditform(old, 'commit.amend') | |
2847 editor = getcommiteditor(editform=editform, | |
2848 **pycompat.strkwargs(opts)) | |
2849 if not message: | |
2850 editor = getcommiteditor(edit=True, editform=editform) | |
2851 message = old.description() | |
2852 | |
2853 pureextra = extra.copy() | |
2854 extra['amend_source'] = old.hex() | |
2855 | |
2856 new = context.memctx(repo, | |
2857 parents=[base.node(), old.p2().node()], | |
2858 text=message, | |
2859 files=files, | |
2860 filectxfn=filectxfn, | |
2861 user=user, | |
2862 date=date, | |
2863 extra=extra, | |
2864 editor=editor) | |
2865 | |
2866 newdesc = changelog.stripdesc(new.description()) | |
2867 if ((not node) | |
2868 and newdesc == old.description() | |
2869 and user == old.user() | |
2870 and date == old.date() | |
2871 and pureextra == old.extra()): | |
2872 # nothing changed. continuing here would create a new node | |
2873 # anyway because of the amend_source noise. | |
2874 # | |
2875 # This not what we expect from amend. | |
2876 return old.node() | |
2877 | |
2878 ph = repo.ui.config('phases', 'new-commit', phases.draft) | |
2879 try: | |
2880 if opts.get('secret'): | |
2881 commitphase = 'secret' | |
2882 else: | |
2883 commitphase = old.phase() | |
2884 repo.ui.setconfig('phases', 'new-commit', commitphase, 'amend') | |
2885 newid = repo.commitctx(new) | |
2886 finally: | |
2887 repo.ui.setconfig('phases', 'new-commit', ph, 'amend') | |
2888 if newid != old.node(): | |
2889 # Reroute the working copy parent to the new changeset | |
2890 repo.setparents(newid, nullid) | |
2891 mapping = {old.node(): (newid,)} | |
2892 if node: | |
2893 mapping[node] = () | |
2894 scmutil.cleanupnodes(repo, mapping, 'amend') | |
2895 return newid | 2894 return newid |
2896 | 2895 |
2897 def commiteditor(repo, ctx, subs, editform=''): | 2896 def commiteditor(repo, ctx, subs, editform=''): |
2898 if ctx.description(): | 2897 if ctx.description(): |
2899 return ctx.description() | 2898 return ctx.description() |