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()