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