Mercurial > hg
view hgext/automv.py @ 43678:52e4bfebc4ba
setup: conditionalize access to `sys.dllhandle` when building extensions
This code is only run on Windows, and was crashing PyOxidizer when running in
`setup-py-install` mode. Now an oxidized binary can be built by simply pointing
to setup.py.
Something is slightly different now that it's not being built from a virtualenv.
Previously, `hg version` could print to the screen, but now it aborts saying
"Incorrect function". But I can see the output if redirected to a file, and
it's not complaining about missing C extensions, so I think those are loading
now (unlike from the virtualenv). The interesting this about this incorrect
function output is that it failed when initially built. I then went back and
did a `make clean` and `make local` with py3 and then py2 to ensure I didn't
break the existing code. At that point I ran the oxidized executable again and
it was able to print to the screen normally! So I ran `pyoxidizer build` again,
it only output the following, and then running the executable failed to output
again:
(pyO2_venv) C:\Users\Matt\hg3\hg_pyO2>pyoxidizer build
Finished dev [unoptimized + debuginfo] target(s) in 0.12s
packaging application into C:/Users/Matt/hg3/hg_pyO2\build\apps\hg_pyO2\x86_64-pc-windows-msvc\debug
purging C:/Users/Matt/hg3/hg_pyO2\build\apps\hg_pyO2\x86_64-pc-windows-msvc\debug
copying C:/Users/Matt/hg3/hg_pyO2\build\target\x86_64-pc-windows-msvc\debug\hg_pyO2.exe to
C:/Users/Matt/hg3/hg_pyO2\build\apps\hg_pyO2\x86_64-pc-windows-msvc\debug\hg_pyO2.exe
resolving packaging state...
writing license for [...]
hg_pyO2 packaged into C:/Users/Matt/hg3/hg_pyO2\build\apps\hg_pyO2\x86_64-pc-windows-msvc\debug
executable path: C:/Users/Matt/hg3/hg_pyO2\build\apps\hg_pyO2\x86_64-pc-windows-msvc\debug\hg_pyO2.exe
Differential Revision: https://phab.mercurial-scm.org/D7444
author | Matt Harbison <matt_harbison@yahoo.com> |
---|---|
date | Sat, 16 Nov 2019 12:19:43 -0500 |
parents | 687b865b95ad |
children | 89a2afe31e82 |
line wrap: on
line source
# automv.py # # Copyright 2013-2016 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. """check for unrecorded moves at commit time (EXPERIMENTAL) This extension checks at commit/amend time if any of the committed files comes from an unrecorded mv. The threshold at which a file is considered a move can be set with the ``automv.similarity`` config option. This option takes a percentage between 0 (disabled) and 100 (files must be identical), the default is 95. """ # Using 95 as a default similarity is based on an analysis of the mercurial # repositories of the cpython, mozilla-central & mercurial repositories, as # well as 2 very large facebook repositories. At 95 50% of all potential # missed moves would be caught, as well as correspond with 87% of all # explicitly marked moves. Together, 80% of moved files are 95% similar or # more. # # See http://markmail.org/thread/5pxnljesvufvom57 for context. from __future__ import absolute_import from mercurial.i18n import _ from mercurial import ( commands, copies, error, extensions, pycompat, registrar, scmutil, similar, ) configtable = {} configitem = registrar.configitem(configtable) configitem( b'automv', b'similarity', default=95, ) def extsetup(ui): entry = extensions.wrapcommand(commands.table, b'commit', mvcheck) entry[1].append( (b'', b'no-automv', None, _(b'disable automatic file move detection')) ) def mvcheck(orig, ui, repo, *pats, **opts): """Hook to check for moves at commit time""" opts = pycompat.byteskwargs(opts) renames = None disabled = opts.pop(b'no_automv', False) if not disabled: threshold = ui.configint(b'automv', b'similarity') if not 0 <= threshold <= 100: raise error.Abort(_(b'automv.similarity must be between 0 and 100')) if threshold > 0: match = scmutil.match(repo[None], pats, opts) added, removed = _interestingfiles(repo, match) uipathfn = scmutil.getuipathfn(repo, legacyrelativevalue=True) renames = _findrenames( repo, uipathfn, added, removed, threshold / 100.0 ) with repo.wlock(): if renames is not None: scmutil._markchanges(repo, (), (), renames) return orig(ui, repo, *pats, **pycompat.strkwargs(opts)) def _interestingfiles(repo, matcher): """Find what files were added or removed in this commit. Returns a tuple of two lists: (added, removed). Only files not *already* marked as moved are included in the added list. """ stat = repo.status(match=matcher) added = stat.added removed = stat.removed copy = copies.pathcopies(repo[b'.'], repo[None], matcher) # remove the copy files for which we already have copy info added = [f for f in added if f not in copy] return added, removed def _findrenames(repo, uipathfn, added, removed, similarity): """Find what files in added are really moved files. Any file named in removed that is at least similarity% similar to a file in added is seen as a rename. """ renames = {} if similarity > 0: for src, dst, score in similar.findrenames( repo, added, removed, similarity ): if repo.ui.verbose: repo.ui.status( _(b'detected move of %s as %s (%d%% similar)\n') % (uipathfn(src), uipathfn(dst), score * 100) ) renames[dst] = src if renames: repo.ui.status(_(b'detected move of %d files\n') % len(renames)) return renames