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