##// END OF EJS Templates
lfs: add the 'lfs' requirement in the changegroup transaction introducing lfs...
Matt Harbison -
r35520:6bb940de default
parent child Browse files
Show More
@@ -1,205 +1,214 b''
1 1 # lfs - hash-preserving large file support using Git-LFS protocol
2 2 #
3 3 # Copyright 2017 Facebook, Inc.
4 4 #
5 5 # This software may be used and distributed according to the terms of the
6 6 # GNU General Public License version 2 or any later version.
7 7
8 8 """lfs - large file support (EXPERIMENTAL)
9 9
10 10 Configs::
11 11
12 12 [lfs]
13 13 # Remote endpoint. Multiple protocols are supported:
14 14 # - http(s)://user:pass@example.com/path
15 15 # git-lfs endpoint
16 16 # - file:///tmp/path
17 17 # local filesystem, usually for testing
18 18 # if unset, lfs will prompt setting this when it must use this value.
19 19 # (default: unset)
20 20 url = https://example.com/lfs
21 21
22 22 # size of a file to make it use LFS
23 23 threshold = 10M
24 24
25 25 # how many times to retry before giving up on transferring an object
26 26 retry = 5
27 27
28 28 # the local directory to store lfs files for sharing across local clones.
29 29 # If not set, the cache is located in an OS specific cache location.
30 30 usercache = /path/to/global/cache
31 31 """
32 32
33 33 from __future__ import absolute_import
34 34
35 35 from mercurial.i18n import _
36 36
37 37 from mercurial import (
38 38 bundle2,
39 39 changegroup,
40 40 context,
41 41 exchange,
42 42 extensions,
43 43 filelog,
44 44 hg,
45 45 localrepo,
46 node,
46 47 registrar,
47 48 revlog,
48 49 scmutil,
49 50 upgrade,
50 51 vfs as vfsmod,
51 52 )
52 53
53 54 from . import (
54 55 blobstore,
55 56 wrapper,
56 57 )
57 58
58 59 # Note for extension authors: ONLY specify testedwith = 'ships-with-hg-core' for
59 60 # extensions which SHIP WITH MERCURIAL. Non-mainline extensions should
60 61 # be specifying the version(s) of Mercurial they are tested with, or
61 62 # leave the attribute unspecified.
62 63 testedwith = 'ships-with-hg-core'
63 64
64 65 configtable = {}
65 66 configitem = registrar.configitem(configtable)
66 67
67 68 configitem('experimental', 'lfs.user-agent',
68 69 default=None,
69 70 )
70 71
71 72 configitem('lfs', 'url',
72 73 default=configitem.dynamicdefault,
73 74 )
74 75 configitem('lfs', 'usercache',
75 76 default=None,
76 77 )
77 78 configitem('lfs', 'threshold',
78 79 default=None,
79 80 )
80 81 configitem('lfs', 'retry',
81 82 default=5,
82 83 )
83 84 # Deprecated
84 85 configitem('lfs', 'remotestore',
85 86 default=None,
86 87 )
87 88 # Deprecated
88 89 configitem('lfs', 'dummy',
89 90 default=None,
90 91 )
91 92 # Deprecated
92 93 configitem('lfs', 'git-lfs',
93 94 default=None,
94 95 )
95 96
96 97 cmdtable = {}
97 98 command = registrar.command(cmdtable)
98 99
99 100 templatekeyword = registrar.templatekeyword()
100 101
101 102 def featuresetup(ui, supported):
102 103 # don't die on seeing a repo with the lfs requirement
103 104 supported |= {'lfs'}
104 105
105 106 def uisetup(ui):
106 107 localrepo.localrepository.featuresetupfuncs.add(featuresetup)
107 108
108 109 def reposetup(ui, repo):
109 110 # Nothing to do with a remote repo
110 111 if not repo.local():
111 112 return
112 113
113 114 threshold = repo.ui.configbytes('lfs', 'threshold')
114 115
115 116 repo.svfs.options['lfsthreshold'] = threshold
116 117 repo.svfs.lfslocalblobstore = blobstore.local(repo)
117 118 repo.svfs.lfsremoteblobstore = blobstore.remote(repo)
118 119
119 120 # Push hook
120 121 repo.prepushoutgoinghooks.add('lfs', wrapper.prepush)
121 122
122 123 if 'lfs' not in repo.requirements:
123 124 def checkrequireslfs(ui, repo, **kwargs):
124 125 if 'lfs' not in repo.requirements:
125 ctx = repo[kwargs['node']]
126 last = kwargs.get('node_last')
127 _bin = node.bin
128 if last:
129 s = repo.set('%n:%n', _bin(kwargs['node']), _bin(last))
130 else:
131 s = repo.set('%n', _bin(kwargs['node']))
132 for ctx in s:
126 133 # TODO: is there a way to just walk the files in the commit?
127 134 if any(ctx[f].islfs() for f in ctx.files() if f in ctx):
128 135 repo.requirements.add('lfs')
129 136 repo._writerequirements()
137 break
130 138
131 139 ui.setconfig('hooks', 'commit.lfs', checkrequireslfs, 'lfs')
140 ui.setconfig('hooks', 'pretxnchangegroup.lfs', checkrequireslfs, 'lfs')
132 141
133 142 def wrapfilelog(filelog):
134 143 wrapfunction = extensions.wrapfunction
135 144
136 145 wrapfunction(filelog, 'addrevision', wrapper.filelogaddrevision)
137 146 wrapfunction(filelog, 'renamed', wrapper.filelogrenamed)
138 147 wrapfunction(filelog, 'size', wrapper.filelogsize)
139 148
140 149 def extsetup(ui):
141 150 wrapfilelog(filelog.filelog)
142 151
143 152 wrapfunction = extensions.wrapfunction
144 153
145 154 wrapfunction(scmutil, 'wrapconvertsink', wrapper.convertsink)
146 155
147 156 wrapfunction(upgrade, '_finishdatamigration',
148 157 wrapper.upgradefinishdatamigration)
149 158
150 159 wrapfunction(upgrade, 'preservedrequirements',
151 160 wrapper.upgraderequirements)
152 161
153 162 wrapfunction(upgrade, 'supporteddestrequirements',
154 163 wrapper.upgraderequirements)
155 164
156 165 wrapfunction(changegroup,
157 166 'supportedoutgoingversions',
158 167 wrapper.supportedoutgoingversions)
159 168 wrapfunction(changegroup,
160 169 'allsupportedversions',
161 170 wrapper.allsupportedversions)
162 171
163 172 wrapfunction(context.basefilectx, 'cmp', wrapper.filectxcmp)
164 173 wrapfunction(context.basefilectx, 'isbinary', wrapper.filectxisbinary)
165 174 context.basefilectx.islfs = wrapper.filectxislfs
166 175
167 176 revlog.addflagprocessor(
168 177 revlog.REVIDX_EXTSTORED,
169 178 (
170 179 wrapper.readfromstore,
171 180 wrapper.writetostore,
172 181 wrapper.bypasscheckhash,
173 182 ),
174 183 )
175 184
176 185 wrapfunction(hg, 'clone', wrapper.hgclone)
177 186 wrapfunction(hg, 'postshare', wrapper.hgpostshare)
178 187
179 188 # Make bundle choose changegroup3 instead of changegroup2. This affects
180 189 # "hg bundle" command. Note: it does not cover all bundle formats like
181 190 # "packed1". Using "packed1" with lfs will likely cause trouble.
182 191 names = [k for k, v in exchange._bundlespeccgversions.items() if v == '02']
183 192 for k in names:
184 193 exchange._bundlespeccgversions[k] = '03'
185 194
186 195 # bundlerepo uses "vfsmod.readonlyvfs(othervfs)", we need to make sure lfs
187 196 # options and blob stores are passed from othervfs to the new readonlyvfs.
188 197 wrapfunction(vfsmod.readonlyvfs, '__init__', wrapper.vfsinit)
189 198
190 199 # when writing a bundle via "hg bundle" command, upload related LFS blobs
191 200 wrapfunction(bundle2, 'writenewbundle', wrapper.writenewbundle)
192 201
193 202 @templatekeyword('lfs_files')
194 203 def lfsfiles(repo, ctx, **args):
195 204 """List of strings. LFS files added or modified by the changeset."""
196 205 pointers = wrapper.pointersfromctx(ctx) # {path: pointer}
197 206 return sorted(pointers.keys())
198 207
199 208 @command('debuglfsupload',
200 209 [('r', 'rev', [], _('upload large files introduced by REV'))])
201 210 def debuglfsupload(ui, repo, **opts):
202 211 """upload lfs blobs added by the working copy parent or given revisions"""
203 212 revs = opts.get('rev', [])
204 213 pointers = wrapper.extractpointers(repo, scmutil.revrange(repo, revs))
205 214 wrapper.uploadblobs(repo, pointers)
@@ -1,292 +1,299 b''
1 1 #testcases lfsremote-on lfsremote-off
2 2 #require serve
3 3
4 4 This test splits `hg serve` with and without using the extension into separate
5 5 tests cases. The tests are broken down as follows, where "LFS"/"No-LFS"
6 6 indicates whether or not there are commits that use an LFS file, and "D"/"E"
7 7 indicates whether or not the extension is loaded. The "X" cases are not tested
8 8 individually, because the lfs requirement causes the process to bail early if
9 9 the extension is disabled.
10 10
11 11 . Server
12 12 .
13 13 . No-LFS LFS
14 14 . +----------------------------+
15 15 . | || D | E | D | E |
16 16 . |---++=======================|
17 17 . C | D || N/A | #1 | X | #4 |
18 18 . l No +---++-----------------------|
19 19 . i LFS | E || #2 | #2 | X | #5 |
20 20 . e +---++-----------------------|
21 21 . n | D || X | X | X | X |
22 22 . t LFS |---++-----------------------|
23 23 . | E || #3 | #3 | X | #6 |
24 24 . |---++-----------------------+
25 25
26 26 $ hg init server
27 27 $ SERVER_REQUIRES="$TESTTMP/server/.hg/requires"
28 28
29 29 Skip the experimental.changegroup3=True config. Failure to agree on this comes
30 30 first, and causes a "ValueError: no common changegroup version" or "abort:
31 31 HTTP Error 500: Internal Server Error", if the extension is only loaded on one
32 32 side. If that *is* enabled, the subsequent failure is "abort: missing processor
33 33 for flag '0x2000'!" if the extension is only loaded on one side (possibly also
34 34 masked by the Internal Server Error message).
35 35 $ cat >> $HGRCPATH <<EOF
36 36 > [lfs]
37 37 > url=file:$TESTTMP/dummy-remote/
38 38 > threshold=10
39 39 > [web]
40 40 > allow_push=*
41 41 > push_ssl=False
42 42 > EOF
43 43
44 44 #if lfsremote-on
45 45 $ hg --config extensions.lfs= -R server \
46 46 > serve -p $HGPORT -d --pid-file=hg.pid --errorlog=$TESTTMP/errors.log
47 47 #else
48 48 $ hg --config extensions.lfs=! -R server \
49 49 > serve -p $HGPORT -d --pid-file=hg.pid --errorlog=$TESTTMP/errors.log
50 50 #endif
51 51
52 52 $ cat hg.pid >> $DAEMON_PIDS
53 53 $ hg clone -q http://localhost:$HGPORT client
54 54 $ grep 'lfs' client/.hg/requires $SERVER_REQUIRES
55 55 [1]
56 56
57 57 --------------------------------------------------------------------------------
58 58 Case #1: client with non-lfs content and the extension disabled; server with
59 59 non-lfs content, and the extension enabled.
60 60
61 61 $ cd client
62 62 $ echo 'non-lfs' > nonlfs.txt
63 63 $ hg ci -Aqm 'non-lfs'
64 64 $ grep 'lfs' .hg/requires $SERVER_REQUIRES
65 65 [1]
66 66
67 67 #if lfsremote-on
68 68
69 69 $ hg push -q
70 70 $ grep 'lfs' .hg/requires $SERVER_REQUIRES
71 71 [1]
72 72
73 73 TODO: fail more gracefully, or don't mandate changegroup3 for non-lfs repos.
74 74
75 75 $ hg clone -q http://localhost:$HGPORT $TESTTMP/client1_clone
76 76 abort: HTTP Error 500: Internal Server Error
77 77 [255]
78 78 $ grep 'lfs' $TESTTMP/client1_clone/.hg/requires $SERVER_REQUIRES
79 79 grep: $TESTTMP/client1_clone/.hg/requires: $ENOENT$
80 80 [2]
81 81
82 82 TODO: fail more gracefully, or don't mandate changegroup3 for non-lfs repos.
83 83
84 84 $ hg init $TESTTMP/client1_pull
85 85 $ hg -R $TESTTMP/client1_pull pull -q http://localhost:$HGPORT
86 86 abort: HTTP Error 500: Internal Server Error
87 87 [255]
88 88 $ grep 'lfs' $TESTTMP/client1_pull/.hg/requires $SERVER_REQUIRES
89 89 [1]
90 90
91 91 $ hg identify http://localhost:$HGPORT
92 92 d437e1d24fbd
93 93
94 94 #endif
95 95
96 96 --------------------------------------------------------------------------------
97 97 Case #2: client with non-lfs content and the extension enabled; server with
98 98 non-lfs content, and the extension state controlled by #testcases.
99 99
100 100 $ cat >> $HGRCPATH <<EOF
101 101 > [extensions]
102 102 > lfs =
103 103 > EOF
104 104 $ echo 'non-lfs' > nonlfs2.txt
105 105 $ hg ci -Aqm 'non-lfs file with lfs client'
106 106
107 107 TODO: fail more gracefully here
108 108 $ hg push -q 2>&1 | grep '^[A-Z]' || true
109 109 Traceback (most recent call last): (lfsremote-off !)
110 110 ValueError: no common changegroup version (lfsremote-off !)
111 111 $ grep 'lfs' .hg/requires $SERVER_REQUIRES
112 112 [1]
113 113
114 114 $ hg clone -q http://localhost:$HGPORT $TESTTMP/client2_clone
115 115 $ grep 'lfs' $TESTTMP/client2_clone/.hg/requires $SERVER_REQUIRES
116 116 [1]
117 117
118 118 $ hg init $TESTTMP/client2_pull
119 119 $ hg -R $TESTTMP/client2_pull pull -q http://localhost:$HGPORT
120 120 $ grep 'lfs' $TESTTMP/client2_pull/.hg/requires $SERVER_REQUIRES
121 121 [1]
122 122
123 123 XXX: The difference here is the push failed above when the extension isn't
124 124 enabled on the server. The extension shouldn't need to mess with changegroup
125 125 versions if there is no lfs content. But the requirement needs to be
126 126 consistently added before that can be ratcheted back.
127 127 $ hg identify http://localhost:$HGPORT
128 128 1477875038c6 (lfsremote-on !)
129 129 000000000000 (lfsremote-off !)
130 130
131 131 --------------------------------------------------------------------------------
132 132 Case #3: client with lfs content and the extension enabled; server with
133 non-lfs content, and the extension state controlled by #testcases.
133 non-lfs content, and the extension state controlled by #testcases. The server
134 should have an 'lfs' requirement after it picks up its first commit with a blob.
134 135
135 TODO: add the 'lfs' requirement on the server for each test in lfsremote-on
136 136 $ echo 'this is a big lfs file' > lfs.bin
137 137 $ hg ci -Aqm 'lfs'
138 138 $ grep 'lfs' .hg/requires $SERVER_REQUIRES
139 139 .hg/requires:lfs
140 140
141 141 TODO: fail more gracefully here
142 142 $ hg push -q 2>&1 | grep '^[A-Z]' || true
143 143 Traceback (most recent call last): (lfsremote-off !)
144 144 ValueError: no common changegroup version (lfsremote-off !)
145 145 $ grep 'lfs' .hg/requires $SERVER_REQUIRES
146 146 .hg/requires:lfs
147 $TESTTMP/server/.hg/requires:lfs (lfsremote-on !)
147 148
148 149 $ hg clone -q http://localhost:$HGPORT $TESTTMP/client3_clone
149 $ grep 'lfs' $TESTTMP/client3_clone/.hg/requires $SERVER_REQUIRES
150 [1]
150 $ grep 'lfs' $TESTTMP/client3_clone/.hg/requires $SERVER_REQUIRES || true
151 $TESTTMP/client3_clone/.hg/requires:lfs (lfsremote-on !)
152 $TESTTMP/server/.hg/requires:lfs (lfsremote-on !)
151 153
152 154 $ hg init $TESTTMP/client3_pull
153 155 $ hg -R $TESTTMP/client3_pull pull -q http://localhost:$HGPORT
154 $ grep 'lfs' $TESTTMP/client3_pull/.hg/requires $SERVER_REQUIRES
155 [1]
156 $ grep 'lfs' $TESTTMP/client3_pull/.hg/requires $SERVER_REQUIRES || true
157 $TESTTMP/client3_pull/.hg/requires:lfs (lfsremote-on !)
158 $TESTTMP/server/.hg/requires:lfs (lfsremote-on !)
156 159
157 160 XXX: The difference here is the push failed above when the extension isn't
158 161 enabled on the server. The extension shouldn't need to mess with changegroup
159 162 versions if there is no lfs content. But the requirement needs to be
160 163 consistently added before that can be ratcheted back.
161 164 $ hg identify http://localhost:$HGPORT
162 165 8374dc4052cb (lfsremote-on !)
163 166 000000000000 (lfsremote-off !)
164 167
165 168 Don't bother testing the lfsremote-off cases- the server won't be able
166 169 to launch if there's lfs content and the extension is disabled.
167 170
168 171 #if lfsremote-on
169 172
170 173 --------------------------------------------------------------------------------
171 174 Case #4: client with non-lfs content and the extension disabled; server with
172 175 lfs content, and the extension enabled.
173 176
174 177 $ cat >> $HGRCPATH <<EOF
175 178 > [extensions]
176 179 > lfs = !
177 180 > EOF
178 181
179 182 $ hg init $TESTTMP/client4
180 183 $ cd $TESTTMP/client4
181 184 $ cat >> .hg/hgrc <<EOF
182 185 > [paths]
183 186 > default = http://localhost:$HGPORT
184 187 > EOF
185 188 $ echo 'non-lfs' > nonlfs2.txt
186 189 $ hg ci -Aqm 'non-lfs'
187 190 $ grep 'lfs' .hg/requires $SERVER_REQUIRES
188 [1]
191 $TESTTMP/server/.hg/requires:lfs
189 192
190 193 $ hg push -q --force
191 194 warning: repository is unrelated
192 195 $ grep 'lfs' .hg/requires $SERVER_REQUIRES
193 [1]
196 $TESTTMP/server/.hg/requires:lfs
194 197
195 198 TODO: fail more gracefully.
196 199
197 200 $ hg clone -q http://localhost:$HGPORT $TESTTMP/client4_clone
198 201 abort: HTTP Error 500: Internal Server Error
199 202 [255]
200 203 $ grep 'lfs' $TESTTMP/client4_clone/.hg/requires $SERVER_REQUIRES
201 204 grep: $TESTTMP/client4_clone/.hg/requires: $ENOENT$
205 $TESTTMP/server/.hg/requires:lfs
202 206 [2]
203 207
204 208 TODO: fail more gracefully.
205 209
206 210 $ hg init $TESTTMP/client4_pull
207 211 $ hg -R $TESTTMP/client4_pull pull -q http://localhost:$HGPORT
208 212 abort: HTTP Error 500: Internal Server Error
209 213 [255]
210 214 $ grep 'lfs' $TESTTMP/client4_pull/.hg/requires $SERVER_REQUIRES
211 [1]
215 $TESTTMP/server/.hg/requires:lfs
212 216
213 217 $ hg identify http://localhost:$HGPORT
214 218 03b080fa9d93
215 219
216 220 --------------------------------------------------------------------------------
217 221 Case #5: client with non-lfs content and the extension enabled; server with
218 222 lfs content, and the extension enabled.
219 223
220 224 $ cat >> $HGRCPATH <<EOF
221 225 > [extensions]
222 226 > lfs =
223 227 > EOF
224 228 $ echo 'non-lfs' > nonlfs3.txt
225 229 $ hg ci -Aqm 'non-lfs file with lfs client'
226 230
227 231 $ hg push -q
228 232 $ grep 'lfs' .hg/requires $SERVER_REQUIRES
229 [1]
233 $TESTTMP/server/.hg/requires:lfs
230 234
231 235 $ hg clone -q http://localhost:$HGPORT $TESTTMP/client5_clone
232 236 $ grep 'lfs' $TESTTMP/client5_clone/.hg/requires $SERVER_REQUIRES
233 [1]
237 $TESTTMP/client5_clone/.hg/requires:lfs
238 $TESTTMP/server/.hg/requires:lfs
234 239
235 240 $ hg init $TESTTMP/client5_pull
236 241 $ hg -R $TESTTMP/client5_pull pull -q http://localhost:$HGPORT
237 242 $ grep 'lfs' $TESTTMP/client5_pull/.hg/requires $SERVER_REQUIRES
238 [1]
243 $TESTTMP/client5_pull/.hg/requires:lfs
244 $TESTTMP/server/.hg/requires:lfs
239 245
240 246 $ hg identify http://localhost:$HGPORT
241 247 c729025cc5e3
242 248
243 249 --------------------------------------------------------------------------------
244 250 Case #6: client with lfs content and the extension enabled; server with
245 251 lfs content, and the extension enabled.
246 252
247 TODO: add the 'lfs' requirement on the server for each test
248
249 253 $ echo 'this is another lfs file' > lfs2.txt
250 254 $ hg ci -Aqm 'lfs file with lfs client'
251 255
252 256 $ hg push -q
253 257 $ grep 'lfs' .hg/requires $SERVER_REQUIRES
254 258 .hg/requires:lfs
259 $TESTTMP/server/.hg/requires:lfs
255 260
256 261 $ hg clone -q http://localhost:$HGPORT $TESTTMP/client6_clone
257 262 $ grep 'lfs' $TESTTMP/client6_clone/.hg/requires $SERVER_REQUIRES
258 [1]
263 $TESTTMP/client6_clone/.hg/requires:lfs
264 $TESTTMP/server/.hg/requires:lfs
259 265
260 266 $ hg init $TESTTMP/client6_pull
261 267 $ hg -R $TESTTMP/client6_pull pull -q http://localhost:$HGPORT
262 268 $ grep 'lfs' $TESTTMP/client6_pull/.hg/requires $SERVER_REQUIRES
263 [1]
269 $TESTTMP/client6_pull/.hg/requires:lfs
270 $TESTTMP/server/.hg/requires:lfs
264 271
265 272 $ hg identify http://localhost:$HGPORT
266 273 d3b84d50eacb
267 274
268 275 --------------------------------------------------------------------------------
269 276 Misc: process dies early if a requirement exists and the extension is disabled
270 277
271 278 $ hg --config extensions.lfs=! summary
272 279 abort: repository requires features unknown to this Mercurial: lfs!
273 280 (see https://mercurial-scm.org/wiki/MissingRequirement for more information)
274 281 [255]
275 282
276 283 #endif
277 284
278 285 $ $PYTHON $TESTDIR/killdaemons.py $DAEMON_PIDS
279 286
280 287 #if lfsremote-on
281 288 $ cat $TESTTMP/errors.log | grep '^[A-Z]'
282 289 Traceback (most recent call last):
283 290 ValueError: no common changegroup version
284 291 Traceback (most recent call last):
285 292 ValueError: no common changegroup version
286 293 Traceback (most recent call last):
287 294 ValueError: no common changegroup version
288 295 Traceback (most recent call last):
289 296 ValueError: no common changegroup version
290 297 #else
291 298 $ cat $TESTTMP/errors.log
292 299 #endif
@@ -1,187 +1,188 b''
1 1 #require lfs-test-server
2 2
3 3 $ LFS_LISTEN="tcp://:$HGPORT"
4 4 $ LFS_HOST="localhost:$HGPORT"
5 5 $ LFS_PUBLIC=1
6 6 $ export LFS_LISTEN LFS_HOST LFS_PUBLIC
7 7 #if no-windows
8 8 $ lfs-test-server &> lfs-server.log &
9 9 $ echo $! >> $DAEMON_PIDS
10 10 #else
11 11 $ cat >> $TESTTMP/spawn.py <<EOF
12 12 > import os
13 13 > import subprocess
14 14 > import sys
15 15 >
16 16 > for path in os.environ["PATH"].split(os.pathsep):
17 17 > exe = os.path.join(path, 'lfs-test-server.exe')
18 18 > if os.path.exists(exe):
19 19 > with open('lfs-server.log', 'wb') as out:
20 20 > p = subprocess.Popen(exe, stdout=out, stderr=out)
21 21 > sys.stdout.write('%s\n' % p.pid)
22 22 > sys.exit(0)
23 23 > sys.exit(1)
24 24 > EOF
25 25 $ $PYTHON $TESTTMP/spawn.py >> $DAEMON_PIDS
26 26 #endif
27 27
28 28 $ cat >> $HGRCPATH <<EOF
29 29 > [extensions]
30 30 > lfs=
31 31 > [lfs]
32 32 > url=http://foo:bar@$LFS_HOST/
33 33 > threshold=1
34 34 > EOF
35 35
36 36 $ hg init repo1
37 37 $ cd repo1
38 38 $ echo THIS-IS-LFS > a
39 39 $ hg commit -m a -A a
40 40
41 41 $ hg init ../repo2
42 42 $ hg push ../repo2 -v
43 43 pushing to ../repo2
44 44 searching for changes
45 45 lfs: uploading 31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b (12 bytes)
46 46 lfs: processed: 31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b
47 47 1 changesets found
48 48 uncompressed size of bundle content:
49 49 * (changelog) (glob)
50 50 * (manifests) (glob)
51 51 * a (glob)
52 52 adding changesets
53 53 adding manifests
54 54 adding file changes
55 55 added 1 changesets with 1 changes to 1 files
56 calling hook pretxnchangegroup.lfs: hgext.lfs.checkrequireslfs
56 57
57 58 Clear the cache to force a download
58 59 $ rm -rf `hg config lfs.usercache`
59 60 $ cd ../repo2
60 61 $ hg update tip -v
61 62 resolving manifests
62 63 getting a
63 64 lfs: downloading 31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b (12 bytes)
64 65 lfs: adding 31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b to the usercache
65 66 lfs: processed: 31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b
66 67 lfs: found 31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b in the local lfs store
67 68 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
68 69
69 70 When the server has some blobs already
70 71
71 72 $ hg mv a b
72 73 $ echo ANOTHER-LARGE-FILE > c
73 74 $ echo ANOTHER-LARGE-FILE2 > d
74 75 $ hg commit -m b-and-c -A b c d
75 76 $ hg push ../repo1 -v | grep -v '^ '
76 77 pushing to ../repo1
77 78 searching for changes
78 79 lfs: need to transfer 2 objects (39 bytes)
79 80 lfs: uploading 37a65ab78d5ecda767e8622c248b5dbff1e68b1678ab0e730d5eb8601ec8ad19 (20 bytes)
80 81 lfs: processed: 37a65ab78d5ecda767e8622c248b5dbff1e68b1678ab0e730d5eb8601ec8ad19
81 82 lfs: uploading d11e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998 (19 bytes)
82 83 lfs: processed: d11e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998
83 84 1 changesets found
84 85 uncompressed size of bundle content:
85 86 adding changesets
86 87 adding manifests
87 88 adding file changes
88 89 added 1 changesets with 3 changes to 3 files
89 90
90 91 Clear the cache to force a download
91 92 $ rm -rf `hg config lfs.usercache`
92 93 $ hg --repo ../repo1 update tip -v
93 94 resolving manifests
94 95 getting b
95 96 lfs: found 31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b in the local lfs store
96 97 getting c
97 98 lfs: downloading d11e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998 (19 bytes)
98 99 lfs: adding d11e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998 to the usercache
99 100 lfs: processed: d11e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998
100 101 lfs: found d11e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998 in the local lfs store
101 102 getting d
102 103 lfs: downloading 37a65ab78d5ecda767e8622c248b5dbff1e68b1678ab0e730d5eb8601ec8ad19 (20 bytes)
103 104 lfs: adding 37a65ab78d5ecda767e8622c248b5dbff1e68b1678ab0e730d5eb8601ec8ad19 to the usercache
104 105 lfs: processed: 37a65ab78d5ecda767e8622c248b5dbff1e68b1678ab0e730d5eb8601ec8ad19
105 106 lfs: found 37a65ab78d5ecda767e8622c248b5dbff1e68b1678ab0e730d5eb8601ec8ad19 in the local lfs store
106 107 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
107 108
108 109 Test a corrupt file download, but clear the cache first to force a download.
109 110
110 111 $ rm -rf `hg config lfs.usercache`
111 112 $ cp $TESTTMP/lfs-content/d1/1e/1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998 blob
112 113 $ echo 'damage' > $TESTTMP/lfs-content/d1/1e/1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998
113 114 $ rm ../repo1/.hg/store/lfs/objects/d1/1e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998
114 115 $ rm ../repo1/*
115 116
116 117 XXX: suggesting `hg verify` won't help with a corrupt file on the lfs server.
117 118 $ hg --repo ../repo1 update -C tip -v
118 119 resolving manifests
119 120 getting a
120 121 lfs: found 31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b in the local lfs store
121 122 getting b
122 123 lfs: found 31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b in the local lfs store
123 124 getting c
124 125 lfs: downloading d11e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998 (19 bytes)
125 126 abort: detected corrupt lfs object: d11e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998
126 127 (run hg verify)
127 128 [255]
128 129
129 130 The corrupted blob is not added to the usercache or local store
130 131
131 132 $ test -f ../repo1/.hg/store/lfs/objects/d1/1e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998
132 133 [1]
133 134 $ test -f `hg config lfs.usercache`/d1/1e1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998
134 135 [1]
135 136 $ cp blob $TESTTMP/lfs-content/d1/1e/1a642b60813aee592094109b406089b8dff4cb157157f753418ec7857998
136 137
137 138 Test a corrupted file upload
138 139
139 140 $ echo 'another lfs blob' > b
140 141 $ hg ci -m 'another blob'
141 142 $ echo 'damage' > .hg/store/lfs/objects/e6/59058e26b07b39d2a9c7145b3f99b41f797b6621c8076600e9cb7ee88291f0
142 143 $ hg push -v ../repo1
143 144 pushing to ../repo1
144 145 searching for changes
145 146 lfs: uploading e659058e26b07b39d2a9c7145b3f99b41f797b6621c8076600e9cb7ee88291f0 (17 bytes)
146 147 abort: detected corrupt lfs object: e659058e26b07b39d2a9c7145b3f99b41f797b6621c8076600e9cb7ee88291f0
147 148 (run hg verify)
148 149 [255]
149 150
150 151 Check error message when the remote missed a blob:
151 152
152 153 $ echo FFFFF > b
153 154 $ hg commit -m b -A b
154 155 $ echo FFFFF >> b
155 156 $ hg commit -m b b
156 157 $ rm -rf .hg/store/lfs
157 158 $ rm -rf `hg config lfs.usercache`
158 159 $ hg update -C '.^'
159 160 abort: LFS server claims required objects do not exist:
160 161 8e6ea5f6c066b44a0efa43bcce86aea73f17e6e23f0663df0251e7524e140a13!
161 162 [255]
162 163
163 164 Check error message when object does not exist:
164 165
165 166 $ hg init test && cd test
166 167 $ echo "[extensions]" >> .hg/hgrc
167 168 $ echo "lfs=" >> .hg/hgrc
168 169 $ echo "[lfs]" >> .hg/hgrc
169 170 $ echo "threshold=1" >> .hg/hgrc
170 171 $ echo a > a
171 172 $ hg add a
172 173 $ hg commit -m 'test'
173 174 $ echo aaaaa > a
174 175 $ hg commit -m 'largefile'
175 176 $ hg debugdata .hg/store/data/a.i 1 # verify this is no the file content but includes "oid", the LFS "pointer".
176 177 version https://git-lfs.github.com/spec/v1
177 178 oid sha256:bdc26931acfb734b142a8d675f205becf27560dc461f501822de13274fe6fc8a
178 179 size 6
179 180 x-is-binary 0
180 181 $ cd ..
181 182 $ rm -rf `hg config lfs.usercache`
182 183 $ hg --config 'lfs.url=https://dewey-lfs.vip.facebook.com/lfs' clone test test2
183 184 updating to branch default
184 185 abort: LFS server error. Remote object for file data/a.i not found:(.*)! (re)
185 186 [255]
186 187
187 188 $ $PYTHON $RUNTESTDIR/killdaemons.py $DAEMON_PIDS
@@ -1,914 +1,916 b''
1 1 # Initial setup
2 2
3 3 $ cat >> $HGRCPATH << EOF
4 4 > [extensions]
5 5 > lfs=
6 6 > [lfs]
7 7 > threshold=1000B
8 8 > EOF
9 9
10 10 $ LONG=AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
11 11
12 12 # Prepare server and enable extension
13 13 $ hg init server
14 14 $ hg clone -q server client
15 15 $ cd client
16 16
17 17 # Commit small file
18 18 $ echo s > smallfile
19 19 $ hg commit -Aqm "add small file"
20 20
21 21 # Commit large file
22 22 $ echo $LONG > largefile
23 23 $ grep lfs .hg/requires
24 24 [1]
25 25 $ hg commit --traceback -Aqm "add large file"
26 26 $ grep lfs .hg/requires
27 27 lfs
28 28
29 29 # Ensure metadata is stored
30 30 $ hg debugdata largefile 0
31 31 version https://git-lfs.github.com/spec/v1
32 32 oid sha256:f11e77c257047a398492d8d6cb9f6acf3aa7c4384bb23080b43546053e183e4b
33 33 size 1501
34 34 x-is-binary 0
35 35
36 36 # Check the blobstore is populated
37 37 $ find .hg/store/lfs/objects | sort
38 38 .hg/store/lfs/objects
39 39 .hg/store/lfs/objects/f1
40 40 .hg/store/lfs/objects/f1/1e77c257047a398492d8d6cb9f6acf3aa7c4384bb23080b43546053e183e4b
41 41
42 42 # Check the blob stored contains the actual contents of the file
43 43 $ cat .hg/store/lfs/objects/f1/1e77c257047a398492d8d6cb9f6acf3aa7c4384bb23080b43546053e183e4b
44 44 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
45 45
46 46 # Push changes to the server
47 47
48 48 $ hg push
49 49 pushing to $TESTTMP/server
50 50 searching for changes
51 51 abort: lfs.url needs to be configured
52 52 [255]
53 53
54 54 $ cat >> $HGRCPATH << EOF
55 55 > [lfs]
56 56 > url=file:$TESTTMP/dummy-remote/
57 57 > EOF
58 58
59 TODO: Push to a local non-lfs repo with the extension enabled should add the
59 Push to a local non-lfs repo with the extension enabled will add the
60 60 lfs requirement
61 61
62 62 $ grep lfs $TESTTMP/server/.hg/requires
63 63 [1]
64 64 $ hg push -v | egrep -v '^(uncompressed| )'
65 65 pushing to $TESTTMP/server
66 66 searching for changes
67 67 lfs: found f11e77c257047a398492d8d6cb9f6acf3aa7c4384bb23080b43546053e183e4b in the local lfs store
68 68 2 changesets found
69 69 adding changesets
70 70 adding manifests
71 71 adding file changes
72 72 added 2 changesets with 2 changes to 2 files
73 calling hook pretxnchangegroup.lfs: hgext.lfs.checkrequireslfs
73 74 $ grep lfs $TESTTMP/server/.hg/requires
74 [1]
75 lfs
75 76
76 77 # Unknown URL scheme
77 78
78 79 $ hg push --config lfs.url=ftp://foobar
79 80 abort: lfs: unknown url scheme: ftp
80 81 [255]
81 82
82 83 $ cd ../
83 84
84 85 # Initialize new client (not cloning) and setup extension
85 86 $ hg init client2
86 87 $ cd client2
87 88 $ cat >> .hg/hgrc <<EOF
88 89 > [paths]
89 90 > default = $TESTTMP/server
90 91 > EOF
91 92
92 93 # Pull from server
93 94
94 TODO: Pulling a local lfs repo into a local non-lfs repo with the extension
95 enabled should add the lfs requirement
95 Pulling a local lfs repo into a local non-lfs repo with the extension
96 enabled adds the lfs requirement
96 97
97 98 $ grep lfs .hg/requires $TESTTMP/server/.hg/requires
98 [1]
99 $TESTTMP/server/.hg/requires:lfs
99 100 $ hg pull default
100 101 pulling from $TESTTMP/server
101 102 requesting all changes
102 103 adding changesets
103 104 adding manifests
104 105 adding file changes
105 106 added 2 changesets with 2 changes to 2 files
106 107 new changesets b29ba743f89d:00c137947d30
107 108 (run 'hg update' to get a working copy)
108 109 $ grep lfs .hg/requires $TESTTMP/server/.hg/requires
109 [1]
110 .hg/requires:lfs
111 $TESTTMP/server/.hg/requires:lfs
110 112
111 113 # Check the blobstore is not yet populated
112 114 $ [ -d .hg/store/lfs/objects ]
113 115 [1]
114 116
115 117 # Update to the last revision containing the large file
116 118 $ hg update
117 119 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
118 120
119 121 # Check the blobstore has been populated on update
120 122 $ find .hg/store/lfs/objects | sort
121 123 .hg/store/lfs/objects
122 124 .hg/store/lfs/objects/f1
123 125 .hg/store/lfs/objects/f1/1e77c257047a398492d8d6cb9f6acf3aa7c4384bb23080b43546053e183e4b
124 126
125 127 # Check the contents of the file are fetched from blobstore when requested
126 128 $ hg cat -r . largefile
127 129 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
128 130
129 131 # Check the file has been copied in the working copy
130 132 $ cat largefile
131 133 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
132 134
133 135 $ cd ..
134 136
135 137 # Check rename, and switch between large and small files
136 138
137 139 $ hg init repo3
138 140 $ cd repo3
139 141 $ cat >> .hg/hgrc << EOF
140 142 > [lfs]
141 143 > threshold=10B
142 144 > EOF
143 145
144 146 $ echo LONGER-THAN-TEN-BYTES-WILL-TRIGGER-LFS > large
145 147 $ echo SHORTER > small
146 148 $ hg add . -q
147 149 $ hg commit -m 'commit with lfs content'
148 150
149 151 $ hg mv large l
150 152 $ hg mv small s
151 153 $ hg commit -m 'renames'
152 154
153 155 $ echo SHORT > l
154 156 $ echo BECOME-LARGER-FROM-SHORTER > s
155 157 $ hg commit -m 'large to small, small to large'
156 158
157 159 $ echo 1 >> l
158 160 $ echo 2 >> s
159 161 $ hg commit -m 'random modifications'
160 162
161 163 $ echo RESTORE-TO-BE-LARGE > l
162 164 $ echo SHORTER > s
163 165 $ hg commit -m 'switch large and small again'
164 166
165 167 # Test lfs_files template
166 168
167 169 $ hg log -r 'all()' -T '{rev} {join(lfs_files, ", ")}\n'
168 170 0 large
169 171 1 l
170 172 2 s
171 173 3 s
172 174 4 l
173 175
174 176 # Push and pull the above repo
175 177
176 178 $ hg --cwd .. init repo4
177 179 $ hg push ../repo4
178 180 pushing to ../repo4
179 181 searching for changes
180 182 adding changesets
181 183 adding manifests
182 184 adding file changes
183 185 added 5 changesets with 10 changes to 4 files
184 186
185 187 $ hg --cwd .. init repo5
186 188 $ hg --cwd ../repo5 pull ../repo3
187 189 pulling from ../repo3
188 190 requesting all changes
189 191 adding changesets
190 192 adding manifests
191 193 adding file changes
192 194 added 5 changesets with 10 changes to 4 files
193 195 new changesets fd47a419c4f7:5adf850972b9
194 196 (run 'hg update' to get a working copy)
195 197
196 198 $ cd ..
197 199
198 200 # Test clone
199 201
200 202 $ hg init repo6
201 203 $ cd repo6
202 204 $ cat >> .hg/hgrc << EOF
203 205 > [lfs]
204 206 > threshold=30B
205 207 > EOF
206 208
207 209 $ echo LARGE-BECAUSE-IT-IS-MORE-THAN-30-BYTES > large
208 210 $ echo SMALL > small
209 211 $ hg commit -Aqm 'create a lfs file' large small
210 212 $ hg debuglfsupload -r 'all()' -v
211 213 lfs: found 8e92251415339ae9b148c8da89ed5ec665905166a1ab11b09dca8fad83344738 in the local lfs store
212 214
213 215 $ cd ..
214 216
215 217 $ hg clone repo6 repo7
216 218 updating to branch default
217 219 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
218 220 $ cd repo7
219 221 $ hg config extensions --debug | grep lfs
220 222 $TESTTMP/repo7/.hg/hgrc:*: extensions.lfs= (glob)
221 223 $ cat large
222 224 LARGE-BECAUSE-IT-IS-MORE-THAN-30-BYTES
223 225 $ cat small
224 226 SMALL
225 227
226 228 $ cd ..
227 229
228 230 $ hg --config extensions.share= share repo7 sharedrepo
229 231 updating working directory
230 232 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
231 233 $ hg -R sharedrepo config extensions --debug | grep lfs
232 234 $TESTTMP/sharedrepo/.hg/hgrc:*: extensions.lfs= (glob)
233 235
234 236 # Test rename and status
235 237
236 238 $ hg init repo8
237 239 $ cd repo8
238 240 $ cat >> .hg/hgrc << EOF
239 241 > [lfs]
240 242 > threshold=10B
241 243 > EOF
242 244
243 245 $ echo THIS-IS-LFS-BECAUSE-10-BYTES > a1
244 246 $ echo SMALL > a2
245 247 $ hg commit -m a -A a1 a2
246 248 $ hg status
247 249 $ hg mv a1 b1
248 250 $ hg mv a2 a1
249 251 $ hg mv b1 a2
250 252 $ hg commit -m b
251 253 $ hg status
252 254 >>> with open('a2', 'wb') as f:
253 255 ... f.write(b'\1\nSTART-WITH-HG-FILELOG-METADATA')
254 256 >>> with open('a1', 'wb') as f:
255 257 ... f.write(b'\1\nMETA\n')
256 258 $ hg commit -m meta
257 259 $ hg status
258 260 $ hg log -T '{rev}: {file_copies} | {file_dels} | {file_adds}\n'
259 261 2: | |
260 262 1: a1 (a2)a2 (a1) | |
261 263 0: | | a1 a2
262 264
263 265 $ for n in a1 a2; do
264 266 > for r in 0 1 2; do
265 267 > printf '\n%s @ %s\n' $n $r
266 268 > hg debugdata $n $r
267 269 > done
268 270 > done
269 271
270 272 a1 @ 0
271 273 version https://git-lfs.github.com/spec/v1
272 274 oid sha256:5bb8341bee63b3649f222b2215bde37322bea075a30575aa685d8f8d21c77024
273 275 size 29
274 276 x-is-binary 0
275 277
276 278 a1 @ 1
277 279 \x01 (esc)
278 280 copy: a2
279 281 copyrev: 50470ad23cf937b1f4b9f80bfe54df38e65b50d9
280 282 \x01 (esc)
281 283 SMALL
282 284
283 285 a1 @ 2
284 286 \x01 (esc)
285 287 \x01 (esc)
286 288 \x01 (esc)
287 289 META
288 290
289 291 a2 @ 0
290 292 SMALL
291 293
292 294 a2 @ 1
293 295 version https://git-lfs.github.com/spec/v1
294 296 oid sha256:5bb8341bee63b3649f222b2215bde37322bea075a30575aa685d8f8d21c77024
295 297 size 29
296 298 x-hg-copy a1
297 299 x-hg-copyrev be23af27908a582af43e5cda209a5a9b319de8d4
298 300 x-is-binary 0
299 301
300 302 a2 @ 2
301 303 version https://git-lfs.github.com/spec/v1
302 304 oid sha256:876dadc86a8542f9798048f2c47f51dbf8e4359aed883e8ec80c5db825f0d943
303 305 size 32
304 306 x-is-binary 0
305 307
306 308 # Verify commit hashes include rename metadata
307 309
308 310 $ hg log -T '{rev}:{node|short} {desc}\n'
309 311 2:0fae949de7fa meta
310 312 1:9cd6bdffdac0 b
311 313 0:7f96794915f7 a
312 314
313 315 $ cd ..
314 316
315 317 # Test bundle
316 318
317 319 $ hg init repo9
318 320 $ cd repo9
319 321 $ cat >> .hg/hgrc << EOF
320 322 > [lfs]
321 323 > threshold=10B
322 324 > [diff]
323 325 > git=1
324 326 > EOF
325 327
326 328 $ for i in 0 single two three 4; do
327 329 > echo 'THIS-IS-LFS-'$i > a
328 330 > hg commit -m a-$i -A a
329 331 > done
330 332
331 333 $ hg update 2 -q
332 334 $ echo 'THIS-IS-LFS-2-CHILD' > a
333 335 $ hg commit -m branching -q
334 336
335 337 $ hg bundle --base 1 bundle.hg -v
336 338 lfs: found 5ab7a3739a5feec94a562d070a14f36dba7cad17e5484a4a89eea8e5f3166888 in the local lfs store
337 339 lfs: found a9c7d1cd6ce2b9bbdf46ed9a862845228717b921c089d0d42e3bcaed29eb612e in the local lfs store
338 340 lfs: found f693890c49c409ec33673b71e53f297681f76c1166daf33b2ad7ebf8b1d3237e in the local lfs store
339 341 lfs: found fda198fea753eb66a252e9856915e1f5cddbe41723bd4b695ece2604ad3c9f75 in the local lfs store
340 342 4 changesets found
341 343 uncompressed size of bundle content:
342 344 * (changelog) (glob)
343 345 * (manifests) (glob)
344 346 * a (glob)
345 347 $ hg --config extensions.strip= strip -r 2 --no-backup --force -q
346 348 $ hg -R bundle.hg log -p -T '{rev} {desc}\n' a
347 349 5 branching
348 350 diff --git a/a b/a
349 351 --- a/a
350 352 +++ b/a
351 353 @@ -1,1 +1,1 @@
352 354 -THIS-IS-LFS-two
353 355 +THIS-IS-LFS-2-CHILD
354 356
355 357 4 a-4
356 358 diff --git a/a b/a
357 359 --- a/a
358 360 +++ b/a
359 361 @@ -1,1 +1,1 @@
360 362 -THIS-IS-LFS-three
361 363 +THIS-IS-LFS-4
362 364
363 365 3 a-three
364 366 diff --git a/a b/a
365 367 --- a/a
366 368 +++ b/a
367 369 @@ -1,1 +1,1 @@
368 370 -THIS-IS-LFS-two
369 371 +THIS-IS-LFS-three
370 372
371 373 2 a-two
372 374 diff --git a/a b/a
373 375 --- a/a
374 376 +++ b/a
375 377 @@ -1,1 +1,1 @@
376 378 -THIS-IS-LFS-single
377 379 +THIS-IS-LFS-two
378 380
379 381 1 a-single
380 382 diff --git a/a b/a
381 383 --- a/a
382 384 +++ b/a
383 385 @@ -1,1 +1,1 @@
384 386 -THIS-IS-LFS-0
385 387 +THIS-IS-LFS-single
386 388
387 389 0 a-0
388 390 diff --git a/a b/a
389 391 new file mode 100644
390 392 --- /dev/null
391 393 +++ b/a
392 394 @@ -0,0 +1,1 @@
393 395 +THIS-IS-LFS-0
394 396
395 397 $ hg bundle -R bundle.hg --base 1 bundle-again.hg -q
396 398 $ hg -R bundle-again.hg log -p -T '{rev} {desc}\n' a
397 399 5 branching
398 400 diff --git a/a b/a
399 401 --- a/a
400 402 +++ b/a
401 403 @@ -1,1 +1,1 @@
402 404 -THIS-IS-LFS-two
403 405 +THIS-IS-LFS-2-CHILD
404 406
405 407 4 a-4
406 408 diff --git a/a b/a
407 409 --- a/a
408 410 +++ b/a
409 411 @@ -1,1 +1,1 @@
410 412 -THIS-IS-LFS-three
411 413 +THIS-IS-LFS-4
412 414
413 415 3 a-three
414 416 diff --git a/a b/a
415 417 --- a/a
416 418 +++ b/a
417 419 @@ -1,1 +1,1 @@
418 420 -THIS-IS-LFS-two
419 421 +THIS-IS-LFS-three
420 422
421 423 2 a-two
422 424 diff --git a/a b/a
423 425 --- a/a
424 426 +++ b/a
425 427 @@ -1,1 +1,1 @@
426 428 -THIS-IS-LFS-single
427 429 +THIS-IS-LFS-two
428 430
429 431 1 a-single
430 432 diff --git a/a b/a
431 433 --- a/a
432 434 +++ b/a
433 435 @@ -1,1 +1,1 @@
434 436 -THIS-IS-LFS-0
435 437 +THIS-IS-LFS-single
436 438
437 439 0 a-0
438 440 diff --git a/a b/a
439 441 new file mode 100644
440 442 --- /dev/null
441 443 +++ b/a
442 444 @@ -0,0 +1,1 @@
443 445 +THIS-IS-LFS-0
444 446
445 447 $ cd ..
446 448
447 449 # Test isbinary
448 450
449 451 $ hg init repo10
450 452 $ cd repo10
451 453 $ cat >> .hg/hgrc << EOF
452 454 > [extensions]
453 455 > lfs=
454 456 > [lfs]
455 457 > threshold=1
456 458 > EOF
457 459 $ $PYTHON <<'EOF'
458 460 > def write(path, content):
459 461 > with open(path, 'wb') as f:
460 462 > f.write(content)
461 463 > write('a', b'\0\0')
462 464 > write('b', b'\1\n')
463 465 > write('c', b'\1\n\0')
464 466 > write('d', b'xx')
465 467 > EOF
466 468 $ hg add a b c d
467 469 $ hg diff --stat
468 470 a | Bin
469 471 b | 1 +
470 472 c | Bin
471 473 d | 1 +
472 474 4 files changed, 2 insertions(+), 0 deletions(-)
473 475 $ hg commit -m binarytest
474 476 $ cat > $TESTTMP/dumpbinary.py << EOF
475 477 > def reposetup(ui, repo):
476 478 > for n in 'abcd':
477 479 > ui.write(('%s: binary=%s\n') % (n, repo['.'][n].isbinary()))
478 480 > EOF
479 481 $ hg --config extensions.dumpbinary=$TESTTMP/dumpbinary.py id --trace
480 482 a: binary=True
481 483 b: binary=False
482 484 c: binary=True
483 485 d: binary=False
484 486 b55353847f02 tip
485 487
486 488 $ cd ..
487 489
488 490 # Test fctx.cmp fastpath - diff without LFS blobs
489 491
490 492 $ hg init repo11
491 493 $ cd repo11
492 494 $ cat >> .hg/hgrc <<EOF
493 495 > [lfs]
494 496 > threshold=1
495 497 > EOF
496 498 $ cat > ../patch.diff <<EOF
497 499 > # HG changeset patch
498 500 > 2
499 501 >
500 502 > diff --git a/a b/a
501 503 > old mode 100644
502 504 > new mode 100755
503 505 > EOF
504 506
505 507 $ for i in 1 2 3; do
506 508 > cp ../repo10/a a
507 509 > if [ $i = 3 ]; then
508 510 > # make a content-only change
509 511 > hg import -q --bypass ../patch.diff
510 512 > hg update -q
511 513 > rm ../patch.diff
512 514 > else
513 515 > echo $i >> a
514 516 > hg commit -m $i -A a
515 517 > fi
516 518 > done
517 519 $ [ -d .hg/store/lfs/objects ]
518 520
519 521 $ cd ..
520 522
521 523 $ hg clone repo11 repo12 --noupdate
522 524 $ cd repo12
523 525 $ hg log --removed -p a -T '{desc}\n' --config diff.nobinary=1 --git
524 526 2
525 527 diff --git a/a b/a
526 528 old mode 100644
527 529 new mode 100755
528 530
529 531 2
530 532 diff --git a/a b/a
531 533 Binary file a has changed
532 534
533 535 1
534 536 diff --git a/a b/a
535 537 new file mode 100644
536 538 Binary file a has changed
537 539
538 540 $ [ -d .hg/store/lfs/objects ]
539 541 [1]
540 542
541 543 $ cd ..
542 544
543 545 # Verify the repos
544 546
545 547 $ cat > $TESTTMP/dumpflog.py << EOF
546 548 > # print raw revision sizes, flags, and hashes for certain files
547 549 > import hashlib
548 550 > from mercurial import revlog
549 551 > from mercurial.node import short
550 552 > def hash(rawtext):
551 553 > h = hashlib.sha512()
552 554 > h.update(rawtext)
553 555 > return h.hexdigest()[:4]
554 556 > def reposetup(ui, repo):
555 557 > # these 2 files are interesting
556 558 > for name in ['l', 's']:
557 559 > fl = repo.file(name)
558 560 > if len(fl) == 0:
559 561 > continue
560 562 > sizes = [revlog.revlog.rawsize(fl, i) for i in fl]
561 563 > texts = [fl.revision(i, raw=True) for i in fl]
562 564 > flags = [int(fl.flags(i)) for i in fl]
563 565 > hashes = [hash(t) for t in texts]
564 566 > print(' %s: rawsizes=%r flags=%r hashes=%r'
565 567 > % (name, sizes, flags, hashes))
566 568 > EOF
567 569
568 570 $ for i in client client2 server repo3 repo4 repo5 repo6 repo7 repo8 repo9 \
569 571 > repo10; do
570 572 > echo 'repo:' $i
571 573 > hg --cwd $i verify --config extensions.dumpflog=$TESTTMP/dumpflog.py -q
572 574 > done
573 575 repo: client
574 576 repo: client2
575 577 repo: server
576 578 repo: repo3
577 579 l: rawsizes=[211, 6, 8, 141] flags=[8192, 0, 0, 8192] hashes=['d2b8', '948c', 'cc88', '724d']
578 580 s: rawsizes=[74, 141, 141, 8] flags=[0, 8192, 8192, 0] hashes=['3c80', 'fce0', '874a', '826b']
579 581 repo: repo4
580 582 l: rawsizes=[211, 6, 8, 141] flags=[8192, 0, 0, 8192] hashes=['d2b8', '948c', 'cc88', '724d']
581 583 s: rawsizes=[74, 141, 141, 8] flags=[0, 8192, 8192, 0] hashes=['3c80', 'fce0', '874a', '826b']
582 584 repo: repo5
583 585 l: rawsizes=[211, 6, 8, 141] flags=[8192, 0, 0, 8192] hashes=['d2b8', '948c', 'cc88', '724d']
584 586 s: rawsizes=[74, 141, 141, 8] flags=[0, 8192, 8192, 0] hashes=['3c80', 'fce0', '874a', '826b']
585 587 repo: repo6
586 588 repo: repo7
587 589 repo: repo8
588 590 repo: repo9
589 591 repo: repo10
590 592
591 593 repo12 doesn't have any cached lfs files and its source never pushed its
592 594 files. Therefore, the files don't exist in the remote store. Use the files in
593 595 the user cache.
594 596
595 597 $ test -d $TESTTMP/repo12/.hg/store/lfs/objects
596 598 [1]
597 599
598 600 $ hg --config extensions.share= share repo12 repo13
599 601 updating working directory
600 602 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
601 603 $ hg -R repo13 -q verify
602 604
603 605 $ hg clone repo12 repo14
604 606 updating to branch default
605 607 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
606 608 $ hg -R repo14 -q verify
607 609
608 610 If the source repo doesn't have the blob (maybe it was pulled or cloned with
609 611 --noupdate), the blob is still accessible via the global cache to send to the
610 612 remote store.
611 613
612 614 $ rm -rf $TESTTMP/repo14/.hg/store/lfs
613 615 $ hg init repo15
614 616 $ hg -R repo14 push repo15
615 617 pushing to repo15
616 618 searching for changes
617 619 adding changesets
618 620 adding manifests
619 621 adding file changes
620 622 added 3 changesets with 2 changes to 1 files
621 623 $ hg -R repo14 -q verify
622 624
623 625 Test damaged file scenarios. (This also damages the usercache because of the
624 626 hardlinks.)
625 627
626 628 $ echo 'damage' >> repo5/.hg/store/lfs/objects/66/100b384bf761271b407d79fc30cdd0554f3b2c5d944836e936d584b88ce88e
627 629
628 630 Repo with damaged lfs objects in any revision will fail verification.
629 631
630 632 $ hg -R repo5 verify
631 633 checking changesets
632 634 checking manifests
633 635 crosschecking files in changesets and manifests
634 636 checking files
635 637 l@1: unpacking 46a2f24864bc: integrity check failed on data/l.i:0
636 638 large@0: unpacking 2c531e0992ff: integrity check failed on data/large.i:0
637 639 4 files, 5 changesets, 10 total revisions
638 640 2 integrity errors encountered!
639 641 (first damaged changeset appears to be 0)
640 642 [1]
641 643
642 644 Updates work after cloning a damaged repo, if the damaged lfs objects aren't in
643 645 the update destination. Those objects won't be added to the new repo's store
644 646 because they aren't accessed.
645 647
646 648 $ hg clone -v repo5 fromcorrupt
647 649 updating to branch default
648 650 resolving manifests
649 651 getting l
650 652 lfs: found 22f66a3fc0b9bf3f012c814303995ec07099b3a9ce02a7af84b5970811074a3b in the usercache
651 653 getting s
652 654 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
653 655 $ test -f fromcorrupt/.hg/store/lfs/objects/66/100b384bf761271b407d79fc30cdd0554f3b2c5d944836e936d584b88ce88e
654 656 [1]
655 657
656 658 Verify will copy/link all lfs objects into the local store that aren't already
657 659 present. Bypass the corrupted usercache to show that verify works when fed by
658 660 the (uncorrupted) remote store.
659 661
660 662 $ hg -R fromcorrupt --config lfs.usercache=emptycache verify -v
661 663 repository uses revlog format 1
662 664 checking changesets
663 665 checking manifests
664 666 crosschecking files in changesets and manifests
665 667 checking files
666 668 lfs: adding 66100b384bf761271b407d79fc30cdd0554f3b2c5d944836e936d584b88ce88e to the usercache
667 669 lfs: found 66100b384bf761271b407d79fc30cdd0554f3b2c5d944836e936d584b88ce88e in the local lfs store
668 670 lfs: found 22f66a3fc0b9bf3f012c814303995ec07099b3a9ce02a7af84b5970811074a3b in the local lfs store
669 671 lfs: found 66100b384bf761271b407d79fc30cdd0554f3b2c5d944836e936d584b88ce88e in the local lfs store
670 672 lfs: adding 89b6070915a3d573ff3599d1cda305bc5e38549b15c4847ab034169da66e1ca8 to the usercache
671 673 lfs: found 89b6070915a3d573ff3599d1cda305bc5e38549b15c4847ab034169da66e1ca8 in the local lfs store
672 674 lfs: adding b1a6ea88da0017a0e77db139a54618986e9a2489bee24af9fe596de9daac498c to the usercache
673 675 lfs: found b1a6ea88da0017a0e77db139a54618986e9a2489bee24af9fe596de9daac498c in the local lfs store
674 676 4 files, 5 changesets, 10 total revisions
675 677
676 678 Verify will not copy/link a corrupted file from the usercache into the local
677 679 store, and poison it. (The verify with a good remote now works.)
678 680
679 681 $ rm -r fromcorrupt/.hg/store/lfs/objects/66/100b384bf761271b407d79fc30cdd0554f3b2c5d944836e936d584b88ce88e
680 682 $ hg -R fromcorrupt verify -v
681 683 repository uses revlog format 1
682 684 checking changesets
683 685 checking manifests
684 686 crosschecking files in changesets and manifests
685 687 checking files
686 688 l@1: unpacking 46a2f24864bc: integrity check failed on data/l.i:0
687 689 lfs: found 22f66a3fc0b9bf3f012c814303995ec07099b3a9ce02a7af84b5970811074a3b in the local lfs store
688 690 large@0: unpacking 2c531e0992ff: integrity check failed on data/large.i:0
689 691 lfs: found 89b6070915a3d573ff3599d1cda305bc5e38549b15c4847ab034169da66e1ca8 in the local lfs store
690 692 lfs: found b1a6ea88da0017a0e77db139a54618986e9a2489bee24af9fe596de9daac498c in the local lfs store
691 693 4 files, 5 changesets, 10 total revisions
692 694 2 integrity errors encountered!
693 695 (first damaged changeset appears to be 0)
694 696 [1]
695 697 $ hg -R fromcorrupt --config lfs.usercache=emptycache verify -v
696 698 repository uses revlog format 1
697 699 checking changesets
698 700 checking manifests
699 701 crosschecking files in changesets and manifests
700 702 checking files
701 703 lfs: found 66100b384bf761271b407d79fc30cdd0554f3b2c5d944836e936d584b88ce88e in the usercache
702 704 lfs: found 22f66a3fc0b9bf3f012c814303995ec07099b3a9ce02a7af84b5970811074a3b in the local lfs store
703 705 lfs: found 66100b384bf761271b407d79fc30cdd0554f3b2c5d944836e936d584b88ce88e in the local lfs store
704 706 lfs: found 89b6070915a3d573ff3599d1cda305bc5e38549b15c4847ab034169da66e1ca8 in the local lfs store
705 707 lfs: found b1a6ea88da0017a0e77db139a54618986e9a2489bee24af9fe596de9daac498c in the local lfs store
706 708 4 files, 5 changesets, 10 total revisions
707 709
708 710 Damaging a file required by the update destination fails the update.
709 711
710 712 $ echo 'damage' >> $TESTTMP/dummy-remote/22/f66a3fc0b9bf3f012c814303995ec07099b3a9ce02a7af84b5970811074a3b
711 713 $ hg --config lfs.usercache=emptycache clone -v repo5 fromcorrupt2
712 714 updating to branch default
713 715 resolving manifests
714 716 getting l
715 717 abort: detected corrupt lfs object: 22f66a3fc0b9bf3f012c814303995ec07099b3a9ce02a7af84b5970811074a3b
716 718 (run hg verify)
717 719 [255]
718 720
719 721 A corrupted lfs blob is not transferred from a file://remotestore to the
720 722 usercache or local store.
721 723
722 724 $ test -f emptycache/22/f66a3fc0b9bf3f012c814303995ec07099b3a9ce02a7af84b5970811074a3b
723 725 [1]
724 726 $ test -f fromcorrupt2/.hg/store/lfs/objects/22/f66a3fc0b9bf3f012c814303995ec07099b3a9ce02a7af84b5970811074a3b
725 727 [1]
726 728
727 729 $ hg -R fromcorrupt2 verify
728 730 checking changesets
729 731 checking manifests
730 732 crosschecking files in changesets and manifests
731 733 checking files
732 734 l@1: unpacking 46a2f24864bc: integrity check failed on data/l.i:0
733 735 large@0: unpacking 2c531e0992ff: integrity check failed on data/large.i:0
734 736 4 files, 5 changesets, 10 total revisions
735 737 2 integrity errors encountered!
736 738 (first damaged changeset appears to be 0)
737 739 [1]
738 740
739 741 Corrupt local files are not sent upstream. (The alternate dummy remote
740 742 avoids the corrupt lfs object in the original remote.)
741 743
742 744 $ mkdir $TESTTMP/dummy-remote2
743 745 $ hg init dest
744 746 $ hg -R fromcorrupt2 --config lfs.url=file:///$TESTTMP/dummy-remote2 push -v dest
745 747 pushing to dest
746 748 searching for changes
747 749 lfs: found 22f66a3fc0b9bf3f012c814303995ec07099b3a9ce02a7af84b5970811074a3b in the local lfs store
748 750 lfs: found 89b6070915a3d573ff3599d1cda305bc5e38549b15c4847ab034169da66e1ca8 in the local lfs store
749 751 lfs: found b1a6ea88da0017a0e77db139a54618986e9a2489bee24af9fe596de9daac498c in the local lfs store
750 752 abort: detected corrupt lfs object: 66100b384bf761271b407d79fc30cdd0554f3b2c5d944836e936d584b88ce88e
751 753 (run hg verify)
752 754 [255]
753 755
754 756 $ hg -R fromcorrupt2 --config lfs.url=file:///$TESTTMP/dummy-remote2 verify -v
755 757 repository uses revlog format 1
756 758 checking changesets
757 759 checking manifests
758 760 crosschecking files in changesets and manifests
759 761 checking files
760 762 l@1: unpacking 46a2f24864bc: integrity check failed on data/l.i:0
761 763 lfs: found 22f66a3fc0b9bf3f012c814303995ec07099b3a9ce02a7af84b5970811074a3b in the local lfs store
762 764 large@0: unpacking 2c531e0992ff: integrity check failed on data/large.i:0
763 765 lfs: found 89b6070915a3d573ff3599d1cda305bc5e38549b15c4847ab034169da66e1ca8 in the local lfs store
764 766 lfs: found b1a6ea88da0017a0e77db139a54618986e9a2489bee24af9fe596de9daac498c in the local lfs store
765 767 4 files, 5 changesets, 10 total revisions
766 768 2 integrity errors encountered!
767 769 (first damaged changeset appears to be 0)
768 770 [1]
769 771
770 772 $ cat $TESTTMP/dummy-remote2/22/f66a3fc0b9bf3f012c814303995ec07099b3a9ce02a7af84b5970811074a3b | $TESTDIR/f --sha256
771 773 sha256=22f66a3fc0b9bf3f012c814303995ec07099b3a9ce02a7af84b5970811074a3b
772 774 $ cat fromcorrupt2/.hg/store/lfs/objects/22/f66a3fc0b9bf3f012c814303995ec07099b3a9ce02a7af84b5970811074a3b | $TESTDIR/f --sha256
773 775 sha256=22f66a3fc0b9bf3f012c814303995ec07099b3a9ce02a7af84b5970811074a3b
774 776 $ test -f $TESTTMP/dummy-remote2/66/100b384bf761271b407d79fc30cdd0554f3b2c5d944836e936d584b88ce88e
775 777 [1]
776 778
777 779 Accessing a corrupt file will complain
778 780
779 781 $ hg --cwd fromcorrupt2 cat -r 0 large
780 782 abort: integrity check failed on data/large.i:0!
781 783 [255]
782 784
783 785 lfs -> normal -> lfs round trip conversions are possible. The threshold for the
784 786 lfs destination is specified here because it was originally listed in the local
785 787 .hgrc, and the global one is too high to trigger lfs usage. For lfs -> normal,
786 788 there's no 'lfs' destination repo requirement. For normal -> lfs, there is.
787 789
788 790 XXX: There's not a great way to ensure that the conversion to normal files
789 791 actually converts _everything_ to normal. The extension needs to be loaded for
790 792 the source, but there's no way to disable it for the destination. The best that
791 793 can be done is to raise the threshold so that lfs isn't used on the destination.
792 794 It doesn't like using '!' to unset the value on the command line.
793 795
794 796 $ hg --config extensions.convert= --config lfs.threshold=1000M \
795 797 > convert repo8 convert_normal
796 798 initializing destination convert_normal repository
797 799 scanning source...
798 800 sorting...
799 801 converting...
800 802 2 a
801 803 1 b
802 804 0 meta
803 805 $ grep 'lfs' convert_normal/.hg/requires
804 806 [1]
805 807 $ hg --cwd convert_normal debugdata a1 0
806 808 THIS-IS-LFS-BECAUSE-10-BYTES
807 809
808 810 $ hg --config extensions.convert= --config lfs.threshold=10B \
809 811 > convert convert_normal convert_lfs
810 812 initializing destination convert_lfs repository
811 813 scanning source...
812 814 sorting...
813 815 converting...
814 816 2 a
815 817 1 b
816 818 0 meta
817 819 $ hg --cwd convert_lfs debugdata a1 0
818 820 version https://git-lfs.github.com/spec/v1
819 821 oid sha256:5bb8341bee63b3649f222b2215bde37322bea075a30575aa685d8f8d21c77024
820 822 size 29
821 823 x-is-binary 0
822 824 $ grep 'lfs' convert_lfs/.hg/requires
823 825 lfs
824 826
825 827 This convert is trickier, because it contains deleted files (via `hg mv`)
826 828
827 829 $ hg --config extensions.convert= --config lfs.threshold=1000M \
828 830 > convert repo3 convert_normal2
829 831 initializing destination convert_normal2 repository
830 832 scanning source...
831 833 sorting...
832 834 converting...
833 835 4 commit with lfs content
834 836 3 renames
835 837 2 large to small, small to large
836 838 1 random modifications
837 839 0 switch large and small again
838 840 $ grep 'lfs' convert_normal2/.hg/requires
839 841 [1]
840 842 $ hg --cwd convert_normal2 debugdata large 0
841 843 LONGER-THAN-TEN-BYTES-WILL-TRIGGER-LFS
842 844
843 845 $ hg --config extensions.convert= --config lfs.threshold=10B \
844 846 > convert convert_normal2 convert_lfs2
845 847 initializing destination convert_lfs2 repository
846 848 scanning source...
847 849 sorting...
848 850 converting...
849 851 4 commit with lfs content
850 852 3 renames
851 853 2 large to small, small to large
852 854 1 random modifications
853 855 0 switch large and small again
854 856 $ grep 'lfs' convert_lfs2/.hg/requires
855 857 lfs
856 858 $ hg --cwd convert_lfs2 debugdata large 0
857 859 version https://git-lfs.github.com/spec/v1
858 860 oid sha256:66100b384bf761271b407d79fc30cdd0554f3b2c5d944836e936d584b88ce88e
859 861 size 39
860 862 x-is-binary 0
861 863
862 864 $ hg -R convert_lfs2 config --debug extensions | grep lfs
863 865 $TESTTMP/convert_lfs2/.hg/hgrc:*: extensions.lfs= (glob)
864 866
865 867 Committing deleted files works:
866 868
867 869 $ hg init $TESTTMP/repo-del
868 870 $ cd $TESTTMP/repo-del
869 871 $ echo 1 > A
870 872 $ hg commit -m 'add A' -A A
871 873 $ hg rm A
872 874 $ hg commit -m 'rm A'
873 875 $ cd ..
874 876
875 TODO: Unbundling adds a requirement to a non-lfs repo, if necessary.
877 Unbundling adds a requirement to a non-lfs repo, if necessary.
876 878
877 879 $ hg bundle -R $TESTTMP/repo-del -qr 0 --base null nolfs.hg
878 880 $ hg bundle -R convert_lfs2 -qr tip --base null lfs.hg
879 881 $ hg init unbundle
880 882 $ hg pull -R unbundle -q nolfs.hg
881 883 $ grep lfs unbundle/.hg/requires
882 884 [1]
883 885 $ hg pull -R unbundle -q lfs.hg
884 886 $ grep lfs unbundle/.hg/requires
885 [1]
887 lfs
886 888
887 889 $ hg init no_lfs
888 890 $ cat >> no_lfs/.hg/hgrc <<EOF
889 891 > [experimental]
890 892 > changegroup3 = True
891 893 > [extensions]
892 894 > lfs=!
893 895 > EOF
894 896 $ cp -R no_lfs no_lfs2
895 897
896 898 Pushing from a local lfs repo to a local repo without an lfs requirement and
897 899 with lfs disabled, fails.
898 900
899 901 $ hg push -R convert_lfs2 no_lfs
900 902 pushing to no_lfs
901 903 abort: required features are not supported in the destination: lfs
902 904 [255]
903 905 $ grep lfs no_lfs/.hg/requires
904 906 [1]
905 907
906 908 Pulling from a local lfs repo to a local repo without an lfs requirement and
907 909 with lfs disabled, fails.
908 910
909 911 $ hg pull -R no_lfs2 convert_lfs2
910 912 pulling from convert_lfs2
911 913 abort: required features are not supported in the destination: lfs
912 914 [255]
913 915 $ grep lfs no_lfs2/.hg/requires
914 916 [1]
General Comments 0
You need to be logged in to leave comments. Login now