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
--- a/hgext/largefiles/lfutil.py Mon Aug 08 18:14:42 2016 +0200
+++ b/hgext/largefiles/lfutil.py Thu Jul 13 18:31:35 2017 -0700
@@ -58,10 +58,9 @@
util.oslink(src, dest)
except OSError:
# if hardlinks fail, fallback on atomic copy
- with open(src, 'rb') as srcf:
- with util.atomictempfile(dest) as dstf:
- for chunk in util.filechunkiter(srcf):
- dstf.write(chunk)
+ with open(src, 'rb') as srcf, util.atomictempfile(dest) as dstf:
+ for chunk in util.filechunkiter(srcf):
+ dstf.write(chunk)
os.chmod(dest, os.stat(src).st_mode)
def usercachepath(ui, hash):
@@ -236,10 +235,9 @@
wvfs.makedirs(wvfs.dirname(wvfs.join(filename)))
# The write may fail before the file is fully written, but we
# don't use atomic writes in the working copy.
- with open(path, 'rb') as srcfd:
- with wvfs(filename, 'wb') as destfd:
- gothash = copyandhash(
- util.filechunkiter(srcfd), destfd)
+ with open(path, 'rb') as srcfd, wvfs(filename, 'wb') as destfd:
+ gothash = copyandhash(
+ util.filechunkiter(srcfd), destfd)
if gothash != hash:
repo.ui.warn(_('%s: data corruption in %s with hash %s\n')
% (filename, path, gothash))
--- 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=''):
--- a/mercurial/debugcommands.py Mon Aug 08 18:14:42 2016 +0200
+++ b/mercurial/debugcommands.py Thu Jul 13 18:31:35 2017 -0700
@@ -2177,9 +2177,8 @@
@command('debugupdatecaches', [])
def debugupdatecaches(ui, repo, *pats, **opts):
"""warm all known caches in the repository"""
- with repo.wlock():
- with repo.lock():
- repo.updatecaches()
+ with repo.wlock(), repo.lock():
+ repo.updatecaches()
@command('debugupgraderepo', [
('o', 'optimize', [], _('extra optimization to perform'), _('NAME')),
--- a/mercurial/upgrade.py Mon Aug 08 18:14:42 2016 +0200
+++ b/mercurial/upgrade.py Thu Jul 13 18:31:35 2017 -0700
@@ -792,35 +792,33 @@
upgradeactions = [a.name for a in actions]
ui.write(_('beginning upgrade...\n'))
- with repo.wlock():
- with repo.lock():
- ui.write(_('repository locked and read-only\n'))
- # Our strategy for upgrading the repository is to create a new,
- # temporary repository, write data to it, then do a swap of the
- # data. There are less heavyweight ways to do this, but it is easier
- # to create a new repo object than to instantiate all the components
- # (like the store) separately.
- tmppath = tempfile.mkdtemp(prefix='upgrade.', dir=repo.path)
- backuppath = None
- try:
- ui.write(_('creating temporary repository to stage migrated '
- 'data: %s\n') % tmppath)
- dstrepo = localrepo.localrepository(repo.baseui,
- path=tmppath,
- create=True)
+ with repo.wlock(), repo.lock():
+ ui.write(_('repository locked and read-only\n'))
+ # Our strategy for upgrading the repository is to create a new,
+ # temporary repository, write data to it, then do a swap of the
+ # data. There are less heavyweight ways to do this, but it is easier
+ # to create a new repo object than to instantiate all the components
+ # (like the store) separately.
+ tmppath = tempfile.mkdtemp(prefix='upgrade.', dir=repo.path)
+ backuppath = None
+ try:
+ ui.write(_('creating temporary repository to stage migrated '
+ 'data: %s\n') % tmppath)
+ dstrepo = localrepo.localrepository(repo.baseui,
+ path=tmppath,
+ create=True)
- with dstrepo.wlock():
- with dstrepo.lock():
- backuppath = _upgraderepo(ui, repo, dstrepo, newreqs,
- upgradeactions)
+ with dstrepo.wlock(), dstrepo.lock():
+ backuppath = _upgraderepo(ui, repo, dstrepo, newreqs,
+ upgradeactions)
- finally:
- ui.write(_('removing temporary repository %s\n') % tmppath)
- repo.vfs.rmtree(tmppath, forcibly=True)
+ finally:
+ ui.write(_('removing temporary repository %s\n') % tmppath)
+ repo.vfs.rmtree(tmppath, forcibly=True)
- if backuppath:
- ui.warn(_('copy of old repository backed up at %s\n') %
- backuppath)
- ui.warn(_('the old repository will not be deleted; remove '
- 'it to free up disk space once the upgraded '
- 'repository is verified\n'))
+ if backuppath:
+ ui.warn(_('copy of old repository backed up at %s\n') %
+ backuppath)
+ ui.warn(_('the old repository will not be deleted; remove '
+ 'it to free up disk space once the upgraded '
+ 'repository is verified\n'))