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