##// END OF EJS Templates
largefiles: delegate to the wrapped clone command...
Matt Harbison -
r17601:6e2ab601 stable
parent child Browse files
Show More
@@ -1,1103 +1,1104 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
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
23 23 # -- Utility functions: commonly/repeatedly needed functionality ---------------
24 24
25 25 def installnormalfilesmatchfn(manifest):
26 26 '''overrides scmutil.match so that the matcher it returns will ignore all
27 27 largefiles'''
28 28 oldmatch = None # for the closure
29 29 def overridematch(ctx, pats=[], opts={}, globbed=False,
30 30 default='relpath'):
31 31 match = oldmatch(ctx, pats, opts, globbed, default)
32 32 m = copy.copy(match)
33 33 notlfile = lambda f: not (lfutil.isstandin(f) or lfutil.standin(f) in
34 34 manifest)
35 35 m._files = filter(notlfile, m._files)
36 36 m._fmap = set(m._files)
37 37 origmatchfn = m.matchfn
38 38 m.matchfn = lambda f: notlfile(f) and origmatchfn(f) or None
39 39 return m
40 40 oldmatch = installmatchfn(overridematch)
41 41
42 42 def installmatchfn(f):
43 43 oldmatch = scmutil.match
44 44 setattr(f, 'oldmatch', oldmatch)
45 45 scmutil.match = f
46 46 return oldmatch
47 47
48 48 def restorematchfn():
49 49 '''restores scmutil.match to what it was before installnormalfilesmatchfn
50 50 was called. no-op if scmutil.match is its original function.
51 51
52 52 Note that n calls to installnormalfilesmatchfn will require n calls to
53 53 restore matchfn to reverse'''
54 54 scmutil.match = getattr(scmutil.match, 'oldmatch', scmutil.match)
55 55
56 56 def addlargefiles(ui, repo, *pats, **opts):
57 57 large = opts.pop('large', None)
58 58 lfsize = lfutil.getminsize(
59 59 ui, lfutil.islfilesrepo(repo), opts.pop('lfsize', None))
60 60
61 61 lfmatcher = None
62 62 if lfutil.islfilesrepo(repo):
63 63 lfpats = ui.configlist(lfutil.longname, 'patterns', default=[])
64 64 if lfpats:
65 65 lfmatcher = match_.match(repo.root, '', list(lfpats))
66 66
67 67 lfnames = []
68 68 m = scmutil.match(repo[None], pats, opts)
69 69 m.bad = lambda x, y: None
70 70 wctx = repo[None]
71 71 for f in repo.walk(m):
72 72 exact = m.exact(f)
73 73 lfile = lfutil.standin(f) in wctx
74 74 nfile = f in wctx
75 75 exists = lfile or nfile
76 76
77 77 # Don't warn the user when they attempt to add a normal tracked file.
78 78 # The normal add code will do that for us.
79 79 if exact and exists:
80 80 if lfile:
81 81 ui.warn(_('%s already a largefile\n') % f)
82 82 continue
83 83
84 84 if (exact or not exists) and not lfutil.isstandin(f):
85 85 wfile = repo.wjoin(f)
86 86
87 87 # In case the file was removed previously, but not committed
88 88 # (issue3507)
89 89 if not os.path.exists(wfile):
90 90 continue
91 91
92 92 abovemin = (lfsize and
93 93 os.lstat(wfile).st_size >= lfsize * 1024 * 1024)
94 94 if large or abovemin or (lfmatcher and lfmatcher(f)):
95 95 lfnames.append(f)
96 96 if ui.verbose or not exact:
97 97 ui.status(_('adding %s as a largefile\n') % m.rel(f))
98 98
99 99 bad = []
100 100 standins = []
101 101
102 102 # Need to lock, otherwise there could be a race condition between
103 103 # when standins are created and added to the repo.
104 104 wlock = repo.wlock()
105 105 try:
106 106 if not opts.get('dry_run'):
107 107 lfdirstate = lfutil.openlfdirstate(ui, repo)
108 108 for f in lfnames:
109 109 standinname = lfutil.standin(f)
110 110 lfutil.writestandin(repo, standinname, hash='',
111 111 executable=lfutil.getexecutable(repo.wjoin(f)))
112 112 standins.append(standinname)
113 113 if lfdirstate[f] == 'r':
114 114 lfdirstate.normallookup(f)
115 115 else:
116 116 lfdirstate.add(f)
117 117 lfdirstate.write()
118 118 bad += [lfutil.splitstandin(f)
119 119 for f in lfutil.repoadd(repo, standins)
120 120 if f in m.files()]
121 121 finally:
122 122 wlock.release()
123 123 return bad
124 124
125 125 def removelargefiles(ui, repo, *pats, **opts):
126 126 after = opts.get('after')
127 127 if not pats and not after:
128 128 raise util.Abort(_('no files specified'))
129 129 m = scmutil.match(repo[None], pats, opts)
130 130 try:
131 131 repo.lfstatus = True
132 132 s = repo.status(match=m, clean=True)
133 133 finally:
134 134 repo.lfstatus = False
135 135 manifest = repo[None].manifest()
136 136 modified, added, deleted, clean = [[f for f in list
137 137 if lfutil.standin(f) in manifest]
138 138 for list in [s[0], s[1], s[3], s[6]]]
139 139
140 140 def warn(files, reason):
141 141 for f in files:
142 142 ui.warn(_('not removing %s: %s (use forget to undo)\n')
143 143 % (m.rel(f), reason))
144 144 return int(len(files) > 0)
145 145
146 146 result = 0
147 147
148 148 if after:
149 149 remove, forget = deleted, []
150 150 result = warn(modified + added + clean, _('file still exists'))
151 151 else:
152 152 remove, forget = deleted + clean, []
153 153 result = warn(modified, _('file is modified'))
154 154 result = warn(added, _('file has been marked for add')) or result
155 155
156 156 for f in sorted(remove + forget):
157 157 if ui.verbose or not m.exact(f):
158 158 ui.status(_('removing %s\n') % m.rel(f))
159 159
160 160 # Need to lock because standin files are deleted then removed from the
161 161 # repository and we could race inbetween.
162 162 wlock = repo.wlock()
163 163 try:
164 164 lfdirstate = lfutil.openlfdirstate(ui, repo)
165 165 for f in remove:
166 166 if not after:
167 167 # If this is being called by addremove, notify the user that we
168 168 # are removing the file.
169 169 if getattr(repo, "_isaddremove", False):
170 170 ui.status(_('removing %s\n') % f)
171 171 if os.path.exists(repo.wjoin(f)):
172 172 util.unlinkpath(repo.wjoin(f))
173 173 lfdirstate.remove(f)
174 174 lfdirstate.write()
175 175 forget = [lfutil.standin(f) for f in forget]
176 176 remove = [lfutil.standin(f) for f in remove]
177 177 lfutil.repoforget(repo, forget)
178 178 # If this is being called by addremove, let the original addremove
179 179 # function handle this.
180 180 if not getattr(repo, "_isaddremove", False):
181 181 lfutil.reporemove(repo, remove, unlink=True)
182 182 else:
183 183 lfutil.reporemove(repo, remove, unlink=False)
184 184 finally:
185 185 wlock.release()
186 186
187 187 return result
188 188
189 189 # For overriding mercurial.hgweb.webcommands so that largefiles will
190 190 # appear at their right place in the manifests.
191 191 def decodepath(orig, path):
192 192 return lfutil.splitstandin(path) or path
193 193
194 194 # -- Wrappers: modify existing commands --------------------------------
195 195
196 196 # Add works by going through the files that the user wanted to add and
197 197 # checking if they should be added as largefiles. Then it makes a new
198 198 # matcher which matches only the normal files and runs the original
199 199 # version of add.
200 200 def overrideadd(orig, ui, repo, *pats, **opts):
201 201 normal = opts.pop('normal')
202 202 if normal:
203 203 if opts.get('large'):
204 204 raise util.Abort(_('--normal cannot be used with --large'))
205 205 return orig(ui, repo, *pats, **opts)
206 206 bad = addlargefiles(ui, repo, *pats, **opts)
207 207 installnormalfilesmatchfn(repo[None].manifest())
208 208 result = orig(ui, repo, *pats, **opts)
209 209 restorematchfn()
210 210
211 211 return (result == 1 or bad) and 1 or 0
212 212
213 213 def overrideremove(orig, ui, repo, *pats, **opts):
214 214 installnormalfilesmatchfn(repo[None].manifest())
215 215 result = orig(ui, repo, *pats, **opts)
216 216 restorematchfn()
217 217 return removelargefiles(ui, repo, *pats, **opts) or result
218 218
219 219 def overridestatusfn(orig, repo, rev2, **opts):
220 220 try:
221 221 repo._repo.lfstatus = True
222 222 return orig(repo, rev2, **opts)
223 223 finally:
224 224 repo._repo.lfstatus = False
225 225
226 226 def overridestatus(orig, ui, repo, *pats, **opts):
227 227 try:
228 228 repo.lfstatus = True
229 229 return orig(ui, repo, *pats, **opts)
230 230 finally:
231 231 repo.lfstatus = False
232 232
233 233 def overridedirty(orig, repo, ignoreupdate=False):
234 234 try:
235 235 repo._repo.lfstatus = True
236 236 return orig(repo, ignoreupdate)
237 237 finally:
238 238 repo._repo.lfstatus = False
239 239
240 240 def overridelog(orig, ui, repo, *pats, **opts):
241 241 try:
242 242 repo.lfstatus = True
243 243 return orig(ui, repo, *pats, **opts)
244 244 finally:
245 245 repo.lfstatus = False
246 246
247 247 def overrideverify(orig, ui, repo, *pats, **opts):
248 248 large = opts.pop('large', False)
249 249 all = opts.pop('lfa', False)
250 250 contents = opts.pop('lfc', False)
251 251
252 252 result = orig(ui, repo, *pats, **opts)
253 253 if large:
254 254 result = result or lfcommands.verifylfiles(ui, repo, all, contents)
255 255 return result
256 256
257 257 # Override needs to refresh standins so that update's normal merge
258 258 # will go through properly. Then the other update hook (overriding repo.update)
259 259 # will get the new files. Filemerge is also overriden so that the merge
260 260 # will merge standins correctly.
261 261 def overrideupdate(orig, ui, repo, *pats, **opts):
262 262 lfdirstate = lfutil.openlfdirstate(ui, repo)
263 263 s = lfdirstate.status(match_.always(repo.root, repo.getcwd()), [], False,
264 264 False, False)
265 265 (unsure, modified, added, removed, missing, unknown, ignored, clean) = s
266 266
267 267 # Need to lock between the standins getting updated and their
268 268 # largefiles getting updated
269 269 wlock = repo.wlock()
270 270 try:
271 271 if opts['check']:
272 272 mod = len(modified) > 0
273 273 for lfile in unsure:
274 274 standin = lfutil.standin(lfile)
275 275 if repo['.'][standin].data().strip() != \
276 276 lfutil.hashfile(repo.wjoin(lfile)):
277 277 mod = True
278 278 else:
279 279 lfdirstate.normal(lfile)
280 280 lfdirstate.write()
281 281 if mod:
282 282 raise util.Abort(_('uncommitted local changes'))
283 283 # XXX handle removed differently
284 284 if not opts['clean']:
285 285 for lfile in unsure + modified + added:
286 286 lfutil.updatestandin(repo, lfutil.standin(lfile))
287 287 finally:
288 288 wlock.release()
289 289 return orig(ui, repo, *pats, **opts)
290 290
291 291 # Before starting the manifest merge, merge.updates will call
292 292 # _checkunknown to check if there are any files in the merged-in
293 293 # changeset that collide with unknown files in the working copy.
294 294 #
295 295 # The largefiles are seen as unknown, so this prevents us from merging
296 296 # in a file 'foo' if we already have a largefile with the same name.
297 297 #
298 298 # The overridden function filters the unknown files by removing any
299 299 # largefiles. This makes the merge proceed and we can then handle this
300 300 # case further in the overridden manifestmerge function below.
301 301 def overridecheckunknownfile(origfn, repo, wctx, mctx, f):
302 302 if lfutil.standin(f) in wctx:
303 303 return False
304 304 return origfn(repo, wctx, mctx, f)
305 305
306 306 # The manifest merge handles conflicts on the manifest level. We want
307 307 # to handle changes in largefile-ness of files at this level too.
308 308 #
309 309 # The strategy is to run the original manifestmerge and then process
310 310 # the action list it outputs. There are two cases we need to deal with:
311 311 #
312 312 # 1. Normal file in p1, largefile in p2. Here the largefile is
313 313 # detected via its standin file, which will enter the working copy
314 314 # with a "get" action. It is not "merge" since the standin is all
315 315 # Mercurial is concerned with at this level -- the link to the
316 316 # existing normal file is not relevant here.
317 317 #
318 318 # 2. Largefile in p1, normal file in p2. Here we get a "merge" action
319 319 # since the largefile will be present in the working copy and
320 320 # different from the normal file in p2. Mercurial therefore
321 321 # triggers a merge action.
322 322 #
323 323 # In both cases, we prompt the user and emit new actions to either
324 324 # remove the standin (if the normal file was kept) or to remove the
325 325 # normal file and get the standin (if the largefile was kept). The
326 326 # default prompt answer is to use the largefile version since it was
327 327 # presumably changed on purpose.
328 328 #
329 329 # Finally, the merge.applyupdates function will then take care of
330 330 # writing the files into the working copy and lfcommands.updatelfiles
331 331 # will update the largefiles.
332 332 def overridemanifestmerge(origfn, repo, p1, p2, pa, overwrite, partial):
333 333 actions = origfn(repo, p1, p2, pa, overwrite, partial)
334 334 processed = []
335 335
336 336 for action in actions:
337 337 if overwrite:
338 338 processed.append(action)
339 339 continue
340 340 f, m = action[:2]
341 341
342 342 choices = (_('&Largefile'), _('&Normal file'))
343 343 if m == "g" and lfutil.splitstandin(f) in p1 and f in p2:
344 344 # Case 1: normal file in the working copy, largefile in
345 345 # the second parent
346 346 lfile = lfutil.splitstandin(f)
347 347 standin = f
348 348 msg = _('%s has been turned into a largefile\n'
349 349 'use (l)argefile or keep as (n)ormal file?') % lfile
350 350 if repo.ui.promptchoice(msg, choices, 0) == 0:
351 351 processed.append((lfile, "r"))
352 352 processed.append((standin, "g", p2.flags(standin)))
353 353 else:
354 354 processed.append((standin, "r"))
355 355 elif m == "g" and lfutil.standin(f) in p1 and f in p2:
356 356 # Case 2: largefile in the working copy, normal file in
357 357 # the second parent
358 358 standin = lfutil.standin(f)
359 359 lfile = f
360 360 msg = _('%s has been turned into a normal file\n'
361 361 'keep as (l)argefile or use (n)ormal file?') % lfile
362 362 if repo.ui.promptchoice(msg, choices, 0) == 0:
363 363 processed.append((lfile, "r"))
364 364 else:
365 365 processed.append((standin, "r"))
366 366 processed.append((lfile, "g", p2.flags(lfile)))
367 367 else:
368 368 processed.append(action)
369 369
370 370 return processed
371 371
372 372 # Override filemerge to prompt the user about how they wish to merge
373 373 # largefiles. This will handle identical edits, and copy/rename +
374 374 # edit without prompting the user.
375 375 def overridefilemerge(origfn, repo, mynode, orig, fcd, fco, fca):
376 376 # Use better variable names here. Because this is a wrapper we cannot
377 377 # change the variable names in the function declaration.
378 378 fcdest, fcother, fcancestor = fcd, fco, fca
379 379 if not lfutil.isstandin(orig):
380 380 return origfn(repo, mynode, orig, fcdest, fcother, fcancestor)
381 381 else:
382 382 if not fcother.cmp(fcdest): # files identical?
383 383 return None
384 384
385 385 # backwards, use working dir parent as ancestor
386 386 if fcancestor == fcother:
387 387 fcancestor = fcdest.parents()[0]
388 388
389 389 if orig != fcother.path():
390 390 repo.ui.status(_('merging %s and %s to %s\n')
391 391 % (lfutil.splitstandin(orig),
392 392 lfutil.splitstandin(fcother.path()),
393 393 lfutil.splitstandin(fcdest.path())))
394 394 else:
395 395 repo.ui.status(_('merging %s\n')
396 396 % lfutil.splitstandin(fcdest.path()))
397 397
398 398 if fcancestor.path() != fcother.path() and fcother.data() == \
399 399 fcancestor.data():
400 400 return 0
401 401 if fcancestor.path() != fcdest.path() and fcdest.data() == \
402 402 fcancestor.data():
403 403 repo.wwrite(fcdest.path(), fcother.data(), fcother.flags())
404 404 return 0
405 405
406 406 if repo.ui.promptchoice(_('largefile %s has a merge conflict\n'
407 407 'keep (l)ocal or take (o)ther?') %
408 408 lfutil.splitstandin(orig),
409 409 (_('&Local'), _('&Other')), 0) == 0:
410 410 return 0
411 411 else:
412 412 repo.wwrite(fcdest.path(), fcother.data(), fcother.flags())
413 413 return 0
414 414
415 415 # Copy first changes the matchers to match standins instead of
416 416 # largefiles. Then it overrides util.copyfile in that function it
417 417 # checks if the destination largefile already exists. It also keeps a
418 418 # list of copied files so that the largefiles can be copied and the
419 419 # dirstate updated.
420 420 def overridecopy(orig, ui, repo, pats, opts, rename=False):
421 421 # doesn't remove largefile on rename
422 422 if len(pats) < 2:
423 423 # this isn't legal, let the original function deal with it
424 424 return orig(ui, repo, pats, opts, rename)
425 425
426 426 def makestandin(relpath):
427 427 path = scmutil.canonpath(repo.root, repo.getcwd(), relpath)
428 428 return os.path.join(repo.wjoin(lfutil.standin(path)))
429 429
430 430 fullpats = scmutil.expandpats(pats)
431 431 dest = fullpats[-1]
432 432
433 433 if os.path.isdir(dest):
434 434 if not os.path.isdir(makestandin(dest)):
435 435 os.makedirs(makestandin(dest))
436 436 # This could copy both lfiles and normal files in one command,
437 437 # but we don't want to do that. First replace their matcher to
438 438 # only match normal files and run it, then replace it to just
439 439 # match largefiles and run it again.
440 440 nonormalfiles = False
441 441 nolfiles = False
442 442 try:
443 443 try:
444 444 installnormalfilesmatchfn(repo[None].manifest())
445 445 result = orig(ui, repo, pats, opts, rename)
446 446 except util.Abort, e:
447 447 if str(e) != _('no files to copy'):
448 448 raise e
449 449 else:
450 450 nonormalfiles = True
451 451 result = 0
452 452 finally:
453 453 restorematchfn()
454 454
455 455 # The first rename can cause our current working directory to be removed.
456 456 # In that case there is nothing left to copy/rename so just quit.
457 457 try:
458 458 repo.getcwd()
459 459 except OSError:
460 460 return result
461 461
462 462 try:
463 463 try:
464 464 # When we call orig below it creates the standins but we don't add
465 465 # them to the dir state until later so lock during that time.
466 466 wlock = repo.wlock()
467 467
468 468 manifest = repo[None].manifest()
469 469 oldmatch = None # for the closure
470 470 def overridematch(ctx, pats=[], opts={}, globbed=False,
471 471 default='relpath'):
472 472 newpats = []
473 473 # The patterns were previously mangled to add the standin
474 474 # directory; we need to remove that now
475 475 for pat in pats:
476 476 if match_.patkind(pat) is None and lfutil.shortname in pat:
477 477 newpats.append(pat.replace(lfutil.shortname, ''))
478 478 else:
479 479 newpats.append(pat)
480 480 match = oldmatch(ctx, newpats, opts, globbed, default)
481 481 m = copy.copy(match)
482 482 lfile = lambda f: lfutil.standin(f) in manifest
483 483 m._files = [lfutil.standin(f) for f in m._files if lfile(f)]
484 484 m._fmap = set(m._files)
485 485 origmatchfn = m.matchfn
486 486 m.matchfn = lambda f: (lfutil.isstandin(f) and
487 487 (f in manifest) and
488 488 origmatchfn(lfutil.splitstandin(f)) or
489 489 None)
490 490 return m
491 491 oldmatch = installmatchfn(overridematch)
492 492 listpats = []
493 493 for pat in pats:
494 494 if match_.patkind(pat) is not None:
495 495 listpats.append(pat)
496 496 else:
497 497 listpats.append(makestandin(pat))
498 498
499 499 try:
500 500 origcopyfile = util.copyfile
501 501 copiedfiles = []
502 502 def overridecopyfile(src, dest):
503 503 if (lfutil.shortname in src and
504 504 dest.startswith(repo.wjoin(lfutil.shortname))):
505 505 destlfile = dest.replace(lfutil.shortname, '')
506 506 if not opts['force'] and os.path.exists(destlfile):
507 507 raise IOError('',
508 508 _('destination largefile already exists'))
509 509 copiedfiles.append((src, dest))
510 510 origcopyfile(src, dest)
511 511
512 512 util.copyfile = overridecopyfile
513 513 result += orig(ui, repo, listpats, opts, rename)
514 514 finally:
515 515 util.copyfile = origcopyfile
516 516
517 517 lfdirstate = lfutil.openlfdirstate(ui, repo)
518 518 for (src, dest) in copiedfiles:
519 519 if (lfutil.shortname in src and
520 520 dest.startswith(repo.wjoin(lfutil.shortname))):
521 521 srclfile = src.replace(repo.wjoin(lfutil.standin('')), '')
522 522 destlfile = dest.replace(repo.wjoin(lfutil.standin('')), '')
523 523 destlfiledir = os.path.dirname(repo.wjoin(destlfile)) or '.'
524 524 if not os.path.isdir(destlfiledir):
525 525 os.makedirs(destlfiledir)
526 526 if rename:
527 527 os.rename(repo.wjoin(srclfile), repo.wjoin(destlfile))
528 528 lfdirstate.remove(srclfile)
529 529 else:
530 530 util.copyfile(repo.wjoin(srclfile),
531 531 repo.wjoin(destlfile))
532 532
533 533 lfdirstate.add(destlfile)
534 534 lfdirstate.write()
535 535 except util.Abort, e:
536 536 if str(e) != _('no files to copy'):
537 537 raise e
538 538 else:
539 539 nolfiles = True
540 540 finally:
541 541 restorematchfn()
542 542 wlock.release()
543 543
544 544 if nolfiles and nonormalfiles:
545 545 raise util.Abort(_('no files to copy'))
546 546
547 547 return result
548 548
549 549 # When the user calls revert, we have to be careful to not revert any
550 550 # changes to other largefiles accidentally. This means we have to keep
551 551 # track of the largefiles that are being reverted so we only pull down
552 552 # the necessary largefiles.
553 553 #
554 554 # Standins are only updated (to match the hash of largefiles) before
555 555 # commits. Update the standins then run the original revert, changing
556 556 # the matcher to hit standins instead of largefiles. Based on the
557 557 # resulting standins update the largefiles. Then return the standins
558 558 # to their proper state
559 559 def overriderevert(orig, ui, repo, *pats, **opts):
560 560 # Because we put the standins in a bad state (by updating them)
561 561 # and then return them to a correct state we need to lock to
562 562 # prevent others from changing them in their incorrect state.
563 563 wlock = repo.wlock()
564 564 try:
565 565 lfdirstate = lfutil.openlfdirstate(ui, repo)
566 566 (modified, added, removed, missing, unknown, ignored, clean) = \
567 567 lfutil.lfdirstatestatus(lfdirstate, repo, repo['.'].rev())
568 568 for lfile in modified:
569 569 lfutil.updatestandin(repo, lfutil.standin(lfile))
570 570 for lfile in missing:
571 571 if (os.path.exists(repo.wjoin(lfutil.standin(lfile)))):
572 572 os.unlink(repo.wjoin(lfutil.standin(lfile)))
573 573
574 574 try:
575 575 ctx = scmutil.revsingle(repo, opts.get('rev'))
576 576 oldmatch = None # for the closure
577 577 def overridematch(ctx, pats=[], opts={}, globbed=False,
578 578 default='relpath'):
579 579 match = oldmatch(ctx, pats, opts, globbed, default)
580 580 m = copy.copy(match)
581 581 def tostandin(f):
582 582 if lfutil.standin(f) in ctx:
583 583 return lfutil.standin(f)
584 584 elif lfutil.standin(f) in repo[None]:
585 585 return None
586 586 return f
587 587 m._files = [tostandin(f) for f in m._files]
588 588 m._files = [f for f in m._files if f is not None]
589 589 m._fmap = set(m._files)
590 590 origmatchfn = m.matchfn
591 591 def matchfn(f):
592 592 if lfutil.isstandin(f):
593 593 # We need to keep track of what largefiles are being
594 594 # matched so we know which ones to update later --
595 595 # otherwise we accidentally revert changes to other
596 596 # largefiles. This is repo-specific, so duckpunch the
597 597 # repo object to keep the list of largefiles for us
598 598 # later.
599 599 if origmatchfn(lfutil.splitstandin(f)) and \
600 600 (f in repo[None] or f in ctx):
601 601 lfileslist = getattr(repo, '_lfilestoupdate', [])
602 602 lfileslist.append(lfutil.splitstandin(f))
603 603 repo._lfilestoupdate = lfileslist
604 604 return True
605 605 else:
606 606 return False
607 607 return origmatchfn(f)
608 608 m.matchfn = matchfn
609 609 return m
610 610 oldmatch = installmatchfn(overridematch)
611 611 scmutil.match
612 612 matches = overridematch(repo[None], pats, opts)
613 613 orig(ui, repo, *pats, **opts)
614 614 finally:
615 615 restorematchfn()
616 616 lfileslist = getattr(repo, '_lfilestoupdate', [])
617 617 lfcommands.updatelfiles(ui, repo, filelist=lfileslist,
618 618 printmessage=False)
619 619
620 620 # empty out the largefiles list so we start fresh next time
621 621 repo._lfilestoupdate = []
622 622 for lfile in modified:
623 623 if lfile in lfileslist:
624 624 if os.path.exists(repo.wjoin(lfutil.standin(lfile))) and lfile\
625 625 in repo['.']:
626 626 lfutil.writestandin(repo, lfutil.standin(lfile),
627 627 repo['.'][lfile].data().strip(),
628 628 'x' in repo['.'][lfile].flags())
629 629 lfdirstate = lfutil.openlfdirstate(ui, repo)
630 630 for lfile in added:
631 631 standin = lfutil.standin(lfile)
632 632 if standin not in ctx and (standin in matches or opts.get('all')):
633 633 if lfile in lfdirstate:
634 634 lfdirstate.drop(lfile)
635 635 util.unlinkpath(repo.wjoin(standin))
636 636 lfdirstate.write()
637 637 finally:
638 638 wlock.release()
639 639
640 640 def hgupdate(orig, repo, node):
641 641 # Only call updatelfiles the standins that have changed to save time
642 642 oldstandins = lfutil.getstandinsstate(repo)
643 643 result = orig(repo, node)
644 644 newstandins = lfutil.getstandinsstate(repo)
645 645 filelist = lfutil.getlfilestoupdate(oldstandins, newstandins)
646 646 lfcommands.updatelfiles(repo.ui, repo, filelist=filelist, printmessage=True)
647 647 return result
648 648
649 649 def hgclean(orig, repo, node, show_stats=True):
650 650 result = orig(repo, node, show_stats)
651 651 lfcommands.updatelfiles(repo.ui, repo)
652 652 return result
653 653
654 654 def hgmerge(orig, repo, node, force=None, remind=True):
655 655 # Mark the repo as being in the middle of a merge, so that
656 656 # updatelfiles() will know that it needs to trust the standins in
657 657 # the working copy, not in the standins in the current node
658 658 repo._ismerging = True
659 659 try:
660 660 result = orig(repo, node, force, remind)
661 661 lfcommands.updatelfiles(repo.ui, repo)
662 662 finally:
663 663 repo._ismerging = False
664 664 return result
665 665
666 666 # When we rebase a repository with remotely changed largefiles, we need to
667 667 # take some extra care so that the largefiles are correctly updated in the
668 668 # working copy
669 669 def overridepull(orig, ui, repo, source=None, **opts):
670 670 revsprepull = len(repo)
671 671 if opts.get('rebase', False):
672 672 repo._isrebasing = True
673 673 try:
674 674 if opts.get('update'):
675 675 del opts['update']
676 676 ui.debug('--update and --rebase are not compatible, ignoring '
677 677 'the update flag\n')
678 678 del opts['rebase']
679 679 cmdutil.bailifchanged(repo)
680 680 origpostincoming = commands.postincoming
681 681 def _dummy(*args, **kwargs):
682 682 pass
683 683 commands.postincoming = _dummy
684 684 repo.lfpullsource = source
685 685 if not source:
686 686 source = 'default'
687 687 try:
688 688 result = commands.pull(ui, repo, source, **opts)
689 689 finally:
690 690 commands.postincoming = origpostincoming
691 691 revspostpull = len(repo)
692 692 if revspostpull > revsprepull:
693 693 result = result or rebase.rebase(ui, repo)
694 694 finally:
695 695 repo._isrebasing = False
696 696 else:
697 697 repo.lfpullsource = source
698 698 if not source:
699 699 source = 'default'
700 700 oldheads = lfutil.getcurrentheads(repo)
701 701 result = orig(ui, repo, source, **opts)
702 702 # If we do not have the new largefiles for any new heads we pulled, we
703 703 # will run into a problem later if we try to merge or rebase with one of
704 704 # these heads, so cache the largefiles now direclty into the system
705 705 # cache.
706 706 ui.status(_("caching new largefiles\n"))
707 707 numcached = 0
708 708 heads = lfutil.getcurrentheads(repo)
709 709 newheads = set(heads).difference(set(oldheads))
710 710 for head in newheads:
711 711 (cached, missing) = lfcommands.cachelfiles(ui, repo, head)
712 712 numcached += len(cached)
713 713 ui.status(_("%d largefiles cached\n") % numcached)
714 714 if opts.get('all_largefiles'):
715 715 revspostpull = len(repo)
716 716 revs = []
717 717 for rev in xrange(revsprepull + 1, revspostpull):
718 718 revs.append(repo[rev].rev())
719 719 lfcommands.downloadlfiles(ui, repo, revs)
720 720 return result
721 721
722 722 def overrideclone(orig, ui, source, dest=None, **opts):
723 723 d = dest
724 724 if d is None:
725 725 d = hg.defaultdest(source)
726 726 if opts.get('all_largefiles') and not hg.islocal(d):
727 727 raise util.Abort(_(
728 728 '--all-largefiles is incompatible with non-local destination %s' %
729 729 d))
730 result = hg.clone(ui, opts, source, dest,
731 pull=opts.get('pull'),
732 stream=opts.get('uncompressed'),
733 rev=opts.get('rev'),
734 update=opts.get('updaterev') or not opts.get('noupdate'),
735 branch=opts.get('branch'))
736 if result is None:
737 return True
738 if opts.get('all_largefiles'):
730
731 return orig(ui, source, dest, **opts)
732
733 def hgclone(orig, ui, opts, *args, **kwargs):
734 result = orig(ui, opts, *args, **kwargs)
735
736 if result is not None and opts.get('all_largefiles'):
739 737 sourcerepo, destrepo = result
740 738 repo = destrepo.local()
741 739
742 740 # The .hglf directory must exist for the standin matcher to match
743 741 # anything (which listlfiles uses for each rev), and .hg/largefiles is
744 742 # assumed to exist by the code that caches the downloaded file. These
745 743 # directories exist if clone updated to any rev.
746 744 if opts.get('noupdate'):
747 745 util.makedirs(repo.pathto(lfutil.shortname))
748 746 util.makedirs(repo.join(lfutil.longname))
749 747
750 748 # Caching is implicitly limited to 'rev' option, since the dest repo was
751 749 # truncated at that point.
752 750 success, missing = lfcommands.downloadlfiles(ui, repo, None)
753 return missing != 0
754 return result is None
751
752 if missing != 0:
753 return None
754
755 return result
755 756
756 757 def overriderebase(orig, ui, repo, **opts):
757 758 repo._isrebasing = True
758 759 try:
759 760 return orig(ui, repo, **opts)
760 761 finally:
761 762 repo._isrebasing = False
762 763
763 764 def overridearchive(orig, repo, dest, node, kind, decode=True, matchfn=None,
764 765 prefix=None, mtime=None, subrepos=None):
765 766 # No need to lock because we are only reading history and
766 767 # largefile caches, neither of which are modified.
767 768 lfcommands.cachelfiles(repo.ui, repo, node)
768 769
769 770 if kind not in archival.archivers:
770 771 raise util.Abort(_("unknown archive type '%s'") % kind)
771 772
772 773 ctx = repo[node]
773 774
774 775 if kind == 'files':
775 776 if prefix:
776 777 raise util.Abort(
777 778 _('cannot give prefix when archiving to files'))
778 779 else:
779 780 prefix = archival.tidyprefix(dest, kind, prefix)
780 781
781 782 def write(name, mode, islink, getdata):
782 783 if matchfn and not matchfn(name):
783 784 return
784 785 data = getdata()
785 786 if decode:
786 787 data = repo.wwritedata(name, data)
787 788 archiver.addfile(prefix + name, mode, islink, data)
788 789
789 790 archiver = archival.archivers[kind](dest, mtime or ctx.date()[0])
790 791
791 792 if repo.ui.configbool("ui", "archivemeta", True):
792 793 def metadata():
793 794 base = 'repo: %s\nnode: %s\nbranch: %s\n' % (
794 795 hex(repo.changelog.node(0)), hex(node), ctx.branch())
795 796
796 797 tags = ''.join('tag: %s\n' % t for t in ctx.tags()
797 798 if repo.tagtype(t) == 'global')
798 799 if not tags:
799 800 repo.ui.pushbuffer()
800 801 opts = {'template': '{latesttag}\n{latesttagdistance}',
801 802 'style': '', 'patch': None, 'git': None}
802 803 cmdutil.show_changeset(repo.ui, repo, opts).show(ctx)
803 804 ltags, dist = repo.ui.popbuffer().split('\n')
804 805 tags = ''.join('latesttag: %s\n' % t for t in ltags.split(':'))
805 806 tags += 'latesttagdistance: %s\n' % dist
806 807
807 808 return base + tags
808 809
809 810 write('.hg_archival.txt', 0644, False, metadata)
810 811
811 812 for f in ctx:
812 813 ff = ctx.flags(f)
813 814 getdata = ctx[f].data
814 815 if lfutil.isstandin(f):
815 816 path = lfutil.findfile(repo, getdata().strip())
816 817 if path is None:
817 818 raise util.Abort(
818 819 _('largefile %s not found in repo store or system cache')
819 820 % lfutil.splitstandin(f))
820 821 f = lfutil.splitstandin(f)
821 822
822 823 def getdatafn():
823 824 fd = None
824 825 try:
825 826 fd = open(path, 'rb')
826 827 return fd.read()
827 828 finally:
828 829 if fd:
829 830 fd.close()
830 831
831 832 getdata = getdatafn
832 833 write(f, 'x' in ff and 0755 or 0644, 'l' in ff, getdata)
833 834
834 835 if subrepos:
835 836 for subpath in ctx.substate:
836 837 sub = ctx.sub(subpath)
837 838 submatch = match_.narrowmatcher(subpath, matchfn)
838 839 sub.archive(repo.ui, archiver, prefix, submatch)
839 840
840 841 archiver.done()
841 842
842 843 def hgsubrepoarchive(orig, repo, ui, archiver, prefix, match=None):
843 844 rev = repo._state[1]
844 845 ctx = repo._repo[rev]
845 846
846 847 lfcommands.cachelfiles(ui, repo._repo, ctx.node())
847 848
848 849 def write(name, mode, islink, getdata):
849 850 # At this point, the standin has been replaced with the largefile name,
850 851 # so the normal matcher works here without the lfutil variants.
851 852 if match and not match(f):
852 853 return
853 854 data = getdata()
854 855
855 856 archiver.addfile(prefix + repo._path + '/' + name, mode, islink, data)
856 857
857 858 for f in ctx:
858 859 ff = ctx.flags(f)
859 860 getdata = ctx[f].data
860 861 if lfutil.isstandin(f):
861 862 path = lfutil.findfile(repo._repo, getdata().strip())
862 863 if path is None:
863 864 raise util.Abort(
864 865 _('largefile %s not found in repo store or system cache')
865 866 % lfutil.splitstandin(f))
866 867 f = lfutil.splitstandin(f)
867 868
868 869 def getdatafn():
869 870 fd = None
870 871 try:
871 872 fd = open(os.path.join(prefix, path), 'rb')
872 873 return fd.read()
873 874 finally:
874 875 if fd:
875 876 fd.close()
876 877
877 878 getdata = getdatafn
878 879
879 880 write(f, 'x' in ff and 0755 or 0644, 'l' in ff, getdata)
880 881
881 882 for subpath in ctx.substate:
882 883 sub = ctx.sub(subpath)
883 884 submatch = match_.narrowmatcher(subpath, match)
884 885 sub.archive(ui, archiver, os.path.join(prefix, repo._path) + '/',
885 886 submatch)
886 887
887 888 # If a largefile is modified, the change is not reflected in its
888 889 # standin until a commit. cmdutil.bailifchanged() raises an exception
889 890 # if the repo has uncommitted changes. Wrap it to also check if
890 891 # largefiles were changed. This is used by bisect and backout.
891 892 def overridebailifchanged(orig, repo):
892 893 orig(repo)
893 894 repo.lfstatus = True
894 895 modified, added, removed, deleted = repo.status()[:4]
895 896 repo.lfstatus = False
896 897 if modified or added or removed or deleted:
897 898 raise util.Abort(_('outstanding uncommitted changes'))
898 899
899 900 # Fetch doesn't use cmdutil.bailifchanged so override it to add the check
900 901 def overridefetch(orig, ui, repo, *pats, **opts):
901 902 repo.lfstatus = True
902 903 modified, added, removed, deleted = repo.status()[:4]
903 904 repo.lfstatus = False
904 905 if modified or added or removed or deleted:
905 906 raise util.Abort(_('outstanding uncommitted changes'))
906 907 return orig(ui, repo, *pats, **opts)
907 908
908 909 def overrideforget(orig, ui, repo, *pats, **opts):
909 910 installnormalfilesmatchfn(repo[None].manifest())
910 911 result = orig(ui, repo, *pats, **opts)
911 912 restorematchfn()
912 913 m = scmutil.match(repo[None], pats, opts)
913 914
914 915 try:
915 916 repo.lfstatus = True
916 917 s = repo.status(match=m, clean=True)
917 918 finally:
918 919 repo.lfstatus = False
919 920 forget = sorted(s[0] + s[1] + s[3] + s[6])
920 921 forget = [f for f in forget if lfutil.standin(f) in repo[None].manifest()]
921 922
922 923 for f in forget:
923 924 if lfutil.standin(f) not in repo.dirstate and not \
924 925 os.path.isdir(m.rel(lfutil.standin(f))):
925 926 ui.warn(_('not removing %s: file is already untracked\n')
926 927 % m.rel(f))
927 928 result = 1
928 929
929 930 for f in forget:
930 931 if ui.verbose or not m.exact(f):
931 932 ui.status(_('removing %s\n') % m.rel(f))
932 933
933 934 # Need to lock because standin files are deleted then removed from the
934 935 # repository and we could race inbetween.
935 936 wlock = repo.wlock()
936 937 try:
937 938 lfdirstate = lfutil.openlfdirstate(ui, repo)
938 939 for f in forget:
939 940 if lfdirstate[f] == 'a':
940 941 lfdirstate.drop(f)
941 942 else:
942 943 lfdirstate.remove(f)
943 944 lfdirstate.write()
944 945 lfutil.reporemove(repo, [lfutil.standin(f) for f in forget],
945 946 unlink=True)
946 947 finally:
947 948 wlock.release()
948 949
949 950 return result
950 951
951 952 def getoutgoinglfiles(ui, repo, dest=None, **opts):
952 953 dest = ui.expandpath(dest or 'default-push', dest or 'default')
953 954 dest, branches = hg.parseurl(dest, opts.get('branch'))
954 955 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
955 956 if revs:
956 957 revs = [repo.lookup(rev) for rev in scmutil.revrange(repo, revs)]
957 958
958 959 try:
959 960 remote = hg.peer(repo, opts, dest)
960 961 except error.RepoError:
961 962 return None
962 963 o = lfutil.findoutgoing(repo, remote, False)
963 964 if not o:
964 965 return None
965 966 o = repo.changelog.nodesbetween(o, revs)[0]
966 967 if opts.get('newest_first'):
967 968 o.reverse()
968 969
969 970 toupload = set()
970 971 for n in o:
971 972 parents = [p for p in repo.changelog.parents(n) if p != node.nullid]
972 973 ctx = repo[n]
973 974 files = set(ctx.files())
974 975 if len(parents) == 2:
975 976 mc = ctx.manifest()
976 977 mp1 = ctx.parents()[0].manifest()
977 978 mp2 = ctx.parents()[1].manifest()
978 979 for f in mp1:
979 980 if f not in mc:
980 981 files.add(f)
981 982 for f in mp2:
982 983 if f not in mc:
983 984 files.add(f)
984 985 for f in mc:
985 986 if mc[f] != mp1.get(f, None) or mc[f] != mp2.get(f, None):
986 987 files.add(f)
987 988 toupload = toupload.union(
988 989 set([f for f in files if lfutil.isstandin(f) and f in ctx]))
989 990 return toupload
990 991
991 992 def overrideoutgoing(orig, ui, repo, dest=None, **opts):
992 993 result = orig(ui, repo, dest, **opts)
993 994
994 995 if opts.pop('large', None):
995 996 toupload = getoutgoinglfiles(ui, repo, dest, **opts)
996 997 if toupload is None:
997 998 ui.status(_('largefiles: No remote repo\n'))
998 999 else:
999 1000 ui.status(_('largefiles to upload:\n'))
1000 1001 for file in toupload:
1001 1002 ui.status(lfutil.splitstandin(file) + '\n')
1002 1003 ui.status('\n')
1003 1004
1004 1005 return result
1005 1006
1006 1007 def overridesummary(orig, ui, repo, *pats, **opts):
1007 1008 try:
1008 1009 repo.lfstatus = True
1009 1010 orig(ui, repo, *pats, **opts)
1010 1011 finally:
1011 1012 repo.lfstatus = False
1012 1013
1013 1014 if opts.pop('large', None):
1014 1015 toupload = getoutgoinglfiles(ui, repo, None, **opts)
1015 1016 if toupload is None:
1016 1017 ui.status(_('largefiles: No remote repo\n'))
1017 1018 else:
1018 1019 ui.status(_('largefiles: %d to upload\n') % len(toupload))
1019 1020
1020 1021 def overrideaddremove(orig, ui, repo, *pats, **opts):
1021 1022 if not lfutil.islfilesrepo(repo):
1022 1023 return orig(ui, repo, *pats, **opts)
1023 1024 # Get the list of missing largefiles so we can remove them
1024 1025 lfdirstate = lfutil.openlfdirstate(ui, repo)
1025 1026 s = lfdirstate.status(match_.always(repo.root, repo.getcwd()), [], False,
1026 1027 False, False)
1027 1028 (unsure, modified, added, removed, missing, unknown, ignored, clean) = s
1028 1029
1029 1030 # Call into the normal remove code, but the removing of the standin, we want
1030 1031 # to have handled by original addremove. Monkey patching here makes sure
1031 1032 # we don't remove the standin in the largefiles code, preventing a very
1032 1033 # confused state later.
1033 1034 if missing:
1034 1035 m = [repo.wjoin(f) for f in missing]
1035 1036 repo._isaddremove = True
1036 1037 removelargefiles(ui, repo, *m, **opts)
1037 1038 repo._isaddremove = False
1038 1039 # Call into the normal add code, and any files that *should* be added as
1039 1040 # largefiles will be
1040 1041 addlargefiles(ui, repo, *pats, **opts)
1041 1042 # Now that we've handled largefiles, hand off to the original addremove
1042 1043 # function to take care of the rest. Make sure it doesn't do anything with
1043 1044 # largefiles by installing a matcher that will ignore them.
1044 1045 installnormalfilesmatchfn(repo[None].manifest())
1045 1046 result = orig(ui, repo, *pats, **opts)
1046 1047 restorematchfn()
1047 1048 return result
1048 1049
1049 1050 # Calling purge with --all will cause the largefiles to be deleted.
1050 1051 # Override repo.status to prevent this from happening.
1051 1052 def overridepurge(orig, ui, repo, *dirs, **opts):
1052 1053 oldstatus = repo.status
1053 1054 def overridestatus(node1='.', node2=None, match=None, ignored=False,
1054 1055 clean=False, unknown=False, listsubrepos=False):
1055 1056 r = oldstatus(node1, node2, match, ignored, clean, unknown,
1056 1057 listsubrepos)
1057 1058 lfdirstate = lfutil.openlfdirstate(ui, repo)
1058 1059 modified, added, removed, deleted, unknown, ignored, clean = r
1059 1060 unknown = [f for f in unknown if lfdirstate[f] == '?']
1060 1061 ignored = [f for f in ignored if lfdirstate[f] == '?']
1061 1062 return modified, added, removed, deleted, unknown, ignored, clean
1062 1063 repo.status = overridestatus
1063 1064 orig(ui, repo, *dirs, **opts)
1064 1065 repo.status = oldstatus
1065 1066
1066 1067 def overriderollback(orig, ui, repo, **opts):
1067 1068 result = orig(ui, repo, **opts)
1068 1069 merge.update(repo, node=None, branchmerge=False, force=True,
1069 1070 partial=lfutil.isstandin)
1070 1071 wlock = repo.wlock()
1071 1072 try:
1072 1073 lfdirstate = lfutil.openlfdirstate(ui, repo)
1073 1074 lfiles = lfutil.listlfiles(repo)
1074 1075 oldlfiles = lfutil.listlfiles(repo, repo[None].parents()[0].rev())
1075 1076 for file in lfiles:
1076 1077 if file in oldlfiles:
1077 1078 lfdirstate.normallookup(file)
1078 1079 else:
1079 1080 lfdirstate.add(file)
1080 1081 lfdirstate.write()
1081 1082 finally:
1082 1083 wlock.release()
1083 1084 return result
1084 1085
1085 1086 def overridetransplant(orig, ui, repo, *revs, **opts):
1086 1087 try:
1087 1088 oldstandins = lfutil.getstandinsstate(repo)
1088 1089 repo._istransplanting = True
1089 1090 result = orig(ui, repo, *revs, **opts)
1090 1091 newstandins = lfutil.getstandinsstate(repo)
1091 1092 filelist = lfutil.getlfilestoupdate(oldstandins, newstandins)
1092 1093 lfcommands.updatelfiles(repo.ui, repo, filelist=filelist,
1093 1094 printmessage=True)
1094 1095 finally:
1095 1096 repo._istransplanting = False
1096 1097 return result
1097 1098
1098 1099 def overridecat(orig, ui, repo, file1, *pats, **opts):
1099 1100 ctx = scmutil.revsingle(repo, opts.get('rev'))
1100 1101 if not lfutil.standin(file1) in ctx:
1101 1102 result = orig(ui, repo, file1, *pats, **opts)
1102 1103 return result
1103 1104 return lfcommands.catlfile(repo, file1, ctx.rev(), opts.get('output'))
@@ -1,167 +1,168 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 '''setup for largefiles extension: uisetup'''
10 10
11 11 from mercurial import archival, cmdutil, commands, extensions, filemerge, hg, \
12 12 httppeer, localrepo, merge, sshpeer, sshserver, wireproto
13 13 from mercurial.i18n import _
14 14 from mercurial.hgweb import hgweb_mod, protocol, webcommands
15 15 from mercurial.subrepo import hgsubrepo
16 16
17 17 import overrides
18 18 import proto
19 19
20 20 def uisetup(ui):
21 21 # Disable auto-status for some commands which assume that all
22 22 # files in the result are under Mercurial's control
23 23
24 24 entry = extensions.wrapcommand(commands.table, 'add',
25 25 overrides.overrideadd)
26 26 addopt = [('', 'large', None, _('add as largefile')),
27 27 ('', 'normal', None, _('add as normal file')),
28 28 ('', 'lfsize', '', _('add all files above this size '
29 29 '(in megabytes) as largefiles '
30 30 '(default: 10)'))]
31 31 entry[1].extend(addopt)
32 32
33 33 entry = extensions.wrapcommand(commands.table, 'addremove',
34 34 overrides.overrideaddremove)
35 35 entry = extensions.wrapcommand(commands.table, 'remove',
36 36 overrides.overrideremove)
37 37 entry = extensions.wrapcommand(commands.table, 'forget',
38 38 overrides.overrideforget)
39 39
40 40 # Subrepos call status function
41 41 entry = extensions.wrapcommand(commands.table, 'status',
42 42 overrides.overridestatus)
43 43 entry = extensions.wrapfunction(hgsubrepo, 'status',
44 44 overrides.overridestatusfn)
45 45
46 46 entry = extensions.wrapcommand(commands.table, 'log',
47 47 overrides.overridelog)
48 48 entry = extensions.wrapcommand(commands.table, 'rollback',
49 49 overrides.overriderollback)
50 50 entry = extensions.wrapcommand(commands.table, 'verify',
51 51 overrides.overrideverify)
52 52
53 53 verifyopt = [('', 'large', None, _('verify largefiles')),
54 54 ('', 'lfa', None,
55 55 _('verify all revisions of largefiles not just current')),
56 56 ('', 'lfc', None,
57 57 _('verify largefile contents not just existence'))]
58 58 entry[1].extend(verifyopt)
59 59
60 60 entry = extensions.wrapcommand(commands.table, 'outgoing',
61 61 overrides.overrideoutgoing)
62 62 outgoingopt = [('', 'large', None, _('display outgoing largefiles'))]
63 63 entry[1].extend(outgoingopt)
64 64 entry = extensions.wrapcommand(commands.table, 'summary',
65 65 overrides.overridesummary)
66 66 summaryopt = [('', 'large', None, _('display outgoing largefiles'))]
67 67 entry[1].extend(summaryopt)
68 68
69 69 entry = extensions.wrapcommand(commands.table, 'update',
70 70 overrides.overrideupdate)
71 71 entry = extensions.wrapcommand(commands.table, 'pull',
72 72 overrides.overridepull)
73 73 pullopt = [('', 'all-largefiles', None,
74 74 _('download all pulled versions of largefiles'))]
75 75 entry[1].extend(pullopt)
76 76 entry = extensions.wrapcommand(commands.table, 'clone',
77 77 overrides.overrideclone)
78 78 cloneopt = [('', 'all-largefiles', None,
79 79 _('download all versions of all largefiles'))]
80 entry[1].extend(cloneopt)
81 entry = extensions.wrapfunction(hg, 'clone', overrides.hgclone)
80 82
81 entry[1].extend(cloneopt)
82 83 entry = extensions.wrapcommand(commands.table, 'cat',
83 84 overrides.overridecat)
84 85 entry = extensions.wrapfunction(merge, '_checkunknownfile',
85 86 overrides.overridecheckunknownfile)
86 87 entry = extensions.wrapfunction(merge, 'manifestmerge',
87 88 overrides.overridemanifestmerge)
88 89 entry = extensions.wrapfunction(filemerge, 'filemerge',
89 90 overrides.overridefilemerge)
90 91 entry = extensions.wrapfunction(cmdutil, 'copy',
91 92 overrides.overridecopy)
92 93
93 94 # Summary calls dirty on the subrepos
94 95 entry = extensions.wrapfunction(hgsubrepo, 'dirty',
95 96 overrides.overridedirty)
96 97
97 98 # Backout calls revert so we need to override both the command and the
98 99 # function
99 100 entry = extensions.wrapcommand(commands.table, 'revert',
100 101 overrides.overriderevert)
101 102 entry = extensions.wrapfunction(commands, 'revert',
102 103 overrides.overriderevert)
103 104
104 105 # clone uses hg._update instead of hg.update even though they are the
105 106 # same function... so wrap both of them)
106 107 extensions.wrapfunction(hg, 'update', overrides.hgupdate)
107 108 extensions.wrapfunction(hg, '_update', overrides.hgupdate)
108 109 extensions.wrapfunction(hg, 'clean', overrides.hgclean)
109 110 extensions.wrapfunction(hg, 'merge', overrides.hgmerge)
110 111
111 112 extensions.wrapfunction(archival, 'archive', overrides.overridearchive)
112 113 extensions.wrapfunction(hgsubrepo, 'archive', overrides.hgsubrepoarchive)
113 114 extensions.wrapfunction(cmdutil, 'bailifchanged',
114 115 overrides.overridebailifchanged)
115 116
116 117 # create the new wireproto commands ...
117 118 wireproto.commands['putlfile'] = (proto.putlfile, 'sha')
118 119 wireproto.commands['getlfile'] = (proto.getlfile, 'sha')
119 120 wireproto.commands['statlfile'] = (proto.statlfile, 'sha')
120 121
121 122 # ... and wrap some existing ones
122 123 wireproto.commands['capabilities'] = (proto.capabilities, '')
123 124 wireproto.commands['heads'] = (proto.heads, '')
124 125 wireproto.commands['lheads'] = (wireproto.heads, '')
125 126
126 127 # make putlfile behave the same as push and {get,stat}lfile behave
127 128 # the same as pull w.r.t. permissions checks
128 129 hgweb_mod.perms['putlfile'] = 'push'
129 130 hgweb_mod.perms['getlfile'] = 'pull'
130 131 hgweb_mod.perms['statlfile'] = 'pull'
131 132
132 133 extensions.wrapfunction(webcommands, 'decodepath', overrides.decodepath)
133 134
134 135 # the hello wireproto command uses wireproto.capabilities, so it won't see
135 136 # our largefiles capability unless we replace the actual function as well.
136 137 proto.capabilitiesorig = wireproto.capabilities
137 138 wireproto.capabilities = proto.capabilities
138 139
139 140 # these let us reject non-largefiles clients and make them display
140 141 # our error messages
141 142 protocol.webproto.refuseclient = proto.webprotorefuseclient
142 143 sshserver.sshserver.refuseclient = proto.sshprotorefuseclient
143 144
144 145 # can't do this in reposetup because it needs to have happened before
145 146 # wirerepo.__init__ is called
146 147 proto.ssholdcallstream = sshpeer.sshpeer._callstream
147 148 proto.httpoldcallstream = httppeer.httppeer._callstream
148 149 sshpeer.sshpeer._callstream = proto.sshrepocallstream
149 150 httppeer.httppeer._callstream = proto.httprepocallstream
150 151
151 152 # don't die on seeing a repo with the largefiles requirement
152 153 localrepo.localrepository.supported |= set(['largefiles'])
153 154
154 155 # override some extensions' stuff as well
155 156 for name, module in extensions.extensions():
156 157 if name == 'fetch':
157 158 extensions.wrapcommand(getattr(module, 'cmdtable'), 'fetch',
158 159 overrides.overridefetch)
159 160 if name == 'purge':
160 161 extensions.wrapcommand(getattr(module, 'cmdtable'), 'purge',
161 162 overrides.overridepurge)
162 163 if name == 'rebase':
163 164 extensions.wrapcommand(getattr(module, 'cmdtable'), 'rebase',
164 165 overrides.overriderebase)
165 166 if name == 'transplant':
166 167 extensions.wrapcommand(getattr(module, 'cmdtable'), 'transplant',
167 168 overrides.overridetransplant)
@@ -1,1541 +1,1547 b''
1 1 $ USERCACHE="$TESTTMP/cache"; export USERCACHE
2 2 $ mkdir "${USERCACHE}"
3 3 $ cat >> $HGRCPATH <<EOF
4 4 > [extensions]
5 5 > largefiles=
6 6 > purge=
7 7 > rebase=
8 8 > transplant=
9 9 > [phases]
10 10 > publish=False
11 11 > [largefiles]
12 12 > minsize=2
13 13 > patterns=glob:**.dat
14 14 > usercache=${USERCACHE}
15 15 > [hooks]
16 16 > precommit=sh -c "echo \\"Invoking status precommit hook\\"; hg status"
17 17 > EOF
18 18
19 19 Create the repo with a couple of revisions of both large and normal
20 20 files, testing that status correctly shows largefiles and that summary output
21 21 is correct.
22 22
23 23 $ hg init a
24 24 $ cd a
25 25 $ mkdir sub
26 26 $ echo normal1 > normal1
27 27 $ echo normal2 > sub/normal2
28 28 $ echo large1 > large1
29 29 $ echo large2 > sub/large2
30 30 $ hg add normal1 sub/normal2
31 31 $ hg add --large large1 sub/large2
32 32 $ hg commit -m "add files"
33 33 Invoking status precommit hook
34 34 A large1
35 35 A normal1
36 36 A sub/large2
37 37 A sub/normal2
38 38 $ echo normal11 > normal1
39 39 $ echo normal22 > sub/normal2
40 40 $ echo large11 > large1
41 41 $ echo large22 > sub/large2
42 42 $ hg commit -m "edit files"
43 43 Invoking status precommit hook
44 44 M large1
45 45 M normal1
46 46 M sub/large2
47 47 M sub/normal2
48 48 $ hg sum --large
49 49 parent: 1:ce8896473775 tip
50 50 edit files
51 51 branch: default
52 52 commit: (clean)
53 53 update: (current)
54 54 largefiles: No remote repo
55 55
56 56 Commit preserved largefile contents.
57 57
58 58 $ cat normal1
59 59 normal11
60 60 $ cat large1
61 61 large11
62 62 $ cat sub/normal2
63 63 normal22
64 64 $ cat sub/large2
65 65 large22
66 66
67 67 Test status, subdir and unknown files
68 68
69 69 $ echo unknown > sub/unknown
70 70 $ hg st --all
71 71 ? sub/unknown
72 72 C large1
73 73 C normal1
74 74 C sub/large2
75 75 C sub/normal2
76 76 $ hg st --all sub
77 77 ? sub/unknown
78 78 C sub/large2
79 79 C sub/normal2
80 80 $ rm sub/unknown
81 81
82 82 Test exit codes for remove warning cases (modified and still exiting)
83 83
84 84 $ hg remove -A large1
85 85 not removing large1: file still exists (use forget to undo)
86 86 [1]
87 87 $ echo 'modified' > large1
88 88 $ hg remove large1
89 89 not removing large1: file is modified (use forget to undo)
90 90 [1]
91 91 $ hg up -Cq
92 92
93 93 Remove both largefiles and normal files.
94 94
95 95 $ hg remove normal1 large1
96 96 $ hg status large1
97 97 R large1
98 98 $ hg commit -m "remove files"
99 99 Invoking status precommit hook
100 100 R large1
101 101 R normal1
102 102 $ ls
103 103 sub
104 104 $ echo "testlargefile" > large1-test
105 105 $ hg add --large large1-test
106 106 $ hg st
107 107 A large1-test
108 108 $ hg rm large1-test
109 109 not removing large1-test: file has been marked for add (use forget to undo)
110 110 [1]
111 111 $ hg st
112 112 A large1-test
113 113 $ hg forget large1-test
114 114 $ hg st
115 115 ? large1-test
116 116 $ hg remove large1-test
117 117 not removing large1-test: file is untracked
118 118 [1]
119 119 $ hg forget large1-test
120 120 not removing large1-test: file is already untracked
121 121 [1]
122 122 $ rm large1-test
123 123
124 124 Copy both largefiles and normal files (testing that status output is correct).
125 125
126 126 $ hg cp sub/normal2 normal1
127 127 $ hg cp sub/large2 large1
128 128 $ hg commit -m "copy files"
129 129 Invoking status precommit hook
130 130 A large1
131 131 A normal1
132 132 $ cat normal1
133 133 normal22
134 134 $ cat large1
135 135 large22
136 136
137 137 Test moving largefiles and verify that normal files are also unaffected.
138 138
139 139 $ hg mv normal1 normal3
140 140 $ hg mv large1 large3
141 141 $ hg mv sub/normal2 sub/normal4
142 142 $ hg mv sub/large2 sub/large4
143 143 $ hg commit -m "move files"
144 144 Invoking status precommit hook
145 145 A large3
146 146 A normal3
147 147 A sub/large4
148 148 A sub/normal4
149 149 R large1
150 150 R normal1
151 151 R sub/large2
152 152 R sub/normal2
153 153 $ cat normal3
154 154 normal22
155 155 $ cat large3
156 156 large22
157 157 $ cat sub/normal4
158 158 normal22
159 159 $ cat sub/large4
160 160 large22
161 161
162 162 Test copies and moves from a directory other than root (issue3516)
163 163
164 164 $ cd ..
165 165 $ hg init lf_cpmv
166 166 $ cd lf_cpmv
167 167 $ mkdir dira
168 168 $ mkdir dira/dirb
169 169 $ touch dira/dirb/largefile
170 170 $ hg add --large dira/dirb/largefile
171 171 $ hg commit -m "added"
172 172 Invoking status precommit hook
173 173 A dira/dirb/largefile
174 174 $ cd dira
175 175 $ hg cp dirb/largefile foo/largefile
176 176 $ hg ci -m "deep copy"
177 177 Invoking status precommit hook
178 178 A dira/foo/largefile
179 179 $ find . | sort
180 180 .
181 181 ./dirb
182 182 ./dirb/largefile
183 183 ./foo
184 184 ./foo/largefile
185 185 $ hg mv foo/largefile baz/largefile
186 186 $ hg ci -m "moved"
187 187 Invoking status precommit hook
188 188 A dira/baz/largefile
189 189 R dira/foo/largefile
190 190 $ find . | sort
191 191 .
192 192 ./baz
193 193 ./baz/largefile
194 194 ./dirb
195 195 ./dirb/largefile
196 196 ./foo
197 197 $ cd ../../a
198 198
199 199 #if hgweb
200 200 Test display of largefiles in hgweb
201 201
202 202 $ hg serve -d -p $HGPORT --pid-file ../hg.pid
203 203 $ cat ../hg.pid >> $DAEMON_PIDS
204 204 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT 'file/tip/?style=raw'
205 205 200 Script output follows
206 206
207 207
208 208 drwxr-xr-x sub
209 209 -rw-r--r-- 41 large3
210 210 -rw-r--r-- 9 normal3
211 211
212 212
213 213 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT 'file/tip/sub/?style=raw'
214 214 200 Script output follows
215 215
216 216
217 217 -rw-r--r-- 41 large4
218 218 -rw-r--r-- 9 normal4
219 219
220 220
221 221 $ "$TESTDIR/killdaemons.py"
222 222 #endif
223 223
224 224 Test archiving the various revisions. These hit corner cases known with
225 225 archiving.
226 226
227 227 $ hg archive -r 0 ../archive0
228 228 $ hg archive -r 1 ../archive1
229 229 $ hg archive -r 2 ../archive2
230 230 $ hg archive -r 3 ../archive3
231 231 $ hg archive -r 4 ../archive4
232 232 $ cd ../archive0
233 233 $ cat normal1
234 234 normal1
235 235 $ cat large1
236 236 large1
237 237 $ cat sub/normal2
238 238 normal2
239 239 $ cat sub/large2
240 240 large2
241 241 $ cd ../archive1
242 242 $ cat normal1
243 243 normal11
244 244 $ cat large1
245 245 large11
246 246 $ cat sub/normal2
247 247 normal22
248 248 $ cat sub/large2
249 249 large22
250 250 $ cd ../archive2
251 251 $ ls
252 252 sub
253 253 $ cat sub/normal2
254 254 normal22
255 255 $ cat sub/large2
256 256 large22
257 257 $ cd ../archive3
258 258 $ cat normal1
259 259 normal22
260 260 $ cat large1
261 261 large22
262 262 $ cat sub/normal2
263 263 normal22
264 264 $ cat sub/large2
265 265 large22
266 266 $ cd ../archive4
267 267 $ cat normal3
268 268 normal22
269 269 $ cat large3
270 270 large22
271 271 $ cat sub/normal4
272 272 normal22
273 273 $ cat sub/large4
274 274 large22
275 275
276 276 Commit corner case: specify files to commit.
277 277
278 278 $ cd ../a
279 279 $ echo normal3 > normal3
280 280 $ echo large3 > large3
281 281 $ echo normal4 > sub/normal4
282 282 $ echo large4 > sub/large4
283 283 $ hg commit normal3 large3 sub/normal4 sub/large4 -m "edit files again"
284 284 Invoking status precommit hook
285 285 M large3
286 286 M normal3
287 287 M sub/large4
288 288 M sub/normal4
289 289 $ cat normal3
290 290 normal3
291 291 $ cat large3
292 292 large3
293 293 $ cat sub/normal4
294 294 normal4
295 295 $ cat sub/large4
296 296 large4
297 297
298 298 One more commit corner case: commit from a subdirectory.
299 299
300 300 $ cd ../a
301 301 $ echo normal33 > normal3
302 302 $ echo large33 > large3
303 303 $ echo normal44 > sub/normal4
304 304 $ echo large44 > sub/large4
305 305 $ cd sub
306 306 $ hg commit -m "edit files yet again"
307 307 Invoking status precommit hook
308 308 M large3
309 309 M normal3
310 310 M sub/large4
311 311 M sub/normal4
312 312 $ cat ../normal3
313 313 normal33
314 314 $ cat ../large3
315 315 large33
316 316 $ cat normal4
317 317 normal44
318 318 $ cat large4
319 319 large44
320 320
321 321 Committing standins is not allowed.
322 322
323 323 $ cd ..
324 324 $ echo large3 > large3
325 325 $ hg commit .hglf/large3 -m "try to commit standin"
326 326 abort: file ".hglf/large3" is a largefile standin
327 327 (commit the largefile itself instead)
328 328 [255]
329 329
330 330 Corner cases for adding largefiles.
331 331
332 332 $ echo large5 > large5
333 333 $ hg add --large large5
334 334 $ hg add --large large5
335 335 large5 already a largefile
336 336 $ mkdir sub2
337 337 $ echo large6 > sub2/large6
338 338 $ echo large7 > sub2/large7
339 339 $ hg add --large sub2
340 340 adding sub2/large6 as a largefile (glob)
341 341 adding sub2/large7 as a largefile (glob)
342 342 $ hg st
343 343 M large3
344 344 A large5
345 345 A sub2/large6
346 346 A sub2/large7
347 347
348 348 Test "hg status" with combination of 'file pattern' and 'directory
349 349 pattern' for largefiles:
350 350
351 351 $ hg status sub2/large6 sub2
352 352 A sub2/large6
353 353 A sub2/large7
354 354
355 355 Config settings (pattern **.dat, minsize 2 MB) are respected.
356 356
357 357 $ echo testdata > test.dat
358 358 $ dd bs=1k count=2k if=/dev/zero of=reallylarge > /dev/null 2> /dev/null
359 359 $ hg add
360 360 adding reallylarge as a largefile
361 361 adding test.dat as a largefile
362 362
363 363 Test that minsize and --lfsize handle float values;
364 364 also tests that --lfsize overrides largefiles.minsize.
365 365 (0.250 MB = 256 kB = 262144 B)
366 366
367 367 $ dd if=/dev/zero of=ratherlarge bs=1024 count=256 > /dev/null 2> /dev/null
368 368 $ dd if=/dev/zero of=medium bs=1024 count=128 > /dev/null 2> /dev/null
369 369 $ hg --config largefiles.minsize=.25 add
370 370 adding ratherlarge as a largefile
371 371 adding medium
372 372 $ hg forget medium
373 373 $ hg --config largefiles.minsize=.25 add --lfsize=.125
374 374 adding medium as a largefile
375 375 $ dd if=/dev/zero of=notlarge bs=1024 count=127 > /dev/null 2> /dev/null
376 376 $ hg --config largefiles.minsize=.25 add --lfsize=.125
377 377 adding notlarge
378 378 $ hg forget notlarge
379 379
380 380 Test forget on largefiles.
381 381
382 382 $ hg forget large3 large5 test.dat reallylarge ratherlarge medium
383 383 $ hg commit -m "add/edit more largefiles"
384 384 Invoking status precommit hook
385 385 A sub2/large6
386 386 A sub2/large7
387 387 R large3
388 388 ? large5
389 389 ? medium
390 390 ? notlarge
391 391 ? ratherlarge
392 392 ? reallylarge
393 393 ? test.dat
394 394 $ hg st
395 395 ? large3
396 396 ? large5
397 397 ? medium
398 398 ? notlarge
399 399 ? ratherlarge
400 400 ? reallylarge
401 401 ? test.dat
402 402
403 403 Purge with largefiles: verify that largefiles are still in the working
404 404 dir after a purge.
405 405
406 406 $ hg purge --all
407 407 $ cat sub/large4
408 408 large44
409 409 $ cat sub2/large6
410 410 large6
411 411 $ cat sub2/large7
412 412 large7
413 413
414 414 Test addremove: verify that files that should be added as largfiles are added as
415 415 such and that already-existing largfiles are not added as normal files by
416 416 accident.
417 417
418 418 $ rm normal3
419 419 $ rm sub/large4
420 420 $ echo "testing addremove with patterns" > testaddremove.dat
421 421 $ echo "normaladdremove" > normaladdremove
422 422 $ hg addremove
423 423 removing sub/large4
424 424 adding testaddremove.dat as a largefile
425 425 removing normal3
426 426 adding normaladdremove
427 427
428 428 Test addremove with -R
429 429
430 430 $ hg up -C
431 431 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
432 432 getting changed largefiles
433 433 1 largefiles updated, 0 removed
434 434 $ rm normal3
435 435 $ rm sub/large4
436 436 $ echo "testing addremove with patterns" > testaddremove.dat
437 437 $ echo "normaladdremove" > normaladdremove
438 438 $ cd ..
439 439 $ hg -R a addremove
440 440 removing sub/large4
441 441 adding a/testaddremove.dat as a largefile (glob)
442 442 removing normal3
443 443 adding normaladdremove
444 444 $ cd a
445 445
446 446 Test 3364
447 447 $ hg clone . ../addrm
448 448 updating to branch default
449 449 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
450 450 getting changed largefiles
451 451 3 largefiles updated, 0 removed
452 452 $ cd ../addrm
453 453 $ cat >> .hg/hgrc <<EOF
454 454 > [hooks]
455 455 > post-commit.stat=sh -c "echo \\"Invoking status postcommit hook\\"; hg status -A"
456 456 > EOF
457 457 $ touch foo
458 458 $ hg add --large foo
459 459 $ hg ci -m "add foo"
460 460 Invoking status precommit hook
461 461 A foo
462 462 Invoking status postcommit hook
463 463 C foo
464 464 C normal3
465 465 C sub/large4
466 466 C sub/normal4
467 467 C sub2/large6
468 468 C sub2/large7
469 469 $ rm foo
470 470 $ hg st
471 471 ! foo
472 472 hmm.. no precommit invoked, but there is a postcommit??
473 473 $ hg ci -m "will not checkin"
474 474 nothing changed
475 475 Invoking status postcommit hook
476 476 ! foo
477 477 C normal3
478 478 C sub/large4
479 479 C sub/normal4
480 480 C sub2/large6
481 481 C sub2/large7
482 482 [1]
483 483 $ hg addremove
484 484 removing foo
485 485 $ hg st
486 486 R foo
487 487 $ hg ci -m "used to say nothing changed"
488 488 Invoking status precommit hook
489 489 R foo
490 490 Invoking status postcommit hook
491 491 C normal3
492 492 C sub/large4
493 493 C sub/normal4
494 494 C sub2/large6
495 495 C sub2/large7
496 496 $ hg st
497 497
498 498 Test 3507 (both normal files and largefiles were a problem)
499 499
500 500 $ touch normal
501 501 $ touch large
502 502 $ hg add normal
503 503 $ hg add --large large
504 504 $ hg ci -m "added"
505 505 Invoking status precommit hook
506 506 A large
507 507 A normal
508 508 Invoking status postcommit hook
509 509 C large
510 510 C normal
511 511 C normal3
512 512 C sub/large4
513 513 C sub/normal4
514 514 C sub2/large6
515 515 C sub2/large7
516 516 $ hg remove normal
517 517 $ hg addremove --traceback
518 518 $ hg ci -m "addremoved normal"
519 519 Invoking status precommit hook
520 520 R normal
521 521 Invoking status postcommit hook
522 522 C large
523 523 C normal3
524 524 C sub/large4
525 525 C sub/normal4
526 526 C sub2/large6
527 527 C sub2/large7
528 528 $ hg up -C '.^'
529 529 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
530 530 getting changed largefiles
531 531 0 largefiles updated, 0 removed
532 532 $ hg remove large
533 533 $ hg addremove --traceback
534 534 $ hg ci -m "removed large"
535 535 Invoking status precommit hook
536 536 R large
537 537 created new head
538 538 Invoking status postcommit hook
539 539 C normal
540 540 C normal3
541 541 C sub/large4
542 542 C sub/normal4
543 543 C sub2/large6
544 544 C sub2/large7
545 545
546 546 Test that a standin can't be added as a large file
547 547
548 548 $ touch large
549 549 $ hg add --large large
550 550 $ hg ci -m "add"
551 551 Invoking status precommit hook
552 552 A large
553 553 Invoking status postcommit hook
554 554 C large
555 555 C normal
556 556 C normal3
557 557 C sub/large4
558 558 C sub/normal4
559 559 C sub2/large6
560 560 C sub2/large7
561 561 $ hg remove large
562 562 $ touch large
563 563 $ hg addremove --config largefiles.patterns=**large --traceback
564 564 adding large as a largefile
565 565
566 566 Test that outgoing --large works (with revsets too)
567 567 $ hg outgoing --rev '.^' --large
568 568 comparing with $TESTTMP/a (glob)
569 569 searching for changes
570 570 changeset: 8:c02fd3b77ec4
571 571 user: test
572 572 date: Thu Jan 01 00:00:00 1970 +0000
573 573 summary: add foo
574 574
575 575 changeset: 9:289dd08c9bbb
576 576 user: test
577 577 date: Thu Jan 01 00:00:00 1970 +0000
578 578 summary: used to say nothing changed
579 579
580 580 changeset: 10:34f23ac6ac12
581 581 user: test
582 582 date: Thu Jan 01 00:00:00 1970 +0000
583 583 summary: added
584 584
585 585 changeset: 12:710c1b2f523c
586 586 parent: 10:34f23ac6ac12
587 587 user: test
588 588 date: Thu Jan 01 00:00:00 1970 +0000
589 589 summary: removed large
590 590
591 591 searching for changes
592 592 largefiles to upload:
593 593 large
594 594 foo
595 595
596 596 $ cd ../a
597 597
598 598 Clone a largefiles repo.
599 599
600 600 $ hg clone . ../b
601 601 updating to branch default
602 602 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
603 603 getting changed largefiles
604 604 3 largefiles updated, 0 removed
605 605 $ cd ../b
606 606 $ hg log --template '{rev}:{node|short} {desc|firstline}\n'
607 607 7:daea875e9014 add/edit more largefiles
608 608 6:4355d653f84f edit files yet again
609 609 5:9d5af5072dbd edit files again
610 610 4:74c02385b94c move files
611 611 3:9e8fbc4bce62 copy files
612 612 2:51a0ae4d5864 remove files
613 613 1:ce8896473775 edit files
614 614 0:30d30fe6a5be add files
615 615 $ cat normal3
616 616 normal33
617 617 $ cat sub/normal4
618 618 normal44
619 619 $ cat sub/large4
620 620 large44
621 621 $ cat sub2/large6
622 622 large6
623 623 $ cat sub2/large7
624 624 large7
625 625 $ cd ..
626 626 $ hg clone a -r 3 c
627 627 adding changesets
628 628 adding manifests
629 629 adding file changes
630 630 added 4 changesets with 10 changes to 4 files
631 631 updating to branch default
632 632 4 files updated, 0 files merged, 0 files removed, 0 files unresolved
633 633 getting changed largefiles
634 634 2 largefiles updated, 0 removed
635 635 $ cd c
636 636 $ hg log --template '{rev}:{node|short} {desc|firstline}\n'
637 637 3:9e8fbc4bce62 copy files
638 638 2:51a0ae4d5864 remove files
639 639 1:ce8896473775 edit files
640 640 0:30d30fe6a5be add files
641 641 $ cat normal1
642 642 normal22
643 643 $ cat large1
644 644 large22
645 645 $ cat sub/normal2
646 646 normal22
647 647 $ cat sub/large2
648 648 large22
649 649
650 650 Old revisions of a clone have correct largefiles content (this also
651 651 tests update).
652 652
653 653 $ hg update -r 1
654 654 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
655 655 getting changed largefiles
656 656 1 largefiles updated, 0 removed
657 657 $ cat large1
658 658 large11
659 659 $ cat sub/large2
660 660 large22
661 661 $ cd ..
662 662
663 663 Test cloning with --all-largefiles flag
664 664
665 665 $ rm "${USERCACHE}"/*
666 666 $ hg clone --all-largefiles a a-backup
667 667 updating to branch default
668 668 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
669 669 getting changed largefiles
670 670 3 largefiles updated, 0 removed
671 671 8 additional largefiles cached
672 672
673 673 $ rm "${USERCACHE}"/*
674 674 $ hg clone --all-largefiles -u 0 a a-clone0
675 675 updating to branch default
676 676 4 files updated, 0 files merged, 0 files removed, 0 files unresolved
677 677 getting changed largefiles
678 678 2 largefiles updated, 0 removed
679 679 9 additional largefiles cached
680 680 $ hg -R a-clone0 sum
681 681 parent: 0:30d30fe6a5be
682 682 add files
683 683 branch: default
684 684 commit: (clean)
685 685 update: 7 new changesets (update)
686 686
687 687 $ rm "${USERCACHE}"/*
688 688 $ hg clone --all-largefiles -u 1 a a-clone1
689 689 updating to branch default
690 690 4 files updated, 0 files merged, 0 files removed, 0 files unresolved
691 691 getting changed largefiles
692 692 2 largefiles updated, 0 removed
693 693 8 additional largefiles cached
694 694 $ hg -R a-clone1 sum
695 695 parent: 1:ce8896473775
696 696 edit files
697 697 branch: default
698 698 commit: (clean)
699 699 update: 6 new changesets (update)
700 700
701 701 $ rm "${USERCACHE}"/*
702 702 $ hg clone --all-largefiles -U a a-clone-u
703 703 11 additional largefiles cached
704 704 $ hg -R a-clone-u sum
705 705 parent: -1:000000000000 (no revision checked out)
706 706 branch: default
707 707 commit: (clean)
708 708 update: 8 new changesets (update)
709 709
710 710 $ mkdir xyz
711 711 $ cd xyz
712 712 $ hg clone ../a
713 713 destination directory: a
714 714 updating to branch default
715 715 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
716 716 getting changed largefiles
717 717 3 largefiles updated, 0 removed
718 718 $ cd ..
719 719
720 Ensure base clone command argument validation
721
722 $ hg clone -U -u 0 a a-clone-failure
723 abort: cannot specify both --noupdate and --updaterev
724 [255]
725
720 726 $ hg clone --all-largefiles a ssh://localhost/a
721 727 abort: --all-largefiles is incompatible with non-local destination ssh://localhost/a
722 728 [255]
723 729
724 730 Test pulling with --all-largefiles flag
725 731
726 732 $ rm -Rf a-backup
727 733 $ hg clone -r 1 a a-backup
728 734 adding changesets
729 735 adding manifests
730 736 adding file changes
731 737 added 2 changesets with 8 changes to 4 files
732 738 updating to branch default
733 739 4 files updated, 0 files merged, 0 files removed, 0 files unresolved
734 740 getting changed largefiles
735 741 2 largefiles updated, 0 removed
736 742 $ rm "${USERCACHE}"/*
737 743 $ cd a-backup
738 744 $ hg pull --all-largefiles
739 745 pulling from $TESTTMP/a (glob)
740 746 searching for changes
741 747 adding changesets
742 748 adding manifests
743 749 adding file changes
744 750 added 6 changesets with 16 changes to 8 files
745 751 (run 'hg update' to get a working copy)
746 752 caching new largefiles
747 753 3 largefiles cached
748 754 3 additional largefiles cached
749 755 $ cd ..
750 756
751 757 Rebasing between two repositories does not revert largefiles to old
752 758 revisions (this was a very bad bug that took a lot of work to fix).
753 759
754 760 $ hg clone a d
755 761 updating to branch default
756 762 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
757 763 getting changed largefiles
758 764 3 largefiles updated, 0 removed
759 765 $ cd b
760 766 $ echo large4-modified > sub/large4
761 767 $ echo normal3-modified > normal3
762 768 $ hg commit -m "modify normal file and largefile in repo b"
763 769 Invoking status precommit hook
764 770 M normal3
765 771 M sub/large4
766 772 $ cd ../d
767 773 $ echo large6-modified > sub2/large6
768 774 $ echo normal4-modified > sub/normal4
769 775 $ hg commit -m "modify normal file largefile in repo d"
770 776 Invoking status precommit hook
771 777 M sub/normal4
772 778 M sub2/large6
773 779 $ cd ..
774 780 $ hg clone d e
775 781 updating to branch default
776 782 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
777 783 getting changed largefiles
778 784 3 largefiles updated, 0 removed
779 785 $ cd d
780 786 $ hg pull --rebase ../b
781 787 pulling from ../b
782 788 searching for changes
783 789 adding changesets
784 790 adding manifests
785 791 adding file changes
786 792 added 1 changesets with 2 changes to 2 files (+1 heads)
787 793 Invoking status precommit hook
788 794 M sub/normal4
789 795 M sub2/large6
790 796 saved backup bundle to $TESTTMP/d/.hg/strip-backup/f574fb32bb45-backup.hg (glob)
791 797 nothing to rebase
792 798 $ hg log --template '{rev}:{node|short} {desc|firstline}\n'
793 799 9:598410d3eb9a modify normal file largefile in repo d
794 800 8:a381d2c8c80e modify normal file and largefile in repo b
795 801 7:daea875e9014 add/edit more largefiles
796 802 6:4355d653f84f edit files yet again
797 803 5:9d5af5072dbd edit files again
798 804 4:74c02385b94c move files
799 805 3:9e8fbc4bce62 copy files
800 806 2:51a0ae4d5864 remove files
801 807 1:ce8896473775 edit files
802 808 0:30d30fe6a5be add files
803 809 $ cat normal3
804 810 normal3-modified
805 811 $ cat sub/normal4
806 812 normal4-modified
807 813 $ cat sub/large4
808 814 large4-modified
809 815 $ cat sub2/large6
810 816 large6-modified
811 817 $ cat sub2/large7
812 818 large7
813 819 $ cd ../e
814 820 $ hg pull ../b
815 821 pulling from ../b
816 822 searching for changes
817 823 adding changesets
818 824 adding manifests
819 825 adding file changes
820 826 added 1 changesets with 2 changes to 2 files (+1 heads)
821 827 (run 'hg heads' to see heads, 'hg merge' to merge)
822 828 caching new largefiles
823 829 0 largefiles cached
824 830 $ hg rebase
825 831 Invoking status precommit hook
826 832 M sub/normal4
827 833 M sub2/large6
828 834 saved backup bundle to $TESTTMP/e/.hg/strip-backup/f574fb32bb45-backup.hg (glob)
829 835 $ hg log --template '{rev}:{node|short} {desc|firstline}\n'
830 836 9:598410d3eb9a modify normal file largefile in repo d
831 837 8:a381d2c8c80e modify normal file and largefile in repo b
832 838 7:daea875e9014 add/edit more largefiles
833 839 6:4355d653f84f edit files yet again
834 840 5:9d5af5072dbd edit files again
835 841 4:74c02385b94c move files
836 842 3:9e8fbc4bce62 copy files
837 843 2:51a0ae4d5864 remove files
838 844 1:ce8896473775 edit files
839 845 0:30d30fe6a5be add files
840 846 $ cat normal3
841 847 normal3-modified
842 848 $ cat sub/normal4
843 849 normal4-modified
844 850 $ cat sub/large4
845 851 large4-modified
846 852 $ cat sub2/large6
847 853 large6-modified
848 854 $ cat sub2/large7
849 855 large7
850 856
851 857 Rollback on largefiles.
852 858
853 859 $ echo large4-modified-again > sub/large4
854 860 $ hg commit -m "Modify large4 again"
855 861 Invoking status precommit hook
856 862 M sub/large4
857 863 $ hg rollback
858 864 repository tip rolled back to revision 9 (undo commit)
859 865 working directory now based on revision 9
860 866 $ hg st
861 867 M sub/large4
862 868 $ hg log --template '{rev}:{node|short} {desc|firstline}\n'
863 869 9:598410d3eb9a modify normal file largefile in repo d
864 870 8:a381d2c8c80e modify normal file and largefile in repo b
865 871 7:daea875e9014 add/edit more largefiles
866 872 6:4355d653f84f edit files yet again
867 873 5:9d5af5072dbd edit files again
868 874 4:74c02385b94c move files
869 875 3:9e8fbc4bce62 copy files
870 876 2:51a0ae4d5864 remove files
871 877 1:ce8896473775 edit files
872 878 0:30d30fe6a5be add files
873 879 $ cat sub/large4
874 880 large4-modified-again
875 881
876 882 "update --check" refuses to update with uncommitted changes.
877 883 $ hg update --check 8
878 884 abort: uncommitted local changes
879 885 [255]
880 886
881 887 "update --clean" leaves correct largefiles in working copy.
882 888
883 889 $ hg update --clean
884 890 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
885 891 getting changed largefiles
886 892 1 largefiles updated, 0 removed
887 893 $ cat normal3
888 894 normal3-modified
889 895 $ cat sub/normal4
890 896 normal4-modified
891 897 $ cat sub/large4
892 898 large4-modified
893 899 $ cat sub2/large6
894 900 large6-modified
895 901 $ cat sub2/large7
896 902 large7
897 903
898 904 Now "update check" is happy.
899 905 $ hg update --check 8
900 906 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
901 907 getting changed largefiles
902 908 1 largefiles updated, 0 removed
903 909 $ hg update --check
904 910 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
905 911 getting changed largefiles
906 912 1 largefiles updated, 0 removed
907 913
908 914 Test removing empty largefiles directories on update
909 915 $ test -d sub2 && echo "sub2 exists"
910 916 sub2 exists
911 917 $ hg update -q null
912 918 $ test -d sub2 && echo "error: sub2 should not exist anymore"
913 919 [1]
914 920 $ hg update -q
915 921
916 922 Test hg remove removes empty largefiles directories
917 923 $ test -d sub2 && echo "sub2 exists"
918 924 sub2 exists
919 925 $ hg remove sub2/*
920 926 $ test -d sub2 && echo "error: sub2 should not exist anymore"
921 927 [1]
922 928 $ hg revert sub2/large6 sub2/large7
923 929
924 930 "revert" works on largefiles (and normal files too).
925 931 $ echo hack3 >> normal3
926 932 $ echo hack4 >> sub/normal4
927 933 $ echo hack4 >> sub/large4
928 934 $ rm sub2/large6
929 935 $ hg revert sub2/large6
930 936 $ hg rm sub2/large6
931 937 $ echo new >> sub2/large8
932 938 $ hg add --large sub2/large8
933 939 # XXX we don't really want to report that we're reverting the standin;
934 940 # that's just an implementation detail. But I don't see an obvious fix. ;-(
935 941 $ hg revert sub
936 942 reverting .hglf/sub/large4 (glob)
937 943 reverting sub/normal4 (glob)
938 944 $ hg status
939 945 M normal3
940 946 A sub2/large8
941 947 R sub2/large6
942 948 ? sub/large4.orig
943 949 ? sub/normal4.orig
944 950 $ cat sub/normal4
945 951 normal4-modified
946 952 $ cat sub/large4
947 953 large4-modified
948 954 $ hg revert -a --no-backup
949 955 undeleting .hglf/sub2/large6 (glob)
950 956 forgetting .hglf/sub2/large8 (glob)
951 957 reverting normal3
952 958 $ hg status
953 959 ? sub/large4.orig
954 960 ? sub/normal4.orig
955 961 ? sub2/large8
956 962 $ cat normal3
957 963 normal3-modified
958 964 $ cat sub2/large6
959 965 large6-modified
960 966 $ rm sub/*.orig sub2/large8
961 967
962 968 revert some files to an older revision
963 969 $ hg revert --no-backup -r 8 sub2
964 970 reverting .hglf/sub2/large6 (glob)
965 971 $ cat sub2/large6
966 972 large6
967 973 $ hg revert --no-backup -C -r '.^' sub2
968 974 reverting .hglf/sub2/large6 (glob)
969 975 $ hg revert --no-backup sub2
970 976 reverting .hglf/sub2/large6 (glob)
971 977 $ hg status
972 978
973 979 "verify --large" actually verifies largefiles
974 980
975 981 $ hg verify --large
976 982 checking changesets
977 983 checking manifests
978 984 crosschecking files in changesets and manifests
979 985 checking files
980 986 10 files, 10 changesets, 28 total revisions
981 987 searching 1 changesets for largefiles
982 988 verified existence of 3 revisions of 3 largefiles
983 989
984 990 Merging does not revert to old versions of largefiles and also check
985 991 that merging after having pulled from a non-default remote works
986 992 correctly.
987 993
988 994 $ cd ..
989 995 $ hg clone -r 7 e temp
990 996 adding changesets
991 997 adding manifests
992 998 adding file changes
993 999 added 8 changesets with 24 changes to 10 files
994 1000 updating to branch default
995 1001 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
996 1002 getting changed largefiles
997 1003 3 largefiles updated, 0 removed
998 1004 $ hg clone temp f
999 1005 updating to branch default
1000 1006 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
1001 1007 getting changed largefiles
1002 1008 3 largefiles updated, 0 removed
1003 1009 # Delete the largefiles in the largefiles system cache so that we have an
1004 1010 # opportunity to test that caching after a pull works.
1005 1011 $ rm "${USERCACHE}"/*
1006 1012 $ cd f
1007 1013 $ echo "large4-merge-test" > sub/large4
1008 1014 $ hg commit -m "Modify large4 to test merge"
1009 1015 Invoking status precommit hook
1010 1016 M sub/large4
1011 1017 $ hg pull ../e
1012 1018 pulling from ../e
1013 1019 searching for changes
1014 1020 adding changesets
1015 1021 adding manifests
1016 1022 adding file changes
1017 1023 added 2 changesets with 4 changes to 4 files (+1 heads)
1018 1024 (run 'hg heads' to see heads, 'hg merge' to merge)
1019 1025 caching new largefiles
1020 1026 2 largefiles cached
1021 1027 $ hg merge
1022 1028 merging sub/large4
1023 1029 largefile sub/large4 has a merge conflict
1024 1030 keep (l)ocal or take (o)ther? l
1025 1031 3 files updated, 1 files merged, 0 files removed, 0 files unresolved
1026 1032 (branch merge, don't forget to commit)
1027 1033 getting changed largefiles
1028 1034 1 largefiles updated, 0 removed
1029 1035 $ hg commit -m "Merge repos e and f"
1030 1036 Invoking status precommit hook
1031 1037 M normal3
1032 1038 M sub/normal4
1033 1039 M sub2/large6
1034 1040 $ cat normal3
1035 1041 normal3-modified
1036 1042 $ cat sub/normal4
1037 1043 normal4-modified
1038 1044 $ cat sub/large4
1039 1045 large4-merge-test
1040 1046 $ cat sub2/large6
1041 1047 large6-modified
1042 1048 $ cat sub2/large7
1043 1049 large7
1044 1050
1045 1051 Test status after merging with a branch that introduces a new largefile:
1046 1052
1047 1053 $ echo large > large
1048 1054 $ hg add --large large
1049 1055 $ hg commit -m 'add largefile'
1050 1056 Invoking status precommit hook
1051 1057 A large
1052 1058 $ hg update -q ".^"
1053 1059 $ echo change >> normal3
1054 1060 $ hg commit -m 'some change'
1055 1061 Invoking status precommit hook
1056 1062 M normal3
1057 1063 created new head
1058 1064 $ hg merge
1059 1065 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1060 1066 (branch merge, don't forget to commit)
1061 1067 getting changed largefiles
1062 1068 1 largefiles updated, 0 removed
1063 1069 $ hg status
1064 1070 M large
1065 1071
1066 1072 Test that a normal file and a largefile with the same name and path cannot
1067 1073 coexist.
1068 1074
1069 1075 $ rm sub2/large7
1070 1076 $ echo "largeasnormal" > sub2/large7
1071 1077 $ hg add sub2/large7
1072 1078 sub2/large7 already a largefile
1073 1079
1074 1080 Test that transplanting a largefile change works correctly.
1075 1081
1076 1082 $ cd ..
1077 1083 $ hg clone -r 8 d g
1078 1084 adding changesets
1079 1085 adding manifests
1080 1086 adding file changes
1081 1087 added 9 changesets with 26 changes to 10 files
1082 1088 updating to branch default
1083 1089 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
1084 1090 getting changed largefiles
1085 1091 3 largefiles updated, 0 removed
1086 1092 $ cd g
1087 1093 $ hg transplant -s ../d 598410d3eb9a
1088 1094 searching for changes
1089 1095 searching for changes
1090 1096 adding changesets
1091 1097 adding manifests
1092 1098 adding file changes
1093 1099 added 1 changesets with 2 changes to 2 files
1094 1100 getting changed largefiles
1095 1101 1 largefiles updated, 0 removed
1096 1102 $ hg log --template '{rev}:{node|short} {desc|firstline}\n'
1097 1103 9:598410d3eb9a modify normal file largefile in repo d
1098 1104 8:a381d2c8c80e modify normal file and largefile in repo b
1099 1105 7:daea875e9014 add/edit more largefiles
1100 1106 6:4355d653f84f edit files yet again
1101 1107 5:9d5af5072dbd edit files again
1102 1108 4:74c02385b94c move files
1103 1109 3:9e8fbc4bce62 copy files
1104 1110 2:51a0ae4d5864 remove files
1105 1111 1:ce8896473775 edit files
1106 1112 0:30d30fe6a5be add files
1107 1113 $ cat normal3
1108 1114 normal3-modified
1109 1115 $ cat sub/normal4
1110 1116 normal4-modified
1111 1117 $ cat sub/large4
1112 1118 large4-modified
1113 1119 $ cat sub2/large6
1114 1120 large6-modified
1115 1121 $ cat sub2/large7
1116 1122 large7
1117 1123
1118 1124 Cat a largefile
1119 1125 $ hg cat normal3
1120 1126 normal3-modified
1121 1127 $ hg cat sub/large4
1122 1128 large4-modified
1123 1129 $ rm "${USERCACHE}"/*
1124 1130 $ hg cat -r a381d2c8c80e -o cat.out sub/large4
1125 1131 $ cat cat.out
1126 1132 large4-modified
1127 1133 $ rm cat.out
1128 1134 $ hg cat -r a381d2c8c80e normal3
1129 1135 normal3-modified
1130 1136 $ hg cat -r '.^' normal3
1131 1137 normal3-modified
1132 1138 $ hg cat -r '.^' sub/large4
1133 1139 large4-modified
1134 1140
1135 1141 Test that renaming a largefile results in correct output for status
1136 1142
1137 1143 $ hg rename sub/large4 large4-renamed
1138 1144 $ hg commit -m "test rename output"
1139 1145 Invoking status precommit hook
1140 1146 A large4-renamed
1141 1147 R sub/large4
1142 1148 $ cat large4-renamed
1143 1149 large4-modified
1144 1150 $ cd sub2
1145 1151 $ hg rename large6 large6-renamed
1146 1152 $ hg st
1147 1153 A sub2/large6-renamed
1148 1154 R sub2/large6
1149 1155 $ cd ..
1150 1156
1151 1157 Test --normal flag
1152 1158
1153 1159 $ dd if=/dev/zero bs=2k count=11k > new-largefile 2> /dev/null
1154 1160 $ hg add --normal --large new-largefile
1155 1161 abort: --normal cannot be used with --large
1156 1162 [255]
1157 1163 $ hg add --normal new-largefile
1158 1164 new-largefile: up to 69 MB of RAM may be required to manage this file
1159 1165 (use 'hg revert new-largefile' to cancel the pending addition)
1160 1166 $ cd ..
1161 1167
1162 1168 #if serve
1163 1169 vanilla clients not locked out from largefiles servers on vanilla repos
1164 1170 $ mkdir r1
1165 1171 $ cd r1
1166 1172 $ hg init
1167 1173 $ echo c1 > f1
1168 1174 $ hg add f1
1169 1175 $ hg commit -m "m1"
1170 1176 Invoking status precommit hook
1171 1177 A f1
1172 1178 $ cd ..
1173 1179 $ hg serve -R r1 -d -p $HGPORT --pid-file hg.pid
1174 1180 $ cat hg.pid >> $DAEMON_PIDS
1175 1181 $ hg --config extensions.largefiles=! clone http://localhost:$HGPORT r2
1176 1182 requesting all changes
1177 1183 adding changesets
1178 1184 adding manifests
1179 1185 adding file changes
1180 1186 added 1 changesets with 1 changes to 1 files
1181 1187 updating to branch default
1182 1188 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1183 1189
1184 1190 largefiles clients still work with vanilla servers
1185 1191 $ hg --config extensions.largefiles=! serve -R r1 -d -p $HGPORT1 --pid-file hg.pid
1186 1192 $ cat hg.pid >> $DAEMON_PIDS
1187 1193 $ hg clone http://localhost:$HGPORT1 r3
1188 1194 requesting all changes
1189 1195 adding changesets
1190 1196 adding manifests
1191 1197 adding file changes
1192 1198 added 1 changesets with 1 changes to 1 files
1193 1199 updating to branch default
1194 1200 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1195 1201 #endif
1196 1202
1197 1203
1198 1204 vanilla clients locked out from largefiles http repos
1199 1205 $ mkdir r4
1200 1206 $ cd r4
1201 1207 $ hg init
1202 1208 $ echo c1 > f1
1203 1209 $ hg add --large f1
1204 1210 $ hg commit -m "m1"
1205 1211 Invoking status precommit hook
1206 1212 A f1
1207 1213 $ cd ..
1208 1214
1209 1215 largefiles can be pushed locally (issue3583)
1210 1216 $ hg init dest
1211 1217 $ cd r4
1212 1218 $ hg outgoing ../dest
1213 1219 comparing with ../dest
1214 1220 searching for changes
1215 1221 changeset: 0:639881c12b4c
1216 1222 tag: tip
1217 1223 user: test
1218 1224 date: Thu Jan 01 00:00:00 1970 +0000
1219 1225 summary: m1
1220 1226
1221 1227 $ hg push ../dest
1222 1228 pushing to ../dest
1223 1229 searching for changes
1224 1230 searching for changes
1225 1231 adding changesets
1226 1232 adding manifests
1227 1233 adding file changes
1228 1234 added 1 changesets with 1 changes to 1 files
1229 1235
1230 1236 exit code with nothing outgoing (issue3611)
1231 1237 $ hg outgoing ../dest
1232 1238 comparing with ../dest
1233 1239 searching for changes
1234 1240 no changes found
1235 1241 [1]
1236 1242 $ cd ..
1237 1243
1238 1244 #if serve
1239 1245 $ hg serve -R r4 -d -p $HGPORT2 --pid-file hg.pid
1240 1246 $ cat hg.pid >> $DAEMON_PIDS
1241 1247 $ hg --config extensions.largefiles=! clone http://localhost:$HGPORT2 r5
1242 1248 abort: remote error:
1243 1249
1244 1250 This repository uses the largefiles extension.
1245 1251
1246 1252 Please enable it in your Mercurial config file.
1247 1253 [255]
1248 1254
1249 1255 used all HGPORTs, kill all daemons
1250 1256 $ "$TESTDIR/killdaemons.py"
1251 1257 #endif
1252 1258
1253 1259 vanilla clients locked out from largefiles ssh repos
1254 1260 $ hg --config extensions.largefiles=! clone -e "python \"$TESTDIR/dummyssh\"" ssh://user@dummy/r4 r5
1255 1261 abort: remote error:
1256 1262
1257 1263 This repository uses the largefiles extension.
1258 1264
1259 1265 Please enable it in your Mercurial config file.
1260 1266 [255]
1261 1267
1262 1268 #if serve
1263 1269
1264 1270 largefiles clients refuse to push largefiles repos to vanilla servers
1265 1271 $ mkdir r6
1266 1272 $ cd r6
1267 1273 $ hg init
1268 1274 $ echo c1 > f1
1269 1275 $ hg add f1
1270 1276 $ hg commit -m "m1"
1271 1277 Invoking status precommit hook
1272 1278 A f1
1273 1279 $ cat >> .hg/hgrc <<!
1274 1280 > [web]
1275 1281 > push_ssl = false
1276 1282 > allow_push = *
1277 1283 > !
1278 1284 $ cd ..
1279 1285 $ hg clone r6 r7
1280 1286 updating to branch default
1281 1287 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1282 1288 $ cd r7
1283 1289 $ echo c2 > f2
1284 1290 $ hg add --large f2
1285 1291 $ hg commit -m "m2"
1286 1292 Invoking status precommit hook
1287 1293 A f2
1288 1294 $ hg --config extensions.largefiles=! -R ../r6 serve -d -p $HGPORT --pid-file ../hg.pid
1289 1295 $ cat ../hg.pid >> $DAEMON_PIDS
1290 1296 $ hg push http://localhost:$HGPORT
1291 1297 pushing to http://localhost:$HGPORT/
1292 1298 searching for changes
1293 1299 abort: http://localhost:$HGPORT/ does not appear to be a largefile store
1294 1300 [255]
1295 1301 $ cd ..
1296 1302
1297 1303 putlfile errors are shown (issue3123)
1298 1304 Corrupt the cached largefile in r7 and in the usercache (required for testing on vfat)
1299 1305 $ echo corruption > "$TESTTMP/r7/.hg/largefiles/4cdac4d8b084d0b599525cf732437fb337d422a8"
1300 1306 $ echo corruption > "$USERCACHE/4cdac4d8b084d0b599525cf732437fb337d422a8"
1301 1307 $ hg init empty
1302 1308 $ hg serve -R empty -d -p $HGPORT1 --pid-file hg.pid \
1303 1309 > --config 'web.allow_push=*' --config web.push_ssl=False
1304 1310 $ cat hg.pid >> $DAEMON_PIDS
1305 1311 $ hg push -R r7 http://localhost:$HGPORT1
1306 1312 pushing to http://localhost:$HGPORT1/
1307 1313 searching for changes
1308 1314 remote: largefiles: failed to put 4cdac4d8b084d0b599525cf732437fb337d422a8 into store: largefile contents do not match hash
1309 1315 abort: remotestore: could not put $TESTTMP/r7/.hg/largefiles/4cdac4d8b084d0b599525cf732437fb337d422a8 to remote store http://localhost:$HGPORT1/ (glob)
1310 1316 [255]
1311 1317 $ rm -rf empty
1312 1318
1313 1319 Push a largefiles repository to a served empty repository
1314 1320 $ hg init r8
1315 1321 $ echo c3 > r8/f1
1316 1322 $ hg add --large r8/f1 -R r8
1317 1323 $ hg commit -m "m1" -R r8
1318 1324 Invoking status precommit hook
1319 1325 A f1
1320 1326 $ hg init empty
1321 1327 $ hg serve -R empty -d -p $HGPORT2 --pid-file hg.pid \
1322 1328 > --config 'web.allow_push=*' --config web.push_ssl=False
1323 1329 $ cat hg.pid >> $DAEMON_PIDS
1324 1330 $ rm "${USERCACHE}"/*
1325 1331 $ hg push -R r8 http://localhost:$HGPORT2
1326 1332 pushing to http://localhost:$HGPORT2/
1327 1333 searching for changes
1328 1334 searching for changes
1329 1335 remote: adding changesets
1330 1336 remote: adding manifests
1331 1337 remote: adding file changes
1332 1338 remote: added 1 changesets with 1 changes to 1 files
1333 1339 $ rm -rf empty
1334 1340
1335 1341 used all HGPORTs, kill all daemons
1336 1342 $ "$TESTDIR/killdaemons.py"
1337 1343
1338 1344 #endif
1339 1345
1340 1346
1341 1347 #if unix-permissions
1342 1348
1343 1349 Clone a local repository owned by another user
1344 1350 We have to simulate that here by setting $HOME and removing write permissions
1345 1351 $ ORIGHOME="$HOME"
1346 1352 $ mkdir alice
1347 1353 $ HOME="`pwd`/alice"
1348 1354 $ cd alice
1349 1355 $ hg init pubrepo
1350 1356 $ cd pubrepo
1351 1357 $ dd if=/dev/zero bs=1k count=11k > a-large-file 2> /dev/null
1352 1358 $ hg add --large a-large-file
1353 1359 $ hg commit -m "Add a large file"
1354 1360 Invoking status precommit hook
1355 1361 A a-large-file
1356 1362 $ cd ..
1357 1363 $ chmod -R a-w pubrepo
1358 1364 $ cd ..
1359 1365 $ mkdir bob
1360 1366 $ HOME="`pwd`/bob"
1361 1367 $ cd bob
1362 1368 $ hg clone --pull ../alice/pubrepo pubrepo
1363 1369 requesting all changes
1364 1370 adding changesets
1365 1371 adding manifests
1366 1372 adding file changes
1367 1373 added 1 changesets with 1 changes to 1 files
1368 1374 updating to branch default
1369 1375 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1370 1376 getting changed largefiles
1371 1377 1 largefiles updated, 0 removed
1372 1378 $ cd ..
1373 1379 $ chmod -R u+w alice/pubrepo
1374 1380 $ HOME="$ORIGHOME"
1375 1381
1376 1382 #endif
1377 1383
1378 1384 #if symlink
1379 1385
1380 1386 Symlink to a large largefile should behave the same as a symlink to a normal file
1381 1387 $ hg init largesymlink
1382 1388 $ cd largesymlink
1383 1389 $ dd if=/dev/zero bs=1k count=10k of=largefile 2>/dev/null
1384 1390 $ hg add --large largefile
1385 1391 $ hg commit -m "commit a large file"
1386 1392 Invoking status precommit hook
1387 1393 A largefile
1388 1394 $ ln -s largefile largelink
1389 1395 $ hg add largelink
1390 1396 $ hg commit -m "commit a large symlink"
1391 1397 Invoking status precommit hook
1392 1398 A largelink
1393 1399 $ rm -f largelink
1394 1400 $ hg up >/dev/null
1395 1401 $ test -f largelink
1396 1402 [1]
1397 1403 $ test -L largelink
1398 1404 [1]
1399 1405 $ rm -f largelink # make next part of the test independent of the previous
1400 1406 $ hg up -C >/dev/null
1401 1407 $ test -f largelink
1402 1408 $ test -L largelink
1403 1409 $ cd ..
1404 1410
1405 1411 #endif
1406 1412
1407 1413 test for pattern matching on 'hg status':
1408 1414 to boost performance, largefiles checks whether specified patterns are
1409 1415 related to largefiles in working directory (NOT to STANDIN) or not.
1410 1416
1411 1417 $ hg init statusmatch
1412 1418 $ cd statusmatch
1413 1419
1414 1420 $ mkdir -p a/b/c/d
1415 1421 $ echo normal > a/b/c/d/e.normal.txt
1416 1422 $ hg add a/b/c/d/e.normal.txt
1417 1423 $ echo large > a/b/c/d/e.large.txt
1418 1424 $ hg add --large a/b/c/d/e.large.txt
1419 1425 $ mkdir -p a/b/c/x
1420 1426 $ echo normal > a/b/c/x/y.normal.txt
1421 1427 $ hg add a/b/c/x/y.normal.txt
1422 1428 $ hg commit -m 'add files'
1423 1429 Invoking status precommit hook
1424 1430 A a/b/c/d/e.large.txt
1425 1431 A a/b/c/d/e.normal.txt
1426 1432 A a/b/c/x/y.normal.txt
1427 1433
1428 1434 (1) no pattern: no performance boost
1429 1435 $ hg status -A
1430 1436 C a/b/c/d/e.large.txt
1431 1437 C a/b/c/d/e.normal.txt
1432 1438 C a/b/c/x/y.normal.txt
1433 1439
1434 1440 (2) pattern not related to largefiles: performance boost
1435 1441 $ hg status -A a/b/c/x
1436 1442 C a/b/c/x/y.normal.txt
1437 1443
1438 1444 (3) pattern related to largefiles: no performance boost
1439 1445 $ hg status -A a/b/c/d
1440 1446 C a/b/c/d/e.large.txt
1441 1447 C a/b/c/d/e.normal.txt
1442 1448
1443 1449 (4) pattern related to STANDIN (not to largefiles): performance boost
1444 1450 $ hg status -A .hglf/a
1445 1451 C .hglf/a/b/c/d/e.large.txt
1446 1452
1447 1453 (5) mixed case: no performance boost
1448 1454 $ hg status -A a/b/c/x a/b/c/d
1449 1455 C a/b/c/d/e.large.txt
1450 1456 C a/b/c/d/e.normal.txt
1451 1457 C a/b/c/x/y.normal.txt
1452 1458
1453 1459 verify that largefiles doesn't break filesets
1454 1460
1455 1461 $ hg log --rev . --exclude "set:binary()"
1456 1462 changeset: 0:41bd42f10efa
1457 1463 tag: tip
1458 1464 user: test
1459 1465 date: Thu Jan 01 00:00:00 1970 +0000
1460 1466 summary: add files
1461 1467
1462 1468 verify that large files in subrepos handled properly
1463 1469 $ hg init subrepo
1464 1470 $ echo "subrepo = subrepo" > .hgsub
1465 1471 $ hg add .hgsub
1466 1472 $ hg ci -m "add subrepo"
1467 1473 Invoking status precommit hook
1468 1474 A .hgsub
1469 1475 ? .hgsubstate
1470 1476 $ echo "rev 1" > subrepo/large.txt
1471 1477 $ hg -R subrepo add --large subrepo/large.txt
1472 1478 $ hg sum
1473 1479 parent: 1:8ee150ea2e9c tip
1474 1480 add subrepo
1475 1481 branch: default
1476 1482 commit: 1 subrepos
1477 1483 update: (current)
1478 1484 $ hg st
1479 1485 $ hg st -S
1480 1486 A subrepo/large.txt
1481 1487 $ hg ci -S -m "commit top repo"
1482 1488 committing subrepository subrepo
1483 1489 Invoking status precommit hook
1484 1490 A large.txt
1485 1491 Invoking status precommit hook
1486 1492 M .hgsubstate
1487 1493 # No differences
1488 1494 $ hg st -S
1489 1495 $ hg sum
1490 1496 parent: 2:ce4cd0c527a6 tip
1491 1497 commit top repo
1492 1498 branch: default
1493 1499 commit: (clean)
1494 1500 update: (current)
1495 1501 $ echo "rev 2" > subrepo/large.txt
1496 1502 $ hg st -S
1497 1503 M subrepo/large.txt
1498 1504 $ hg sum
1499 1505 parent: 2:ce4cd0c527a6 tip
1500 1506 commit top repo
1501 1507 branch: default
1502 1508 commit: 1 subrepos
1503 1509 update: (current)
1504 1510 $ hg ci -m "this commit should fail without -S"
1505 1511 abort: uncommitted changes in subrepo subrepo
1506 1512 (use --subrepos for recursive commit)
1507 1513 [255]
1508 1514
1509 1515 Add a normal file to the subrepo, then test archiving
1510 1516
1511 1517 $ echo 'normal file' > subrepo/normal.txt
1512 1518 $ hg -R subrepo add subrepo/normal.txt
1513 1519
1514 1520 Lock in subrepo, otherwise the change isn't archived
1515 1521
1516 1522 $ hg ci -S -m "add normal file to top level"
1517 1523 committing subrepository subrepo
1518 1524 Invoking status precommit hook
1519 1525 M large.txt
1520 1526 A normal.txt
1521 1527 Invoking status precommit hook
1522 1528 M .hgsubstate
1523 1529 $ hg archive -S lf_subrepo_archive
1524 1530 $ find lf_subrepo_archive | sort
1525 1531 lf_subrepo_archive
1526 1532 lf_subrepo_archive/.hg_archival.txt
1527 1533 lf_subrepo_archive/.hgsub
1528 1534 lf_subrepo_archive/.hgsubstate
1529 1535 lf_subrepo_archive/a
1530 1536 lf_subrepo_archive/a/b
1531 1537 lf_subrepo_archive/a/b/c
1532 1538 lf_subrepo_archive/a/b/c/d
1533 1539 lf_subrepo_archive/a/b/c/d/e.large.txt
1534 1540 lf_subrepo_archive/a/b/c/d/e.normal.txt
1535 1541 lf_subrepo_archive/a/b/c/x
1536 1542 lf_subrepo_archive/a/b/c/x/y.normal.txt
1537 1543 lf_subrepo_archive/subrepo
1538 1544 lf_subrepo_archive/subrepo/large.txt
1539 1545 lf_subrepo_archive/subrepo/normal.txt
1540 1546
1541 1547 $ cd ..
General Comments 0
You need to be logged in to leave comments. Login now