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