##// END OF EJS Templates
largefiles: fix cat of non-largefiles from subdirectory...
Mads Kiilerich -
r18974:d78a136a default
parent child Browse files
Show More
@@ -1,565 +1,547 b''
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, errno
11 import os, errno
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 cmdutil, scmutil, commands
15 cmdutil, scmutil, commands
16 from mercurial.i18n import _
16 from mercurial.i18n import _
17 from mercurial.lock import release
17 from mercurial.lock import release
18
18
19 import lfutil
19 import lfutil
20 import basestore
20 import basestore
21
21
22 # -- Commands ----------------------------------------------------------
22 # -- Commands ----------------------------------------------------------
23
23
24 def lfconvert(ui, src, dest, *pats, **opts):
24 def lfconvert(ui, src, dest, *pats, **opts):
25 '''convert a normal repository to a largefiles repository
25 '''convert a normal repository to a largefiles repository
26
26
27 Convert repository SOURCE to a new repository DEST, identical to
27 Convert repository SOURCE to a new repository DEST, identical to
28 SOURCE except that certain files will be converted as largefiles:
28 SOURCE except that certain files will be converted as largefiles:
29 specifically, any file that matches any PATTERN *or* whose size is
29 specifically, any file that matches any PATTERN *or* whose size is
30 above the minimum size threshold is converted as a largefile. The
30 above the minimum size threshold is converted as a largefile. The
31 size used to determine whether or not to track a file as a
31 size used to determine whether or not to track a file as a
32 largefile is the size of the first version of the file. The
32 largefile is the size of the first version of the file. The
33 minimum size can be specified either with --size or in
33 minimum size can be specified either with --size or in
34 configuration as ``largefiles.size``.
34 configuration as ``largefiles.size``.
35
35
36 After running this command you will need to make sure that
36 After running this command you will need to make sure that
37 largefiles is enabled anywhere you intend to push the new
37 largefiles is enabled anywhere you intend to push the new
38 repository.
38 repository.
39
39
40 Use --to-normal to convert largefiles back to normal files; after
40 Use --to-normal to convert largefiles back to normal files; after
41 this, the DEST repository can be used without largefiles at all.'''
41 this, the DEST repository can be used without largefiles at all.'''
42
42
43 if opts['to_normal']:
43 if opts['to_normal']:
44 tolfile = False
44 tolfile = False
45 else:
45 else:
46 tolfile = True
46 tolfile = True
47 size = lfutil.getminsize(ui, True, opts.get('size'), default=None)
47 size = lfutil.getminsize(ui, True, opts.get('size'), default=None)
48
48
49 if not hg.islocal(src):
49 if not hg.islocal(src):
50 raise util.Abort(_('%s is not a local Mercurial repo') % src)
50 raise util.Abort(_('%s is not a local Mercurial repo') % src)
51 if not hg.islocal(dest):
51 if not hg.islocal(dest):
52 raise util.Abort(_('%s is not a local Mercurial repo') % dest)
52 raise util.Abort(_('%s is not a local Mercurial repo') % dest)
53
53
54 rsrc = hg.repository(ui, src)
54 rsrc = hg.repository(ui, src)
55 ui.status(_('initializing destination %s\n') % dest)
55 ui.status(_('initializing destination %s\n') % dest)
56 rdst = hg.repository(ui, dest, create=True)
56 rdst = hg.repository(ui, dest, create=True)
57
57
58 success = False
58 success = False
59 dstwlock = dstlock = None
59 dstwlock = dstlock = None
60 try:
60 try:
61 # Lock destination to prevent modification while it is converted to.
61 # Lock destination to prevent modification while it is converted to.
62 # Don't need to lock src because we are just reading from its history
62 # Don't need to lock src because we are just reading from its history
63 # which can't change.
63 # which can't change.
64 dstwlock = rdst.wlock()
64 dstwlock = rdst.wlock()
65 dstlock = rdst.lock()
65 dstlock = rdst.lock()
66
66
67 # Get a list of all changesets in the source. The easy way to do this
67 # Get a list of all changesets in the source. The easy way to do this
68 # is to simply walk the changelog, using changelog.nodesbetween().
68 # is to simply walk the changelog, using changelog.nodesbetween().
69 # Take a look at mercurial/revlog.py:639 for more details.
69 # Take a look at mercurial/revlog.py:639 for more details.
70 # Use a generator instead of a list to decrease memory usage
70 # Use a generator instead of a list to decrease memory usage
71 ctxs = (rsrc[ctx] for ctx in rsrc.changelog.nodesbetween(None,
71 ctxs = (rsrc[ctx] for ctx in rsrc.changelog.nodesbetween(None,
72 rsrc.heads())[0])
72 rsrc.heads())[0])
73 revmap = {node.nullid: node.nullid}
73 revmap = {node.nullid: node.nullid}
74 if tolfile:
74 if tolfile:
75 lfiles = set()
75 lfiles = set()
76 normalfiles = set()
76 normalfiles = set()
77 if not pats:
77 if not pats:
78 pats = ui.configlist(lfutil.longname, 'patterns', default=[])
78 pats = ui.configlist(lfutil.longname, 'patterns', default=[])
79 if pats:
79 if pats:
80 matcher = match_.match(rsrc.root, '', list(pats))
80 matcher = match_.match(rsrc.root, '', list(pats))
81 else:
81 else:
82 matcher = None
82 matcher = None
83
83
84 lfiletohash = {}
84 lfiletohash = {}
85 for ctx in ctxs:
85 for ctx in ctxs:
86 ui.progress(_('converting revisions'), ctx.rev(),
86 ui.progress(_('converting revisions'), ctx.rev(),
87 unit=_('revision'), total=rsrc['tip'].rev())
87 unit=_('revision'), total=rsrc['tip'].rev())
88 _lfconvert_addchangeset(rsrc, rdst, ctx, revmap,
88 _lfconvert_addchangeset(rsrc, rdst, ctx, revmap,
89 lfiles, normalfiles, matcher, size, lfiletohash)
89 lfiles, normalfiles, matcher, size, lfiletohash)
90 ui.progress(_('converting revisions'), None)
90 ui.progress(_('converting revisions'), None)
91
91
92 if os.path.exists(rdst.wjoin(lfutil.shortname)):
92 if os.path.exists(rdst.wjoin(lfutil.shortname)):
93 shutil.rmtree(rdst.wjoin(lfutil.shortname))
93 shutil.rmtree(rdst.wjoin(lfutil.shortname))
94
94
95 for f in lfiletohash.keys():
95 for f in lfiletohash.keys():
96 if os.path.isfile(rdst.wjoin(f)):
96 if os.path.isfile(rdst.wjoin(f)):
97 os.unlink(rdst.wjoin(f))
97 os.unlink(rdst.wjoin(f))
98 try:
98 try:
99 os.removedirs(os.path.dirname(rdst.wjoin(f)))
99 os.removedirs(os.path.dirname(rdst.wjoin(f)))
100 except OSError:
100 except OSError:
101 pass
101 pass
102
102
103 # If there were any files converted to largefiles, add largefiles
103 # If there were any files converted to largefiles, add largefiles
104 # to the destination repository's requirements.
104 # to the destination repository's requirements.
105 if lfiles:
105 if lfiles:
106 rdst.requirements.add('largefiles')
106 rdst.requirements.add('largefiles')
107 rdst._writerequirements()
107 rdst._writerequirements()
108 else:
108 else:
109 for ctx in ctxs:
109 for ctx in ctxs:
110 ui.progress(_('converting revisions'), ctx.rev(),
110 ui.progress(_('converting revisions'), ctx.rev(),
111 unit=_('revision'), total=rsrc['tip'].rev())
111 unit=_('revision'), total=rsrc['tip'].rev())
112 _addchangeset(ui, rsrc, rdst, ctx, revmap)
112 _addchangeset(ui, rsrc, rdst, ctx, revmap)
113
113
114 ui.progress(_('converting revisions'), None)
114 ui.progress(_('converting revisions'), None)
115 success = True
115 success = True
116 finally:
116 finally:
117 rdst.dirstate.clear()
117 rdst.dirstate.clear()
118 release(dstlock, dstwlock)
118 release(dstlock, dstwlock)
119 if not success:
119 if not success:
120 # we failed, remove the new directory
120 # we failed, remove the new directory
121 shutil.rmtree(rdst.root)
121 shutil.rmtree(rdst.root)
122
122
123 def _addchangeset(ui, rsrc, rdst, ctx, revmap):
123 def _addchangeset(ui, rsrc, rdst, ctx, revmap):
124 # Convert src parents to dst parents
124 # Convert src parents to dst parents
125 parents = _convertparents(ctx, revmap)
125 parents = _convertparents(ctx, revmap)
126
126
127 # Generate list of changed files
127 # Generate list of changed files
128 files = _getchangedfiles(ctx, parents)
128 files = _getchangedfiles(ctx, parents)
129
129
130 def getfilectx(repo, memctx, f):
130 def getfilectx(repo, memctx, f):
131 if lfutil.standin(f) in files:
131 if lfutil.standin(f) in files:
132 # if the file isn't in the manifest then it was removed
132 # if the file isn't in the manifest then it was removed
133 # or renamed, raise IOError to indicate this
133 # or renamed, raise IOError to indicate this
134 try:
134 try:
135 fctx = ctx.filectx(lfutil.standin(f))
135 fctx = ctx.filectx(lfutil.standin(f))
136 except error.LookupError:
136 except error.LookupError:
137 raise IOError
137 raise IOError
138 renamed = fctx.renamed()
138 renamed = fctx.renamed()
139 if renamed:
139 if renamed:
140 renamed = lfutil.splitstandin(renamed[0])
140 renamed = lfutil.splitstandin(renamed[0])
141
141
142 hash = fctx.data().strip()
142 hash = fctx.data().strip()
143 path = lfutil.findfile(rsrc, hash)
143 path = lfutil.findfile(rsrc, hash)
144
144
145 # If one file is missing, likely all files from this rev are
145 # If one file is missing, likely all files from this rev are
146 if path is None:
146 if path is None:
147 cachelfiles(ui, rsrc, ctx.node())
147 cachelfiles(ui, rsrc, ctx.node())
148 path = lfutil.findfile(rsrc, hash)
148 path = lfutil.findfile(rsrc, hash)
149
149
150 if path is None:
150 if path is None:
151 raise util.Abort(
151 raise util.Abort(
152 _("missing largefile \'%s\' from revision %s")
152 _("missing largefile \'%s\' from revision %s")
153 % (f, node.hex(ctx.node())))
153 % (f, node.hex(ctx.node())))
154
154
155 data = ''
155 data = ''
156 fd = None
156 fd = None
157 try:
157 try:
158 fd = open(path, 'rb')
158 fd = open(path, 'rb')
159 data = fd.read()
159 data = fd.read()
160 finally:
160 finally:
161 if fd:
161 if fd:
162 fd.close()
162 fd.close()
163 return context.memfilectx(f, data, 'l' in fctx.flags(),
163 return context.memfilectx(f, data, 'l' in fctx.flags(),
164 'x' in fctx.flags(), renamed)
164 'x' in fctx.flags(), renamed)
165 else:
165 else:
166 return _getnormalcontext(repo.ui, ctx, f, revmap)
166 return _getnormalcontext(repo.ui, ctx, f, revmap)
167
167
168 dstfiles = []
168 dstfiles = []
169 for file in files:
169 for file in files:
170 if lfutil.isstandin(file):
170 if lfutil.isstandin(file):
171 dstfiles.append(lfutil.splitstandin(file))
171 dstfiles.append(lfutil.splitstandin(file))
172 else:
172 else:
173 dstfiles.append(file)
173 dstfiles.append(file)
174 # Commit
174 # Commit
175 _commitcontext(rdst, parents, ctx, dstfiles, getfilectx, revmap)
175 _commitcontext(rdst, parents, ctx, dstfiles, getfilectx, revmap)
176
176
177 def _lfconvert_addchangeset(rsrc, rdst, ctx, revmap, lfiles, normalfiles,
177 def _lfconvert_addchangeset(rsrc, rdst, ctx, revmap, lfiles, normalfiles,
178 matcher, size, lfiletohash):
178 matcher, size, lfiletohash):
179 # Convert src parents to dst parents
179 # Convert src parents to dst parents
180 parents = _convertparents(ctx, revmap)
180 parents = _convertparents(ctx, revmap)
181
181
182 # Generate list of changed files
182 # Generate list of changed files
183 files = _getchangedfiles(ctx, parents)
183 files = _getchangedfiles(ctx, parents)
184
184
185 dstfiles = []
185 dstfiles = []
186 for f in files:
186 for f in files:
187 if f not in lfiles and f not in normalfiles:
187 if f not in lfiles and f not in normalfiles:
188 islfile = _islfile(f, ctx, matcher, size)
188 islfile = _islfile(f, ctx, matcher, size)
189 # If this file was renamed or copied then copy
189 # If this file was renamed or copied then copy
190 # the largefile-ness of its predecessor
190 # the largefile-ness of its predecessor
191 if f in ctx.manifest():
191 if f in ctx.manifest():
192 fctx = ctx.filectx(f)
192 fctx = ctx.filectx(f)
193 renamed = fctx.renamed()
193 renamed = fctx.renamed()
194 renamedlfile = renamed and renamed[0] in lfiles
194 renamedlfile = renamed and renamed[0] in lfiles
195 islfile |= renamedlfile
195 islfile |= renamedlfile
196 if 'l' in fctx.flags():
196 if 'l' in fctx.flags():
197 if renamedlfile:
197 if renamedlfile:
198 raise util.Abort(
198 raise util.Abort(
199 _('renamed/copied largefile %s becomes symlink')
199 _('renamed/copied largefile %s becomes symlink')
200 % f)
200 % f)
201 islfile = False
201 islfile = False
202 if islfile:
202 if islfile:
203 lfiles.add(f)
203 lfiles.add(f)
204 else:
204 else:
205 normalfiles.add(f)
205 normalfiles.add(f)
206
206
207 if f in lfiles:
207 if f in lfiles:
208 dstfiles.append(lfutil.standin(f))
208 dstfiles.append(lfutil.standin(f))
209 # largefile in manifest if it has not been removed/renamed
209 # largefile in manifest if it has not been removed/renamed
210 if f in ctx.manifest():
210 if f in ctx.manifest():
211 fctx = ctx.filectx(f)
211 fctx = ctx.filectx(f)
212 if 'l' in fctx.flags():
212 if 'l' in fctx.flags():
213 renamed = fctx.renamed()
213 renamed = fctx.renamed()
214 if renamed and renamed[0] in lfiles:
214 if renamed and renamed[0] in lfiles:
215 raise util.Abort(_('largefile %s becomes symlink') % f)
215 raise util.Abort(_('largefile %s becomes symlink') % f)
216
216
217 # largefile was modified, update standins
217 # largefile was modified, update standins
218 fullpath = rdst.wjoin(f)
218 fullpath = rdst.wjoin(f)
219 util.makedirs(os.path.dirname(fullpath))
219 util.makedirs(os.path.dirname(fullpath))
220 m = util.sha1('')
220 m = util.sha1('')
221 m.update(ctx[f].data())
221 m.update(ctx[f].data())
222 hash = m.hexdigest()
222 hash = m.hexdigest()
223 if f not in lfiletohash or lfiletohash[f] != hash:
223 if f not in lfiletohash or lfiletohash[f] != hash:
224 try:
224 try:
225 fd = open(fullpath, 'wb')
225 fd = open(fullpath, 'wb')
226 fd.write(ctx[f].data())
226 fd.write(ctx[f].data())
227 finally:
227 finally:
228 if fd:
228 if fd:
229 fd.close()
229 fd.close()
230 executable = 'x' in ctx[f].flags()
230 executable = 'x' in ctx[f].flags()
231 os.chmod(fullpath, lfutil.getmode(executable))
231 os.chmod(fullpath, lfutil.getmode(executable))
232 lfutil.writestandin(rdst, lfutil.standin(f), hash,
232 lfutil.writestandin(rdst, lfutil.standin(f), hash,
233 executable)
233 executable)
234 lfiletohash[f] = hash
234 lfiletohash[f] = hash
235 else:
235 else:
236 # normal file
236 # normal file
237 dstfiles.append(f)
237 dstfiles.append(f)
238
238
239 def getfilectx(repo, memctx, f):
239 def getfilectx(repo, memctx, f):
240 if lfutil.isstandin(f):
240 if lfutil.isstandin(f):
241 # if the file isn't in the manifest then it was removed
241 # if the file isn't in the manifest then it was removed
242 # or renamed, raise IOError to indicate this
242 # or renamed, raise IOError to indicate this
243 srcfname = lfutil.splitstandin(f)
243 srcfname = lfutil.splitstandin(f)
244 try:
244 try:
245 fctx = ctx.filectx(srcfname)
245 fctx = ctx.filectx(srcfname)
246 except error.LookupError:
246 except error.LookupError:
247 raise IOError
247 raise IOError
248 renamed = fctx.renamed()
248 renamed = fctx.renamed()
249 if renamed:
249 if renamed:
250 # standin is always a largefile because largefile-ness
250 # standin is always a largefile because largefile-ness
251 # doesn't change after rename or copy
251 # doesn't change after rename or copy
252 renamed = lfutil.standin(renamed[0])
252 renamed = lfutil.standin(renamed[0])
253
253
254 return context.memfilectx(f, lfiletohash[srcfname] + '\n', 'l' in
254 return context.memfilectx(f, lfiletohash[srcfname] + '\n', 'l' in
255 fctx.flags(), 'x' in fctx.flags(), renamed)
255 fctx.flags(), 'x' in fctx.flags(), renamed)
256 else:
256 else:
257 return _getnormalcontext(repo.ui, ctx, f, revmap)
257 return _getnormalcontext(repo.ui, ctx, f, revmap)
258
258
259 # Commit
259 # Commit
260 _commitcontext(rdst, parents, ctx, dstfiles, getfilectx, revmap)
260 _commitcontext(rdst, parents, ctx, dstfiles, getfilectx, revmap)
261
261
262 def _commitcontext(rdst, parents, ctx, dstfiles, getfilectx, revmap):
262 def _commitcontext(rdst, parents, ctx, dstfiles, getfilectx, revmap):
263 mctx = context.memctx(rdst, parents, ctx.description(), dstfiles,
263 mctx = context.memctx(rdst, parents, ctx.description(), dstfiles,
264 getfilectx, ctx.user(), ctx.date(), ctx.extra())
264 getfilectx, ctx.user(), ctx.date(), ctx.extra())
265 ret = rdst.commitctx(mctx)
265 ret = rdst.commitctx(mctx)
266 rdst.setparents(ret)
266 rdst.setparents(ret)
267 revmap[ctx.node()] = rdst.changelog.tip()
267 revmap[ctx.node()] = rdst.changelog.tip()
268
268
269 # Generate list of changed files
269 # Generate list of changed files
270 def _getchangedfiles(ctx, parents):
270 def _getchangedfiles(ctx, parents):
271 files = set(ctx.files())
271 files = set(ctx.files())
272 if node.nullid not in parents:
272 if node.nullid not in parents:
273 mc = ctx.manifest()
273 mc = ctx.manifest()
274 mp1 = ctx.parents()[0].manifest()
274 mp1 = ctx.parents()[0].manifest()
275 mp2 = ctx.parents()[1].manifest()
275 mp2 = ctx.parents()[1].manifest()
276 files |= (set(mp1) | set(mp2)) - set(mc)
276 files |= (set(mp1) | set(mp2)) - set(mc)
277 for f in mc:
277 for f in mc:
278 if mc[f] != mp1.get(f, None) or mc[f] != mp2.get(f, None):
278 if mc[f] != mp1.get(f, None) or mc[f] != mp2.get(f, None):
279 files.add(f)
279 files.add(f)
280 return files
280 return files
281
281
282 # Convert src parents to dst parents
282 # Convert src parents to dst parents
283 def _convertparents(ctx, revmap):
283 def _convertparents(ctx, revmap):
284 parents = []
284 parents = []
285 for p in ctx.parents():
285 for p in ctx.parents():
286 parents.append(revmap[p.node()])
286 parents.append(revmap[p.node()])
287 while len(parents) < 2:
287 while len(parents) < 2:
288 parents.append(node.nullid)
288 parents.append(node.nullid)
289 return parents
289 return parents
290
290
291 # Get memfilectx for a normal file
291 # Get memfilectx for a normal file
292 def _getnormalcontext(ui, ctx, f, revmap):
292 def _getnormalcontext(ui, ctx, f, revmap):
293 try:
293 try:
294 fctx = ctx.filectx(f)
294 fctx = ctx.filectx(f)
295 except error.LookupError:
295 except error.LookupError:
296 raise IOError
296 raise IOError
297 renamed = fctx.renamed()
297 renamed = fctx.renamed()
298 if renamed:
298 if renamed:
299 renamed = renamed[0]
299 renamed = renamed[0]
300
300
301 data = fctx.data()
301 data = fctx.data()
302 if f == '.hgtags':
302 if f == '.hgtags':
303 data = _converttags (ui, revmap, data)
303 data = _converttags (ui, revmap, data)
304 return context.memfilectx(f, data, 'l' in fctx.flags(),
304 return context.memfilectx(f, data, 'l' in fctx.flags(),
305 'x' in fctx.flags(), renamed)
305 'x' in fctx.flags(), renamed)
306
306
307 # Remap tag data using a revision map
307 # Remap tag data using a revision map
308 def _converttags(ui, revmap, data):
308 def _converttags(ui, revmap, data):
309 newdata = []
309 newdata = []
310 for line in data.splitlines():
310 for line in data.splitlines():
311 try:
311 try:
312 id, name = line.split(' ', 1)
312 id, name = line.split(' ', 1)
313 except ValueError:
313 except ValueError:
314 ui.warn(_('skipping incorrectly formatted tag %s\n'
314 ui.warn(_('skipping incorrectly formatted tag %s\n'
315 % line))
315 % line))
316 continue
316 continue
317 try:
317 try:
318 newid = node.bin(id)
318 newid = node.bin(id)
319 except TypeError:
319 except TypeError:
320 ui.warn(_('skipping incorrectly formatted id %s\n'
320 ui.warn(_('skipping incorrectly formatted id %s\n'
321 % id))
321 % id))
322 continue
322 continue
323 try:
323 try:
324 newdata.append('%s %s\n' % (node.hex(revmap[newid]),
324 newdata.append('%s %s\n' % (node.hex(revmap[newid]),
325 name))
325 name))
326 except KeyError:
326 except KeyError:
327 ui.warn(_('no mapping for id %s\n') % id)
327 ui.warn(_('no mapping for id %s\n') % id)
328 continue
328 continue
329 return ''.join(newdata)
329 return ''.join(newdata)
330
330
331 def _islfile(file, ctx, matcher, size):
331 def _islfile(file, ctx, matcher, size):
332 '''Return true if file should be considered a largefile, i.e.
332 '''Return true if file should be considered a largefile, i.e.
333 matcher matches it or it is larger than size.'''
333 matcher matches it or it is larger than size.'''
334 # never store special .hg* files as largefiles
334 # never store special .hg* files as largefiles
335 if file == '.hgtags' or file == '.hgignore' or file == '.hgsigs':
335 if file == '.hgtags' or file == '.hgignore' or file == '.hgsigs':
336 return False
336 return False
337 if matcher and matcher(file):
337 if matcher and matcher(file):
338 return True
338 return True
339 try:
339 try:
340 return ctx.filectx(file).size() >= size * 1024 * 1024
340 return ctx.filectx(file).size() >= size * 1024 * 1024
341 except error.LookupError:
341 except error.LookupError:
342 return False
342 return False
343
343
344 def uploadlfiles(ui, rsrc, rdst, files):
344 def uploadlfiles(ui, rsrc, rdst, files):
345 '''upload largefiles to the central store'''
345 '''upload largefiles to the central store'''
346
346
347 if not files:
347 if not files:
348 return
348 return
349
349
350 store = basestore._openstore(rsrc, rdst, put=True)
350 store = basestore._openstore(rsrc, rdst, put=True)
351
351
352 at = 0
352 at = 0
353 ui.debug("sending statlfile command for %d largefiles\n" % len(files))
353 ui.debug("sending statlfile command for %d largefiles\n" % len(files))
354 retval = store.exists(files)
354 retval = store.exists(files)
355 files = filter(lambda h: not retval[h], files)
355 files = filter(lambda h: not retval[h], files)
356 ui.debug("%d largefiles need to be uploaded\n" % len(files))
356 ui.debug("%d largefiles need to be uploaded\n" % len(files))
357
357
358 for hash in files:
358 for hash in files:
359 ui.progress(_('uploading largefiles'), at, unit='largefile',
359 ui.progress(_('uploading largefiles'), at, unit='largefile',
360 total=len(files))
360 total=len(files))
361 source = lfutil.findfile(rsrc, hash)
361 source = lfutil.findfile(rsrc, hash)
362 if not source:
362 if not source:
363 raise util.Abort(_('largefile %s missing from store'
363 raise util.Abort(_('largefile %s missing from store'
364 ' (needs to be uploaded)') % hash)
364 ' (needs to be uploaded)') % hash)
365 # XXX check for errors here
365 # XXX check for errors here
366 store.put(source, hash)
366 store.put(source, hash)
367 at += 1
367 at += 1
368 ui.progress(_('uploading largefiles'), None)
368 ui.progress(_('uploading largefiles'), None)
369
369
370 def verifylfiles(ui, repo, all=False, contents=False):
370 def verifylfiles(ui, repo, all=False, contents=False):
371 '''Verify that every largefile revision in the current changeset
371 '''Verify that every largefile revision in the current changeset
372 exists in the central store. With --contents, also verify that
372 exists in the central store. With --contents, also verify that
373 the contents of each local largefile file revision are correct (SHA-1 hash
373 the contents of each local largefile file revision are correct (SHA-1 hash
374 matches the revision ID). With --all, check every changeset in
374 matches the revision ID). With --all, check every changeset in
375 this repository.'''
375 this repository.'''
376 if all:
376 if all:
377 # Pass a list to the function rather than an iterator because we know a
377 # Pass a list to the function rather than an iterator because we know a
378 # list will work.
378 # list will work.
379 revs = range(len(repo))
379 revs = range(len(repo))
380 else:
380 else:
381 revs = ['.']
381 revs = ['.']
382
382
383 store = basestore._openstore(repo)
383 store = basestore._openstore(repo)
384 return store.verify(revs, contents=contents)
384 return store.verify(revs, contents=contents)
385
385
386 def debugdirstate(ui, repo):
386 def debugdirstate(ui, repo):
387 '''Show basic information for the largefiles dirstate'''
387 '''Show basic information for the largefiles dirstate'''
388 lfdirstate = lfutil.openlfdirstate(ui, repo)
388 lfdirstate = lfutil.openlfdirstate(ui, repo)
389 for file_, ent in sorted(lfdirstate._map.iteritems()):
389 for file_, ent in sorted(lfdirstate._map.iteritems()):
390 mode = '%3o' % (ent[1] & 0777 & ~util.umask)
390 mode = '%3o' % (ent[1] & 0777 & ~util.umask)
391 ui.write("%c %s %10d %s\n" % (ent[0], mode, ent[2], file_))
391 ui.write("%c %s %10d %s\n" % (ent[0], mode, ent[2], file_))
392
392
393 def cachelfiles(ui, repo, node, filelist=None):
393 def cachelfiles(ui, repo, node, filelist=None):
394 '''cachelfiles ensures that all largefiles needed by the specified revision
394 '''cachelfiles ensures that all largefiles needed by the specified revision
395 are present in the repository's largefile cache.
395 are present in the repository's largefile cache.
396
396
397 returns a tuple (cached, missing). cached is the list of files downloaded
397 returns a tuple (cached, missing). cached is the list of files downloaded
398 by this operation; missing is the list of files that were needed but could
398 by this operation; missing is the list of files that were needed but could
399 not be found.'''
399 not be found.'''
400 lfiles = lfutil.listlfiles(repo, node)
400 lfiles = lfutil.listlfiles(repo, node)
401 if filelist:
401 if filelist:
402 lfiles = set(lfiles) & set(filelist)
402 lfiles = set(lfiles) & set(filelist)
403 toget = []
403 toget = []
404
404
405 for lfile in lfiles:
405 for lfile in lfiles:
406 try:
406 try:
407 expectedhash = repo[node][lfutil.standin(lfile)].data().strip()
407 expectedhash = repo[node][lfutil.standin(lfile)].data().strip()
408 except IOError, err:
408 except IOError, err:
409 if err.errno == errno.ENOENT:
409 if err.errno == errno.ENOENT:
410 continue # node must be None and standin wasn't found in wctx
410 continue # node must be None and standin wasn't found in wctx
411 raise
411 raise
412 if not lfutil.findfile(repo, expectedhash):
412 if not lfutil.findfile(repo, expectedhash):
413 toget.append((lfile, expectedhash))
413 toget.append((lfile, expectedhash))
414
414
415 if toget:
415 if toget:
416 store = basestore._openstore(repo)
416 store = basestore._openstore(repo)
417 ret = store.get(toget)
417 ret = store.get(toget)
418 return ret
418 return ret
419
419
420 return ([], [])
420 return ([], [])
421
421
422 def downloadlfiles(ui, repo, rev=None):
422 def downloadlfiles(ui, repo, rev=None):
423 matchfn = scmutil.match(repo[None],
423 matchfn = scmutil.match(repo[None],
424 [repo.wjoin(lfutil.shortname)], {})
424 [repo.wjoin(lfutil.shortname)], {})
425 def prepare(ctx, fns):
425 def prepare(ctx, fns):
426 pass
426 pass
427 totalsuccess = 0
427 totalsuccess = 0
428 totalmissing = 0
428 totalmissing = 0
429 if rev != []: # walkchangerevs on empty list would return all revs
429 if rev != []: # walkchangerevs on empty list would return all revs
430 for ctx in cmdutil.walkchangerevs(repo, matchfn, {'rev' : rev},
430 for ctx in cmdutil.walkchangerevs(repo, matchfn, {'rev' : rev},
431 prepare):
431 prepare):
432 success, missing = cachelfiles(ui, repo, ctx.node())
432 success, missing = cachelfiles(ui, repo, ctx.node())
433 totalsuccess += len(success)
433 totalsuccess += len(success)
434 totalmissing += len(missing)
434 totalmissing += len(missing)
435 ui.status(_("%d additional largefiles cached\n") % totalsuccess)
435 ui.status(_("%d additional largefiles cached\n") % totalsuccess)
436 if totalmissing > 0:
436 if totalmissing > 0:
437 ui.status(_("%d largefiles failed to download\n") % totalmissing)
437 ui.status(_("%d largefiles failed to download\n") % totalmissing)
438 return totalsuccess, totalmissing
438 return totalsuccess, totalmissing
439
439
440 def updatelfiles(ui, repo, filelist=None, printmessage=True):
440 def updatelfiles(ui, repo, filelist=None, printmessage=True):
441 wlock = repo.wlock()
441 wlock = repo.wlock()
442 try:
442 try:
443 lfdirstate = lfutil.openlfdirstate(ui, repo)
443 lfdirstate = lfutil.openlfdirstate(ui, repo)
444 lfiles = set(lfutil.listlfiles(repo)) | set(lfdirstate)
444 lfiles = set(lfutil.listlfiles(repo)) | set(lfdirstate)
445
445
446 if filelist is not None:
446 if filelist is not None:
447 lfiles = [f for f in lfiles if f in filelist]
447 lfiles = [f for f in lfiles if f in filelist]
448
448
449 printed = False
449 printed = False
450 if printmessage and lfiles:
450 if printmessage and lfiles:
451 ui.status(_('getting changed largefiles\n'))
451 ui.status(_('getting changed largefiles\n'))
452 printed = True
452 printed = True
453 cachelfiles(ui, repo, None, lfiles)
453 cachelfiles(ui, repo, None, lfiles)
454
454
455 updated, removed = 0, 0
455 updated, removed = 0, 0
456 for f in lfiles:
456 for f in lfiles:
457 i = _updatelfile(repo, lfdirstate, f)
457 i = _updatelfile(repo, lfdirstate, f)
458 if i:
458 if i:
459 if i > 0:
459 if i > 0:
460 updated += i
460 updated += i
461 else:
461 else:
462 removed -= i
462 removed -= i
463 if printmessage and (removed or updated) and not printed:
463 if printmessage and (removed or updated) and not printed:
464 ui.status(_('getting changed largefiles\n'))
464 ui.status(_('getting changed largefiles\n'))
465 printed = True
465 printed = True
466
466
467 lfdirstate.write()
467 lfdirstate.write()
468 if printed and printmessage:
468 if printed and printmessage:
469 ui.status(_('%d largefiles updated, %d removed\n') % (updated,
469 ui.status(_('%d largefiles updated, %d removed\n') % (updated,
470 removed))
470 removed))
471 finally:
471 finally:
472 wlock.release()
472 wlock.release()
473
473
474 def _updatelfile(repo, lfdirstate, lfile):
474 def _updatelfile(repo, lfdirstate, lfile):
475 '''updates a single largefile and copies the state of its standin from
475 '''updates a single largefile and copies the state of its standin from
476 the repository's dirstate to its state in the lfdirstate.
476 the repository's dirstate to its state in the lfdirstate.
477
477
478 returns 1 if the file was modified, -1 if the file was removed, 0 if the
478 returns 1 if the file was modified, -1 if the file was removed, 0 if the
479 file was unchanged, and None if the needed largefile was missing from the
479 file was unchanged, and None if the needed largefile was missing from the
480 cache.'''
480 cache.'''
481 ret = 0
481 ret = 0
482 abslfile = repo.wjoin(lfile)
482 abslfile = repo.wjoin(lfile)
483 absstandin = repo.wjoin(lfutil.standin(lfile))
483 absstandin = repo.wjoin(lfutil.standin(lfile))
484 if os.path.exists(absstandin):
484 if os.path.exists(absstandin):
485 if os.path.exists(absstandin + '.orig') and os.path.exists(abslfile):
485 if os.path.exists(absstandin + '.orig') and os.path.exists(abslfile):
486 shutil.copyfile(abslfile, abslfile + '.orig')
486 shutil.copyfile(abslfile, abslfile + '.orig')
487 expecthash = lfutil.readstandin(repo, lfile)
487 expecthash = lfutil.readstandin(repo, lfile)
488 if (expecthash != '' and
488 if (expecthash != '' and
489 (not os.path.exists(abslfile) or
489 (not os.path.exists(abslfile) or
490 expecthash != lfutil.hashfile(abslfile))):
490 expecthash != lfutil.hashfile(abslfile))):
491 if not lfutil.copyfromcache(repo, expecthash, lfile):
491 if not lfutil.copyfromcache(repo, expecthash, lfile):
492 # use normallookup() to allocate entry in largefiles dirstate,
492 # use normallookup() to allocate entry in largefiles dirstate,
493 # because lack of it misleads lfilesrepo.status() into
493 # because lack of it misleads lfilesrepo.status() into
494 # recognition that such cache missing files are REMOVED.
494 # recognition that such cache missing files are REMOVED.
495 if lfile not in repo[None]: # not switched to normal file
495 if lfile not in repo[None]: # not switched to normal file
496 util.unlinkpath(abslfile, ignoremissing=True)
496 util.unlinkpath(abslfile, ignoremissing=True)
497 lfdirstate.normallookup(lfile)
497 lfdirstate.normallookup(lfile)
498 return None # don't try to set the mode
498 return None # don't try to set the mode
499 else:
499 else:
500 # Synchronize largefile dirstate to the last modified time of
500 # Synchronize largefile dirstate to the last modified time of
501 # the file
501 # the file
502 lfdirstate.normal(lfile)
502 lfdirstate.normal(lfile)
503 ret = 1
503 ret = 1
504 mode = os.stat(absstandin).st_mode
504 mode = os.stat(absstandin).st_mode
505 if mode != os.stat(abslfile).st_mode:
505 if mode != os.stat(abslfile).st_mode:
506 os.chmod(abslfile, mode)
506 os.chmod(abslfile, mode)
507 ret = 1
507 ret = 1
508 else:
508 else:
509 # Remove lfiles for which the standin is deleted, unless the
509 # Remove lfiles for which the standin is deleted, unless the
510 # lfile is added to the repository again. This happens when a
510 # lfile is added to the repository again. This happens when a
511 # largefile is converted back to a normal file: the standin
511 # largefile is converted back to a normal file: the standin
512 # disappears, but a new (normal) file appears as the lfile.
512 # disappears, but a new (normal) file appears as the lfile.
513 if os.path.exists(abslfile) and lfile not in repo[None]:
513 if os.path.exists(abslfile) and lfile not in repo[None]:
514 util.unlinkpath(abslfile)
514 util.unlinkpath(abslfile)
515 ret = -1
515 ret = -1
516 state = repo.dirstate[lfutil.standin(lfile)]
516 state = repo.dirstate[lfutil.standin(lfile)]
517 if state == 'n':
517 if state == 'n':
518 # When rebasing, we need to synchronize the standin and the largefile,
518 # When rebasing, we need to synchronize the standin and the largefile,
519 # because otherwise the largefile will get reverted. But for commit's
519 # because otherwise the largefile will get reverted. But for commit's
520 # sake, we have to mark the file as unclean.
520 # sake, we have to mark the file as unclean.
521 if getattr(repo, "_isrebasing", False):
521 if getattr(repo, "_isrebasing", False):
522 lfdirstate.normallookup(lfile)
522 lfdirstate.normallookup(lfile)
523 else:
523 else:
524 lfdirstate.normal(lfile)
524 lfdirstate.normal(lfile)
525 elif state == 'r':
525 elif state == 'r':
526 lfdirstate.remove(lfile)
526 lfdirstate.remove(lfile)
527 elif state == 'a':
527 elif state == 'a':
528 lfdirstate.add(lfile)
528 lfdirstate.add(lfile)
529 elif state == '?':
529 elif state == '?':
530 lfdirstate.drop(lfile)
530 lfdirstate.drop(lfile)
531 return ret
531 return ret
532
532
533 def catlfile(repo, lfile, rev, filename):
534 hash = lfutil.readstandin(repo, lfile, rev)
535 if not lfutil.inusercache(repo.ui, hash):
536 store = basestore._openstore(repo)
537 success, missing = store.get([(lfile, hash)])
538 if len(success) != 1:
539 raise util.Abort(
540 _('largefile %s is not in cache and could not be downloaded')
541 % lfile)
542 path = lfutil.usercachepath(repo.ui, hash)
543 fpout = cmdutil.makefileobj(repo, filename)
544 fpin = open(path, "rb")
545 for chunk in lfutil.blockstream(fpin):
546 fpout.write(chunk)
547 fpout.close()
548 fpin.close()
549 return 0
550
551 # -- hg commands declarations ------------------------------------------------
533 # -- hg commands declarations ------------------------------------------------
552
534
553 cmdtable = {
535 cmdtable = {
554 'lfconvert': (lfconvert,
536 'lfconvert': (lfconvert,
555 [('s', 'size', '',
537 [('s', 'size', '',
556 _('minimum size (MB) for files to be converted '
538 _('minimum size (MB) for files to be converted '
557 'as largefiles'),
539 'as largefiles'),
558 'SIZE'),
540 'SIZE'),
559 ('', 'to-normal', False,
541 ('', 'to-normal', False,
560 _('convert from a largefiles repo to a normal repo')),
542 _('convert from a largefiles repo to a normal repo')),
561 ],
543 ],
562 _('hg lfconvert SOURCE DEST [FILE ...]')),
544 _('hg lfconvert SOURCE DEST [FILE ...]')),
563 }
545 }
564
546
565 commands.inferrepo += " lfconvert"
547 commands.inferrepo += " lfconvert"
@@ -1,1173 +1,1198 b''
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 '''Overridden Mercurial commands and functions for the largefiles extension'''
9 '''Overridden Mercurial commands and functions for the largefiles extension'''
10
10
11 import os
11 import os
12 import copy
12 import copy
13
13
14 from mercurial import hg, commands, util, cmdutil, scmutil, match as match_, \
14 from mercurial import hg, commands, util, cmdutil, scmutil, match as match_, \
15 node, archival, error, merge, discovery
15 node, archival, error, merge, discovery
16 from mercurial.i18n import _
16 from mercurial.i18n import _
17 from mercurial.node import hex
17 from mercurial.node import hex
18 from hgext import rebase
18 from hgext import rebase
19
19
20 import lfutil
20 import lfutil
21 import lfcommands
21 import lfcommands
22 import basestore
22
23
23 # -- Utility functions: commonly/repeatedly needed functionality ---------------
24 # -- Utility functions: commonly/repeatedly needed functionality ---------------
24
25
25 def installnormalfilesmatchfn(manifest):
26 def installnormalfilesmatchfn(manifest):
26 '''overrides scmutil.match so that the matcher it returns will ignore all
27 '''overrides scmutil.match so that the matcher it returns will ignore all
27 largefiles'''
28 largefiles'''
28 oldmatch = None # for the closure
29 oldmatch = None # for the closure
29 def overridematch(ctx, pats=[], opts={}, globbed=False,
30 def overridematch(ctx, pats=[], opts={}, globbed=False,
30 default='relpath'):
31 default='relpath'):
31 match = oldmatch(ctx, pats, opts, globbed, default)
32 match = oldmatch(ctx, pats, opts, globbed, default)
32 m = copy.copy(match)
33 m = copy.copy(match)
33 notlfile = lambda f: not (lfutil.isstandin(f) or lfutil.standin(f) in
34 notlfile = lambda f: not (lfutil.isstandin(f) or lfutil.standin(f) in
34 manifest)
35 manifest)
35 m._files = filter(notlfile, m._files)
36 m._files = filter(notlfile, m._files)
36 m._fmap = set(m._files)
37 m._fmap = set(m._files)
37 m._always = False
38 m._always = False
38 origmatchfn = m.matchfn
39 origmatchfn = m.matchfn
39 m.matchfn = lambda f: notlfile(f) and origmatchfn(f) or None
40 m.matchfn = lambda f: notlfile(f) and origmatchfn(f) or None
40 return m
41 return m
41 oldmatch = installmatchfn(overridematch)
42 oldmatch = installmatchfn(overridematch)
42
43
43 def installmatchfn(f):
44 def installmatchfn(f):
44 oldmatch = scmutil.match
45 oldmatch = scmutil.match
45 setattr(f, 'oldmatch', oldmatch)
46 setattr(f, 'oldmatch', oldmatch)
46 scmutil.match = f
47 scmutil.match = f
47 return oldmatch
48 return oldmatch
48
49
49 def restorematchfn():
50 def restorematchfn():
50 '''restores scmutil.match to what it was before installnormalfilesmatchfn
51 '''restores scmutil.match to what it was before installnormalfilesmatchfn
51 was called. no-op if scmutil.match is its original function.
52 was called. no-op if scmutil.match is its original function.
52
53
53 Note that n calls to installnormalfilesmatchfn will require n calls to
54 Note that n calls to installnormalfilesmatchfn will require n calls to
54 restore matchfn to reverse'''
55 restore matchfn to reverse'''
55 scmutil.match = getattr(scmutil.match, 'oldmatch', scmutil.match)
56 scmutil.match = getattr(scmutil.match, 'oldmatch', scmutil.match)
56
57
57 def addlargefiles(ui, repo, *pats, **opts):
58 def addlargefiles(ui, repo, *pats, **opts):
58 large = opts.pop('large', None)
59 large = opts.pop('large', None)
59 lfsize = lfutil.getminsize(
60 lfsize = lfutil.getminsize(
60 ui, lfutil.islfilesrepo(repo), opts.pop('lfsize', None))
61 ui, lfutil.islfilesrepo(repo), opts.pop('lfsize', None))
61
62
62 lfmatcher = None
63 lfmatcher = None
63 if lfutil.islfilesrepo(repo):
64 if lfutil.islfilesrepo(repo):
64 lfpats = ui.configlist(lfutil.longname, 'patterns', default=[])
65 lfpats = ui.configlist(lfutil.longname, 'patterns', default=[])
65 if lfpats:
66 if lfpats:
66 lfmatcher = match_.match(repo.root, '', list(lfpats))
67 lfmatcher = match_.match(repo.root, '', list(lfpats))
67
68
68 lfnames = []
69 lfnames = []
69 m = scmutil.match(repo[None], pats, opts)
70 m = scmutil.match(repo[None], pats, opts)
70 m.bad = lambda x, y: None
71 m.bad = lambda x, y: None
71 wctx = repo[None]
72 wctx = repo[None]
72 for f in repo.walk(m):
73 for f in repo.walk(m):
73 exact = m.exact(f)
74 exact = m.exact(f)
74 lfile = lfutil.standin(f) in wctx
75 lfile = lfutil.standin(f) in wctx
75 nfile = f in wctx
76 nfile = f in wctx
76 exists = lfile or nfile
77 exists = lfile or nfile
77
78
78 # Don't warn the user when they attempt to add a normal tracked file.
79 # Don't warn the user when they attempt to add a normal tracked file.
79 # The normal add code will do that for us.
80 # The normal add code will do that for us.
80 if exact and exists:
81 if exact and exists:
81 if lfile:
82 if lfile:
82 ui.warn(_('%s already a largefile\n') % f)
83 ui.warn(_('%s already a largefile\n') % f)
83 continue
84 continue
84
85
85 if (exact or not exists) and not lfutil.isstandin(f):
86 if (exact or not exists) and not lfutil.isstandin(f):
86 wfile = repo.wjoin(f)
87 wfile = repo.wjoin(f)
87
88
88 # In case the file was removed previously, but not committed
89 # In case the file was removed previously, but not committed
89 # (issue3507)
90 # (issue3507)
90 if not os.path.exists(wfile):
91 if not os.path.exists(wfile):
91 continue
92 continue
92
93
93 abovemin = (lfsize and
94 abovemin = (lfsize and
94 os.lstat(wfile).st_size >= lfsize * 1024 * 1024)
95 os.lstat(wfile).st_size >= lfsize * 1024 * 1024)
95 if large or abovemin or (lfmatcher and lfmatcher(f)):
96 if large or abovemin or (lfmatcher and lfmatcher(f)):
96 lfnames.append(f)
97 lfnames.append(f)
97 if ui.verbose or not exact:
98 if ui.verbose or not exact:
98 ui.status(_('adding %s as a largefile\n') % m.rel(f))
99 ui.status(_('adding %s as a largefile\n') % m.rel(f))
99
100
100 bad = []
101 bad = []
101 standins = []
102 standins = []
102
103
103 # Need to lock, otherwise there could be a race condition between
104 # Need to lock, otherwise there could be a race condition between
104 # when standins are created and added to the repo.
105 # when standins are created and added to the repo.
105 wlock = repo.wlock()
106 wlock = repo.wlock()
106 try:
107 try:
107 if not opts.get('dry_run'):
108 if not opts.get('dry_run'):
108 lfdirstate = lfutil.openlfdirstate(ui, repo)
109 lfdirstate = lfutil.openlfdirstate(ui, repo)
109 for f in lfnames:
110 for f in lfnames:
110 standinname = lfutil.standin(f)
111 standinname = lfutil.standin(f)
111 lfutil.writestandin(repo, standinname, hash='',
112 lfutil.writestandin(repo, standinname, hash='',
112 executable=lfutil.getexecutable(repo.wjoin(f)))
113 executable=lfutil.getexecutable(repo.wjoin(f)))
113 standins.append(standinname)
114 standins.append(standinname)
114 if lfdirstate[f] == 'r':
115 if lfdirstate[f] == 'r':
115 lfdirstate.normallookup(f)
116 lfdirstate.normallookup(f)
116 else:
117 else:
117 lfdirstate.add(f)
118 lfdirstate.add(f)
118 lfdirstate.write()
119 lfdirstate.write()
119 bad += [lfutil.splitstandin(f)
120 bad += [lfutil.splitstandin(f)
120 for f in repo[None].add(standins)
121 for f in repo[None].add(standins)
121 if f in m.files()]
122 if f in m.files()]
122 finally:
123 finally:
123 wlock.release()
124 wlock.release()
124 return bad
125 return bad
125
126
126 def removelargefiles(ui, repo, *pats, **opts):
127 def removelargefiles(ui, repo, *pats, **opts):
127 after = opts.get('after')
128 after = opts.get('after')
128 if not pats and not after:
129 if not pats and not after:
129 raise util.Abort(_('no files specified'))
130 raise util.Abort(_('no files specified'))
130 m = scmutil.match(repo[None], pats, opts)
131 m = scmutil.match(repo[None], pats, opts)
131 try:
132 try:
132 repo.lfstatus = True
133 repo.lfstatus = True
133 s = repo.status(match=m, clean=True)
134 s = repo.status(match=m, clean=True)
134 finally:
135 finally:
135 repo.lfstatus = False
136 repo.lfstatus = False
136 manifest = repo[None].manifest()
137 manifest = repo[None].manifest()
137 modified, added, deleted, clean = [[f for f in list
138 modified, added, deleted, clean = [[f for f in list
138 if lfutil.standin(f) in manifest]
139 if lfutil.standin(f) in manifest]
139 for list in [s[0], s[1], s[3], s[6]]]
140 for list in [s[0], s[1], s[3], s[6]]]
140
141
141 def warn(files, msg):
142 def warn(files, msg):
142 for f in files:
143 for f in files:
143 ui.warn(msg % m.rel(f))
144 ui.warn(msg % m.rel(f))
144 return int(len(files) > 0)
145 return int(len(files) > 0)
145
146
146 result = 0
147 result = 0
147
148
148 if after:
149 if after:
149 remove, forget = deleted, []
150 remove, forget = deleted, []
150 result = warn(modified + added + clean,
151 result = warn(modified + added + clean,
151 _('not removing %s: file still exists\n'))
152 _('not removing %s: file still exists\n'))
152 else:
153 else:
153 remove, forget = deleted + clean, []
154 remove, forget = deleted + clean, []
154 result = warn(modified, _('not removing %s: file is modified (use -f'
155 result = warn(modified, _('not removing %s: file is modified (use -f'
155 ' to force removal)\n'))
156 ' to force removal)\n'))
156 result = warn(added, _('not removing %s: file has been marked for add'
157 result = warn(added, _('not removing %s: file has been marked for add'
157 ' (use forget to undo)\n')) or result
158 ' (use forget to undo)\n')) or result
158
159
159 for f in sorted(remove + forget):
160 for f in sorted(remove + forget):
160 if ui.verbose or not m.exact(f):
161 if ui.verbose or not m.exact(f):
161 ui.status(_('removing %s\n') % m.rel(f))
162 ui.status(_('removing %s\n') % m.rel(f))
162
163
163 # Need to lock because standin files are deleted then removed from the
164 # Need to lock because standin files are deleted then removed from the
164 # repository and we could race in-between.
165 # repository and we could race in-between.
165 wlock = repo.wlock()
166 wlock = repo.wlock()
166 try:
167 try:
167 lfdirstate = lfutil.openlfdirstate(ui, repo)
168 lfdirstate = lfutil.openlfdirstate(ui, repo)
168 for f in remove:
169 for f in remove:
169 if not after:
170 if not after:
170 # If this is being called by addremove, notify the user that we
171 # If this is being called by addremove, notify the user that we
171 # are removing the file.
172 # are removing the file.
172 if getattr(repo, "_isaddremove", False):
173 if getattr(repo, "_isaddremove", False):
173 ui.status(_('removing %s\n') % f)
174 ui.status(_('removing %s\n') % f)
174 util.unlinkpath(repo.wjoin(f), ignoremissing=True)
175 util.unlinkpath(repo.wjoin(f), ignoremissing=True)
175 lfdirstate.remove(f)
176 lfdirstate.remove(f)
176 lfdirstate.write()
177 lfdirstate.write()
177 forget = [lfutil.standin(f) for f in forget]
178 forget = [lfutil.standin(f) for f in forget]
178 remove = [lfutil.standin(f) for f in remove]
179 remove = [lfutil.standin(f) for f in remove]
179 repo[None].forget(forget)
180 repo[None].forget(forget)
180 # If this is being called by addremove, let the original addremove
181 # If this is being called by addremove, let the original addremove
181 # function handle this.
182 # function handle this.
182 if not getattr(repo, "_isaddremove", False):
183 if not getattr(repo, "_isaddremove", False):
183 for f in remove:
184 for f in remove:
184 util.unlinkpath(repo.wjoin(f), ignoremissing=True)
185 util.unlinkpath(repo.wjoin(f), ignoremissing=True)
185 repo[None].forget(remove)
186 repo[None].forget(remove)
186 finally:
187 finally:
187 wlock.release()
188 wlock.release()
188
189
189 return result
190 return result
190
191
191 # For overriding mercurial.hgweb.webcommands so that largefiles will
192 # For overriding mercurial.hgweb.webcommands so that largefiles will
192 # appear at their right place in the manifests.
193 # appear at their right place in the manifests.
193 def decodepath(orig, path):
194 def decodepath(orig, path):
194 return lfutil.splitstandin(path) or path
195 return lfutil.splitstandin(path) or path
195
196
196 # -- Wrappers: modify existing commands --------------------------------
197 # -- Wrappers: modify existing commands --------------------------------
197
198
198 # Add works by going through the files that the user wanted to add and
199 # Add works by going through the files that the user wanted to add and
199 # checking if they should be added as largefiles. Then it makes a new
200 # checking if they should be added as largefiles. Then it makes a new
200 # matcher which matches only the normal files and runs the original
201 # matcher which matches only the normal files and runs the original
201 # version of add.
202 # version of add.
202 def overrideadd(orig, ui, repo, *pats, **opts):
203 def overrideadd(orig, ui, repo, *pats, **opts):
203 normal = opts.pop('normal')
204 normal = opts.pop('normal')
204 if normal:
205 if normal:
205 if opts.get('large'):
206 if opts.get('large'):
206 raise util.Abort(_('--normal cannot be used with --large'))
207 raise util.Abort(_('--normal cannot be used with --large'))
207 return orig(ui, repo, *pats, **opts)
208 return orig(ui, repo, *pats, **opts)
208 bad = addlargefiles(ui, repo, *pats, **opts)
209 bad = addlargefiles(ui, repo, *pats, **opts)
209 installnormalfilesmatchfn(repo[None].manifest())
210 installnormalfilesmatchfn(repo[None].manifest())
210 result = orig(ui, repo, *pats, **opts)
211 result = orig(ui, repo, *pats, **opts)
211 restorematchfn()
212 restorematchfn()
212
213
213 return (result == 1 or bad) and 1 or 0
214 return (result == 1 or bad) and 1 or 0
214
215
215 def overrideremove(orig, ui, repo, *pats, **opts):
216 def overrideremove(orig, ui, repo, *pats, **opts):
216 installnormalfilesmatchfn(repo[None].manifest())
217 installnormalfilesmatchfn(repo[None].manifest())
217 result = orig(ui, repo, *pats, **opts)
218 result = orig(ui, repo, *pats, **opts)
218 restorematchfn()
219 restorematchfn()
219 return removelargefiles(ui, repo, *pats, **opts) or result
220 return removelargefiles(ui, repo, *pats, **opts) or result
220
221
221 def overridestatusfn(orig, repo, rev2, **opts):
222 def overridestatusfn(orig, repo, rev2, **opts):
222 try:
223 try:
223 repo._repo.lfstatus = True
224 repo._repo.lfstatus = True
224 return orig(repo, rev2, **opts)
225 return orig(repo, rev2, **opts)
225 finally:
226 finally:
226 repo._repo.lfstatus = False
227 repo._repo.lfstatus = False
227
228
228 def overridestatus(orig, ui, repo, *pats, **opts):
229 def overridestatus(orig, ui, repo, *pats, **opts):
229 try:
230 try:
230 repo.lfstatus = True
231 repo.lfstatus = True
231 return orig(ui, repo, *pats, **opts)
232 return orig(ui, repo, *pats, **opts)
232 finally:
233 finally:
233 repo.lfstatus = False
234 repo.lfstatus = False
234
235
235 def overridedirty(orig, repo, ignoreupdate=False):
236 def overridedirty(orig, repo, ignoreupdate=False):
236 try:
237 try:
237 repo._repo.lfstatus = True
238 repo._repo.lfstatus = True
238 return orig(repo, ignoreupdate)
239 return orig(repo, ignoreupdate)
239 finally:
240 finally:
240 repo._repo.lfstatus = False
241 repo._repo.lfstatus = False
241
242
242 def overridelog(orig, ui, repo, *pats, **opts):
243 def overridelog(orig, ui, repo, *pats, **opts):
243 def overridematch(ctx, pats=[], opts={}, globbed=False,
244 def overridematch(ctx, pats=[], opts={}, globbed=False,
244 default='relpath'):
245 default='relpath'):
245 """Matcher that merges root directory with .hglf, suitable for log.
246 """Matcher that merges root directory with .hglf, suitable for log.
246 It is still possible to match .hglf directly.
247 It is still possible to match .hglf directly.
247 For any listed files run log on the standin too.
248 For any listed files run log on the standin too.
248 matchfn tries both the given filename and with .hglf stripped.
249 matchfn tries both the given filename and with .hglf stripped.
249 """
250 """
250 match = oldmatch(ctx, pats, opts, globbed, default)
251 match = oldmatch(ctx, pats, opts, globbed, default)
251 m = copy.copy(match)
252 m = copy.copy(match)
252 standins = [lfutil.standin(f) for f in m._files]
253 standins = [lfutil.standin(f) for f in m._files]
253 m._files.extend(standins)
254 m._files.extend(standins)
254 m._fmap = set(m._files)
255 m._fmap = set(m._files)
255 m._always = False
256 m._always = False
256 origmatchfn = m.matchfn
257 origmatchfn = m.matchfn
257 def lfmatchfn(f):
258 def lfmatchfn(f):
258 lf = lfutil.splitstandin(f)
259 lf = lfutil.splitstandin(f)
259 if lf is not None and origmatchfn(lf):
260 if lf is not None and origmatchfn(lf):
260 return True
261 return True
261 r = origmatchfn(f)
262 r = origmatchfn(f)
262 return r
263 return r
263 m.matchfn = lfmatchfn
264 m.matchfn = lfmatchfn
264 return m
265 return m
265 oldmatch = installmatchfn(overridematch)
266 oldmatch = installmatchfn(overridematch)
266 try:
267 try:
267 repo.lfstatus = True
268 repo.lfstatus = True
268 return orig(ui, repo, *pats, **opts)
269 return orig(ui, repo, *pats, **opts)
269 finally:
270 finally:
270 repo.lfstatus = False
271 repo.lfstatus = False
271 restorematchfn()
272 restorematchfn()
272
273
273 def overrideverify(orig, ui, repo, *pats, **opts):
274 def overrideverify(orig, ui, repo, *pats, **opts):
274 large = opts.pop('large', False)
275 large = opts.pop('large', False)
275 all = opts.pop('lfa', False)
276 all = opts.pop('lfa', False)
276 contents = opts.pop('lfc', False)
277 contents = opts.pop('lfc', False)
277
278
278 result = orig(ui, repo, *pats, **opts)
279 result = orig(ui, repo, *pats, **opts)
279 if large or all or contents:
280 if large or all or contents:
280 result = result or lfcommands.verifylfiles(ui, repo, all, contents)
281 result = result or lfcommands.verifylfiles(ui, repo, all, contents)
281 return result
282 return result
282
283
283 def overridedebugstate(orig, ui, repo, *pats, **opts):
284 def overridedebugstate(orig, ui, repo, *pats, **opts):
284 large = opts.pop('large', False)
285 large = opts.pop('large', False)
285 if large:
286 if large:
286 lfcommands.debugdirstate(ui, repo)
287 lfcommands.debugdirstate(ui, repo)
287 else:
288 else:
288 orig(ui, repo, *pats, **opts)
289 orig(ui, repo, *pats, **opts)
289
290
290 # Override needs to refresh standins so that update's normal merge
291 # Override needs to refresh standins so that update's normal merge
291 # will go through properly. Then the other update hook (overriding repo.update)
292 # will go through properly. Then the other update hook (overriding repo.update)
292 # will get the new files. Filemerge is also overridden so that the merge
293 # will get the new files. Filemerge is also overridden so that the merge
293 # will merge standins correctly.
294 # will merge standins correctly.
294 def overrideupdate(orig, ui, repo, *pats, **opts):
295 def overrideupdate(orig, ui, repo, *pats, **opts):
295 lfdirstate = lfutil.openlfdirstate(ui, repo)
296 lfdirstate = lfutil.openlfdirstate(ui, repo)
296 s = lfdirstate.status(match_.always(repo.root, repo.getcwd()), [], False,
297 s = lfdirstate.status(match_.always(repo.root, repo.getcwd()), [], False,
297 False, False)
298 False, False)
298 (unsure, modified, added, removed, missing, unknown, ignored, clean) = s
299 (unsure, modified, added, removed, missing, unknown, ignored, clean) = s
299
300
300 # Need to lock between the standins getting updated and their
301 # Need to lock between the standins getting updated and their
301 # largefiles getting updated
302 # largefiles getting updated
302 wlock = repo.wlock()
303 wlock = repo.wlock()
303 try:
304 try:
304 if opts['check']:
305 if opts['check']:
305 mod = len(modified) > 0
306 mod = len(modified) > 0
306 for lfile in unsure:
307 for lfile in unsure:
307 standin = lfutil.standin(lfile)
308 standin = lfutil.standin(lfile)
308 if repo['.'][standin].data().strip() != \
309 if repo['.'][standin].data().strip() != \
309 lfutil.hashfile(repo.wjoin(lfile)):
310 lfutil.hashfile(repo.wjoin(lfile)):
310 mod = True
311 mod = True
311 else:
312 else:
312 lfdirstate.normal(lfile)
313 lfdirstate.normal(lfile)
313 lfdirstate.write()
314 lfdirstate.write()
314 if mod:
315 if mod:
315 raise util.Abort(_('uncommitted local changes'))
316 raise util.Abort(_('uncommitted local changes'))
316 # XXX handle removed differently
317 # XXX handle removed differently
317 if not opts['clean']:
318 if not opts['clean']:
318 for lfile in unsure + modified + added:
319 for lfile in unsure + modified + added:
319 lfutil.updatestandin(repo, lfutil.standin(lfile))
320 lfutil.updatestandin(repo, lfutil.standin(lfile))
320 finally:
321 finally:
321 wlock.release()
322 wlock.release()
322 return orig(ui, repo, *pats, **opts)
323 return orig(ui, repo, *pats, **opts)
323
324
324 # Before starting the manifest merge, merge.updates will call
325 # Before starting the manifest merge, merge.updates will call
325 # _checkunknown to check if there are any files in the merged-in
326 # _checkunknown to check if there are any files in the merged-in
326 # changeset that collide with unknown files in the working copy.
327 # changeset that collide with unknown files in the working copy.
327 #
328 #
328 # The largefiles are seen as unknown, so this prevents us from merging
329 # The largefiles are seen as unknown, so this prevents us from merging
329 # in a file 'foo' if we already have a largefile with the same name.
330 # in a file 'foo' if we already have a largefile with the same name.
330 #
331 #
331 # The overridden function filters the unknown files by removing any
332 # The overridden function filters the unknown files by removing any
332 # largefiles. This makes the merge proceed and we can then handle this
333 # largefiles. This makes the merge proceed and we can then handle this
333 # case further in the overridden manifestmerge function below.
334 # case further in the overridden manifestmerge function below.
334 def overridecheckunknownfile(origfn, repo, wctx, mctx, f):
335 def overridecheckunknownfile(origfn, repo, wctx, mctx, f):
335 if lfutil.standin(f) in wctx:
336 if lfutil.standin(f) in wctx:
336 return False
337 return False
337 return origfn(repo, wctx, mctx, f)
338 return origfn(repo, wctx, mctx, f)
338
339
339 # The manifest merge handles conflicts on the manifest level. We want
340 # The manifest merge handles conflicts on the manifest level. We want
340 # to handle changes in largefile-ness of files at this level too.
341 # to handle changes in largefile-ness of files at this level too.
341 #
342 #
342 # The strategy is to run the original manifestmerge and then process
343 # The strategy is to run the original manifestmerge and then process
343 # the action list it outputs. There are two cases we need to deal with:
344 # the action list it outputs. There are two cases we need to deal with:
344 #
345 #
345 # 1. Normal file in p1, largefile in p2. Here the largefile is
346 # 1. Normal file in p1, largefile in p2. Here the largefile is
346 # detected via its standin file, which will enter the working copy
347 # detected via its standin file, which will enter the working copy
347 # with a "get" action. It is not "merge" since the standin is all
348 # with a "get" action. It is not "merge" since the standin is all
348 # Mercurial is concerned with at this level -- the link to the
349 # Mercurial is concerned with at this level -- the link to the
349 # existing normal file is not relevant here.
350 # existing normal file is not relevant here.
350 #
351 #
351 # 2. Largefile in p1, normal file in p2. Here we get a "merge" action
352 # 2. Largefile in p1, normal file in p2. Here we get a "merge" action
352 # since the largefile will be present in the working copy and
353 # since the largefile will be present in the working copy and
353 # different from the normal file in p2. Mercurial therefore
354 # different from the normal file in p2. Mercurial therefore
354 # triggers a merge action.
355 # triggers a merge action.
355 #
356 #
356 # In both cases, we prompt the user and emit new actions to either
357 # In both cases, we prompt the user and emit new actions to either
357 # remove the standin (if the normal file was kept) or to remove the
358 # remove the standin (if the normal file was kept) or to remove the
358 # normal file and get the standin (if the largefile was kept). The
359 # normal file and get the standin (if the largefile was kept). The
359 # default prompt answer is to use the largefile version since it was
360 # default prompt answer is to use the largefile version since it was
360 # presumably changed on purpose.
361 # presumably changed on purpose.
361 #
362 #
362 # Finally, the merge.applyupdates function will then take care of
363 # Finally, the merge.applyupdates function will then take care of
363 # writing the files into the working copy and lfcommands.updatelfiles
364 # writing the files into the working copy and lfcommands.updatelfiles
364 # will update the largefiles.
365 # will update the largefiles.
365 def overridemanifestmerge(origfn, repo, p1, p2, pa, branchmerge, force,
366 def overridemanifestmerge(origfn, repo, p1, p2, pa, branchmerge, force,
366 partial, acceptremote=False):
367 partial, acceptremote=False):
367 overwrite = force and not branchmerge
368 overwrite = force and not branchmerge
368 actions = origfn(repo, p1, p2, pa, branchmerge, force, partial,
369 actions = origfn(repo, p1, p2, pa, branchmerge, force, partial,
369 acceptremote)
370 acceptremote)
370 processed = []
371 processed = []
371
372
372 for action in actions:
373 for action in actions:
373 if overwrite:
374 if overwrite:
374 processed.append(action)
375 processed.append(action)
375 continue
376 continue
376 f, m, args, msg = action
377 f, m, args, msg = action
377
378
378 choices = (_('&Largefile'), _('&Normal file'))
379 choices = (_('&Largefile'), _('&Normal file'))
379
380
380 splitstandin = lfutil.splitstandin(f)
381 splitstandin = lfutil.splitstandin(f)
381 if (m == "g" and splitstandin is not None and
382 if (m == "g" and splitstandin is not None and
382 splitstandin in p1 and f in p2):
383 splitstandin in p1 and f in p2):
383 # Case 1: normal file in the working copy, largefile in
384 # Case 1: normal file in the working copy, largefile in
384 # the second parent
385 # the second parent
385 lfile = splitstandin
386 lfile = splitstandin
386 standin = f
387 standin = f
387 msg = _('%s has been turned into a largefile\n'
388 msg = _('%s has been turned into a largefile\n'
388 'use (l)argefile or keep as (n)ormal file?') % lfile
389 'use (l)argefile or keep as (n)ormal file?') % lfile
389 if repo.ui.promptchoice(msg, choices, 0) == 0:
390 if repo.ui.promptchoice(msg, choices, 0) == 0:
390 processed.append((lfile, "r", None, msg))
391 processed.append((lfile, "r", None, msg))
391 processed.append((standin, "g", (p2.flags(standin),), msg))
392 processed.append((standin, "g", (p2.flags(standin),), msg))
392 else:
393 else:
393 processed.append((standin, "r", None, msg))
394 processed.append((standin, "r", None, msg))
394 elif m == "g" and lfutil.standin(f) in p1 and f in p2:
395 elif m == "g" and lfutil.standin(f) in p1 and f in p2:
395 # Case 2: largefile in the working copy, normal file in
396 # Case 2: largefile in the working copy, normal file in
396 # the second parent
397 # the second parent
397 standin = lfutil.standin(f)
398 standin = lfutil.standin(f)
398 lfile = f
399 lfile = f
399 msg = _('%s has been turned into a normal file\n'
400 msg = _('%s has been turned into a normal file\n'
400 'keep as (l)argefile or use (n)ormal file?') % lfile
401 'keep as (l)argefile or use (n)ormal file?') % lfile
401 if repo.ui.promptchoice(msg, choices, 0) == 0:
402 if repo.ui.promptchoice(msg, choices, 0) == 0:
402 processed.append((lfile, "r", None, msg))
403 processed.append((lfile, "r", None, msg))
403 else:
404 else:
404 processed.append((standin, "r", None, msg))
405 processed.append((standin, "r", None, msg))
405 processed.append((lfile, "g", (p2.flags(lfile),), msg))
406 processed.append((lfile, "g", (p2.flags(lfile),), msg))
406 else:
407 else:
407 processed.append(action)
408 processed.append(action)
408
409
409 return processed
410 return processed
410
411
411 # Override filemerge to prompt the user about how they wish to merge
412 # Override filemerge to prompt the user about how they wish to merge
412 # largefiles. This will handle identical edits, and copy/rename +
413 # largefiles. This will handle identical edits, and copy/rename +
413 # edit without prompting the user.
414 # edit without prompting the user.
414 def overridefilemerge(origfn, repo, mynode, orig, fcd, fco, fca):
415 def overridefilemerge(origfn, repo, mynode, orig, fcd, fco, fca):
415 # Use better variable names here. Because this is a wrapper we cannot
416 # Use better variable names here. Because this is a wrapper we cannot
416 # change the variable names in the function declaration.
417 # change the variable names in the function declaration.
417 fcdest, fcother, fcancestor = fcd, fco, fca
418 fcdest, fcother, fcancestor = fcd, fco, fca
418 if not lfutil.isstandin(orig):
419 if not lfutil.isstandin(orig):
419 return origfn(repo, mynode, orig, fcdest, fcother, fcancestor)
420 return origfn(repo, mynode, orig, fcdest, fcother, fcancestor)
420 else:
421 else:
421 if not fcother.cmp(fcdest): # files identical?
422 if not fcother.cmp(fcdest): # files identical?
422 return None
423 return None
423
424
424 # backwards, use working dir parent as ancestor
425 # backwards, use working dir parent as ancestor
425 if fcancestor == fcother:
426 if fcancestor == fcother:
426 fcancestor = fcdest.parents()[0]
427 fcancestor = fcdest.parents()[0]
427
428
428 if orig != fcother.path():
429 if orig != fcother.path():
429 repo.ui.status(_('merging %s and %s to %s\n')
430 repo.ui.status(_('merging %s and %s to %s\n')
430 % (lfutil.splitstandin(orig),
431 % (lfutil.splitstandin(orig),
431 lfutil.splitstandin(fcother.path()),
432 lfutil.splitstandin(fcother.path()),
432 lfutil.splitstandin(fcdest.path())))
433 lfutil.splitstandin(fcdest.path())))
433 else:
434 else:
434 repo.ui.status(_('merging %s\n')
435 repo.ui.status(_('merging %s\n')
435 % lfutil.splitstandin(fcdest.path()))
436 % lfutil.splitstandin(fcdest.path()))
436
437
437 if fcancestor.path() != fcother.path() and fcother.data() == \
438 if fcancestor.path() != fcother.path() and fcother.data() == \
438 fcancestor.data():
439 fcancestor.data():
439 return 0
440 return 0
440 if fcancestor.path() != fcdest.path() and fcdest.data() == \
441 if fcancestor.path() != fcdest.path() and fcdest.data() == \
441 fcancestor.data():
442 fcancestor.data():
442 repo.wwrite(fcdest.path(), fcother.data(), fcother.flags())
443 repo.wwrite(fcdest.path(), fcother.data(), fcother.flags())
443 return 0
444 return 0
444
445
445 if repo.ui.promptchoice(_('largefile %s has a merge conflict\n'
446 if repo.ui.promptchoice(_('largefile %s has a merge conflict\n'
446 'keep (l)ocal or take (o)ther?') %
447 'keep (l)ocal or take (o)ther?') %
447 lfutil.splitstandin(orig),
448 lfutil.splitstandin(orig),
448 (_('&Local'), _('&Other')), 0) == 0:
449 (_('&Local'), _('&Other')), 0) == 0:
449 return 0
450 return 0
450 else:
451 else:
451 repo.wwrite(fcdest.path(), fcother.data(), fcother.flags())
452 repo.wwrite(fcdest.path(), fcother.data(), fcother.flags())
452 return 0
453 return 0
453
454
454 # Copy first changes the matchers to match standins instead of
455 # Copy first changes the matchers to match standins instead of
455 # largefiles. Then it overrides util.copyfile in that function it
456 # largefiles. Then it overrides util.copyfile in that function it
456 # checks if the destination largefile already exists. It also keeps a
457 # checks if the destination largefile already exists. It also keeps a
457 # list of copied files so that the largefiles can be copied and the
458 # list of copied files so that the largefiles can be copied and the
458 # dirstate updated.
459 # dirstate updated.
459 def overridecopy(orig, ui, repo, pats, opts, rename=False):
460 def overridecopy(orig, ui, repo, pats, opts, rename=False):
460 # doesn't remove largefile on rename
461 # doesn't remove largefile on rename
461 if len(pats) < 2:
462 if len(pats) < 2:
462 # this isn't legal, let the original function deal with it
463 # this isn't legal, let the original function deal with it
463 return orig(ui, repo, pats, opts, rename)
464 return orig(ui, repo, pats, opts, rename)
464
465
465 def makestandin(relpath):
466 def makestandin(relpath):
466 path = scmutil.canonpath(repo.root, repo.getcwd(), relpath)
467 path = scmutil.canonpath(repo.root, repo.getcwd(), relpath)
467 return os.path.join(repo.wjoin(lfutil.standin(path)))
468 return os.path.join(repo.wjoin(lfutil.standin(path)))
468
469
469 fullpats = scmutil.expandpats(pats)
470 fullpats = scmutil.expandpats(pats)
470 dest = fullpats[-1]
471 dest = fullpats[-1]
471
472
472 if os.path.isdir(dest):
473 if os.path.isdir(dest):
473 if not os.path.isdir(makestandin(dest)):
474 if not os.path.isdir(makestandin(dest)):
474 os.makedirs(makestandin(dest))
475 os.makedirs(makestandin(dest))
475 # This could copy both lfiles and normal files in one command,
476 # This could copy both lfiles and normal files in one command,
476 # but we don't want to do that. First replace their matcher to
477 # but we don't want to do that. First replace their matcher to
477 # only match normal files and run it, then replace it to just
478 # only match normal files and run it, then replace it to just
478 # match largefiles and run it again.
479 # match largefiles and run it again.
479 nonormalfiles = False
480 nonormalfiles = False
480 nolfiles = False
481 nolfiles = False
481 try:
482 try:
482 try:
483 try:
483 installnormalfilesmatchfn(repo[None].manifest())
484 installnormalfilesmatchfn(repo[None].manifest())
484 result = orig(ui, repo, pats, opts, rename)
485 result = orig(ui, repo, pats, opts, rename)
485 except util.Abort, e:
486 except util.Abort, e:
486 if str(e) != _('no files to copy'):
487 if str(e) != _('no files to copy'):
487 raise e
488 raise e
488 else:
489 else:
489 nonormalfiles = True
490 nonormalfiles = True
490 result = 0
491 result = 0
491 finally:
492 finally:
492 restorematchfn()
493 restorematchfn()
493
494
494 # The first rename can cause our current working directory to be removed.
495 # The first rename can cause our current working directory to be removed.
495 # In that case there is nothing left to copy/rename so just quit.
496 # In that case there is nothing left to copy/rename so just quit.
496 try:
497 try:
497 repo.getcwd()
498 repo.getcwd()
498 except OSError:
499 except OSError:
499 return result
500 return result
500
501
501 try:
502 try:
502 try:
503 try:
503 # When we call orig below it creates the standins but we don't add
504 # When we call orig below it creates the standins but we don't add
504 # them to the dir state until later so lock during that time.
505 # them to the dir state until later so lock during that time.
505 wlock = repo.wlock()
506 wlock = repo.wlock()
506
507
507 manifest = repo[None].manifest()
508 manifest = repo[None].manifest()
508 oldmatch = None # for the closure
509 oldmatch = None # for the closure
509 def overridematch(ctx, pats=[], opts={}, globbed=False,
510 def overridematch(ctx, pats=[], opts={}, globbed=False,
510 default='relpath'):
511 default='relpath'):
511 newpats = []
512 newpats = []
512 # The patterns were previously mangled to add the standin
513 # The patterns were previously mangled to add the standin
513 # directory; we need to remove that now
514 # directory; we need to remove that now
514 for pat in pats:
515 for pat in pats:
515 if match_.patkind(pat) is None and lfutil.shortname in pat:
516 if match_.patkind(pat) is None and lfutil.shortname in pat:
516 newpats.append(pat.replace(lfutil.shortname, ''))
517 newpats.append(pat.replace(lfutil.shortname, ''))
517 else:
518 else:
518 newpats.append(pat)
519 newpats.append(pat)
519 match = oldmatch(ctx, newpats, opts, globbed, default)
520 match = oldmatch(ctx, newpats, opts, globbed, default)
520 m = copy.copy(match)
521 m = copy.copy(match)
521 lfile = lambda f: lfutil.standin(f) in manifest
522 lfile = lambda f: lfutil.standin(f) in manifest
522 m._files = [lfutil.standin(f) for f in m._files if lfile(f)]
523 m._files = [lfutil.standin(f) for f in m._files if lfile(f)]
523 m._fmap = set(m._files)
524 m._fmap = set(m._files)
524 m._always = False
525 m._always = False
525 origmatchfn = m.matchfn
526 origmatchfn = m.matchfn
526 m.matchfn = lambda f: (lfutil.isstandin(f) and
527 m.matchfn = lambda f: (lfutil.isstandin(f) and
527 (f in manifest) and
528 (f in manifest) and
528 origmatchfn(lfutil.splitstandin(f)) or
529 origmatchfn(lfutil.splitstandin(f)) or
529 None)
530 None)
530 return m
531 return m
531 oldmatch = installmatchfn(overridematch)
532 oldmatch = installmatchfn(overridematch)
532 listpats = []
533 listpats = []
533 for pat in pats:
534 for pat in pats:
534 if match_.patkind(pat) is not None:
535 if match_.patkind(pat) is not None:
535 listpats.append(pat)
536 listpats.append(pat)
536 else:
537 else:
537 listpats.append(makestandin(pat))
538 listpats.append(makestandin(pat))
538
539
539 try:
540 try:
540 origcopyfile = util.copyfile
541 origcopyfile = util.copyfile
541 copiedfiles = []
542 copiedfiles = []
542 def overridecopyfile(src, dest):
543 def overridecopyfile(src, dest):
543 if (lfutil.shortname in src and
544 if (lfutil.shortname in src and
544 dest.startswith(repo.wjoin(lfutil.shortname))):
545 dest.startswith(repo.wjoin(lfutil.shortname))):
545 destlfile = dest.replace(lfutil.shortname, '')
546 destlfile = dest.replace(lfutil.shortname, '')
546 if not opts['force'] and os.path.exists(destlfile):
547 if not opts['force'] and os.path.exists(destlfile):
547 raise IOError('',
548 raise IOError('',
548 _('destination largefile already exists'))
549 _('destination largefile already exists'))
549 copiedfiles.append((src, dest))
550 copiedfiles.append((src, dest))
550 origcopyfile(src, dest)
551 origcopyfile(src, dest)
551
552
552 util.copyfile = overridecopyfile
553 util.copyfile = overridecopyfile
553 result += orig(ui, repo, listpats, opts, rename)
554 result += orig(ui, repo, listpats, opts, rename)
554 finally:
555 finally:
555 util.copyfile = origcopyfile
556 util.copyfile = origcopyfile
556
557
557 lfdirstate = lfutil.openlfdirstate(ui, repo)
558 lfdirstate = lfutil.openlfdirstate(ui, repo)
558 for (src, dest) in copiedfiles:
559 for (src, dest) in copiedfiles:
559 if (lfutil.shortname in src and
560 if (lfutil.shortname in src and
560 dest.startswith(repo.wjoin(lfutil.shortname))):
561 dest.startswith(repo.wjoin(lfutil.shortname))):
561 srclfile = src.replace(repo.wjoin(lfutil.standin('')), '')
562 srclfile = src.replace(repo.wjoin(lfutil.standin('')), '')
562 destlfile = dest.replace(repo.wjoin(lfutil.standin('')), '')
563 destlfile = dest.replace(repo.wjoin(lfutil.standin('')), '')
563 destlfiledir = os.path.dirname(repo.wjoin(destlfile)) or '.'
564 destlfiledir = os.path.dirname(repo.wjoin(destlfile)) or '.'
564 if not os.path.isdir(destlfiledir):
565 if not os.path.isdir(destlfiledir):
565 os.makedirs(destlfiledir)
566 os.makedirs(destlfiledir)
566 if rename:
567 if rename:
567 os.rename(repo.wjoin(srclfile), repo.wjoin(destlfile))
568 os.rename(repo.wjoin(srclfile), repo.wjoin(destlfile))
568 lfdirstate.remove(srclfile)
569 lfdirstate.remove(srclfile)
569 else:
570 else:
570 util.copyfile(repo.wjoin(srclfile),
571 util.copyfile(repo.wjoin(srclfile),
571 repo.wjoin(destlfile))
572 repo.wjoin(destlfile))
572
573
573 lfdirstate.add(destlfile)
574 lfdirstate.add(destlfile)
574 lfdirstate.write()
575 lfdirstate.write()
575 except util.Abort, e:
576 except util.Abort, e:
576 if str(e) != _('no files to copy'):
577 if str(e) != _('no files to copy'):
577 raise e
578 raise e
578 else:
579 else:
579 nolfiles = True
580 nolfiles = True
580 finally:
581 finally:
581 restorematchfn()
582 restorematchfn()
582 wlock.release()
583 wlock.release()
583
584
584 if nolfiles and nonormalfiles:
585 if nolfiles and nonormalfiles:
585 raise util.Abort(_('no files to copy'))
586 raise util.Abort(_('no files to copy'))
586
587
587 return result
588 return result
588
589
589 # When the user calls revert, we have to be careful to not revert any
590 # When the user calls revert, we have to be careful to not revert any
590 # changes to other largefiles accidentally. This means we have to keep
591 # changes to other largefiles accidentally. This means we have to keep
591 # track of the largefiles that are being reverted so we only pull down
592 # track of the largefiles that are being reverted so we only pull down
592 # the necessary largefiles.
593 # the necessary largefiles.
593 #
594 #
594 # Standins are only updated (to match the hash of largefiles) before
595 # Standins are only updated (to match the hash of largefiles) before
595 # commits. Update the standins then run the original revert, changing
596 # commits. Update the standins then run the original revert, changing
596 # the matcher to hit standins instead of largefiles. Based on the
597 # the matcher to hit standins instead of largefiles. Based on the
597 # resulting standins update the largefiles. Then return the standins
598 # resulting standins update the largefiles. Then return the standins
598 # to their proper state
599 # to their proper state
599 def overriderevert(orig, ui, repo, *pats, **opts):
600 def overriderevert(orig, ui, repo, *pats, **opts):
600 # Because we put the standins in a bad state (by updating them)
601 # Because we put the standins in a bad state (by updating them)
601 # and then return them to a correct state we need to lock to
602 # and then return them to a correct state we need to lock to
602 # prevent others from changing them in their incorrect state.
603 # prevent others from changing them in their incorrect state.
603 wlock = repo.wlock()
604 wlock = repo.wlock()
604 try:
605 try:
605 lfdirstate = lfutil.openlfdirstate(ui, repo)
606 lfdirstate = lfutil.openlfdirstate(ui, repo)
606 (modified, added, removed, missing, unknown, ignored, clean) = \
607 (modified, added, removed, missing, unknown, ignored, clean) = \
607 lfutil.lfdirstatestatus(lfdirstate, repo, repo['.'].rev())
608 lfutil.lfdirstatestatus(lfdirstate, repo, repo['.'].rev())
608 lfdirstate.write()
609 lfdirstate.write()
609 for lfile in modified:
610 for lfile in modified:
610 lfutil.updatestandin(repo, lfutil.standin(lfile))
611 lfutil.updatestandin(repo, lfutil.standin(lfile))
611 for lfile in missing:
612 for lfile in missing:
612 if (os.path.exists(repo.wjoin(lfutil.standin(lfile)))):
613 if (os.path.exists(repo.wjoin(lfutil.standin(lfile)))):
613 os.unlink(repo.wjoin(lfutil.standin(lfile)))
614 os.unlink(repo.wjoin(lfutil.standin(lfile)))
614
615
615 try:
616 try:
616 ctx = scmutil.revsingle(repo, opts.get('rev'))
617 ctx = scmutil.revsingle(repo, opts.get('rev'))
617 oldmatch = None # for the closure
618 oldmatch = None # for the closure
618 def overridematch(ctx, pats=[], opts={}, globbed=False,
619 def overridematch(ctx, pats=[], opts={}, globbed=False,
619 default='relpath'):
620 default='relpath'):
620 match = oldmatch(ctx, pats, opts, globbed, default)
621 match = oldmatch(ctx, pats, opts, globbed, default)
621 m = copy.copy(match)
622 m = copy.copy(match)
622 def tostandin(f):
623 def tostandin(f):
623 if lfutil.standin(f) in ctx:
624 if lfutil.standin(f) in ctx:
624 return lfutil.standin(f)
625 return lfutil.standin(f)
625 elif lfutil.standin(f) in repo[None]:
626 elif lfutil.standin(f) in repo[None]:
626 return None
627 return None
627 return f
628 return f
628 m._files = [tostandin(f) for f in m._files]
629 m._files = [tostandin(f) for f in m._files]
629 m._files = [f for f in m._files if f is not None]
630 m._files = [f for f in m._files if f is not None]
630 m._fmap = set(m._files)
631 m._fmap = set(m._files)
631 m._always = False
632 m._always = False
632 origmatchfn = m.matchfn
633 origmatchfn = m.matchfn
633 def matchfn(f):
634 def matchfn(f):
634 if lfutil.isstandin(f):
635 if lfutil.isstandin(f):
635 # We need to keep track of what largefiles are being
636 # We need to keep track of what largefiles are being
636 # matched so we know which ones to update later --
637 # matched so we know which ones to update later --
637 # otherwise we accidentally revert changes to other
638 # otherwise we accidentally revert changes to other
638 # largefiles. This is repo-specific, so duckpunch the
639 # largefiles. This is repo-specific, so duckpunch the
639 # repo object to keep the list of largefiles for us
640 # repo object to keep the list of largefiles for us
640 # later.
641 # later.
641 if origmatchfn(lfutil.splitstandin(f)) and \
642 if origmatchfn(lfutil.splitstandin(f)) and \
642 (f in repo[None] or f in ctx):
643 (f in repo[None] or f in ctx):
643 lfileslist = getattr(repo, '_lfilestoupdate', [])
644 lfileslist = getattr(repo, '_lfilestoupdate', [])
644 lfileslist.append(lfutil.splitstandin(f))
645 lfileslist.append(lfutil.splitstandin(f))
645 repo._lfilestoupdate = lfileslist
646 repo._lfilestoupdate = lfileslist
646 return True
647 return True
647 else:
648 else:
648 return False
649 return False
649 return origmatchfn(f)
650 return origmatchfn(f)
650 m.matchfn = matchfn
651 m.matchfn = matchfn
651 return m
652 return m
652 oldmatch = installmatchfn(overridematch)
653 oldmatch = installmatchfn(overridematch)
653 scmutil.match
654 scmutil.match
654 matches = overridematch(repo[None], pats, opts)
655 matches = overridematch(repo[None], pats, opts)
655 orig(ui, repo, *pats, **opts)
656 orig(ui, repo, *pats, **opts)
656 finally:
657 finally:
657 restorematchfn()
658 restorematchfn()
658 lfileslist = getattr(repo, '_lfilestoupdate', [])
659 lfileslist = getattr(repo, '_lfilestoupdate', [])
659 lfcommands.updatelfiles(ui, repo, filelist=lfileslist,
660 lfcommands.updatelfiles(ui, repo, filelist=lfileslist,
660 printmessage=False)
661 printmessage=False)
661
662
662 # empty out the largefiles list so we start fresh next time
663 # empty out the largefiles list so we start fresh next time
663 repo._lfilestoupdate = []
664 repo._lfilestoupdate = []
664 for lfile in modified:
665 for lfile in modified:
665 if lfile in lfileslist:
666 if lfile in lfileslist:
666 if os.path.exists(repo.wjoin(lfutil.standin(lfile))) and lfile\
667 if os.path.exists(repo.wjoin(lfutil.standin(lfile))) and lfile\
667 in repo['.']:
668 in repo['.']:
668 lfutil.writestandin(repo, lfutil.standin(lfile),
669 lfutil.writestandin(repo, lfutil.standin(lfile),
669 repo['.'][lfile].data().strip(),
670 repo['.'][lfile].data().strip(),
670 'x' in repo['.'][lfile].flags())
671 'x' in repo['.'][lfile].flags())
671 lfdirstate = lfutil.openlfdirstate(ui, repo)
672 lfdirstate = lfutil.openlfdirstate(ui, repo)
672 for lfile in added:
673 for lfile in added:
673 standin = lfutil.standin(lfile)
674 standin = lfutil.standin(lfile)
674 if standin not in ctx and (standin in matches or opts.get('all')):
675 if standin not in ctx and (standin in matches or opts.get('all')):
675 if lfile in lfdirstate:
676 if lfile in lfdirstate:
676 lfdirstate.drop(lfile)
677 lfdirstate.drop(lfile)
677 util.unlinkpath(repo.wjoin(standin))
678 util.unlinkpath(repo.wjoin(standin))
678 lfdirstate.write()
679 lfdirstate.write()
679 finally:
680 finally:
680 wlock.release()
681 wlock.release()
681
682
682 def hgupdaterepo(orig, repo, node, overwrite):
683 def hgupdaterepo(orig, repo, node, overwrite):
683 if not overwrite:
684 if not overwrite:
684 # Only call updatelfiles on the standins that have changed to save time
685 # Only call updatelfiles on the standins that have changed to save time
685 oldstandins = lfutil.getstandinsstate(repo)
686 oldstandins = lfutil.getstandinsstate(repo)
686
687
687 result = orig(repo, node, overwrite)
688 result = orig(repo, node, overwrite)
688
689
689 filelist = None
690 filelist = None
690 if not overwrite:
691 if not overwrite:
691 newstandins = lfutil.getstandinsstate(repo)
692 newstandins = lfutil.getstandinsstate(repo)
692 filelist = lfutil.getlfilestoupdate(oldstandins, newstandins)
693 filelist = lfutil.getlfilestoupdate(oldstandins, newstandins)
693 lfcommands.updatelfiles(repo.ui, repo, filelist=filelist)
694 lfcommands.updatelfiles(repo.ui, repo, filelist=filelist)
694 return result
695 return result
695
696
696 def hgmerge(orig, repo, node, force=None, remind=True):
697 def hgmerge(orig, repo, node, force=None, remind=True):
697 result = orig(repo, node, force, remind)
698 result = orig(repo, node, force, remind)
698 lfcommands.updatelfiles(repo.ui, repo)
699 lfcommands.updatelfiles(repo.ui, repo)
699 return result
700 return result
700
701
701 # When we rebase a repository with remotely changed largefiles, we need to
702 # When we rebase a repository with remotely changed largefiles, we need to
702 # take some extra care so that the largefiles are correctly updated in the
703 # take some extra care so that the largefiles are correctly updated in the
703 # working copy
704 # working copy
704 def overridepull(orig, ui, repo, source=None, **opts):
705 def overridepull(orig, ui, repo, source=None, **opts):
705 revsprepull = len(repo)
706 revsprepull = len(repo)
706 if opts.get('rebase', False):
707 if opts.get('rebase', False):
707 repo._isrebasing = True
708 repo._isrebasing = True
708 try:
709 try:
709 if opts.get('update'):
710 if opts.get('update'):
710 del opts['update']
711 del opts['update']
711 ui.debug('--update and --rebase are not compatible, ignoring '
712 ui.debug('--update and --rebase are not compatible, ignoring '
712 'the update flag\n')
713 'the update flag\n')
713 del opts['rebase']
714 del opts['rebase']
714 cmdutil.bailifchanged(repo)
715 cmdutil.bailifchanged(repo)
715 origpostincoming = commands.postincoming
716 origpostincoming = commands.postincoming
716 def _dummy(*args, **kwargs):
717 def _dummy(*args, **kwargs):
717 pass
718 pass
718 commands.postincoming = _dummy
719 commands.postincoming = _dummy
719 if not source:
720 if not source:
720 source = 'default'
721 source = 'default'
721 repo.lfpullsource = source
722 repo.lfpullsource = source
722 try:
723 try:
723 result = commands.pull(ui, repo, source, **opts)
724 result = commands.pull(ui, repo, source, **opts)
724 finally:
725 finally:
725 commands.postincoming = origpostincoming
726 commands.postincoming = origpostincoming
726 revspostpull = len(repo)
727 revspostpull = len(repo)
727 if revspostpull > revsprepull:
728 if revspostpull > revsprepull:
728 result = result or rebase.rebase(ui, repo)
729 result = result or rebase.rebase(ui, repo)
729 finally:
730 finally:
730 repo._isrebasing = False
731 repo._isrebasing = False
731 else:
732 else:
732 if not source:
733 if not source:
733 source = 'default'
734 source = 'default'
734 repo.lfpullsource = source
735 repo.lfpullsource = source
735 oldheads = lfutil.getcurrentheads(repo)
736 oldheads = lfutil.getcurrentheads(repo)
736 result = orig(ui, repo, source, **opts)
737 result = orig(ui, repo, source, **opts)
737 if opts.get('cache_largefiles'):
738 if opts.get('cache_largefiles'):
738 # If you are pulling from a remote location that is not your
739 # If you are pulling from a remote location that is not your
739 # default location, you may want to cache largefiles for new heads
740 # default location, you may want to cache largefiles for new heads
740 # that have been pulled, so you can easily merge or rebase with
741 # that have been pulled, so you can easily merge or rebase with
741 # them later
742 # them later
742 numcached = 0
743 numcached = 0
743 heads = lfutil.getcurrentheads(repo)
744 heads = lfutil.getcurrentheads(repo)
744 newheads = set(heads).difference(set(oldheads))
745 newheads = set(heads).difference(set(oldheads))
745 if len(newheads) > 0:
746 if len(newheads) > 0:
746 ui.status(_("caching largefiles for %s heads\n") %
747 ui.status(_("caching largefiles for %s heads\n") %
747 len(newheads))
748 len(newheads))
748 for head in newheads:
749 for head in newheads:
749 (cached, missing) = lfcommands.cachelfiles(ui, repo, head)
750 (cached, missing) = lfcommands.cachelfiles(ui, repo, head)
750 numcached += len(cached)
751 numcached += len(cached)
751 ui.status(_("%d largefiles cached\n") % numcached)
752 ui.status(_("%d largefiles cached\n") % numcached)
752 if opts.get('all_largefiles'):
753 if opts.get('all_largefiles'):
753 revspostpull = len(repo)
754 revspostpull = len(repo)
754 revs = []
755 revs = []
755 for rev in xrange(revsprepull, revspostpull):
756 for rev in xrange(revsprepull, revspostpull):
756 revs.append(repo[rev].rev())
757 revs.append(repo[rev].rev())
757 lfcommands.downloadlfiles(ui, repo, revs)
758 lfcommands.downloadlfiles(ui, repo, revs)
758 return result
759 return result
759
760
760 def overrideclone(orig, ui, source, dest=None, **opts):
761 def overrideclone(orig, ui, source, dest=None, **opts):
761 d = dest
762 d = dest
762 if d is None:
763 if d is None:
763 d = hg.defaultdest(source)
764 d = hg.defaultdest(source)
764 if opts.get('all_largefiles') and not hg.islocal(d):
765 if opts.get('all_largefiles') and not hg.islocal(d):
765 raise util.Abort(_(
766 raise util.Abort(_(
766 '--all-largefiles is incompatible with non-local destination %s' %
767 '--all-largefiles is incompatible with non-local destination %s' %
767 d))
768 d))
768
769
769 return orig(ui, source, dest, **opts)
770 return orig(ui, source, dest, **opts)
770
771
771 def hgclone(orig, ui, opts, *args, **kwargs):
772 def hgclone(orig, ui, opts, *args, **kwargs):
772 result = orig(ui, opts, *args, **kwargs)
773 result = orig(ui, opts, *args, **kwargs)
773
774
774 if result is not None:
775 if result is not None:
775 sourcerepo, destrepo = result
776 sourcerepo, destrepo = result
776 repo = destrepo.local()
777 repo = destrepo.local()
777
778
778 # Caching is implicitly limited to 'rev' option, since the dest repo was
779 # Caching is implicitly limited to 'rev' option, since the dest repo was
779 # truncated at that point. The user may expect a download count with
780 # truncated at that point. The user may expect a download count with
780 # this option, so attempt whether or not this is a largefile repo.
781 # this option, so attempt whether or not this is a largefile repo.
781 if opts.get('all_largefiles'):
782 if opts.get('all_largefiles'):
782 success, missing = lfcommands.downloadlfiles(ui, repo, None)
783 success, missing = lfcommands.downloadlfiles(ui, repo, None)
783
784
784 if missing != 0:
785 if missing != 0:
785 return None
786 return None
786
787
787 return result
788 return result
788
789
789 def overriderebase(orig, ui, repo, **opts):
790 def overriderebase(orig, ui, repo, **opts):
790 repo._isrebasing = True
791 repo._isrebasing = True
791 try:
792 try:
792 return orig(ui, repo, **opts)
793 return orig(ui, repo, **opts)
793 finally:
794 finally:
794 repo._isrebasing = False
795 repo._isrebasing = False
795
796
796 def overridearchive(orig, repo, dest, node, kind, decode=True, matchfn=None,
797 def overridearchive(orig, repo, dest, node, kind, decode=True, matchfn=None,
797 prefix=None, mtime=None, subrepos=None):
798 prefix=None, mtime=None, subrepos=None):
798 # No need to lock because we are only reading history and
799 # No need to lock because we are only reading history and
799 # largefile caches, neither of which are modified.
800 # largefile caches, neither of which are modified.
800 lfcommands.cachelfiles(repo.ui, repo, node)
801 lfcommands.cachelfiles(repo.ui, repo, node)
801
802
802 if kind not in archival.archivers:
803 if kind not in archival.archivers:
803 raise util.Abort(_("unknown archive type '%s'") % kind)
804 raise util.Abort(_("unknown archive type '%s'") % kind)
804
805
805 ctx = repo[node]
806 ctx = repo[node]
806
807
807 if kind == 'files':
808 if kind == 'files':
808 if prefix:
809 if prefix:
809 raise util.Abort(
810 raise util.Abort(
810 _('cannot give prefix when archiving to files'))
811 _('cannot give prefix when archiving to files'))
811 else:
812 else:
812 prefix = archival.tidyprefix(dest, kind, prefix)
813 prefix = archival.tidyprefix(dest, kind, prefix)
813
814
814 def write(name, mode, islink, getdata):
815 def write(name, mode, islink, getdata):
815 if matchfn and not matchfn(name):
816 if matchfn and not matchfn(name):
816 return
817 return
817 data = getdata()
818 data = getdata()
818 if decode:
819 if decode:
819 data = repo.wwritedata(name, data)
820 data = repo.wwritedata(name, data)
820 archiver.addfile(prefix + name, mode, islink, data)
821 archiver.addfile(prefix + name, mode, islink, data)
821
822
822 archiver = archival.archivers[kind](dest, mtime or ctx.date()[0])
823 archiver = archival.archivers[kind](dest, mtime or ctx.date()[0])
823
824
824 if repo.ui.configbool("ui", "archivemeta", True):
825 if repo.ui.configbool("ui", "archivemeta", True):
825 def metadata():
826 def metadata():
826 base = 'repo: %s\nnode: %s\nbranch: %s\n' % (
827 base = 'repo: %s\nnode: %s\nbranch: %s\n' % (
827 hex(repo.changelog.node(0)), hex(node), ctx.branch())
828 hex(repo.changelog.node(0)), hex(node), ctx.branch())
828
829
829 tags = ''.join('tag: %s\n' % t for t in ctx.tags()
830 tags = ''.join('tag: %s\n' % t for t in ctx.tags()
830 if repo.tagtype(t) == 'global')
831 if repo.tagtype(t) == 'global')
831 if not tags:
832 if not tags:
832 repo.ui.pushbuffer()
833 repo.ui.pushbuffer()
833 opts = {'template': '{latesttag}\n{latesttagdistance}',
834 opts = {'template': '{latesttag}\n{latesttagdistance}',
834 'style': '', 'patch': None, 'git': None}
835 'style': '', 'patch': None, 'git': None}
835 cmdutil.show_changeset(repo.ui, repo, opts).show(ctx)
836 cmdutil.show_changeset(repo.ui, repo, opts).show(ctx)
836 ltags, dist = repo.ui.popbuffer().split('\n')
837 ltags, dist = repo.ui.popbuffer().split('\n')
837 tags = ''.join('latesttag: %s\n' % t for t in ltags.split(':'))
838 tags = ''.join('latesttag: %s\n' % t for t in ltags.split(':'))
838 tags += 'latesttagdistance: %s\n' % dist
839 tags += 'latesttagdistance: %s\n' % dist
839
840
840 return base + tags
841 return base + tags
841
842
842 write('.hg_archival.txt', 0644, False, metadata)
843 write('.hg_archival.txt', 0644, False, metadata)
843
844
844 for f in ctx:
845 for f in ctx:
845 ff = ctx.flags(f)
846 ff = ctx.flags(f)
846 getdata = ctx[f].data
847 getdata = ctx[f].data
847 if lfutil.isstandin(f):
848 if lfutil.isstandin(f):
848 path = lfutil.findfile(repo, getdata().strip())
849 path = lfutil.findfile(repo, getdata().strip())
849 if path is None:
850 if path is None:
850 raise util.Abort(
851 raise util.Abort(
851 _('largefile %s not found in repo store or system cache')
852 _('largefile %s not found in repo store or system cache')
852 % lfutil.splitstandin(f))
853 % lfutil.splitstandin(f))
853 f = lfutil.splitstandin(f)
854 f = lfutil.splitstandin(f)
854
855
855 def getdatafn():
856 def getdatafn():
856 fd = None
857 fd = None
857 try:
858 try:
858 fd = open(path, 'rb')
859 fd = open(path, 'rb')
859 return fd.read()
860 return fd.read()
860 finally:
861 finally:
861 if fd:
862 if fd:
862 fd.close()
863 fd.close()
863
864
864 getdata = getdatafn
865 getdata = getdatafn
865 write(f, 'x' in ff and 0755 or 0644, 'l' in ff, getdata)
866 write(f, 'x' in ff and 0755 or 0644, 'l' in ff, getdata)
866
867
867 if subrepos:
868 if subrepos:
868 for subpath in sorted(ctx.substate):
869 for subpath in sorted(ctx.substate):
869 sub = ctx.sub(subpath)
870 sub = ctx.sub(subpath)
870 submatch = match_.narrowmatcher(subpath, matchfn)
871 submatch = match_.narrowmatcher(subpath, matchfn)
871 sub.archive(repo.ui, archiver, prefix, submatch)
872 sub.archive(repo.ui, archiver, prefix, submatch)
872
873
873 archiver.done()
874 archiver.done()
874
875
875 def hgsubrepoarchive(orig, repo, ui, archiver, prefix, match=None):
876 def hgsubrepoarchive(orig, repo, ui, archiver, prefix, match=None):
876 repo._get(repo._state + ('hg',))
877 repo._get(repo._state + ('hg',))
877 rev = repo._state[1]
878 rev = repo._state[1]
878 ctx = repo._repo[rev]
879 ctx = repo._repo[rev]
879
880
880 lfcommands.cachelfiles(ui, repo._repo, ctx.node())
881 lfcommands.cachelfiles(ui, repo._repo, ctx.node())
881
882
882 def write(name, mode, islink, getdata):
883 def write(name, mode, islink, getdata):
883 # At this point, the standin has been replaced with the largefile name,
884 # At this point, the standin has been replaced with the largefile name,
884 # so the normal matcher works here without the lfutil variants.
885 # so the normal matcher works here without the lfutil variants.
885 if match and not match(f):
886 if match and not match(f):
886 return
887 return
887 data = getdata()
888 data = getdata()
888
889
889 archiver.addfile(prefix + repo._path + '/' + name, mode, islink, data)
890 archiver.addfile(prefix + repo._path + '/' + name, mode, islink, data)
890
891
891 for f in ctx:
892 for f in ctx:
892 ff = ctx.flags(f)
893 ff = ctx.flags(f)
893 getdata = ctx[f].data
894 getdata = ctx[f].data
894 if lfutil.isstandin(f):
895 if lfutil.isstandin(f):
895 path = lfutil.findfile(repo._repo, getdata().strip())
896 path = lfutil.findfile(repo._repo, getdata().strip())
896 if path is None:
897 if path is None:
897 raise util.Abort(
898 raise util.Abort(
898 _('largefile %s not found in repo store or system cache')
899 _('largefile %s not found in repo store or system cache')
899 % lfutil.splitstandin(f))
900 % lfutil.splitstandin(f))
900 f = lfutil.splitstandin(f)
901 f = lfutil.splitstandin(f)
901
902
902 def getdatafn():
903 def getdatafn():
903 fd = None
904 fd = None
904 try:
905 try:
905 fd = open(os.path.join(prefix, path), 'rb')
906 fd = open(os.path.join(prefix, path), 'rb')
906 return fd.read()
907 return fd.read()
907 finally:
908 finally:
908 if fd:
909 if fd:
909 fd.close()
910 fd.close()
910
911
911 getdata = getdatafn
912 getdata = getdatafn
912
913
913 write(f, 'x' in ff and 0755 or 0644, 'l' in ff, getdata)
914 write(f, 'x' in ff and 0755 or 0644, 'l' in ff, getdata)
914
915
915 for subpath in sorted(ctx.substate):
916 for subpath in sorted(ctx.substate):
916 sub = ctx.sub(subpath)
917 sub = ctx.sub(subpath)
917 submatch = match_.narrowmatcher(subpath, match)
918 submatch = match_.narrowmatcher(subpath, match)
918 sub.archive(ui, archiver, os.path.join(prefix, repo._path) + '/',
919 sub.archive(ui, archiver, os.path.join(prefix, repo._path) + '/',
919 submatch)
920 submatch)
920
921
921 # If a largefile is modified, the change is not reflected in its
922 # If a largefile is modified, the change is not reflected in its
922 # standin until a commit. cmdutil.bailifchanged() raises an exception
923 # standin until a commit. cmdutil.bailifchanged() raises an exception
923 # if the repo has uncommitted changes. Wrap it to also check if
924 # if the repo has uncommitted changes. Wrap it to also check if
924 # largefiles were changed. This is used by bisect and backout.
925 # largefiles were changed. This is used by bisect and backout.
925 def overridebailifchanged(orig, repo):
926 def overridebailifchanged(orig, repo):
926 orig(repo)
927 orig(repo)
927 repo.lfstatus = True
928 repo.lfstatus = True
928 modified, added, removed, deleted = repo.status()[:4]
929 modified, added, removed, deleted = repo.status()[:4]
929 repo.lfstatus = False
930 repo.lfstatus = False
930 if modified or added or removed or deleted:
931 if modified or added or removed or deleted:
931 raise util.Abort(_('outstanding uncommitted changes'))
932 raise util.Abort(_('outstanding uncommitted changes'))
932
933
933 # Fetch doesn't use cmdutil.bailifchanged so override it to add the check
934 # Fetch doesn't use cmdutil.bailifchanged so override it to add the check
934 def overridefetch(orig, ui, repo, *pats, **opts):
935 def overridefetch(orig, ui, repo, *pats, **opts):
935 repo.lfstatus = True
936 repo.lfstatus = True
936 modified, added, removed, deleted = repo.status()[:4]
937 modified, added, removed, deleted = repo.status()[:4]
937 repo.lfstatus = False
938 repo.lfstatus = False
938 if modified or added or removed or deleted:
939 if modified or added or removed or deleted:
939 raise util.Abort(_('outstanding uncommitted changes'))
940 raise util.Abort(_('outstanding uncommitted changes'))
940 return orig(ui, repo, *pats, **opts)
941 return orig(ui, repo, *pats, **opts)
941
942
942 def overrideforget(orig, ui, repo, *pats, **opts):
943 def overrideforget(orig, ui, repo, *pats, **opts):
943 installnormalfilesmatchfn(repo[None].manifest())
944 installnormalfilesmatchfn(repo[None].manifest())
944 result = orig(ui, repo, *pats, **opts)
945 result = orig(ui, repo, *pats, **opts)
945 restorematchfn()
946 restorematchfn()
946 m = scmutil.match(repo[None], pats, opts)
947 m = scmutil.match(repo[None], pats, opts)
947
948
948 try:
949 try:
949 repo.lfstatus = True
950 repo.lfstatus = True
950 s = repo.status(match=m, clean=True)
951 s = repo.status(match=m, clean=True)
951 finally:
952 finally:
952 repo.lfstatus = False
953 repo.lfstatus = False
953 forget = sorted(s[0] + s[1] + s[3] + s[6])
954 forget = sorted(s[0] + s[1] + s[3] + s[6])
954 forget = [f for f in forget if lfutil.standin(f) in repo[None].manifest()]
955 forget = [f for f in forget if lfutil.standin(f) in repo[None].manifest()]
955
956
956 for f in forget:
957 for f in forget:
957 if lfutil.standin(f) not in repo.dirstate and not \
958 if lfutil.standin(f) not in repo.dirstate and not \
958 os.path.isdir(m.rel(lfutil.standin(f))):
959 os.path.isdir(m.rel(lfutil.standin(f))):
959 ui.warn(_('not removing %s: file is already untracked\n')
960 ui.warn(_('not removing %s: file is already untracked\n')
960 % m.rel(f))
961 % m.rel(f))
961 result = 1
962 result = 1
962
963
963 for f in forget:
964 for f in forget:
964 if ui.verbose or not m.exact(f):
965 if ui.verbose or not m.exact(f):
965 ui.status(_('removing %s\n') % m.rel(f))
966 ui.status(_('removing %s\n') % m.rel(f))
966
967
967 # Need to lock because standin files are deleted then removed from the
968 # Need to lock because standin files are deleted then removed from the
968 # repository and we could race in-between.
969 # repository and we could race in-between.
969 wlock = repo.wlock()
970 wlock = repo.wlock()
970 try:
971 try:
971 lfdirstate = lfutil.openlfdirstate(ui, repo)
972 lfdirstate = lfutil.openlfdirstate(ui, repo)
972 for f in forget:
973 for f in forget:
973 if lfdirstate[f] == 'a':
974 if lfdirstate[f] == 'a':
974 lfdirstate.drop(f)
975 lfdirstate.drop(f)
975 else:
976 else:
976 lfdirstate.remove(f)
977 lfdirstate.remove(f)
977 lfdirstate.write()
978 lfdirstate.write()
978 standins = [lfutil.standin(f) for f in forget]
979 standins = [lfutil.standin(f) for f in forget]
979 for f in standins:
980 for f in standins:
980 util.unlinkpath(repo.wjoin(f), ignoremissing=True)
981 util.unlinkpath(repo.wjoin(f), ignoremissing=True)
981 repo[None].forget(standins)
982 repo[None].forget(standins)
982 finally:
983 finally:
983 wlock.release()
984 wlock.release()
984
985
985 return result
986 return result
986
987
987 def getoutgoinglfiles(ui, repo, dest=None, **opts):
988 def getoutgoinglfiles(ui, repo, dest=None, **opts):
988 dest = ui.expandpath(dest or 'default-push', dest or 'default')
989 dest = ui.expandpath(dest or 'default-push', dest or 'default')
989 dest, branches = hg.parseurl(dest, opts.get('branch'))
990 dest, branches = hg.parseurl(dest, opts.get('branch'))
990 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
991 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
991 if revs:
992 if revs:
992 revs = [repo.lookup(rev) for rev in scmutil.revrange(repo, revs)]
993 revs = [repo.lookup(rev) for rev in scmutil.revrange(repo, revs)]
993
994
994 try:
995 try:
995 remote = hg.peer(repo, opts, dest)
996 remote = hg.peer(repo, opts, dest)
996 except error.RepoError:
997 except error.RepoError:
997 return None
998 return None
998 outgoing = discovery.findcommonoutgoing(repo, remote.peer(), force=False)
999 outgoing = discovery.findcommonoutgoing(repo, remote.peer(), force=False)
999 if not outgoing.missing:
1000 if not outgoing.missing:
1000 return outgoing.missing
1001 return outgoing.missing
1001 o = repo.changelog.nodesbetween(outgoing.missing, revs)[0]
1002 o = repo.changelog.nodesbetween(outgoing.missing, revs)[0]
1002 if opts.get('newest_first'):
1003 if opts.get('newest_first'):
1003 o.reverse()
1004 o.reverse()
1004
1005
1005 toupload = set()
1006 toupload = set()
1006 for n in o:
1007 for n in o:
1007 parents = [p for p in repo.changelog.parents(n) if p != node.nullid]
1008 parents = [p for p in repo.changelog.parents(n) if p != node.nullid]
1008 ctx = repo[n]
1009 ctx = repo[n]
1009 files = set(ctx.files())
1010 files = set(ctx.files())
1010 if len(parents) == 2:
1011 if len(parents) == 2:
1011 mc = ctx.manifest()
1012 mc = ctx.manifest()
1012 mp1 = ctx.parents()[0].manifest()
1013 mp1 = ctx.parents()[0].manifest()
1013 mp2 = ctx.parents()[1].manifest()
1014 mp2 = ctx.parents()[1].manifest()
1014 for f in mp1:
1015 for f in mp1:
1015 if f not in mc:
1016 if f not in mc:
1016 files.add(f)
1017 files.add(f)
1017 for f in mp2:
1018 for f in mp2:
1018 if f not in mc:
1019 if f not in mc:
1019 files.add(f)
1020 files.add(f)
1020 for f in mc:
1021 for f in mc:
1021 if mc[f] != mp1.get(f, None) or mc[f] != mp2.get(f, None):
1022 if mc[f] != mp1.get(f, None) or mc[f] != mp2.get(f, None):
1022 files.add(f)
1023 files.add(f)
1023 toupload = toupload.union(
1024 toupload = toupload.union(
1024 set([f for f in files if lfutil.isstandin(f) and f in ctx]))
1025 set([f for f in files if lfutil.isstandin(f) and f in ctx]))
1025 return sorted(toupload)
1026 return sorted(toupload)
1026
1027
1027 def overrideoutgoing(orig, ui, repo, dest=None, **opts):
1028 def overrideoutgoing(orig, ui, repo, dest=None, **opts):
1028 result = orig(ui, repo, dest, **opts)
1029 result = orig(ui, repo, dest, **opts)
1029
1030
1030 if opts.pop('large', None):
1031 if opts.pop('large', None):
1031 toupload = getoutgoinglfiles(ui, repo, dest, **opts)
1032 toupload = getoutgoinglfiles(ui, repo, dest, **opts)
1032 if toupload is None:
1033 if toupload is None:
1033 ui.status(_('largefiles: No remote repo\n'))
1034 ui.status(_('largefiles: No remote repo\n'))
1034 elif not toupload:
1035 elif not toupload:
1035 ui.status(_('largefiles: no files to upload\n'))
1036 ui.status(_('largefiles: no files to upload\n'))
1036 else:
1037 else:
1037 ui.status(_('largefiles to upload:\n'))
1038 ui.status(_('largefiles to upload:\n'))
1038 for file in toupload:
1039 for file in toupload:
1039 ui.status(lfutil.splitstandin(file) + '\n')
1040 ui.status(lfutil.splitstandin(file) + '\n')
1040 ui.status('\n')
1041 ui.status('\n')
1041
1042
1042 return result
1043 return result
1043
1044
1044 def overridesummary(orig, ui, repo, *pats, **opts):
1045 def overridesummary(orig, ui, repo, *pats, **opts):
1045 try:
1046 try:
1046 repo.lfstatus = True
1047 repo.lfstatus = True
1047 orig(ui, repo, *pats, **opts)
1048 orig(ui, repo, *pats, **opts)
1048 finally:
1049 finally:
1049 repo.lfstatus = False
1050 repo.lfstatus = False
1050
1051
1051 if opts.pop('large', None):
1052 if opts.pop('large', None):
1052 toupload = getoutgoinglfiles(ui, repo, None, **opts)
1053 toupload = getoutgoinglfiles(ui, repo, None, **opts)
1053 if toupload is None:
1054 if toupload is None:
1054 # i18n: column positioning for "hg summary"
1055 # i18n: column positioning for "hg summary"
1055 ui.status(_('largefiles: (no remote repo)\n'))
1056 ui.status(_('largefiles: (no remote repo)\n'))
1056 elif not toupload:
1057 elif not toupload:
1057 # i18n: column positioning for "hg summary"
1058 # i18n: column positioning for "hg summary"
1058 ui.status(_('largefiles: (no files to upload)\n'))
1059 ui.status(_('largefiles: (no files to upload)\n'))
1059 else:
1060 else:
1060 # i18n: column positioning for "hg summary"
1061 # i18n: column positioning for "hg summary"
1061 ui.status(_('largefiles: %d to upload\n') % len(toupload))
1062 ui.status(_('largefiles: %d to upload\n') % len(toupload))
1062
1063
1063 def scmutiladdremove(orig, repo, pats=[], opts={}, dry_run=None,
1064 def scmutiladdremove(orig, repo, pats=[], opts={}, dry_run=None,
1064 similarity=None):
1065 similarity=None):
1065 if not lfutil.islfilesrepo(repo):
1066 if not lfutil.islfilesrepo(repo):
1066 return orig(repo, pats, opts, dry_run, similarity)
1067 return orig(repo, pats, opts, dry_run, similarity)
1067 # Get the list of missing largefiles so we can remove them
1068 # Get the list of missing largefiles so we can remove them
1068 lfdirstate = lfutil.openlfdirstate(repo.ui, repo)
1069 lfdirstate = lfutil.openlfdirstate(repo.ui, repo)
1069 s = lfdirstate.status(match_.always(repo.root, repo.getcwd()), [], False,
1070 s = lfdirstate.status(match_.always(repo.root, repo.getcwd()), [], False,
1070 False, False)
1071 False, False)
1071 (unsure, modified, added, removed, missing, unknown, ignored, clean) = s
1072 (unsure, modified, added, removed, missing, unknown, ignored, clean) = s
1072
1073
1073 # Call into the normal remove code, but the removing of the standin, we want
1074 # Call into the normal remove code, but the removing of the standin, we want
1074 # to have handled by original addremove. Monkey patching here makes sure
1075 # to have handled by original addremove. Monkey patching here makes sure
1075 # we don't remove the standin in the largefiles code, preventing a very
1076 # we don't remove the standin in the largefiles code, preventing a very
1076 # confused state later.
1077 # confused state later.
1077 if missing:
1078 if missing:
1078 m = [repo.wjoin(f) for f in missing]
1079 m = [repo.wjoin(f) for f in missing]
1079 repo._isaddremove = True
1080 repo._isaddremove = True
1080 removelargefiles(repo.ui, repo, *m, **opts)
1081 removelargefiles(repo.ui, repo, *m, **opts)
1081 repo._isaddremove = False
1082 repo._isaddremove = False
1082 # Call into the normal add code, and any files that *should* be added as
1083 # Call into the normal add code, and any files that *should* be added as
1083 # largefiles will be
1084 # largefiles will be
1084 addlargefiles(repo.ui, repo, *pats, **opts)
1085 addlargefiles(repo.ui, repo, *pats, **opts)
1085 # Now that we've handled largefiles, hand off to the original addremove
1086 # Now that we've handled largefiles, hand off to the original addremove
1086 # function to take care of the rest. Make sure it doesn't do anything with
1087 # function to take care of the rest. Make sure it doesn't do anything with
1087 # largefiles by installing a matcher that will ignore them.
1088 # largefiles by installing a matcher that will ignore them.
1088 installnormalfilesmatchfn(repo[None].manifest())
1089 installnormalfilesmatchfn(repo[None].manifest())
1089 result = orig(repo, pats, opts, dry_run, similarity)
1090 result = orig(repo, pats, opts, dry_run, similarity)
1090 restorematchfn()
1091 restorematchfn()
1091 return result
1092 return result
1092
1093
1093 # Calling purge with --all will cause the largefiles to be deleted.
1094 # Calling purge with --all will cause the largefiles to be deleted.
1094 # Override repo.status to prevent this from happening.
1095 # Override repo.status to prevent this from happening.
1095 def overridepurge(orig, ui, repo, *dirs, **opts):
1096 def overridepurge(orig, ui, repo, *dirs, **opts):
1096 # XXX large file status is buggy when used on repo proxy.
1097 # XXX large file status is buggy when used on repo proxy.
1097 # XXX this needs to be investigate.
1098 # XXX this needs to be investigate.
1098 repo = repo.unfiltered()
1099 repo = repo.unfiltered()
1099 oldstatus = repo.status
1100 oldstatus = repo.status
1100 def overridestatus(node1='.', node2=None, match=None, ignored=False,
1101 def overridestatus(node1='.', node2=None, match=None, ignored=False,
1101 clean=False, unknown=False, listsubrepos=False):
1102 clean=False, unknown=False, listsubrepos=False):
1102 r = oldstatus(node1, node2, match, ignored, clean, unknown,
1103 r = oldstatus(node1, node2, match, ignored, clean, unknown,
1103 listsubrepos)
1104 listsubrepos)
1104 lfdirstate = lfutil.openlfdirstate(ui, repo)
1105 lfdirstate = lfutil.openlfdirstate(ui, repo)
1105 modified, added, removed, deleted, unknown, ignored, clean = r
1106 modified, added, removed, deleted, unknown, ignored, clean = r
1106 unknown = [f for f in unknown if lfdirstate[f] == '?']
1107 unknown = [f for f in unknown if lfdirstate[f] == '?']
1107 ignored = [f for f in ignored if lfdirstate[f] == '?']
1108 ignored = [f for f in ignored if lfdirstate[f] == '?']
1108 return modified, added, removed, deleted, unknown, ignored, clean
1109 return modified, added, removed, deleted, unknown, ignored, clean
1109 repo.status = overridestatus
1110 repo.status = overridestatus
1110 orig(ui, repo, *dirs, **opts)
1111 orig(ui, repo, *dirs, **opts)
1111 repo.status = oldstatus
1112 repo.status = oldstatus
1112
1113
1113 def overriderollback(orig, ui, repo, **opts):
1114 def overriderollback(orig, ui, repo, **opts):
1114 result = orig(ui, repo, **opts)
1115 result = orig(ui, repo, **opts)
1115 merge.update(repo, node=None, branchmerge=False, force=True,
1116 merge.update(repo, node=None, branchmerge=False, force=True,
1116 partial=lfutil.isstandin)
1117 partial=lfutil.isstandin)
1117 wlock = repo.wlock()
1118 wlock = repo.wlock()
1118 try:
1119 try:
1119 lfdirstate = lfutil.openlfdirstate(ui, repo)
1120 lfdirstate = lfutil.openlfdirstate(ui, repo)
1120 lfiles = lfutil.listlfiles(repo)
1121 lfiles = lfutil.listlfiles(repo)
1121 oldlfiles = lfutil.listlfiles(repo, repo[None].parents()[0].rev())
1122 oldlfiles = lfutil.listlfiles(repo, repo[None].parents()[0].rev())
1122 for file in lfiles:
1123 for file in lfiles:
1123 if file in oldlfiles:
1124 if file in oldlfiles:
1124 lfdirstate.normallookup(file)
1125 lfdirstate.normallookup(file)
1125 else:
1126 else:
1126 lfdirstate.add(file)
1127 lfdirstate.add(file)
1127 lfdirstate.write()
1128 lfdirstate.write()
1128 finally:
1129 finally:
1129 wlock.release()
1130 wlock.release()
1130 return result
1131 return result
1131
1132
1132 def overridetransplant(orig, ui, repo, *revs, **opts):
1133 def overridetransplant(orig, ui, repo, *revs, **opts):
1133 try:
1134 try:
1134 oldstandins = lfutil.getstandinsstate(repo)
1135 oldstandins = lfutil.getstandinsstate(repo)
1135 repo._istransplanting = True
1136 repo._istransplanting = True
1136 result = orig(ui, repo, *revs, **opts)
1137 result = orig(ui, repo, *revs, **opts)
1137 newstandins = lfutil.getstandinsstate(repo)
1138 newstandins = lfutil.getstandinsstate(repo)
1138 filelist = lfutil.getlfilestoupdate(oldstandins, newstandins)
1139 filelist = lfutil.getlfilestoupdate(oldstandins, newstandins)
1139 lfcommands.updatelfiles(repo.ui, repo, filelist=filelist,
1140 lfcommands.updatelfiles(repo.ui, repo, filelist=filelist,
1140 printmessage=True)
1141 printmessage=True)
1141 finally:
1142 finally:
1142 repo._istransplanting = False
1143 repo._istransplanting = False
1143 return result
1144 return result
1144
1145
1145 def overridecat(orig, ui, repo, file1, *pats, **opts):
1146 def overridecat(orig, ui, repo, file1, *pats, **opts):
1146 ctx = scmutil.revsingle(repo, opts.get('rev'))
1147 ctx = scmutil.revsingle(repo, opts.get('rev'))
1147 err = 1
1148 err = 1
1148 notbad = set()
1149 notbad = set()
1149 m = scmutil.match(ctx, (file1,) + pats, opts)
1150 m = scmutil.match(ctx, (file1,) + pats, opts)
1150 origmatchfn = m.matchfn
1151 origmatchfn = m.matchfn
1151 def lfmatchfn(f):
1152 def lfmatchfn(f):
1152 lf = lfutil.splitstandin(f)
1153 lf = lfutil.splitstandin(f)
1153 if lf is None:
1154 if lf is None:
1154 return origmatchfn(f)
1155 return origmatchfn(f)
1155 notbad.add(lf)
1156 notbad.add(lf)
1156 return origmatchfn(lf)
1157 return origmatchfn(lf)
1157 m.matchfn = lfmatchfn
1158 m.matchfn = lfmatchfn
1158 m.bad = lambda f, msg: f not in notbad
1159 origbadfn = m.bad
1160 def lfbadfn(f, msg):
1161 if not f in notbad:
1162 return origbadfn(f, msg)
1163 m.bad = lfbadfn
1159 for f in ctx.walk(m):
1164 for f in ctx.walk(m):
1165 fp = cmdutil.makefileobj(repo, opts.get('output'), ctx.node(),
1166 pathname=f)
1160 lf = lfutil.splitstandin(f)
1167 lf = lfutil.splitstandin(f)
1161 if lf is None:
1168 if lf is None:
1162 err = orig(ui, repo, f, **opts)
1169 # duplicating unreachable code from commands.cat
1170 data = ctx[f].data()
1171 if opts.get('decode'):
1172 data = repo.wwritedata(f, data)
1173 fp.write(data)
1163 else:
1174 else:
1164 err = lfcommands.catlfile(repo, lf, ctx.rev(), opts.get('output'))
1175 hash = lfutil.readstandin(repo, lf, ctx.rev())
1176 if not lfutil.inusercache(repo.ui, hash):
1177 store = basestore._openstore(repo)
1178 success, missing = store.get([(lf, hash)])
1179 if len(success) != 1:
1180 raise util.Abort(
1181 _('largefile %s is not in cache and could not be '
1182 'downloaded') % lf)
1183 path = lfutil.usercachepath(repo.ui, hash)
1184 fpin = open(path, "rb")
1185 for chunk in lfutil.blockstream(fpin):
1186 fp.write(chunk)
1187 fpin.close()
1188 fp.close()
1189 err = 0
1165 return err
1190 return err
1166
1191
1167 def mercurialsinkbefore(orig, sink):
1192 def mercurialsinkbefore(orig, sink):
1168 sink.repo._isconverting = True
1193 sink.repo._isconverting = True
1169 orig(sink)
1194 orig(sink)
1170
1195
1171 def mercurialsinkafter(orig, sink):
1196 def mercurialsinkafter(orig, sink):
1172 sink.repo._isconverting = False
1197 sink.repo._isconverting = False
1173 orig(sink)
1198 orig(sink)
@@ -1,2175 +1,2178 b''
1 $ USERCACHE="$TESTTMP/cache"; export USERCACHE
1 $ USERCACHE="$TESTTMP/cache"; export USERCACHE
2 $ mkdir "${USERCACHE}"
2 $ mkdir "${USERCACHE}"
3 $ cat >> $HGRCPATH <<EOF
3 $ cat >> $HGRCPATH <<EOF
4 > [extensions]
4 > [extensions]
5 > largefiles=
5 > largefiles=
6 > purge=
6 > purge=
7 > rebase=
7 > rebase=
8 > transplant=
8 > transplant=
9 > [phases]
9 > [phases]
10 > publish=False
10 > publish=False
11 > [largefiles]
11 > [largefiles]
12 > minsize=2
12 > minsize=2
13 > patterns=glob:**.dat
13 > patterns=glob:**.dat
14 > usercache=${USERCACHE}
14 > usercache=${USERCACHE}
15 > [hooks]
15 > [hooks]
16 > precommit=sh -c "echo \\"Invoking status precommit hook\\"; hg status"
16 > precommit=sh -c "echo \\"Invoking status precommit hook\\"; hg status"
17 > EOF
17 > EOF
18
18
19 Create the repo with a couple of revisions of both large and normal
19 Create the repo with a couple of revisions of both large and normal
20 files.
20 files.
21 Test status and dirstate of largefiles and that summary output is correct.
21 Test status and dirstate of largefiles and that summary output is correct.
22
22
23 $ hg init a
23 $ hg init a
24 $ cd a
24 $ cd a
25 $ mkdir sub
25 $ mkdir sub
26 $ echo normal1 > normal1
26 $ echo normal1 > normal1
27 $ echo normal2 > sub/normal2
27 $ echo normal2 > sub/normal2
28 $ echo large1 > large1
28 $ echo large1 > large1
29 $ echo large2 > sub/large2
29 $ echo large2 > sub/large2
30 $ hg add normal1 sub/normal2
30 $ hg add normal1 sub/normal2
31 $ hg add --large large1 sub/large2
31 $ hg add --large large1 sub/large2
32 $ hg commit -m "add files"
32 $ hg commit -m "add files"
33 Invoking status precommit hook
33 Invoking status precommit hook
34 A large1
34 A large1
35 A normal1
35 A normal1
36 A sub/large2
36 A sub/large2
37 A sub/normal2
37 A sub/normal2
38 $ touch large1 sub/large2
38 $ touch large1 sub/large2
39 $ sleep 1
39 $ sleep 1
40 $ hg st
40 $ hg st
41 $ hg debugstate --nodates
41 $ hg debugstate --nodates
42 n 644 41 .hglf/large1
42 n 644 41 .hglf/large1
43 n 644 41 .hglf/sub/large2
43 n 644 41 .hglf/sub/large2
44 n 644 8 normal1
44 n 644 8 normal1
45 n 644 8 sub/normal2
45 n 644 8 sub/normal2
46 $ hg debugstate --large
46 $ hg debugstate --large
47 n 644 7 large1
47 n 644 7 large1
48 n 644 7 sub/large2
48 n 644 7 sub/large2
49 $ echo normal11 > normal1
49 $ echo normal11 > normal1
50 $ echo normal22 > sub/normal2
50 $ echo normal22 > sub/normal2
51 $ echo large11 > large1
51 $ echo large11 > large1
52 $ echo large22 > sub/large2
52 $ echo large22 > sub/large2
53 $ hg commit -m "edit files"
53 $ hg commit -m "edit files"
54 Invoking status precommit hook
54 Invoking status precommit hook
55 M large1
55 M large1
56 M normal1
56 M normal1
57 M sub/large2
57 M sub/large2
58 M sub/normal2
58 M sub/normal2
59 $ hg sum --large
59 $ hg sum --large
60 parent: 1:ce8896473775 tip
60 parent: 1:ce8896473775 tip
61 edit files
61 edit files
62 branch: default
62 branch: default
63 commit: (clean)
63 commit: (clean)
64 update: (current)
64 update: (current)
65 largefiles: (no remote repo)
65 largefiles: (no remote repo)
66
66
67 Commit preserved largefile contents.
67 Commit preserved largefile contents.
68
68
69 $ cat normal1
69 $ cat normal1
70 normal11
70 normal11
71 $ cat large1
71 $ cat large1
72 large11
72 large11
73 $ cat sub/normal2
73 $ cat sub/normal2
74 normal22
74 normal22
75 $ cat sub/large2
75 $ cat sub/large2
76 large22
76 large22
77
77
78 Test status, subdir and unknown files
78 Test status, subdir and unknown files
79
79
80 $ echo unknown > sub/unknown
80 $ echo unknown > sub/unknown
81 $ hg st --all
81 $ hg st --all
82 ? sub/unknown
82 ? sub/unknown
83 C large1
83 C large1
84 C normal1
84 C normal1
85 C sub/large2
85 C sub/large2
86 C sub/normal2
86 C sub/normal2
87 $ hg st --all sub
87 $ hg st --all sub
88 ? sub/unknown
88 ? sub/unknown
89 C sub/large2
89 C sub/large2
90 C sub/normal2
90 C sub/normal2
91 $ rm sub/unknown
91 $ rm sub/unknown
92
92
93 Test messages and exit codes for remove warning cases
93 Test messages and exit codes for remove warning cases
94
94
95 $ hg remove -A large1
95 $ hg remove -A large1
96 not removing large1: file still exists
96 not removing large1: file still exists
97 [1]
97 [1]
98 $ echo 'modified' > large1
98 $ echo 'modified' > large1
99 $ hg remove large1
99 $ hg remove large1
100 not removing large1: file is modified (use -f to force removal)
100 not removing large1: file is modified (use -f to force removal)
101 [1]
101 [1]
102 $ echo 'new' > normalnew
102 $ echo 'new' > normalnew
103 $ hg add normalnew
103 $ hg add normalnew
104 $ echo 'new' > largenew
104 $ echo 'new' > largenew
105 $ hg add --large normalnew
105 $ hg add --large normalnew
106 normalnew already tracked!
106 normalnew already tracked!
107 $ hg remove normalnew largenew
107 $ hg remove normalnew largenew
108 not removing largenew: file is untracked
108 not removing largenew: file is untracked
109 not removing normalnew: file has been marked for add (use forget to undo)
109 not removing normalnew: file has been marked for add (use forget to undo)
110 [1]
110 [1]
111 $ rm normalnew largenew
111 $ rm normalnew largenew
112 $ hg up -Cq
112 $ hg up -Cq
113
113
114 Remove both largefiles and normal files.
114 Remove both largefiles and normal files.
115
115
116 $ hg remove normal1 large1
116 $ hg remove normal1 large1
117 $ hg status large1
117 $ hg status large1
118 R large1
118 R large1
119 $ hg commit -m "remove files"
119 $ hg commit -m "remove files"
120 Invoking status precommit hook
120 Invoking status precommit hook
121 R large1
121 R large1
122 R normal1
122 R normal1
123 $ ls
123 $ ls
124 sub
124 sub
125 $ echo "testlargefile" > large1-test
125 $ echo "testlargefile" > large1-test
126 $ hg add --large large1-test
126 $ hg add --large large1-test
127 $ hg st
127 $ hg st
128 A large1-test
128 A large1-test
129 $ hg rm large1-test
129 $ hg rm large1-test
130 not removing large1-test: file has been marked for add (use forget to undo)
130 not removing large1-test: file has been marked for add (use forget to undo)
131 [1]
131 [1]
132 $ hg st
132 $ hg st
133 A large1-test
133 A large1-test
134 $ hg forget large1-test
134 $ hg forget large1-test
135 $ hg st
135 $ hg st
136 ? large1-test
136 ? large1-test
137 $ hg remove large1-test
137 $ hg remove large1-test
138 not removing large1-test: file is untracked
138 not removing large1-test: file is untracked
139 [1]
139 [1]
140 $ hg forget large1-test
140 $ hg forget large1-test
141 not removing large1-test: file is already untracked
141 not removing large1-test: file is already untracked
142 [1]
142 [1]
143 $ rm large1-test
143 $ rm large1-test
144
144
145 Copy both largefiles and normal files (testing that status output is correct).
145 Copy both largefiles and normal files (testing that status output is correct).
146
146
147 $ hg cp sub/normal2 normal1
147 $ hg cp sub/normal2 normal1
148 $ hg cp sub/large2 large1
148 $ hg cp sub/large2 large1
149 $ hg commit -m "copy files"
149 $ hg commit -m "copy files"
150 Invoking status precommit hook
150 Invoking status precommit hook
151 A large1
151 A large1
152 A normal1
152 A normal1
153 $ cat normal1
153 $ cat normal1
154 normal22
154 normal22
155 $ cat large1
155 $ cat large1
156 large22
156 large22
157
157
158 Test moving largefiles and verify that normal files are also unaffected.
158 Test moving largefiles and verify that normal files are also unaffected.
159
159
160 $ hg mv normal1 normal3
160 $ hg mv normal1 normal3
161 $ hg mv large1 large3
161 $ hg mv large1 large3
162 $ hg mv sub/normal2 sub/normal4
162 $ hg mv sub/normal2 sub/normal4
163 $ hg mv sub/large2 sub/large4
163 $ hg mv sub/large2 sub/large4
164 $ hg commit -m "move files"
164 $ hg commit -m "move files"
165 Invoking status precommit hook
165 Invoking status precommit hook
166 A large3
166 A large3
167 A normal3
167 A normal3
168 A sub/large4
168 A sub/large4
169 A sub/normal4
169 A sub/normal4
170 R large1
170 R large1
171 R normal1
171 R normal1
172 R sub/large2
172 R sub/large2
173 R sub/normal2
173 R sub/normal2
174 $ cat normal3
174 $ cat normal3
175 normal22
175 normal22
176 $ cat large3
176 $ cat large3
177 large22
177 large22
178 $ cat sub/normal4
178 $ cat sub/normal4
179 normal22
179 normal22
180 $ cat sub/large4
180 $ cat sub/large4
181 large22
181 large22
182
182
183 Test repo method wrapping detection
183 Test repo method wrapping detection
184
184
185 $ cat > $TESTTMP/wrapping1.py <<EOF
185 $ cat > $TESTTMP/wrapping1.py <<EOF
186 > from hgext import largefiles
186 > from hgext import largefiles
187 > def reposetup(ui, repo):
187 > def reposetup(ui, repo):
188 > class derived(repo.__class__):
188 > class derived(repo.__class__):
189 > def push(self, *args, **kwargs):
189 > def push(self, *args, **kwargs):
190 > return super(derived, self).push(*args, **kwargs)
190 > return super(derived, self).push(*args, **kwargs)
191 > repo.__class__ = derived
191 > repo.__class__ = derived
192 > largefiles.reposetup(ui, repo)
192 > largefiles.reposetup(ui, repo)
193 > uisetup = largefiles.uisetup
193 > uisetup = largefiles.uisetup
194 > EOF
194 > EOF
195 $ hg --config extensions.largefiles=$TESTTMP/wrapping1.py status
195 $ hg --config extensions.largefiles=$TESTTMP/wrapping1.py status
196 largefiles: repo method 'push' appears to have already been wrapped by another extension: largefiles may behave incorrectly
196 largefiles: repo method 'push' appears to have already been wrapped by another extension: largefiles may behave incorrectly
197
197
198 $ cat > $TESTTMP/wrapping2.py <<EOF
198 $ cat > $TESTTMP/wrapping2.py <<EOF
199 > from hgext import largefiles
199 > from hgext import largefiles
200 > def reposetup(ui, repo):
200 > def reposetup(ui, repo):
201 > orgpush = repo.push
201 > orgpush = repo.push
202 > def push(*args, **kwargs):
202 > def push(*args, **kwargs):
203 > return orgpush(*args, **kwargs)
203 > return orgpush(*args, **kwargs)
204 > repo.push = push
204 > repo.push = push
205 > largefiles.reposetup(ui, repo)
205 > largefiles.reposetup(ui, repo)
206 > uisetup = largefiles.uisetup
206 > uisetup = largefiles.uisetup
207 > EOF
207 > EOF
208 $ hg --config extensions.largefiles=$TESTTMP/wrapping2.py status
208 $ hg --config extensions.largefiles=$TESTTMP/wrapping2.py status
209 largefiles: repo method 'push' appears to have already been wrapped by another extension: largefiles may behave incorrectly
209 largefiles: repo method 'push' appears to have already been wrapped by another extension: largefiles may behave incorrectly
210
210
211 Test copies and moves from a directory other than root (issue3516)
211 Test copies and moves from a directory other than root (issue3516)
212
212
213 $ cd ..
213 $ cd ..
214 $ hg init lf_cpmv
214 $ hg init lf_cpmv
215 $ cd lf_cpmv
215 $ cd lf_cpmv
216 $ mkdir dira
216 $ mkdir dira
217 $ mkdir dira/dirb
217 $ mkdir dira/dirb
218 $ touch dira/dirb/largefile
218 $ touch dira/dirb/largefile
219 $ hg add --large dira/dirb/largefile
219 $ hg add --large dira/dirb/largefile
220 $ hg commit -m "added"
220 $ hg commit -m "added"
221 Invoking status precommit hook
221 Invoking status precommit hook
222 A dira/dirb/largefile
222 A dira/dirb/largefile
223 $ cd dira
223 $ cd dira
224 $ hg cp dirb/largefile foo/largefile
224 $ hg cp dirb/largefile foo/largefile
225 $ hg ci -m "deep copy"
225 $ hg ci -m "deep copy"
226 Invoking status precommit hook
226 Invoking status precommit hook
227 A dira/foo/largefile
227 A dira/foo/largefile
228 $ find . | sort
228 $ find . | sort
229 .
229 .
230 ./dirb
230 ./dirb
231 ./dirb/largefile
231 ./dirb/largefile
232 ./foo
232 ./foo
233 ./foo/largefile
233 ./foo/largefile
234 $ hg mv foo/largefile baz/largefile
234 $ hg mv foo/largefile baz/largefile
235 $ hg ci -m "moved"
235 $ hg ci -m "moved"
236 Invoking status precommit hook
236 Invoking status precommit hook
237 A dira/baz/largefile
237 A dira/baz/largefile
238 R dira/foo/largefile
238 R dira/foo/largefile
239 $ find . | sort
239 $ find . | sort
240 .
240 .
241 ./baz
241 ./baz
242 ./baz/largefile
242 ./baz/largefile
243 ./dirb
243 ./dirb
244 ./dirb/largefile
244 ./dirb/largefile
245 ./foo
245 ./foo
246 $ cd ../../a
246 $ cd ../../a
247
247
248 #if serve
248 #if serve
249 Test display of largefiles in hgweb
249 Test display of largefiles in hgweb
250
250
251 $ hg serve -d -p $HGPORT --pid-file ../hg.pid
251 $ hg serve -d -p $HGPORT --pid-file ../hg.pid
252 $ cat ../hg.pid >> $DAEMON_PIDS
252 $ cat ../hg.pid >> $DAEMON_PIDS
253 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT 'file/tip/?style=raw'
253 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT 'file/tip/?style=raw'
254 200 Script output follows
254 200 Script output follows
255
255
256
256
257 drwxr-xr-x sub
257 drwxr-xr-x sub
258 -rw-r--r-- 41 large3
258 -rw-r--r-- 41 large3
259 -rw-r--r-- 9 normal3
259 -rw-r--r-- 9 normal3
260
260
261
261
262 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT 'file/tip/sub/?style=raw'
262 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT 'file/tip/sub/?style=raw'
263 200 Script output follows
263 200 Script output follows
264
264
265
265
266 -rw-r--r-- 41 large4
266 -rw-r--r-- 41 large4
267 -rw-r--r-- 9 normal4
267 -rw-r--r-- 9 normal4
268
268
269
269
270 $ "$TESTDIR/killdaemons.py" $DAEMON_PIDS
270 $ "$TESTDIR/killdaemons.py" $DAEMON_PIDS
271 #endif
271 #endif
272
272
273 Test archiving the various revisions. These hit corner cases known with
273 Test archiving the various revisions. These hit corner cases known with
274 archiving.
274 archiving.
275
275
276 $ hg archive -r 0 ../archive0
276 $ hg archive -r 0 ../archive0
277 $ hg archive -r 1 ../archive1
277 $ hg archive -r 1 ../archive1
278 $ hg archive -r 2 ../archive2
278 $ hg archive -r 2 ../archive2
279 $ hg archive -r 3 ../archive3
279 $ hg archive -r 3 ../archive3
280 $ hg archive -r 4 ../archive4
280 $ hg archive -r 4 ../archive4
281 $ cd ../archive0
281 $ cd ../archive0
282 $ cat normal1
282 $ cat normal1
283 normal1
283 normal1
284 $ cat large1
284 $ cat large1
285 large1
285 large1
286 $ cat sub/normal2
286 $ cat sub/normal2
287 normal2
287 normal2
288 $ cat sub/large2
288 $ cat sub/large2
289 large2
289 large2
290 $ cd ../archive1
290 $ cd ../archive1
291 $ cat normal1
291 $ cat normal1
292 normal11
292 normal11
293 $ cat large1
293 $ cat large1
294 large11
294 large11
295 $ cat sub/normal2
295 $ cat sub/normal2
296 normal22
296 normal22
297 $ cat sub/large2
297 $ cat sub/large2
298 large22
298 large22
299 $ cd ../archive2
299 $ cd ../archive2
300 $ ls
300 $ ls
301 sub
301 sub
302 $ cat sub/normal2
302 $ cat sub/normal2
303 normal22
303 normal22
304 $ cat sub/large2
304 $ cat sub/large2
305 large22
305 large22
306 $ cd ../archive3
306 $ cd ../archive3
307 $ cat normal1
307 $ cat normal1
308 normal22
308 normal22
309 $ cat large1
309 $ cat large1
310 large22
310 large22
311 $ cat sub/normal2
311 $ cat sub/normal2
312 normal22
312 normal22
313 $ cat sub/large2
313 $ cat sub/large2
314 large22
314 large22
315 $ cd ../archive4
315 $ cd ../archive4
316 $ cat normal3
316 $ cat normal3
317 normal22
317 normal22
318 $ cat large3
318 $ cat large3
319 large22
319 large22
320 $ cat sub/normal4
320 $ cat sub/normal4
321 normal22
321 normal22
322 $ cat sub/large4
322 $ cat sub/large4
323 large22
323 large22
324
324
325 Commit corner case: specify files to commit.
325 Commit corner case: specify files to commit.
326
326
327 $ cd ../a
327 $ cd ../a
328 $ echo normal3 > normal3
328 $ echo normal3 > normal3
329 $ echo large3 > large3
329 $ echo large3 > large3
330 $ echo normal4 > sub/normal4
330 $ echo normal4 > sub/normal4
331 $ echo large4 > sub/large4
331 $ echo large4 > sub/large4
332 $ hg commit normal3 large3 sub/normal4 sub/large4 -m "edit files again"
332 $ hg commit normal3 large3 sub/normal4 sub/large4 -m "edit files again"
333 Invoking status precommit hook
333 Invoking status precommit hook
334 M large3
334 M large3
335 M normal3
335 M normal3
336 M sub/large4
336 M sub/large4
337 M sub/normal4
337 M sub/normal4
338 $ cat normal3
338 $ cat normal3
339 normal3
339 normal3
340 $ cat large3
340 $ cat large3
341 large3
341 large3
342 $ cat sub/normal4
342 $ cat sub/normal4
343 normal4
343 normal4
344 $ cat sub/large4
344 $ cat sub/large4
345 large4
345 large4
346
346
347 One more commit corner case: commit from a subdirectory.
347 One more commit corner case: commit from a subdirectory.
348
348
349 $ cd ../a
349 $ cd ../a
350 $ echo normal33 > normal3
350 $ echo normal33 > normal3
351 $ echo large33 > large3
351 $ echo large33 > large3
352 $ echo normal44 > sub/normal4
352 $ echo normal44 > sub/normal4
353 $ echo large44 > sub/large4
353 $ echo large44 > sub/large4
354 $ cd sub
354 $ cd sub
355 $ hg commit -m "edit files yet again"
355 $ hg commit -m "edit files yet again"
356 Invoking status precommit hook
356 Invoking status precommit hook
357 M large3
357 M large3
358 M normal3
358 M normal3
359 M sub/large4
359 M sub/large4
360 M sub/normal4
360 M sub/normal4
361 $ cat ../normal3
361 $ cat ../normal3
362 normal33
362 normal33
363 $ cat ../large3
363 $ cat ../large3
364 large33
364 large33
365 $ cat normal4
365 $ cat normal4
366 normal44
366 normal44
367 $ cat large4
367 $ cat large4
368 large44
368 large44
369
369
370 Committing standins is not allowed.
370 Committing standins is not allowed.
371
371
372 $ cd ..
372 $ cd ..
373 $ echo large3 > large3
373 $ echo large3 > large3
374 $ hg commit .hglf/large3 -m "try to commit standin"
374 $ hg commit .hglf/large3 -m "try to commit standin"
375 abort: file ".hglf/large3" is a largefile standin
375 abort: file ".hglf/large3" is a largefile standin
376 (commit the largefile itself instead)
376 (commit the largefile itself instead)
377 [255]
377 [255]
378
378
379 Corner cases for adding largefiles.
379 Corner cases for adding largefiles.
380
380
381 $ echo large5 > large5
381 $ echo large5 > large5
382 $ hg add --large large5
382 $ hg add --large large5
383 $ hg add --large large5
383 $ hg add --large large5
384 large5 already a largefile
384 large5 already a largefile
385 $ mkdir sub2
385 $ mkdir sub2
386 $ echo large6 > sub2/large6
386 $ echo large6 > sub2/large6
387 $ echo large7 > sub2/large7
387 $ echo large7 > sub2/large7
388 $ hg add --large sub2
388 $ hg add --large sub2
389 adding sub2/large6 as a largefile (glob)
389 adding sub2/large6 as a largefile (glob)
390 adding sub2/large7 as a largefile (glob)
390 adding sub2/large7 as a largefile (glob)
391 $ hg st
391 $ hg st
392 M large3
392 M large3
393 A large5
393 A large5
394 A sub2/large6
394 A sub2/large6
395 A sub2/large7
395 A sub2/large7
396
396
397 Committing directories containing only largefiles.
397 Committing directories containing only largefiles.
398
398
399 $ mkdir -p z/y/x/m
399 $ mkdir -p z/y/x/m
400 $ touch z/y/x/m/large1
400 $ touch z/y/x/m/large1
401 $ touch z/y/x/large2
401 $ touch z/y/x/large2
402 $ hg add --large z/y/x/m/large1 z/y/x/large2
402 $ hg add --large z/y/x/m/large1 z/y/x/large2
403 $ hg commit -m "Subdir with directory only containing largefiles" z
403 $ hg commit -m "Subdir with directory only containing largefiles" z
404 Invoking status precommit hook
404 Invoking status precommit hook
405 M large3
405 M large3
406 A large5
406 A large5
407 A sub2/large6
407 A sub2/large6
408 A sub2/large7
408 A sub2/large7
409 A z/y/x/large2
409 A z/y/x/large2
410 A z/y/x/m/large1
410 A z/y/x/m/large1
411 $ hg rollback --quiet
411 $ hg rollback --quiet
412 $ touch z/y/x/m/normal
412 $ touch z/y/x/m/normal
413 $ hg add z/y/x/m/normal
413 $ hg add z/y/x/m/normal
414 $ hg commit -m "Subdir with mixed contents" z
414 $ hg commit -m "Subdir with mixed contents" z
415 Invoking status precommit hook
415 Invoking status precommit hook
416 M large3
416 M large3
417 A large5
417 A large5
418 A sub2/large6
418 A sub2/large6
419 A sub2/large7
419 A sub2/large7
420 A z/y/x/large2
420 A z/y/x/large2
421 A z/y/x/m/large1
421 A z/y/x/m/large1
422 A z/y/x/m/normal
422 A z/y/x/m/normal
423 $ hg st
423 $ hg st
424 M large3
424 M large3
425 A large5
425 A large5
426 A sub2/large6
426 A sub2/large6
427 A sub2/large7
427 A sub2/large7
428 $ hg rollback --quiet
428 $ hg rollback --quiet
429 $ hg revert z/y/x/large2 z/y/x/m/large1
429 $ hg revert z/y/x/large2 z/y/x/m/large1
430 $ rm z/y/x/large2 z/y/x/m/large1
430 $ rm z/y/x/large2 z/y/x/m/large1
431 $ hg commit -m "Subdir with normal contents" z
431 $ hg commit -m "Subdir with normal contents" z
432 Invoking status precommit hook
432 Invoking status precommit hook
433 M large3
433 M large3
434 A large5
434 A large5
435 A sub2/large6
435 A sub2/large6
436 A sub2/large7
436 A sub2/large7
437 A z/y/x/m/normal
437 A z/y/x/m/normal
438 $ hg st
438 $ hg st
439 M large3
439 M large3
440 A large5
440 A large5
441 A sub2/large6
441 A sub2/large6
442 A sub2/large7
442 A sub2/large7
443 $ hg rollback --quiet
443 $ hg rollback --quiet
444 $ hg revert --quiet z
444 $ hg revert --quiet z
445 $ hg commit -m "Empty subdir" z
445 $ hg commit -m "Empty subdir" z
446 abort: z: no match under directory!
446 abort: z: no match under directory!
447 [255]
447 [255]
448 $ rm -rf z
448 $ rm -rf z
449 $ hg ci -m "standin" .hglf
449 $ hg ci -m "standin" .hglf
450 abort: file ".hglf" is a largefile standin
450 abort: file ".hglf" is a largefile standin
451 (commit the largefile itself instead)
451 (commit the largefile itself instead)
452 [255]
452 [255]
453
453
454 Test "hg status" with combination of 'file pattern' and 'directory
454 Test "hg status" with combination of 'file pattern' and 'directory
455 pattern' for largefiles:
455 pattern' for largefiles:
456
456
457 $ hg status sub2/large6 sub2
457 $ hg status sub2/large6 sub2
458 A sub2/large6
458 A sub2/large6
459 A sub2/large7
459 A sub2/large7
460
460
461 Config settings (pattern **.dat, minsize 2 MB) are respected.
461 Config settings (pattern **.dat, minsize 2 MB) are respected.
462
462
463 $ echo testdata > test.dat
463 $ echo testdata > test.dat
464 $ dd bs=1k count=2k if=/dev/zero of=reallylarge > /dev/null 2> /dev/null
464 $ dd bs=1k count=2k if=/dev/zero of=reallylarge > /dev/null 2> /dev/null
465 $ hg add
465 $ hg add
466 adding reallylarge as a largefile
466 adding reallylarge as a largefile
467 adding test.dat as a largefile
467 adding test.dat as a largefile
468
468
469 Test that minsize and --lfsize handle float values;
469 Test that minsize and --lfsize handle float values;
470 also tests that --lfsize overrides largefiles.minsize.
470 also tests that --lfsize overrides largefiles.minsize.
471 (0.250 MB = 256 kB = 262144 B)
471 (0.250 MB = 256 kB = 262144 B)
472
472
473 $ dd if=/dev/zero of=ratherlarge bs=1024 count=256 > /dev/null 2> /dev/null
473 $ dd if=/dev/zero of=ratherlarge bs=1024 count=256 > /dev/null 2> /dev/null
474 $ dd if=/dev/zero of=medium bs=1024 count=128 > /dev/null 2> /dev/null
474 $ dd if=/dev/zero of=medium bs=1024 count=128 > /dev/null 2> /dev/null
475 $ hg --config largefiles.minsize=.25 add
475 $ hg --config largefiles.minsize=.25 add
476 adding ratherlarge as a largefile
476 adding ratherlarge as a largefile
477 adding medium
477 adding medium
478 $ hg forget medium
478 $ hg forget medium
479 $ hg --config largefiles.minsize=.25 add --lfsize=.125
479 $ hg --config largefiles.minsize=.25 add --lfsize=.125
480 adding medium as a largefile
480 adding medium as a largefile
481 $ dd if=/dev/zero of=notlarge bs=1024 count=127 > /dev/null 2> /dev/null
481 $ dd if=/dev/zero of=notlarge bs=1024 count=127 > /dev/null 2> /dev/null
482 $ hg --config largefiles.minsize=.25 add --lfsize=.125
482 $ hg --config largefiles.minsize=.25 add --lfsize=.125
483 adding notlarge
483 adding notlarge
484 $ hg forget notlarge
484 $ hg forget notlarge
485
485
486 Test forget on largefiles.
486 Test forget on largefiles.
487
487
488 $ hg forget large3 large5 test.dat reallylarge ratherlarge medium
488 $ hg forget large3 large5 test.dat reallylarge ratherlarge medium
489 $ hg commit -m "add/edit more largefiles"
489 $ hg commit -m "add/edit more largefiles"
490 Invoking status precommit hook
490 Invoking status precommit hook
491 A sub2/large6
491 A sub2/large6
492 A sub2/large7
492 A sub2/large7
493 R large3
493 R large3
494 ? large5
494 ? large5
495 ? medium
495 ? medium
496 ? notlarge
496 ? notlarge
497 ? ratherlarge
497 ? ratherlarge
498 ? reallylarge
498 ? reallylarge
499 ? test.dat
499 ? test.dat
500 $ hg st
500 $ hg st
501 ? large3
501 ? large3
502 ? large5
502 ? large5
503 ? medium
503 ? medium
504 ? notlarge
504 ? notlarge
505 ? ratherlarge
505 ? ratherlarge
506 ? reallylarge
506 ? reallylarge
507 ? test.dat
507 ? test.dat
508
508
509 Purge with largefiles: verify that largefiles are still in the working
509 Purge with largefiles: verify that largefiles are still in the working
510 dir after a purge.
510 dir after a purge.
511
511
512 $ hg purge --all
512 $ hg purge --all
513 $ cat sub/large4
513 $ cat sub/large4
514 large44
514 large44
515 $ cat sub2/large6
515 $ cat sub2/large6
516 large6
516 large6
517 $ cat sub2/large7
517 $ cat sub2/large7
518 large7
518 large7
519
519
520 Test addremove: verify that files that should be added as largfiles are added as
520 Test addremove: verify that files that should be added as largfiles are added as
521 such and that already-existing largfiles are not added as normal files by
521 such and that already-existing largfiles are not added as normal files by
522 accident.
522 accident.
523
523
524 $ rm normal3
524 $ rm normal3
525 $ rm sub/large4
525 $ rm sub/large4
526 $ echo "testing addremove with patterns" > testaddremove.dat
526 $ echo "testing addremove with patterns" > testaddremove.dat
527 $ echo "normaladdremove" > normaladdremove
527 $ echo "normaladdremove" > normaladdremove
528 $ hg addremove
528 $ hg addremove
529 removing sub/large4
529 removing sub/large4
530 adding testaddremove.dat as a largefile
530 adding testaddremove.dat as a largefile
531 removing normal3
531 removing normal3
532 adding normaladdremove
532 adding normaladdremove
533
533
534 Test addremove with -R
534 Test addremove with -R
535
535
536 $ hg up -C
536 $ hg up -C
537 getting changed largefiles
537 getting changed largefiles
538 1 largefiles updated, 0 removed
538 1 largefiles updated, 0 removed
539 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
539 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
540 $ rm normal3
540 $ rm normal3
541 $ rm sub/large4
541 $ rm sub/large4
542 $ echo "testing addremove with patterns" > testaddremove.dat
542 $ echo "testing addremove with patterns" > testaddremove.dat
543 $ echo "normaladdremove" > normaladdremove
543 $ echo "normaladdremove" > normaladdremove
544 $ cd ..
544 $ cd ..
545 $ hg -R a addremove
545 $ hg -R a addremove
546 removing sub/large4
546 removing sub/large4
547 adding a/testaddremove.dat as a largefile (glob)
547 adding a/testaddremove.dat as a largefile (glob)
548 removing normal3
548 removing normal3
549 adding normaladdremove
549 adding normaladdremove
550 $ cd a
550 $ cd a
551
551
552 Test 3364
552 Test 3364
553 $ hg clone . ../addrm
553 $ hg clone . ../addrm
554 updating to branch default
554 updating to branch default
555 getting changed largefiles
555 getting changed largefiles
556 3 largefiles updated, 0 removed
556 3 largefiles updated, 0 removed
557 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
557 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
558 $ cd ../addrm
558 $ cd ../addrm
559 $ cat >> .hg/hgrc <<EOF
559 $ cat >> .hg/hgrc <<EOF
560 > [hooks]
560 > [hooks]
561 > post-commit.stat=sh -c "echo \\"Invoking status postcommit hook\\"; hg status -A"
561 > post-commit.stat=sh -c "echo \\"Invoking status postcommit hook\\"; hg status -A"
562 > EOF
562 > EOF
563 $ touch foo
563 $ touch foo
564 $ hg add --large foo
564 $ hg add --large foo
565 $ hg ci -m "add foo"
565 $ hg ci -m "add foo"
566 Invoking status precommit hook
566 Invoking status precommit hook
567 A foo
567 A foo
568 Invoking status postcommit hook
568 Invoking status postcommit hook
569 C foo
569 C foo
570 C normal3
570 C normal3
571 C sub/large4
571 C sub/large4
572 C sub/normal4
572 C sub/normal4
573 C sub2/large6
573 C sub2/large6
574 C sub2/large7
574 C sub2/large7
575 $ rm foo
575 $ rm foo
576 $ hg st
576 $ hg st
577 ! foo
577 ! foo
578 hmm.. no precommit invoked, but there is a postcommit??
578 hmm.. no precommit invoked, but there is a postcommit??
579 $ hg ci -m "will not checkin"
579 $ hg ci -m "will not checkin"
580 nothing changed
580 nothing changed
581 Invoking status postcommit hook
581 Invoking status postcommit hook
582 ! foo
582 ! foo
583 C normal3
583 C normal3
584 C sub/large4
584 C sub/large4
585 C sub/normal4
585 C sub/normal4
586 C sub2/large6
586 C sub2/large6
587 C sub2/large7
587 C sub2/large7
588 [1]
588 [1]
589 $ hg addremove
589 $ hg addremove
590 removing foo
590 removing foo
591 $ hg st
591 $ hg st
592 R foo
592 R foo
593 $ hg ci -m "used to say nothing changed"
593 $ hg ci -m "used to say nothing changed"
594 Invoking status precommit hook
594 Invoking status precommit hook
595 R foo
595 R foo
596 Invoking status postcommit hook
596 Invoking status postcommit hook
597 C normal3
597 C normal3
598 C sub/large4
598 C sub/large4
599 C sub/normal4
599 C sub/normal4
600 C sub2/large6
600 C sub2/large6
601 C sub2/large7
601 C sub2/large7
602 $ hg st
602 $ hg st
603
603
604 Test 3507 (both normal files and largefiles were a problem)
604 Test 3507 (both normal files and largefiles were a problem)
605
605
606 $ touch normal
606 $ touch normal
607 $ touch large
607 $ touch large
608 $ hg add normal
608 $ hg add normal
609 $ hg add --large large
609 $ hg add --large large
610 $ hg ci -m "added"
610 $ hg ci -m "added"
611 Invoking status precommit hook
611 Invoking status precommit hook
612 A large
612 A large
613 A normal
613 A normal
614 Invoking status postcommit hook
614 Invoking status postcommit hook
615 C large
615 C large
616 C normal
616 C normal
617 C normal3
617 C normal3
618 C sub/large4
618 C sub/large4
619 C sub/normal4
619 C sub/normal4
620 C sub2/large6
620 C sub2/large6
621 C sub2/large7
621 C sub2/large7
622 $ hg remove normal
622 $ hg remove normal
623 $ hg addremove --traceback
623 $ hg addremove --traceback
624 $ hg ci -m "addremoved normal"
624 $ hg ci -m "addremoved normal"
625 Invoking status precommit hook
625 Invoking status precommit hook
626 R normal
626 R normal
627 Invoking status postcommit hook
627 Invoking status postcommit hook
628 C large
628 C large
629 C normal3
629 C normal3
630 C sub/large4
630 C sub/large4
631 C sub/normal4
631 C sub/normal4
632 C sub2/large6
632 C sub2/large6
633 C sub2/large7
633 C sub2/large7
634 $ hg up -C '.^'
634 $ hg up -C '.^'
635 getting changed largefiles
635 getting changed largefiles
636 0 largefiles updated, 0 removed
636 0 largefiles updated, 0 removed
637 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
637 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
638 $ hg remove large
638 $ hg remove large
639 $ hg addremove --traceback
639 $ hg addremove --traceback
640 $ hg ci -m "removed large"
640 $ hg ci -m "removed large"
641 Invoking status precommit hook
641 Invoking status precommit hook
642 R large
642 R large
643 created new head
643 created new head
644 Invoking status postcommit hook
644 Invoking status postcommit hook
645 C normal
645 C normal
646 C normal3
646 C normal3
647 C sub/large4
647 C sub/large4
648 C sub/normal4
648 C sub/normal4
649 C sub2/large6
649 C sub2/large6
650 C sub2/large7
650 C sub2/large7
651
651
652 Test commit -A (issue 3542)
652 Test commit -A (issue 3542)
653 $ echo large8 > large8
653 $ echo large8 > large8
654 $ hg add --large large8
654 $ hg add --large large8
655 $ hg ci -Am 'this used to add large8 as normal and commit both'
655 $ hg ci -Am 'this used to add large8 as normal and commit both'
656 Invoking status precommit hook
656 Invoking status precommit hook
657 A large8
657 A large8
658 Invoking status postcommit hook
658 Invoking status postcommit hook
659 C large8
659 C large8
660 C normal
660 C normal
661 C normal3
661 C normal3
662 C sub/large4
662 C sub/large4
663 C sub/normal4
663 C sub/normal4
664 C sub2/large6
664 C sub2/large6
665 C sub2/large7
665 C sub2/large7
666 $ rm large8
666 $ rm large8
667 $ hg ci -Am 'this used to not notice the rm'
667 $ hg ci -Am 'this used to not notice the rm'
668 removing large8
668 removing large8
669 Invoking status precommit hook
669 Invoking status precommit hook
670 R large8
670 R large8
671 Invoking status postcommit hook
671 Invoking status postcommit hook
672 C normal
672 C normal
673 C normal3
673 C normal3
674 C sub/large4
674 C sub/large4
675 C sub/normal4
675 C sub/normal4
676 C sub2/large6
676 C sub2/large6
677 C sub2/large7
677 C sub2/large7
678
678
679 Test that a standin can't be added as a large file
679 Test that a standin can't be added as a large file
680
680
681 $ touch large
681 $ touch large
682 $ hg add --large large
682 $ hg add --large large
683 $ hg ci -m "add"
683 $ hg ci -m "add"
684 Invoking status precommit hook
684 Invoking status precommit hook
685 A large
685 A large
686 Invoking status postcommit hook
686 Invoking status postcommit hook
687 C large
687 C large
688 C normal
688 C normal
689 C normal3
689 C normal3
690 C sub/large4
690 C sub/large4
691 C sub/normal4
691 C sub/normal4
692 C sub2/large6
692 C sub2/large6
693 C sub2/large7
693 C sub2/large7
694 $ hg remove large
694 $ hg remove large
695 $ touch large
695 $ touch large
696 $ hg addremove --config largefiles.patterns=**large --traceback
696 $ hg addremove --config largefiles.patterns=**large --traceback
697 adding large as a largefile
697 adding large as a largefile
698
698
699 Test that outgoing --large works (with revsets too)
699 Test that outgoing --large works (with revsets too)
700 $ hg outgoing --rev '.^' --large
700 $ hg outgoing --rev '.^' --large
701 comparing with $TESTTMP/a (glob)
701 comparing with $TESTTMP/a (glob)
702 searching for changes
702 searching for changes
703 changeset: 8:c02fd3b77ec4
703 changeset: 8:c02fd3b77ec4
704 user: test
704 user: test
705 date: Thu Jan 01 00:00:00 1970 +0000
705 date: Thu Jan 01 00:00:00 1970 +0000
706 summary: add foo
706 summary: add foo
707
707
708 changeset: 9:289dd08c9bbb
708 changeset: 9:289dd08c9bbb
709 user: test
709 user: test
710 date: Thu Jan 01 00:00:00 1970 +0000
710 date: Thu Jan 01 00:00:00 1970 +0000
711 summary: used to say nothing changed
711 summary: used to say nothing changed
712
712
713 changeset: 10:34f23ac6ac12
713 changeset: 10:34f23ac6ac12
714 user: test
714 user: test
715 date: Thu Jan 01 00:00:00 1970 +0000
715 date: Thu Jan 01 00:00:00 1970 +0000
716 summary: added
716 summary: added
717
717
718 changeset: 12:710c1b2f523c
718 changeset: 12:710c1b2f523c
719 parent: 10:34f23ac6ac12
719 parent: 10:34f23ac6ac12
720 user: test
720 user: test
721 date: Thu Jan 01 00:00:00 1970 +0000
721 date: Thu Jan 01 00:00:00 1970 +0000
722 summary: removed large
722 summary: removed large
723
723
724 changeset: 13:0a3e75774479
724 changeset: 13:0a3e75774479
725 user: test
725 user: test
726 date: Thu Jan 01 00:00:00 1970 +0000
726 date: Thu Jan 01 00:00:00 1970 +0000
727 summary: this used to add large8 as normal and commit both
727 summary: this used to add large8 as normal and commit both
728
728
729 changeset: 14:84f3d378175c
729 changeset: 14:84f3d378175c
730 user: test
730 user: test
731 date: Thu Jan 01 00:00:00 1970 +0000
731 date: Thu Jan 01 00:00:00 1970 +0000
732 summary: this used to not notice the rm
732 summary: this used to not notice the rm
733
733
734 searching for changes
734 searching for changes
735 largefiles to upload:
735 largefiles to upload:
736 foo
736 foo
737 large
737 large
738 large8
738 large8
739
739
740 $ cd ../a
740 $ cd ../a
741
741
742 Clone a largefiles repo.
742 Clone a largefiles repo.
743
743
744 $ hg clone . ../b
744 $ hg clone . ../b
745 updating to branch default
745 updating to branch default
746 getting changed largefiles
746 getting changed largefiles
747 3 largefiles updated, 0 removed
747 3 largefiles updated, 0 removed
748 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
748 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
749 $ cd ../b
749 $ cd ../b
750 $ hg log --template '{rev}:{node|short} {desc|firstline}\n'
750 $ hg log --template '{rev}:{node|short} {desc|firstline}\n'
751 7:daea875e9014 add/edit more largefiles
751 7:daea875e9014 add/edit more largefiles
752 6:4355d653f84f edit files yet again
752 6:4355d653f84f edit files yet again
753 5:9d5af5072dbd edit files again
753 5:9d5af5072dbd edit files again
754 4:74c02385b94c move files
754 4:74c02385b94c move files
755 3:9e8fbc4bce62 copy files
755 3:9e8fbc4bce62 copy files
756 2:51a0ae4d5864 remove files
756 2:51a0ae4d5864 remove files
757 1:ce8896473775 edit files
757 1:ce8896473775 edit files
758 0:30d30fe6a5be add files
758 0:30d30fe6a5be add files
759 $ cat normal3
759 $ cat normal3
760 normal33
760 normal33
761 $ cat sub/normal4
761 $ cat sub/normal4
762 normal44
762 normal44
763 $ cat sub/large4
763 $ cat sub/large4
764 large44
764 large44
765 $ cat sub2/large6
765 $ cat sub2/large6
766 large6
766 large6
767 $ cat sub2/large7
767 $ cat sub2/large7
768 large7
768 large7
769 $ cd ..
769 $ cd ..
770 $ hg clone a -r 3 c
770 $ hg clone a -r 3 c
771 adding changesets
771 adding changesets
772 adding manifests
772 adding manifests
773 adding file changes
773 adding file changes
774 added 4 changesets with 10 changes to 4 files
774 added 4 changesets with 10 changes to 4 files
775 updating to branch default
775 updating to branch default
776 getting changed largefiles
776 getting changed largefiles
777 2 largefiles updated, 0 removed
777 2 largefiles updated, 0 removed
778 4 files updated, 0 files merged, 0 files removed, 0 files unresolved
778 4 files updated, 0 files merged, 0 files removed, 0 files unresolved
779 $ cd c
779 $ cd c
780 $ hg log --template '{rev}:{node|short} {desc|firstline}\n'
780 $ hg log --template '{rev}:{node|short} {desc|firstline}\n'
781 3:9e8fbc4bce62 copy files
781 3:9e8fbc4bce62 copy files
782 2:51a0ae4d5864 remove files
782 2:51a0ae4d5864 remove files
783 1:ce8896473775 edit files
783 1:ce8896473775 edit files
784 0:30d30fe6a5be add files
784 0:30d30fe6a5be add files
785 $ cat normal1
785 $ cat normal1
786 normal22
786 normal22
787 $ cat large1
787 $ cat large1
788 large22
788 large22
789 $ cat sub/normal2
789 $ cat sub/normal2
790 normal22
790 normal22
791 $ cat sub/large2
791 $ cat sub/large2
792 large22
792 large22
793
793
794 Old revisions of a clone have correct largefiles content (this also
794 Old revisions of a clone have correct largefiles content (this also
795 tests update).
795 tests update).
796
796
797 $ hg update -r 1
797 $ hg update -r 1
798 getting changed largefiles
798 getting changed largefiles
799 1 largefiles updated, 0 removed
799 1 largefiles updated, 0 removed
800 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
800 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
801 $ cat large1
801 $ cat large1
802 large11
802 large11
803 $ cat sub/large2
803 $ cat sub/large2
804 large22
804 large22
805 $ cd ..
805 $ cd ..
806
806
807 Test cloning with --all-largefiles flag
807 Test cloning with --all-largefiles flag
808
808
809 $ rm "${USERCACHE}"/*
809 $ rm "${USERCACHE}"/*
810 $ hg clone --all-largefiles a a-backup
810 $ hg clone --all-largefiles a a-backup
811 updating to branch default
811 updating to branch default
812 getting changed largefiles
812 getting changed largefiles
813 3 largefiles updated, 0 removed
813 3 largefiles updated, 0 removed
814 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
814 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
815 8 additional largefiles cached
815 8 additional largefiles cached
816
816
817 $ rm "${USERCACHE}"/*
817 $ rm "${USERCACHE}"/*
818 $ hg clone --all-largefiles -u 0 a a-clone0
818 $ hg clone --all-largefiles -u 0 a a-clone0
819 updating to branch default
819 updating to branch default
820 getting changed largefiles
820 getting changed largefiles
821 2 largefiles updated, 0 removed
821 2 largefiles updated, 0 removed
822 4 files updated, 0 files merged, 0 files removed, 0 files unresolved
822 4 files updated, 0 files merged, 0 files removed, 0 files unresolved
823 9 additional largefiles cached
823 9 additional largefiles cached
824 $ hg -R a-clone0 sum
824 $ hg -R a-clone0 sum
825 parent: 0:30d30fe6a5be
825 parent: 0:30d30fe6a5be
826 add files
826 add files
827 branch: default
827 branch: default
828 commit: (clean)
828 commit: (clean)
829 update: 7 new changesets (update)
829 update: 7 new changesets (update)
830
830
831 $ rm "${USERCACHE}"/*
831 $ rm "${USERCACHE}"/*
832 $ hg clone --all-largefiles -u 1 a a-clone1
832 $ hg clone --all-largefiles -u 1 a a-clone1
833 updating to branch default
833 updating to branch default
834 getting changed largefiles
834 getting changed largefiles
835 2 largefiles updated, 0 removed
835 2 largefiles updated, 0 removed
836 4 files updated, 0 files merged, 0 files removed, 0 files unresolved
836 4 files updated, 0 files merged, 0 files removed, 0 files unresolved
837 8 additional largefiles cached
837 8 additional largefiles cached
838 $ hg -R a-clone1 verify --large --lfa --lfc
838 $ hg -R a-clone1 verify --large --lfa --lfc
839 checking changesets
839 checking changesets
840 checking manifests
840 checking manifests
841 crosschecking files in changesets and manifests
841 crosschecking files in changesets and manifests
842 checking files
842 checking files
843 10 files, 8 changesets, 24 total revisions
843 10 files, 8 changesets, 24 total revisions
844 searching 8 changesets for largefiles
844 searching 8 changesets for largefiles
845 verified contents of 13 revisions of 6 largefiles
845 verified contents of 13 revisions of 6 largefiles
846 $ hg -R a-clone1 sum
846 $ hg -R a-clone1 sum
847 parent: 1:ce8896473775
847 parent: 1:ce8896473775
848 edit files
848 edit files
849 branch: default
849 branch: default
850 commit: (clean)
850 commit: (clean)
851 update: 6 new changesets (update)
851 update: 6 new changesets (update)
852
852
853 $ rm "${USERCACHE}"/*
853 $ rm "${USERCACHE}"/*
854 $ hg clone --all-largefiles -U a a-clone-u
854 $ hg clone --all-largefiles -U a a-clone-u
855 11 additional largefiles cached
855 11 additional largefiles cached
856 $ hg -R a-clone-u sum
856 $ hg -R a-clone-u sum
857 parent: -1:000000000000 (no revision checked out)
857 parent: -1:000000000000 (no revision checked out)
858 branch: default
858 branch: default
859 commit: (clean)
859 commit: (clean)
860 update: 8 new changesets (update)
860 update: 8 new changesets (update)
861
861
862 Show computed destination directory:
862 Show computed destination directory:
863
863
864 $ mkdir xyz
864 $ mkdir xyz
865 $ cd xyz
865 $ cd xyz
866 $ hg clone ../a
866 $ hg clone ../a
867 destination directory: a
867 destination directory: a
868 updating to branch default
868 updating to branch default
869 getting changed largefiles
869 getting changed largefiles
870 3 largefiles updated, 0 removed
870 3 largefiles updated, 0 removed
871 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
871 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
872 $ cd ..
872 $ cd ..
873
873
874 Clone URL without path:
874 Clone URL without path:
875
875
876 $ hg clone file://
876 $ hg clone file://
877 abort: repository / not found!
877 abort: repository / not found!
878 [255]
878 [255]
879
879
880 Ensure base clone command argument validation
880 Ensure base clone command argument validation
881
881
882 $ hg clone -U -u 0 a a-clone-failure
882 $ hg clone -U -u 0 a a-clone-failure
883 abort: cannot specify both --noupdate and --updaterev
883 abort: cannot specify both --noupdate and --updaterev
884 [255]
884 [255]
885
885
886 $ hg clone --all-largefiles a ssh://localhost/a
886 $ hg clone --all-largefiles a ssh://localhost/a
887 abort: --all-largefiles is incompatible with non-local destination ssh://localhost/a
887 abort: --all-largefiles is incompatible with non-local destination ssh://localhost/a
888 [255]
888 [255]
889
889
890 Test pulling with --all-largefiles flag. Also test that the largefiles are
890 Test pulling with --all-largefiles flag. Also test that the largefiles are
891 downloaded from 'default' instead of 'default-push' when no source is specified
891 downloaded from 'default' instead of 'default-push' when no source is specified
892 (issue3584)
892 (issue3584)
893
893
894 $ rm -Rf a-backup
894 $ rm -Rf a-backup
895 $ hg clone -r 1 a a-backup
895 $ hg clone -r 1 a a-backup
896 adding changesets
896 adding changesets
897 adding manifests
897 adding manifests
898 adding file changes
898 adding file changes
899 added 2 changesets with 8 changes to 4 files
899 added 2 changesets with 8 changes to 4 files
900 updating to branch default
900 updating to branch default
901 getting changed largefiles
901 getting changed largefiles
902 2 largefiles updated, 0 removed
902 2 largefiles updated, 0 removed
903 4 files updated, 0 files merged, 0 files removed, 0 files unresolved
903 4 files updated, 0 files merged, 0 files removed, 0 files unresolved
904 $ rm "${USERCACHE}"/*
904 $ rm "${USERCACHE}"/*
905 $ cd a-backup
905 $ cd a-backup
906 $ hg pull --all-largefiles --config paths.default-push=bogus/path
906 $ hg pull --all-largefiles --config paths.default-push=bogus/path
907 pulling from $TESTTMP/a (glob)
907 pulling from $TESTTMP/a (glob)
908 searching for changes
908 searching for changes
909 adding changesets
909 adding changesets
910 adding manifests
910 adding manifests
911 adding file changes
911 adding file changes
912 added 6 changesets with 16 changes to 8 files
912 added 6 changesets with 16 changes to 8 files
913 (run 'hg update' to get a working copy)
913 (run 'hg update' to get a working copy)
914 6 additional largefiles cached
914 6 additional largefiles cached
915 $ cd ..
915 $ cd ..
916
916
917 Rebasing between two repositories does not revert largefiles to old
917 Rebasing between two repositories does not revert largefiles to old
918 revisions (this was a very bad bug that took a lot of work to fix).
918 revisions (this was a very bad bug that took a lot of work to fix).
919
919
920 $ hg clone a d
920 $ hg clone a d
921 updating to branch default
921 updating to branch default
922 getting changed largefiles
922 getting changed largefiles
923 3 largefiles updated, 0 removed
923 3 largefiles updated, 0 removed
924 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
924 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
925 $ cd b
925 $ cd b
926 $ echo large4-modified > sub/large4
926 $ echo large4-modified > sub/large4
927 $ echo normal3-modified > normal3
927 $ echo normal3-modified > normal3
928 $ hg commit -m "modify normal file and largefile in repo b"
928 $ hg commit -m "modify normal file and largefile in repo b"
929 Invoking status precommit hook
929 Invoking status precommit hook
930 M normal3
930 M normal3
931 M sub/large4
931 M sub/large4
932 $ cd ../d
932 $ cd ../d
933 $ echo large6-modified > sub2/large6
933 $ echo large6-modified > sub2/large6
934 $ echo normal4-modified > sub/normal4
934 $ echo normal4-modified > sub/normal4
935 $ hg commit -m "modify normal file largefile in repo d"
935 $ hg commit -m "modify normal file largefile in repo d"
936 Invoking status precommit hook
936 Invoking status precommit hook
937 M sub/normal4
937 M sub/normal4
938 M sub2/large6
938 M sub2/large6
939 $ cd ..
939 $ cd ..
940 $ hg clone d e
940 $ hg clone d e
941 updating to branch default
941 updating to branch default
942 getting changed largefiles
942 getting changed largefiles
943 3 largefiles updated, 0 removed
943 3 largefiles updated, 0 removed
944 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
944 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
945 $ cd d
945 $ cd d
946
946
947 More rebase testing, but also test that the largefiles are downloaded from
947 More rebase testing, but also test that the largefiles are downloaded from
948 'default-push' when no source is specified (issue3584). (The largefile from the
948 'default-push' when no source is specified (issue3584). (The largefile from the
949 pulled revision is however not downloaded but found in the local cache.)
949 pulled revision is however not downloaded but found in the local cache.)
950 Largefiles are fetched for the new pulled revision, not for existing revisions,
950 Largefiles are fetched for the new pulled revision, not for existing revisions,
951 rebased or not.
951 rebased or not.
952
952
953 $ [ ! -f .hg/largefiles/e166e74c7303192238d60af5a9c4ce9bef0b7928 ]
953 $ [ ! -f .hg/largefiles/e166e74c7303192238d60af5a9c4ce9bef0b7928 ]
954 $ hg pull --rebase --all-largefiles --config paths.default-push=bogus/path --config paths.default=../b
954 $ hg pull --rebase --all-largefiles --config paths.default-push=bogus/path --config paths.default=../b
955 pulling from $TESTTMP/b (glob)
955 pulling from $TESTTMP/b (glob)
956 searching for changes
956 searching for changes
957 adding changesets
957 adding changesets
958 adding manifests
958 adding manifests
959 adding file changes
959 adding file changes
960 added 1 changesets with 2 changes to 2 files (+1 heads)
960 added 1 changesets with 2 changes to 2 files (+1 heads)
961 Invoking status precommit hook
961 Invoking status precommit hook
962 M sub/normal4
962 M sub/normal4
963 M sub2/large6
963 M sub2/large6
964 saved backup bundle to $TESTTMP/d/.hg/strip-backup/f574fb32bb45-backup.hg (glob)
964 saved backup bundle to $TESTTMP/d/.hg/strip-backup/f574fb32bb45-backup.hg (glob)
965 0 additional largefiles cached
965 0 additional largefiles cached
966 nothing to rebase
966 nothing to rebase
967 $ [ -f .hg/largefiles/e166e74c7303192238d60af5a9c4ce9bef0b7928 ]
967 $ [ -f .hg/largefiles/e166e74c7303192238d60af5a9c4ce9bef0b7928 ]
968 $ hg log --template '{rev}:{node|short} {desc|firstline}\n'
968 $ hg log --template '{rev}:{node|short} {desc|firstline}\n'
969 9:598410d3eb9a modify normal file largefile in repo d
969 9:598410d3eb9a modify normal file largefile in repo d
970 8:a381d2c8c80e modify normal file and largefile in repo b
970 8:a381d2c8c80e modify normal file and largefile in repo b
971 7:daea875e9014 add/edit more largefiles
971 7:daea875e9014 add/edit more largefiles
972 6:4355d653f84f edit files yet again
972 6:4355d653f84f edit files yet again
973 5:9d5af5072dbd edit files again
973 5:9d5af5072dbd edit files again
974 4:74c02385b94c move files
974 4:74c02385b94c move files
975 3:9e8fbc4bce62 copy files
975 3:9e8fbc4bce62 copy files
976 2:51a0ae4d5864 remove files
976 2:51a0ae4d5864 remove files
977 1:ce8896473775 edit files
977 1:ce8896473775 edit files
978 0:30d30fe6a5be add files
978 0:30d30fe6a5be add files
979 $ cat normal3
979 $ cat normal3
980 normal3-modified
980 normal3-modified
981 $ cat sub/normal4
981 $ cat sub/normal4
982 normal4-modified
982 normal4-modified
983 $ cat sub/large4
983 $ cat sub/large4
984 large4-modified
984 large4-modified
985 $ cat sub2/large6
985 $ cat sub2/large6
986 large6-modified
986 large6-modified
987 $ cat sub2/large7
987 $ cat sub2/large7
988 large7
988 large7
989 $ cd ../e
989 $ cd ../e
990 $ hg pull ../b
990 $ hg pull ../b
991 pulling from ../b
991 pulling from ../b
992 searching for changes
992 searching for changes
993 adding changesets
993 adding changesets
994 adding manifests
994 adding manifests
995 adding file changes
995 adding file changes
996 added 1 changesets with 2 changes to 2 files (+1 heads)
996 added 1 changesets with 2 changes to 2 files (+1 heads)
997 (run 'hg heads' to see heads, 'hg merge' to merge)
997 (run 'hg heads' to see heads, 'hg merge' to merge)
998 $ hg rebase
998 $ hg rebase
999 Invoking status precommit hook
999 Invoking status precommit hook
1000 M sub/normal4
1000 M sub/normal4
1001 M sub2/large6
1001 M sub2/large6
1002 saved backup bundle to $TESTTMP/e/.hg/strip-backup/f574fb32bb45-backup.hg (glob)
1002 saved backup bundle to $TESTTMP/e/.hg/strip-backup/f574fb32bb45-backup.hg (glob)
1003 $ hg log --template '{rev}:{node|short} {desc|firstline}\n'
1003 $ hg log --template '{rev}:{node|short} {desc|firstline}\n'
1004 9:598410d3eb9a modify normal file largefile in repo d
1004 9:598410d3eb9a modify normal file largefile in repo d
1005 8:a381d2c8c80e modify normal file and largefile in repo b
1005 8:a381d2c8c80e modify normal file and largefile in repo b
1006 7:daea875e9014 add/edit more largefiles
1006 7:daea875e9014 add/edit more largefiles
1007 6:4355d653f84f edit files yet again
1007 6:4355d653f84f edit files yet again
1008 5:9d5af5072dbd edit files again
1008 5:9d5af5072dbd edit files again
1009 4:74c02385b94c move files
1009 4:74c02385b94c move files
1010 3:9e8fbc4bce62 copy files
1010 3:9e8fbc4bce62 copy files
1011 2:51a0ae4d5864 remove files
1011 2:51a0ae4d5864 remove files
1012 1:ce8896473775 edit files
1012 1:ce8896473775 edit files
1013 0:30d30fe6a5be add files
1013 0:30d30fe6a5be add files
1014 $ cat normal3
1014 $ cat normal3
1015 normal3-modified
1015 normal3-modified
1016 $ cat sub/normal4
1016 $ cat sub/normal4
1017 normal4-modified
1017 normal4-modified
1018 $ cat sub/large4
1018 $ cat sub/large4
1019 large4-modified
1019 large4-modified
1020 $ cat sub2/large6
1020 $ cat sub2/large6
1021 large6-modified
1021 large6-modified
1022 $ cat sub2/large7
1022 $ cat sub2/large7
1023 large7
1023 large7
1024
1024
1025 Log on largefiles
1025 Log on largefiles
1026
1026
1027 - same output
1027 - same output
1028 $ hg log --template '{rev}:{node|short} {desc|firstline}\n' .hglf/sub/large4
1028 $ hg log --template '{rev}:{node|short} {desc|firstline}\n' .hglf/sub/large4
1029 8:a381d2c8c80e modify normal file and largefile in repo b
1029 8:a381d2c8c80e modify normal file and largefile in repo b
1030 6:4355d653f84f edit files yet again
1030 6:4355d653f84f edit files yet again
1031 5:9d5af5072dbd edit files again
1031 5:9d5af5072dbd edit files again
1032 4:74c02385b94c move files
1032 4:74c02385b94c move files
1033 $ hg log --template '{rev}:{node|short} {desc|firstline}\n' sub/large4
1033 $ hg log --template '{rev}:{node|short} {desc|firstline}\n' sub/large4
1034 8:a381d2c8c80e modify normal file and largefile in repo b
1034 8:a381d2c8c80e modify normal file and largefile in repo b
1035 6:4355d653f84f edit files yet again
1035 6:4355d653f84f edit files yet again
1036 5:9d5af5072dbd edit files again
1036 5:9d5af5072dbd edit files again
1037 4:74c02385b94c move files
1037 4:74c02385b94c move files
1038
1038
1039 - .hglf only matches largefiles, without .hglf it matches 9 bco sub/normal
1039 - .hglf only matches largefiles, without .hglf it matches 9 bco sub/normal
1040 $ hg log --template '{rev}:{node|short} {desc|firstline}\n' .hglf/sub
1040 $ hg log --template '{rev}:{node|short} {desc|firstline}\n' .hglf/sub
1041 8:a381d2c8c80e modify normal file and largefile in repo b
1041 8:a381d2c8c80e modify normal file and largefile in repo b
1042 6:4355d653f84f edit files yet again
1042 6:4355d653f84f edit files yet again
1043 5:9d5af5072dbd edit files again
1043 5:9d5af5072dbd edit files again
1044 4:74c02385b94c move files
1044 4:74c02385b94c move files
1045 1:ce8896473775 edit files
1045 1:ce8896473775 edit files
1046 0:30d30fe6a5be add files
1046 0:30d30fe6a5be add files
1047 $ hg log --template '{rev}:{node|short} {desc|firstline}\n' sub
1047 $ hg log --template '{rev}:{node|short} {desc|firstline}\n' sub
1048 9:598410d3eb9a modify normal file largefile in repo d
1048 9:598410d3eb9a modify normal file largefile in repo d
1049 8:a381d2c8c80e modify normal file and largefile in repo b
1049 8:a381d2c8c80e modify normal file and largefile in repo b
1050 6:4355d653f84f edit files yet again
1050 6:4355d653f84f edit files yet again
1051 5:9d5af5072dbd edit files again
1051 5:9d5af5072dbd edit files again
1052 4:74c02385b94c move files
1052 4:74c02385b94c move files
1053 1:ce8896473775 edit files
1053 1:ce8896473775 edit files
1054 0:30d30fe6a5be add files
1054 0:30d30fe6a5be add files
1055
1055
1056 - globbing gives same result
1056 - globbing gives same result
1057 $ hg log --template '{rev}:{node|short} {desc|firstline}\n' 'glob:sub/*'
1057 $ hg log --template '{rev}:{node|short} {desc|firstline}\n' 'glob:sub/*'
1058 9:598410d3eb9a modify normal file largefile in repo d
1058 9:598410d3eb9a modify normal file largefile in repo d
1059 8:a381d2c8c80e modify normal file and largefile in repo b
1059 8:a381d2c8c80e modify normal file and largefile in repo b
1060 6:4355d653f84f edit files yet again
1060 6:4355d653f84f edit files yet again
1061 5:9d5af5072dbd edit files again
1061 5:9d5af5072dbd edit files again
1062 4:74c02385b94c move files
1062 4:74c02385b94c move files
1063 1:ce8896473775 edit files
1063 1:ce8896473775 edit files
1064 0:30d30fe6a5be add files
1064 0:30d30fe6a5be add files
1065
1065
1066 Rollback on largefiles.
1066 Rollback on largefiles.
1067
1067
1068 $ echo large4-modified-again > sub/large4
1068 $ echo large4-modified-again > sub/large4
1069 $ hg commit -m "Modify large4 again"
1069 $ hg commit -m "Modify large4 again"
1070 Invoking status precommit hook
1070 Invoking status precommit hook
1071 M sub/large4
1071 M sub/large4
1072 $ hg rollback
1072 $ hg rollback
1073 repository tip rolled back to revision 9 (undo commit)
1073 repository tip rolled back to revision 9 (undo commit)
1074 working directory now based on revision 9
1074 working directory now based on revision 9
1075 $ hg st
1075 $ hg st
1076 M sub/large4
1076 M sub/large4
1077 $ hg log --template '{rev}:{node|short} {desc|firstline}\n'
1077 $ hg log --template '{rev}:{node|short} {desc|firstline}\n'
1078 9:598410d3eb9a modify normal file largefile in repo d
1078 9:598410d3eb9a modify normal file largefile in repo d
1079 8:a381d2c8c80e modify normal file and largefile in repo b
1079 8:a381d2c8c80e modify normal file and largefile in repo b
1080 7:daea875e9014 add/edit more largefiles
1080 7:daea875e9014 add/edit more largefiles
1081 6:4355d653f84f edit files yet again
1081 6:4355d653f84f edit files yet again
1082 5:9d5af5072dbd edit files again
1082 5:9d5af5072dbd edit files again
1083 4:74c02385b94c move files
1083 4:74c02385b94c move files
1084 3:9e8fbc4bce62 copy files
1084 3:9e8fbc4bce62 copy files
1085 2:51a0ae4d5864 remove files
1085 2:51a0ae4d5864 remove files
1086 1:ce8896473775 edit files
1086 1:ce8896473775 edit files
1087 0:30d30fe6a5be add files
1087 0:30d30fe6a5be add files
1088 $ cat sub/large4
1088 $ cat sub/large4
1089 large4-modified-again
1089 large4-modified-again
1090
1090
1091 "update --check" refuses to update with uncommitted changes.
1091 "update --check" refuses to update with uncommitted changes.
1092 $ hg update --check 8
1092 $ hg update --check 8
1093 abort: uncommitted local changes
1093 abort: uncommitted local changes
1094 [255]
1094 [255]
1095
1095
1096 "update --clean" leaves correct largefiles in working copy, even when there is
1096 "update --clean" leaves correct largefiles in working copy, even when there is
1097 .orig files from revert in .hglf.
1097 .orig files from revert in .hglf.
1098
1098
1099 $ echo mistake > sub2/large7
1099 $ echo mistake > sub2/large7
1100 $ hg revert sub2/large7
1100 $ hg revert sub2/large7
1101 $ hg -q update --clean -r null
1101 $ hg -q update --clean -r null
1102 $ hg update --clean
1102 $ hg update --clean
1103 getting changed largefiles
1103 getting changed largefiles
1104 3 largefiles updated, 0 removed
1104 3 largefiles updated, 0 removed
1105 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
1105 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
1106 $ cat normal3
1106 $ cat normal3
1107 normal3-modified
1107 normal3-modified
1108 $ cat sub/normal4
1108 $ cat sub/normal4
1109 normal4-modified
1109 normal4-modified
1110 $ cat sub/large4
1110 $ cat sub/large4
1111 large4-modified
1111 large4-modified
1112 $ cat sub2/large6
1112 $ cat sub2/large6
1113 large6-modified
1113 large6-modified
1114 $ cat sub2/large7
1114 $ cat sub2/large7
1115 large7
1115 large7
1116 $ cat sub2/large7.orig
1116 $ cat sub2/large7.orig
1117 mistake
1117 mistake
1118 $ cat .hglf/sub2/large7.orig
1118 $ cat .hglf/sub2/large7.orig
1119 9dbfb2c79b1c40981b258c3efa1b10b03f18ad31
1119 9dbfb2c79b1c40981b258c3efa1b10b03f18ad31
1120
1120
1121 demonstrate misfeature: .orig file is overwritten on every update -C,
1121 demonstrate misfeature: .orig file is overwritten on every update -C,
1122 also when clean:
1122 also when clean:
1123 $ hg update --clean
1123 $ hg update --clean
1124 getting changed largefiles
1124 getting changed largefiles
1125 0 largefiles updated, 0 removed
1125 0 largefiles updated, 0 removed
1126 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
1126 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
1127 $ cat sub2/large7.orig
1127 $ cat sub2/large7.orig
1128 large7
1128 large7
1129 $ rm sub2/large7.orig .hglf/sub2/large7.orig
1129 $ rm sub2/large7.orig .hglf/sub2/large7.orig
1130
1130
1131 Now "update check" is happy.
1131 Now "update check" is happy.
1132 $ hg update --check 8
1132 $ hg update --check 8
1133 getting changed largefiles
1133 getting changed largefiles
1134 1 largefiles updated, 0 removed
1134 1 largefiles updated, 0 removed
1135 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
1135 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
1136 $ hg update --check
1136 $ hg update --check
1137 getting changed largefiles
1137 getting changed largefiles
1138 1 largefiles updated, 0 removed
1138 1 largefiles updated, 0 removed
1139 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
1139 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
1140
1140
1141 Test removing empty largefiles directories on update
1141 Test removing empty largefiles directories on update
1142 $ test -d sub2 && echo "sub2 exists"
1142 $ test -d sub2 && echo "sub2 exists"
1143 sub2 exists
1143 sub2 exists
1144 $ hg update -q null
1144 $ hg update -q null
1145 $ test -d sub2 && echo "error: sub2 should not exist anymore"
1145 $ test -d sub2 && echo "error: sub2 should not exist anymore"
1146 [1]
1146 [1]
1147 $ hg update -q
1147 $ hg update -q
1148
1148
1149 Test hg remove removes empty largefiles directories
1149 Test hg remove removes empty largefiles directories
1150 $ test -d sub2 && echo "sub2 exists"
1150 $ test -d sub2 && echo "sub2 exists"
1151 sub2 exists
1151 sub2 exists
1152 $ hg remove sub2/*
1152 $ hg remove sub2/*
1153 $ test -d sub2 && echo "error: sub2 should not exist anymore"
1153 $ test -d sub2 && echo "error: sub2 should not exist anymore"
1154 [1]
1154 [1]
1155 $ hg revert sub2/large6 sub2/large7
1155 $ hg revert sub2/large6 sub2/large7
1156
1156
1157 "revert" works on largefiles (and normal files too).
1157 "revert" works on largefiles (and normal files too).
1158 $ echo hack3 >> normal3
1158 $ echo hack3 >> normal3
1159 $ echo hack4 >> sub/normal4
1159 $ echo hack4 >> sub/normal4
1160 $ echo hack4 >> sub/large4
1160 $ echo hack4 >> sub/large4
1161 $ rm sub2/large6
1161 $ rm sub2/large6
1162 $ hg revert sub2/large6
1162 $ hg revert sub2/large6
1163 $ hg rm sub2/large6
1163 $ hg rm sub2/large6
1164 $ echo new >> sub2/large8
1164 $ echo new >> sub2/large8
1165 $ hg add --large sub2/large8
1165 $ hg add --large sub2/large8
1166 # XXX we don't really want to report that we're reverting the standin;
1166 # XXX we don't really want to report that we're reverting the standin;
1167 # that's just an implementation detail. But I don't see an obvious fix. ;-(
1167 # that's just an implementation detail. But I don't see an obvious fix. ;-(
1168 $ hg revert sub
1168 $ hg revert sub
1169 reverting .hglf/sub/large4 (glob)
1169 reverting .hglf/sub/large4 (glob)
1170 reverting sub/normal4 (glob)
1170 reverting sub/normal4 (glob)
1171 $ hg status
1171 $ hg status
1172 M normal3
1172 M normal3
1173 A sub2/large8
1173 A sub2/large8
1174 R sub2/large6
1174 R sub2/large6
1175 ? sub/large4.orig
1175 ? sub/large4.orig
1176 ? sub/normal4.orig
1176 ? sub/normal4.orig
1177 $ cat sub/normal4
1177 $ cat sub/normal4
1178 normal4-modified
1178 normal4-modified
1179 $ cat sub/large4
1179 $ cat sub/large4
1180 large4-modified
1180 large4-modified
1181 $ hg revert -a --no-backup
1181 $ hg revert -a --no-backup
1182 undeleting .hglf/sub2/large6 (glob)
1182 undeleting .hglf/sub2/large6 (glob)
1183 forgetting .hglf/sub2/large8 (glob)
1183 forgetting .hglf/sub2/large8 (glob)
1184 reverting normal3
1184 reverting normal3
1185 $ hg status
1185 $ hg status
1186 ? sub/large4.orig
1186 ? sub/large4.orig
1187 ? sub/normal4.orig
1187 ? sub/normal4.orig
1188 ? sub2/large8
1188 ? sub2/large8
1189 $ cat normal3
1189 $ cat normal3
1190 normal3-modified
1190 normal3-modified
1191 $ cat sub2/large6
1191 $ cat sub2/large6
1192 large6-modified
1192 large6-modified
1193 $ rm sub/*.orig sub2/large8
1193 $ rm sub/*.orig sub2/large8
1194
1194
1195 revert some files to an older revision
1195 revert some files to an older revision
1196 $ hg revert --no-backup -r 8 sub2
1196 $ hg revert --no-backup -r 8 sub2
1197 reverting .hglf/sub2/large6 (glob)
1197 reverting .hglf/sub2/large6 (glob)
1198 $ cat sub2/large6
1198 $ cat sub2/large6
1199 large6
1199 large6
1200 $ hg revert --no-backup -C -r '.^' sub2
1200 $ hg revert --no-backup -C -r '.^' sub2
1201 reverting .hglf/sub2/large6 (glob)
1201 reverting .hglf/sub2/large6 (glob)
1202 $ hg revert --no-backup sub2
1202 $ hg revert --no-backup sub2
1203 reverting .hglf/sub2/large6 (glob)
1203 reverting .hglf/sub2/large6 (glob)
1204 $ hg status
1204 $ hg status
1205
1205
1206 "verify --large" actually verifies largefiles
1206 "verify --large" actually verifies largefiles
1207
1207
1208 - Where Do We Come From? What Are We? Where Are We Going?
1208 - Where Do We Come From? What Are We? Where Are We Going?
1209 $ pwd
1209 $ pwd
1210 $TESTTMP/e
1210 $TESTTMP/e
1211 $ hg paths
1211 $ hg paths
1212 default = $TESTTMP/d (glob)
1212 default = $TESTTMP/d (glob)
1213
1213
1214 $ hg verify --large
1214 $ hg verify --large
1215 checking changesets
1215 checking changesets
1216 checking manifests
1216 checking manifests
1217 crosschecking files in changesets and manifests
1217 crosschecking files in changesets and manifests
1218 checking files
1218 checking files
1219 10 files, 10 changesets, 28 total revisions
1219 10 files, 10 changesets, 28 total revisions
1220 searching 1 changesets for largefiles
1220 searching 1 changesets for largefiles
1221 verified existence of 3 revisions of 3 largefiles
1221 verified existence of 3 revisions of 3 largefiles
1222
1222
1223 - introduce missing blob in local store repo and make sure that this is caught:
1223 - introduce missing blob in local store repo and make sure that this is caught:
1224 $ mv $TESTTMP/d/.hg/largefiles/e166e74c7303192238d60af5a9c4ce9bef0b7928 .
1224 $ mv $TESTTMP/d/.hg/largefiles/e166e74c7303192238d60af5a9c4ce9bef0b7928 .
1225 $ hg verify --large
1225 $ hg verify --large
1226 checking changesets
1226 checking changesets
1227 checking manifests
1227 checking manifests
1228 crosschecking files in changesets and manifests
1228 crosschecking files in changesets and manifests
1229 checking files
1229 checking files
1230 10 files, 10 changesets, 28 total revisions
1230 10 files, 10 changesets, 28 total revisions
1231 searching 1 changesets for largefiles
1231 searching 1 changesets for largefiles
1232 changeset 9:598410d3eb9a: sub/large4 references missing $TESTTMP/d/.hg/largefiles/e166e74c7303192238d60af5a9c4ce9bef0b7928 (glob)
1232 changeset 9:598410d3eb9a: sub/large4 references missing $TESTTMP/d/.hg/largefiles/e166e74c7303192238d60af5a9c4ce9bef0b7928 (glob)
1233 verified existence of 3 revisions of 3 largefiles
1233 verified existence of 3 revisions of 3 largefiles
1234 [1]
1234 [1]
1235
1235
1236 - introduce corruption and make sure that it is caught when checking content:
1236 - introduce corruption and make sure that it is caught when checking content:
1237 $ echo '5 cents' > $TESTTMP/d/.hg/largefiles/e166e74c7303192238d60af5a9c4ce9bef0b7928
1237 $ echo '5 cents' > $TESTTMP/d/.hg/largefiles/e166e74c7303192238d60af5a9c4ce9bef0b7928
1238 $ hg verify -q --large --lfc
1238 $ hg verify -q --large --lfc
1239 changeset 9:598410d3eb9a: sub/large4 references corrupted $TESTTMP/d/.hg/largefiles/e166e74c7303192238d60af5a9c4ce9bef0b7928 (glob)
1239 changeset 9:598410d3eb9a: sub/large4 references corrupted $TESTTMP/d/.hg/largefiles/e166e74c7303192238d60af5a9c4ce9bef0b7928 (glob)
1240 [1]
1240 [1]
1241
1241
1242 - cleanup
1242 - cleanup
1243 $ mv e166e74c7303192238d60af5a9c4ce9bef0b7928 $TESTTMP/d/.hg/largefiles/
1243 $ mv e166e74c7303192238d60af5a9c4ce9bef0b7928 $TESTTMP/d/.hg/largefiles/
1244
1244
1245 - verifying all revisions will fail because we didn't clone all largefiles to d:
1245 - verifying all revisions will fail because we didn't clone all largefiles to d:
1246 $ echo 'T-shirt' > $TESTTMP/d/.hg/largefiles/eb7338044dc27f9bc59b8dd5a246b065ead7a9c4
1246 $ echo 'T-shirt' > $TESTTMP/d/.hg/largefiles/eb7338044dc27f9bc59b8dd5a246b065ead7a9c4
1247 $ hg verify -q --lfa --lfc
1247 $ hg verify -q --lfa --lfc
1248 changeset 0:30d30fe6a5be: large1 references missing $TESTTMP/d/.hg/largefiles/4669e532d5b2c093a78eca010077e708a071bb64 (glob)
1248 changeset 0:30d30fe6a5be: large1 references missing $TESTTMP/d/.hg/largefiles/4669e532d5b2c093a78eca010077e708a071bb64 (glob)
1249 changeset 0:30d30fe6a5be: sub/large2 references missing $TESTTMP/d/.hg/largefiles/1deebade43c8c498a3c8daddac0244dc55d1331d (glob)
1249 changeset 0:30d30fe6a5be: sub/large2 references missing $TESTTMP/d/.hg/largefiles/1deebade43c8c498a3c8daddac0244dc55d1331d (glob)
1250 changeset 1:ce8896473775: large1 references missing $TESTTMP/d/.hg/largefiles/5f78770c0e77ba4287ad6ef3071c9bf9c379742f (glob)
1250 changeset 1:ce8896473775: large1 references missing $TESTTMP/d/.hg/largefiles/5f78770c0e77ba4287ad6ef3071c9bf9c379742f (glob)
1251 changeset 1:ce8896473775: sub/large2 references corrupted $TESTTMP/d/.hg/largefiles/eb7338044dc27f9bc59b8dd5a246b065ead7a9c4 (glob)
1251 changeset 1:ce8896473775: sub/large2 references corrupted $TESTTMP/d/.hg/largefiles/eb7338044dc27f9bc59b8dd5a246b065ead7a9c4 (glob)
1252 changeset 3:9e8fbc4bce62: large1 references corrupted $TESTTMP/d/.hg/largefiles/eb7338044dc27f9bc59b8dd5a246b065ead7a9c4 (glob)
1252 changeset 3:9e8fbc4bce62: large1 references corrupted $TESTTMP/d/.hg/largefiles/eb7338044dc27f9bc59b8dd5a246b065ead7a9c4 (glob)
1253 changeset 4:74c02385b94c: large3 references corrupted $TESTTMP/d/.hg/largefiles/eb7338044dc27f9bc59b8dd5a246b065ead7a9c4 (glob)
1253 changeset 4:74c02385b94c: large3 references corrupted $TESTTMP/d/.hg/largefiles/eb7338044dc27f9bc59b8dd5a246b065ead7a9c4 (glob)
1254 changeset 4:74c02385b94c: sub/large4 references corrupted $TESTTMP/d/.hg/largefiles/eb7338044dc27f9bc59b8dd5a246b065ead7a9c4 (glob)
1254 changeset 4:74c02385b94c: sub/large4 references corrupted $TESTTMP/d/.hg/largefiles/eb7338044dc27f9bc59b8dd5a246b065ead7a9c4 (glob)
1255 changeset 5:9d5af5072dbd: large3 references missing $TESTTMP/d/.hg/largefiles/baaf12afde9d8d67f25dab6dced0d2bf77dba47c (glob)
1255 changeset 5:9d5af5072dbd: large3 references missing $TESTTMP/d/.hg/largefiles/baaf12afde9d8d67f25dab6dced0d2bf77dba47c (glob)
1256 changeset 5:9d5af5072dbd: sub/large4 references missing $TESTTMP/d/.hg/largefiles/aeb2210d19f02886dde00dac279729a48471e2f9 (glob)
1256 changeset 5:9d5af5072dbd: sub/large4 references missing $TESTTMP/d/.hg/largefiles/aeb2210d19f02886dde00dac279729a48471e2f9 (glob)
1257 changeset 6:4355d653f84f: large3 references missing $TESTTMP/d/.hg/largefiles/7838695e10da2bb75ac1156565f40a2595fa2fa0 (glob)
1257 changeset 6:4355d653f84f: large3 references missing $TESTTMP/d/.hg/largefiles/7838695e10da2bb75ac1156565f40a2595fa2fa0 (glob)
1258 [1]
1258 [1]
1259
1259
1260 - cleanup
1260 - cleanup
1261 $ rm $TESTTMP/d/.hg/largefiles/eb7338044dc27f9bc59b8dd5a246b065ead7a9c4
1261 $ rm $TESTTMP/d/.hg/largefiles/eb7338044dc27f9bc59b8dd5a246b065ead7a9c4
1262 $ rm -f .hglf/sub/*.orig
1262 $ rm -f .hglf/sub/*.orig
1263
1263
1264 Update to revision with missing largefile - and make sure it really is missing
1264 Update to revision with missing largefile - and make sure it really is missing
1265
1265
1266 $ rm ${USERCACHE}/7838695e10da2bb75ac1156565f40a2595fa2fa0
1266 $ rm ${USERCACHE}/7838695e10da2bb75ac1156565f40a2595fa2fa0
1267 $ hg up -r 6
1267 $ hg up -r 6
1268 getting changed largefiles
1268 getting changed largefiles
1269 error getting id 7838695e10da2bb75ac1156565f40a2595fa2fa0 from url file:$TESTTMP/d for file large3: can't get file locally (glob)
1269 error getting id 7838695e10da2bb75ac1156565f40a2595fa2fa0 from url file:$TESTTMP/d for file large3: can't get file locally (glob)
1270 1 largefiles updated, 2 removed
1270 1 largefiles updated, 2 removed
1271 4 files updated, 0 files merged, 2 files removed, 0 files unresolved
1271 4 files updated, 0 files merged, 2 files removed, 0 files unresolved
1272 $ rm normal3
1272 $ rm normal3
1273 $ echo >> sub/normal4
1273 $ echo >> sub/normal4
1274 $ hg ci -m 'commit with missing files'
1274 $ hg ci -m 'commit with missing files'
1275 Invoking status precommit hook
1275 Invoking status precommit hook
1276 M sub/normal4
1276 M sub/normal4
1277 ! large3
1277 ! large3
1278 ! normal3
1278 ! normal3
1279 created new head
1279 created new head
1280 $ hg st
1280 $ hg st
1281 ! large3
1281 ! large3
1282 ! normal3
1282 ! normal3
1283 $ hg up -r.
1283 $ hg up -r.
1284 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
1284 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
1285 $ hg st
1285 $ hg st
1286 ! large3
1286 ! large3
1287 ! normal3
1287 ! normal3
1288 $ hg up -Cr.
1288 $ hg up -Cr.
1289 getting changed largefiles
1289 getting changed largefiles
1290 error getting id 7838695e10da2bb75ac1156565f40a2595fa2fa0 from url file:$TESTTMP/d for file large3: can't get file locally (glob)
1290 error getting id 7838695e10da2bb75ac1156565f40a2595fa2fa0 from url file:$TESTTMP/d for file large3: can't get file locally (glob)
1291 0 largefiles updated, 0 removed
1291 0 largefiles updated, 0 removed
1292 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1292 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1293 $ hg st
1293 $ hg st
1294 ! large3
1294 ! large3
1295 $ hg rollback
1295 $ hg rollback
1296 repository tip rolled back to revision 9 (undo commit)
1296 repository tip rolled back to revision 9 (undo commit)
1297 working directory now based on revision 6
1297 working directory now based on revision 6
1298
1298
1299 Merge with revision with missing largefile - and make sure it tries to fetch it.
1299 Merge with revision with missing largefile - and make sure it tries to fetch it.
1300
1300
1301 $ hg up -Cqr null
1301 $ hg up -Cqr null
1302 $ echo f > f
1302 $ echo f > f
1303 $ hg ci -Am branch
1303 $ hg ci -Am branch
1304 adding f
1304 adding f
1305 Invoking status precommit hook
1305 Invoking status precommit hook
1306 A f
1306 A f
1307 created new head
1307 created new head
1308 $ hg merge -r 6
1308 $ hg merge -r 6
1309 4 files updated, 0 files merged, 0 files removed, 0 files unresolved
1309 4 files updated, 0 files merged, 0 files removed, 0 files unresolved
1310 (branch merge, don't forget to commit)
1310 (branch merge, don't forget to commit)
1311 getting changed largefiles
1311 getting changed largefiles
1312 error getting id 7838695e10da2bb75ac1156565f40a2595fa2fa0 from url file:$TESTTMP/d for file large3: can't get file locally (glob)
1312 error getting id 7838695e10da2bb75ac1156565f40a2595fa2fa0 from url file:$TESTTMP/d for file large3: can't get file locally (glob)
1313 1 largefiles updated, 0 removed
1313 1 largefiles updated, 0 removed
1314
1314
1315 $ hg rollback -q
1315 $ hg rollback -q
1316 $ hg up -Cq
1316 $ hg up -Cq
1317
1317
1318 Pulling 0 revisions with --all-largefiles should not fetch for all revisions
1318 Pulling 0 revisions with --all-largefiles should not fetch for all revisions
1319
1319
1320 $ hg pull --all-largefiles
1320 $ hg pull --all-largefiles
1321 pulling from $TESTTMP/d (glob)
1321 pulling from $TESTTMP/d (glob)
1322 searching for changes
1322 searching for changes
1323 no changes found
1323 no changes found
1324 0 additional largefiles cached
1324 0 additional largefiles cached
1325
1325
1326 Merging does not revert to old versions of largefiles and also check
1326 Merging does not revert to old versions of largefiles and also check
1327 that merging after having pulled from a non-default remote works
1327 that merging after having pulled from a non-default remote works
1328 correctly.
1328 correctly.
1329
1329
1330 $ cd ..
1330 $ cd ..
1331 $ hg clone -r 7 e temp
1331 $ hg clone -r 7 e temp
1332 adding changesets
1332 adding changesets
1333 adding manifests
1333 adding manifests
1334 adding file changes
1334 adding file changes
1335 added 8 changesets with 24 changes to 10 files
1335 added 8 changesets with 24 changes to 10 files
1336 updating to branch default
1336 updating to branch default
1337 getting changed largefiles
1337 getting changed largefiles
1338 3 largefiles updated, 0 removed
1338 3 largefiles updated, 0 removed
1339 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
1339 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
1340 $ hg clone temp f
1340 $ hg clone temp f
1341 updating to branch default
1341 updating to branch default
1342 getting changed largefiles
1342 getting changed largefiles
1343 3 largefiles updated, 0 removed
1343 3 largefiles updated, 0 removed
1344 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
1344 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
1345 # Delete the largefiles in the largefiles system cache so that we have an
1345 # Delete the largefiles in the largefiles system cache so that we have an
1346 # opportunity to test that caching after a pull works.
1346 # opportunity to test that caching after a pull works.
1347 $ rm "${USERCACHE}"/*
1347 $ rm "${USERCACHE}"/*
1348 $ cd f
1348 $ cd f
1349 $ echo "large4-merge-test" > sub/large4
1349 $ echo "large4-merge-test" > sub/large4
1350 $ hg commit -m "Modify large4 to test merge"
1350 $ hg commit -m "Modify large4 to test merge"
1351 Invoking status precommit hook
1351 Invoking status precommit hook
1352 M sub/large4
1352 M sub/large4
1353 # Test --cache-largefiles flag
1353 # Test --cache-largefiles flag
1354 $ hg pull --cache-largefiles ../e
1354 $ hg pull --cache-largefiles ../e
1355 pulling from ../e
1355 pulling from ../e
1356 searching for changes
1356 searching for changes
1357 adding changesets
1357 adding changesets
1358 adding manifests
1358 adding manifests
1359 adding file changes
1359 adding file changes
1360 added 2 changesets with 4 changes to 4 files (+1 heads)
1360 added 2 changesets with 4 changes to 4 files (+1 heads)
1361 (run 'hg heads' to see heads, 'hg merge' to merge)
1361 (run 'hg heads' to see heads, 'hg merge' to merge)
1362 caching largefiles for 1 heads
1362 caching largefiles for 1 heads
1363 2 largefiles cached
1363 2 largefiles cached
1364 $ hg merge
1364 $ hg merge
1365 merging sub/large4
1365 merging sub/large4
1366 largefile sub/large4 has a merge conflict
1366 largefile sub/large4 has a merge conflict
1367 keep (l)ocal or take (o)ther? l
1367 keep (l)ocal or take (o)ther? l
1368 3 files updated, 1 files merged, 0 files removed, 0 files unresolved
1368 3 files updated, 1 files merged, 0 files removed, 0 files unresolved
1369 (branch merge, don't forget to commit)
1369 (branch merge, don't forget to commit)
1370 getting changed largefiles
1370 getting changed largefiles
1371 1 largefiles updated, 0 removed
1371 1 largefiles updated, 0 removed
1372 $ hg commit -m "Merge repos e and f"
1372 $ hg commit -m "Merge repos e and f"
1373 Invoking status precommit hook
1373 Invoking status precommit hook
1374 M normal3
1374 M normal3
1375 M sub/normal4
1375 M sub/normal4
1376 M sub2/large6
1376 M sub2/large6
1377 $ cat normal3
1377 $ cat normal3
1378 normal3-modified
1378 normal3-modified
1379 $ cat sub/normal4
1379 $ cat sub/normal4
1380 normal4-modified
1380 normal4-modified
1381 $ cat sub/large4
1381 $ cat sub/large4
1382 large4-merge-test
1382 large4-merge-test
1383 $ cat sub2/large6
1383 $ cat sub2/large6
1384 large6-modified
1384 large6-modified
1385 $ cat sub2/large7
1385 $ cat sub2/large7
1386 large7
1386 large7
1387
1387
1388 Test status after merging with a branch that introduces a new largefile:
1388 Test status after merging with a branch that introduces a new largefile:
1389
1389
1390 $ echo large > large
1390 $ echo large > large
1391 $ hg add --large large
1391 $ hg add --large large
1392 $ hg commit -m 'add largefile'
1392 $ hg commit -m 'add largefile'
1393 Invoking status precommit hook
1393 Invoking status precommit hook
1394 A large
1394 A large
1395 $ hg update -q ".^"
1395 $ hg update -q ".^"
1396 $ echo change >> normal3
1396 $ echo change >> normal3
1397 $ hg commit -m 'some change'
1397 $ hg commit -m 'some change'
1398 Invoking status precommit hook
1398 Invoking status precommit hook
1399 M normal3
1399 M normal3
1400 created new head
1400 created new head
1401 $ hg merge
1401 $ hg merge
1402 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1402 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1403 (branch merge, don't forget to commit)
1403 (branch merge, don't forget to commit)
1404 getting changed largefiles
1404 getting changed largefiles
1405 1 largefiles updated, 0 removed
1405 1 largefiles updated, 0 removed
1406 $ hg status
1406 $ hg status
1407 M large
1407 M large
1408
1408
1409 - make sure update of merge with removed largefiles fails as expected
1409 - make sure update of merge with removed largefiles fails as expected
1410 $ hg rm sub2/large6
1410 $ hg rm sub2/large6
1411 $ hg up -r.
1411 $ hg up -r.
1412 abort: outstanding uncommitted merges
1412 abort: outstanding uncommitted merges
1413 [255]
1413 [255]
1414
1414
1415 - revert should be able to revert files introduced in a pending merge
1415 - revert should be able to revert files introduced in a pending merge
1416 $ hg revert --all -r .
1416 $ hg revert --all -r .
1417 removing .hglf/large (glob)
1417 removing .hglf/large (glob)
1418 undeleting .hglf/sub2/large6 (glob)
1418 undeleting .hglf/sub2/large6 (glob)
1419
1419
1420 Test that a normal file and a largefile with the same name and path cannot
1420 Test that a normal file and a largefile with the same name and path cannot
1421 coexist.
1421 coexist.
1422
1422
1423 $ rm sub2/large7
1423 $ rm sub2/large7
1424 $ echo "largeasnormal" > sub2/large7
1424 $ echo "largeasnormal" > sub2/large7
1425 $ hg add sub2/large7
1425 $ hg add sub2/large7
1426 sub2/large7 already a largefile
1426 sub2/large7 already a largefile
1427
1427
1428 Test that transplanting a largefile change works correctly.
1428 Test that transplanting a largefile change works correctly.
1429
1429
1430 $ cd ..
1430 $ cd ..
1431 $ hg clone -r 8 d g
1431 $ hg clone -r 8 d g
1432 adding changesets
1432 adding changesets
1433 adding manifests
1433 adding manifests
1434 adding file changes
1434 adding file changes
1435 added 9 changesets with 26 changes to 10 files
1435 added 9 changesets with 26 changes to 10 files
1436 updating to branch default
1436 updating to branch default
1437 getting changed largefiles
1437 getting changed largefiles
1438 3 largefiles updated, 0 removed
1438 3 largefiles updated, 0 removed
1439 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
1439 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
1440 $ cd g
1440 $ cd g
1441 $ hg transplant -s ../d 598410d3eb9a
1441 $ hg transplant -s ../d 598410d3eb9a
1442 searching for changes
1442 searching for changes
1443 searching for changes
1443 searching for changes
1444 adding changesets
1444 adding changesets
1445 adding manifests
1445 adding manifests
1446 adding file changes
1446 adding file changes
1447 added 1 changesets with 2 changes to 2 files
1447 added 1 changesets with 2 changes to 2 files
1448 getting changed largefiles
1448 getting changed largefiles
1449 1 largefiles updated, 0 removed
1449 1 largefiles updated, 0 removed
1450 $ hg log --template '{rev}:{node|short} {desc|firstline}\n'
1450 $ hg log --template '{rev}:{node|short} {desc|firstline}\n'
1451 9:598410d3eb9a modify normal file largefile in repo d
1451 9:598410d3eb9a modify normal file largefile in repo d
1452 8:a381d2c8c80e modify normal file and largefile in repo b
1452 8:a381d2c8c80e modify normal file and largefile in repo b
1453 7:daea875e9014 add/edit more largefiles
1453 7:daea875e9014 add/edit more largefiles
1454 6:4355d653f84f edit files yet again
1454 6:4355d653f84f edit files yet again
1455 5:9d5af5072dbd edit files again
1455 5:9d5af5072dbd edit files again
1456 4:74c02385b94c move files
1456 4:74c02385b94c move files
1457 3:9e8fbc4bce62 copy files
1457 3:9e8fbc4bce62 copy files
1458 2:51a0ae4d5864 remove files
1458 2:51a0ae4d5864 remove files
1459 1:ce8896473775 edit files
1459 1:ce8896473775 edit files
1460 0:30d30fe6a5be add files
1460 0:30d30fe6a5be add files
1461 $ cat normal3
1461 $ cat normal3
1462 normal3-modified
1462 normal3-modified
1463 $ cat sub/normal4
1463 $ cat sub/normal4
1464 normal4-modified
1464 normal4-modified
1465 $ cat sub/large4
1465 $ cat sub/large4
1466 large4-modified
1466 large4-modified
1467 $ cat sub2/large6
1467 $ cat sub2/large6
1468 large6-modified
1468 large6-modified
1469 $ cat sub2/large7
1469 $ cat sub2/large7
1470 large7
1470 large7
1471
1471
1472 Cat a largefile
1472 Cat a largefile
1473 $ hg cat normal3
1473 $ hg cat normal3
1474 normal3-modified
1474 normal3-modified
1475 $ hg cat sub/large4
1475 $ hg cat sub/large4
1476 large4-modified
1476 large4-modified
1477 $ rm "${USERCACHE}"/*
1477 $ rm "${USERCACHE}"/*
1478 $ hg cat -r a381d2c8c80e -o cat.out sub/large4
1478 $ hg cat -r a381d2c8c80e -o cat.out sub/large4
1479 $ cat cat.out
1479 $ cat cat.out
1480 large4-modified
1480 large4-modified
1481 $ rm cat.out
1481 $ rm cat.out
1482 $ hg cat -r a381d2c8c80e normal3
1482 $ hg cat -r a381d2c8c80e normal3
1483 normal3-modified
1483 normal3-modified
1484 $ hg cat -r '.^' normal3
1484 $ hg cat -r '.^' normal3
1485 normal3-modified
1485 normal3-modified
1486 $ hg cat -r '.^' sub/large4 doesntexist
1486 $ hg cat -r '.^' sub/large4 doesntexist
1487 large4-modified
1487 large4-modified
1488 doesntexist: no such file in rev a381d2c8c80e
1488 doesntexist: no such file in rev a381d2c8c80e
1489 [1]
1489 $ hg --cwd sub cat -r '.^' large4
1490 large4-modified
1491 $ hg --cwd sub cat -r '.^' ../normal3
1492 normal3-modified
1490
1493
1491 Test that renaming a largefile results in correct output for status
1494 Test that renaming a largefile results in correct output for status
1492
1495
1493 $ hg rename sub/large4 large4-renamed
1496 $ hg rename sub/large4 large4-renamed
1494 $ hg commit -m "test rename output"
1497 $ hg commit -m "test rename output"
1495 Invoking status precommit hook
1498 Invoking status precommit hook
1496 A large4-renamed
1499 A large4-renamed
1497 R sub/large4
1500 R sub/large4
1498 $ cat large4-renamed
1501 $ cat large4-renamed
1499 large4-modified
1502 large4-modified
1500 $ cd sub2
1503 $ cd sub2
1501 $ hg rename large6 large6-renamed
1504 $ hg rename large6 large6-renamed
1502 $ hg st
1505 $ hg st
1503 A sub2/large6-renamed
1506 A sub2/large6-renamed
1504 R sub2/large6
1507 R sub2/large6
1505 $ cd ..
1508 $ cd ..
1506
1509
1507 Test --normal flag
1510 Test --normal flag
1508
1511
1509 $ dd if=/dev/zero bs=2k count=11k > new-largefile 2> /dev/null
1512 $ dd if=/dev/zero bs=2k count=11k > new-largefile 2> /dev/null
1510 $ hg add --normal --large new-largefile
1513 $ hg add --normal --large new-largefile
1511 abort: --normal cannot be used with --large
1514 abort: --normal cannot be used with --large
1512 [255]
1515 [255]
1513 $ hg add --normal new-largefile
1516 $ hg add --normal new-largefile
1514 new-largefile: up to 69 MB of RAM may be required to manage this file
1517 new-largefile: up to 69 MB of RAM may be required to manage this file
1515 (use 'hg revert new-largefile' to cancel the pending addition)
1518 (use 'hg revert new-largefile' to cancel the pending addition)
1516 $ cd ..
1519 $ cd ..
1517
1520
1518 #if serve
1521 #if serve
1519 vanilla clients not locked out from largefiles servers on vanilla repos
1522 vanilla clients not locked out from largefiles servers on vanilla repos
1520 $ mkdir r1
1523 $ mkdir r1
1521 $ cd r1
1524 $ cd r1
1522 $ hg init
1525 $ hg init
1523 $ echo c1 > f1
1526 $ echo c1 > f1
1524 $ hg add f1
1527 $ hg add f1
1525 $ hg commit -m "m1"
1528 $ hg commit -m "m1"
1526 Invoking status precommit hook
1529 Invoking status precommit hook
1527 A f1
1530 A f1
1528 $ cd ..
1531 $ cd ..
1529 $ hg serve -R r1 -d -p $HGPORT --pid-file hg.pid
1532 $ hg serve -R r1 -d -p $HGPORT --pid-file hg.pid
1530 $ cat hg.pid >> $DAEMON_PIDS
1533 $ cat hg.pid >> $DAEMON_PIDS
1531 $ hg --config extensions.largefiles=! clone http://localhost:$HGPORT r2
1534 $ hg --config extensions.largefiles=! clone http://localhost:$HGPORT r2
1532 requesting all changes
1535 requesting all changes
1533 adding changesets
1536 adding changesets
1534 adding manifests
1537 adding manifests
1535 adding file changes
1538 adding file changes
1536 added 1 changesets with 1 changes to 1 files
1539 added 1 changesets with 1 changes to 1 files
1537 updating to branch default
1540 updating to branch default
1538 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1541 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1539
1542
1540 largefiles clients still work with vanilla servers
1543 largefiles clients still work with vanilla servers
1541 $ hg --config extensions.largefiles=! serve -R r1 -d -p $HGPORT1 --pid-file hg.pid
1544 $ hg --config extensions.largefiles=! serve -R r1 -d -p $HGPORT1 --pid-file hg.pid
1542 $ cat hg.pid >> $DAEMON_PIDS
1545 $ cat hg.pid >> $DAEMON_PIDS
1543 $ hg clone http://localhost:$HGPORT1 r3
1546 $ hg clone http://localhost:$HGPORT1 r3
1544 requesting all changes
1547 requesting all changes
1545 adding changesets
1548 adding changesets
1546 adding manifests
1549 adding manifests
1547 adding file changes
1550 adding file changes
1548 added 1 changesets with 1 changes to 1 files
1551 added 1 changesets with 1 changes to 1 files
1549 updating to branch default
1552 updating to branch default
1550 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1553 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1551 #endif
1554 #endif
1552
1555
1553
1556
1554 vanilla clients locked out from largefiles http repos
1557 vanilla clients locked out from largefiles http repos
1555 $ mkdir r4
1558 $ mkdir r4
1556 $ cd r4
1559 $ cd r4
1557 $ hg init
1560 $ hg init
1558 $ echo c1 > f1
1561 $ echo c1 > f1
1559 $ hg add --large f1
1562 $ hg add --large f1
1560 $ hg commit -m "m1"
1563 $ hg commit -m "m1"
1561 Invoking status precommit hook
1564 Invoking status precommit hook
1562 A f1
1565 A f1
1563 $ cd ..
1566 $ cd ..
1564
1567
1565 largefiles can be pushed locally (issue3583)
1568 largefiles can be pushed locally (issue3583)
1566 $ hg init dest
1569 $ hg init dest
1567 $ cd r4
1570 $ cd r4
1568 $ hg outgoing ../dest
1571 $ hg outgoing ../dest
1569 comparing with ../dest
1572 comparing with ../dest
1570 searching for changes
1573 searching for changes
1571 changeset: 0:639881c12b4c
1574 changeset: 0:639881c12b4c
1572 tag: tip
1575 tag: tip
1573 user: test
1576 user: test
1574 date: Thu Jan 01 00:00:00 1970 +0000
1577 date: Thu Jan 01 00:00:00 1970 +0000
1575 summary: m1
1578 summary: m1
1576
1579
1577 $ hg push ../dest
1580 $ hg push ../dest
1578 pushing to ../dest
1581 pushing to ../dest
1579 searching for changes
1582 searching for changes
1580 searching for changes
1583 searching for changes
1581 adding changesets
1584 adding changesets
1582 adding manifests
1585 adding manifests
1583 adding file changes
1586 adding file changes
1584 added 1 changesets with 1 changes to 1 files
1587 added 1 changesets with 1 changes to 1 files
1585
1588
1586 exit code with nothing outgoing (issue3611)
1589 exit code with nothing outgoing (issue3611)
1587 $ hg outgoing ../dest
1590 $ hg outgoing ../dest
1588 comparing with ../dest
1591 comparing with ../dest
1589 searching for changes
1592 searching for changes
1590 no changes found
1593 no changes found
1591 [1]
1594 [1]
1592 $ cd ..
1595 $ cd ..
1593
1596
1594 #if serve
1597 #if serve
1595 $ hg serve -R r4 -d -p $HGPORT2 --pid-file hg.pid
1598 $ hg serve -R r4 -d -p $HGPORT2 --pid-file hg.pid
1596 $ cat hg.pid >> $DAEMON_PIDS
1599 $ cat hg.pid >> $DAEMON_PIDS
1597 $ hg --config extensions.largefiles=! clone http://localhost:$HGPORT2 r5
1600 $ hg --config extensions.largefiles=! clone http://localhost:$HGPORT2 r5
1598 abort: remote error:
1601 abort: remote error:
1599
1602
1600 This repository uses the largefiles extension.
1603 This repository uses the largefiles extension.
1601
1604
1602 Please enable it in your Mercurial config file.
1605 Please enable it in your Mercurial config file.
1603 [255]
1606 [255]
1604
1607
1605 used all HGPORTs, kill all daemons
1608 used all HGPORTs, kill all daemons
1606 $ "$TESTDIR/killdaemons.py" $DAEMON_PIDS
1609 $ "$TESTDIR/killdaemons.py" $DAEMON_PIDS
1607 #endif
1610 #endif
1608
1611
1609 vanilla clients locked out from largefiles ssh repos
1612 vanilla clients locked out from largefiles ssh repos
1610 $ hg --config extensions.largefiles=! clone -e "python \"$TESTDIR/dummyssh\"" ssh://user@dummy/r4 r5
1613 $ hg --config extensions.largefiles=! clone -e "python \"$TESTDIR/dummyssh\"" ssh://user@dummy/r4 r5
1611 abort: remote error:
1614 abort: remote error:
1612
1615
1613 This repository uses the largefiles extension.
1616 This repository uses the largefiles extension.
1614
1617
1615 Please enable it in your Mercurial config file.
1618 Please enable it in your Mercurial config file.
1616 [255]
1619 [255]
1617
1620
1618 #if serve
1621 #if serve
1619
1622
1620 largefiles clients refuse to push largefiles repos to vanilla servers
1623 largefiles clients refuse to push largefiles repos to vanilla servers
1621 $ mkdir r6
1624 $ mkdir r6
1622 $ cd r6
1625 $ cd r6
1623 $ hg init
1626 $ hg init
1624 $ echo c1 > f1
1627 $ echo c1 > f1
1625 $ hg add f1
1628 $ hg add f1
1626 $ hg commit -m "m1"
1629 $ hg commit -m "m1"
1627 Invoking status precommit hook
1630 Invoking status precommit hook
1628 A f1
1631 A f1
1629 $ cat >> .hg/hgrc <<!
1632 $ cat >> .hg/hgrc <<!
1630 > [web]
1633 > [web]
1631 > push_ssl = false
1634 > push_ssl = false
1632 > allow_push = *
1635 > allow_push = *
1633 > !
1636 > !
1634 $ cd ..
1637 $ cd ..
1635 $ hg clone r6 r7
1638 $ hg clone r6 r7
1636 updating to branch default
1639 updating to branch default
1637 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1640 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1638 $ cd r7
1641 $ cd r7
1639 $ echo c2 > f2
1642 $ echo c2 > f2
1640 $ hg add --large f2
1643 $ hg add --large f2
1641 $ hg commit -m "m2"
1644 $ hg commit -m "m2"
1642 Invoking status precommit hook
1645 Invoking status precommit hook
1643 A f2
1646 A f2
1644 $ hg --config extensions.largefiles=! -R ../r6 serve -d -p $HGPORT --pid-file ../hg.pid
1647 $ hg --config extensions.largefiles=! -R ../r6 serve -d -p $HGPORT --pid-file ../hg.pid
1645 $ cat ../hg.pid >> $DAEMON_PIDS
1648 $ cat ../hg.pid >> $DAEMON_PIDS
1646 $ hg push http://localhost:$HGPORT
1649 $ hg push http://localhost:$HGPORT
1647 pushing to http://localhost:$HGPORT/
1650 pushing to http://localhost:$HGPORT/
1648 searching for changes
1651 searching for changes
1649 abort: http://localhost:$HGPORT/ does not appear to be a largefile store
1652 abort: http://localhost:$HGPORT/ does not appear to be a largefile store
1650 [255]
1653 [255]
1651 $ cd ..
1654 $ cd ..
1652
1655
1653 putlfile errors are shown (issue3123)
1656 putlfile errors are shown (issue3123)
1654 Corrupt the cached largefile in r7 and move it out of the servers usercache
1657 Corrupt the cached largefile in r7 and move it out of the servers usercache
1655 $ mv r7/.hg/largefiles/4cdac4d8b084d0b599525cf732437fb337d422a8 .
1658 $ mv r7/.hg/largefiles/4cdac4d8b084d0b599525cf732437fb337d422a8 .
1656 $ echo 'client side corruption' > r7/.hg/largefiles/4cdac4d8b084d0b599525cf732437fb337d422a8
1659 $ echo 'client side corruption' > r7/.hg/largefiles/4cdac4d8b084d0b599525cf732437fb337d422a8
1657 $ rm "$USERCACHE/4cdac4d8b084d0b599525cf732437fb337d422a8"
1660 $ rm "$USERCACHE/4cdac4d8b084d0b599525cf732437fb337d422a8"
1658 $ hg init empty
1661 $ hg init empty
1659 $ hg serve -R empty -d -p $HGPORT1 --pid-file hg.pid \
1662 $ hg serve -R empty -d -p $HGPORT1 --pid-file hg.pid \
1660 > --config 'web.allow_push=*' --config web.push_ssl=False
1663 > --config 'web.allow_push=*' --config web.push_ssl=False
1661 $ cat hg.pid >> $DAEMON_PIDS
1664 $ cat hg.pid >> $DAEMON_PIDS
1662 $ hg push -R r7 http://localhost:$HGPORT1
1665 $ hg push -R r7 http://localhost:$HGPORT1
1663 pushing to http://localhost:$HGPORT1/
1666 pushing to http://localhost:$HGPORT1/
1664 searching for changes
1667 searching for changes
1665 remote: largefiles: failed to put 4cdac4d8b084d0b599525cf732437fb337d422a8 into store: largefile contents do not match hash
1668 remote: largefiles: failed to put 4cdac4d8b084d0b599525cf732437fb337d422a8 into store: largefile contents do not match hash
1666 abort: remotestore: could not put $TESTTMP/r7/.hg/largefiles/4cdac4d8b084d0b599525cf732437fb337d422a8 to remote store http://localhost:$HGPORT1/ (glob)
1669 abort: remotestore: could not put $TESTTMP/r7/.hg/largefiles/4cdac4d8b084d0b599525cf732437fb337d422a8 to remote store http://localhost:$HGPORT1/ (glob)
1667 [255]
1670 [255]
1668 $ mv 4cdac4d8b084d0b599525cf732437fb337d422a8 r7/.hg/largefiles/4cdac4d8b084d0b599525cf732437fb337d422a8
1671 $ mv 4cdac4d8b084d0b599525cf732437fb337d422a8 r7/.hg/largefiles/4cdac4d8b084d0b599525cf732437fb337d422a8
1669 Push of file that exists on server but is corrupted - magic healing would be nice ... but too magic
1672 Push of file that exists on server but is corrupted - magic healing would be nice ... but too magic
1670 $ echo "server side corruption" > empty/.hg/largefiles/4cdac4d8b084d0b599525cf732437fb337d422a8
1673 $ echo "server side corruption" > empty/.hg/largefiles/4cdac4d8b084d0b599525cf732437fb337d422a8
1671 $ hg push -R r7 http://localhost:$HGPORT1
1674 $ hg push -R r7 http://localhost:$HGPORT1
1672 pushing to http://localhost:$HGPORT1/
1675 pushing to http://localhost:$HGPORT1/
1673 searching for changes
1676 searching for changes
1674 searching for changes
1677 searching for changes
1675 remote: adding changesets
1678 remote: adding changesets
1676 remote: adding manifests
1679 remote: adding manifests
1677 remote: adding file changes
1680 remote: adding file changes
1678 remote: added 2 changesets with 2 changes to 2 files
1681 remote: added 2 changesets with 2 changes to 2 files
1679 $ cat empty/.hg/largefiles/4cdac4d8b084d0b599525cf732437fb337d422a8
1682 $ cat empty/.hg/largefiles/4cdac4d8b084d0b599525cf732437fb337d422a8
1680 server side corruption
1683 server side corruption
1681 $ rm -rf empty
1684 $ rm -rf empty
1682
1685
1683 Push a largefiles repository to a served empty repository
1686 Push a largefiles repository to a served empty repository
1684 $ hg init r8
1687 $ hg init r8
1685 $ echo c3 > r8/f1
1688 $ echo c3 > r8/f1
1686 $ hg add --large r8/f1 -R r8
1689 $ hg add --large r8/f1 -R r8
1687 $ hg commit -m "m1" -R r8
1690 $ hg commit -m "m1" -R r8
1688 Invoking status precommit hook
1691 Invoking status precommit hook
1689 A f1
1692 A f1
1690 $ hg init empty
1693 $ hg init empty
1691 $ hg serve -R empty -d -p $HGPORT2 --pid-file hg.pid \
1694 $ hg serve -R empty -d -p $HGPORT2 --pid-file hg.pid \
1692 > --config 'web.allow_push=*' --config web.push_ssl=False
1695 > --config 'web.allow_push=*' --config web.push_ssl=False
1693 $ cat hg.pid >> $DAEMON_PIDS
1696 $ cat hg.pid >> $DAEMON_PIDS
1694 $ rm "${USERCACHE}"/*
1697 $ rm "${USERCACHE}"/*
1695 $ hg push -R r8 http://localhost:$HGPORT2/#default
1698 $ hg push -R r8 http://localhost:$HGPORT2/#default
1696 pushing to http://localhost:$HGPORT2/
1699 pushing to http://localhost:$HGPORT2/
1697 searching for changes
1700 searching for changes
1698 searching for changes
1701 searching for changes
1699 remote: adding changesets
1702 remote: adding changesets
1700 remote: adding manifests
1703 remote: adding manifests
1701 remote: adding file changes
1704 remote: adding file changes
1702 remote: added 1 changesets with 1 changes to 1 files
1705 remote: added 1 changesets with 1 changes to 1 files
1703 $ [ -f "${USERCACHE}"/02a439e5c31c526465ab1a0ca1f431f76b827b90 ]
1706 $ [ -f "${USERCACHE}"/02a439e5c31c526465ab1a0ca1f431f76b827b90 ]
1704 $ [ -f empty/.hg/largefiles/02a439e5c31c526465ab1a0ca1f431f76b827b90 ]
1707 $ [ -f empty/.hg/largefiles/02a439e5c31c526465ab1a0ca1f431f76b827b90 ]
1705
1708
1706 Clone over http, no largefiles pulled on clone.
1709 Clone over http, no largefiles pulled on clone.
1707
1710
1708 $ hg clone http://localhost:$HGPORT2/#default http-clone -U
1711 $ hg clone http://localhost:$HGPORT2/#default http-clone -U
1709 adding changesets
1712 adding changesets
1710 adding manifests
1713 adding manifests
1711 adding file changes
1714 adding file changes
1712 added 1 changesets with 1 changes to 1 files
1715 added 1 changesets with 1 changes to 1 files
1713
1716
1714 test 'verify' with remotestore:
1717 test 'verify' with remotestore:
1715
1718
1716 $ rm "${USERCACHE}"/02a439e5c31c526465ab1a0ca1f431f76b827b90
1719 $ rm "${USERCACHE}"/02a439e5c31c526465ab1a0ca1f431f76b827b90
1717 $ mv empty/.hg/largefiles/02a439e5c31c526465ab1a0ca1f431f76b827b90 .
1720 $ mv empty/.hg/largefiles/02a439e5c31c526465ab1a0ca1f431f76b827b90 .
1718 $ hg -R http-clone verify --large --lfa
1721 $ hg -R http-clone verify --large --lfa
1719 checking changesets
1722 checking changesets
1720 checking manifests
1723 checking manifests
1721 crosschecking files in changesets and manifests
1724 crosschecking files in changesets and manifests
1722 checking files
1725 checking files
1723 1 files, 1 changesets, 1 total revisions
1726 1 files, 1 changesets, 1 total revisions
1724 searching 1 changesets for largefiles
1727 searching 1 changesets for largefiles
1725 changeset 0:cf03e5bb9936: f1 missing
1728 changeset 0:cf03e5bb9936: f1 missing
1726 verified existence of 1 revisions of 1 largefiles
1729 verified existence of 1 revisions of 1 largefiles
1727 [1]
1730 [1]
1728 $ mv 02a439e5c31c526465ab1a0ca1f431f76b827b90 empty/.hg/largefiles/
1731 $ mv 02a439e5c31c526465ab1a0ca1f431f76b827b90 empty/.hg/largefiles/
1729 $ hg -R http-clone -q verify --large --lfa
1732 $ hg -R http-clone -q verify --large --lfa
1730
1733
1731 largefiles pulled on update - a largefile missing on the server:
1734 largefiles pulled on update - a largefile missing on the server:
1732 $ mv empty/.hg/largefiles/02a439e5c31c526465ab1a0ca1f431f76b827b90 .
1735 $ mv empty/.hg/largefiles/02a439e5c31c526465ab1a0ca1f431f76b827b90 .
1733 $ hg -R http-clone up --config largefiles.usercache=http-clone-usercache
1736 $ hg -R http-clone up --config largefiles.usercache=http-clone-usercache
1734 getting changed largefiles
1737 getting changed largefiles
1735 abort: remotestore: largefile 02a439e5c31c526465ab1a0ca1f431f76b827b90 is missing
1738 abort: remotestore: largefile 02a439e5c31c526465ab1a0ca1f431f76b827b90 is missing
1736 [255]
1739 [255]
1737 $ hg -R http-clone up -Cqr null
1740 $ hg -R http-clone up -Cqr null
1738
1741
1739 largefiles pulled on update - a largefile corrupted on the server:
1742 largefiles pulled on update - a largefile corrupted on the server:
1740 $ echo corruption > empty/.hg/largefiles/02a439e5c31c526465ab1a0ca1f431f76b827b90
1743 $ echo corruption > empty/.hg/largefiles/02a439e5c31c526465ab1a0ca1f431f76b827b90
1741 $ hg -R http-clone up --config largefiles.usercache=http-clone-usercache
1744 $ hg -R http-clone up --config largefiles.usercache=http-clone-usercache
1742 getting changed largefiles
1745 getting changed largefiles
1743 f1: data corruption (expected 02a439e5c31c526465ab1a0ca1f431f76b827b90, got 6a7bb2556144babe3899b25e5428123735bb1e27)
1746 f1: data corruption (expected 02a439e5c31c526465ab1a0ca1f431f76b827b90, got 6a7bb2556144babe3899b25e5428123735bb1e27)
1744 0 largefiles updated, 0 removed
1747 0 largefiles updated, 0 removed
1745 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1748 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1746 $ hg -R http-clone st
1749 $ hg -R http-clone st
1747 ! f1
1750 ! f1
1748 $ [ ! -f http-clone/.hg/largefiles/02a439e5c31c526465ab1a0ca1f431f76b827b90 ]
1751 $ [ ! -f http-clone/.hg/largefiles/02a439e5c31c526465ab1a0ca1f431f76b827b90 ]
1749 $ [ ! -f http-clone/f1 ]
1752 $ [ ! -f http-clone/f1 ]
1750 $ [ ! -f http-clone-usercache ]
1753 $ [ ! -f http-clone-usercache ]
1751 $ hg -R http-clone verify --large --lfc
1754 $ hg -R http-clone verify --large --lfc
1752 checking changesets
1755 checking changesets
1753 checking manifests
1756 checking manifests
1754 crosschecking files in changesets and manifests
1757 crosschecking files in changesets and manifests
1755 checking files
1758 checking files
1756 1 files, 1 changesets, 1 total revisions
1759 1 files, 1 changesets, 1 total revisions
1757 searching 1 changesets for largefiles
1760 searching 1 changesets for largefiles
1758 verified contents of 1 revisions of 1 largefiles
1761 verified contents of 1 revisions of 1 largefiles
1759 $ hg -R http-clone up -Cqr null
1762 $ hg -R http-clone up -Cqr null
1760
1763
1761 largefiles pulled on update - no server side problems:
1764 largefiles pulled on update - no server side problems:
1762 $ mv 02a439e5c31c526465ab1a0ca1f431f76b827b90 empty/.hg/largefiles/
1765 $ mv 02a439e5c31c526465ab1a0ca1f431f76b827b90 empty/.hg/largefiles/
1763 $ hg -R http-clone --debug up --config largefiles.usercache=http-clone-usercache
1766 $ hg -R http-clone --debug up --config largefiles.usercache=http-clone-usercache
1764 resolving manifests
1767 resolving manifests
1765 branchmerge: False, force: False, partial: False
1768 branchmerge: False, force: False, partial: False
1766 ancestor: 000000000000, local: 000000000000+, remote: cf03e5bb9936
1769 ancestor: 000000000000, local: 000000000000+, remote: cf03e5bb9936
1767 .hglf/f1: remote created -> g
1770 .hglf/f1: remote created -> g
1768 getting .hglf/f1
1771 getting .hglf/f1
1769 updating: .hglf/f1 1/1 files (100.00%)
1772 updating: .hglf/f1 1/1 files (100.00%)
1770 getting changed largefiles
1773 getting changed largefiles
1771 using http://localhost:$HGPORT2/
1774 using http://localhost:$HGPORT2/
1772 sending capabilities command
1775 sending capabilities command
1773 getting largefiles: 0/1 lfile (0.00%)
1776 getting largefiles: 0/1 lfile (0.00%)
1774 getting f1:02a439e5c31c526465ab1a0ca1f431f76b827b90
1777 getting f1:02a439e5c31c526465ab1a0ca1f431f76b827b90
1775 sending batch command
1778 sending batch command
1776 sending getlfile command
1779 sending getlfile command
1777 found 02a439e5c31c526465ab1a0ca1f431f76b827b90 in store
1780 found 02a439e5c31c526465ab1a0ca1f431f76b827b90 in store
1778 1 largefiles updated, 0 removed
1781 1 largefiles updated, 0 removed
1779 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1782 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1780
1783
1781 $ ls http-clone-usercache/*
1784 $ ls http-clone-usercache/*
1782 http-clone-usercache/02a439e5c31c526465ab1a0ca1f431f76b827b90
1785 http-clone-usercache/02a439e5c31c526465ab1a0ca1f431f76b827b90
1783
1786
1784 $ rm -rf empty http-clone*
1787 $ rm -rf empty http-clone*
1785
1788
1786 used all HGPORTs, kill all daemons
1789 used all HGPORTs, kill all daemons
1787 $ "$TESTDIR/killdaemons.py" $DAEMON_PIDS
1790 $ "$TESTDIR/killdaemons.py" $DAEMON_PIDS
1788
1791
1789 #endif
1792 #endif
1790
1793
1791
1794
1792 #if unix-permissions
1795 #if unix-permissions
1793
1796
1794 Clone a local repository owned by another user
1797 Clone a local repository owned by another user
1795 We have to simulate that here by setting $HOME and removing write permissions
1798 We have to simulate that here by setting $HOME and removing write permissions
1796 $ ORIGHOME="$HOME"
1799 $ ORIGHOME="$HOME"
1797 $ mkdir alice
1800 $ mkdir alice
1798 $ HOME="`pwd`/alice"
1801 $ HOME="`pwd`/alice"
1799 $ cd alice
1802 $ cd alice
1800 $ hg init pubrepo
1803 $ hg init pubrepo
1801 $ cd pubrepo
1804 $ cd pubrepo
1802 $ dd if=/dev/zero bs=1k count=11k > a-large-file 2> /dev/null
1805 $ dd if=/dev/zero bs=1k count=11k > a-large-file 2> /dev/null
1803 $ hg add --large a-large-file
1806 $ hg add --large a-large-file
1804 $ hg commit -m "Add a large file"
1807 $ hg commit -m "Add a large file"
1805 Invoking status precommit hook
1808 Invoking status precommit hook
1806 A a-large-file
1809 A a-large-file
1807 $ cd ..
1810 $ cd ..
1808 $ chmod -R a-w pubrepo
1811 $ chmod -R a-w pubrepo
1809 $ cd ..
1812 $ cd ..
1810 $ mkdir bob
1813 $ mkdir bob
1811 $ HOME="`pwd`/bob"
1814 $ HOME="`pwd`/bob"
1812 $ cd bob
1815 $ cd bob
1813 $ hg clone --pull ../alice/pubrepo pubrepo
1816 $ hg clone --pull ../alice/pubrepo pubrepo
1814 requesting all changes
1817 requesting all changes
1815 adding changesets
1818 adding changesets
1816 adding manifests
1819 adding manifests
1817 adding file changes
1820 adding file changes
1818 added 1 changesets with 1 changes to 1 files
1821 added 1 changesets with 1 changes to 1 files
1819 updating to branch default
1822 updating to branch default
1820 getting changed largefiles
1823 getting changed largefiles
1821 1 largefiles updated, 0 removed
1824 1 largefiles updated, 0 removed
1822 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1825 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1823 $ cd ..
1826 $ cd ..
1824 $ chmod -R u+w alice/pubrepo
1827 $ chmod -R u+w alice/pubrepo
1825 $ HOME="$ORIGHOME"
1828 $ HOME="$ORIGHOME"
1826
1829
1827 #endif
1830 #endif
1828
1831
1829 #if symlink
1832 #if symlink
1830
1833
1831 Symlink to a large largefile should behave the same as a symlink to a normal file
1834 Symlink to a large largefile should behave the same as a symlink to a normal file
1832 $ hg init largesymlink
1835 $ hg init largesymlink
1833 $ cd largesymlink
1836 $ cd largesymlink
1834 $ dd if=/dev/zero bs=1k count=10k of=largefile 2>/dev/null
1837 $ dd if=/dev/zero bs=1k count=10k of=largefile 2>/dev/null
1835 $ hg add --large largefile
1838 $ hg add --large largefile
1836 $ hg commit -m "commit a large file"
1839 $ hg commit -m "commit a large file"
1837 Invoking status precommit hook
1840 Invoking status precommit hook
1838 A largefile
1841 A largefile
1839 $ ln -s largefile largelink
1842 $ ln -s largefile largelink
1840 $ hg add largelink
1843 $ hg add largelink
1841 $ hg commit -m "commit a large symlink"
1844 $ hg commit -m "commit a large symlink"
1842 Invoking status precommit hook
1845 Invoking status precommit hook
1843 A largelink
1846 A largelink
1844 $ rm -f largelink
1847 $ rm -f largelink
1845 $ hg up >/dev/null
1848 $ hg up >/dev/null
1846 $ test -f largelink
1849 $ test -f largelink
1847 [1]
1850 [1]
1848 $ test -L largelink
1851 $ test -L largelink
1849 [1]
1852 [1]
1850 $ rm -f largelink # make next part of the test independent of the previous
1853 $ rm -f largelink # make next part of the test independent of the previous
1851 $ hg up -C >/dev/null
1854 $ hg up -C >/dev/null
1852 $ test -f largelink
1855 $ test -f largelink
1853 $ test -L largelink
1856 $ test -L largelink
1854 $ cd ..
1857 $ cd ..
1855
1858
1856 #endif
1859 #endif
1857
1860
1858 test for pattern matching on 'hg status':
1861 test for pattern matching on 'hg status':
1859 to boost performance, largefiles checks whether specified patterns are
1862 to boost performance, largefiles checks whether specified patterns are
1860 related to largefiles in working directory (NOT to STANDIN) or not.
1863 related to largefiles in working directory (NOT to STANDIN) or not.
1861
1864
1862 $ hg init statusmatch
1865 $ hg init statusmatch
1863 $ cd statusmatch
1866 $ cd statusmatch
1864
1867
1865 $ mkdir -p a/b/c/d
1868 $ mkdir -p a/b/c/d
1866 $ echo normal > a/b/c/d/e.normal.txt
1869 $ echo normal > a/b/c/d/e.normal.txt
1867 $ hg add a/b/c/d/e.normal.txt
1870 $ hg add a/b/c/d/e.normal.txt
1868 $ echo large > a/b/c/d/e.large.txt
1871 $ echo large > a/b/c/d/e.large.txt
1869 $ hg add --large a/b/c/d/e.large.txt
1872 $ hg add --large a/b/c/d/e.large.txt
1870 $ mkdir -p a/b/c/x
1873 $ mkdir -p a/b/c/x
1871 $ echo normal > a/b/c/x/y.normal.txt
1874 $ echo normal > a/b/c/x/y.normal.txt
1872 $ hg add a/b/c/x/y.normal.txt
1875 $ hg add a/b/c/x/y.normal.txt
1873 $ hg commit -m 'add files'
1876 $ hg commit -m 'add files'
1874 Invoking status precommit hook
1877 Invoking status precommit hook
1875 A a/b/c/d/e.large.txt
1878 A a/b/c/d/e.large.txt
1876 A a/b/c/d/e.normal.txt
1879 A a/b/c/d/e.normal.txt
1877 A a/b/c/x/y.normal.txt
1880 A a/b/c/x/y.normal.txt
1878
1881
1879 (1) no pattern: no performance boost
1882 (1) no pattern: no performance boost
1880 $ hg status -A
1883 $ hg status -A
1881 C a/b/c/d/e.large.txt
1884 C a/b/c/d/e.large.txt
1882 C a/b/c/d/e.normal.txt
1885 C a/b/c/d/e.normal.txt
1883 C a/b/c/x/y.normal.txt
1886 C a/b/c/x/y.normal.txt
1884
1887
1885 (2) pattern not related to largefiles: performance boost
1888 (2) pattern not related to largefiles: performance boost
1886 $ hg status -A a/b/c/x
1889 $ hg status -A a/b/c/x
1887 C a/b/c/x/y.normal.txt
1890 C a/b/c/x/y.normal.txt
1888
1891
1889 (3) pattern related to largefiles: no performance boost
1892 (3) pattern related to largefiles: no performance boost
1890 $ hg status -A a/b/c/d
1893 $ hg status -A a/b/c/d
1891 C a/b/c/d/e.large.txt
1894 C a/b/c/d/e.large.txt
1892 C a/b/c/d/e.normal.txt
1895 C a/b/c/d/e.normal.txt
1893
1896
1894 (4) pattern related to STANDIN (not to largefiles): performance boost
1897 (4) pattern related to STANDIN (not to largefiles): performance boost
1895 $ hg status -A .hglf/a
1898 $ hg status -A .hglf/a
1896 C .hglf/a/b/c/d/e.large.txt
1899 C .hglf/a/b/c/d/e.large.txt
1897
1900
1898 (5) mixed case: no performance boost
1901 (5) mixed case: no performance boost
1899 $ hg status -A a/b/c/x a/b/c/d
1902 $ hg status -A a/b/c/x a/b/c/d
1900 C a/b/c/d/e.large.txt
1903 C a/b/c/d/e.large.txt
1901 C a/b/c/d/e.normal.txt
1904 C a/b/c/d/e.normal.txt
1902 C a/b/c/x/y.normal.txt
1905 C a/b/c/x/y.normal.txt
1903
1906
1904 verify that largefiles doesn't break filesets
1907 verify that largefiles doesn't break filesets
1905
1908
1906 $ hg log --rev . --exclude "set:binary()"
1909 $ hg log --rev . --exclude "set:binary()"
1907 changeset: 0:41bd42f10efa
1910 changeset: 0:41bd42f10efa
1908 tag: tip
1911 tag: tip
1909 user: test
1912 user: test
1910 date: Thu Jan 01 00:00:00 1970 +0000
1913 date: Thu Jan 01 00:00:00 1970 +0000
1911 summary: add files
1914 summary: add files
1912
1915
1913 verify that large files in subrepos handled properly
1916 verify that large files in subrepos handled properly
1914 $ hg init subrepo
1917 $ hg init subrepo
1915 $ echo "subrepo = subrepo" > .hgsub
1918 $ echo "subrepo = subrepo" > .hgsub
1916 $ hg add .hgsub
1919 $ hg add .hgsub
1917 $ hg ci -m "add subrepo"
1920 $ hg ci -m "add subrepo"
1918 Invoking status precommit hook
1921 Invoking status precommit hook
1919 A .hgsub
1922 A .hgsub
1920 ? .hgsubstate
1923 ? .hgsubstate
1921 $ echo "rev 1" > subrepo/large.txt
1924 $ echo "rev 1" > subrepo/large.txt
1922 $ hg -R subrepo add --large subrepo/large.txt
1925 $ hg -R subrepo add --large subrepo/large.txt
1923 $ hg sum
1926 $ hg sum
1924 parent: 1:8ee150ea2e9c tip
1927 parent: 1:8ee150ea2e9c tip
1925 add subrepo
1928 add subrepo
1926 branch: default
1929 branch: default
1927 commit: 1 subrepos
1930 commit: 1 subrepos
1928 update: (current)
1931 update: (current)
1929 $ hg st
1932 $ hg st
1930 $ hg st -S
1933 $ hg st -S
1931 A subrepo/large.txt
1934 A subrepo/large.txt
1932 $ hg ci -S -m "commit top repo"
1935 $ hg ci -S -m "commit top repo"
1933 committing subrepository subrepo
1936 committing subrepository subrepo
1934 Invoking status precommit hook
1937 Invoking status precommit hook
1935 A large.txt
1938 A large.txt
1936 Invoking status precommit hook
1939 Invoking status precommit hook
1937 M .hgsubstate
1940 M .hgsubstate
1938 # No differences
1941 # No differences
1939 $ hg st -S
1942 $ hg st -S
1940 $ hg sum
1943 $ hg sum
1941 parent: 2:ce4cd0c527a6 tip
1944 parent: 2:ce4cd0c527a6 tip
1942 commit top repo
1945 commit top repo
1943 branch: default
1946 branch: default
1944 commit: (clean)
1947 commit: (clean)
1945 update: (current)
1948 update: (current)
1946 $ echo "rev 2" > subrepo/large.txt
1949 $ echo "rev 2" > subrepo/large.txt
1947 $ hg st -S
1950 $ hg st -S
1948 M subrepo/large.txt
1951 M subrepo/large.txt
1949 $ hg sum
1952 $ hg sum
1950 parent: 2:ce4cd0c527a6 tip
1953 parent: 2:ce4cd0c527a6 tip
1951 commit top repo
1954 commit top repo
1952 branch: default
1955 branch: default
1953 commit: 1 subrepos
1956 commit: 1 subrepos
1954 update: (current)
1957 update: (current)
1955 $ hg ci -m "this commit should fail without -S"
1958 $ hg ci -m "this commit should fail without -S"
1956 abort: uncommitted changes in subrepo subrepo
1959 abort: uncommitted changes in subrepo subrepo
1957 (use --subrepos for recursive commit)
1960 (use --subrepos for recursive commit)
1958 [255]
1961 [255]
1959
1962
1960 Add a normal file to the subrepo, then test archiving
1963 Add a normal file to the subrepo, then test archiving
1961
1964
1962 $ echo 'normal file' > subrepo/normal.txt
1965 $ echo 'normal file' > subrepo/normal.txt
1963 $ hg -R subrepo add subrepo/normal.txt
1966 $ hg -R subrepo add subrepo/normal.txt
1964
1967
1965 Lock in subrepo, otherwise the change isn't archived
1968 Lock in subrepo, otherwise the change isn't archived
1966
1969
1967 $ hg ci -S -m "add normal file to top level"
1970 $ hg ci -S -m "add normal file to top level"
1968 committing subrepository subrepo
1971 committing subrepository subrepo
1969 Invoking status precommit hook
1972 Invoking status precommit hook
1970 M large.txt
1973 M large.txt
1971 A normal.txt
1974 A normal.txt
1972 Invoking status precommit hook
1975 Invoking status precommit hook
1973 M .hgsubstate
1976 M .hgsubstate
1974 $ hg archive -S ../lf_subrepo_archive
1977 $ hg archive -S ../lf_subrepo_archive
1975 $ find ../lf_subrepo_archive | sort
1978 $ find ../lf_subrepo_archive | sort
1976 ../lf_subrepo_archive
1979 ../lf_subrepo_archive
1977 ../lf_subrepo_archive/.hg_archival.txt
1980 ../lf_subrepo_archive/.hg_archival.txt
1978 ../lf_subrepo_archive/.hgsub
1981 ../lf_subrepo_archive/.hgsub
1979 ../lf_subrepo_archive/.hgsubstate
1982 ../lf_subrepo_archive/.hgsubstate
1980 ../lf_subrepo_archive/a
1983 ../lf_subrepo_archive/a
1981 ../lf_subrepo_archive/a/b
1984 ../lf_subrepo_archive/a/b
1982 ../lf_subrepo_archive/a/b/c
1985 ../lf_subrepo_archive/a/b/c
1983 ../lf_subrepo_archive/a/b/c/d
1986 ../lf_subrepo_archive/a/b/c/d
1984 ../lf_subrepo_archive/a/b/c/d/e.large.txt
1987 ../lf_subrepo_archive/a/b/c/d/e.large.txt
1985 ../lf_subrepo_archive/a/b/c/d/e.normal.txt
1988 ../lf_subrepo_archive/a/b/c/d/e.normal.txt
1986 ../lf_subrepo_archive/a/b/c/x
1989 ../lf_subrepo_archive/a/b/c/x
1987 ../lf_subrepo_archive/a/b/c/x/y.normal.txt
1990 ../lf_subrepo_archive/a/b/c/x/y.normal.txt
1988 ../lf_subrepo_archive/subrepo
1991 ../lf_subrepo_archive/subrepo
1989 ../lf_subrepo_archive/subrepo/large.txt
1992 ../lf_subrepo_archive/subrepo/large.txt
1990 ../lf_subrepo_archive/subrepo/normal.txt
1993 ../lf_subrepo_archive/subrepo/normal.txt
1991
1994
1992 Test update with subrepos.
1995 Test update with subrepos.
1993
1996
1994 $ hg update 0
1997 $ hg update 0
1995 getting changed largefiles
1998 getting changed largefiles
1996 0 largefiles updated, 1 removed
1999 0 largefiles updated, 1 removed
1997 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
2000 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
1998 $ hg status -S
2001 $ hg status -S
1999 $ hg update tip
2002 $ hg update tip
2000 getting changed largefiles
2003 getting changed largefiles
2001 1 largefiles updated, 0 removed
2004 1 largefiles updated, 0 removed
2002 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
2005 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
2003 $ hg status -S
2006 $ hg status -S
2004 # modify a large file
2007 # modify a large file
2005 $ echo "modified" > subrepo/large.txt
2008 $ echo "modified" > subrepo/large.txt
2006 $ hg st -S
2009 $ hg st -S
2007 M subrepo/large.txt
2010 M subrepo/large.txt
2008 # update -C should revert the change.
2011 # update -C should revert the change.
2009 $ hg update -C
2012 $ hg update -C
2010 getting changed largefiles
2013 getting changed largefiles
2011 1 largefiles updated, 0 removed
2014 1 largefiles updated, 0 removed
2012 getting changed largefiles
2015 getting changed largefiles
2013 0 largefiles updated, 0 removed
2016 0 largefiles updated, 0 removed
2014 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
2017 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
2015 $ hg status -S
2018 $ hg status -S
2016
2019
2017 Test archiving a revision that references a subrepo that is not yet
2020 Test archiving a revision that references a subrepo that is not yet
2018 cloned (see test-subrepo-recursion.t):
2021 cloned (see test-subrepo-recursion.t):
2019
2022
2020 $ hg clone -U . ../empty
2023 $ hg clone -U . ../empty
2021 $ cd ../empty
2024 $ cd ../empty
2022 $ hg archive --subrepos -r tip ../archive.tar.gz
2025 $ hg archive --subrepos -r tip ../archive.tar.gz
2023 cloning subrepo subrepo from $TESTTMP/statusmatch/subrepo
2026 cloning subrepo subrepo from $TESTTMP/statusmatch/subrepo
2024 $ cd ..
2027 $ cd ..
2025
2028
2026 Test that addremove picks up largefiles prior to the initial commit (issue3541)
2029 Test that addremove picks up largefiles prior to the initial commit (issue3541)
2027
2030
2028 $ hg init addrm2
2031 $ hg init addrm2
2029 $ cd addrm2
2032 $ cd addrm2
2030 $ touch large.dat
2033 $ touch large.dat
2031 $ touch large2.dat
2034 $ touch large2.dat
2032 $ touch normal
2035 $ touch normal
2033 $ hg add --large large.dat
2036 $ hg add --large large.dat
2034 $ hg addremove -v
2037 $ hg addremove -v
2035 adding large2.dat as a largefile
2038 adding large2.dat as a largefile
2036 adding normal
2039 adding normal
2037
2040
2038 Test that forgetting all largefiles reverts to islfilesrepo() == False
2041 Test that forgetting all largefiles reverts to islfilesrepo() == False
2039 (addremove will add *.dat as normal files now)
2042 (addremove will add *.dat as normal files now)
2040 $ hg forget large.dat
2043 $ hg forget large.dat
2041 $ hg forget large2.dat
2044 $ hg forget large2.dat
2042 $ hg addremove -v
2045 $ hg addremove -v
2043 adding large.dat
2046 adding large.dat
2044 adding large2.dat
2047 adding large2.dat
2045
2048
2046 Test commit's addremove option prior to the first commit
2049 Test commit's addremove option prior to the first commit
2047 $ hg forget large.dat
2050 $ hg forget large.dat
2048 $ hg forget large2.dat
2051 $ hg forget large2.dat
2049 $ hg add --large large.dat
2052 $ hg add --large large.dat
2050 $ hg ci -Am "commit"
2053 $ hg ci -Am "commit"
2051 adding large2.dat as a largefile
2054 adding large2.dat as a largefile
2052 Invoking status precommit hook
2055 Invoking status precommit hook
2053 A large.dat
2056 A large.dat
2054 A large2.dat
2057 A large2.dat
2055 A normal
2058 A normal
2056 $ find .hglf | sort
2059 $ find .hglf | sort
2057 .hglf
2060 .hglf
2058 .hglf/large.dat
2061 .hglf/large.dat
2059 .hglf/large2.dat
2062 .hglf/large2.dat
2060
2063
2061 Test actions on largefiles using relative paths from subdir
2064 Test actions on largefiles using relative paths from subdir
2062
2065
2063 $ mkdir sub
2066 $ mkdir sub
2064 $ cd sub
2067 $ cd sub
2065 $ echo anotherlarge > anotherlarge
2068 $ echo anotherlarge > anotherlarge
2066 $ hg add --large anotherlarge
2069 $ hg add --large anotherlarge
2067 $ hg st
2070 $ hg st
2068 A sub/anotherlarge
2071 A sub/anotherlarge
2069 $ hg st anotherlarge
2072 $ hg st anotherlarge
2070 A anotherlarge
2073 A anotherlarge
2071 $ hg commit -m anotherlarge anotherlarge
2074 $ hg commit -m anotherlarge anotherlarge
2072 Invoking status precommit hook
2075 Invoking status precommit hook
2073 A sub/anotherlarge
2076 A sub/anotherlarge
2074 $ hg log anotherlarge
2077 $ hg log anotherlarge
2075 changeset: 1:9627a577c5e9
2078 changeset: 1:9627a577c5e9
2076 tag: tip
2079 tag: tip
2077 user: test
2080 user: test
2078 date: Thu Jan 01 00:00:00 1970 +0000
2081 date: Thu Jan 01 00:00:00 1970 +0000
2079 summary: anotherlarge
2082 summary: anotherlarge
2080
2083
2081 $ echo more >> anotherlarge
2084 $ echo more >> anotherlarge
2082 $ hg st .
2085 $ hg st .
2083 M anotherlarge
2086 M anotherlarge
2084 $ hg cat anotherlarge
2087 $ hg cat anotherlarge
2085 anotherlarge
2088 anotherlarge
2086 $ hg revert anotherlarge
2089 $ hg revert anotherlarge
2087 $ hg st
2090 $ hg st
2088 ? sub/anotherlarge.orig
2091 ? sub/anotherlarge.orig
2089 $ cd ..
2092 $ cd ..
2090
2093
2091 $ cd ..
2094 $ cd ..
2092
2095
2093 issue3651: summary/outgoing with largefiles shows "no remote repo"
2096 issue3651: summary/outgoing with largefiles shows "no remote repo"
2094 unexpectedly
2097 unexpectedly
2095
2098
2096 $ mkdir issue3651
2099 $ mkdir issue3651
2097 $ cd issue3651
2100 $ cd issue3651
2098
2101
2099 $ hg init src
2102 $ hg init src
2100 $ echo a > src/a
2103 $ echo a > src/a
2101 $ hg -R src add --large src/a
2104 $ hg -R src add --large src/a
2102 $ hg -R src commit -m '#0'
2105 $ hg -R src commit -m '#0'
2103 Invoking status precommit hook
2106 Invoking status precommit hook
2104 A a
2107 A a
2105
2108
2106 check messages when no remote repository is specified:
2109 check messages when no remote repository is specified:
2107 "no remote repo" route for "hg outgoing --large" is not tested here,
2110 "no remote repo" route for "hg outgoing --large" is not tested here,
2108 because it can't be reproduced easily.
2111 because it can't be reproduced easily.
2109
2112
2110 $ hg init clone1
2113 $ hg init clone1
2111 $ hg -R clone1 -q pull src
2114 $ hg -R clone1 -q pull src
2112 $ hg -R clone1 -q update
2115 $ hg -R clone1 -q update
2113 $ hg -R clone1 paths | grep default
2116 $ hg -R clone1 paths | grep default
2114 [1]
2117 [1]
2115
2118
2116 $ hg -R clone1 summary --large
2119 $ hg -R clone1 summary --large
2117 parent: 0:fc0bd45326d3 tip
2120 parent: 0:fc0bd45326d3 tip
2118 #0
2121 #0
2119 branch: default
2122 branch: default
2120 commit: (clean)
2123 commit: (clean)
2121 update: (current)
2124 update: (current)
2122 largefiles: (no remote repo)
2125 largefiles: (no remote repo)
2123
2126
2124 check messages when there is no files to upload:
2127 check messages when there is no files to upload:
2125
2128
2126 $ hg -q clone src clone2
2129 $ hg -q clone src clone2
2127 $ hg -R clone2 paths | grep default
2130 $ hg -R clone2 paths | grep default
2128 default = $TESTTMP/issue3651/src (glob)
2131 default = $TESTTMP/issue3651/src (glob)
2129
2132
2130 $ hg -R clone2 summary --large
2133 $ hg -R clone2 summary --large
2131 parent: 0:fc0bd45326d3 tip
2134 parent: 0:fc0bd45326d3 tip
2132 #0
2135 #0
2133 branch: default
2136 branch: default
2134 commit: (clean)
2137 commit: (clean)
2135 update: (current)
2138 update: (current)
2136 searching for changes
2139 searching for changes
2137 largefiles: (no files to upload)
2140 largefiles: (no files to upload)
2138 $ hg -R clone2 outgoing --large
2141 $ hg -R clone2 outgoing --large
2139 comparing with $TESTTMP/issue3651/src (glob)
2142 comparing with $TESTTMP/issue3651/src (glob)
2140 searching for changes
2143 searching for changes
2141 no changes found
2144 no changes found
2142 searching for changes
2145 searching for changes
2143 largefiles: no files to upload
2146 largefiles: no files to upload
2144 [1]
2147 [1]
2145
2148
2146 check messages when there are files to upload:
2149 check messages when there are files to upload:
2147
2150
2148 $ echo b > clone2/b
2151 $ echo b > clone2/b
2149 $ hg -R clone2 add --large clone2/b
2152 $ hg -R clone2 add --large clone2/b
2150 $ hg -R clone2 commit -m '#1'
2153 $ hg -R clone2 commit -m '#1'
2151 Invoking status precommit hook
2154 Invoking status precommit hook
2152 A b
2155 A b
2153 $ hg -R clone2 summary --large
2156 $ hg -R clone2 summary --large
2154 parent: 1:1acbe71ce432 tip
2157 parent: 1:1acbe71ce432 tip
2155 #1
2158 #1
2156 branch: default
2159 branch: default
2157 commit: (clean)
2160 commit: (clean)
2158 update: (current)
2161 update: (current)
2159 searching for changes
2162 searching for changes
2160 largefiles: 1 to upload
2163 largefiles: 1 to upload
2161 $ hg -R clone2 outgoing --large
2164 $ hg -R clone2 outgoing --large
2162 comparing with $TESTTMP/issue3651/src (glob)
2165 comparing with $TESTTMP/issue3651/src (glob)
2163 searching for changes
2166 searching for changes
2164 changeset: 1:1acbe71ce432
2167 changeset: 1:1acbe71ce432
2165 tag: tip
2168 tag: tip
2166 user: test
2169 user: test
2167 date: Thu Jan 01 00:00:00 1970 +0000
2170 date: Thu Jan 01 00:00:00 1970 +0000
2168 summary: #1
2171 summary: #1
2169
2172
2170 searching for changes
2173 searching for changes
2171 largefiles to upload:
2174 largefiles to upload:
2172 b
2175 b
2173
2176
2174
2177
2175 $ cd ..
2178 $ cd ..
General Comments 0
You need to be logged in to leave comments. Login now