# HG changeset patch # User Jun Wu # Date 1499995895 25200 # Node ID 8056481caa818a3b56f7c0f4e4205a09b3de25af # Parent 0720e6265c8ad1dded51af78244bee96db3d3f5f 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 diff -r 0720e6265c8a -r 8056481caa81 hgext/largefiles/lfutil.py --- 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)) diff -r 0720e6265c8a -r 8056481caa81 mercurial/cmdutil.py --- 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=''): diff -r 0720e6265c8a -r 8056481caa81 mercurial/debugcommands.py --- 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')), diff -r 0720e6265c8a -r 8056481caa81 mercurial/upgrade.py --- 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'))