Show More
@@ -438,91 +438,93 b' def updatelfiles(ui, repo, filelist=None' | |||||
438 | if filelist is not None: |
|
438 | if filelist is not None: | |
439 | lfiles = [f for f in lfiles if f in filelist] |
|
439 | lfiles = [f for f in lfiles if f in filelist] | |
440 |
|
440 | |||
441 |
|
|
441 | update = {} | |
442 | if printmessage and lfiles: |
|
442 | updated, removed = 0, 0 | |
443 | ui.status(_('getting changed largefiles\n')) |
|
443 | for lfile in lfiles: | |
444 | printed = True |
|
444 | abslfile = repo.wjoin(lfile) | |
|
445 | absstandin = repo.wjoin(lfutil.standin(lfile)) | |||
|
446 | if os.path.exists(absstandin): | |||
|
447 | if (os.path.exists(absstandin + '.orig') and | |||
|
448 | os.path.exists(abslfile)): | |||
|
449 | shutil.copyfile(abslfile, abslfile + '.orig') | |||
|
450 | expecthash = lfutil.readstandin(repo, lfile) | |||
|
451 | if (expecthash != '' and | |||
|
452 | (not os.path.exists(abslfile) or | |||
|
453 | expecthash != lfutil.hashfile(abslfile))): | |||
|
454 | if lfile not in repo[None]: # not switched to normal file | |||
|
455 | util.unlinkpath(abslfile, ignoremissing=True) | |||
|
456 | # use normallookup() to allocate entry in largefiles | |||
|
457 | # dirstate, because lack of it misleads | |||
|
458 | # lfilesrepo.status() into recognition that such cache | |||
|
459 | # missing files are REMOVED. | |||
|
460 | lfdirstate.normallookup(lfile) | |||
|
461 | update[lfile] = expecthash | |||
|
462 | else: | |||
|
463 | # Remove lfiles for which the standin is deleted, unless the | |||
|
464 | # lfile is added to the repository again. This happens when a | |||
|
465 | # largefile is converted back to a normal file: the standin | |||
|
466 | # disappears, but a new (normal) file appears as the lfile. | |||
|
467 | if (os.path.exists(abslfile) and | |||
|
468 | repo.dirstate.normalize(lfile) not in repo[None]): | |||
|
469 | util.unlinkpath(abslfile) | |||
|
470 | removed += 1 | |||
|
471 | ||||
|
472 | # largefile processing might be slow and be interrupted - be prepared | |||
|
473 | lfdirstate.write() | |||
|
474 | ||||
|
475 | if lfiles: | |||
|
476 | if printmessage: | |||
|
477 | ui.status(_('getting changed largefiles\n')) | |||
445 | cachelfiles(ui, repo, None, lfiles) |
|
478 | cachelfiles(ui, repo, None, lfiles) | |
446 |
|
479 | |||
447 | updated, removed = 0, 0 |
|
480 | for lfile in lfiles: | |
448 | for f in lfiles: |
|
481 | update1 = 0 | |
449 | i = _updatelfile(repo, lfdirstate, f) |
|
482 | ||
450 | if i: |
|
483 | expecthash = update.get(lfile) | |
451 |
|
|
484 | if expecthash: | |
452 | updated += i |
|
485 | if not lfutil.copyfromcache(repo, expecthash, lfile): | |
|
486 | # failed ... but already removed and set to normallookup | |||
|
487 | continue | |||
|
488 | # Synchronize largefile dirstate to the last modified | |||
|
489 | # time of the file | |||
|
490 | lfdirstate.normal(lfile) | |||
|
491 | update1 = 1 | |||
|
492 | ||||
|
493 | # copy the state of largefile standin from the repository's | |||
|
494 | # dirstate to its state in the lfdirstate. | |||
|
495 | abslfile = repo.wjoin(lfile) | |||
|
496 | absstandin = repo.wjoin(lfutil.standin(lfile)) | |||
|
497 | if os.path.exists(absstandin): | |||
|
498 | mode = os.stat(absstandin).st_mode | |||
|
499 | if mode != os.stat(abslfile).st_mode: | |||
|
500 | os.chmod(abslfile, mode) | |||
|
501 | update1 = 1 | |||
|
502 | ||||
|
503 | updated += update1 | |||
|
504 | ||||
|
505 | state = repo.dirstate[lfutil.standin(lfile)] | |||
|
506 | if state == 'n': | |||
|
507 | # When rebasing, we need to synchronize the standin and the | |||
|
508 | # largefile, because otherwise the largefile will get reverted. | |||
|
509 | # But for commit's sake, we have to mark the file as unclean. | |||
|
510 | if getattr(repo, "_isrebasing", False): | |||
|
511 | lfdirstate.normallookup(lfile) | |||
453 | else: |
|
512 | else: | |
454 |
|
|
513 | lfdirstate.normal(lfile) | |
455 | if printmessage and (removed or updated) and not printed: |
|
514 | elif state == 'r': | |
456 | ui.status(_('getting changed largefiles\n')) |
|
515 | lfdirstate.remove(lfile) | |
457 |
|
|
516 | elif state == 'a': | |
|
517 | lfdirstate.add(lfile) | |||
|
518 | elif state == '?': | |||
|
519 | lfdirstate.drop(lfile) | |||
458 |
|
520 | |||
459 | lfdirstate.write() |
|
521 | lfdirstate.write() | |
460 |
if print |
|
522 | if printmessage and lfiles: | |
461 | ui.status(_('%d largefiles updated, %d removed\n') % (updated, |
|
523 | ui.status(_('%d largefiles updated, %d removed\n') % (updated, | |
462 | removed)) |
|
524 | removed)) | |
463 | finally: |
|
525 | finally: | |
464 | wlock.release() |
|
526 | wlock.release() | |
465 |
|
527 | |||
466 | def _updatelfile(repo, lfdirstate, lfile): |
|
|||
467 | '''updates a single largefile and copies the state of its standin from |
|
|||
468 | the repository's dirstate to its state in the lfdirstate. |
|
|||
469 |
|
||||
470 | returns 1 if the file was modified, -1 if the file was removed, 0 if the |
|
|||
471 | file was unchanged, and None if the needed largefile was missing from the |
|
|||
472 | cache.''' |
|
|||
473 | ret = 0 |
|
|||
474 | abslfile = repo.wjoin(lfile) |
|
|||
475 | absstandin = repo.wjoin(lfutil.standin(lfile)) |
|
|||
476 | if os.path.exists(absstandin): |
|
|||
477 | if os.path.exists(absstandin + '.orig') and os.path.exists(abslfile): |
|
|||
478 | shutil.copyfile(abslfile, abslfile + '.orig') |
|
|||
479 | expecthash = lfutil.readstandin(repo, lfile) |
|
|||
480 | if (expecthash != '' and |
|
|||
481 | (not os.path.exists(abslfile) or |
|
|||
482 | expecthash != lfutil.hashfile(abslfile))): |
|
|||
483 | if not lfutil.copyfromcache(repo, expecthash, lfile): |
|
|||
484 | # use normallookup() to allocate entry in largefiles dirstate, |
|
|||
485 | # because lack of it misleads lfilesrepo.status() into |
|
|||
486 | # recognition that such cache missing files are REMOVED. |
|
|||
487 | if lfile not in repo[None]: # not switched to normal file |
|
|||
488 | util.unlinkpath(abslfile, ignoremissing=True) |
|
|||
489 | lfdirstate.normallookup(lfile) |
|
|||
490 | return None # don't try to set the mode |
|
|||
491 | else: |
|
|||
492 | # Synchronize largefile dirstate to the last modified time of |
|
|||
493 | # the file |
|
|||
494 | lfdirstate.normal(lfile) |
|
|||
495 | ret = 1 |
|
|||
496 | mode = os.stat(absstandin).st_mode |
|
|||
497 | if mode != os.stat(abslfile).st_mode: |
|
|||
498 | os.chmod(abslfile, mode) |
|
|||
499 | ret = 1 |
|
|||
500 | else: |
|
|||
501 | # Remove lfiles for which the standin is deleted, unless the |
|
|||
502 | # lfile is added to the repository again. This happens when a |
|
|||
503 | # largefile is converted back to a normal file: the standin |
|
|||
504 | # disappears, but a new (normal) file appears as the lfile. |
|
|||
505 | if (os.path.exists(abslfile) and |
|
|||
506 | repo.dirstate.normalize(lfile) not in repo[None]): |
|
|||
507 | util.unlinkpath(abslfile) |
|
|||
508 | ret = -1 |
|
|||
509 | state = repo.dirstate[lfutil.standin(lfile)] |
|
|||
510 | if state == 'n': |
|
|||
511 | # When rebasing, we need to synchronize the standin and the largefile, |
|
|||
512 | # because otherwise the largefile will get reverted. But for commit's |
|
|||
513 | # sake, we have to mark the file as unclean. |
|
|||
514 | if getattr(repo, "_isrebasing", False): |
|
|||
515 | lfdirstate.normallookup(lfile) |
|
|||
516 | else: |
|
|||
517 | lfdirstate.normal(lfile) |
|
|||
518 | elif state == 'r': |
|
|||
519 | lfdirstate.remove(lfile) |
|
|||
520 | elif state == 'a': |
|
|||
521 | lfdirstate.add(lfile) |
|
|||
522 | elif state == '?': |
|
|||
523 | lfdirstate.drop(lfile) |
|
|||
524 | return ret |
|
|||
525 |
|
||||
526 | def lfpull(ui, repo, source="default", **opts): |
|
528 | def lfpull(ui, repo, source="default", **opts): | |
527 | """pull largefiles for the specified revisions from the specified source |
|
529 | """pull largefiles for the specified revisions from the specified source | |
528 |
|
530 |
@@ -610,7 +610,7 b' def unshelve(ui, repo, *shelved, **opts)' | |||||
610 | # but it doesn't update the inmemory structures, so addchangegroup |
|
610 | # but it doesn't update the inmemory structures, so addchangegroup | |
611 | # hooks still fire and try to operate on the missing commits. |
|
611 | # hooks still fire and try to operate on the missing commits. | |
612 | # Clean up manually to prevent this. |
|
612 | # Clean up manually to prevent this. | |
613 | repo.changelog.strip(oldtiprev, tr) |
|
613 | repo.unfiltered().changelog.strip(oldtiprev, tr) | |
614 |
|
614 | |||
615 | unshelvecleanup(ui, repo, basename, opts) |
|
615 | unshelvecleanup(ui, repo, basename, opts) | |
616 | finally: |
|
616 | finally: |
@@ -64,3 +64,4 b' makes copies instead of hardlinks:' | |||||
64 | The largefile is not created in .hg/largefiles: |
|
64 | The largefile is not created in .hg/largefiles: | |
65 |
|
65 | |||
66 | $ ls bob/.hg/largefiles |
|
66 | $ ls bob/.hg/largefiles | |
|
67 | dirstate |
@@ -520,4 +520,23 b' unshelve should work on an ancestor of t' | |||||
520 | $ hg status |
|
520 | $ hg status | |
521 | A d |
|
521 | A d | |
522 |
|
522 | |||
|
523 | test bug 4073 we need to enable obsolete markers for it | |||
|
524 | ||||
|
525 | $ cat > ../obs.py << EOF | |||
|
526 | > import mercurial.obsolete | |||
|
527 | > mercurial.obsolete._enabled = True | |||
|
528 | > EOF | |||
|
529 | $ echo '[extensions]' >> $HGRCPATH | |||
|
530 | $ echo "obs=${TESTTMP}/obs.py" >> $HGRCPATH | |||
|
531 | $ hg shelve | |||
|
532 | shelved as default | |||
|
533 | 0 files updated, 0 files merged, 1 files removed, 0 files unresolved | |||
|
534 | $ hg debugobsolete `hg --debug id -i -r 1` | |||
|
535 | $ hg unshelve | |||
|
536 | unshelving change 'default' | |||
|
537 | adding changesets | |||
|
538 | adding manifests | |||
|
539 | adding file changes | |||
|
540 | added 1 changesets with 1 changes to 2 files (+1 heads) | |||
|
541 | ||||
523 | $ cd .. |
|
542 | $ cd .. |
General Comments 0
You need to be logged in to leave comments.
Login now