##// END OF EJS Templates
lfs: don't automatically exclude '.hg*' files from external tracking...
Matt Harbison -
r35817:b91bca85 stable
parent child Browse files
Show More
@@ -1,350 +1,349 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 textlen = len(text)
126 textlen = len(text)
127 # exclude hg rename meta from file size
127 # exclude hg rename meta from file size
128 meta, offset = filelog.parsemeta(text)
128 meta, offset = filelog.parsemeta(text)
129 if offset:
129 if offset:
130 textlen -= offset
130 textlen -= offset
131
131
132 lfstrack = self.opener.options['lfstrack']
132 lfstrack = self.opener.options['lfstrack']
133
133
134 # Always exclude hg owned files
134 if lfstrack(self.filename, textlen):
135 if not self.filename.startswith('.hg') and lfstrack(self.filename, textlen):
136 flags |= revlog.REVIDX_EXTSTORED
135 flags |= revlog.REVIDX_EXTSTORED
137
136
138 return orig(self, text, transaction, link, p1, p2, cachedelta=cachedelta,
137 return orig(self, text, transaction, link, p1, p2, cachedelta=cachedelta,
139 node=node, flags=flags, **kwds)
138 node=node, flags=flags, **kwds)
140
139
141 def filelogrenamed(orig, self, node):
140 def filelogrenamed(orig, self, node):
142 if _islfs(self, node):
141 if _islfs(self, node):
143 rawtext = self.revision(node, raw=True)
142 rawtext = self.revision(node, raw=True)
144 if not rawtext:
143 if not rawtext:
145 return False
144 return False
146 metadata = pointer.deserialize(rawtext)
145 metadata = pointer.deserialize(rawtext)
147 if 'x-hg-copy' in metadata and 'x-hg-copyrev' in metadata:
146 if 'x-hg-copy' in metadata and 'x-hg-copyrev' in metadata:
148 return metadata['x-hg-copy'], bin(metadata['x-hg-copyrev'])
147 return metadata['x-hg-copy'], bin(metadata['x-hg-copyrev'])
149 else:
148 else:
150 return False
149 return False
151 return orig(self, node)
150 return orig(self, node)
152
151
153 def filelogsize(orig, self, rev):
152 def filelogsize(orig, self, rev):
154 if _islfs(self, rev=rev):
153 if _islfs(self, rev=rev):
155 # fast path: use lfs metadata to answer size
154 # fast path: use lfs metadata to answer size
156 rawtext = self.revision(rev, raw=True)
155 rawtext = self.revision(rev, raw=True)
157 metadata = pointer.deserialize(rawtext)
156 metadata = pointer.deserialize(rawtext)
158 return int(metadata['size'])
157 return int(metadata['size'])
159 return orig(self, rev)
158 return orig(self, rev)
160
159
161 def filectxcmp(orig, self, fctx):
160 def filectxcmp(orig, self, fctx):
162 """returns True if text is different than fctx"""
161 """returns True if text is different than fctx"""
163 # some fctx (ex. hg-git) is not based on basefilectx and do not have islfs
162 # some fctx (ex. hg-git) is not based on basefilectx and do not have islfs
164 if self.islfs() and getattr(fctx, 'islfs', lambda: False)():
163 if self.islfs() and getattr(fctx, 'islfs', lambda: False)():
165 # fast path: check LFS oid
164 # fast path: check LFS oid
166 p1 = pointer.deserialize(self.rawdata())
165 p1 = pointer.deserialize(self.rawdata())
167 p2 = pointer.deserialize(fctx.rawdata())
166 p2 = pointer.deserialize(fctx.rawdata())
168 return p1.oid() != p2.oid()
167 return p1.oid() != p2.oid()
169 return orig(self, fctx)
168 return orig(self, fctx)
170
169
171 def filectxisbinary(orig, self):
170 def filectxisbinary(orig, self):
172 if self.islfs():
171 if self.islfs():
173 # fast path: use lfs metadata to answer isbinary
172 # fast path: use lfs metadata to answer isbinary
174 metadata = pointer.deserialize(self.rawdata())
173 metadata = pointer.deserialize(self.rawdata())
175 # if lfs metadata says nothing, assume it's binary by default
174 # if lfs metadata says nothing, assume it's binary by default
176 return bool(int(metadata.get('x-is-binary', 1)))
175 return bool(int(metadata.get('x-is-binary', 1)))
177 return orig(self)
176 return orig(self)
178
177
179 def filectxislfs(self):
178 def filectxislfs(self):
180 return _islfs(self.filelog(), self.filenode())
179 return _islfs(self.filelog(), self.filenode())
181
180
182 def _updatecatformatter(orig, fm, ctx, matcher, path, decode):
181 def _updatecatformatter(orig, fm, ctx, matcher, path, decode):
183 orig(fm, ctx, matcher, path, decode)
182 orig(fm, ctx, matcher, path, decode)
184 fm.data(rawdata=ctx[path].rawdata())
183 fm.data(rawdata=ctx[path].rawdata())
185
184
186 def convertsink(orig, sink):
185 def convertsink(orig, sink):
187 sink = orig(sink)
186 sink = orig(sink)
188 if sink.repotype == 'hg':
187 if sink.repotype == 'hg':
189 class lfssink(sink.__class__):
188 class lfssink(sink.__class__):
190 def putcommit(self, files, copies, parents, commit, source, revmap,
189 def putcommit(self, files, copies, parents, commit, source, revmap,
191 full, cleanp2):
190 full, cleanp2):
192 pc = super(lfssink, self).putcommit
191 pc = super(lfssink, self).putcommit
193 node = pc(files, copies, parents, commit, source, revmap, full,
192 node = pc(files, copies, parents, commit, source, revmap, full,
194 cleanp2)
193 cleanp2)
195
194
196 if 'lfs' not in self.repo.requirements:
195 if 'lfs' not in self.repo.requirements:
197 ctx = self.repo[node]
196 ctx = self.repo[node]
198
197
199 # The file list may contain removed files, so check for
198 # The file list may contain removed files, so check for
200 # membership before assuming it is in the context.
199 # membership before assuming it is in the context.
201 if any(f in ctx and ctx[f].islfs() for f, n in files):
200 if any(f in ctx and ctx[f].islfs() for f, n in files):
202 self.repo.requirements.add('lfs')
201 self.repo.requirements.add('lfs')
203 self.repo._writerequirements()
202 self.repo._writerequirements()
204
203
205 # Permanently enable lfs locally
204 # Permanently enable lfs locally
206 self.repo.vfs.append(
205 self.repo.vfs.append(
207 'hgrc', util.tonativeeol('\n[extensions]\nlfs=\n'))
206 'hgrc', util.tonativeeol('\n[extensions]\nlfs=\n'))
208
207
209 return node
208 return node
210
209
211 sink.__class__ = lfssink
210 sink.__class__ = lfssink
212
211
213 return sink
212 return sink
214
213
215 def vfsinit(orig, self, othervfs):
214 def vfsinit(orig, self, othervfs):
216 orig(self, othervfs)
215 orig(self, othervfs)
217 # copy lfs related options
216 # copy lfs related options
218 for k, v in othervfs.options.items():
217 for k, v in othervfs.options.items():
219 if k.startswith('lfs'):
218 if k.startswith('lfs'):
220 self.options[k] = v
219 self.options[k] = v
221 # also copy lfs blobstores. note: this can run before reposetup, so lfs
220 # also copy lfs blobstores. note: this can run before reposetup, so lfs
222 # blobstore attributes are not always ready at this time.
221 # blobstore attributes are not always ready at this time.
223 for name in ['lfslocalblobstore', 'lfsremoteblobstore']:
222 for name in ['lfslocalblobstore', 'lfsremoteblobstore']:
224 if util.safehasattr(othervfs, name):
223 if util.safehasattr(othervfs, name):
225 setattr(self, name, getattr(othervfs, name))
224 setattr(self, name, getattr(othervfs, name))
226
225
227 def hgclone(orig, ui, opts, *args, **kwargs):
226 def hgclone(orig, ui, opts, *args, **kwargs):
228 result = orig(ui, opts, *args, **kwargs)
227 result = orig(ui, opts, *args, **kwargs)
229
228
230 if result is not None:
229 if result is not None:
231 sourcerepo, destrepo = result
230 sourcerepo, destrepo = result
232 repo = destrepo.local()
231 repo = destrepo.local()
233
232
234 # When cloning to a remote repo (like through SSH), no repo is available
233 # When cloning to a remote repo (like through SSH), no repo is available
235 # from the peer. Therefore the hgrc can't be updated.
234 # from the peer. Therefore the hgrc can't be updated.
236 if not repo:
235 if not repo:
237 return result
236 return result
238
237
239 # If lfs is required for this repo, permanently enable it locally
238 # If lfs is required for this repo, permanently enable it locally
240 if 'lfs' in repo.requirements:
239 if 'lfs' in repo.requirements:
241 repo.vfs.append('hgrc',
240 repo.vfs.append('hgrc',
242 util.tonativeeol('\n[extensions]\nlfs=\n'))
241 util.tonativeeol('\n[extensions]\nlfs=\n'))
243
242
244 return result
243 return result
245
244
246 def hgpostshare(orig, sourcerepo, destrepo, bookmarks=True, defaultpath=None):
245 def hgpostshare(orig, sourcerepo, destrepo, bookmarks=True, defaultpath=None):
247 orig(sourcerepo, destrepo, bookmarks, defaultpath)
246 orig(sourcerepo, destrepo, bookmarks, defaultpath)
248
247
249 # If lfs is required for this repo, permanently enable it locally
248 # If lfs is required for this repo, permanently enable it locally
250 if 'lfs' in destrepo.requirements:
249 if 'lfs' in destrepo.requirements:
251 destrepo.vfs.append('hgrc', util.tonativeeol('\n[extensions]\nlfs=\n'))
250 destrepo.vfs.append('hgrc', util.tonativeeol('\n[extensions]\nlfs=\n'))
252
251
253 def _canskipupload(repo):
252 def _canskipupload(repo):
254 # if remotestore is a null store, upload is a no-op and can be skipped
253 # if remotestore is a null store, upload is a no-op and can be skipped
255 return isinstance(repo.svfs.lfsremoteblobstore, blobstore._nullremote)
254 return isinstance(repo.svfs.lfsremoteblobstore, blobstore._nullremote)
256
255
257 def candownload(repo):
256 def candownload(repo):
258 # if remotestore is a null store, downloads will lead to nothing
257 # if remotestore is a null store, downloads will lead to nothing
259 return not isinstance(repo.svfs.lfsremoteblobstore, blobstore._nullremote)
258 return not isinstance(repo.svfs.lfsremoteblobstore, blobstore._nullremote)
260
259
261 def uploadblobsfromrevs(repo, revs):
260 def uploadblobsfromrevs(repo, revs):
262 '''upload lfs blobs introduced by revs
261 '''upload lfs blobs introduced by revs
263
262
264 Note: also used by other extensions e. g. infinitepush. avoid renaming.
263 Note: also used by other extensions e. g. infinitepush. avoid renaming.
265 '''
264 '''
266 if _canskipupload(repo):
265 if _canskipupload(repo):
267 return
266 return
268 pointers = extractpointers(repo, revs)
267 pointers = extractpointers(repo, revs)
269 uploadblobs(repo, pointers)
268 uploadblobs(repo, pointers)
270
269
271 def prepush(pushop):
270 def prepush(pushop):
272 """Prepush hook.
271 """Prepush hook.
273
272
274 Read through the revisions to push, looking for filelog entries that can be
273 Read through the revisions to push, looking for filelog entries that can be
275 deserialized into metadata so that we can block the push on their upload to
274 deserialized into metadata so that we can block the push on their upload to
276 the remote blobstore.
275 the remote blobstore.
277 """
276 """
278 return uploadblobsfromrevs(pushop.repo, pushop.outgoing.missing)
277 return uploadblobsfromrevs(pushop.repo, pushop.outgoing.missing)
279
278
280 def push(orig, repo, remote, *args, **kwargs):
279 def push(orig, repo, remote, *args, **kwargs):
281 """bail on push if the extension isn't enabled on remote when needed"""
280 """bail on push if the extension isn't enabled on remote when needed"""
282 if 'lfs' in repo.requirements:
281 if 'lfs' in repo.requirements:
283 # If the remote peer is for a local repo, the requirement tests in the
282 # If the remote peer is for a local repo, the requirement tests in the
284 # base class method enforce lfs support. Otherwise, some revisions in
283 # base class method enforce lfs support. Otherwise, some revisions in
285 # this repo use lfs, and the remote repo needs the extension loaded.
284 # this repo use lfs, and the remote repo needs the extension loaded.
286 if not remote.local() and not remote.capable('lfs'):
285 if not remote.local() and not remote.capable('lfs'):
287 # This is a copy of the message in exchange.push() when requirements
286 # This is a copy of the message in exchange.push() when requirements
288 # are missing between local repos.
287 # are missing between local repos.
289 m = _("required features are not supported in the destination: %s")
288 m = _("required features are not supported in the destination: %s")
290 raise error.Abort(m % 'lfs',
289 raise error.Abort(m % 'lfs',
291 hint=_('enable the lfs extension on the server'))
290 hint=_('enable the lfs extension on the server'))
292 return orig(repo, remote, *args, **kwargs)
291 return orig(repo, remote, *args, **kwargs)
293
292
294 def writenewbundle(orig, ui, repo, source, filename, bundletype, outgoing,
293 def writenewbundle(orig, ui, repo, source, filename, bundletype, outgoing,
295 *args, **kwargs):
294 *args, **kwargs):
296 """upload LFS blobs added by outgoing revisions on 'hg bundle'"""
295 """upload LFS blobs added by outgoing revisions on 'hg bundle'"""
297 uploadblobsfromrevs(repo, outgoing.missing)
296 uploadblobsfromrevs(repo, outgoing.missing)
298 return orig(ui, repo, source, filename, bundletype, outgoing, *args,
297 return orig(ui, repo, source, filename, bundletype, outgoing, *args,
299 **kwargs)
298 **kwargs)
300
299
301 def extractpointers(repo, revs):
300 def extractpointers(repo, revs):
302 """return a list of lfs pointers added by given revs"""
301 """return a list of lfs pointers added by given revs"""
303 repo.ui.debug('lfs: computing set of blobs to upload\n')
302 repo.ui.debug('lfs: computing set of blobs to upload\n')
304 pointers = {}
303 pointers = {}
305 for r in revs:
304 for r in revs:
306 ctx = repo[r]
305 ctx = repo[r]
307 for p in pointersfromctx(ctx).values():
306 for p in pointersfromctx(ctx).values():
308 pointers[p.oid()] = p
307 pointers[p.oid()] = p
309 return sorted(pointers.values())
308 return sorted(pointers.values())
310
309
311 def pointersfromctx(ctx):
310 def pointersfromctx(ctx):
312 """return a dict {path: pointer} for given single changectx"""
311 """return a dict {path: pointer} for given single changectx"""
313 result = {}
312 result = {}
314 for f in ctx.files():
313 for f in ctx.files():
315 if f not in ctx:
314 if f not in ctx:
316 continue
315 continue
317 fctx = ctx[f]
316 fctx = ctx[f]
318 if not _islfs(fctx.filelog(), fctx.filenode()):
317 if not _islfs(fctx.filelog(), fctx.filenode()):
319 continue
318 continue
320 try:
319 try:
321 result[f] = pointer.deserialize(fctx.rawdata())
320 result[f] = pointer.deserialize(fctx.rawdata())
322 except pointer.InvalidPointer as ex:
321 except pointer.InvalidPointer as ex:
323 raise error.Abort(_('lfs: corrupted pointer (%s@%s): %s\n')
322 raise error.Abort(_('lfs: corrupted pointer (%s@%s): %s\n')
324 % (f, short(ctx.node()), ex))
323 % (f, short(ctx.node()), ex))
325 return result
324 return result
326
325
327 def uploadblobs(repo, pointers):
326 def uploadblobs(repo, pointers):
328 """upload given pointers from local blobstore"""
327 """upload given pointers from local blobstore"""
329 if not pointers:
328 if not pointers:
330 return
329 return
331
330
332 remoteblob = repo.svfs.lfsremoteblobstore
331 remoteblob = repo.svfs.lfsremoteblobstore
333 remoteblob.writebatch(pointers, repo.svfs.lfslocalblobstore)
332 remoteblob.writebatch(pointers, repo.svfs.lfslocalblobstore)
334
333
335 def upgradefinishdatamigration(orig, ui, srcrepo, dstrepo, requirements):
334 def upgradefinishdatamigration(orig, ui, srcrepo, dstrepo, requirements):
336 orig(ui, srcrepo, dstrepo, requirements)
335 orig(ui, srcrepo, dstrepo, requirements)
337
336
338 srclfsvfs = srcrepo.svfs.lfslocalblobstore.vfs
337 srclfsvfs = srcrepo.svfs.lfslocalblobstore.vfs
339 dstlfsvfs = dstrepo.svfs.lfslocalblobstore.vfs
338 dstlfsvfs = dstrepo.svfs.lfslocalblobstore.vfs
340
339
341 for dirpath, dirs, files in srclfsvfs.walk():
340 for dirpath, dirs, files in srclfsvfs.walk():
342 for oid in files:
341 for oid in files:
343 ui.write(_('copying lfs blob %s\n') % oid)
342 ui.write(_('copying lfs blob %s\n') % oid)
344 lfutil.link(srclfsvfs.join(oid), dstlfsvfs.join(oid))
343 lfutil.link(srclfsvfs.join(oid), dstlfsvfs.join(oid))
345
344
346 def upgraderequirements(orig, repo):
345 def upgraderequirements(orig, repo):
347 reqs = orig(repo)
346 reqs = orig(repo)
348 if 'lfs' in repo.requirements:
347 if 'lfs' in repo.requirements:
349 reqs.add('lfs')
348 reqs.add('lfs')
350 return reqs
349 return reqs
@@ -1,1065 +1,1064 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 > # Test deprecated config
8 > threshold=1000B
8 > threshold=1000B
9 > EOF
9 > EOF
10
10
11 $ LONG=AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
11 $ LONG=AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
12
12
13 # Prepare server and enable extension
13 # Prepare server and enable extension
14 $ hg init server
14 $ hg init server
15 $ hg clone -q server client
15 $ hg clone -q server client
16 $ cd client
16 $ cd client
17
17
18 # Commit small file
18 # Commit small file
19 $ echo s > smallfile
19 $ echo s > smallfile
20 $ echo '**.py = LF' > .hgeol
20 $ echo '**.py = LF' > .hgeol
21 $ hg --config lfs.track='size(">1000B") | "path:.hgeol"' commit -Aqm "add small file"
21 $ hg --config lfs.track='size(">1000B")' commit -Aqm "add small file"
22 $ hg debugdata .hgeol 0
23 **.py = LF
24
22
25 # Commit large file
23 # Commit large file
26 $ echo $LONG > largefile
24 $ echo $LONG > largefile
27 $ grep lfs .hg/requires
25 $ grep lfs .hg/requires
28 [1]
26 [1]
29 $ hg commit --traceback -Aqm "add large file"
27 $ hg commit --traceback -Aqm "add large file"
30 $ grep lfs .hg/requires
28 $ grep lfs .hg/requires
31 lfs
29 lfs
32
30
33 # Ensure metadata is stored
31 # Ensure metadata is stored
34 $ hg debugdata largefile 0
32 $ hg debugdata largefile 0
35 version https://git-lfs.github.com/spec/v1
33 version https://git-lfs.github.com/spec/v1
36 oid sha256:f11e77c257047a398492d8d6cb9f6acf3aa7c4384bb23080b43546053e183e4b
34 oid sha256:f11e77c257047a398492d8d6cb9f6acf3aa7c4384bb23080b43546053e183e4b
37 size 1501
35 size 1501
38 x-is-binary 0
36 x-is-binary 0
39
37
40 # Check the blobstore is populated
38 # Check the blobstore is populated
41 $ find .hg/store/lfs/objects | sort
39 $ find .hg/store/lfs/objects | sort
42 .hg/store/lfs/objects
40 .hg/store/lfs/objects
43 .hg/store/lfs/objects/f1
41 .hg/store/lfs/objects/f1
44 .hg/store/lfs/objects/f1/1e77c257047a398492d8d6cb9f6acf3aa7c4384bb23080b43546053e183e4b
42 .hg/store/lfs/objects/f1/1e77c257047a398492d8d6cb9f6acf3aa7c4384bb23080b43546053e183e4b
45
43
46 # Check the blob stored contains the actual contents of the file
44 # Check the blob stored contains the actual contents of the file
47 $ cat .hg/store/lfs/objects/f1/1e77c257047a398492d8d6cb9f6acf3aa7c4384bb23080b43546053e183e4b
45 $ cat .hg/store/lfs/objects/f1/1e77c257047a398492d8d6cb9f6acf3aa7c4384bb23080b43546053e183e4b
48 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
46 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
49
47
50 # Push changes to the server
48 # Push changes to the server
51
49
52 $ hg push
50 $ hg push
53 pushing to $TESTTMP/server
51 pushing to $TESTTMP/server
54 searching for changes
52 searching for changes
55 abort: lfs.url needs to be configured
53 abort: lfs.url needs to be configured
56 [255]
54 [255]
57
55
58 $ cat >> $HGRCPATH << EOF
56 $ cat >> $HGRCPATH << EOF
59 > [lfs]
57 > [lfs]
60 > url=file:$TESTTMP/dummy-remote/
58 > url=file:$TESTTMP/dummy-remote/
61 > EOF
59 > EOF
62
60
63 Push to a local non-lfs repo with the extension enabled will add the
61 Push to a local non-lfs repo with the extension enabled will add the
64 lfs requirement
62 lfs requirement
65
63
66 $ grep lfs $TESTTMP/server/.hg/requires
64 $ grep lfs $TESTTMP/server/.hg/requires
67 [1]
65 [1]
68 $ hg push -v | egrep -v '^(uncompressed| )'
66 $ hg push -v | egrep -v '^(uncompressed| )'
69 pushing to $TESTTMP/server
67 pushing to $TESTTMP/server
70 searching for changes
68 searching for changes
71 lfs: found f11e77c257047a398492d8d6cb9f6acf3aa7c4384bb23080b43546053e183e4b in the local lfs store
69 lfs: found f11e77c257047a398492d8d6cb9f6acf3aa7c4384bb23080b43546053e183e4b in the local lfs store
72 2 changesets found
70 2 changesets found
73 adding changesets
71 adding changesets
74 adding manifests
72 adding manifests
75 adding file changes
73 adding file changes
76 added 2 changesets with 3 changes to 3 files
74 added 2 changesets with 3 changes to 3 files
77 calling hook pretxnchangegroup.lfs: hgext.lfs.checkrequireslfs
75 calling hook pretxnchangegroup.lfs: hgext.lfs.checkrequireslfs
78 $ grep lfs $TESTTMP/server/.hg/requires
76 $ grep lfs $TESTTMP/server/.hg/requires
79 lfs
77 lfs
80
78
81 # Unknown URL scheme
79 # Unknown URL scheme
82
80
83 $ hg push --config lfs.url=ftp://foobar
81 $ hg push --config lfs.url=ftp://foobar
84 abort: lfs: unknown url scheme: ftp
82 abort: lfs: unknown url scheme: ftp
85 [255]
83 [255]
86
84
87 $ cd ../
85 $ cd ../
88
86
89 # Initialize new client (not cloning) and setup extension
87 # Initialize new client (not cloning) and setup extension
90 $ hg init client2
88 $ hg init client2
91 $ cd client2
89 $ cd client2
92 $ cat >> .hg/hgrc <<EOF
90 $ cat >> .hg/hgrc <<EOF
93 > [paths]
91 > [paths]
94 > default = $TESTTMP/server
92 > default = $TESTTMP/server
95 > EOF
93 > EOF
96
94
97 # Pull from server
95 # Pull from server
98
96
99 Pulling a local lfs repo into a local non-lfs repo with the extension
97 Pulling a local lfs repo into a local non-lfs repo with the extension
100 enabled adds the lfs requirement
98 enabled adds the lfs requirement
101
99
102 $ grep lfs .hg/requires $TESTTMP/server/.hg/requires
100 $ grep lfs .hg/requires $TESTTMP/server/.hg/requires
103 $TESTTMP/server/.hg/requires:lfs
101 $TESTTMP/server/.hg/requires:lfs
104 $ hg pull default
102 $ hg pull default
105 pulling from $TESTTMP/server
103 pulling from $TESTTMP/server
106 requesting all changes
104 requesting all changes
107 adding changesets
105 adding changesets
108 adding manifests
106 adding manifests
109 adding file changes
107 adding file changes
110 added 2 changesets with 3 changes to 3 files
108 added 2 changesets with 3 changes to 3 files
111 new changesets 0ead593177f7:b88141481348
109 new changesets 0ead593177f7:b88141481348
112 (run 'hg update' to get a working copy)
110 (run 'hg update' to get a working copy)
113 $ grep lfs .hg/requires $TESTTMP/server/.hg/requires
111 $ grep lfs .hg/requires $TESTTMP/server/.hg/requires
114 .hg/requires:lfs
112 .hg/requires:lfs
115 $TESTTMP/server/.hg/requires:lfs
113 $TESTTMP/server/.hg/requires:lfs
116
114
117 # Check the blobstore is not yet populated
115 # Check the blobstore is not yet populated
118 $ [ -d .hg/store/lfs/objects ]
116 $ [ -d .hg/store/lfs/objects ]
119 [1]
117 [1]
120
118
121 # Update to the last revision containing the large file
119 # Update to the last revision containing the large file
122 $ hg update
120 $ hg update
123 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
121 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
124
122
125 # Check the blobstore has been populated on update
123 # Check the blobstore has been populated on update
126 $ find .hg/store/lfs/objects | sort
124 $ find .hg/store/lfs/objects | sort
127 .hg/store/lfs/objects
125 .hg/store/lfs/objects
128 .hg/store/lfs/objects/f1
126 .hg/store/lfs/objects/f1
129 .hg/store/lfs/objects/f1/1e77c257047a398492d8d6cb9f6acf3aa7c4384bb23080b43546053e183e4b
127 .hg/store/lfs/objects/f1/1e77c257047a398492d8d6cb9f6acf3aa7c4384bb23080b43546053e183e4b
130
128
131 # Check the contents of the file are fetched from blobstore when requested
129 # Check the contents of the file are fetched from blobstore when requested
132 $ hg cat -r . largefile
130 $ hg cat -r . largefile
133 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
131 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
134
132
135 # Check the file has been copied in the working copy
133 # Check the file has been copied in the working copy
136 $ cat largefile
134 $ cat largefile
137 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
135 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
138
136
139 $ cd ..
137 $ cd ..
140
138
141 # Check rename, and switch between large and small files
139 # Check rename, and switch between large and small files
142
140
143 $ hg init repo3
141 $ hg init repo3
144 $ cd repo3
142 $ cd repo3
145 $ cat >> .hg/hgrc << EOF
143 $ cat >> .hg/hgrc << EOF
146 > [lfs]
144 > [lfs]
147 > track=size(">10B")
145 > track=size(">10B")
148 > EOF
146 > EOF
149
147
150 $ echo LONGER-THAN-TEN-BYTES-WILL-TRIGGER-LFS > large
148 $ echo LONGER-THAN-TEN-BYTES-WILL-TRIGGER-LFS > large
151 $ echo SHORTER > small
149 $ echo SHORTER > small
152 $ hg add . -q
150 $ hg add . -q
153 $ hg commit -m 'commit with lfs content'
151 $ hg commit -m 'commit with lfs content'
154
152
155 $ hg mv large l
153 $ hg mv large l
156 $ hg mv small s
154 $ hg mv small s
157 $ hg commit -m 'renames'
155 $ hg commit -m 'renames'
158
156
159 $ echo SHORT > l
157 $ echo SHORT > l
160 $ echo BECOME-LARGER-FROM-SHORTER > s
158 $ echo BECOME-LARGER-FROM-SHORTER > s
161 $ hg commit -m 'large to small, small to large'
159 $ hg commit -m 'large to small, small to large'
162
160
163 $ echo 1 >> l
161 $ echo 1 >> l
164 $ echo 2 >> s
162 $ echo 2 >> s
165 $ hg commit -m 'random modifications'
163 $ hg commit -m 'random modifications'
166
164
167 $ echo RESTORE-TO-BE-LARGE > l
165 $ echo RESTORE-TO-BE-LARGE > l
168 $ echo SHORTER > s
166 $ echo SHORTER > s
169 $ hg commit -m 'switch large and small again'
167 $ hg commit -m 'switch large and small again'
170
168
171 # Test lfs_files template
169 # Test lfs_files template
172
170
173 $ hg log -r 'all()' -T '{rev} {join(lfs_files, ", ")}\n'
171 $ hg log -r 'all()' -T '{rev} {join(lfs_files, ", ")}\n'
174 0 large
172 0 large
175 1 l
173 1 l
176 2 s
174 2 s
177 3 s
175 3 s
178 4 l
176 4 l
179
177
180 # Push and pull the above repo
178 # Push and pull the above repo
181
179
182 $ hg --cwd .. init repo4
180 $ hg --cwd .. init repo4
183 $ hg push ../repo4
181 $ hg push ../repo4
184 pushing to ../repo4
182 pushing to ../repo4
185 searching for changes
183 searching for changes
186 adding changesets
184 adding changesets
187 adding manifests
185 adding manifests
188 adding file changes
186 adding file changes
189 added 5 changesets with 10 changes to 4 files
187 added 5 changesets with 10 changes to 4 files
190
188
191 $ hg --cwd .. init repo5
189 $ hg --cwd .. init repo5
192 $ hg --cwd ../repo5 pull ../repo3
190 $ hg --cwd ../repo5 pull ../repo3
193 pulling from ../repo3
191 pulling from ../repo3
194 requesting all changes
192 requesting all changes
195 adding changesets
193 adding changesets
196 adding manifests
194 adding manifests
197 adding file changes
195 adding file changes
198 added 5 changesets with 10 changes to 4 files
196 added 5 changesets with 10 changes to 4 files
199 new changesets fd47a419c4f7:5adf850972b9
197 new changesets fd47a419c4f7:5adf850972b9
200 (run 'hg update' to get a working copy)
198 (run 'hg update' to get a working copy)
201
199
202 $ cd ..
200 $ cd ..
203
201
204 # Test clone
202 # Test clone
205
203
206 $ hg init repo6
204 $ hg init repo6
207 $ cd repo6
205 $ cd repo6
208 $ cat >> .hg/hgrc << EOF
206 $ cat >> .hg/hgrc << EOF
209 > [lfs]
207 > [lfs]
210 > track=size(">30B")
208 > track=size(">30B")
211 > EOF
209 > EOF
212
210
213 $ echo LARGE-BECAUSE-IT-IS-MORE-THAN-30-BYTES > large
211 $ echo LARGE-BECAUSE-IT-IS-MORE-THAN-30-BYTES > large
214 $ echo SMALL > small
212 $ echo SMALL > small
215 $ hg commit -Aqm 'create a lfs file' large small
213 $ hg commit -Aqm 'create a lfs file' large small
216 $ hg debuglfsupload -r 'all()' -v
214 $ hg debuglfsupload -r 'all()' -v
217 lfs: found 8e92251415339ae9b148c8da89ed5ec665905166a1ab11b09dca8fad83344738 in the local lfs store
215 lfs: found 8e92251415339ae9b148c8da89ed5ec665905166a1ab11b09dca8fad83344738 in the local lfs store
218
216
219 $ cd ..
217 $ cd ..
220
218
221 $ hg clone repo6 repo7
219 $ hg clone repo6 repo7
222 updating to branch default
220 updating to branch default
223 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
221 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
224 $ cd repo7
222 $ cd repo7
225 $ hg config extensions --debug | grep lfs
223 $ hg config extensions --debug | grep lfs
226 $TESTTMP/repo7/.hg/hgrc:*: extensions.lfs= (glob)
224 $TESTTMP/repo7/.hg/hgrc:*: extensions.lfs= (glob)
227 $ cat large
225 $ cat large
228 LARGE-BECAUSE-IT-IS-MORE-THAN-30-BYTES
226 LARGE-BECAUSE-IT-IS-MORE-THAN-30-BYTES
229 $ cat small
227 $ cat small
230 SMALL
228 SMALL
231
229
232 $ cd ..
230 $ cd ..
233
231
234 $ hg --config extensions.share= share repo7 sharedrepo
232 $ hg --config extensions.share= share repo7 sharedrepo
235 updating working directory
233 updating working directory
236 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
234 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
237 $ hg -R sharedrepo config extensions --debug | grep lfs
235 $ hg -R sharedrepo config extensions --debug | grep lfs
238 $TESTTMP/sharedrepo/.hg/hgrc:*: extensions.lfs= (glob)
236 $TESTTMP/sharedrepo/.hg/hgrc:*: extensions.lfs= (glob)
239
237
240 # Test rename and status
238 # Test rename and status
241
239
242 $ hg init repo8
240 $ hg init repo8
243 $ cd repo8
241 $ cd repo8
244 $ cat >> .hg/hgrc << EOF
242 $ cat >> .hg/hgrc << EOF
245 > [lfs]
243 > [lfs]
246 > track=size(">10B")
244 > track=size(">10B")
247 > EOF
245 > EOF
248
246
249 $ echo THIS-IS-LFS-BECAUSE-10-BYTES > a1
247 $ echo THIS-IS-LFS-BECAUSE-10-BYTES > a1
250 $ echo SMALL > a2
248 $ echo SMALL > a2
251 $ hg commit -m a -A a1 a2
249 $ hg commit -m a -A a1 a2
252 $ hg status
250 $ hg status
253 $ hg mv a1 b1
251 $ hg mv a1 b1
254 $ hg mv a2 a1
252 $ hg mv a2 a1
255 $ hg mv b1 a2
253 $ hg mv b1 a2
256 $ hg commit -m b
254 $ hg commit -m b
257 $ hg status
255 $ hg status
258 >>> with open('a2', 'wb') as f:
256 >>> with open('a2', 'wb') as f:
259 ... f.write(b'\1\nSTART-WITH-HG-FILELOG-METADATA')
257 ... f.write(b'\1\nSTART-WITH-HG-FILELOG-METADATA')
260 >>> with open('a1', 'wb') as f:
258 >>> with open('a1', 'wb') as f:
261 ... f.write(b'\1\nMETA\n')
259 ... f.write(b'\1\nMETA\n')
262 $ hg commit -m meta
260 $ hg commit -m meta
263 $ hg status
261 $ hg status
264 $ hg log -T '{rev}: {file_copies} | {file_dels} | {file_adds}\n'
262 $ hg log -T '{rev}: {file_copies} | {file_dels} | {file_adds}\n'
265 2: | |
263 2: | |
266 1: a1 (a2)a2 (a1) | |
264 1: a1 (a2)a2 (a1) | |
267 0: | | a1 a2
265 0: | | a1 a2
268
266
269 $ for n in a1 a2; do
267 $ for n in a1 a2; do
270 > for r in 0 1 2; do
268 > for r in 0 1 2; do
271 > printf '\n%s @ %s\n' $n $r
269 > printf '\n%s @ %s\n' $n $r
272 > hg debugdata $n $r
270 > hg debugdata $n $r
273 > done
271 > done
274 > done
272 > done
275
273
276 a1 @ 0
274 a1 @ 0
277 version https://git-lfs.github.com/spec/v1
275 version https://git-lfs.github.com/spec/v1
278 oid sha256:5bb8341bee63b3649f222b2215bde37322bea075a30575aa685d8f8d21c77024
276 oid sha256:5bb8341bee63b3649f222b2215bde37322bea075a30575aa685d8f8d21c77024
279 size 29
277 size 29
280 x-is-binary 0
278 x-is-binary 0
281
279
282 a1 @ 1
280 a1 @ 1
283 \x01 (esc)
281 \x01 (esc)
284 copy: a2
282 copy: a2
285 copyrev: 50470ad23cf937b1f4b9f80bfe54df38e65b50d9
283 copyrev: 50470ad23cf937b1f4b9f80bfe54df38e65b50d9
286 \x01 (esc)
284 \x01 (esc)
287 SMALL
285 SMALL
288
286
289 a1 @ 2
287 a1 @ 2
290 \x01 (esc)
288 \x01 (esc)
291 \x01 (esc)
289 \x01 (esc)
292 \x01 (esc)
290 \x01 (esc)
293 META
291 META
294
292
295 a2 @ 0
293 a2 @ 0
296 SMALL
294 SMALL
297
295
298 a2 @ 1
296 a2 @ 1
299 version https://git-lfs.github.com/spec/v1
297 version https://git-lfs.github.com/spec/v1
300 oid sha256:5bb8341bee63b3649f222b2215bde37322bea075a30575aa685d8f8d21c77024
298 oid sha256:5bb8341bee63b3649f222b2215bde37322bea075a30575aa685d8f8d21c77024
301 size 29
299 size 29
302 x-hg-copy a1
300 x-hg-copy a1
303 x-hg-copyrev be23af27908a582af43e5cda209a5a9b319de8d4
301 x-hg-copyrev be23af27908a582af43e5cda209a5a9b319de8d4
304 x-is-binary 0
302 x-is-binary 0
305
303
306 a2 @ 2
304 a2 @ 2
307 version https://git-lfs.github.com/spec/v1
305 version https://git-lfs.github.com/spec/v1
308 oid sha256:876dadc86a8542f9798048f2c47f51dbf8e4359aed883e8ec80c5db825f0d943
306 oid sha256:876dadc86a8542f9798048f2c47f51dbf8e4359aed883e8ec80c5db825f0d943
309 size 32
307 size 32
310 x-is-binary 0
308 x-is-binary 0
311
309
312 # Verify commit hashes include rename metadata
310 # Verify commit hashes include rename metadata
313
311
314 $ hg log -T '{rev}:{node|short} {desc}\n'
312 $ hg log -T '{rev}:{node|short} {desc}\n'
315 2:0fae949de7fa meta
313 2:0fae949de7fa meta
316 1:9cd6bdffdac0 b
314 1:9cd6bdffdac0 b
317 0:7f96794915f7 a
315 0:7f96794915f7 a
318
316
319 $ cd ..
317 $ cd ..
320
318
321 # Test bundle
319 # Test bundle
322
320
323 $ hg init repo9
321 $ hg init repo9
324 $ cd repo9
322 $ cd repo9
325 $ cat >> .hg/hgrc << EOF
323 $ cat >> .hg/hgrc << EOF
326 > [lfs]
324 > [lfs]
327 > track=size(">10B")
325 > track=size(">10B")
328 > [diff]
326 > [diff]
329 > git=1
327 > git=1
330 > EOF
328 > EOF
331
329
332 $ for i in 0 single two three 4; do
330 $ for i in 0 single two three 4; do
333 > echo 'THIS-IS-LFS-'$i > a
331 > echo 'THIS-IS-LFS-'$i > a
334 > hg commit -m a-$i -A a
332 > hg commit -m a-$i -A a
335 > done
333 > done
336
334
337 $ hg update 2 -q
335 $ hg update 2 -q
338 $ echo 'THIS-IS-LFS-2-CHILD' > a
336 $ echo 'THIS-IS-LFS-2-CHILD' > a
339 $ hg commit -m branching -q
337 $ hg commit -m branching -q
340
338
341 $ hg bundle --base 1 bundle.hg -v
339 $ hg bundle --base 1 bundle.hg -v
342 lfs: found 5ab7a3739a5feec94a562d070a14f36dba7cad17e5484a4a89eea8e5f3166888 in the local lfs store
340 lfs: found 5ab7a3739a5feec94a562d070a14f36dba7cad17e5484a4a89eea8e5f3166888 in the local lfs store
343 lfs: found a9c7d1cd6ce2b9bbdf46ed9a862845228717b921c089d0d42e3bcaed29eb612e in the local lfs store
341 lfs: found a9c7d1cd6ce2b9bbdf46ed9a862845228717b921c089d0d42e3bcaed29eb612e in the local lfs store
344 lfs: found f693890c49c409ec33673b71e53f297681f76c1166daf33b2ad7ebf8b1d3237e in the local lfs store
342 lfs: found f693890c49c409ec33673b71e53f297681f76c1166daf33b2ad7ebf8b1d3237e in the local lfs store
345 lfs: found fda198fea753eb66a252e9856915e1f5cddbe41723bd4b695ece2604ad3c9f75 in the local lfs store
343 lfs: found fda198fea753eb66a252e9856915e1f5cddbe41723bd4b695ece2604ad3c9f75 in the local lfs store
346 4 changesets found
344 4 changesets found
347 uncompressed size of bundle content:
345 uncompressed size of bundle content:
348 * (changelog) (glob)
346 * (changelog) (glob)
349 * (manifests) (glob)
347 * (manifests) (glob)
350 * a (glob)
348 * a (glob)
351 $ hg --config extensions.strip= strip -r 2 --no-backup --force -q
349 $ hg --config extensions.strip= strip -r 2 --no-backup --force -q
352 $ hg -R bundle.hg log -p -T '{rev} {desc}\n' a
350 $ hg -R bundle.hg log -p -T '{rev} {desc}\n' a
353 5 branching
351 5 branching
354 diff --git a/a b/a
352 diff --git a/a b/a
355 --- a/a
353 --- a/a
356 +++ b/a
354 +++ b/a
357 @@ -1,1 +1,1 @@
355 @@ -1,1 +1,1 @@
358 -THIS-IS-LFS-two
356 -THIS-IS-LFS-two
359 +THIS-IS-LFS-2-CHILD
357 +THIS-IS-LFS-2-CHILD
360
358
361 4 a-4
359 4 a-4
362 diff --git a/a b/a
360 diff --git a/a b/a
363 --- a/a
361 --- a/a
364 +++ b/a
362 +++ b/a
365 @@ -1,1 +1,1 @@
363 @@ -1,1 +1,1 @@
366 -THIS-IS-LFS-three
364 -THIS-IS-LFS-three
367 +THIS-IS-LFS-4
365 +THIS-IS-LFS-4
368
366
369 3 a-three
367 3 a-three
370 diff --git a/a b/a
368 diff --git a/a b/a
371 --- a/a
369 --- a/a
372 +++ b/a
370 +++ b/a
373 @@ -1,1 +1,1 @@
371 @@ -1,1 +1,1 @@
374 -THIS-IS-LFS-two
372 -THIS-IS-LFS-two
375 +THIS-IS-LFS-three
373 +THIS-IS-LFS-three
376
374
377 2 a-two
375 2 a-two
378 diff --git a/a b/a
376 diff --git a/a b/a
379 --- a/a
377 --- a/a
380 +++ b/a
378 +++ b/a
381 @@ -1,1 +1,1 @@
379 @@ -1,1 +1,1 @@
382 -THIS-IS-LFS-single
380 -THIS-IS-LFS-single
383 +THIS-IS-LFS-two
381 +THIS-IS-LFS-two
384
382
385 1 a-single
383 1 a-single
386 diff --git a/a b/a
384 diff --git a/a b/a
387 --- a/a
385 --- a/a
388 +++ b/a
386 +++ b/a
389 @@ -1,1 +1,1 @@
387 @@ -1,1 +1,1 @@
390 -THIS-IS-LFS-0
388 -THIS-IS-LFS-0
391 +THIS-IS-LFS-single
389 +THIS-IS-LFS-single
392
390
393 0 a-0
391 0 a-0
394 diff --git a/a b/a
392 diff --git a/a b/a
395 new file mode 100644
393 new file mode 100644
396 --- /dev/null
394 --- /dev/null
397 +++ b/a
395 +++ b/a
398 @@ -0,0 +1,1 @@
396 @@ -0,0 +1,1 @@
399 +THIS-IS-LFS-0
397 +THIS-IS-LFS-0
400
398
401 $ hg bundle -R bundle.hg --base 1 bundle-again.hg -q
399 $ hg bundle -R bundle.hg --base 1 bundle-again.hg -q
402 $ hg -R bundle-again.hg log -p -T '{rev} {desc}\n' a
400 $ hg -R bundle-again.hg log -p -T '{rev} {desc}\n' a
403 5 branching
401 5 branching
404 diff --git a/a b/a
402 diff --git a/a b/a
405 --- a/a
403 --- a/a
406 +++ b/a
404 +++ b/a
407 @@ -1,1 +1,1 @@
405 @@ -1,1 +1,1 @@
408 -THIS-IS-LFS-two
406 -THIS-IS-LFS-two
409 +THIS-IS-LFS-2-CHILD
407 +THIS-IS-LFS-2-CHILD
410
408
411 4 a-4
409 4 a-4
412 diff --git a/a b/a
410 diff --git a/a b/a
413 --- a/a
411 --- a/a
414 +++ b/a
412 +++ b/a
415 @@ -1,1 +1,1 @@
413 @@ -1,1 +1,1 @@
416 -THIS-IS-LFS-three
414 -THIS-IS-LFS-three
417 +THIS-IS-LFS-4
415 +THIS-IS-LFS-4
418
416
419 3 a-three
417 3 a-three
420 diff --git a/a b/a
418 diff --git a/a b/a
421 --- a/a
419 --- a/a
422 +++ b/a
420 +++ b/a
423 @@ -1,1 +1,1 @@
421 @@ -1,1 +1,1 @@
424 -THIS-IS-LFS-two
422 -THIS-IS-LFS-two
425 +THIS-IS-LFS-three
423 +THIS-IS-LFS-three
426
424
427 2 a-two
425 2 a-two
428 diff --git a/a b/a
426 diff --git a/a b/a
429 --- a/a
427 --- a/a
430 +++ b/a
428 +++ b/a
431 @@ -1,1 +1,1 @@
429 @@ -1,1 +1,1 @@
432 -THIS-IS-LFS-single
430 -THIS-IS-LFS-single
433 +THIS-IS-LFS-two
431 +THIS-IS-LFS-two
434
432
435 1 a-single
433 1 a-single
436 diff --git a/a b/a
434 diff --git a/a b/a
437 --- a/a
435 --- a/a
438 +++ b/a
436 +++ b/a
439 @@ -1,1 +1,1 @@
437 @@ -1,1 +1,1 @@
440 -THIS-IS-LFS-0
438 -THIS-IS-LFS-0
441 +THIS-IS-LFS-single
439 +THIS-IS-LFS-single
442
440
443 0 a-0
441 0 a-0
444 diff --git a/a b/a
442 diff --git a/a b/a
445 new file mode 100644
443 new file mode 100644
446 --- /dev/null
444 --- /dev/null
447 +++ b/a
445 +++ b/a
448 @@ -0,0 +1,1 @@
446 @@ -0,0 +1,1 @@
449 +THIS-IS-LFS-0
447 +THIS-IS-LFS-0
450
448
451 $ cd ..
449 $ cd ..
452
450
453 # Test isbinary
451 # Test isbinary
454
452
455 $ hg init repo10
453 $ hg init repo10
456 $ cd repo10
454 $ cd repo10
457 $ cat >> .hg/hgrc << EOF
455 $ cat >> .hg/hgrc << EOF
458 > [extensions]
456 > [extensions]
459 > lfs=
457 > lfs=
460 > [lfs]
458 > [lfs]
461 > track=all()
459 > track=all()
462 > EOF
460 > EOF
463 $ $PYTHON <<'EOF'
461 $ $PYTHON <<'EOF'
464 > def write(path, content):
462 > def write(path, content):
465 > with open(path, 'wb') as f:
463 > with open(path, 'wb') as f:
466 > f.write(content)
464 > f.write(content)
467 > write('a', b'\0\0')
465 > write('a', b'\0\0')
468 > write('b', b'\1\n')
466 > write('b', b'\1\n')
469 > write('c', b'\1\n\0')
467 > write('c', b'\1\n\0')
470 > write('d', b'xx')
468 > write('d', b'xx')
471 > EOF
469 > EOF
472 $ hg add a b c d
470 $ hg add a b c d
473 $ hg diff --stat
471 $ hg diff --stat
474 a | Bin
472 a | Bin
475 b | 1 +
473 b | 1 +
476 c | Bin
474 c | Bin
477 d | 1 +
475 d | 1 +
478 4 files changed, 2 insertions(+), 0 deletions(-)
476 4 files changed, 2 insertions(+), 0 deletions(-)
479 $ hg commit -m binarytest
477 $ hg commit -m binarytest
480 $ cat > $TESTTMP/dumpbinary.py << EOF
478 $ cat > $TESTTMP/dumpbinary.py << EOF
481 > def reposetup(ui, repo):
479 > def reposetup(ui, repo):
482 > for n in 'abcd':
480 > for n in 'abcd':
483 > ui.write(('%s: binary=%s\n') % (n, repo['.'][n].isbinary()))
481 > ui.write(('%s: binary=%s\n') % (n, repo['.'][n].isbinary()))
484 > EOF
482 > EOF
485 $ hg --config extensions.dumpbinary=$TESTTMP/dumpbinary.py id --trace
483 $ hg --config extensions.dumpbinary=$TESTTMP/dumpbinary.py id --trace
486 a: binary=True
484 a: binary=True
487 b: binary=False
485 b: binary=False
488 c: binary=True
486 c: binary=True
489 d: binary=False
487 d: binary=False
490 b55353847f02 tip
488 b55353847f02 tip
491
489
492 $ cd ..
490 $ cd ..
493
491
494 # Test fctx.cmp fastpath - diff without LFS blobs
492 # Test fctx.cmp fastpath - diff without LFS blobs
495
493
496 $ hg init repo12
494 $ hg init repo12
497 $ cd repo12
495 $ cd repo12
498 $ cat >> .hg/hgrc <<EOF
496 $ cat >> .hg/hgrc <<EOF
499 > [lfs]
497 > [lfs]
500 > threshold=1
498 > threshold=1
501 > EOF
499 > EOF
502 $ cat > ../patch.diff <<EOF
500 $ cat > ../patch.diff <<EOF
503 > # HG changeset patch
501 > # HG changeset patch
504 > 2
502 > 2
505 >
503 >
506 > diff --git a/a b/a
504 > diff --git a/a b/a
507 > old mode 100644
505 > old mode 100644
508 > new mode 100755
506 > new mode 100755
509 > EOF
507 > EOF
510
508
511 $ for i in 1 2 3; do
509 $ for i in 1 2 3; do
512 > cp ../repo10/a a
510 > cp ../repo10/a a
513 > if [ $i = 3 ]; then
511 > if [ $i = 3 ]; then
514 > # make a content-only change
512 > # make a content-only change
515 > hg import -q --bypass ../patch.diff
513 > hg import -q --bypass ../patch.diff
516 > hg update -q
514 > hg update -q
517 > rm ../patch.diff
515 > rm ../patch.diff
518 > else
516 > else
519 > echo $i >> a
517 > echo $i >> a
520 > hg commit -m $i -A a
518 > hg commit -m $i -A a
521 > fi
519 > fi
522 > done
520 > done
523 $ [ -d .hg/store/lfs/objects ]
521 $ [ -d .hg/store/lfs/objects ]
524
522
525 $ cd ..
523 $ cd ..
526
524
527 $ hg clone repo12 repo13 --noupdate
525 $ hg clone repo12 repo13 --noupdate
528 $ cd repo13
526 $ cd repo13
529 $ hg log --removed -p a -T '{desc}\n' --config diff.nobinary=1 --git
527 $ hg log --removed -p a -T '{desc}\n' --config diff.nobinary=1 --git
530 2
528 2
531 diff --git a/a b/a
529 diff --git a/a b/a
532 old mode 100644
530 old mode 100644
533 new mode 100755
531 new mode 100755
534
532
535 2
533 2
536 diff --git a/a b/a
534 diff --git a/a b/a
537 Binary file a has changed
535 Binary file a has changed
538
536
539 1
537 1
540 diff --git a/a b/a
538 diff --git a/a b/a
541 new file mode 100644
539 new file mode 100644
542 Binary file a has changed
540 Binary file a has changed
543
541
544 $ [ -d .hg/store/lfs/objects ]
542 $ [ -d .hg/store/lfs/objects ]
545 [1]
543 [1]
546
544
547 $ cd ..
545 $ cd ..
548
546
549 # Test filter
547 # Test filter
550
548
551 $ hg init repo11
549 $ hg init repo11
552 $ cd repo11
550 $ cd repo11
553 $ cat >> .hg/hgrc << EOF
551 $ cat >> .hg/hgrc << EOF
554 > [lfs]
552 > [lfs]
555 > track=(**.a & size(">5B")) | (**.b & !size(">5B"))
553 > track=(**.a & size(">5B")) | (**.b & !size(">5B"))
556 > | (**.c & "path:d" & !"path:d/c.c") | size(">10B")
554 > | (**.c & "path:d" & !"path:d/c.c") | size(">10B")
557 > EOF
555 > EOF
558
556
559 $ mkdir a
557 $ mkdir a
560 $ echo aaaaaa > a/1.a
558 $ echo aaaaaa > a/1.a
561 $ echo a > a/2.a
559 $ echo a > a/2.a
562 $ echo aaaaaa > 1.b
560 $ echo aaaaaa > 1.b
563 $ echo a > 2.b
561 $ echo a > 2.b
564 $ echo a > 1.c
562 $ echo a > 1.c
565 $ mkdir d
563 $ mkdir d
566 $ echo a > d/c.c
564 $ echo a > d/c.c
567 $ echo a > d/d.c
565 $ echo a > d/d.c
568 $ echo aaaaaaaaaaaa > x
566 $ echo aaaaaaaaaaaa > x
569 $ hg add . -q
567 $ hg add . -q
570 $ hg commit -m files
568 $ hg commit -m files
571
569
572 $ for p in a/1.a a/2.a 1.b 2.b 1.c d/c.c d/d.c x; do
570 $ for p in a/1.a a/2.a 1.b 2.b 1.c d/c.c d/d.c x; do
573 > if hg debugdata $p 0 2>&1 | grep git-lfs >/dev/null; then
571 > if hg debugdata $p 0 2>&1 | grep git-lfs >/dev/null; then
574 > echo "${p}: is lfs"
572 > echo "${p}: is lfs"
575 > else
573 > else
576 > echo "${p}: not lfs"
574 > echo "${p}: not lfs"
577 > fi
575 > fi
578 > done
576 > done
579 a/1.a: is lfs
577 a/1.a: is lfs
580 a/2.a: not lfs
578 a/2.a: not lfs
581 1.b: not lfs
579 1.b: not lfs
582 2.b: is lfs
580 2.b: is lfs
583 1.c: not lfs
581 1.c: not lfs
584 d/c.c: not lfs
582 d/c.c: not lfs
585 d/d.c: is lfs
583 d/d.c: is lfs
586 x: is lfs
584 x: is lfs
587
585
588 $ cd ..
586 $ cd ..
589
587
590 # Verify the repos
588 # Verify the repos
591
589
592 $ cat > $TESTTMP/dumpflog.py << EOF
590 $ cat > $TESTTMP/dumpflog.py << EOF
593 > # print raw revision sizes, flags, and hashes for certain files
591 > # print raw revision sizes, flags, and hashes for certain files
594 > import hashlib
592 > import hashlib
595 > from mercurial import revlog
593 > from mercurial import revlog
596 > from mercurial.node import short
594 > from mercurial.node import short
597 > def hash(rawtext):
595 > def hash(rawtext):
598 > h = hashlib.sha512()
596 > h = hashlib.sha512()
599 > h.update(rawtext)
597 > h.update(rawtext)
600 > return h.hexdigest()[:4]
598 > return h.hexdigest()[:4]
601 > def reposetup(ui, repo):
599 > def reposetup(ui, repo):
602 > # these 2 files are interesting
600 > # these 2 files are interesting
603 > for name in ['l', 's']:
601 > for name in ['l', 's']:
604 > fl = repo.file(name)
602 > fl = repo.file(name)
605 > if len(fl) == 0:
603 > if len(fl) == 0:
606 > continue
604 > continue
607 > sizes = [revlog.revlog.rawsize(fl, i) for i in fl]
605 > sizes = [revlog.revlog.rawsize(fl, i) for i in fl]
608 > texts = [fl.revision(i, raw=True) for i in fl]
606 > texts = [fl.revision(i, raw=True) for i in fl]
609 > flags = [int(fl.flags(i)) for i in fl]
607 > flags = [int(fl.flags(i)) for i in fl]
610 > hashes = [hash(t) for t in texts]
608 > hashes = [hash(t) for t in texts]
611 > print(' %s: rawsizes=%r flags=%r hashes=%r'
609 > print(' %s: rawsizes=%r flags=%r hashes=%r'
612 > % (name, sizes, flags, hashes))
610 > % (name, sizes, flags, hashes))
613 > EOF
611 > EOF
614
612
615 $ for i in client client2 server repo3 repo4 repo5 repo6 repo7 repo8 repo9 \
613 $ for i in client client2 server repo3 repo4 repo5 repo6 repo7 repo8 repo9 \
616 > repo10; do
614 > repo10; do
617 > echo 'repo:' $i
615 > echo 'repo:' $i
618 > hg --cwd $i verify --config extensions.dumpflog=$TESTTMP/dumpflog.py -q
616 > hg --cwd $i verify --config extensions.dumpflog=$TESTTMP/dumpflog.py -q
619 > done
617 > done
620 repo: client
618 repo: client
621 repo: client2
619 repo: client2
622 repo: server
620 repo: server
623 repo: repo3
621 repo: repo3
624 l: rawsizes=[211, 6, 8, 141] flags=[8192, 0, 0, 8192] hashes=['d2b8', '948c', 'cc88', '724d']
622 l: rawsizes=[211, 6, 8, 141] flags=[8192, 0, 0, 8192] hashes=['d2b8', '948c', 'cc88', '724d']
625 s: rawsizes=[74, 141, 141, 8] flags=[0, 8192, 8192, 0] hashes=['3c80', 'fce0', '874a', '826b']
623 s: rawsizes=[74, 141, 141, 8] flags=[0, 8192, 8192, 0] hashes=['3c80', 'fce0', '874a', '826b']
626 repo: repo4
624 repo: repo4
627 l: rawsizes=[211, 6, 8, 141] flags=[8192, 0, 0, 8192] hashes=['d2b8', '948c', 'cc88', '724d']
625 l: rawsizes=[211, 6, 8, 141] flags=[8192, 0, 0, 8192] hashes=['d2b8', '948c', 'cc88', '724d']
628 s: rawsizes=[74, 141, 141, 8] flags=[0, 8192, 8192, 0] hashes=['3c80', 'fce0', '874a', '826b']
626 s: rawsizes=[74, 141, 141, 8] flags=[0, 8192, 8192, 0] hashes=['3c80', 'fce0', '874a', '826b']
629 repo: repo5
627 repo: repo5
630 l: rawsizes=[211, 6, 8, 141] flags=[8192, 0, 0, 8192] hashes=['d2b8', '948c', 'cc88', '724d']
628 l: rawsizes=[211, 6, 8, 141] flags=[8192, 0, 0, 8192] hashes=['d2b8', '948c', 'cc88', '724d']
631 s: rawsizes=[74, 141, 141, 8] flags=[0, 8192, 8192, 0] hashes=['3c80', 'fce0', '874a', '826b']
629 s: rawsizes=[74, 141, 141, 8] flags=[0, 8192, 8192, 0] hashes=['3c80', 'fce0', '874a', '826b']
632 repo: repo6
630 repo: repo6
633 repo: repo7
631 repo: repo7
634 repo: repo8
632 repo: repo8
635 repo: repo9
633 repo: repo9
636 repo: repo10
634 repo: repo10
637
635
638 repo13 doesn't have any cached lfs files and its source never pushed its
636 repo13 doesn't have any cached lfs files and its source never pushed its
639 files. Therefore, the files don't exist in the remote store. Use the files in
637 files. Therefore, the files don't exist in the remote store. Use the files in
640 the user cache.
638 the user cache.
641
639
642 $ test -d $TESTTMP/repo13/.hg/store/lfs/objects
640 $ test -d $TESTTMP/repo13/.hg/store/lfs/objects
643 [1]
641 [1]
644
642
645 $ hg --config extensions.share= share repo13 repo14
643 $ hg --config extensions.share= share repo13 repo14
646 updating working directory
644 updating working directory
647 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
645 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
648 $ hg -R repo14 -q verify
646 $ hg -R repo14 -q verify
649
647
650 $ hg clone repo13 repo15
648 $ hg clone repo13 repo15
651 updating to branch default
649 updating to branch default
652 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
650 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
653 $ hg -R repo15 -q verify
651 $ hg -R repo15 -q verify
654
652
655 If the source repo doesn't have the blob (maybe it was pulled or cloned with
653 If the source repo doesn't have the blob (maybe it was pulled or cloned with
656 --noupdate), the blob is still accessible via the global cache to send to the
654 --noupdate), the blob is still accessible via the global cache to send to the
657 remote store.
655 remote store.
658
656
659 $ rm -rf $TESTTMP/repo15/.hg/store/lfs
657 $ rm -rf $TESTTMP/repo15/.hg/store/lfs
660 $ hg init repo16
658 $ hg init repo16
661 $ hg -R repo15 push repo16
659 $ hg -R repo15 push repo16
662 pushing to repo16
660 pushing to repo16
663 searching for changes
661 searching for changes
664 adding changesets
662 adding changesets
665 adding manifests
663 adding manifests
666 adding file changes
664 adding file changes
667 added 3 changesets with 2 changes to 1 files
665 added 3 changesets with 2 changes to 1 files
668 $ hg -R repo15 -q verify
666 $ hg -R repo15 -q verify
669
667
670 Test damaged file scenarios. (This also damages the usercache because of the
668 Test damaged file scenarios. (This also damages the usercache because of the
671 hardlinks.)
669 hardlinks.)
672
670
673 $ echo 'damage' >> repo5/.hg/store/lfs/objects/66/100b384bf761271b407d79fc30cdd0554f3b2c5d944836e936d584b88ce88e
671 $ echo 'damage' >> repo5/.hg/store/lfs/objects/66/100b384bf761271b407d79fc30cdd0554f3b2c5d944836e936d584b88ce88e
674
672
675 Repo with damaged lfs objects in any revision will fail verification.
673 Repo with damaged lfs objects in any revision will fail verification.
676
674
677 $ hg -R repo5 verify
675 $ hg -R repo5 verify
678 checking changesets
676 checking changesets
679 checking manifests
677 checking manifests
680 crosschecking files in changesets and manifests
678 crosschecking files in changesets and manifests
681 checking files
679 checking files
682 l@1: unpacking 46a2f24864bc: integrity check failed on data/l.i:0
680 l@1: unpacking 46a2f24864bc: integrity check failed on data/l.i:0
683 large@0: unpacking 2c531e0992ff: integrity check failed on data/large.i:0
681 large@0: unpacking 2c531e0992ff: integrity check failed on data/large.i:0
684 4 files, 5 changesets, 10 total revisions
682 4 files, 5 changesets, 10 total revisions
685 2 integrity errors encountered!
683 2 integrity errors encountered!
686 (first damaged changeset appears to be 0)
684 (first damaged changeset appears to be 0)
687 [1]
685 [1]
688
686
689 Updates work after cloning a damaged repo, if the damaged lfs objects aren't in
687 Updates work after cloning a damaged repo, if the damaged lfs objects aren't in
690 the update destination. Those objects won't be added to the new repo's store
688 the update destination. Those objects won't be added to the new repo's store
691 because they aren't accessed.
689 because they aren't accessed.
692
690
693 $ hg clone -v repo5 fromcorrupt
691 $ hg clone -v repo5 fromcorrupt
694 updating to branch default
692 updating to branch default
695 resolving manifests
693 resolving manifests
696 getting l
694 getting l
697 lfs: found 22f66a3fc0b9bf3f012c814303995ec07099b3a9ce02a7af84b5970811074a3b in the usercache
695 lfs: found 22f66a3fc0b9bf3f012c814303995ec07099b3a9ce02a7af84b5970811074a3b in the usercache
698 getting s
696 getting s
699 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
697 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
700 $ test -f fromcorrupt/.hg/store/lfs/objects/66/100b384bf761271b407d79fc30cdd0554f3b2c5d944836e936d584b88ce88e
698 $ test -f fromcorrupt/.hg/store/lfs/objects/66/100b384bf761271b407d79fc30cdd0554f3b2c5d944836e936d584b88ce88e
701 [1]
699 [1]
702
700
703 Verify will copy/link all lfs objects into the local store that aren't already
701 Verify will copy/link all lfs objects into the local store that aren't already
704 present. Bypass the corrupted usercache to show that verify works when fed by
702 present. Bypass the corrupted usercache to show that verify works when fed by
705 the (uncorrupted) remote store.
703 the (uncorrupted) remote store.
706
704
707 $ hg -R fromcorrupt --config lfs.usercache=emptycache verify -v
705 $ hg -R fromcorrupt --config lfs.usercache=emptycache verify -v
708 repository uses revlog format 1
706 repository uses revlog format 1
709 checking changesets
707 checking changesets
710 checking manifests
708 checking manifests
711 crosschecking files in changesets and manifests
709 crosschecking files in changesets and manifests
712 checking files
710 checking files
713 lfs: adding 66100b384bf761271b407d79fc30cdd0554f3b2c5d944836e936d584b88ce88e to the usercache
711 lfs: adding 66100b384bf761271b407d79fc30cdd0554f3b2c5d944836e936d584b88ce88e to the usercache
714 lfs: found 66100b384bf761271b407d79fc30cdd0554f3b2c5d944836e936d584b88ce88e in the local lfs store
712 lfs: found 66100b384bf761271b407d79fc30cdd0554f3b2c5d944836e936d584b88ce88e in the local lfs store
715 lfs: found 22f66a3fc0b9bf3f012c814303995ec07099b3a9ce02a7af84b5970811074a3b in the local lfs store
713 lfs: found 22f66a3fc0b9bf3f012c814303995ec07099b3a9ce02a7af84b5970811074a3b in the local lfs store
716 lfs: found 66100b384bf761271b407d79fc30cdd0554f3b2c5d944836e936d584b88ce88e in the local lfs store
714 lfs: found 66100b384bf761271b407d79fc30cdd0554f3b2c5d944836e936d584b88ce88e in the local lfs store
717 lfs: adding 89b6070915a3d573ff3599d1cda305bc5e38549b15c4847ab034169da66e1ca8 to the usercache
715 lfs: adding 89b6070915a3d573ff3599d1cda305bc5e38549b15c4847ab034169da66e1ca8 to the usercache
718 lfs: found 89b6070915a3d573ff3599d1cda305bc5e38549b15c4847ab034169da66e1ca8 in the local lfs store
716 lfs: found 89b6070915a3d573ff3599d1cda305bc5e38549b15c4847ab034169da66e1ca8 in the local lfs store
719 lfs: adding b1a6ea88da0017a0e77db139a54618986e9a2489bee24af9fe596de9daac498c to the usercache
717 lfs: adding b1a6ea88da0017a0e77db139a54618986e9a2489bee24af9fe596de9daac498c to the usercache
720 lfs: found b1a6ea88da0017a0e77db139a54618986e9a2489bee24af9fe596de9daac498c in the local lfs store
718 lfs: found b1a6ea88da0017a0e77db139a54618986e9a2489bee24af9fe596de9daac498c in the local lfs store
721 4 files, 5 changesets, 10 total revisions
719 4 files, 5 changesets, 10 total revisions
722
720
723 Verify will not copy/link a corrupted file from the usercache into the local
721 Verify will not copy/link a corrupted file from the usercache into the local
724 store, and poison it. (The verify with a good remote now works.)
722 store, and poison it. (The verify with a good remote now works.)
725
723
726 $ rm -r fromcorrupt/.hg/store/lfs/objects/66/100b384bf761271b407d79fc30cdd0554f3b2c5d944836e936d584b88ce88e
724 $ rm -r fromcorrupt/.hg/store/lfs/objects/66/100b384bf761271b407d79fc30cdd0554f3b2c5d944836e936d584b88ce88e
727 $ hg -R fromcorrupt verify -v
725 $ hg -R fromcorrupt verify -v
728 repository uses revlog format 1
726 repository uses revlog format 1
729 checking changesets
727 checking changesets
730 checking manifests
728 checking manifests
731 crosschecking files in changesets and manifests
729 crosschecking files in changesets and manifests
732 checking files
730 checking files
733 l@1: unpacking 46a2f24864bc: integrity check failed on data/l.i:0
731 l@1: unpacking 46a2f24864bc: integrity check failed on data/l.i:0
734 lfs: found 22f66a3fc0b9bf3f012c814303995ec07099b3a9ce02a7af84b5970811074a3b in the local lfs store
732 lfs: found 22f66a3fc0b9bf3f012c814303995ec07099b3a9ce02a7af84b5970811074a3b in the local lfs store
735 large@0: unpacking 2c531e0992ff: integrity check failed on data/large.i:0
733 large@0: unpacking 2c531e0992ff: integrity check failed on data/large.i:0
736 lfs: found 89b6070915a3d573ff3599d1cda305bc5e38549b15c4847ab034169da66e1ca8 in the local lfs store
734 lfs: found 89b6070915a3d573ff3599d1cda305bc5e38549b15c4847ab034169da66e1ca8 in the local lfs store
737 lfs: found b1a6ea88da0017a0e77db139a54618986e9a2489bee24af9fe596de9daac498c in the local lfs store
735 lfs: found b1a6ea88da0017a0e77db139a54618986e9a2489bee24af9fe596de9daac498c in the local lfs store
738 4 files, 5 changesets, 10 total revisions
736 4 files, 5 changesets, 10 total revisions
739 2 integrity errors encountered!
737 2 integrity errors encountered!
740 (first damaged changeset appears to be 0)
738 (first damaged changeset appears to be 0)
741 [1]
739 [1]
742 $ hg -R fromcorrupt --config lfs.usercache=emptycache verify -v
740 $ hg -R fromcorrupt --config lfs.usercache=emptycache verify -v
743 repository uses revlog format 1
741 repository uses revlog format 1
744 checking changesets
742 checking changesets
745 checking manifests
743 checking manifests
746 crosschecking files in changesets and manifests
744 crosschecking files in changesets and manifests
747 checking files
745 checking files
748 lfs: found 66100b384bf761271b407d79fc30cdd0554f3b2c5d944836e936d584b88ce88e in the usercache
746 lfs: found 66100b384bf761271b407d79fc30cdd0554f3b2c5d944836e936d584b88ce88e in the usercache
749 lfs: found 22f66a3fc0b9bf3f012c814303995ec07099b3a9ce02a7af84b5970811074a3b in the local lfs store
747 lfs: found 22f66a3fc0b9bf3f012c814303995ec07099b3a9ce02a7af84b5970811074a3b in the local lfs store
750 lfs: found 66100b384bf761271b407d79fc30cdd0554f3b2c5d944836e936d584b88ce88e in the local lfs store
748 lfs: found 66100b384bf761271b407d79fc30cdd0554f3b2c5d944836e936d584b88ce88e in the local lfs store
751 lfs: found 89b6070915a3d573ff3599d1cda305bc5e38549b15c4847ab034169da66e1ca8 in the local lfs store
749 lfs: found 89b6070915a3d573ff3599d1cda305bc5e38549b15c4847ab034169da66e1ca8 in the local lfs store
752 lfs: found b1a6ea88da0017a0e77db139a54618986e9a2489bee24af9fe596de9daac498c in the local lfs store
750 lfs: found b1a6ea88da0017a0e77db139a54618986e9a2489bee24af9fe596de9daac498c in the local lfs store
753 4 files, 5 changesets, 10 total revisions
751 4 files, 5 changesets, 10 total revisions
754
752
755 Damaging a file required by the update destination fails the update.
753 Damaging a file required by the update destination fails the update.
756
754
757 $ echo 'damage' >> $TESTTMP/dummy-remote/22/f66a3fc0b9bf3f012c814303995ec07099b3a9ce02a7af84b5970811074a3b
755 $ echo 'damage' >> $TESTTMP/dummy-remote/22/f66a3fc0b9bf3f012c814303995ec07099b3a9ce02a7af84b5970811074a3b
758 $ hg --config lfs.usercache=emptycache clone -v repo5 fromcorrupt2
756 $ hg --config lfs.usercache=emptycache clone -v repo5 fromcorrupt2
759 updating to branch default
757 updating to branch default
760 resolving manifests
758 resolving manifests
761 getting l
759 getting l
762 abort: corrupt remote lfs object: 22f66a3fc0b9bf3f012c814303995ec07099b3a9ce02a7af84b5970811074a3b
760 abort: corrupt remote lfs object: 22f66a3fc0b9bf3f012c814303995ec07099b3a9ce02a7af84b5970811074a3b
763 [255]
761 [255]
764
762
765 A corrupted lfs blob is not transferred from a file://remotestore to the
763 A corrupted lfs blob is not transferred from a file://remotestore to the
766 usercache or local store.
764 usercache or local store.
767
765
768 $ test -f emptycache/22/f66a3fc0b9bf3f012c814303995ec07099b3a9ce02a7af84b5970811074a3b
766 $ test -f emptycache/22/f66a3fc0b9bf3f012c814303995ec07099b3a9ce02a7af84b5970811074a3b
769 [1]
767 [1]
770 $ test -f fromcorrupt2/.hg/store/lfs/objects/22/f66a3fc0b9bf3f012c814303995ec07099b3a9ce02a7af84b5970811074a3b
768 $ test -f fromcorrupt2/.hg/store/lfs/objects/22/f66a3fc0b9bf3f012c814303995ec07099b3a9ce02a7af84b5970811074a3b
771 [1]
769 [1]
772
770
773 $ hg -R fromcorrupt2 verify
771 $ hg -R fromcorrupt2 verify
774 checking changesets
772 checking changesets
775 checking manifests
773 checking manifests
776 crosschecking files in changesets and manifests
774 crosschecking files in changesets and manifests
777 checking files
775 checking files
778 l@1: unpacking 46a2f24864bc: integrity check failed on data/l.i:0
776 l@1: unpacking 46a2f24864bc: integrity check failed on data/l.i:0
779 large@0: unpacking 2c531e0992ff: integrity check failed on data/large.i:0
777 large@0: unpacking 2c531e0992ff: integrity check failed on data/large.i:0
780 4 files, 5 changesets, 10 total revisions
778 4 files, 5 changesets, 10 total revisions
781 2 integrity errors encountered!
779 2 integrity errors encountered!
782 (first damaged changeset appears to be 0)
780 (first damaged changeset appears to be 0)
783 [1]
781 [1]
784
782
785 Corrupt local files are not sent upstream. (The alternate dummy remote
783 Corrupt local files are not sent upstream. (The alternate dummy remote
786 avoids the corrupt lfs object in the original remote.)
784 avoids the corrupt lfs object in the original remote.)
787
785
788 $ mkdir $TESTTMP/dummy-remote2
786 $ mkdir $TESTTMP/dummy-remote2
789 $ hg init dest
787 $ hg init dest
790 $ hg -R fromcorrupt2 --config lfs.url=file:///$TESTTMP/dummy-remote2 push -v dest
788 $ hg -R fromcorrupt2 --config lfs.url=file:///$TESTTMP/dummy-remote2 push -v dest
791 pushing to dest
789 pushing to dest
792 searching for changes
790 searching for changes
793 lfs: found 22f66a3fc0b9bf3f012c814303995ec07099b3a9ce02a7af84b5970811074a3b in the local lfs store
791 lfs: found 22f66a3fc0b9bf3f012c814303995ec07099b3a9ce02a7af84b5970811074a3b in the local lfs store
794 lfs: found 89b6070915a3d573ff3599d1cda305bc5e38549b15c4847ab034169da66e1ca8 in the local lfs store
792 lfs: found 89b6070915a3d573ff3599d1cda305bc5e38549b15c4847ab034169da66e1ca8 in the local lfs store
795 lfs: found b1a6ea88da0017a0e77db139a54618986e9a2489bee24af9fe596de9daac498c in the local lfs store
793 lfs: found b1a6ea88da0017a0e77db139a54618986e9a2489bee24af9fe596de9daac498c in the local lfs store
796 abort: detected corrupt lfs object: 66100b384bf761271b407d79fc30cdd0554f3b2c5d944836e936d584b88ce88e
794 abort: detected corrupt lfs object: 66100b384bf761271b407d79fc30cdd0554f3b2c5d944836e936d584b88ce88e
797 (run hg verify)
795 (run hg verify)
798 [255]
796 [255]
799
797
800 $ hg -R fromcorrupt2 --config lfs.url=file:///$TESTTMP/dummy-remote2 verify -v
798 $ hg -R fromcorrupt2 --config lfs.url=file:///$TESTTMP/dummy-remote2 verify -v
801 repository uses revlog format 1
799 repository uses revlog format 1
802 checking changesets
800 checking changesets
803 checking manifests
801 checking manifests
804 crosschecking files in changesets and manifests
802 crosschecking files in changesets and manifests
805 checking files
803 checking files
806 l@1: unpacking 46a2f24864bc: integrity check failed on data/l.i:0
804 l@1: unpacking 46a2f24864bc: integrity check failed on data/l.i:0
807 lfs: found 22f66a3fc0b9bf3f012c814303995ec07099b3a9ce02a7af84b5970811074a3b in the local lfs store
805 lfs: found 22f66a3fc0b9bf3f012c814303995ec07099b3a9ce02a7af84b5970811074a3b in the local lfs store
808 large@0: unpacking 2c531e0992ff: integrity check failed on data/large.i:0
806 large@0: unpacking 2c531e0992ff: integrity check failed on data/large.i:0
809 lfs: found 89b6070915a3d573ff3599d1cda305bc5e38549b15c4847ab034169da66e1ca8 in the local lfs store
807 lfs: found 89b6070915a3d573ff3599d1cda305bc5e38549b15c4847ab034169da66e1ca8 in the local lfs store
810 lfs: found b1a6ea88da0017a0e77db139a54618986e9a2489bee24af9fe596de9daac498c in the local lfs store
808 lfs: found b1a6ea88da0017a0e77db139a54618986e9a2489bee24af9fe596de9daac498c in the local lfs store
811 4 files, 5 changesets, 10 total revisions
809 4 files, 5 changesets, 10 total revisions
812 2 integrity errors encountered!
810 2 integrity errors encountered!
813 (first damaged changeset appears to be 0)
811 (first damaged changeset appears to be 0)
814 [1]
812 [1]
815
813
816 $ cat $TESTTMP/dummy-remote2/22/f66a3fc0b9bf3f012c814303995ec07099b3a9ce02a7af84b5970811074a3b | $TESTDIR/f --sha256
814 $ cat $TESTTMP/dummy-remote2/22/f66a3fc0b9bf3f012c814303995ec07099b3a9ce02a7af84b5970811074a3b | $TESTDIR/f --sha256
817 sha256=22f66a3fc0b9bf3f012c814303995ec07099b3a9ce02a7af84b5970811074a3b
815 sha256=22f66a3fc0b9bf3f012c814303995ec07099b3a9ce02a7af84b5970811074a3b
818 $ cat fromcorrupt2/.hg/store/lfs/objects/22/f66a3fc0b9bf3f012c814303995ec07099b3a9ce02a7af84b5970811074a3b | $TESTDIR/f --sha256
816 $ cat fromcorrupt2/.hg/store/lfs/objects/22/f66a3fc0b9bf3f012c814303995ec07099b3a9ce02a7af84b5970811074a3b | $TESTDIR/f --sha256
819 sha256=22f66a3fc0b9bf3f012c814303995ec07099b3a9ce02a7af84b5970811074a3b
817 sha256=22f66a3fc0b9bf3f012c814303995ec07099b3a9ce02a7af84b5970811074a3b
820 $ test -f $TESTTMP/dummy-remote2/66/100b384bf761271b407d79fc30cdd0554f3b2c5d944836e936d584b88ce88e
818 $ test -f $TESTTMP/dummy-remote2/66/100b384bf761271b407d79fc30cdd0554f3b2c5d944836e936d584b88ce88e
821 [1]
819 [1]
822
820
823 Accessing a corrupt file will complain
821 Accessing a corrupt file will complain
824
822
825 $ hg --cwd fromcorrupt2 cat -r 0 large
823 $ hg --cwd fromcorrupt2 cat -r 0 large
826 abort: integrity check failed on data/large.i:0!
824 abort: integrity check failed on data/large.i:0!
827 [255]
825 [255]
828
826
829 lfs -> normal -> lfs round trip conversions are possible. The 'none()'
827 lfs -> normal -> lfs round trip conversions are possible. The 'none()'
830 predicate on the command line will override whatever is configured globally and
828 predicate on the command line will override whatever is configured globally and
831 locally, and ensures everything converts to a regular file. For lfs -> normal,
829 locally, and ensures everything converts to a regular file. For lfs -> normal,
832 there's no 'lfs' destination repo requirement. For normal -> lfs, there is.
830 there's no 'lfs' destination repo requirement. For normal -> lfs, there is.
833
831
834 $ hg --config extensions.convert= --config 'lfs.track=none()' \
832 $ hg --config extensions.convert= --config 'lfs.track=none()' \
835 > convert repo8 convert_normal
833 > convert repo8 convert_normal
836 initializing destination convert_normal repository
834 initializing destination convert_normal repository
837 scanning source...
835 scanning source...
838 sorting...
836 sorting...
839 converting...
837 converting...
840 2 a
838 2 a
841 1 b
839 1 b
842 0 meta
840 0 meta
843 $ grep 'lfs' convert_normal/.hg/requires
841 $ grep 'lfs' convert_normal/.hg/requires
844 [1]
842 [1]
845 $ hg --cwd convert_normal cat a1 -r 0 -T '{rawdata}'
843 $ hg --cwd convert_normal cat a1 -r 0 -T '{rawdata}'
846 THIS-IS-LFS-BECAUSE-10-BYTES
844 THIS-IS-LFS-BECAUSE-10-BYTES
847
845
848 $ hg --config extensions.convert= --config lfs.threshold=10B \
846 $ hg --config extensions.convert= --config lfs.threshold=10B \
849 > convert convert_normal convert_lfs
847 > convert convert_normal convert_lfs
850 initializing destination convert_lfs repository
848 initializing destination convert_lfs repository
851 scanning source...
849 scanning source...
852 sorting...
850 sorting...
853 converting...
851 converting...
854 2 a
852 2 a
855 1 b
853 1 b
856 0 meta
854 0 meta
857
855
858 $ hg --cwd convert_lfs cat -r 0 a1 -T '{rawdata}'
856 $ hg --cwd convert_lfs cat -r 0 a1 -T '{rawdata}'
859 version https://git-lfs.github.com/spec/v1
857 version https://git-lfs.github.com/spec/v1
860 oid sha256:5bb8341bee63b3649f222b2215bde37322bea075a30575aa685d8f8d21c77024
858 oid sha256:5bb8341bee63b3649f222b2215bde37322bea075a30575aa685d8f8d21c77024
861 size 29
859 size 29
862 x-is-binary 0
860 x-is-binary 0
863 $ hg --cwd convert_lfs debugdata a1 0
861 $ hg --cwd convert_lfs debugdata a1 0
864 version https://git-lfs.github.com/spec/v1
862 version https://git-lfs.github.com/spec/v1
865 oid sha256:5bb8341bee63b3649f222b2215bde37322bea075a30575aa685d8f8d21c77024
863 oid sha256:5bb8341bee63b3649f222b2215bde37322bea075a30575aa685d8f8d21c77024
866 size 29
864 size 29
867 x-is-binary 0
865 x-is-binary 0
868 $ hg --cwd convert_lfs log -r 0 -T "{lfs_files % '{lfspointer % '{key}={value}\n'}'}"
866 $ hg --cwd convert_lfs log -r 0 -T "{lfs_files % '{lfspointer % '{key}={value}\n'}'}"
869 version=https://git-lfs.github.com/spec/v1
867 version=https://git-lfs.github.com/spec/v1
870 oid=sha256:5bb8341bee63b3649f222b2215bde37322bea075a30575aa685d8f8d21c77024
868 oid=sha256:5bb8341bee63b3649f222b2215bde37322bea075a30575aa685d8f8d21c77024
871 size=29
869 size=29
872 x-is-binary=0
870 x-is-binary=0
873 $ hg --cwd convert_lfs log -r 0 \
871 $ hg --cwd convert_lfs log -r 0 \
874 > -T '{lfs_files % "{get(lfspointer, "oid")}\n"}{lfs_files % "{lfspointer.oid}\n"}'
872 > -T '{lfs_files % "{get(lfspointer, "oid")}\n"}{lfs_files % "{lfspointer.oid}\n"}'
875 sha256:5bb8341bee63b3649f222b2215bde37322bea075a30575aa685d8f8d21c77024
873 sha256:5bb8341bee63b3649f222b2215bde37322bea075a30575aa685d8f8d21c77024
876 sha256:5bb8341bee63b3649f222b2215bde37322bea075a30575aa685d8f8d21c77024
874 sha256:5bb8341bee63b3649f222b2215bde37322bea075a30575aa685d8f8d21c77024
877 $ hg --cwd convert_lfs log -r 0 -T '{lfs_files % "{lfspointer}\n"}'
875 $ hg --cwd convert_lfs log -r 0 -T '{lfs_files % "{lfspointer}\n"}'
878 version=https://git-lfs.github.com/spec/v1 oid=sha256:5bb8341bee63b3649f222b2215bde37322bea075a30575aa685d8f8d21c77024 size=29 x-is-binary=0
876 version=https://git-lfs.github.com/spec/v1 oid=sha256:5bb8341bee63b3649f222b2215bde37322bea075a30575aa685d8f8d21c77024 size=29 x-is-binary=0
879 $ hg --cwd convert_lfs \
877 $ hg --cwd convert_lfs \
880 > log -r 'all()' -T '{rev}: {lfs_files % "{file}: {lfsoid}\n"}'
878 > log -r 'all()' -T '{rev}: {lfs_files % "{file}: {lfsoid}\n"}'
881 0: a1: 5bb8341bee63b3649f222b2215bde37322bea075a30575aa685d8f8d21c77024
879 0: a1: 5bb8341bee63b3649f222b2215bde37322bea075a30575aa685d8f8d21c77024
882 1: a2: 5bb8341bee63b3649f222b2215bde37322bea075a30575aa685d8f8d21c77024
880 1: a2: 5bb8341bee63b3649f222b2215bde37322bea075a30575aa685d8f8d21c77024
883 2: a2: 876dadc86a8542f9798048f2c47f51dbf8e4359aed883e8ec80c5db825f0d943
881 2: a2: 876dadc86a8542f9798048f2c47f51dbf8e4359aed883e8ec80c5db825f0d943
884
882
885 $ grep 'lfs' convert_lfs/.hg/requires
883 $ grep 'lfs' convert_lfs/.hg/requires
886 lfs
884 lfs
887
885
888 The hashes in all stages of the conversion are unchanged.
886 The hashes in all stages of the conversion are unchanged.
889
887
890 $ hg -R repo8 log -T '{node|short}\n'
888 $ hg -R repo8 log -T '{node|short}\n'
891 0fae949de7fa
889 0fae949de7fa
892 9cd6bdffdac0
890 9cd6bdffdac0
893 7f96794915f7
891 7f96794915f7
894 $ hg -R convert_normal log -T '{node|short}\n'
892 $ hg -R convert_normal log -T '{node|short}\n'
895 0fae949de7fa
893 0fae949de7fa
896 9cd6bdffdac0
894 9cd6bdffdac0
897 7f96794915f7
895 7f96794915f7
898 $ hg -R convert_lfs log -T '{node|short}\n'
896 $ hg -R convert_lfs log -T '{node|short}\n'
899 0fae949de7fa
897 0fae949de7fa
900 9cd6bdffdac0
898 9cd6bdffdac0
901 7f96794915f7
899 7f96794915f7
902
900
903 This convert is trickier, because it contains deleted files (via `hg mv`)
901 This convert is trickier, because it contains deleted files (via `hg mv`)
904
902
905 $ hg --config extensions.convert= --config lfs.threshold=1000M \
903 $ hg --config extensions.convert= --config lfs.threshold=1000M \
906 > convert repo3 convert_normal2
904 > convert repo3 convert_normal2
907 initializing destination convert_normal2 repository
905 initializing destination convert_normal2 repository
908 scanning source...
906 scanning source...
909 sorting...
907 sorting...
910 converting...
908 converting...
911 4 commit with lfs content
909 4 commit with lfs content
912 3 renames
910 3 renames
913 2 large to small, small to large
911 2 large to small, small to large
914 1 random modifications
912 1 random modifications
915 0 switch large and small again
913 0 switch large and small again
916 $ grep 'lfs' convert_normal2/.hg/requires
914 $ grep 'lfs' convert_normal2/.hg/requires
917 [1]
915 [1]
918 $ hg --cwd convert_normal2 debugdata large 0
916 $ hg --cwd convert_normal2 debugdata large 0
919 LONGER-THAN-TEN-BYTES-WILL-TRIGGER-LFS
917 LONGER-THAN-TEN-BYTES-WILL-TRIGGER-LFS
920
918
921 $ hg --config extensions.convert= --config lfs.threshold=10B \
919 $ hg --config extensions.convert= --config lfs.threshold=10B \
922 > convert convert_normal2 convert_lfs2
920 > convert convert_normal2 convert_lfs2
923 initializing destination convert_lfs2 repository
921 initializing destination convert_lfs2 repository
924 scanning source...
922 scanning source...
925 sorting...
923 sorting...
926 converting...
924 converting...
927 4 commit with lfs content
925 4 commit with lfs content
928 3 renames
926 3 renames
929 2 large to small, small to large
927 2 large to small, small to large
930 1 random modifications
928 1 random modifications
931 0 switch large and small again
929 0 switch large and small again
932 $ grep 'lfs' convert_lfs2/.hg/requires
930 $ grep 'lfs' convert_lfs2/.hg/requires
933 lfs
931 lfs
934 $ hg --cwd convert_lfs2 debugdata large 0
932 $ hg --cwd convert_lfs2 debugdata large 0
935 version https://git-lfs.github.com/spec/v1
933 version https://git-lfs.github.com/spec/v1
936 oid sha256:66100b384bf761271b407d79fc30cdd0554f3b2c5d944836e936d584b88ce88e
934 oid sha256:66100b384bf761271b407d79fc30cdd0554f3b2c5d944836e936d584b88ce88e
937 size 39
935 size 39
938 x-is-binary 0
936 x-is-binary 0
939
937
940 $ hg -R convert_lfs2 config --debug extensions | grep lfs
938 $ hg -R convert_lfs2 config --debug extensions | grep lfs
941 $TESTTMP/convert_lfs2/.hg/hgrc:*: extensions.lfs= (glob)
939 $TESTTMP/convert_lfs2/.hg/hgrc:*: extensions.lfs= (glob)
942
940
943 Committing deleted files works:
941 Committing deleted files works:
944
942
945 $ hg init $TESTTMP/repo-del
943 $ hg init $TESTTMP/repo-del
946 $ cd $TESTTMP/repo-del
944 $ cd $TESTTMP/repo-del
947 $ echo 1 > A
945 $ echo 1 > A
948 $ hg commit -m 'add A' -A A
946 $ hg commit -m 'add A' -A A
949 $ hg rm A
947 $ hg rm A
950 $ hg commit -m 'rm A'
948 $ hg commit -m 'rm A'
951
949
952 Bad .hglfs files will block the commit with a useful message
950 Bad .hglfs files will block the commit with a useful message
953
951
954 $ cat > .hglfs << EOF
952 $ cat > .hglfs << EOF
955 > [track]
953 > [track]
956 > **.test = size(">5B")
954 > **.test = size(">5B")
957 > bad file ... no commit
955 > bad file ... no commit
958 > EOF
956 > EOF
959
957
960 $ echo x > file.txt
958 $ echo x > file.txt
961 $ hg ci -Aqm 'should fail'
959 $ hg ci -Aqm 'should fail'
962 hg: parse error at .hglfs:3: bad file ... no commit
960 hg: parse error at .hglfs:3: bad file ... no commit
963 [255]
961 [255]
964
962
965 $ cat > .hglfs << EOF
963 $ cat > .hglfs << EOF
966 > [track]
964 > [track]
967 > **.test = size(">5B")
965 > **.test = size(">5B")
968 > ** = nonexistent()
966 > ** = nonexistent()
969 > EOF
967 > EOF
970
968
971 $ hg ci -Aqm 'should fail'
969 $ hg ci -Aqm 'should fail'
972 abort: parse error in .hglfs: unknown identifier: nonexistent
970 abort: parse error in .hglfs: unknown identifier: nonexistent
973 [255]
971 [255]
974
972
975 '**' works out to mean all files.
973 '**' works out to mean all files.
976
974
977 $ cat > .hglfs << EOF
975 $ cat > .hglfs << EOF
978 > [track]
976 > [track]
977 > path:.hglfs = none()
979 > **.test = size(">5B")
978 > **.test = size(">5B")
980 > **.exclude = none()
979 > **.exclude = none()
981 > ** = size(">10B")
980 > ** = size(">10B")
982 > EOF
981 > EOF
983
982
984 The LFS policy takes effect as the .hglfs file is committed
983 The LFS policy takes effect as the .hglfs file is committed
985
984
986 $ echo 'largefile' > lfs.test
985 $ echo 'largefile' > lfs.test
987 $ echo '012345678901234567890' > nolfs.exclude
986 $ echo '012345678901234567890' > nolfs.exclude
988 $ echo '01234567890123456' > lfs.catchall
987 $ echo '01234567890123456' > lfs.catchall
989 $ hg ci -Aqm 'added .hglfs'
988 $ hg ci -Aqm 'added .hglfs'
990 $ hg log -r . -T '{rev}: {lfs_files % "{file}: {lfsoid}\n"}\n'
989 $ hg log -r . -T '{rev}: {lfs_files % "{file}: {lfsoid}\n"}\n'
991 2: lfs.catchall: d4ec46c2869ba22eceb42a729377432052d9dd75d82fc40390ebaadecee87ee9
990 2: lfs.catchall: d4ec46c2869ba22eceb42a729377432052d9dd75d82fc40390ebaadecee87ee9
992 lfs.test: 5489e6ced8c36a7b267292bde9fd5242a5f80a7482e8f23fa0477393dfaa4d6c
991 lfs.test: 5489e6ced8c36a7b267292bde9fd5242a5f80a7482e8f23fa0477393dfaa4d6c
993
992
994 The existing .hglfs file is used even when it is not in the 'A' or 'M' states
993 The existing .hglfs file is used even when it is not in the 'A' or 'M' states
995
994
996 $ echo 'largefile2' > lfs.test
995 $ echo 'largefile2' > lfs.test
997 $ echo '012345678901234567890a' > nolfs.exclude
996 $ echo '012345678901234567890a' > nolfs.exclude
998 $ echo '01234567890123456a' > lfs.catchall
997 $ echo '01234567890123456a' > lfs.catchall
999 $ hg ci -qm 'unmodified .hglfs'
998 $ hg ci -qm 'unmodified .hglfs'
1000 $ hg log -r . -T '{rev}: {lfs_files % "{file}: {lfsoid}\n"}\n'
999 $ hg log -r . -T '{rev}: {lfs_files % "{file}: {lfsoid}\n"}\n'
1001 3: lfs.catchall: 31f43b9c62b540126b0ad5884dc013d21a61c9329b77de1fceeae2fc58511573
1000 3: lfs.catchall: 31f43b9c62b540126b0ad5884dc013d21a61c9329b77de1fceeae2fc58511573
1002 lfs.test: 8acd23467967bc7b8cc5a280056589b0ba0b17ff21dbd88a7b6474d6290378a6
1001 lfs.test: 8acd23467967bc7b8cc5a280056589b0ba0b17ff21dbd88a7b6474d6290378a6
1003
1002
1004 Excluding the .hglfs file from the commit postpones the policy change
1003 Excluding the .hglfs file from the commit postpones the policy change
1005
1004
1006 $ hg rm .hglfs
1005 $ hg rm .hglfs
1007 $ echo 'largefile3' > lfs.test
1006 $ echo 'largefile3' > lfs.test
1008 $ echo '012345678901234567890abc' > nolfs.exclude
1007 $ echo '012345678901234567890abc' > nolfs.exclude
1009 $ echo '01234567890123456abc' > lfs.catchall
1008 $ echo '01234567890123456abc' > lfs.catchall
1010 $ hg ci -qm 'file test' -X .hglfs
1009 $ hg ci -qm 'file test' -X .hglfs
1011 $ hg log -r . -T '{rev}: {lfs_files % "{file}: {lfsoid}\n"}\n'
1010 $ hg log -r . -T '{rev}: {lfs_files % "{file}: {lfsoid}\n"}\n'
1012 4: lfs.catchall: 6747cfb1b83965b4a884e7a6061813ae31e4122028bc6a88d2ac5e5f9e05c5af
1011 4: lfs.catchall: 6747cfb1b83965b4a884e7a6061813ae31e4122028bc6a88d2ac5e5f9e05c5af
1013 lfs.test: 3f40b70c2294e91e0fa789ebcf73c5a1d1c7aef270f83e477e40cb0513237e8c
1012 lfs.test: 3f40b70c2294e91e0fa789ebcf73c5a1d1c7aef270f83e477e40cb0513237e8c
1014
1013
1015 The policy change takes effect when the .hglfs is committed
1014 The policy change takes effect when the .hglfs is committed
1016
1015
1017 $ echo 'largefile4' > lfs.test
1016 $ echo 'largefile4' > lfs.test
1018 $ echo '012345678901234567890abcdef' > nolfs.exclude
1017 $ echo '012345678901234567890abcdef' > nolfs.exclude
1019 $ echo '01234567890123456abcdef' > lfs.catchall
1018 $ echo '01234567890123456abcdef' > lfs.catchall
1020 $ hg ci -qm 'file test'
1019 $ hg ci -qm 'file test'
1021 $ hg log -r . -T '{rev}: {lfs_files % "{file}: {lfsoid}\n"}\n'
1020 $ hg log -r . -T '{rev}: {lfs_files % "{file}: {lfsoid}\n"}\n'
1022 5:
1021 5:
1023
1022
1024 $ cd ..
1023 $ cd ..
1025
1024
1026 Unbundling adds a requirement to a non-lfs repo, if necessary.
1025 Unbundling adds a requirement to a non-lfs repo, if necessary.
1027
1026
1028 $ hg bundle -R $TESTTMP/repo-del -qr 0 --base null nolfs.hg
1027 $ hg bundle -R $TESTTMP/repo-del -qr 0 --base null nolfs.hg
1029 $ hg bundle -R convert_lfs2 -qr tip --base null lfs.hg
1028 $ hg bundle -R convert_lfs2 -qr tip --base null lfs.hg
1030 $ hg init unbundle
1029 $ hg init unbundle
1031 $ hg pull -R unbundle -q nolfs.hg
1030 $ hg pull -R unbundle -q nolfs.hg
1032 $ grep lfs unbundle/.hg/requires
1031 $ grep lfs unbundle/.hg/requires
1033 [1]
1032 [1]
1034 $ hg pull -R unbundle -q lfs.hg
1033 $ hg pull -R unbundle -q lfs.hg
1035 $ grep lfs unbundle/.hg/requires
1034 $ grep lfs unbundle/.hg/requires
1036 lfs
1035 lfs
1037
1036
1038 $ hg init no_lfs
1037 $ hg init no_lfs
1039 $ cat >> no_lfs/.hg/hgrc <<EOF
1038 $ cat >> no_lfs/.hg/hgrc <<EOF
1040 > [experimental]
1039 > [experimental]
1041 > changegroup3 = True
1040 > changegroup3 = True
1042 > [extensions]
1041 > [extensions]
1043 > lfs=!
1042 > lfs=!
1044 > EOF
1043 > EOF
1045 $ cp -R no_lfs no_lfs2
1044 $ cp -R no_lfs no_lfs2
1046
1045
1047 Pushing from a local lfs repo to a local repo without an lfs requirement and
1046 Pushing from a local lfs repo to a local repo without an lfs requirement and
1048 with lfs disabled, fails.
1047 with lfs disabled, fails.
1049
1048
1050 $ hg push -R convert_lfs2 no_lfs
1049 $ hg push -R convert_lfs2 no_lfs
1051 pushing to no_lfs
1050 pushing to no_lfs
1052 abort: required features are not supported in the destination: lfs
1051 abort: required features are not supported in the destination: lfs
1053 [255]
1052 [255]
1054 $ grep lfs no_lfs/.hg/requires
1053 $ grep lfs no_lfs/.hg/requires
1055 [1]
1054 [1]
1056
1055
1057 Pulling from a local lfs repo to a local repo without an lfs requirement and
1056 Pulling from a local lfs repo to a local repo without an lfs requirement and
1058 with lfs disabled, fails.
1057 with lfs disabled, fails.
1059
1058
1060 $ hg pull -R no_lfs2 convert_lfs2
1059 $ hg pull -R no_lfs2 convert_lfs2
1061 pulling from convert_lfs2
1060 pulling from convert_lfs2
1062 abort: required features are not supported in the destination: lfs
1061 abort: required features are not supported in the destination: lfs
1063 [255]
1062 [255]
1064 $ grep lfs no_lfs2/.hg/requires
1063 $ grep lfs no_lfs2/.hg/requires
1065 [1]
1064 [1]
General Comments 0
You need to be logged in to leave comments. Login now