##// END OF EJS Templates
largefiles: include 'largefiles' in converted repository requirements
Eli Carter -
r15303:07811b3b stable
parent child Browse files
Show More
@@ -1,481 +1,486
1 # Copyright 2009-2010 Gregory P. Ward
1 # Copyright 2009-2010 Gregory P. Ward
2 # Copyright 2009-2010 Intelerad Medical Systems Incorporated
2 # Copyright 2009-2010 Intelerad Medical Systems Incorporated
3 # Copyright 2010-2011 Fog Creek Software
3 # Copyright 2010-2011 Fog Creek Software
4 # Copyright 2010-2011 Unity Technologies
4 # Copyright 2010-2011 Unity Technologies
5 #
5 #
6 # This software may be used and distributed according to the terms of the
6 # This software may be used and distributed according to the terms of the
7 # GNU General Public License version 2 or any later version.
7 # GNU General Public License version 2 or any later version.
8
8
9 '''High-level command function for lfconvert, plus the cmdtable.'''
9 '''High-level command function for lfconvert, plus the cmdtable.'''
10
10
11 import os
11 import os
12 import shutil
12 import shutil
13
13
14 from mercurial import util, match as match_, hg, node, context, error
14 from mercurial import util, match as match_, hg, node, context, error
15 from mercurial.i18n import _
15 from mercurial.i18n import _
16
16
17 import lfutil
17 import lfutil
18 import basestore
18 import basestore
19
19
20 # -- Commands ----------------------------------------------------------
20 # -- Commands ----------------------------------------------------------
21
21
22 def lfconvert(ui, src, dest, *pats, **opts):
22 def lfconvert(ui, src, dest, *pats, **opts):
23 '''convert a normal repository to a largefiles repository
23 '''convert a normal repository to a largefiles repository
24
24
25 Convert repository SOURCE to a new repository DEST, identical to
25 Convert repository SOURCE to a new repository DEST, identical to
26 SOURCE except that certain files will be converted as largefiles:
26 SOURCE except that certain files will be converted as largefiles:
27 specifically, any file that matches any PATTERN *or* whose size is
27 specifically, any file that matches any PATTERN *or* whose size is
28 above the minimum size threshold is converted as a largefile. The
28 above the minimum size threshold is converted as a largefile. The
29 size used to determine whether or not to track a file as a
29 size used to determine whether or not to track a file as a
30 largefile is the size of the first version of the file. The
30 largefile is the size of the first version of the file. The
31 minimum size can be specified either with --size or in
31 minimum size can be specified either with --size or in
32 configuration as ``largefiles.size``.
32 configuration as ``largefiles.size``.
33
33
34 After running this command you will need to make sure that
34 After running this command you will need to make sure that
35 largefiles is enabled anywhere you intend to push the new
35 largefiles is enabled anywhere you intend to push the new
36 repository.
36 repository.
37
37
38 Use --tonormal to convert largefiles back to normal files; after
38 Use --tonormal to convert largefiles back to normal files; after
39 this, the DEST repository can be used without largefiles at all.'''
39 this, the DEST repository can be used without largefiles at all.'''
40
40
41 if opts['tonormal']:
41 if opts['tonormal']:
42 tolfile = False
42 tolfile = False
43 else:
43 else:
44 tolfile = True
44 tolfile = True
45 size = lfutil.getminsize(ui, True, opts.get('size'), default=None)
45 size = lfutil.getminsize(ui, True, opts.get('size'), default=None)
46 try:
46 try:
47 rsrc = hg.repository(ui, src)
47 rsrc = hg.repository(ui, src)
48 if not rsrc.local():
48 if not rsrc.local():
49 raise util.Abort(_('%s is not a local Mercurial repo') % src)
49 raise util.Abort(_('%s is not a local Mercurial repo') % src)
50 except error.RepoError, err:
50 except error.RepoError, err:
51 ui.traceback()
51 ui.traceback()
52 raise util.Abort(err.args[0])
52 raise util.Abort(err.args[0])
53 if os.path.exists(dest):
53 if os.path.exists(dest):
54 if not os.path.isdir(dest):
54 if not os.path.isdir(dest):
55 raise util.Abort(_('destination %s already exists') % dest)
55 raise util.Abort(_('destination %s already exists') % dest)
56 elif os.listdir(dest):
56 elif os.listdir(dest):
57 raise util.Abort(_('destination %s is not empty') % dest)
57 raise util.Abort(_('destination %s is not empty') % dest)
58 try:
58 try:
59 ui.status(_('initializing destination %s\n') % dest)
59 ui.status(_('initializing destination %s\n') % dest)
60 rdst = hg.repository(ui, dest, create=True)
60 rdst = hg.repository(ui, dest, create=True)
61 if not rdst.local():
61 if not rdst.local():
62 raise util.Abort(_('%s is not a local Mercurial repo') % dest)
62 raise util.Abort(_('%s is not a local Mercurial repo') % dest)
63 except error.RepoError:
63 except error.RepoError:
64 ui.traceback()
64 ui.traceback()
65 raise util.Abort(_('%s is not a repo') % dest)
65 raise util.Abort(_('%s is not a repo') % dest)
66
66
67 success = False
67 success = False
68 try:
68 try:
69 # Lock destination to prevent modification while it is converted to.
69 # Lock destination to prevent modification while it is converted to.
70 # Don't need to lock src because we are just reading from its history
70 # Don't need to lock src because we are just reading from its history
71 # which can't change.
71 # which can't change.
72 dst_lock = rdst.lock()
72 dst_lock = rdst.lock()
73
73
74 # Get a list of all changesets in the source. The easy way to do this
74 # Get a list of all changesets in the source. The easy way to do this
75 # is to simply walk the changelog, using changelog.nodesbewteen().
75 # is to simply walk the changelog, using changelog.nodesbewteen().
76 # Take a look at mercurial/revlog.py:639 for more details.
76 # Take a look at mercurial/revlog.py:639 for more details.
77 # Use a generator instead of a list to decrease memory usage
77 # Use a generator instead of a list to decrease memory usage
78 ctxs = (rsrc[ctx] for ctx in rsrc.changelog.nodesbetween(None,
78 ctxs = (rsrc[ctx] for ctx in rsrc.changelog.nodesbetween(None,
79 rsrc.heads())[0])
79 rsrc.heads())[0])
80 revmap = {node.nullid: node.nullid}
80 revmap = {node.nullid: node.nullid}
81 if tolfile:
81 if tolfile:
82 lfiles = set()
82 lfiles = set()
83 normalfiles = set()
83 normalfiles = set()
84 if not pats:
84 if not pats:
85 pats = ui.config(lfutil.longname, 'patterns', default=())
85 pats = ui.config(lfutil.longname, 'patterns', default=())
86 if pats:
86 if pats:
87 pats = pats.split(' ')
87 pats = pats.split(' ')
88 if pats:
88 if pats:
89 matcher = match_.match(rsrc.root, '', list(pats))
89 matcher = match_.match(rsrc.root, '', list(pats))
90 else:
90 else:
91 matcher = None
91 matcher = None
92
92
93 lfiletohash = {}
93 lfiletohash = {}
94 for ctx in ctxs:
94 for ctx in ctxs:
95 ui.progress(_('converting revisions'), ctx.rev(),
95 ui.progress(_('converting revisions'), ctx.rev(),
96 unit=_('revision'), total=rsrc['tip'].rev())
96 unit=_('revision'), total=rsrc['tip'].rev())
97 _lfconvert_addchangeset(rsrc, rdst, ctx, revmap,
97 _lfconvert_addchangeset(rsrc, rdst, ctx, revmap,
98 lfiles, normalfiles, matcher, size, lfiletohash)
98 lfiles, normalfiles, matcher, size, lfiletohash)
99 ui.progress(_('converting revisions'), None)
99 ui.progress(_('converting revisions'), None)
100
100
101 if os.path.exists(rdst.wjoin(lfutil.shortname)):
101 if os.path.exists(rdst.wjoin(lfutil.shortname)):
102 shutil.rmtree(rdst.wjoin(lfutil.shortname))
102 shutil.rmtree(rdst.wjoin(lfutil.shortname))
103
103
104 for f in lfiletohash.keys():
104 for f in lfiletohash.keys():
105 if os.path.isfile(rdst.wjoin(f)):
105 if os.path.isfile(rdst.wjoin(f)):
106 os.unlink(rdst.wjoin(f))
106 os.unlink(rdst.wjoin(f))
107 try:
107 try:
108 os.removedirs(os.path.dirname(rdst.wjoin(f)))
108 os.removedirs(os.path.dirname(rdst.wjoin(f)))
109 except OSError:
109 except OSError:
110 pass
110 pass
111
111
112 # If there were any files converted to largefiles, add largefiles
113 # to the destination repository's requirements.
114 if lfiles:
115 rdst.requirements.add('largefiles')
116 rdst._writerequirements()
112 else:
117 else:
113 for ctx in ctxs:
118 for ctx in ctxs:
114 ui.progress(_('converting revisions'), ctx.rev(),
119 ui.progress(_('converting revisions'), ctx.rev(),
115 unit=_('revision'), total=rsrc['tip'].rev())
120 unit=_('revision'), total=rsrc['tip'].rev())
116 _addchangeset(ui, rsrc, rdst, ctx, revmap)
121 _addchangeset(ui, rsrc, rdst, ctx, revmap)
117
122
118 ui.progress(_('converting revisions'), None)
123 ui.progress(_('converting revisions'), None)
119 success = True
124 success = True
120 finally:
125 finally:
121 if not success:
126 if not success:
122 # we failed, remove the new directory
127 # we failed, remove the new directory
123 shutil.rmtree(rdst.root)
128 shutil.rmtree(rdst.root)
124 dst_lock.release()
129 dst_lock.release()
125
130
126 def _addchangeset(ui, rsrc, rdst, ctx, revmap):
131 def _addchangeset(ui, rsrc, rdst, ctx, revmap):
127 # Convert src parents to dst parents
132 # Convert src parents to dst parents
128 parents = []
133 parents = []
129 for p in ctx.parents():
134 for p in ctx.parents():
130 parents.append(revmap[p.node()])
135 parents.append(revmap[p.node()])
131 while len(parents) < 2:
136 while len(parents) < 2:
132 parents.append(node.nullid)
137 parents.append(node.nullid)
133
138
134 # Generate list of changed files
139 # Generate list of changed files
135 files = set(ctx.files())
140 files = set(ctx.files())
136 if node.nullid not in parents:
141 if node.nullid not in parents:
137 mc = ctx.manifest()
142 mc = ctx.manifest()
138 mp1 = ctx.parents()[0].manifest()
143 mp1 = ctx.parents()[0].manifest()
139 mp2 = ctx.parents()[1].manifest()
144 mp2 = ctx.parents()[1].manifest()
140 files |= (set(mp1) | set(mp2)) - set(mc)
145 files |= (set(mp1) | set(mp2)) - set(mc)
141 for f in mc:
146 for f in mc:
142 if mc[f] != mp1.get(f, None) or mc[f] != mp2.get(f, None):
147 if mc[f] != mp1.get(f, None) or mc[f] != mp2.get(f, None):
143 files.add(f)
148 files.add(f)
144
149
145 def getfilectx(repo, memctx, f):
150 def getfilectx(repo, memctx, f):
146 if lfutil.standin(f) in files:
151 if lfutil.standin(f) in files:
147 # if the file isn't in the manifest then it was removed
152 # if the file isn't in the manifest then it was removed
148 # or renamed, raise IOError to indicate this
153 # or renamed, raise IOError to indicate this
149 try:
154 try:
150 fctx = ctx.filectx(lfutil.standin(f))
155 fctx = ctx.filectx(lfutil.standin(f))
151 except error.LookupError:
156 except error.LookupError:
152 raise IOError()
157 raise IOError()
153 renamed = fctx.renamed()
158 renamed = fctx.renamed()
154 if renamed:
159 if renamed:
155 renamed = lfutil.splitstandin(renamed[0])
160 renamed = lfutil.splitstandin(renamed[0])
156
161
157 hash = fctx.data().strip()
162 hash = fctx.data().strip()
158 path = lfutil.findfile(rsrc, hash)
163 path = lfutil.findfile(rsrc, hash)
159 ### TODO: What if the file is not cached?
164 ### TODO: What if the file is not cached?
160 data = ''
165 data = ''
161 fd = None
166 fd = None
162 try:
167 try:
163 fd = open(path, 'rb')
168 fd = open(path, 'rb')
164 data = fd.read()
169 data = fd.read()
165 finally:
170 finally:
166 if fd:
171 if fd:
167 fd.close()
172 fd.close()
168 return context.memfilectx(f, data, 'l' in fctx.flags(),
173 return context.memfilectx(f, data, 'l' in fctx.flags(),
169 'x' in fctx.flags(), renamed)
174 'x' in fctx.flags(), renamed)
170 else:
175 else:
171 try:
176 try:
172 fctx = ctx.filectx(f)
177 fctx = ctx.filectx(f)
173 except error.LookupError:
178 except error.LookupError:
174 raise IOError()
179 raise IOError()
175 renamed = fctx.renamed()
180 renamed = fctx.renamed()
176 if renamed:
181 if renamed:
177 renamed = renamed[0]
182 renamed = renamed[0]
178 data = fctx.data()
183 data = fctx.data()
179 if f == '.hgtags':
184 if f == '.hgtags':
180 newdata = []
185 newdata = []
181 for line in data.splitlines():
186 for line in data.splitlines():
182 id, name = line.split(' ', 1)
187 id, name = line.split(' ', 1)
183 newdata.append('%s %s\n' % (node.hex(revmap[node.bin(id)]),
188 newdata.append('%s %s\n' % (node.hex(revmap[node.bin(id)]),
184 name))
189 name))
185 data = ''.join(newdata)
190 data = ''.join(newdata)
186 return context.memfilectx(f, data, 'l' in fctx.flags(),
191 return context.memfilectx(f, data, 'l' in fctx.flags(),
187 'x' in fctx.flags(), renamed)
192 'x' in fctx.flags(), renamed)
188
193
189 dstfiles = []
194 dstfiles = []
190 for file in files:
195 for file in files:
191 if lfutil.isstandin(file):
196 if lfutil.isstandin(file):
192 dstfiles.append(lfutil.splitstandin(file))
197 dstfiles.append(lfutil.splitstandin(file))
193 else:
198 else:
194 dstfiles.append(file)
199 dstfiles.append(file)
195 # Commit
200 # Commit
196 mctx = context.memctx(rdst, parents, ctx.description(), dstfiles,
201 mctx = context.memctx(rdst, parents, ctx.description(), dstfiles,
197 getfilectx, ctx.user(), ctx.date(), ctx.extra())
202 getfilectx, ctx.user(), ctx.date(), ctx.extra())
198 ret = rdst.commitctx(mctx)
203 ret = rdst.commitctx(mctx)
199 rdst.dirstate.setparents(ret)
204 rdst.dirstate.setparents(ret)
200 revmap[ctx.node()] = rdst.changelog.tip()
205 revmap[ctx.node()] = rdst.changelog.tip()
201
206
202 def _lfconvert_addchangeset(rsrc, rdst, ctx, revmap, lfiles, normalfiles,
207 def _lfconvert_addchangeset(rsrc, rdst, ctx, revmap, lfiles, normalfiles,
203 matcher, size, lfiletohash):
208 matcher, size, lfiletohash):
204 # Convert src parents to dst parents
209 # Convert src parents to dst parents
205 parents = []
210 parents = []
206 for p in ctx.parents():
211 for p in ctx.parents():
207 parents.append(revmap[p.node()])
212 parents.append(revmap[p.node()])
208 while len(parents) < 2:
213 while len(parents) < 2:
209 parents.append(node.nullid)
214 parents.append(node.nullid)
210
215
211 # Generate list of changed files
216 # Generate list of changed files
212 files = set(ctx.files())
217 files = set(ctx.files())
213 if node.nullid not in parents:
218 if node.nullid not in parents:
214 mc = ctx.manifest()
219 mc = ctx.manifest()
215 mp1 = ctx.parents()[0].manifest()
220 mp1 = ctx.parents()[0].manifest()
216 mp2 = ctx.parents()[1].manifest()
221 mp2 = ctx.parents()[1].manifest()
217 files |= (set(mp1) | set(mp2)) - set(mc)
222 files |= (set(mp1) | set(mp2)) - set(mc)
218 for f in mc:
223 for f in mc:
219 if mc[f] != mp1.get(f, None) or mc[f] != mp2.get(f, None):
224 if mc[f] != mp1.get(f, None) or mc[f] != mp2.get(f, None):
220 files.add(f)
225 files.add(f)
221
226
222 dstfiles = []
227 dstfiles = []
223 for f in files:
228 for f in files:
224 if f not in lfiles and f not in normalfiles:
229 if f not in lfiles and f not in normalfiles:
225 islfile = _islfile(f, ctx, matcher, size)
230 islfile = _islfile(f, ctx, matcher, size)
226 # If this file was renamed or copied then copy
231 # If this file was renamed or copied then copy
227 # the lfileness of its predecessor
232 # the lfileness of its predecessor
228 if f in ctx.manifest():
233 if f in ctx.manifest():
229 fctx = ctx.filectx(f)
234 fctx = ctx.filectx(f)
230 renamed = fctx.renamed()
235 renamed = fctx.renamed()
231 renamedlfile = renamed and renamed[0] in lfiles
236 renamedlfile = renamed and renamed[0] in lfiles
232 islfile |= renamedlfile
237 islfile |= renamedlfile
233 if 'l' in fctx.flags():
238 if 'l' in fctx.flags():
234 if renamedlfile:
239 if renamedlfile:
235 raise util.Abort(
240 raise util.Abort(
236 _('Renamed/copied largefile %s becomes symlink')
241 _('Renamed/copied largefile %s becomes symlink')
237 % f)
242 % f)
238 islfile = False
243 islfile = False
239 if islfile:
244 if islfile:
240 lfiles.add(f)
245 lfiles.add(f)
241 else:
246 else:
242 normalfiles.add(f)
247 normalfiles.add(f)
243
248
244 if f in lfiles:
249 if f in lfiles:
245 dstfiles.append(lfutil.standin(f))
250 dstfiles.append(lfutil.standin(f))
246 # largefile in manifest if it has not been removed/renamed
251 # largefile in manifest if it has not been removed/renamed
247 if f in ctx.manifest():
252 if f in ctx.manifest():
248 if 'l' in ctx.filectx(f).flags():
253 if 'l' in ctx.filectx(f).flags():
249 if renamed and renamed[0] in lfiles:
254 if renamed and renamed[0] in lfiles:
250 raise util.Abort(_('largefile %s becomes symlink') % f)
255 raise util.Abort(_('largefile %s becomes symlink') % f)
251
256
252 # largefile was modified, update standins
257 # largefile was modified, update standins
253 fullpath = rdst.wjoin(f)
258 fullpath = rdst.wjoin(f)
254 lfutil.createdir(os.path.dirname(fullpath))
259 lfutil.createdir(os.path.dirname(fullpath))
255 m = util.sha1('')
260 m = util.sha1('')
256 m.update(ctx[f].data())
261 m.update(ctx[f].data())
257 hash = m.hexdigest()
262 hash = m.hexdigest()
258 if f not in lfiletohash or lfiletohash[f] != hash:
263 if f not in lfiletohash or lfiletohash[f] != hash:
259 try:
264 try:
260 fd = open(fullpath, 'wb')
265 fd = open(fullpath, 'wb')
261 fd.write(ctx[f].data())
266 fd.write(ctx[f].data())
262 finally:
267 finally:
263 if fd:
268 if fd:
264 fd.close()
269 fd.close()
265 executable = 'x' in ctx[f].flags()
270 executable = 'x' in ctx[f].flags()
266 os.chmod(fullpath, lfutil.getmode(executable))
271 os.chmod(fullpath, lfutil.getmode(executable))
267 lfutil.writestandin(rdst, lfutil.standin(f), hash,
272 lfutil.writestandin(rdst, lfutil.standin(f), hash,
268 executable)
273 executable)
269 lfiletohash[f] = hash
274 lfiletohash[f] = hash
270 else:
275 else:
271 # normal file
276 # normal file
272 dstfiles.append(f)
277 dstfiles.append(f)
273
278
274 def getfilectx(repo, memctx, f):
279 def getfilectx(repo, memctx, f):
275 if lfutil.isstandin(f):
280 if lfutil.isstandin(f):
276 # if the file isn't in the manifest then it was removed
281 # if the file isn't in the manifest then it was removed
277 # or renamed, raise IOError to indicate this
282 # or renamed, raise IOError to indicate this
278 srcfname = lfutil.splitstandin(f)
283 srcfname = lfutil.splitstandin(f)
279 try:
284 try:
280 fctx = ctx.filectx(srcfname)
285 fctx = ctx.filectx(srcfname)
281 except error.LookupError:
286 except error.LookupError:
282 raise IOError()
287 raise IOError()
283 renamed = fctx.renamed()
288 renamed = fctx.renamed()
284 if renamed:
289 if renamed:
285 # standin is always a largefile because largefile-ness
290 # standin is always a largefile because largefile-ness
286 # doesn't change after rename or copy
291 # doesn't change after rename or copy
287 renamed = lfutil.standin(renamed[0])
292 renamed = lfutil.standin(renamed[0])
288
293
289 return context.memfilectx(f, lfiletohash[srcfname], 'l' in
294 return context.memfilectx(f, lfiletohash[srcfname], 'l' in
290 fctx.flags(), 'x' in fctx.flags(), renamed)
295 fctx.flags(), 'x' in fctx.flags(), renamed)
291 else:
296 else:
292 try:
297 try:
293 fctx = ctx.filectx(f)
298 fctx = ctx.filectx(f)
294 except error.LookupError:
299 except error.LookupError:
295 raise IOError()
300 raise IOError()
296 renamed = fctx.renamed()
301 renamed = fctx.renamed()
297 if renamed:
302 if renamed:
298 renamed = renamed[0]
303 renamed = renamed[0]
299
304
300 data = fctx.data()
305 data = fctx.data()
301 if f == '.hgtags':
306 if f == '.hgtags':
302 newdata = []
307 newdata = []
303 for line in data.splitlines():
308 for line in data.splitlines():
304 id, name = line.split(' ', 1)
309 id, name = line.split(' ', 1)
305 newdata.append('%s %s\n' % (node.hex(revmap[node.bin(id)]),
310 newdata.append('%s %s\n' % (node.hex(revmap[node.bin(id)]),
306 name))
311 name))
307 data = ''.join(newdata)
312 data = ''.join(newdata)
308 return context.memfilectx(f, data, 'l' in fctx.flags(),
313 return context.memfilectx(f, data, 'l' in fctx.flags(),
309 'x' in fctx.flags(), renamed)
314 'x' in fctx.flags(), renamed)
310
315
311 # Commit
316 # Commit
312 mctx = context.memctx(rdst, parents, ctx.description(), dstfiles,
317 mctx = context.memctx(rdst, parents, ctx.description(), dstfiles,
313 getfilectx, ctx.user(), ctx.date(), ctx.extra())
318 getfilectx, ctx.user(), ctx.date(), ctx.extra())
314 ret = rdst.commitctx(mctx)
319 ret = rdst.commitctx(mctx)
315 rdst.dirstate.setparents(ret)
320 rdst.dirstate.setparents(ret)
316 revmap[ctx.node()] = rdst.changelog.tip()
321 revmap[ctx.node()] = rdst.changelog.tip()
317
322
318 def _islfile(file, ctx, matcher, size):
323 def _islfile(file, ctx, matcher, size):
319 '''Return true if file should be considered a largefile, i.e.
324 '''Return true if file should be considered a largefile, i.e.
320 matcher matches it or it is larger than size.'''
325 matcher matches it or it is larger than size.'''
321 # never store special .hg* files as largefiles
326 # never store special .hg* files as largefiles
322 if file == '.hgtags' or file == '.hgignore' or file == '.hgsigs':
327 if file == '.hgtags' or file == '.hgignore' or file == '.hgsigs':
323 return False
328 return False
324 if matcher and matcher(file):
329 if matcher and matcher(file):
325 return True
330 return True
326 try:
331 try:
327 return ctx.filectx(file).size() >= size * 1024 * 1024
332 return ctx.filectx(file).size() >= size * 1024 * 1024
328 except error.LookupError:
333 except error.LookupError:
329 return False
334 return False
330
335
331 def uploadlfiles(ui, rsrc, rdst, files):
336 def uploadlfiles(ui, rsrc, rdst, files):
332 '''upload largefiles to the central store'''
337 '''upload largefiles to the central store'''
333
338
334 # Don't upload locally. All largefiles are in the system wide cache
339 # Don't upload locally. All largefiles are in the system wide cache
335 # so the other repo can just get them from there.
340 # so the other repo can just get them from there.
336 if not files or rdst.local():
341 if not files or rdst.local():
337 return
342 return
338
343
339 store = basestore._openstore(rsrc, rdst, put=True)
344 store = basestore._openstore(rsrc, rdst, put=True)
340
345
341 at = 0
346 at = 0
342 files = filter(lambda h: not store.exists(h), files)
347 files = filter(lambda h: not store.exists(h), files)
343 for hash in files:
348 for hash in files:
344 ui.progress(_('uploading largefiles'), at, unit='largefile',
349 ui.progress(_('uploading largefiles'), at, unit='largefile',
345 total=len(files))
350 total=len(files))
346 source = lfutil.findfile(rsrc, hash)
351 source = lfutil.findfile(rsrc, hash)
347 if not source:
352 if not source:
348 raise util.Abort(_('largefile %s missing from store'
353 raise util.Abort(_('largefile %s missing from store'
349 ' (needs to be uploaded)') % hash)
354 ' (needs to be uploaded)') % hash)
350 # XXX check for errors here
355 # XXX check for errors here
351 store.put(source, hash)
356 store.put(source, hash)
352 at += 1
357 at += 1
353 ui.progress(_('uploading largefiles'), None)
358 ui.progress(_('uploading largefiles'), None)
354
359
355 def verifylfiles(ui, repo, all=False, contents=False):
360 def verifylfiles(ui, repo, all=False, contents=False):
356 '''Verify that every big file revision in the current changeset
361 '''Verify that every big file revision in the current changeset
357 exists in the central store. With --contents, also verify that
362 exists in the central store. With --contents, also verify that
358 the contents of each big file revision are correct (SHA-1 hash
363 the contents of each big file revision are correct (SHA-1 hash
359 matches the revision ID). With --all, check every changeset in
364 matches the revision ID). With --all, check every changeset in
360 this repository.'''
365 this repository.'''
361 if all:
366 if all:
362 # Pass a list to the function rather than an iterator because we know a
367 # Pass a list to the function rather than an iterator because we know a
363 # list will work.
368 # list will work.
364 revs = range(len(repo))
369 revs = range(len(repo))
365 else:
370 else:
366 revs = ['.']
371 revs = ['.']
367
372
368 store = basestore._openstore(repo)
373 store = basestore._openstore(repo)
369 return store.verify(revs, contents=contents)
374 return store.verify(revs, contents=contents)
370
375
371 def cachelfiles(ui, repo, node):
376 def cachelfiles(ui, repo, node):
372 '''cachelfiles ensures that all largefiles needed by the specified revision
377 '''cachelfiles ensures that all largefiles needed by the specified revision
373 are present in the repository's largefile cache.
378 are present in the repository's largefile cache.
374
379
375 returns a tuple (cached, missing). cached is the list of files downloaded
380 returns a tuple (cached, missing). cached is the list of files downloaded
376 by this operation; missing is the list of files that were needed but could
381 by this operation; missing is the list of files that were needed but could
377 not be found.'''
382 not be found.'''
378 lfiles = lfutil.listlfiles(repo, node)
383 lfiles = lfutil.listlfiles(repo, node)
379 toget = []
384 toget = []
380
385
381 for lfile in lfiles:
386 for lfile in lfiles:
382 expectedhash = repo[node][lfutil.standin(lfile)].data().strip()
387 expectedhash = repo[node][lfutil.standin(lfile)].data().strip()
383 # if it exists and its hash matches, it might have been locally
388 # if it exists and its hash matches, it might have been locally
384 # modified before updating and the user chose 'local'. in this case,
389 # modified before updating and the user chose 'local'. in this case,
385 # it will not be in any store, so don't look for it.
390 # it will not be in any store, so don't look for it.
386 if ((not os.path.exists(repo.wjoin(lfile)) or
391 if ((not os.path.exists(repo.wjoin(lfile)) or
387 expectedhash != lfutil.hashfile(repo.wjoin(lfile))) and
392 expectedhash != lfutil.hashfile(repo.wjoin(lfile))) and
388 not lfutil.findfile(repo, expectedhash)):
393 not lfutil.findfile(repo, expectedhash)):
389 toget.append((lfile, expectedhash))
394 toget.append((lfile, expectedhash))
390
395
391 if toget:
396 if toget:
392 store = basestore._openstore(repo)
397 store = basestore._openstore(repo)
393 ret = store.get(toget)
398 ret = store.get(toget)
394 return ret
399 return ret
395
400
396 return ([], [])
401 return ([], [])
397
402
398 def updatelfiles(ui, repo, filelist=None, printmessage=True):
403 def updatelfiles(ui, repo, filelist=None, printmessage=True):
399 wlock = repo.wlock()
404 wlock = repo.wlock()
400 try:
405 try:
401 lfdirstate = lfutil.openlfdirstate(ui, repo)
406 lfdirstate = lfutil.openlfdirstate(ui, repo)
402 lfiles = set(lfutil.listlfiles(repo)) | set(lfdirstate)
407 lfiles = set(lfutil.listlfiles(repo)) | set(lfdirstate)
403
408
404 if filelist is not None:
409 if filelist is not None:
405 lfiles = [f for f in lfiles if f in filelist]
410 lfiles = [f for f in lfiles if f in filelist]
406
411
407 printed = False
412 printed = False
408 if printmessage and lfiles:
413 if printmessage and lfiles:
409 ui.status(_('getting changed largefiles\n'))
414 ui.status(_('getting changed largefiles\n'))
410 printed = True
415 printed = True
411 cachelfiles(ui, repo, '.')
416 cachelfiles(ui, repo, '.')
412
417
413 updated, removed = 0, 0
418 updated, removed = 0, 0
414 for i in map(lambda f: _updatelfile(repo, lfdirstate, f), lfiles):
419 for i in map(lambda f: _updatelfile(repo, lfdirstate, f), lfiles):
415 # increment the appropriate counter according to _updatelfile's
420 # increment the appropriate counter according to _updatelfile's
416 # return value
421 # return value
417 updated += i > 0 and i or 0
422 updated += i > 0 and i or 0
418 removed -= i < 0 and i or 0
423 removed -= i < 0 and i or 0
419 if printmessage and (removed or updated) and not printed:
424 if printmessage and (removed or updated) and not printed:
420 ui.status(_('getting changed largefiles\n'))
425 ui.status(_('getting changed largefiles\n'))
421 printed = True
426 printed = True
422
427
423 lfdirstate.write()
428 lfdirstate.write()
424 if printed and printmessage:
429 if printed and printmessage:
425 ui.status(_('%d largefiles updated, %d removed\n') % (updated,
430 ui.status(_('%d largefiles updated, %d removed\n') % (updated,
426 removed))
431 removed))
427 finally:
432 finally:
428 wlock.release()
433 wlock.release()
429
434
430 def _updatelfile(repo, lfdirstate, lfile):
435 def _updatelfile(repo, lfdirstate, lfile):
431 '''updates a single largefile and copies the state of its standin from
436 '''updates a single largefile and copies the state of its standin from
432 the repository's dirstate to its state in the lfdirstate.
437 the repository's dirstate to its state in the lfdirstate.
433
438
434 returns 1 if the file was modified, -1 if the file was removed, 0 if the
439 returns 1 if the file was modified, -1 if the file was removed, 0 if the
435 file was unchanged, and None if the needed largefile was missing from the
440 file was unchanged, and None if the needed largefile was missing from the
436 cache.'''
441 cache.'''
437 ret = 0
442 ret = 0
438 abslfile = repo.wjoin(lfile)
443 abslfile = repo.wjoin(lfile)
439 absstandin = repo.wjoin(lfutil.standin(lfile))
444 absstandin = repo.wjoin(lfutil.standin(lfile))
440 if os.path.exists(absstandin):
445 if os.path.exists(absstandin):
441 if os.path.exists(absstandin+'.orig'):
446 if os.path.exists(absstandin+'.orig'):
442 shutil.copyfile(abslfile, abslfile+'.orig')
447 shutil.copyfile(abslfile, abslfile+'.orig')
443 expecthash = lfutil.readstandin(repo, lfile)
448 expecthash = lfutil.readstandin(repo, lfile)
444 if (expecthash != '' and
449 if (expecthash != '' and
445 (not os.path.exists(abslfile) or
450 (not os.path.exists(abslfile) or
446 expecthash != lfutil.hashfile(abslfile))):
451 expecthash != lfutil.hashfile(abslfile))):
447 if not lfutil.copyfromcache(repo, expecthash, lfile):
452 if not lfutil.copyfromcache(repo, expecthash, lfile):
448 return None # don't try to set the mode or update the dirstate
453 return None # don't try to set the mode or update the dirstate
449 ret = 1
454 ret = 1
450 mode = os.stat(absstandin).st_mode
455 mode = os.stat(absstandin).st_mode
451 if mode != os.stat(abslfile).st_mode:
456 if mode != os.stat(abslfile).st_mode:
452 os.chmod(abslfile, mode)
457 os.chmod(abslfile, mode)
453 ret = 1
458 ret = 1
454 else:
459 else:
455 if os.path.exists(abslfile):
460 if os.path.exists(abslfile):
456 os.unlink(abslfile)
461 os.unlink(abslfile)
457 ret = -1
462 ret = -1
458 state = repo.dirstate[lfutil.standin(lfile)]
463 state = repo.dirstate[lfutil.standin(lfile)]
459 if state == 'n':
464 if state == 'n':
460 lfdirstate.normal(lfile)
465 lfdirstate.normal(lfile)
461 elif state == 'r':
466 elif state == 'r':
462 lfdirstate.remove(lfile)
467 lfdirstate.remove(lfile)
463 elif state == 'a':
468 elif state == 'a':
464 lfdirstate.add(lfile)
469 lfdirstate.add(lfile)
465 elif state == '?':
470 elif state == '?':
466 lfdirstate.drop(lfile)
471 lfdirstate.drop(lfile)
467 return ret
472 return ret
468
473
469 # -- hg commands declarations ------------------------------------------------
474 # -- hg commands declarations ------------------------------------------------
470
475
471 cmdtable = {
476 cmdtable = {
472 'lfconvert': (lfconvert,
477 'lfconvert': (lfconvert,
473 [('s', 'size', '',
478 [('s', 'size', '',
474 _('minimum size (MB) for files to be converted '
479 _('minimum size (MB) for files to be converted '
475 'as largefiles'),
480 'as largefiles'),
476 'SIZE'),
481 'SIZE'),
477 ('', 'tonormal', False,
482 ('', 'tonormal', False,
478 _('convert from a largefiles repo to a normal repo')),
483 _('convert from a largefiles repo to a normal repo')),
479 ],
484 ],
480 _('hg lfconvert SOURCE DEST [FILE ...]')),
485 _('hg lfconvert SOURCE DEST [FILE ...]')),
481 }
486 }
@@ -1,663 +1,687
1 $ cat >> $HGRCPATH <<EOF
1 $ cat >> $HGRCPATH <<EOF
2 > [extensions]
2 > [extensions]
3 > largefiles=
3 > largefiles=
4 > purge=
4 > purge=
5 > rebase=
5 > rebase=
6 > [largefiles]
6 > [largefiles]
7 > size=2
7 > size=2
8 > patterns=glob:**.dat
8 > patterns=glob:**.dat
9 > EOF
9 > EOF
10
10
11 Create the repo with a couple of revisions of both large and normal
11 Create the repo with a couple of revisions of both large and normal
12 files (testing that status correctly shows largefiles.
12 files (testing that status correctly shows largefiles.
13
13
14 $ hg init a
14 $ hg init a
15 $ cd a
15 $ cd a
16 $ mkdir sub
16 $ mkdir sub
17 $ echo normal1 > normal1
17 $ echo normal1 > normal1
18 $ echo normal2 > sub/normal2
18 $ echo normal2 > sub/normal2
19 $ echo large1 > large1
19 $ echo large1 > large1
20 $ echo large2 > sub/large2
20 $ echo large2 > sub/large2
21 $ hg add normal1 sub/normal2
21 $ hg add normal1 sub/normal2
22 $ hg add --large large1 sub/large2
22 $ hg add --large large1 sub/large2
23 $ hg commit -m "add files"
23 $ hg commit -m "add files"
24 $ echo normal11 > normal1
24 $ echo normal11 > normal1
25 $ echo normal22 > sub/normal2
25 $ echo normal22 > sub/normal2
26 $ echo large11 > large1
26 $ echo large11 > large1
27 $ echo large22 > sub/large2
27 $ echo large22 > sub/large2
28 $ hg st
28 $ hg st
29 M large1
29 M large1
30 M normal1
30 M normal1
31 M sub/large2
31 M sub/large2
32 M sub/normal2
32 M sub/normal2
33 $ hg commit -m "edit files"
33 $ hg commit -m "edit files"
34
34
35 Verify that committing new versions of largefiles results in correct
35 Verify that committing new versions of largefiles results in correct
36 largefile contents, and also that non-largefiles are not affected
36 largefile contents, and also that non-largefiles are not affected
37 badly.
37 badly.
38
38
39 $ cat normal1
39 $ cat normal1
40 normal11
40 normal11
41 $ cat large1
41 $ cat large1
42 large11
42 large11
43 $ cat sub/normal2
43 $ cat sub/normal2
44 normal22
44 normal22
45 $ cat sub/large2
45 $ cat sub/large2
46 large22
46 large22
47
47
48 Verify removing largefiles and normal files works on largefile repos.
48 Verify removing largefiles and normal files works on largefile repos.
49
49
50 $ hg remove normal1 large1
50 $ hg remove normal1 large1
51 $ hg commit -m "remove files"
51 $ hg commit -m "remove files"
52 $ ls
52 $ ls
53 sub
53 sub
54
54
55 Test copying largefiles.
55 Test copying largefiles.
56
56
57 $ hg cp sub/normal2 normal1
57 $ hg cp sub/normal2 normal1
58 $ hg cp sub/large2 large1
58 $ hg cp sub/large2 large1
59 $ hg commit -m "copy files"
59 $ hg commit -m "copy files"
60 $ cat normal1
60 $ cat normal1
61 normal22
61 normal22
62 $ cat large1
62 $ cat large1
63 large22
63 large22
64
64
65 Test moving largefiles and verify that normal files are also unaffected.
65 Test moving largefiles and verify that normal files are also unaffected.
66
66
67 $ hg mv normal1 normal3
67 $ hg mv normal1 normal3
68 $ hg mv large1 large3
68 $ hg mv large1 large3
69 $ hg mv sub/normal2 sub/normal4
69 $ hg mv sub/normal2 sub/normal4
70 $ hg mv sub/large2 sub/large4
70 $ hg mv sub/large2 sub/large4
71 $ hg commit -m "move files"
71 $ hg commit -m "move files"
72 $ cat normal3
72 $ cat normal3
73 normal22
73 normal22
74 $ cat large3
74 $ cat large3
75 large22
75 large22
76 $ cat sub/normal4
76 $ cat sub/normal4
77 normal22
77 normal22
78 $ cat sub/large4
78 $ cat sub/large4
79 large22
79 large22
80
80
81 Test archiving the various revisions. These hit corner cases known with
81 Test archiving the various revisions. These hit corner cases known with
82 archiving.
82 archiving.
83
83
84 $ hg archive -r 0 ../archive0
84 $ hg archive -r 0 ../archive0
85 $ hg archive -r 1 ../archive1
85 $ hg archive -r 1 ../archive1
86 $ hg archive -r 2 ../archive2
86 $ hg archive -r 2 ../archive2
87 $ hg archive -r 3 ../archive3
87 $ hg archive -r 3 ../archive3
88 $ hg archive -r 4 ../archive4
88 $ hg archive -r 4 ../archive4
89 $ cd ../archive0
89 $ cd ../archive0
90 $ cat normal1
90 $ cat normal1
91 normal1
91 normal1
92 $ cat large1
92 $ cat large1
93 large1
93 large1
94 $ cat sub/normal2
94 $ cat sub/normal2
95 normal2
95 normal2
96 $ cat sub/large2
96 $ cat sub/large2
97 large2
97 large2
98 $ cd ../archive1
98 $ cd ../archive1
99 $ cat normal1
99 $ cat normal1
100 normal11
100 normal11
101 $ cat large1
101 $ cat large1
102 large11
102 large11
103 $ cat sub/normal2
103 $ cat sub/normal2
104 normal22
104 normal22
105 $ cat sub/large2
105 $ cat sub/large2
106 large22
106 large22
107 $ cd ../archive2
107 $ cd ../archive2
108 $ ls
108 $ ls
109 sub
109 sub
110 $ cat sub/normal2
110 $ cat sub/normal2
111 normal22
111 normal22
112 $ cat sub/large2
112 $ cat sub/large2
113 large22
113 large22
114 $ cd ../archive3
114 $ cd ../archive3
115 $ cat normal1
115 $ cat normal1
116 normal22
116 normal22
117 $ cat large1
117 $ cat large1
118 large22
118 large22
119 $ cat sub/normal2
119 $ cat sub/normal2
120 normal22
120 normal22
121 $ cat sub/large2
121 $ cat sub/large2
122 large22
122 large22
123 $ cd ../archive4
123 $ cd ../archive4
124 $ cat normal3
124 $ cat normal3
125 normal22
125 normal22
126 $ cat large3
126 $ cat large3
127 large22
127 large22
128 $ cat sub/normal4
128 $ cat sub/normal4
129 normal22
129 normal22
130 $ cat sub/large4
130 $ cat sub/large4
131 large22
131 large22
132
132
133 Test a separate commit corner case (specifying files to commit) and check
133 Test a separate commit corner case (specifying files to commit) and check
134 that the commited files have the right value.
134 that the commited files have the right value.
135
135
136 $ cd ../a
136 $ cd ../a
137 $ echo normal3 > normal3
137 $ echo normal3 > normal3
138 $ echo large3 > large3
138 $ echo large3 > large3
139 $ echo normal4 > sub/normal4
139 $ echo normal4 > sub/normal4
140 $ echo large4 > sub/large4
140 $ echo large4 > sub/large4
141 $ hg commit normal3 large3 sub/normal4 sub/large4 -m "edit files again"
141 $ hg commit normal3 large3 sub/normal4 sub/large4 -m "edit files again"
142 $ cat normal3
142 $ cat normal3
143 normal3
143 normal3
144 $ cat large3
144 $ cat large3
145 large3
145 large3
146 $ cat sub/normal4
146 $ cat sub/normal4
147 normal4
147 normal4
148 $ cat sub/large4
148 $ cat sub/large4
149 large4
149 large4
150
150
151 Test one more commit corner case that has been known to break (comitting from
151 Test one more commit corner case that has been known to break (comitting from
152 a sub-directory of the repo).
152 a sub-directory of the repo).
153
153
154 $ cd ../a
154 $ cd ../a
155 $ echo normal33 > normal3
155 $ echo normal33 > normal3
156 $ echo large33 > large3
156 $ echo large33 > large3
157 $ echo normal44 > sub/normal4
157 $ echo normal44 > sub/normal4
158 $ echo large44 > sub/large4
158 $ echo large44 > sub/large4
159 $ cd sub
159 $ cd sub
160 $ hg commit -m "edit files yet again"
160 $ hg commit -m "edit files yet again"
161 $ cat ../normal3
161 $ cat ../normal3
162 normal33
162 normal33
163 $ cat ../large3
163 $ cat ../large3
164 large33
164 large33
165 $ cat normal4
165 $ cat normal4
166 normal44
166 normal44
167 $ cat large4
167 $ cat large4
168 large44
168 large44
169
169
170 Check that committing standins is not allowed.
170 Check that committing standins is not allowed.
171
171
172 $ cd ..
172 $ cd ..
173 $ echo large3 > large3
173 $ echo large3 > large3
174 $ hg commit .hglf/large3 -m "try to commit standin"
174 $ hg commit .hglf/large3 -m "try to commit standin"
175 abort: file ".hglf/large3" is a largefile standin
175 abort: file ".hglf/large3" is a largefile standin
176 (commit the largefile itself instead)
176 (commit the largefile itself instead)
177 [255]
177 [255]
178
178
179 Test some cornercases for adding largefiles.
179 Test some cornercases for adding largefiles.
180
180
181 $ echo large5 > large5
181 $ echo large5 > large5
182 $ hg add --large large5
182 $ hg add --large large5
183 $ hg add --large large5
183 $ hg add --large large5
184 large5 already a largefile
184 large5 already a largefile
185 $ mkdir sub2
185 $ mkdir sub2
186 $ echo large6 > sub2/large6
186 $ echo large6 > sub2/large6
187 $ echo large7 > sub2/large7
187 $ echo large7 > sub2/large7
188 $ hg add --large sub2
188 $ hg add --large sub2
189 adding sub2/large6 as a largefile
189 adding sub2/large6 as a largefile
190 adding sub2/large7 as a largefile
190 adding sub2/large7 as a largefile
191 $ hg st
191 $ hg st
192 M large3
192 M large3
193 A large5
193 A large5
194 A sub2/large6
194 A sub2/large6
195 A sub2/large7
195 A sub2/large7
196
196
197 Test that files get added as largefiles based on .hgrc settings
197 Test that files get added as largefiles based on .hgrc settings
198
198
199 $ echo testdata > test.dat
199 $ echo testdata > test.dat
200 $ dd bs=3145728 count=1 if=/dev/zero of=reallylarge > /dev/null 2> /dev/null
200 $ dd bs=3145728 count=1 if=/dev/zero of=reallylarge > /dev/null 2> /dev/null
201 $ hg add
201 $ hg add
202 adding reallylarge as a largefile
202 adding reallylarge as a largefile
203 adding test.dat as a largefile
203 adding test.dat as a largefile
204 $ dd bs=1048576 count=1 if=/dev/zero of=reallylarge2 > /dev/null 2> /dev/null
204 $ dd bs=1048576 count=1 if=/dev/zero of=reallylarge2 > /dev/null 2> /dev/null
205
205
206 Test that specifying the --lsize command on the comand-line works
206 Test that specifying the --lsize command on the comand-line works
207
207
208 $ hg add --lfsize 1
208 $ hg add --lfsize 1
209 adding reallylarge2 as a largefile
209 adding reallylarge2 as a largefile
210
210
211 Test forget on largefiles.
211 Test forget on largefiles.
212
212
213 $ hg forget large3 large5 test.dat reallylarge reallylarge2
213 $ hg forget large3 large5 test.dat reallylarge reallylarge2
214 $ hg st
214 $ hg st
215 A sub2/large6
215 A sub2/large6
216 A sub2/large7
216 A sub2/large7
217 R large3
217 R large3
218 ? large5
218 ? large5
219 ? reallylarge
219 ? reallylarge
220 ? reallylarge2
220 ? reallylarge2
221 ? test.dat
221 ? test.dat
222 $ hg commit -m "add/edit more largefiles"
222 $ hg commit -m "add/edit more largefiles"
223 $ hg st
223 $ hg st
224 ? large3
224 ? large3
225 ? large5
225 ? large5
226 ? reallylarge
226 ? reallylarge
227 ? reallylarge2
227 ? reallylarge2
228 ? test.dat
228 ? test.dat
229
229
230 Test purge with largefiles (verify that largefiles get populated in the
230 Test purge with largefiles (verify that largefiles get populated in the
231 working copy correctly after a purge)
231 working copy correctly after a purge)
232
232
233 $ hg purge --all
233 $ hg purge --all
234 $ cat sub/large4
234 $ cat sub/large4
235 large44
235 large44
236 $ cat sub2/large6
236 $ cat sub2/large6
237 large6
237 large6
238 $ cat sub2/large7
238 $ cat sub2/large7
239 large7
239 large7
240
240
241 Test cloning a largefiles repo.
241 Test cloning a largefiles repo.
242
242
243 $ cd ..
243 $ cd ..
244 $ hg clone a b
244 $ hg clone a b
245 updating to branch default
245 updating to branch default
246 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
246 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
247 getting changed largefiles
247 getting changed largefiles
248 3 largefiles updated, 0 removed
248 3 largefiles updated, 0 removed
249 $ cd b
249 $ cd b
250 $ hg log
250 $ hg log
251 changeset: 7:daea875e9014
251 changeset: 7:daea875e9014
252 tag: tip
252 tag: tip
253 user: test
253 user: test
254 date: Thu Jan 01 00:00:00 1970 +0000
254 date: Thu Jan 01 00:00:00 1970 +0000
255 summary: add/edit more largefiles
255 summary: add/edit more largefiles
256
256
257 changeset: 6:4355d653f84f
257 changeset: 6:4355d653f84f
258 user: test
258 user: test
259 date: Thu Jan 01 00:00:00 1970 +0000
259 date: Thu Jan 01 00:00:00 1970 +0000
260 summary: edit files yet again
260 summary: edit files yet again
261
261
262 changeset: 5:9d5af5072dbd
262 changeset: 5:9d5af5072dbd
263 user: test
263 user: test
264 date: Thu Jan 01 00:00:00 1970 +0000
264 date: Thu Jan 01 00:00:00 1970 +0000
265 summary: edit files again
265 summary: edit files again
266
266
267 changeset: 4:74c02385b94c
267 changeset: 4:74c02385b94c
268 user: test
268 user: test
269 date: Thu Jan 01 00:00:00 1970 +0000
269 date: Thu Jan 01 00:00:00 1970 +0000
270 summary: move files
270 summary: move files
271
271
272 changeset: 3:9e8fbc4bce62
272 changeset: 3:9e8fbc4bce62
273 user: test
273 user: test
274 date: Thu Jan 01 00:00:00 1970 +0000
274 date: Thu Jan 01 00:00:00 1970 +0000
275 summary: copy files
275 summary: copy files
276
276
277 changeset: 2:51a0ae4d5864
277 changeset: 2:51a0ae4d5864
278 user: test
278 user: test
279 date: Thu Jan 01 00:00:00 1970 +0000
279 date: Thu Jan 01 00:00:00 1970 +0000
280 summary: remove files
280 summary: remove files
281
281
282 changeset: 1:ce8896473775
282 changeset: 1:ce8896473775
283 user: test
283 user: test
284 date: Thu Jan 01 00:00:00 1970 +0000
284 date: Thu Jan 01 00:00:00 1970 +0000
285 summary: edit files
285 summary: edit files
286
286
287 changeset: 0:30d30fe6a5be
287 changeset: 0:30d30fe6a5be
288 user: test
288 user: test
289 date: Thu Jan 01 00:00:00 1970 +0000
289 date: Thu Jan 01 00:00:00 1970 +0000
290 summary: add files
290 summary: add files
291
291
292 $ cat normal3
292 $ cat normal3
293 normal33
293 normal33
294 $ cat sub/normal4
294 $ cat sub/normal4
295 normal44
295 normal44
296 $ cat sub/large4
296 $ cat sub/large4
297 large44
297 large44
298 $ cat sub2/large6
298 $ cat sub2/large6
299 large6
299 large6
300 $ cat sub2/large7
300 $ cat sub2/large7
301 large7
301 large7
302 $ cd ..
302 $ cd ..
303 $ hg clone a -r 3 c
303 $ hg clone a -r 3 c
304 adding changesets
304 adding changesets
305 adding manifests
305 adding manifests
306 adding file changes
306 adding file changes
307 added 4 changesets with 10 changes to 4 files
307 added 4 changesets with 10 changes to 4 files
308 updating to branch default
308 updating to branch default
309 4 files updated, 0 files merged, 0 files removed, 0 files unresolved
309 4 files updated, 0 files merged, 0 files removed, 0 files unresolved
310 getting changed largefiles
310 getting changed largefiles
311 2 largefiles updated, 0 removed
311 2 largefiles updated, 0 removed
312 $ cd c
312 $ cd c
313 $ hg log
313 $ hg log
314 changeset: 3:9e8fbc4bce62
314 changeset: 3:9e8fbc4bce62
315 tag: tip
315 tag: tip
316 user: test
316 user: test
317 date: Thu Jan 01 00:00:00 1970 +0000
317 date: Thu Jan 01 00:00:00 1970 +0000
318 summary: copy files
318 summary: copy files
319
319
320 changeset: 2:51a0ae4d5864
320 changeset: 2:51a0ae4d5864
321 user: test
321 user: test
322 date: Thu Jan 01 00:00:00 1970 +0000
322 date: Thu Jan 01 00:00:00 1970 +0000
323 summary: remove files
323 summary: remove files
324
324
325 changeset: 1:ce8896473775
325 changeset: 1:ce8896473775
326 user: test
326 user: test
327 date: Thu Jan 01 00:00:00 1970 +0000
327 date: Thu Jan 01 00:00:00 1970 +0000
328 summary: edit files
328 summary: edit files
329
329
330 changeset: 0:30d30fe6a5be
330 changeset: 0:30d30fe6a5be
331 user: test
331 user: test
332 date: Thu Jan 01 00:00:00 1970 +0000
332 date: Thu Jan 01 00:00:00 1970 +0000
333 summary: add files
333 summary: add files
334
334
335 $ cat normal1
335 $ cat normal1
336 normal22
336 normal22
337 $ cat large1
337 $ cat large1
338 large22
338 large22
339 $ cat sub/normal2
339 $ cat sub/normal2
340 normal22
340 normal22
341 $ cat sub/large2
341 $ cat sub/large2
342 large22
342 large22
343
343
344 Test that old revisions of a clone have correct largefiles content. This also
344 Test that old revisions of a clone have correct largefiles content. This also
345 tests update.
345 tests update.
346
346
347 $ hg update -r 1
347 $ hg update -r 1
348 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
348 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
349 getting changed largefiles
349 getting changed largefiles
350 1 largefiles updated, 0 removed
350 1 largefiles updated, 0 removed
351 $ cat large1
351 $ cat large1
352 large11
352 large11
353 $ cat sub/large2
353 $ cat sub/large2
354 large22
354 large22
355
355
356 Test that rebasing between two repositories does not revert largefiles to old
356 Test that rebasing between two repositories does not revert largefiles to old
357 revisions (this was a very bad bug that took a lot of work to fix).
357 revisions (this was a very bad bug that took a lot of work to fix).
358
358
359 $ cd ..
359 $ cd ..
360 $ hg clone a d
360 $ hg clone a d
361 updating to branch default
361 updating to branch default
362 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
362 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
363 getting changed largefiles
363 getting changed largefiles
364 3 largefiles updated, 0 removed
364 3 largefiles updated, 0 removed
365 $ cd b
365 $ cd b
366 $ echo large4-modified > sub/large4
366 $ echo large4-modified > sub/large4
367 $ echo normal3-modified > normal3
367 $ echo normal3-modified > normal3
368 $ hg commit -m "modify normal file and largefile in repo b"
368 $ hg commit -m "modify normal file and largefile in repo b"
369 $ cd ../d
369 $ cd ../d
370 $ echo large6-modified > sub2/large6
370 $ echo large6-modified > sub2/large6
371 $ echo normal4-modified > sub/normal4
371 $ echo normal4-modified > sub/normal4
372 $ hg commit -m "modify normal file largefile in repo d"
372 $ hg commit -m "modify normal file largefile in repo d"
373 $ cd ..
373 $ cd ..
374 $ hg clone d e
374 $ hg clone d e
375 updating to branch default
375 updating to branch default
376 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
376 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
377 getting changed largefiles
377 getting changed largefiles
378 3 largefiles updated, 0 removed
378 3 largefiles updated, 0 removed
379 $ cd d
379 $ cd d
380 $ hg pull --rebase ../b
380 $ hg pull --rebase ../b
381 pulling from ../b
381 pulling from ../b
382 searching for changes
382 searching for changes
383 adding changesets
383 adding changesets
384 adding manifests
384 adding manifests
385 adding file changes
385 adding file changes
386 added 1 changesets with 2 changes to 2 files (+1 heads)
386 added 1 changesets with 2 changes to 2 files (+1 heads)
387 getting changed largefiles
387 getting changed largefiles
388 1 largefiles updated, 0 removed
388 1 largefiles updated, 0 removed
389 saved backup bundle to $TESTTMP/d/.hg/strip-backup/f574fb32bb45-backup.hg
389 saved backup bundle to $TESTTMP/d/.hg/strip-backup/f574fb32bb45-backup.hg
390 nothing to rebase
390 nothing to rebase
391 $ hg log
391 $ hg log
392 changeset: 9:598410d3eb9a
392 changeset: 9:598410d3eb9a
393 tag: tip
393 tag: tip
394 user: test
394 user: test
395 date: Thu Jan 01 00:00:00 1970 +0000
395 date: Thu Jan 01 00:00:00 1970 +0000
396 summary: modify normal file largefile in repo d
396 summary: modify normal file largefile in repo d
397
397
398 changeset: 8:a381d2c8c80e
398 changeset: 8:a381d2c8c80e
399 user: test
399 user: test
400 date: Thu Jan 01 00:00:00 1970 +0000
400 date: Thu Jan 01 00:00:00 1970 +0000
401 summary: modify normal file and largefile in repo b
401 summary: modify normal file and largefile in repo b
402
402
403 changeset: 7:daea875e9014
403 changeset: 7:daea875e9014
404 user: test
404 user: test
405 date: Thu Jan 01 00:00:00 1970 +0000
405 date: Thu Jan 01 00:00:00 1970 +0000
406 summary: add/edit more largefiles
406 summary: add/edit more largefiles
407
407
408 changeset: 6:4355d653f84f
408 changeset: 6:4355d653f84f
409 user: test
409 user: test
410 date: Thu Jan 01 00:00:00 1970 +0000
410 date: Thu Jan 01 00:00:00 1970 +0000
411 summary: edit files yet again
411 summary: edit files yet again
412
412
413 changeset: 5:9d5af5072dbd
413 changeset: 5:9d5af5072dbd
414 user: test
414 user: test
415 date: Thu Jan 01 00:00:00 1970 +0000
415 date: Thu Jan 01 00:00:00 1970 +0000
416 summary: edit files again
416 summary: edit files again
417
417
418 changeset: 4:74c02385b94c
418 changeset: 4:74c02385b94c
419 user: test
419 user: test
420 date: Thu Jan 01 00:00:00 1970 +0000
420 date: Thu Jan 01 00:00:00 1970 +0000
421 summary: move files
421 summary: move files
422
422
423 changeset: 3:9e8fbc4bce62
423 changeset: 3:9e8fbc4bce62
424 user: test
424 user: test
425 date: Thu Jan 01 00:00:00 1970 +0000
425 date: Thu Jan 01 00:00:00 1970 +0000
426 summary: copy files
426 summary: copy files
427
427
428 changeset: 2:51a0ae4d5864
428 changeset: 2:51a0ae4d5864
429 user: test
429 user: test
430 date: Thu Jan 01 00:00:00 1970 +0000
430 date: Thu Jan 01 00:00:00 1970 +0000
431 summary: remove files
431 summary: remove files
432
432
433 changeset: 1:ce8896473775
433 changeset: 1:ce8896473775
434 user: test
434 user: test
435 date: Thu Jan 01 00:00:00 1970 +0000
435 date: Thu Jan 01 00:00:00 1970 +0000
436 summary: edit files
436 summary: edit files
437
437
438 changeset: 0:30d30fe6a5be
438 changeset: 0:30d30fe6a5be
439 user: test
439 user: test
440 date: Thu Jan 01 00:00:00 1970 +0000
440 date: Thu Jan 01 00:00:00 1970 +0000
441 summary: add files
441 summary: add files
442
442
443 $ cat normal3
443 $ cat normal3
444 normal3-modified
444 normal3-modified
445 $ cat sub/normal4
445 $ cat sub/normal4
446 normal4-modified
446 normal4-modified
447 $ cat sub/large4
447 $ cat sub/large4
448 large4-modified
448 large4-modified
449 $ cat sub2/large6
449 $ cat sub2/large6
450 large6-modified
450 large6-modified
451 $ cat sub2/large7
451 $ cat sub2/large7
452 large7
452 large7
453 $ cd ../e
453 $ cd ../e
454 $ hg pull ../b
454 $ hg pull ../b
455 pulling from ../b
455 pulling from ../b
456 searching for changes
456 searching for changes
457 adding changesets
457 adding changesets
458 adding manifests
458 adding manifests
459 adding file changes
459 adding file changes
460 added 1 changesets with 2 changes to 2 files (+1 heads)
460 added 1 changesets with 2 changes to 2 files (+1 heads)
461 (run 'hg heads' to see heads, 'hg merge' to merge)
461 (run 'hg heads' to see heads, 'hg merge' to merge)
462 $ hg rebase
462 $ hg rebase
463 getting changed largefiles
463 getting changed largefiles
464 1 largefiles updated, 0 removed
464 1 largefiles updated, 0 removed
465 saved backup bundle to $TESTTMP/e/.hg/strip-backup/f574fb32bb45-backup.hg
465 saved backup bundle to $TESTTMP/e/.hg/strip-backup/f574fb32bb45-backup.hg
466 $ hg log
466 $ hg log
467 changeset: 9:598410d3eb9a
467 changeset: 9:598410d3eb9a
468 tag: tip
468 tag: tip
469 user: test
469 user: test
470 date: Thu Jan 01 00:00:00 1970 +0000
470 date: Thu Jan 01 00:00:00 1970 +0000
471 summary: modify normal file largefile in repo d
471 summary: modify normal file largefile in repo d
472
472
473 changeset: 8:a381d2c8c80e
473 changeset: 8:a381d2c8c80e
474 user: test
474 user: test
475 date: Thu Jan 01 00:00:00 1970 +0000
475 date: Thu Jan 01 00:00:00 1970 +0000
476 summary: modify normal file and largefile in repo b
476 summary: modify normal file and largefile in repo b
477
477
478 changeset: 7:daea875e9014
478 changeset: 7:daea875e9014
479 user: test
479 user: test
480 date: Thu Jan 01 00:00:00 1970 +0000
480 date: Thu Jan 01 00:00:00 1970 +0000
481 summary: add/edit more largefiles
481 summary: add/edit more largefiles
482
482
483 changeset: 6:4355d653f84f
483 changeset: 6:4355d653f84f
484 user: test
484 user: test
485 date: Thu Jan 01 00:00:00 1970 +0000
485 date: Thu Jan 01 00:00:00 1970 +0000
486 summary: edit files yet again
486 summary: edit files yet again
487
487
488 changeset: 5:9d5af5072dbd
488 changeset: 5:9d5af5072dbd
489 user: test
489 user: test
490 date: Thu Jan 01 00:00:00 1970 +0000
490 date: Thu Jan 01 00:00:00 1970 +0000
491 summary: edit files again
491 summary: edit files again
492
492
493 changeset: 4:74c02385b94c
493 changeset: 4:74c02385b94c
494 user: test
494 user: test
495 date: Thu Jan 01 00:00:00 1970 +0000
495 date: Thu Jan 01 00:00:00 1970 +0000
496 summary: move files
496 summary: move files
497
497
498 changeset: 3:9e8fbc4bce62
498 changeset: 3:9e8fbc4bce62
499 user: test
499 user: test
500 date: Thu Jan 01 00:00:00 1970 +0000
500 date: Thu Jan 01 00:00:00 1970 +0000
501 summary: copy files
501 summary: copy files
502
502
503 changeset: 2:51a0ae4d5864
503 changeset: 2:51a0ae4d5864
504 user: test
504 user: test
505 date: Thu Jan 01 00:00:00 1970 +0000
505 date: Thu Jan 01 00:00:00 1970 +0000
506 summary: remove files
506 summary: remove files
507
507
508 changeset: 1:ce8896473775
508 changeset: 1:ce8896473775
509 user: test
509 user: test
510 date: Thu Jan 01 00:00:00 1970 +0000
510 date: Thu Jan 01 00:00:00 1970 +0000
511 summary: edit files
511 summary: edit files
512
512
513 changeset: 0:30d30fe6a5be
513 changeset: 0:30d30fe6a5be
514 user: test
514 user: test
515 date: Thu Jan 01 00:00:00 1970 +0000
515 date: Thu Jan 01 00:00:00 1970 +0000
516 summary: add files
516 summary: add files
517
517
518 $ cat normal3
518 $ cat normal3
519 normal3-modified
519 normal3-modified
520 $ cat sub/normal4
520 $ cat sub/normal4
521 normal4-modified
521 normal4-modified
522 $ cat sub/large4
522 $ cat sub/large4
523 large4-modified
523 large4-modified
524 $ cat sub2/large6
524 $ cat sub2/large6
525 large6-modified
525 large6-modified
526 $ cat sub2/large7
526 $ cat sub2/large7
527 large7
527 large7
528
528
529 Test rollback on largefiles
529 Test rollback on largefiles
530
530
531 $ echo large4-modified-again > sub/large4
531 $ echo large4-modified-again > sub/large4
532 $ hg commit -m "Modify large4 again"
532 $ hg commit -m "Modify large4 again"
533 $ hg rollback
533 $ hg rollback
534 repository tip rolled back to revision 9 (undo commit)
534 repository tip rolled back to revision 9 (undo commit)
535 working directory now based on revision 9
535 working directory now based on revision 9
536 $ hg st
536 $ hg st
537 M sub/large4
537 M sub/large4
538 $ hg log
538 $ hg log
539 changeset: 9:598410d3eb9a
539 changeset: 9:598410d3eb9a
540 tag: tip
540 tag: tip
541 user: test
541 user: test
542 date: Thu Jan 01 00:00:00 1970 +0000
542 date: Thu Jan 01 00:00:00 1970 +0000
543 summary: modify normal file largefile in repo d
543 summary: modify normal file largefile in repo d
544
544
545 changeset: 8:a381d2c8c80e
545 changeset: 8:a381d2c8c80e
546 user: test
546 user: test
547 date: Thu Jan 01 00:00:00 1970 +0000
547 date: Thu Jan 01 00:00:00 1970 +0000
548 summary: modify normal file and largefile in repo b
548 summary: modify normal file and largefile in repo b
549
549
550 changeset: 7:daea875e9014
550 changeset: 7:daea875e9014
551 user: test
551 user: test
552 date: Thu Jan 01 00:00:00 1970 +0000
552 date: Thu Jan 01 00:00:00 1970 +0000
553 summary: add/edit more largefiles
553 summary: add/edit more largefiles
554
554
555 changeset: 6:4355d653f84f
555 changeset: 6:4355d653f84f
556 user: test
556 user: test
557 date: Thu Jan 01 00:00:00 1970 +0000
557 date: Thu Jan 01 00:00:00 1970 +0000
558 summary: edit files yet again
558 summary: edit files yet again
559
559
560 changeset: 5:9d5af5072dbd
560 changeset: 5:9d5af5072dbd
561 user: test
561 user: test
562 date: Thu Jan 01 00:00:00 1970 +0000
562 date: Thu Jan 01 00:00:00 1970 +0000
563 summary: edit files again
563 summary: edit files again
564
564
565 changeset: 4:74c02385b94c
565 changeset: 4:74c02385b94c
566 user: test
566 user: test
567 date: Thu Jan 01 00:00:00 1970 +0000
567 date: Thu Jan 01 00:00:00 1970 +0000
568 summary: move files
568 summary: move files
569
569
570 changeset: 3:9e8fbc4bce62
570 changeset: 3:9e8fbc4bce62
571 user: test
571 user: test
572 date: Thu Jan 01 00:00:00 1970 +0000
572 date: Thu Jan 01 00:00:00 1970 +0000
573 summary: copy files
573 summary: copy files
574
574
575 changeset: 2:51a0ae4d5864
575 changeset: 2:51a0ae4d5864
576 user: test
576 user: test
577 date: Thu Jan 01 00:00:00 1970 +0000
577 date: Thu Jan 01 00:00:00 1970 +0000
578 summary: remove files
578 summary: remove files
579
579
580 changeset: 1:ce8896473775
580 changeset: 1:ce8896473775
581 user: test
581 user: test
582 date: Thu Jan 01 00:00:00 1970 +0000
582 date: Thu Jan 01 00:00:00 1970 +0000
583 summary: edit files
583 summary: edit files
584
584
585 changeset: 0:30d30fe6a5be
585 changeset: 0:30d30fe6a5be
586 user: test
586 user: test
587 date: Thu Jan 01 00:00:00 1970 +0000
587 date: Thu Jan 01 00:00:00 1970 +0000
588 summary: add files
588 summary: add files
589
589
590 $ cat sub/large4
590 $ cat sub/large4
591 large4-modified-again
591 large4-modified-again
592
592
593 Test that `update --clean` leaves correct largefiles in working copy.
593 Test that `update --clean` leaves correct largefiles in working copy.
594
594
595 $ hg update --clean
595 $ hg update --clean
596 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
596 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
597 getting changed largefiles
597 getting changed largefiles
598 1 largefiles updated, 0 removed
598 1 largefiles updated, 0 removed
599 $ cat normal3
599 $ cat normal3
600 normal3-modified
600 normal3-modified
601 $ cat sub/normal4
601 $ cat sub/normal4
602 normal4-modified
602 normal4-modified
603 $ cat sub/large4
603 $ cat sub/large4
604 large4-modified
604 large4-modified
605 $ cat sub2/large6
605 $ cat sub2/large6
606 large6-modified
606 large6-modified
607 $ cat sub2/large7
607 $ cat sub2/large7
608 large7
608 large7
609
609
610 Test that verify --large actaully verifies largefiles
610 Test that verify --large actaully verifies largefiles
611
611
612 $ hg verify --large
612 $ hg verify --large
613 checking changesets
613 checking changesets
614 checking manifests
614 checking manifests
615 crosschecking files in changesets and manifests
615 crosschecking files in changesets and manifests
616 checking files
616 checking files
617 10 files, 10 changesets, 28 total revisions
617 10 files, 10 changesets, 28 total revisions
618 searching 1 changesets for largefiles
618 searching 1 changesets for largefiles
619 verified existence of 3 revisions of 3 largefiles
619 verified existence of 3 revisions of 3 largefiles
620
620
621 Test that merging does not revert to old versions of largefiles (this has
621 Test that merging does not revert to old versions of largefiles (this has
622 also been very problematic).
622 also been very problematic).
623
623
624 $ cd ..
624 $ cd ..
625 $ hg clone -r 7 e f
625 $ hg clone -r 7 e f
626 adding changesets
626 adding changesets
627 adding manifests
627 adding manifests
628 adding file changes
628 adding file changes
629 added 8 changesets with 24 changes to 10 files
629 added 8 changesets with 24 changes to 10 files
630 updating to branch default
630 updating to branch default
631 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
631 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
632 getting changed largefiles
632 getting changed largefiles
633 3 largefiles updated, 0 removed
633 3 largefiles updated, 0 removed
634 $ cd f
634 $ cd f
635 $ echo "large4-merge-test" > sub/large4
635 $ echo "large4-merge-test" > sub/large4
636 $ hg commit -m "Modify large4 to test merge"
636 $ hg commit -m "Modify large4 to test merge"
637 $ hg pull ../e
637 $ hg pull ../e
638 pulling from ../e
638 pulling from ../e
639 searching for changes
639 searching for changes
640 adding changesets
640 adding changesets
641 adding manifests
641 adding manifests
642 adding file changes
642 adding file changes
643 added 2 changesets with 4 changes to 4 files (+1 heads)
643 added 2 changesets with 4 changes to 4 files (+1 heads)
644 (run 'hg heads' to see heads, 'hg merge' to merge)
644 (run 'hg heads' to see heads, 'hg merge' to merge)
645 $ hg merge
645 $ hg merge
646 merging sub/large4
646 merging sub/large4
647 largefile sub/large4 has a merge conflict
647 largefile sub/large4 has a merge conflict
648 keep (l)ocal or take (o)ther? l
648 keep (l)ocal or take (o)ther? l
649 3 files updated, 1 files merged, 0 files removed, 0 files unresolved
649 3 files updated, 1 files merged, 0 files removed, 0 files unresolved
650 (branch merge, don't forget to commit)
650 (branch merge, don't forget to commit)
651 getting changed largefiles
651 getting changed largefiles
652 1 largefiles updated, 0 removed
652 1 largefiles updated, 0 removed
653 $ hg commit -m "Merge repos e and f"
653 $ hg commit -m "Merge repos e and f"
654 $ cat normal3
654 $ cat normal3
655 normal3-modified
655 normal3-modified
656 $ cat sub/normal4
656 $ cat sub/normal4
657 normal4-modified
657 normal4-modified
658 $ cat sub/large4
658 $ cat sub/large4
659 large4-merge-test
659 large4-merge-test
660 $ cat sub2/large6
660 $ cat sub2/large6
661 large6-modified
661 large6-modified
662 $ cat sub2/large7
662 $ cat sub2/large7
663 large7
663 large7
664 $ cd ..
665
666 Verify that lfconvert adds 'largefiles' to .hg/requires
667 $ hg init bigfile-repo
668 $ cd bigfile-repo
669 $ dd if=/dev/zero bs=1k count=23k > a-large-file 2> /dev/null
670 $ hg addremove
671 adding a-large-file
672 a-large-file: up to 72 MB of RAM may be required to manage this file
673 (use 'hg revert a-large-file' to cancel the pending addition)
674 $ hg commit -m "Commit file without making it be a largefile"
675 $ find .hg/largefiles
676 .hg/largefiles
677 $ cd ..
678 $ hg lfconvert --size 10 bigfile-repo largefiles-repo
679 initializing destination largefiles-repo
680 $ cat largefiles-repo/.hg/requires
681 largefiles
682 revlogv1
683 fncache
684 store
685 dotencode
686 $ rm -rf bigfile-repo largefiles-repo
687
General Comments 0
You need to be logged in to leave comments. Login now