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