##// END OF EJS Templates
revlog: add an exception hint when processing LFS flags without the extension...
Matt Harbison -
r51180:10db46e1 default
parent child Browse files
Show More
@@ -1,194 +1,198
1 1 # flagutils.py - code to deal with revlog flags and their processors
2 2 #
3 3 # Copyright 2016 Remi Chaintron <remi@fb.com>
4 4 # Copyright 2016-2019 Pierre-Yves David <pierre-yves.david@ens-lyon.org>
5 5 #
6 6 # This software may be used and distributed according to the terms of the
7 7 # GNU General Public License version 2 or any later version.
8 8
9 9
10 10 from ..i18n import _
11 11
12 12 from .constants import (
13 13 REVIDX_DEFAULT_FLAGS,
14 14 REVIDX_ELLIPSIS,
15 15 REVIDX_EXTSTORED,
16 16 REVIDX_FLAGS_ORDER,
17 17 REVIDX_HASCOPIESINFO,
18 18 REVIDX_ISCENSORED,
19 19 REVIDX_RAWTEXT_CHANGING_FLAGS,
20 20 )
21 21
22 22 from .. import error, util
23 23
24 24 # blanked usage of all the name to prevent pyflakes constraints
25 25 # We need these name available in the module for extensions.
26 26 REVIDX_ISCENSORED
27 27 REVIDX_ELLIPSIS
28 28 REVIDX_EXTSTORED
29 29 REVIDX_HASCOPIESINFO,
30 30 REVIDX_DEFAULT_FLAGS
31 31 REVIDX_FLAGS_ORDER
32 32 REVIDX_RAWTEXT_CHANGING_FLAGS
33 33
34 34 # Keep this in sync with REVIDX_KNOWN_FLAGS in rust/hg-core/src/revlog/revlog.rs
35 35 REVIDX_KNOWN_FLAGS = util.bitsfrom(REVIDX_FLAGS_ORDER)
36 36
37 37 # Store flag processors (cf. 'addflagprocessor()' to register)
38 38 flagprocessors = {
39 39 REVIDX_ISCENSORED: None,
40 40 REVIDX_HASCOPIESINFO: None,
41 41 }
42 42
43 43
44 44 def addflagprocessor(flag, processor):
45 45 """Register a flag processor on a revision data flag.
46 46
47 47 Invariant:
48 48 - Flags need to be defined in REVIDX_KNOWN_FLAGS and REVIDX_FLAGS_ORDER,
49 49 and REVIDX_RAWTEXT_CHANGING_FLAGS if they can alter rawtext.
50 50 - Only one flag processor can be registered on a specific flag.
51 51 - flagprocessors must be 3-tuples of functions (read, write, raw) with the
52 52 following signatures:
53 53 - (read) f(self, rawtext) -> text, bool
54 54 - (write) f(self, text) -> rawtext, bool
55 55 - (raw) f(self, rawtext) -> bool
56 56 "text" is presented to the user. "rawtext" is stored in revlog data, not
57 57 directly visible to the user.
58 58 The boolean returned by these transforms is used to determine whether
59 59 the returned text can be used for hash integrity checking. For example,
60 60 if "write" returns False, then "text" is used to generate hash. If
61 61 "write" returns True, that basically means "rawtext" returned by "write"
62 62 should be used to generate hash. Usually, "write" and "read" return
63 63 different booleans. And "raw" returns a same boolean as "write".
64 64
65 65 Note: The 'raw' transform is used for changegroup generation and in some
66 66 debug commands. In this case the transform only indicates whether the
67 67 contents can be used for hash integrity checks.
68 68 """
69 69 insertflagprocessor(flag, processor, flagprocessors)
70 70
71 71
72 72 def insertflagprocessor(flag, processor, flagprocessors):
73 73 if not flag & REVIDX_KNOWN_FLAGS:
74 74 msg = _(b"cannot register processor on unknown flag '%#x'.") % flag
75 75 raise error.ProgrammingError(msg)
76 76 if flag not in REVIDX_FLAGS_ORDER:
77 77 msg = _(b"flag '%#x' undefined in REVIDX_FLAGS_ORDER.") % flag
78 78 raise error.ProgrammingError(msg)
79 79 if flag in flagprocessors:
80 80 msg = _(b"cannot register multiple processors on flag '%#x'.") % flag
81 81 raise error.Abort(msg)
82 82 flagprocessors[flag] = processor
83 83
84 84
85 85 def processflagswrite(revlog, text, flags):
86 86 """Inspect revision data flags and applies write transformations defined
87 87 by registered flag processors.
88 88
89 89 ``text`` - the revision data to process
90 90 ``flags`` - the revision flags
91 91
92 92 This method processes the flags in the order (or reverse order if
93 93 ``operation`` is 'write') defined by REVIDX_FLAGS_ORDER, applying the
94 94 flag processors registered for present flags. The order of flags defined
95 95 in REVIDX_FLAGS_ORDER needs to be stable to allow non-commutativity.
96 96
97 97 Returns a 2-tuple of ``(text, validatehash)`` where ``text`` is the
98 98 processed text and ``validatehash`` is a bool indicating whether the
99 99 returned text should be checked for hash integrity.
100 100 """
101 101 return _processflagsfunc(
102 102 revlog,
103 103 text,
104 104 flags,
105 105 b'write',
106 106 )[:2]
107 107
108 108
109 109 def processflagsread(revlog, text, flags):
110 110 """Inspect revision data flags and applies read transformations defined
111 111 by registered flag processors.
112 112
113 113 ``text`` - the revision data to process
114 114 ``flags`` - the revision flags
115 115 ``raw`` - an optional argument describing if the raw transform should be
116 116 applied.
117 117
118 118 This method processes the flags in the order (or reverse order if
119 119 ``operation`` is 'write') defined by REVIDX_FLAGS_ORDER, applying the
120 120 flag processors registered for present flags. The order of flags defined
121 121 in REVIDX_FLAGS_ORDER needs to be stable to allow non-commutativity.
122 122
123 123 Returns a 2-tuple of ``(text, validatehash)`` where ``text`` is the
124 124 processed text and ``validatehash`` is a bool indicating whether the
125 125 returned text should be checked for hash integrity.
126 126 """
127 127 return _processflagsfunc(revlog, text, flags, b'read')
128 128
129 129
130 130 def processflagsraw(revlog, text, flags):
131 131 """Inspect revision data flags to check is the content hash should be
132 132 validated.
133 133
134 134 ``text`` - the revision data to process
135 135 ``flags`` - the revision flags
136 136
137 137 This method processes the flags in the order (or reverse order if
138 138 ``operation`` is 'write') defined by REVIDX_FLAGS_ORDER, applying the
139 139 flag processors registered for present flags. The order of flags defined
140 140 in REVIDX_FLAGS_ORDER needs to be stable to allow non-commutativity.
141 141
142 142 Returns a 2-tuple of ``(text, validatehash)`` where ``text`` is the
143 143 processed text and ``validatehash`` is a bool indicating whether the
144 144 returned text should be checked for hash integrity.
145 145 """
146 146 return _processflagsfunc(revlog, text, flags, b'raw')[1]
147 147
148 148
149 149 def _processflagsfunc(revlog, text, flags, operation):
150 150 """internal function to process flag on a revlog
151 151
152 152 This function is private to this module, code should never needs to call it
153 153 directly."""
154 154 # fast path: no flag processors will run
155 155 if flags == 0:
156 156 return text, True
157 157 if operation not in (b'read', b'write', b'raw'):
158 158 raise error.ProgrammingError(_(b"invalid '%s' operation") % operation)
159 159 # Check all flags are known.
160 160 if flags & ~REVIDX_KNOWN_FLAGS:
161 161 raise revlog._flagserrorclass(
162 162 _(b"incompatible revision flag '%#x'")
163 163 % (flags & ~REVIDX_KNOWN_FLAGS)
164 164 )
165 165 validatehash = True
166 166 # Depending on the operation (read or write), the order might be
167 167 # reversed due to non-commutative transforms.
168 168 orderedflags = REVIDX_FLAGS_ORDER
169 169 if operation == b'write':
170 170 orderedflags = reversed(orderedflags)
171 171
172 172 for flag in orderedflags:
173 173 # If a flagprocessor has been registered for a known flag, apply the
174 174 # related operation transform and update result tuple.
175 175 if flag & flags:
176 176 vhash = True
177 177
178 178 if flag not in revlog._flagprocessors:
179 hint = None
180 if flag == REVIDX_EXTSTORED:
181 hint = _(b"the lfs extension must be enabled")
182
179 183 message = _(b"missing processor for flag '%#x'") % flag
180 raise revlog._flagserrorclass(message)
184 raise revlog._flagserrorclass(message, hint=hint)
181 185
182 186 processor = revlog._flagprocessors[flag]
183 187 if processor is not None:
184 188 readtransform, writetransform, rawtransform = processor
185 189
186 190 if operation == b'raw':
187 191 vhash = rawtransform(revlog, text)
188 192 elif operation == b'read':
189 193 text, vhash = readtransform(revlog, text)
190 194 else: # write operation
191 195 text, vhash = writetransform(revlog, text)
192 196 validatehash = validatehash and vhash
193 197
194 198 return text, validatehash
@@ -1,720 +1,721
1 1 #testcases lfsremote-on lfsremote-off
2 2 #require serve no-reposimplestore no-chg
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 make command server magic visible
27 27
28 28 #if windows
29 29 $ PYTHONPATH="$TESTDIR/../contrib;$PYTHONPATH"
30 30 #else
31 31 $ PYTHONPATH="$TESTDIR/../contrib:$PYTHONPATH"
32 32 #endif
33 33 $ export PYTHONPATH
34 34
35 35 $ hg init server
36 36 $ SERVER_REQUIRES="$TESTTMP/server/.hg/requires"
37 37 $ SERVER_PATH="$TESTTMP/server/"
38 38
39 39 $ cat > $TESTTMP/debugprocessors.py <<EOF
40 40 > from mercurial import (
41 41 > cmdutil,
42 42 > commands,
43 43 > pycompat,
44 44 > registrar,
45 45 > )
46 46 > cmdtable = {}
47 47 > command = registrar.command(cmdtable)
48 48 > @command(b'debugprocessors', [], b'FILE')
49 49 > def debugprocessors(ui, repo, file_=None, **opts):
50 50 > opts = pycompat.byteskwargs(opts)
51 51 > opts[b'changelog'] = False
52 52 > opts[b'manifest'] = False
53 53 > opts[b'dir'] = False
54 54 > rl = cmdutil.openrevlog(repo, b'debugprocessors', file_, opts)
55 55 > for flag, proc in rl._flagprocessors.items():
56 56 > ui.status(b"registered processor '%#x'\n" % (flag))
57 57 > EOF
58 58
59 59 Skip the experimental.changegroup3=True config. Failure to agree on this comes
60 60 first, and causes an "abort: no common changegroup version" if the extension is
61 61 only loaded on one side. If that *is* enabled, the subsequent failure is "abort:
62 62 missing processor for flag '0x2000'!" if the extension is only loaded on one side
63 63 (possibly also masked by the Internal Server Error message).
64 64 $ cat >> $HGRCPATH <<EOF
65 65 > [extensions]
66 66 > debugprocessors = $TESTTMP/debugprocessors.py
67 67 > [experimental]
68 68 > lfs.disableusercache = True
69 69 > lfs.worker-enable = False
70 70 > [lfs]
71 71 > threshold=10
72 72 > [web]
73 73 > allow_push=*
74 74 > push_ssl=False
75 75 > EOF
76 76
77 77 $ cp $HGRCPATH $HGRCPATH.orig
78 78
79 79 #if lfsremote-on
80 80 $ hg --config extensions.lfs= -R server \
81 81 > serve -p $HGPORT -d --pid-file=hg.pid --errorlog=$TESTTMP/errors.log
82 82 #else
83 83 $ hg --config extensions.lfs=! -R server \
84 84 > serve -p $HGPORT -d --pid-file=hg.pid --errorlog=$TESTTMP/errors.log
85 85 #endif
86 86
87 87 $ cat hg.pid >> $DAEMON_PIDS
88 88 $ hg clone -q http://localhost:$HGPORT client
89 89 $ hg debugrequires -R client | grep 'lfs'
90 90 [1]
91 91 $ hg debugrequires -R $SERVER_PATH | grep 'lfs'
92 92 [1]
93 93
94 94 This trivial repo will force commandserver to load the extension, but not call
95 95 reposetup() on another repo actually being operated on. This gives coverage
96 96 that wrapper functions are not assuming reposetup() was called.
97 97
98 98 $ hg init $TESTTMP/cmdservelfs
99 99 $ cat >> $TESTTMP/cmdservelfs/.hg/hgrc << EOF
100 100 > [extensions]
101 101 > lfs =
102 102 > EOF
103 103
104 104 --------------------------------------------------------------------------------
105 105 Case #1: client with non-lfs content and the extension disabled; server with
106 106 non-lfs content, and the extension enabled.
107 107
108 108 $ cd client
109 109 $ echo 'non-lfs' > nonlfs.txt
110 110 >>> from hgclient import check, readchannel, runcommand
111 111 >>> @check
112 112 ... def diff(server):
113 113 ... readchannel(server)
114 114 ... # run an arbitrary command in the repo with the extension loaded
115 115 ... runcommand(server, [b'id', b'-R', b'../cmdservelfs'])
116 116 ... # now run a command in a repo without the extension to ensure that
117 117 ... # files are added safely..
118 118 ... runcommand(server, [b'ci', b'-Aqm', b'non-lfs'])
119 119 ... # .. and that scmutil.prefetchfiles() safely no-ops..
120 120 ... runcommand(server, [b'diff', b'-r', b'.~1'])
121 121 ... # .. and that debugupgraderepo safely no-ops.
122 122 ... runcommand(server, [b'debugupgraderepo', b'-q', b'--run'])
123 123 *** runcommand id -R ../cmdservelfs
124 124 000000000000 tip
125 125 *** runcommand ci -Aqm non-lfs
126 126 *** runcommand diff -r .~1
127 127 diff -r 000000000000 nonlfs.txt
128 128 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
129 129 +++ b/nonlfs.txt Thu Jan 01 00:00:00 1970 +0000
130 130 @@ -0,0 +1,1 @@
131 131 +non-lfs
132 132 *** runcommand debugupgraderepo -q --run
133 133
134 134 $ hg debugrequires -R $SERVER_PATH | grep 'lfs'
135 135 [1]
136 136
137 137 #if lfsremote-on
138 138
139 139 $ hg push -q
140 140 $ hg debugrequires -R $SERVER_PATH | grep 'lfs'
141 141 [1]
142 142
143 143 $ hg clone -q http://localhost:$HGPORT $TESTTMP/client1_clone
144 144 $ hg debugrequires -R $TESTTMP/client1_clone/ | grep 'lfs'
145 145 [1]
146 146 $ hg debugrequires -R $SERVER_PATH | grep 'lfs'
147 147 [1]
148 148
149 149 $ hg init $TESTTMP/client1_pull
150 150 $ hg -R $TESTTMP/client1_pull pull -q http://localhost:$HGPORT
151 151 $ hg debugrequires -R $TESTTMP/client1_pull/ | grep 'lfs'
152 152 [1]
153 153 $ hg debugrequires -R $SERVER_PATH | grep 'lfs'
154 154 [1]
155 155 $ hg identify http://localhost:$HGPORT
156 156 d437e1d24fbd
157 157
158 158 #endif
159 159
160 160 --------------------------------------------------------------------------------
161 161 Case #2: client with non-lfs content and the extension enabled; server with
162 162 non-lfs content, and the extension state controlled by #testcases.
163 163
164 164 $ cat >> $HGRCPATH <<EOF
165 165 > [extensions]
166 166 > lfs =
167 167 > EOF
168 168 $ echo 'non-lfs' > nonlfs2.txt
169 169 $ hg ci -Aqm 'non-lfs file with lfs client'
170 170
171 171 Since no lfs content has been added yet, the push is allowed, even when the
172 172 extension is not enabled remotely.
173 173
174 174 $ hg push -q
175 175 $ hg debugrequires | grep 'lfs'
176 176 [1]
177 177 $ hg debugrequires -R $SERVER_PATH | grep 'lfs'
178 178 [1]
179 179
180 180 $ hg clone -q http://localhost:$HGPORT $TESTTMP/client2_clone
181 181 $ hg debugrequires -R $TESTTMP/client2_clone/ | grep 'lfs'
182 182 [1]
183 183 $ hg debugrequires -R $SERVER_PATH | grep 'lfs'
184 184 [1]
185 185
186 186 $ hg init $TESTTMP/client2_pull
187 187 $ hg -R $TESTTMP/client2_pull pull -q http://localhost:$HGPORT
188 188 $ hg debugrequires -R $TESTTMP/client2_pull/ | grep 'lfs'
189 189 [1]
190 190 $ hg debugrequires -R $SERVER_PATH | grep 'lfs'
191 191 [1]
192 192
193 193 $ hg identify http://localhost:$HGPORT
194 194 1477875038c6
195 195
196 196 --------------------------------------------------------------------------------
197 197 Case #3: client with lfs content and the extension enabled; server with
198 198 non-lfs content, and the extension state controlled by #testcases. The server
199 199 should have an 'lfs' requirement after it picks up its first commit with a blob.
200 200
201 201 $ echo 'this is a big lfs file' > lfs.bin
202 202 $ hg ci -Aqm 'lfs'
203 203 $ hg debugrequires | grep 'lfs'
204 204 lfs
205 205 $ hg debugrequires -R $SERVER_PATH | grep 'lfs'
206 206 [1]
207 207
208 208 #if lfsremote-off
209 209 $ hg push -q
210 210 abort: required features are not supported in the destination: lfs
211 211 (enable the lfs extension on the server)
212 212 [255]
213 213 #else
214 214 $ hg push -q
215 215 #endif
216 216 $ hg debugrequires | grep 'lfs'
217 217 lfs
218 218 $ hg debugrequires -R $SERVER_PATH | grep 'lfs' || true
219 219 lfs (lfsremote-on !)
220 220
221 221 $ hg clone -q http://localhost:$HGPORT $TESTTMP/client3_clone
222 222
223 223 $ hg debugrequires -R $TESTTMP/client3_clone/ | grep 'lfs' || true
224 224 lfs (lfsremote-on !)
225 225 $ hg debugrequires -R $SERVER_PATH | grep 'lfs' || true
226 226 lfs (lfsremote-on !)
227 227
228 228 $ hg init $TESTTMP/client3_pull
229 229 $ hg -R $TESTTMP/client3_pull pull -q http://localhost:$HGPORT
230 230 $ hg debugrequires -R $TESTTMP/client3_pull/ | grep 'lfs' || true
231 231 lfs (lfsremote-on !)
232 232 $ hg debugrequires -R $SERVER_PATH | grep 'lfs' || true
233 233 lfs (lfsremote-on !)
234 234
235 235 Test that the commit/changegroup requirement check hook can be run multiple
236 236 times.
237 237
238 238 $ hg clone -qr 0 http://localhost:$HGPORT $TESTTMP/cmdserve_client3
239 239
240 240 $ cd ../cmdserve_client3
241 241
242 242 >>> from hgclient import check, readchannel, runcommand
243 243 >>> @check
244 244 ... def addrequirement(server):
245 245 ... readchannel(server)
246 246 ... # change the repo in a way that adds the lfs requirement
247 247 ... runcommand(server, [b'pull', b'-qu'])
248 248 ... # Now cause the requirement adding hook to fire again, without going
249 249 ... # through reposetup() again.
250 250 ... with open('file.txt', 'wb') as fp:
251 251 ... fp.write(b'data')
252 252 ... runcommand(server, [b'ci', b'-Aqm', b'non-lfs'])
253 253 *** runcommand pull -qu
254 254 *** runcommand ci -Aqm non-lfs
255 255
256 256 $ cd ../client
257 257
258 258 The difference here is the push failed above when the extension isn't
259 259 enabled on the server.
260 260 $ hg identify http://localhost:$HGPORT
261 261 8374dc4052cb (lfsremote-on !)
262 262 1477875038c6 (lfsremote-off !)
263 263
264 264 Don't bother testing the lfsremote-off cases- the server won't be able
265 265 to launch if there's lfs content and the extension is disabled.
266 266
267 267 #if lfsremote-on
268 268
269 269 --------------------------------------------------------------------------------
270 270 Case #4: client with non-lfs content and the extension disabled; server with
271 271 lfs content, and the extension enabled.
272 272
273 273 $ cat >> $HGRCPATH <<EOF
274 274 > [extensions]
275 275 > lfs = !
276 276 > EOF
277 277
278 278 $ hg init $TESTTMP/client4
279 279 $ cd $TESTTMP/client4
280 280 $ cat >> .hg/hgrc <<EOF
281 281 > [paths]
282 282 > default = http://localhost:$HGPORT
283 283 > EOF
284 284 $ echo 'non-lfs' > nonlfs2.txt
285 285 $ hg ci -Aqm 'non-lfs'
286 286 $ hg debugrequires -R $SERVER_PATH --config extensions.lfs= | grep 'lfs'
287 287 lfs
288 288
289 289 $ hg push -q --force
290 290 warning: repository is unrelated
291 291 $ hg debugrequires -R $SERVER_PATH --config extensions.lfs= | grep 'lfs'
292 292 lfs
293 293
294 294 $ hg clone http://localhost:$HGPORT $TESTTMP/client4_clone
295 295 (remote is using large file support (lfs), but it is explicitly disabled in the local configuration)
296 296 abort: repository requires features unknown to this Mercurial: lfs
297 297 (see https://mercurial-scm.org/wiki/MissingRequirement for more information)
298 298 [255]
299 299 $ hg debugrequires -R $TESTTMP/client4_clone/ | grep 'lfs'
300 300 abort: repository $TESTTMP/client4_clone/ not found
301 301 [1]
302 302 $ hg debugrequires -R $SERVER_PATH --config extensions.lfs= | grep 'lfs'
303 303 lfs
304 304
305 305 TODO: fail more gracefully.
306 306
307 307 $ hg init $TESTTMP/client4_pull
308 308 $ hg -R $TESTTMP/client4_pull pull http://localhost:$HGPORT
309 309 pulling from http://localhost:$HGPORT/
310 310 requesting all changes
311 311 adding changesets
312 312 adding manifests
313 313 adding file changes
314 314 transaction abort!
315 315 rollback completed
316 316 abort: missing processor for flag '0x2000'
317 (the lfs extension must be enabled)
317 318 [50]
318 319 $ hg debugrequires -R $TESTTMP/client4_pull/ | grep 'lfs'
319 320 [1]
320 321 $ hg debugrequires -R $SERVER_PATH --config extensions.lfs= | grep 'lfs'
321 322 lfs
322 323
323 324 $ hg identify http://localhost:$HGPORT
324 325 03b080fa9d93
325 326
326 327 --------------------------------------------------------------------------------
327 328 Case #5: client with non-lfs content and the extension enabled; server with
328 329 lfs content, and the extension enabled.
329 330
330 331 $ cat >> $HGRCPATH <<EOF
331 332 > [extensions]
332 333 > lfs =
333 334 > EOF
334 335 $ echo 'non-lfs' > nonlfs3.txt
335 336 $ hg ci -Aqm 'non-lfs file with lfs client'
336 337
337 338 $ hg push -q
338 339 $ hg debugrequires -R $SERVER_PATH | grep 'lfs'
339 340 lfs
340 341
341 342 $ hg clone -q http://localhost:$HGPORT $TESTTMP/client5_clone
342 343 $ hg debugrequires -R $TESTTMP/client5_clone/ | grep 'lfs'
343 344 lfs
344 345 $ hg debugrequires -R $SERVER_PATH | grep 'lfs'
345 346 lfs
346 347
347 348 $ hg init $TESTTMP/client5_pull
348 349 $ hg -R $TESTTMP/client5_pull pull -q http://localhost:$HGPORT
349 350 $ hg debugrequires -R $TESTTMP/client5_pull/ | grep 'lfs'
350 351 lfs
351 352 $ hg debugrequires -R $SERVER_PATH | grep 'lfs'
352 353 lfs
353 354
354 355 $ hg identify http://localhost:$HGPORT
355 356 c729025cc5e3
356 357
357 358 $ mv $HGRCPATH $HGRCPATH.tmp
358 359 $ cp $HGRCPATH.orig $HGRCPATH
359 360
360 361 >>> from hgclient import bprint, check, readchannel, runcommand, stdout
361 362 >>> @check
362 363 ... def checkflags(server):
363 364 ... readchannel(server)
364 365 ... bprint(b'')
365 366 ... bprint(b'# LFS required- both lfs and non-lfs revlogs have 0x2000 flag')
366 367 ... stdout.flush()
367 368 ... runcommand(server, [b'debugprocessors', b'lfs.bin', b'-R',
368 369 ... b'../server'])
369 370 ... runcommand(server, [b'debugprocessors', b'nonlfs2.txt', b'-R',
370 371 ... b'../server'])
371 372 ... runcommand(server, [b'config', b'extensions', b'--cwd',
372 373 ... b'../server'])
373 374 ...
374 375 ... bprint(b"\n# LFS not enabled- revlogs don't have 0x2000 flag")
375 376 ... stdout.flush()
376 377 ... runcommand(server, [b'debugprocessors', b'nonlfs3.txt'])
377 378 ... runcommand(server, [b'config', b'extensions'])
378 379
379 380 # LFS required- both lfs and non-lfs revlogs have 0x2000 flag
380 381 *** runcommand debugprocessors lfs.bin -R ../server
381 382 registered processor '0x8000'
382 383 registered processor '0x1000'
383 384 registered processor '0x2000'
384 385 *** runcommand debugprocessors nonlfs2.txt -R ../server
385 386 registered processor '0x8000'
386 387 registered processor '0x1000'
387 388 registered processor '0x2000'
388 389 *** runcommand config extensions --cwd ../server
389 390 extensions.debugprocessors=$TESTTMP/debugprocessors.py
390 391 extensions.lfs=
391 392
392 393 # LFS not enabled- revlogs don't have 0x2000 flag
393 394 *** runcommand debugprocessors nonlfs3.txt
394 395 registered processor '0x8000'
395 396 registered processor '0x1000'
396 397 *** runcommand config extensions
397 398 extensions.debugprocessors=$TESTTMP/debugprocessors.py
398 399
399 400 $ rm $HGRCPATH
400 401 $ mv $HGRCPATH.tmp $HGRCPATH
401 402
402 403 $ hg clone $TESTTMP/client $TESTTMP/nonlfs -qr 0 --config extensions.lfs=
403 404 $ cat >> $TESTTMP/nonlfs/.hg/hgrc <<EOF
404 405 > [extensions]
405 406 > lfs = !
406 407 > EOF
407 408
408 409 >>> from hgclient import bprint, check, readchannel, runcommand, stdout
409 410 >>> @check
410 411 ... def checkflags2(server):
411 412 ... readchannel(server)
412 413 ... bprint(b'')
413 414 ... bprint(b'# LFS enabled- both lfs and non-lfs revlogs have 0x2000 flag')
414 415 ... stdout.flush()
415 416 ... runcommand(server, [b'debugprocessors', b'lfs.bin', b'-R',
416 417 ... b'../server'])
417 418 ... runcommand(server, [b'debugprocessors', b'nonlfs2.txt', b'-R',
418 419 ... b'../server'])
419 420 ... runcommand(server, [b'config', b'extensions', b'--cwd',
420 421 ... b'../server'])
421 422 ...
422 423 ... bprint(b'\n# LFS enabled without requirement- revlogs have 0x2000 flag')
423 424 ... stdout.flush()
424 425 ... runcommand(server, [b'debugprocessors', b'nonlfs3.txt'])
425 426 ... runcommand(server, [b'config', b'extensions'])
426 427 ...
427 428 ... bprint(b"\n# LFS disabled locally- revlogs don't have 0x2000 flag")
428 429 ... stdout.flush()
429 430 ... runcommand(server, [b'debugprocessors', b'nonlfs.txt', b'-R',
430 431 ... b'../nonlfs'])
431 432 ... runcommand(server, [b'config', b'extensions', b'--cwd',
432 433 ... b'../nonlfs'])
433 434
434 435 # LFS enabled- both lfs and non-lfs revlogs have 0x2000 flag
435 436 *** runcommand debugprocessors lfs.bin -R ../server
436 437 registered processor '0x8000'
437 438 registered processor '0x1000'
438 439 registered processor '0x2000'
439 440 *** runcommand debugprocessors nonlfs2.txt -R ../server
440 441 registered processor '0x8000'
441 442 registered processor '0x1000'
442 443 registered processor '0x2000'
443 444 *** runcommand config extensions --cwd ../server
444 445 extensions.debugprocessors=$TESTTMP/debugprocessors.py
445 446 extensions.lfs=
446 447
447 448 # LFS enabled without requirement- revlogs have 0x2000 flag
448 449 *** runcommand debugprocessors nonlfs3.txt
449 450 registered processor '0x8000'
450 451 registered processor '0x1000'
451 452 registered processor '0x2000'
452 453 *** runcommand config extensions
453 454 extensions.debugprocessors=$TESTTMP/debugprocessors.py
454 455 extensions.lfs=
455 456
456 457 # LFS disabled locally- revlogs don't have 0x2000 flag
457 458 *** runcommand debugprocessors nonlfs.txt -R ../nonlfs
458 459 registered processor '0x8000'
459 460 registered processor '0x1000'
460 461 *** runcommand config extensions --cwd ../nonlfs
461 462 extensions.debugprocessors=$TESTTMP/debugprocessors.py
462 463 extensions.lfs=!
463 464
464 465 --------------------------------------------------------------------------------
465 466 Case #6: client with lfs content and the extension enabled; server with
466 467 lfs content, and the extension enabled.
467 468
468 469 $ echo 'this is another lfs file' > lfs2.txt
469 470 $ hg ci -Aqm 'lfs file with lfs client'
470 471
471 472 $ hg --config paths.default= push -v http://localhost:$HGPORT
472 473 pushing to http://localhost:$HGPORT/
473 474 lfs: assuming remote store: http://localhost:$HGPORT/.git/info/lfs
474 475 searching for changes
475 476 remote has heads on branch 'default' that are not known locally: 8374dc4052cb
476 477 lfs: uploading a82f1c5cea0d40e3bb3a849686bb4e6ae47ca27e614de55c1ed0325698ef68de (25 bytes)
477 478 lfs: processed: a82f1c5cea0d40e3bb3a849686bb4e6ae47ca27e614de55c1ed0325698ef68de
478 479 lfs: uploaded 1 files (25 bytes)
479 480 1 changesets found
480 481 uncompressed size of bundle content:
481 482 206 (changelog)
482 483 172 (manifests)
483 484 275 lfs2.txt
484 485 remote: adding changesets
485 486 remote: adding manifests
486 487 remote: adding file changes
487 488 remote: added 1 changesets with 1 changes to 1 files
488 489 (sent 8 HTTP requests and * bytes; received * bytes in responses) (glob) (?)
489 490 $ hg debugrequires | grep lfs
490 491 lfs
491 492 $ hg debugrequires -R $SERVER_PATH | grep lfs
492 493 lfs
493 494
494 495 $ hg clone -q http://localhost:$HGPORT $TESTTMP/client6_clone
495 496 $ hg debugrequires -R $TESTTMP/client6_clone/ | grep lfs
496 497 lfs
497 498 $ hg debugrequires -R $SERVER_PATH | grep lfs
498 499 lfs
499 500
500 501 $ hg init $TESTTMP/client6_pull
501 502 $ hg -R $TESTTMP/client6_pull pull -u -v http://localhost:$HGPORT
502 503 pulling from http://localhost:$HGPORT/
503 504 requesting all changes
504 505 adding changesets
505 506 adding manifests
506 507 adding file changes
507 508 calling hook pretxnchangegroup.lfs: hgext.lfs.checkrequireslfs
508 509 added 6 changesets with 5 changes to 5 files (+1 heads)
509 510 new changesets d437e1d24fbd:d3b84d50eacb
510 511 resolving manifests
511 512 lfs: assuming remote store: http://localhost:$HGPORT/.git/info/lfs
512 513 lfs: downloading a82f1c5cea0d40e3bb3a849686bb4e6ae47ca27e614de55c1ed0325698ef68de (25 bytes)
513 514 lfs: processed: a82f1c5cea0d40e3bb3a849686bb4e6ae47ca27e614de55c1ed0325698ef68de
514 515 lfs: downloaded 1 files (25 bytes)
515 516 getting lfs2.txt
516 517 lfs: found a82f1c5cea0d40e3bb3a849686bb4e6ae47ca27e614de55c1ed0325698ef68de in the local lfs store
517 518 getting nonlfs2.txt
518 519 getting nonlfs3.txt
519 520 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
520 521 updated to "d3b84d50eacb: lfs file with lfs client"
521 522 1 other heads for branch "default"
522 523 (sent 3 HTTP requests and * bytes; received * bytes in responses) (glob)
523 524 $ hg debugrequires -R $TESTTMP/client6_pull/ | grep lfs
524 525 lfs
525 526 $ hg debugrequires -R $SERVER_PATH | grep lfs
526 527 lfs
527 528
528 529 $ hg identify http://localhost:$HGPORT
529 530 d3b84d50eacb
530 531
531 532 --------------------------------------------------------------------------------
532 533 Misc: process dies early if a requirement exists and the extension is disabled
533 534
534 535 $ hg --config extensions.lfs=! summary
535 536 abort: repository requires features unknown to this Mercurial: lfs
536 537 (see https://mercurial-scm.org/wiki/MissingRequirement for more information)
537 538 [255]
538 539
539 540 $ echo 'this is an lfs file' > $TESTTMP/client6_clone/lfspair1.bin
540 541 $ echo 'this is an lfs file too' > $TESTTMP/client6_clone/lfspair2.bin
541 542 $ hg -R $TESTTMP/client6_clone ci -Aqm 'add lfs pair'
542 543 $ hg -R $TESTTMP/client6_clone push -q
543 544
544 545 $ hg clone -qU http://localhost:$HGPORT $TESTTMP/bulkfetch
545 546
546 547 Cat doesn't prefetch unless data is needed (e.g. '-T {rawdata}' doesn't need it)
547 548
548 549 $ hg --cwd $TESTTMP/bulkfetch cat -vr tip lfspair1.bin -T '{rawdata}\n{path}\n'
549 550 lfs: assuming remote store: http://localhost:$HGPORT/.git/info/lfs
550 551 version https://git-lfs.github.com/spec/v1
551 552 oid sha256:cf1b2787b74e66547d931b6ebe28ff63303e803cb2baa14a8f57c4383d875782
552 553 size 20
553 554 x-is-binary 0
554 555
555 556 lfspair1.bin
556 557
557 558 $ hg --cwd $TESTTMP/bulkfetch cat -vr tip lfspair1.bin -T json
558 559 lfs: assuming remote store: http://localhost:$HGPORT/.git/info/lfs
559 560 [lfs: assuming remote store: http://localhost:$HGPORT/.git/info/lfs
560 561 lfs: downloading cf1b2787b74e66547d931b6ebe28ff63303e803cb2baa14a8f57c4383d875782 (20 bytes)
561 562 lfs: processed: cf1b2787b74e66547d931b6ebe28ff63303e803cb2baa14a8f57c4383d875782
562 563 lfs: downloaded 1 files (20 bytes)
563 564 lfs: found cf1b2787b74e66547d931b6ebe28ff63303e803cb2baa14a8f57c4383d875782 in the local lfs store
564 565
565 566 {
566 567 "data": "this is an lfs file\n",
567 568 "path": "lfspair1.bin",
568 569 "rawdata": "version https://git-lfs.github.com/spec/v1\noid sha256:cf1b2787b74e66547d931b6ebe28ff63303e803cb2baa14a8f57c4383d875782\nsize 20\nx-is-binary 0\n"
569 570 }
570 571 ]
571 572
572 573 $ rm -r $TESTTMP/bulkfetch/.hg/store/lfs
573 574
574 575 $ hg --cwd $TESTTMP/bulkfetch cat -vr tip lfspair1.bin -T '{data}\n'
575 576 lfs: assuming remote store: http://localhost:$HGPORT/.git/info/lfs
576 577 lfs: assuming remote store: http://localhost:$HGPORT/.git/info/lfs
577 578 lfs: downloading cf1b2787b74e66547d931b6ebe28ff63303e803cb2baa14a8f57c4383d875782 (20 bytes)
578 579 lfs: processed: cf1b2787b74e66547d931b6ebe28ff63303e803cb2baa14a8f57c4383d875782
579 580 lfs: downloaded 1 files (20 bytes)
580 581 lfs: found cf1b2787b74e66547d931b6ebe28ff63303e803cb2baa14a8f57c4383d875782 in the local lfs store
581 582 this is an lfs file
582 583
583 584 $ hg --cwd $TESTTMP/bulkfetch cat -vr tip lfspair2.bin
584 585 lfs: assuming remote store: http://localhost:$HGPORT/.git/info/lfs
585 586 lfs: assuming remote store: http://localhost:$HGPORT/.git/info/lfs
586 587 lfs: downloading d96eda2c74b56e95cfb5ffb66b6503e198cc6fc4a09dc877de925feebc65786e (24 bytes)
587 588 lfs: processed: d96eda2c74b56e95cfb5ffb66b6503e198cc6fc4a09dc877de925feebc65786e
588 589 lfs: downloaded 1 files (24 bytes)
589 590 lfs: found d96eda2c74b56e95cfb5ffb66b6503e198cc6fc4a09dc877de925feebc65786e in the local lfs store
590 591 this is an lfs file too
591 592
592 593 Export will prefetch all needed files across all needed revisions
593 594
594 595 $ rm -r $TESTTMP/bulkfetch/.hg/store/lfs
595 596 $ hg -R $TESTTMP/bulkfetch -v export -r 0:tip -o all.export
596 597 lfs: assuming remote store: http://localhost:$HGPORT/.git/info/lfs
597 598 exporting patches:
598 599 lfs: assuming remote store: http://localhost:$HGPORT/.git/info/lfs
599 600 lfs: need to transfer 4 objects (92 bytes)
600 601 lfs: downloading a82f1c5cea0d40e3bb3a849686bb4e6ae47ca27e614de55c1ed0325698ef68de (25 bytes)
601 602 lfs: processed: a82f1c5cea0d40e3bb3a849686bb4e6ae47ca27e614de55c1ed0325698ef68de
602 603 lfs: downloading bed80f00180ac404b843628ab56a1c1984d6145c391cd1628a7dd7d2598d71fc (23 bytes)
603 604 lfs: processed: bed80f00180ac404b843628ab56a1c1984d6145c391cd1628a7dd7d2598d71fc
604 605 lfs: downloading cf1b2787b74e66547d931b6ebe28ff63303e803cb2baa14a8f57c4383d875782 (20 bytes)
605 606 lfs: processed: cf1b2787b74e66547d931b6ebe28ff63303e803cb2baa14a8f57c4383d875782
606 607 lfs: downloading d96eda2c74b56e95cfb5ffb66b6503e198cc6fc4a09dc877de925feebc65786e (24 bytes)
607 608 lfs: processed: d96eda2c74b56e95cfb5ffb66b6503e198cc6fc4a09dc877de925feebc65786e
608 609 lfs: downloaded 4 files (92 bytes)
609 610 all.export
610 611 lfs: found bed80f00180ac404b843628ab56a1c1984d6145c391cd1628a7dd7d2598d71fc in the local lfs store
611 612 lfs: found a82f1c5cea0d40e3bb3a849686bb4e6ae47ca27e614de55c1ed0325698ef68de in the local lfs store
612 613 lfs: found cf1b2787b74e66547d931b6ebe28ff63303e803cb2baa14a8f57c4383d875782 in the local lfs store
613 614 lfs: found d96eda2c74b56e95cfb5ffb66b6503e198cc6fc4a09dc877de925feebc65786e in the local lfs store
614 615
615 616 Export with selected files is used with `extdiff --patch`
616 617
617 618 $ rm -r $TESTTMP/bulkfetch/.hg/store/lfs
618 619 $ hg --config extensions.extdiff= \
619 620 > -R $TESTTMP/bulkfetch -v extdiff -r 2:tip --patch $TESTTMP/bulkfetch/lfs.bin
620 621 lfs: assuming remote store: http://localhost:$HGPORT/.git/info/lfs
621 622 lfs: assuming remote store: http://localhost:$HGPORT/.git/info/lfs
622 623 lfs: downloading bed80f00180ac404b843628ab56a1c1984d6145c391cd1628a7dd7d2598d71fc (23 bytes)
623 624 lfs: processed: bed80f00180ac404b843628ab56a1c1984d6145c391cd1628a7dd7d2598d71fc
624 625 lfs: downloaded 1 files (23 bytes)
625 626 */hg-8374dc4052cb.patch (glob)
626 627 lfs: found bed80f00180ac404b843628ab56a1c1984d6145c391cd1628a7dd7d2598d71fc in the local lfs store
627 628 */hg-9640b57e77b1.patch (glob)
628 629 --- */hg-8374dc4052cb.patch * (glob)
629 630 +++ */hg-9640b57e77b1.patch * (glob)
630 631 @@ -2,12 +2,7 @@
631 632 # User test
632 633 # Date 0 0
633 634 # Thu Jan 01 00:00:00 1970 +0000
634 635 -# Node ID 8374dc4052cbd388e79d9dc4ddb29784097aa354
635 636 -# Parent 1477875038c60152e391238920a16381c627b487
636 637 -lfs
637 638 +# Node ID 9640b57e77b14c3a0144fb4478b6cc13e13ea0d1
638 639 +# Parent d3b84d50eacbd56638e11abce6b8616aaba54420
639 640 +add lfs pair
640 641
641 642 -diff -r 1477875038c6 -r 8374dc4052cb lfs.bin
642 643 ---- /dev/null Thu Jan 01 00:00:00 1970 +0000
643 644 -+++ b/lfs.bin Thu Jan 01 00:00:00 1970 +0000
644 645 -@@ -0,0 +1,1 @@
645 646 -+this is a big lfs file
646 647 cleaning up temp directory
647 648 [1]
648 649
649 650 Diff will prefetch files
650 651
651 652 $ rm -r $TESTTMP/bulkfetch/.hg/store/lfs
652 653 $ hg -R $TESTTMP/bulkfetch -v diff -r 2:tip
653 654 lfs: assuming remote store: http://localhost:$HGPORT/.git/info/lfs
654 655 lfs: assuming remote store: http://localhost:$HGPORT/.git/info/lfs
655 656 lfs: need to transfer 4 objects (92 bytes)
656 657 lfs: downloading a82f1c5cea0d40e3bb3a849686bb4e6ae47ca27e614de55c1ed0325698ef68de (25 bytes)
657 658 lfs: processed: a82f1c5cea0d40e3bb3a849686bb4e6ae47ca27e614de55c1ed0325698ef68de
658 659 lfs: downloading bed80f00180ac404b843628ab56a1c1984d6145c391cd1628a7dd7d2598d71fc (23 bytes)
659 660 lfs: processed: bed80f00180ac404b843628ab56a1c1984d6145c391cd1628a7dd7d2598d71fc
660 661 lfs: downloading cf1b2787b74e66547d931b6ebe28ff63303e803cb2baa14a8f57c4383d875782 (20 bytes)
661 662 lfs: processed: cf1b2787b74e66547d931b6ebe28ff63303e803cb2baa14a8f57c4383d875782
662 663 lfs: downloading d96eda2c74b56e95cfb5ffb66b6503e198cc6fc4a09dc877de925feebc65786e (24 bytes)
663 664 lfs: processed: d96eda2c74b56e95cfb5ffb66b6503e198cc6fc4a09dc877de925feebc65786e
664 665 lfs: downloaded 4 files (92 bytes)
665 666 lfs: found bed80f00180ac404b843628ab56a1c1984d6145c391cd1628a7dd7d2598d71fc in the local lfs store
666 667 lfs: found a82f1c5cea0d40e3bb3a849686bb4e6ae47ca27e614de55c1ed0325698ef68de in the local lfs store
667 668 lfs: found cf1b2787b74e66547d931b6ebe28ff63303e803cb2baa14a8f57c4383d875782 in the local lfs store
668 669 lfs: found d96eda2c74b56e95cfb5ffb66b6503e198cc6fc4a09dc877de925feebc65786e in the local lfs store
669 670 diff -r 8374dc4052cb -r 9640b57e77b1 lfs.bin
670 671 --- a/lfs.bin Thu Jan 01 00:00:00 1970 +0000
671 672 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
672 673 @@ -1,1 +0,0 @@
673 674 -this is a big lfs file
674 675 diff -r 8374dc4052cb -r 9640b57e77b1 lfs2.txt
675 676 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
676 677 +++ b/lfs2.txt Thu Jan 01 00:00:00 1970 +0000
677 678 @@ -0,0 +1,1 @@
678 679 +this is another lfs file
679 680 diff -r 8374dc4052cb -r 9640b57e77b1 lfspair1.bin
680 681 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
681 682 +++ b/lfspair1.bin Thu Jan 01 00:00:00 1970 +0000
682 683 @@ -0,0 +1,1 @@
683 684 +this is an lfs file
684 685 diff -r 8374dc4052cb -r 9640b57e77b1 lfspair2.bin
685 686 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
686 687 +++ b/lfspair2.bin Thu Jan 01 00:00:00 1970 +0000
687 688 @@ -0,0 +1,1 @@
688 689 +this is an lfs file too
689 690 diff -r 8374dc4052cb -r 9640b57e77b1 nonlfs.txt
690 691 --- a/nonlfs.txt Thu Jan 01 00:00:00 1970 +0000
691 692 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
692 693 @@ -1,1 +0,0 @@
693 694 -non-lfs
694 695 diff -r 8374dc4052cb -r 9640b57e77b1 nonlfs3.txt
695 696 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
696 697 +++ b/nonlfs3.txt Thu Jan 01 00:00:00 1970 +0000
697 698 @@ -0,0 +1,1 @@
698 699 +non-lfs
699 700
700 701 Only the files required by diff are prefetched
701 702
702 703 $ rm -r $TESTTMP/bulkfetch/.hg/store/lfs
703 704 $ hg -R $TESTTMP/bulkfetch -v diff -r 2:tip $TESTTMP/bulkfetch/lfspair2.bin
704 705 lfs: assuming remote store: http://localhost:$HGPORT/.git/info/lfs
705 706 lfs: assuming remote store: http://localhost:$HGPORT/.git/info/lfs
706 707 lfs: downloading d96eda2c74b56e95cfb5ffb66b6503e198cc6fc4a09dc877de925feebc65786e (24 bytes)
707 708 lfs: processed: d96eda2c74b56e95cfb5ffb66b6503e198cc6fc4a09dc877de925feebc65786e
708 709 lfs: downloaded 1 files (24 bytes)
709 710 lfs: found d96eda2c74b56e95cfb5ffb66b6503e198cc6fc4a09dc877de925feebc65786e in the local lfs store
710 711 diff -r 8374dc4052cb -r 9640b57e77b1 lfspair2.bin
711 712 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
712 713 +++ b/lfspair2.bin Thu Jan 01 00:00:00 1970 +0000
713 714 @@ -0,0 +1,1 @@
714 715 +this is an lfs file too
715 716
716 717 #endif
717 718
718 719 $ "$PYTHON" $TESTDIR/killdaemons.py $DAEMON_PIDS
719 720
720 721 $ cat $TESTTMP/errors.log
General Comments 0
You need to be logged in to leave comments. Login now