##// END OF EJS Templates
lfs: migrate most file filtering from threshold to custom filter...
Matt Harbison -
r35636:c780e064 default
parent child Browse files
Show More
@@ -1,206 +1,233 b''
1 # lfs - hash-preserving large file support using Git-LFS protocol
1 # lfs - hash-preserving large file support using Git-LFS protocol
2 #
2 #
3 # Copyright 2017 Facebook, Inc.
3 # Copyright 2017 Facebook, Inc.
4 #
4 #
5 # This software may be used and distributed according to the terms of the
5 # This software may be used and distributed according to the terms of the
6 # GNU General Public License version 2 or any later version.
6 # GNU General Public License version 2 or any later version.
7
7
8 """lfs - large file support (EXPERIMENTAL)
8 """lfs - large file support (EXPERIMENTAL)
9
9
10 Configs::
10 Configs::
11
11
12 [lfs]
12 [lfs]
13 # Remote endpoint. Multiple protocols are supported:
13 # Remote endpoint. Multiple protocols are supported:
14 # - http(s)://user:pass@example.com/path
14 # - http(s)://user:pass@example.com/path
15 # git-lfs endpoint
15 # git-lfs endpoint
16 # - file:///tmp/path
16 # - file:///tmp/path
17 # local filesystem, usually for testing
17 # local filesystem, usually for testing
18 # if unset, lfs will prompt setting this when it must use this value.
18 # if unset, lfs will prompt setting this when it must use this value.
19 # (default: unset)
19 # (default: unset)
20 url = https://example.com/lfs
20 url = https://example.com/lfs
21
21
22 # size of a file to make it use LFS
22 # Which files to track in LFS. Path tests are "**.extname" for file
23 threshold = 10M
23 # extensions, and "path:under/some/directory" for path prefix. Both
24 # are relative to the repository root, and the latter must be quoted.
25 # File size can be tested with the "size()" fileset, and tests can be
26 # joined with fileset operators. (See "hg help filesets.operators".)
27 #
28 # Some examples:
29 # - all() # everything
30 # - none() # nothing
31 # - size(">20MB") # larger than 20MB
32 # - !**.txt # anything not a *.txt file
33 # - **.zip | **.tar.gz | **.7z # some types of compressed files
34 # - "path:bin" # files under "bin" in the project root
35 # - (**.php & size(">2MB")) | (**.js & size(">5MB")) | **.tar.gz
36 # | ("path:bin" & !"path:/bin/README") | size(">1GB")
37 # (default: none())
38 track = size(">10M")
24
39
25 # how many times to retry before giving up on transferring an object
40 # how many times to retry before giving up on transferring an object
26 retry = 5
41 retry = 5
27
42
28 # the local directory to store lfs files for sharing across local clones.
43 # 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.
44 # If not set, the cache is located in an OS specific cache location.
30 usercache = /path/to/global/cache
45 usercache = /path/to/global/cache
31 """
46 """
32
47
33 from __future__ import absolute_import
48 from __future__ import absolute_import
34
49
35 from mercurial.i18n import _
50 from mercurial.i18n import _
36
51
37 from mercurial import (
52 from mercurial import (
38 bundle2,
53 bundle2,
39 changegroup,
54 changegroup,
40 context,
55 context,
41 exchange,
56 exchange,
42 extensions,
57 extensions,
43 filelog,
58 filelog,
59 fileset,
44 hg,
60 hg,
45 localrepo,
61 localrepo,
62 minifileset,
46 node,
63 node,
47 registrar,
64 registrar,
48 revlog,
65 revlog,
49 scmutil,
66 scmutil,
50 upgrade,
67 upgrade,
51 vfs as vfsmod,
68 vfs as vfsmod,
52 wireproto,
69 wireproto,
53 )
70 )
54
71
55 from . import (
72 from . import (
56 blobstore,
73 blobstore,
57 wrapper,
74 wrapper,
58 )
75 )
59
76
60 # Note for extension authors: ONLY specify testedwith = 'ships-with-hg-core' for
77 # Note for extension authors: ONLY specify testedwith = 'ships-with-hg-core' for
61 # extensions which SHIP WITH MERCURIAL. Non-mainline extensions should
78 # extensions which SHIP WITH MERCURIAL. Non-mainline extensions should
62 # be specifying the version(s) of Mercurial they are tested with, or
79 # be specifying the version(s) of Mercurial they are tested with, or
63 # leave the attribute unspecified.
80 # leave the attribute unspecified.
64 testedwith = 'ships-with-hg-core'
81 testedwith = 'ships-with-hg-core'
65
82
66 configtable = {}
83 configtable = {}
67 configitem = registrar.configitem(configtable)
84 configitem = registrar.configitem(configtable)
68
85
69 configitem('experimental', 'lfs.user-agent',
86 configitem('experimental', 'lfs.user-agent',
70 default=None,
87 default=None,
71 )
88 )
72
89
73 configitem('lfs', 'url',
90 configitem('lfs', 'url',
74 default=None,
91 default=None,
75 )
92 )
76 configitem('lfs', 'usercache',
93 configitem('lfs', 'usercache',
77 default=None,
94 default=None,
78 )
95 )
96 # Deprecated
79 configitem('lfs', 'threshold',
97 configitem('lfs', 'threshold',
80 default=None,
98 default=None,
81 )
99 )
100 configitem('lfs', 'track',
101 default='none()',
102 )
82 configitem('lfs', 'retry',
103 configitem('lfs', 'retry',
83 default=5,
104 default=5,
84 )
105 )
85
106
86 cmdtable = {}
107 cmdtable = {}
87 command = registrar.command(cmdtable)
108 command = registrar.command(cmdtable)
88
109
89 templatekeyword = registrar.templatekeyword()
110 templatekeyword = registrar.templatekeyword()
90
111
91 def featuresetup(ui, supported):
112 def featuresetup(ui, supported):
92 # don't die on seeing a repo with the lfs requirement
113 # don't die on seeing a repo with the lfs requirement
93 supported |= {'lfs'}
114 supported |= {'lfs'}
94
115
95 def uisetup(ui):
116 def uisetup(ui):
96 localrepo.localrepository.featuresetupfuncs.add(featuresetup)
117 localrepo.localrepository.featuresetupfuncs.add(featuresetup)
97
118
98 def reposetup(ui, repo):
119 def reposetup(ui, repo):
99 # Nothing to do with a remote repo
120 # Nothing to do with a remote repo
100 if not repo.local():
121 if not repo.local():
101 return
122 return
102
123
103 threshold = repo.ui.configbytes('lfs', 'threshold')
124 trackspec = repo.ui.config('lfs', 'track')
104
125
105 repo.svfs.options['lfsthreshold'] = threshold
126 # deprecated config: lfs.threshold
127 threshold = repo.ui.configbytes('lfs', 'threshold')
128 if threshold:
129 fileset.parse(trackspec) # make sure syntax errors are confined
130 trackspec = "(%s) | size('>%d')" % (trackspec, threshold)
131
132 repo.svfs.options['lfstrack'] = minifileset.compile(trackspec)
106 repo.svfs.lfslocalblobstore = blobstore.local(repo)
133 repo.svfs.lfslocalblobstore = blobstore.local(repo)
107 repo.svfs.lfsremoteblobstore = blobstore.remote(repo)
134 repo.svfs.lfsremoteblobstore = blobstore.remote(repo)
108
135
109 # Push hook
136 # Push hook
110 repo.prepushoutgoinghooks.add('lfs', wrapper.prepush)
137 repo.prepushoutgoinghooks.add('lfs', wrapper.prepush)
111
138
112 if 'lfs' not in repo.requirements:
139 if 'lfs' not in repo.requirements:
113 def checkrequireslfs(ui, repo, **kwargs):
140 def checkrequireslfs(ui, repo, **kwargs):
114 if 'lfs' not in repo.requirements:
141 if 'lfs' not in repo.requirements:
115 last = kwargs.get('node_last')
142 last = kwargs.get('node_last')
116 _bin = node.bin
143 _bin = node.bin
117 if last:
144 if last:
118 s = repo.set('%n:%n', _bin(kwargs['node']), _bin(last))
145 s = repo.set('%n:%n', _bin(kwargs['node']), _bin(last))
119 else:
146 else:
120 s = repo.set('%n', _bin(kwargs['node']))
147 s = repo.set('%n', _bin(kwargs['node']))
121 for ctx in s:
148 for ctx in s:
122 # TODO: is there a way to just walk the files in the commit?
149 # TODO: is there a way to just walk the files in the commit?
123 if any(ctx[f].islfs() for f in ctx.files() if f in ctx):
150 if any(ctx[f].islfs() for f in ctx.files() if f in ctx):
124 repo.requirements.add('lfs')
151 repo.requirements.add('lfs')
125 repo._writerequirements()
152 repo._writerequirements()
126 break
153 break
127
154
128 ui.setconfig('hooks', 'commit.lfs', checkrequireslfs, 'lfs')
155 ui.setconfig('hooks', 'commit.lfs', checkrequireslfs, 'lfs')
129 ui.setconfig('hooks', 'pretxnchangegroup.lfs', checkrequireslfs, 'lfs')
156 ui.setconfig('hooks', 'pretxnchangegroup.lfs', checkrequireslfs, 'lfs')
130
157
131 def wrapfilelog(filelog):
158 def wrapfilelog(filelog):
132 wrapfunction = extensions.wrapfunction
159 wrapfunction = extensions.wrapfunction
133
160
134 wrapfunction(filelog, 'addrevision', wrapper.filelogaddrevision)
161 wrapfunction(filelog, 'addrevision', wrapper.filelogaddrevision)
135 wrapfunction(filelog, 'renamed', wrapper.filelogrenamed)
162 wrapfunction(filelog, 'renamed', wrapper.filelogrenamed)
136 wrapfunction(filelog, 'size', wrapper.filelogsize)
163 wrapfunction(filelog, 'size', wrapper.filelogsize)
137
164
138 def extsetup(ui):
165 def extsetup(ui):
139 wrapfilelog(filelog.filelog)
166 wrapfilelog(filelog.filelog)
140
167
141 wrapfunction = extensions.wrapfunction
168 wrapfunction = extensions.wrapfunction
142
169
143 wrapfunction(scmutil, 'wrapconvertsink', wrapper.convertsink)
170 wrapfunction(scmutil, 'wrapconvertsink', wrapper.convertsink)
144
171
145 wrapfunction(upgrade, '_finishdatamigration',
172 wrapfunction(upgrade, '_finishdatamigration',
146 wrapper.upgradefinishdatamigration)
173 wrapper.upgradefinishdatamigration)
147
174
148 wrapfunction(upgrade, 'preservedrequirements',
175 wrapfunction(upgrade, 'preservedrequirements',
149 wrapper.upgraderequirements)
176 wrapper.upgraderequirements)
150
177
151 wrapfunction(upgrade, 'supporteddestrequirements',
178 wrapfunction(upgrade, 'supporteddestrequirements',
152 wrapper.upgraderequirements)
179 wrapper.upgraderequirements)
153
180
154 wrapfunction(changegroup,
181 wrapfunction(changegroup,
155 'supportedoutgoingversions',
182 'supportedoutgoingversions',
156 wrapper.supportedoutgoingversions)
183 wrapper.supportedoutgoingversions)
157 wrapfunction(changegroup,
184 wrapfunction(changegroup,
158 'allsupportedversions',
185 'allsupportedversions',
159 wrapper.allsupportedversions)
186 wrapper.allsupportedversions)
160
187
161 wrapfunction(exchange, 'push', wrapper.push)
188 wrapfunction(exchange, 'push', wrapper.push)
162 wrapfunction(wireproto, '_capabilities', wrapper._capabilities)
189 wrapfunction(wireproto, '_capabilities', wrapper._capabilities)
163
190
164 wrapfunction(context.basefilectx, 'cmp', wrapper.filectxcmp)
191 wrapfunction(context.basefilectx, 'cmp', wrapper.filectxcmp)
165 wrapfunction(context.basefilectx, 'isbinary', wrapper.filectxisbinary)
192 wrapfunction(context.basefilectx, 'isbinary', wrapper.filectxisbinary)
166 context.basefilectx.islfs = wrapper.filectxislfs
193 context.basefilectx.islfs = wrapper.filectxislfs
167
194
168 revlog.addflagprocessor(
195 revlog.addflagprocessor(
169 revlog.REVIDX_EXTSTORED,
196 revlog.REVIDX_EXTSTORED,
170 (
197 (
171 wrapper.readfromstore,
198 wrapper.readfromstore,
172 wrapper.writetostore,
199 wrapper.writetostore,
173 wrapper.bypasscheckhash,
200 wrapper.bypasscheckhash,
174 ),
201 ),
175 )
202 )
176
203
177 wrapfunction(hg, 'clone', wrapper.hgclone)
204 wrapfunction(hg, 'clone', wrapper.hgclone)
178 wrapfunction(hg, 'postshare', wrapper.hgpostshare)
205 wrapfunction(hg, 'postshare', wrapper.hgpostshare)
179
206
180 # Make bundle choose changegroup3 instead of changegroup2. This affects
207 # Make bundle choose changegroup3 instead of changegroup2. This affects
181 # "hg bundle" command. Note: it does not cover all bundle formats like
208 # "hg bundle" command. Note: it does not cover all bundle formats like
182 # "packed1". Using "packed1" with lfs will likely cause trouble.
209 # "packed1". Using "packed1" with lfs will likely cause trouble.
183 names = [k for k, v in exchange._bundlespeccgversions.items() if v == '02']
210 names = [k for k, v in exchange._bundlespeccgversions.items() if v == '02']
184 for k in names:
211 for k in names:
185 exchange._bundlespeccgversions[k] = '03'
212 exchange._bundlespeccgversions[k] = '03'
186
213
187 # bundlerepo uses "vfsmod.readonlyvfs(othervfs)", we need to make sure lfs
214 # bundlerepo uses "vfsmod.readonlyvfs(othervfs)", we need to make sure lfs
188 # options and blob stores are passed from othervfs to the new readonlyvfs.
215 # options and blob stores are passed from othervfs to the new readonlyvfs.
189 wrapfunction(vfsmod.readonlyvfs, '__init__', wrapper.vfsinit)
216 wrapfunction(vfsmod.readonlyvfs, '__init__', wrapper.vfsinit)
190
217
191 # when writing a bundle via "hg bundle" command, upload related LFS blobs
218 # when writing a bundle via "hg bundle" command, upload related LFS blobs
192 wrapfunction(bundle2, 'writenewbundle', wrapper.writenewbundle)
219 wrapfunction(bundle2, 'writenewbundle', wrapper.writenewbundle)
193
220
194 @templatekeyword('lfs_files')
221 @templatekeyword('lfs_files')
195 def lfsfiles(repo, ctx, **args):
222 def lfsfiles(repo, ctx, **args):
196 """List of strings. LFS files added or modified by the changeset."""
223 """List of strings. LFS files added or modified by the changeset."""
197 pointers = wrapper.pointersfromctx(ctx) # {path: pointer}
224 pointers = wrapper.pointersfromctx(ctx) # {path: pointer}
198 return sorted(pointers.keys())
225 return sorted(pointers.keys())
199
226
200 @command('debuglfsupload',
227 @command('debuglfsupload',
201 [('r', 'rev', [], _('upload large files introduced by REV'))])
228 [('r', 'rev', [], _('upload large files introduced by REV'))])
202 def debuglfsupload(ui, repo, **opts):
229 def debuglfsupload(ui, repo, **opts):
203 """upload lfs blobs added by the working copy parent or given revisions"""
230 """upload lfs blobs added by the working copy parent or given revisions"""
204 revs = opts.get('rev', [])
231 revs = opts.get('rev', [])
205 pointers = wrapper.extractpointers(repo, scmutil.revrange(repo, revs))
232 pointers = wrapper.extractpointers(repo, scmutil.revrange(repo, revs))
206 wrapper.uploadblobs(repo, pointers)
233 wrapper.uploadblobs(repo, pointers)
@@ -1,345 +1,345 b''
1 # wrapper.py - methods wrapping core mercurial logic
1 # wrapper.py - methods wrapping core mercurial logic
2 #
2 #
3 # Copyright 2017 Facebook, Inc.
3 # Copyright 2017 Facebook, Inc.
4 #
4 #
5 # This software may be used and distributed according to the terms of the
5 # This software may be used and distributed according to the terms of the
6 # GNU General Public License version 2 or any later version.
6 # GNU General Public License version 2 or any later version.
7
7
8 from __future__ import absolute_import
8 from __future__ import absolute_import
9
9
10 import hashlib
10 import hashlib
11
11
12 from mercurial.i18n import _
12 from mercurial.i18n import _
13 from mercurial.node import bin, nullid, short
13 from mercurial.node import bin, nullid, short
14
14
15 from mercurial import (
15 from mercurial import (
16 error,
16 error,
17 filelog,
17 filelog,
18 revlog,
18 revlog,
19 util,
19 util,
20 )
20 )
21
21
22 from ..largefiles import lfutil
22 from ..largefiles import lfutil
23
23
24 from . import (
24 from . import (
25 blobstore,
25 blobstore,
26 pointer,
26 pointer,
27 )
27 )
28
28
29 def supportedoutgoingversions(orig, repo):
29 def supportedoutgoingversions(orig, repo):
30 versions = orig(repo)
30 versions = orig(repo)
31 if 'lfs' in repo.requirements:
31 if 'lfs' in repo.requirements:
32 versions.discard('01')
32 versions.discard('01')
33 versions.discard('02')
33 versions.discard('02')
34 versions.add('03')
34 versions.add('03')
35 return versions
35 return versions
36
36
37 def allsupportedversions(orig, ui):
37 def allsupportedversions(orig, ui):
38 versions = orig(ui)
38 versions = orig(ui)
39 versions.add('03')
39 versions.add('03')
40 return versions
40 return versions
41
41
42 def _capabilities(orig, repo, proto):
42 def _capabilities(orig, repo, proto):
43 '''Wrap server command to announce lfs server capability'''
43 '''Wrap server command to announce lfs server capability'''
44 caps = orig(repo, proto)
44 caps = orig(repo, proto)
45 # XXX: change to 'lfs=serve' when separate git server isn't required?
45 # XXX: change to 'lfs=serve' when separate git server isn't required?
46 caps.append('lfs')
46 caps.append('lfs')
47 return caps
47 return caps
48
48
49 def bypasscheckhash(self, text):
49 def bypasscheckhash(self, text):
50 return False
50 return False
51
51
52 def readfromstore(self, text):
52 def readfromstore(self, text):
53 """Read filelog content from local blobstore transform for flagprocessor.
53 """Read filelog content from local blobstore transform for flagprocessor.
54
54
55 Default tranform for flagprocessor, returning contents from blobstore.
55 Default tranform for flagprocessor, returning contents from blobstore.
56 Returns a 2-typle (text, validatehash) where validatehash is True as the
56 Returns a 2-typle (text, validatehash) where validatehash is True as the
57 contents of the blobstore should be checked using checkhash.
57 contents of the blobstore should be checked using checkhash.
58 """
58 """
59 p = pointer.deserialize(text)
59 p = pointer.deserialize(text)
60 oid = p.oid()
60 oid = p.oid()
61 store = self.opener.lfslocalblobstore
61 store = self.opener.lfslocalblobstore
62 if not store.has(oid):
62 if not store.has(oid):
63 p.filename = self.filename
63 p.filename = self.filename
64 self.opener.lfsremoteblobstore.readbatch([p], store)
64 self.opener.lfsremoteblobstore.readbatch([p], store)
65
65
66 # The caller will validate the content
66 # The caller will validate the content
67 text = store.read(oid, verify=False)
67 text = store.read(oid, verify=False)
68
68
69 # pack hg filelog metadata
69 # pack hg filelog metadata
70 hgmeta = {}
70 hgmeta = {}
71 for k in p.keys():
71 for k in p.keys():
72 if k.startswith('x-hg-'):
72 if k.startswith('x-hg-'):
73 name = k[len('x-hg-'):]
73 name = k[len('x-hg-'):]
74 hgmeta[name] = p[k]
74 hgmeta[name] = p[k]
75 if hgmeta or text.startswith('\1\n'):
75 if hgmeta or text.startswith('\1\n'):
76 text = filelog.packmeta(hgmeta, text)
76 text = filelog.packmeta(hgmeta, text)
77
77
78 return (text, True)
78 return (text, True)
79
79
80 def writetostore(self, text):
80 def writetostore(self, text):
81 # hg filelog metadata (includes rename, etc)
81 # hg filelog metadata (includes rename, etc)
82 hgmeta, offset = filelog.parsemeta(text)
82 hgmeta, offset = filelog.parsemeta(text)
83 if offset and offset > 0:
83 if offset and offset > 0:
84 # lfs blob does not contain hg filelog metadata
84 # lfs blob does not contain hg filelog metadata
85 text = text[offset:]
85 text = text[offset:]
86
86
87 # git-lfs only supports sha256
87 # git-lfs only supports sha256
88 oid = hashlib.sha256(text).hexdigest()
88 oid = hashlib.sha256(text).hexdigest()
89 self.opener.lfslocalblobstore.write(oid, text)
89 self.opener.lfslocalblobstore.write(oid, text)
90
90
91 # replace contents with metadata
91 # replace contents with metadata
92 longoid = 'sha256:%s' % oid
92 longoid = 'sha256:%s' % oid
93 metadata = pointer.gitlfspointer(oid=longoid, size=str(len(text)))
93 metadata = pointer.gitlfspointer(oid=longoid, size=str(len(text)))
94
94
95 # by default, we expect the content to be binary. however, LFS could also
95 # by default, we expect the content to be binary. however, LFS could also
96 # be used for non-binary content. add a special entry for non-binary data.
96 # be used for non-binary content. add a special entry for non-binary data.
97 # this will be used by filectx.isbinary().
97 # this will be used by filectx.isbinary().
98 if not util.binary(text):
98 if not util.binary(text):
99 # not hg filelog metadata (affecting commit hash), no "x-hg-" prefix
99 # not hg filelog metadata (affecting commit hash), no "x-hg-" prefix
100 metadata['x-is-binary'] = '0'
100 metadata['x-is-binary'] = '0'
101
101
102 # translate hg filelog metadata to lfs metadata with "x-hg-" prefix
102 # translate hg filelog metadata to lfs metadata with "x-hg-" prefix
103 if hgmeta is not None:
103 if hgmeta is not None:
104 for k, v in hgmeta.iteritems():
104 for k, v in hgmeta.iteritems():
105 metadata['x-hg-%s' % k] = v
105 metadata['x-hg-%s' % k] = v
106
106
107 rawtext = metadata.serialize()
107 rawtext = metadata.serialize()
108 return (rawtext, False)
108 return (rawtext, False)
109
109
110 def _islfs(rlog, node=None, rev=None):
110 def _islfs(rlog, node=None, rev=None):
111 if rev is None:
111 if rev is None:
112 if node is None:
112 if node is None:
113 # both None - likely working copy content where node is not ready
113 # both None - likely working copy content where node is not ready
114 return False
114 return False
115 rev = rlog.rev(node)
115 rev = rlog.rev(node)
116 else:
116 else:
117 node = rlog.node(rev)
117 node = rlog.node(rev)
118 if node == nullid:
118 if node == nullid:
119 return False
119 return False
120 flags = rlog.flags(rev)
120 flags = rlog.flags(rev)
121 return bool(flags & revlog.REVIDX_EXTSTORED)
121 return bool(flags & revlog.REVIDX_EXTSTORED)
122
122
123 def filelogaddrevision(orig, self, text, transaction, link, p1, p2,
123 def filelogaddrevision(orig, self, text, transaction, link, p1, p2,
124 cachedelta=None, node=None,
124 cachedelta=None, node=None,
125 flags=revlog.REVIDX_DEFAULT_FLAGS, **kwds):
125 flags=revlog.REVIDX_DEFAULT_FLAGS, **kwds):
126 threshold = self.opener.options['lfsthreshold']
127 textlen = len(text)
126 textlen = len(text)
128 # exclude hg rename meta from file size
127 # exclude hg rename meta from file size
129 meta, offset = filelog.parsemeta(text)
128 meta, offset = filelog.parsemeta(text)
130 if offset:
129 if offset:
131 textlen -= offset
130 textlen -= offset
132
131
133 if threshold and textlen > threshold:
132 lfstrack = self.opener.options['lfstrack']
133 if lfstrack(self.filename, textlen):
134 flags |= revlog.REVIDX_EXTSTORED
134 flags |= revlog.REVIDX_EXTSTORED
135
135
136 return orig(self, text, transaction, link, p1, p2, cachedelta=cachedelta,
136 return orig(self, text, transaction, link, p1, p2, cachedelta=cachedelta,
137 node=node, flags=flags, **kwds)
137 node=node, flags=flags, **kwds)
138
138
139 def filelogrenamed(orig, self, node):
139 def filelogrenamed(orig, self, node):
140 if _islfs(self, node):
140 if _islfs(self, node):
141 rawtext = self.revision(node, raw=True)
141 rawtext = self.revision(node, raw=True)
142 if not rawtext:
142 if not rawtext:
143 return False
143 return False
144 metadata = pointer.deserialize(rawtext)
144 metadata = pointer.deserialize(rawtext)
145 if 'x-hg-copy' in metadata and 'x-hg-copyrev' in metadata:
145 if 'x-hg-copy' in metadata and 'x-hg-copyrev' in metadata:
146 return metadata['x-hg-copy'], bin(metadata['x-hg-copyrev'])
146 return metadata['x-hg-copy'], bin(metadata['x-hg-copyrev'])
147 else:
147 else:
148 return False
148 return False
149 return orig(self, node)
149 return orig(self, node)
150
150
151 def filelogsize(orig, self, rev):
151 def filelogsize(orig, self, rev):
152 if _islfs(self, rev=rev):
152 if _islfs(self, rev=rev):
153 # fast path: use lfs metadata to answer size
153 # fast path: use lfs metadata to answer size
154 rawtext = self.revision(rev, raw=True)
154 rawtext = self.revision(rev, raw=True)
155 metadata = pointer.deserialize(rawtext)
155 metadata = pointer.deserialize(rawtext)
156 return int(metadata['size'])
156 return int(metadata['size'])
157 return orig(self, rev)
157 return orig(self, rev)
158
158
159 def filectxcmp(orig, self, fctx):
159 def filectxcmp(orig, self, fctx):
160 """returns True if text is different than fctx"""
160 """returns True if text is different than fctx"""
161 # some fctx (ex. hg-git) is not based on basefilectx and do not have islfs
161 # some fctx (ex. hg-git) is not based on basefilectx and do not have islfs
162 if self.islfs() and getattr(fctx, 'islfs', lambda: False)():
162 if self.islfs() and getattr(fctx, 'islfs', lambda: False)():
163 # fast path: check LFS oid
163 # fast path: check LFS oid
164 p1 = pointer.deserialize(self.rawdata())
164 p1 = pointer.deserialize(self.rawdata())
165 p2 = pointer.deserialize(fctx.rawdata())
165 p2 = pointer.deserialize(fctx.rawdata())
166 return p1.oid() != p2.oid()
166 return p1.oid() != p2.oid()
167 return orig(self, fctx)
167 return orig(self, fctx)
168
168
169 def filectxisbinary(orig, self):
169 def filectxisbinary(orig, self):
170 if self.islfs():
170 if self.islfs():
171 # fast path: use lfs metadata to answer isbinary
171 # fast path: use lfs metadata to answer isbinary
172 metadata = pointer.deserialize(self.rawdata())
172 metadata = pointer.deserialize(self.rawdata())
173 # if lfs metadata says nothing, assume it's binary by default
173 # if lfs metadata says nothing, assume it's binary by default
174 return bool(int(metadata.get('x-is-binary', 1)))
174 return bool(int(metadata.get('x-is-binary', 1)))
175 return orig(self)
175 return orig(self)
176
176
177 def filectxislfs(self):
177 def filectxislfs(self):
178 return _islfs(self.filelog(), self.filenode())
178 return _islfs(self.filelog(), self.filenode())
179
179
180 def convertsink(orig, sink):
180 def convertsink(orig, sink):
181 sink = orig(sink)
181 sink = orig(sink)
182 if sink.repotype == 'hg':
182 if sink.repotype == 'hg':
183 class lfssink(sink.__class__):
183 class lfssink(sink.__class__):
184 def putcommit(self, files, copies, parents, commit, source, revmap,
184 def putcommit(self, files, copies, parents, commit, source, revmap,
185 full, cleanp2):
185 full, cleanp2):
186 pc = super(lfssink, self).putcommit
186 pc = super(lfssink, self).putcommit
187 node = pc(files, copies, parents, commit, source, revmap, full,
187 node = pc(files, copies, parents, commit, source, revmap, full,
188 cleanp2)
188 cleanp2)
189
189
190 if 'lfs' not in self.repo.requirements:
190 if 'lfs' not in self.repo.requirements:
191 ctx = self.repo[node]
191 ctx = self.repo[node]
192
192
193 # The file list may contain removed files, so check for
193 # The file list may contain removed files, so check for
194 # membership before assuming it is in the context.
194 # membership before assuming it is in the context.
195 if any(f in ctx and ctx[f].islfs() for f, n in files):
195 if any(f in ctx and ctx[f].islfs() for f, n in files):
196 self.repo.requirements.add('lfs')
196 self.repo.requirements.add('lfs')
197 self.repo._writerequirements()
197 self.repo._writerequirements()
198
198
199 # Permanently enable lfs locally
199 # Permanently enable lfs locally
200 with self.repo.vfs('hgrc', 'a', text=True) as fp:
200 with self.repo.vfs('hgrc', 'a', text=True) as fp:
201 fp.write('\n[extensions]\nlfs=\n')
201 fp.write('\n[extensions]\nlfs=\n')
202
202
203 return node
203 return node
204
204
205 sink.__class__ = lfssink
205 sink.__class__ = lfssink
206
206
207 return sink
207 return sink
208
208
209 def vfsinit(orig, self, othervfs):
209 def vfsinit(orig, self, othervfs):
210 orig(self, othervfs)
210 orig(self, othervfs)
211 # copy lfs related options
211 # copy lfs related options
212 for k, v in othervfs.options.items():
212 for k, v in othervfs.options.items():
213 if k.startswith('lfs'):
213 if k.startswith('lfs'):
214 self.options[k] = v
214 self.options[k] = v
215 # also copy lfs blobstores. note: this can run before reposetup, so lfs
215 # also copy lfs blobstores. note: this can run before reposetup, so lfs
216 # blobstore attributes are not always ready at this time.
216 # blobstore attributes are not always ready at this time.
217 for name in ['lfslocalblobstore', 'lfsremoteblobstore']:
217 for name in ['lfslocalblobstore', 'lfsremoteblobstore']:
218 if util.safehasattr(othervfs, name):
218 if util.safehasattr(othervfs, name):
219 setattr(self, name, getattr(othervfs, name))
219 setattr(self, name, getattr(othervfs, name))
220
220
221 def hgclone(orig, ui, opts, *args, **kwargs):
221 def hgclone(orig, ui, opts, *args, **kwargs):
222 result = orig(ui, opts, *args, **kwargs)
222 result = orig(ui, opts, *args, **kwargs)
223
223
224 if result is not None:
224 if result is not None:
225 sourcerepo, destrepo = result
225 sourcerepo, destrepo = result
226 repo = destrepo.local()
226 repo = destrepo.local()
227
227
228 # When cloning to a remote repo (like through SSH), no repo is available
228 # When cloning to a remote repo (like through SSH), no repo is available
229 # from the peer. Therefore the hgrc can't be updated.
229 # from the peer. Therefore the hgrc can't be updated.
230 if not repo:
230 if not repo:
231 return result
231 return result
232
232
233 # If lfs is required for this repo, permanently enable it locally
233 # If lfs is required for this repo, permanently enable it locally
234 if 'lfs' in repo.requirements:
234 if 'lfs' in repo.requirements:
235 with repo.vfs('hgrc', 'a', text=True) as fp:
235 with repo.vfs('hgrc', 'a', text=True) as fp:
236 fp.write('\n[extensions]\nlfs=\n')
236 fp.write('\n[extensions]\nlfs=\n')
237
237
238 return result
238 return result
239
239
240 def hgpostshare(orig, sourcerepo, destrepo, bookmarks=True, defaultpath=None):
240 def hgpostshare(orig, sourcerepo, destrepo, bookmarks=True, defaultpath=None):
241 orig(sourcerepo, destrepo, bookmarks, defaultpath)
241 orig(sourcerepo, destrepo, bookmarks, defaultpath)
242
242
243 # If lfs is required for this repo, permanently enable it locally
243 # If lfs is required for this repo, permanently enable it locally
244 if 'lfs' in destrepo.requirements:
244 if 'lfs' in destrepo.requirements:
245 with destrepo.vfs('hgrc', 'a', text=True) as fp:
245 with destrepo.vfs('hgrc', 'a', text=True) as fp:
246 fp.write('\n[extensions]\nlfs=\n')
246 fp.write('\n[extensions]\nlfs=\n')
247
247
248 def _canskipupload(repo):
248 def _canskipupload(repo):
249 # if remotestore is a null store, upload is a no-op and can be skipped
249 # if remotestore is a null store, upload is a no-op and can be skipped
250 return isinstance(repo.svfs.lfsremoteblobstore, blobstore._nullremote)
250 return isinstance(repo.svfs.lfsremoteblobstore, blobstore._nullremote)
251
251
252 def candownload(repo):
252 def candownload(repo):
253 # if remotestore is a null store, downloads will lead to nothing
253 # if remotestore is a null store, downloads will lead to nothing
254 return not isinstance(repo.svfs.lfsremoteblobstore, blobstore._nullremote)
254 return not isinstance(repo.svfs.lfsremoteblobstore, blobstore._nullremote)
255
255
256 def uploadblobsfromrevs(repo, revs):
256 def uploadblobsfromrevs(repo, revs):
257 '''upload lfs blobs introduced by revs
257 '''upload lfs blobs introduced by revs
258
258
259 Note: also used by other extensions e. g. infinitepush. avoid renaming.
259 Note: also used by other extensions e. g. infinitepush. avoid renaming.
260 '''
260 '''
261 if _canskipupload(repo):
261 if _canskipupload(repo):
262 return
262 return
263 pointers = extractpointers(repo, revs)
263 pointers = extractpointers(repo, revs)
264 uploadblobs(repo, pointers)
264 uploadblobs(repo, pointers)
265
265
266 def prepush(pushop):
266 def prepush(pushop):
267 """Prepush hook.
267 """Prepush hook.
268
268
269 Read through the revisions to push, looking for filelog entries that can be
269 Read through the revisions to push, looking for filelog entries that can be
270 deserialized into metadata so that we can block the push on their upload to
270 deserialized into metadata so that we can block the push on their upload to
271 the remote blobstore.
271 the remote blobstore.
272 """
272 """
273 return uploadblobsfromrevs(pushop.repo, pushop.outgoing.missing)
273 return uploadblobsfromrevs(pushop.repo, pushop.outgoing.missing)
274
274
275 def push(orig, repo, remote, *args, **kwargs):
275 def push(orig, repo, remote, *args, **kwargs):
276 """bail on push if the extension isn't enabled on remote when needed"""
276 """bail on push if the extension isn't enabled on remote when needed"""
277 if 'lfs' in repo.requirements:
277 if 'lfs' in repo.requirements:
278 # If the remote peer is for a local repo, the requirement tests in the
278 # If the remote peer is for a local repo, the requirement tests in the
279 # base class method enforce lfs support. Otherwise, some revisions in
279 # base class method enforce lfs support. Otherwise, some revisions in
280 # this repo use lfs, and the remote repo needs the extension loaded.
280 # this repo use lfs, and the remote repo needs the extension loaded.
281 if not remote.local() and not remote.capable('lfs'):
281 if not remote.local() and not remote.capable('lfs'):
282 # This is a copy of the message in exchange.push() when requirements
282 # This is a copy of the message in exchange.push() when requirements
283 # are missing between local repos.
283 # are missing between local repos.
284 m = _("required features are not supported in the destination: %s")
284 m = _("required features are not supported in the destination: %s")
285 raise error.Abort(m % 'lfs',
285 raise error.Abort(m % 'lfs',
286 hint=_('enable the lfs extension on the server'))
286 hint=_('enable the lfs extension on the server'))
287 return orig(repo, remote, *args, **kwargs)
287 return orig(repo, remote, *args, **kwargs)
288
288
289 def writenewbundle(orig, ui, repo, source, filename, bundletype, outgoing,
289 def writenewbundle(orig, ui, repo, source, filename, bundletype, outgoing,
290 *args, **kwargs):
290 *args, **kwargs):
291 """upload LFS blobs added by outgoing revisions on 'hg bundle'"""
291 """upload LFS blobs added by outgoing revisions on 'hg bundle'"""
292 uploadblobsfromrevs(repo, outgoing.missing)
292 uploadblobsfromrevs(repo, outgoing.missing)
293 return orig(ui, repo, source, filename, bundletype, outgoing, *args,
293 return orig(ui, repo, source, filename, bundletype, outgoing, *args,
294 **kwargs)
294 **kwargs)
295
295
296 def extractpointers(repo, revs):
296 def extractpointers(repo, revs):
297 """return a list of lfs pointers added by given revs"""
297 """return a list of lfs pointers added by given revs"""
298 repo.ui.debug('lfs: computing set of blobs to upload\n')
298 repo.ui.debug('lfs: computing set of blobs to upload\n')
299 pointers = {}
299 pointers = {}
300 for r in revs:
300 for r in revs:
301 ctx = repo[r]
301 ctx = repo[r]
302 for p in pointersfromctx(ctx).values():
302 for p in pointersfromctx(ctx).values():
303 pointers[p.oid()] = p
303 pointers[p.oid()] = p
304 return sorted(pointers.values())
304 return sorted(pointers.values())
305
305
306 def pointersfromctx(ctx):
306 def pointersfromctx(ctx):
307 """return a dict {path: pointer} for given single changectx"""
307 """return a dict {path: pointer} for given single changectx"""
308 result = {}
308 result = {}
309 for f in ctx.files():
309 for f in ctx.files():
310 if f not in ctx:
310 if f not in ctx:
311 continue
311 continue
312 fctx = ctx[f]
312 fctx = ctx[f]
313 if not _islfs(fctx.filelog(), fctx.filenode()):
313 if not _islfs(fctx.filelog(), fctx.filenode()):
314 continue
314 continue
315 try:
315 try:
316 result[f] = pointer.deserialize(fctx.rawdata())
316 result[f] = pointer.deserialize(fctx.rawdata())
317 except pointer.InvalidPointer as ex:
317 except pointer.InvalidPointer as ex:
318 raise error.Abort(_('lfs: corrupted pointer (%s@%s): %s\n')
318 raise error.Abort(_('lfs: corrupted pointer (%s@%s): %s\n')
319 % (f, short(ctx.node()), ex))
319 % (f, short(ctx.node()), ex))
320 return result
320 return result
321
321
322 def uploadblobs(repo, pointers):
322 def uploadblobs(repo, pointers):
323 """upload given pointers from local blobstore"""
323 """upload given pointers from local blobstore"""
324 if not pointers:
324 if not pointers:
325 return
325 return
326
326
327 remoteblob = repo.svfs.lfsremoteblobstore
327 remoteblob = repo.svfs.lfsremoteblobstore
328 remoteblob.writebatch(pointers, repo.svfs.lfslocalblobstore)
328 remoteblob.writebatch(pointers, repo.svfs.lfslocalblobstore)
329
329
330 def upgradefinishdatamigration(orig, ui, srcrepo, dstrepo, requirements):
330 def upgradefinishdatamigration(orig, ui, srcrepo, dstrepo, requirements):
331 orig(ui, srcrepo, dstrepo, requirements)
331 orig(ui, srcrepo, dstrepo, requirements)
332
332
333 srclfsvfs = srcrepo.svfs.lfslocalblobstore.vfs
333 srclfsvfs = srcrepo.svfs.lfslocalblobstore.vfs
334 dstlfsvfs = dstrepo.svfs.lfslocalblobstore.vfs
334 dstlfsvfs = dstrepo.svfs.lfslocalblobstore.vfs
335
335
336 for dirpath, dirs, files in srclfsvfs.walk():
336 for dirpath, dirs, files in srclfsvfs.walk():
337 for oid in files:
337 for oid in files:
338 ui.write(_('copying lfs blob %s\n') % oid)
338 ui.write(_('copying lfs blob %s\n') % oid)
339 lfutil.link(srclfsvfs.join(oid), dstlfsvfs.join(oid))
339 lfutil.link(srclfsvfs.join(oid), dstlfsvfs.join(oid))
340
340
341 def upgraderequirements(orig, repo):
341 def upgraderequirements(orig, repo):
342 reqs = orig(repo)
342 reqs = orig(repo)
343 if 'lfs' in repo.requirements:
343 if 'lfs' in repo.requirements:
344 reqs.add('lfs')
344 reqs.add('lfs')
345 return reqs
345 return reqs
@@ -1,191 +1,191 b''
1 #require lfs-test-server
1 #require lfs-test-server
2
2
3 $ LFS_LISTEN="tcp://:$HGPORT"
3 $ LFS_LISTEN="tcp://:$HGPORT"
4 $ LFS_HOST="localhost:$HGPORT"
4 $ LFS_HOST="localhost:$HGPORT"
5 $ LFS_PUBLIC=1
5 $ LFS_PUBLIC=1
6 $ export LFS_LISTEN LFS_HOST LFS_PUBLIC
6 $ export LFS_LISTEN LFS_HOST LFS_PUBLIC
7 #if no-windows
7 #if no-windows
8 $ lfs-test-server &> lfs-server.log &
8 $ lfs-test-server &> lfs-server.log &
9 $ echo $! >> $DAEMON_PIDS
9 $ echo $! >> $DAEMON_PIDS
10 #else
10 #else
11 $ cat >> $TESTTMP/spawn.py <<EOF
11 $ cat >> $TESTTMP/spawn.py <<EOF
12 > import os
12 > import os
13 > import subprocess
13 > import subprocess
14 > import sys
14 > import sys
15 >
15 >
16 > for path in os.environ["PATH"].split(os.pathsep):
16 > for path in os.environ["PATH"].split(os.pathsep):
17 > exe = os.path.join(path, 'lfs-test-server.exe')
17 > exe = os.path.join(path, 'lfs-test-server.exe')
18 > if os.path.exists(exe):
18 > if os.path.exists(exe):
19 > with open('lfs-server.log', 'wb') as out:
19 > with open('lfs-server.log', 'wb') as out:
20 > p = subprocess.Popen(exe, stdout=out, stderr=out)
20 > p = subprocess.Popen(exe, stdout=out, stderr=out)
21 > sys.stdout.write('%s\n' % p.pid)
21 > sys.stdout.write('%s\n' % p.pid)
22 > sys.exit(0)
22 > sys.exit(0)
23 > sys.exit(1)
23 > sys.exit(1)
24 > EOF
24 > EOF
25 $ $PYTHON $TESTTMP/spawn.py >> $DAEMON_PIDS
25 $ $PYTHON $TESTTMP/spawn.py >> $DAEMON_PIDS
26 #endif
26 #endif
27
27
28 $ cat >> $HGRCPATH <<EOF
28 $ cat >> $HGRCPATH <<EOF
29 > [extensions]
29 > [extensions]
30 > lfs=
30 > lfs=
31 > [lfs]
31 > [lfs]
32 > url=http://foo:bar@$LFS_HOST/
32 > url=http://foo:bar@$LFS_HOST/
33 > threshold=1
33 > track=all()
34 > EOF
34 > EOF
35
35
36 $ hg init repo1
36 $ hg init repo1
37 $ cd repo1
37 $ cd repo1
38 $ echo THIS-IS-LFS > a
38 $ echo THIS-IS-LFS > a
39 $ hg commit -m a -A a
39 $ hg commit -m a -A a
40
40
41 A push can be serviced directly from the usercache if it isn't in the local
41 A push can be serviced directly from the usercache if it isn't in the local
42 store.
42 store.
43
43
44 $ hg init ../repo2
44 $ hg init ../repo2
45 $ mv .hg/store/lfs .hg/store/lfs_
45 $ mv .hg/store/lfs .hg/store/lfs_
46 $ hg push ../repo2 -v
46 $ hg push ../repo2 -v
47 pushing to ../repo2
47 pushing to ../repo2
48 searching for changes
48 searching for changes
49 lfs: uploading 31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b (12 bytes)
49 lfs: uploading 31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b (12 bytes)
50 lfs: processed: 31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b
50 lfs: processed: 31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b
51 1 changesets found
51 1 changesets found
52 uncompressed size of bundle content:
52 uncompressed size of bundle content:
53 * (changelog) (glob)
53 * (changelog) (glob)
54 * (manifests) (glob)
54 * (manifests) (glob)
55 * a (glob)
55 * a (glob)
56 adding changesets
56 adding changesets
57 adding manifests
57 adding manifests
58 adding file changes
58 adding file changes
59 added 1 changesets with 1 changes to 1 files
59 added 1 changesets with 1 changes to 1 files
60 calling hook pretxnchangegroup.lfs: hgext.lfs.checkrequireslfs
60 calling hook pretxnchangegroup.lfs: hgext.lfs.checkrequireslfs
61 $ mv .hg/store/lfs_ .hg/store/lfs
61 $ mv .hg/store/lfs_ .hg/store/lfs
62
62
63 Clear the cache to force a download
63 Clear the cache to force a download
64 $ rm -rf `hg config lfs.usercache`
64 $ rm -rf `hg config lfs.usercache`
65 $ cd ../repo2
65 $ cd ../repo2
66 $ hg update tip -v
66 $ hg update tip -v
67 resolving manifests
67 resolving manifests
68 getting a
68 getting a
69 lfs: downloading 31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b (12 bytes)
69 lfs: downloading 31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b (12 bytes)
70 lfs: adding 31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b to the usercache
70 lfs: adding 31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b to the usercache
71 lfs: processed: 31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b
71 lfs: processed: 31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b
72 lfs: found 31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b in the local lfs store
72 lfs: found 31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b in the local lfs store
73 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
73 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
74
74
75 When the server has some blobs already
75 When the server has some blobs already
76
76
77 $ hg mv a b
77 $ hg mv a b
78 $ echo ANOTHER-LARGE-FILE > c
78 $ echo ANOTHER-LARGE-FILE > c
79 $ echo ANOTHER-LARGE-FILE2 > d
79 $ echo ANOTHER-LARGE-FILE2 > d
80 $ hg commit -m b-and-c -A b c d
80 $ hg commit -m b-and-c -A b c d
81 $ hg push ../repo1 -v | grep -v '^ '
81 $ hg push ../repo1 -v | grep -v '^ '
82 pushing to ../repo1
82 pushing to ../repo1
83 searching for changes
83 searching for changes
84 lfs: need to transfer 2 objects (39 bytes)
84 lfs: need to transfer 2 objects (39 bytes)
85 lfs: uploading 37a65ab78d5ecda767e8622c248b5dbff1e68b1678ab0e730d5eb8601ec8ad19 (20 bytes)
85 lfs: uploading 37a65ab78d5ecda767e8622c248b5dbff1e68b1678ab0e730d5eb8601ec8ad19 (20 bytes)
86 lfs: processed: 37a65ab78d5ecda767e8622c248b5dbff1e68b1678ab0e730d5eb8601ec8ad19
86 lfs: processed: 37a65ab78d5ecda767e8622c248b5dbff1e68b1678ab0e730d5eb8601ec8ad19
87 lfs: uploading d11e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998 (19 bytes)
87 lfs: uploading d11e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998 (19 bytes)
88 lfs: processed: d11e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998
88 lfs: processed: d11e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998
89 1 changesets found
89 1 changesets found
90 uncompressed size of bundle content:
90 uncompressed size of bundle content:
91 adding changesets
91 adding changesets
92 adding manifests
92 adding manifests
93 adding file changes
93 adding file changes
94 added 1 changesets with 3 changes to 3 files
94 added 1 changesets with 3 changes to 3 files
95
95
96 Clear the cache to force a download
96 Clear the cache to force a download
97 $ rm -rf `hg config lfs.usercache`
97 $ rm -rf `hg config lfs.usercache`
98 $ hg --repo ../repo1 update tip -v
98 $ hg --repo ../repo1 update tip -v
99 resolving manifests
99 resolving manifests
100 getting b
100 getting b
101 lfs: found 31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b in the local lfs store
101 lfs: found 31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b in the local lfs store
102 getting c
102 getting c
103 lfs: downloading d11e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998 (19 bytes)
103 lfs: downloading d11e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998 (19 bytes)
104 lfs: adding d11e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998 to the usercache
104 lfs: adding d11e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998 to the usercache
105 lfs: processed: d11e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998
105 lfs: processed: d11e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998
106 lfs: found d11e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998 in the local lfs store
106 lfs: found d11e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998 in the local lfs store
107 getting d
107 getting d
108 lfs: downloading 37a65ab78d5ecda767e8622c248b5dbff1e68b1678ab0e730d5eb8601ec8ad19 (20 bytes)
108 lfs: downloading 37a65ab78d5ecda767e8622c248b5dbff1e68b1678ab0e730d5eb8601ec8ad19 (20 bytes)
109 lfs: adding 37a65ab78d5ecda767e8622c248b5dbff1e68b1678ab0e730d5eb8601ec8ad19 to the usercache
109 lfs: adding 37a65ab78d5ecda767e8622c248b5dbff1e68b1678ab0e730d5eb8601ec8ad19 to the usercache
110 lfs: processed: 37a65ab78d5ecda767e8622c248b5dbff1e68b1678ab0e730d5eb8601ec8ad19
110 lfs: processed: 37a65ab78d5ecda767e8622c248b5dbff1e68b1678ab0e730d5eb8601ec8ad19
111 lfs: found 37a65ab78d5ecda767e8622c248b5dbff1e68b1678ab0e730d5eb8601ec8ad19 in the local lfs store
111 lfs: found 37a65ab78d5ecda767e8622c248b5dbff1e68b1678ab0e730d5eb8601ec8ad19 in the local lfs store
112 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
112 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
113
113
114 Test a corrupt file download, but clear the cache first to force a download.
114 Test a corrupt file download, but clear the cache first to force a download.
115
115
116 $ rm -rf `hg config lfs.usercache`
116 $ rm -rf `hg config lfs.usercache`
117 $ cp $TESTTMP/lfs-content/d1/1e/1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998 blob
117 $ cp $TESTTMP/lfs-content/d1/1e/1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998 blob
118 $ echo 'damage' > $TESTTMP/lfs-content/d1/1e/1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998
118 $ echo 'damage' > $TESTTMP/lfs-content/d1/1e/1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998
119 $ rm ../repo1/.hg/store/lfs/objects/d1/1e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998
119 $ rm ../repo1/.hg/store/lfs/objects/d1/1e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998
120 $ rm ../repo1/*
120 $ rm ../repo1/*
121
121
122 $ hg --repo ../repo1 update -C tip -v
122 $ hg --repo ../repo1 update -C tip -v
123 resolving manifests
123 resolving manifests
124 getting a
124 getting a
125 lfs: found 31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b in the local lfs store
125 lfs: found 31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b in the local lfs store
126 getting b
126 getting b
127 lfs: found 31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b in the local lfs store
127 lfs: found 31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b in the local lfs store
128 getting c
128 getting c
129 lfs: downloading d11e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998 (19 bytes)
129 lfs: downloading d11e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998 (19 bytes)
130 abort: corrupt remote lfs object: d11e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998
130 abort: corrupt remote lfs object: d11e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998
131 [255]
131 [255]
132
132
133 The corrupted blob is not added to the usercache or local store
133 The corrupted blob is not added to the usercache or local store
134
134
135 $ test -f ../repo1/.hg/store/lfs/objects/d1/1e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998
135 $ test -f ../repo1/.hg/store/lfs/objects/d1/1e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998
136 [1]
136 [1]
137 $ test -f `hg config lfs.usercache`/d1/1e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998
137 $ test -f `hg config lfs.usercache`/d1/1e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998
138 [1]
138 [1]
139 $ cp blob $TESTTMP/lfs-content/d1/1e/1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998
139 $ cp blob $TESTTMP/lfs-content/d1/1e/1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998
140
140
141 Test a corrupted file upload
141 Test a corrupted file upload
142
142
143 $ echo 'another lfs blob' > b
143 $ echo 'another lfs blob' > b
144 $ hg ci -m 'another blob'
144 $ hg ci -m 'another blob'
145 $ echo 'damage' > .hg/store/lfs/objects/e6/59058e26b07b39d2a9c7145b3f99b41f797b6621c8076600e9cb7ee88291f0
145 $ echo 'damage' > .hg/store/lfs/objects/e6/59058e26b07b39d2a9c7145b3f99b41f797b6621c8076600e9cb7ee88291f0
146 $ hg push -v ../repo1
146 $ hg push -v ../repo1
147 pushing to ../repo1
147 pushing to ../repo1
148 searching for changes
148 searching for changes
149 lfs: uploading e659058e26b07b39d2a9c7145b3f99b41f797b6621c8076600e9cb7ee88291f0 (17 bytes)
149 lfs: uploading e659058e26b07b39d2a9c7145b3f99b41f797b6621c8076600e9cb7ee88291f0 (17 bytes)
150 abort: detected corrupt lfs object: e659058e26b07b39d2a9c7145b3f99b41f797b6621c8076600e9cb7ee88291f0
150 abort: detected corrupt lfs object: e659058e26b07b39d2a9c7145b3f99b41f797b6621c8076600e9cb7ee88291f0
151 (run hg verify)
151 (run hg verify)
152 [255]
152 [255]
153
153
154 Check error message when the remote missed a blob:
154 Check error message when the remote missed a blob:
155
155
156 $ echo FFFFF > b
156 $ echo FFFFF > b
157 $ hg commit -m b -A b
157 $ hg commit -m b -A b
158 $ echo FFFFF >> b
158 $ echo FFFFF >> b
159 $ hg commit -m b b
159 $ hg commit -m b b
160 $ rm -rf .hg/store/lfs
160 $ rm -rf .hg/store/lfs
161 $ rm -rf `hg config lfs.usercache`
161 $ rm -rf `hg config lfs.usercache`
162 $ hg update -C '.^'
162 $ hg update -C '.^'
163 abort: LFS server claims required objects do not exist:
163 abort: LFS server claims required objects do not exist:
164 8e6ea5f6c066b44a0efa43bcce86aea73f17e6e23f0663df0251e7524e140a13!
164 8e6ea5f6c066b44a0efa43bcce86aea73f17e6e23f0663df0251e7524e140a13!
165 [255]
165 [255]
166
166
167 Check error message when object does not exist:
167 Check error message when object does not exist:
168
168
169 $ hg init test && cd test
169 $ hg init test && cd test
170 $ echo "[extensions]" >> .hg/hgrc
170 $ echo "[extensions]" >> .hg/hgrc
171 $ echo "lfs=" >> .hg/hgrc
171 $ echo "lfs=" >> .hg/hgrc
172 $ echo "[lfs]" >> .hg/hgrc
172 $ echo "[lfs]" >> .hg/hgrc
173 $ echo "threshold=1" >> .hg/hgrc
173 $ echo "threshold=1" >> .hg/hgrc
174 $ echo a > a
174 $ echo a > a
175 $ hg add a
175 $ hg add a
176 $ hg commit -m 'test'
176 $ hg commit -m 'test'
177 $ echo aaaaa > a
177 $ echo aaaaa > a
178 $ hg commit -m 'largefile'
178 $ hg commit -m 'largefile'
179 $ hg debugdata .hg/store/data/a.i 1 # verify this is no the file content but includes "oid", the LFS "pointer".
179 $ hg debugdata .hg/store/data/a.i 1 # verify this is no the file content but includes "oid", the LFS "pointer".
180 version https://git-lfs.github.com/spec/v1
180 version https://git-lfs.github.com/spec/v1
181 oid sha256:bdc26931acfb734b142a8d675f205becf27560dc461f501822de13274fe6fc8a
181 oid sha256:bdc26931acfb734b142a8d675f205becf27560dc461f501822de13274fe6fc8a
182 size 6
182 size 6
183 x-is-binary 0
183 x-is-binary 0
184 $ cd ..
184 $ cd ..
185 $ rm -rf `hg config lfs.usercache`
185 $ rm -rf `hg config lfs.usercache`
186 $ hg --config 'lfs.url=https://dewey-lfs.vip.facebook.com/lfs' clone test test2
186 $ hg --config 'lfs.url=https://dewey-lfs.vip.facebook.com/lfs' clone test test2
187 updating to branch default
187 updating to branch default
188 abort: LFS server error. Remote object for "a" not found:(.*)! (re)
188 abort: LFS server error. Remote object for "a" not found:(.*)! (re)
189 [255]
189 [255]
190
190
191 $ $PYTHON $RUNTESTDIR/killdaemons.py $DAEMON_PIDS
191 $ $PYTHON $RUNTESTDIR/killdaemons.py $DAEMON_PIDS
@@ -1,915 +1,957 b''
1 # Initial setup
1 # Initial setup
2
2
3 $ cat >> $HGRCPATH << EOF
3 $ cat >> $HGRCPATH << EOF
4 > [extensions]
4 > [extensions]
5 > lfs=
5 > lfs=
6 > [lfs]
6 > [lfs]
7 > # Test deprecated config
7 > threshold=1000B
8 > threshold=1000B
8 > EOF
9 > EOF
9
10
10 $ LONG=AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
11 $ LONG=AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
11
12
12 # Prepare server and enable extension
13 # Prepare server and enable extension
13 $ hg init server
14 $ hg init server
14 $ hg clone -q server client
15 $ hg clone -q server client
15 $ cd client
16 $ cd client
16
17
17 # Commit small file
18 # Commit small file
18 $ echo s > smallfile
19 $ echo s > smallfile
19 $ hg commit -Aqm "add small file"
20 $ hg commit -Aqm "add small file"
20
21
21 # Commit large file
22 # Commit large file
22 $ echo $LONG > largefile
23 $ echo $LONG > largefile
23 $ grep lfs .hg/requires
24 $ grep lfs .hg/requires
24 [1]
25 [1]
25 $ hg commit --traceback -Aqm "add large file"
26 $ hg commit --traceback -Aqm "add large file"
26 $ grep lfs .hg/requires
27 $ grep lfs .hg/requires
27 lfs
28 lfs
28
29
29 # Ensure metadata is stored
30 # Ensure metadata is stored
30 $ hg debugdata largefile 0
31 $ hg debugdata largefile 0
31 version https://git-lfs.github.com/spec/v1
32 version https://git-lfs.github.com/spec/v1
32 oid sha256:f11e77c257047a398492d8d6cb9f6acf3aa7c4384bb23080b43546053e183e4b
33 oid sha256:f11e77c257047a398492d8d6cb9f6acf3aa7c4384bb23080b43546053e183e4b
33 size 1501
34 size 1501
34 x-is-binary 0
35 x-is-binary 0
35
36
36 # Check the blobstore is populated
37 # Check the blobstore is populated
37 $ find .hg/store/lfs/objects | sort
38 $ find .hg/store/lfs/objects | sort
38 .hg/store/lfs/objects
39 .hg/store/lfs/objects
39 .hg/store/lfs/objects/f1
40 .hg/store/lfs/objects/f1
40 .hg/store/lfs/objects/f1/1e77c257047a398492d8d6cb9f6acf3aa7c4384bb23080b43546053e183e4b
41 .hg/store/lfs/objects/f1/1e77c257047a398492d8d6cb9f6acf3aa7c4384bb23080b43546053e183e4b
41
42
42 # Check the blob stored contains the actual contents of the file
43 # Check the blob stored contains the actual contents of the file
43 $ cat .hg/store/lfs/objects/f1/1e77c257047a398492d8d6cb9f6acf3aa7c4384bb23080b43546053e183e4b
44 $ cat .hg/store/lfs/objects/f1/1e77c257047a398492d8d6cb9f6acf3aa7c4384bb23080b43546053e183e4b
44 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
45 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
45
46
46 # Push changes to the server
47 # Push changes to the server
47
48
48 $ hg push
49 $ hg push
49 pushing to $TESTTMP/server
50 pushing to $TESTTMP/server
50 searching for changes
51 searching for changes
51 abort: lfs.url needs to be configured
52 abort: lfs.url needs to be configured
52 [255]
53 [255]
53
54
54 $ cat >> $HGRCPATH << EOF
55 $ cat >> $HGRCPATH << EOF
55 > [lfs]
56 > [lfs]
56 > url=file:$TESTTMP/dummy-remote/
57 > url=file:$TESTTMP/dummy-remote/
57 > EOF
58 > EOF
58
59
59 Push to a local non-lfs repo with the extension enabled will add the
60 Push to a local non-lfs repo with the extension enabled will add the
60 lfs requirement
61 lfs requirement
61
62
62 $ grep lfs $TESTTMP/server/.hg/requires
63 $ grep lfs $TESTTMP/server/.hg/requires
63 [1]
64 [1]
64 $ hg push -v | egrep -v '^(uncompressed| )'
65 $ hg push -v | egrep -v '^(uncompressed| )'
65 pushing to $TESTTMP/server
66 pushing to $TESTTMP/server
66 searching for changes
67 searching for changes
67 lfs: found f11e77c257047a398492d8d6cb9f6acf3aa7c4384bb23080b43546053e183e4b in the local lfs store
68 lfs: found f11e77c257047a398492d8d6cb9f6acf3aa7c4384bb23080b43546053e183e4b in the local lfs store
68 2 changesets found
69 2 changesets found
69 adding changesets
70 adding changesets
70 adding manifests
71 adding manifests
71 adding file changes
72 adding file changes
72 added 2 changesets with 2 changes to 2 files
73 added 2 changesets with 2 changes to 2 files
73 calling hook pretxnchangegroup.lfs: hgext.lfs.checkrequireslfs
74 calling hook pretxnchangegroup.lfs: hgext.lfs.checkrequireslfs
74 $ grep lfs $TESTTMP/server/.hg/requires
75 $ grep lfs $TESTTMP/server/.hg/requires
75 lfs
76 lfs
76
77
77 # Unknown URL scheme
78 # Unknown URL scheme
78
79
79 $ hg push --config lfs.url=ftp://foobar
80 $ hg push --config lfs.url=ftp://foobar
80 abort: lfs: unknown url scheme: ftp
81 abort: lfs: unknown url scheme: ftp
81 [255]
82 [255]
82
83
83 $ cd ../
84 $ cd ../
84
85
85 # Initialize new client (not cloning) and setup extension
86 # Initialize new client (not cloning) and setup extension
86 $ hg init client2
87 $ hg init client2
87 $ cd client2
88 $ cd client2
88 $ cat >> .hg/hgrc <<EOF
89 $ cat >> .hg/hgrc <<EOF
89 > [paths]
90 > [paths]
90 > default = $TESTTMP/server
91 > default = $TESTTMP/server
91 > EOF
92 > EOF
92
93
93 # Pull from server
94 # Pull from server
94
95
95 Pulling a local lfs repo into a local non-lfs repo with the extension
96 Pulling a local lfs repo into a local non-lfs repo with the extension
96 enabled adds the lfs requirement
97 enabled adds the lfs requirement
97
98
98 $ grep lfs .hg/requires $TESTTMP/server/.hg/requires
99 $ grep lfs .hg/requires $TESTTMP/server/.hg/requires
99 $TESTTMP/server/.hg/requires:lfs
100 $TESTTMP/server/.hg/requires:lfs
100 $ hg pull default
101 $ hg pull default
101 pulling from $TESTTMP/server
102 pulling from $TESTTMP/server
102 requesting all changes
103 requesting all changes
103 adding changesets
104 adding changesets
104 adding manifests
105 adding manifests
105 adding file changes
106 adding file changes
106 added 2 changesets with 2 changes to 2 files
107 added 2 changesets with 2 changes to 2 files
107 new changesets b29ba743f89d:00c137947d30
108 new changesets b29ba743f89d:00c137947d30
108 (run 'hg update' to get a working copy)
109 (run 'hg update' to get a working copy)
109 $ grep lfs .hg/requires $TESTTMP/server/.hg/requires
110 $ grep lfs .hg/requires $TESTTMP/server/.hg/requires
110 .hg/requires:lfs
111 .hg/requires:lfs
111 $TESTTMP/server/.hg/requires:lfs
112 $TESTTMP/server/.hg/requires:lfs
112
113
113 # Check the blobstore is not yet populated
114 # Check the blobstore is not yet populated
114 $ [ -d .hg/store/lfs/objects ]
115 $ [ -d .hg/store/lfs/objects ]
115 [1]
116 [1]
116
117
117 # Update to the last revision containing the large file
118 # Update to the last revision containing the large file
118 $ hg update
119 $ hg update
119 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
120 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
120
121
121 # Check the blobstore has been populated on update
122 # Check the blobstore has been populated on update
122 $ find .hg/store/lfs/objects | sort
123 $ find .hg/store/lfs/objects | sort
123 .hg/store/lfs/objects
124 .hg/store/lfs/objects
124 .hg/store/lfs/objects/f1
125 .hg/store/lfs/objects/f1
125 .hg/store/lfs/objects/f1/1e77c257047a398492d8d6cb9f6acf3aa7c4384bb23080b43546053e183e4b
126 .hg/store/lfs/objects/f1/1e77c257047a398492d8d6cb9f6acf3aa7c4384bb23080b43546053e183e4b
126
127
127 # Check the contents of the file are fetched from blobstore when requested
128 # Check the contents of the file are fetched from blobstore when requested
128 $ hg cat -r . largefile
129 $ hg cat -r . largefile
129 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
130 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
130
131
131 # Check the file has been copied in the working copy
132 # Check the file has been copied in the working copy
132 $ cat largefile
133 $ cat largefile
133 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
134 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
134
135
135 $ cd ..
136 $ cd ..
136
137
137 # Check rename, and switch between large and small files
138 # Check rename, and switch between large and small files
138
139
139 $ hg init repo3
140 $ hg init repo3
140 $ cd repo3
141 $ cd repo3
141 $ cat >> .hg/hgrc << EOF
142 $ cat >> .hg/hgrc << EOF
142 > [lfs]
143 > [lfs]
143 > threshold=10B
144 > track=size(">10B")
144 > EOF
145 > EOF
145
146
146 $ echo LONGER-THAN-TEN-BYTES-WILL-TRIGGER-LFS > large
147 $ echo LONGER-THAN-TEN-BYTES-WILL-TRIGGER-LFS > large
147 $ echo SHORTER > small
148 $ echo SHORTER > small
148 $ hg add . -q
149 $ hg add . -q
149 $ hg commit -m 'commit with lfs content'
150 $ hg commit -m 'commit with lfs content'
150
151
151 $ hg mv large l
152 $ hg mv large l
152 $ hg mv small s
153 $ hg mv small s
153 $ hg commit -m 'renames'
154 $ hg commit -m 'renames'
154
155
155 $ echo SHORT > l
156 $ echo SHORT > l
156 $ echo BECOME-LARGER-FROM-SHORTER > s
157 $ echo BECOME-LARGER-FROM-SHORTER > s
157 $ hg commit -m 'large to small, small to large'
158 $ hg commit -m 'large to small, small to large'
158
159
159 $ echo 1 >> l
160 $ echo 1 >> l
160 $ echo 2 >> s
161 $ echo 2 >> s
161 $ hg commit -m 'random modifications'
162 $ hg commit -m 'random modifications'
162
163
163 $ echo RESTORE-TO-BE-LARGE > l
164 $ echo RESTORE-TO-BE-LARGE > l
164 $ echo SHORTER > s
165 $ echo SHORTER > s
165 $ hg commit -m 'switch large and small again'
166 $ hg commit -m 'switch large and small again'
166
167
167 # Test lfs_files template
168 # Test lfs_files template
168
169
169 $ hg log -r 'all()' -T '{rev} {join(lfs_files, ", ")}\n'
170 $ hg log -r 'all()' -T '{rev} {join(lfs_files, ", ")}\n'
170 0 large
171 0 large
171 1 l
172 1 l
172 2 s
173 2 s
173 3 s
174 3 s
174 4 l
175 4 l
175
176
176 # Push and pull the above repo
177 # Push and pull the above repo
177
178
178 $ hg --cwd .. init repo4
179 $ hg --cwd .. init repo4
179 $ hg push ../repo4
180 $ hg push ../repo4
180 pushing to ../repo4
181 pushing to ../repo4
181 searching for changes
182 searching for changes
182 adding changesets
183 adding changesets
183 adding manifests
184 adding manifests
184 adding file changes
185 adding file changes
185 added 5 changesets with 10 changes to 4 files
186 added 5 changesets with 10 changes to 4 files
186
187
187 $ hg --cwd .. init repo5
188 $ hg --cwd .. init repo5
188 $ hg --cwd ../repo5 pull ../repo3
189 $ hg --cwd ../repo5 pull ../repo3
189 pulling from ../repo3
190 pulling from ../repo3
190 requesting all changes
191 requesting all changes
191 adding changesets
192 adding changesets
192 adding manifests
193 adding manifests
193 adding file changes
194 adding file changes
194 added 5 changesets with 10 changes to 4 files
195 added 5 changesets with 10 changes to 4 files
195 new changesets fd47a419c4f7:5adf850972b9
196 new changesets fd47a419c4f7:5adf850972b9
196 (run 'hg update' to get a working copy)
197 (run 'hg update' to get a working copy)
197
198
198 $ cd ..
199 $ cd ..
199
200
200 # Test clone
201 # Test clone
201
202
202 $ hg init repo6
203 $ hg init repo6
203 $ cd repo6
204 $ cd repo6
204 $ cat >> .hg/hgrc << EOF
205 $ cat >> .hg/hgrc << EOF
205 > [lfs]
206 > [lfs]
206 > threshold=30B
207 > track=size(">30B")
207 > EOF
208 > EOF
208
209
209 $ echo LARGE-BECAUSE-IT-IS-MORE-THAN-30-BYTES > large
210 $ echo LARGE-BECAUSE-IT-IS-MORE-THAN-30-BYTES > large
210 $ echo SMALL > small
211 $ echo SMALL > small
211 $ hg commit -Aqm 'create a lfs file' large small
212 $ hg commit -Aqm 'create a lfs file' large small
212 $ hg debuglfsupload -r 'all()' -v
213 $ hg debuglfsupload -r 'all()' -v
213 lfs: found 8e92251415339ae9b148c8da89ed5ec665905166a1ab11b09dca8fad83344738 in the local lfs store
214 lfs: found 8e92251415339ae9b148c8da89ed5ec665905166a1ab11b09dca8fad83344738 in the local lfs store
214
215
215 $ cd ..
216 $ cd ..
216
217
217 $ hg clone repo6 repo7
218 $ hg clone repo6 repo7
218 updating to branch default
219 updating to branch default
219 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
220 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
220 $ cd repo7
221 $ cd repo7
221 $ hg config extensions --debug | grep lfs
222 $ hg config extensions --debug | grep lfs
222 $TESTTMP/repo7/.hg/hgrc:*: extensions.lfs= (glob)
223 $TESTTMP/repo7/.hg/hgrc:*: extensions.lfs= (glob)
223 $ cat large
224 $ cat large
224 LARGE-BECAUSE-IT-IS-MORE-THAN-30-BYTES
225 LARGE-BECAUSE-IT-IS-MORE-THAN-30-BYTES
225 $ cat small
226 $ cat small
226 SMALL
227 SMALL
227
228
228 $ cd ..
229 $ cd ..
229
230
230 $ hg --config extensions.share= share repo7 sharedrepo
231 $ hg --config extensions.share= share repo7 sharedrepo
231 updating working directory
232 updating working directory
232 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
233 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
233 $ hg -R sharedrepo config extensions --debug | grep lfs
234 $ hg -R sharedrepo config extensions --debug | grep lfs
234 $TESTTMP/sharedrepo/.hg/hgrc:*: extensions.lfs= (glob)
235 $TESTTMP/sharedrepo/.hg/hgrc:*: extensions.lfs= (glob)
235
236
236 # Test rename and status
237 # Test rename and status
237
238
238 $ hg init repo8
239 $ hg init repo8
239 $ cd repo8
240 $ cd repo8
240 $ cat >> .hg/hgrc << EOF
241 $ cat >> .hg/hgrc << EOF
241 > [lfs]
242 > [lfs]
242 > threshold=10B
243 > track=size(">10B")
243 > EOF
244 > EOF
244
245
245 $ echo THIS-IS-LFS-BECAUSE-10-BYTES > a1
246 $ echo THIS-IS-LFS-BECAUSE-10-BYTES > a1
246 $ echo SMALL > a2
247 $ echo SMALL > a2
247 $ hg commit -m a -A a1 a2
248 $ hg commit -m a -A a1 a2
248 $ hg status
249 $ hg status
249 $ hg mv a1 b1
250 $ hg mv a1 b1
250 $ hg mv a2 a1
251 $ hg mv a2 a1
251 $ hg mv b1 a2
252 $ hg mv b1 a2
252 $ hg commit -m b
253 $ hg commit -m b
253 $ hg status
254 $ hg status
254 >>> with open('a2', 'wb') as f:
255 >>> with open('a2', 'wb') as f:
255 ... f.write(b'\1\nSTART-WITH-HG-FILELOG-METADATA')
256 ... f.write(b'\1\nSTART-WITH-HG-FILELOG-METADATA')
256 >>> with open('a1', 'wb') as f:
257 >>> with open('a1', 'wb') as f:
257 ... f.write(b'\1\nMETA\n')
258 ... f.write(b'\1\nMETA\n')
258 $ hg commit -m meta
259 $ hg commit -m meta
259 $ hg status
260 $ hg status
260 $ hg log -T '{rev}: {file_copies} | {file_dels} | {file_adds}\n'
261 $ hg log -T '{rev}: {file_copies} | {file_dels} | {file_adds}\n'
261 2: | |
262 2: | |
262 1: a1 (a2)a2 (a1) | |
263 1: a1 (a2)a2 (a1) | |
263 0: | | a1 a2
264 0: | | a1 a2
264
265
265 $ for n in a1 a2; do
266 $ for n in a1 a2; do
266 > for r in 0 1 2; do
267 > for r in 0 1 2; do
267 > printf '\n%s @ %s\n' $n $r
268 > printf '\n%s @ %s\n' $n $r
268 > hg debugdata $n $r
269 > hg debugdata $n $r
269 > done
270 > done
270 > done
271 > done
271
272
272 a1 @ 0
273 a1 @ 0
273 version https://git-lfs.github.com/spec/v1
274 version https://git-lfs.github.com/spec/v1
274 oid sha256:5bb8341bee63b3649f222b2215bde37322bea075a30575aa685d8f8d21c77024
275 oid sha256:5bb8341bee63b3649f222b2215bde37322bea075a30575aa685d8f8d21c77024
275 size 29
276 size 29
276 x-is-binary 0
277 x-is-binary 0
277
278
278 a1 @ 1
279 a1 @ 1
279 \x01 (esc)
280 \x01 (esc)
280 copy: a2
281 copy: a2
281 copyrev: 50470ad23cf937b1f4b9f80bfe54df38e65b50d9
282 copyrev: 50470ad23cf937b1f4b9f80bfe54df38e65b50d9
282 \x01 (esc)
283 \x01 (esc)
283 SMALL
284 SMALL
284
285
285 a1 @ 2
286 a1 @ 2
286 \x01 (esc)
287 \x01 (esc)
287 \x01 (esc)
288 \x01 (esc)
288 \x01 (esc)
289 \x01 (esc)
289 META
290 META
290
291
291 a2 @ 0
292 a2 @ 0
292 SMALL
293 SMALL
293
294
294 a2 @ 1
295 a2 @ 1
295 version https://git-lfs.github.com/spec/v1
296 version https://git-lfs.github.com/spec/v1
296 oid sha256:5bb8341bee63b3649f222b2215bde37322bea075a30575aa685d8f8d21c77024
297 oid sha256:5bb8341bee63b3649f222b2215bde37322bea075a30575aa685d8f8d21c77024
297 size 29
298 size 29
298 x-hg-copy a1
299 x-hg-copy a1
299 x-hg-copyrev be23af27908a582af43e5cda209a5a9b319de8d4
300 x-hg-copyrev be23af27908a582af43e5cda209a5a9b319de8d4
300 x-is-binary 0
301 x-is-binary 0
301
302
302 a2 @ 2
303 a2 @ 2
303 version https://git-lfs.github.com/spec/v1
304 version https://git-lfs.github.com/spec/v1
304 oid sha256:876dadc86a8542f9798048f2c47f51dbf8e4359aed883e8ec80c5db825f0d943
305 oid sha256:876dadc86a8542f9798048f2c47f51dbf8e4359aed883e8ec80c5db825f0d943
305 size 32
306 size 32
306 x-is-binary 0
307 x-is-binary 0
307
308
308 # Verify commit hashes include rename metadata
309 # Verify commit hashes include rename metadata
309
310
310 $ hg log -T '{rev}:{node|short} {desc}\n'
311 $ hg log -T '{rev}:{node|short} {desc}\n'
311 2:0fae949de7fa meta
312 2:0fae949de7fa meta
312 1:9cd6bdffdac0 b
313 1:9cd6bdffdac0 b
313 0:7f96794915f7 a
314 0:7f96794915f7 a
314
315
315 $ cd ..
316 $ cd ..
316
317
317 # Test bundle
318 # Test bundle
318
319
319 $ hg init repo9
320 $ hg init repo9
320 $ cd repo9
321 $ cd repo9
321 $ cat >> .hg/hgrc << EOF
322 $ cat >> .hg/hgrc << EOF
322 > [lfs]
323 > [lfs]
323 > threshold=10B
324 > track=size(">10B")
324 > [diff]
325 > [diff]
325 > git=1
326 > git=1
326 > EOF
327 > EOF
327
328
328 $ for i in 0 single two three 4; do
329 $ for i in 0 single two three 4; do
329 > echo 'THIS-IS-LFS-'$i > a
330 > echo 'THIS-IS-LFS-'$i > a
330 > hg commit -m a-$i -A a
331 > hg commit -m a-$i -A a
331 > done
332 > done
332
333
333 $ hg update 2 -q
334 $ hg update 2 -q
334 $ echo 'THIS-IS-LFS-2-CHILD' > a
335 $ echo 'THIS-IS-LFS-2-CHILD' > a
335 $ hg commit -m branching -q
336 $ hg commit -m branching -q
336
337
337 $ hg bundle --base 1 bundle.hg -v
338 $ hg bundle --base 1 bundle.hg -v
338 lfs: found 5ab7a3739a5feec94a562d070a14f36dba7cad17e5484a4a89eea8e5f3166888 in the local lfs store
339 lfs: found 5ab7a3739a5feec94a562d070a14f36dba7cad17e5484a4a89eea8e5f3166888 in the local lfs store
339 lfs: found a9c7d1cd6ce2b9bbdf46ed9a862845228717b921c089d0d42e3bcaed29eb612e in the local lfs store
340 lfs: found a9c7d1cd6ce2b9bbdf46ed9a862845228717b921c089d0d42e3bcaed29eb612e in the local lfs store
340 lfs: found f693890c49c409ec33673b71e53f297681f76c1166daf33b2ad7ebf8b1d3237e in the local lfs store
341 lfs: found f693890c49c409ec33673b71e53f297681f76c1166daf33b2ad7ebf8b1d3237e in the local lfs store
341 lfs: found fda198fea753eb66a252e9856915e1f5cddbe41723bd4b695ece2604ad3c9f75 in the local lfs store
342 lfs: found fda198fea753eb66a252e9856915e1f5cddbe41723bd4b695ece2604ad3c9f75 in the local lfs store
342 4 changesets found
343 4 changesets found
343 uncompressed size of bundle content:
344 uncompressed size of bundle content:
344 * (changelog) (glob)
345 * (changelog) (glob)
345 * (manifests) (glob)
346 * (manifests) (glob)
346 * a (glob)
347 * a (glob)
347 $ hg --config extensions.strip= strip -r 2 --no-backup --force -q
348 $ hg --config extensions.strip= strip -r 2 --no-backup --force -q
348 $ hg -R bundle.hg log -p -T '{rev} {desc}\n' a
349 $ hg -R bundle.hg log -p -T '{rev} {desc}\n' a
349 5 branching
350 5 branching
350 diff --git a/a b/a
351 diff --git a/a b/a
351 --- a/a
352 --- a/a
352 +++ b/a
353 +++ b/a
353 @@ -1,1 +1,1 @@
354 @@ -1,1 +1,1 @@
354 -THIS-IS-LFS-two
355 -THIS-IS-LFS-two
355 +THIS-IS-LFS-2-CHILD
356 +THIS-IS-LFS-2-CHILD
356
357
357 4 a-4
358 4 a-4
358 diff --git a/a b/a
359 diff --git a/a b/a
359 --- a/a
360 --- a/a
360 +++ b/a
361 +++ b/a
361 @@ -1,1 +1,1 @@
362 @@ -1,1 +1,1 @@
362 -THIS-IS-LFS-three
363 -THIS-IS-LFS-three
363 +THIS-IS-LFS-4
364 +THIS-IS-LFS-4
364
365
365 3 a-three
366 3 a-three
366 diff --git a/a b/a
367 diff --git a/a b/a
367 --- a/a
368 --- a/a
368 +++ b/a
369 +++ b/a
369 @@ -1,1 +1,1 @@
370 @@ -1,1 +1,1 @@
370 -THIS-IS-LFS-two
371 -THIS-IS-LFS-two
371 +THIS-IS-LFS-three
372 +THIS-IS-LFS-three
372
373
373 2 a-two
374 2 a-two
374 diff --git a/a b/a
375 diff --git a/a b/a
375 --- a/a
376 --- a/a
376 +++ b/a
377 +++ b/a
377 @@ -1,1 +1,1 @@
378 @@ -1,1 +1,1 @@
378 -THIS-IS-LFS-single
379 -THIS-IS-LFS-single
379 +THIS-IS-LFS-two
380 +THIS-IS-LFS-two
380
381
381 1 a-single
382 1 a-single
382 diff --git a/a b/a
383 diff --git a/a b/a
383 --- a/a
384 --- a/a
384 +++ b/a
385 +++ b/a
385 @@ -1,1 +1,1 @@
386 @@ -1,1 +1,1 @@
386 -THIS-IS-LFS-0
387 -THIS-IS-LFS-0
387 +THIS-IS-LFS-single
388 +THIS-IS-LFS-single
388
389
389 0 a-0
390 0 a-0
390 diff --git a/a b/a
391 diff --git a/a b/a
391 new file mode 100644
392 new file mode 100644
392 --- /dev/null
393 --- /dev/null
393 +++ b/a
394 +++ b/a
394 @@ -0,0 +1,1 @@
395 @@ -0,0 +1,1 @@
395 +THIS-IS-LFS-0
396 +THIS-IS-LFS-0
396
397
397 $ hg bundle -R bundle.hg --base 1 bundle-again.hg -q
398 $ hg bundle -R bundle.hg --base 1 bundle-again.hg -q
398 $ hg -R bundle-again.hg log -p -T '{rev} {desc}\n' a
399 $ hg -R bundle-again.hg log -p -T '{rev} {desc}\n' a
399 5 branching
400 5 branching
400 diff --git a/a b/a
401 diff --git a/a b/a
401 --- a/a
402 --- a/a
402 +++ b/a
403 +++ b/a
403 @@ -1,1 +1,1 @@
404 @@ -1,1 +1,1 @@
404 -THIS-IS-LFS-two
405 -THIS-IS-LFS-two
405 +THIS-IS-LFS-2-CHILD
406 +THIS-IS-LFS-2-CHILD
406
407
407 4 a-4
408 4 a-4
408 diff --git a/a b/a
409 diff --git a/a b/a
409 --- a/a
410 --- a/a
410 +++ b/a
411 +++ b/a
411 @@ -1,1 +1,1 @@
412 @@ -1,1 +1,1 @@
412 -THIS-IS-LFS-three
413 -THIS-IS-LFS-three
413 +THIS-IS-LFS-4
414 +THIS-IS-LFS-4
414
415
415 3 a-three
416 3 a-three
416 diff --git a/a b/a
417 diff --git a/a b/a
417 --- a/a
418 --- a/a
418 +++ b/a
419 +++ b/a
419 @@ -1,1 +1,1 @@
420 @@ -1,1 +1,1 @@
420 -THIS-IS-LFS-two
421 -THIS-IS-LFS-two
421 +THIS-IS-LFS-three
422 +THIS-IS-LFS-three
422
423
423 2 a-two
424 2 a-two
424 diff --git a/a b/a
425 diff --git a/a b/a
425 --- a/a
426 --- a/a
426 +++ b/a
427 +++ b/a
427 @@ -1,1 +1,1 @@
428 @@ -1,1 +1,1 @@
428 -THIS-IS-LFS-single
429 -THIS-IS-LFS-single
429 +THIS-IS-LFS-two
430 +THIS-IS-LFS-two
430
431
431 1 a-single
432 1 a-single
432 diff --git a/a b/a
433 diff --git a/a b/a
433 --- a/a
434 --- a/a
434 +++ b/a
435 +++ b/a
435 @@ -1,1 +1,1 @@
436 @@ -1,1 +1,1 @@
436 -THIS-IS-LFS-0
437 -THIS-IS-LFS-0
437 +THIS-IS-LFS-single
438 +THIS-IS-LFS-single
438
439
439 0 a-0
440 0 a-0
440 diff --git a/a b/a
441 diff --git a/a b/a
441 new file mode 100644
442 new file mode 100644
442 --- /dev/null
443 --- /dev/null
443 +++ b/a
444 +++ b/a
444 @@ -0,0 +1,1 @@
445 @@ -0,0 +1,1 @@
445 +THIS-IS-LFS-0
446 +THIS-IS-LFS-0
446
447
447 $ cd ..
448 $ cd ..
448
449
449 # Test isbinary
450 # Test isbinary
450
451
451 $ hg init repo10
452 $ hg init repo10
452 $ cd repo10
453 $ cd repo10
453 $ cat >> .hg/hgrc << EOF
454 $ cat >> .hg/hgrc << EOF
454 > [extensions]
455 > [extensions]
455 > lfs=
456 > lfs=
456 > [lfs]
457 > [lfs]
457 > threshold=1
458 > track=all()
458 > EOF
459 > EOF
459 $ $PYTHON <<'EOF'
460 $ $PYTHON <<'EOF'
460 > def write(path, content):
461 > def write(path, content):
461 > with open(path, 'wb') as f:
462 > with open(path, 'wb') as f:
462 > f.write(content)
463 > f.write(content)
463 > write('a', b'\0\0')
464 > write('a', b'\0\0')
464 > write('b', b'\1\n')
465 > write('b', b'\1\n')
465 > write('c', b'\1\n\0')
466 > write('c', b'\1\n\0')
466 > write('d', b'xx')
467 > write('d', b'xx')
467 > EOF
468 > EOF
468 $ hg add a b c d
469 $ hg add a b c d
469 $ hg diff --stat
470 $ hg diff --stat
470 a | Bin
471 a | Bin
471 b | 1 +
472 b | 1 +
472 c | Bin
473 c | Bin
473 d | 1 +
474 d | 1 +
474 4 files changed, 2 insertions(+), 0 deletions(-)
475 4 files changed, 2 insertions(+), 0 deletions(-)
475 $ hg commit -m binarytest
476 $ hg commit -m binarytest
476 $ cat > $TESTTMP/dumpbinary.py << EOF
477 $ cat > $TESTTMP/dumpbinary.py << EOF
477 > def reposetup(ui, repo):
478 > def reposetup(ui, repo):
478 > for n in 'abcd':
479 > for n in 'abcd':
479 > ui.write(('%s: binary=%s\n') % (n, repo['.'][n].isbinary()))
480 > ui.write(('%s: binary=%s\n') % (n, repo['.'][n].isbinary()))
480 > EOF
481 > EOF
481 $ hg --config extensions.dumpbinary=$TESTTMP/dumpbinary.py id --trace
482 $ hg --config extensions.dumpbinary=$TESTTMP/dumpbinary.py id --trace
482 a: binary=True
483 a: binary=True
483 b: binary=False
484 b: binary=False
484 c: binary=True
485 c: binary=True
485 d: binary=False
486 d: binary=False
486 b55353847f02 tip
487 b55353847f02 tip
487
488
488 $ cd ..
489 $ cd ..
489
490
490 # Test fctx.cmp fastpath - diff without LFS blobs
491 # Test fctx.cmp fastpath - diff without LFS blobs
491
492
492 $ hg init repo12
493 $ hg init repo12
493 $ cd repo12
494 $ cd repo12
494 $ cat >> .hg/hgrc <<EOF
495 $ cat >> .hg/hgrc <<EOF
495 > [lfs]
496 > [lfs]
496 > threshold=1
497 > threshold=1
497 > EOF
498 > EOF
498 $ cat > ../patch.diff <<EOF
499 $ cat > ../patch.diff <<EOF
499 > # HG changeset patch
500 > # HG changeset patch
500 > 2
501 > 2
501 >
502 >
502 > diff --git a/a b/a
503 > diff --git a/a b/a
503 > old mode 100644
504 > old mode 100644
504 > new mode 100755
505 > new mode 100755
505 > EOF
506 > EOF
506
507
507 $ for i in 1 2 3; do
508 $ for i in 1 2 3; do
508 > cp ../repo10/a a
509 > cp ../repo10/a a
509 > if [ $i = 3 ]; then
510 > if [ $i = 3 ]; then
510 > # make a content-only change
511 > # make a content-only change
511 > hg import -q --bypass ../patch.diff
512 > hg import -q --bypass ../patch.diff
512 > hg update -q
513 > hg update -q
513 > rm ../patch.diff
514 > rm ../patch.diff
514 > else
515 > else
515 > echo $i >> a
516 > echo $i >> a
516 > hg commit -m $i -A a
517 > hg commit -m $i -A a
517 > fi
518 > fi
518 > done
519 > done
519 $ [ -d .hg/store/lfs/objects ]
520 $ [ -d .hg/store/lfs/objects ]
520
521
521 $ cd ..
522 $ cd ..
522
523
523 $ hg clone repo12 repo13 --noupdate
524 $ hg clone repo12 repo13 --noupdate
524 $ cd repo13
525 $ cd repo13
525 $ hg log --removed -p a -T '{desc}\n' --config diff.nobinary=1 --git
526 $ hg log --removed -p a -T '{desc}\n' --config diff.nobinary=1 --git
526 2
527 2
527 diff --git a/a b/a
528 diff --git a/a b/a
528 old mode 100644
529 old mode 100644
529 new mode 100755
530 new mode 100755
530
531
531 2
532 2
532 diff --git a/a b/a
533 diff --git a/a b/a
533 Binary file a has changed
534 Binary file a has changed
534
535
535 1
536 1
536 diff --git a/a b/a
537 diff --git a/a b/a
537 new file mode 100644
538 new file mode 100644
538 Binary file a has changed
539 Binary file a has changed
539
540
540 $ [ -d .hg/store/lfs/objects ]
541 $ [ -d .hg/store/lfs/objects ]
541 [1]
542 [1]
542
543
543 $ cd ..
544 $ cd ..
544
545
546 # Test filter
547
548 $ hg init repo11
549 $ cd repo11
550 $ cat >> .hg/hgrc << EOF
551 > [lfs]
552 > track=(**.a & size(">5B")) | (**.b & !size(">5B"))
553 > | (**.c & "path:d" & !"path:d/c.c") | size(">10B")
554 > EOF
555
556 $ mkdir a
557 $ echo aaaaaa > a/1.a
558 $ echo a > a/2.a
559 $ echo aaaaaa > 1.b
560 $ echo a > 2.b
561 $ echo a > 1.c
562 $ mkdir d
563 $ echo a > d/c.c
564 $ echo a > d/d.c
565 $ echo aaaaaaaaaaaa > x
566 $ hg add . -q
567 $ hg commit -m files
568
569 $ for p in a/1.a a/2.a 1.b 2.b 1.c d/c.c d/d.c x; do
570 > if hg debugdata $p 0 2>&1 | grep git-lfs >/dev/null; then
571 > echo "${p}: is lfs"
572 > else
573 > echo "${p}: not lfs"
574 > fi
575 > done
576 a/1.a: is lfs
577 a/2.a: not lfs
578 1.b: not lfs
579 2.b: is lfs
580 1.c: not lfs
581 d/c.c: not lfs
582 d/d.c: is lfs
583 x: is lfs
584
585 $ cd ..
586
545 # Verify the repos
587 # Verify the repos
546
588
547 $ cat > $TESTTMP/dumpflog.py << EOF
589 $ cat > $TESTTMP/dumpflog.py << EOF
548 > # print raw revision sizes, flags, and hashes for certain files
590 > # print raw revision sizes, flags, and hashes for certain files
549 > import hashlib
591 > import hashlib
550 > from mercurial import revlog
592 > from mercurial import revlog
551 > from mercurial.node import short
593 > from mercurial.node import short
552 > def hash(rawtext):
594 > def hash(rawtext):
553 > h = hashlib.sha512()
595 > h = hashlib.sha512()
554 > h.update(rawtext)
596 > h.update(rawtext)
555 > return h.hexdigest()[:4]
597 > return h.hexdigest()[:4]
556 > def reposetup(ui, repo):
598 > def reposetup(ui, repo):
557 > # these 2 files are interesting
599 > # these 2 files are interesting
558 > for name in ['l', 's']:
600 > for name in ['l', 's']:
559 > fl = repo.file(name)
601 > fl = repo.file(name)
560 > if len(fl) == 0:
602 > if len(fl) == 0:
561 > continue
603 > continue
562 > sizes = [revlog.revlog.rawsize(fl, i) for i in fl]
604 > sizes = [revlog.revlog.rawsize(fl, i) for i in fl]
563 > texts = [fl.revision(i, raw=True) for i in fl]
605 > texts = [fl.revision(i, raw=True) for i in fl]
564 > flags = [int(fl.flags(i)) for i in fl]
606 > flags = [int(fl.flags(i)) for i in fl]
565 > hashes = [hash(t) for t in texts]
607 > hashes = [hash(t) for t in texts]
566 > print(' %s: rawsizes=%r flags=%r hashes=%r'
608 > print(' %s: rawsizes=%r flags=%r hashes=%r'
567 > % (name, sizes, flags, hashes))
609 > % (name, sizes, flags, hashes))
568 > EOF
610 > EOF
569
611
570 $ for i in client client2 server repo3 repo4 repo5 repo6 repo7 repo8 repo9 \
612 $ for i in client client2 server repo3 repo4 repo5 repo6 repo7 repo8 repo9 \
571 > repo10; do
613 > repo10; do
572 > echo 'repo:' $i
614 > echo 'repo:' $i
573 > hg --cwd $i verify --config extensions.dumpflog=$TESTTMP/dumpflog.py -q
615 > hg --cwd $i verify --config extensions.dumpflog=$TESTTMP/dumpflog.py -q
574 > done
616 > done
575 repo: client
617 repo: client
576 repo: client2
618 repo: client2
577 repo: server
619 repo: server
578 repo: repo3
620 repo: repo3
579 l: rawsizes=[211, 6, 8, 141] flags=[8192, 0, 0, 8192] hashes=['d2b8', '948c', 'cc88', '724d']
621 l: rawsizes=[211, 6, 8, 141] flags=[8192, 0, 0, 8192] hashes=['d2b8', '948c', 'cc88', '724d']
580 s: rawsizes=[74, 141, 141, 8] flags=[0, 8192, 8192, 0] hashes=['3c80', 'fce0', '874a', '826b']
622 s: rawsizes=[74, 141, 141, 8] flags=[0, 8192, 8192, 0] hashes=['3c80', 'fce0', '874a', '826b']
581 repo: repo4
623 repo: repo4
582 l: rawsizes=[211, 6, 8, 141] flags=[8192, 0, 0, 8192] hashes=['d2b8', '948c', 'cc88', '724d']
624 l: rawsizes=[211, 6, 8, 141] flags=[8192, 0, 0, 8192] hashes=['d2b8', '948c', 'cc88', '724d']
583 s: rawsizes=[74, 141, 141, 8] flags=[0, 8192, 8192, 0] hashes=['3c80', 'fce0', '874a', '826b']
625 s: rawsizes=[74, 141, 141, 8] flags=[0, 8192, 8192, 0] hashes=['3c80', 'fce0', '874a', '826b']
584 repo: repo5
626 repo: repo5
585 l: rawsizes=[211, 6, 8, 141] flags=[8192, 0, 0, 8192] hashes=['d2b8', '948c', 'cc88', '724d']
627 l: rawsizes=[211, 6, 8, 141] flags=[8192, 0, 0, 8192] hashes=['d2b8', '948c', 'cc88', '724d']
586 s: rawsizes=[74, 141, 141, 8] flags=[0, 8192, 8192, 0] hashes=['3c80', 'fce0', '874a', '826b']
628 s: rawsizes=[74, 141, 141, 8] flags=[0, 8192, 8192, 0] hashes=['3c80', 'fce0', '874a', '826b']
587 repo: repo6
629 repo: repo6
588 repo: repo7
630 repo: repo7
589 repo: repo8
631 repo: repo8
590 repo: repo9
632 repo: repo9
591 repo: repo10
633 repo: repo10
592
634
593 repo13 doesn't have any cached lfs files and its source never pushed its
635 repo13 doesn't have any cached lfs files and its source never pushed its
594 files. Therefore, the files don't exist in the remote store. Use the files in
636 files. Therefore, the files don't exist in the remote store. Use the files in
595 the user cache.
637 the user cache.
596
638
597 $ test -d $TESTTMP/repo13/.hg/store/lfs/objects
639 $ test -d $TESTTMP/repo13/.hg/store/lfs/objects
598 [1]
640 [1]
599
641
600 $ hg --config extensions.share= share repo13 repo14
642 $ hg --config extensions.share= share repo13 repo14
601 updating working directory
643 updating working directory
602 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
644 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
603 $ hg -R repo14 -q verify
645 $ hg -R repo14 -q verify
604
646
605 $ hg clone repo13 repo15
647 $ hg clone repo13 repo15
606 updating to branch default
648 updating to branch default
607 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
649 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
608 $ hg -R repo15 -q verify
650 $ hg -R repo15 -q verify
609
651
610 If the source repo doesn't have the blob (maybe it was pulled or cloned with
652 If the source repo doesn't have the blob (maybe it was pulled or cloned with
611 --noupdate), the blob is still accessible via the global cache to send to the
653 --noupdate), the blob is still accessible via the global cache to send to the
612 remote store.
654 remote store.
613
655
614 $ rm -rf $TESTTMP/repo15/.hg/store/lfs
656 $ rm -rf $TESTTMP/repo15/.hg/store/lfs
615 $ hg init repo16
657 $ hg init repo16
616 $ hg -R repo15 push repo16
658 $ hg -R repo15 push repo16
617 pushing to repo16
659 pushing to repo16
618 searching for changes
660 searching for changes
619 adding changesets
661 adding changesets
620 adding manifests
662 adding manifests
621 adding file changes
663 adding file changes
622 added 3 changesets with 2 changes to 1 files
664 added 3 changesets with 2 changes to 1 files
623 $ hg -R repo15 -q verify
665 $ hg -R repo15 -q verify
624
666
625 Test damaged file scenarios. (This also damages the usercache because of the
667 Test damaged file scenarios. (This also damages the usercache because of the
626 hardlinks.)
668 hardlinks.)
627
669
628 $ echo 'damage' >> repo5/.hg/store/lfs/objects/66/100b384bf761271b407d79fc30cdd0554f3b2c5d944836e936d584b88ce88e
670 $ echo 'damage' >> repo5/.hg/store/lfs/objects/66/100b384bf761271b407d79fc30cdd0554f3b2c5d944836e936d584b88ce88e
629
671
630 Repo with damaged lfs objects in any revision will fail verification.
672 Repo with damaged lfs objects in any revision will fail verification.
631
673
632 $ hg -R repo5 verify
674 $ hg -R repo5 verify
633 checking changesets
675 checking changesets
634 checking manifests
676 checking manifests
635 crosschecking files in changesets and manifests
677 crosschecking files in changesets and manifests
636 checking files
678 checking files
637 l@1: unpacking 46a2f24864bc: integrity check failed on data/l.i:0
679 l@1: unpacking 46a2f24864bc: integrity check failed on data/l.i:0
638 large@0: unpacking 2c531e0992ff: integrity check failed on data/large.i:0
680 large@0: unpacking 2c531e0992ff: integrity check failed on data/large.i:0
639 4 files, 5 changesets, 10 total revisions
681 4 files, 5 changesets, 10 total revisions
640 2 integrity errors encountered!
682 2 integrity errors encountered!
641 (first damaged changeset appears to be 0)
683 (first damaged changeset appears to be 0)
642 [1]
684 [1]
643
685
644 Updates work after cloning a damaged repo, if the damaged lfs objects aren't in
686 Updates work after cloning a damaged repo, if the damaged lfs objects aren't in
645 the update destination. Those objects won't be added to the new repo's store
687 the update destination. Those objects won't be added to the new repo's store
646 because they aren't accessed.
688 because they aren't accessed.
647
689
648 $ hg clone -v repo5 fromcorrupt
690 $ hg clone -v repo5 fromcorrupt
649 updating to branch default
691 updating to branch default
650 resolving manifests
692 resolving manifests
651 getting l
693 getting l
652 lfs: found 22f66a3fc0b9bf3f012c814303995ec07099b3a9ce02a7af84b5970811074a3b in the usercache
694 lfs: found 22f66a3fc0b9bf3f012c814303995ec07099b3a9ce02a7af84b5970811074a3b in the usercache
653 getting s
695 getting s
654 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
696 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
655 $ test -f fromcorrupt/.hg/store/lfs/objects/66/100b384bf761271b407d79fc30cdd0554f3b2c5d944836e936d584b88ce88e
697 $ test -f fromcorrupt/.hg/store/lfs/objects/66/100b384bf761271b407d79fc30cdd0554f3b2c5d944836e936d584b88ce88e
656 [1]
698 [1]
657
699
658 Verify will copy/link all lfs objects into the local store that aren't already
700 Verify will copy/link all lfs objects into the local store that aren't already
659 present. Bypass the corrupted usercache to show that verify works when fed by
701 present. Bypass the corrupted usercache to show that verify works when fed by
660 the (uncorrupted) remote store.
702 the (uncorrupted) remote store.
661
703
662 $ hg -R fromcorrupt --config lfs.usercache=emptycache verify -v
704 $ hg -R fromcorrupt --config lfs.usercache=emptycache verify -v
663 repository uses revlog format 1
705 repository uses revlog format 1
664 checking changesets
706 checking changesets
665 checking manifests
707 checking manifests
666 crosschecking files in changesets and manifests
708 crosschecking files in changesets and manifests
667 checking files
709 checking files
668 lfs: adding 66100b384bf761271b407d79fc30cdd0554f3b2c5d944836e936d584b88ce88e to the usercache
710 lfs: adding 66100b384bf761271b407d79fc30cdd0554f3b2c5d944836e936d584b88ce88e to the usercache
669 lfs: found 66100b384bf761271b407d79fc30cdd0554f3b2c5d944836e936d584b88ce88e in the local lfs store
711 lfs: found 66100b384bf761271b407d79fc30cdd0554f3b2c5d944836e936d584b88ce88e in the local lfs store
670 lfs: found 22f66a3fc0b9bf3f012c814303995ec07099b3a9ce02a7af84b5970811074a3b in the local lfs store
712 lfs: found 22f66a3fc0b9bf3f012c814303995ec07099b3a9ce02a7af84b5970811074a3b in the local lfs store
671 lfs: found 66100b384bf761271b407d79fc30cdd0554f3b2c5d944836e936d584b88ce88e in the local lfs store
713 lfs: found 66100b384bf761271b407d79fc30cdd0554f3b2c5d944836e936d584b88ce88e in the local lfs store
672 lfs: adding 89b6070915a3d573ff3599d1cda305bc5e38549b15c4847ab034169da66e1ca8 to the usercache
714 lfs: adding 89b6070915a3d573ff3599d1cda305bc5e38549b15c4847ab034169da66e1ca8 to the usercache
673 lfs: found 89b6070915a3d573ff3599d1cda305bc5e38549b15c4847ab034169da66e1ca8 in the local lfs store
715 lfs: found 89b6070915a3d573ff3599d1cda305bc5e38549b15c4847ab034169da66e1ca8 in the local lfs store
674 lfs: adding b1a6ea88da0017a0e77db139a54618986e9a2489bee24af9fe596de9daac498c to the usercache
716 lfs: adding b1a6ea88da0017a0e77db139a54618986e9a2489bee24af9fe596de9daac498c to the usercache
675 lfs: found b1a6ea88da0017a0e77db139a54618986e9a2489bee24af9fe596de9daac498c in the local lfs store
717 lfs: found b1a6ea88da0017a0e77db139a54618986e9a2489bee24af9fe596de9daac498c in the local lfs store
676 4 files, 5 changesets, 10 total revisions
718 4 files, 5 changesets, 10 total revisions
677
719
678 Verify will not copy/link a corrupted file from the usercache into the local
720 Verify will not copy/link a corrupted file from the usercache into the local
679 store, and poison it. (The verify with a good remote now works.)
721 store, and poison it. (The verify with a good remote now works.)
680
722
681 $ rm -r fromcorrupt/.hg/store/lfs/objects/66/100b384bf761271b407d79fc30cdd0554f3b2c5d944836e936d584b88ce88e
723 $ rm -r fromcorrupt/.hg/store/lfs/objects/66/100b384bf761271b407d79fc30cdd0554f3b2c5d944836e936d584b88ce88e
682 $ hg -R fromcorrupt verify -v
724 $ hg -R fromcorrupt verify -v
683 repository uses revlog format 1
725 repository uses revlog format 1
684 checking changesets
726 checking changesets
685 checking manifests
727 checking manifests
686 crosschecking files in changesets and manifests
728 crosschecking files in changesets and manifests
687 checking files
729 checking files
688 l@1: unpacking 46a2f24864bc: integrity check failed on data/l.i:0
730 l@1: unpacking 46a2f24864bc: integrity check failed on data/l.i:0
689 lfs: found 22f66a3fc0b9bf3f012c814303995ec07099b3a9ce02a7af84b5970811074a3b in the local lfs store
731 lfs: found 22f66a3fc0b9bf3f012c814303995ec07099b3a9ce02a7af84b5970811074a3b in the local lfs store
690 large@0: unpacking 2c531e0992ff: integrity check failed on data/large.i:0
732 large@0: unpacking 2c531e0992ff: integrity check failed on data/large.i:0
691 lfs: found 89b6070915a3d573ff3599d1cda305bc5e38549b15c4847ab034169da66e1ca8 in the local lfs store
733 lfs: found 89b6070915a3d573ff3599d1cda305bc5e38549b15c4847ab034169da66e1ca8 in the local lfs store
692 lfs: found b1a6ea88da0017a0e77db139a54618986e9a2489bee24af9fe596de9daac498c in the local lfs store
734 lfs: found b1a6ea88da0017a0e77db139a54618986e9a2489bee24af9fe596de9daac498c in the local lfs store
693 4 files, 5 changesets, 10 total revisions
735 4 files, 5 changesets, 10 total revisions
694 2 integrity errors encountered!
736 2 integrity errors encountered!
695 (first damaged changeset appears to be 0)
737 (first damaged changeset appears to be 0)
696 [1]
738 [1]
697 $ hg -R fromcorrupt --config lfs.usercache=emptycache verify -v
739 $ hg -R fromcorrupt --config lfs.usercache=emptycache verify -v
698 repository uses revlog format 1
740 repository uses revlog format 1
699 checking changesets
741 checking changesets
700 checking manifests
742 checking manifests
701 crosschecking files in changesets and manifests
743 crosschecking files in changesets and manifests
702 checking files
744 checking files
703 lfs: found 66100b384bf761271b407d79fc30cdd0554f3b2c5d944836e936d584b88ce88e in the usercache
745 lfs: found 66100b384bf761271b407d79fc30cdd0554f3b2c5d944836e936d584b88ce88e in the usercache
704 lfs: found 22f66a3fc0b9bf3f012c814303995ec07099b3a9ce02a7af84b5970811074a3b in the local lfs store
746 lfs: found 22f66a3fc0b9bf3f012c814303995ec07099b3a9ce02a7af84b5970811074a3b in the local lfs store
705 lfs: found 66100b384bf761271b407d79fc30cdd0554f3b2c5d944836e936d584b88ce88e in the local lfs store
747 lfs: found 66100b384bf761271b407d79fc30cdd0554f3b2c5d944836e936d584b88ce88e in the local lfs store
706 lfs: found 89b6070915a3d573ff3599d1cda305bc5e38549b15c4847ab034169da66e1ca8 in the local lfs store
748 lfs: found 89b6070915a3d573ff3599d1cda305bc5e38549b15c4847ab034169da66e1ca8 in the local lfs store
707 lfs: found b1a6ea88da0017a0e77db139a54618986e9a2489bee24af9fe596de9daac498c in the local lfs store
749 lfs: found b1a6ea88da0017a0e77db139a54618986e9a2489bee24af9fe596de9daac498c in the local lfs store
708 4 files, 5 changesets, 10 total revisions
750 4 files, 5 changesets, 10 total revisions
709
751
710 Damaging a file required by the update destination fails the update.
752 Damaging a file required by the update destination fails the update.
711
753
712 $ echo 'damage' >> $TESTTMP/dummy-remote/22/f66a3fc0b9bf3f012c814303995ec07099b3a9ce02a7af84b5970811074a3b
754 $ echo 'damage' >> $TESTTMP/dummy-remote/22/f66a3fc0b9bf3f012c814303995ec07099b3a9ce02a7af84b5970811074a3b
713 $ hg --config lfs.usercache=emptycache clone -v repo5 fromcorrupt2
755 $ hg --config lfs.usercache=emptycache clone -v repo5 fromcorrupt2
714 updating to branch default
756 updating to branch default
715 resolving manifests
757 resolving manifests
716 getting l
758 getting l
717 abort: corrupt remote lfs object: 22f66a3fc0b9bf3f012c814303995ec07099b3a9ce02a7af84b5970811074a3b
759 abort: corrupt remote lfs object: 22f66a3fc0b9bf3f012c814303995ec07099b3a9ce02a7af84b5970811074a3b
718 [255]
760 [255]
719
761
720 A corrupted lfs blob is not transferred from a file://remotestore to the
762 A corrupted lfs blob is not transferred from a file://remotestore to the
721 usercache or local store.
763 usercache or local store.
722
764
723 $ test -f emptycache/22/f66a3fc0b9bf3f012c814303995ec07099b3a9ce02a7af84b5970811074a3b
765 $ test -f emptycache/22/f66a3fc0b9bf3f012c814303995ec07099b3a9ce02a7af84b5970811074a3b
724 [1]
766 [1]
725 $ test -f fromcorrupt2/.hg/store/lfs/objects/22/f66a3fc0b9bf3f012c814303995ec07099b3a9ce02a7af84b5970811074a3b
767 $ test -f fromcorrupt2/.hg/store/lfs/objects/22/f66a3fc0b9bf3f012c814303995ec07099b3a9ce02a7af84b5970811074a3b
726 [1]
768 [1]
727
769
728 $ hg -R fromcorrupt2 verify
770 $ hg -R fromcorrupt2 verify
729 checking changesets
771 checking changesets
730 checking manifests
772 checking manifests
731 crosschecking files in changesets and manifests
773 crosschecking files in changesets and manifests
732 checking files
774 checking files
733 l@1: unpacking 46a2f24864bc: integrity check failed on data/l.i:0
775 l@1: unpacking 46a2f24864bc: integrity check failed on data/l.i:0
734 large@0: unpacking 2c531e0992ff: integrity check failed on data/large.i:0
776 large@0: unpacking 2c531e0992ff: integrity check failed on data/large.i:0
735 4 files, 5 changesets, 10 total revisions
777 4 files, 5 changesets, 10 total revisions
736 2 integrity errors encountered!
778 2 integrity errors encountered!
737 (first damaged changeset appears to be 0)
779 (first damaged changeset appears to be 0)
738 [1]
780 [1]
739
781
740 Corrupt local files are not sent upstream. (The alternate dummy remote
782 Corrupt local files are not sent upstream. (The alternate dummy remote
741 avoids the corrupt lfs object in the original remote.)
783 avoids the corrupt lfs object in the original remote.)
742
784
743 $ mkdir $TESTTMP/dummy-remote2
785 $ mkdir $TESTTMP/dummy-remote2
744 $ hg init dest
786 $ hg init dest
745 $ hg -R fromcorrupt2 --config lfs.url=file:///$TESTTMP/dummy-remote2 push -v dest
787 $ hg -R fromcorrupt2 --config lfs.url=file:///$TESTTMP/dummy-remote2 push -v dest
746 pushing to dest
788 pushing to dest
747 searching for changes
789 searching for changes
748 lfs: found 22f66a3fc0b9bf3f012c814303995ec07099b3a9ce02a7af84b5970811074a3b in the local lfs store
790 lfs: found 22f66a3fc0b9bf3f012c814303995ec07099b3a9ce02a7af84b5970811074a3b in the local lfs store
749 lfs: found 89b6070915a3d573ff3599d1cda305bc5e38549b15c4847ab034169da66e1ca8 in the local lfs store
791 lfs: found 89b6070915a3d573ff3599d1cda305bc5e38549b15c4847ab034169da66e1ca8 in the local lfs store
750 lfs: found b1a6ea88da0017a0e77db139a54618986e9a2489bee24af9fe596de9daac498c in the local lfs store
792 lfs: found b1a6ea88da0017a0e77db139a54618986e9a2489bee24af9fe596de9daac498c in the local lfs store
751 abort: detected corrupt lfs object: 66100b384bf761271b407d79fc30cdd0554f3b2c5d944836e936d584b88ce88e
793 abort: detected corrupt lfs object: 66100b384bf761271b407d79fc30cdd0554f3b2c5d944836e936d584b88ce88e
752 (run hg verify)
794 (run hg verify)
753 [255]
795 [255]
754
796
755 $ hg -R fromcorrupt2 --config lfs.url=file:///$TESTTMP/dummy-remote2 verify -v
797 $ hg -R fromcorrupt2 --config lfs.url=file:///$TESTTMP/dummy-remote2 verify -v
756 repository uses revlog format 1
798 repository uses revlog format 1
757 checking changesets
799 checking changesets
758 checking manifests
800 checking manifests
759 crosschecking files in changesets and manifests
801 crosschecking files in changesets and manifests
760 checking files
802 checking files
761 l@1: unpacking 46a2f24864bc: integrity check failed on data/l.i:0
803 l@1: unpacking 46a2f24864bc: integrity check failed on data/l.i:0
762 lfs: found 22f66a3fc0b9bf3f012c814303995ec07099b3a9ce02a7af84b5970811074a3b in the local lfs store
804 lfs: found 22f66a3fc0b9bf3f012c814303995ec07099b3a9ce02a7af84b5970811074a3b in the local lfs store
763 large@0: unpacking 2c531e0992ff: integrity check failed on data/large.i:0
805 large@0: unpacking 2c531e0992ff: integrity check failed on data/large.i:0
764 lfs: found 89b6070915a3d573ff3599d1cda305bc5e38549b15c4847ab034169da66e1ca8 in the local lfs store
806 lfs: found 89b6070915a3d573ff3599d1cda305bc5e38549b15c4847ab034169da66e1ca8 in the local lfs store
765 lfs: found b1a6ea88da0017a0e77db139a54618986e9a2489bee24af9fe596de9daac498c in the local lfs store
807 lfs: found b1a6ea88da0017a0e77db139a54618986e9a2489bee24af9fe596de9daac498c in the local lfs store
766 4 files, 5 changesets, 10 total revisions
808 4 files, 5 changesets, 10 total revisions
767 2 integrity errors encountered!
809 2 integrity errors encountered!
768 (first damaged changeset appears to be 0)
810 (first damaged changeset appears to be 0)
769 [1]
811 [1]
770
812
771 $ cat $TESTTMP/dummy-remote2/22/f66a3fc0b9bf3f012c814303995ec07099b3a9ce02a7af84b5970811074a3b | $TESTDIR/f --sha256
813 $ cat $TESTTMP/dummy-remote2/22/f66a3fc0b9bf3f012c814303995ec07099b3a9ce02a7af84b5970811074a3b | $TESTDIR/f --sha256
772 sha256=22f66a3fc0b9bf3f012c814303995ec07099b3a9ce02a7af84b5970811074a3b
814 sha256=22f66a3fc0b9bf3f012c814303995ec07099b3a9ce02a7af84b5970811074a3b
773 $ cat fromcorrupt2/.hg/store/lfs/objects/22/f66a3fc0b9bf3f012c814303995ec07099b3a9ce02a7af84b5970811074a3b | $TESTDIR/f --sha256
815 $ cat fromcorrupt2/.hg/store/lfs/objects/22/f66a3fc0b9bf3f012c814303995ec07099b3a9ce02a7af84b5970811074a3b | $TESTDIR/f --sha256
774 sha256=22f66a3fc0b9bf3f012c814303995ec07099b3a9ce02a7af84b5970811074a3b
816 sha256=22f66a3fc0b9bf3f012c814303995ec07099b3a9ce02a7af84b5970811074a3b
775 $ test -f $TESTTMP/dummy-remote2/66/100b384bf761271b407d79fc30cdd0554f3b2c5d944836e936d584b88ce88e
817 $ test -f $TESTTMP/dummy-remote2/66/100b384bf761271b407d79fc30cdd0554f3b2c5d944836e936d584b88ce88e
776 [1]
818 [1]
777
819
778 Accessing a corrupt file will complain
820 Accessing a corrupt file will complain
779
821
780 $ hg --cwd fromcorrupt2 cat -r 0 large
822 $ hg --cwd fromcorrupt2 cat -r 0 large
781 abort: integrity check failed on data/large.i:0!
823 abort: integrity check failed on data/large.i:0!
782 [255]
824 [255]
783
825
784 lfs -> normal -> lfs round trip conversions are possible. The threshold for the
826 lfs -> normal -> lfs round trip conversions are possible. The threshold for the
785 lfs destination is specified here because it was originally listed in the local
827 lfs destination is specified here because it was originally listed in the local
786 .hgrc, and the global one is too high to trigger lfs usage. For lfs -> normal,
828 .hgrc, and the global one is too high to trigger lfs usage. For lfs -> normal,
787 there's no 'lfs' destination repo requirement. For normal -> lfs, there is.
829 there's no 'lfs' destination repo requirement. For normal -> lfs, there is.
788
830
789 XXX: There's not a great way to ensure that the conversion to normal files
831 XXX: There's not a great way to ensure that the conversion to normal files
790 actually converts _everything_ to normal. The extension needs to be loaded for
832 actually converts _everything_ to normal. The extension needs to be loaded for
791 the source, but there's no way to disable it for the destination. The best that
833 the source, but there's no way to disable it for the destination. The best that
792 can be done is to raise the threshold so that lfs isn't used on the destination.
834 can be done is to raise the threshold so that lfs isn't used on the destination.
793 It doesn't like using '!' to unset the value on the command line.
835 It doesn't like using '!' to unset the value on the command line.
794
836
795 $ hg --config extensions.convert= --config lfs.threshold=1000M \
837 $ hg --config extensions.convert= --config lfs.threshold=1000M \
796 > convert repo8 convert_normal
838 > convert repo8 convert_normal
797 initializing destination convert_normal repository
839 initializing destination convert_normal repository
798 scanning source...
840 scanning source...
799 sorting...
841 sorting...
800 converting...
842 converting...
801 2 a
843 2 a
802 1 b
844 1 b
803 0 meta
845 0 meta
804 $ grep 'lfs' convert_normal/.hg/requires
846 $ grep 'lfs' convert_normal/.hg/requires
805 [1]
847 [1]
806 $ hg --cwd convert_normal debugdata a1 0
848 $ hg --cwd convert_normal debugdata a1 0
807 THIS-IS-LFS-BECAUSE-10-BYTES
849 THIS-IS-LFS-BECAUSE-10-BYTES
808
850
809 $ hg --config extensions.convert= --config lfs.threshold=10B \
851 $ hg --config extensions.convert= --config lfs.threshold=10B \
810 > convert convert_normal convert_lfs
852 > convert convert_normal convert_lfs
811 initializing destination convert_lfs repository
853 initializing destination convert_lfs repository
812 scanning source...
854 scanning source...
813 sorting...
855 sorting...
814 converting...
856 converting...
815 2 a
857 2 a
816 1 b
858 1 b
817 0 meta
859 0 meta
818 $ hg --cwd convert_lfs debugdata a1 0
860 $ hg --cwd convert_lfs debugdata a1 0
819 version https://git-lfs.github.com/spec/v1
861 version https://git-lfs.github.com/spec/v1
820 oid sha256:5bb8341bee63b3649f222b2215bde37322bea075a30575aa685d8f8d21c77024
862 oid sha256:5bb8341bee63b3649f222b2215bde37322bea075a30575aa685d8f8d21c77024
821 size 29
863 size 29
822 x-is-binary 0
864 x-is-binary 0
823 $ grep 'lfs' convert_lfs/.hg/requires
865 $ grep 'lfs' convert_lfs/.hg/requires
824 lfs
866 lfs
825
867
826 This convert is trickier, because it contains deleted files (via `hg mv`)
868 This convert is trickier, because it contains deleted files (via `hg mv`)
827
869
828 $ hg --config extensions.convert= --config lfs.threshold=1000M \
870 $ hg --config extensions.convert= --config lfs.threshold=1000M \
829 > convert repo3 convert_normal2
871 > convert repo3 convert_normal2
830 initializing destination convert_normal2 repository
872 initializing destination convert_normal2 repository
831 scanning source...
873 scanning source...
832 sorting...
874 sorting...
833 converting...
875 converting...
834 4 commit with lfs content
876 4 commit with lfs content
835 3 renames
877 3 renames
836 2 large to small, small to large
878 2 large to small, small to large
837 1 random modifications
879 1 random modifications
838 0 switch large and small again
880 0 switch large and small again
839 $ grep 'lfs' convert_normal2/.hg/requires
881 $ grep 'lfs' convert_normal2/.hg/requires
840 [1]
882 [1]
841 $ hg --cwd convert_normal2 debugdata large 0
883 $ hg --cwd convert_normal2 debugdata large 0
842 LONGER-THAN-TEN-BYTES-WILL-TRIGGER-LFS
884 LONGER-THAN-TEN-BYTES-WILL-TRIGGER-LFS
843
885
844 $ hg --config extensions.convert= --config lfs.threshold=10B \
886 $ hg --config extensions.convert= --config lfs.threshold=10B \
845 > convert convert_normal2 convert_lfs2
887 > convert convert_normal2 convert_lfs2
846 initializing destination convert_lfs2 repository
888 initializing destination convert_lfs2 repository
847 scanning source...
889 scanning source...
848 sorting...
890 sorting...
849 converting...
891 converting...
850 4 commit with lfs content
892 4 commit with lfs content
851 3 renames
893 3 renames
852 2 large to small, small to large
894 2 large to small, small to large
853 1 random modifications
895 1 random modifications
854 0 switch large and small again
896 0 switch large and small again
855 $ grep 'lfs' convert_lfs2/.hg/requires
897 $ grep 'lfs' convert_lfs2/.hg/requires
856 lfs
898 lfs
857 $ hg --cwd convert_lfs2 debugdata large 0
899 $ hg --cwd convert_lfs2 debugdata large 0
858 version https://git-lfs.github.com/spec/v1
900 version https://git-lfs.github.com/spec/v1
859 oid sha256:66100b384bf761271b407d79fc30cdd0554f3b2c5d944836e936d584b88ce88e
901 oid sha256:66100b384bf761271b407d79fc30cdd0554f3b2c5d944836e936d584b88ce88e
860 size 39
902 size 39
861 x-is-binary 0
903 x-is-binary 0
862
904
863 $ hg -R convert_lfs2 config --debug extensions | grep lfs
905 $ hg -R convert_lfs2 config --debug extensions | grep lfs
864 $TESTTMP/convert_lfs2/.hg/hgrc:*: extensions.lfs= (glob)
906 $TESTTMP/convert_lfs2/.hg/hgrc:*: extensions.lfs= (glob)
865
907
866 Committing deleted files works:
908 Committing deleted files works:
867
909
868 $ hg init $TESTTMP/repo-del
910 $ hg init $TESTTMP/repo-del
869 $ cd $TESTTMP/repo-del
911 $ cd $TESTTMP/repo-del
870 $ echo 1 > A
912 $ echo 1 > A
871 $ hg commit -m 'add A' -A A
913 $ hg commit -m 'add A' -A A
872 $ hg rm A
914 $ hg rm A
873 $ hg commit -m 'rm A'
915 $ hg commit -m 'rm A'
874 $ cd ..
916 $ cd ..
875
917
876 Unbundling adds a requirement to a non-lfs repo, if necessary.
918 Unbundling adds a requirement to a non-lfs repo, if necessary.
877
919
878 $ hg bundle -R $TESTTMP/repo-del -qr 0 --base null nolfs.hg
920 $ hg bundle -R $TESTTMP/repo-del -qr 0 --base null nolfs.hg
879 $ hg bundle -R convert_lfs2 -qr tip --base null lfs.hg
921 $ hg bundle -R convert_lfs2 -qr tip --base null lfs.hg
880 $ hg init unbundle
922 $ hg init unbundle
881 $ hg pull -R unbundle -q nolfs.hg
923 $ hg pull -R unbundle -q nolfs.hg
882 $ grep lfs unbundle/.hg/requires
924 $ grep lfs unbundle/.hg/requires
883 [1]
925 [1]
884 $ hg pull -R unbundle -q lfs.hg
926 $ hg pull -R unbundle -q lfs.hg
885 $ grep lfs unbundle/.hg/requires
927 $ grep lfs unbundle/.hg/requires
886 lfs
928 lfs
887
929
888 $ hg init no_lfs
930 $ hg init no_lfs
889 $ cat >> no_lfs/.hg/hgrc <<EOF
931 $ cat >> no_lfs/.hg/hgrc <<EOF
890 > [experimental]
932 > [experimental]
891 > changegroup3 = True
933 > changegroup3 = True
892 > [extensions]
934 > [extensions]
893 > lfs=!
935 > lfs=!
894 > EOF
936 > EOF
895 $ cp -R no_lfs no_lfs2
937 $ cp -R no_lfs no_lfs2
896
938
897 Pushing from a local lfs repo to a local repo without an lfs requirement and
939 Pushing from a local lfs repo to a local repo without an lfs requirement and
898 with lfs disabled, fails.
940 with lfs disabled, fails.
899
941
900 $ hg push -R convert_lfs2 no_lfs
942 $ hg push -R convert_lfs2 no_lfs
901 pushing to no_lfs
943 pushing to no_lfs
902 abort: required features are not supported in the destination: lfs
944 abort: required features are not supported in the destination: lfs
903 [255]
945 [255]
904 $ grep lfs no_lfs/.hg/requires
946 $ grep lfs no_lfs/.hg/requires
905 [1]
947 [1]
906
948
907 Pulling from a local lfs repo to a local repo without an lfs requirement and
949 Pulling from a local lfs repo to a local repo without an lfs requirement and
908 with lfs disabled, fails.
950 with lfs disabled, fails.
909
951
910 $ hg pull -R no_lfs2 convert_lfs2
952 $ hg pull -R no_lfs2 convert_lfs2
911 pulling from convert_lfs2
953 pulling from convert_lfs2
912 abort: required features are not supported in the destination: lfs
954 abort: required features are not supported in the destination: lfs
913 [255]
955 [255]
914 $ grep lfs no_lfs2/.hg/requires
956 $ grep lfs no_lfs2/.hg/requires
915 [1]
957 [1]
General Comments 0
You need to be logged in to leave comments. Login now