##// END OF EJS Templates
lfs: introduce a user level cache for lfs files...
Matt Harbison -
r35281:8e72f915 default
parent child Browse files
Show More
@@ -24,6 +24,10 b' Configs::'
24
24
25 # how many times to retry before giving up on transferring an object
25 # how many times to retry before giving up on transferring an object
26 retry = 5
26 retry = 5
27
28 # the local directory to store lfs files for sharing across local clones.
29 # If not set, the cache is located in an OS specific cache location.
30 usercache = /path/to/global/cache
27 """
31 """
28
32
29 from __future__ import absolute_import
33 from __future__ import absolute_import
@@ -62,6 +66,9 b' configitem = registrar.configitem(config'
62 configitem('lfs', 'url',
66 configitem('lfs', 'url',
63 default=configitem.dynamicdefault,
67 default=configitem.dynamicdefault,
64 )
68 )
69 configitem('lfs', 'usercache',
70 default=None,
71 )
65 configitem('lfs', 'threshold',
72 configitem('lfs', 'threshold',
66 default=None,
73 default=None,
67 )
74 )
@@ -20,6 +20,8 b' from mercurial import ('
20 vfs as vfsmod,
20 vfs as vfsmod,
21 )
21 )
22
22
23 from ..largefiles import lfutil
24
23 # 64 bytes for SHA256
25 # 64 bytes for SHA256
24 _lfsre = re.compile(r'\A[a-f0-9]{64}\Z')
26 _lfsre = re.compile(r'\A[a-f0-9]{64}\Z')
25
27
@@ -68,20 +70,29 b' class local(object):'
68 def __init__(self, repo):
70 def __init__(self, repo):
69 fullpath = repo.svfs.join('lfs/objects')
71 fullpath = repo.svfs.join('lfs/objects')
70 self.vfs = lfsvfs(fullpath)
72 self.vfs = lfsvfs(fullpath)
73 usercache = lfutil._usercachedir(repo.ui, 'lfs')
74 self.cachevfs = lfsvfs(usercache)
71
75
72 def write(self, oid, data):
76 def write(self, oid, data):
73 """Write blob to local blobstore."""
77 """Write blob to local blobstore."""
74 with self.vfs(oid, 'wb', atomictemp=True) as fp:
78 with self.vfs(oid, 'wb', atomictemp=True) as fp:
75 fp.write(data)
79 fp.write(data)
76
80
81 # XXX: should we verify the content of the cache, and hardlink back to
82 # the local store on success, but truncate, write and link on failure?
83 if not self.cachevfs.exists(oid):
84 lfutil.link(self.vfs.join(oid), self.cachevfs.join(oid))
85
77 def read(self, oid):
86 def read(self, oid):
78 """Read blob from local blobstore."""
87 """Read blob from local blobstore."""
88 if not self.vfs.exists(oid):
89 lfutil.link(self.cachevfs.join(oid), self.vfs.join(oid))
79 return self.vfs.read(oid)
90 return self.vfs.read(oid)
80
91
81 def has(self, oid):
92 def has(self, oid):
82 """Returns True if the local blobstore contains the requested blob,
93 """Returns True if the local blobstore contains the requested blob,
83 False otherwise."""
94 False otherwise."""
84 return self.vfs.exists(oid)
95 return self.cachevfs.exists(oid) or self.vfs.exists(oid)
85
96
86 class _gitlfsremote(object):
97 class _gitlfsremote(object):
87
98
@@ -1102,6 +1102,9 b' class Test(unittest.TestCase):'
1102 hgrc.write(b'[largefiles]\n')
1102 hgrc.write(b'[largefiles]\n')
1103 hgrc.write(b'usercache = %s\n' %
1103 hgrc.write(b'usercache = %s\n' %
1104 (os.path.join(self._testtmp, b'.cache/largefiles')))
1104 (os.path.join(self._testtmp, b'.cache/largefiles')))
1105 hgrc.write(b'[lfs]\n')
1106 hgrc.write(b'usercache = %s\n' %
1107 (os.path.join(self._testtmp, b'.cache/lfs')))
1105 hgrc.write(b'[web]\n')
1108 hgrc.write(b'[web]\n')
1106 hgrc.write(b'address = localhost\n')
1109 hgrc.write(b'address = localhost\n')
1107 hgrc.write(b'ipv6 = %s\n' % str(self._useipv6).encode('ascii'))
1110 hgrc.write(b'ipv6 = %s\n' % str(self._useipv6).encode('ascii'))
@@ -5,6 +5,7 b' Create a repository:'
5 devel.default-date=0 0
5 devel.default-date=0 0
6 extensions.fsmonitor= (fsmonitor !)
6 extensions.fsmonitor= (fsmonitor !)
7 largefiles.usercache=$TESTTMP/.cache/largefiles (glob)
7 largefiles.usercache=$TESTTMP/.cache/largefiles (glob)
8 lfs.usercache=$TESTTMP/.cache/lfs (glob)
8 ui.slash=True
9 ui.slash=True
9 ui.interactive=False
10 ui.interactive=False
10 ui.mergemarkers=detailed
11 ui.mergemarkers=detailed
@@ -207,6 +207,7 b' check that local configs for the cached '
207 devel.default-date=0 0
207 devel.default-date=0 0
208 extensions.fsmonitor= (fsmonitor !)
208 extensions.fsmonitor= (fsmonitor !)
209 largefiles.usercache=$TESTTMP/.cache/largefiles
209 largefiles.usercache=$TESTTMP/.cache/largefiles
210 lfs.usercache=$TESTTMP/.cache/lfs
210 ui.slash=True
211 ui.slash=True
211 ui.interactive=False
212 ui.interactive=False
212 ui.mergemarkers=detailed
213 ui.mergemarkers=detailed
@@ -53,6 +53,8 b''
53 adding file changes
53 adding file changes
54 added 1 changesets with 1 changes to 1 files
54 added 1 changesets with 1 changes to 1 files
55
55
56 Clear the cache to force a download
57 $ rm -rf `hg config lfs.usercache`
56 $ cd ../repo2
58 $ cd ../repo2
57 $ hg update tip -v
59 $ hg update tip -v
58 resolving manifests
60 resolving manifests
@@ -79,6 +81,8 b' When the server has some blobs already'
79 adding file changes
81 adding file changes
80 added 1 changesets with 3 changes to 3 files
82 added 1 changesets with 3 changes to 3 files
81
83
84 Clear the cache to force a download
85 $ rm -rf `hg config lfs.usercache`
82 $ hg --repo ../repo1 update tip -v
86 $ hg --repo ../repo1 update tip -v
83 resolving manifests
87 resolving manifests
84 getting b
88 getting b
@@ -95,6 +99,7 b' Check error message when the remote miss'
95 $ echo FFFFF >> b
99 $ echo FFFFF >> b
96 $ hg commit -m b b
100 $ hg commit -m b b
97 $ rm -rf .hg/store/lfs
101 $ rm -rf .hg/store/lfs
102 $ rm -rf `hg config lfs.usercache`
98 $ hg update -C '.^'
103 $ hg update -C '.^'
99 abort: LFS server claims required objects do not exist:
104 abort: LFS server claims required objects do not exist:
100 8e6ea5f6c066b44a0efa43bcce86aea73f17e6e23f0663df0251e7524e140a13!
105 8e6ea5f6c066b44a0efa43bcce86aea73f17e6e23f0663df0251e7524e140a13!
@@ -118,6 +123,7 b' Check error message when object does not'
118 size 6
123 size 6
119 x-is-binary 0
124 x-is-binary 0
120 $ cd ..
125 $ cd ..
126 $ rm -rf `hg config lfs.usercache`
121 $ hg --config 'lfs.url=https://dewey-lfs.vip.facebook.com/lfs' clone test test2
127 $ hg --config 'lfs.url=https://dewey-lfs.vip.facebook.com/lfs' clone test test2
122 updating to branch default
128 updating to branch default
123 abort: LFS server error. Remote object for file data/a.i not found:(.*)! (re)
129 abort: LFS server error. Remote object for file data/a.i not found:(.*)! (re)
@@ -566,9 +566,9 b''
566 repo: repo9
566 repo: repo9
567 repo: repo10
567 repo: repo10
568
568
569 TODO: repo12 doesn't have any cached lfs files. Figure out how to get the
569 repo12 doesn't have any cached lfs files and its source never pushed its
570 unpushed files from repo12's source instead of the remote store, where they
570 files. Therefore, the files don't exist in the remote store. Use the files in
571 don't exist.
571 the user cache.
572
572
573 $ find $TESTTMP/repo12/.hg/store/lfs/objects -type f
573 $ find $TESTTMP/repo12/.hg/store/lfs/objects -type f
574 find: */repo12/.hg/store/lfs/objects': $ENOENT$ (glob)
574 find: */repo12/.hg/store/lfs/objects': $ENOENT$ (glob)
@@ -576,24 +576,28 b" don't exist."
576
576
577 $ hg --config extensions.share= share repo12 repo13
577 $ hg --config extensions.share= share repo12 repo13
578 updating working directory
578 updating working directory
579 abort: $TESTTMP/dummy-remote/09/66faba9a01f6c78082aa45899a4fef732002d0b26404e90093adf1e876ab8d: $ENOTDIR$ (glob)
579 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
580 [255]
580 $ hg -R repo13 -q verify
581
581 $ hg clone repo12 repo14
582 $ hg clone repo12 repo14
582 updating to branch default
583 updating to branch default
583 abort: $TESTTMP/dummy-remote/09/66faba9a01f6c78082aa45899a4fef732002d0b26404e90093adf1e876ab8d: $ENOTDIR$ (glob)
584 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
584 [255]
585 $ hg -R repo14 -q verify
585
586
586 TODO: If the source repo doesn't have the blob (maybe it was pulled or cloned
587 If the source repo doesn't have the blob (maybe it was pulled or cloned with
587 with --noupdate), the blob should be accessible via the global cache to send to
588 --noupdate), the blob is still accessible via the global cache to send to the
588 the remote store.
589 remote store.
589
590
590 $ rm -rf $TESTTMP/repo14/.hg/store/lfs
591 $ rm -rf $TESTTMP/repo14/.hg/store/lfs
591 $ hg init repo15
592 $ hg init repo15
592 $ hg -R repo14 push repo15
593 $ hg -R repo14 push repo15
593 pushing to repo15
594 pushing to repo15
594 searching for changes
595 searching for changes
595 abort: $TESTTMP/repo14/.hg/store/lfs/objects/1c/896a0adcf9262119f4a98216aaa5ca00a58b9a0ce848914a02f9cd876f65a3: $ENOTDIR$ (glob)
596 adding changesets
596 [255]
597 adding manifests
598 adding file changes
599 added 3 changesets with 2 changes to 1 files
600 $ hg -R repo14 -q verify
597
601
598 lfs -> normal -> lfs round trip conversions are possible. The threshold for the
602 lfs -> normal -> lfs round trip conversions are possible. The threshold for the
599 lfs destination is specified here because it was originally listed in the local
603 lfs destination is specified here because it was originally listed in the local
General Comments 0
You need to be logged in to leave comments. Login now