Show More
@@ -1,107 +1,109 | |||||
1 | # extension to emulate invoking 'dirstate.write()' at the time |
|
1 | # extension to emulate invoking 'dirstate.write()' at the time | |
2 | # specified by '[fakedirstatewritetime] fakenow', only when |
|
2 | # specified by '[fakedirstatewritetime] fakenow', only when | |
3 | # 'dirstate.write()' is invoked via functions below: |
|
3 | # 'dirstate.write()' is invoked via functions below: | |
4 | # |
|
4 | # | |
5 | # - 'workingctx._poststatusfixup()' (= 'repo.status()') |
|
5 | # - 'workingctx._poststatusfixup()' (= 'repo.status()') | |
6 | # - 'committablectx.markcommitted()' |
|
6 | # - 'committablectx.markcommitted()' | |
7 |
|
7 | |||
8 | from __future__ import absolute_import |
|
8 | from __future__ import absolute_import | |
9 |
|
9 | |||
10 | from mercurial import ( |
|
10 | from mercurial import ( | |
11 | context, |
|
11 | context, | |
12 | dirstate, |
|
12 | dirstate, | |
13 | dirstatemap as dirstatemapmod, |
|
13 | dirstatemap as dirstatemapmod, | |
14 | extensions, |
|
14 | extensions, | |
15 | policy, |
|
15 | policy, | |
16 | registrar, |
|
16 | registrar, | |
17 | ) |
|
17 | ) | |
18 | from mercurial.utils import dateutil |
|
18 | from mercurial.utils import dateutil | |
19 |
|
19 | |||
20 | try: |
|
20 | try: | |
21 | from mercurial import rustext |
|
21 | from mercurial import rustext | |
22 |
|
22 | |||
23 | rustext.__name__ # force actual import (see hgdemandimport) |
|
23 | rustext.__name__ # force actual import (see hgdemandimport) | |
24 | except ImportError: |
|
24 | except ImportError: | |
25 | rustext = None |
|
25 | rustext = None | |
26 |
|
26 | |||
27 | configtable = {} |
|
27 | configtable = {} | |
28 | configitem = registrar.configitem(configtable) |
|
28 | configitem = registrar.configitem(configtable) | |
29 |
|
29 | |||
30 | configitem( |
|
30 | configitem( | |
31 | b'fakedirstatewritetime', |
|
31 | b'fakedirstatewritetime', | |
32 | b'fakenow', |
|
32 | b'fakenow', | |
33 | default=None, |
|
33 | default=None, | |
34 | ) |
|
34 | ) | |
35 |
|
35 | |||
36 | parsers = policy.importmod('parsers') |
|
36 | parsers = policy.importmod('parsers') | |
37 | rustmod = policy.importrust('parsers') |
|
37 | rustmod = policy.importrust('parsers') | |
38 |
|
38 | |||
39 |
|
39 | |||
40 | def pack_dirstate(fakenow, orig, dmap, copymap, pl, now): |
|
40 | def pack_dirstate(fakenow, orig, dmap, copymap, pl, now): | |
41 | # execute what original parsers.pack_dirstate should do actually |
|
41 | # execute what original parsers.pack_dirstate should do actually | |
42 | # for consistency |
|
42 | # for consistency | |
43 | actualnow = int(now) |
|
43 | actualnow = int(now) | |
44 | for f, e in dmap.items(): |
|
44 | for f, e in dmap.items(): | |
45 |
if e |
|
45 | if e.need_delay(actualnow): | |
46 |
e = parsers.DirstateItem( |
|
46 | e = parsers.DirstateItem( | |
|
47 | e.state, e.mode, e.size, dirstatemapmod.AMBIGUOUS_TIME | |||
|
48 | ) | |||
47 | dmap[f] = e |
|
49 | dmap[f] = e | |
48 |
|
50 | |||
49 | return orig(dmap, copymap, pl, fakenow) |
|
51 | return orig(dmap, copymap, pl, fakenow) | |
50 |
|
52 | |||
51 |
|
53 | |||
52 | def fakewrite(ui, func): |
|
54 | def fakewrite(ui, func): | |
53 | # fake "now" of 'pack_dirstate' only if it is invoked while 'func' |
|
55 | # fake "now" of 'pack_dirstate' only if it is invoked while 'func' | |
54 |
|
56 | |||
55 | fakenow = ui.config(b'fakedirstatewritetime', b'fakenow') |
|
57 | fakenow = ui.config(b'fakedirstatewritetime', b'fakenow') | |
56 | if not fakenow: |
|
58 | if not fakenow: | |
57 | # Execute original one, if fakenow isn't configured. This is |
|
59 | # Execute original one, if fakenow isn't configured. This is | |
58 | # useful to prevent subrepos from executing replaced one, |
|
60 | # useful to prevent subrepos from executing replaced one, | |
59 | # because replacing 'parsers.pack_dirstate' is also effective |
|
61 | # because replacing 'parsers.pack_dirstate' is also effective | |
60 | # in subrepos. |
|
62 | # in subrepos. | |
61 | return func() |
|
63 | return func() | |
62 |
|
64 | |||
63 | # parsing 'fakenow' in YYYYmmddHHMM format makes comparison between |
|
65 | # parsing 'fakenow' in YYYYmmddHHMM format makes comparison between | |
64 | # 'fakenow' value and 'touch -t YYYYmmddHHMM' argument easy |
|
66 | # 'fakenow' value and 'touch -t YYYYmmddHHMM' argument easy | |
65 | fakenow = dateutil.parsedate(fakenow, [b'%Y%m%d%H%M'])[0] |
|
67 | fakenow = dateutil.parsedate(fakenow, [b'%Y%m%d%H%M'])[0] | |
66 |
|
68 | |||
67 | if rustmod is not None: |
|
69 | if rustmod is not None: | |
68 | # The Rust implementation does not use public parse/pack dirstate |
|
70 | # The Rust implementation does not use public parse/pack dirstate | |
69 | # to prevent conversion round-trips |
|
71 | # to prevent conversion round-trips | |
70 | orig_dirstatemap_write = dirstatemapmod.dirstatemap.write |
|
72 | orig_dirstatemap_write = dirstatemapmod.dirstatemap.write | |
71 | wrapper = lambda self, st, now: orig_dirstatemap_write( |
|
73 | wrapper = lambda self, st, now: orig_dirstatemap_write( | |
72 | self, st, fakenow |
|
74 | self, st, fakenow | |
73 | ) |
|
75 | ) | |
74 | dirstatemapmod.dirstatemap.write = wrapper |
|
76 | dirstatemapmod.dirstatemap.write = wrapper | |
75 |
|
77 | |||
76 | orig_dirstate_getfsnow = dirstate._getfsnow |
|
78 | orig_dirstate_getfsnow = dirstate._getfsnow | |
77 | wrapper = lambda *args: pack_dirstate(fakenow, orig_pack_dirstate, *args) |
|
79 | wrapper = lambda *args: pack_dirstate(fakenow, orig_pack_dirstate, *args) | |
78 |
|
80 | |||
79 | orig_module = parsers |
|
81 | orig_module = parsers | |
80 | orig_pack_dirstate = parsers.pack_dirstate |
|
82 | orig_pack_dirstate = parsers.pack_dirstate | |
81 |
|
83 | |||
82 | orig_module.pack_dirstate = wrapper |
|
84 | orig_module.pack_dirstate = wrapper | |
83 | dirstate._getfsnow = lambda *args: fakenow |
|
85 | dirstate._getfsnow = lambda *args: fakenow | |
84 | try: |
|
86 | try: | |
85 | return func() |
|
87 | return func() | |
86 | finally: |
|
88 | finally: | |
87 | orig_module.pack_dirstate = orig_pack_dirstate |
|
89 | orig_module.pack_dirstate = orig_pack_dirstate | |
88 | dirstate._getfsnow = orig_dirstate_getfsnow |
|
90 | dirstate._getfsnow = orig_dirstate_getfsnow | |
89 | if rustmod is not None: |
|
91 | if rustmod is not None: | |
90 | dirstatemapmod.dirstatemap.write = orig_dirstatemap_write |
|
92 | dirstatemapmod.dirstatemap.write = orig_dirstatemap_write | |
91 |
|
93 | |||
92 |
|
94 | |||
93 | def _poststatusfixup(orig, workingctx, status, fixup): |
|
95 | def _poststatusfixup(orig, workingctx, status, fixup): | |
94 | ui = workingctx.repo().ui |
|
96 | ui = workingctx.repo().ui | |
95 | return fakewrite(ui, lambda: orig(workingctx, status, fixup)) |
|
97 | return fakewrite(ui, lambda: orig(workingctx, status, fixup)) | |
96 |
|
98 | |||
97 |
|
99 | |||
98 | def markcommitted(orig, committablectx, node): |
|
100 | def markcommitted(orig, committablectx, node): | |
99 | ui = committablectx.repo().ui |
|
101 | ui = committablectx.repo().ui | |
100 | return fakewrite(ui, lambda: orig(committablectx, node)) |
|
102 | return fakewrite(ui, lambda: orig(committablectx, node)) | |
101 |
|
103 | |||
102 |
|
104 | |||
103 | def extsetup(ui): |
|
105 | def extsetup(ui): | |
104 | extensions.wrapfunction( |
|
106 | extensions.wrapfunction( | |
105 | context.workingctx, '_poststatusfixup', _poststatusfixup |
|
107 | context.workingctx, '_poststatusfixup', _poststatusfixup | |
106 | ) |
|
108 | ) | |
107 | extensions.wrapfunction(context.workingctx, 'markcommitted', markcommitted) |
|
109 | extensions.wrapfunction(context.workingctx, 'markcommitted', markcommitted) |
General Comments 0
You need to be logged in to leave comments.
Login now