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