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