comparison hgext/largefiles/reposetup.py @ 15617:74e691b141c4

largefiles: optimize performance of status on largefiles repos (issue3136)
author Na'Tosha Bard <natosha@unity3d.com>
date Wed, 07 Dec 2011 12:56:44 +0100
parents 4439ec496378
children 931dc4af0d95
comparison
equal deleted inserted replaced
15614:260a6449d83a 15617:74e691b141c4
125 def tostandin(file): 125 def tostandin(file):
126 if inctx(lfutil.standin(file), ctx2): 126 if inctx(lfutil.standin(file), ctx2):
127 return lfutil.standin(file) 127 return lfutil.standin(file)
128 return file 128 return file
129 129
130 # Create a function that we can use to override what is
131 # normally the ignore matcher. We've already checked
132 # for ignored files on the first dirstate walk, and
133 # unecessarily re-checking here causes a huge performance
134 # hit because lfdirstate only knows about largefiles
135 def _ignoreoverride(self):
136 return False
137
130 m = copy.copy(match) 138 m = copy.copy(match)
131 m._files = [tostandin(f) for f in m._files] 139 m._files = [tostandin(f) for f in m._files]
132 140
133 # get ignored, clean, and unknown but remove them 141 # Get ignored files here even if we weren't asked for them; we
134 # later if they were not asked for 142 # must use the result here for filtering later
135 try: 143 try:
136 result = super(lfiles_repo, self).status(node1, node2, m, 144 result = super(lfiles_repo, self).status(node1, node2, m,
137 True, True, True, listsubrepos) 145 True, clean, unknown, listsubrepos)
138 except TypeError: 146 except TypeError:
139 result = super(lfiles_repo, self).status(node1, node2, m, 147 result = super(lfiles_repo, self).status(node1, node2, m,
140 True, True, True) 148 True, clean, unknown)
141 if working: 149 if working:
142 # hold the wlock while we read largefiles and 150 # hold the wlock while we read largefiles and
143 # update the lfdirstate 151 # update the lfdirstate
144 wlock = repo.wlock() 152 wlock = repo.wlock()
145 try: 153 try:
146 # Any non-largefiles that were explicitly listed must be 154 # Any non-largefiles that were explicitly listed must be
147 # taken out or lfdirstate.status will report an error. 155 # taken out or lfdirstate.status will report an error.
148 # The status of these files was already computed using 156 # The status of these files was already computed using
149 # super's status. 157 # super's status.
150 lfdirstate = lfutil.openlfdirstate(ui, self) 158 lfdirstate = lfutil.openlfdirstate(ui, self)
159 # Override lfdirstate's ignore matcher to not do
160 # anything
161 orig_ignore = lfdirstate._ignore
162 lfdirstate._ignore = _ignoreoverride
163
151 match._files = [f for f in match._files if f in 164 match._files = [f for f in match._files if f in
152 lfdirstate] 165 lfdirstate]
153 s = lfdirstate.status(match, [], listignored, 166 # Don't waste time getting the ignored and unknown
154 listclean, listunknown) 167 # files again; we already have them
168 s = lfdirstate.status(match, [], False,
169 listclean, False)
155 (unsure, modified, added, removed, missing, unknown, 170 (unsure, modified, added, removed, missing, unknown,
156 ignored, clean) = s 171 ignored, clean) = s
172 # Replace the list of ignored and unknown files with
173 # the previously caclulated lists, and strip out the
174 # largefiles
175 lfiles = set(lfdirstate._map)
176 ignored = set(result[5]).difference(lfiles)
177 unknown = set(result[4]).difference(lfiles)
157 if parentworking: 178 if parentworking:
158 for lfile in unsure: 179 for lfile in unsure:
159 if ctx1[lfutil.standin(lfile)].data().strip() \ 180 if ctx1[lfutil.standin(lfile)].data().strip() \
160 != lfutil.hashfile(self.wjoin(lfile)): 181 != lfutil.hashfile(self.wjoin(lfile)):
161 modified.append(lfile) 182 modified.append(lfile)
175 modified.append(lfile) 196 modified.append(lfile)
176 else: 197 else:
177 clean.append(lfile) 198 clean.append(lfile)
178 else: 199 else:
179 added.append(lfile) 200 added.append(lfile)
201 # Replace the original ignore function
202 lfdirstate._ignore = orig_ignore
180 finally: 203 finally:
181 wlock.release() 204 wlock.release()
182 205
183 for standin in ctx1.manifest(): 206 for standin in ctx1.manifest():
184 if not lfutil.isstandin(standin): 207 if not lfutil.isstandin(standin):
190 removed.append(lfile) 213 removed.append(lfile)
191 # Handle unknown and ignored differently 214 # Handle unknown and ignored differently
192 lfiles = (modified, added, removed, missing, [], [], clean) 215 lfiles = (modified, added, removed, missing, [], [], clean)
193 result = list(result) 216 result = list(result)
194 # Unknown files 217 # Unknown files
218 unknown = set(unknown).difference(ignored)
195 result[4] = [f for f in unknown 219 result[4] = [f for f in unknown
196 if (repo.dirstate[f] == '?' and 220 if (repo.dirstate[f] == '?' and
197 not lfutil.isstandin(f))] 221 not lfutil.isstandin(f))]
198 # Ignored files must be ignored by both the dirstate and 222 # Ignored files were calculated earlier by the dirstate,
199 # lfdirstate 223 # and we already stripped out the largefiles from the list
200 result[5] = set(ignored).intersection(set(result[5])) 224 result[5] = ignored
201 # combine normal files and largefiles 225 # combine normal files and largefiles
202 normals = [[fn for fn in filelist 226 normals = [[fn for fn in filelist
203 if not lfutil.isstandin(fn)] 227 if not lfutil.isstandin(fn)]
204 for filelist in result] 228 for filelist in result]
205 result = [sorted(list1 + list2) 229 result = [sorted(list1 + list2)