##// END OF EJS Templates
largefiles: delete unused repo.status_nolfiles()...
Martin von Zweigbergk -
r43985:d77e8800 default
parent child Browse files
Show More
@@ -1,457 +1,454
1 1 # Copyright 2009-2010 Gregory P. Ward
2 2 # Copyright 2009-2010 Intelerad Medical Systems Incorporated
3 3 # Copyright 2010-2011 Fog Creek Software
4 4 # Copyright 2010-2011 Unity Technologies
5 5 #
6 6 # This software may be used and distributed according to the terms of the
7 7 # GNU General Public License version 2 or any later version.
8 8
9 9 '''setup for largefiles repositories: reposetup'''
10 10 from __future__ import absolute_import
11 11
12 12 import copy
13 13
14 14 from mercurial.i18n import _
15 15
16 16 from mercurial import (
17 17 error,
18 18 localrepo,
19 19 match as matchmod,
20 20 scmutil,
21 21 util,
22 22 )
23 23
24 24 from . import (
25 25 lfcommands,
26 26 lfutil,
27 27 )
28 28
29 29
30 30 def reposetup(ui, repo):
31 31 # wire repositories should be given new wireproto functions
32 32 # by "proto.wirereposetup()" via "hg.wirepeersetupfuncs"
33 33 if not repo.local():
34 34 return
35 35
36 36 class lfilesrepo(repo.__class__):
37 37 # the mark to examine whether "repo" object enables largefiles or not
38 38 _largefilesenabled = True
39 39
40 40 lfstatus = False
41 41
42 def status_nolfiles(self, *args, **kwargs):
43 return super(lfilesrepo, self).status(*args, **kwargs)
44
45 42 # When lfstatus is set, return a context that gives the names
46 43 # of largefiles instead of their corresponding standins and
47 44 # identifies the largefiles as always binary, regardless of
48 45 # their actual contents.
49 46 def __getitem__(self, changeid):
50 47 ctx = super(lfilesrepo, self).__getitem__(changeid)
51 48 if self.lfstatus:
52 49
53 50 class lfilesctx(ctx.__class__):
54 51 def files(self):
55 52 filenames = super(lfilesctx, self).files()
56 53 return [lfutil.splitstandin(f) or f for f in filenames]
57 54
58 55 def manifest(self):
59 56 man1 = super(lfilesctx, self).manifest()
60 57
61 58 class lfilesmanifest(man1.__class__):
62 59 def __contains__(self, filename):
63 60 orig = super(lfilesmanifest, self).__contains__
64 61 return orig(filename) or orig(
65 62 lfutil.standin(filename)
66 63 )
67 64
68 65 man1.__class__ = lfilesmanifest
69 66 return man1
70 67
71 68 def filectx(self, path, fileid=None, filelog=None):
72 69 orig = super(lfilesctx, self).filectx
73 70 try:
74 71 if filelog is not None:
75 72 result = orig(path, fileid, filelog)
76 73 else:
77 74 result = orig(path, fileid)
78 75 except error.LookupError:
79 76 # Adding a null character will cause Mercurial to
80 77 # identify this as a binary file.
81 78 if filelog is not None:
82 79 result = orig(
83 80 lfutil.standin(path), fileid, filelog
84 81 )
85 82 else:
86 83 result = orig(lfutil.standin(path), fileid)
87 84 olddata = result.data
88 85 result.data = lambda: olddata() + b'\0'
89 86 return result
90 87
91 88 ctx.__class__ = lfilesctx
92 89 return ctx
93 90
94 91 # Figure out the status of big files and insert them into the
95 92 # appropriate list in the result. Also removes standin files
96 93 # from the listing. Revert to the original status if
97 94 # self.lfstatus is False.
98 95 # XXX large file status is buggy when used on repo proxy.
99 96 # XXX this needs to be investigated.
100 97 @localrepo.unfilteredmethod
101 98 def status(
102 99 self,
103 100 node1=b'.',
104 101 node2=None,
105 102 match=None,
106 103 ignored=False,
107 104 clean=False,
108 105 unknown=False,
109 106 listsubrepos=False,
110 107 ):
111 108 listignored, listclean, listunknown = ignored, clean, unknown
112 109 orig = super(lfilesrepo, self).status
113 110 if not self.lfstatus:
114 111 return orig(
115 112 node1,
116 113 node2,
117 114 match,
118 115 listignored,
119 116 listclean,
120 117 listunknown,
121 118 listsubrepos,
122 119 )
123 120
124 121 # some calls in this function rely on the old version of status
125 122 self.lfstatus = False
126 123 ctx1 = self[node1]
127 124 ctx2 = self[node2]
128 125 working = ctx2.rev() is None
129 126 parentworking = working and ctx1 == self[b'.']
130 127
131 128 if match is None:
132 129 match = matchmod.always()
133 130
134 131 try:
135 132 # updating the dirstate is optional
136 133 # so we don't wait on the lock
137 134 wlock = self.wlock(False)
138 135 gotlock = True
139 136 except error.LockError:
140 137 wlock = util.nullcontextmanager()
141 138 gotlock = False
142 139 with wlock:
143 140
144 141 # First check if paths or patterns were specified on the
145 142 # command line. If there were, and they don't match any
146 143 # largefiles, we should just bail here and let super
147 144 # handle it -- thus gaining a big performance boost.
148 145 lfdirstate = lfutil.openlfdirstate(ui, self)
149 146 if not match.always():
150 147 for f in lfdirstate:
151 148 if match(f):
152 149 break
153 150 else:
154 151 return orig(
155 152 node1,
156 153 node2,
157 154 match,
158 155 listignored,
159 156 listclean,
160 157 listunknown,
161 158 listsubrepos,
162 159 )
163 160
164 161 # Create a copy of match that matches standins instead
165 162 # of largefiles.
166 163 def tostandins(files):
167 164 if not working:
168 165 return files
169 166 newfiles = []
170 167 dirstate = self.dirstate
171 168 for f in files:
172 169 sf = lfutil.standin(f)
173 170 if sf in dirstate:
174 171 newfiles.append(sf)
175 172 elif dirstate.hasdir(sf):
176 173 # Directory entries could be regular or
177 174 # standin, check both
178 175 newfiles.extend((f, sf))
179 176 else:
180 177 newfiles.append(f)
181 178 return newfiles
182 179
183 180 m = copy.copy(match)
184 181 m._files = tostandins(m._files)
185 182
186 183 result = orig(
187 184 node1, node2, m, ignored, clean, unknown, listsubrepos
188 185 )
189 186 if working:
190 187
191 188 def sfindirstate(f):
192 189 sf = lfutil.standin(f)
193 190 dirstate = self.dirstate
194 191 return sf in dirstate or dirstate.hasdir(sf)
195 192
196 193 match._files = [f for f in match._files if sfindirstate(f)]
197 194 # Don't waste time getting the ignored and unknown
198 195 # files from lfdirstate
199 196 unsure, s = lfdirstate.status(
200 197 match,
201 198 subrepos=[],
202 199 ignored=False,
203 200 clean=listclean,
204 201 unknown=False,
205 202 )
206 203 (modified, added, removed, deleted, clean) = (
207 204 s.modified,
208 205 s.added,
209 206 s.removed,
210 207 s.deleted,
211 208 s.clean,
212 209 )
213 210 if parentworking:
214 211 for lfile in unsure:
215 212 standin = lfutil.standin(lfile)
216 213 if standin not in ctx1:
217 214 # from second parent
218 215 modified.append(lfile)
219 216 elif lfutil.readasstandin(
220 217 ctx1[standin]
221 218 ) != lfutil.hashfile(self.wjoin(lfile)):
222 219 modified.append(lfile)
223 220 else:
224 221 if listclean:
225 222 clean.append(lfile)
226 223 lfdirstate.normal(lfile)
227 224 else:
228 225 tocheck = unsure + modified + added + clean
229 226 modified, added, clean = [], [], []
230 227 checkexec = self.dirstate._checkexec
231 228
232 229 for lfile in tocheck:
233 230 standin = lfutil.standin(lfile)
234 231 if standin in ctx1:
235 232 abslfile = self.wjoin(lfile)
236 233 if (
237 234 lfutil.readasstandin(ctx1[standin])
238 235 != lfutil.hashfile(abslfile)
239 236 ) or (
240 237 checkexec
241 238 and (b'x' in ctx1.flags(standin))
242 239 != bool(lfutil.getexecutable(abslfile))
243 240 ):
244 241 modified.append(lfile)
245 242 elif listclean:
246 243 clean.append(lfile)
247 244 else:
248 245 added.append(lfile)
249 246
250 247 # at this point, 'removed' contains largefiles
251 248 # marked as 'R' in the working context.
252 249 # then, largefiles not managed also in the target
253 250 # context should be excluded from 'removed'.
254 251 removed = [
255 252 lfile
256 253 for lfile in removed
257 254 if lfutil.standin(lfile) in ctx1
258 255 ]
259 256
260 257 # Standins no longer found in lfdirstate have been deleted
261 258 for standin in ctx1.walk(lfutil.getstandinmatcher(self)):
262 259 lfile = lfutil.splitstandin(standin)
263 260 if not match(lfile):
264 261 continue
265 262 if lfile not in lfdirstate:
266 263 deleted.append(lfile)
267 264 # Sync "largefile has been removed" back to the
268 265 # standin. Removing a file as a side effect of
269 266 # running status is gross, but the alternatives (if
270 267 # any) are worse.
271 268 self.wvfs.unlinkpath(standin, ignoremissing=True)
272 269
273 270 # Filter result lists
274 271 result = list(result)
275 272
276 273 # Largefiles are not really removed when they're
277 274 # still in the normal dirstate. Likewise, normal
278 275 # files are not really removed if they are still in
279 276 # lfdirstate. This happens in merges where files
280 277 # change type.
281 278 removed = [f for f in removed if f not in self.dirstate]
282 279 result[2] = [f for f in result[2] if f not in lfdirstate]
283 280
284 281 lfiles = set(lfdirstate)
285 282 # Unknown files
286 283 result[4] = set(result[4]).difference(lfiles)
287 284 # Ignored files
288 285 result[5] = set(result[5]).difference(lfiles)
289 286 # combine normal files and largefiles
290 287 normals = [
291 288 [fn for fn in filelist if not lfutil.isstandin(fn)]
292 289 for filelist in result
293 290 ]
294 291 lfstatus = (
295 292 modified,
296 293 added,
297 294 removed,
298 295 deleted,
299 296 [],
300 297 [],
301 298 clean,
302 299 )
303 300 result = [
304 301 sorted(list1 + list2)
305 302 for (list1, list2) in zip(normals, lfstatus)
306 303 ]
307 304 else: # not against working directory
308 305 result = [
309 306 [lfutil.splitstandin(f) or f for f in items]
310 307 for items in result
311 308 ]
312 309
313 310 if gotlock:
314 311 lfdirstate.write()
315 312
316 313 self.lfstatus = True
317 314 return scmutil.status(*result)
318 315
319 316 def commitctx(self, ctx, *args, **kwargs):
320 317 node = super(lfilesrepo, self).commitctx(ctx, *args, **kwargs)
321 318
322 319 class lfilesctx(ctx.__class__):
323 320 def markcommitted(self, node):
324 321 orig = super(lfilesctx, self).markcommitted
325 322 return lfutil.markcommitted(orig, self, node)
326 323
327 324 ctx.__class__ = lfilesctx
328 325 return node
329 326
330 327 # Before commit, largefile standins have not had their
331 328 # contents updated to reflect the hash of their largefile.
332 329 # Do that here.
333 330 def commit(
334 331 self,
335 332 text=b"",
336 333 user=None,
337 334 date=None,
338 335 match=None,
339 336 force=False,
340 337 editor=False,
341 338 extra=None,
342 339 ):
343 340 if extra is None:
344 341 extra = {}
345 342 orig = super(lfilesrepo, self).commit
346 343
347 344 with self.wlock():
348 345 lfcommithook = self._lfcommithooks[-1]
349 346 match = lfcommithook(self, match)
350 347 result = orig(
351 348 text=text,
352 349 user=user,
353 350 date=date,
354 351 match=match,
355 352 force=force,
356 353 editor=editor,
357 354 extra=extra,
358 355 )
359 356 return result
360 357
361 358 # TODO: _subdirlfs should be moved into "lfutil.py", because
362 359 # it is referred only from "lfutil.updatestandinsbymatch"
363 360 def _subdirlfs(self, files, lfiles):
364 361 '''
365 362 Adjust matched file list
366 363 If we pass a directory to commit whose only committable files
367 364 are largefiles, the core commit code aborts before finding
368 365 the largefiles.
369 366 So we do the following:
370 367 For directories that only have largefiles as matches,
371 368 we explicitly add the largefiles to the match list and remove
372 369 the directory.
373 370 In other cases, we leave the match list unmodified.
374 371 '''
375 372 actualfiles = []
376 373 dirs = []
377 374 regulars = []
378 375
379 376 for f in files:
380 377 if lfutil.isstandin(f + b'/'):
381 378 raise error.Abort(
382 379 _(b'file "%s" is a largefile standin') % f,
383 380 hint=b'commit the largefile itself instead',
384 381 )
385 382 # Scan directories
386 383 if self.wvfs.isdir(f):
387 384 dirs.append(f)
388 385 else:
389 386 regulars.append(f)
390 387
391 388 for f in dirs:
392 389 matcheddir = False
393 390 d = self.dirstate.normalize(f) + b'/'
394 391 # Check for matched normal files
395 392 for mf in regulars:
396 393 if self.dirstate.normalize(mf).startswith(d):
397 394 actualfiles.append(f)
398 395 matcheddir = True
399 396 break
400 397 if not matcheddir:
401 398 # If no normal match, manually append
402 399 # any matching largefiles
403 400 for lf in lfiles:
404 401 if self.dirstate.normalize(lf).startswith(d):
405 402 actualfiles.append(lf)
406 403 if not matcheddir:
407 404 # There may still be normal files in the dir, so
408 405 # add a directory to the list, which
409 406 # forces status/dirstate to walk all files and
410 407 # call the match function on the matcher, even
411 408 # on case sensitive filesystems.
412 409 actualfiles.append(b'.')
413 410 matcheddir = True
414 411 # Nothing in dir, so readd it
415 412 # and let commit reject it
416 413 if not matcheddir:
417 414 actualfiles.append(f)
418 415
419 416 # Always add normal files
420 417 actualfiles += regulars
421 418 return actualfiles
422 419
423 420 repo.__class__ = lfilesrepo
424 421
425 422 # stack of hooks being executed before committing.
426 423 # only last element ("_lfcommithooks[-1]") is used for each committing.
427 424 repo._lfcommithooks = [lfutil.updatestandinsbymatch]
428 425
429 426 # Stack of status writer functions taking "*msg, **opts" arguments
430 427 # like "ui.status()". Only last element ("_lfstatuswriters[-1]")
431 428 # is used to write status out.
432 429 repo._lfstatuswriters = [ui.status]
433 430
434 431 def prepushoutgoinghook(pushop):
435 432 """Push largefiles for pushop before pushing revisions."""
436 433 lfrevs = pushop.lfrevs
437 434 if lfrevs is None:
438 435 lfrevs = pushop.outgoing.missing
439 436 if lfrevs:
440 437 toupload = set()
441 438 addfunc = lambda fn, lfhash: toupload.add(lfhash)
442 439 lfutil.getlfilestoupload(pushop.repo, lfrevs, addfunc)
443 440 lfcommands.uploadlfiles(ui, pushop.repo, pushop.remote, toupload)
444 441
445 442 repo.prepushoutgoinghooks.add(b"largefiles", prepushoutgoinghook)
446 443
447 444 def checkrequireslfiles(ui, repo, **kwargs):
448 445 if b'largefiles' not in repo.requirements and any(
449 446 lfutil.shortname + b'/' in f[0] for f in repo.store.datafiles()
450 447 ):
451 448 repo.requirements.add(b'largefiles')
452 449 repo._writerequirements()
453 450
454 451 ui.setconfig(
455 452 b'hooks', b'changegroup.lfiles', checkrequireslfiles, b'largefiles'
456 453 )
457 454 ui.setconfig(b'hooks', b'commit.lfiles', checkrequireslfiles, b'largefiles')
General Comments 0
You need to be logged in to leave comments. Login now