Mercurial > hg > mercurial-crew-with-dirclash
annotate mercurial/demandimport.py @ 4307:c8919eb0f315
purge: abort with missing files avoiding problems with name-mangling fs
In a name mangling filesystem (e.g. a case insensitive one)
dirstate.walk() can yield filenames different from the ones
stored in the dirstate. This already confuses the status and
add commands, but with purge this may cause data loss.
To prevent this purge refuses to work if there are missing
files and has a 'force' option if the user knows it is safe.
Even with the force option purge checks if any of the missing
files is still available in the working dir: if so there
may be some problem with the underlying filesystem, so it
unconditionally aborts.
author | Emanuele Aina <em@nerd.ocracy.org> |
---|---|
date | Wed, 28 Mar 2007 21:34:12 +0200 |
parents | b9dcee25be8e |
children | eb99af2d845e |
rev | line source |
---|---|
3886
abaee83ce0a6
Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1 # demandimport.py - global demand-loading of modules for Mercurial |
abaee83ce0a6
Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
2 # |
abaee83ce0a6
Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
3 # Copyright 2006 Matt Mackall <mpm@selenic.com> |
abaee83ce0a6
Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
4 # |
abaee83ce0a6
Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
5 # This software may be used and distributed according to the terms |
abaee83ce0a6
Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
6 # of the GNU General Public License, incorporated herein by reference. |
abaee83ce0a6
Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
7 |
abaee83ce0a6
Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
8 ''' |
abaee83ce0a6
Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
9 demandimport - automatic demandloading of modules |
abaee83ce0a6
Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
10 |
abaee83ce0a6
Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
11 To enable this module, do: |
abaee83ce0a6
Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
12 |
abaee83ce0a6
Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
13 import demandimport; demandimport.enable() |
abaee83ce0a6
Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
14 |
abaee83ce0a6
Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
15 Imports of the following forms will be demand-loaded: |
abaee83ce0a6
Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
16 |
abaee83ce0a6
Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
17 import a, b.c |
abaee83ce0a6
Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
18 import a.b as c |
abaee83ce0a6
Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
19 from a import b,c # a will be loaded immediately |
abaee83ce0a6
Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
20 |
abaee83ce0a6
Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
21 These imports will not be delayed: |
abaee83ce0a6
Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
22 |
abaee83ce0a6
Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
23 from a import * |
abaee83ce0a6
Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
24 b = __import__(a) |
abaee83ce0a6
Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
25 ''' |
abaee83ce0a6
Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
26 |
abaee83ce0a6
Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
27 _origimport = __import__ |
abaee83ce0a6
Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
28 |
abaee83ce0a6
Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
29 class _demandmod(object): |
abaee83ce0a6
Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
30 """module demand-loader and proxy""" |
abaee83ce0a6
Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
31 def __init__(self, name, globals, locals): |
abaee83ce0a6
Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
32 if '.' in name: |
abaee83ce0a6
Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
33 head, rest = name.split('.', 1) |
abaee83ce0a6
Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
34 after = [rest] |
abaee83ce0a6
Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
35 else: |
abaee83ce0a6
Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
36 head = name |
abaee83ce0a6
Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
37 after = [] |
3888
3b628b5da9e9
use parent.__setattr__ instead of __dict__
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
3886
diff
changeset
|
38 object.__setattr__(self, "_data", (head, globals, locals, after)) |
3b628b5da9e9
use parent.__setattr__ instead of __dict__
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
3886
diff
changeset
|
39 object.__setattr__(self, "_module", None) |
3886
abaee83ce0a6
Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
40 def _extend(self, name): |
abaee83ce0a6
Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
41 """add to the list of submodules to load""" |
abaee83ce0a6
Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
42 self._data[3].append(name) |
abaee83ce0a6
Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
43 def _load(self): |
abaee83ce0a6
Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
44 if not self._module: |
abaee83ce0a6
Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
45 head, globals, locals, after = self._data |
abaee83ce0a6
Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
46 mod = _origimport(head, globals, locals) |
abaee83ce0a6
Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
47 # load submodules |
3921
6d0d025e125a
demandimport: fix import x.y.z as a when x.y is already imported.
Matt Mackall <mpm@selenic.com>
parents:
3903
diff
changeset
|
48 def subload(mod, p): |
6d0d025e125a
demandimport: fix import x.y.z as a when x.y is already imported.
Matt Mackall <mpm@selenic.com>
parents:
3903
diff
changeset
|
49 h, t = p, None |
6d0d025e125a
demandimport: fix import x.y.z as a when x.y is already imported.
Matt Mackall <mpm@selenic.com>
parents:
3903
diff
changeset
|
50 if '.' in p: |
6d0d025e125a
demandimport: fix import x.y.z as a when x.y is already imported.
Matt Mackall <mpm@selenic.com>
parents:
3903
diff
changeset
|
51 h, t = p.split('.', 1) |
6d0d025e125a
demandimport: fix import x.y.z as a when x.y is already imported.
Matt Mackall <mpm@selenic.com>
parents:
3903
diff
changeset
|
52 if not hasattr(mod, h): |
6d0d025e125a
demandimport: fix import x.y.z as a when x.y is already imported.
Matt Mackall <mpm@selenic.com>
parents:
3903
diff
changeset
|
53 setattr(mod, h, _demandmod(p, mod.__dict__, mod.__dict__)) |
3923
de6ae8f016af
demandimport: handle already-loaded nested modules in subload
Brendan Cully <brendan@kublai.com>
parents:
3921
diff
changeset
|
54 elif t: |
3921
6d0d025e125a
demandimport: fix import x.y.z as a when x.y is already imported.
Matt Mackall <mpm@selenic.com>
parents:
3903
diff
changeset
|
55 subload(getattr(mod, h), t) |
6d0d025e125a
demandimport: fix import x.y.z as a when x.y is already imported.
Matt Mackall <mpm@selenic.com>
parents:
3903
diff
changeset
|
56 |
3886
abaee83ce0a6
Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
57 for x in after: |
3921
6d0d025e125a
demandimport: fix import x.y.z as a when x.y is already imported.
Matt Mackall <mpm@selenic.com>
parents:
3903
diff
changeset
|
58 subload(mod, x) |
6d0d025e125a
demandimport: fix import x.y.z as a when x.y is already imported.
Matt Mackall <mpm@selenic.com>
parents:
3903
diff
changeset
|
59 |
3886
abaee83ce0a6
Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
60 # are we in the locals dictionary still? |
abaee83ce0a6
Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
61 if locals and locals.get(head) == self: |
abaee83ce0a6
Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
62 locals[head] = mod |
3888
3b628b5da9e9
use parent.__setattr__ instead of __dict__
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
3886
diff
changeset
|
63 object.__setattr__(self, "_module", mod) |
3886
abaee83ce0a6
Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
64 def __repr__(self): |
abaee83ce0a6
Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
65 return "<unloaded module '%s'>" % self._data[0] |
abaee83ce0a6
Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
66 def __call__(self, *args, **kwargs): |
abaee83ce0a6
Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
67 raise TypeError("'unloaded module' object is not callable") |
3903
f9136599700f
Make demandimport pass all tests on python2.5.
Brendan Cully <brendan@kublai.com>
parents:
3898
diff
changeset
|
68 def __getattribute__(self, attr): |
f9136599700f
Make demandimport pass all tests on python2.5.
Brendan Cully <brendan@kublai.com>
parents:
3898
diff
changeset
|
69 if attr in ('_data', '_extend', '_load', '_module'): |
f9136599700f
Make demandimport pass all tests on python2.5.
Brendan Cully <brendan@kublai.com>
parents:
3898
diff
changeset
|
70 return object.__getattribute__(self, attr) |
3886
abaee83ce0a6
Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
71 self._load() |
abaee83ce0a6
Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
72 return getattr(self._module, attr) |
abaee83ce0a6
Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
73 def __setattr__(self, attr, val): |
abaee83ce0a6
Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
74 self._load() |
abaee83ce0a6
Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
75 setattr(self._module, attr, val) |
abaee83ce0a6
Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
76 |
abaee83ce0a6
Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
77 def _demandimport(name, globals=None, locals=None, fromlist=None): |
abaee83ce0a6
Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
78 if not locals or name in ignore or fromlist == ('*',): |
abaee83ce0a6
Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
79 # these cases we can't really delay |
abaee83ce0a6
Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
80 return _origimport(name, globals, locals, fromlist) |
abaee83ce0a6
Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
81 elif not fromlist: |
abaee83ce0a6
Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
82 # import a [as b] |
abaee83ce0a6
Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
83 if '.' in name: # a.b |
abaee83ce0a6
Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
84 base, rest = name.split('.', 1) |
3903
f9136599700f
Make demandimport pass all tests on python2.5.
Brendan Cully <brendan@kublai.com>
parents:
3898
diff
changeset
|
85 # email.__init__ loading email.mime |
f9136599700f
Make demandimport pass all tests on python2.5.
Brendan Cully <brendan@kublai.com>
parents:
3898
diff
changeset
|
86 if globals and globals.get('__name__', None) == base: |
f9136599700f
Make demandimport pass all tests on python2.5.
Brendan Cully <brendan@kublai.com>
parents:
3898
diff
changeset
|
87 return _origimport(name, globals, locals, fromlist) |
3886
abaee83ce0a6
Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
88 # if a is already demand-loaded, add b to its submodule list |
abaee83ce0a6
Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
89 if base in locals: |
abaee83ce0a6
Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
90 if isinstance(locals[base], _demandmod): |
abaee83ce0a6
Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
91 locals[base]._extend(rest) |
abaee83ce0a6
Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
92 return locals[base] |
abaee83ce0a6
Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
93 return _demandmod(name, globals, locals) |
abaee83ce0a6
Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
94 else: |
abaee83ce0a6
Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
95 # from a import b,c,d |
abaee83ce0a6
Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
96 mod = _origimport(name, globals, locals) |
abaee83ce0a6
Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
97 # recurse down the module chain |
abaee83ce0a6
Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
98 for comp in name.split('.')[1:]: |
abaee83ce0a6
Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
99 mod = getattr(mod, comp) |
abaee83ce0a6
Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
100 for x in fromlist: |
abaee83ce0a6
Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
101 # set requested submodules for demand load |
abaee83ce0a6
Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
102 if not(hasattr(mod, x)): |
abaee83ce0a6
Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
103 setattr(mod, x, _demandmod(x, mod.__dict__, mod.__dict__)) |
abaee83ce0a6
Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
104 return mod |
abaee83ce0a6
Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
105 |
4126
b9dcee25be8e
Add _xmlplus to the demandimport blacklist. (HGCIA was failing to load.)
Brendan Cully <brendan@kublai.com>
parents:
3929
diff
changeset
|
106 ignore = ['_hashlib', '_xmlplus', 'fcntl', 'win32com.gen_py'] |
3886
abaee83ce0a6
Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
107 |
abaee83ce0a6
Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
108 def enable(): |
abaee83ce0a6
Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
109 "enable global demand-loading of modules" |
abaee83ce0a6
Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
110 __builtins__["__import__"] = _demandimport |
abaee83ce0a6
Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
111 |
abaee83ce0a6
Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
112 def disable(): |
abaee83ce0a6
Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
113 "disable global demand-loading of modules" |
abaee83ce0a6
Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
114 __builtins__["__import__"] = _origimport |
abaee83ce0a6
Replace demandload with new demandimport
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
115 |