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 |
$ |
|
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 |
|
|
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 |
|
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 |
|
|
587 | If the source repo doesn't have the blob (maybe it was pulled or cloned with | |
587 |
|
|
588 | --noupdate), the blob is still accessible via the global cache to send to the | |
588 |
|
|
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