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