comparison tests/test-lfs.t @ 35098:66c5a8cf2868

lfs: import the Facebook git-lfs client extension The purpose of this is the same as the built-in largefiles extension- to handle huge files outside of the normal storage system, generally to keep the amount of data cloned to a lower amount. There are several benefits of implementing the git-lfs protocol, instead of using the largefiles extension: - Bitbucket and Github support (and probably wider support in 3rd party hosting sites in general). [1][2] - The number of hg internals monkey patched are several orders of magnitude lower, so it will be easier to reason about and maintain. Future commands will likely just work, without requiring various wrappers. - The "standin" files are only written to the filelog, not the disk. That should avoid weird edge cases where the largefile and standin files get out of sync. [3] It also avoids the occasional printing of the "hidden" standin file in various messages. - Filesets like size() will work, even if the file isn't present. (It always says 41 bytes for largefiles, whether present or not.) The only place that I see where largefiles comes out on top is that it works with `hg serve` for simple sharing, without external infrastructure. Getting lfs-test-server working was a hassle, and took awhile to figure out. Maybe we can do something to make it work in the future. Long term, I expect that this will be highly preferred over largefiles. But if we are to recommend this to largefile users, there are some UI issues to bikeshed. Until they are resolved, I've marked this experimental, and am not putting a pointer to this in the largefiles help. The (non exhaustive) list of issues I've seen so far are: - It isn't sufficient to just enable the largefiles extension- you have to explicitly add a file with --large before it will pay attention to the configured sizes and patterns on future adds. The justification being that once you use it, you're stuck with it. I've seen people confused by this, and haven't liked it myself. But it's also saved me a few times. Should we do something like have a specific enabling config setting that must be set in the local repo config, so that enabling this extension in the user or system hgrc doesn't silently start storing lfs files? - The largefiles extension adds a repo requirement when the first largefile is committed, so that the extension must always be enabled in the future. This extension is not doing that, and since I only enabled it locally to avoid infecting other repos, I got a cryptic error about missing flag processors when I cloned. Is there no repo requirement due to shallow/narrow clone considerations (or other future advanced things)? - In the (small amount of) reading I've done about the git implementation, it seems that the files and sizes are stored in a tracked .gitattributes file. I think a tracked file for this would be extremely useful for consistency across developers, but this kind of touches on the tracked hgrc file proposal a few months back. - The git client can specify file patterns, not just sizes. - The largefiles extension has a cache directory in the local repo, but also a system wide one. We should probably implement a system wide cache too, so that multiple clones don't have to refetch the files from the server. - Jun mentioned other missing features, like SSH authentication, gc, etc. The code corresponds to c0492b73c7ef in hg-experimental. [4] The only tweaks are to load the extension in the tests with 'lfs=' instead of 'lfs=$TESTDIR/../hgext3rd/lfs', change the import in the *.py test to hgext (from hgext3rd), add the 'testedwith' declaration, and mark it experimental for now. The infinite-push, p4fastimport, and remotefilelog tests were left behind. The devel-warnings for unregistered config options are not corrected yet, nor are the import check warnings. [1] https://www.mercurial-scm.org/pipermail/mercurial/2017-November/050699.html [2] https://bitbucket.org/site/master/issues/3843/largefiles-support-bb-3903 [3] https://bz.mercurial-scm.org/show_bug.cgi?id=5738 [4] https://bitbucket.org/facebook/hg-experimental
author Matt Harbison <matt_harbison@yahoo.com>
date Tue, 14 Nov 2017 00:06:23 -0500
parents
children eb4241f914a3
comparison
equal deleted inserted replaced
35097:fc0f3ed071fc 35098:66c5a8cf2868
1 # Initial setup
2
3 $ cat >> $HGRCPATH << EOF
4 > [extensions]
5 > lfs=
6 > [lfs]
7 > threshold=1000B
8 > EOF
9
10 $ LONG=AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
11
12 # Prepare server and enable extension
13 $ hg init server
14 $ hg clone -q server client
15 $ cd client
16
17 # Commit small file
18 $ echo s > smallfile
19 $ hg commit -Aqm "add small file"
20
21 # Commit large file
22 $ echo $LONG > largefile
23 $ hg commit --traceback -Aqm "add large file"
24
25 # Ensure metadata is stored
26 $ hg debugdata largefile 0
27 version https://git-lfs.github.com/spec/v1
28 oid sha256:f11e77c257047a398492d8d6cb9f6acf3aa7c4384bb23080b43546053e183e4b
29 size 1501
30 x-is-binary 0
31
32 # Check the blobstore is populated
33 $ find .hg/store/lfs/objects | sort
34 .hg/store/lfs/objects
35 .hg/store/lfs/objects/f1
36 .hg/store/lfs/objects/f1/1e77c257047a398492d8d6cb9f6acf3aa7c4384bb23080b43546053e183e4b
37
38 # Check the blob stored contains the actual contents of the file
39 $ cat .hg/store/lfs/objects/f1/1e77c257047a398492d8d6cb9f6acf3aa7c4384bb23080b43546053e183e4b
40 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
41
42 # Push changes to the server
43
44 $ hg push
45 pushing to $TESTTMP/server (glob)
46 searching for changes
47 abort: lfs.url needs to be configured
48 [255]
49
50 $ cat >> $HGRCPATH << EOF
51 > [lfs]
52 > url=file:$TESTTMP/dummy-remote/
53 > EOF
54
55 $ hg push -v | egrep -v '^(uncompressed| )'
56 pushing to $TESTTMP/server (glob)
57 searching for changes
58 2 changesets found
59 adding changesets
60 adding manifests
61 adding file changes
62 added 2 changesets with 2 changes to 2 files
63
64 # Unknown URL scheme
65
66 $ hg push --config lfs.url=ftp://foobar
67 abort: lfs: unknown url scheme: ftp
68 [255]
69
70 $ cd ../
71
72 # Initialize new client (not cloning) and setup extension
73 $ hg init client2
74 $ cd client2
75 $ cat >> .hg/hgrc <<EOF
76 > [paths]
77 > default = $TESTTMP/server
78 > EOF
79
80 # Pull from server
81 $ hg pull default
82 pulling from $TESTTMP/server (glob)
83 requesting all changes
84 adding changesets
85 adding manifests
86 adding file changes
87 added 2 changesets with 2 changes to 2 files
88 new changesets b29ba743f89d:00c137947d30
89 (run 'hg update' to get a working copy)
90
91 # Check the blobstore is not yet populated
92 $ [ -d .hg/store/lfs/objects ]
93 [1]
94
95 # Update to the last revision containing the large file
96 $ hg update
97 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
98
99 # Check the blobstore has been populated on update
100 $ find .hg/store/lfs/objects | sort
101 .hg/store/lfs/objects
102 .hg/store/lfs/objects/f1
103 .hg/store/lfs/objects/f1/1e77c257047a398492d8d6cb9f6acf3aa7c4384bb23080b43546053e183e4b
104
105 # Check the contents of the file are fetched from blobstore when requested
106 $ hg cat -r . largefile
107 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
108
109 # Check the file has been copied in the working copy
110 $ cat largefile
111 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
112
113 $ cd ..
114
115 # Check rename, and switch between large and small files
116
117 $ hg init repo3
118 $ cd repo3
119 $ cat >> .hg/hgrc << EOF
120 > [lfs]
121 > threshold=10B
122 > EOF
123
124 $ echo LONGER-THAN-TEN-BYTES-WILL-TRIGGER-LFS > large
125 $ echo SHORTER > small
126 $ hg add . -q
127 $ hg commit -m 'commit with lfs content'
128
129 $ hg mv large l
130 $ hg mv small s
131 $ hg commit -m 'renames'
132
133 $ echo SHORT > l
134 $ echo BECOME-LARGER-FROM-SHORTER > s
135 $ hg commit -m 'large to small, small to large'
136
137 $ echo 1 >> l
138 $ echo 2 >> s
139 $ hg commit -m 'random modifications'
140
141 $ echo RESTORE-TO-BE-LARGE > l
142 $ echo SHORTER > s
143 $ hg commit -m 'switch large and small again'
144
145 # Test lfs_files template
146
147 $ hg log -r 'all()' -T '{rev} {join(lfs_files, ", ")}\n'
148 0 large
149 1 l
150 2 s
151 3 s
152 4 l
153
154 # Push and pull the above repo
155
156 $ hg --cwd .. init repo4
157 $ hg push ../repo4
158 pushing to ../repo4
159 searching for changes
160 adding changesets
161 adding manifests
162 adding file changes
163 added 5 changesets with 10 changes to 4 files
164
165 $ hg --cwd .. init repo5
166 $ hg --cwd ../repo5 pull ../repo3
167 pulling from ../repo3
168 requesting all changes
169 adding changesets
170 adding manifests
171 adding file changes
172 added 5 changesets with 10 changes to 4 files
173 new changesets fd47a419c4f7:5adf850972b9
174 (run 'hg update' to get a working copy)
175
176 $ cd ..
177
178 # Test clone
179
180 $ hg init repo6
181 $ cd repo6
182 $ cat >> .hg/hgrc << EOF
183 > [lfs]
184 > threshold=30B
185 > EOF
186
187 $ echo LARGE-BECAUSE-IT-IS-MORE-THAN-30-BYTES > large
188 $ echo SMALL > small
189 $ hg commit -Aqm 'create a lfs file' large small
190 $ hg debuglfsupload -r 'all()' -v
191
192 $ cd ..
193
194 $ hg clone repo6 repo7
195 updating to branch default
196 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
197 $ cd repo7
198 $ cat large
199 LARGE-BECAUSE-IT-IS-MORE-THAN-30-BYTES
200 $ cat small
201 SMALL
202
203 $ cd ..
204
205 # Test rename and status
206
207 $ hg init repo8
208 $ cd repo8
209 $ cat >> .hg/hgrc << EOF
210 > [lfs]
211 > threshold=10B
212 > EOF
213
214 $ echo THIS-IS-LFS-BECAUSE-10-BYTES > a1
215 $ echo SMALL > a2
216 $ hg commit -m a -A a1 a2
217 $ hg status
218 $ hg mv a1 b1
219 $ hg mv a2 a1
220 $ hg mv b1 a2
221 $ hg commit -m b
222 $ hg status
223 $ HEADER=$'\1\n'
224 $ printf '%sSTART-WITH-HG-FILELOG-METADATA' "$HEADER" > a2
225 $ printf '%sMETA\n' "$HEADER" > a1
226 $ hg commit -m meta
227 $ hg status
228 $ hg log -T '{rev}: {file_copies} | {file_dels} | {file_adds}\n'
229 2: | |
230 1: a1 (a2)a2 (a1) | |
231 0: | | a1 a2
232
233 $ for n in a1 a2; do
234 > for r in 0 1 2; do
235 > printf '\n%s @ %s\n' $n $r
236 > hg debugdata $n $r
237 > done
238 > done
239
240 a1 @ 0
241 version https://git-lfs.github.com/spec/v1
242 oid sha256:5bb8341bee63b3649f222b2215bde37322bea075a30575aa685d8f8d21c77024
243 size 29
244 x-is-binary 0
245
246 a1 @ 1
247 \x01 (esc)
248 copy: a2
249 copyrev: 50470ad23cf937b1f4b9f80bfe54df38e65b50d9
250 \x01 (esc)
251 SMALL
252
253 a1 @ 2
254 \x01 (esc)
255 \x01 (esc)
256 \x01 (esc)
257 META
258
259 a2 @ 0
260 SMALL
261
262 a2 @ 1
263 version https://git-lfs.github.com/spec/v1
264 oid sha256:5bb8341bee63b3649f222b2215bde37322bea075a30575aa685d8f8d21c77024
265 size 29
266 x-hg-copy a1
267 x-hg-copyrev be23af27908a582af43e5cda209a5a9b319de8d4
268 x-is-binary 0
269
270 a2 @ 2
271 version https://git-lfs.github.com/spec/v1
272 oid sha256:876dadc86a8542f9798048f2c47f51dbf8e4359aed883e8ec80c5db825f0d943
273 size 32
274 x-is-binary 0
275
276 # Verify commit hashes include rename metadata
277
278 $ hg log -T '{rev}:{node|short} {desc}\n'
279 2:0fae949de7fa meta
280 1:9cd6bdffdac0 b
281 0:7f96794915f7 a
282
283 $ cd ..
284
285 # Test bundle
286
287 $ hg init repo9
288 $ cd repo9
289 $ cat >> .hg/hgrc << EOF
290 > [lfs]
291 > threshold=10B
292 > [diff]
293 > git=1
294 > EOF
295
296 $ for i in 0 single two three 4; do
297 > echo 'THIS-IS-LFS-'$i > a
298 > hg commit -m a-$i -A a
299 > done
300
301 $ hg update 2 -q
302 $ echo 'THIS-IS-LFS-2-CHILD' > a
303 $ hg commit -m branching -q
304
305 $ hg bundle --base 1 bundle.hg -v
306 4 changesets found
307 uncompressed size of bundle content:
308 * (changelog) (glob)
309 * (manifests) (glob)
310 * a (glob)
311 $ hg --config extensions.strip= strip -r 2 --no-backup --force -q
312 $ hg -R bundle.hg log -p -T '{rev} {desc}\n' a
313 5 branching
314 diff --git a/a b/a
315 --- a/a
316 +++ b/a
317 @@ -1,1 +1,1 @@
318 -THIS-IS-LFS-two
319 +THIS-IS-LFS-2-CHILD
320
321 4 a-4
322 diff --git a/a b/a
323 --- a/a
324 +++ b/a
325 @@ -1,1 +1,1 @@
326 -THIS-IS-LFS-three
327 +THIS-IS-LFS-4
328
329 3 a-three
330 diff --git a/a b/a
331 --- a/a
332 +++ b/a
333 @@ -1,1 +1,1 @@
334 -THIS-IS-LFS-two
335 +THIS-IS-LFS-three
336
337 2 a-two
338 diff --git a/a b/a
339 --- a/a
340 +++ b/a
341 @@ -1,1 +1,1 @@
342 -THIS-IS-LFS-single
343 +THIS-IS-LFS-two
344
345 1 a-single
346 diff --git a/a b/a
347 --- a/a
348 +++ b/a
349 @@ -1,1 +1,1 @@
350 -THIS-IS-LFS-0
351 +THIS-IS-LFS-single
352
353 0 a-0
354 diff --git a/a b/a
355 new file mode 100644
356 --- /dev/null
357 +++ b/a
358 @@ -0,0 +1,1 @@
359 +THIS-IS-LFS-0
360
361 $ hg bundle -R bundle.hg --base 1 bundle-again.hg -q
362 $ hg -R bundle-again.hg log -p -T '{rev} {desc}\n' a
363 5 branching
364 diff --git a/a b/a
365 --- a/a
366 +++ b/a
367 @@ -1,1 +1,1 @@
368 -THIS-IS-LFS-two
369 +THIS-IS-LFS-2-CHILD
370
371 4 a-4
372 diff --git a/a b/a
373 --- a/a
374 +++ b/a
375 @@ -1,1 +1,1 @@
376 -THIS-IS-LFS-three
377 +THIS-IS-LFS-4
378
379 3 a-three
380 diff --git a/a b/a
381 --- a/a
382 +++ b/a
383 @@ -1,1 +1,1 @@
384 -THIS-IS-LFS-two
385 +THIS-IS-LFS-three
386
387 2 a-two
388 diff --git a/a b/a
389 --- a/a
390 +++ b/a
391 @@ -1,1 +1,1 @@
392 -THIS-IS-LFS-single
393 +THIS-IS-LFS-two
394
395 1 a-single
396 diff --git a/a b/a
397 --- a/a
398 +++ b/a
399 @@ -1,1 +1,1 @@
400 -THIS-IS-LFS-0
401 +THIS-IS-LFS-single
402
403 0 a-0
404 diff --git a/a b/a
405 new file mode 100644
406 --- /dev/null
407 +++ b/a
408 @@ -0,0 +1,1 @@
409 +THIS-IS-LFS-0
410
411 $ cd ..
412
413 # Test isbinary
414
415 $ hg init repo10
416 $ cd repo10
417 $ cat >> .hg/hgrc << EOF
418 > [extensions]
419 > lfs=
420 > [lfs]
421 > threshold=1
422 > EOF
423 $ $PYTHON <<'EOF'
424 > def write(path, content):
425 > with open(path, 'wb') as f:
426 > f.write(content)
427 > write('a', b'\0\0')
428 > write('b', b'\1\n')
429 > write('c', b'\1\n\0')
430 > write('d', b'xx')
431 > EOF
432 $ hg add a b c d
433 $ hg diff --stat
434 a | Bin
435 b | 1 +
436 c | Bin
437 d | 1 +
438 4 files changed, 2 insertions(+), 0 deletions(-)
439 $ hg commit -m binarytest
440 $ cat > $TESTTMP/dumpbinary.py << EOF
441 > def reposetup(ui, repo):
442 > for n in 'abcd':
443 > ui.write(('%s: binary=%s\n') % (n, repo['.'][n].isbinary()))
444 > EOF
445 $ hg --config extensions.dumpbinary=$TESTTMP/dumpbinary.py id --trace
446 a: binary=True
447 b: binary=False
448 c: binary=True
449 d: binary=False
450 b55353847f02 tip
451
452 $ cd ..
453
454 # Test fctx.cmp fastpath - diff without LFS blobs
455
456 $ hg init repo11
457 $ cd repo11
458 $ cat >> .hg/hgrc <<EOF
459 > [lfs]
460 > threshold=1
461 > EOF
462 $ for i in 1 2 3; do
463 > cp ../repo10/a a
464 > if [ $i = 3 ]; then
465 > # make a content-only change
466 > chmod +x a
467 > i=2
468 > fi
469 > echo $i >> a
470 > hg commit -m $i -A a
471 > done
472 $ [ -d .hg/store/lfs/objects ]
473
474 $ cd ..
475
476 $ hg clone repo11 repo12 --noupdate
477 $ cd repo12
478 $ hg log --removed -p a -T '{desc}\n' --config diff.nobinary=1 --git
479 2
480 diff --git a/a b/a
481 old mode 100644
482 new mode 100755
483
484 2
485 diff --git a/a b/a
486 Binary file a has changed
487
488 1
489 diff --git a/a b/a
490 new file mode 100644
491 Binary file a has changed
492
493 $ [ -d .hg/store/lfs/objects ]
494 [1]
495
496 $ cd ..
497
498 # Verify the repos
499
500 $ cat > $TESTTMP/dumpflog.py << EOF
501 > # print raw revision sizes, flags, and hashes for certain files
502 > import hashlib
503 > from mercurial import revlog
504 > from mercurial.node import short
505 > def hash(rawtext):
506 > h = hashlib.sha512()
507 > h.update(rawtext)
508 > return h.hexdigest()[:4]
509 > def reposetup(ui, repo):
510 > # these 2 files are interesting
511 > for name in ['l', 's']:
512 > fl = repo.file(name)
513 > if len(fl) == 0:
514 > continue
515 > sizes = [revlog.revlog.rawsize(fl, i) for i in fl]
516 > texts = [fl.revision(i, raw=True) for i in fl]
517 > flags = [fl.flags(i) for i in fl]
518 > hashes = [hash(t) for t in texts]
519 > print(' %s: rawsizes=%r flags=%r hashes=%r'
520 > % (name, sizes, flags, hashes))
521 > EOF
522
523 $ for i in client client2 server repo3 repo4 repo5 repo6 repo7 repo8 repo9 \
524 > repo10; do
525 > echo 'repo:' $i
526 > hg --cwd $i verify --config extensions.dumpflog=$TESTTMP/dumpflog.py -q
527 > done
528 repo: client
529 repo: client2
530 repo: server
531 repo: repo3
532 l: rawsizes=[211, 6, 8, 141] flags=[8192, 0, 0, 8192] hashes=['d2b8', '948c', 'cc88', '724d']
533 s: rawsizes=[74, 141, 141, 8] flags=[0, 8192, 8192, 0] hashes=['3c80', 'fce0', '874a', '826b']
534 repo: repo4
535 l: rawsizes=[211, 6, 8, 141] flags=[8192, 0, 0, 8192] hashes=['d2b8', '948c', 'cc88', '724d']
536 s: rawsizes=[74, 141, 141, 8] flags=[0, 8192, 8192, 0] hashes=['3c80', 'fce0', '874a', '826b']
537 repo: repo5
538 l: rawsizes=[211, 6, 8, 141] flags=[8192, 0, 0, 8192] hashes=['d2b8', '948c', 'cc88', '724d']
539 s: rawsizes=[74, 141, 141, 8] flags=[0, 8192, 8192, 0] hashes=['3c80', 'fce0', '874a', '826b']
540 repo: repo6
541 repo: repo7
542 repo: repo8
543 repo: repo9
544 repo: repo10