##// END OF EJS Templates
lfs: enable the extension locally after converting to an 'lfs' repo...
Matt Harbison -
r35216:8887a45e default
parent child Browse files
Show More
@@ -1,300 +1,304
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 . import (
22 from . import (
23 blobstore,
23 blobstore,
24 pointer,
24 pointer,
25 )
25 )
26
26
27 def supportedoutgoingversions(orig, repo):
27 def supportedoutgoingversions(orig, repo):
28 versions = orig(repo)
28 versions = orig(repo)
29 versions.discard('01')
29 versions.discard('01')
30 versions.discard('02')
30 versions.discard('02')
31 versions.add('03')
31 versions.add('03')
32 return versions
32 return versions
33
33
34 def allsupportedversions(orig, ui):
34 def allsupportedversions(orig, ui):
35 versions = orig(ui)
35 versions = orig(ui)
36 versions.add('03')
36 versions.add('03')
37 return versions
37 return versions
38
38
39 def bypasscheckhash(self, text):
39 def bypasscheckhash(self, text):
40 return False
40 return False
41
41
42 def readfromstore(self, text):
42 def readfromstore(self, text):
43 """Read filelog content from local blobstore transform for flagprocessor.
43 """Read filelog content from local blobstore transform for flagprocessor.
44
44
45 Default tranform for flagprocessor, returning contents from blobstore.
45 Default tranform for flagprocessor, returning contents from blobstore.
46 Returns a 2-typle (text, validatehash) where validatehash is True as the
46 Returns a 2-typle (text, validatehash) where validatehash is True as the
47 contents of the blobstore should be checked using checkhash.
47 contents of the blobstore should be checked using checkhash.
48 """
48 """
49 p = pointer.deserialize(text)
49 p = pointer.deserialize(text)
50 oid = p.oid()
50 oid = p.oid()
51 store = self.opener.lfslocalblobstore
51 store = self.opener.lfslocalblobstore
52 if not store.has(oid):
52 if not store.has(oid):
53 p.filename = getattr(self, 'indexfile', None)
53 p.filename = getattr(self, 'indexfile', None)
54 self.opener.lfsremoteblobstore.readbatch([p], store)
54 self.opener.lfsremoteblobstore.readbatch([p], store)
55 text = store.read(oid)
55 text = store.read(oid)
56
56
57 # pack hg filelog metadata
57 # pack hg filelog metadata
58 hgmeta = {}
58 hgmeta = {}
59 for k in p.keys():
59 for k in p.keys():
60 if k.startswith('x-hg-'):
60 if k.startswith('x-hg-'):
61 name = k[len('x-hg-'):]
61 name = k[len('x-hg-'):]
62 hgmeta[name] = p[k]
62 hgmeta[name] = p[k]
63 if hgmeta or text.startswith('\1\n'):
63 if hgmeta or text.startswith('\1\n'):
64 text = filelog.packmeta(hgmeta, text)
64 text = filelog.packmeta(hgmeta, text)
65
65
66 return (text, True)
66 return (text, True)
67
67
68 def writetostore(self, text):
68 def writetostore(self, text):
69 # hg filelog metadata (includes rename, etc)
69 # hg filelog metadata (includes rename, etc)
70 hgmeta, offset = filelog.parsemeta(text)
70 hgmeta, offset = filelog.parsemeta(text)
71 if offset and offset > 0:
71 if offset and offset > 0:
72 # lfs blob does not contain hg filelog metadata
72 # lfs blob does not contain hg filelog metadata
73 text = text[offset:]
73 text = text[offset:]
74
74
75 # git-lfs only supports sha256
75 # git-lfs only supports sha256
76 oid = hashlib.sha256(text).hexdigest()
76 oid = hashlib.sha256(text).hexdigest()
77 self.opener.lfslocalblobstore.write(oid, text)
77 self.opener.lfslocalblobstore.write(oid, text)
78
78
79 # replace contents with metadata
79 # replace contents with metadata
80 longoid = 'sha256:%s' % oid
80 longoid = 'sha256:%s' % oid
81 metadata = pointer.gitlfspointer(oid=longoid, size=str(len(text)))
81 metadata = pointer.gitlfspointer(oid=longoid, size=str(len(text)))
82
82
83 # by default, we expect the content to be binary. however, LFS could also
83 # by default, we expect the content to be binary. however, LFS could also
84 # be used for non-binary content. add a special entry for non-binary data.
84 # be used for non-binary content. add a special entry for non-binary data.
85 # this will be used by filectx.isbinary().
85 # this will be used by filectx.isbinary().
86 if not util.binary(text):
86 if not util.binary(text):
87 # not hg filelog metadata (affecting commit hash), no "x-hg-" prefix
87 # not hg filelog metadata (affecting commit hash), no "x-hg-" prefix
88 metadata['x-is-binary'] = '0'
88 metadata['x-is-binary'] = '0'
89
89
90 # translate hg filelog metadata to lfs metadata with "x-hg-" prefix
90 # translate hg filelog metadata to lfs metadata with "x-hg-" prefix
91 if hgmeta is not None:
91 if hgmeta is not None:
92 for k, v in hgmeta.iteritems():
92 for k, v in hgmeta.iteritems():
93 metadata['x-hg-%s' % k] = v
93 metadata['x-hg-%s' % k] = v
94
94
95 rawtext = metadata.serialize()
95 rawtext = metadata.serialize()
96 return (rawtext, False)
96 return (rawtext, False)
97
97
98 def _islfs(rlog, node=None, rev=None):
98 def _islfs(rlog, node=None, rev=None):
99 if rev is None:
99 if rev is None:
100 if node is None:
100 if node is None:
101 # both None - likely working copy content where node is not ready
101 # both None - likely working copy content where node is not ready
102 return False
102 return False
103 rev = rlog.rev(node)
103 rev = rlog.rev(node)
104 else:
104 else:
105 node = rlog.node(rev)
105 node = rlog.node(rev)
106 if node == nullid:
106 if node == nullid:
107 return False
107 return False
108 flags = rlog.flags(rev)
108 flags = rlog.flags(rev)
109 return bool(flags & revlog.REVIDX_EXTSTORED)
109 return bool(flags & revlog.REVIDX_EXTSTORED)
110
110
111 def filelogaddrevision(orig, self, text, transaction, link, p1, p2,
111 def filelogaddrevision(orig, self, text, transaction, link, p1, p2,
112 cachedelta=None, node=None,
112 cachedelta=None, node=None,
113 flags=revlog.REVIDX_DEFAULT_FLAGS, **kwds):
113 flags=revlog.REVIDX_DEFAULT_FLAGS, **kwds):
114 threshold = self.opener.options['lfsthreshold']
114 threshold = self.opener.options['lfsthreshold']
115 textlen = len(text)
115 textlen = len(text)
116 # exclude hg rename meta from file size
116 # exclude hg rename meta from file size
117 meta, offset = filelog.parsemeta(text)
117 meta, offset = filelog.parsemeta(text)
118 if offset:
118 if offset:
119 textlen -= offset
119 textlen -= offset
120
120
121 if threshold and textlen > threshold:
121 if threshold and textlen > threshold:
122 flags |= revlog.REVIDX_EXTSTORED
122 flags |= revlog.REVIDX_EXTSTORED
123
123
124 return orig(self, text, transaction, link, p1, p2, cachedelta=cachedelta,
124 return orig(self, text, transaction, link, p1, p2, cachedelta=cachedelta,
125 node=node, flags=flags, **kwds)
125 node=node, flags=flags, **kwds)
126
126
127 def filelogrenamed(orig, self, node):
127 def filelogrenamed(orig, self, node):
128 if _islfs(self, node):
128 if _islfs(self, node):
129 rawtext = self.revision(node, raw=True)
129 rawtext = self.revision(node, raw=True)
130 if not rawtext:
130 if not rawtext:
131 return False
131 return False
132 metadata = pointer.deserialize(rawtext)
132 metadata = pointer.deserialize(rawtext)
133 if 'x-hg-copy' in metadata and 'x-hg-copyrev' in metadata:
133 if 'x-hg-copy' in metadata and 'x-hg-copyrev' in metadata:
134 return metadata['x-hg-copy'], bin(metadata['x-hg-copyrev'])
134 return metadata['x-hg-copy'], bin(metadata['x-hg-copyrev'])
135 else:
135 else:
136 return False
136 return False
137 return orig(self, node)
137 return orig(self, node)
138
138
139 def filelogsize(orig, self, rev):
139 def filelogsize(orig, self, rev):
140 if _islfs(self, rev=rev):
140 if _islfs(self, rev=rev):
141 # fast path: use lfs metadata to answer size
141 # fast path: use lfs metadata to answer size
142 rawtext = self.revision(rev, raw=True)
142 rawtext = self.revision(rev, raw=True)
143 metadata = pointer.deserialize(rawtext)
143 metadata = pointer.deserialize(rawtext)
144 return int(metadata['size'])
144 return int(metadata['size'])
145 return orig(self, rev)
145 return orig(self, rev)
146
146
147 def filectxcmp(orig, self, fctx):
147 def filectxcmp(orig, self, fctx):
148 """returns True if text is different than fctx"""
148 """returns True if text is different than fctx"""
149 # some fctx (ex. hg-git) is not based on basefilectx and do not have islfs
149 # some fctx (ex. hg-git) is not based on basefilectx and do not have islfs
150 if self.islfs() and getattr(fctx, 'islfs', lambda: False)():
150 if self.islfs() and getattr(fctx, 'islfs', lambda: False)():
151 # fast path: check LFS oid
151 # fast path: check LFS oid
152 p1 = pointer.deserialize(self.rawdata())
152 p1 = pointer.deserialize(self.rawdata())
153 p2 = pointer.deserialize(fctx.rawdata())
153 p2 = pointer.deserialize(fctx.rawdata())
154 return p1.oid() != p2.oid()
154 return p1.oid() != p2.oid()
155 return orig(self, fctx)
155 return orig(self, fctx)
156
156
157 def filectxisbinary(orig, self):
157 def filectxisbinary(orig, self):
158 if self.islfs():
158 if self.islfs():
159 # fast path: use lfs metadata to answer isbinary
159 # fast path: use lfs metadata to answer isbinary
160 metadata = pointer.deserialize(self.rawdata())
160 metadata = pointer.deserialize(self.rawdata())
161 # if lfs metadata says nothing, assume it's binary by default
161 # if lfs metadata says nothing, assume it's binary by default
162 return bool(int(metadata.get('x-is-binary', 1)))
162 return bool(int(metadata.get('x-is-binary', 1)))
163 return orig(self)
163 return orig(self)
164
164
165 def filectxislfs(self):
165 def filectxislfs(self):
166 return _islfs(self.filelog(), self.filenode())
166 return _islfs(self.filelog(), self.filenode())
167
167
168 def convertsink(orig, sink):
168 def convertsink(orig, sink):
169 sink = orig(sink)
169 sink = orig(sink)
170 if sink.repotype == 'hg':
170 if sink.repotype == 'hg':
171 class lfssink(sink.__class__):
171 class lfssink(sink.__class__):
172 def putcommit(self, files, copies, parents, commit, source, revmap,
172 def putcommit(self, files, copies, parents, commit, source, revmap,
173 full, cleanp2):
173 full, cleanp2):
174 pc = super(lfssink, self).putcommit
174 pc = super(lfssink, self).putcommit
175 node = pc(files, copies, parents, commit, source, revmap, full,
175 node = pc(files, copies, parents, commit, source, revmap, full,
176 cleanp2)
176 cleanp2)
177
177
178 if 'lfs' not in self.repo.requirements:
178 if 'lfs' not in self.repo.requirements:
179 ctx = self.repo[node]
179 ctx = self.repo[node]
180
180
181 # The file list may contain removed files, so check for
181 # The file list may contain removed files, so check for
182 # membership before assuming it is in the context.
182 # membership before assuming it is in the context.
183 if any(f in ctx and ctx[f].islfs() for f, n in files):
183 if any(f in ctx and ctx[f].islfs() for f, n in files):
184 self.repo.requirements.add('lfs')
184 self.repo.requirements.add('lfs')
185 self.repo._writerequirements()
185 self.repo._writerequirements()
186
186
187 # Permanently enable lfs locally
188 with self.repo.vfs('hgrc', 'a', text=True) as fp:
189 fp.write('\n[extensions]\nlfs=\n')
190
187 return node
191 return node
188
192
189 sink.__class__ = lfssink
193 sink.__class__ = lfssink
190
194
191 return sink
195 return sink
192
196
193 def vfsinit(orig, self, othervfs):
197 def vfsinit(orig, self, othervfs):
194 orig(self, othervfs)
198 orig(self, othervfs)
195 # copy lfs related options
199 # copy lfs related options
196 for k, v in othervfs.options.items():
200 for k, v in othervfs.options.items():
197 if k.startswith('lfs'):
201 if k.startswith('lfs'):
198 self.options[k] = v
202 self.options[k] = v
199 # also copy lfs blobstores. note: this can run before reposetup, so lfs
203 # also copy lfs blobstores. note: this can run before reposetup, so lfs
200 # blobstore attributes are not always ready at this time.
204 # blobstore attributes are not always ready at this time.
201 for name in ['lfslocalblobstore', 'lfsremoteblobstore']:
205 for name in ['lfslocalblobstore', 'lfsremoteblobstore']:
202 if util.safehasattr(othervfs, name):
206 if util.safehasattr(othervfs, name):
203 setattr(self, name, getattr(othervfs, name))
207 setattr(self, name, getattr(othervfs, name))
204
208
205 def hgclone(orig, ui, opts, *args, **kwargs):
209 def hgclone(orig, ui, opts, *args, **kwargs):
206 result = orig(ui, opts, *args, **kwargs)
210 result = orig(ui, opts, *args, **kwargs)
207
211
208 if result is not None:
212 if result is not None:
209 sourcerepo, destrepo = result
213 sourcerepo, destrepo = result
210 repo = destrepo.local()
214 repo = destrepo.local()
211
215
212 # When cloning to a remote repo (like through SSH), no repo is available
216 # When cloning to a remote repo (like through SSH), no repo is available
213 # from the peer. Therefore the hgrc can't be updated.
217 # from the peer. Therefore the hgrc can't be updated.
214 if not repo:
218 if not repo:
215 return result
219 return result
216
220
217 # If lfs is required for this repo, permanently enable it locally
221 # If lfs is required for this repo, permanently enable it locally
218 if 'lfs' in repo.requirements:
222 if 'lfs' in repo.requirements:
219 with repo.vfs('hgrc', 'a', text=True) as fp:
223 with repo.vfs('hgrc', 'a', text=True) as fp:
220 fp.write('\n[extensions]\nlfs=\n')
224 fp.write('\n[extensions]\nlfs=\n')
221
225
222 return result
226 return result
223
227
224 def hgpostshare(orig, sourcerepo, destrepo, bookmarks=True, defaultpath=None):
228 def hgpostshare(orig, sourcerepo, destrepo, bookmarks=True, defaultpath=None):
225 orig(sourcerepo, destrepo, bookmarks, defaultpath)
229 orig(sourcerepo, destrepo, bookmarks, defaultpath)
226
230
227 # If lfs is required for this repo, permanently enable it locally
231 # If lfs is required for this repo, permanently enable it locally
228 if 'lfs' in destrepo.requirements:
232 if 'lfs' in destrepo.requirements:
229 with destrepo.vfs('hgrc', 'a', text=True) as fp:
233 with destrepo.vfs('hgrc', 'a', text=True) as fp:
230 fp.write('\n[extensions]\nlfs=\n')
234 fp.write('\n[extensions]\nlfs=\n')
231
235
232 def _canskipupload(repo):
236 def _canskipupload(repo):
233 # if remotestore is a null store, upload is a no-op and can be skipped
237 # if remotestore is a null store, upload is a no-op and can be skipped
234 return isinstance(repo.svfs.lfsremoteblobstore, blobstore._nullremote)
238 return isinstance(repo.svfs.lfsremoteblobstore, blobstore._nullremote)
235
239
236 def candownload(repo):
240 def candownload(repo):
237 # if remotestore is a null store, downloads will lead to nothing
241 # if remotestore is a null store, downloads will lead to nothing
238 return not isinstance(repo.svfs.lfsremoteblobstore, blobstore._nullremote)
242 return not isinstance(repo.svfs.lfsremoteblobstore, blobstore._nullremote)
239
243
240 def uploadblobsfromrevs(repo, revs):
244 def uploadblobsfromrevs(repo, revs):
241 '''upload lfs blobs introduced by revs
245 '''upload lfs blobs introduced by revs
242
246
243 Note: also used by other extensions e. g. infinitepush. avoid renaming.
247 Note: also used by other extensions e. g. infinitepush. avoid renaming.
244 '''
248 '''
245 if _canskipupload(repo):
249 if _canskipupload(repo):
246 return
250 return
247 pointers = extractpointers(repo, revs)
251 pointers = extractpointers(repo, revs)
248 uploadblobs(repo, pointers)
252 uploadblobs(repo, pointers)
249
253
250 def prepush(pushop):
254 def prepush(pushop):
251 """Prepush hook.
255 """Prepush hook.
252
256
253 Read through the revisions to push, looking for filelog entries that can be
257 Read through the revisions to push, looking for filelog entries that can be
254 deserialized into metadata so that we can block the push on their upload to
258 deserialized into metadata so that we can block the push on their upload to
255 the remote blobstore.
259 the remote blobstore.
256 """
260 """
257 return uploadblobsfromrevs(pushop.repo, pushop.outgoing.missing)
261 return uploadblobsfromrevs(pushop.repo, pushop.outgoing.missing)
258
262
259 def writenewbundle(orig, ui, repo, source, filename, bundletype, outgoing,
263 def writenewbundle(orig, ui, repo, source, filename, bundletype, outgoing,
260 *args, **kwargs):
264 *args, **kwargs):
261 """upload LFS blobs added by outgoing revisions on 'hg bundle'"""
265 """upload LFS blobs added by outgoing revisions on 'hg bundle'"""
262 uploadblobsfromrevs(repo, outgoing.missing)
266 uploadblobsfromrevs(repo, outgoing.missing)
263 return orig(ui, repo, source, filename, bundletype, outgoing, *args,
267 return orig(ui, repo, source, filename, bundletype, outgoing, *args,
264 **kwargs)
268 **kwargs)
265
269
266 def extractpointers(repo, revs):
270 def extractpointers(repo, revs):
267 """return a list of lfs pointers added by given revs"""
271 """return a list of lfs pointers added by given revs"""
268 ui = repo.ui
272 ui = repo.ui
269 if ui.debugflag:
273 if ui.debugflag:
270 ui.write(_('lfs: computing set of blobs to upload\n'))
274 ui.write(_('lfs: computing set of blobs to upload\n'))
271 pointers = {}
275 pointers = {}
272 for r in revs:
276 for r in revs:
273 ctx = repo[r]
277 ctx = repo[r]
274 for p in pointersfromctx(ctx).values():
278 for p in pointersfromctx(ctx).values():
275 pointers[p.oid()] = p
279 pointers[p.oid()] = p
276 return pointers.values()
280 return pointers.values()
277
281
278 def pointersfromctx(ctx):
282 def pointersfromctx(ctx):
279 """return a dict {path: pointer} for given single changectx"""
283 """return a dict {path: pointer} for given single changectx"""
280 result = {}
284 result = {}
281 for f in ctx.files():
285 for f in ctx.files():
282 if f not in ctx:
286 if f not in ctx:
283 continue
287 continue
284 fctx = ctx[f]
288 fctx = ctx[f]
285 if not _islfs(fctx.filelog(), fctx.filenode()):
289 if not _islfs(fctx.filelog(), fctx.filenode()):
286 continue
290 continue
287 try:
291 try:
288 result[f] = pointer.deserialize(fctx.rawdata())
292 result[f] = pointer.deserialize(fctx.rawdata())
289 except pointer.InvalidPointer as ex:
293 except pointer.InvalidPointer as ex:
290 raise error.Abort(_('lfs: corrupted pointer (%s@%s): %s\n')
294 raise error.Abort(_('lfs: corrupted pointer (%s@%s): %s\n')
291 % (f, short(ctx.node()), ex))
295 % (f, short(ctx.node()), ex))
292 return result
296 return result
293
297
294 def uploadblobs(repo, pointers):
298 def uploadblobs(repo, pointers):
295 """upload given pointers from local blobstore"""
299 """upload given pointers from local blobstore"""
296 if not pointers:
300 if not pointers:
297 return
301 return
298
302
299 remoteblob = repo.svfs.lfsremoteblobstore
303 remoteblob = repo.svfs.lfsremoteblobstore
300 remoteblob.writebatch(pointers, repo.svfs.lfslocalblobstore)
304 remoteblob.writebatch(pointers, repo.svfs.lfslocalblobstore)
@@ -1,351 +1,354
1 This tests the interaction between the largefiles and lfs extensions, and
1 This tests the interaction between the largefiles and lfs extensions, and
2 conversion from largefiles -> lfs.
2 conversion from largefiles -> lfs.
3
3
4 $ cat >> $HGRCPATH << EOF
4 $ cat >> $HGRCPATH << EOF
5 > [extensions]
5 > [extensions]
6 > largefiles =
6 > largefiles =
7 >
7 >
8 > [lfs]
8 > [lfs]
9 > # standin files are 41 bytes. Stay bigger for clarity.
9 > # standin files are 41 bytes. Stay bigger for clarity.
10 > threshold = 42
10 > threshold = 42
11 > EOF
11 > EOF
12
12
13 Setup a repo with a normal file and a largefile, above and below the lfs
13 Setup a repo with a normal file and a largefile, above and below the lfs
14 threshold to test lfconvert. *.txt start life as a normal file; *.bin start as
14 threshold to test lfconvert. *.txt start life as a normal file; *.bin start as
15 an lfs/largefile.
15 an lfs/largefile.
16
16
17 $ hg init largefiles
17 $ hg init largefiles
18 $ cd largefiles
18 $ cd largefiles
19 $ echo 'normal' > normal.txt
19 $ echo 'normal' > normal.txt
20 $ echo 'normal above lfs threshold 0000000000000000000000000' > lfs.txt
20 $ echo 'normal above lfs threshold 0000000000000000000000000' > lfs.txt
21 $ hg ci -Am 'normal.txt'
21 $ hg ci -Am 'normal.txt'
22 adding lfs.txt
22 adding lfs.txt
23 adding normal.txt
23 adding normal.txt
24 $ echo 'largefile' > large.bin
24 $ echo 'largefile' > large.bin
25 $ echo 'largefile above lfs threshold 0000000000000000000000' > lfs.bin
25 $ echo 'largefile above lfs threshold 0000000000000000000000' > lfs.bin
26 $ hg add --large large.bin lfs.bin
26 $ hg add --large large.bin lfs.bin
27 $ hg ci -m 'add largefiles'
27 $ hg ci -m 'add largefiles'
28
28
29 $ cat >> $HGRCPATH << EOF
29 $ cat >> $HGRCPATH << EOF
30 > [extensions]
30 > [extensions]
31 > lfs =
31 > lfs =
32 > EOF
32 > EOF
33
33
34 Add an lfs file and normal file that collide with files on the other branch.
34 Add an lfs file and normal file that collide with files on the other branch.
35 large.bin is added as a normal file, and is named as such only to clash with the
35 large.bin is added as a normal file, and is named as such only to clash with the
36 largefile on the other branch.
36 largefile on the other branch.
37
37
38 $ hg up -q '.^'
38 $ hg up -q '.^'
39 $ echo 'below lfs threshold' > large.bin
39 $ echo 'below lfs threshold' > large.bin
40 $ echo 'lfs above the lfs threshold for length 0000000000000' > lfs.bin
40 $ echo 'lfs above the lfs threshold for length 0000000000000' > lfs.bin
41 $ hg ci -Am 'add with lfs extension'
41 $ hg ci -Am 'add with lfs extension'
42 adding large.bin
42 adding large.bin
43 adding lfs.bin
43 adding lfs.bin
44 created new head
44 created new head
45
45
46 $ hg log -G
46 $ hg log -G
47 @ changeset: 2:e989d0fa3764
47 @ changeset: 2:e989d0fa3764
48 | tag: tip
48 | tag: tip
49 | parent: 0:29361292f54d
49 | parent: 0:29361292f54d
50 | user: test
50 | user: test
51 | date: Thu Jan 01 00:00:00 1970 +0000
51 | date: Thu Jan 01 00:00:00 1970 +0000
52 | summary: add with lfs extension
52 | summary: add with lfs extension
53 |
53 |
54 | o changeset: 1:6513aaab9ca0
54 | o changeset: 1:6513aaab9ca0
55 |/ user: test
55 |/ user: test
56 | date: Thu Jan 01 00:00:00 1970 +0000
56 | date: Thu Jan 01 00:00:00 1970 +0000
57 | summary: add largefiles
57 | summary: add largefiles
58 |
58 |
59 o changeset: 0:29361292f54d
59 o changeset: 0:29361292f54d
60 user: test
60 user: test
61 date: Thu Jan 01 00:00:00 1970 +0000
61 date: Thu Jan 01 00:00:00 1970 +0000
62 summary: normal.txt
62 summary: normal.txt
63
63
64 --------------------------------------------------------------------------------
64 --------------------------------------------------------------------------------
65 Merge largefiles into lfs branch
65 Merge largefiles into lfs branch
66
66
67 The largefiles extension will prompt to use the normal or largefile when merged
67 The largefiles extension will prompt to use the normal or largefile when merged
68 into the lfs files. `hg manifest` will show standins if present. They aren't,
68 into the lfs files. `hg manifest` will show standins if present. They aren't,
69 because largefiles merge doesn't merge content. If it did, selecting (n)ormal
69 because largefiles merge doesn't merge content. If it did, selecting (n)ormal
70 would convert to lfs on commit, if appropriate.
70 would convert to lfs on commit, if appropriate.
71
71
72 BUG: Largefiles isn't running the merge tool, like when two lfs files are
72 BUG: Largefiles isn't running the merge tool, like when two lfs files are
73 merged. This is probably by design, but it should probably at least prompt if
73 merged. This is probably by design, but it should probably at least prompt if
74 content should be taken from (l)ocal or (o)ther as well.
74 content should be taken from (l)ocal or (o)ther as well.
75
75
76 $ hg --config ui.interactive=True merge 6513aaab9ca0 <<EOF
76 $ hg --config ui.interactive=True merge 6513aaab9ca0 <<EOF
77 > n
77 > n
78 > n
78 > n
79 > EOF
79 > EOF
80 remote turned local normal file large.bin into a largefile
80 remote turned local normal file large.bin into a largefile
81 use (l)argefile or keep (n)ormal file? n
81 use (l)argefile or keep (n)ormal file? n
82 remote turned local normal file lfs.bin into a largefile
82 remote turned local normal file lfs.bin into a largefile
83 use (l)argefile or keep (n)ormal file? n
83 use (l)argefile or keep (n)ormal file? n
84 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
84 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
85 (branch merge, don't forget to commit)
85 (branch merge, don't forget to commit)
86 $ hg ci -m 'merge lfs with largefiles -> normal'
86 $ hg ci -m 'merge lfs with largefiles -> normal'
87 $ hg manifest
87 $ hg manifest
88 large.bin
88 large.bin
89 lfs.bin
89 lfs.bin
90 lfs.txt
90 lfs.txt
91 normal.txt
91 normal.txt
92
92
93 The merged lfs.bin resolved to lfs because the (n)ormal option was picked. The
93 The merged lfs.bin resolved to lfs because the (n)ormal option was picked. The
94 lfs.txt file is unchanged by the merge, because it was added before lfs was
94 lfs.txt file is unchanged by the merge, because it was added before lfs was
95 enabled, and the content didn't change.
95 enabled, and the content didn't change.
96 $ hg debugdata lfs.bin 0
96 $ hg debugdata lfs.bin 0
97 version https://git-lfs.github.com/spec/v1
97 version https://git-lfs.github.com/spec/v1
98 oid sha256:81c7492b2c05e130431f65a87651b54a30c5da72c99ce35a1e9b9872a807312b
98 oid sha256:81c7492b2c05e130431f65a87651b54a30c5da72c99ce35a1e9b9872a807312b
99 size 53
99 size 53
100 x-is-binary 0
100 x-is-binary 0
101 $ hg debugdata lfs.txt 0
101 $ hg debugdata lfs.txt 0
102 normal above lfs threshold 0000000000000000000000000
102 normal above lfs threshold 0000000000000000000000000
103
103
104 Another filelog entry is NOT made by the merge, so nothing is committed as lfs.
104 Another filelog entry is NOT made by the merge, so nothing is committed as lfs.
105 $ hg log -r . -T '{join(lfs_files, ", ")}\n'
105 $ hg log -r . -T '{join(lfs_files, ", ")}\n'
106
106
107
107
108 Replay the last merge, but pick (l)arge this time. The manifest will show any
108 Replay the last merge, but pick (l)arge this time. The manifest will show any
109 standins.
109 standins.
110
110
111 $ hg up -Cq e989d0fa3764
111 $ hg up -Cq e989d0fa3764
112
112
113 $ hg --config ui.interactive=True merge 6513aaab9ca0 <<EOF
113 $ hg --config ui.interactive=True merge 6513aaab9ca0 <<EOF
114 > l
114 > l
115 > l
115 > l
116 > EOF
116 > EOF
117 remote turned local normal file large.bin into a largefile
117 remote turned local normal file large.bin into a largefile
118 use (l)argefile or keep (n)ormal file? l
118 use (l)argefile or keep (n)ormal file? l
119 remote turned local normal file lfs.bin into a largefile
119 remote turned local normal file lfs.bin into a largefile
120 use (l)argefile or keep (n)ormal file? l
120 use (l)argefile or keep (n)ormal file? l
121 getting changed largefiles
121 getting changed largefiles
122 2 largefiles updated, 0 removed
122 2 largefiles updated, 0 removed
123 2 files updated, 0 files merged, 2 files removed, 0 files unresolved
123 2 files updated, 0 files merged, 2 files removed, 0 files unresolved
124 (branch merge, don't forget to commit)
124 (branch merge, don't forget to commit)
125 $ hg ci -m 'merge lfs with largefiles -> large'
125 $ hg ci -m 'merge lfs with largefiles -> large'
126 created new head
126 created new head
127 $ hg manifest
127 $ hg manifest
128 .hglf/large.bin
128 .hglf/large.bin
129 .hglf/lfs.bin
129 .hglf/lfs.bin
130 lfs.txt
130 lfs.txt
131 normal.txt
131 normal.txt
132
132
133 --------------------------------------------------------------------------------
133 --------------------------------------------------------------------------------
134 Merge lfs into largefiles branch
134 Merge lfs into largefiles branch
135
135
136 $ hg up -Cq 6513aaab9ca0
136 $ hg up -Cq 6513aaab9ca0
137 $ hg --config ui.interactive=True merge e989d0fa3764 <<EOF
137 $ hg --config ui.interactive=True merge e989d0fa3764 <<EOF
138 > n
138 > n
139 > n
139 > n
140 > EOF
140 > EOF
141 remote turned local largefile large.bin into a normal file
141 remote turned local largefile large.bin into a normal file
142 keep (l)argefile or use (n)ormal file? n
142 keep (l)argefile or use (n)ormal file? n
143 remote turned local largefile lfs.bin into a normal file
143 remote turned local largefile lfs.bin into a normal file
144 keep (l)argefile or use (n)ormal file? n
144 keep (l)argefile or use (n)ormal file? n
145 getting changed largefiles
145 getting changed largefiles
146 0 largefiles updated, 0 removed
146 0 largefiles updated, 0 removed
147 2 files updated, 0 files merged, 2 files removed, 0 files unresolved
147 2 files updated, 0 files merged, 2 files removed, 0 files unresolved
148 (branch merge, don't forget to commit)
148 (branch merge, don't forget to commit)
149 $ hg ci -m 'merge largefiles with lfs -> normal'
149 $ hg ci -m 'merge largefiles with lfs -> normal'
150 created new head
150 created new head
151 $ hg manifest
151 $ hg manifest
152 large.bin
152 large.bin
153 lfs.bin
153 lfs.bin
154 lfs.txt
154 lfs.txt
155 normal.txt
155 normal.txt
156
156
157 The merged lfs.bin got converted to lfs because the (n)ormal option was picked.
157 The merged lfs.bin got converted to lfs because the (n)ormal option was picked.
158 The lfs.txt file is unchanged by the merge, because it was added before lfs was
158 The lfs.txt file is unchanged by the merge, because it was added before lfs was
159 enabled.
159 enabled.
160 $ hg debugdata lfs.bin 0
160 $ hg debugdata lfs.bin 0
161 version https://git-lfs.github.com/spec/v1
161 version https://git-lfs.github.com/spec/v1
162 oid sha256:81c7492b2c05e130431f65a87651b54a30c5da72c99ce35a1e9b9872a807312b
162 oid sha256:81c7492b2c05e130431f65a87651b54a30c5da72c99ce35a1e9b9872a807312b
163 size 53
163 size 53
164 x-is-binary 0
164 x-is-binary 0
165 $ hg debugdata lfs.txt 0
165 $ hg debugdata lfs.txt 0
166 normal above lfs threshold 0000000000000000000000000
166 normal above lfs threshold 0000000000000000000000000
167
167
168 Another filelog entry is NOT made by the merge, so nothing is committed as lfs.
168 Another filelog entry is NOT made by the merge, so nothing is committed as lfs.
169 $ hg log -r . -T '{join(lfs_files, ", ")}\n'
169 $ hg log -r . -T '{join(lfs_files, ", ")}\n'
170
170
171
171
172 Replay the last merge, but pick (l)arge this time. The manifest will show the
172 Replay the last merge, but pick (l)arge this time. The manifest will show the
173 standins.
173 standins.
174
174
175 $ hg up -Cq 6513aaab9ca0
175 $ hg up -Cq 6513aaab9ca0
176
176
177 $ hg --config ui.interactive=True merge e989d0fa3764 <<EOF
177 $ hg --config ui.interactive=True merge e989d0fa3764 <<EOF
178 > l
178 > l
179 > l
179 > l
180 > EOF
180 > EOF
181 remote turned local largefile large.bin into a normal file
181 remote turned local largefile large.bin into a normal file
182 keep (l)argefile or use (n)ormal file? l
182 keep (l)argefile or use (n)ormal file? l
183 remote turned local largefile lfs.bin into a normal file
183 remote turned local largefile lfs.bin into a normal file
184 keep (l)argefile or use (n)ormal file? l
184 keep (l)argefile or use (n)ormal file? l
185 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
185 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
186 (branch merge, don't forget to commit)
186 (branch merge, don't forget to commit)
187 $ hg ci -m 'merge largefiles with lfs -> large'
187 $ hg ci -m 'merge largefiles with lfs -> large'
188 created new head
188 created new head
189 $ hg manifest
189 $ hg manifest
190 .hglf/large.bin
190 .hglf/large.bin
191 .hglf/lfs.bin
191 .hglf/lfs.bin
192 lfs.txt
192 lfs.txt
193 normal.txt
193 normal.txt
194
194
195 --------------------------------------------------------------------------------
195 --------------------------------------------------------------------------------
196
196
197 When both largefiles and lfs are configured to add by size, the tie goes to
197 When both largefiles and lfs are configured to add by size, the tie goes to
198 largefiles since it hooks cmdutil.add() and lfs hooks the filelog write in the
198 largefiles since it hooks cmdutil.add() and lfs hooks the filelog write in the
199 commit. By the time the commit occurs, the tracked file is smaller than the
199 commit. By the time the commit occurs, the tracked file is smaller than the
200 threshold (assuming it is > 41, so the standins don't become lfs objects).
200 threshold (assuming it is > 41, so the standins don't become lfs objects).
201
201
202 $ $PYTHON -c 'import sys ; sys.stdout.write("y\n" * 1048576)' > large_by_size.bin
202 $ $PYTHON -c 'import sys ; sys.stdout.write("y\n" * 1048576)' > large_by_size.bin
203 $ hg --config largefiles.minsize=1 ci -Am 'large by size'
203 $ hg --config largefiles.minsize=1 ci -Am 'large by size'
204 adding large_by_size.bin as a largefile
204 adding large_by_size.bin as a largefile
205 $ hg manifest
205 $ hg manifest
206 .hglf/large.bin
206 .hglf/large.bin
207 .hglf/large_by_size.bin
207 .hglf/large_by_size.bin
208 .hglf/lfs.bin
208 .hglf/lfs.bin
209 lfs.txt
209 lfs.txt
210 normal.txt
210 normal.txt
211
211
212 $ hg rm large_by_size.bin
212 $ hg rm large_by_size.bin
213 $ hg ci -m 'remove large_by_size.bin'
213 $ hg ci -m 'remove large_by_size.bin'
214
214
215 Largefiles doesn't do anything special with diff, so it falls back to diffing
215 Largefiles doesn't do anything special with diff, so it falls back to diffing
216 the standins. Extdiff also is standin based comparison. Diff and extdiff both
216 the standins. Extdiff also is standin based comparison. Diff and extdiff both
217 work on the original file for lfs objects.
217 work on the original file for lfs objects.
218
218
219 Largefile -> lfs transition
219 Largefile -> lfs transition
220 $ hg diff -r 1 -r 3
220 $ hg diff -r 1 -r 3
221 diff -r 6513aaab9ca0 -r dcc5ce63e252 .hglf/large.bin
221 diff -r 6513aaab9ca0 -r dcc5ce63e252 .hglf/large.bin
222 --- a/.hglf/large.bin Thu Jan 01 00:00:00 1970 +0000
222 --- a/.hglf/large.bin Thu Jan 01 00:00:00 1970 +0000
223 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
223 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
224 @@ -1,1 +0,0 @@
224 @@ -1,1 +0,0 @@
225 -cef9a458373df9b0743a0d3c14d0c66fb19b8629
225 -cef9a458373df9b0743a0d3c14d0c66fb19b8629
226 diff -r 6513aaab9ca0 -r dcc5ce63e252 .hglf/lfs.bin
226 diff -r 6513aaab9ca0 -r dcc5ce63e252 .hglf/lfs.bin
227 --- a/.hglf/lfs.bin Thu Jan 01 00:00:00 1970 +0000
227 --- a/.hglf/lfs.bin Thu Jan 01 00:00:00 1970 +0000
228 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
228 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
229 @@ -1,1 +0,0 @@
229 @@ -1,1 +0,0 @@
230 -557fb6309cef935e1ac2c8296508379e4b15a6e6
230 -557fb6309cef935e1ac2c8296508379e4b15a6e6
231 diff -r 6513aaab9ca0 -r dcc5ce63e252 large.bin
231 diff -r 6513aaab9ca0 -r dcc5ce63e252 large.bin
232 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
232 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
233 +++ b/large.bin Thu Jan 01 00:00:00 1970 +0000
233 +++ b/large.bin Thu Jan 01 00:00:00 1970 +0000
234 @@ -0,0 +1,1 @@
234 @@ -0,0 +1,1 @@
235 +below lfs threshold
235 +below lfs threshold
236 diff -r 6513aaab9ca0 -r dcc5ce63e252 lfs.bin
236 diff -r 6513aaab9ca0 -r dcc5ce63e252 lfs.bin
237 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
237 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
238 +++ b/lfs.bin Thu Jan 01 00:00:00 1970 +0000
238 +++ b/lfs.bin Thu Jan 01 00:00:00 1970 +0000
239 @@ -0,0 +1,1 @@
239 @@ -0,0 +1,1 @@
240 +lfs above the lfs threshold for length 0000000000000
240 +lfs above the lfs threshold for length 0000000000000
241
241
242 lfs -> largefiles transition
242 lfs -> largefiles transition
243 $ hg diff -r 2 -r 6
243 $ hg diff -r 2 -r 6
244 diff -r e989d0fa3764 -r 95e1e80325c8 .hglf/large.bin
244 diff -r e989d0fa3764 -r 95e1e80325c8 .hglf/large.bin
245 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
245 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
246 +++ b/.hglf/large.bin Thu Jan 01 00:00:00 1970 +0000
246 +++ b/.hglf/large.bin Thu Jan 01 00:00:00 1970 +0000
247 @@ -0,0 +1,1 @@
247 @@ -0,0 +1,1 @@
248 +cef9a458373df9b0743a0d3c14d0c66fb19b8629
248 +cef9a458373df9b0743a0d3c14d0c66fb19b8629
249 diff -r e989d0fa3764 -r 95e1e80325c8 .hglf/lfs.bin
249 diff -r e989d0fa3764 -r 95e1e80325c8 .hglf/lfs.bin
250 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
250 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
251 +++ b/.hglf/lfs.bin Thu Jan 01 00:00:00 1970 +0000
251 +++ b/.hglf/lfs.bin Thu Jan 01 00:00:00 1970 +0000
252 @@ -0,0 +1,1 @@
252 @@ -0,0 +1,1 @@
253 +557fb6309cef935e1ac2c8296508379e4b15a6e6
253 +557fb6309cef935e1ac2c8296508379e4b15a6e6
254 diff -r e989d0fa3764 -r 95e1e80325c8 large.bin
254 diff -r e989d0fa3764 -r 95e1e80325c8 large.bin
255 --- a/large.bin Thu Jan 01 00:00:00 1970 +0000
255 --- a/large.bin Thu Jan 01 00:00:00 1970 +0000
256 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
256 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
257 @@ -1,1 +0,0 @@
257 @@ -1,1 +0,0 @@
258 -below lfs threshold
258 -below lfs threshold
259 diff -r e989d0fa3764 -r 95e1e80325c8 lfs.bin
259 diff -r e989d0fa3764 -r 95e1e80325c8 lfs.bin
260 --- a/lfs.bin Thu Jan 01 00:00:00 1970 +0000
260 --- a/lfs.bin Thu Jan 01 00:00:00 1970 +0000
261 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
261 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
262 @@ -1,1 +0,0 @@
262 @@ -1,1 +0,0 @@
263 -lfs above the lfs threshold for length 0000000000000
263 -lfs above the lfs threshold for length 0000000000000
264
264
265 A largefiles repo can be converted to lfs. The lfconvert command uses the
265 A largefiles repo can be converted to lfs. The lfconvert command uses the
266 convert extension under the hood with --to-normal. So the --config based
266 convert extension under the hood with --to-normal. So the --config based
267 parameters are available, but not --authormap, --branchmap, etc.
267 parameters are available, but not --authormap, --branchmap, etc.
268
268
269 $ cd ..
269 $ cd ..
270 $ hg lfconvert --to-normal largefiles nolargefiles 2>&1
270 $ hg lfconvert --to-normal largefiles nolargefiles 2>&1
271 initializing destination nolargefiles
271 initializing destination nolargefiles
272 0 additional largefiles cached
272 0 additional largefiles cached
273 scanning source...
273 scanning source...
274 sorting...
274 sorting...
275 converting...
275 converting...
276 8 normal.txt
276 8 normal.txt
277 7 add largefiles
277 7 add largefiles
278 6 add with lfs extension
278 6 add with lfs extension
279 5 merge lfs with largefiles -> normal
279 5 merge lfs with largefiles -> normal
280 4 merge lfs with largefiles -> large
280 4 merge lfs with largefiles -> large
281 3 merge largefiles with lfs -> normal
281 3 merge largefiles with lfs -> normal
282 2 merge largefiles with lfs -> large
282 2 merge largefiles with lfs -> large
283 1 large by size
283 1 large by size
284 0 remove large_by_size.bin
284 0 remove large_by_size.bin
285 $ cd nolargefiles
285 $ cd nolargefiles
286
286
287 The requirement is added to the destination repo
287 The requirement is added to the destination repo, and the extension is enabled
288 locally.
288
289
289 $ cat .hg/requires
290 $ cat .hg/requires
290 dotencode
291 dotencode
291 fncache
292 fncache
292 generaldelta
293 generaldelta
293 lfs
294 lfs
294 revlogv1
295 revlogv1
295 store
296 store
297 $ hg config --debug extensions | grep lfs
298 $TESTTMP/nolargefiles/.hg/hgrc:*: extensions.lfs= (glob)
296
299
297 $ hg log -r 'all()' -G -T '{rev} {join(lfs_files, ", ")} ({desc})\n'
300 $ hg log -r 'all()' -G -T '{rev} {join(lfs_files, ", ")} ({desc})\n'
298 o 8 (remove large_by_size.bin)
301 o 8 (remove large_by_size.bin)
299 |
302 |
300 o 7 large_by_size.bin (large by size)
303 o 7 large_by_size.bin (large by size)
301 |
304 |
302 o 6 (merge largefiles with lfs -> large)
305 o 6 (merge largefiles with lfs -> large)
303 |\
306 |\
304 +---o 5 (merge largefiles with lfs -> normal)
307 +---o 5 (merge largefiles with lfs -> normal)
305 | |/
308 | |/
306 +---o 4 lfs.bin (merge lfs with largefiles -> large)
309 +---o 4 lfs.bin (merge lfs with largefiles -> large)
307 | |/
310 | |/
308 +---o 3 (merge lfs with largefiles -> normal)
311 +---o 3 (merge lfs with largefiles -> normal)
309 | |/
312 | |/
310 | o 2 lfs.bin (add with lfs extension)
313 | o 2 lfs.bin (add with lfs extension)
311 | |
314 | |
312 o | 1 lfs.bin (add largefiles)
315 o | 1 lfs.bin (add largefiles)
313 |/
316 |/
314 o 0 lfs.txt (normal.txt)
317 o 0 lfs.txt (normal.txt)
315
318
316 $ hg debugdata lfs.bin 0
319 $ hg debugdata lfs.bin 0
317 version https://git-lfs.github.com/spec/v1
320 version https://git-lfs.github.com/spec/v1
318 oid sha256:2172a5bd492dd41ec533b9bb695f7691b6351719407ac797f0ccad5348c81e62
321 oid sha256:2172a5bd492dd41ec533b9bb695f7691b6351719407ac797f0ccad5348c81e62
319 size 53
322 size 53
320 x-is-binary 0
323 x-is-binary 0
321 $ hg debugdata lfs.bin 1
324 $ hg debugdata lfs.bin 1
322 version https://git-lfs.github.com/spec/v1
325 version https://git-lfs.github.com/spec/v1
323 oid sha256:81c7492b2c05e130431f65a87651b54a30c5da72c99ce35a1e9b9872a807312b
326 oid sha256:81c7492b2c05e130431f65a87651b54a30c5da72c99ce35a1e9b9872a807312b
324 size 53
327 size 53
325 x-is-binary 0
328 x-is-binary 0
326 $ hg debugdata lfs.bin 2
329 $ hg debugdata lfs.bin 2
327 version https://git-lfs.github.com/spec/v1
330 version https://git-lfs.github.com/spec/v1
328 oid sha256:2172a5bd492dd41ec533b9bb695f7691b6351719407ac797f0ccad5348c81e62
331 oid sha256:2172a5bd492dd41ec533b9bb695f7691b6351719407ac797f0ccad5348c81e62
329 size 53
332 size 53
330 x-is-binary 0
333 x-is-binary 0
331 $ hg debugdata lfs.bin 3
334 $ hg debugdata lfs.bin 3
332 abort: invalid revision identifier 3
335 abort: invalid revision identifier 3
333 [255]
336 [255]
334
337
335 No diffs when comparing merge and p1 that kept p1's changes. Diff of lfs to
338 No diffs when comparing merge and p1 that kept p1's changes. Diff of lfs to
336 largefiles no longer operates in standin files.
339 largefiles no longer operates in standin files.
337
340
338 $ hg diff -r 2:3
341 $ hg diff -r 2:3
339 $ hg diff -r 2:6
342 $ hg diff -r 2:6
340 diff -r e989d0fa3764 -r 752e3a0d8488 large.bin
343 diff -r e989d0fa3764 -r 752e3a0d8488 large.bin
341 --- a/large.bin Thu Jan 01 00:00:00 1970 +0000
344 --- a/large.bin Thu Jan 01 00:00:00 1970 +0000
342 +++ b/large.bin Thu Jan 01 00:00:00 1970 +0000
345 +++ b/large.bin Thu Jan 01 00:00:00 1970 +0000
343 @@ -1,1 +1,1 @@
346 @@ -1,1 +1,1 @@
344 -below lfs threshold
347 -below lfs threshold
345 +largefile
348 +largefile
346 diff -r e989d0fa3764 -r 752e3a0d8488 lfs.bin
349 diff -r e989d0fa3764 -r 752e3a0d8488 lfs.bin
347 --- a/lfs.bin Thu Jan 01 00:00:00 1970 +0000
350 --- a/lfs.bin Thu Jan 01 00:00:00 1970 +0000
348 +++ b/lfs.bin Thu Jan 01 00:00:00 1970 +0000
351 +++ b/lfs.bin Thu Jan 01 00:00:00 1970 +0000
349 @@ -1,1 +1,1 @@
352 @@ -1,1 +1,1 @@
350 -lfs above the lfs threshold for length 0000000000000
353 -lfs above the lfs threshold for length 0000000000000
351 +largefile above lfs threshold 0000000000000000000000
354 +largefile above lfs threshold 0000000000000000000000
@@ -1,646 +1,649
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 > threshold=1000B
7 > threshold=1000B
8 > EOF
8 > EOF
9
9
10 $ LONG=AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
10 $ LONG=AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
11
11
12 # Prepare server and enable extension
12 # Prepare server and enable extension
13 $ hg init server
13 $ hg init server
14 $ hg clone -q server client
14 $ hg clone -q server client
15 $ cd client
15 $ cd client
16
16
17 # Commit small file
17 # Commit small file
18 $ echo s > smallfile
18 $ echo s > smallfile
19 $ hg commit -Aqm "add small file"
19 $ hg commit -Aqm "add small file"
20
20
21 # Commit large file
21 # Commit large file
22 $ echo $LONG > largefile
22 $ echo $LONG > largefile
23 $ grep lfs .hg/requires
23 $ grep lfs .hg/requires
24 [1]
24 [1]
25 $ hg commit --traceback -Aqm "add large file"
25 $ hg commit --traceback -Aqm "add large file"
26 $ grep lfs .hg/requires
26 $ grep lfs .hg/requires
27 lfs
27 lfs
28
28
29 # Ensure metadata is stored
29 # Ensure metadata is stored
30 $ hg debugdata largefile 0
30 $ hg debugdata largefile 0
31 version https://git-lfs.github.com/spec/v1
31 version https://git-lfs.github.com/spec/v1
32 oid sha256:f11e77c257047a398492d8d6cb9f6acf3aa7c4384bb23080b43546053e183e4b
32 oid sha256:f11e77c257047a398492d8d6cb9f6acf3aa7c4384bb23080b43546053e183e4b
33 size 1501
33 size 1501
34 x-is-binary 0
34 x-is-binary 0
35
35
36 # Check the blobstore is populated
36 # Check the blobstore is populated
37 $ find .hg/store/lfs/objects | sort
37 $ find .hg/store/lfs/objects | sort
38 .hg/store/lfs/objects
38 .hg/store/lfs/objects
39 .hg/store/lfs/objects/f1
39 .hg/store/lfs/objects/f1
40 .hg/store/lfs/objects/f1/1e77c257047a398492d8d6cb9f6acf3aa7c4384bb23080b43546053e183e4b
40 .hg/store/lfs/objects/f1/1e77c257047a398492d8d6cb9f6acf3aa7c4384bb23080b43546053e183e4b
41
41
42 # Check the blob stored contains the actual contents of the file
42 # Check the blob stored contains the actual contents of the file
43 $ cat .hg/store/lfs/objects/f1/1e77c257047a398492d8d6cb9f6acf3aa7c4384bb23080b43546053e183e4b
43 $ cat .hg/store/lfs/objects/f1/1e77c257047a398492d8d6cb9f6acf3aa7c4384bb23080b43546053e183e4b
44 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
44 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
45
45
46 # Push changes to the server
46 # Push changes to the server
47
47
48 $ hg push
48 $ hg push
49 pushing to $TESTTMP/server (glob)
49 pushing to $TESTTMP/server (glob)
50 searching for changes
50 searching for changes
51 abort: lfs.url needs to be configured
51 abort: lfs.url needs to be configured
52 [255]
52 [255]
53
53
54 $ cat >> $HGRCPATH << EOF
54 $ cat >> $HGRCPATH << EOF
55 > [lfs]
55 > [lfs]
56 > url=file:$TESTTMP/dummy-remote/
56 > url=file:$TESTTMP/dummy-remote/
57 > EOF
57 > EOF
58
58
59 $ hg push -v | egrep -v '^(uncompressed| )'
59 $ hg push -v | egrep -v '^(uncompressed| )'
60 pushing to $TESTTMP/server (glob)
60 pushing to $TESTTMP/server (glob)
61 searching for changes
61 searching for changes
62 2 changesets found
62 2 changesets found
63 adding changesets
63 adding changesets
64 adding manifests
64 adding manifests
65 adding file changes
65 adding file changes
66 added 2 changesets with 2 changes to 2 files
66 added 2 changesets with 2 changes to 2 files
67
67
68 # Unknown URL scheme
68 # Unknown URL scheme
69
69
70 $ hg push --config lfs.url=ftp://foobar
70 $ hg push --config lfs.url=ftp://foobar
71 abort: lfs: unknown url scheme: ftp
71 abort: lfs: unknown url scheme: ftp
72 [255]
72 [255]
73
73
74 $ cd ../
74 $ cd ../
75
75
76 # Initialize new client (not cloning) and setup extension
76 # Initialize new client (not cloning) and setup extension
77 $ hg init client2
77 $ hg init client2
78 $ cd client2
78 $ cd client2
79 $ cat >> .hg/hgrc <<EOF
79 $ cat >> .hg/hgrc <<EOF
80 > [paths]
80 > [paths]
81 > default = $TESTTMP/server
81 > default = $TESTTMP/server
82 > EOF
82 > EOF
83
83
84 # Pull from server
84 # Pull from server
85 $ hg pull default
85 $ hg pull default
86 pulling from $TESTTMP/server (glob)
86 pulling from $TESTTMP/server (glob)
87 requesting all changes
87 requesting all changes
88 adding changesets
88 adding changesets
89 adding manifests
89 adding manifests
90 adding file changes
90 adding file changes
91 added 2 changesets with 2 changes to 2 files
91 added 2 changesets with 2 changes to 2 files
92 new changesets b29ba743f89d:00c137947d30
92 new changesets b29ba743f89d:00c137947d30
93 (run 'hg update' to get a working copy)
93 (run 'hg update' to get a working copy)
94
94
95 # Check the blobstore is not yet populated
95 # Check the blobstore is not yet populated
96 $ [ -d .hg/store/lfs/objects ]
96 $ [ -d .hg/store/lfs/objects ]
97 [1]
97 [1]
98
98
99 # Update to the last revision containing the large file
99 # Update to the last revision containing the large file
100 $ hg update
100 $ hg update
101 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
101 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
102
102
103 # Check the blobstore has been populated on update
103 # Check the blobstore has been populated on update
104 $ find .hg/store/lfs/objects | sort
104 $ find .hg/store/lfs/objects | sort
105 .hg/store/lfs/objects
105 .hg/store/lfs/objects
106 .hg/store/lfs/objects/f1
106 .hg/store/lfs/objects/f1
107 .hg/store/lfs/objects/f1/1e77c257047a398492d8d6cb9f6acf3aa7c4384bb23080b43546053e183e4b
107 .hg/store/lfs/objects/f1/1e77c257047a398492d8d6cb9f6acf3aa7c4384bb23080b43546053e183e4b
108
108
109 # Check the contents of the file are fetched from blobstore when requested
109 # Check the contents of the file are fetched from blobstore when requested
110 $ hg cat -r . largefile
110 $ hg cat -r . largefile
111 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
111 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
112
112
113 # Check the file has been copied in the working copy
113 # Check the file has been copied in the working copy
114 $ cat largefile
114 $ cat largefile
115 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
115 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
116
116
117 $ cd ..
117 $ cd ..
118
118
119 # Check rename, and switch between large and small files
119 # Check rename, and switch between large and small files
120
120
121 $ hg init repo3
121 $ hg init repo3
122 $ cd repo3
122 $ cd repo3
123 $ cat >> .hg/hgrc << EOF
123 $ cat >> .hg/hgrc << EOF
124 > [lfs]
124 > [lfs]
125 > threshold=10B
125 > threshold=10B
126 > EOF
126 > EOF
127
127
128 $ echo LONGER-THAN-TEN-BYTES-WILL-TRIGGER-LFS > large
128 $ echo LONGER-THAN-TEN-BYTES-WILL-TRIGGER-LFS > large
129 $ echo SHORTER > small
129 $ echo SHORTER > small
130 $ hg add . -q
130 $ hg add . -q
131 $ hg commit -m 'commit with lfs content'
131 $ hg commit -m 'commit with lfs content'
132
132
133 $ hg mv large l
133 $ hg mv large l
134 $ hg mv small s
134 $ hg mv small s
135 $ hg commit -m 'renames'
135 $ hg commit -m 'renames'
136
136
137 $ echo SHORT > l
137 $ echo SHORT > l
138 $ echo BECOME-LARGER-FROM-SHORTER > s
138 $ echo BECOME-LARGER-FROM-SHORTER > s
139 $ hg commit -m 'large to small, small to large'
139 $ hg commit -m 'large to small, small to large'
140
140
141 $ echo 1 >> l
141 $ echo 1 >> l
142 $ echo 2 >> s
142 $ echo 2 >> s
143 $ hg commit -m 'random modifications'
143 $ hg commit -m 'random modifications'
144
144
145 $ echo RESTORE-TO-BE-LARGE > l
145 $ echo RESTORE-TO-BE-LARGE > l
146 $ echo SHORTER > s
146 $ echo SHORTER > s
147 $ hg commit -m 'switch large and small again'
147 $ hg commit -m 'switch large and small again'
148
148
149 # Test lfs_files template
149 # Test lfs_files template
150
150
151 $ hg log -r 'all()' -T '{rev} {join(lfs_files, ", ")}\n'
151 $ hg log -r 'all()' -T '{rev} {join(lfs_files, ", ")}\n'
152 0 large
152 0 large
153 1 l
153 1 l
154 2 s
154 2 s
155 3 s
155 3 s
156 4 l
156 4 l
157
157
158 # Push and pull the above repo
158 # Push and pull the above repo
159
159
160 $ hg --cwd .. init repo4
160 $ hg --cwd .. init repo4
161 $ hg push ../repo4
161 $ hg push ../repo4
162 pushing to ../repo4
162 pushing to ../repo4
163 searching for changes
163 searching for changes
164 adding changesets
164 adding changesets
165 adding manifests
165 adding manifests
166 adding file changes
166 adding file changes
167 added 5 changesets with 10 changes to 4 files
167 added 5 changesets with 10 changes to 4 files
168
168
169 $ hg --cwd .. init repo5
169 $ hg --cwd .. init repo5
170 $ hg --cwd ../repo5 pull ../repo3
170 $ hg --cwd ../repo5 pull ../repo3
171 pulling from ../repo3
171 pulling from ../repo3
172 requesting all changes
172 requesting all changes
173 adding changesets
173 adding changesets
174 adding manifests
174 adding manifests
175 adding file changes
175 adding file changes
176 added 5 changesets with 10 changes to 4 files
176 added 5 changesets with 10 changes to 4 files
177 new changesets fd47a419c4f7:5adf850972b9
177 new changesets fd47a419c4f7:5adf850972b9
178 (run 'hg update' to get a working copy)
178 (run 'hg update' to get a working copy)
179
179
180 $ cd ..
180 $ cd ..
181
181
182 # Test clone
182 # Test clone
183
183
184 $ hg init repo6
184 $ hg init repo6
185 $ cd repo6
185 $ cd repo6
186 $ cat >> .hg/hgrc << EOF
186 $ cat >> .hg/hgrc << EOF
187 > [lfs]
187 > [lfs]
188 > threshold=30B
188 > threshold=30B
189 > EOF
189 > EOF
190
190
191 $ echo LARGE-BECAUSE-IT-IS-MORE-THAN-30-BYTES > large
191 $ echo LARGE-BECAUSE-IT-IS-MORE-THAN-30-BYTES > large
192 $ echo SMALL > small
192 $ echo SMALL > small
193 $ hg commit -Aqm 'create a lfs file' large small
193 $ hg commit -Aqm 'create a lfs file' large small
194 $ hg debuglfsupload -r 'all()' -v
194 $ hg debuglfsupload -r 'all()' -v
195
195
196 $ cd ..
196 $ cd ..
197
197
198 $ hg clone repo6 repo7
198 $ hg clone repo6 repo7
199 updating to branch default
199 updating to branch default
200 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
200 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
201 $ cd repo7
201 $ cd repo7
202 $ hg config extensions --debug | grep lfs
202 $ hg config extensions --debug | grep lfs
203 $TESTTMP/repo7/.hg/hgrc:*: extensions.lfs= (glob)
203 $TESTTMP/repo7/.hg/hgrc:*: extensions.lfs= (glob)
204 $ cat large
204 $ cat large
205 LARGE-BECAUSE-IT-IS-MORE-THAN-30-BYTES
205 LARGE-BECAUSE-IT-IS-MORE-THAN-30-BYTES
206 $ cat small
206 $ cat small
207 SMALL
207 SMALL
208
208
209 $ cd ..
209 $ cd ..
210
210
211 $ hg --config extensions.share= share repo7 sharedrepo
211 $ hg --config extensions.share= share repo7 sharedrepo
212 updating working directory
212 updating working directory
213 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
213 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
214 $ hg -R sharedrepo config extensions --debug | grep lfs
214 $ hg -R sharedrepo config extensions --debug | grep lfs
215 $TESTTMP/sharedrepo/.hg/hgrc:*: extensions.lfs= (glob)
215 $TESTTMP/sharedrepo/.hg/hgrc:*: extensions.lfs= (glob)
216
216
217 # Test rename and status
217 # Test rename and status
218
218
219 $ hg init repo8
219 $ hg init repo8
220 $ cd repo8
220 $ cd repo8
221 $ cat >> .hg/hgrc << EOF
221 $ cat >> .hg/hgrc << EOF
222 > [lfs]
222 > [lfs]
223 > threshold=10B
223 > threshold=10B
224 > EOF
224 > EOF
225
225
226 $ echo THIS-IS-LFS-BECAUSE-10-BYTES > a1
226 $ echo THIS-IS-LFS-BECAUSE-10-BYTES > a1
227 $ echo SMALL > a2
227 $ echo SMALL > a2
228 $ hg commit -m a -A a1 a2
228 $ hg commit -m a -A a1 a2
229 $ hg status
229 $ hg status
230 $ hg mv a1 b1
230 $ hg mv a1 b1
231 $ hg mv a2 a1
231 $ hg mv a2 a1
232 $ hg mv b1 a2
232 $ hg mv b1 a2
233 $ hg commit -m b
233 $ hg commit -m b
234 $ hg status
234 $ hg status
235 $ HEADER=$'\1\n'
235 $ HEADER=$'\1\n'
236 $ printf '%sSTART-WITH-HG-FILELOG-METADATA' "$HEADER" > a2
236 $ printf '%sSTART-WITH-HG-FILELOG-METADATA' "$HEADER" > a2
237 $ printf '%sMETA\n' "$HEADER" > a1
237 $ printf '%sMETA\n' "$HEADER" > a1
238 $ hg commit -m meta
238 $ hg commit -m meta
239 $ hg status
239 $ hg status
240 $ hg log -T '{rev}: {file_copies} | {file_dels} | {file_adds}\n'
240 $ hg log -T '{rev}: {file_copies} | {file_dels} | {file_adds}\n'
241 2: | |
241 2: | |
242 1: a1 (a2)a2 (a1) | |
242 1: a1 (a2)a2 (a1) | |
243 0: | | a1 a2
243 0: | | a1 a2
244
244
245 $ for n in a1 a2; do
245 $ for n in a1 a2; do
246 > for r in 0 1 2; do
246 > for r in 0 1 2; do
247 > printf '\n%s @ %s\n' $n $r
247 > printf '\n%s @ %s\n' $n $r
248 > hg debugdata $n $r
248 > hg debugdata $n $r
249 > done
249 > done
250 > done
250 > done
251
251
252 a1 @ 0
252 a1 @ 0
253 version https://git-lfs.github.com/spec/v1
253 version https://git-lfs.github.com/spec/v1
254 oid sha256:5bb8341bee63b3649f222b2215bde37322bea075a30575aa685d8f8d21c77024
254 oid sha256:5bb8341bee63b3649f222b2215bde37322bea075a30575aa685d8f8d21c77024
255 size 29
255 size 29
256 x-is-binary 0
256 x-is-binary 0
257
257
258 a1 @ 1
258 a1 @ 1
259 \x01 (esc)
259 \x01 (esc)
260 copy: a2
260 copy: a2
261 copyrev: 50470ad23cf937b1f4b9f80bfe54df38e65b50d9
261 copyrev: 50470ad23cf937b1f4b9f80bfe54df38e65b50d9
262 \x01 (esc)
262 \x01 (esc)
263 SMALL
263 SMALL
264
264
265 a1 @ 2
265 a1 @ 2
266 \x01 (esc)
266 \x01 (esc)
267 \x01 (esc)
267 \x01 (esc)
268 \x01 (esc)
268 \x01 (esc)
269 META
269 META
270
270
271 a2 @ 0
271 a2 @ 0
272 SMALL
272 SMALL
273
273
274 a2 @ 1
274 a2 @ 1
275 version https://git-lfs.github.com/spec/v1
275 version https://git-lfs.github.com/spec/v1
276 oid sha256:5bb8341bee63b3649f222b2215bde37322bea075a30575aa685d8f8d21c77024
276 oid sha256:5bb8341bee63b3649f222b2215bde37322bea075a30575aa685d8f8d21c77024
277 size 29
277 size 29
278 x-hg-copy a1
278 x-hg-copy a1
279 x-hg-copyrev be23af27908a582af43e5cda209a5a9b319de8d4
279 x-hg-copyrev be23af27908a582af43e5cda209a5a9b319de8d4
280 x-is-binary 0
280 x-is-binary 0
281
281
282 a2 @ 2
282 a2 @ 2
283 version https://git-lfs.github.com/spec/v1
283 version https://git-lfs.github.com/spec/v1
284 oid sha256:876dadc86a8542f9798048f2c47f51dbf8e4359aed883e8ec80c5db825f0d943
284 oid sha256:876dadc86a8542f9798048f2c47f51dbf8e4359aed883e8ec80c5db825f0d943
285 size 32
285 size 32
286 x-is-binary 0
286 x-is-binary 0
287
287
288 # Verify commit hashes include rename metadata
288 # Verify commit hashes include rename metadata
289
289
290 $ hg log -T '{rev}:{node|short} {desc}\n'
290 $ hg log -T '{rev}:{node|short} {desc}\n'
291 2:0fae949de7fa meta
291 2:0fae949de7fa meta
292 1:9cd6bdffdac0 b
292 1:9cd6bdffdac0 b
293 0:7f96794915f7 a
293 0:7f96794915f7 a
294
294
295 $ cd ..
295 $ cd ..
296
296
297 # Test bundle
297 # Test bundle
298
298
299 $ hg init repo9
299 $ hg init repo9
300 $ cd repo9
300 $ cd repo9
301 $ cat >> .hg/hgrc << EOF
301 $ cat >> .hg/hgrc << EOF
302 > [lfs]
302 > [lfs]
303 > threshold=10B
303 > threshold=10B
304 > [diff]
304 > [diff]
305 > git=1
305 > git=1
306 > EOF
306 > EOF
307
307
308 $ for i in 0 single two three 4; do
308 $ for i in 0 single two three 4; do
309 > echo 'THIS-IS-LFS-'$i > a
309 > echo 'THIS-IS-LFS-'$i > a
310 > hg commit -m a-$i -A a
310 > hg commit -m a-$i -A a
311 > done
311 > done
312
312
313 $ hg update 2 -q
313 $ hg update 2 -q
314 $ echo 'THIS-IS-LFS-2-CHILD' > a
314 $ echo 'THIS-IS-LFS-2-CHILD' > a
315 $ hg commit -m branching -q
315 $ hg commit -m branching -q
316
316
317 $ hg bundle --base 1 bundle.hg -v
317 $ hg bundle --base 1 bundle.hg -v
318 4 changesets found
318 4 changesets found
319 uncompressed size of bundle content:
319 uncompressed size of bundle content:
320 * (changelog) (glob)
320 * (changelog) (glob)
321 * (manifests) (glob)
321 * (manifests) (glob)
322 * a (glob)
322 * a (glob)
323 $ hg --config extensions.strip= strip -r 2 --no-backup --force -q
323 $ hg --config extensions.strip= strip -r 2 --no-backup --force -q
324 $ hg -R bundle.hg log -p -T '{rev} {desc}\n' a
324 $ hg -R bundle.hg log -p -T '{rev} {desc}\n' a
325 5 branching
325 5 branching
326 diff --git a/a b/a
326 diff --git a/a b/a
327 --- a/a
327 --- a/a
328 +++ b/a
328 +++ b/a
329 @@ -1,1 +1,1 @@
329 @@ -1,1 +1,1 @@
330 -THIS-IS-LFS-two
330 -THIS-IS-LFS-two
331 +THIS-IS-LFS-2-CHILD
331 +THIS-IS-LFS-2-CHILD
332
332
333 4 a-4
333 4 a-4
334 diff --git a/a b/a
334 diff --git a/a b/a
335 --- a/a
335 --- a/a
336 +++ b/a
336 +++ b/a
337 @@ -1,1 +1,1 @@
337 @@ -1,1 +1,1 @@
338 -THIS-IS-LFS-three
338 -THIS-IS-LFS-three
339 +THIS-IS-LFS-4
339 +THIS-IS-LFS-4
340
340
341 3 a-three
341 3 a-three
342 diff --git a/a b/a
342 diff --git a/a b/a
343 --- a/a
343 --- a/a
344 +++ b/a
344 +++ b/a
345 @@ -1,1 +1,1 @@
345 @@ -1,1 +1,1 @@
346 -THIS-IS-LFS-two
346 -THIS-IS-LFS-two
347 +THIS-IS-LFS-three
347 +THIS-IS-LFS-three
348
348
349 2 a-two
349 2 a-two
350 diff --git a/a b/a
350 diff --git a/a b/a
351 --- a/a
351 --- a/a
352 +++ b/a
352 +++ b/a
353 @@ -1,1 +1,1 @@
353 @@ -1,1 +1,1 @@
354 -THIS-IS-LFS-single
354 -THIS-IS-LFS-single
355 +THIS-IS-LFS-two
355 +THIS-IS-LFS-two
356
356
357 1 a-single
357 1 a-single
358 diff --git a/a b/a
358 diff --git a/a b/a
359 --- a/a
359 --- a/a
360 +++ b/a
360 +++ b/a
361 @@ -1,1 +1,1 @@
361 @@ -1,1 +1,1 @@
362 -THIS-IS-LFS-0
362 -THIS-IS-LFS-0
363 +THIS-IS-LFS-single
363 +THIS-IS-LFS-single
364
364
365 0 a-0
365 0 a-0
366 diff --git a/a b/a
366 diff --git a/a b/a
367 new file mode 100644
367 new file mode 100644
368 --- /dev/null
368 --- /dev/null
369 +++ b/a
369 +++ b/a
370 @@ -0,0 +1,1 @@
370 @@ -0,0 +1,1 @@
371 +THIS-IS-LFS-0
371 +THIS-IS-LFS-0
372
372
373 $ hg bundle -R bundle.hg --base 1 bundle-again.hg -q
373 $ hg bundle -R bundle.hg --base 1 bundle-again.hg -q
374 $ hg -R bundle-again.hg log -p -T '{rev} {desc}\n' a
374 $ hg -R bundle-again.hg log -p -T '{rev} {desc}\n' a
375 5 branching
375 5 branching
376 diff --git a/a b/a
376 diff --git a/a b/a
377 --- a/a
377 --- a/a
378 +++ b/a
378 +++ b/a
379 @@ -1,1 +1,1 @@
379 @@ -1,1 +1,1 @@
380 -THIS-IS-LFS-two
380 -THIS-IS-LFS-two
381 +THIS-IS-LFS-2-CHILD
381 +THIS-IS-LFS-2-CHILD
382
382
383 4 a-4
383 4 a-4
384 diff --git a/a b/a
384 diff --git a/a b/a
385 --- a/a
385 --- a/a
386 +++ b/a
386 +++ b/a
387 @@ -1,1 +1,1 @@
387 @@ -1,1 +1,1 @@
388 -THIS-IS-LFS-three
388 -THIS-IS-LFS-three
389 +THIS-IS-LFS-4
389 +THIS-IS-LFS-4
390
390
391 3 a-three
391 3 a-three
392 diff --git a/a b/a
392 diff --git a/a b/a
393 --- a/a
393 --- a/a
394 +++ b/a
394 +++ b/a
395 @@ -1,1 +1,1 @@
395 @@ -1,1 +1,1 @@
396 -THIS-IS-LFS-two
396 -THIS-IS-LFS-two
397 +THIS-IS-LFS-three
397 +THIS-IS-LFS-three
398
398
399 2 a-two
399 2 a-two
400 diff --git a/a b/a
400 diff --git a/a b/a
401 --- a/a
401 --- a/a
402 +++ b/a
402 +++ b/a
403 @@ -1,1 +1,1 @@
403 @@ -1,1 +1,1 @@
404 -THIS-IS-LFS-single
404 -THIS-IS-LFS-single
405 +THIS-IS-LFS-two
405 +THIS-IS-LFS-two
406
406
407 1 a-single
407 1 a-single
408 diff --git a/a b/a
408 diff --git a/a b/a
409 --- a/a
409 --- a/a
410 +++ b/a
410 +++ b/a
411 @@ -1,1 +1,1 @@
411 @@ -1,1 +1,1 @@
412 -THIS-IS-LFS-0
412 -THIS-IS-LFS-0
413 +THIS-IS-LFS-single
413 +THIS-IS-LFS-single
414
414
415 0 a-0
415 0 a-0
416 diff --git a/a b/a
416 diff --git a/a b/a
417 new file mode 100644
417 new file mode 100644
418 --- /dev/null
418 --- /dev/null
419 +++ b/a
419 +++ b/a
420 @@ -0,0 +1,1 @@
420 @@ -0,0 +1,1 @@
421 +THIS-IS-LFS-0
421 +THIS-IS-LFS-0
422
422
423 $ cd ..
423 $ cd ..
424
424
425 # Test isbinary
425 # Test isbinary
426
426
427 $ hg init repo10
427 $ hg init repo10
428 $ cd repo10
428 $ cd repo10
429 $ cat >> .hg/hgrc << EOF
429 $ cat >> .hg/hgrc << EOF
430 > [extensions]
430 > [extensions]
431 > lfs=
431 > lfs=
432 > [lfs]
432 > [lfs]
433 > threshold=1
433 > threshold=1
434 > EOF
434 > EOF
435 $ $PYTHON <<'EOF'
435 $ $PYTHON <<'EOF'
436 > def write(path, content):
436 > def write(path, content):
437 > with open(path, 'wb') as f:
437 > with open(path, 'wb') as f:
438 > f.write(content)
438 > f.write(content)
439 > write('a', b'\0\0')
439 > write('a', b'\0\0')
440 > write('b', b'\1\n')
440 > write('b', b'\1\n')
441 > write('c', b'\1\n\0')
441 > write('c', b'\1\n\0')
442 > write('d', b'xx')
442 > write('d', b'xx')
443 > EOF
443 > EOF
444 $ hg add a b c d
444 $ hg add a b c d
445 $ hg diff --stat
445 $ hg diff --stat
446 a | Bin
446 a | Bin
447 b | 1 +
447 b | 1 +
448 c | Bin
448 c | Bin
449 d | 1 +
449 d | 1 +
450 4 files changed, 2 insertions(+), 0 deletions(-)
450 4 files changed, 2 insertions(+), 0 deletions(-)
451 $ hg commit -m binarytest
451 $ hg commit -m binarytest
452 $ cat > $TESTTMP/dumpbinary.py << EOF
452 $ cat > $TESTTMP/dumpbinary.py << EOF
453 > def reposetup(ui, repo):
453 > def reposetup(ui, repo):
454 > for n in 'abcd':
454 > for n in 'abcd':
455 > ui.write(('%s: binary=%s\n') % (n, repo['.'][n].isbinary()))
455 > ui.write(('%s: binary=%s\n') % (n, repo['.'][n].isbinary()))
456 > EOF
456 > EOF
457 $ hg --config extensions.dumpbinary=$TESTTMP/dumpbinary.py id --trace
457 $ hg --config extensions.dumpbinary=$TESTTMP/dumpbinary.py id --trace
458 a: binary=True
458 a: binary=True
459 b: binary=False
459 b: binary=False
460 c: binary=True
460 c: binary=True
461 d: binary=False
461 d: binary=False
462 b55353847f02 tip
462 b55353847f02 tip
463
463
464 $ cd ..
464 $ cd ..
465
465
466 # Test fctx.cmp fastpath - diff without LFS blobs
466 # Test fctx.cmp fastpath - diff without LFS blobs
467
467
468 $ hg init repo11
468 $ hg init repo11
469 $ cd repo11
469 $ cd repo11
470 $ cat >> .hg/hgrc <<EOF
470 $ cat >> .hg/hgrc <<EOF
471 > [lfs]
471 > [lfs]
472 > threshold=1
472 > threshold=1
473 > EOF
473 > EOF
474 $ cat > ../patch.diff <<EOF
474 $ cat > ../patch.diff <<EOF
475 > # HG changeset patch
475 > # HG changeset patch
476 > 2
476 > 2
477 >
477 >
478 > diff --git a/a b/a
478 > diff --git a/a b/a
479 > old mode 100644
479 > old mode 100644
480 > new mode 100755
480 > new mode 100755
481 > EOF
481 > EOF
482
482
483 $ for i in 1 2 3; do
483 $ for i in 1 2 3; do
484 > cp ../repo10/a a
484 > cp ../repo10/a a
485 > if [ $i = 3 ]; then
485 > if [ $i = 3 ]; then
486 > # make a content-only change
486 > # make a content-only change
487 > hg import -q --bypass ../patch.diff
487 > hg import -q --bypass ../patch.diff
488 > hg update -q
488 > hg update -q
489 > rm ../patch.diff
489 > rm ../patch.diff
490 > else
490 > else
491 > echo $i >> a
491 > echo $i >> a
492 > hg commit -m $i -A a
492 > hg commit -m $i -A a
493 > fi
493 > fi
494 > done
494 > done
495 $ [ -d .hg/store/lfs/objects ]
495 $ [ -d .hg/store/lfs/objects ]
496
496
497 $ cd ..
497 $ cd ..
498
498
499 $ hg clone repo11 repo12 --noupdate
499 $ hg clone repo11 repo12 --noupdate
500 $ cd repo12
500 $ cd repo12
501 $ hg log --removed -p a -T '{desc}\n' --config diff.nobinary=1 --git
501 $ hg log --removed -p a -T '{desc}\n' --config diff.nobinary=1 --git
502 2
502 2
503 diff --git a/a b/a
503 diff --git a/a b/a
504 old mode 100644
504 old mode 100644
505 new mode 100755
505 new mode 100755
506
506
507 2
507 2
508 diff --git a/a b/a
508 diff --git a/a b/a
509 Binary file a has changed
509 Binary file a has changed
510
510
511 1
511 1
512 diff --git a/a b/a
512 diff --git a/a b/a
513 new file mode 100644
513 new file mode 100644
514 Binary file a has changed
514 Binary file a has changed
515
515
516 $ [ -d .hg/store/lfs/objects ]
516 $ [ -d .hg/store/lfs/objects ]
517 [1]
517 [1]
518
518
519 $ cd ..
519 $ cd ..
520
520
521 # Verify the repos
521 # Verify the repos
522
522
523 $ cat > $TESTTMP/dumpflog.py << EOF
523 $ cat > $TESTTMP/dumpflog.py << EOF
524 > # print raw revision sizes, flags, and hashes for certain files
524 > # print raw revision sizes, flags, and hashes for certain files
525 > import hashlib
525 > import hashlib
526 > from mercurial import revlog
526 > from mercurial import revlog
527 > from mercurial.node import short
527 > from mercurial.node import short
528 > def hash(rawtext):
528 > def hash(rawtext):
529 > h = hashlib.sha512()
529 > h = hashlib.sha512()
530 > h.update(rawtext)
530 > h.update(rawtext)
531 > return h.hexdigest()[:4]
531 > return h.hexdigest()[:4]
532 > def reposetup(ui, repo):
532 > def reposetup(ui, repo):
533 > # these 2 files are interesting
533 > # these 2 files are interesting
534 > for name in ['l', 's']:
534 > for name in ['l', 's']:
535 > fl = repo.file(name)
535 > fl = repo.file(name)
536 > if len(fl) == 0:
536 > if len(fl) == 0:
537 > continue
537 > continue
538 > sizes = [revlog.revlog.rawsize(fl, i) for i in fl]
538 > sizes = [revlog.revlog.rawsize(fl, i) for i in fl]
539 > texts = [fl.revision(i, raw=True) for i in fl]
539 > texts = [fl.revision(i, raw=True) for i in fl]
540 > flags = [int(fl.flags(i)) for i in fl]
540 > flags = [int(fl.flags(i)) for i in fl]
541 > hashes = [hash(t) for t in texts]
541 > hashes = [hash(t) for t in texts]
542 > print(' %s: rawsizes=%r flags=%r hashes=%r'
542 > print(' %s: rawsizes=%r flags=%r hashes=%r'
543 > % (name, sizes, flags, hashes))
543 > % (name, sizes, flags, hashes))
544 > EOF
544 > EOF
545
545
546 $ for i in client client2 server repo3 repo4 repo5 repo6 repo7 repo8 repo9 \
546 $ for i in client client2 server repo3 repo4 repo5 repo6 repo7 repo8 repo9 \
547 > repo10; do
547 > repo10; do
548 > echo 'repo:' $i
548 > echo 'repo:' $i
549 > hg --cwd $i verify --config extensions.dumpflog=$TESTTMP/dumpflog.py -q
549 > hg --cwd $i verify --config extensions.dumpflog=$TESTTMP/dumpflog.py -q
550 > done
550 > done
551 repo: client
551 repo: client
552 repo: client2
552 repo: client2
553 repo: server
553 repo: server
554 repo: repo3
554 repo: repo3
555 l: rawsizes=[211, 6, 8, 141] flags=[8192, 0, 0, 8192] hashes=['d2b8', '948c', 'cc88', '724d']
555 l: rawsizes=[211, 6, 8, 141] flags=[8192, 0, 0, 8192] hashes=['d2b8', '948c', 'cc88', '724d']
556 s: rawsizes=[74, 141, 141, 8] flags=[0, 8192, 8192, 0] hashes=['3c80', 'fce0', '874a', '826b']
556 s: rawsizes=[74, 141, 141, 8] flags=[0, 8192, 8192, 0] hashes=['3c80', 'fce0', '874a', '826b']
557 repo: repo4
557 repo: repo4
558 l: rawsizes=[211, 6, 8, 141] flags=[8192, 0, 0, 8192] hashes=['d2b8', '948c', 'cc88', '724d']
558 l: rawsizes=[211, 6, 8, 141] flags=[8192, 0, 0, 8192] hashes=['d2b8', '948c', 'cc88', '724d']
559 s: rawsizes=[74, 141, 141, 8] flags=[0, 8192, 8192, 0] hashes=['3c80', 'fce0', '874a', '826b']
559 s: rawsizes=[74, 141, 141, 8] flags=[0, 8192, 8192, 0] hashes=['3c80', 'fce0', '874a', '826b']
560 repo: repo5
560 repo: repo5
561 l: rawsizes=[211, 6, 8, 141] flags=[8192, 0, 0, 8192] hashes=['d2b8', '948c', 'cc88', '724d']
561 l: rawsizes=[211, 6, 8, 141] flags=[8192, 0, 0, 8192] hashes=['d2b8', '948c', 'cc88', '724d']
562 s: rawsizes=[74, 141, 141, 8] flags=[0, 8192, 8192, 0] hashes=['3c80', 'fce0', '874a', '826b']
562 s: rawsizes=[74, 141, 141, 8] flags=[0, 8192, 8192, 0] hashes=['3c80', 'fce0', '874a', '826b']
563 repo: repo6
563 repo: repo6
564 repo: repo7
564 repo: repo7
565 repo: repo8
565 repo: repo8
566 repo: repo9
566 repo: repo9
567 repo: repo10
567 repo: repo10
568
568
569 lfs -> normal -> lfs round trip conversions are possible. The threshold for the
569 lfs -> normal -> lfs round trip conversions are possible. The threshold for the
570 lfs destination is specified here because it was originally listed in the local
570 lfs destination is specified here because it was originally listed in the local
571 .hgrc, and the global one is too high to trigger lfs usage. For lfs -> normal,
571 .hgrc, and the global one is too high to trigger lfs usage. For lfs -> normal,
572 there's no 'lfs' destination repo requirement. For normal -> lfs, there is.
572 there's no 'lfs' destination repo requirement. For normal -> lfs, there is.
573
573
574 XXX: There's not a great way to ensure that the conversion to normal files
574 XXX: There's not a great way to ensure that the conversion to normal files
575 actually converts _everything_ to normal. The extension needs to be loaded for
575 actually converts _everything_ to normal. The extension needs to be loaded for
576 the source, but there's no way to disable it for the destination. The best that
576 the source, but there's no way to disable it for the destination. The best that
577 can be done is to raise the threshold so that lfs isn't used on the destination.
577 can be done is to raise the threshold so that lfs isn't used on the destination.
578 It doesn't like using '!' to unset the value on the command line.
578 It doesn't like using '!' to unset the value on the command line.
579
579
580 $ hg --config extensions.convert= --config lfs.threshold=1000M \
580 $ hg --config extensions.convert= --config lfs.threshold=1000M \
581 > convert repo8 convert_normal
581 > convert repo8 convert_normal
582 initializing destination convert_normal repository
582 initializing destination convert_normal repository
583 scanning source...
583 scanning source...
584 sorting...
584 sorting...
585 converting...
585 converting...
586 2 a
586 2 a
587 1 b
587 1 b
588 0 meta
588 0 meta
589 $ grep 'lfs' convert_normal/.hg/requires
589 $ grep 'lfs' convert_normal/.hg/requires
590 [1]
590 [1]
591 $ hg --cwd convert_normal debugdata a1 0
591 $ hg --cwd convert_normal debugdata a1 0
592 THIS-IS-LFS-BECAUSE-10-BYTES
592 THIS-IS-LFS-BECAUSE-10-BYTES
593
593
594 $ hg --config extensions.convert= --config lfs.threshold=10B \
594 $ hg --config extensions.convert= --config lfs.threshold=10B \
595 > convert convert_normal convert_lfs
595 > convert convert_normal convert_lfs
596 initializing destination convert_lfs repository
596 initializing destination convert_lfs repository
597 scanning source...
597 scanning source...
598 sorting...
598 sorting...
599 converting...
599 converting...
600 2 a
600 2 a
601 1 b
601 1 b
602 0 meta
602 0 meta
603 $ hg --cwd convert_lfs debugdata a1 0
603 $ hg --cwd convert_lfs debugdata a1 0
604 version https://git-lfs.github.com/spec/v1
604 version https://git-lfs.github.com/spec/v1
605 oid sha256:5bb8341bee63b3649f222b2215bde37322bea075a30575aa685d8f8d21c77024
605 oid sha256:5bb8341bee63b3649f222b2215bde37322bea075a30575aa685d8f8d21c77024
606 size 29
606 size 29
607 x-is-binary 0
607 x-is-binary 0
608 $ grep 'lfs' convert_lfs/.hg/requires
608 $ grep 'lfs' convert_lfs/.hg/requires
609 lfs
609 lfs
610
610
611 This convert is trickier, because it contains deleted files (via `hg mv`)
611 This convert is trickier, because it contains deleted files (via `hg mv`)
612
612
613 $ hg --config extensions.convert= --config lfs.threshold=1000M \
613 $ hg --config extensions.convert= --config lfs.threshold=1000M \
614 > convert repo3 convert_normal2
614 > convert repo3 convert_normal2
615 initializing destination convert_normal2 repository
615 initializing destination convert_normal2 repository
616 scanning source...
616 scanning source...
617 sorting...
617 sorting...
618 converting...
618 converting...
619 4 commit with lfs content
619 4 commit with lfs content
620 3 renames
620 3 renames
621 2 large to small, small to large
621 2 large to small, small to large
622 1 random modifications
622 1 random modifications
623 0 switch large and small again
623 0 switch large and small again
624 $ grep 'lfs' convert_normal2/.hg/requires
624 $ grep 'lfs' convert_normal2/.hg/requires
625 [1]
625 [1]
626 $ hg --cwd convert_normal2 debugdata large 0
626 $ hg --cwd convert_normal2 debugdata large 0
627 LONGER-THAN-TEN-BYTES-WILL-TRIGGER-LFS
627 LONGER-THAN-TEN-BYTES-WILL-TRIGGER-LFS
628
628
629 $ hg --config extensions.convert= --config lfs.threshold=10B \
629 $ hg --config extensions.convert= --config lfs.threshold=10B \
630 > convert convert_normal2 convert_lfs2
630 > convert convert_normal2 convert_lfs2
631 initializing destination convert_lfs2 repository
631 initializing destination convert_lfs2 repository
632 scanning source...
632 scanning source...
633 sorting...
633 sorting...
634 converting...
634 converting...
635 4 commit with lfs content
635 4 commit with lfs content
636 3 renames
636 3 renames
637 2 large to small, small to large
637 2 large to small, small to large
638 1 random modifications
638 1 random modifications
639 0 switch large and small again
639 0 switch large and small again
640 $ grep 'lfs' convert_lfs2/.hg/requires
640 $ grep 'lfs' convert_lfs2/.hg/requires
641 lfs
641 lfs
642 $ hg --cwd convert_lfs2 debugdata large 0
642 $ hg --cwd convert_lfs2 debugdata large 0
643 version https://git-lfs.github.com/spec/v1
643 version https://git-lfs.github.com/spec/v1
644 oid sha256:66100b384bf761271b407d79fc30cdd0554f3b2c5d944836e936d584b88ce88e
644 oid sha256:66100b384bf761271b407d79fc30cdd0554f3b2c5d944836e936d584b88ce88e
645 size 39
645 size 39
646 x-is-binary 0
646 x-is-binary 0
647
648 $ hg -R convert_lfs2 config --debug extensions | grep lfs
649 $TESTTMP/convert_lfs2/.hg/hgrc:*: extensions.lfs= (glob)
General Comments 0
You need to be logged in to leave comments. Login now