Show More
@@ -786,23 +786,26 b' class filecacheentry(object):' | |||
|
786 | 786 | entry.refresh() |
|
787 | 787 | |
|
788 | 788 | class filecache(object): |
|
789 |
'''A property like decorator that tracks |
|
|
789 | '''A property like decorator that tracks files under .hg/ for updates. | |
|
790 | 790 | |
|
791 | 791 | Records stat info when called in _filecache. |
|
792 | 792 | |
|
793 | On subsequent calls, compares old stat info with new info, and recreates | |
|
794 |
|
|
|
793 | On subsequent calls, compares old stat info with new info, and recreates the | |
|
794 | object when any of the files changes, updating the new stat info in | |
|
795 | _filecache. | |
|
795 | 796 | |
|
796 | 797 | Mercurial either atomic renames or appends for files under .hg, |
|
797 | 798 | so to ensure the cache is reliable we need the filesystem to be able |
|
798 | 799 | to tell us if a file has been replaced. If it can't, we fallback to |
|
799 | 800 | recreating the object on every call (essentially the same behaviour as |
|
800 |
propertycache). |
|
|
801 | def __init__(self, path): | |
|
802 | self.path = path | |
|
801 | propertycache). | |
|
802 | ||
|
803 | ''' | |
|
804 | def __init__(self, *paths): | |
|
805 | self.paths = paths | |
|
803 | 806 | |
|
804 | 807 | def join(self, obj, fname): |
|
805 |
"""Used to compute the runtime path of |
|
|
808 | """Used to compute the runtime path of a cached file. | |
|
806 | 809 | |
|
807 | 810 | Users should subclass filecache and provide their own version of this |
|
808 | 811 | function to call the appropriate join function on 'obj' (an instance |
@@ -827,11 +830,11 b' class filecache(object):' | |||
|
827 | 830 | if entry.changed(): |
|
828 | 831 | entry.obj = self.func(obj) |
|
829 | 832 | else: |
|
830 |
path = self.join(obj, self.path |
|
|
833 | paths = [self.join(obj, path) for path in self.paths] | |
|
831 | 834 | |
|
832 | 835 | # We stat -before- creating the object so our cache doesn't lie if |
|
833 | 836 | # a writer modified between the time we read and stat |
|
834 |
entry = filecache |
|
|
837 | entry = filecacheentry(paths, True) | |
|
835 | 838 | entry.obj = self.func(obj) |
|
836 | 839 | |
|
837 | 840 | obj._filecache[self.name] = entry |
@@ -843,7 +846,8 b' class filecache(object):' | |||
|
843 | 846 | if self.name not in obj._filecache: |
|
844 | 847 | # we add an entry for the missing value because X in __dict__ |
|
845 | 848 | # implies X in _filecache |
|
846 |
|
|
|
849 | paths = [self.join(obj, path) for path in self.paths] | |
|
850 | ce = filecacheentry(paths, False) | |
|
847 | 851 | obj._filecache[self.name] = ce |
|
848 | 852 | else: |
|
849 | 853 | ce = obj._filecache[self.name] |
@@ -18,7 +18,7 b' class fakerepo(object):' | |||
|
18 | 18 | def sjoin(self, p): |
|
19 | 19 | return p |
|
20 | 20 | |
|
21 | @filecache('x') | |
|
21 | @filecache('x', 'y') | |
|
22 | 22 | def cached(self): |
|
23 | 23 | print 'creating' |
|
24 | 24 | return 'string from function' |
@@ -31,12 +31,12 b' class fakerepo(object):' | |||
|
31 | 31 | pass |
|
32 | 32 | |
|
33 | 33 | def basic(repo): |
|
34 |
print "* file |
|
|
34 | print "* neither file exists" | |
|
35 | 35 | # calls function |
|
36 | 36 | repo.cached |
|
37 | 37 | |
|
38 | 38 | repo.invalidate() |
|
39 |
print "* file still |
|
|
39 | print "* neither file still exists" | |
|
40 | 40 | # uses cache |
|
41 | 41 | repo.cached |
|
42 | 42 | |
@@ -57,7 +57,7 b' def basic(repo):' | |||
|
57 | 57 | repo.cached |
|
58 | 58 | |
|
59 | 59 | repo.invalidate() |
|
60 |
print "* nothing changed with file |
|
|
60 | print "* nothing changed with either file" | |
|
61 | 61 | # stats file again, reuses object |
|
62 | 62 | repo.cached |
|
63 | 63 | |
@@ -72,6 +72,41 b' def basic(repo):' | |||
|
72 | 72 | print "* file x changed inode" |
|
73 | 73 | repo.cached |
|
74 | 74 | |
|
75 | # create empty file y | |
|
76 | f = open('y', 'w') | |
|
77 | f.close() | |
|
78 | repo.invalidate() | |
|
79 | print "* empty file y created" | |
|
80 | # should recreate the object | |
|
81 | repo.cached | |
|
82 | ||
|
83 | f = open('y', 'w') | |
|
84 | f.write('A') | |
|
85 | f.close() | |
|
86 | repo.invalidate() | |
|
87 | print "* file y changed size" | |
|
88 | # should recreate the object | |
|
89 | repo.cached | |
|
90 | ||
|
91 | f = scmutil.opener('.')('y', 'w', atomictemp=True) | |
|
92 | f.write('B') | |
|
93 | f.close() | |
|
94 | ||
|
95 | repo.invalidate() | |
|
96 | print "* file y changed inode" | |
|
97 | repo.cached | |
|
98 | ||
|
99 | f = scmutil.opener('.')('x', 'w', atomictemp=True) | |
|
100 | f.write('c') | |
|
101 | f.close() | |
|
102 | f = scmutil.opener('.')('y', 'w', atomictemp=True) | |
|
103 | f.write('C') | |
|
104 | f.close() | |
|
105 | ||
|
106 | repo.invalidate() | |
|
107 | print "* both files changed inode" | |
|
108 | repo.cached | |
|
109 | ||
|
75 | 110 | def fakeuncacheable(): |
|
76 | 111 | def wrapcacheable(orig, *args, **kwargs): |
|
77 | 112 | return False |
@@ -83,8 +118,9 b' def fakeuncacheable():' | |||
|
83 | 118 | origcacheable = extensions.wrapfunction(util.cachestat, 'cacheable', |
|
84 | 119 | wrapcacheable) |
|
85 | 120 | |
|
121 | for fn in ['x', 'y']: | |
|
86 | 122 | try: |
|
87 |
os.remove( |
|
|
123 | os.remove(fn) | |
|
88 | 124 | except OSError: |
|
89 | 125 | pass |
|
90 | 126 | |
@@ -110,9 +146,10 b' def test_filecache_synced():' | |||
|
110 | 146 | |
|
111 | 147 | def setbeforeget(repo): |
|
112 | 148 | os.remove('x') |
|
149 | os.remove('y') | |
|
113 | 150 | repo.cached = 'string set externally' |
|
114 | 151 | repo.invalidate() |
|
115 |
print "* file |
|
|
152 | print "* neither file exists" | |
|
116 | 153 | print repo.cached |
|
117 | 154 | repo.invalidate() |
|
118 | 155 | f = open('x', 'w') |
@@ -121,6 +158,18 b' def setbeforeget(repo):' | |||
|
121 | 158 | print "* file x created" |
|
122 | 159 | print repo.cached |
|
123 | 160 | |
|
161 | repo.cached = 'string 2 set externally' | |
|
162 | repo.invalidate() | |
|
163 | print "* string set externally again" | |
|
164 | print repo.cached | |
|
165 | ||
|
166 | repo.invalidate() | |
|
167 | f = open('y', 'w') | |
|
168 | f.write('b') | |
|
169 | f.close() | |
|
170 | print "* file y created" | |
|
171 | print repo.cached | |
|
172 | ||
|
124 | 173 | print 'basic:' |
|
125 | 174 | |
|
126 | 175 | basic(fakerepo()) |
@@ -1,30 +1,46 b'' | |||
|
1 | 1 | basic: |
|
2 | 2 | |
|
3 | * file doesn't exist | |
|
3 | * neither file exists | |
|
4 | 4 | creating |
|
5 |
* file still |
|
|
5 | * neither file still exists | |
|
6 | 6 | * empty file x created |
|
7 | 7 | creating |
|
8 | 8 | * file x changed size |
|
9 | 9 | creating |
|
10 |
* nothing changed with file |
|
|
10 | * nothing changed with either file | |
|
11 | 11 | * file x changed inode |
|
12 | 12 | creating |
|
13 | * empty file y created | |
|
14 | creating | |
|
15 | * file y changed size | |
|
16 | creating | |
|
17 | * file y changed inode | |
|
18 | creating | |
|
19 | * both files changed inode | |
|
20 | creating | |
|
13 | 21 | |
|
14 | 22 | fakeuncacheable: |
|
15 | 23 | |
|
16 | * file doesn't exist | |
|
24 | * neither file exists | |
|
17 | 25 | creating |
|
18 |
* file still |
|
|
26 | * neither file still exists | |
|
19 | 27 | creating |
|
20 | 28 | * empty file x created |
|
21 | 29 | creating |
|
22 | 30 | * file x changed size |
|
23 | 31 | creating |
|
24 |
* nothing changed with file |
|
|
32 | * nothing changed with either file | |
|
25 | 33 | creating |
|
26 | 34 | * file x changed inode |
|
27 | 35 | creating |
|
36 | * empty file y created | |
|
37 | creating | |
|
38 | * file y changed size | |
|
39 | creating | |
|
40 | * file y changed inode | |
|
41 | creating | |
|
42 | * both files changed inode | |
|
43 | creating | |
|
28 | 44 | repository tip rolled back to revision -1 (undo commit) |
|
29 | 45 | working directory now based on revision -1 |
|
30 | 46 | repository tip rolled back to revision -1 (undo commit) |
@@ -32,8 +48,13 b' working directory now based on revision ' | |||
|
32 | 48 | |
|
33 | 49 | setbeforeget: |
|
34 | 50 | |
|
35 | * file x doesn't exist | |
|
51 | * neither file exists | |
|
36 | 52 | string set externally |
|
37 | 53 | * file x created |
|
38 | 54 | creating |
|
39 | 55 | string from function |
|
56 | * string set externally again | |
|
57 | string 2 set externally | |
|
58 | * file y created | |
|
59 | creating | |
|
60 | string from function |
General Comments 0
You need to be logged in to leave comments.
Login now