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