Annoying API change in dirstate.py
Greg Ward
greg at gerg.ca
Mon Feb 15 08:18:25 CST 2010
Between 1.4 and 1.5, there was an API change to dirstate.walk() and
dirstate.status() that breaks two of my extensions. The changeset was
changeset: 10178:24ce8f0c0a39
user: Augie Fackler <durin42 at gmail.com>
date: Thu Dec 31 17:19:30 2009 -0600
files: contrib/perf.py hgext/inotify/__init__.py
mercurial/context.py mercurial/dirstate.py mercurial/localrepo.py
description:
dirstate: don't check state of subrepo directories
and the API change in particular is:
--- a/mercurial/dirstate.py
+++ b/mercurial/dirstate.py
@@ -425,7 +425,7 @@
[...]
- def walk(self, match, unknown, ignored):
+ def walk(self, match, subrepos, unknown, ignored):
[...]
- def status(self, match, ignored, clean, unknown):
+ def status(self, match, subrepos, ignored, clean, unknown):
Just to see how painful it would be, I started hacking up bfiles so it
can work with dirstate from either 1.4 or 1.5. Here is the best I
have been able to come up with (this is scattered fragments of a patch
to bfiles.py):
+_dirstate_version = None
+
+def _get_dirstate_version(ui):
+ global _dirstate_version
+ if _dirstate_version is None:
+ varnames = dirstate.dirstate.status.im_func.func_code.co_varnames
+ if 'subrepos' in varnames:
+ ui.debug('bfiles: dirstate.status() takes \'subrepos\':
this is hg 1.5\n')
+ _dirstate_version = '1.5'
+ else:
+ ui.debug('bfiles: dirstate.status() does not take
\'subrepos\': this is hg 1.4\n')
+ _dirstate_version = '1.4'
+
+ return _dirstate_version
[...]
+ if _get_dirstate_version(ui) == '1.5':
+ status_args = ([], False, False, False)
+ else:
+ status_args = (False, False, False)
+
matcher = match.match(repo.root, repo.getcwd(), pats, default='relpath')
- status = bfdirstate.status(matcher, False, False, False)
+ status = bfdirstate.status(matcher, *status_args)
[...]
+ if _get_dirstate_version(ui) == '1.5':
+ walk_args = ([], False, False)
+ else:
+ walk_args = (False, False)
matcher = _get_standin_matcher(repo, pats, opts)
- for standin in repo.dirstate.walk(matcher, False, False):
+ for standin in repo.dirstate.walk(matcher, *walk_args):
[...]
You get the idea. I have to do this everywhere I call
dirstate.status() or dirstate.walk(). Gross. Yuck. Blecch. And in
my other affected extension, I wrap dirstate.status(), which makes
this even more painful. Now multiply my pain by the number of
extension authors out there calling or wrapping dirstate.status()
and/or dirstate.walk(). No fun!
I would like to propose a more extension-friendly API change, namely:
--- a/mercurial/dirstate.py
+++ b/mercurial/dirstate.py
@@ -430,7 +430,7 @@
return True
return False
- def walk(self, match, subrepos, unknown, ignored):
+ def walk(self, match, unknown, ignored, subrepos=None):
'''
Walk recursively through the directory tree, finding all files
matched by match.
@@ -580,7 +580,7 @@
del results['.hg']
return results
- def status(self, match, subrepos, ignored, clean, unknown):
+ def status(self, match, ignored, clean, unknown, subrepos=None):
'''Determine the status of the working copy relative to the
dirstate and return a tuple of lists (unsure, modified, added,
removed, deleted, unknown, ignored, clean), where:
This will require a little extra work in dirstate.walk(), but IMHO
it's worth it to preserve the sanity of extension authors.
I'm going to work on a patch now. Please let me know if you object!
Greg
More information about the Mercurial-devel
mailing list