$ "$TESTDIR/hghave" symlink unix-permissions serve || exit 80 $ cat >> $HGRCPATH < [extensions] > largefiles= > purge= > rebase= > transplant= > [phases] > publish=False > [largefiles] > minsize=2 > patterns=glob:**.dat > EOF Create the repo with a couple of revisions of both large and normal files, testing that status correctly shows largefiles. $ hg init a $ cd a $ mkdir sub $ echo normal1 > normal1 $ echo normal2 > sub/normal2 $ echo large1 > large1 $ echo large2 > sub/large2 $ hg add normal1 sub/normal2 $ hg add --large large1 sub/large2 $ hg commit -m "add files" $ echo normal11 > normal1 $ echo normal22 > sub/normal2 $ echo large11 > large1 $ echo large22 > sub/large2 $ hg st M large1 M normal1 M sub/large2 M sub/normal2 $ hg commit -m "edit files" Commit preserved largefile contents. $ cat normal1 normal11 $ cat large1 large11 $ cat sub/normal2 normal22 $ cat sub/large2 large22 Remove both largefiles and normal files. $ hg remove normal1 large1 $ hg commit -m "remove files" $ ls sub Copy both largefiles and normal files (testing that status output is correct). $ hg cp sub/normal2 normal1 $ hg cp sub/large2 large1 $ hg st A large1 A normal1 $ hg commit -m "copy files" $ cat normal1 normal22 $ cat large1 large22 Test moving largefiles and verify that normal files are also unaffected. $ hg mv normal1 normal3 $ hg mv large1 large3 $ hg mv sub/normal2 sub/normal4 $ hg mv sub/large2 sub/large4 $ hg commit -m "move files" $ cat normal3 normal22 $ cat large3 large22 $ cat sub/normal4 normal22 $ cat sub/large4 large22 Test archiving the various revisions. These hit corner cases known with archiving. $ hg archive -r 0 ../archive0 $ hg archive -r 1 ../archive1 $ hg archive -r 2 ../archive2 $ hg archive -r 3 ../archive3 $ hg archive -r 4 ../archive4 $ cd ../archive0 $ cat normal1 normal1 $ cat large1 large1 $ cat sub/normal2 normal2 $ cat sub/large2 large2 $ cd ../archive1 $ cat normal1 normal11 $ cat large1 large11 $ cat sub/normal2 normal22 $ cat sub/large2 large22 $ cd ../archive2 $ ls sub $ cat sub/normal2 normal22 $ cat sub/large2 large22 $ cd ../archive3 $ cat normal1 normal22 $ cat large1 large22 $ cat sub/normal2 normal22 $ cat sub/large2 large22 $ cd ../archive4 $ cat normal3 normal22 $ cat large3 large22 $ cat sub/normal4 normal22 $ cat sub/large4 large22 Commit corner case: specify files to commit. $ cd ../a $ echo normal3 > normal3 $ echo large3 > large3 $ echo normal4 > sub/normal4 $ echo large4 > sub/large4 $ hg commit normal3 large3 sub/normal4 sub/large4 -m "edit files again" $ cat normal3 normal3 $ cat large3 large3 $ cat sub/normal4 normal4 $ cat sub/large4 large4 One more commit corner case: commit from a subdirectory. $ cd ../a $ echo normal33 > normal3 $ echo large33 > large3 $ echo normal44 > sub/normal4 $ echo large44 > sub/large4 $ cd sub $ hg commit -m "edit files yet again" $ cat ../normal3 normal33 $ cat ../large3 large33 $ cat normal4 normal44 $ cat large4 large44 Committing standins is not allowed. $ cd .. $ echo large3 > large3 $ hg commit .hglf/large3 -m "try to commit standin" abort: file ".hglf/large3" is a largefile standin (commit the largefile itself instead) [255] Corner cases for adding largefiles. $ echo large5 > large5 $ hg add --large large5 $ hg add --large large5 large5 already a largefile $ mkdir sub2 $ echo large6 > sub2/large6 $ echo large7 > sub2/large7 $ hg add --large sub2 adding sub2/large6 as a largefile (glob) adding sub2/large7 as a largefile (glob) $ hg st M large3 A large5 A sub2/large6 A sub2/large7 Config settings (pattern **.dat, minsize 2 MB) are respected. $ echo testdata > test.dat $ dd bs=1k count=2k if=/dev/zero of=reallylarge > /dev/null 2> /dev/null $ hg add adding reallylarge as a largefile adding test.dat as a largefile Test that minsize and --lfsize handle float values; also tests that --lfsize overrides largefiles.minsize. (0.250 MB = 256 kB = 262144 B) $ dd if=/dev/zero of=ratherlarge bs=1024 count=256 > /dev/null 2> /dev/null $ dd if=/dev/zero of=medium bs=1024 count=128 > /dev/null 2> /dev/null $ hg --config largefiles.minsize=.25 add adding ratherlarge as a largefile adding medium $ hg forget medium $ hg --config largefiles.minsize=.25 add --lfsize=.125 adding medium as a largefile $ dd if=/dev/zero of=notlarge bs=1024 count=127 > /dev/null 2> /dev/null $ hg --config largefiles.minsize=.25 add --lfsize=.125 adding notlarge $ hg forget notlarge Test forget on largefiles. $ hg forget large3 large5 test.dat reallylarge ratherlarge medium $ hg st A sub2/large6 A sub2/large7 R large3 ? large5 ? medium ? notlarge ? ratherlarge ? reallylarge ? test.dat $ hg commit -m "add/edit more largefiles" $ hg st ? large3 ? large5 ? medium ? notlarge ? ratherlarge ? reallylarge ? test.dat Purge with largefiles: verify that largefiles are still in the working dir after a purge. $ hg purge --all $ cat sub/large4 large44 $ cat sub2/large6 large6 $ cat sub2/large7 large7 Clone a largefiles repo. $ hg clone . ../b updating to branch default 5 files updated, 0 files merged, 0 files removed, 0 files unresolved getting changed largefiles 3 largefiles updated, 0 removed $ cd ../b $ hg log --template '{rev}:{node|short} {desc|firstline}\n' 7:daea875e9014 add/edit more largefiles 6:4355d653f84f edit files yet again 5:9d5af5072dbd edit files again 4:74c02385b94c move files 3:9e8fbc4bce62 copy files 2:51a0ae4d5864 remove files 1:ce8896473775 edit files 0:30d30fe6a5be add files $ cat normal3 normal33 $ cat sub/normal4 normal44 $ cat sub/large4 large44 $ cat sub2/large6 large6 $ cat sub2/large7 large7 $ cd .. $ hg clone a -r 3 c adding changesets adding manifests adding file changes added 4 changesets with 10 changes to 4 files updating to branch default 4 files updated, 0 files merged, 0 files removed, 0 files unresolved getting changed largefiles 2 largefiles updated, 0 removed $ cd c $ hg log --template '{rev}:{node|short} {desc|firstline}\n' 3:9e8fbc4bce62 copy files 2:51a0ae4d5864 remove files 1:ce8896473775 edit files 0:30d30fe6a5be add files $ cat normal1 normal22 $ cat large1 large22 $ cat sub/normal2 normal22 $ cat sub/large2 large22 Old revisions of a clone have correct largefiles content (this also tests update). $ hg update -r 1 2 files updated, 0 files merged, 0 files removed, 0 files unresolved getting changed largefiles 1 largefiles updated, 0 removed $ cat large1 large11 $ cat sub/large2 large22 Rebasing between two repositories does not revert largefiles to old revisions (this was a very bad bug that took a lot of work to fix). $ cd .. $ hg clone a d updating to branch default 5 files updated, 0 files merged, 0 files removed, 0 files unresolved getting changed largefiles 3 largefiles updated, 0 removed $ cd b $ echo large4-modified > sub/large4 $ echo normal3-modified > normal3 $ hg commit -m "modify normal file and largefile in repo b" $ cd ../d $ echo large6-modified > sub2/large6 $ echo normal4-modified > sub/normal4 $ hg commit -m "modify normal file largefile in repo d" $ cd .. $ hg clone d e updating to branch default 5 files updated, 0 files merged, 0 files removed, 0 files unresolved getting changed largefiles 3 largefiles updated, 0 removed $ cd d $ hg pull --rebase ../b pulling from ../b searching for changes adding changesets adding manifests adding file changes added 1 changesets with 2 changes to 2 files (+1 heads) getting changed largefiles 1 largefiles updated, 0 removed saved backup bundle to $TESTTMP/d/.hg/strip-backup/f574fb32bb45-backup.hg (glob) nothing to rebase $ hg log --template '{rev}:{node|short} {desc|firstline}\n' 9:598410d3eb9a modify normal file largefile in repo d 8:a381d2c8c80e modify normal file and largefile in repo b 7:daea875e9014 add/edit more largefiles 6:4355d653f84f edit files yet again 5:9d5af5072dbd edit files again 4:74c02385b94c move files 3:9e8fbc4bce62 copy files 2:51a0ae4d5864 remove files 1:ce8896473775 edit files 0:30d30fe6a5be add files $ cat normal3 normal3-modified $ cat sub/normal4 normal4-modified $ cat sub/large4 large4-modified $ cat sub2/large6 large6-modified $ cat sub2/large7 large7 $ cd ../e $ hg pull ../b pulling from ../b searching for changes adding changesets adding manifests adding file changes added 1 changesets with 2 changes to 2 files (+1 heads) (run 'hg heads' to see heads, 'hg merge' to merge) $ hg rebase getting changed largefiles 1 largefiles updated, 0 removed saved backup bundle to $TESTTMP/e/.hg/strip-backup/f574fb32bb45-backup.hg (glob) $ hg log changeset: 9:598410d3eb9a tag: tip user: test date: Thu Jan 01 00:00:00 1970 +0000 summary: modify normal file largefile in repo d changeset: 8:a381d2c8c80e user: test date: Thu Jan 01 00:00:00 1970 +0000 summary: modify normal file and largefile in repo b changeset: 7:daea875e9014 user: test date: Thu Jan 01 00:00:00 1970 +0000 summary: add/edit more largefiles changeset: 6:4355d653f84f user: test date: Thu Jan 01 00:00:00 1970 +0000 summary: edit files yet again changeset: 5:9d5af5072dbd user: test date: Thu Jan 01 00:00:00 1970 +0000 summary: edit files again changeset: 4:74c02385b94c user: test date: Thu Jan 01 00:00:00 1970 +0000 summary: move files changeset: 3:9e8fbc4bce62 user: test date: Thu Jan 01 00:00:00 1970 +0000 summary: copy files changeset: 2:51a0ae4d5864 user: test date: Thu Jan 01 00:00:00 1970 +0000 summary: remove files changeset: 1:ce8896473775 user: test date: Thu Jan 01 00:00:00 1970 +0000 summary: edit files changeset: 0:30d30fe6a5be user: test date: Thu Jan 01 00:00:00 1970 +0000 summary: add files $ cat normal3 normal3-modified $ cat sub/normal4 normal4-modified $ cat sub/large4 large4-modified $ cat sub2/large6 large6-modified $ cat sub2/large7 large7 Rollback on largefiles. $ echo large4-modified-again > sub/large4 $ hg commit -m "Modify large4 again" $ hg rollback repository tip rolled back to revision 9 (undo commit) working directory now based on revision 9 $ hg st M sub/large4 $ hg log changeset: 9:598410d3eb9a tag: tip user: test date: Thu Jan 01 00:00:00 1970 +0000 summary: modify normal file largefile in repo d changeset: 8:a381d2c8c80e user: test date: Thu Jan 01 00:00:00 1970 +0000 summary: modify normal file and largefile in repo b changeset: 7:daea875e9014 user: test date: Thu Jan 01 00:00:00 1970 +0000 summary: add/edit more largefiles changeset: 6:4355d653f84f user: test date: Thu Jan 01 00:00:00 1970 +0000 summary: edit files yet again changeset: 5:9d5af5072dbd user: test date: Thu Jan 01 00:00:00 1970 +0000 summary: edit files again changeset: 4:74c02385b94c user: test date: Thu Jan 01 00:00:00 1970 +0000 summary: move files changeset: 3:9e8fbc4bce62 user: test date: Thu Jan 01 00:00:00 1970 +0000 summary: copy files changeset: 2:51a0ae4d5864 user: test date: Thu Jan 01 00:00:00 1970 +0000 summary: remove files changeset: 1:ce8896473775 user: test date: Thu Jan 01 00:00:00 1970 +0000 summary: edit files changeset: 0:30d30fe6a5be user: test date: Thu Jan 01 00:00:00 1970 +0000 summary: add files $ cat sub/large4 large4-modified-again "update --check" refuses to update with uncommitted changes. $ hg update --check 8 abort: uncommitted local changes [255] "update --clean" leaves correct largefiles in working copy. $ hg update --clean 0 files updated, 0 files merged, 0 files removed, 0 files unresolved getting changed largefiles 1 largefiles updated, 0 removed $ cat normal3 normal3-modified $ cat sub/normal4 normal4-modified $ cat sub/large4 large4-modified $ cat sub2/large6 large6-modified $ cat sub2/large7 large7 Now "update check" is happy. $ hg update --check 8 2 files updated, 0 files merged, 0 files removed, 0 files unresolved getting changed largefiles 1 largefiles updated, 0 removed $ hg update --check 2 files updated, 0 files merged, 0 files removed, 0 files unresolved getting changed largefiles 1 largefiles updated, 0 removed "revert" works on largefiles (and normal files too). $ echo hack3 >> normal3 $ echo hack4 >> sub/normal4 $ echo hack4 >> sub/large4 $ hg rm sub2/large6 $ echo new >> sub2/large8 $ hg add --large sub2/large8 # XXX we don't really want to report that we're reverting the standin; # that's just an implementation detail. But I don't see an obvious fix. ;-( $ hg revert sub reverting .hglf/sub/large4 (glob) reverting sub/normal4 (glob) $ hg status M normal3 A sub2/large8 R sub2/large6 ? sub/large4.orig ? sub/normal4.orig $ cat sub/normal4 normal4-modified $ cat sub/large4 large4-modified $ hg revert -a --no-backup undeleting .hglf/sub2/large6 (glob) forgetting .hglf/sub2/large8 (glob) reverting normal3 $ hg status ? sub/large4.orig ? sub/normal4.orig ? sub2/large8 $ cat normal3 normal3-modified $ cat sub2/large6 large6-modified $ rm sub/*.orig sub2/large8 revert some files to an older revision $ hg revert --no-backup -r 8 sub2 reverting .hglf/sub2/large6 (glob) $ cat sub2/large6 large6 $ hg revert --no-backup sub2 reverting .hglf/sub2/large6 (glob) $ hg status "verify --large" actually verifies largefiles $ hg verify --large checking changesets checking manifests crosschecking files in changesets and manifests checking files 10 files, 10 changesets, 28 total revisions searching 1 changesets for largefiles verified existence of 3 revisions of 3 largefiles Merging does not revert to old versions of largefiles (this has also been very problematic). $ cd .. $ hg clone -r 7 e f adding changesets adding manifests adding file changes added 8 changesets with 24 changes to 10 files updating to branch default 5 files updated, 0 files merged, 0 files removed, 0 files unresolved getting changed largefiles 3 largefiles updated, 0 removed $ cd f $ echo "large4-merge-test" > sub/large4 $ hg commit -m "Modify large4 to test merge" $ hg pull ../e pulling from ../e searching for changes adding changesets adding manifests adding file changes added 2 changesets with 4 changes to 4 files (+1 heads) (run 'hg heads' to see heads, 'hg merge' to merge) $ hg merge merging sub/large4 largefile sub/large4 has a merge conflict keep (l)ocal or take (o)ther? l 3 files updated, 1 files merged, 0 files removed, 0 files unresolved (branch merge, don't forget to commit) getting changed largefiles 1 largefiles updated, 0 removed $ hg commit -m "Merge repos e and f" $ cat normal3 normal3-modified $ cat sub/normal4 normal4-modified $ cat sub/large4 large4-merge-test $ cat sub2/large6 large6-modified $ cat sub2/large7 large7 Test status after merging with a branch that introduces a new largefile: $ echo large > large $ hg add --large large $ hg commit -m 'add largefile' $ hg update -q ".^" $ echo change >> normal3 $ hg commit -m 'some change' created new head $ hg merge 1 files updated, 0 files merged, 0 files removed, 0 files unresolved (branch merge, don't forget to commit) getting changed largefiles 1 largefiles updated, 0 removed $ hg status M large Test that a normal file and a largefile with the same name and path cannot coexist. $ rm sub2/large7 $ echo "largeasnormal" > sub2/large7 $ hg add sub2/large7 sub2/large7 already a largefile Test that transplanting a largefile change works correctly. $ cd .. $ hg clone -r 8 d g adding changesets adding manifests adding file changes added 9 changesets with 26 changes to 10 files updating to branch default 5 files updated, 0 files merged, 0 files removed, 0 files unresolved getting changed largefiles 3 largefiles updated, 0 removed $ cd g $ hg transplant -s ../d 598410d3eb9a searching for changes searching for changes adding changesets adding manifests adding file changes added 1 changesets with 2 changes to 2 files getting changed largefiles 1 largefiles updated, 0 removed $ hg log --template '{rev}:{node|short} {desc|firstline}\n' 9:598410d3eb9a modify normal file largefile in repo d 8:a381d2c8c80e modify normal file and largefile in repo b 7:daea875e9014 add/edit more largefiles 6:4355d653f84f edit files yet again 5:9d5af5072dbd edit files again 4:74c02385b94c move files 3:9e8fbc4bce62 copy files 2:51a0ae4d5864 remove files 1:ce8896473775 edit files 0:30d30fe6a5be add files $ cat normal3 normal3-modified $ cat sub/normal4 normal4-modified $ cat sub/large4 large4-modified $ cat sub2/large6 large6-modified $ cat sub2/large7 large7 Test that renaming a largefile results in correct output for status $ hg rename sub/large4 large4-renamed $ hg st A large4-renamed R sub/large4 $ hg commit -m "test rename output" $ cat large4-renamed large4-modified $ cd sub2 $ hg rename large6 large6-renamed $ hg st A sub2/large6-renamed R sub2/large6 $ cd ../.. vanilla clients not locked out from largefiles servers on vanilla repos $ mkdir r1 $ cd r1 $ hg init $ echo c1 > f1 $ hg add f1 $ hg com -m "m1" $ cd .. $ hg serve -R r1 -d -p $HGPORT --pid-file hg.pid $ cat hg.pid >> $DAEMON_PIDS $ hg --config extensions.largefiles=! clone http://localhost:$HGPORT r2 requesting all changes adding changesets adding manifests adding file changes added 1 changesets with 1 changes to 1 files updating to branch default 1 files updated, 0 files merged, 0 files removed, 0 files unresolved largefiles clients still work with vanilla servers $ hg --config extensions.largefiles=! serve -R r1 -d -p $HGPORT1 --pid-file hg.pid $ cat hg.pid >> $DAEMON_PIDS $ hg clone http://localhost:$HGPORT1 r3 requesting all changes adding changesets adding manifests adding file changes added 1 changesets with 1 changes to 1 files updating to branch default 1 files updated, 0 files merged, 0 files removed, 0 files unresolved vanilla clients locked out from largefiles http repos $ mkdir r4 $ cd r4 $ hg init $ echo c1 > f1 $ hg add --large f1 $ hg com -m "m1" $ cd .. $ hg serve -R r4 -d -p $HGPORT2 --pid-file hg.pid $ cat hg.pid >> $DAEMON_PIDS $ hg --config extensions.largefiles=! clone http://localhost:$HGPORT2 r5 abort: remote error: This repository uses the largefiles extension. Please enable it in your Mercurial config file. [255] used all HGPORTs, kill all daemons $ "$TESTDIR/killdaemons.py" vanilla clients locked out from largefiles ssh repos $ hg --config extensions.largefiles=! clone -e "python $TESTDIR/dummyssh" ssh://user@dummy/r4 r5 abort: remote error: This repository uses the largefiles extension. Please enable it in your Mercurial config file. [255] largefiles clients refuse to push largefiles repos to vanilla servers $ mkdir r6 $ cd r6 $ hg init $ echo c1 > f1 $ hg add f1 $ hg com -m "m1" $ cat >> .hg/hgrc < [web] > push_ssl = false > allow_push = * > ! $ cd .. $ hg clone r6 r7 updating to branch default 1 files updated, 0 files merged, 0 files removed, 0 files unresolved $ cd r7 $ echo c2 > f2 $ hg add --large f2 $ hg com -m "m2" $ hg --config extensions.largefiles=! -R ../r6 serve -d -p $HGPORT --pid-file ../hg.pid $ cat ../hg.pid >> $DAEMON_PIDS $ hg push http://localhost:$HGPORT pushing to http://localhost:$HGPORT/ searching for changes abort: http://localhost:$HGPORT/ does not appear to be a largefile store [255] $ cd .. Clone a local repository owned by another user We have to simulate that here by setting $HOME and removing write permissions $ ORIGHOME="$HOME" $ mkdir alice $ HOME="`pwd`/alice" $ cd alice $ hg init pubrepo $ cd pubrepo $ dd if=/dev/urandom bs=1k count=11k > a-large-file 2> /dev/null $ hg add --large a-large-file $ hg commit -m "Add a large file" $ cd .. $ chmod -R a-w pubrepo $ cd .. $ mkdir bob $ HOME="`pwd`/bob" $ cd bob $ hg clone --pull ../alice/pubrepo pubrepo requesting all changes adding changesets adding manifests adding file changes added 1 changesets with 1 changes to 1 files updating to branch default 1 files updated, 0 files merged, 0 files removed, 0 files unresolved getting changed largefiles 1 largefiles updated, 0 removed $ cd .. $ chmod -R u+w alice/pubrepo $ HOME="$ORIGHOME" Symlink to a large largefile should behave the same as a symlink to a normal file $ hg init largesymlink $ cd largesymlink $ dd if=/dev/zero bs=1k count=10k of=largefile 2>/dev/null $ hg add --large largefile $ hg commit -m "commit a large file" $ ln -s largefile largelink $ hg add largelink $ hg commit -m "commit a large symlink" $ rm -f largelink $ hg up >/dev/null $ test -f largelink [1] $ test -L largelink [1] $ rm -f largelink # make next part of the test independent of the previous $ hg up -C >/dev/null $ test -f largelink $ test -L largelink $ cd ..