Mon, 10 Jul 2017 21:47:34 +0200 bookmark: deprecate direct set of a bookmark value
Boris Feld <boris.feld@octobus.net> [Mon, 10 Jul 2017 21:47:34 +0200] rev 33517
bookmark: deprecate direct set of a bookmark value We want all bookmark update to go through 'applychanges', so lets deprecate legacy ways of doing bookmark update.
Mon, 10 Jul 2017 20:26:53 +0200 bookmark: track bookmark changes at the transaction level
Boris Feld <boris.feld@octobus.net> [Mon, 10 Jul 2017 20:26:53 +0200] rev 33516
bookmark: track bookmark changes at the transaction level The transaction has now a 'bookmarks' dictionary in tr.changes. The structure of the dictionary is {BOOKMARK_NAME: (OLD_NODE, NEW_NODE)}. If a bookmark is deleted NEW_NODE will be None. If a bookmark is created OLD_NODE will be None. If the bookmark is updated multiple time, the initial value is preserved.
Mon, 10 Jul 2017 20:10:03 +0200 bookmark: deprecate 'recordchange' in favor of 'applychanges'
Boris Feld <boris.feld@octobus.net> [Mon, 10 Jul 2017 20:10:03 +0200] rev 33515
bookmark: deprecate 'recordchange' in favor of 'applychanges' Now that we have migrated all in-core caller of 'recordchange' to 'applychanges', deprecate 'recordchange' so external callers will move to the new unified method.
Mon, 10 Jul 2017 20:06:15 +0200 bookmark: drop deletedivergent
Boris Feld <boris.feld@octobus.net> [Mon, 10 Jul 2017 20:06:15 +0200] rev 33514
bookmark: drop deletedivergent It has no caller anymore.
Mon, 10 Jul 2017 20:02:32 +0200 bookmark: use 'divergent2delete' in checkconflict
Boris Feld <boris.feld@octobus.net> [Mon, 10 Jul 2017 20:02:32 +0200] rev 33513
bookmark: use 'divergent2delete' in checkconflict checkconflict used to also do some bookmark deletion in case of divergence. It is a bit suspicious given the function name, but it's not the goal of this series. In order to unify bookmarks changing, checkconflict now return the list of divergent bookmarks to clean up and the callers must clean them by calling applyphases.
Mon, 10 Jul 2017 19:12:25 +0200 bookmark: use 'divergent2delete' when updating a bookmark
Boris Feld <boris.feld@octobus.net> [Mon, 10 Jul 2017 19:12:25 +0200] rev 33512
bookmark: use 'divergent2delete' when updating a bookmark
Mon, 10 Jul 2017 19:10:13 +0200 bookmark: use 'divergent2delete' in 'scmutil.cleanupnode'
Boris Feld <boris.feld@octobus.net> [Mon, 10 Jul 2017 19:10:13 +0200] rev 33511
bookmark: use 'divergent2delete' in 'scmutil.cleanupnode'
Mon, 10 Jul 2017 19:08:17 +0200 bookmark: split out target computation from 'deletedivergent'
Boris Feld <boris.feld@octobus.net> [Mon, 10 Jul 2017 19:08:17 +0200] rev 33510
bookmark: split out target computation from 'deletedivergent' We want to use applychanges in order to unify bookmark movement. We need a way to compute divergence deletion without actually removing them. We split the function in two in this patch while we migrate the existing users of this code on next patches.
Mon, 10 Jul 2017 17:48:33 +0200 bookmark: remove a useless 'recordchange' in the amend code
Boris Feld <boris.feld@octobus.net> [Mon, 10 Jul 2017 17:48:33 +0200] rev 33509
bookmark: remove a useless 'recordchange' in the amend code We do not touch the bookmarks store in this code, just the active bookmark, not covered by the transaction. So it seems we can safely drop this call and the tests agree with us.
Sat, 15 Jul 2017 23:46:33 -0400 test-phase-exchange: stabilize for Windows
Matt Harbison <matt_harbison@yahoo.com> [Sat, 15 Jul 2017 23:46:33 -0400] rev 33508
test-phase-exchange: stabilize for Windows
Sat, 15 Jul 2017 15:23:29 -0400 debugignore: eliminate inconsistencies with `hg status` (issue5222)
Matt Harbison <matt_harbison@yahoo.com> [Sat, 15 Jul 2017 15:23:29 -0400] rev 33507
debugignore: eliminate inconsistencies with `hg status` (issue5222) Using a matcher for this command allows processing the named file(s) as relative to cwd. It also leverages the icasefs normalization logic the same way the status command does. (However, a false indicator is given for a nonexistent file in some cases, e.g. passing 'foo.REJ' when that file doesn't exist, and the rule is '*.rej'. Maybe the regex itself needs to be case insensitive on these platforms, at least for the debug command.) Finally, the file printed is relative to cwd and uses platform specific slashes, so a few (glob)s were needed in seemingly unrelated tests.
Sun, 16 Jul 2017 04:39:32 -0700 commandserver: close selector explicitly
Jun Wu <quark@fb.com> [Sun, 16 Jul 2017 04:39:32 -0700] rev 33506
commandserver: close selector explicitly The selector does not have a __del__ method and needs a manual close. We can also use "with selector" but that makes the code too indented. Therefore append a "selector.close()" after the end of the main loop for now.
Sat, 15 Jul 2017 15:01:29 +0900 scmutil: remove duplicated import of i18n._()
Yuya Nishihara <yuya@tcha.org> [Sat, 15 Jul 2017 15:01:29 +0900] rev 33505
scmutil: remove duplicated import of i18n._()
Sun, 04 Jun 2017 10:02:09 -0700 obsstore: let read marker API take a range of offsets
Jun Wu <quark@fb.com> [Sun, 04 Jun 2017 10:02:09 -0700] rev 33504
obsstore: let read marker API take a range of offsets This allows us to read a customized range of markers, instead of loading all of them. The condition of stop is made consistent across C and Python implementation so we will still read marker when offset=a, stop=a+1.
Fri, 14 Jul 2017 20:26:21 -0700 commandserver: use selectors2
Jun Wu <quark@fb.com> [Fri, 14 Jul 2017 20:26:21 -0700] rev 33503
commandserver: use selectors2 Previously, commandserver was using select.select. That could have issue if _sock.fileno() >= FD_SETSIZE (usually 1024), which raises: ValueError: filedescriptor out of range in select() We got that in production today, although it's the code opening that many files to blame, it seems better for commandserver to work in this case. There are multiple way to "solve" it, like preserving a fd with a small number and swap it with sock using dup2(). But upgrading to a modern selector supported by the system seems to be the most correct way.
Fri, 14 Jul 2017 20:19:46 -0700 selector2: vendor selector2 library
Jun Wu <quark@fb.com> [Fri, 14 Jul 2017 20:19:46 -0700] rev 33502
selector2: vendor selector2 library This library was a backport of the Python 3 "selectors" library. It is useful to provide a better selector interface for Python2, to address some issues of the plain old select.select, mentioned in the next patch. The code [1] was ported using the MIT license, with some minor modifications to make our test happy: 1. "# no-check-code" was added since it's foreign code. 2. "from __future__ import absolute_import" was added. 3. "from collections import namedtuple, Mapping" changed to avoid direct symbol import. [1]: https://github.com/SethMichaelLarson/selectors2/blob/d27dbd2fdc48331fb76ed431f44b6e6956de7f82/selectors2.py # no-check-commit
Tue, 11 Jul 2017 00:40:29 -0400 context: name files relative to cwd in warning messages
Matt Harbison <matt_harbison@yahoo.com> [Tue, 11 Jul 2017 00:40:29 -0400] rev 33501
context: name files relative to cwd in warning messages I was several directories deep in the kernel tree, ran `hg add`, and got the warning about the size of one of the files. I noticed that it suggested undoing the add with a specific revert command. The problem is, it would have failed since the path printed was relative to the repo root instead of cwd. While here, I just fixed the other messages too. As an added benefit, these messages now look the same as the verbose/inexact messages for the corresponding command. I don't think most of these messages are reachable (typically the corresponding cmdutil function does the check). I wasn't able to figure out why the keyword tests were failing when using pathto()- I couldn't cause an absolute path to be used by manipulating the --cwd flag on a regular add. (I did notice that keyword is adding the file without holding wlock.)
Sat, 15 Jul 2017 00:52:36 -0400 run-tests: disable color on Windows
Matt Harbison <matt_harbison@yahoo.com> [Sat, 15 Jul 2017 00:52:36 -0400] rev 33500
run-tests: disable color on Windows More Windows sadness. Maybe someone can figure out how to make win32 color work, but I think we avoid importing stuff from the mercurial package in this module. On the plus side, this conditionalizes away a test failure.
Fri, 14 Jul 2017 14:22:40 -0700 codemod: register core configitems using a script
Jun Wu <quark@fb.com> [Fri, 14 Jul 2017 14:22:40 -0700] rev 33499
codemod: register core configitems using a script This is done by a script [2] using RedBaron [1], a tool designed for doing code refactoring. All "default" values are decided by the script and are strongly consistent with the existing code. There are 2 changes done manually to fix tests: [warn] mercurial/exchange.py: experimental.bundle2-output-capture: default needs manual removal [warn] mercurial/localrepo.py: experimental.hook-track-tags: default needs manual removal Since RedBaron is not confident about how to indent things [2]. [1]: https://github.com/PyCQA/redbaron [2]: https://github.com/PyCQA/redbaron/issues/100 [3]: #!/usr/bin/env python # codemod_configitems.py - codemod tool to fill configitems # # 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 os 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) _configmethods = {'config', 'configbool', 'configint', 'configbytes', 'configlist', 'configdate'} def extractstring(rnode): """get the string from a RedBaron string or call_argument node""" while rnode.type != 'string': rnode = rnode.value return rnode.value[1:-1] # unquote, "'str'" -> "str" def uiconfigitems(red): """match *.ui.config* pattern, yield (node, method, args, section, name)""" for node in red.find_all('atomtrailers'): entry = None try: obj = node[-3].value method = node[-2].value args = node[-1] section = args[0].value name = args[1].value if (obj in ('ui', 'self') and method in _configmethods and section.type == 'string' and name.type == 'string'): entry = (node, method, args, extractstring(section), extractstring(name)) except Exception: pass else: if entry: yield entry def coreconfigitems(red): """match coreconfigitem(...) pattern, yield (node, args, section, name)""" for node in red.find_all('atomtrailers'): entry = None try: args = node[1] section = args[0].value name = args[1].value if (node[0].value == 'coreconfigitem' and section.type == 'string' and name.type == 'string'): entry = (node, args, extractstring(section), extractstring(name)) except Exception: pass else: if entry: yield entry def registercoreconfig(cfgred, section, name, defaultrepr): """insert coreconfigitem to cfgred AST section and name are plain string, defaultrepr is a string """ # find a place to insert the "coreconfigitem" item entries = list(coreconfigitems(cfgred)) for node, args, nodesection, nodename in reversed(entries): if (nodesection, nodename) < (section, name): # insert after this entry node.insert_after( 'coreconfigitem(%r, %r,\n' ' default=%s,\n' ')' % (section, name, defaultrepr)) return def main(argv): if not argv: print('Usage: codemod_configitems.py FILES\n' 'For example, FILES could be "{hgext,mercurial}/*/**.py"') dirname = os.path.dirname reporoot = dirname(dirname(dirname(os.path.abspath(__file__)))) # register configitems to this destination cfgpath = os.path.join(reporoot, 'mercurial', 'configitems.py') cfgred = redbaron.RedBaron(readpath(cfgpath)) # state about what to do registered = set((s, n) for n, a, s, n in coreconfigitems(cfgred)) toregister = {} # {(section, name): defaultrepr} coreconfigs = set() # {(section, name)}, whether it's used in core # first loop: scan all files before taking any action for i, path in enumerate(argv): print('(%d/%d) scanning %s' % (i + 1, len(argv), path)) iscore = ('mercurial' in path) and ('hgext' not in path) red = redbaron.RedBaron(readpath(path)) # find all repo.ui.config* and ui.config* calls, and collect their # section, name and default value information. for node, method, args, section, name in uiconfigitems(red): if section == 'web': # [web] section has some weirdness, ignore them for now continue defaultrepr = None key = (section, name) if len(args) == 2: if key in registered: continue if method == 'configlist': defaultrepr = 'list' elif method == 'configbool': defaultrepr = 'False' else: defaultrepr = 'None' elif len(args) >= 3 and (args[2].target is None or args[2].target.value == 'default'): # try to understand the "default" value dnode = args[2].value if dnode.type == 'name': if dnode.value in {'None', 'True', 'False'}: defaultrepr = dnode.value elif dnode.type == 'string': defaultrepr = repr(dnode.value[1:-1]) elif dnode.type in ('int', 'float'): defaultrepr = dnode.value # inconsistent default if key in toregister and toregister[key] != defaultrepr: defaultrepr = None # interesting to rewrite if key not in registered: if defaultrepr is None: print('[note] %s: %s.%s: unsupported default' % (path, section, name)) registered.add(key) # skip checking it again else: toregister[key] = defaultrepr if iscore: coreconfigs.add(key) # second loop: rewrite files given "toregister" result for path in argv: # reconstruct redbaron - trade CPU for memory red = redbaron.RedBaron(readpath(path)) changed = False for node, method, args, section, name in uiconfigitems(red): key = (section, name) defaultrepr = toregister.get(key) if defaultrepr is None or key not in coreconfigs: continue if len(args) >= 3 and (args[2].target is None or args[2].target.value == 'default'): try: del args[2] changed = True except Exception: # redbaron fails to do the rewrite due to indentation # see https://github.com/PyCQA/redbaron/issues/100 print('[warn] %s: %s.%s: default needs manual removal' % (path, section, name)) if key not in registered: print('registering %s.%s' % (section, name)) registercoreconfig(cfgred, section, name, defaultrepr) registered.add(key) if changed: print('updating %s' % path) writepath(path, red.dumps()) if toregister: print('updating configitems.py') writepath(cfgpath, cfgred.dumps()) if __name__ == "__main__": sys.exit(main(sys.argv[1:]))
Tue, 11 Jul 2017 08:52:55 -0700 phabricator: allow specifying reviewers on phabsend
Jun Wu <quark@fb.com> [Tue, 11 Jul 2017 08:52:55 -0700] rev 33498
phabricator: allow specifying reviewers on phabsend Sometimes people want to specify reviewer explicitly for a stack. The webpage only allows changing reviewer for one revision at a time. This patch adds a `--reviewer` flag to make it easier to specify reviewers. Test Plan: On a test Phabricator instance, enable `differential.allow-self-accept`, assign myself as a reviewer and make sure it works. Also try an invalid username and make sure it raises. Differential Revision: https://phab.mercurial-scm.org/D38
Tue, 11 Jul 2017 10:46:55 -0700 match: remove unused negatematcher
Martin von Zweigbergk <martinvonz@google.com> [Tue, 11 Jul 2017 10:46:55 -0700] rev 33497
match: remove unused negatematcher This was only used by the sparse extension's dirstate._ignore override, which no longer exists. Differential Revision: https://phab.mercurial-scm.org/D60
Tue, 11 Jul 2017 10:46:35 -0700 sparse: override dirstate.walk() instead of dirstate._ignore
Martin von Zweigbergk <martinvonz@google.com> [Tue, 11 Jul 2017 10:46:35 -0700] rev 33496
sparse: override dirstate.walk() instead of dirstate._ignore Instead of treating files that are outside the sparse config as ignored, this makes it so we list only those that are within the sparse config by passing the sparse matcher to dirstate.walk(). Once we add support for narrow (sparseness applied to history, not just working copy), we will need to do a similar restriction of the walk over manifests, so this will be more consistent then. It also simplifies the code a bit. Note that a side-effect of this change is that files outside the sparse config used to be listed as ignored, but they will now not be listed at all. This can be seen in the test case where "hg purge" no longer has any effect because it doesn't see that the files outside the space config exist. To fix that, I think we should add an option to dirstate.walk() to walk outside the sparse config. We might expose that to the user as --no-sparse flag to e.g. "hg status" and "hg purge", but that's work for another day. Differential Revision: https://phab.mercurial-scm.org/D59
Wed, 12 Jul 2017 15:24:47 -0700 patch: use devel.all-warnings to replace devel.all
Jun Wu <quark@fb.com> [Wed, 12 Jul 2017 15:24:47 -0700] rev 33495
patch: use devel.all-warnings to replace devel.all It appears to be a misspell in patch.py.
Wed, 12 Jul 2017 18:37:13 -0400 sslutil: inform the user about how to fix an incomplete certificate chain
Matt Harbison <matt_harbison@yahoo.com> [Wed, 12 Jul 2017 18:37:13 -0400] rev 33494
sslutil: inform the user about how to fix an incomplete certificate chain This is a Windows only thing. Unfortunately, the socket is closed at this point (so the certificate is unavailable to check the chain). That means it's printed out when verification fails as a guess, on the assumption that 1) most of the time verification won't fail, and 2) sites using expired or certs that are too new will be rare. Maybe this is an argument for adding more functionality to debugssl, to test for problems and print certificate info. Or maybe it's an argument for bundling certificates with the Windows builds. That idea was set aside when the enhanced SSL code went in last summer, and it looks like there were issues with using certifi on Windows anyway[1]. This was tested by deleting the certificate out of certmgr.msc > "Third-Party Root Certification Authorities" > "Certificates", seeing `hg pull` fail (with the new message), trying this command, and then successfully performing the pull command. [1] https://www.mercurial-scm.org/pipermail/mercurial-devel/2016-October/089573.html
Thu, 30 Mar 2017 00:27:46 -0400 debug: add a method to check the state of, and built an SSL cert chain
Matt Harbison <matt_harbison@yahoo.com> [Thu, 30 Mar 2017 00:27:46 -0400] rev 33493
debug: add a method to check the state of, and built an SSL cert chain This is only useful on Windows, and avoids the need to use Internet Explorer to build the certificate chain. I can see this being extended in the future to print information about the certificate(s) to help debug issues on any platform. Maybe even perform some of the python checks listed on the secure connections wiki page. But for now, all I need is 1) a command that can be invoked in a setup script to ensure the certificate is installed, and 2) a command that the user can run if/when a certificate changes in the future. It would have been nice to leverage the sslutil library to pick up host specific settings, but attempting to use sslutil.wrapsocket() failed the 'not sslsocket.cipher()' check in it and aborted. The output is a little more chatty than some commands, but I've seen the update take 10+ seconds, and this is only a debug command.
Wed, 29 Mar 2017 23:45:23 -0400 win32: add a method to trigger the Crypto API to complete a certificate chain
Matt Harbison <matt_harbison@yahoo.com> [Wed, 29 Mar 2017 23:45:23 -0400] rev 33492
win32: add a method to trigger the Crypto API to complete a certificate chain I started a thread[1] on the mailing list awhile ago, but the short version is that Windows doesn't ship with a full list of certificates[2]. Even if the server sends the whole chain, if Windows doesn't have the appropriate certificate pre-installed in its "Third-Party Root Certification Authorities" store, connections mysteriously fail with: abort: error: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:661) Windows expects the application to call the methods invoked here as part of the certificate verification, triggering a call out to Windows update if necessary, to complete the trust chain. The python bug to add this support[3] hasn't had any recent activity, and isn't targeting py27 anyway. The only work around that I could find (besides figuring out the certificate and walking through the import wizard) is to browse to the site in Internet Explorer. Opening the page with FireFox or Chrome didn't work. That's a pretty obscure way to fix a pretty obscure problem. We go to great lengths to demystify various SSL errors, but this case is clearly lacking. Let's try to make things easier to diagnose and fix. When I had trouble figuring out how to get ctypes to work with all of the API pointers, I found that there are other python projects[4] using this API to achieve the same thing. [1] https://www.mercurial-scm.org/pipermail/mercurial-devel/2017-April/096501.html [2] https://support.microsoft.com/en-us/help/931125/how-to-get-a-root-certificate-update-for-windows [3] https://bugs.python.org/issue20916 [4] https://github.com/nvaccess/nvda/blob/3b86bce2066b1934df14b96f2e83369900860ecf/source/updateCheck.py#L511
Mon, 10 Jul 2017 19:40:23 +0200 bookmarks: use 'applychanges' for bookmark update
Boris Feld <boris.feld@octobus.net> [Mon, 10 Jul 2017 19:40:23 +0200] rev 33491
bookmarks: use 'applychanges' for bookmark update There is still some use of 'deletedivergent' bookmark here. They will be taken care of later. The 'deletedivergent' code needs some rework before fitting in the new world.
Mon, 10 Jul 2017 17:46:47 +0200 bookmark: use 'applychanges' in 'repair.strip'
Boris Feld <boris.feld@octobus.net> [Mon, 10 Jul 2017 17:46:47 +0200] rev 33490
bookmark: use 'applychanges' in 'repair.strip'
Mon, 10 Jul 2017 17:44:25 +0200 bookmark: use 'applychanges' in the mq extension
Boris Feld <boris.feld@octobus.net> [Mon, 10 Jul 2017 17:44:25 +0200] rev 33489
bookmark: use 'applychanges' in the mq extension
Mon, 10 Jul 2017 17:37:48 +0200 bookmark: use 'applychanges' when stripping
Boris Feld <boris.feld@octobus.net> [Mon, 10 Jul 2017 17:37:48 +0200] rev 33488
bookmark: use 'applychanges' when stripping
(0) -30000 -10000 -3000 -1000 -300 -100 -50 -30 +30 +50 +100 +300 +1000 +3000 +10000 tip