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