##// END OF EJS Templates
largefiles: use "summaryremotehooks" to avoid redundant outgoing check...
FUJIWARA Katsunori -
r21048:ca7a5746 default
parent child Browse files
Show More
@@ -1,1178 +1,1190 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, error, merge, discovery, 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 '''overrides scmutil.match so that the matcher it returns will ignore all
28 28 largefiles'''
29 29 oldmatch = None # for the closure
30 30 def overridematch(ctx, pats=[], opts={}, globbed=False,
31 31 default='relpath'):
32 32 match = oldmatch(ctx, pats, opts, globbed, default)
33 33 m = copy.copy(match)
34 34 notlfile = lambda f: not (lfutil.isstandin(f) or lfutil.standin(f) in
35 35 manifest)
36 36 m._files = filter(notlfile, m._files)
37 37 m._fmap = set(m._files)
38 38 m._always = False
39 39 origmatchfn = m.matchfn
40 40 m.matchfn = lambda f: notlfile(f) and origmatchfn(f) or None
41 41 return m
42 42 oldmatch = installmatchfn(overridematch)
43 43
44 44 def installmatchfn(f):
45 45 oldmatch = scmutil.match
46 46 setattr(f, 'oldmatch', oldmatch)
47 47 scmutil.match = f
48 48 return oldmatch
49 49
50 50 def restorematchfn():
51 51 '''restores scmutil.match to what it was before installnormalfilesmatchfn
52 52 was called. no-op if scmutil.match is its original function.
53 53
54 54 Note that n calls to installnormalfilesmatchfn will require n calls to
55 55 restore matchfn to reverse'''
56 56 scmutil.match = getattr(scmutil.match, 'oldmatch', scmutil.match)
57 57
58 58 def addlargefiles(ui, repo, *pats, **opts):
59 59 large = opts.pop('large', None)
60 60 lfsize = lfutil.getminsize(
61 61 ui, lfutil.islfilesrepo(repo), opts.pop('lfsize', None))
62 62
63 63 lfmatcher = None
64 64 if lfutil.islfilesrepo(repo):
65 65 lfpats = ui.configlist(lfutil.longname, 'patterns', default=[])
66 66 if lfpats:
67 67 lfmatcher = match_.match(repo.root, '', list(lfpats))
68 68
69 69 lfnames = []
70 70 m = scmutil.match(repo[None], pats, opts)
71 71 m.bad = lambda x, y: None
72 72 wctx = repo[None]
73 73 for f in repo.walk(m):
74 74 exact = m.exact(f)
75 75 lfile = lfutil.standin(f) in wctx
76 76 nfile = f in wctx
77 77 exists = lfile or nfile
78 78
79 79 # Don't warn the user when they attempt to add a normal tracked file.
80 80 # The normal add code will do that for us.
81 81 if exact and exists:
82 82 if lfile:
83 83 ui.warn(_('%s already a largefile\n') % f)
84 84 continue
85 85
86 86 if (exact or not exists) and not lfutil.isstandin(f):
87 87 wfile = repo.wjoin(f)
88 88
89 89 # In case the file was removed previously, but not committed
90 90 # (issue3507)
91 91 if not os.path.exists(wfile):
92 92 continue
93 93
94 94 abovemin = (lfsize and
95 95 os.lstat(wfile).st_size >= lfsize * 1024 * 1024)
96 96 if large or abovemin or (lfmatcher and lfmatcher(f)):
97 97 lfnames.append(f)
98 98 if ui.verbose or not exact:
99 99 ui.status(_('adding %s as a largefile\n') % m.rel(f))
100 100
101 101 bad = []
102 102 standins = []
103 103
104 104 # Need to lock, otherwise there could be a race condition between
105 105 # when standins are created and added to the repo.
106 106 wlock = repo.wlock()
107 107 try:
108 108 if not opts.get('dry_run'):
109 109 lfdirstate = lfutil.openlfdirstate(ui, repo)
110 110 for f in lfnames:
111 111 standinname = lfutil.standin(f)
112 112 lfutil.writestandin(repo, standinname, hash='',
113 113 executable=lfutil.getexecutable(repo.wjoin(f)))
114 114 standins.append(standinname)
115 115 if lfdirstate[f] == 'r':
116 116 lfdirstate.normallookup(f)
117 117 else:
118 118 lfdirstate.add(f)
119 119 lfdirstate.write()
120 120 bad += [lfutil.splitstandin(f)
121 121 for f in repo[None].add(standins)
122 122 if f in m.files()]
123 123 finally:
124 124 wlock.release()
125 125 return bad
126 126
127 127 def removelargefiles(ui, repo, *pats, **opts):
128 128 after = opts.get('after')
129 129 if not pats and not after:
130 130 raise util.Abort(_('no files specified'))
131 131 m = scmutil.match(repo[None], pats, opts)
132 132 try:
133 133 repo.lfstatus = True
134 134 s = repo.status(match=m, clean=True)
135 135 finally:
136 136 repo.lfstatus = False
137 137 manifest = repo[None].manifest()
138 138 modified, added, deleted, clean = [[f for f in list
139 139 if lfutil.standin(f) in manifest]
140 140 for list in [s[0], s[1], s[3], s[6]]]
141 141
142 142 def warn(files, msg):
143 143 for f in files:
144 144 ui.warn(msg % m.rel(f))
145 145 return int(len(files) > 0)
146 146
147 147 result = 0
148 148
149 149 if after:
150 150 remove, forget = deleted, []
151 151 result = warn(modified + added + clean,
152 152 _('not removing %s: file still exists\n'))
153 153 else:
154 154 remove, forget = deleted + clean, []
155 155 result = warn(modified, _('not removing %s: file is modified (use -f'
156 156 ' to force removal)\n'))
157 157 result = warn(added, _('not removing %s: file has been marked for add'
158 158 ' (use forget to undo)\n')) or result
159 159
160 160 for f in sorted(remove + forget):
161 161 if ui.verbose or not m.exact(f):
162 162 ui.status(_('removing %s\n') % m.rel(f))
163 163
164 164 # Need to lock because standin files are deleted then removed from the
165 165 # repository and we could race in-between.
166 166 wlock = repo.wlock()
167 167 try:
168 168 lfdirstate = lfutil.openlfdirstate(ui, repo)
169 169 for f in remove:
170 170 if not after:
171 171 # If this is being called by addremove, notify the user that we
172 172 # are removing the file.
173 173 if getattr(repo, "_isaddremove", False):
174 174 ui.status(_('removing %s\n') % f)
175 175 util.unlinkpath(repo.wjoin(f), ignoremissing=True)
176 176 lfdirstate.remove(f)
177 177 lfdirstate.write()
178 178 forget = [lfutil.standin(f) for f in forget]
179 179 remove = [lfutil.standin(f) for f in remove]
180 180 repo[None].forget(forget)
181 181 # If this is being called by addremove, let the original addremove
182 182 # function handle this.
183 183 if not getattr(repo, "_isaddremove", False):
184 184 for f in remove:
185 185 util.unlinkpath(repo.wjoin(f), ignoremissing=True)
186 186 repo[None].forget(remove)
187 187 finally:
188 188 wlock.release()
189 189
190 190 return result
191 191
192 192 # For overriding mercurial.hgweb.webcommands so that largefiles will
193 193 # appear at their right place in the manifests.
194 194 def decodepath(orig, path):
195 195 return lfutil.splitstandin(path) or path
196 196
197 197 # -- Wrappers: modify existing commands --------------------------------
198 198
199 199 # Add works by going through the files that the user wanted to add and
200 200 # checking if they should be added as largefiles. Then it makes a new
201 201 # matcher which matches only the normal files and runs the original
202 202 # version of add.
203 203 def overrideadd(orig, ui, repo, *pats, **opts):
204 204 normal = opts.pop('normal')
205 205 if normal:
206 206 if opts.get('large'):
207 207 raise util.Abort(_('--normal cannot be used with --large'))
208 208 return orig(ui, repo, *pats, **opts)
209 209 bad = addlargefiles(ui, repo, *pats, **opts)
210 210 installnormalfilesmatchfn(repo[None].manifest())
211 211 result = orig(ui, repo, *pats, **opts)
212 212 restorematchfn()
213 213
214 214 return (result == 1 or bad) and 1 or 0
215 215
216 216 def overrideremove(orig, ui, repo, *pats, **opts):
217 217 installnormalfilesmatchfn(repo[None].manifest())
218 218 result = orig(ui, repo, *pats, **opts)
219 219 restorematchfn()
220 220 return removelargefiles(ui, repo, *pats, **opts) or result
221 221
222 222 def overridestatusfn(orig, repo, rev2, **opts):
223 223 try:
224 224 repo._repo.lfstatus = True
225 225 return orig(repo, rev2, **opts)
226 226 finally:
227 227 repo._repo.lfstatus = False
228 228
229 229 def overridestatus(orig, ui, repo, *pats, **opts):
230 230 try:
231 231 repo.lfstatus = True
232 232 return orig(ui, repo, *pats, **opts)
233 233 finally:
234 234 repo.lfstatus = False
235 235
236 236 def overridedirty(orig, repo, ignoreupdate=False):
237 237 try:
238 238 repo._repo.lfstatus = True
239 239 return orig(repo, ignoreupdate)
240 240 finally:
241 241 repo._repo.lfstatus = False
242 242
243 243 def overridelog(orig, ui, repo, *pats, **opts):
244 244 def overridematch(ctx, pats=[], opts={}, globbed=False,
245 245 default='relpath'):
246 246 """Matcher that merges root directory with .hglf, suitable for log.
247 247 It is still possible to match .hglf directly.
248 248 For any listed files run log on the standin too.
249 249 matchfn tries both the given filename and with .hglf stripped.
250 250 """
251 251 match = oldmatch(ctx, pats, opts, globbed, default)
252 252 m = copy.copy(match)
253 253 for i in range(0, len(m._files)):
254 254 standin = lfutil.standin(m._files[i])
255 255 if standin in repo[ctx.node()]:
256 256 m._files[i] = standin
257 257 m._fmap = set(m._files)
258 258 m._always = False
259 259 origmatchfn = m.matchfn
260 260 def lfmatchfn(f):
261 261 lf = lfutil.splitstandin(f)
262 262 if lf is not None and origmatchfn(lf):
263 263 return True
264 264 r = origmatchfn(f)
265 265 return r
266 266 m.matchfn = lfmatchfn
267 267 return m
268 268 oldmatch = installmatchfn(overridematch)
269 269 try:
270 270 repo.lfstatus = True
271 271 return orig(ui, repo, *pats, **opts)
272 272 finally:
273 273 repo.lfstatus = False
274 274 restorematchfn()
275 275
276 276 def overrideverify(orig, ui, repo, *pats, **opts):
277 277 large = opts.pop('large', False)
278 278 all = opts.pop('lfa', False)
279 279 contents = opts.pop('lfc', False)
280 280
281 281 result = orig(ui, repo, *pats, **opts)
282 282 if large or all or contents:
283 283 result = result or lfcommands.verifylfiles(ui, repo, all, contents)
284 284 return result
285 285
286 286 def overridedebugstate(orig, ui, repo, *pats, **opts):
287 287 large = opts.pop('large', False)
288 288 if large:
289 289 lfcommands.debugdirstate(ui, repo)
290 290 else:
291 291 orig(ui, repo, *pats, **opts)
292 292
293 293 # Override needs to refresh standins so that update's normal merge
294 294 # will go through properly. Then the other update hook (overriding repo.update)
295 295 # will get the new files. Filemerge is also overridden so that the merge
296 296 # will merge standins correctly.
297 297 def overrideupdate(orig, ui, repo, *pats, **opts):
298 298 lfdirstate = lfutil.openlfdirstate(ui, repo)
299 299 s = lfdirstate.status(match_.always(repo.root, repo.getcwd()), [], False,
300 300 False, False)
301 301 (unsure, modified, added, removed, missing, unknown, ignored, clean) = s
302 302
303 303 # Need to lock between the standins getting updated and their
304 304 # largefiles getting updated
305 305 wlock = repo.wlock()
306 306 try:
307 307 if opts['check']:
308 308 mod = len(modified) > 0
309 309 for lfile in unsure:
310 310 standin = lfutil.standin(lfile)
311 311 if repo['.'][standin].data().strip() != \
312 312 lfutil.hashfile(repo.wjoin(lfile)):
313 313 mod = True
314 314 else:
315 315 lfdirstate.normal(lfile)
316 316 lfdirstate.write()
317 317 if mod:
318 318 raise util.Abort(_('uncommitted changes'))
319 319 # XXX handle removed differently
320 320 if not opts['clean']:
321 321 for lfile in unsure + modified + added:
322 322 lfutil.updatestandin(repo, lfutil.standin(lfile))
323 323 finally:
324 324 wlock.release()
325 325 return orig(ui, repo, *pats, **opts)
326 326
327 327 # Before starting the manifest merge, merge.updates will call
328 328 # _checkunknown to check if there are any files in the merged-in
329 329 # changeset that collide with unknown files in the working copy.
330 330 #
331 331 # The largefiles are seen as unknown, so this prevents us from merging
332 332 # in a file 'foo' if we already have a largefile with the same name.
333 333 #
334 334 # The overridden function filters the unknown files by removing any
335 335 # largefiles. This makes the merge proceed and we can then handle this
336 336 # case further in the overridden manifestmerge function below.
337 337 def overridecheckunknownfile(origfn, repo, wctx, mctx, f):
338 338 if lfutil.standin(repo.dirstate.normalize(f)) in wctx:
339 339 return False
340 340 return origfn(repo, wctx, mctx, f)
341 341
342 342 # The manifest merge handles conflicts on the manifest level. We want
343 343 # to handle changes in largefile-ness of files at this level too.
344 344 #
345 345 # The strategy is to run the original manifestmerge and then process
346 346 # the action list it outputs. There are two cases we need to deal with:
347 347 #
348 348 # 1. Normal file in p1, largefile in p2. Here the largefile is
349 349 # detected via its standin file, which will enter the working copy
350 350 # with a "get" action. It is not "merge" since the standin is all
351 351 # Mercurial is concerned with at this level -- the link to the
352 352 # existing normal file is not relevant here.
353 353 #
354 354 # 2. Largefile in p1, normal file in p2. Here we get a "merge" action
355 355 # since the largefile will be present in the working copy and
356 356 # different from the normal file in p2. Mercurial therefore
357 357 # triggers a merge action.
358 358 #
359 359 # In both cases, we prompt the user and emit new actions to either
360 360 # remove the standin (if the normal file was kept) or to remove the
361 361 # normal file and get the standin (if the largefile was kept). The
362 362 # default prompt answer is to use the largefile version since it was
363 363 # presumably changed on purpose.
364 364 #
365 365 # Finally, the merge.applyupdates function will then take care of
366 366 # writing the files into the working copy and lfcommands.updatelfiles
367 367 # will update the largefiles.
368 368 def overridecalculateupdates(origfn, repo, p1, p2, pa, branchmerge, force,
369 369 partial, acceptremote=False):
370 370 overwrite = force and not branchmerge
371 371 actions = origfn(repo, p1, p2, pa, branchmerge, force, partial,
372 372 acceptremote)
373 373
374 374 if overwrite:
375 375 return actions
376 376
377 377 removes = set(a[0] for a in actions if a[1] == 'r')
378 378 processed = []
379 379
380 380 for action in actions:
381 381 f, m, args, msg = action
382 382
383 383 splitstandin = f and lfutil.splitstandin(f)
384 384 if (m == "g" and splitstandin is not None and
385 385 splitstandin in p1 and splitstandin not in removes):
386 386 # Case 1: normal file in the working copy, largefile in
387 387 # the second parent
388 388 lfile = splitstandin
389 389 standin = f
390 390 msg = _('remote turned local normal file %s into a largefile\n'
391 391 'use (l)argefile or keep (n)ormal file?'
392 392 '$$ &Largefile $$ &Normal file') % lfile
393 393 if repo.ui.promptchoice(msg, 0) == 0:
394 394 processed.append((lfile, "r", None, msg))
395 395 processed.append((standin, "g", (p2.flags(standin),), msg))
396 396 else:
397 397 processed.append((standin, "r", None, msg))
398 398 elif (m == "g" and
399 399 lfutil.standin(f) in p1 and lfutil.standin(f) not in removes):
400 400 # Case 2: largefile in the working copy, normal file in
401 401 # the second parent
402 402 standin = lfutil.standin(f)
403 403 lfile = f
404 404 msg = _('remote turned local largefile %s into a normal file\n'
405 405 'keep (l)argefile or use (n)ormal file?'
406 406 '$$ &Largefile $$ &Normal file') % lfile
407 407 if repo.ui.promptchoice(msg, 0) == 0:
408 408 processed.append((lfile, "r", None, msg))
409 409 else:
410 410 processed.append((standin, "r", None, msg))
411 411 processed.append((lfile, "g", (p2.flags(lfile),), msg))
412 412 else:
413 413 processed.append(action)
414 414
415 415 return processed
416 416
417 417 # Override filemerge to prompt the user about how they wish to merge
418 418 # largefiles. This will handle identical edits without prompting the user.
419 419 def overridefilemerge(origfn, repo, mynode, orig, fcd, fco, fca):
420 420 if not lfutil.isstandin(orig):
421 421 return origfn(repo, mynode, orig, fcd, fco, fca)
422 422
423 423 ahash = fca.data().strip().lower()
424 424 dhash = fcd.data().strip().lower()
425 425 ohash = fco.data().strip().lower()
426 426 if (ohash != ahash and
427 427 ohash != dhash and
428 428 (dhash == ahash or
429 429 repo.ui.promptchoice(
430 430 _('largefile %s has a merge conflict\nancestor was %s\n'
431 431 'keep (l)ocal %s or\ntake (o)ther %s?'
432 432 '$$ &Local $$ &Other') %
433 433 (lfutil.splitstandin(orig), ahash, dhash, ohash),
434 434 0) == 1)):
435 435 repo.wwrite(fcd.path(), fco.data(), fco.flags())
436 436 return 0
437 437
438 438 # Copy first changes the matchers to match standins instead of
439 439 # largefiles. Then it overrides util.copyfile in that function it
440 440 # checks if the destination largefile already exists. It also keeps a
441 441 # list of copied files so that the largefiles can be copied and the
442 442 # dirstate updated.
443 443 def overridecopy(orig, ui, repo, pats, opts, rename=False):
444 444 # doesn't remove largefile on rename
445 445 if len(pats) < 2:
446 446 # this isn't legal, let the original function deal with it
447 447 return orig(ui, repo, pats, opts, rename)
448 448
449 449 def makestandin(relpath):
450 450 path = pathutil.canonpath(repo.root, repo.getcwd(), relpath)
451 451 return os.path.join(repo.wjoin(lfutil.standin(path)))
452 452
453 453 fullpats = scmutil.expandpats(pats)
454 454 dest = fullpats[-1]
455 455
456 456 if os.path.isdir(dest):
457 457 if not os.path.isdir(makestandin(dest)):
458 458 os.makedirs(makestandin(dest))
459 459 # This could copy both lfiles and normal files in one command,
460 460 # but we don't want to do that. First replace their matcher to
461 461 # only match normal files and run it, then replace it to just
462 462 # match largefiles and run it again.
463 463 nonormalfiles = False
464 464 nolfiles = False
465 465 try:
466 466 try:
467 467 installnormalfilesmatchfn(repo[None].manifest())
468 468 result = orig(ui, repo, pats, opts, rename)
469 469 except util.Abort, e:
470 470 if str(e) != _('no files to copy'):
471 471 raise e
472 472 else:
473 473 nonormalfiles = True
474 474 result = 0
475 475 finally:
476 476 restorematchfn()
477 477
478 478 # The first rename can cause our current working directory to be removed.
479 479 # In that case there is nothing left to copy/rename so just quit.
480 480 try:
481 481 repo.getcwd()
482 482 except OSError:
483 483 return result
484 484
485 485 try:
486 486 try:
487 487 # When we call orig below it creates the standins but we don't add
488 488 # them to the dir state until later so lock during that time.
489 489 wlock = repo.wlock()
490 490
491 491 manifest = repo[None].manifest()
492 492 oldmatch = None # for the closure
493 493 def overridematch(ctx, pats=[], opts={}, globbed=False,
494 494 default='relpath'):
495 495 newpats = []
496 496 # The patterns were previously mangled to add the standin
497 497 # directory; we need to remove that now
498 498 for pat in pats:
499 499 if match_.patkind(pat) is None and lfutil.shortname in pat:
500 500 newpats.append(pat.replace(lfutil.shortname, ''))
501 501 else:
502 502 newpats.append(pat)
503 503 match = oldmatch(ctx, newpats, opts, globbed, default)
504 504 m = copy.copy(match)
505 505 lfile = lambda f: lfutil.standin(f) in manifest
506 506 m._files = [lfutil.standin(f) for f in m._files if lfile(f)]
507 507 m._fmap = set(m._files)
508 508 m._always = False
509 509 origmatchfn = m.matchfn
510 510 m.matchfn = lambda f: (lfutil.isstandin(f) and
511 511 (f in manifest) and
512 512 origmatchfn(lfutil.splitstandin(f)) or
513 513 None)
514 514 return m
515 515 oldmatch = installmatchfn(overridematch)
516 516 listpats = []
517 517 for pat in pats:
518 518 if match_.patkind(pat) is not None:
519 519 listpats.append(pat)
520 520 else:
521 521 listpats.append(makestandin(pat))
522 522
523 523 try:
524 524 origcopyfile = util.copyfile
525 525 copiedfiles = []
526 526 def overridecopyfile(src, dest):
527 527 if (lfutil.shortname in src and
528 528 dest.startswith(repo.wjoin(lfutil.shortname))):
529 529 destlfile = dest.replace(lfutil.shortname, '')
530 530 if not opts['force'] and os.path.exists(destlfile):
531 531 raise IOError('',
532 532 _('destination largefile already exists'))
533 533 copiedfiles.append((src, dest))
534 534 origcopyfile(src, dest)
535 535
536 536 util.copyfile = overridecopyfile
537 537 result += orig(ui, repo, listpats, opts, rename)
538 538 finally:
539 539 util.copyfile = origcopyfile
540 540
541 541 lfdirstate = lfutil.openlfdirstate(ui, repo)
542 542 for (src, dest) in copiedfiles:
543 543 if (lfutil.shortname in src and
544 544 dest.startswith(repo.wjoin(lfutil.shortname))):
545 545 srclfile = src.replace(repo.wjoin(lfutil.standin('')), '')
546 546 destlfile = dest.replace(repo.wjoin(lfutil.standin('')), '')
547 547 destlfiledir = os.path.dirname(repo.wjoin(destlfile)) or '.'
548 548 if not os.path.isdir(destlfiledir):
549 549 os.makedirs(destlfiledir)
550 550 if rename:
551 551 os.rename(repo.wjoin(srclfile), repo.wjoin(destlfile))
552 552 lfdirstate.remove(srclfile)
553 553 else:
554 554 util.copyfile(repo.wjoin(srclfile),
555 555 repo.wjoin(destlfile))
556 556
557 557 lfdirstate.add(destlfile)
558 558 lfdirstate.write()
559 559 except util.Abort, e:
560 560 if str(e) != _('no files to copy'):
561 561 raise e
562 562 else:
563 563 nolfiles = True
564 564 finally:
565 565 restorematchfn()
566 566 wlock.release()
567 567
568 568 if nolfiles and nonormalfiles:
569 569 raise util.Abort(_('no files to copy'))
570 570
571 571 return result
572 572
573 573 # When the user calls revert, we have to be careful to not revert any
574 574 # changes to other largefiles accidentally. This means we have to keep
575 575 # track of the largefiles that are being reverted so we only pull down
576 576 # the necessary largefiles.
577 577 #
578 578 # Standins are only updated (to match the hash of largefiles) before
579 579 # commits. Update the standins then run the original revert, changing
580 580 # the matcher to hit standins instead of largefiles. Based on the
581 581 # resulting standins update the largefiles. Then return the standins
582 582 # to their proper state
583 583 def overriderevert(orig, ui, repo, *pats, **opts):
584 584 # Because we put the standins in a bad state (by updating them)
585 585 # and then return them to a correct state we need to lock to
586 586 # prevent others from changing them in their incorrect state.
587 587 wlock = repo.wlock()
588 588 try:
589 589 lfdirstate = lfutil.openlfdirstate(ui, repo)
590 590 (modified, added, removed, missing, unknown, ignored, clean) = \
591 591 lfutil.lfdirstatestatus(lfdirstate, repo, repo['.'].rev())
592 592 lfdirstate.write()
593 593 for lfile in modified:
594 594 lfutil.updatestandin(repo, lfutil.standin(lfile))
595 595 for lfile in missing:
596 596 if (os.path.exists(repo.wjoin(lfutil.standin(lfile)))):
597 597 os.unlink(repo.wjoin(lfutil.standin(lfile)))
598 598
599 599 try:
600 600 ctx = scmutil.revsingle(repo, opts.get('rev'))
601 601 oldmatch = None # for the closure
602 602 def overridematch(ctx, pats=[], opts={}, globbed=False,
603 603 default='relpath'):
604 604 match = oldmatch(ctx, pats, opts, globbed, default)
605 605 m = copy.copy(match)
606 606 def tostandin(f):
607 607 if lfutil.standin(f) in ctx:
608 608 return lfutil.standin(f)
609 609 elif lfutil.standin(f) in repo[None]:
610 610 return None
611 611 return f
612 612 m._files = [tostandin(f) for f in m._files]
613 613 m._files = [f for f in m._files if f is not None]
614 614 m._fmap = set(m._files)
615 615 m._always = False
616 616 origmatchfn = m.matchfn
617 617 def matchfn(f):
618 618 if lfutil.isstandin(f):
619 619 # We need to keep track of what largefiles are being
620 620 # matched so we know which ones to update later --
621 621 # otherwise we accidentally revert changes to other
622 622 # largefiles. This is repo-specific, so duckpunch the
623 623 # repo object to keep the list of largefiles for us
624 624 # later.
625 625 if origmatchfn(lfutil.splitstandin(f)) and \
626 626 (f in repo[None] or f in ctx):
627 627 lfileslist = getattr(repo, '_lfilestoupdate', [])
628 628 lfileslist.append(lfutil.splitstandin(f))
629 629 repo._lfilestoupdate = lfileslist
630 630 return True
631 631 else:
632 632 return False
633 633 return origmatchfn(f)
634 634 m.matchfn = matchfn
635 635 return m
636 636 oldmatch = installmatchfn(overridematch)
637 637 scmutil.match
638 638 matches = overridematch(repo[None], pats, opts)
639 639 orig(ui, repo, *pats, **opts)
640 640 finally:
641 641 restorematchfn()
642 642 lfileslist = getattr(repo, '_lfilestoupdate', [])
643 643 lfcommands.updatelfiles(ui, repo, filelist=lfileslist,
644 644 printmessage=False)
645 645
646 646 # empty out the largefiles list so we start fresh next time
647 647 repo._lfilestoupdate = []
648 648 for lfile in modified:
649 649 if lfile in lfileslist:
650 650 if os.path.exists(repo.wjoin(lfutil.standin(lfile))) and lfile\
651 651 in repo['.']:
652 652 lfutil.writestandin(repo, lfutil.standin(lfile),
653 653 repo['.'][lfile].data().strip(),
654 654 'x' in repo['.'][lfile].flags())
655 655 lfdirstate = lfutil.openlfdirstate(ui, repo)
656 656 for lfile in added:
657 657 standin = lfutil.standin(lfile)
658 658 if standin not in ctx and (standin in matches or opts.get('all')):
659 659 if lfile in lfdirstate:
660 660 lfdirstate.drop(lfile)
661 661 util.unlinkpath(repo.wjoin(standin))
662 662 lfdirstate.write()
663 663 finally:
664 664 wlock.release()
665 665
666 666 def hgupdaterepo(orig, repo, node, overwrite):
667 667 if not overwrite:
668 668 # Only call updatelfiles on the standins that have changed to save time
669 669 oldstandins = lfutil.getstandinsstate(repo)
670 670
671 671 result = orig(repo, node, overwrite)
672 672
673 673 filelist = None
674 674 if not overwrite:
675 675 newstandins = lfutil.getstandinsstate(repo)
676 676 filelist = lfutil.getlfilestoupdate(oldstandins, newstandins)
677 677 lfcommands.updatelfiles(repo.ui, repo, filelist=filelist)
678 678 return result
679 679
680 680 def hgmerge(orig, repo, node, force=None, remind=True):
681 681 result = orig(repo, node, force, remind)
682 682 lfcommands.updatelfiles(repo.ui, repo)
683 683 return result
684 684
685 685 # When we rebase a repository with remotely changed largefiles, we need to
686 686 # take some extra care so that the largefiles are correctly updated in the
687 687 # working copy
688 688 def overridepull(orig, ui, repo, source=None, **opts):
689 689 revsprepull = len(repo)
690 690 if not source:
691 691 source = 'default'
692 692 repo.lfpullsource = source
693 693 if opts.get('rebase', False):
694 694 repo._isrebasing = True
695 695 try:
696 696 if opts.get('update'):
697 697 del opts['update']
698 698 ui.debug('--update and --rebase are not compatible, ignoring '
699 699 'the update flag\n')
700 700 del opts['rebase']
701 701 origpostincoming = commands.postincoming
702 702 def _dummy(*args, **kwargs):
703 703 pass
704 704 commands.postincoming = _dummy
705 705 try:
706 706 result = commands.pull(ui, repo, source, **opts)
707 707 finally:
708 708 commands.postincoming = origpostincoming
709 709 revspostpull = len(repo)
710 710 if revspostpull > revsprepull:
711 711 result = result or rebase.rebase(ui, repo)
712 712 finally:
713 713 repo._isrebasing = False
714 714 else:
715 715 result = orig(ui, repo, source, **opts)
716 716 revspostpull = len(repo)
717 717 lfrevs = opts.get('lfrev', [])
718 718 if opts.get('all_largefiles'):
719 719 lfrevs.append('pulled()')
720 720 if lfrevs and revspostpull > revsprepull:
721 721 numcached = 0
722 722 repo.firstpulled = revsprepull # for pulled() revset expression
723 723 try:
724 724 for rev in scmutil.revrange(repo, lfrevs):
725 725 ui.note(_('pulling largefiles for revision %s\n') % rev)
726 726 (cached, missing) = lfcommands.cachelfiles(ui, repo, rev)
727 727 numcached += len(cached)
728 728 finally:
729 729 del repo.firstpulled
730 730 ui.status(_("%d largefiles cached\n") % numcached)
731 731 return result
732 732
733 733 def pulledrevsetsymbol(repo, subset, x):
734 734 """``pulled()``
735 735 Changesets that just has been pulled.
736 736
737 737 Only available with largefiles from pull --lfrev expressions.
738 738
739 739 .. container:: verbose
740 740
741 741 Some examples:
742 742
743 743 - pull largefiles for all new changesets::
744 744
745 745 hg pull -lfrev "pulled()"
746 746
747 747 - pull largefiles for all new branch heads::
748 748
749 749 hg pull -lfrev "head(pulled()) and not closed()"
750 750
751 751 """
752 752
753 753 try:
754 754 firstpulled = repo.firstpulled
755 755 except AttributeError:
756 756 raise util.Abort(_("pulled() only available in --lfrev"))
757 757 return revset.baseset([r for r in subset if r >= firstpulled])
758 758
759 759 def overrideclone(orig, ui, source, dest=None, **opts):
760 760 d = dest
761 761 if d is None:
762 762 d = hg.defaultdest(source)
763 763 if opts.get('all_largefiles') and not hg.islocal(d):
764 764 raise util.Abort(_(
765 765 '--all-largefiles is incompatible with non-local destination %s' %
766 766 d))
767 767
768 768 return orig(ui, source, dest, **opts)
769 769
770 770 def hgclone(orig, ui, opts, *args, **kwargs):
771 771 result = orig(ui, opts, *args, **kwargs)
772 772
773 773 if result is not None:
774 774 sourcerepo, destrepo = result
775 775 repo = destrepo.local()
776 776
777 777 # Caching is implicitly limited to 'rev' option, since the dest repo was
778 778 # truncated at that point. The user may expect a download count with
779 779 # this option, so attempt whether or not this is a largefile repo.
780 780 if opts.get('all_largefiles'):
781 781 success, missing = lfcommands.downloadlfiles(ui, repo, None)
782 782
783 783 if missing != 0:
784 784 return None
785 785
786 786 return result
787 787
788 788 def overriderebase(orig, ui, repo, **opts):
789 789 repo._isrebasing = True
790 790 try:
791 791 return orig(ui, repo, **opts)
792 792 finally:
793 793 repo._isrebasing = False
794 794
795 795 def overridearchive(orig, repo, dest, node, kind, decode=True, matchfn=None,
796 796 prefix=None, mtime=None, subrepos=None):
797 797 # No need to lock because we are only reading history and
798 798 # largefile caches, neither of which are modified.
799 799 lfcommands.cachelfiles(repo.ui, repo, node)
800 800
801 801 if kind not in archival.archivers:
802 802 raise util.Abort(_("unknown archive type '%s'") % kind)
803 803
804 804 ctx = repo[node]
805 805
806 806 if kind == 'files':
807 807 if prefix:
808 808 raise util.Abort(
809 809 _('cannot give prefix when archiving to files'))
810 810 else:
811 811 prefix = archival.tidyprefix(dest, kind, prefix)
812 812
813 813 def write(name, mode, islink, getdata):
814 814 if matchfn and not matchfn(name):
815 815 return
816 816 data = getdata()
817 817 if decode:
818 818 data = repo.wwritedata(name, data)
819 819 archiver.addfile(prefix + name, mode, islink, data)
820 820
821 821 archiver = archival.archivers[kind](dest, mtime or ctx.date()[0])
822 822
823 823 if repo.ui.configbool("ui", "archivemeta", True):
824 824 def metadata():
825 825 base = 'repo: %s\nnode: %s\nbranch: %s\n' % (
826 826 hex(repo.changelog.node(0)), hex(node), ctx.branch())
827 827
828 828 tags = ''.join('tag: %s\n' % t for t in ctx.tags()
829 829 if repo.tagtype(t) == 'global')
830 830 if not tags:
831 831 repo.ui.pushbuffer()
832 832 opts = {'template': '{latesttag}\n{latesttagdistance}',
833 833 'style': '', 'patch': None, 'git': None}
834 834 cmdutil.show_changeset(repo.ui, repo, opts).show(ctx)
835 835 ltags, dist = repo.ui.popbuffer().split('\n')
836 836 tags = ''.join('latesttag: %s\n' % t for t in ltags.split(':'))
837 837 tags += 'latesttagdistance: %s\n' % dist
838 838
839 839 return base + tags
840 840
841 841 write('.hg_archival.txt', 0644, False, metadata)
842 842
843 843 for f in ctx:
844 844 ff = ctx.flags(f)
845 845 getdata = ctx[f].data
846 846 if lfutil.isstandin(f):
847 847 path = lfutil.findfile(repo, getdata().strip())
848 848 if path is None:
849 849 raise util.Abort(
850 850 _('largefile %s not found in repo store or system cache')
851 851 % lfutil.splitstandin(f))
852 852 f = lfutil.splitstandin(f)
853 853
854 854 def getdatafn():
855 855 fd = None
856 856 try:
857 857 fd = open(path, 'rb')
858 858 return fd.read()
859 859 finally:
860 860 if fd:
861 861 fd.close()
862 862
863 863 getdata = getdatafn
864 864 write(f, 'x' in ff and 0755 or 0644, 'l' in ff, getdata)
865 865
866 866 if subrepos:
867 867 for subpath in sorted(ctx.substate):
868 868 sub = ctx.sub(subpath)
869 869 submatch = match_.narrowmatcher(subpath, matchfn)
870 870 sub.archive(repo.ui, archiver, prefix, submatch)
871 871
872 872 archiver.done()
873 873
874 874 def hgsubrepoarchive(orig, repo, ui, archiver, prefix, match=None):
875 875 repo._get(repo._state + ('hg',))
876 876 rev = repo._state[1]
877 877 ctx = repo._repo[rev]
878 878
879 879 lfcommands.cachelfiles(ui, repo._repo, ctx.node())
880 880
881 881 def write(name, mode, islink, getdata):
882 882 # At this point, the standin has been replaced with the largefile name,
883 883 # so the normal matcher works here without the lfutil variants.
884 884 if match and not match(f):
885 885 return
886 886 data = getdata()
887 887
888 888 archiver.addfile(prefix + repo._path + '/' + name, mode, islink, data)
889 889
890 890 for f in ctx:
891 891 ff = ctx.flags(f)
892 892 getdata = ctx[f].data
893 893 if lfutil.isstandin(f):
894 894 path = lfutil.findfile(repo._repo, getdata().strip())
895 895 if path is None:
896 896 raise util.Abort(
897 897 _('largefile %s not found in repo store or system cache')
898 898 % lfutil.splitstandin(f))
899 899 f = lfutil.splitstandin(f)
900 900
901 901 def getdatafn():
902 902 fd = None
903 903 try:
904 904 fd = open(os.path.join(prefix, path), 'rb')
905 905 return fd.read()
906 906 finally:
907 907 if fd:
908 908 fd.close()
909 909
910 910 getdata = getdatafn
911 911
912 912 write(f, 'x' in ff and 0755 or 0644, 'l' in ff, getdata)
913 913
914 914 for subpath in sorted(ctx.substate):
915 915 sub = ctx.sub(subpath)
916 916 submatch = match_.narrowmatcher(subpath, match)
917 917 sub.archive(ui, archiver, os.path.join(prefix, repo._path) + '/',
918 918 submatch)
919 919
920 920 # If a largefile is modified, the change is not reflected in its
921 921 # standin until a commit. cmdutil.bailifchanged() raises an exception
922 922 # if the repo has uncommitted changes. Wrap it to also check if
923 923 # largefiles were changed. This is used by bisect and backout.
924 924 def overridebailifchanged(orig, repo):
925 925 orig(repo)
926 926 repo.lfstatus = True
927 927 modified, added, removed, deleted = repo.status()[:4]
928 928 repo.lfstatus = False
929 929 if modified or added or removed or deleted:
930 930 raise util.Abort(_('uncommitted changes'))
931 931
932 932 # Fetch doesn't use cmdutil.bailifchanged so override it to add the check
933 933 def overridefetch(orig, ui, repo, *pats, **opts):
934 934 repo.lfstatus = True
935 935 modified, added, removed, deleted = repo.status()[:4]
936 936 repo.lfstatus = False
937 937 if modified or added or removed or deleted:
938 938 raise util.Abort(_('uncommitted changes'))
939 939 return orig(ui, repo, *pats, **opts)
940 940
941 941 def overrideforget(orig, ui, repo, *pats, **opts):
942 942 installnormalfilesmatchfn(repo[None].manifest())
943 943 result = orig(ui, repo, *pats, **opts)
944 944 restorematchfn()
945 945 m = scmutil.match(repo[None], pats, opts)
946 946
947 947 try:
948 948 repo.lfstatus = True
949 949 s = repo.status(match=m, clean=True)
950 950 finally:
951 951 repo.lfstatus = False
952 952 forget = sorted(s[0] + s[1] + s[3] + s[6])
953 953 forget = [f for f in forget if lfutil.standin(f) in repo[None].manifest()]
954 954
955 955 for f in forget:
956 956 if lfutil.standin(f) not in repo.dirstate and not \
957 957 os.path.isdir(m.rel(lfutil.standin(f))):
958 958 ui.warn(_('not removing %s: file is already untracked\n')
959 959 % m.rel(f))
960 960 result = 1
961 961
962 962 for f in forget:
963 963 if ui.verbose or not m.exact(f):
964 964 ui.status(_('removing %s\n') % m.rel(f))
965 965
966 966 # Need to lock because standin files are deleted then removed from the
967 967 # repository and we could race in-between.
968 968 wlock = repo.wlock()
969 969 try:
970 970 lfdirstate = lfutil.openlfdirstate(ui, repo)
971 971 for f in forget:
972 972 if lfdirstate[f] == 'a':
973 973 lfdirstate.drop(f)
974 974 else:
975 975 lfdirstate.remove(f)
976 976 lfdirstate.write()
977 977 standins = [lfutil.standin(f) for f in forget]
978 978 for f in standins:
979 979 util.unlinkpath(repo.wjoin(f), ignoremissing=True)
980 980 repo[None].forget(standins)
981 981 finally:
982 982 wlock.release()
983 983
984 984 return result
985 985
986 986 def getoutgoinglfiles(ui, repo, dest=None, **opts):
987 987 dest = ui.expandpath(dest or 'default-push', dest or 'default')
988 988 dest, branches = hg.parseurl(dest, opts.get('branch'))
989 989 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
990 990 if revs:
991 991 revs = [repo.lookup(rev) for rev in scmutil.revrange(repo, revs)]
992 992
993 993 try:
994 994 remote = hg.peer(repo, opts, dest)
995 995 except error.RepoError:
996 996 return None
997 997 outgoing = discovery.findcommonoutgoing(repo, remote.peer(), force=False)
998 998 if not outgoing.missing:
999 999 return outgoing.missing
1000 1000 o = repo.changelog.nodesbetween(outgoing.missing, revs)[0]
1001 1001 if opts.get('newest_first'):
1002 1002 o.reverse()
1003 1003
1004 1004 toupload = set()
1005 1005 lfutil.getlfilestoupload(repo, o, lambda fn, lfhash: toupload.add(fn))
1006 1006 return sorted(toupload)
1007 1007
1008 1008 def overrideoutgoing(orig, ui, repo, dest=None, **opts):
1009 1009 result = orig(ui, repo, dest, **opts)
1010 1010
1011 1011 if opts.pop('large', None):
1012 1012 toupload = getoutgoinglfiles(ui, repo, dest, **opts)
1013 1013 if toupload is None:
1014 1014 ui.status(_('largefiles: No remote repo\n'))
1015 1015 elif not toupload:
1016 1016 ui.status(_('largefiles: no files to upload\n'))
1017 1017 else:
1018 1018 ui.status(_('largefiles to upload:\n'))
1019 1019 for file in toupload:
1020 1020 ui.status(lfutil.splitstandin(file) + '\n')
1021 1021 ui.status('\n')
1022 1022
1023 1023 return result
1024 1024
1025 def summaryremotehook(ui, repo, opts, changes):
1026 largeopt = opts.get('large', False)
1027 if changes is None:
1028 if largeopt:
1029 return (False, True) # only outgoing check is needed
1030 else:
1031 return (False, False)
1032 elif largeopt:
1033 url, branch, peer, outgoing = changes[1]
1034 if peer is None:
1035 # i18n: column positioning for "hg summary"
1036 ui.status(_('largefiles: (no remote repo)\n'))
1037 return
1038
1039 toupload = set()
1040 lfutil.getlfilestoupload(repo, outgoing.missing,
1041 lambda fn, lfhash: toupload.add(fn))
1042 if not toupload:
1043 # i18n: column positioning for "hg summary"
1044 ui.status(_('largefiles: (no files to upload)\n'))
1045 else:
1046 # i18n: column positioning for "hg summary"
1047 ui.status(_('largefiles: %d to upload\n') % len(toupload))
1048
1025 1049 def overridesummary(orig, ui, repo, *pats, **opts):
1026 1050 try:
1027 1051 repo.lfstatus = True
1028 1052 orig(ui, repo, *pats, **opts)
1029 1053 finally:
1030 1054 repo.lfstatus = False
1031 1055
1032 if opts.pop('large', None):
1033 toupload = getoutgoinglfiles(ui, repo, None, **opts)
1034 if toupload is None:
1035 # i18n: column positioning for "hg summary"
1036 ui.status(_('largefiles: (no remote repo)\n'))
1037 elif not toupload:
1038 # i18n: column positioning for "hg summary"
1039 ui.status(_('largefiles: (no files to upload)\n'))
1040 else:
1041 # i18n: column positioning for "hg summary"
1042 ui.status(_('largefiles: %d to upload\n') % len(toupload))
1043
1044 1056 def scmutiladdremove(orig, repo, pats=[], opts={}, dry_run=None,
1045 1057 similarity=None):
1046 1058 if not lfutil.islfilesrepo(repo):
1047 1059 return orig(repo, pats, opts, dry_run, similarity)
1048 1060 # Get the list of missing largefiles so we can remove them
1049 1061 lfdirstate = lfutil.openlfdirstate(repo.ui, repo)
1050 1062 s = lfdirstate.status(match_.always(repo.root, repo.getcwd()), [], False,
1051 1063 False, False)
1052 1064 (unsure, modified, added, removed, missing, unknown, ignored, clean) = s
1053 1065
1054 1066 # Call into the normal remove code, but the removing of the standin, we want
1055 1067 # to have handled by original addremove. Monkey patching here makes sure
1056 1068 # we don't remove the standin in the largefiles code, preventing a very
1057 1069 # confused state later.
1058 1070 if missing:
1059 1071 m = [repo.wjoin(f) for f in missing]
1060 1072 repo._isaddremove = True
1061 1073 removelargefiles(repo.ui, repo, *m, **opts)
1062 1074 repo._isaddremove = False
1063 1075 # Call into the normal add code, and any files that *should* be added as
1064 1076 # largefiles will be
1065 1077 addlargefiles(repo.ui, repo, *pats, **opts)
1066 1078 # Now that we've handled largefiles, hand off to the original addremove
1067 1079 # function to take care of the rest. Make sure it doesn't do anything with
1068 1080 # largefiles by installing a matcher that will ignore them.
1069 1081 installnormalfilesmatchfn(repo[None].manifest())
1070 1082 result = orig(repo, pats, opts, dry_run, similarity)
1071 1083 restorematchfn()
1072 1084 return result
1073 1085
1074 1086 # Calling purge with --all will cause the largefiles to be deleted.
1075 1087 # Override repo.status to prevent this from happening.
1076 1088 def overridepurge(orig, ui, repo, *dirs, **opts):
1077 1089 # XXX large file status is buggy when used on repo proxy.
1078 1090 # XXX this needs to be investigate.
1079 1091 repo = repo.unfiltered()
1080 1092 oldstatus = repo.status
1081 1093 def overridestatus(node1='.', node2=None, match=None, ignored=False,
1082 1094 clean=False, unknown=False, listsubrepos=False):
1083 1095 r = oldstatus(node1, node2, match, ignored, clean, unknown,
1084 1096 listsubrepos)
1085 1097 lfdirstate = lfutil.openlfdirstate(ui, repo)
1086 1098 modified, added, removed, deleted, unknown, ignored, clean = r
1087 1099 unknown = [f for f in unknown if lfdirstate[f] == '?']
1088 1100 ignored = [f for f in ignored if lfdirstate[f] == '?']
1089 1101 return modified, added, removed, deleted, unknown, ignored, clean
1090 1102 repo.status = overridestatus
1091 1103 orig(ui, repo, *dirs, **opts)
1092 1104 repo.status = oldstatus
1093 1105
1094 1106 def overriderollback(orig, ui, repo, **opts):
1095 1107 result = orig(ui, repo, **opts)
1096 1108 merge.update(repo, node=None, branchmerge=False, force=True,
1097 1109 partial=lfutil.isstandin)
1098 1110 wlock = repo.wlock()
1099 1111 try:
1100 1112 lfdirstate = lfutil.openlfdirstate(ui, repo)
1101 1113 lfiles = lfutil.listlfiles(repo)
1102 1114 oldlfiles = lfutil.listlfiles(repo, repo[None].parents()[0].rev())
1103 1115 for file in lfiles:
1104 1116 if file in oldlfiles:
1105 1117 lfdirstate.normallookup(file)
1106 1118 else:
1107 1119 lfdirstate.add(file)
1108 1120 lfdirstate.write()
1109 1121 finally:
1110 1122 wlock.release()
1111 1123 return result
1112 1124
1113 1125 def overridetransplant(orig, ui, repo, *revs, **opts):
1114 1126 try:
1115 1127 oldstandins = lfutil.getstandinsstate(repo)
1116 1128 repo._istransplanting = True
1117 1129 result = orig(ui, repo, *revs, **opts)
1118 1130 newstandins = lfutil.getstandinsstate(repo)
1119 1131 filelist = lfutil.getlfilestoupdate(oldstandins, newstandins)
1120 1132 lfcommands.updatelfiles(repo.ui, repo, filelist=filelist,
1121 1133 printmessage=True)
1122 1134 finally:
1123 1135 repo._istransplanting = False
1124 1136 return result
1125 1137
1126 1138 def overridecat(orig, ui, repo, file1, *pats, **opts):
1127 1139 ctx = scmutil.revsingle(repo, opts.get('rev'))
1128 1140 err = 1
1129 1141 notbad = set()
1130 1142 m = scmutil.match(ctx, (file1,) + pats, opts)
1131 1143 origmatchfn = m.matchfn
1132 1144 def lfmatchfn(f):
1133 1145 lf = lfutil.splitstandin(f)
1134 1146 if lf is None:
1135 1147 return origmatchfn(f)
1136 1148 notbad.add(lf)
1137 1149 return origmatchfn(lf)
1138 1150 m.matchfn = lfmatchfn
1139 1151 origbadfn = m.bad
1140 1152 def lfbadfn(f, msg):
1141 1153 if not f in notbad:
1142 1154 return origbadfn(f, msg)
1143 1155 m.bad = lfbadfn
1144 1156 for f in ctx.walk(m):
1145 1157 fp = cmdutil.makefileobj(repo, opts.get('output'), ctx.node(),
1146 1158 pathname=f)
1147 1159 lf = lfutil.splitstandin(f)
1148 1160 if lf is None:
1149 1161 # duplicating unreachable code from commands.cat
1150 1162 data = ctx[f].data()
1151 1163 if opts.get('decode'):
1152 1164 data = repo.wwritedata(f, data)
1153 1165 fp.write(data)
1154 1166 else:
1155 1167 hash = lfutil.readstandin(repo, lf, ctx.rev())
1156 1168 if not lfutil.inusercache(repo.ui, hash):
1157 1169 store = basestore._openstore(repo)
1158 1170 success, missing = store.get([(lf, hash)])
1159 1171 if len(success) != 1:
1160 1172 raise util.Abort(
1161 1173 _('largefile %s is not in cache and could not be '
1162 1174 'downloaded') % lf)
1163 1175 path = lfutil.usercachepath(repo.ui, hash)
1164 1176 fpin = open(path, "rb")
1165 1177 for chunk in util.filechunkiter(fpin, 128 * 1024):
1166 1178 fp.write(chunk)
1167 1179 fpin.close()
1168 1180 fp.close()
1169 1181 err = 0
1170 1182 return err
1171 1183
1172 1184 def mercurialsinkbefore(orig, sink):
1173 1185 sink.repo._isconverting = True
1174 1186 orig(sink)
1175 1187
1176 1188 def mercurialsinkafter(orig, sink):
1177 1189 sink.repo._isconverting = False
1178 1190 orig(sink)
@@ -1,175 +1,176 b''
1 1 # Copyright 2009-2010 Gregory P. Ward
2 2 # Copyright 2009-2010 Intelerad Medical Systems Incorporated
3 3 # Copyright 2010-2011 Fog Creek Software
4 4 # Copyright 2010-2011 Unity Technologies
5 5 #
6 6 # This software may be used and distributed according to the terms of the
7 7 # GNU General Public License version 2 or any later version.
8 8
9 9 '''setup for largefiles extension: uisetup'''
10 10
11 11 from mercurial import archival, cmdutil, commands, extensions, filemerge, hg, \
12 12 httppeer, merge, scmutil, sshpeer, wireproto, revset
13 13 from mercurial.i18n import _
14 14 from mercurial.hgweb import hgweb_mod, webcommands
15 15 from mercurial.subrepo import hgsubrepo
16 16
17 17 import overrides
18 18 import proto
19 19
20 20 def uisetup(ui):
21 21 # Disable auto-status for some commands which assume that all
22 22 # files in the result are under Mercurial's control
23 23
24 24 entry = extensions.wrapcommand(commands.table, 'add',
25 25 overrides.overrideadd)
26 26 addopt = [('', 'large', None, _('add as largefile')),
27 27 ('', 'normal', None, _('add as normal file')),
28 28 ('', 'lfsize', '', _('add all files above this size '
29 29 '(in megabytes) as largefiles '
30 30 '(default: 10)'))]
31 31 entry[1].extend(addopt)
32 32
33 33 # The scmutil function is called both by the (trivial) addremove command,
34 34 # and in the process of handling commit -A (issue3542)
35 35 entry = extensions.wrapfunction(scmutil, 'addremove',
36 36 overrides.scmutiladdremove)
37 37 entry = extensions.wrapcommand(commands.table, 'remove',
38 38 overrides.overrideremove)
39 39 entry = extensions.wrapcommand(commands.table, 'forget',
40 40 overrides.overrideforget)
41 41
42 42 # Subrepos call status function
43 43 entry = extensions.wrapcommand(commands.table, 'status',
44 44 overrides.overridestatus)
45 45 entry = extensions.wrapfunction(hgsubrepo, 'status',
46 46 overrides.overridestatusfn)
47 47
48 48 entry = extensions.wrapcommand(commands.table, 'log',
49 49 overrides.overridelog)
50 50 entry = extensions.wrapcommand(commands.table, 'rollback',
51 51 overrides.overriderollback)
52 52 entry = extensions.wrapcommand(commands.table, 'verify',
53 53 overrides.overrideverify)
54 54
55 55 verifyopt = [('', 'large', None,
56 56 _('verify that all largefiles in current revision exists')),
57 57 ('', 'lfa', None,
58 58 _('verify largefiles in all revisions, not just current')),
59 59 ('', 'lfc', None,
60 60 _('verify local largefile contents, not just existence'))]
61 61 entry[1].extend(verifyopt)
62 62
63 63 entry = extensions.wrapcommand(commands.table, 'debugstate',
64 64 overrides.overridedebugstate)
65 65 debugstateopt = [('', 'large', None, _('display largefiles dirstate'))]
66 66 entry[1].extend(debugstateopt)
67 67
68 68 entry = extensions.wrapcommand(commands.table, 'outgoing',
69 69 overrides.overrideoutgoing)
70 70 outgoingopt = [('', 'large', None, _('display outgoing largefiles'))]
71 71 entry[1].extend(outgoingopt)
72 72 entry = extensions.wrapcommand(commands.table, 'summary',
73 73 overrides.overridesummary)
74 74 summaryopt = [('', 'large', None, _('display outgoing largefiles'))]
75 75 entry[1].extend(summaryopt)
76 cmdutil.summaryremotehooks.add('largefiles', overrides.summaryremotehook)
76 77
77 78 entry = extensions.wrapcommand(commands.table, 'update',
78 79 overrides.overrideupdate)
79 80 entry = extensions.wrapcommand(commands.table, 'pull',
80 81 overrides.overridepull)
81 82 pullopt = [('', 'all-largefiles', None,
82 83 _('download all pulled versions of largefiles (DEPRECATED)')),
83 84 ('', 'lfrev', [],
84 85 _('download largefiles for these revisions'), _('REV'))]
85 86 entry[1].extend(pullopt)
86 87 revset.symbols['pulled'] = overrides.pulledrevsetsymbol
87 88
88 89 entry = extensions.wrapcommand(commands.table, 'clone',
89 90 overrides.overrideclone)
90 91 cloneopt = [('', 'all-largefiles', None,
91 92 _('download all versions of all largefiles'))]
92 93 entry[1].extend(cloneopt)
93 94 entry = extensions.wrapfunction(hg, 'clone', overrides.hgclone)
94 95
95 96 entry = extensions.wrapcommand(commands.table, 'cat',
96 97 overrides.overridecat)
97 98 entry = extensions.wrapfunction(merge, '_checkunknownfile',
98 99 overrides.overridecheckunknownfile)
99 100 entry = extensions.wrapfunction(merge, 'calculateupdates',
100 101 overrides.overridecalculateupdates)
101 102 entry = extensions.wrapfunction(filemerge, 'filemerge',
102 103 overrides.overridefilemerge)
103 104 entry = extensions.wrapfunction(cmdutil, 'copy',
104 105 overrides.overridecopy)
105 106
106 107 # Summary calls dirty on the subrepos
107 108 entry = extensions.wrapfunction(hgsubrepo, 'dirty',
108 109 overrides.overridedirty)
109 110
110 111 # Backout calls revert so we need to override both the command and the
111 112 # function
112 113 entry = extensions.wrapcommand(commands.table, 'revert',
113 114 overrides.overriderevert)
114 115 entry = extensions.wrapfunction(commands, 'revert',
115 116 overrides.overriderevert)
116 117
117 118 extensions.wrapfunction(hg, 'updaterepo', overrides.hgupdaterepo)
118 119 extensions.wrapfunction(hg, 'merge', overrides.hgmerge)
119 120
120 121 extensions.wrapfunction(archival, 'archive', overrides.overridearchive)
121 122 extensions.wrapfunction(hgsubrepo, 'archive', overrides.hgsubrepoarchive)
122 123 extensions.wrapfunction(cmdutil, 'bailifchanged',
123 124 overrides.overridebailifchanged)
124 125
125 126 # create the new wireproto commands ...
126 127 wireproto.commands['putlfile'] = (proto.putlfile, 'sha')
127 128 wireproto.commands['getlfile'] = (proto.getlfile, 'sha')
128 129 wireproto.commands['statlfile'] = (proto.statlfile, 'sha')
129 130
130 131 # ... and wrap some existing ones
131 132 wireproto.commands['capabilities'] = (proto.capabilities, '')
132 133 wireproto.commands['heads'] = (proto.heads, '')
133 134 wireproto.commands['lheads'] = (wireproto.heads, '')
134 135
135 136 # make putlfile behave the same as push and {get,stat}lfile behave
136 137 # the same as pull w.r.t. permissions checks
137 138 hgweb_mod.perms['putlfile'] = 'push'
138 139 hgweb_mod.perms['getlfile'] = 'pull'
139 140 hgweb_mod.perms['statlfile'] = 'pull'
140 141
141 142 extensions.wrapfunction(webcommands, 'decodepath', overrides.decodepath)
142 143
143 144 # the hello wireproto command uses wireproto.capabilities, so it won't see
144 145 # our largefiles capability unless we replace the actual function as well.
145 146 proto.capabilitiesorig = wireproto.capabilities
146 147 wireproto.capabilities = proto.capabilities
147 148
148 149 # can't do this in reposetup because it needs to have happened before
149 150 # wirerepo.__init__ is called
150 151 proto.ssholdcallstream = sshpeer.sshpeer._callstream
151 152 proto.httpoldcallstream = httppeer.httppeer._callstream
152 153 sshpeer.sshpeer._callstream = proto.sshrepocallstream
153 154 httppeer.httppeer._callstream = proto.httprepocallstream
154 155
155 156 # override some extensions' stuff as well
156 157 for name, module in extensions.extensions():
157 158 if name == 'fetch':
158 159 extensions.wrapcommand(getattr(module, 'cmdtable'), 'fetch',
159 160 overrides.overridefetch)
160 161 if name == 'purge':
161 162 extensions.wrapcommand(getattr(module, 'cmdtable'), 'purge',
162 163 overrides.overridepurge)
163 164 if name == 'rebase':
164 165 extensions.wrapcommand(getattr(module, 'cmdtable'), 'rebase',
165 166 overrides.overriderebase)
166 167 if name == 'transplant':
167 168 extensions.wrapcommand(getattr(module, 'cmdtable'), 'transplant',
168 169 overrides.overridetransplant)
169 170 if name == 'convert':
170 171 convcmd = getattr(module, 'convcmd')
171 172 hgsink = getattr(convcmd, 'mercurial_sink')
172 173 extensions.wrapfunction(hgsink, 'before',
173 174 overrides.mercurialsinkbefore)
174 175 extensions.wrapfunction(hgsink, 'after',
175 176 overrides.mercurialsinkafter)
@@ -1,2386 +1,2384 b''
1 1 $ USERCACHE="$TESTTMP/cache"; export USERCACHE
2 2 $ mkdir "${USERCACHE}"
3 3 $ cat >> $HGRCPATH <<EOF
4 4 > [extensions]
5 5 > largefiles=
6 6 > purge=
7 7 > rebase=
8 8 > transplant=
9 9 > [phases]
10 10 > publish=False
11 11 > [largefiles]
12 12 > minsize=2
13 13 > patterns=glob:**.dat
14 14 > usercache=${USERCACHE}
15 15 > [hooks]
16 16 > precommit=sh -c "echo \\"Invoking status precommit hook\\"; hg status"
17 17 > EOF
18 18
19 19 Create the repo with a couple of revisions of both large and normal
20 20 files.
21 21 Test status and dirstate of largefiles and that summary output is correct.
22 22
23 23 $ hg init a
24 24 $ cd a
25 25 $ mkdir sub
26 26 $ echo normal1 > normal1
27 27 $ echo normal2 > sub/normal2
28 28 $ echo large1 > large1
29 29 $ echo large2 > sub/large2
30 30 $ hg add normal1 sub/normal2
31 31 $ hg add --large large1 sub/large2
32 32 $ hg commit -m "add files"
33 33 Invoking status precommit hook
34 34 A large1
35 35 A normal1
36 36 A sub/large2
37 37 A sub/normal2
38 38 $ touch large1 sub/large2
39 39 $ sleep 1
40 40 $ hg st
41 41 $ hg debugstate --nodates
42 42 n 644 41 .hglf/large1
43 43 n 644 41 .hglf/sub/large2
44 44 n 644 8 normal1
45 45 n 644 8 sub/normal2
46 46 $ hg debugstate --large
47 47 n 644 7 large1
48 48 n 644 7 sub/large2
49 49 $ echo normal11 > normal1
50 50 $ echo normal22 > sub/normal2
51 51 $ echo large11 > large1
52 52 $ echo large22 > sub/large2
53 53 $ hg commit -m "edit files"
54 54 Invoking status precommit hook
55 55 M large1
56 56 M normal1
57 57 M sub/large2
58 58 M sub/normal2
59 59 $ hg sum --large
60 60 parent: 1:ce8896473775 tip
61 61 edit files
62 62 branch: default
63 63 commit: (clean)
64 64 update: (current)
65 65 largefiles: (no remote repo)
66 66
67 67 Commit preserved largefile contents.
68 68
69 69 $ cat normal1
70 70 normal11
71 71 $ cat large1
72 72 large11
73 73 $ cat sub/normal2
74 74 normal22
75 75 $ cat sub/large2
76 76 large22
77 77
78 78 Test status, subdir and unknown files
79 79
80 80 $ echo unknown > sub/unknown
81 81 $ hg st --all
82 82 ? sub/unknown
83 83 C large1
84 84 C normal1
85 85 C sub/large2
86 86 C sub/normal2
87 87 $ hg st --all sub
88 88 ? sub/unknown
89 89 C sub/large2
90 90 C sub/normal2
91 91 $ rm sub/unknown
92 92
93 93 Test messages and exit codes for remove warning cases
94 94
95 95 $ hg remove -A large1
96 96 not removing large1: file still exists
97 97 [1]
98 98 $ echo 'modified' > large1
99 99 $ hg remove large1
100 100 not removing large1: file is modified (use -f to force removal)
101 101 [1]
102 102 $ echo 'new' > normalnew
103 103 $ hg add normalnew
104 104 $ echo 'new' > largenew
105 105 $ hg add --large normalnew
106 106 normalnew already tracked!
107 107 $ hg remove normalnew largenew
108 108 not removing largenew: file is untracked
109 109 not removing normalnew: file has been marked for add (use forget to undo)
110 110 [1]
111 111 $ rm normalnew largenew
112 112 $ hg up -Cq
113 113
114 114 Remove both largefiles and normal files.
115 115
116 116 $ hg remove normal1 large1
117 117 $ hg status large1
118 118 R large1
119 119 $ hg commit -m "remove files"
120 120 Invoking status precommit hook
121 121 R large1
122 122 R normal1
123 123 $ ls
124 124 sub
125 125 $ echo "testlargefile" > large1-test
126 126 $ hg add --large large1-test
127 127 $ hg st
128 128 A large1-test
129 129 $ hg rm large1-test
130 130 not removing large1-test: file has been marked for add (use forget to undo)
131 131 [1]
132 132 $ hg st
133 133 A large1-test
134 134 $ hg forget large1-test
135 135 $ hg st
136 136 ? large1-test
137 137 $ hg remove large1-test
138 138 not removing large1-test: file is untracked
139 139 [1]
140 140 $ hg forget large1-test
141 141 not removing large1-test: file is already untracked
142 142 [1]
143 143 $ rm large1-test
144 144
145 145 Copy both largefiles and normal files (testing that status output is correct).
146 146
147 147 $ hg cp sub/normal2 normal1
148 148 $ hg cp sub/large2 large1
149 149 $ hg commit -m "copy files"
150 150 Invoking status precommit hook
151 151 A large1
152 152 A normal1
153 153 $ cat normal1
154 154 normal22
155 155 $ cat large1
156 156 large22
157 157
158 158 Test moving largefiles and verify that normal files are also unaffected.
159 159
160 160 $ hg mv normal1 normal3
161 161 $ hg mv large1 large3
162 162 $ hg mv sub/normal2 sub/normal4
163 163 $ hg mv sub/large2 sub/large4
164 164 $ hg commit -m "move files"
165 165 Invoking status precommit hook
166 166 A large3
167 167 A normal3
168 168 A sub/large4
169 169 A sub/normal4
170 170 R large1
171 171 R normal1
172 172 R sub/large2
173 173 R sub/normal2
174 174 $ cat normal3
175 175 normal22
176 176 $ cat large3
177 177 large22
178 178 $ cat sub/normal4
179 179 normal22
180 180 $ cat sub/large4
181 181 large22
182 182
183 183 Test copies and moves from a directory other than root (issue3516)
184 184
185 185 $ cd ..
186 186 $ hg init lf_cpmv
187 187 $ cd lf_cpmv
188 188 $ mkdir dira
189 189 $ mkdir dira/dirb
190 190 $ touch dira/dirb/largefile
191 191 $ hg add --large dira/dirb/largefile
192 192 $ hg commit -m "added"
193 193 Invoking status precommit hook
194 194 A dira/dirb/largefile
195 195 $ cd dira
196 196 $ hg cp dirb/largefile foo/largefile
197 197 $ hg ci -m "deep copy"
198 198 Invoking status precommit hook
199 199 A dira/foo/largefile
200 200 $ find . | sort
201 201 .
202 202 ./dirb
203 203 ./dirb/largefile
204 204 ./foo
205 205 ./foo/largefile
206 206 $ hg mv foo/largefile baz/largefile
207 207 $ hg ci -m "moved"
208 208 Invoking status precommit hook
209 209 A dira/baz/largefile
210 210 R dira/foo/largefile
211 211 $ find . | sort
212 212 .
213 213 ./baz
214 214 ./baz/largefile
215 215 ./dirb
216 216 ./dirb/largefile
217 217 ./foo
218 218 $ cd ../../a
219 219
220 220 #if serve
221 221 Test display of largefiles in hgweb
222 222
223 223 $ hg serve -d -p $HGPORT --pid-file ../hg.pid
224 224 $ cat ../hg.pid >> $DAEMON_PIDS
225 225 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT 'file/tip/?style=raw'
226 226 200 Script output follows
227 227
228 228
229 229 drwxr-xr-x sub
230 230 -rw-r--r-- 41 large3
231 231 -rw-r--r-- 9 normal3
232 232
233 233
234 234 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT 'file/tip/sub/?style=raw'
235 235 200 Script output follows
236 236
237 237
238 238 -rw-r--r-- 41 large4
239 239 -rw-r--r-- 9 normal4
240 240
241 241
242 242 $ "$TESTDIR/killdaemons.py" $DAEMON_PIDS
243 243 #endif
244 244
245 245 Test archiving the various revisions. These hit corner cases known with
246 246 archiving.
247 247
248 248 $ hg archive -r 0 ../archive0
249 249 $ hg archive -r 1 ../archive1
250 250 $ hg archive -r 2 ../archive2
251 251 $ hg archive -r 3 ../archive3
252 252 $ hg archive -r 4 ../archive4
253 253 $ cd ../archive0
254 254 $ cat normal1
255 255 normal1
256 256 $ cat large1
257 257 large1
258 258 $ cat sub/normal2
259 259 normal2
260 260 $ cat sub/large2
261 261 large2
262 262 $ cd ../archive1
263 263 $ cat normal1
264 264 normal11
265 265 $ cat large1
266 266 large11
267 267 $ cat sub/normal2
268 268 normal22
269 269 $ cat sub/large2
270 270 large22
271 271 $ cd ../archive2
272 272 $ ls
273 273 sub
274 274 $ cat sub/normal2
275 275 normal22
276 276 $ cat sub/large2
277 277 large22
278 278 $ cd ../archive3
279 279 $ cat normal1
280 280 normal22
281 281 $ cat large1
282 282 large22
283 283 $ cat sub/normal2
284 284 normal22
285 285 $ cat sub/large2
286 286 large22
287 287 $ cd ../archive4
288 288 $ cat normal3
289 289 normal22
290 290 $ cat large3
291 291 large22
292 292 $ cat sub/normal4
293 293 normal22
294 294 $ cat sub/large4
295 295 large22
296 296
297 297 Commit corner case: specify files to commit.
298 298
299 299 $ cd ../a
300 300 $ echo normal3 > normal3
301 301 $ echo large3 > large3
302 302 $ echo normal4 > sub/normal4
303 303 $ echo large4 > sub/large4
304 304 $ hg commit normal3 large3 sub/normal4 sub/large4 -m "edit files again"
305 305 Invoking status precommit hook
306 306 M large3
307 307 M normal3
308 308 M sub/large4
309 309 M sub/normal4
310 310 $ cat normal3
311 311 normal3
312 312 $ cat large3
313 313 large3
314 314 $ cat sub/normal4
315 315 normal4
316 316 $ cat sub/large4
317 317 large4
318 318
319 319 One more commit corner case: commit from a subdirectory.
320 320
321 321 $ cd ../a
322 322 $ echo normal33 > normal3
323 323 $ echo large33 > large3
324 324 $ echo normal44 > sub/normal4
325 325 $ echo large44 > sub/large4
326 326 $ cd sub
327 327 $ hg commit -m "edit files yet again"
328 328 Invoking status precommit hook
329 329 M large3
330 330 M normal3
331 331 M sub/large4
332 332 M sub/normal4
333 333 $ cat ../normal3
334 334 normal33
335 335 $ cat ../large3
336 336 large33
337 337 $ cat normal4
338 338 normal44
339 339 $ cat large4
340 340 large44
341 341
342 342 Committing standins is not allowed.
343 343
344 344 $ cd ..
345 345 $ echo large3 > large3
346 346 $ hg commit .hglf/large3 -m "try to commit standin"
347 347 abort: file ".hglf/large3" is a largefile standin
348 348 (commit the largefile itself instead)
349 349 [255]
350 350
351 351 Corner cases for adding largefiles.
352 352
353 353 $ echo large5 > large5
354 354 $ hg add --large large5
355 355 $ hg add --large large5
356 356 large5 already a largefile
357 357 $ mkdir sub2
358 358 $ echo large6 > sub2/large6
359 359 $ echo large7 > sub2/large7
360 360 $ hg add --large sub2
361 361 adding sub2/large6 as a largefile (glob)
362 362 adding sub2/large7 as a largefile (glob)
363 363 $ hg st
364 364 M large3
365 365 A large5
366 366 A sub2/large6
367 367 A sub2/large7
368 368
369 369 Committing directories containing only largefiles.
370 370
371 371 $ mkdir -p z/y/x/m
372 372 $ touch z/y/x/m/large1
373 373 $ touch z/y/x/large2
374 374 $ hg add --large z/y/x/m/large1 z/y/x/large2
375 375 $ hg commit -m "Subdir with directory only containing largefiles" z
376 376 Invoking status precommit hook
377 377 M large3
378 378 A large5
379 379 A sub2/large6
380 380 A sub2/large7
381 381 A z/y/x/large2
382 382 A z/y/x/m/large1
383 383 $ hg rollback --quiet
384 384 $ touch z/y/x/m/normal
385 385 $ hg add z/y/x/m/normal
386 386 $ hg commit -m "Subdir with mixed contents" z
387 387 Invoking status precommit hook
388 388 M large3
389 389 A large5
390 390 A sub2/large6
391 391 A sub2/large7
392 392 A z/y/x/large2
393 393 A z/y/x/m/large1
394 394 A z/y/x/m/normal
395 395 $ hg st
396 396 M large3
397 397 A large5
398 398 A sub2/large6
399 399 A sub2/large7
400 400 $ hg rollback --quiet
401 401 $ hg revert z/y/x/large2 z/y/x/m/large1
402 402 $ rm z/y/x/large2 z/y/x/m/large1
403 403 $ hg commit -m "Subdir with normal contents" z
404 404 Invoking status precommit hook
405 405 M large3
406 406 A large5
407 407 A sub2/large6
408 408 A sub2/large7
409 409 A z/y/x/m/normal
410 410 $ hg st
411 411 M large3
412 412 A large5
413 413 A sub2/large6
414 414 A sub2/large7
415 415 $ hg rollback --quiet
416 416 $ hg revert --quiet z
417 417 $ hg commit -m "Empty subdir" z
418 418 abort: z: no match under directory!
419 419 [255]
420 420 $ rm -rf z
421 421 $ hg ci -m "standin" .hglf
422 422 abort: file ".hglf" is a largefile standin
423 423 (commit the largefile itself instead)
424 424 [255]
425 425
426 426 Test "hg status" with combination of 'file pattern' and 'directory
427 427 pattern' for largefiles:
428 428
429 429 $ hg status sub2/large6 sub2
430 430 A sub2/large6
431 431 A sub2/large7
432 432
433 433 Config settings (pattern **.dat, minsize 2 MB) are respected.
434 434
435 435 $ echo testdata > test.dat
436 436 $ dd bs=1k count=2k if=/dev/zero of=reallylarge > /dev/null 2> /dev/null
437 437 $ hg add
438 438 adding reallylarge as a largefile
439 439 adding test.dat as a largefile
440 440
441 441 Test that minsize and --lfsize handle float values;
442 442 also tests that --lfsize overrides largefiles.minsize.
443 443 (0.250 MB = 256 kB = 262144 B)
444 444
445 445 $ dd if=/dev/zero of=ratherlarge bs=1024 count=256 > /dev/null 2> /dev/null
446 446 $ dd if=/dev/zero of=medium bs=1024 count=128 > /dev/null 2> /dev/null
447 447 $ hg --config largefiles.minsize=.25 add
448 448 adding ratherlarge as a largefile
449 449 adding medium
450 450 $ hg forget medium
451 451 $ hg --config largefiles.minsize=.25 add --lfsize=.125
452 452 adding medium as a largefile
453 453 $ dd if=/dev/zero of=notlarge bs=1024 count=127 > /dev/null 2> /dev/null
454 454 $ hg --config largefiles.minsize=.25 add --lfsize=.125
455 455 adding notlarge
456 456 $ hg forget notlarge
457 457
458 458 Test forget on largefiles.
459 459
460 460 $ hg forget large3 large5 test.dat reallylarge ratherlarge medium
461 461 $ hg commit -m "add/edit more largefiles"
462 462 Invoking status precommit hook
463 463 A sub2/large6
464 464 A sub2/large7
465 465 R large3
466 466 ? large5
467 467 ? medium
468 468 ? notlarge
469 469 ? ratherlarge
470 470 ? reallylarge
471 471 ? test.dat
472 472 $ hg st
473 473 ? large3
474 474 ? large5
475 475 ? medium
476 476 ? notlarge
477 477 ? ratherlarge
478 478 ? reallylarge
479 479 ? test.dat
480 480
481 481 Purge with largefiles: verify that largefiles are still in the working
482 482 dir after a purge.
483 483
484 484 $ hg purge --all
485 485 $ cat sub/large4
486 486 large44
487 487 $ cat sub2/large6
488 488 large6
489 489 $ cat sub2/large7
490 490 large7
491 491
492 492 Test addremove: verify that files that should be added as largefiles are added as
493 493 such and that already-existing largefiles are not added as normal files by
494 494 accident.
495 495
496 496 $ rm normal3
497 497 $ rm sub/large4
498 498 $ echo "testing addremove with patterns" > testaddremove.dat
499 499 $ echo "normaladdremove" > normaladdremove
500 500 $ hg addremove
501 501 removing sub/large4
502 502 adding testaddremove.dat as a largefile
503 503 removing normal3
504 504 adding normaladdremove
505 505
506 506 Test addremove with -R
507 507
508 508 $ hg up -C
509 509 getting changed largefiles
510 510 1 largefiles updated, 0 removed
511 511 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
512 512 $ rm normal3
513 513 $ rm sub/large4
514 514 $ echo "testing addremove with patterns" > testaddremove.dat
515 515 $ echo "normaladdremove" > normaladdremove
516 516 $ cd ..
517 517 $ hg -R a addremove
518 518 removing sub/large4
519 519 adding a/testaddremove.dat as a largefile (glob)
520 520 removing normal3
521 521 adding normaladdremove
522 522 $ cd a
523 523
524 524 Test 3364
525 525 $ hg clone . ../addrm
526 526 updating to branch default
527 527 getting changed largefiles
528 528 3 largefiles updated, 0 removed
529 529 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
530 530 $ cd ../addrm
531 531 $ cat >> .hg/hgrc <<EOF
532 532 > [hooks]
533 533 > post-commit.stat=sh -c "echo \\"Invoking status postcommit hook\\"; hg status -A"
534 534 > EOF
535 535 $ touch foo
536 536 $ hg add --large foo
537 537 $ hg ci -m "add foo"
538 538 Invoking status precommit hook
539 539 A foo
540 540 Invoking status postcommit hook
541 541 C foo
542 542 C normal3
543 543 C sub/large4
544 544 C sub/normal4
545 545 C sub2/large6
546 546 C sub2/large7
547 547 $ rm foo
548 548 $ hg st
549 549 ! foo
550 550 hmm.. no precommit invoked, but there is a postcommit??
551 551 $ hg ci -m "will not checkin"
552 552 nothing changed
553 553 Invoking status postcommit hook
554 554 ! foo
555 555 C normal3
556 556 C sub/large4
557 557 C sub/normal4
558 558 C sub2/large6
559 559 C sub2/large7
560 560 [1]
561 561 $ hg addremove
562 562 removing foo
563 563 $ hg st
564 564 R foo
565 565 $ hg ci -m "used to say nothing changed"
566 566 Invoking status precommit hook
567 567 R foo
568 568 Invoking status postcommit hook
569 569 C normal3
570 570 C sub/large4
571 571 C sub/normal4
572 572 C sub2/large6
573 573 C sub2/large7
574 574 $ hg st
575 575
576 576 Test 3507 (both normal files and largefiles were a problem)
577 577
578 578 $ touch normal
579 579 $ touch large
580 580 $ hg add normal
581 581 $ hg add --large large
582 582 $ hg ci -m "added"
583 583 Invoking status precommit hook
584 584 A large
585 585 A normal
586 586 Invoking status postcommit hook
587 587 C large
588 588 C normal
589 589 C normal3
590 590 C sub/large4
591 591 C sub/normal4
592 592 C sub2/large6
593 593 C sub2/large7
594 594 $ hg remove normal
595 595 $ hg addremove --traceback
596 596 $ hg ci -m "addremoved normal"
597 597 Invoking status precommit hook
598 598 R normal
599 599 Invoking status postcommit hook
600 600 C large
601 601 C normal3
602 602 C sub/large4
603 603 C sub/normal4
604 604 C sub2/large6
605 605 C sub2/large7
606 606 $ hg up -C '.^'
607 607 getting changed largefiles
608 608 0 largefiles updated, 0 removed
609 609 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
610 610 $ hg remove large
611 611 $ hg addremove --traceback
612 612 $ hg ci -m "removed large"
613 613 Invoking status precommit hook
614 614 R large
615 615 created new head
616 616 Invoking status postcommit hook
617 617 C normal
618 618 C normal3
619 619 C sub/large4
620 620 C sub/normal4
621 621 C sub2/large6
622 622 C sub2/large7
623 623
624 624 Test commit -A (issue 3542)
625 625 $ echo large8 > large8
626 626 $ hg add --large large8
627 627 $ hg ci -Am 'this used to add large8 as normal and commit both'
628 628 Invoking status precommit hook
629 629 A large8
630 630 Invoking status postcommit hook
631 631 C large8
632 632 C normal
633 633 C normal3
634 634 C sub/large4
635 635 C sub/normal4
636 636 C sub2/large6
637 637 C sub2/large7
638 638 $ rm large8
639 639 $ hg ci -Am 'this used to not notice the rm'
640 640 removing large8
641 641 Invoking status precommit hook
642 642 R large8
643 643 Invoking status postcommit hook
644 644 C normal
645 645 C normal3
646 646 C sub/large4
647 647 C sub/normal4
648 648 C sub2/large6
649 649 C sub2/large7
650 650
651 651 Test that a standin can't be added as a large file
652 652
653 653 $ touch large
654 654 $ hg add --large large
655 655 $ hg ci -m "add"
656 656 Invoking status precommit hook
657 657 A large
658 658 Invoking status postcommit hook
659 659 C large
660 660 C normal
661 661 C normal3
662 662 C sub/large4
663 663 C sub/normal4
664 664 C sub2/large6
665 665 C sub2/large7
666 666 $ hg remove large
667 667 $ touch large
668 668 $ hg addremove --config largefiles.patterns=**large --traceback
669 669 adding large as a largefile
670 670
671 671 Test that outgoing --large works (with revsets too)
672 672 $ hg outgoing --rev '.^' --large
673 673 comparing with $TESTTMP/a (glob)
674 674 searching for changes
675 675 changeset: 8:c02fd3b77ec4
676 676 user: test
677 677 date: Thu Jan 01 00:00:00 1970 +0000
678 678 summary: add foo
679 679
680 680 changeset: 9:289dd08c9bbb
681 681 user: test
682 682 date: Thu Jan 01 00:00:00 1970 +0000
683 683 summary: used to say nothing changed
684 684
685 685 changeset: 10:34f23ac6ac12
686 686 user: test
687 687 date: Thu Jan 01 00:00:00 1970 +0000
688 688 summary: added
689 689
690 690 changeset: 12:710c1b2f523c
691 691 parent: 10:34f23ac6ac12
692 692 user: test
693 693 date: Thu Jan 01 00:00:00 1970 +0000
694 694 summary: removed large
695 695
696 696 changeset: 13:0a3e75774479
697 697 user: test
698 698 date: Thu Jan 01 00:00:00 1970 +0000
699 699 summary: this used to add large8 as normal and commit both
700 700
701 701 changeset: 14:84f3d378175c
702 702 user: test
703 703 date: Thu Jan 01 00:00:00 1970 +0000
704 704 summary: this used to not notice the rm
705 705
706 706 searching for changes
707 707 largefiles to upload:
708 708 foo
709 709 large
710 710 large8
711 711
712 712 $ cd ../a
713 713
714 714 Clone a largefiles repo.
715 715
716 716 $ hg clone . ../b
717 717 updating to branch default
718 718 getting changed largefiles
719 719 3 largefiles updated, 0 removed
720 720 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
721 721 $ cd ../b
722 722 $ hg log --template '{rev}:{node|short} {desc|firstline}\n'
723 723 7:daea875e9014 add/edit more largefiles
724 724 6:4355d653f84f edit files yet again
725 725 5:9d5af5072dbd edit files again
726 726 4:74c02385b94c move files
727 727 3:9e8fbc4bce62 copy files
728 728 2:51a0ae4d5864 remove files
729 729 1:ce8896473775 edit files
730 730 0:30d30fe6a5be add files
731 731 $ cat normal3
732 732 normal33
733 733 $ cat sub/normal4
734 734 normal44
735 735 $ cat sub/large4
736 736 large44
737 737 $ cat sub2/large6
738 738 large6
739 739 $ cat sub2/large7
740 740 large7
741 741 $ hg log -qf sub2/large7
742 742 7:daea875e9014
743 743 $ cd ..
744 744 $ hg clone a -r 3 c
745 745 adding changesets
746 746 adding manifests
747 747 adding file changes
748 748 added 4 changesets with 10 changes to 4 files
749 749 updating to branch default
750 750 getting changed largefiles
751 751 2 largefiles updated, 0 removed
752 752 4 files updated, 0 files merged, 0 files removed, 0 files unresolved
753 753 $ cd c
754 754 $ hg log --template '{rev}:{node|short} {desc|firstline}\n'
755 755 3:9e8fbc4bce62 copy files
756 756 2:51a0ae4d5864 remove files
757 757 1:ce8896473775 edit files
758 758 0:30d30fe6a5be add files
759 759 $ cat normal1
760 760 normal22
761 761 $ cat large1
762 762 large22
763 763 $ cat sub/normal2
764 764 normal22
765 765 $ cat sub/large2
766 766 large22
767 767
768 768 Old revisions of a clone have correct largefiles content (this also
769 769 tests update).
770 770
771 771 $ hg update -r 1
772 772 getting changed largefiles
773 773 1 largefiles updated, 0 removed
774 774 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
775 775 $ cat large1
776 776 large11
777 777 $ cat sub/large2
778 778 large22
779 779 $ cd ..
780 780
781 781 Test cloning with --all-largefiles flag
782 782
783 783 $ rm "${USERCACHE}"/*
784 784 $ hg clone --all-largefiles a a-backup
785 785 updating to branch default
786 786 getting changed largefiles
787 787 3 largefiles updated, 0 removed
788 788 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
789 789 8 additional largefiles cached
790 790
791 791 $ rm "${USERCACHE}"/*
792 792 $ hg clone --all-largefiles -u 0 a a-clone0
793 793 updating to branch default
794 794 getting changed largefiles
795 795 2 largefiles updated, 0 removed
796 796 4 files updated, 0 files merged, 0 files removed, 0 files unresolved
797 797 9 additional largefiles cached
798 798 $ hg -R a-clone0 sum
799 799 parent: 0:30d30fe6a5be
800 800 add files
801 801 branch: default
802 802 commit: (clean)
803 803 update: 7 new changesets (update)
804 804
805 805 $ rm "${USERCACHE}"/*
806 806 $ hg clone --all-largefiles -u 1 a a-clone1
807 807 updating to branch default
808 808 getting changed largefiles
809 809 2 largefiles updated, 0 removed
810 810 4 files updated, 0 files merged, 0 files removed, 0 files unresolved
811 811 8 additional largefiles cached
812 812 $ hg -R a-clone1 verify --large --lfa --lfc
813 813 checking changesets
814 814 checking manifests
815 815 crosschecking files in changesets and manifests
816 816 checking files
817 817 10 files, 8 changesets, 24 total revisions
818 818 searching 8 changesets for largefiles
819 819 verified contents of 13 revisions of 6 largefiles
820 820 $ hg -R a-clone1 sum
821 821 parent: 1:ce8896473775
822 822 edit files
823 823 branch: default
824 824 commit: (clean)
825 825 update: 6 new changesets (update)
826 826
827 827 $ rm "${USERCACHE}"/*
828 828 $ hg clone --all-largefiles -U a a-clone-u
829 829 11 additional largefiles cached
830 830 $ hg -R a-clone-u sum
831 831 parent: -1:000000000000 (no revision checked out)
832 832 branch: default
833 833 commit: (clean)
834 834 update: 8 new changesets (update)
835 835
836 836 Show computed destination directory:
837 837
838 838 $ mkdir xyz
839 839 $ cd xyz
840 840 $ hg clone ../a
841 841 destination directory: a
842 842 updating to branch default
843 843 getting changed largefiles
844 844 3 largefiles updated, 0 removed
845 845 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
846 846 $ cd ..
847 847
848 848 Clone URL without path:
849 849
850 850 $ hg clone file://
851 851 abort: repository / not found!
852 852 [255]
853 853
854 854 Ensure base clone command argument validation
855 855
856 856 $ hg clone -U -u 0 a a-clone-failure
857 857 abort: cannot specify both --noupdate and --updaterev
858 858 [255]
859 859
860 860 $ hg clone --all-largefiles a ssh://localhost/a
861 861 abort: --all-largefiles is incompatible with non-local destination ssh://localhost/a
862 862 [255]
863 863
864 864 Test pulling with --all-largefiles flag. Also test that the largefiles are
865 865 downloaded from 'default' instead of 'default-push' when no source is specified
866 866 (issue3584)
867 867
868 868 $ rm -Rf a-backup
869 869 $ hg clone -r 1 a a-backup
870 870 adding changesets
871 871 adding manifests
872 872 adding file changes
873 873 added 2 changesets with 8 changes to 4 files
874 874 updating to branch default
875 875 getting changed largefiles
876 876 2 largefiles updated, 0 removed
877 877 4 files updated, 0 files merged, 0 files removed, 0 files unresolved
878 878 $ rm "${USERCACHE}"/*
879 879 $ cd a-backup
880 880 $ hg pull --all-largefiles --config paths.default-push=bogus/path
881 881 pulling from $TESTTMP/a (glob)
882 882 searching for changes
883 883 adding changesets
884 884 adding manifests
885 885 adding file changes
886 886 added 6 changesets with 16 changes to 8 files
887 887 (run 'hg update' to get a working copy)
888 888 6 largefiles cached
889 889
890 890 redo pull with --lfrev and check it pulls largefiles for the right revs
891 891
892 892 $ hg rollback
893 893 repository tip rolled back to revision 1 (undo pull)
894 894 $ hg pull -v --lfrev 'heads(pulled())+min(pulled())'
895 895 pulling from $TESTTMP/a (glob)
896 896 searching for changes
897 897 all local heads known remotely
898 898 6 changesets found
899 899 adding changesets
900 900 adding manifests
901 901 adding file changes
902 902 added 6 changesets with 16 changes to 8 files
903 903 calling hook changegroup.lfiles: hgext.largefiles.reposetup.checkrequireslfiles
904 904 (run 'hg update' to get a working copy)
905 905 pulling largefiles for revision 7
906 906 found 971fb41e78fea4f8e0ba5244784239371cb00591 in store
907 907 found 0d6d75887db61b2c7e6c74b5dd8fc6ad50c0cc30 in store
908 908 found bb3151689acb10f0c3125c560d5e63df914bc1af in store
909 909 pulling largefiles for revision 2
910 910 found eb7338044dc27f9bc59b8dd5a246b065ead7a9c4 in store
911 911 0 largefiles cached
912 912
913 913 lfpull
914 914
915 915 $ hg lfpull -r : --config largefiles.usercache=usercache-lfpull
916 916 2 largefiles cached
917 917 $ hg lfpull -v -r 4+2 --config largefiles.usercache=usercache-lfpull
918 918 pulling largefiles for revision 4
919 919 found eb7338044dc27f9bc59b8dd5a246b065ead7a9c4 in store
920 920 found eb7338044dc27f9bc59b8dd5a246b065ead7a9c4 in store
921 921 pulling largefiles for revision 2
922 922 found eb7338044dc27f9bc59b8dd5a246b065ead7a9c4 in store
923 923 0 largefiles cached
924 924
925 925 $ ls usercache-lfpull/* | sort
926 926 usercache-lfpull/1deebade43c8c498a3c8daddac0244dc55d1331d
927 927 usercache-lfpull/4669e532d5b2c093a78eca010077e708a071bb64
928 928
929 929 $ cd ..
930 930
931 931 Rebasing between two repositories does not revert largefiles to old
932 932 revisions (this was a very bad bug that took a lot of work to fix).
933 933
934 934 $ hg clone a d
935 935 updating to branch default
936 936 getting changed largefiles
937 937 3 largefiles updated, 0 removed
938 938 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
939 939 $ cd b
940 940 $ echo large4-modified > sub/large4
941 941 $ echo normal3-modified > normal3
942 942 $ hg commit -m "modify normal file and largefile in repo b"
943 943 Invoking status precommit hook
944 944 M normal3
945 945 M sub/large4
946 946 $ cd ../d
947 947 $ echo large6-modified > sub2/large6
948 948 $ echo normal4-modified > sub/normal4
949 949 $ hg commit -m "modify normal file largefile in repo d"
950 950 Invoking status precommit hook
951 951 M sub/normal4
952 952 M sub2/large6
953 953 $ cd ..
954 954 $ hg clone d e
955 955 updating to branch default
956 956 getting changed largefiles
957 957 3 largefiles updated, 0 removed
958 958 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
959 959 $ cd d
960 960
961 961 More rebase testing, but also test that the largefiles are downloaded from
962 962 'default-push' when no source is specified (issue3584). (The largefile from the
963 963 pulled revision is however not downloaded but found in the local cache.)
964 964 Largefiles are fetched for the new pulled revision, not for existing revisions,
965 965 rebased or not.
966 966
967 967 $ [ ! -f .hg/largefiles/e166e74c7303192238d60af5a9c4ce9bef0b7928 ]
968 968 $ hg pull --rebase --all-largefiles --config paths.default-push=bogus/path --config paths.default=../b
969 969 pulling from $TESTTMP/b (glob)
970 970 searching for changes
971 971 adding changesets
972 972 adding manifests
973 973 adding file changes
974 974 added 1 changesets with 2 changes to 2 files (+1 heads)
975 975 Invoking status precommit hook
976 976 M sub/normal4
977 977 M sub2/large6
978 978 saved backup bundle to $TESTTMP/d/.hg/strip-backup/f574fb32bb45-backup.hg (glob)
979 979 0 largefiles cached
980 980 nothing to rebase - working directory parent is also destination
981 981 $ [ -f .hg/largefiles/e166e74c7303192238d60af5a9c4ce9bef0b7928 ]
982 982 $ hg log --template '{rev}:{node|short} {desc|firstline}\n'
983 983 9:598410d3eb9a modify normal file largefile in repo d
984 984 8:a381d2c8c80e modify normal file and largefile in repo b
985 985 7:daea875e9014 add/edit more largefiles
986 986 6:4355d653f84f edit files yet again
987 987 5:9d5af5072dbd edit files again
988 988 4:74c02385b94c move files
989 989 3:9e8fbc4bce62 copy files
990 990 2:51a0ae4d5864 remove files
991 991 1:ce8896473775 edit files
992 992 0:30d30fe6a5be add files
993 993 $ cat normal3
994 994 normal3-modified
995 995 $ cat sub/normal4
996 996 normal4-modified
997 997 $ cat sub/large4
998 998 large4-modified
999 999 $ cat sub2/large6
1000 1000 large6-modified
1001 1001 $ cat sub2/large7
1002 1002 large7
1003 1003 $ cd ../e
1004 1004 $ hg pull ../b
1005 1005 pulling from ../b
1006 1006 searching for changes
1007 1007 adding changesets
1008 1008 adding manifests
1009 1009 adding file changes
1010 1010 added 1 changesets with 2 changes to 2 files (+1 heads)
1011 1011 (run 'hg heads' to see heads, 'hg merge' to merge)
1012 1012 $ hg rebase
1013 1013 Invoking status precommit hook
1014 1014 M sub/normal4
1015 1015 M sub2/large6
1016 1016 saved backup bundle to $TESTTMP/e/.hg/strip-backup/f574fb32bb45-backup.hg (glob)
1017 1017 $ hg log --template '{rev}:{node|short} {desc|firstline}\n'
1018 1018 9:598410d3eb9a modify normal file largefile in repo d
1019 1019 8:a381d2c8c80e modify normal file and largefile in repo b
1020 1020 7:daea875e9014 add/edit more largefiles
1021 1021 6:4355d653f84f edit files yet again
1022 1022 5:9d5af5072dbd edit files again
1023 1023 4:74c02385b94c move files
1024 1024 3:9e8fbc4bce62 copy files
1025 1025 2:51a0ae4d5864 remove files
1026 1026 1:ce8896473775 edit files
1027 1027 0:30d30fe6a5be add files
1028 1028 $ cat normal3
1029 1029 normal3-modified
1030 1030 $ cat sub/normal4
1031 1031 normal4-modified
1032 1032 $ cat sub/large4
1033 1033 large4-modified
1034 1034 $ cat sub2/large6
1035 1035 large6-modified
1036 1036 $ cat sub2/large7
1037 1037 large7
1038 1038
1039 1039 Log on largefiles
1040 1040
1041 1041 - same output
1042 1042 $ hg log --template '{rev}:{node|short} {desc|firstline}\n' .hglf/sub/large4
1043 1043 8:a381d2c8c80e modify normal file and largefile in repo b
1044 1044 6:4355d653f84f edit files yet again
1045 1045 5:9d5af5072dbd edit files again
1046 1046 4:74c02385b94c move files
1047 1047 $ hg log --template '{rev}:{node|short} {desc|firstline}\n' sub/large4
1048 1048 8:a381d2c8c80e modify normal file and largefile in repo b
1049 1049 6:4355d653f84f edit files yet again
1050 1050 5:9d5af5072dbd edit files again
1051 1051 4:74c02385b94c move files
1052 1052
1053 1053 - .hglf only matches largefiles, without .hglf it matches 9 bco sub/normal
1054 1054 $ hg log --template '{rev}:{node|short} {desc|firstline}\n' .hglf/sub
1055 1055 8:a381d2c8c80e modify normal file and largefile in repo b
1056 1056 6:4355d653f84f edit files yet again
1057 1057 5:9d5af5072dbd edit files again
1058 1058 4:74c02385b94c move files
1059 1059 1:ce8896473775 edit files
1060 1060 0:30d30fe6a5be add files
1061 1061 $ hg log --template '{rev}:{node|short} {desc|firstline}\n' sub
1062 1062 9:598410d3eb9a modify normal file largefile in repo d
1063 1063 8:a381d2c8c80e modify normal file and largefile in repo b
1064 1064 6:4355d653f84f edit files yet again
1065 1065 5:9d5af5072dbd edit files again
1066 1066 4:74c02385b94c move files
1067 1067 1:ce8896473775 edit files
1068 1068 0:30d30fe6a5be add files
1069 1069
1070 1070 - globbing gives same result
1071 1071 $ hg log --template '{rev}:{node|short} {desc|firstline}\n' 'glob:sub/*'
1072 1072 9:598410d3eb9a modify normal file largefile in repo d
1073 1073 8:a381d2c8c80e modify normal file and largefile in repo b
1074 1074 6:4355d653f84f edit files yet again
1075 1075 5:9d5af5072dbd edit files again
1076 1076 4:74c02385b94c move files
1077 1077 1:ce8896473775 edit files
1078 1078 0:30d30fe6a5be add files
1079 1079
1080 1080 Rollback on largefiles.
1081 1081
1082 1082 $ echo large4-modified-again > sub/large4
1083 1083 $ hg commit -m "Modify large4 again"
1084 1084 Invoking status precommit hook
1085 1085 M sub/large4
1086 1086 $ hg rollback
1087 1087 repository tip rolled back to revision 9 (undo commit)
1088 1088 working directory now based on revision 9
1089 1089 $ hg st
1090 1090 M sub/large4
1091 1091 $ hg log --template '{rev}:{node|short} {desc|firstline}\n'
1092 1092 9:598410d3eb9a modify normal file largefile in repo d
1093 1093 8:a381d2c8c80e modify normal file and largefile in repo b
1094 1094 7:daea875e9014 add/edit more largefiles
1095 1095 6:4355d653f84f edit files yet again
1096 1096 5:9d5af5072dbd edit files again
1097 1097 4:74c02385b94c move files
1098 1098 3:9e8fbc4bce62 copy files
1099 1099 2:51a0ae4d5864 remove files
1100 1100 1:ce8896473775 edit files
1101 1101 0:30d30fe6a5be add files
1102 1102 $ cat sub/large4
1103 1103 large4-modified-again
1104 1104
1105 1105 "update --check" refuses to update with uncommitted changes.
1106 1106 $ hg update --check 8
1107 1107 abort: uncommitted changes
1108 1108 [255]
1109 1109
1110 1110 "update --clean" leaves correct largefiles in working copy, even when there is
1111 1111 .orig files from revert in .hglf.
1112 1112
1113 1113 $ echo mistake > sub2/large7
1114 1114 $ hg revert sub2/large7
1115 1115 $ hg -q update --clean -r null
1116 1116 $ hg update --clean
1117 1117 getting changed largefiles
1118 1118 3 largefiles updated, 0 removed
1119 1119 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
1120 1120 $ cat normal3
1121 1121 normal3-modified
1122 1122 $ cat sub/normal4
1123 1123 normal4-modified
1124 1124 $ cat sub/large4
1125 1125 large4-modified
1126 1126 $ cat sub2/large6
1127 1127 large6-modified
1128 1128 $ cat sub2/large7
1129 1129 large7
1130 1130 $ cat sub2/large7.orig
1131 1131 mistake
1132 1132 $ cat .hglf/sub2/large7.orig
1133 1133 9dbfb2c79b1c40981b258c3efa1b10b03f18ad31
1134 1134
1135 1135 demonstrate misfeature: .orig file is overwritten on every update -C,
1136 1136 also when clean:
1137 1137 $ hg update --clean
1138 1138 getting changed largefiles
1139 1139 0 largefiles updated, 0 removed
1140 1140 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
1141 1141 $ cat sub2/large7.orig
1142 1142 large7
1143 1143 $ rm sub2/large7.orig .hglf/sub2/large7.orig
1144 1144
1145 1145 Now "update check" is happy.
1146 1146 $ hg update --check 8
1147 1147 getting changed largefiles
1148 1148 1 largefiles updated, 0 removed
1149 1149 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
1150 1150 $ hg update --check
1151 1151 getting changed largefiles
1152 1152 1 largefiles updated, 0 removed
1153 1153 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
1154 1154
1155 1155 Test removing empty largefiles directories on update
1156 1156 $ test -d sub2 && echo "sub2 exists"
1157 1157 sub2 exists
1158 1158 $ hg update -q null
1159 1159 $ test -d sub2 && echo "error: sub2 should not exist anymore"
1160 1160 [1]
1161 1161 $ hg update -q
1162 1162
1163 1163 Test hg remove removes empty largefiles directories
1164 1164 $ test -d sub2 && echo "sub2 exists"
1165 1165 sub2 exists
1166 1166 $ hg remove sub2/*
1167 1167 $ test -d sub2 && echo "error: sub2 should not exist anymore"
1168 1168 [1]
1169 1169 $ hg revert sub2/large6 sub2/large7
1170 1170
1171 1171 "revert" works on largefiles (and normal files too).
1172 1172 $ echo hack3 >> normal3
1173 1173 $ echo hack4 >> sub/normal4
1174 1174 $ echo hack4 >> sub/large4
1175 1175 $ rm sub2/large6
1176 1176 $ hg revert sub2/large6
1177 1177 $ hg rm sub2/large6
1178 1178 $ echo new >> sub2/large8
1179 1179 $ hg add --large sub2/large8
1180 1180 # XXX we don't really want to report that we're reverting the standin;
1181 1181 # that's just an implementation detail. But I don't see an obvious fix. ;-(
1182 1182 $ hg revert sub
1183 1183 reverting .hglf/sub/large4 (glob)
1184 1184 reverting sub/normal4 (glob)
1185 1185 $ hg status
1186 1186 M normal3
1187 1187 A sub2/large8
1188 1188 R sub2/large6
1189 1189 ? sub/large4.orig
1190 1190 ? sub/normal4.orig
1191 1191 $ cat sub/normal4
1192 1192 normal4-modified
1193 1193 $ cat sub/large4
1194 1194 large4-modified
1195 1195 $ hg revert -a --no-backup
1196 1196 undeleting .hglf/sub2/large6 (glob)
1197 1197 forgetting .hglf/sub2/large8 (glob)
1198 1198 reverting normal3
1199 1199 $ hg status
1200 1200 ? sub/large4.orig
1201 1201 ? sub/normal4.orig
1202 1202 ? sub2/large8
1203 1203 $ cat normal3
1204 1204 normal3-modified
1205 1205 $ cat sub2/large6
1206 1206 large6-modified
1207 1207 $ rm sub/*.orig sub2/large8
1208 1208
1209 1209 revert some files to an older revision
1210 1210 $ hg revert --no-backup -r 8 sub2
1211 1211 reverting .hglf/sub2/large6 (glob)
1212 1212 $ cat sub2/large6
1213 1213 large6
1214 1214 $ hg revert --no-backup -C -r '.^' sub2
1215 1215 reverting .hglf/sub2/large6 (glob)
1216 1216 $ hg revert --no-backup sub2
1217 1217 reverting .hglf/sub2/large6 (glob)
1218 1218 $ hg status
1219 1219
1220 1220 "verify --large" actually verifies largefiles
1221 1221
1222 1222 - Where Do We Come From? What Are We? Where Are We Going?
1223 1223 $ pwd
1224 1224 $TESTTMP/e
1225 1225 $ hg paths
1226 1226 default = $TESTTMP/d (glob)
1227 1227
1228 1228 $ hg verify --large
1229 1229 checking changesets
1230 1230 checking manifests
1231 1231 crosschecking files in changesets and manifests
1232 1232 checking files
1233 1233 10 files, 10 changesets, 28 total revisions
1234 1234 searching 1 changesets for largefiles
1235 1235 verified existence of 3 revisions of 3 largefiles
1236 1236
1237 1237 - introduce missing blob in local store repo and make sure that this is caught:
1238 1238 $ mv $TESTTMP/d/.hg/largefiles/e166e74c7303192238d60af5a9c4ce9bef0b7928 .
1239 1239 $ hg verify --large
1240 1240 checking changesets
1241 1241 checking manifests
1242 1242 crosschecking files in changesets and manifests
1243 1243 checking files
1244 1244 10 files, 10 changesets, 28 total revisions
1245 1245 searching 1 changesets for largefiles
1246 1246 changeset 9:598410d3eb9a: sub/large4 references missing $TESTTMP/d/.hg/largefiles/e166e74c7303192238d60af5a9c4ce9bef0b7928 (glob)
1247 1247 verified existence of 3 revisions of 3 largefiles
1248 1248 [1]
1249 1249
1250 1250 - introduce corruption and make sure that it is caught when checking content:
1251 1251 $ echo '5 cents' > $TESTTMP/d/.hg/largefiles/e166e74c7303192238d60af5a9c4ce9bef0b7928
1252 1252 $ hg verify -q --large --lfc
1253 1253 changeset 9:598410d3eb9a: sub/large4 references corrupted $TESTTMP/d/.hg/largefiles/e166e74c7303192238d60af5a9c4ce9bef0b7928 (glob)
1254 1254 [1]
1255 1255
1256 1256 - cleanup
1257 1257 $ mv e166e74c7303192238d60af5a9c4ce9bef0b7928 $TESTTMP/d/.hg/largefiles/
1258 1258
1259 1259 - verifying all revisions will fail because we didn't clone all largefiles to d:
1260 1260 $ echo 'T-shirt' > $TESTTMP/d/.hg/largefiles/eb7338044dc27f9bc59b8dd5a246b065ead7a9c4
1261 1261 $ hg verify -q --lfa --lfc
1262 1262 changeset 0:30d30fe6a5be: large1 references missing $TESTTMP/d/.hg/largefiles/4669e532d5b2c093a78eca010077e708a071bb64 (glob)
1263 1263 changeset 0:30d30fe6a5be: sub/large2 references missing $TESTTMP/d/.hg/largefiles/1deebade43c8c498a3c8daddac0244dc55d1331d (glob)
1264 1264 changeset 1:ce8896473775: large1 references missing $TESTTMP/d/.hg/largefiles/5f78770c0e77ba4287ad6ef3071c9bf9c379742f (glob)
1265 1265 changeset 1:ce8896473775: sub/large2 references corrupted $TESTTMP/d/.hg/largefiles/eb7338044dc27f9bc59b8dd5a246b065ead7a9c4 (glob)
1266 1266 changeset 3:9e8fbc4bce62: large1 references corrupted $TESTTMP/d/.hg/largefiles/eb7338044dc27f9bc59b8dd5a246b065ead7a9c4 (glob)
1267 1267 changeset 4:74c02385b94c: large3 references corrupted $TESTTMP/d/.hg/largefiles/eb7338044dc27f9bc59b8dd5a246b065ead7a9c4 (glob)
1268 1268 changeset 4:74c02385b94c: sub/large4 references corrupted $TESTTMP/d/.hg/largefiles/eb7338044dc27f9bc59b8dd5a246b065ead7a9c4 (glob)
1269 1269 changeset 5:9d5af5072dbd: large3 references missing $TESTTMP/d/.hg/largefiles/baaf12afde9d8d67f25dab6dced0d2bf77dba47c (glob)
1270 1270 changeset 5:9d5af5072dbd: sub/large4 references missing $TESTTMP/d/.hg/largefiles/aeb2210d19f02886dde00dac279729a48471e2f9 (glob)
1271 1271 changeset 6:4355d653f84f: large3 references missing $TESTTMP/d/.hg/largefiles/7838695e10da2bb75ac1156565f40a2595fa2fa0 (glob)
1272 1272 [1]
1273 1273
1274 1274 - cleanup
1275 1275 $ rm $TESTTMP/d/.hg/largefiles/eb7338044dc27f9bc59b8dd5a246b065ead7a9c4
1276 1276 $ rm -f .hglf/sub/*.orig
1277 1277
1278 1278 Update to revision with missing largefile - and make sure it really is missing
1279 1279
1280 1280 $ rm ${USERCACHE}/7838695e10da2bb75ac1156565f40a2595fa2fa0
1281 1281 $ hg up -r 6
1282 1282 getting changed largefiles
1283 1283 large3: largefile 7838695e10da2bb75ac1156565f40a2595fa2fa0 not available from file:/*/$TESTTMP/d (glob)
1284 1284 1 largefiles updated, 2 removed
1285 1285 4 files updated, 0 files merged, 2 files removed, 0 files unresolved
1286 1286 $ rm normal3
1287 1287 $ echo >> sub/normal4
1288 1288 $ hg ci -m 'commit with missing files'
1289 1289 Invoking status precommit hook
1290 1290 M sub/normal4
1291 1291 ! large3
1292 1292 ! normal3
1293 1293 created new head
1294 1294 $ hg st
1295 1295 ! large3
1296 1296 ! normal3
1297 1297 $ hg up -r.
1298 1298 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
1299 1299 $ hg st
1300 1300 ! large3
1301 1301 ! normal3
1302 1302 $ hg up -Cr.
1303 1303 getting changed largefiles
1304 1304 large3: largefile 7838695e10da2bb75ac1156565f40a2595fa2fa0 not available from file:/*/$TESTTMP/d (glob)
1305 1305 0 largefiles updated, 0 removed
1306 1306 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1307 1307 $ hg st
1308 1308 ! large3
1309 1309 $ hg rollback
1310 1310 repository tip rolled back to revision 9 (undo commit)
1311 1311 working directory now based on revision 6
1312 1312
1313 1313 Merge with revision with missing largefile - and make sure it tries to fetch it.
1314 1314
1315 1315 $ hg up -Cqr null
1316 1316 $ echo f > f
1317 1317 $ hg ci -Am branch
1318 1318 adding f
1319 1319 Invoking status precommit hook
1320 1320 A f
1321 1321 created new head
1322 1322 $ hg merge -r 6
1323 1323 4 files updated, 0 files merged, 0 files removed, 0 files unresolved
1324 1324 (branch merge, don't forget to commit)
1325 1325 getting changed largefiles
1326 1326 large3: largefile 7838695e10da2bb75ac1156565f40a2595fa2fa0 not available from file:/*/$TESTTMP/d (glob)
1327 1327 1 largefiles updated, 0 removed
1328 1328
1329 1329 $ hg rollback -q
1330 1330 $ hg up -Cq
1331 1331
1332 1332 Pulling 0 revisions with --all-largefiles should not fetch for all revisions
1333 1333
1334 1334 $ hg pull --all-largefiles
1335 1335 pulling from $TESTTMP/d (glob)
1336 1336 searching for changes
1337 1337 no changes found
1338 1338
1339 1339 Merging does not revert to old versions of largefiles and also check
1340 1340 that merging after having pulled from a non-default remote works
1341 1341 correctly.
1342 1342
1343 1343 $ cd ..
1344 1344 $ hg clone -r 7 e temp
1345 1345 adding changesets
1346 1346 adding manifests
1347 1347 adding file changes
1348 1348 added 8 changesets with 24 changes to 10 files
1349 1349 updating to branch default
1350 1350 getting changed largefiles
1351 1351 3 largefiles updated, 0 removed
1352 1352 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
1353 1353 $ hg clone temp f
1354 1354 updating to branch default
1355 1355 getting changed largefiles
1356 1356 3 largefiles updated, 0 removed
1357 1357 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
1358 1358 # Delete the largefiles in the largefiles system cache so that we have an
1359 1359 # opportunity to test that caching after a pull works.
1360 1360 $ rm "${USERCACHE}"/*
1361 1361 $ cd f
1362 1362 $ echo "large4-merge-test" > sub/large4
1363 1363 $ hg commit -m "Modify large4 to test merge"
1364 1364 Invoking status precommit hook
1365 1365 M sub/large4
1366 1366 # Test --cache-largefiles flag
1367 1367 $ hg pull --lfrev 'heads(pulled())' ../e
1368 1368 pulling from ../e
1369 1369 searching for changes
1370 1370 adding changesets
1371 1371 adding manifests
1372 1372 adding file changes
1373 1373 added 2 changesets with 4 changes to 4 files (+1 heads)
1374 1374 (run 'hg heads' to see heads, 'hg merge' to merge)
1375 1375 2 largefiles cached
1376 1376 $ hg merge
1377 1377 largefile sub/large4 has a merge conflict
1378 1378 ancestor was 971fb41e78fea4f8e0ba5244784239371cb00591
1379 1379 keep (l)ocal d846f26643bfa8ec210be40cc93cc6b7ff1128ea or
1380 1380 take (o)ther e166e74c7303192238d60af5a9c4ce9bef0b7928? l
1381 1381 3 files updated, 1 files merged, 0 files removed, 0 files unresolved
1382 1382 (branch merge, don't forget to commit)
1383 1383 getting changed largefiles
1384 1384 1 largefiles updated, 0 removed
1385 1385 $ hg commit -m "Merge repos e and f"
1386 1386 Invoking status precommit hook
1387 1387 M normal3
1388 1388 M sub/normal4
1389 1389 M sub2/large6
1390 1390 $ cat normal3
1391 1391 normal3-modified
1392 1392 $ cat sub/normal4
1393 1393 normal4-modified
1394 1394 $ cat sub/large4
1395 1395 large4-merge-test
1396 1396 $ cat sub2/large6
1397 1397 large6-modified
1398 1398 $ cat sub2/large7
1399 1399 large7
1400 1400
1401 1401 Test status after merging with a branch that introduces a new largefile:
1402 1402
1403 1403 $ echo large > large
1404 1404 $ hg add --large large
1405 1405 $ hg commit -m 'add largefile'
1406 1406 Invoking status precommit hook
1407 1407 A large
1408 1408 $ hg update -q ".^"
1409 1409 $ echo change >> normal3
1410 1410 $ hg commit -m 'some change'
1411 1411 Invoking status precommit hook
1412 1412 M normal3
1413 1413 created new head
1414 1414 $ hg merge
1415 1415 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1416 1416 (branch merge, don't forget to commit)
1417 1417 getting changed largefiles
1418 1418 1 largefiles updated, 0 removed
1419 1419 $ hg status
1420 1420 M large
1421 1421
1422 1422 - make sure update of merge with removed largefiles fails as expected
1423 1423 $ hg rm sub2/large6
1424 1424 $ hg up -r.
1425 1425 abort: outstanding uncommitted merges
1426 1426 [255]
1427 1427
1428 1428 - revert should be able to revert files introduced in a pending merge
1429 1429 $ hg revert --all -r .
1430 1430 removing .hglf/large (glob)
1431 1431 undeleting .hglf/sub2/large6 (glob)
1432 1432
1433 1433 Test that a normal file and a largefile with the same name and path cannot
1434 1434 coexist.
1435 1435
1436 1436 $ rm sub2/large7
1437 1437 $ echo "largeasnormal" > sub2/large7
1438 1438 $ hg add sub2/large7
1439 1439 sub2/large7 already a largefile
1440 1440
1441 1441 Test that transplanting a largefile change works correctly.
1442 1442
1443 1443 $ cd ..
1444 1444 $ hg clone -r 8 d g
1445 1445 adding changesets
1446 1446 adding manifests
1447 1447 adding file changes
1448 1448 added 9 changesets with 26 changes to 10 files
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 $ cd g
1454 1454 $ hg transplant -s ../d 598410d3eb9a
1455 1455 searching for changes
1456 1456 searching for changes
1457 1457 adding changesets
1458 1458 adding manifests
1459 1459 adding file changes
1460 1460 added 1 changesets with 2 changes to 2 files
1461 1461 getting changed largefiles
1462 1462 1 largefiles updated, 0 removed
1463 1463 $ hg log --template '{rev}:{node|short} {desc|firstline}\n'
1464 1464 9:598410d3eb9a modify normal file largefile in repo d
1465 1465 8:a381d2c8c80e modify normal file and largefile in repo b
1466 1466 7:daea875e9014 add/edit more largefiles
1467 1467 6:4355d653f84f edit files yet again
1468 1468 5:9d5af5072dbd edit files again
1469 1469 4:74c02385b94c move files
1470 1470 3:9e8fbc4bce62 copy files
1471 1471 2:51a0ae4d5864 remove files
1472 1472 1:ce8896473775 edit files
1473 1473 0:30d30fe6a5be add files
1474 1474 $ cat normal3
1475 1475 normal3-modified
1476 1476 $ cat sub/normal4
1477 1477 normal4-modified
1478 1478 $ cat sub/large4
1479 1479 large4-modified
1480 1480 $ cat sub2/large6
1481 1481 large6-modified
1482 1482 $ cat sub2/large7
1483 1483 large7
1484 1484
1485 1485 Cat a largefile
1486 1486 $ hg cat normal3
1487 1487 normal3-modified
1488 1488 $ hg cat sub/large4
1489 1489 large4-modified
1490 1490 $ rm "${USERCACHE}"/*
1491 1491 $ hg cat -r a381d2c8c80e -o cat.out sub/large4
1492 1492 $ cat cat.out
1493 1493 large4-modified
1494 1494 $ rm cat.out
1495 1495 $ hg cat -r a381d2c8c80e normal3
1496 1496 normal3-modified
1497 1497 $ hg cat -r '.^' normal3
1498 1498 normal3-modified
1499 1499 $ hg cat -r '.^' sub/large4 doesntexist
1500 1500 large4-modified
1501 1501 doesntexist: no such file in rev a381d2c8c80e
1502 1502 $ hg --cwd sub cat -r '.^' large4
1503 1503 large4-modified
1504 1504 $ hg --cwd sub cat -r '.^' ../normal3
1505 1505 normal3-modified
1506 1506
1507 1507 Test that renaming a largefile results in correct output for status
1508 1508
1509 1509 $ hg rename sub/large4 large4-renamed
1510 1510 $ hg commit -m "test rename output"
1511 1511 Invoking status precommit hook
1512 1512 A large4-renamed
1513 1513 R sub/large4
1514 1514 $ cat large4-renamed
1515 1515 large4-modified
1516 1516 $ cd sub2
1517 1517 $ hg rename large6 large6-renamed
1518 1518 $ hg st
1519 1519 A sub2/large6-renamed
1520 1520 R sub2/large6
1521 1521 $ cd ..
1522 1522
1523 1523 Test --normal flag
1524 1524
1525 1525 $ dd if=/dev/zero bs=2k count=11k > new-largefile 2> /dev/null
1526 1526 $ hg add --normal --large new-largefile
1527 1527 abort: --normal cannot be used with --large
1528 1528 [255]
1529 1529 $ hg add --normal new-largefile
1530 1530 new-largefile: up to 69 MB of RAM may be required to manage this file
1531 1531 (use 'hg revert new-largefile' to cancel the pending addition)
1532 1532 $ cd ..
1533 1533
1534 1534 #if serve
1535 1535 vanilla clients not locked out from largefiles servers on vanilla repos
1536 1536 $ mkdir r1
1537 1537 $ cd r1
1538 1538 $ hg init
1539 1539 $ echo c1 > f1
1540 1540 $ hg add f1
1541 1541 $ hg commit -m "m1"
1542 1542 Invoking status precommit hook
1543 1543 A f1
1544 1544 $ cd ..
1545 1545 $ hg serve -R r1 -d -p $HGPORT --pid-file hg.pid
1546 1546 $ cat hg.pid >> $DAEMON_PIDS
1547 1547 $ hg --config extensions.largefiles=! clone http://localhost:$HGPORT r2
1548 1548 requesting all changes
1549 1549 adding changesets
1550 1550 adding manifests
1551 1551 adding file changes
1552 1552 added 1 changesets with 1 changes to 1 files
1553 1553 updating to branch default
1554 1554 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1555 1555
1556 1556 largefiles clients still work with vanilla servers
1557 1557 $ hg --config extensions.largefiles=! serve -R r1 -d -p $HGPORT1 --pid-file hg.pid
1558 1558 $ cat hg.pid >> $DAEMON_PIDS
1559 1559 $ hg clone http://localhost:$HGPORT1 r3
1560 1560 requesting all changes
1561 1561 adding changesets
1562 1562 adding manifests
1563 1563 adding file changes
1564 1564 added 1 changesets with 1 changes to 1 files
1565 1565 updating to branch default
1566 1566 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1567 1567 #endif
1568 1568
1569 1569
1570 1570 vanilla clients locked out from largefiles http repos
1571 1571 $ mkdir r4
1572 1572 $ cd r4
1573 1573 $ hg init
1574 1574 $ echo c1 > f1
1575 1575 $ hg add --large f1
1576 1576 $ hg commit -m "m1"
1577 1577 Invoking status precommit hook
1578 1578 A f1
1579 1579 $ cd ..
1580 1580
1581 1581 largefiles can be pushed locally (issue3583)
1582 1582 $ hg init dest
1583 1583 $ cd r4
1584 1584 $ hg outgoing ../dest
1585 1585 comparing with ../dest
1586 1586 searching for changes
1587 1587 changeset: 0:639881c12b4c
1588 1588 tag: tip
1589 1589 user: test
1590 1590 date: Thu Jan 01 00:00:00 1970 +0000
1591 1591 summary: m1
1592 1592
1593 1593 $ hg push ../dest
1594 1594 pushing to ../dest
1595 1595 searching for changes
1596 1596 adding changesets
1597 1597 adding manifests
1598 1598 adding file changes
1599 1599 added 1 changesets with 1 changes to 1 files
1600 1600
1601 1601 exit code with nothing outgoing (issue3611)
1602 1602 $ hg outgoing ../dest
1603 1603 comparing with ../dest
1604 1604 searching for changes
1605 1605 no changes found
1606 1606 [1]
1607 1607 $ cd ..
1608 1608
1609 1609 #if serve
1610 1610 $ hg serve -R r4 -d -p $HGPORT2 --pid-file hg.pid
1611 1611 $ cat hg.pid >> $DAEMON_PIDS
1612 1612 $ hg --config extensions.largefiles=! clone http://localhost:$HGPORT2 r5
1613 1613 abort: remote error:
1614 1614
1615 1615 This repository uses the largefiles extension.
1616 1616
1617 1617 Please enable it in your Mercurial config file.
1618 1618 [255]
1619 1619
1620 1620 used all HGPORTs, kill all daemons
1621 1621 $ "$TESTDIR/killdaemons.py" $DAEMON_PIDS
1622 1622 #endif
1623 1623
1624 1624 vanilla clients locked out from largefiles ssh repos
1625 1625 $ hg --config extensions.largefiles=! clone -e "python \"$TESTDIR/dummyssh\"" ssh://user@dummy/r4 r5
1626 1626 abort: remote error:
1627 1627
1628 1628 This repository uses the largefiles extension.
1629 1629
1630 1630 Please enable it in your Mercurial config file.
1631 1631 [255]
1632 1632
1633 1633 #if serve
1634 1634
1635 1635 largefiles clients refuse to push largefiles repos to vanilla servers
1636 1636 $ mkdir r6
1637 1637 $ cd r6
1638 1638 $ hg init
1639 1639 $ echo c1 > f1
1640 1640 $ hg add f1
1641 1641 $ hg commit -m "m1"
1642 1642 Invoking status precommit hook
1643 1643 A f1
1644 1644 $ cat >> .hg/hgrc <<!
1645 1645 > [web]
1646 1646 > push_ssl = false
1647 1647 > allow_push = *
1648 1648 > !
1649 1649 $ cd ..
1650 1650 $ hg clone r6 r7
1651 1651 updating to branch default
1652 1652 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1653 1653 $ cd r7
1654 1654 $ echo c2 > f2
1655 1655 $ hg add --large f2
1656 1656 $ hg commit -m "m2"
1657 1657 Invoking status precommit hook
1658 1658 A f2
1659 1659 $ hg --config extensions.largefiles=! -R ../r6 serve -d -p $HGPORT --pid-file ../hg.pid
1660 1660 $ cat ../hg.pid >> $DAEMON_PIDS
1661 1661 $ hg push http://localhost:$HGPORT
1662 1662 pushing to http://localhost:$HGPORT/
1663 1663 searching for changes
1664 1664 abort: http://localhost:$HGPORT/ does not appear to be a largefile store
1665 1665 [255]
1666 1666 $ cd ..
1667 1667
1668 1668 putlfile errors are shown (issue3123)
1669 1669 Corrupt the cached largefile in r7 and move it out of the servers usercache
1670 1670 $ mv r7/.hg/largefiles/4cdac4d8b084d0b599525cf732437fb337d422a8 .
1671 1671 $ echo 'client side corruption' > r7/.hg/largefiles/4cdac4d8b084d0b599525cf732437fb337d422a8
1672 1672 $ rm "$USERCACHE/4cdac4d8b084d0b599525cf732437fb337d422a8"
1673 1673 $ hg init empty
1674 1674 $ hg serve -R empty -d -p $HGPORT1 --pid-file hg.pid \
1675 1675 > --config 'web.allow_push=*' --config web.push_ssl=False
1676 1676 $ cat hg.pid >> $DAEMON_PIDS
1677 1677 $ hg push -R r7 http://localhost:$HGPORT1
1678 1678 pushing to http://localhost:$HGPORT1/
1679 1679 searching for changes
1680 1680 remote: largefiles: failed to put 4cdac4d8b084d0b599525cf732437fb337d422a8 into store: largefile contents do not match hash
1681 1681 abort: remotestore: could not put $TESTTMP/r7/.hg/largefiles/4cdac4d8b084d0b599525cf732437fb337d422a8 to remote store http://localhost:$HGPORT1/ (glob)
1682 1682 [255]
1683 1683 $ mv 4cdac4d8b084d0b599525cf732437fb337d422a8 r7/.hg/largefiles/4cdac4d8b084d0b599525cf732437fb337d422a8
1684 1684 Push of file that exists on server but is corrupted - magic healing would be nice ... but too magic
1685 1685 $ echo "server side corruption" > empty/.hg/largefiles/4cdac4d8b084d0b599525cf732437fb337d422a8
1686 1686 $ hg push -R r7 http://localhost:$HGPORT1
1687 1687 pushing to http://localhost:$HGPORT1/
1688 1688 searching for changes
1689 1689 remote: adding changesets
1690 1690 remote: adding manifests
1691 1691 remote: adding file changes
1692 1692 remote: added 2 changesets with 2 changes to 2 files
1693 1693 $ cat empty/.hg/largefiles/4cdac4d8b084d0b599525cf732437fb337d422a8
1694 1694 server side corruption
1695 1695 $ rm -rf empty
1696 1696
1697 1697 Push a largefiles repository to a served empty repository
1698 1698 $ hg init r8
1699 1699 $ echo c3 > r8/f1
1700 1700 $ hg add --large r8/f1 -R r8
1701 1701 $ hg commit -m "m1" -R r8
1702 1702 Invoking status precommit hook
1703 1703 A f1
1704 1704 $ hg init empty
1705 1705 $ hg serve -R empty -d -p $HGPORT2 --pid-file hg.pid \
1706 1706 > --config 'web.allow_push=*' --config web.push_ssl=False
1707 1707 $ cat hg.pid >> $DAEMON_PIDS
1708 1708 $ rm "${USERCACHE}"/*
1709 1709 $ hg push -R r8 http://localhost:$HGPORT2/#default
1710 1710 pushing to http://localhost:$HGPORT2/
1711 1711 searching for changes
1712 1712 remote: adding changesets
1713 1713 remote: adding manifests
1714 1714 remote: adding file changes
1715 1715 remote: added 1 changesets with 1 changes to 1 files
1716 1716 $ [ -f "${USERCACHE}"/02a439e5c31c526465ab1a0ca1f431f76b827b90 ]
1717 1717 $ [ -f empty/.hg/largefiles/02a439e5c31c526465ab1a0ca1f431f76b827b90 ]
1718 1718
1719 1719 Clone over http, no largefiles pulled on clone.
1720 1720
1721 1721 $ hg clone http://localhost:$HGPORT2/#default http-clone -U
1722 1722 adding changesets
1723 1723 adding manifests
1724 1724 adding file changes
1725 1725 added 1 changesets with 1 changes to 1 files
1726 1726
1727 1727 test 'verify' with remotestore:
1728 1728
1729 1729 $ rm "${USERCACHE}"/02a439e5c31c526465ab1a0ca1f431f76b827b90
1730 1730 $ mv empty/.hg/largefiles/02a439e5c31c526465ab1a0ca1f431f76b827b90 .
1731 1731 $ hg -R http-clone verify --large --lfa
1732 1732 checking changesets
1733 1733 checking manifests
1734 1734 crosschecking files in changesets and manifests
1735 1735 checking files
1736 1736 1 files, 1 changesets, 1 total revisions
1737 1737 searching 1 changesets for largefiles
1738 1738 changeset 0:cf03e5bb9936: f1 missing
1739 1739 verified existence of 1 revisions of 1 largefiles
1740 1740 [1]
1741 1741 $ mv 02a439e5c31c526465ab1a0ca1f431f76b827b90 empty/.hg/largefiles/
1742 1742 $ hg -R http-clone -q verify --large --lfa
1743 1743
1744 1744 largefiles pulled on update - a largefile missing on the server:
1745 1745 $ mv empty/.hg/largefiles/02a439e5c31c526465ab1a0ca1f431f76b827b90 .
1746 1746 $ hg -R http-clone up --config largefiles.usercache=http-clone-usercache
1747 1747 getting changed largefiles
1748 1748 f1: largefile 02a439e5c31c526465ab1a0ca1f431f76b827b90 not available from http://localhost:$HGPORT2/
1749 1749 0 largefiles updated, 0 removed
1750 1750 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1751 1751 $ hg -R http-clone st
1752 1752 ! f1
1753 1753 $ hg -R http-clone up -Cqr null
1754 1754
1755 1755 largefiles pulled on update - a largefile corrupted on the server:
1756 1756 $ echo corruption > empty/.hg/largefiles/02a439e5c31c526465ab1a0ca1f431f76b827b90
1757 1757 $ hg -R http-clone up --config largefiles.usercache=http-clone-usercache
1758 1758 getting changed largefiles
1759 1759 f1: data corruption (expected 02a439e5c31c526465ab1a0ca1f431f76b827b90, got 6a7bb2556144babe3899b25e5428123735bb1e27)
1760 1760 0 largefiles updated, 0 removed
1761 1761 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1762 1762 $ hg -R http-clone st
1763 1763 ! f1
1764 1764 $ [ ! -f http-clone/.hg/largefiles/02a439e5c31c526465ab1a0ca1f431f76b827b90 ]
1765 1765 $ [ ! -f http-clone/f1 ]
1766 1766 $ [ ! -f http-clone-usercache ]
1767 1767 $ hg -R http-clone verify --large --lfc
1768 1768 checking changesets
1769 1769 checking manifests
1770 1770 crosschecking files in changesets and manifests
1771 1771 checking files
1772 1772 1 files, 1 changesets, 1 total revisions
1773 1773 searching 1 changesets for largefiles
1774 1774 verified contents of 1 revisions of 1 largefiles
1775 1775 $ hg -R http-clone up -Cqr null
1776 1776
1777 1777 largefiles pulled on update - no server side problems:
1778 1778 $ mv 02a439e5c31c526465ab1a0ca1f431f76b827b90 empty/.hg/largefiles/
1779 1779 $ hg -R http-clone --debug up --config largefiles.usercache=http-clone-usercache
1780 1780 resolving manifests
1781 1781 branchmerge: False, force: False, partial: False
1782 1782 ancestor: 000000000000, local: 000000000000+, remote: cf03e5bb9936
1783 1783 .hglf/f1: remote created -> g
1784 1784 getting .hglf/f1
1785 1785 updating: .hglf/f1 1/1 files (100.00%)
1786 1786 getting changed largefiles
1787 1787 using http://localhost:$HGPORT2/
1788 1788 sending capabilities command
1789 1789 sending batch command
1790 1790 getting largefiles: 0/1 lfile (0.00%)
1791 1791 getting f1:02a439e5c31c526465ab1a0ca1f431f76b827b90
1792 1792 sending getlfile command
1793 1793 found 02a439e5c31c526465ab1a0ca1f431f76b827b90 in store
1794 1794 1 largefiles updated, 0 removed
1795 1795 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1796 1796
1797 1797 $ ls http-clone-usercache/*
1798 1798 http-clone-usercache/02a439e5c31c526465ab1a0ca1f431f76b827b90
1799 1799
1800 1800 $ rm -rf empty http-clone*
1801 1801
1802 1802 used all HGPORTs, kill all daemons
1803 1803 $ "$TESTDIR/killdaemons.py" $DAEMON_PIDS
1804 1804
1805 1805 #endif
1806 1806
1807 1807
1808 1808 #if unix-permissions
1809 1809
1810 1810 Clone a local repository owned by another user
1811 1811 We have to simulate that here by setting $HOME and removing write permissions
1812 1812 $ ORIGHOME="$HOME"
1813 1813 $ mkdir alice
1814 1814 $ HOME="`pwd`/alice"
1815 1815 $ cd alice
1816 1816 $ hg init pubrepo
1817 1817 $ cd pubrepo
1818 1818 $ dd if=/dev/zero bs=1k count=11k > a-large-file 2> /dev/null
1819 1819 $ hg add --large a-large-file
1820 1820 $ hg commit -m "Add a large file"
1821 1821 Invoking status precommit hook
1822 1822 A a-large-file
1823 1823 $ cd ..
1824 1824 $ chmod -R a-w pubrepo
1825 1825 $ cd ..
1826 1826 $ mkdir bob
1827 1827 $ HOME="`pwd`/bob"
1828 1828 $ cd bob
1829 1829 $ hg clone --pull ../alice/pubrepo pubrepo
1830 1830 requesting all changes
1831 1831 adding changesets
1832 1832 adding manifests
1833 1833 adding file changes
1834 1834 added 1 changesets with 1 changes to 1 files
1835 1835 updating to branch default
1836 1836 getting changed largefiles
1837 1837 1 largefiles updated, 0 removed
1838 1838 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1839 1839 $ cd ..
1840 1840 $ chmod -R u+w alice/pubrepo
1841 1841 $ HOME="$ORIGHOME"
1842 1842
1843 1843 #endif
1844 1844
1845 1845 #if symlink
1846 1846
1847 1847 Symlink to a large largefile should behave the same as a symlink to a normal file
1848 1848 $ hg init largesymlink
1849 1849 $ cd largesymlink
1850 1850 $ dd if=/dev/zero bs=1k count=10k of=largefile 2>/dev/null
1851 1851 $ hg add --large largefile
1852 1852 $ hg commit -m "commit a large file"
1853 1853 Invoking status precommit hook
1854 1854 A largefile
1855 1855 $ ln -s largefile largelink
1856 1856 $ hg add largelink
1857 1857 $ hg commit -m "commit a large symlink"
1858 1858 Invoking status precommit hook
1859 1859 A largelink
1860 1860 $ rm -f largelink
1861 1861 $ hg up >/dev/null
1862 1862 $ test -f largelink
1863 1863 [1]
1864 1864 $ test -L largelink
1865 1865 [1]
1866 1866 $ rm -f largelink # make next part of the test independent of the previous
1867 1867 $ hg up -C >/dev/null
1868 1868 $ test -f largelink
1869 1869 $ test -L largelink
1870 1870 $ cd ..
1871 1871
1872 1872 #endif
1873 1873
1874 1874 test for pattern matching on 'hg status':
1875 1875 to boost performance, largefiles checks whether specified patterns are
1876 1876 related to largefiles in working directory (NOT to STANDIN) or not.
1877 1877
1878 1878 $ hg init statusmatch
1879 1879 $ cd statusmatch
1880 1880
1881 1881 $ mkdir -p a/b/c/d
1882 1882 $ echo normal > a/b/c/d/e.normal.txt
1883 1883 $ hg add a/b/c/d/e.normal.txt
1884 1884 $ echo large > a/b/c/d/e.large.txt
1885 1885 $ hg add --large a/b/c/d/e.large.txt
1886 1886 $ mkdir -p a/b/c/x
1887 1887 $ echo normal > a/b/c/x/y.normal.txt
1888 1888 $ hg add a/b/c/x/y.normal.txt
1889 1889 $ hg commit -m 'add files'
1890 1890 Invoking status precommit hook
1891 1891 A a/b/c/d/e.large.txt
1892 1892 A a/b/c/d/e.normal.txt
1893 1893 A a/b/c/x/y.normal.txt
1894 1894
1895 1895 (1) no pattern: no performance boost
1896 1896 $ hg status -A
1897 1897 C a/b/c/d/e.large.txt
1898 1898 C a/b/c/d/e.normal.txt
1899 1899 C a/b/c/x/y.normal.txt
1900 1900
1901 1901 (2) pattern not related to largefiles: performance boost
1902 1902 $ hg status -A a/b/c/x
1903 1903 C a/b/c/x/y.normal.txt
1904 1904
1905 1905 (3) pattern related to largefiles: no performance boost
1906 1906 $ hg status -A a/b/c/d
1907 1907 C a/b/c/d/e.large.txt
1908 1908 C a/b/c/d/e.normal.txt
1909 1909
1910 1910 (4) pattern related to STANDIN (not to largefiles): performance boost
1911 1911 $ hg status -A .hglf/a
1912 1912 C .hglf/a/b/c/d/e.large.txt
1913 1913
1914 1914 (5) mixed case: no performance boost
1915 1915 $ hg status -A a/b/c/x a/b/c/d
1916 1916 C a/b/c/d/e.large.txt
1917 1917 C a/b/c/d/e.normal.txt
1918 1918 C a/b/c/x/y.normal.txt
1919 1919
1920 1920 verify that largefiles doesn't break filesets
1921 1921
1922 1922 $ hg log --rev . --exclude "set:binary()"
1923 1923 changeset: 0:41bd42f10efa
1924 1924 tag: tip
1925 1925 user: test
1926 1926 date: Thu Jan 01 00:00:00 1970 +0000
1927 1927 summary: add files
1928 1928
1929 1929 verify that large files in subrepos handled properly
1930 1930 $ hg init subrepo
1931 1931 $ echo "subrepo = subrepo" > .hgsub
1932 1932 $ hg add .hgsub
1933 1933 $ hg ci -m "add subrepo"
1934 1934 Invoking status precommit hook
1935 1935 A .hgsub
1936 1936 ? .hgsubstate
1937 1937 $ echo "rev 1" > subrepo/large.txt
1938 1938 $ hg -R subrepo add --large subrepo/large.txt
1939 1939 $ hg sum
1940 1940 parent: 1:8ee150ea2e9c tip
1941 1941 add subrepo
1942 1942 branch: default
1943 1943 commit: 1 subrepos
1944 1944 update: (current)
1945 1945 $ hg st
1946 1946 $ hg st -S
1947 1947 A subrepo/large.txt
1948 1948 $ hg ci -S -m "commit top repo"
1949 1949 committing subrepository subrepo
1950 1950 Invoking status precommit hook
1951 1951 A large.txt
1952 1952 Invoking status precommit hook
1953 1953 M .hgsubstate
1954 1954 # No differences
1955 1955 $ hg st -S
1956 1956 $ hg sum
1957 1957 parent: 2:ce4cd0c527a6 tip
1958 1958 commit top repo
1959 1959 branch: default
1960 1960 commit: (clean)
1961 1961 update: (current)
1962 1962 $ echo "rev 2" > subrepo/large.txt
1963 1963 $ hg st -S
1964 1964 M subrepo/large.txt
1965 1965 $ hg sum
1966 1966 parent: 2:ce4cd0c527a6 tip
1967 1967 commit top repo
1968 1968 branch: default
1969 1969 commit: 1 subrepos
1970 1970 update: (current)
1971 1971 $ hg ci -m "this commit should fail without -S"
1972 1972 abort: uncommitted changes in subrepo subrepo
1973 1973 (use --subrepos for recursive commit)
1974 1974 [255]
1975 1975
1976 1976 Add a normal file to the subrepo, then test archiving
1977 1977
1978 1978 $ echo 'normal file' > subrepo/normal.txt
1979 1979 $ hg -R subrepo add subrepo/normal.txt
1980 1980
1981 1981 Lock in subrepo, otherwise the change isn't archived
1982 1982
1983 1983 $ hg ci -S -m "add normal file to top level"
1984 1984 committing subrepository subrepo
1985 1985 Invoking status precommit hook
1986 1986 M large.txt
1987 1987 A normal.txt
1988 1988 Invoking status precommit hook
1989 1989 M .hgsubstate
1990 1990 $ hg archive -S ../lf_subrepo_archive
1991 1991 $ find ../lf_subrepo_archive | sort
1992 1992 ../lf_subrepo_archive
1993 1993 ../lf_subrepo_archive/.hg_archival.txt
1994 1994 ../lf_subrepo_archive/.hgsub
1995 1995 ../lf_subrepo_archive/.hgsubstate
1996 1996 ../lf_subrepo_archive/a
1997 1997 ../lf_subrepo_archive/a/b
1998 1998 ../lf_subrepo_archive/a/b/c
1999 1999 ../lf_subrepo_archive/a/b/c/d
2000 2000 ../lf_subrepo_archive/a/b/c/d/e.large.txt
2001 2001 ../lf_subrepo_archive/a/b/c/d/e.normal.txt
2002 2002 ../lf_subrepo_archive/a/b/c/x
2003 2003 ../lf_subrepo_archive/a/b/c/x/y.normal.txt
2004 2004 ../lf_subrepo_archive/subrepo
2005 2005 ../lf_subrepo_archive/subrepo/large.txt
2006 2006 ../lf_subrepo_archive/subrepo/normal.txt
2007 2007
2008 2008 Test update with subrepos.
2009 2009
2010 2010 $ hg update 0
2011 2011 getting changed largefiles
2012 2012 0 largefiles updated, 1 removed
2013 2013 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
2014 2014 $ hg status -S
2015 2015 $ hg update tip
2016 2016 getting changed largefiles
2017 2017 1 largefiles updated, 0 removed
2018 2018 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
2019 2019 $ hg status -S
2020 2020 # modify a large file
2021 2021 $ echo "modified" > subrepo/large.txt
2022 2022 $ hg st -S
2023 2023 M subrepo/large.txt
2024 2024 # update -C should revert the change.
2025 2025 $ hg update -C
2026 2026 getting changed largefiles
2027 2027 1 largefiles updated, 0 removed
2028 2028 getting changed largefiles
2029 2029 0 largefiles updated, 0 removed
2030 2030 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
2031 2031 $ hg status -S
2032 2032
2033 2033 Test archiving a revision that references a subrepo that is not yet
2034 2034 cloned (see test-subrepo-recursion.t):
2035 2035
2036 2036 $ hg clone -U . ../empty
2037 2037 $ cd ../empty
2038 2038 $ hg archive --subrepos -r tip ../archive.tar.gz
2039 2039 cloning subrepo subrepo from $TESTTMP/statusmatch/subrepo
2040 2040 $ cd ..
2041 2041
2042 2042 Test that addremove picks up largefiles prior to the initial commit (issue3541)
2043 2043
2044 2044 $ hg init addrm2
2045 2045 $ cd addrm2
2046 2046 $ touch large.dat
2047 2047 $ touch large2.dat
2048 2048 $ touch normal
2049 2049 $ hg add --large large.dat
2050 2050 $ hg addremove -v
2051 2051 adding large2.dat as a largefile
2052 2052 adding normal
2053 2053
2054 2054 Test that forgetting all largefiles reverts to islfilesrepo() == False
2055 2055 (addremove will add *.dat as normal files now)
2056 2056 $ hg forget large.dat
2057 2057 $ hg forget large2.dat
2058 2058 $ hg addremove -v
2059 2059 adding large.dat
2060 2060 adding large2.dat
2061 2061
2062 2062 Test commit's addremove option prior to the first commit
2063 2063 $ hg forget large.dat
2064 2064 $ hg forget large2.dat
2065 2065 $ hg add --large large.dat
2066 2066 $ hg ci -Am "commit"
2067 2067 adding large2.dat as a largefile
2068 2068 Invoking status precommit hook
2069 2069 A large.dat
2070 2070 A large2.dat
2071 2071 A normal
2072 2072 $ find .hglf | sort
2073 2073 .hglf
2074 2074 .hglf/large.dat
2075 2075 .hglf/large2.dat
2076 2076
2077 2077 Test actions on largefiles using relative paths from subdir
2078 2078
2079 2079 $ mkdir sub
2080 2080 $ cd sub
2081 2081 $ echo anotherlarge > anotherlarge
2082 2082 $ hg add --large anotherlarge
2083 2083 $ hg st
2084 2084 A sub/anotherlarge
2085 2085 $ hg st anotherlarge
2086 2086 A anotherlarge
2087 2087 $ hg commit -m anotherlarge anotherlarge
2088 2088 Invoking status precommit hook
2089 2089 A sub/anotherlarge
2090 2090 $ hg log anotherlarge
2091 2091 changeset: 1:9627a577c5e9
2092 2092 tag: tip
2093 2093 user: test
2094 2094 date: Thu Jan 01 00:00:00 1970 +0000
2095 2095 summary: anotherlarge
2096 2096
2097 2097 $ echo more >> anotherlarge
2098 2098 $ hg st .
2099 2099 M anotherlarge
2100 2100 $ hg cat anotherlarge
2101 2101 anotherlarge
2102 2102 $ hg revert anotherlarge
2103 2103 $ hg st
2104 2104 ? sub/anotherlarge.orig
2105 2105 $ cd ..
2106 2106
2107 2107 $ cd ..
2108 2108
2109 2109 issue3651: summary/outgoing with largefiles shows "no remote repo"
2110 2110 unexpectedly
2111 2111
2112 2112 $ mkdir issue3651
2113 2113 $ cd issue3651
2114 2114
2115 2115 $ hg init src
2116 2116 $ echo a > src/a
2117 2117 $ hg -R src add --large src/a
2118 2118 $ hg -R src commit -m '#0'
2119 2119 Invoking status precommit hook
2120 2120 A a
2121 2121
2122 2122 check messages when no remote repository is specified:
2123 2123 "no remote repo" route for "hg outgoing --large" is not tested here,
2124 2124 because it can't be reproduced easily.
2125 2125
2126 2126 $ hg init clone1
2127 2127 $ hg -R clone1 -q pull src
2128 2128 $ hg -R clone1 -q update
2129 2129 $ hg -R clone1 paths | grep default
2130 2130 [1]
2131 2131
2132 2132 $ hg -R clone1 summary --large
2133 2133 parent: 0:fc0bd45326d3 tip
2134 2134 #0
2135 2135 branch: default
2136 2136 commit: (clean)
2137 2137 update: (current)
2138 2138 largefiles: (no remote repo)
2139 2139
2140 2140 check messages when there is no files to upload:
2141 2141
2142 2142 $ hg -q clone src clone2
2143 2143 $ hg -R clone2 paths | grep default
2144 2144 default = $TESTTMP/issue3651/src (glob)
2145 2145
2146 2146 $ hg -R clone2 summary --large
2147 2147 parent: 0:fc0bd45326d3 tip
2148 2148 #0
2149 2149 branch: default
2150 2150 commit: (clean)
2151 2151 update: (current)
2152 searching for changes
2153 2152 largefiles: (no files to upload)
2154 2153 $ hg -R clone2 outgoing --large
2155 2154 comparing with $TESTTMP/issue3651/src (glob)
2156 2155 searching for changes
2157 2156 no changes found
2158 2157 searching for changes
2159 2158 largefiles: no files to upload
2160 2159 [1]
2161 2160
2162 2161 check messages when there are files to upload:
2163 2162
2164 2163 $ echo b > clone2/b
2165 2164 $ hg -R clone2 add --large clone2/b
2166 2165 $ hg -R clone2 commit -m '#1'
2167 2166 Invoking status precommit hook
2168 2167 A b
2169 2168 $ hg -R clone2 summary --large
2170 2169 parent: 1:1acbe71ce432 tip
2171 2170 #1
2172 2171 branch: default
2173 2172 commit: (clean)
2174 2173 update: (current)
2175 searching for changes
2176 2174 largefiles: 1 to upload
2177 2175 $ hg -R clone2 outgoing --large
2178 2176 comparing with $TESTTMP/issue3651/src (glob)
2179 2177 searching for changes
2180 2178 changeset: 1:1acbe71ce432
2181 2179 tag: tip
2182 2180 user: test
2183 2181 date: Thu Jan 01 00:00:00 1970 +0000
2184 2182 summary: #1
2185 2183
2186 2184 searching for changes
2187 2185 largefiles to upload:
2188 2186 b
2189 2187
2190 2188
2191 2189 $ cd ..
2192 2190
2193 2191 merge action 'd' for 'local renamed directory to d2/g' which has no filename
2194 2192
2195 2193 $ hg init merge-action
2196 2194 $ cd merge-action
2197 2195 $ touch l
2198 2196 $ hg add --large l
2199 2197 $ mkdir d1
2200 2198 $ touch d1/f
2201 2199 $ hg ci -Aqm0
2202 2200 Invoking status precommit hook
2203 2201 A d1/f
2204 2202 A l
2205 2203 $ echo > d1/f
2206 2204 $ touch d1/g
2207 2205 $ hg ci -Aqm1
2208 2206 Invoking status precommit hook
2209 2207 M d1/f
2210 2208 A d1/g
2211 2209 $ hg up -qr0
2212 2210 $ hg mv d1 d2
2213 2211 moving d1/f to d2/f (glob)
2214 2212 $ hg ci -qm2
2215 2213 Invoking status precommit hook
2216 2214 A d2/f
2217 2215 R d1/f
2218 2216 $ hg merge
2219 2217 merging d2/f and d1/f to d2/f
2220 2218 1 files updated, 1 files merged, 0 files removed, 0 files unresolved
2221 2219 (branch merge, don't forget to commit)
2222 2220 getting changed largefiles
2223 2221 0 largefiles updated, 0 removed
2224 2222 $ cd ..
2225 2223
2226 2224
2227 2225 Merge conflicts:
2228 2226
2229 2227 $ hg init merge
2230 2228 $ cd merge
2231 2229 $ echo 0 > f-different
2232 2230 $ echo 0 > f-same
2233 2231 $ echo 0 > f-unchanged-1
2234 2232 $ echo 0 > f-unchanged-2
2235 2233 $ hg add --large *
2236 2234 $ hg ci -m0
2237 2235 Invoking status precommit hook
2238 2236 A f-different
2239 2237 A f-same
2240 2238 A f-unchanged-1
2241 2239 A f-unchanged-2
2242 2240 $ echo tmp1 > f-unchanged-1
2243 2241 $ echo tmp1 > f-unchanged-2
2244 2242 $ echo tmp1 > f-same
2245 2243 $ hg ci -m1
2246 2244 Invoking status precommit hook
2247 2245 M f-same
2248 2246 M f-unchanged-1
2249 2247 M f-unchanged-2
2250 2248 $ echo 2 > f-different
2251 2249 $ echo 0 > f-unchanged-1
2252 2250 $ echo 1 > f-unchanged-2
2253 2251 $ echo 1 > f-same
2254 2252 $ hg ci -m2
2255 2253 Invoking status precommit hook
2256 2254 M f-different
2257 2255 M f-same
2258 2256 M f-unchanged-1
2259 2257 M f-unchanged-2
2260 2258 $ hg up -qr0
2261 2259 $ echo tmp2 > f-unchanged-1
2262 2260 $ echo tmp2 > f-unchanged-2
2263 2261 $ echo tmp2 > f-same
2264 2262 $ hg ci -m3
2265 2263 Invoking status precommit hook
2266 2264 M f-same
2267 2265 M f-unchanged-1
2268 2266 M f-unchanged-2
2269 2267 created new head
2270 2268 $ echo 1 > f-different
2271 2269 $ echo 1 > f-unchanged-1
2272 2270 $ echo 0 > f-unchanged-2
2273 2271 $ echo 1 > f-same
2274 2272 $ hg ci -m4
2275 2273 Invoking status precommit hook
2276 2274 M f-different
2277 2275 M f-same
2278 2276 M f-unchanged-1
2279 2277 M f-unchanged-2
2280 2278 $ hg merge
2281 2279 largefile f-different has a merge conflict
2282 2280 ancestor was 09d2af8dd22201dd8d48e5dcfcaed281ff9422c7
2283 2281 keep (l)ocal e5fa44f2b31c1fb553b6021e7360d07d5d91ff5e or
2284 2282 take (o)ther 7448d8798a4380162d4b56f9b452e2f6f9e24e7a? l
2285 2283 0 files updated, 4 files merged, 0 files removed, 0 files unresolved
2286 2284 (branch merge, don't forget to commit)
2287 2285 getting changed largefiles
2288 2286 1 largefiles updated, 0 removed
2289 2287 $ cat f-different
2290 2288 1
2291 2289 $ cat f-same
2292 2290 1
2293 2291 $ cat f-unchanged-1
2294 2292 1
2295 2293 $ cat f-unchanged-2
2296 2294 1
2297 2295 $ cd ..
2298 2296
2299 2297 Check whether "largefiles" feature is supported only in repositories
2300 2298 enabling largefiles extension.
2301 2299
2302 2300 $ mkdir individualenabling
2303 2301 $ cd individualenabling
2304 2302
2305 2303 $ hg init enabledlocally
2306 2304 $ echo large > enabledlocally/large
2307 2305 $ hg -R enabledlocally add --large enabledlocally/large
2308 2306 $ hg -R enabledlocally commit -m '#0'
2309 2307 Invoking status precommit hook
2310 2308 A large
2311 2309
2312 2310 $ hg init notenabledlocally
2313 2311 $ echo large > notenabledlocally/large
2314 2312 $ hg -R notenabledlocally add --large notenabledlocally/large
2315 2313 $ hg -R notenabledlocally commit -m '#0'
2316 2314 Invoking status precommit hook
2317 2315 A large
2318 2316
2319 2317 $ cat >> $HGRCPATH <<EOF
2320 2318 > [extensions]
2321 2319 > # disable globally
2322 2320 > largefiles=!
2323 2321 > EOF
2324 2322 $ cat >> enabledlocally/.hg/hgrc <<EOF
2325 2323 > [extensions]
2326 2324 > # enable locally
2327 2325 > largefiles=
2328 2326 > EOF
2329 2327 $ hg -R enabledlocally root
2330 2328 $TESTTMP/individualenabling/enabledlocally (glob)
2331 2329 $ hg -R notenabledlocally root
2332 2330 abort: repository requires features unknown to this Mercurial: largefiles!
2333 2331 (see http://mercurial.selenic.com/wiki/MissingRequirement for more information)
2334 2332 [255]
2335 2333
2336 2334 $ hg init push-dst
2337 2335 $ hg -R enabledlocally push push-dst
2338 2336 pushing to push-dst
2339 2337 abort: required features are not supported in the destination: largefiles
2340 2338 [255]
2341 2339
2342 2340 $ hg init pull-src
2343 2341 $ hg -R pull-src pull enabledlocally
2344 2342 pulling from enabledlocally
2345 2343 abort: required features are not supported in the destination: largefiles
2346 2344 [255]
2347 2345
2348 2346 $ hg clone enabledlocally clone-dst
2349 2347 abort: repository requires features unknown to this Mercurial: largefiles!
2350 2348 (see http://mercurial.selenic.com/wiki/MissingRequirement for more information)
2351 2349 [255]
2352 2350 $ test -d clone-dst
2353 2351 [1]
2354 2352 $ hg clone --pull enabledlocally clone-pull-dst
2355 2353 abort: required features are not supported in the destination: largefiles
2356 2354 [255]
2357 2355 $ test -d clone-pull-dst
2358 2356 [1]
2359 2357
2360 2358 #if serve
2361 2359
2362 2360 Test largefiles specific peer setup, when largefiles is enabled
2363 2361 locally (issue4109)
2364 2362
2365 2363 $ hg showconfig extensions | grep largefiles
2366 2364 extensions.largefiles=!
2367 2365 $ mkdir -p $TESTTMP/individualenabling/usercache
2368 2366
2369 2367 $ hg serve -R enabledlocally -d -p $HGPORT --pid-file hg.pid
2370 2368 $ cat hg.pid >> $DAEMON_PIDS
2371 2369
2372 2370 $ hg init pull-dst
2373 2371 $ cat > pull-dst/.hg/hgrc <<EOF
2374 2372 > [extensions]
2375 2373 > # enable locally
2376 2374 > largefiles=
2377 2375 > [largefiles]
2378 2376 > # ignore system cache to force largefiles specific wire proto access
2379 2377 > usercache=$TESTTMP/individualenabling/usercache
2380 2378 > EOF
2381 2379 $ hg -R pull-dst -q pull -u http://localhost:$HGPORT
2382 2380
2383 2381 $ "$TESTDIR/killdaemons.py" $DAEMON_PIDS
2384 2382 #endif
2385 2383
2386 2384 $ cd ..
General Comments 0
You need to be logged in to leave comments. Login now