##// END OF EJS Templates
largefiles: stylistic cleanup of filemerge
Mads Kiilerich -
r20298:9d350fa0 default
parent child Browse files
Show More
@@ -1,1199 +1,1194 b''
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 '''Overridden Mercurial commands and functions for the largefiles extension'''
10 10
11 11 import os
12 12 import copy
13 13
14 14 from mercurial import hg, commands, util, cmdutil, scmutil, match as match_, \
15 15 node, archival, error, merge, discovery, pathutil
16 16 from mercurial.i18n import _
17 17 from mercurial.node import hex
18 18 from hgext import rebase
19 19
20 20 import lfutil
21 21 import lfcommands
22 22 import basestore
23 23
24 24 # -- Utility functions: commonly/repeatedly needed functionality ---------------
25 25
26 26 def installnormalfilesmatchfn(manifest):
27 27 '''overrides scmutil.match so that the matcher it returns will ignore all
28 28 largefiles'''
29 29 oldmatch = None # for the closure
30 30 def overridematch(ctx, pats=[], opts={}, globbed=False,
31 31 default='relpath'):
32 32 match = oldmatch(ctx, pats, opts, globbed, default)
33 33 m = copy.copy(match)
34 34 notlfile = lambda f: not (lfutil.isstandin(f) or lfutil.standin(f) in
35 35 manifest)
36 36 m._files = filter(notlfile, m._files)
37 37 m._fmap = set(m._files)
38 38 m._always = False
39 39 origmatchfn = m.matchfn
40 40 m.matchfn = lambda f: notlfile(f) and origmatchfn(f) or None
41 41 return m
42 42 oldmatch = installmatchfn(overridematch)
43 43
44 44 def installmatchfn(f):
45 45 oldmatch = scmutil.match
46 46 setattr(f, 'oldmatch', oldmatch)
47 47 scmutil.match = f
48 48 return oldmatch
49 49
50 50 def restorematchfn():
51 51 '''restores scmutil.match to what it was before installnormalfilesmatchfn
52 52 was called. no-op if scmutil.match is its original function.
53 53
54 54 Note that n calls to installnormalfilesmatchfn will require n calls to
55 55 restore matchfn to reverse'''
56 56 scmutil.match = getattr(scmutil.match, 'oldmatch', scmutil.match)
57 57
58 58 def addlargefiles(ui, repo, *pats, **opts):
59 59 large = opts.pop('large', None)
60 60 lfsize = lfutil.getminsize(
61 61 ui, lfutil.islfilesrepo(repo), opts.pop('lfsize', None))
62 62
63 63 lfmatcher = None
64 64 if lfutil.islfilesrepo(repo):
65 65 lfpats = ui.configlist(lfutil.longname, 'patterns', default=[])
66 66 if lfpats:
67 67 lfmatcher = match_.match(repo.root, '', list(lfpats))
68 68
69 69 lfnames = []
70 70 m = scmutil.match(repo[None], pats, opts)
71 71 m.bad = lambda x, y: None
72 72 wctx = repo[None]
73 73 for f in repo.walk(m):
74 74 exact = m.exact(f)
75 75 lfile = lfutil.standin(f) in wctx
76 76 nfile = f in wctx
77 77 exists = lfile or nfile
78 78
79 79 # Don't warn the user when they attempt to add a normal tracked file.
80 80 # The normal add code will do that for us.
81 81 if exact and exists:
82 82 if lfile:
83 83 ui.warn(_('%s already a largefile\n') % f)
84 84 continue
85 85
86 86 if (exact or not exists) and not lfutil.isstandin(f):
87 87 wfile = repo.wjoin(f)
88 88
89 89 # In case the file was removed previously, but not committed
90 90 # (issue3507)
91 91 if not os.path.exists(wfile):
92 92 continue
93 93
94 94 abovemin = (lfsize and
95 95 os.lstat(wfile).st_size >= lfsize * 1024 * 1024)
96 96 if large or abovemin or (lfmatcher and lfmatcher(f)):
97 97 lfnames.append(f)
98 98 if ui.verbose or not exact:
99 99 ui.status(_('adding %s as a largefile\n') % m.rel(f))
100 100
101 101 bad = []
102 102 standins = []
103 103
104 104 # Need to lock, otherwise there could be a race condition between
105 105 # when standins are created and added to the repo.
106 106 wlock = repo.wlock()
107 107 try:
108 108 if not opts.get('dry_run'):
109 109 lfdirstate = lfutil.openlfdirstate(ui, repo)
110 110 for f in lfnames:
111 111 standinname = lfutil.standin(f)
112 112 lfutil.writestandin(repo, standinname, hash='',
113 113 executable=lfutil.getexecutable(repo.wjoin(f)))
114 114 standins.append(standinname)
115 115 if lfdirstate[f] == 'r':
116 116 lfdirstate.normallookup(f)
117 117 else:
118 118 lfdirstate.add(f)
119 119 lfdirstate.write()
120 120 bad += [lfutil.splitstandin(f)
121 121 for f in repo[None].add(standins)
122 122 if f in m.files()]
123 123 finally:
124 124 wlock.release()
125 125 return bad
126 126
127 127 def removelargefiles(ui, repo, *pats, **opts):
128 128 after = opts.get('after')
129 129 if not pats and not after:
130 130 raise util.Abort(_('no files specified'))
131 131 m = scmutil.match(repo[None], pats, opts)
132 132 try:
133 133 repo.lfstatus = True
134 134 s = repo.status(match=m, clean=True)
135 135 finally:
136 136 repo.lfstatus = False
137 137 manifest = repo[None].manifest()
138 138 modified, added, deleted, clean = [[f for f in list
139 139 if lfutil.standin(f) in manifest]
140 140 for list in [s[0], s[1], s[3], s[6]]]
141 141
142 142 def warn(files, msg):
143 143 for f in files:
144 144 ui.warn(msg % m.rel(f))
145 145 return int(len(files) > 0)
146 146
147 147 result = 0
148 148
149 149 if after:
150 150 remove, forget = deleted, []
151 151 result = warn(modified + added + clean,
152 152 _('not removing %s: file still exists\n'))
153 153 else:
154 154 remove, forget = deleted + clean, []
155 155 result = warn(modified, _('not removing %s: file is modified (use -f'
156 156 ' to force removal)\n'))
157 157 result = warn(added, _('not removing %s: file has been marked for add'
158 158 ' (use forget to undo)\n')) or result
159 159
160 160 for f in sorted(remove + forget):
161 161 if ui.verbose or not m.exact(f):
162 162 ui.status(_('removing %s\n') % m.rel(f))
163 163
164 164 # Need to lock because standin files are deleted then removed from the
165 165 # repository and we could race in-between.
166 166 wlock = repo.wlock()
167 167 try:
168 168 lfdirstate = lfutil.openlfdirstate(ui, repo)
169 169 for f in remove:
170 170 if not after:
171 171 # If this is being called by addremove, notify the user that we
172 172 # are removing the file.
173 173 if getattr(repo, "_isaddremove", False):
174 174 ui.status(_('removing %s\n') % f)
175 175 util.unlinkpath(repo.wjoin(f), ignoremissing=True)
176 176 lfdirstate.remove(f)
177 177 lfdirstate.write()
178 178 forget = [lfutil.standin(f) for f in forget]
179 179 remove = [lfutil.standin(f) for f in remove]
180 180 repo[None].forget(forget)
181 181 # If this is being called by addremove, let the original addremove
182 182 # function handle this.
183 183 if not getattr(repo, "_isaddremove", False):
184 184 for f in remove:
185 185 util.unlinkpath(repo.wjoin(f), ignoremissing=True)
186 186 repo[None].forget(remove)
187 187 finally:
188 188 wlock.release()
189 189
190 190 return result
191 191
192 192 # For overriding mercurial.hgweb.webcommands so that largefiles will
193 193 # appear at their right place in the manifests.
194 194 def decodepath(orig, path):
195 195 return lfutil.splitstandin(path) or path
196 196
197 197 # -- Wrappers: modify existing commands --------------------------------
198 198
199 199 # Add works by going through the files that the user wanted to add and
200 200 # checking if they should be added as largefiles. Then it makes a new
201 201 # matcher which matches only the normal files and runs the original
202 202 # version of add.
203 203 def overrideadd(orig, ui, repo, *pats, **opts):
204 204 normal = opts.pop('normal')
205 205 if normal:
206 206 if opts.get('large'):
207 207 raise util.Abort(_('--normal cannot be used with --large'))
208 208 return orig(ui, repo, *pats, **opts)
209 209 bad = addlargefiles(ui, repo, *pats, **opts)
210 210 installnormalfilesmatchfn(repo[None].manifest())
211 211 result = orig(ui, repo, *pats, **opts)
212 212 restorematchfn()
213 213
214 214 return (result == 1 or bad) and 1 or 0
215 215
216 216 def overrideremove(orig, ui, repo, *pats, **opts):
217 217 installnormalfilesmatchfn(repo[None].manifest())
218 218 result = orig(ui, repo, *pats, **opts)
219 219 restorematchfn()
220 220 return removelargefiles(ui, repo, *pats, **opts) or result
221 221
222 222 def overridestatusfn(orig, repo, rev2, **opts):
223 223 try:
224 224 repo._repo.lfstatus = True
225 225 return orig(repo, rev2, **opts)
226 226 finally:
227 227 repo._repo.lfstatus = False
228 228
229 229 def overridestatus(orig, ui, repo, *pats, **opts):
230 230 try:
231 231 repo.lfstatus = True
232 232 return orig(ui, repo, *pats, **opts)
233 233 finally:
234 234 repo.lfstatus = False
235 235
236 236 def overridedirty(orig, repo, ignoreupdate=False):
237 237 try:
238 238 repo._repo.lfstatus = True
239 239 return orig(repo, ignoreupdate)
240 240 finally:
241 241 repo._repo.lfstatus = False
242 242
243 243 def overridelog(orig, ui, repo, *pats, **opts):
244 244 def overridematch(ctx, pats=[], opts={}, globbed=False,
245 245 default='relpath'):
246 246 """Matcher that merges root directory with .hglf, suitable for log.
247 247 It is still possible to match .hglf directly.
248 248 For any listed files run log on the standin too.
249 249 matchfn tries both the given filename and with .hglf stripped.
250 250 """
251 251 match = oldmatch(ctx, pats, opts, globbed, default)
252 252 m = copy.copy(match)
253 253 for i in range(0, len(m._files)):
254 254 standin = lfutil.standin(m._files[i])
255 255 if standin in repo[ctx.node()]:
256 256 m._files[i] = standin
257 257 m._fmap = set(m._files)
258 258 m._always = False
259 259 origmatchfn = m.matchfn
260 260 def lfmatchfn(f):
261 261 lf = lfutil.splitstandin(f)
262 262 if lf is not None and origmatchfn(lf):
263 263 return True
264 264 r = origmatchfn(f)
265 265 return r
266 266 m.matchfn = lfmatchfn
267 267 return m
268 268 oldmatch = installmatchfn(overridematch)
269 269 try:
270 270 repo.lfstatus = True
271 271 return orig(ui, repo, *pats, **opts)
272 272 finally:
273 273 repo.lfstatus = False
274 274 restorematchfn()
275 275
276 276 def overrideverify(orig, ui, repo, *pats, **opts):
277 277 large = opts.pop('large', False)
278 278 all = opts.pop('lfa', False)
279 279 contents = opts.pop('lfc', False)
280 280
281 281 result = orig(ui, repo, *pats, **opts)
282 282 if large or all or contents:
283 283 result = result or lfcommands.verifylfiles(ui, repo, all, contents)
284 284 return result
285 285
286 286 def overridedebugstate(orig, ui, repo, *pats, **opts):
287 287 large = opts.pop('large', False)
288 288 if large:
289 289 lfcommands.debugdirstate(ui, repo)
290 290 else:
291 291 orig(ui, repo, *pats, **opts)
292 292
293 293 # Override needs to refresh standins so that update's normal merge
294 294 # will go through properly. Then the other update hook (overriding repo.update)
295 295 # will get the new files. Filemerge is also overridden so that the merge
296 296 # will merge standins correctly.
297 297 def overrideupdate(orig, ui, repo, *pats, **opts):
298 298 lfdirstate = lfutil.openlfdirstate(ui, repo)
299 299 s = lfdirstate.status(match_.always(repo.root, repo.getcwd()), [], False,
300 300 False, False)
301 301 (unsure, modified, added, removed, missing, unknown, ignored, clean) = s
302 302
303 303 # Need to lock between the standins getting updated and their
304 304 # largefiles getting updated
305 305 wlock = repo.wlock()
306 306 try:
307 307 if opts['check']:
308 308 mod = len(modified) > 0
309 309 for lfile in unsure:
310 310 standin = lfutil.standin(lfile)
311 311 if repo['.'][standin].data().strip() != \
312 312 lfutil.hashfile(repo.wjoin(lfile)):
313 313 mod = True
314 314 else:
315 315 lfdirstate.normal(lfile)
316 316 lfdirstate.write()
317 317 if mod:
318 318 raise util.Abort(_('uncommitted changes'))
319 319 # XXX handle removed differently
320 320 if not opts['clean']:
321 321 for lfile in unsure + modified + added:
322 322 lfutil.updatestandin(repo, lfutil.standin(lfile))
323 323 finally:
324 324 wlock.release()
325 325 return orig(ui, repo, *pats, **opts)
326 326
327 327 # Before starting the manifest merge, merge.updates will call
328 328 # _checkunknown to check if there are any files in the merged-in
329 329 # changeset that collide with unknown files in the working copy.
330 330 #
331 331 # The largefiles are seen as unknown, so this prevents us from merging
332 332 # in a file 'foo' if we already have a largefile with the same name.
333 333 #
334 334 # The overridden function filters the unknown files by removing any
335 335 # largefiles. This makes the merge proceed and we can then handle this
336 336 # case further in the overridden manifestmerge function below.
337 337 def overridecheckunknownfile(origfn, repo, wctx, mctx, f):
338 338 if lfutil.standin(repo.dirstate.normalize(f)) in wctx:
339 339 return False
340 340 return origfn(repo, wctx, mctx, f)
341 341
342 342 # The manifest merge handles conflicts on the manifest level. We want
343 343 # to handle changes in largefile-ness of files at this level too.
344 344 #
345 345 # The strategy is to run the original manifestmerge and then process
346 346 # the action list it outputs. There are two cases we need to deal with:
347 347 #
348 348 # 1. Normal file in p1, largefile in p2. Here the largefile is
349 349 # detected via its standin file, which will enter the working copy
350 350 # with a "get" action. It is not "merge" since the standin is all
351 351 # Mercurial is concerned with at this level -- the link to the
352 352 # existing normal file is not relevant here.
353 353 #
354 354 # 2. Largefile in p1, normal file in p2. Here we get a "merge" action
355 355 # since the largefile will be present in the working copy and
356 356 # different from the normal file in p2. Mercurial therefore
357 357 # triggers a merge action.
358 358 #
359 359 # In both cases, we prompt the user and emit new actions to either
360 360 # remove the standin (if the normal file was kept) or to remove the
361 361 # normal file and get the standin (if the largefile was kept). The
362 362 # default prompt answer is to use the largefile version since it was
363 363 # presumably changed on purpose.
364 364 #
365 365 # Finally, the merge.applyupdates function will then take care of
366 366 # writing the files into the working copy and lfcommands.updatelfiles
367 367 # will update the largefiles.
368 368 def overridemanifestmerge(origfn, repo, p1, p2, pa, branchmerge, force,
369 369 partial, acceptremote=False):
370 370 overwrite = force and not branchmerge
371 371 actions = origfn(repo, p1, p2, pa, branchmerge, force, partial,
372 372 acceptremote)
373 373
374 374 if overwrite:
375 375 return actions
376 376
377 377 removes = set(a[0] for a in actions if a[1] == 'r')
378 378 processed = []
379 379
380 380 for action in actions:
381 381 f, m, args, msg = action
382 382
383 383 splitstandin = f and lfutil.splitstandin(f)
384 384 if (m == "g" and splitstandin is not None and
385 385 splitstandin in p1 and splitstandin not in removes):
386 386 # Case 1: normal file in the working copy, largefile in
387 387 # the second parent
388 388 lfile = splitstandin
389 389 standin = f
390 390 msg = _('remote turned local normal file %s into a largefile\n'
391 391 'use (l)argefile or keep (n)ormal file?'
392 392 '$$ &Largefile $$ &Normal file') % lfile
393 393 if repo.ui.promptchoice(msg, 0) == 0:
394 394 processed.append((lfile, "r", None, msg))
395 395 processed.append((standin, "g", (p2.flags(standin),), msg))
396 396 else:
397 397 processed.append((standin, "r", None, msg))
398 398 elif (m == "g" and
399 399 lfutil.standin(f) in p1 and lfutil.standin(f) not in removes):
400 400 # Case 2: largefile in the working copy, normal file in
401 401 # the second parent
402 402 standin = lfutil.standin(f)
403 403 lfile = f
404 404 msg = _('remote turned local largefile %s into a normal file\n'
405 405 'keep (l)argefile or use (n)ormal file?'
406 406 '$$ &Largefile $$ &Normal file') % lfile
407 407 if repo.ui.promptchoice(msg, 0) == 0:
408 408 processed.append((lfile, "r", None, msg))
409 409 else:
410 410 processed.append((standin, "r", None, msg))
411 411 processed.append((lfile, "g", (p2.flags(lfile),), msg))
412 412 else:
413 413 processed.append(action)
414 414
415 415 return processed
416 416
417 417 # Override filemerge to prompt the user about how they wish to merge
418 418 # largefiles. This will handle identical edits without prompting the user.
419 419 def overridefilemerge(origfn, repo, mynode, orig, fcd, fco, fca):
420 # Use better variable names here. Because this is a wrapper we cannot
421 # change the variable names in the function declaration.
422 fcdest, fcother, fcancestor = fcd, fco, fca
423 420 if not lfutil.isstandin(orig):
424 return origfn(repo, mynode, orig, fcdest, fcother, fcancestor)
425 else:
426 if not fcother.cmp(fcdest): # files identical?
427 return None
421 return origfn(repo, mynode, orig, fcd, fco, fca)
422
423 if not fco.cmp(fcd): # files identical?
424 return None
428 425
429 if repo.ui.promptchoice(
430 _('largefile %s has a merge conflict\nancestor was %s\n'
431 'keep (l)ocal %s or\ntake (o)ther %s?'
432 '$$ &Local $$ &Other') %
433 (lfutil.splitstandin(orig),
434 fca.data().strip(), fcd.data().strip(), fco.data().strip()),
435 0) == 0:
436 return 0
437 else:
438 repo.wwrite(fcdest.path(), fcother.data(), fcother.flags())
439 return 0
426 if repo.ui.promptchoice(
427 _('largefile %s has a merge conflict\nancestor was %s\n'
428 'keep (l)ocal %s or\ntake (o)ther %s?'
429 '$$ &Local $$ &Other') %
430 (lfutil.splitstandin(orig),
431 fca.data().strip(), fcd.data().strip(), fco.data().strip()),
432 0) == 1:
433 repo.wwrite(fcd.path(), fco.data(), fco.flags())
434 return 0
440 435
441 436 # Copy first changes the matchers to match standins instead of
442 437 # largefiles. Then it overrides util.copyfile in that function it
443 438 # checks if the destination largefile already exists. It also keeps a
444 439 # list of copied files so that the largefiles can be copied and the
445 440 # dirstate updated.
446 441 def overridecopy(orig, ui, repo, pats, opts, rename=False):
447 442 # doesn't remove largefile on rename
448 443 if len(pats) < 2:
449 444 # this isn't legal, let the original function deal with it
450 445 return orig(ui, repo, pats, opts, rename)
451 446
452 447 def makestandin(relpath):
453 448 path = pathutil.canonpath(repo.root, repo.getcwd(), relpath)
454 449 return os.path.join(repo.wjoin(lfutil.standin(path)))
455 450
456 451 fullpats = scmutil.expandpats(pats)
457 452 dest = fullpats[-1]
458 453
459 454 if os.path.isdir(dest):
460 455 if not os.path.isdir(makestandin(dest)):
461 456 os.makedirs(makestandin(dest))
462 457 # This could copy both lfiles and normal files in one command,
463 458 # but we don't want to do that. First replace their matcher to
464 459 # only match normal files and run it, then replace it to just
465 460 # match largefiles and run it again.
466 461 nonormalfiles = False
467 462 nolfiles = False
468 463 try:
469 464 try:
470 465 installnormalfilesmatchfn(repo[None].manifest())
471 466 result = orig(ui, repo, pats, opts, rename)
472 467 except util.Abort, e:
473 468 if str(e) != _('no files to copy'):
474 469 raise e
475 470 else:
476 471 nonormalfiles = True
477 472 result = 0
478 473 finally:
479 474 restorematchfn()
480 475
481 476 # The first rename can cause our current working directory to be removed.
482 477 # In that case there is nothing left to copy/rename so just quit.
483 478 try:
484 479 repo.getcwd()
485 480 except OSError:
486 481 return result
487 482
488 483 try:
489 484 try:
490 485 # When we call orig below it creates the standins but we don't add
491 486 # them to the dir state until later so lock during that time.
492 487 wlock = repo.wlock()
493 488
494 489 manifest = repo[None].manifest()
495 490 oldmatch = None # for the closure
496 491 def overridematch(ctx, pats=[], opts={}, globbed=False,
497 492 default='relpath'):
498 493 newpats = []
499 494 # The patterns were previously mangled to add the standin
500 495 # directory; we need to remove that now
501 496 for pat in pats:
502 497 if match_.patkind(pat) is None and lfutil.shortname in pat:
503 498 newpats.append(pat.replace(lfutil.shortname, ''))
504 499 else:
505 500 newpats.append(pat)
506 501 match = oldmatch(ctx, newpats, opts, globbed, default)
507 502 m = copy.copy(match)
508 503 lfile = lambda f: lfutil.standin(f) in manifest
509 504 m._files = [lfutil.standin(f) for f in m._files if lfile(f)]
510 505 m._fmap = set(m._files)
511 506 m._always = False
512 507 origmatchfn = m.matchfn
513 508 m.matchfn = lambda f: (lfutil.isstandin(f) and
514 509 (f in manifest) and
515 510 origmatchfn(lfutil.splitstandin(f)) or
516 511 None)
517 512 return m
518 513 oldmatch = installmatchfn(overridematch)
519 514 listpats = []
520 515 for pat in pats:
521 516 if match_.patkind(pat) is not None:
522 517 listpats.append(pat)
523 518 else:
524 519 listpats.append(makestandin(pat))
525 520
526 521 try:
527 522 origcopyfile = util.copyfile
528 523 copiedfiles = []
529 524 def overridecopyfile(src, dest):
530 525 if (lfutil.shortname in src and
531 526 dest.startswith(repo.wjoin(lfutil.shortname))):
532 527 destlfile = dest.replace(lfutil.shortname, '')
533 528 if not opts['force'] and os.path.exists(destlfile):
534 529 raise IOError('',
535 530 _('destination largefile already exists'))
536 531 copiedfiles.append((src, dest))
537 532 origcopyfile(src, dest)
538 533
539 534 util.copyfile = overridecopyfile
540 535 result += orig(ui, repo, listpats, opts, rename)
541 536 finally:
542 537 util.copyfile = origcopyfile
543 538
544 539 lfdirstate = lfutil.openlfdirstate(ui, repo)
545 540 for (src, dest) in copiedfiles:
546 541 if (lfutil.shortname in src and
547 542 dest.startswith(repo.wjoin(lfutil.shortname))):
548 543 srclfile = src.replace(repo.wjoin(lfutil.standin('')), '')
549 544 destlfile = dest.replace(repo.wjoin(lfutil.standin('')), '')
550 545 destlfiledir = os.path.dirname(repo.wjoin(destlfile)) or '.'
551 546 if not os.path.isdir(destlfiledir):
552 547 os.makedirs(destlfiledir)
553 548 if rename:
554 549 os.rename(repo.wjoin(srclfile), repo.wjoin(destlfile))
555 550 lfdirstate.remove(srclfile)
556 551 else:
557 552 util.copyfile(repo.wjoin(srclfile),
558 553 repo.wjoin(destlfile))
559 554
560 555 lfdirstate.add(destlfile)
561 556 lfdirstate.write()
562 557 except util.Abort, e:
563 558 if str(e) != _('no files to copy'):
564 559 raise e
565 560 else:
566 561 nolfiles = True
567 562 finally:
568 563 restorematchfn()
569 564 wlock.release()
570 565
571 566 if nolfiles and nonormalfiles:
572 567 raise util.Abort(_('no files to copy'))
573 568
574 569 return result
575 570
576 571 # When the user calls revert, we have to be careful to not revert any
577 572 # changes to other largefiles accidentally. This means we have to keep
578 573 # track of the largefiles that are being reverted so we only pull down
579 574 # the necessary largefiles.
580 575 #
581 576 # Standins are only updated (to match the hash of largefiles) before
582 577 # commits. Update the standins then run the original revert, changing
583 578 # the matcher to hit standins instead of largefiles. Based on the
584 579 # resulting standins update the largefiles. Then return the standins
585 580 # to their proper state
586 581 def overriderevert(orig, ui, repo, *pats, **opts):
587 582 # Because we put the standins in a bad state (by updating them)
588 583 # and then return them to a correct state we need to lock to
589 584 # prevent others from changing them in their incorrect state.
590 585 wlock = repo.wlock()
591 586 try:
592 587 lfdirstate = lfutil.openlfdirstate(ui, repo)
593 588 (modified, added, removed, missing, unknown, ignored, clean) = \
594 589 lfutil.lfdirstatestatus(lfdirstate, repo, repo['.'].rev())
595 590 lfdirstate.write()
596 591 for lfile in modified:
597 592 lfutil.updatestandin(repo, lfutil.standin(lfile))
598 593 for lfile in missing:
599 594 if (os.path.exists(repo.wjoin(lfutil.standin(lfile)))):
600 595 os.unlink(repo.wjoin(lfutil.standin(lfile)))
601 596
602 597 try:
603 598 ctx = scmutil.revsingle(repo, opts.get('rev'))
604 599 oldmatch = None # for the closure
605 600 def overridematch(ctx, pats=[], opts={}, globbed=False,
606 601 default='relpath'):
607 602 match = oldmatch(ctx, pats, opts, globbed, default)
608 603 m = copy.copy(match)
609 604 def tostandin(f):
610 605 if lfutil.standin(f) in ctx:
611 606 return lfutil.standin(f)
612 607 elif lfutil.standin(f) in repo[None]:
613 608 return None
614 609 return f
615 610 m._files = [tostandin(f) for f in m._files]
616 611 m._files = [f for f in m._files if f is not None]
617 612 m._fmap = set(m._files)
618 613 m._always = False
619 614 origmatchfn = m.matchfn
620 615 def matchfn(f):
621 616 if lfutil.isstandin(f):
622 617 # We need to keep track of what largefiles are being
623 618 # matched so we know which ones to update later --
624 619 # otherwise we accidentally revert changes to other
625 620 # largefiles. This is repo-specific, so duckpunch the
626 621 # repo object to keep the list of largefiles for us
627 622 # later.
628 623 if origmatchfn(lfutil.splitstandin(f)) and \
629 624 (f in repo[None] or f in ctx):
630 625 lfileslist = getattr(repo, '_lfilestoupdate', [])
631 626 lfileslist.append(lfutil.splitstandin(f))
632 627 repo._lfilestoupdate = lfileslist
633 628 return True
634 629 else:
635 630 return False
636 631 return origmatchfn(f)
637 632 m.matchfn = matchfn
638 633 return m
639 634 oldmatch = installmatchfn(overridematch)
640 635 scmutil.match
641 636 matches = overridematch(repo[None], pats, opts)
642 637 orig(ui, repo, *pats, **opts)
643 638 finally:
644 639 restorematchfn()
645 640 lfileslist = getattr(repo, '_lfilestoupdate', [])
646 641 lfcommands.updatelfiles(ui, repo, filelist=lfileslist,
647 642 printmessage=False)
648 643
649 644 # empty out the largefiles list so we start fresh next time
650 645 repo._lfilestoupdate = []
651 646 for lfile in modified:
652 647 if lfile in lfileslist:
653 648 if os.path.exists(repo.wjoin(lfutil.standin(lfile))) and lfile\
654 649 in repo['.']:
655 650 lfutil.writestandin(repo, lfutil.standin(lfile),
656 651 repo['.'][lfile].data().strip(),
657 652 'x' in repo['.'][lfile].flags())
658 653 lfdirstate = lfutil.openlfdirstate(ui, repo)
659 654 for lfile in added:
660 655 standin = lfutil.standin(lfile)
661 656 if standin not in ctx and (standin in matches or opts.get('all')):
662 657 if lfile in lfdirstate:
663 658 lfdirstate.drop(lfile)
664 659 util.unlinkpath(repo.wjoin(standin))
665 660 lfdirstate.write()
666 661 finally:
667 662 wlock.release()
668 663
669 664 def hgupdaterepo(orig, repo, node, overwrite):
670 665 if not overwrite:
671 666 # Only call updatelfiles on the standins that have changed to save time
672 667 oldstandins = lfutil.getstandinsstate(repo)
673 668
674 669 result = orig(repo, node, overwrite)
675 670
676 671 filelist = None
677 672 if not overwrite:
678 673 newstandins = lfutil.getstandinsstate(repo)
679 674 filelist = lfutil.getlfilestoupdate(oldstandins, newstandins)
680 675 lfcommands.updatelfiles(repo.ui, repo, filelist=filelist)
681 676 return result
682 677
683 678 def hgmerge(orig, repo, node, force=None, remind=True):
684 679 result = orig(repo, node, force, remind)
685 680 lfcommands.updatelfiles(repo.ui, repo)
686 681 return result
687 682
688 683 # When we rebase a repository with remotely changed largefiles, we need to
689 684 # take some extra care so that the largefiles are correctly updated in the
690 685 # working copy
691 686 def overridepull(orig, ui, repo, source=None, **opts):
692 687 revsprepull = len(repo)
693 688 if not source:
694 689 source = 'default'
695 690 repo.lfpullsource = source
696 691 if opts.get('rebase', False):
697 692 repo._isrebasing = True
698 693 try:
699 694 if opts.get('update'):
700 695 del opts['update']
701 696 ui.debug('--update and --rebase are not compatible, ignoring '
702 697 'the update flag\n')
703 698 del opts['rebase']
704 699 origpostincoming = commands.postincoming
705 700 def _dummy(*args, **kwargs):
706 701 pass
707 702 commands.postincoming = _dummy
708 703 try:
709 704 result = commands.pull(ui, repo, source, **opts)
710 705 finally:
711 706 commands.postincoming = origpostincoming
712 707 revspostpull = len(repo)
713 708 if revspostpull > revsprepull:
714 709 result = result or rebase.rebase(ui, repo)
715 710 finally:
716 711 repo._isrebasing = False
717 712 else:
718 713 result = orig(ui, repo, source, **opts)
719 714 revspostpull = len(repo)
720 715 lfrevs = opts.get('lfrev', [])
721 716 if opts.get('all_largefiles'):
722 717 lfrevs.append('pulled()')
723 718 if lfrevs and revspostpull > revsprepull:
724 719 numcached = 0
725 720 repo.firstpulled = revsprepull # for pulled() revset expression
726 721 try:
727 722 for rev in scmutil.revrange(repo, lfrevs):
728 723 ui.note(_('pulling largefiles for revision %s\n') % rev)
729 724 (cached, missing) = lfcommands.cachelfiles(ui, repo, rev)
730 725 numcached += len(cached)
731 726 finally:
732 727 del repo.firstpulled
733 728 ui.status(_("%d largefiles cached\n") % numcached)
734 729 return result
735 730
736 731 def pulledrevsetsymbol(repo, subset, x):
737 732 """``pulled()``
738 733 Changesets that just has been pulled.
739 734
740 735 Only available with largefiles from pull --lfrev expressions.
741 736
742 737 .. container:: verbose
743 738
744 739 Some examples:
745 740
746 741 - pull largefiles for all new changesets::
747 742
748 743 hg pull -lfrev "pulled()"
749 744
750 745 - pull largefiles for all new branch heads::
751 746
752 747 hg pull -lfrev "head(pulled()) and not closed()"
753 748
754 749 """
755 750
756 751 try:
757 752 firstpulled = repo.firstpulled
758 753 except AttributeError:
759 754 raise util.Abort(_("pulled() only available in --lfrev"))
760 755 return [r for r in subset if r >= firstpulled]
761 756
762 757 def overrideclone(orig, ui, source, dest=None, **opts):
763 758 d = dest
764 759 if d is None:
765 760 d = hg.defaultdest(source)
766 761 if opts.get('all_largefiles') and not hg.islocal(d):
767 762 raise util.Abort(_(
768 763 '--all-largefiles is incompatible with non-local destination %s' %
769 764 d))
770 765
771 766 return orig(ui, source, dest, **opts)
772 767
773 768 def hgclone(orig, ui, opts, *args, **kwargs):
774 769 result = orig(ui, opts, *args, **kwargs)
775 770
776 771 if result is not None:
777 772 sourcerepo, destrepo = result
778 773 repo = destrepo.local()
779 774
780 775 # Caching is implicitly limited to 'rev' option, since the dest repo was
781 776 # truncated at that point. The user may expect a download count with
782 777 # this option, so attempt whether or not this is a largefile repo.
783 778 if opts.get('all_largefiles'):
784 779 success, missing = lfcommands.downloadlfiles(ui, repo, None)
785 780
786 781 if missing != 0:
787 782 return None
788 783
789 784 return result
790 785
791 786 def overriderebase(orig, ui, repo, **opts):
792 787 repo._isrebasing = True
793 788 try:
794 789 return orig(ui, repo, **opts)
795 790 finally:
796 791 repo._isrebasing = False
797 792
798 793 def overridearchive(orig, repo, dest, node, kind, decode=True, matchfn=None,
799 794 prefix=None, mtime=None, subrepos=None):
800 795 # No need to lock because we are only reading history and
801 796 # largefile caches, neither of which are modified.
802 797 lfcommands.cachelfiles(repo.ui, repo, node)
803 798
804 799 if kind not in archival.archivers:
805 800 raise util.Abort(_("unknown archive type '%s'") % kind)
806 801
807 802 ctx = repo[node]
808 803
809 804 if kind == 'files':
810 805 if prefix:
811 806 raise util.Abort(
812 807 _('cannot give prefix when archiving to files'))
813 808 else:
814 809 prefix = archival.tidyprefix(dest, kind, prefix)
815 810
816 811 def write(name, mode, islink, getdata):
817 812 if matchfn and not matchfn(name):
818 813 return
819 814 data = getdata()
820 815 if decode:
821 816 data = repo.wwritedata(name, data)
822 817 archiver.addfile(prefix + name, mode, islink, data)
823 818
824 819 archiver = archival.archivers[kind](dest, mtime or ctx.date()[0])
825 820
826 821 if repo.ui.configbool("ui", "archivemeta", True):
827 822 def metadata():
828 823 base = 'repo: %s\nnode: %s\nbranch: %s\n' % (
829 824 hex(repo.changelog.node(0)), hex(node), ctx.branch())
830 825
831 826 tags = ''.join('tag: %s\n' % t for t in ctx.tags()
832 827 if repo.tagtype(t) == 'global')
833 828 if not tags:
834 829 repo.ui.pushbuffer()
835 830 opts = {'template': '{latesttag}\n{latesttagdistance}',
836 831 'style': '', 'patch': None, 'git': None}
837 832 cmdutil.show_changeset(repo.ui, repo, opts).show(ctx)
838 833 ltags, dist = repo.ui.popbuffer().split('\n')
839 834 tags = ''.join('latesttag: %s\n' % t for t in ltags.split(':'))
840 835 tags += 'latesttagdistance: %s\n' % dist
841 836
842 837 return base + tags
843 838
844 839 write('.hg_archival.txt', 0644, False, metadata)
845 840
846 841 for f in ctx:
847 842 ff = ctx.flags(f)
848 843 getdata = ctx[f].data
849 844 if lfutil.isstandin(f):
850 845 path = lfutil.findfile(repo, getdata().strip())
851 846 if path is None:
852 847 raise util.Abort(
853 848 _('largefile %s not found in repo store or system cache')
854 849 % lfutil.splitstandin(f))
855 850 f = lfutil.splitstandin(f)
856 851
857 852 def getdatafn():
858 853 fd = None
859 854 try:
860 855 fd = open(path, 'rb')
861 856 return fd.read()
862 857 finally:
863 858 if fd:
864 859 fd.close()
865 860
866 861 getdata = getdatafn
867 862 write(f, 'x' in ff and 0755 or 0644, 'l' in ff, getdata)
868 863
869 864 if subrepos:
870 865 for subpath in sorted(ctx.substate):
871 866 sub = ctx.sub(subpath)
872 867 submatch = match_.narrowmatcher(subpath, matchfn)
873 868 sub.archive(repo.ui, archiver, prefix, submatch)
874 869
875 870 archiver.done()
876 871
877 872 def hgsubrepoarchive(orig, repo, ui, archiver, prefix, match=None):
878 873 repo._get(repo._state + ('hg',))
879 874 rev = repo._state[1]
880 875 ctx = repo._repo[rev]
881 876
882 877 lfcommands.cachelfiles(ui, repo._repo, ctx.node())
883 878
884 879 def write(name, mode, islink, getdata):
885 880 # At this point, the standin has been replaced with the largefile name,
886 881 # so the normal matcher works here without the lfutil variants.
887 882 if match and not match(f):
888 883 return
889 884 data = getdata()
890 885
891 886 archiver.addfile(prefix + repo._path + '/' + name, mode, islink, data)
892 887
893 888 for f in ctx:
894 889 ff = ctx.flags(f)
895 890 getdata = ctx[f].data
896 891 if lfutil.isstandin(f):
897 892 path = lfutil.findfile(repo._repo, getdata().strip())
898 893 if path is None:
899 894 raise util.Abort(
900 895 _('largefile %s not found in repo store or system cache')
901 896 % lfutil.splitstandin(f))
902 897 f = lfutil.splitstandin(f)
903 898
904 899 def getdatafn():
905 900 fd = None
906 901 try:
907 902 fd = open(os.path.join(prefix, path), 'rb')
908 903 return fd.read()
909 904 finally:
910 905 if fd:
911 906 fd.close()
912 907
913 908 getdata = getdatafn
914 909
915 910 write(f, 'x' in ff and 0755 or 0644, 'l' in ff, getdata)
916 911
917 912 for subpath in sorted(ctx.substate):
918 913 sub = ctx.sub(subpath)
919 914 submatch = match_.narrowmatcher(subpath, match)
920 915 sub.archive(ui, archiver, os.path.join(prefix, repo._path) + '/',
921 916 submatch)
922 917
923 918 # If a largefile is modified, the change is not reflected in its
924 919 # standin until a commit. cmdutil.bailifchanged() raises an exception
925 920 # if the repo has uncommitted changes. Wrap it to also check if
926 921 # largefiles were changed. This is used by bisect and backout.
927 922 def overridebailifchanged(orig, repo):
928 923 orig(repo)
929 924 repo.lfstatus = True
930 925 modified, added, removed, deleted = repo.status()[:4]
931 926 repo.lfstatus = False
932 927 if modified or added or removed or deleted:
933 928 raise util.Abort(_('uncommitted changes'))
934 929
935 930 # Fetch doesn't use cmdutil.bailifchanged so override it to add the check
936 931 def overridefetch(orig, ui, repo, *pats, **opts):
937 932 repo.lfstatus = True
938 933 modified, added, removed, deleted = repo.status()[:4]
939 934 repo.lfstatus = False
940 935 if modified or added or removed or deleted:
941 936 raise util.Abort(_('uncommitted changes'))
942 937 return orig(ui, repo, *pats, **opts)
943 938
944 939 def overrideforget(orig, ui, repo, *pats, **opts):
945 940 installnormalfilesmatchfn(repo[None].manifest())
946 941 result = orig(ui, repo, *pats, **opts)
947 942 restorematchfn()
948 943 m = scmutil.match(repo[None], pats, opts)
949 944
950 945 try:
951 946 repo.lfstatus = True
952 947 s = repo.status(match=m, clean=True)
953 948 finally:
954 949 repo.lfstatus = False
955 950 forget = sorted(s[0] + s[1] + s[3] + s[6])
956 951 forget = [f for f in forget if lfutil.standin(f) in repo[None].manifest()]
957 952
958 953 for f in forget:
959 954 if lfutil.standin(f) not in repo.dirstate and not \
960 955 os.path.isdir(m.rel(lfutil.standin(f))):
961 956 ui.warn(_('not removing %s: file is already untracked\n')
962 957 % m.rel(f))
963 958 result = 1
964 959
965 960 for f in forget:
966 961 if ui.verbose or not m.exact(f):
967 962 ui.status(_('removing %s\n') % m.rel(f))
968 963
969 964 # Need to lock because standin files are deleted then removed from the
970 965 # repository and we could race in-between.
971 966 wlock = repo.wlock()
972 967 try:
973 968 lfdirstate = lfutil.openlfdirstate(ui, repo)
974 969 for f in forget:
975 970 if lfdirstate[f] == 'a':
976 971 lfdirstate.drop(f)
977 972 else:
978 973 lfdirstate.remove(f)
979 974 lfdirstate.write()
980 975 standins = [lfutil.standin(f) for f in forget]
981 976 for f in standins:
982 977 util.unlinkpath(repo.wjoin(f), ignoremissing=True)
983 978 repo[None].forget(standins)
984 979 finally:
985 980 wlock.release()
986 981
987 982 return result
988 983
989 984 def getoutgoinglfiles(ui, repo, dest=None, **opts):
990 985 dest = ui.expandpath(dest or 'default-push', dest or 'default')
991 986 dest, branches = hg.parseurl(dest, opts.get('branch'))
992 987 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
993 988 if revs:
994 989 revs = [repo.lookup(rev) for rev in scmutil.revrange(repo, revs)]
995 990
996 991 try:
997 992 remote = hg.peer(repo, opts, dest)
998 993 except error.RepoError:
999 994 return None
1000 995 outgoing = discovery.findcommonoutgoing(repo, remote.peer(), force=False)
1001 996 if not outgoing.missing:
1002 997 return outgoing.missing
1003 998 o = repo.changelog.nodesbetween(outgoing.missing, revs)[0]
1004 999 if opts.get('newest_first'):
1005 1000 o.reverse()
1006 1001
1007 1002 toupload = set()
1008 1003 for n in o:
1009 1004 parents = [p for p in repo.changelog.parents(n) if p != node.nullid]
1010 1005 ctx = repo[n]
1011 1006 files = set(ctx.files())
1012 1007 if len(parents) == 2:
1013 1008 mc = ctx.manifest()
1014 1009 mp1 = ctx.parents()[0].manifest()
1015 1010 mp2 = ctx.parents()[1].manifest()
1016 1011 for f in mp1:
1017 1012 if f not in mc:
1018 1013 files.add(f)
1019 1014 for f in mp2:
1020 1015 if f not in mc:
1021 1016 files.add(f)
1022 1017 for f in mc:
1023 1018 if mc[f] != mp1.get(f, None) or mc[f] != mp2.get(f, None):
1024 1019 files.add(f)
1025 1020 toupload = toupload.union(
1026 1021 set([f for f in files if lfutil.isstandin(f) and f in ctx]))
1027 1022 return sorted(toupload)
1028 1023
1029 1024 def overrideoutgoing(orig, ui, repo, dest=None, **opts):
1030 1025 result = orig(ui, repo, dest, **opts)
1031 1026
1032 1027 if opts.pop('large', None):
1033 1028 toupload = getoutgoinglfiles(ui, repo, dest, **opts)
1034 1029 if toupload is None:
1035 1030 ui.status(_('largefiles: No remote repo\n'))
1036 1031 elif not toupload:
1037 1032 ui.status(_('largefiles: no files to upload\n'))
1038 1033 else:
1039 1034 ui.status(_('largefiles to upload:\n'))
1040 1035 for file in toupload:
1041 1036 ui.status(lfutil.splitstandin(file) + '\n')
1042 1037 ui.status('\n')
1043 1038
1044 1039 return result
1045 1040
1046 1041 def overridesummary(orig, ui, repo, *pats, **opts):
1047 1042 try:
1048 1043 repo.lfstatus = True
1049 1044 orig(ui, repo, *pats, **opts)
1050 1045 finally:
1051 1046 repo.lfstatus = False
1052 1047
1053 1048 if opts.pop('large', None):
1054 1049 toupload = getoutgoinglfiles(ui, repo, None, **opts)
1055 1050 if toupload is None:
1056 1051 # i18n: column positioning for "hg summary"
1057 1052 ui.status(_('largefiles: (no remote repo)\n'))
1058 1053 elif not toupload:
1059 1054 # i18n: column positioning for "hg summary"
1060 1055 ui.status(_('largefiles: (no files to upload)\n'))
1061 1056 else:
1062 1057 # i18n: column positioning for "hg summary"
1063 1058 ui.status(_('largefiles: %d to upload\n') % len(toupload))
1064 1059
1065 1060 def scmutiladdremove(orig, repo, pats=[], opts={}, dry_run=None,
1066 1061 similarity=None):
1067 1062 if not lfutil.islfilesrepo(repo):
1068 1063 return orig(repo, pats, opts, dry_run, similarity)
1069 1064 # Get the list of missing largefiles so we can remove them
1070 1065 lfdirstate = lfutil.openlfdirstate(repo.ui, repo)
1071 1066 s = lfdirstate.status(match_.always(repo.root, repo.getcwd()), [], False,
1072 1067 False, False)
1073 1068 (unsure, modified, added, removed, missing, unknown, ignored, clean) = s
1074 1069
1075 1070 # Call into the normal remove code, but the removing of the standin, we want
1076 1071 # to have handled by original addremove. Monkey patching here makes sure
1077 1072 # we don't remove the standin in the largefiles code, preventing a very
1078 1073 # confused state later.
1079 1074 if missing:
1080 1075 m = [repo.wjoin(f) for f in missing]
1081 1076 repo._isaddremove = True
1082 1077 removelargefiles(repo.ui, repo, *m, **opts)
1083 1078 repo._isaddremove = False
1084 1079 # Call into the normal add code, and any files that *should* be added as
1085 1080 # largefiles will be
1086 1081 addlargefiles(repo.ui, repo, *pats, **opts)
1087 1082 # Now that we've handled largefiles, hand off to the original addremove
1088 1083 # function to take care of the rest. Make sure it doesn't do anything with
1089 1084 # largefiles by installing a matcher that will ignore them.
1090 1085 installnormalfilesmatchfn(repo[None].manifest())
1091 1086 result = orig(repo, pats, opts, dry_run, similarity)
1092 1087 restorematchfn()
1093 1088 return result
1094 1089
1095 1090 # Calling purge with --all will cause the largefiles to be deleted.
1096 1091 # Override repo.status to prevent this from happening.
1097 1092 def overridepurge(orig, ui, repo, *dirs, **opts):
1098 1093 # XXX large file status is buggy when used on repo proxy.
1099 1094 # XXX this needs to be investigate.
1100 1095 repo = repo.unfiltered()
1101 1096 oldstatus = repo.status
1102 1097 def overridestatus(node1='.', node2=None, match=None, ignored=False,
1103 1098 clean=False, unknown=False, listsubrepos=False):
1104 1099 r = oldstatus(node1, node2, match, ignored, clean, unknown,
1105 1100 listsubrepos)
1106 1101 lfdirstate = lfutil.openlfdirstate(ui, repo)
1107 1102 modified, added, removed, deleted, unknown, ignored, clean = r
1108 1103 unknown = [f for f in unknown if lfdirstate[f] == '?']
1109 1104 ignored = [f for f in ignored if lfdirstate[f] == '?']
1110 1105 return modified, added, removed, deleted, unknown, ignored, clean
1111 1106 repo.status = overridestatus
1112 1107 orig(ui, repo, *dirs, **opts)
1113 1108 repo.status = oldstatus
1114 1109
1115 1110 def overriderollback(orig, ui, repo, **opts):
1116 1111 result = orig(ui, repo, **opts)
1117 1112 merge.update(repo, node=None, branchmerge=False, force=True,
1118 1113 partial=lfutil.isstandin)
1119 1114 wlock = repo.wlock()
1120 1115 try:
1121 1116 lfdirstate = lfutil.openlfdirstate(ui, repo)
1122 1117 lfiles = lfutil.listlfiles(repo)
1123 1118 oldlfiles = lfutil.listlfiles(repo, repo[None].parents()[0].rev())
1124 1119 for file in lfiles:
1125 1120 if file in oldlfiles:
1126 1121 lfdirstate.normallookup(file)
1127 1122 else:
1128 1123 lfdirstate.add(file)
1129 1124 lfdirstate.write()
1130 1125 finally:
1131 1126 wlock.release()
1132 1127 return result
1133 1128
1134 1129 def overridetransplant(orig, ui, repo, *revs, **opts):
1135 1130 try:
1136 1131 oldstandins = lfutil.getstandinsstate(repo)
1137 1132 repo._istransplanting = True
1138 1133 result = orig(ui, repo, *revs, **opts)
1139 1134 newstandins = lfutil.getstandinsstate(repo)
1140 1135 filelist = lfutil.getlfilestoupdate(oldstandins, newstandins)
1141 1136 lfcommands.updatelfiles(repo.ui, repo, filelist=filelist,
1142 1137 printmessage=True)
1143 1138 finally:
1144 1139 repo._istransplanting = False
1145 1140 return result
1146 1141
1147 1142 def overridecat(orig, ui, repo, file1, *pats, **opts):
1148 1143 ctx = scmutil.revsingle(repo, opts.get('rev'))
1149 1144 err = 1
1150 1145 notbad = set()
1151 1146 m = scmutil.match(ctx, (file1,) + pats, opts)
1152 1147 origmatchfn = m.matchfn
1153 1148 def lfmatchfn(f):
1154 1149 lf = lfutil.splitstandin(f)
1155 1150 if lf is None:
1156 1151 return origmatchfn(f)
1157 1152 notbad.add(lf)
1158 1153 return origmatchfn(lf)
1159 1154 m.matchfn = lfmatchfn
1160 1155 origbadfn = m.bad
1161 1156 def lfbadfn(f, msg):
1162 1157 if not f in notbad:
1163 1158 return origbadfn(f, msg)
1164 1159 m.bad = lfbadfn
1165 1160 for f in ctx.walk(m):
1166 1161 fp = cmdutil.makefileobj(repo, opts.get('output'), ctx.node(),
1167 1162 pathname=f)
1168 1163 lf = lfutil.splitstandin(f)
1169 1164 if lf is None:
1170 1165 # duplicating unreachable code from commands.cat
1171 1166 data = ctx[f].data()
1172 1167 if opts.get('decode'):
1173 1168 data = repo.wwritedata(f, data)
1174 1169 fp.write(data)
1175 1170 else:
1176 1171 hash = lfutil.readstandin(repo, lf, ctx.rev())
1177 1172 if not lfutil.inusercache(repo.ui, hash):
1178 1173 store = basestore._openstore(repo)
1179 1174 success, missing = store.get([(lf, hash)])
1180 1175 if len(success) != 1:
1181 1176 raise util.Abort(
1182 1177 _('largefile %s is not in cache and could not be '
1183 1178 'downloaded') % lf)
1184 1179 path = lfutil.usercachepath(repo.ui, hash)
1185 1180 fpin = open(path, "rb")
1186 1181 for chunk in util.filechunkiter(fpin, 128 * 1024):
1187 1182 fp.write(chunk)
1188 1183 fpin.close()
1189 1184 fp.close()
1190 1185 err = 0
1191 1186 return err
1192 1187
1193 1188 def mercurialsinkbefore(orig, sink):
1194 1189 sink.repo._isconverting = True
1195 1190 orig(sink)
1196 1191
1197 1192 def mercurialsinkafter(orig, sink):
1198 1193 sink.repo._isconverting = False
1199 1194 orig(sink)
General Comments 0
You need to be logged in to leave comments. Login now