##// END OF EJS Templates
largefiles: support revsets for outgoing --large...
Matt Harbison -
r17271:a09cc6ae stable
parent child Browse files
Show More
@@ -1,1082 +1,1082 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
15 node, archival, error, merge
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
22
23 # -- Utility functions: commonly/repeatedly needed functionality ---------------
23 # -- Utility functions: commonly/repeatedly needed functionality ---------------
24
24
25 def installnormalfilesmatchfn(manifest):
25 def installnormalfilesmatchfn(manifest):
26 '''overrides scmutil.match so that the matcher it returns will ignore all
26 '''overrides scmutil.match so that the matcher it returns will ignore all
27 largefiles'''
27 largefiles'''
28 oldmatch = None # for the closure
28 oldmatch = None # for the closure
29 def overridematch(ctx, pats=[], opts={}, globbed=False,
29 def overridematch(ctx, pats=[], opts={}, globbed=False,
30 default='relpath'):
30 default='relpath'):
31 match = oldmatch(ctx, pats, opts, globbed, default)
31 match = oldmatch(ctx, pats, opts, globbed, default)
32 m = copy.copy(match)
32 m = copy.copy(match)
33 notlfile = lambda f: not (lfutil.isstandin(f) or lfutil.standin(f) in
33 notlfile = lambda f: not (lfutil.isstandin(f) or lfutil.standin(f) in
34 manifest)
34 manifest)
35 m._files = filter(notlfile, m._files)
35 m._files = filter(notlfile, m._files)
36 m._fmap = set(m._files)
36 m._fmap = set(m._files)
37 origmatchfn = m.matchfn
37 origmatchfn = m.matchfn
38 m.matchfn = lambda f: notlfile(f) and origmatchfn(f) or None
38 m.matchfn = lambda f: notlfile(f) and origmatchfn(f) or None
39 return m
39 return m
40 oldmatch = installmatchfn(overridematch)
40 oldmatch = installmatchfn(overridematch)
41
41
42 def installmatchfn(f):
42 def installmatchfn(f):
43 oldmatch = scmutil.match
43 oldmatch = scmutil.match
44 setattr(f, 'oldmatch', oldmatch)
44 setattr(f, 'oldmatch', oldmatch)
45 scmutil.match = f
45 scmutil.match = f
46 return oldmatch
46 return oldmatch
47
47
48 def restorematchfn():
48 def restorematchfn():
49 '''restores scmutil.match to what it was before installnormalfilesmatchfn
49 '''restores scmutil.match to what it was before installnormalfilesmatchfn
50 was called. no-op if scmutil.match is its original function.
50 was called. no-op if scmutil.match is its original function.
51
51
52 Note that n calls to installnormalfilesmatchfn will require n calls to
52 Note that n calls to installnormalfilesmatchfn will require n calls to
53 restore matchfn to reverse'''
53 restore matchfn to reverse'''
54 scmutil.match = getattr(scmutil.match, 'oldmatch', scmutil.match)
54 scmutil.match = getattr(scmutil.match, 'oldmatch', scmutil.match)
55
55
56 def addlargefiles(ui, repo, *pats, **opts):
56 def addlargefiles(ui, repo, *pats, **opts):
57 large = opts.pop('large', None)
57 large = opts.pop('large', None)
58 lfsize = lfutil.getminsize(
58 lfsize = lfutil.getminsize(
59 ui, lfutil.islfilesrepo(repo), opts.pop('lfsize', None))
59 ui, lfutil.islfilesrepo(repo), opts.pop('lfsize', None))
60
60
61 lfmatcher = None
61 lfmatcher = None
62 if lfutil.islfilesrepo(repo):
62 if lfutil.islfilesrepo(repo):
63 lfpats = ui.configlist(lfutil.longname, 'patterns', default=[])
63 lfpats = ui.configlist(lfutil.longname, 'patterns', default=[])
64 if lfpats:
64 if lfpats:
65 lfmatcher = match_.match(repo.root, '', list(lfpats))
65 lfmatcher = match_.match(repo.root, '', list(lfpats))
66
66
67 lfnames = []
67 lfnames = []
68 m = scmutil.match(repo[None], pats, opts)
68 m = scmutil.match(repo[None], pats, opts)
69 m.bad = lambda x, y: None
69 m.bad = lambda x, y: None
70 wctx = repo[None]
70 wctx = repo[None]
71 for f in repo.walk(m):
71 for f in repo.walk(m):
72 exact = m.exact(f)
72 exact = m.exact(f)
73 lfile = lfutil.standin(f) in wctx
73 lfile = lfutil.standin(f) in wctx
74 nfile = f in wctx
74 nfile = f in wctx
75 exists = lfile or nfile
75 exists = lfile or nfile
76
76
77 # Don't warn the user when they attempt to add a normal tracked file.
77 # Don't warn the user when they attempt to add a normal tracked file.
78 # The normal add code will do that for us.
78 # The normal add code will do that for us.
79 if exact and exists:
79 if exact and exists:
80 if lfile:
80 if lfile:
81 ui.warn(_('%s already a largefile\n') % f)
81 ui.warn(_('%s already a largefile\n') % f)
82 continue
82 continue
83
83
84 if (exact or not exists) and not lfutil.isstandin(f):
84 if (exact or not exists) and not lfutil.isstandin(f):
85 wfile = repo.wjoin(f)
85 wfile = repo.wjoin(f)
86
86
87 # In case the file was removed previously, but not committed
87 # In case the file was removed previously, but not committed
88 # (issue3507)
88 # (issue3507)
89 if not os.path.exists(wfile):
89 if not os.path.exists(wfile):
90 continue
90 continue
91
91
92 abovemin = (lfsize and
92 abovemin = (lfsize and
93 os.lstat(wfile).st_size >= lfsize * 1024 * 1024)
93 os.lstat(wfile).st_size >= lfsize * 1024 * 1024)
94 if large or abovemin or (lfmatcher and lfmatcher(f)):
94 if large or abovemin or (lfmatcher and lfmatcher(f)):
95 lfnames.append(f)
95 lfnames.append(f)
96 if ui.verbose or not exact:
96 if ui.verbose or not exact:
97 ui.status(_('adding %s as a largefile\n') % m.rel(f))
97 ui.status(_('adding %s as a largefile\n') % m.rel(f))
98
98
99 bad = []
99 bad = []
100 standins = []
100 standins = []
101
101
102 # Need to lock, otherwise there could be a race condition between
102 # Need to lock, otherwise there could be a race condition between
103 # when standins are created and added to the repo.
103 # when standins are created and added to the repo.
104 wlock = repo.wlock()
104 wlock = repo.wlock()
105 try:
105 try:
106 if not opts.get('dry_run'):
106 if not opts.get('dry_run'):
107 lfdirstate = lfutil.openlfdirstate(ui, repo)
107 lfdirstate = lfutil.openlfdirstate(ui, repo)
108 for f in lfnames:
108 for f in lfnames:
109 standinname = lfutil.standin(f)
109 standinname = lfutil.standin(f)
110 lfutil.writestandin(repo, standinname, hash='',
110 lfutil.writestandin(repo, standinname, hash='',
111 executable=lfutil.getexecutable(repo.wjoin(f)))
111 executable=lfutil.getexecutable(repo.wjoin(f)))
112 standins.append(standinname)
112 standins.append(standinname)
113 if lfdirstate[f] == 'r':
113 if lfdirstate[f] == 'r':
114 lfdirstate.normallookup(f)
114 lfdirstate.normallookup(f)
115 else:
115 else:
116 lfdirstate.add(f)
116 lfdirstate.add(f)
117 lfdirstate.write()
117 lfdirstate.write()
118 bad += [lfutil.splitstandin(f)
118 bad += [lfutil.splitstandin(f)
119 for f in lfutil.repoadd(repo, standins)
119 for f in lfutil.repoadd(repo, standins)
120 if f in m.files()]
120 if f in m.files()]
121 finally:
121 finally:
122 wlock.release()
122 wlock.release()
123 return bad
123 return bad
124
124
125 def removelargefiles(ui, repo, *pats, **opts):
125 def removelargefiles(ui, repo, *pats, **opts):
126 after = opts.get('after')
126 after = opts.get('after')
127 if not pats and not after:
127 if not pats and not after:
128 raise util.Abort(_('no files specified'))
128 raise util.Abort(_('no files specified'))
129 m = scmutil.match(repo[None], pats, opts)
129 m = scmutil.match(repo[None], pats, opts)
130 try:
130 try:
131 repo.lfstatus = True
131 repo.lfstatus = True
132 s = repo.status(match=m, clean=True)
132 s = repo.status(match=m, clean=True)
133 finally:
133 finally:
134 repo.lfstatus = False
134 repo.lfstatus = False
135 manifest = repo[None].manifest()
135 manifest = repo[None].manifest()
136 modified, added, deleted, clean = [[f for f in list
136 modified, added, deleted, clean = [[f for f in list
137 if lfutil.standin(f) in manifest]
137 if lfutil.standin(f) in manifest]
138 for list in [s[0], s[1], s[3], s[6]]]
138 for list in [s[0], s[1], s[3], s[6]]]
139
139
140 def warn(files, reason):
140 def warn(files, reason):
141 for f in files:
141 for f in files:
142 ui.warn(_('not removing %s: %s (use forget to undo)\n')
142 ui.warn(_('not removing %s: %s (use forget to undo)\n')
143 % (m.rel(f), reason))
143 % (m.rel(f), reason))
144
144
145 if after:
145 if after:
146 remove, forget = deleted, []
146 remove, forget = deleted, []
147 warn(modified + added + clean, _('file still exists'))
147 warn(modified + added + clean, _('file still exists'))
148 else:
148 else:
149 remove, forget = deleted + clean, []
149 remove, forget = deleted + clean, []
150 warn(modified, _('file is modified'))
150 warn(modified, _('file is modified'))
151 warn(added, _('file has been marked for add'))
151 warn(added, _('file has been marked for add'))
152
152
153 for f in sorted(remove + forget):
153 for f in sorted(remove + forget):
154 if ui.verbose or not m.exact(f):
154 if ui.verbose or not m.exact(f):
155 ui.status(_('removing %s\n') % m.rel(f))
155 ui.status(_('removing %s\n') % m.rel(f))
156
156
157 # Need to lock because standin files are deleted then removed from the
157 # Need to lock because standin files are deleted then removed from the
158 # repository and we could race inbetween.
158 # repository and we could race inbetween.
159 wlock = repo.wlock()
159 wlock = repo.wlock()
160 try:
160 try:
161 lfdirstate = lfutil.openlfdirstate(ui, repo)
161 lfdirstate = lfutil.openlfdirstate(ui, repo)
162 for f in remove:
162 for f in remove:
163 if not after:
163 if not after:
164 # If this is being called by addremove, notify the user that we
164 # If this is being called by addremove, notify the user that we
165 # are removing the file.
165 # are removing the file.
166 if getattr(repo, "_isaddremove", False):
166 if getattr(repo, "_isaddremove", False):
167 ui.status(_('removing %s\n') % f)
167 ui.status(_('removing %s\n') % f)
168 if os.path.exists(repo.wjoin(f)):
168 if os.path.exists(repo.wjoin(f)):
169 util.unlinkpath(repo.wjoin(f))
169 util.unlinkpath(repo.wjoin(f))
170 lfdirstate.remove(f)
170 lfdirstate.remove(f)
171 lfdirstate.write()
171 lfdirstate.write()
172 forget = [lfutil.standin(f) for f in forget]
172 forget = [lfutil.standin(f) for f in forget]
173 remove = [lfutil.standin(f) for f in remove]
173 remove = [lfutil.standin(f) for f in remove]
174 lfutil.repoforget(repo, forget)
174 lfutil.repoforget(repo, forget)
175 # If this is being called by addremove, let the original addremove
175 # If this is being called by addremove, let the original addremove
176 # function handle this.
176 # function handle this.
177 if not getattr(repo, "_isaddremove", False):
177 if not getattr(repo, "_isaddremove", False):
178 lfutil.reporemove(repo, remove, unlink=True)
178 lfutil.reporemove(repo, remove, unlink=True)
179 else:
179 else:
180 lfutil.reporemove(repo, remove, unlink=False)
180 lfutil.reporemove(repo, remove, unlink=False)
181 finally:
181 finally:
182 wlock.release()
182 wlock.release()
183
183
184 # For overriding mercurial.hgweb.webcommands so that largefiles will
184 # For overriding mercurial.hgweb.webcommands so that largefiles will
185 # appear at their right place in the manifests.
185 # appear at their right place in the manifests.
186 def decodepath(orig, path):
186 def decodepath(orig, path):
187 return lfutil.splitstandin(path) or path
187 return lfutil.splitstandin(path) or path
188
188
189 # -- Wrappers: modify existing commands --------------------------------
189 # -- Wrappers: modify existing commands --------------------------------
190
190
191 # Add works by going through the files that the user wanted to add and
191 # Add works by going through the files that the user wanted to add and
192 # checking if they should be added as largefiles. Then it makes a new
192 # checking if they should be added as largefiles. Then it makes a new
193 # matcher which matches only the normal files and runs the original
193 # matcher which matches only the normal files and runs the original
194 # version of add.
194 # version of add.
195 def overrideadd(orig, ui, repo, *pats, **opts):
195 def overrideadd(orig, ui, repo, *pats, **opts):
196 normal = opts.pop('normal')
196 normal = opts.pop('normal')
197 if normal:
197 if normal:
198 if opts.get('large'):
198 if opts.get('large'):
199 raise util.Abort(_('--normal cannot be used with --large'))
199 raise util.Abort(_('--normal cannot be used with --large'))
200 return orig(ui, repo, *pats, **opts)
200 return orig(ui, repo, *pats, **opts)
201 bad = addlargefiles(ui, repo, *pats, **opts)
201 bad = addlargefiles(ui, repo, *pats, **opts)
202 installnormalfilesmatchfn(repo[None].manifest())
202 installnormalfilesmatchfn(repo[None].manifest())
203 result = orig(ui, repo, *pats, **opts)
203 result = orig(ui, repo, *pats, **opts)
204 restorematchfn()
204 restorematchfn()
205
205
206 return (result == 1 or bad) and 1 or 0
206 return (result == 1 or bad) and 1 or 0
207
207
208 def overrideremove(orig, ui, repo, *pats, **opts):
208 def overrideremove(orig, ui, repo, *pats, **opts):
209 installnormalfilesmatchfn(repo[None].manifest())
209 installnormalfilesmatchfn(repo[None].manifest())
210 orig(ui, repo, *pats, **opts)
210 orig(ui, repo, *pats, **opts)
211 restorematchfn()
211 restorematchfn()
212 removelargefiles(ui, repo, *pats, **opts)
212 removelargefiles(ui, repo, *pats, **opts)
213
213
214 def overridestatusfn(orig, repo, rev2, **opts):
214 def overridestatusfn(orig, repo, rev2, **opts):
215 try:
215 try:
216 repo._repo.lfstatus = True
216 repo._repo.lfstatus = True
217 return orig(repo, rev2, **opts)
217 return orig(repo, rev2, **opts)
218 finally:
218 finally:
219 repo._repo.lfstatus = False
219 repo._repo.lfstatus = False
220
220
221 def overridestatus(orig, ui, repo, *pats, **opts):
221 def overridestatus(orig, ui, repo, *pats, **opts):
222 try:
222 try:
223 repo.lfstatus = True
223 repo.lfstatus = True
224 return orig(ui, repo, *pats, **opts)
224 return orig(ui, repo, *pats, **opts)
225 finally:
225 finally:
226 repo.lfstatus = False
226 repo.lfstatus = False
227
227
228 def overridedirty(orig, repo, ignoreupdate=False):
228 def overridedirty(orig, repo, ignoreupdate=False):
229 try:
229 try:
230 repo._repo.lfstatus = True
230 repo._repo.lfstatus = True
231 return orig(repo, ignoreupdate)
231 return orig(repo, ignoreupdate)
232 finally:
232 finally:
233 repo._repo.lfstatus = False
233 repo._repo.lfstatus = False
234
234
235 def overridelog(orig, ui, repo, *pats, **opts):
235 def overridelog(orig, ui, repo, *pats, **opts):
236 try:
236 try:
237 repo.lfstatus = True
237 repo.lfstatus = True
238 orig(ui, repo, *pats, **opts)
238 orig(ui, repo, *pats, **opts)
239 finally:
239 finally:
240 repo.lfstatus = False
240 repo.lfstatus = False
241
241
242 def overrideverify(orig, ui, repo, *pats, **opts):
242 def overrideverify(orig, ui, repo, *pats, **opts):
243 large = opts.pop('large', False)
243 large = opts.pop('large', False)
244 all = opts.pop('lfa', False)
244 all = opts.pop('lfa', False)
245 contents = opts.pop('lfc', False)
245 contents = opts.pop('lfc', False)
246
246
247 result = orig(ui, repo, *pats, **opts)
247 result = orig(ui, repo, *pats, **opts)
248 if large:
248 if large:
249 result = result or lfcommands.verifylfiles(ui, repo, all, contents)
249 result = result or lfcommands.verifylfiles(ui, repo, all, contents)
250 return result
250 return result
251
251
252 # Override needs to refresh standins so that update's normal merge
252 # Override needs to refresh standins so that update's normal merge
253 # will go through properly. Then the other update hook (overriding repo.update)
253 # will go through properly. Then the other update hook (overriding repo.update)
254 # will get the new files. Filemerge is also overriden so that the merge
254 # will get the new files. Filemerge is also overriden so that the merge
255 # will merge standins correctly.
255 # will merge standins correctly.
256 def overrideupdate(orig, ui, repo, *pats, **opts):
256 def overrideupdate(orig, ui, repo, *pats, **opts):
257 lfdirstate = lfutil.openlfdirstate(ui, repo)
257 lfdirstate = lfutil.openlfdirstate(ui, repo)
258 s = lfdirstate.status(match_.always(repo.root, repo.getcwd()), [], False,
258 s = lfdirstate.status(match_.always(repo.root, repo.getcwd()), [], False,
259 False, False)
259 False, False)
260 (unsure, modified, added, removed, missing, unknown, ignored, clean) = s
260 (unsure, modified, added, removed, missing, unknown, ignored, clean) = s
261
261
262 # Need to lock between the standins getting updated and their
262 # Need to lock between the standins getting updated and their
263 # largefiles getting updated
263 # largefiles getting updated
264 wlock = repo.wlock()
264 wlock = repo.wlock()
265 try:
265 try:
266 if opts['check']:
266 if opts['check']:
267 mod = len(modified) > 0
267 mod = len(modified) > 0
268 for lfile in unsure:
268 for lfile in unsure:
269 standin = lfutil.standin(lfile)
269 standin = lfutil.standin(lfile)
270 if repo['.'][standin].data().strip() != \
270 if repo['.'][standin].data().strip() != \
271 lfutil.hashfile(repo.wjoin(lfile)):
271 lfutil.hashfile(repo.wjoin(lfile)):
272 mod = True
272 mod = True
273 else:
273 else:
274 lfdirstate.normal(lfile)
274 lfdirstate.normal(lfile)
275 lfdirstate.write()
275 lfdirstate.write()
276 if mod:
276 if mod:
277 raise util.Abort(_('uncommitted local changes'))
277 raise util.Abort(_('uncommitted local changes'))
278 # XXX handle removed differently
278 # XXX handle removed differently
279 if not opts['clean']:
279 if not opts['clean']:
280 for lfile in unsure + modified + added:
280 for lfile in unsure + modified + added:
281 lfutil.updatestandin(repo, lfutil.standin(lfile))
281 lfutil.updatestandin(repo, lfutil.standin(lfile))
282 finally:
282 finally:
283 wlock.release()
283 wlock.release()
284 return orig(ui, repo, *pats, **opts)
284 return orig(ui, repo, *pats, **opts)
285
285
286 # Before starting the manifest merge, merge.updates will call
286 # Before starting the manifest merge, merge.updates will call
287 # _checkunknown to check if there are any files in the merged-in
287 # _checkunknown to check if there are any files in the merged-in
288 # changeset that collide with unknown files in the working copy.
288 # changeset that collide with unknown files in the working copy.
289 #
289 #
290 # The largefiles are seen as unknown, so this prevents us from merging
290 # The largefiles are seen as unknown, so this prevents us from merging
291 # in a file 'foo' if we already have a largefile with the same name.
291 # in a file 'foo' if we already have a largefile with the same name.
292 #
292 #
293 # The overridden function filters the unknown files by removing any
293 # The overridden function filters the unknown files by removing any
294 # largefiles. This makes the merge proceed and we can then handle this
294 # largefiles. This makes the merge proceed and we can then handle this
295 # case further in the overridden manifestmerge function below.
295 # case further in the overridden manifestmerge function below.
296 def overridecheckunknownfile(origfn, repo, wctx, mctx, f):
296 def overridecheckunknownfile(origfn, repo, wctx, mctx, f):
297 if lfutil.standin(f) in wctx:
297 if lfutil.standin(f) in wctx:
298 return False
298 return False
299 return origfn(repo, wctx, mctx, f)
299 return origfn(repo, wctx, mctx, f)
300
300
301 # The manifest merge handles conflicts on the manifest level. We want
301 # The manifest merge handles conflicts on the manifest level. We want
302 # to handle changes in largefile-ness of files at this level too.
302 # to handle changes in largefile-ness of files at this level too.
303 #
303 #
304 # The strategy is to run the original manifestmerge and then process
304 # The strategy is to run the original manifestmerge and then process
305 # the action list it outputs. There are two cases we need to deal with:
305 # the action list it outputs. There are two cases we need to deal with:
306 #
306 #
307 # 1. Normal file in p1, largefile in p2. Here the largefile is
307 # 1. Normal file in p1, largefile in p2. Here the largefile is
308 # detected via its standin file, which will enter the working copy
308 # detected via its standin file, which will enter the working copy
309 # with a "get" action. It is not "merge" since the standin is all
309 # with a "get" action. It is not "merge" since the standin is all
310 # Mercurial is concerned with at this level -- the link to the
310 # Mercurial is concerned with at this level -- the link to the
311 # existing normal file is not relevant here.
311 # existing normal file is not relevant here.
312 #
312 #
313 # 2. Largefile in p1, normal file in p2. Here we get a "merge" action
313 # 2. Largefile in p1, normal file in p2. Here we get a "merge" action
314 # since the largefile will be present in the working copy and
314 # since the largefile will be present in the working copy and
315 # different from the normal file in p2. Mercurial therefore
315 # different from the normal file in p2. Mercurial therefore
316 # triggers a merge action.
316 # triggers a merge action.
317 #
317 #
318 # In both cases, we prompt the user and emit new actions to either
318 # In both cases, we prompt the user and emit new actions to either
319 # remove the standin (if the normal file was kept) or to remove the
319 # remove the standin (if the normal file was kept) or to remove the
320 # normal file and get the standin (if the largefile was kept). The
320 # normal file and get the standin (if the largefile was kept). The
321 # default prompt answer is to use the largefile version since it was
321 # default prompt answer is to use the largefile version since it was
322 # presumably changed on purpose.
322 # presumably changed on purpose.
323 #
323 #
324 # Finally, the merge.applyupdates function will then take care of
324 # Finally, the merge.applyupdates function will then take care of
325 # writing the files into the working copy and lfcommands.updatelfiles
325 # writing the files into the working copy and lfcommands.updatelfiles
326 # will update the largefiles.
326 # will update the largefiles.
327 def overridemanifestmerge(origfn, repo, p1, p2, pa, overwrite, partial):
327 def overridemanifestmerge(origfn, repo, p1, p2, pa, overwrite, partial):
328 actions = origfn(repo, p1, p2, pa, overwrite, partial)
328 actions = origfn(repo, p1, p2, pa, overwrite, partial)
329 processed = []
329 processed = []
330
330
331 for action in actions:
331 for action in actions:
332 if overwrite:
332 if overwrite:
333 processed.append(action)
333 processed.append(action)
334 continue
334 continue
335 f, m = action[:2]
335 f, m = action[:2]
336
336
337 choices = (_('&Largefile'), _('&Normal file'))
337 choices = (_('&Largefile'), _('&Normal file'))
338 if m == "g" and lfutil.splitstandin(f) in p1 and f in p2:
338 if m == "g" and lfutil.splitstandin(f) in p1 and f in p2:
339 # Case 1: normal file in the working copy, largefile in
339 # Case 1: normal file in the working copy, largefile in
340 # the second parent
340 # the second parent
341 lfile = lfutil.splitstandin(f)
341 lfile = lfutil.splitstandin(f)
342 standin = f
342 standin = f
343 msg = _('%s has been turned into a largefile\n'
343 msg = _('%s has been turned into a largefile\n'
344 'use (l)argefile or keep as (n)ormal file?') % lfile
344 'use (l)argefile or keep as (n)ormal file?') % lfile
345 if repo.ui.promptchoice(msg, choices, 0) == 0:
345 if repo.ui.promptchoice(msg, choices, 0) == 0:
346 processed.append((lfile, "r"))
346 processed.append((lfile, "r"))
347 processed.append((standin, "g", p2.flags(standin)))
347 processed.append((standin, "g", p2.flags(standin)))
348 else:
348 else:
349 processed.append((standin, "r"))
349 processed.append((standin, "r"))
350 elif m == "g" and lfutil.standin(f) in p1 and f in p2:
350 elif m == "g" and lfutil.standin(f) in p1 and f in p2:
351 # Case 2: largefile in the working copy, normal file in
351 # Case 2: largefile in the working copy, normal file in
352 # the second parent
352 # the second parent
353 standin = lfutil.standin(f)
353 standin = lfutil.standin(f)
354 lfile = f
354 lfile = f
355 msg = _('%s has been turned into a normal file\n'
355 msg = _('%s has been turned into a normal file\n'
356 'keep as (l)argefile or use (n)ormal file?') % lfile
356 'keep as (l)argefile or use (n)ormal file?') % lfile
357 if repo.ui.promptchoice(msg, choices, 0) == 0:
357 if repo.ui.promptchoice(msg, choices, 0) == 0:
358 processed.append((lfile, "r"))
358 processed.append((lfile, "r"))
359 else:
359 else:
360 processed.append((standin, "r"))
360 processed.append((standin, "r"))
361 processed.append((lfile, "g", p2.flags(lfile)))
361 processed.append((lfile, "g", p2.flags(lfile)))
362 else:
362 else:
363 processed.append(action)
363 processed.append(action)
364
364
365 return processed
365 return processed
366
366
367 # Override filemerge to prompt the user about how they wish to merge
367 # Override filemerge to prompt the user about how they wish to merge
368 # largefiles. This will handle identical edits, and copy/rename +
368 # largefiles. This will handle identical edits, and copy/rename +
369 # edit without prompting the user.
369 # edit without prompting the user.
370 def overridefilemerge(origfn, repo, mynode, orig, fcd, fco, fca):
370 def overridefilemerge(origfn, repo, mynode, orig, fcd, fco, fca):
371 # Use better variable names here. Because this is a wrapper we cannot
371 # Use better variable names here. Because this is a wrapper we cannot
372 # change the variable names in the function declaration.
372 # change the variable names in the function declaration.
373 fcdest, fcother, fcancestor = fcd, fco, fca
373 fcdest, fcother, fcancestor = fcd, fco, fca
374 if not lfutil.isstandin(orig):
374 if not lfutil.isstandin(orig):
375 return origfn(repo, mynode, orig, fcdest, fcother, fcancestor)
375 return origfn(repo, mynode, orig, fcdest, fcother, fcancestor)
376 else:
376 else:
377 if not fcother.cmp(fcdest): # files identical?
377 if not fcother.cmp(fcdest): # files identical?
378 return None
378 return None
379
379
380 # backwards, use working dir parent as ancestor
380 # backwards, use working dir parent as ancestor
381 if fcancestor == fcother:
381 if fcancestor == fcother:
382 fcancestor = fcdest.parents()[0]
382 fcancestor = fcdest.parents()[0]
383
383
384 if orig != fcother.path():
384 if orig != fcother.path():
385 repo.ui.status(_('merging %s and %s to %s\n')
385 repo.ui.status(_('merging %s and %s to %s\n')
386 % (lfutil.splitstandin(orig),
386 % (lfutil.splitstandin(orig),
387 lfutil.splitstandin(fcother.path()),
387 lfutil.splitstandin(fcother.path()),
388 lfutil.splitstandin(fcdest.path())))
388 lfutil.splitstandin(fcdest.path())))
389 else:
389 else:
390 repo.ui.status(_('merging %s\n')
390 repo.ui.status(_('merging %s\n')
391 % lfutil.splitstandin(fcdest.path()))
391 % lfutil.splitstandin(fcdest.path()))
392
392
393 if fcancestor.path() != fcother.path() and fcother.data() == \
393 if fcancestor.path() != fcother.path() and fcother.data() == \
394 fcancestor.data():
394 fcancestor.data():
395 return 0
395 return 0
396 if fcancestor.path() != fcdest.path() and fcdest.data() == \
396 if fcancestor.path() != fcdest.path() and fcdest.data() == \
397 fcancestor.data():
397 fcancestor.data():
398 repo.wwrite(fcdest.path(), fcother.data(), fcother.flags())
398 repo.wwrite(fcdest.path(), fcother.data(), fcother.flags())
399 return 0
399 return 0
400
400
401 if repo.ui.promptchoice(_('largefile %s has a merge conflict\n'
401 if repo.ui.promptchoice(_('largefile %s has a merge conflict\n'
402 'keep (l)ocal or take (o)ther?') %
402 'keep (l)ocal or take (o)ther?') %
403 lfutil.splitstandin(orig),
403 lfutil.splitstandin(orig),
404 (_('&Local'), _('&Other')), 0) == 0:
404 (_('&Local'), _('&Other')), 0) == 0:
405 return 0
405 return 0
406 else:
406 else:
407 repo.wwrite(fcdest.path(), fcother.data(), fcother.flags())
407 repo.wwrite(fcdest.path(), fcother.data(), fcother.flags())
408 return 0
408 return 0
409
409
410 # Copy first changes the matchers to match standins instead of
410 # Copy first changes the matchers to match standins instead of
411 # largefiles. Then it overrides util.copyfile in that function it
411 # largefiles. Then it overrides util.copyfile in that function it
412 # checks if the destination largefile already exists. It also keeps a
412 # checks if the destination largefile already exists. It also keeps a
413 # list of copied files so that the largefiles can be copied and the
413 # list of copied files so that the largefiles can be copied and the
414 # dirstate updated.
414 # dirstate updated.
415 def overridecopy(orig, ui, repo, pats, opts, rename=False):
415 def overridecopy(orig, ui, repo, pats, opts, rename=False):
416 # doesn't remove largefile on rename
416 # doesn't remove largefile on rename
417 if len(pats) < 2:
417 if len(pats) < 2:
418 # this isn't legal, let the original function deal with it
418 # this isn't legal, let the original function deal with it
419 return orig(ui, repo, pats, opts, rename)
419 return orig(ui, repo, pats, opts, rename)
420
420
421 def makestandin(relpath):
421 def makestandin(relpath):
422 path = scmutil.canonpath(repo.root, repo.getcwd(), relpath)
422 path = scmutil.canonpath(repo.root, repo.getcwd(), relpath)
423 return os.path.join(repo.wjoin(lfutil.standin(path)))
423 return os.path.join(repo.wjoin(lfutil.standin(path)))
424
424
425 fullpats = scmutil.expandpats(pats)
425 fullpats = scmutil.expandpats(pats)
426 dest = fullpats[-1]
426 dest = fullpats[-1]
427
427
428 if os.path.isdir(dest):
428 if os.path.isdir(dest):
429 if not os.path.isdir(makestandin(dest)):
429 if not os.path.isdir(makestandin(dest)):
430 os.makedirs(makestandin(dest))
430 os.makedirs(makestandin(dest))
431 # This could copy both lfiles and normal files in one command,
431 # This could copy both lfiles and normal files in one command,
432 # but we don't want to do that. First replace their matcher to
432 # but we don't want to do that. First replace their matcher to
433 # only match normal files and run it, then replace it to just
433 # only match normal files and run it, then replace it to just
434 # match largefiles and run it again.
434 # match largefiles and run it again.
435 nonormalfiles = False
435 nonormalfiles = False
436 nolfiles = False
436 nolfiles = False
437 try:
437 try:
438 try:
438 try:
439 installnormalfilesmatchfn(repo[None].manifest())
439 installnormalfilesmatchfn(repo[None].manifest())
440 result = orig(ui, repo, pats, opts, rename)
440 result = orig(ui, repo, pats, opts, rename)
441 except util.Abort, e:
441 except util.Abort, e:
442 if str(e) != _('no files to copy'):
442 if str(e) != _('no files to copy'):
443 raise e
443 raise e
444 else:
444 else:
445 nonormalfiles = True
445 nonormalfiles = True
446 result = 0
446 result = 0
447 finally:
447 finally:
448 restorematchfn()
448 restorematchfn()
449
449
450 # The first rename can cause our current working directory to be removed.
450 # The first rename can cause our current working directory to be removed.
451 # In that case there is nothing left to copy/rename so just quit.
451 # In that case there is nothing left to copy/rename so just quit.
452 try:
452 try:
453 repo.getcwd()
453 repo.getcwd()
454 except OSError:
454 except OSError:
455 return result
455 return result
456
456
457 try:
457 try:
458 try:
458 try:
459 # When we call orig below it creates the standins but we don't add
459 # When we call orig below it creates the standins but we don't add
460 # them to the dir state until later so lock during that time.
460 # them to the dir state until later so lock during that time.
461 wlock = repo.wlock()
461 wlock = repo.wlock()
462
462
463 manifest = repo[None].manifest()
463 manifest = repo[None].manifest()
464 oldmatch = None # for the closure
464 oldmatch = None # for the closure
465 def overridematch(ctx, pats=[], opts={}, globbed=False,
465 def overridematch(ctx, pats=[], opts={}, globbed=False,
466 default='relpath'):
466 default='relpath'):
467 newpats = []
467 newpats = []
468 # The patterns were previously mangled to add the standin
468 # The patterns were previously mangled to add the standin
469 # directory; we need to remove that now
469 # directory; we need to remove that now
470 for pat in pats:
470 for pat in pats:
471 if match_.patkind(pat) is None and lfutil.shortname in pat:
471 if match_.patkind(pat) is None and lfutil.shortname in pat:
472 newpats.append(pat.replace(lfutil.shortname, ''))
472 newpats.append(pat.replace(lfutil.shortname, ''))
473 else:
473 else:
474 newpats.append(pat)
474 newpats.append(pat)
475 match = oldmatch(ctx, newpats, opts, globbed, default)
475 match = oldmatch(ctx, newpats, opts, globbed, default)
476 m = copy.copy(match)
476 m = copy.copy(match)
477 lfile = lambda f: lfutil.standin(f) in manifest
477 lfile = lambda f: lfutil.standin(f) in manifest
478 m._files = [lfutil.standin(f) for f in m._files if lfile(f)]
478 m._files = [lfutil.standin(f) for f in m._files if lfile(f)]
479 m._fmap = set(m._files)
479 m._fmap = set(m._files)
480 origmatchfn = m.matchfn
480 origmatchfn = m.matchfn
481 m.matchfn = lambda f: (lfutil.isstandin(f) and
481 m.matchfn = lambda f: (lfutil.isstandin(f) and
482 (f in manifest) and
482 (f in manifest) and
483 origmatchfn(lfutil.splitstandin(f)) or
483 origmatchfn(lfutil.splitstandin(f)) or
484 None)
484 None)
485 return m
485 return m
486 oldmatch = installmatchfn(overridematch)
486 oldmatch = installmatchfn(overridematch)
487 listpats = []
487 listpats = []
488 for pat in pats:
488 for pat in pats:
489 if match_.patkind(pat) is not None:
489 if match_.patkind(pat) is not None:
490 listpats.append(pat)
490 listpats.append(pat)
491 else:
491 else:
492 listpats.append(makestandin(pat))
492 listpats.append(makestandin(pat))
493
493
494 try:
494 try:
495 origcopyfile = util.copyfile
495 origcopyfile = util.copyfile
496 copiedfiles = []
496 copiedfiles = []
497 def overridecopyfile(src, dest):
497 def overridecopyfile(src, dest):
498 if (lfutil.shortname in src and
498 if (lfutil.shortname in src and
499 dest.startswith(repo.wjoin(lfutil.shortname))):
499 dest.startswith(repo.wjoin(lfutil.shortname))):
500 destlfile = dest.replace(lfutil.shortname, '')
500 destlfile = dest.replace(lfutil.shortname, '')
501 if not opts['force'] and os.path.exists(destlfile):
501 if not opts['force'] and os.path.exists(destlfile):
502 raise IOError('',
502 raise IOError('',
503 _('destination largefile already exists'))
503 _('destination largefile already exists'))
504 copiedfiles.append((src, dest))
504 copiedfiles.append((src, dest))
505 origcopyfile(src, dest)
505 origcopyfile(src, dest)
506
506
507 util.copyfile = overridecopyfile
507 util.copyfile = overridecopyfile
508 result += orig(ui, repo, listpats, opts, rename)
508 result += orig(ui, repo, listpats, opts, rename)
509 finally:
509 finally:
510 util.copyfile = origcopyfile
510 util.copyfile = origcopyfile
511
511
512 lfdirstate = lfutil.openlfdirstate(ui, repo)
512 lfdirstate = lfutil.openlfdirstate(ui, repo)
513 for (src, dest) in copiedfiles:
513 for (src, dest) in copiedfiles:
514 if (lfutil.shortname in src and
514 if (lfutil.shortname in src and
515 dest.startswith(repo.wjoin(lfutil.shortname))):
515 dest.startswith(repo.wjoin(lfutil.shortname))):
516 srclfile = src.replace(repo.wjoin(lfutil.standin('')), '')
516 srclfile = src.replace(repo.wjoin(lfutil.standin('')), '')
517 destlfile = dest.replace(repo.wjoin(lfutil.standin('')), '')
517 destlfile = dest.replace(repo.wjoin(lfutil.standin('')), '')
518 destlfiledir = os.path.dirname(repo.wjoin(destlfile)) or '.'
518 destlfiledir = os.path.dirname(repo.wjoin(destlfile)) or '.'
519 if not os.path.isdir(destlfiledir):
519 if not os.path.isdir(destlfiledir):
520 os.makedirs(destlfiledir)
520 os.makedirs(destlfiledir)
521 if rename:
521 if rename:
522 os.rename(repo.wjoin(srclfile), repo.wjoin(destlfile))
522 os.rename(repo.wjoin(srclfile), repo.wjoin(destlfile))
523 lfdirstate.remove(srclfile)
523 lfdirstate.remove(srclfile)
524 else:
524 else:
525 util.copyfile(repo.wjoin(srclfile),
525 util.copyfile(repo.wjoin(srclfile),
526 repo.wjoin(destlfile))
526 repo.wjoin(destlfile))
527
527
528 lfdirstate.add(destlfile)
528 lfdirstate.add(destlfile)
529 lfdirstate.write()
529 lfdirstate.write()
530 except util.Abort, e:
530 except util.Abort, e:
531 if str(e) != _('no files to copy'):
531 if str(e) != _('no files to copy'):
532 raise e
532 raise e
533 else:
533 else:
534 nolfiles = True
534 nolfiles = True
535 finally:
535 finally:
536 restorematchfn()
536 restorematchfn()
537 wlock.release()
537 wlock.release()
538
538
539 if nolfiles and nonormalfiles:
539 if nolfiles and nonormalfiles:
540 raise util.Abort(_('no files to copy'))
540 raise util.Abort(_('no files to copy'))
541
541
542 return result
542 return result
543
543
544 # When the user calls revert, we have to be careful to not revert any
544 # When the user calls revert, we have to be careful to not revert any
545 # changes to other largefiles accidentally. This means we have to keep
545 # changes to other largefiles accidentally. This means we have to keep
546 # track of the largefiles that are being reverted so we only pull down
546 # track of the largefiles that are being reverted so we only pull down
547 # the necessary largefiles.
547 # the necessary largefiles.
548 #
548 #
549 # Standins are only updated (to match the hash of largefiles) before
549 # Standins are only updated (to match the hash of largefiles) before
550 # commits. Update the standins then run the original revert, changing
550 # commits. Update the standins then run the original revert, changing
551 # the matcher to hit standins instead of largefiles. Based on the
551 # the matcher to hit standins instead of largefiles. Based on the
552 # resulting standins update the largefiles. Then return the standins
552 # resulting standins update the largefiles. Then return the standins
553 # to their proper state
553 # to their proper state
554 def overriderevert(orig, ui, repo, *pats, **opts):
554 def overriderevert(orig, ui, repo, *pats, **opts):
555 # Because we put the standins in a bad state (by updating them)
555 # Because we put the standins in a bad state (by updating them)
556 # and then return them to a correct state we need to lock to
556 # and then return them to a correct state we need to lock to
557 # prevent others from changing them in their incorrect state.
557 # prevent others from changing them in their incorrect state.
558 wlock = repo.wlock()
558 wlock = repo.wlock()
559 try:
559 try:
560 lfdirstate = lfutil.openlfdirstate(ui, repo)
560 lfdirstate = lfutil.openlfdirstate(ui, repo)
561 (modified, added, removed, missing, unknown, ignored, clean) = \
561 (modified, added, removed, missing, unknown, ignored, clean) = \
562 lfutil.lfdirstatestatus(lfdirstate, repo, repo['.'].rev())
562 lfutil.lfdirstatestatus(lfdirstate, repo, repo['.'].rev())
563 for lfile in modified:
563 for lfile in modified:
564 lfutil.updatestandin(repo, lfutil.standin(lfile))
564 lfutil.updatestandin(repo, lfutil.standin(lfile))
565 for lfile in missing:
565 for lfile in missing:
566 if (os.path.exists(repo.wjoin(lfutil.standin(lfile)))):
566 if (os.path.exists(repo.wjoin(lfutil.standin(lfile)))):
567 os.unlink(repo.wjoin(lfutil.standin(lfile)))
567 os.unlink(repo.wjoin(lfutil.standin(lfile)))
568
568
569 try:
569 try:
570 ctx = scmutil.revsingle(repo, opts.get('rev'))
570 ctx = scmutil.revsingle(repo, opts.get('rev'))
571 oldmatch = None # for the closure
571 oldmatch = None # for the closure
572 def overridematch(ctx, pats=[], opts={}, globbed=False,
572 def overridematch(ctx, pats=[], opts={}, globbed=False,
573 default='relpath'):
573 default='relpath'):
574 match = oldmatch(ctx, pats, opts, globbed, default)
574 match = oldmatch(ctx, pats, opts, globbed, default)
575 m = copy.copy(match)
575 m = copy.copy(match)
576 def tostandin(f):
576 def tostandin(f):
577 if lfutil.standin(f) in ctx:
577 if lfutil.standin(f) in ctx:
578 return lfutil.standin(f)
578 return lfutil.standin(f)
579 elif lfutil.standin(f) in repo[None]:
579 elif lfutil.standin(f) in repo[None]:
580 return None
580 return None
581 return f
581 return f
582 m._files = [tostandin(f) for f in m._files]
582 m._files = [tostandin(f) for f in m._files]
583 m._files = [f for f in m._files if f is not None]
583 m._files = [f for f in m._files if f is not None]
584 m._fmap = set(m._files)
584 m._fmap = set(m._files)
585 origmatchfn = m.matchfn
585 origmatchfn = m.matchfn
586 def matchfn(f):
586 def matchfn(f):
587 if lfutil.isstandin(f):
587 if lfutil.isstandin(f):
588 # We need to keep track of what largefiles are being
588 # We need to keep track of what largefiles are being
589 # matched so we know which ones to update later --
589 # matched so we know which ones to update later --
590 # otherwise we accidentally revert changes to other
590 # otherwise we accidentally revert changes to other
591 # largefiles. This is repo-specific, so duckpunch the
591 # largefiles. This is repo-specific, so duckpunch the
592 # repo object to keep the list of largefiles for us
592 # repo object to keep the list of largefiles for us
593 # later.
593 # later.
594 if origmatchfn(lfutil.splitstandin(f)) and \
594 if origmatchfn(lfutil.splitstandin(f)) and \
595 (f in repo[None] or f in ctx):
595 (f in repo[None] or f in ctx):
596 lfileslist = getattr(repo, '_lfilestoupdate', [])
596 lfileslist = getattr(repo, '_lfilestoupdate', [])
597 lfileslist.append(lfutil.splitstandin(f))
597 lfileslist.append(lfutil.splitstandin(f))
598 repo._lfilestoupdate = lfileslist
598 repo._lfilestoupdate = lfileslist
599 return True
599 return True
600 else:
600 else:
601 return False
601 return False
602 return origmatchfn(f)
602 return origmatchfn(f)
603 m.matchfn = matchfn
603 m.matchfn = matchfn
604 return m
604 return m
605 oldmatch = installmatchfn(overridematch)
605 oldmatch = installmatchfn(overridematch)
606 scmutil.match
606 scmutil.match
607 matches = overridematch(repo[None], pats, opts)
607 matches = overridematch(repo[None], pats, opts)
608 orig(ui, repo, *pats, **opts)
608 orig(ui, repo, *pats, **opts)
609 finally:
609 finally:
610 restorematchfn()
610 restorematchfn()
611 lfileslist = getattr(repo, '_lfilestoupdate', [])
611 lfileslist = getattr(repo, '_lfilestoupdate', [])
612 lfcommands.updatelfiles(ui, repo, filelist=lfileslist,
612 lfcommands.updatelfiles(ui, repo, filelist=lfileslist,
613 printmessage=False)
613 printmessage=False)
614
614
615 # empty out the largefiles list so we start fresh next time
615 # empty out the largefiles list so we start fresh next time
616 repo._lfilestoupdate = []
616 repo._lfilestoupdate = []
617 for lfile in modified:
617 for lfile in modified:
618 if lfile in lfileslist:
618 if lfile in lfileslist:
619 if os.path.exists(repo.wjoin(lfutil.standin(lfile))) and lfile\
619 if os.path.exists(repo.wjoin(lfutil.standin(lfile))) and lfile\
620 in repo['.']:
620 in repo['.']:
621 lfutil.writestandin(repo, lfutil.standin(lfile),
621 lfutil.writestandin(repo, lfutil.standin(lfile),
622 repo['.'][lfile].data().strip(),
622 repo['.'][lfile].data().strip(),
623 'x' in repo['.'][lfile].flags())
623 'x' in repo['.'][lfile].flags())
624 lfdirstate = lfutil.openlfdirstate(ui, repo)
624 lfdirstate = lfutil.openlfdirstate(ui, repo)
625 for lfile in added:
625 for lfile in added:
626 standin = lfutil.standin(lfile)
626 standin = lfutil.standin(lfile)
627 if standin not in ctx and (standin in matches or opts.get('all')):
627 if standin not in ctx and (standin in matches or opts.get('all')):
628 if lfile in lfdirstate:
628 if lfile in lfdirstate:
629 lfdirstate.drop(lfile)
629 lfdirstate.drop(lfile)
630 util.unlinkpath(repo.wjoin(standin))
630 util.unlinkpath(repo.wjoin(standin))
631 lfdirstate.write()
631 lfdirstate.write()
632 finally:
632 finally:
633 wlock.release()
633 wlock.release()
634
634
635 def hgupdate(orig, repo, node):
635 def hgupdate(orig, repo, node):
636 # Only call updatelfiles the standins that have changed to save time
636 # Only call updatelfiles the standins that have changed to save time
637 oldstandins = lfutil.getstandinsstate(repo)
637 oldstandins = lfutil.getstandinsstate(repo)
638 result = orig(repo, node)
638 result = orig(repo, node)
639 newstandins = lfutil.getstandinsstate(repo)
639 newstandins = lfutil.getstandinsstate(repo)
640 filelist = lfutil.getlfilestoupdate(oldstandins, newstandins)
640 filelist = lfutil.getlfilestoupdate(oldstandins, newstandins)
641 lfcommands.updatelfiles(repo.ui, repo, filelist=filelist, printmessage=True)
641 lfcommands.updatelfiles(repo.ui, repo, filelist=filelist, printmessage=True)
642 return result
642 return result
643
643
644 def hgclean(orig, repo, node, show_stats=True):
644 def hgclean(orig, repo, node, show_stats=True):
645 result = orig(repo, node, show_stats)
645 result = orig(repo, node, show_stats)
646 lfcommands.updatelfiles(repo.ui, repo)
646 lfcommands.updatelfiles(repo.ui, repo)
647 return result
647 return result
648
648
649 def hgmerge(orig, repo, node, force=None, remind=True):
649 def hgmerge(orig, repo, node, force=None, remind=True):
650 # Mark the repo as being in the middle of a merge, so that
650 # Mark the repo as being in the middle of a merge, so that
651 # updatelfiles() will know that it needs to trust the standins in
651 # updatelfiles() will know that it needs to trust the standins in
652 # the working copy, not in the standins in the current node
652 # the working copy, not in the standins in the current node
653 repo._ismerging = True
653 repo._ismerging = True
654 try:
654 try:
655 result = orig(repo, node, force, remind)
655 result = orig(repo, node, force, remind)
656 lfcommands.updatelfiles(repo.ui, repo)
656 lfcommands.updatelfiles(repo.ui, repo)
657 finally:
657 finally:
658 repo._ismerging = False
658 repo._ismerging = False
659 return result
659 return result
660
660
661 # When we rebase a repository with remotely changed largefiles, we need to
661 # When we rebase a repository with remotely changed largefiles, we need to
662 # take some extra care so that the largefiles are correctly updated in the
662 # take some extra care so that the largefiles are correctly updated in the
663 # working copy
663 # working copy
664 def overridepull(orig, ui, repo, source=None, **opts):
664 def overridepull(orig, ui, repo, source=None, **opts):
665 revsprepull = len(repo)
665 revsprepull = len(repo)
666 if opts.get('rebase', False):
666 if opts.get('rebase', False):
667 repo._isrebasing = True
667 repo._isrebasing = True
668 try:
668 try:
669 if opts.get('update'):
669 if opts.get('update'):
670 del opts['update']
670 del opts['update']
671 ui.debug('--update and --rebase are not compatible, ignoring '
671 ui.debug('--update and --rebase are not compatible, ignoring '
672 'the update flag\n')
672 'the update flag\n')
673 del opts['rebase']
673 del opts['rebase']
674 cmdutil.bailifchanged(repo)
674 cmdutil.bailifchanged(repo)
675 origpostincoming = commands.postincoming
675 origpostincoming = commands.postincoming
676 def _dummy(*args, **kwargs):
676 def _dummy(*args, **kwargs):
677 pass
677 pass
678 commands.postincoming = _dummy
678 commands.postincoming = _dummy
679 repo.lfpullsource = source
679 repo.lfpullsource = source
680 if not source:
680 if not source:
681 source = 'default'
681 source = 'default'
682 try:
682 try:
683 result = commands.pull(ui, repo, source, **opts)
683 result = commands.pull(ui, repo, source, **opts)
684 finally:
684 finally:
685 commands.postincoming = origpostincoming
685 commands.postincoming = origpostincoming
686 revspostpull = len(repo)
686 revspostpull = len(repo)
687 if revspostpull > revsprepull:
687 if revspostpull > revsprepull:
688 result = result or rebase.rebase(ui, repo)
688 result = result or rebase.rebase(ui, repo)
689 finally:
689 finally:
690 repo._isrebasing = False
690 repo._isrebasing = False
691 else:
691 else:
692 repo.lfpullsource = source
692 repo.lfpullsource = source
693 if not source:
693 if not source:
694 source = 'default'
694 source = 'default'
695 oldheads = lfutil.getcurrentheads(repo)
695 oldheads = lfutil.getcurrentheads(repo)
696 result = orig(ui, repo, source, **opts)
696 result = orig(ui, repo, source, **opts)
697 # If we do not have the new largefiles for any new heads we pulled, we
697 # If we do not have the new largefiles for any new heads we pulled, we
698 # will run into a problem later if we try to merge or rebase with one of
698 # will run into a problem later if we try to merge or rebase with one of
699 # these heads, so cache the largefiles now direclty into the system
699 # these heads, so cache the largefiles now direclty into the system
700 # cache.
700 # cache.
701 ui.status(_("caching new largefiles\n"))
701 ui.status(_("caching new largefiles\n"))
702 numcached = 0
702 numcached = 0
703 heads = lfutil.getcurrentheads(repo)
703 heads = lfutil.getcurrentheads(repo)
704 newheads = set(heads).difference(set(oldheads))
704 newheads = set(heads).difference(set(oldheads))
705 for head in newheads:
705 for head in newheads:
706 (cached, missing) = lfcommands.cachelfiles(ui, repo, head)
706 (cached, missing) = lfcommands.cachelfiles(ui, repo, head)
707 numcached += len(cached)
707 numcached += len(cached)
708 ui.status(_("%d largefiles cached\n") % numcached)
708 ui.status(_("%d largefiles cached\n") % numcached)
709 if opts.get('all_largefiles'):
709 if opts.get('all_largefiles'):
710 revspostpull = len(repo)
710 revspostpull = len(repo)
711 revs = []
711 revs = []
712 for rev in xrange(revsprepull + 1, revspostpull):
712 for rev in xrange(revsprepull + 1, revspostpull):
713 revs.append(repo[rev].rev())
713 revs.append(repo[rev].rev())
714 lfcommands.downloadlfiles(ui, repo, revs)
714 lfcommands.downloadlfiles(ui, repo, revs)
715 return result
715 return result
716
716
717 def overrideclone(orig, ui, source, dest=None, **opts):
717 def overrideclone(orig, ui, source, dest=None, **opts):
718 if dest is None:
718 if dest is None:
719 dest = hg.defaultdest(source)
719 dest = hg.defaultdest(source)
720 if opts.get('all_largefiles') and not hg.islocal(dest):
720 if opts.get('all_largefiles') and not hg.islocal(dest):
721 raise util.Abort(_(
721 raise util.Abort(_(
722 '--all-largefiles is incompatible with non-local destination %s' %
722 '--all-largefiles is incompatible with non-local destination %s' %
723 dest))
723 dest))
724 result = hg.clone(ui, opts, source, dest,
724 result = hg.clone(ui, opts, source, dest,
725 pull=opts.get('pull'),
725 pull=opts.get('pull'),
726 stream=opts.get('uncompressed'),
726 stream=opts.get('uncompressed'),
727 rev=opts.get('rev'),
727 rev=opts.get('rev'),
728 update=True, # required for successful walkchangerevs
728 update=True, # required for successful walkchangerevs
729 branch=opts.get('branch'))
729 branch=opts.get('branch'))
730 if result is None:
730 if result is None:
731 return True
731 return True
732 if opts.get('all_largefiles'):
732 if opts.get('all_largefiles'):
733 sourcerepo, destrepo = result
733 sourcerepo, destrepo = result
734 success, missing = lfcommands.downloadlfiles(ui, destrepo.local(), None)
734 success, missing = lfcommands.downloadlfiles(ui, destrepo.local(), None)
735 return missing != 0
735 return missing != 0
736 return result is None
736 return result is None
737
737
738 def overriderebase(orig, ui, repo, **opts):
738 def overriderebase(orig, ui, repo, **opts):
739 repo._isrebasing = True
739 repo._isrebasing = True
740 try:
740 try:
741 orig(ui, repo, **opts)
741 orig(ui, repo, **opts)
742 finally:
742 finally:
743 repo._isrebasing = False
743 repo._isrebasing = False
744
744
745 def overridearchive(orig, repo, dest, node, kind, decode=True, matchfn=None,
745 def overridearchive(orig, repo, dest, node, kind, decode=True, matchfn=None,
746 prefix=None, mtime=None, subrepos=None):
746 prefix=None, mtime=None, subrepos=None):
747 # No need to lock because we are only reading history and
747 # No need to lock because we are only reading history and
748 # largefile caches, neither of which are modified.
748 # largefile caches, neither of which are modified.
749 lfcommands.cachelfiles(repo.ui, repo, node)
749 lfcommands.cachelfiles(repo.ui, repo, node)
750
750
751 if kind not in archival.archivers:
751 if kind not in archival.archivers:
752 raise util.Abort(_("unknown archive type '%s'") % kind)
752 raise util.Abort(_("unknown archive type '%s'") % kind)
753
753
754 ctx = repo[node]
754 ctx = repo[node]
755
755
756 if kind == 'files':
756 if kind == 'files':
757 if prefix:
757 if prefix:
758 raise util.Abort(
758 raise util.Abort(
759 _('cannot give prefix when archiving to files'))
759 _('cannot give prefix when archiving to files'))
760 else:
760 else:
761 prefix = archival.tidyprefix(dest, kind, prefix)
761 prefix = archival.tidyprefix(dest, kind, prefix)
762
762
763 def write(name, mode, islink, getdata):
763 def write(name, mode, islink, getdata):
764 if matchfn and not matchfn(name):
764 if matchfn and not matchfn(name):
765 return
765 return
766 data = getdata()
766 data = getdata()
767 if decode:
767 if decode:
768 data = repo.wwritedata(name, data)
768 data = repo.wwritedata(name, data)
769 archiver.addfile(prefix + name, mode, islink, data)
769 archiver.addfile(prefix + name, mode, islink, data)
770
770
771 archiver = archival.archivers[kind](dest, mtime or ctx.date()[0])
771 archiver = archival.archivers[kind](dest, mtime or ctx.date()[0])
772
772
773 if repo.ui.configbool("ui", "archivemeta", True):
773 if repo.ui.configbool("ui", "archivemeta", True):
774 def metadata():
774 def metadata():
775 base = 'repo: %s\nnode: %s\nbranch: %s\n' % (
775 base = 'repo: %s\nnode: %s\nbranch: %s\n' % (
776 hex(repo.changelog.node(0)), hex(node), ctx.branch())
776 hex(repo.changelog.node(0)), hex(node), ctx.branch())
777
777
778 tags = ''.join('tag: %s\n' % t for t in ctx.tags()
778 tags = ''.join('tag: %s\n' % t for t in ctx.tags()
779 if repo.tagtype(t) == 'global')
779 if repo.tagtype(t) == 'global')
780 if not tags:
780 if not tags:
781 repo.ui.pushbuffer()
781 repo.ui.pushbuffer()
782 opts = {'template': '{latesttag}\n{latesttagdistance}',
782 opts = {'template': '{latesttag}\n{latesttagdistance}',
783 'style': '', 'patch': None, 'git': None}
783 'style': '', 'patch': None, 'git': None}
784 cmdutil.show_changeset(repo.ui, repo, opts).show(ctx)
784 cmdutil.show_changeset(repo.ui, repo, opts).show(ctx)
785 ltags, dist = repo.ui.popbuffer().split('\n')
785 ltags, dist = repo.ui.popbuffer().split('\n')
786 tags = ''.join('latesttag: %s\n' % t for t in ltags.split(':'))
786 tags = ''.join('latesttag: %s\n' % t for t in ltags.split(':'))
787 tags += 'latesttagdistance: %s\n' % dist
787 tags += 'latesttagdistance: %s\n' % dist
788
788
789 return base + tags
789 return base + tags
790
790
791 write('.hg_archival.txt', 0644, False, metadata)
791 write('.hg_archival.txt', 0644, False, metadata)
792
792
793 for f in ctx:
793 for f in ctx:
794 ff = ctx.flags(f)
794 ff = ctx.flags(f)
795 getdata = ctx[f].data
795 getdata = ctx[f].data
796 if lfutil.isstandin(f):
796 if lfutil.isstandin(f):
797 path = lfutil.findfile(repo, getdata().strip())
797 path = lfutil.findfile(repo, getdata().strip())
798 if path is None:
798 if path is None:
799 raise util.Abort(
799 raise util.Abort(
800 _('largefile %s not found in repo store or system cache')
800 _('largefile %s not found in repo store or system cache')
801 % lfutil.splitstandin(f))
801 % lfutil.splitstandin(f))
802 f = lfutil.splitstandin(f)
802 f = lfutil.splitstandin(f)
803
803
804 def getdatafn():
804 def getdatafn():
805 fd = None
805 fd = None
806 try:
806 try:
807 fd = open(path, 'rb')
807 fd = open(path, 'rb')
808 return fd.read()
808 return fd.read()
809 finally:
809 finally:
810 if fd:
810 if fd:
811 fd.close()
811 fd.close()
812
812
813 getdata = getdatafn
813 getdata = getdatafn
814 write(f, 'x' in ff and 0755 or 0644, 'l' in ff, getdata)
814 write(f, 'x' in ff and 0755 or 0644, 'l' in ff, getdata)
815
815
816 if subrepos:
816 if subrepos:
817 for subpath in ctx.substate:
817 for subpath in ctx.substate:
818 sub = ctx.sub(subpath)
818 sub = ctx.sub(subpath)
819 submatch = match_.narrowmatcher(subpath, matchfn)
819 submatch = match_.narrowmatcher(subpath, matchfn)
820 sub.archive(repo.ui, archiver, prefix, submatch)
820 sub.archive(repo.ui, archiver, prefix, submatch)
821
821
822 archiver.done()
822 archiver.done()
823
823
824 def hgsubrepoarchive(orig, repo, ui, archiver, prefix, match=None):
824 def hgsubrepoarchive(orig, repo, ui, archiver, prefix, match=None):
825 rev = repo._state[1]
825 rev = repo._state[1]
826 ctx = repo._repo[rev]
826 ctx = repo._repo[rev]
827
827
828 lfcommands.cachelfiles(ui, repo._repo, ctx.node())
828 lfcommands.cachelfiles(ui, repo._repo, ctx.node())
829
829
830 def write(name, mode, islink, getdata):
830 def write(name, mode, islink, getdata):
831 # At this point, the standin has been replaced with the largefile name,
831 # At this point, the standin has been replaced with the largefile name,
832 # so the normal matcher works here without the lfutil variants.
832 # so the normal matcher works here without the lfutil variants.
833 if match and not match(f):
833 if match and not match(f):
834 return
834 return
835 data = getdata()
835 data = getdata()
836
836
837 archiver.addfile(prefix + repo._path + '/' + name, mode, islink, data)
837 archiver.addfile(prefix + repo._path + '/' + name, mode, islink, data)
838
838
839 for f in ctx:
839 for f in ctx:
840 ff = ctx.flags(f)
840 ff = ctx.flags(f)
841 getdata = ctx[f].data
841 getdata = ctx[f].data
842 if lfutil.isstandin(f):
842 if lfutil.isstandin(f):
843 path = lfutil.findfile(repo._repo, getdata().strip())
843 path = lfutil.findfile(repo._repo, getdata().strip())
844 if path is None:
844 if path is None:
845 raise util.Abort(
845 raise util.Abort(
846 _('largefile %s not found in repo store or system cache')
846 _('largefile %s not found in repo store or system cache')
847 % lfutil.splitstandin(f))
847 % lfutil.splitstandin(f))
848 f = lfutil.splitstandin(f)
848 f = lfutil.splitstandin(f)
849
849
850 def getdatafn():
850 def getdatafn():
851 fd = None
851 fd = None
852 try:
852 try:
853 fd = open(os.path.join(prefix, path), 'rb')
853 fd = open(os.path.join(prefix, path), 'rb')
854 return fd.read()
854 return fd.read()
855 finally:
855 finally:
856 if fd:
856 if fd:
857 fd.close()
857 fd.close()
858
858
859 getdata = getdatafn
859 getdata = getdatafn
860
860
861 write(f, 'x' in ff and 0755 or 0644, 'l' in ff, getdata)
861 write(f, 'x' in ff and 0755 or 0644, 'l' in ff, getdata)
862
862
863 for subpath in ctx.substate:
863 for subpath in ctx.substate:
864 sub = ctx.sub(subpath)
864 sub = ctx.sub(subpath)
865 submatch = match_.narrowmatcher(subpath, match)
865 submatch = match_.narrowmatcher(subpath, match)
866 sub.archive(ui, archiver, os.path.join(prefix, repo._path) + '/',
866 sub.archive(ui, archiver, os.path.join(prefix, repo._path) + '/',
867 submatch)
867 submatch)
868
868
869 # If a largefile is modified, the change is not reflected in its
869 # If a largefile is modified, the change is not reflected in its
870 # standin until a commit. cmdutil.bailifchanged() raises an exception
870 # standin until a commit. cmdutil.bailifchanged() raises an exception
871 # if the repo has uncommitted changes. Wrap it to also check if
871 # if the repo has uncommitted changes. Wrap it to also check if
872 # largefiles were changed. This is used by bisect and backout.
872 # largefiles were changed. This is used by bisect and backout.
873 def overridebailifchanged(orig, repo):
873 def overridebailifchanged(orig, repo):
874 orig(repo)
874 orig(repo)
875 repo.lfstatus = True
875 repo.lfstatus = True
876 modified, added, removed, deleted = repo.status()[:4]
876 modified, added, removed, deleted = repo.status()[:4]
877 repo.lfstatus = False
877 repo.lfstatus = False
878 if modified or added or removed or deleted:
878 if modified or added or removed or deleted:
879 raise util.Abort(_('outstanding uncommitted changes'))
879 raise util.Abort(_('outstanding uncommitted changes'))
880
880
881 # Fetch doesn't use cmdutil.bailifchanged so override it to add the check
881 # Fetch doesn't use cmdutil.bailifchanged so override it to add the check
882 def overridefetch(orig, ui, repo, *pats, **opts):
882 def overridefetch(orig, ui, repo, *pats, **opts):
883 repo.lfstatus = True
883 repo.lfstatus = True
884 modified, added, removed, deleted = repo.status()[:4]
884 modified, added, removed, deleted = repo.status()[:4]
885 repo.lfstatus = False
885 repo.lfstatus = False
886 if modified or added or removed or deleted:
886 if modified or added or removed or deleted:
887 raise util.Abort(_('outstanding uncommitted changes'))
887 raise util.Abort(_('outstanding uncommitted changes'))
888 return orig(ui, repo, *pats, **opts)
888 return orig(ui, repo, *pats, **opts)
889
889
890 def overrideforget(orig, ui, repo, *pats, **opts):
890 def overrideforget(orig, ui, repo, *pats, **opts):
891 installnormalfilesmatchfn(repo[None].manifest())
891 installnormalfilesmatchfn(repo[None].manifest())
892 orig(ui, repo, *pats, **opts)
892 orig(ui, repo, *pats, **opts)
893 restorematchfn()
893 restorematchfn()
894 m = scmutil.match(repo[None], pats, opts)
894 m = scmutil.match(repo[None], pats, opts)
895
895
896 try:
896 try:
897 repo.lfstatus = True
897 repo.lfstatus = True
898 s = repo.status(match=m, clean=True)
898 s = repo.status(match=m, clean=True)
899 finally:
899 finally:
900 repo.lfstatus = False
900 repo.lfstatus = False
901 forget = sorted(s[0] + s[1] + s[3] + s[6])
901 forget = sorted(s[0] + s[1] + s[3] + s[6])
902 forget = [f for f in forget if lfutil.standin(f) in repo[None].manifest()]
902 forget = [f for f in forget if lfutil.standin(f) in repo[None].manifest()]
903
903
904 for f in forget:
904 for f in forget:
905 if lfutil.standin(f) not in repo.dirstate and not \
905 if lfutil.standin(f) not in repo.dirstate and not \
906 os.path.isdir(m.rel(lfutil.standin(f))):
906 os.path.isdir(m.rel(lfutil.standin(f))):
907 ui.warn(_('not removing %s: file is already untracked\n')
907 ui.warn(_('not removing %s: file is already untracked\n')
908 % m.rel(f))
908 % m.rel(f))
909
909
910 for f in forget:
910 for f in forget:
911 if ui.verbose or not m.exact(f):
911 if ui.verbose or not m.exact(f):
912 ui.status(_('removing %s\n') % m.rel(f))
912 ui.status(_('removing %s\n') % m.rel(f))
913
913
914 # Need to lock because standin files are deleted then removed from the
914 # Need to lock because standin files are deleted then removed from the
915 # repository and we could race inbetween.
915 # repository and we could race inbetween.
916 wlock = repo.wlock()
916 wlock = repo.wlock()
917 try:
917 try:
918 lfdirstate = lfutil.openlfdirstate(ui, repo)
918 lfdirstate = lfutil.openlfdirstate(ui, repo)
919 for f in forget:
919 for f in forget:
920 if lfdirstate[f] == 'a':
920 if lfdirstate[f] == 'a':
921 lfdirstate.drop(f)
921 lfdirstate.drop(f)
922 else:
922 else:
923 lfdirstate.remove(f)
923 lfdirstate.remove(f)
924 lfdirstate.write()
924 lfdirstate.write()
925 lfutil.reporemove(repo, [lfutil.standin(f) for f in forget],
925 lfutil.reporemove(repo, [lfutil.standin(f) for f in forget],
926 unlink=True)
926 unlink=True)
927 finally:
927 finally:
928 wlock.release()
928 wlock.release()
929
929
930 def getoutgoinglfiles(ui, repo, dest=None, **opts):
930 def getoutgoinglfiles(ui, repo, dest=None, **opts):
931 dest = ui.expandpath(dest or 'default-push', dest or 'default')
931 dest = ui.expandpath(dest or 'default-push', dest or 'default')
932 dest, branches = hg.parseurl(dest, opts.get('branch'))
932 dest, branches = hg.parseurl(dest, opts.get('branch'))
933 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
933 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
934 if revs:
934 if revs:
935 revs = [repo.lookup(rev) for rev in revs]
935 revs = [repo.lookup(rev) for rev in scmutil.revrange(repo, revs)]
936
936
937 remoteui = hg.remoteui
937 remoteui = hg.remoteui
938
938
939 try:
939 try:
940 remote = hg.repository(remoteui(repo, opts), dest)
940 remote = hg.repository(remoteui(repo, opts), dest)
941 except error.RepoError:
941 except error.RepoError:
942 return None
942 return None
943 o = lfutil.findoutgoing(repo, remote, False)
943 o = lfutil.findoutgoing(repo, remote, False)
944 if not o:
944 if not o:
945 return None
945 return None
946 o = repo.changelog.nodesbetween(o, revs)[0]
946 o = repo.changelog.nodesbetween(o, revs)[0]
947 if opts.get('newest_first'):
947 if opts.get('newest_first'):
948 o.reverse()
948 o.reverse()
949
949
950 toupload = set()
950 toupload = set()
951 for n in o:
951 for n in o:
952 parents = [p for p in repo.changelog.parents(n) if p != node.nullid]
952 parents = [p for p in repo.changelog.parents(n) if p != node.nullid]
953 ctx = repo[n]
953 ctx = repo[n]
954 files = set(ctx.files())
954 files = set(ctx.files())
955 if len(parents) == 2:
955 if len(parents) == 2:
956 mc = ctx.manifest()
956 mc = ctx.manifest()
957 mp1 = ctx.parents()[0].manifest()
957 mp1 = ctx.parents()[0].manifest()
958 mp2 = ctx.parents()[1].manifest()
958 mp2 = ctx.parents()[1].manifest()
959 for f in mp1:
959 for f in mp1:
960 if f not in mc:
960 if f not in mc:
961 files.add(f)
961 files.add(f)
962 for f in mp2:
962 for f in mp2:
963 if f not in mc:
963 if f not in mc:
964 files.add(f)
964 files.add(f)
965 for f in mc:
965 for f in mc:
966 if mc[f] != mp1.get(f, None) or mc[f] != mp2.get(f, None):
966 if mc[f] != mp1.get(f, None) or mc[f] != mp2.get(f, None):
967 files.add(f)
967 files.add(f)
968 toupload = toupload.union(
968 toupload = toupload.union(
969 set([f for f in files if lfutil.isstandin(f) and f in ctx]))
969 set([f for f in files if lfutil.isstandin(f) and f in ctx]))
970 return toupload
970 return toupload
971
971
972 def overrideoutgoing(orig, ui, repo, dest=None, **opts):
972 def overrideoutgoing(orig, ui, repo, dest=None, **opts):
973 orig(ui, repo, dest, **opts)
973 orig(ui, repo, dest, **opts)
974
974
975 if opts.pop('large', None):
975 if opts.pop('large', None):
976 toupload = getoutgoinglfiles(ui, repo, dest, **opts)
976 toupload = getoutgoinglfiles(ui, repo, dest, **opts)
977 if toupload is None:
977 if toupload is None:
978 ui.status(_('largefiles: No remote repo\n'))
978 ui.status(_('largefiles: No remote repo\n'))
979 else:
979 else:
980 ui.status(_('largefiles to upload:\n'))
980 ui.status(_('largefiles to upload:\n'))
981 for file in toupload:
981 for file in toupload:
982 ui.status(lfutil.splitstandin(file) + '\n')
982 ui.status(lfutil.splitstandin(file) + '\n')
983 ui.status('\n')
983 ui.status('\n')
984
984
985 def overridesummary(orig, ui, repo, *pats, **opts):
985 def overridesummary(orig, ui, repo, *pats, **opts):
986 try:
986 try:
987 repo.lfstatus = True
987 repo.lfstatus = True
988 orig(ui, repo, *pats, **opts)
988 orig(ui, repo, *pats, **opts)
989 finally:
989 finally:
990 repo.lfstatus = False
990 repo.lfstatus = False
991
991
992 if opts.pop('large', None):
992 if opts.pop('large', None):
993 toupload = getoutgoinglfiles(ui, repo, None, **opts)
993 toupload = getoutgoinglfiles(ui, repo, None, **opts)
994 if toupload is None:
994 if toupload is None:
995 ui.status(_('largefiles: No remote repo\n'))
995 ui.status(_('largefiles: No remote repo\n'))
996 else:
996 else:
997 ui.status(_('largefiles: %d to upload\n') % len(toupload))
997 ui.status(_('largefiles: %d to upload\n') % len(toupload))
998
998
999 def overrideaddremove(orig, ui, repo, *pats, **opts):
999 def overrideaddremove(orig, ui, repo, *pats, **opts):
1000 if not lfutil.islfilesrepo(repo):
1000 if not lfutil.islfilesrepo(repo):
1001 return orig(ui, repo, *pats, **opts)
1001 return orig(ui, repo, *pats, **opts)
1002 # Get the list of missing largefiles so we can remove them
1002 # Get the list of missing largefiles so we can remove them
1003 lfdirstate = lfutil.openlfdirstate(ui, repo)
1003 lfdirstate = lfutil.openlfdirstate(ui, repo)
1004 s = lfdirstate.status(match_.always(repo.root, repo.getcwd()), [], False,
1004 s = lfdirstate.status(match_.always(repo.root, repo.getcwd()), [], False,
1005 False, False)
1005 False, False)
1006 (unsure, modified, added, removed, missing, unknown, ignored, clean) = s
1006 (unsure, modified, added, removed, missing, unknown, ignored, clean) = s
1007
1007
1008 # Call into the normal remove code, but the removing of the standin, we want
1008 # Call into the normal remove code, but the removing of the standin, we want
1009 # to have handled by original addremove. Monkey patching here makes sure
1009 # to have handled by original addremove. Monkey patching here makes sure
1010 # we don't remove the standin in the largefiles code, preventing a very
1010 # we don't remove the standin in the largefiles code, preventing a very
1011 # confused state later.
1011 # confused state later.
1012 if missing:
1012 if missing:
1013 m = [repo.wjoin(f) for f in missing]
1013 m = [repo.wjoin(f) for f in missing]
1014 repo._isaddremove = True
1014 repo._isaddremove = True
1015 removelargefiles(ui, repo, *m, **opts)
1015 removelargefiles(ui, repo, *m, **opts)
1016 repo._isaddremove = False
1016 repo._isaddremove = False
1017 # Call into the normal add code, and any files that *should* be added as
1017 # Call into the normal add code, and any files that *should* be added as
1018 # largefiles will be
1018 # largefiles will be
1019 addlargefiles(ui, repo, *pats, **opts)
1019 addlargefiles(ui, repo, *pats, **opts)
1020 # Now that we've handled largefiles, hand off to the original addremove
1020 # Now that we've handled largefiles, hand off to the original addremove
1021 # function to take care of the rest. Make sure it doesn't do anything with
1021 # function to take care of the rest. Make sure it doesn't do anything with
1022 # largefiles by installing a matcher that will ignore them.
1022 # largefiles by installing a matcher that will ignore them.
1023 installnormalfilesmatchfn(repo[None].manifest())
1023 installnormalfilesmatchfn(repo[None].manifest())
1024 result = orig(ui, repo, *pats, **opts)
1024 result = orig(ui, repo, *pats, **opts)
1025 restorematchfn()
1025 restorematchfn()
1026 return result
1026 return result
1027
1027
1028 # Calling purge with --all will cause the largefiles to be deleted.
1028 # Calling purge with --all will cause the largefiles to be deleted.
1029 # Override repo.status to prevent this from happening.
1029 # Override repo.status to prevent this from happening.
1030 def overridepurge(orig, ui, repo, *dirs, **opts):
1030 def overridepurge(orig, ui, repo, *dirs, **opts):
1031 oldstatus = repo.status
1031 oldstatus = repo.status
1032 def overridestatus(node1='.', node2=None, match=None, ignored=False,
1032 def overridestatus(node1='.', node2=None, match=None, ignored=False,
1033 clean=False, unknown=False, listsubrepos=False):
1033 clean=False, unknown=False, listsubrepos=False):
1034 r = oldstatus(node1, node2, match, ignored, clean, unknown,
1034 r = oldstatus(node1, node2, match, ignored, clean, unknown,
1035 listsubrepos)
1035 listsubrepos)
1036 lfdirstate = lfutil.openlfdirstate(ui, repo)
1036 lfdirstate = lfutil.openlfdirstate(ui, repo)
1037 modified, added, removed, deleted, unknown, ignored, clean = r
1037 modified, added, removed, deleted, unknown, ignored, clean = r
1038 unknown = [f for f in unknown if lfdirstate[f] == '?']
1038 unknown = [f for f in unknown if lfdirstate[f] == '?']
1039 ignored = [f for f in ignored if lfdirstate[f] == '?']
1039 ignored = [f for f in ignored if lfdirstate[f] == '?']
1040 return modified, added, removed, deleted, unknown, ignored, clean
1040 return modified, added, removed, deleted, unknown, ignored, clean
1041 repo.status = overridestatus
1041 repo.status = overridestatus
1042 orig(ui, repo, *dirs, **opts)
1042 orig(ui, repo, *dirs, **opts)
1043 repo.status = oldstatus
1043 repo.status = oldstatus
1044
1044
1045 def overriderollback(orig, ui, repo, **opts):
1045 def overriderollback(orig, ui, repo, **opts):
1046 result = orig(ui, repo, **opts)
1046 result = orig(ui, repo, **opts)
1047 merge.update(repo, node=None, branchmerge=False, force=True,
1047 merge.update(repo, node=None, branchmerge=False, force=True,
1048 partial=lfutil.isstandin)
1048 partial=lfutil.isstandin)
1049 wlock = repo.wlock()
1049 wlock = repo.wlock()
1050 try:
1050 try:
1051 lfdirstate = lfutil.openlfdirstate(ui, repo)
1051 lfdirstate = lfutil.openlfdirstate(ui, repo)
1052 lfiles = lfutil.listlfiles(repo)
1052 lfiles = lfutil.listlfiles(repo)
1053 oldlfiles = lfutil.listlfiles(repo, repo[None].parents()[0].rev())
1053 oldlfiles = lfutil.listlfiles(repo, repo[None].parents()[0].rev())
1054 for file in lfiles:
1054 for file in lfiles:
1055 if file in oldlfiles:
1055 if file in oldlfiles:
1056 lfdirstate.normallookup(file)
1056 lfdirstate.normallookup(file)
1057 else:
1057 else:
1058 lfdirstate.add(file)
1058 lfdirstate.add(file)
1059 lfdirstate.write()
1059 lfdirstate.write()
1060 finally:
1060 finally:
1061 wlock.release()
1061 wlock.release()
1062 return result
1062 return result
1063
1063
1064 def overridetransplant(orig, ui, repo, *revs, **opts):
1064 def overridetransplant(orig, ui, repo, *revs, **opts):
1065 try:
1065 try:
1066 oldstandins = lfutil.getstandinsstate(repo)
1066 oldstandins = lfutil.getstandinsstate(repo)
1067 repo._istransplanting = True
1067 repo._istransplanting = True
1068 result = orig(ui, repo, *revs, **opts)
1068 result = orig(ui, repo, *revs, **opts)
1069 newstandins = lfutil.getstandinsstate(repo)
1069 newstandins = lfutil.getstandinsstate(repo)
1070 filelist = lfutil.getlfilestoupdate(oldstandins, newstandins)
1070 filelist = lfutil.getlfilestoupdate(oldstandins, newstandins)
1071 lfcommands.updatelfiles(repo.ui, repo, filelist=filelist,
1071 lfcommands.updatelfiles(repo.ui, repo, filelist=filelist,
1072 printmessage=True)
1072 printmessage=True)
1073 finally:
1073 finally:
1074 repo._istransplanting = False
1074 repo._istransplanting = False
1075 return result
1075 return result
1076
1076
1077 def overridecat(orig, ui, repo, file1, *pats, **opts):
1077 def overridecat(orig, ui, repo, file1, *pats, **opts):
1078 ctx = scmutil.revsingle(repo, opts.get('rev'))
1078 ctx = scmutil.revsingle(repo, opts.get('rev'))
1079 if not lfutil.standin(file1) in ctx:
1079 if not lfutil.standin(file1) in ctx:
1080 result = orig(ui, repo, file1, *pats, **opts)
1080 result = orig(ui, repo, file1, *pats, **opts)
1081 return result
1081 return result
1082 return lfcommands.catlfile(repo, file1, ctx.rev(), opts.get('output'))
1082 return lfcommands.catlfile(repo, file1, ctx.rev(), opts.get('output'))
@@ -1,1447 +1,1447 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, testing that status correctly shows largefiles and that summary output
20 files, testing that status correctly shows largefiles and that summary output
21 is correct.
21 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 $ echo normal11 > normal1
38 $ echo normal11 > normal1
39 $ echo normal22 > sub/normal2
39 $ echo normal22 > sub/normal2
40 $ echo large11 > large1
40 $ echo large11 > large1
41 $ echo large22 > sub/large2
41 $ echo large22 > sub/large2
42 $ hg commit -m "edit files"
42 $ hg commit -m "edit files"
43 Invoking status precommit hook
43 Invoking status precommit hook
44 M large1
44 M large1
45 M normal1
45 M normal1
46 M sub/large2
46 M sub/large2
47 M sub/normal2
47 M sub/normal2
48 $ hg sum --large
48 $ hg sum --large
49 parent: 1:ce8896473775 tip
49 parent: 1:ce8896473775 tip
50 edit files
50 edit files
51 branch: default
51 branch: default
52 commit: (clean)
52 commit: (clean)
53 update: (current)
53 update: (current)
54 largefiles: No remote repo
54 largefiles: No remote repo
55
55
56 Commit preserved largefile contents.
56 Commit preserved largefile contents.
57
57
58 $ cat normal1
58 $ cat normal1
59 normal11
59 normal11
60 $ cat large1
60 $ cat large1
61 large11
61 large11
62 $ cat sub/normal2
62 $ cat sub/normal2
63 normal22
63 normal22
64 $ cat sub/large2
64 $ cat sub/large2
65 large22
65 large22
66
66
67 Test status, subdir and unknown files
67 Test status, subdir and unknown files
68
68
69 $ echo unknown > sub/unknown
69 $ echo unknown > sub/unknown
70 $ hg st --all
70 $ hg st --all
71 ? sub/unknown
71 ? sub/unknown
72 C large1
72 C large1
73 C normal1
73 C normal1
74 C sub/large2
74 C sub/large2
75 C sub/normal2
75 C sub/normal2
76 $ hg st --all sub
76 $ hg st --all sub
77 ? sub/unknown
77 ? sub/unknown
78 C sub/large2
78 C sub/large2
79 C sub/normal2
79 C sub/normal2
80 $ rm sub/unknown
80 $ rm sub/unknown
81
81
82 Remove both largefiles and normal files.
82 Remove both largefiles and normal files.
83
83
84 $ hg remove normal1 large1
84 $ hg remove normal1 large1
85 $ hg status large1
85 $ hg status large1
86 R large1
86 R large1
87 $ hg commit -m "remove files"
87 $ hg commit -m "remove files"
88 Invoking status precommit hook
88 Invoking status precommit hook
89 R large1
89 R large1
90 R normal1
90 R normal1
91 $ ls
91 $ ls
92 sub
92 sub
93 $ echo "testlargefile" > large1-test
93 $ echo "testlargefile" > large1-test
94 $ hg add --large large1-test
94 $ hg add --large large1-test
95 $ hg st
95 $ hg st
96 A large1-test
96 A large1-test
97 $ hg rm large1-test
97 $ hg rm large1-test
98 not removing large1-test: file has been marked for add (use forget to undo)
98 not removing large1-test: file has been marked for add (use forget to undo)
99 $ hg st
99 $ hg st
100 A large1-test
100 A large1-test
101 $ hg forget large1-test
101 $ hg forget large1-test
102 $ hg st
102 $ hg st
103 ? large1-test
103 ? large1-test
104 $ rm large1-test
104 $ rm large1-test
105
105
106 Copy both largefiles and normal files (testing that status output is correct).
106 Copy both largefiles and normal files (testing that status output is correct).
107
107
108 $ hg cp sub/normal2 normal1
108 $ hg cp sub/normal2 normal1
109 $ hg cp sub/large2 large1
109 $ hg cp sub/large2 large1
110 $ hg commit -m "copy files"
110 $ hg commit -m "copy files"
111 Invoking status precommit hook
111 Invoking status precommit hook
112 A large1
112 A large1
113 A normal1
113 A normal1
114 $ cat normal1
114 $ cat normal1
115 normal22
115 normal22
116 $ cat large1
116 $ cat large1
117 large22
117 large22
118
118
119 Test moving largefiles and verify that normal files are also unaffected.
119 Test moving largefiles and verify that normal files are also unaffected.
120
120
121 $ hg mv normal1 normal3
121 $ hg mv normal1 normal3
122 $ hg mv large1 large3
122 $ hg mv large1 large3
123 $ hg mv sub/normal2 sub/normal4
123 $ hg mv sub/normal2 sub/normal4
124 $ hg mv sub/large2 sub/large4
124 $ hg mv sub/large2 sub/large4
125 $ hg commit -m "move files"
125 $ hg commit -m "move files"
126 Invoking status precommit hook
126 Invoking status precommit hook
127 A large3
127 A large3
128 A normal3
128 A normal3
129 A sub/large4
129 A sub/large4
130 A sub/normal4
130 A sub/normal4
131 R large1
131 R large1
132 R normal1
132 R normal1
133 R sub/large2
133 R sub/large2
134 R sub/normal2
134 R sub/normal2
135 $ cat normal3
135 $ cat normal3
136 normal22
136 normal22
137 $ cat large3
137 $ cat large3
138 large22
138 large22
139 $ cat sub/normal4
139 $ cat sub/normal4
140 normal22
140 normal22
141 $ cat sub/large4
141 $ cat sub/large4
142 large22
142 large22
143
143
144 Test copies and moves from a directory other than root (issue3516)
144 Test copies and moves from a directory other than root (issue3516)
145
145
146 $ cd ..
146 $ cd ..
147 $ hg init lf_cpmv
147 $ hg init lf_cpmv
148 $ cd lf_cpmv
148 $ cd lf_cpmv
149 $ mkdir dira
149 $ mkdir dira
150 $ mkdir dira/dirb
150 $ mkdir dira/dirb
151 $ touch dira/dirb/largefile
151 $ touch dira/dirb/largefile
152 $ hg add --large dira/dirb/largefile
152 $ hg add --large dira/dirb/largefile
153 $ hg commit -m "added"
153 $ hg commit -m "added"
154 Invoking status precommit hook
154 Invoking status precommit hook
155 A dira/dirb/largefile
155 A dira/dirb/largefile
156 $ cd dira
156 $ cd dira
157 $ hg cp dirb/largefile foo/largefile
157 $ hg cp dirb/largefile foo/largefile
158 $ hg ci -m "deep copy"
158 $ hg ci -m "deep copy"
159 Invoking status precommit hook
159 Invoking status precommit hook
160 A dira/foo/largefile
160 A dira/foo/largefile
161 $ find . | sort
161 $ find . | sort
162 .
162 .
163 ./dirb
163 ./dirb
164 ./dirb/largefile
164 ./dirb/largefile
165 ./foo
165 ./foo
166 ./foo/largefile
166 ./foo/largefile
167 $ hg mv foo/largefile baz/largefile
167 $ hg mv foo/largefile baz/largefile
168 $ hg ci -m "moved"
168 $ hg ci -m "moved"
169 Invoking status precommit hook
169 Invoking status precommit hook
170 A dira/baz/largefile
170 A dira/baz/largefile
171 R dira/foo/largefile
171 R dira/foo/largefile
172 $ find . | sort
172 $ find . | sort
173 .
173 .
174 ./baz
174 ./baz
175 ./baz/largefile
175 ./baz/largefile
176 ./dirb
176 ./dirb
177 ./dirb/largefile
177 ./dirb/largefile
178 ./foo
178 ./foo
179 $ cd ../../a
179 $ cd ../../a
180
180
181 #if hgweb
181 #if hgweb
182 Test display of largefiles in hgweb
182 Test display of largefiles in hgweb
183
183
184 $ hg serve -d -p $HGPORT --pid-file ../hg.pid
184 $ hg serve -d -p $HGPORT --pid-file ../hg.pid
185 $ cat ../hg.pid >> $DAEMON_PIDS
185 $ cat ../hg.pid >> $DAEMON_PIDS
186 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT 'file/tip/?style=raw'
186 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT 'file/tip/?style=raw'
187 200 Script output follows
187 200 Script output follows
188
188
189
189
190 drwxr-xr-x sub
190 drwxr-xr-x sub
191 -rw-r--r-- 41 large3
191 -rw-r--r-- 41 large3
192 -rw-r--r-- 9 normal3
192 -rw-r--r-- 9 normal3
193
193
194
194
195 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT 'file/tip/sub/?style=raw'
195 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT 'file/tip/sub/?style=raw'
196 200 Script output follows
196 200 Script output follows
197
197
198
198
199 -rw-r--r-- 41 large4
199 -rw-r--r-- 41 large4
200 -rw-r--r-- 9 normal4
200 -rw-r--r-- 9 normal4
201
201
202
202
203 $ "$TESTDIR/killdaemons.py"
203 $ "$TESTDIR/killdaemons.py"
204 #endif
204 #endif
205
205
206 Test archiving the various revisions. These hit corner cases known with
206 Test archiving the various revisions. These hit corner cases known with
207 archiving.
207 archiving.
208
208
209 $ hg archive -r 0 ../archive0
209 $ hg archive -r 0 ../archive0
210 $ hg archive -r 1 ../archive1
210 $ hg archive -r 1 ../archive1
211 $ hg archive -r 2 ../archive2
211 $ hg archive -r 2 ../archive2
212 $ hg archive -r 3 ../archive3
212 $ hg archive -r 3 ../archive3
213 $ hg archive -r 4 ../archive4
213 $ hg archive -r 4 ../archive4
214 $ cd ../archive0
214 $ cd ../archive0
215 $ cat normal1
215 $ cat normal1
216 normal1
216 normal1
217 $ cat large1
217 $ cat large1
218 large1
218 large1
219 $ cat sub/normal2
219 $ cat sub/normal2
220 normal2
220 normal2
221 $ cat sub/large2
221 $ cat sub/large2
222 large2
222 large2
223 $ cd ../archive1
223 $ cd ../archive1
224 $ cat normal1
224 $ cat normal1
225 normal11
225 normal11
226 $ cat large1
226 $ cat large1
227 large11
227 large11
228 $ cat sub/normal2
228 $ cat sub/normal2
229 normal22
229 normal22
230 $ cat sub/large2
230 $ cat sub/large2
231 large22
231 large22
232 $ cd ../archive2
232 $ cd ../archive2
233 $ ls
233 $ ls
234 sub
234 sub
235 $ cat sub/normal2
235 $ cat sub/normal2
236 normal22
236 normal22
237 $ cat sub/large2
237 $ cat sub/large2
238 large22
238 large22
239 $ cd ../archive3
239 $ cd ../archive3
240 $ cat normal1
240 $ cat normal1
241 normal22
241 normal22
242 $ cat large1
242 $ cat large1
243 large22
243 large22
244 $ cat sub/normal2
244 $ cat sub/normal2
245 normal22
245 normal22
246 $ cat sub/large2
246 $ cat sub/large2
247 large22
247 large22
248 $ cd ../archive4
248 $ cd ../archive4
249 $ cat normal3
249 $ cat normal3
250 normal22
250 normal22
251 $ cat large3
251 $ cat large3
252 large22
252 large22
253 $ cat sub/normal4
253 $ cat sub/normal4
254 normal22
254 normal22
255 $ cat sub/large4
255 $ cat sub/large4
256 large22
256 large22
257
257
258 Commit corner case: specify files to commit.
258 Commit corner case: specify files to commit.
259
259
260 $ cd ../a
260 $ cd ../a
261 $ echo normal3 > normal3
261 $ echo normal3 > normal3
262 $ echo large3 > large3
262 $ echo large3 > large3
263 $ echo normal4 > sub/normal4
263 $ echo normal4 > sub/normal4
264 $ echo large4 > sub/large4
264 $ echo large4 > sub/large4
265 $ hg commit normal3 large3 sub/normal4 sub/large4 -m "edit files again"
265 $ hg commit normal3 large3 sub/normal4 sub/large4 -m "edit files again"
266 Invoking status precommit hook
266 Invoking status precommit hook
267 M large3
267 M large3
268 M normal3
268 M normal3
269 M sub/large4
269 M sub/large4
270 M sub/normal4
270 M sub/normal4
271 $ cat normal3
271 $ cat normal3
272 normal3
272 normal3
273 $ cat large3
273 $ cat large3
274 large3
274 large3
275 $ cat sub/normal4
275 $ cat sub/normal4
276 normal4
276 normal4
277 $ cat sub/large4
277 $ cat sub/large4
278 large4
278 large4
279
279
280 One more commit corner case: commit from a subdirectory.
280 One more commit corner case: commit from a subdirectory.
281
281
282 $ cd ../a
282 $ cd ../a
283 $ echo normal33 > normal3
283 $ echo normal33 > normal3
284 $ echo large33 > large3
284 $ echo large33 > large3
285 $ echo normal44 > sub/normal4
285 $ echo normal44 > sub/normal4
286 $ echo large44 > sub/large4
286 $ echo large44 > sub/large4
287 $ cd sub
287 $ cd sub
288 $ hg commit -m "edit files yet again"
288 $ hg commit -m "edit files yet again"
289 Invoking status precommit hook
289 Invoking status precommit hook
290 M large3
290 M large3
291 M normal3
291 M normal3
292 M sub/large4
292 M sub/large4
293 M sub/normal4
293 M sub/normal4
294 $ cat ../normal3
294 $ cat ../normal3
295 normal33
295 normal33
296 $ cat ../large3
296 $ cat ../large3
297 large33
297 large33
298 $ cat normal4
298 $ cat normal4
299 normal44
299 normal44
300 $ cat large4
300 $ cat large4
301 large44
301 large44
302
302
303 Committing standins is not allowed.
303 Committing standins is not allowed.
304
304
305 $ cd ..
305 $ cd ..
306 $ echo large3 > large3
306 $ echo large3 > large3
307 $ hg commit .hglf/large3 -m "try to commit standin"
307 $ hg commit .hglf/large3 -m "try to commit standin"
308 abort: file ".hglf/large3" is a largefile standin
308 abort: file ".hglf/large3" is a largefile standin
309 (commit the largefile itself instead)
309 (commit the largefile itself instead)
310 [255]
310 [255]
311
311
312 Corner cases for adding largefiles.
312 Corner cases for adding largefiles.
313
313
314 $ echo large5 > large5
314 $ echo large5 > large5
315 $ hg add --large large5
315 $ hg add --large large5
316 $ hg add --large large5
316 $ hg add --large large5
317 large5 already a largefile
317 large5 already a largefile
318 $ mkdir sub2
318 $ mkdir sub2
319 $ echo large6 > sub2/large6
319 $ echo large6 > sub2/large6
320 $ echo large7 > sub2/large7
320 $ echo large7 > sub2/large7
321 $ hg add --large sub2
321 $ hg add --large sub2
322 adding sub2/large6 as a largefile (glob)
322 adding sub2/large6 as a largefile (glob)
323 adding sub2/large7 as a largefile (glob)
323 adding sub2/large7 as a largefile (glob)
324 $ hg st
324 $ hg st
325 M large3
325 M large3
326 A large5
326 A large5
327 A sub2/large6
327 A sub2/large6
328 A sub2/large7
328 A sub2/large7
329
329
330 Test "hg status" with combination of 'file pattern' and 'directory
330 Test "hg status" with combination of 'file pattern' and 'directory
331 pattern' for largefiles:
331 pattern' for largefiles:
332
332
333 $ hg status sub2/large6 sub2
333 $ hg status sub2/large6 sub2
334 A sub2/large6
334 A sub2/large6
335 A sub2/large7
335 A sub2/large7
336
336
337 Config settings (pattern **.dat, minsize 2 MB) are respected.
337 Config settings (pattern **.dat, minsize 2 MB) are respected.
338
338
339 $ echo testdata > test.dat
339 $ echo testdata > test.dat
340 $ dd bs=1k count=2k if=/dev/zero of=reallylarge > /dev/null 2> /dev/null
340 $ dd bs=1k count=2k if=/dev/zero of=reallylarge > /dev/null 2> /dev/null
341 $ hg add
341 $ hg add
342 adding reallylarge as a largefile
342 adding reallylarge as a largefile
343 adding test.dat as a largefile
343 adding test.dat as a largefile
344
344
345 Test that minsize and --lfsize handle float values;
345 Test that minsize and --lfsize handle float values;
346 also tests that --lfsize overrides largefiles.minsize.
346 also tests that --lfsize overrides largefiles.minsize.
347 (0.250 MB = 256 kB = 262144 B)
347 (0.250 MB = 256 kB = 262144 B)
348
348
349 $ dd if=/dev/zero of=ratherlarge bs=1024 count=256 > /dev/null 2> /dev/null
349 $ dd if=/dev/zero of=ratherlarge bs=1024 count=256 > /dev/null 2> /dev/null
350 $ dd if=/dev/zero of=medium bs=1024 count=128 > /dev/null 2> /dev/null
350 $ dd if=/dev/zero of=medium bs=1024 count=128 > /dev/null 2> /dev/null
351 $ hg --config largefiles.minsize=.25 add
351 $ hg --config largefiles.minsize=.25 add
352 adding ratherlarge as a largefile
352 adding ratherlarge as a largefile
353 adding medium
353 adding medium
354 $ hg forget medium
354 $ hg forget medium
355 $ hg --config largefiles.minsize=.25 add --lfsize=.125
355 $ hg --config largefiles.minsize=.25 add --lfsize=.125
356 adding medium as a largefile
356 adding medium as a largefile
357 $ dd if=/dev/zero of=notlarge bs=1024 count=127 > /dev/null 2> /dev/null
357 $ dd if=/dev/zero of=notlarge bs=1024 count=127 > /dev/null 2> /dev/null
358 $ hg --config largefiles.minsize=.25 add --lfsize=.125
358 $ hg --config largefiles.minsize=.25 add --lfsize=.125
359 adding notlarge
359 adding notlarge
360 $ hg forget notlarge
360 $ hg forget notlarge
361
361
362 Test forget on largefiles.
362 Test forget on largefiles.
363
363
364 $ hg forget large3 large5 test.dat reallylarge ratherlarge medium
364 $ hg forget large3 large5 test.dat reallylarge ratherlarge medium
365 $ hg commit -m "add/edit more largefiles"
365 $ hg commit -m "add/edit more largefiles"
366 Invoking status precommit hook
366 Invoking status precommit hook
367 A sub2/large6
367 A sub2/large6
368 A sub2/large7
368 A sub2/large7
369 R large3
369 R large3
370 ? large5
370 ? large5
371 ? medium
371 ? medium
372 ? notlarge
372 ? notlarge
373 ? ratherlarge
373 ? ratherlarge
374 ? reallylarge
374 ? reallylarge
375 ? test.dat
375 ? test.dat
376 $ hg st
376 $ hg st
377 ? large3
377 ? large3
378 ? large5
378 ? large5
379 ? medium
379 ? medium
380 ? notlarge
380 ? notlarge
381 ? ratherlarge
381 ? ratherlarge
382 ? reallylarge
382 ? reallylarge
383 ? test.dat
383 ? test.dat
384
384
385 Purge with largefiles: verify that largefiles are still in the working
385 Purge with largefiles: verify that largefiles are still in the working
386 dir after a purge.
386 dir after a purge.
387
387
388 $ hg purge --all
388 $ hg purge --all
389 $ cat sub/large4
389 $ cat sub/large4
390 large44
390 large44
391 $ cat sub2/large6
391 $ cat sub2/large6
392 large6
392 large6
393 $ cat sub2/large7
393 $ cat sub2/large7
394 large7
394 large7
395
395
396 Test addremove: verify that files that should be added as largfiles are added as
396 Test addremove: verify that files that should be added as largfiles are added as
397 such and that already-existing largfiles are not added as normal files by
397 such and that already-existing largfiles are not added as normal files by
398 accident.
398 accident.
399
399
400 $ rm normal3
400 $ rm normal3
401 $ rm sub/large4
401 $ rm sub/large4
402 $ echo "testing addremove with patterns" > testaddremove.dat
402 $ echo "testing addremove with patterns" > testaddremove.dat
403 $ echo "normaladdremove" > normaladdremove
403 $ echo "normaladdremove" > normaladdremove
404 $ hg addremove
404 $ hg addremove
405 removing sub/large4
405 removing sub/large4
406 adding testaddremove.dat as a largefile
406 adding testaddremove.dat as a largefile
407 removing normal3
407 removing normal3
408 adding normaladdremove
408 adding normaladdremove
409
409
410 Test addremove with -R
410 Test addremove with -R
411
411
412 $ hg up -C
412 $ hg up -C
413 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
413 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
414 getting changed largefiles
414 getting changed largefiles
415 1 largefiles updated, 0 removed
415 1 largefiles updated, 0 removed
416 $ rm normal3
416 $ rm normal3
417 $ rm sub/large4
417 $ rm sub/large4
418 $ echo "testing addremove with patterns" > testaddremove.dat
418 $ echo "testing addremove with patterns" > testaddremove.dat
419 $ echo "normaladdremove" > normaladdremove
419 $ echo "normaladdremove" > normaladdremove
420 $ cd ..
420 $ cd ..
421 $ hg -R a addremove
421 $ hg -R a addremove
422 removing sub/large4
422 removing sub/large4
423 adding a/testaddremove.dat as a largefile (glob)
423 adding a/testaddremove.dat as a largefile (glob)
424 removing normal3
424 removing normal3
425 adding normaladdremove
425 adding normaladdremove
426 $ cd a
426 $ cd a
427
427
428 Test 3364
428 Test 3364
429 $ hg clone . ../addrm
429 $ hg clone . ../addrm
430 updating to branch default
430 updating to branch default
431 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
431 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
432 getting changed largefiles
432 getting changed largefiles
433 3 largefiles updated, 0 removed
433 3 largefiles updated, 0 removed
434 $ cd ../addrm
434 $ cd ../addrm
435 $ cat >> .hg/hgrc <<EOF
435 $ cat >> .hg/hgrc <<EOF
436 > [hooks]
436 > [hooks]
437 > post-commit.stat=sh -c "echo \"Invoking status postcommit hook\"; hg status -A"
437 > post-commit.stat=sh -c "echo \"Invoking status postcommit hook\"; hg status -A"
438 > EOF
438 > EOF
439 $ touch foo
439 $ touch foo
440 $ hg add --large foo
440 $ hg add --large foo
441 $ hg ci -m "add foo"
441 $ hg ci -m "add foo"
442 Invoking status precommit hook
442 Invoking status precommit hook
443 A foo
443 A foo
444 Invoking status postcommit hook
444 Invoking status postcommit hook
445 C foo
445 C foo
446 C normal3
446 C normal3
447 C sub/large4
447 C sub/large4
448 C sub/normal4
448 C sub/normal4
449 C sub2/large6
449 C sub2/large6
450 C sub2/large7
450 C sub2/large7
451 $ rm foo
451 $ rm foo
452 $ hg st
452 $ hg st
453 ! foo
453 ! foo
454 hmm.. no precommit invoked, but there is a postcommit??
454 hmm.. no precommit invoked, but there is a postcommit??
455 $ hg ci -m "will not checkin"
455 $ hg ci -m "will not checkin"
456 nothing changed
456 nothing changed
457 Invoking status postcommit hook
457 Invoking status postcommit hook
458 ! foo
458 ! foo
459 C normal3
459 C normal3
460 C sub/large4
460 C sub/large4
461 C sub/normal4
461 C sub/normal4
462 C sub2/large6
462 C sub2/large6
463 C sub2/large7
463 C sub2/large7
464 [1]
464 [1]
465 $ hg addremove
465 $ hg addremove
466 removing foo
466 removing foo
467 $ hg st
467 $ hg st
468 R foo
468 R foo
469 $ hg ci -m "used to say nothing changed"
469 $ hg ci -m "used to say nothing changed"
470 Invoking status precommit hook
470 Invoking status precommit hook
471 R foo
471 R foo
472 Invoking status postcommit hook
472 Invoking status postcommit hook
473 C normal3
473 C normal3
474 C sub/large4
474 C sub/large4
475 C sub/normal4
475 C sub/normal4
476 C sub2/large6
476 C sub2/large6
477 C sub2/large7
477 C sub2/large7
478 $ hg st
478 $ hg st
479
479
480 Test 3507 (both normal files and largefiles were a problem)
480 Test 3507 (both normal files and largefiles were a problem)
481
481
482 $ touch normal
482 $ touch normal
483 $ touch large
483 $ touch large
484 $ hg add normal
484 $ hg add normal
485 $ hg add --large large
485 $ hg add --large large
486 $ hg ci -m "added"
486 $ hg ci -m "added"
487 Invoking status precommit hook
487 Invoking status precommit hook
488 A large
488 A large
489 A normal
489 A normal
490 Invoking status postcommit hook
490 Invoking status postcommit hook
491 C large
491 C large
492 C normal
492 C normal
493 C normal3
493 C normal3
494 C sub/large4
494 C sub/large4
495 C sub/normal4
495 C sub/normal4
496 C sub2/large6
496 C sub2/large6
497 C sub2/large7
497 C sub2/large7
498 $ hg remove normal
498 $ hg remove normal
499 $ hg addremove --traceback
499 $ hg addremove --traceback
500 $ hg ci -m "addremoved normal"
500 $ hg ci -m "addremoved normal"
501 Invoking status precommit hook
501 Invoking status precommit hook
502 R normal
502 R normal
503 Invoking status postcommit hook
503 Invoking status postcommit hook
504 C large
504 C large
505 C normal3
505 C normal3
506 C sub/large4
506 C sub/large4
507 C sub/normal4
507 C sub/normal4
508 C sub2/large6
508 C sub2/large6
509 C sub2/large7
509 C sub2/large7
510 $ hg up -C '.^'
510 $ hg up -C '.^'
511 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
511 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
512 getting changed largefiles
512 getting changed largefiles
513 0 largefiles updated, 0 removed
513 0 largefiles updated, 0 removed
514 $ hg remove large
514 $ hg remove large
515 $ hg addremove --traceback
515 $ hg addremove --traceback
516 $ hg ci -m "removed large"
516 $ hg ci -m "removed large"
517 Invoking status precommit hook
517 Invoking status precommit hook
518 R large
518 R large
519 created new head
519 created new head
520 Invoking status postcommit hook
520 Invoking status postcommit hook
521 C normal
521 C normal
522 C normal3
522 C normal3
523 C sub/large4
523 C sub/large4
524 C sub/normal4
524 C sub/normal4
525 C sub2/large6
525 C sub2/large6
526 C sub2/large7
526 C sub2/large7
527
527
528 Test that a standin can't be added as a large file
528 Test that a standin can't be added as a large file
529
529
530 $ touch large
530 $ touch large
531 $ hg add --large large
531 $ hg add --large large
532 $ hg ci -m "add"
532 $ hg ci -m "add"
533 Invoking status precommit hook
533 Invoking status precommit hook
534 A large
534 A large
535 Invoking status postcommit hook
535 Invoking status postcommit hook
536 C large
536 C large
537 C normal
537 C normal
538 C normal3
538 C normal3
539 C sub/large4
539 C sub/large4
540 C sub/normal4
540 C sub/normal4
541 C sub2/large6
541 C sub2/large6
542 C sub2/large7
542 C sub2/large7
543 $ hg remove large
543 $ hg remove large
544 $ touch large
544 $ touch large
545 $ hg addremove --config largefiles.patterns=**large --traceback
545 $ hg addremove --config largefiles.patterns=**large --traceback
546 adding large as a largefile
546 adding large as a largefile
547
547
548 Test that outgoing --large works
548 Test that outgoing --large works (with revsets too)
549 $ hg outgoing --rev 12 --large
549 $ hg outgoing --rev '.^' --large
550 comparing with $TESTTMP/a (glob)
550 comparing with $TESTTMP/a (glob)
551 searching for changes
551 searching for changes
552 changeset: 8:c02fd3b77ec4
552 changeset: 8:c02fd3b77ec4
553 user: test
553 user: test
554 date: Thu Jan 01 00:00:00 1970 +0000
554 date: Thu Jan 01 00:00:00 1970 +0000
555 summary: add foo
555 summary: add foo
556
556
557 changeset: 9:289dd08c9bbb
557 changeset: 9:289dd08c9bbb
558 user: test
558 user: test
559 date: Thu Jan 01 00:00:00 1970 +0000
559 date: Thu Jan 01 00:00:00 1970 +0000
560 summary: used to say nothing changed
560 summary: used to say nothing changed
561
561
562 changeset: 10:34f23ac6ac12
562 changeset: 10:34f23ac6ac12
563 user: test
563 user: test
564 date: Thu Jan 01 00:00:00 1970 +0000
564 date: Thu Jan 01 00:00:00 1970 +0000
565 summary: added
565 summary: added
566
566
567 changeset: 12:710c1b2f523c
567 changeset: 12:710c1b2f523c
568 parent: 10:34f23ac6ac12
568 parent: 10:34f23ac6ac12
569 user: test
569 user: test
570 date: Thu Jan 01 00:00:00 1970 +0000
570 date: Thu Jan 01 00:00:00 1970 +0000
571 summary: removed large
571 summary: removed large
572
572
573 searching for changes
573 searching for changes
574 largefiles to upload:
574 largefiles to upload:
575 large
575 large
576 foo
576 foo
577
577
578 $ cd ../a
578 $ cd ../a
579
579
580 Clone a largefiles repo.
580 Clone a largefiles repo.
581
581
582 $ hg clone . ../b
582 $ hg clone . ../b
583 updating to branch default
583 updating to branch default
584 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
584 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
585 getting changed largefiles
585 getting changed largefiles
586 3 largefiles updated, 0 removed
586 3 largefiles updated, 0 removed
587 $ cd ../b
587 $ cd ../b
588 $ hg log --template '{rev}:{node|short} {desc|firstline}\n'
588 $ hg log --template '{rev}:{node|short} {desc|firstline}\n'
589 7:daea875e9014 add/edit more largefiles
589 7:daea875e9014 add/edit more largefiles
590 6:4355d653f84f edit files yet again
590 6:4355d653f84f edit files yet again
591 5:9d5af5072dbd edit files again
591 5:9d5af5072dbd edit files again
592 4:74c02385b94c move files
592 4:74c02385b94c move files
593 3:9e8fbc4bce62 copy files
593 3:9e8fbc4bce62 copy files
594 2:51a0ae4d5864 remove files
594 2:51a0ae4d5864 remove files
595 1:ce8896473775 edit files
595 1:ce8896473775 edit files
596 0:30d30fe6a5be add files
596 0:30d30fe6a5be add files
597 $ cat normal3
597 $ cat normal3
598 normal33
598 normal33
599 $ cat sub/normal4
599 $ cat sub/normal4
600 normal44
600 normal44
601 $ cat sub/large4
601 $ cat sub/large4
602 large44
602 large44
603 $ cat sub2/large6
603 $ cat sub2/large6
604 large6
604 large6
605 $ cat sub2/large7
605 $ cat sub2/large7
606 large7
606 large7
607 $ cd ..
607 $ cd ..
608 $ hg clone a -r 3 c
608 $ hg clone a -r 3 c
609 adding changesets
609 adding changesets
610 adding manifests
610 adding manifests
611 adding file changes
611 adding file changes
612 added 4 changesets with 10 changes to 4 files
612 added 4 changesets with 10 changes to 4 files
613 updating to branch default
613 updating to branch default
614 4 files updated, 0 files merged, 0 files removed, 0 files unresolved
614 4 files updated, 0 files merged, 0 files removed, 0 files unresolved
615 getting changed largefiles
615 getting changed largefiles
616 2 largefiles updated, 0 removed
616 2 largefiles updated, 0 removed
617 $ cd c
617 $ cd c
618 $ hg log --template '{rev}:{node|short} {desc|firstline}\n'
618 $ hg log --template '{rev}:{node|short} {desc|firstline}\n'
619 3:9e8fbc4bce62 copy files
619 3:9e8fbc4bce62 copy files
620 2:51a0ae4d5864 remove files
620 2:51a0ae4d5864 remove files
621 1:ce8896473775 edit files
621 1:ce8896473775 edit files
622 0:30d30fe6a5be add files
622 0:30d30fe6a5be add files
623 $ cat normal1
623 $ cat normal1
624 normal22
624 normal22
625 $ cat large1
625 $ cat large1
626 large22
626 large22
627 $ cat sub/normal2
627 $ cat sub/normal2
628 normal22
628 normal22
629 $ cat sub/large2
629 $ cat sub/large2
630 large22
630 large22
631
631
632 Old revisions of a clone have correct largefiles content (this also
632 Old revisions of a clone have correct largefiles content (this also
633 tests update).
633 tests update).
634
634
635 $ hg update -r 1
635 $ hg update -r 1
636 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
636 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
637 getting changed largefiles
637 getting changed largefiles
638 1 largefiles updated, 0 removed
638 1 largefiles updated, 0 removed
639 $ cat large1
639 $ cat large1
640 large11
640 large11
641 $ cat sub/large2
641 $ cat sub/large2
642 large22
642 large22
643 $ cd ..
643 $ cd ..
644
644
645 Test cloning with --all-largefiles flag
645 Test cloning with --all-largefiles flag
646
646
647 $ rm "${USERCACHE}"/*
647 $ rm "${USERCACHE}"/*
648 $ hg clone --all-largefiles a a-backup
648 $ hg clone --all-largefiles a a-backup
649 updating to branch default
649 updating to branch default
650 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
650 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
651 getting changed largefiles
651 getting changed largefiles
652 3 largefiles updated, 0 removed
652 3 largefiles updated, 0 removed
653 8 additional largefiles cached
653 8 additional largefiles cached
654
654
655 $ hg clone --all-largefiles a ssh://localhost/a
655 $ hg clone --all-largefiles a ssh://localhost/a
656 abort: --all-largefiles is incompatible with non-local destination ssh://localhost/a
656 abort: --all-largefiles is incompatible with non-local destination ssh://localhost/a
657 [255]
657 [255]
658
658
659 Test pulling with --all-largefiles flag
659 Test pulling with --all-largefiles flag
660
660
661 $ rm -Rf a-backup
661 $ rm -Rf a-backup
662 $ hg clone -r 1 a a-backup
662 $ hg clone -r 1 a a-backup
663 adding changesets
663 adding changesets
664 adding manifests
664 adding manifests
665 adding file changes
665 adding file changes
666 added 2 changesets with 8 changes to 4 files
666 added 2 changesets with 8 changes to 4 files
667 updating to branch default
667 updating to branch default
668 4 files updated, 0 files merged, 0 files removed, 0 files unresolved
668 4 files updated, 0 files merged, 0 files removed, 0 files unresolved
669 getting changed largefiles
669 getting changed largefiles
670 2 largefiles updated, 0 removed
670 2 largefiles updated, 0 removed
671 $ rm "${USERCACHE}"/*
671 $ rm "${USERCACHE}"/*
672 $ cd a-backup
672 $ cd a-backup
673 $ hg pull --all-largefiles
673 $ hg pull --all-largefiles
674 pulling from $TESTTMP/a (glob)
674 pulling from $TESTTMP/a (glob)
675 searching for changes
675 searching for changes
676 adding changesets
676 adding changesets
677 adding manifests
677 adding manifests
678 adding file changes
678 adding file changes
679 added 6 changesets with 16 changes to 8 files
679 added 6 changesets with 16 changes to 8 files
680 (run 'hg update' to get a working copy)
680 (run 'hg update' to get a working copy)
681 caching new largefiles
681 caching new largefiles
682 3 largefiles cached
682 3 largefiles cached
683 3 additional largefiles cached
683 3 additional largefiles cached
684 $ cd ..
684 $ cd ..
685
685
686 Rebasing between two repositories does not revert largefiles to old
686 Rebasing between two repositories does not revert largefiles to old
687 revisions (this was a very bad bug that took a lot of work to fix).
687 revisions (this was a very bad bug that took a lot of work to fix).
688
688
689 $ hg clone a d
689 $ hg clone a d
690 updating to branch default
690 updating to branch default
691 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
691 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
692 getting changed largefiles
692 getting changed largefiles
693 3 largefiles updated, 0 removed
693 3 largefiles updated, 0 removed
694 $ cd b
694 $ cd b
695 $ echo large4-modified > sub/large4
695 $ echo large4-modified > sub/large4
696 $ echo normal3-modified > normal3
696 $ echo normal3-modified > normal3
697 $ hg commit -m "modify normal file and largefile in repo b"
697 $ hg commit -m "modify normal file and largefile in repo b"
698 Invoking status precommit hook
698 Invoking status precommit hook
699 M normal3
699 M normal3
700 M sub/large4
700 M sub/large4
701 $ cd ../d
701 $ cd ../d
702 $ echo large6-modified > sub2/large6
702 $ echo large6-modified > sub2/large6
703 $ echo normal4-modified > sub/normal4
703 $ echo normal4-modified > sub/normal4
704 $ hg commit -m "modify normal file largefile in repo d"
704 $ hg commit -m "modify normal file largefile in repo d"
705 Invoking status precommit hook
705 Invoking status precommit hook
706 M sub/normal4
706 M sub/normal4
707 M sub2/large6
707 M sub2/large6
708 $ cd ..
708 $ cd ..
709 $ hg clone d e
709 $ hg clone d e
710 updating to branch default
710 updating to branch default
711 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
711 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
712 getting changed largefiles
712 getting changed largefiles
713 3 largefiles updated, 0 removed
713 3 largefiles updated, 0 removed
714 $ cd d
714 $ cd d
715 $ hg pull --rebase ../b
715 $ hg pull --rebase ../b
716 pulling from ../b
716 pulling from ../b
717 searching for changes
717 searching for changes
718 adding changesets
718 adding changesets
719 adding manifests
719 adding manifests
720 adding file changes
720 adding file changes
721 added 1 changesets with 2 changes to 2 files (+1 heads)
721 added 1 changesets with 2 changes to 2 files (+1 heads)
722 Invoking status precommit hook
722 Invoking status precommit hook
723 M sub/normal4
723 M sub/normal4
724 M sub2/large6
724 M sub2/large6
725 saved backup bundle to $TESTTMP/d/.hg/strip-backup/f574fb32bb45-backup.hg (glob)
725 saved backup bundle to $TESTTMP/d/.hg/strip-backup/f574fb32bb45-backup.hg (glob)
726 nothing to rebase
726 nothing to rebase
727 $ hg log --template '{rev}:{node|short} {desc|firstline}\n'
727 $ hg log --template '{rev}:{node|short} {desc|firstline}\n'
728 9:598410d3eb9a modify normal file largefile in repo d
728 9:598410d3eb9a modify normal file largefile in repo d
729 8:a381d2c8c80e modify normal file and largefile in repo b
729 8:a381d2c8c80e modify normal file and largefile in repo b
730 7:daea875e9014 add/edit more largefiles
730 7:daea875e9014 add/edit more largefiles
731 6:4355d653f84f edit files yet again
731 6:4355d653f84f edit files yet again
732 5:9d5af5072dbd edit files again
732 5:9d5af5072dbd edit files again
733 4:74c02385b94c move files
733 4:74c02385b94c move files
734 3:9e8fbc4bce62 copy files
734 3:9e8fbc4bce62 copy files
735 2:51a0ae4d5864 remove files
735 2:51a0ae4d5864 remove files
736 1:ce8896473775 edit files
736 1:ce8896473775 edit files
737 0:30d30fe6a5be add files
737 0:30d30fe6a5be add files
738 $ cat normal3
738 $ cat normal3
739 normal3-modified
739 normal3-modified
740 $ cat sub/normal4
740 $ cat sub/normal4
741 normal4-modified
741 normal4-modified
742 $ cat sub/large4
742 $ cat sub/large4
743 large4-modified
743 large4-modified
744 $ cat sub2/large6
744 $ cat sub2/large6
745 large6-modified
745 large6-modified
746 $ cat sub2/large7
746 $ cat sub2/large7
747 large7
747 large7
748 $ cd ../e
748 $ cd ../e
749 $ hg pull ../b
749 $ hg pull ../b
750 pulling from ../b
750 pulling from ../b
751 searching for changes
751 searching for changes
752 adding changesets
752 adding changesets
753 adding manifests
753 adding manifests
754 adding file changes
754 adding file changes
755 added 1 changesets with 2 changes to 2 files (+1 heads)
755 added 1 changesets with 2 changes to 2 files (+1 heads)
756 (run 'hg heads' to see heads, 'hg merge' to merge)
756 (run 'hg heads' to see heads, 'hg merge' to merge)
757 caching new largefiles
757 caching new largefiles
758 0 largefiles cached
758 0 largefiles cached
759 $ hg rebase
759 $ hg rebase
760 Invoking status precommit hook
760 Invoking status precommit hook
761 M sub/normal4
761 M sub/normal4
762 M sub2/large6
762 M sub2/large6
763 saved backup bundle to $TESTTMP/e/.hg/strip-backup/f574fb32bb45-backup.hg (glob)
763 saved backup bundle to $TESTTMP/e/.hg/strip-backup/f574fb32bb45-backup.hg (glob)
764 $ hg log --template '{rev}:{node|short} {desc|firstline}\n'
764 $ hg log --template '{rev}:{node|short} {desc|firstline}\n'
765 9:598410d3eb9a modify normal file largefile in repo d
765 9:598410d3eb9a modify normal file largefile in repo d
766 8:a381d2c8c80e modify normal file and largefile in repo b
766 8:a381d2c8c80e modify normal file and largefile in repo b
767 7:daea875e9014 add/edit more largefiles
767 7:daea875e9014 add/edit more largefiles
768 6:4355d653f84f edit files yet again
768 6:4355d653f84f edit files yet again
769 5:9d5af5072dbd edit files again
769 5:9d5af5072dbd edit files again
770 4:74c02385b94c move files
770 4:74c02385b94c move files
771 3:9e8fbc4bce62 copy files
771 3:9e8fbc4bce62 copy files
772 2:51a0ae4d5864 remove files
772 2:51a0ae4d5864 remove files
773 1:ce8896473775 edit files
773 1:ce8896473775 edit files
774 0:30d30fe6a5be add files
774 0:30d30fe6a5be add files
775 $ cat normal3
775 $ cat normal3
776 normal3-modified
776 normal3-modified
777 $ cat sub/normal4
777 $ cat sub/normal4
778 normal4-modified
778 normal4-modified
779 $ cat sub/large4
779 $ cat sub/large4
780 large4-modified
780 large4-modified
781 $ cat sub2/large6
781 $ cat sub2/large6
782 large6-modified
782 large6-modified
783 $ cat sub2/large7
783 $ cat sub2/large7
784 large7
784 large7
785
785
786 Rollback on largefiles.
786 Rollback on largefiles.
787
787
788 $ echo large4-modified-again > sub/large4
788 $ echo large4-modified-again > sub/large4
789 $ hg commit -m "Modify large4 again"
789 $ hg commit -m "Modify large4 again"
790 Invoking status precommit hook
790 Invoking status precommit hook
791 M sub/large4
791 M sub/large4
792 $ hg rollback
792 $ hg rollback
793 repository tip rolled back to revision 9 (undo commit)
793 repository tip rolled back to revision 9 (undo commit)
794 working directory now based on revision 9
794 working directory now based on revision 9
795 $ hg st
795 $ hg st
796 M sub/large4
796 M sub/large4
797 $ hg log --template '{rev}:{node|short} {desc|firstline}\n'
797 $ hg log --template '{rev}:{node|short} {desc|firstline}\n'
798 9:598410d3eb9a modify normal file largefile in repo d
798 9:598410d3eb9a modify normal file largefile in repo d
799 8:a381d2c8c80e modify normal file and largefile in repo b
799 8:a381d2c8c80e modify normal file and largefile in repo b
800 7:daea875e9014 add/edit more largefiles
800 7:daea875e9014 add/edit more largefiles
801 6:4355d653f84f edit files yet again
801 6:4355d653f84f edit files yet again
802 5:9d5af5072dbd edit files again
802 5:9d5af5072dbd edit files again
803 4:74c02385b94c move files
803 4:74c02385b94c move files
804 3:9e8fbc4bce62 copy files
804 3:9e8fbc4bce62 copy files
805 2:51a0ae4d5864 remove files
805 2:51a0ae4d5864 remove files
806 1:ce8896473775 edit files
806 1:ce8896473775 edit files
807 0:30d30fe6a5be add files
807 0:30d30fe6a5be add files
808 $ cat sub/large4
808 $ cat sub/large4
809 large4-modified-again
809 large4-modified-again
810
810
811 "update --check" refuses to update with uncommitted changes.
811 "update --check" refuses to update with uncommitted changes.
812 $ hg update --check 8
812 $ hg update --check 8
813 abort: uncommitted local changes
813 abort: uncommitted local changes
814 [255]
814 [255]
815
815
816 "update --clean" leaves correct largefiles in working copy.
816 "update --clean" leaves correct largefiles in working copy.
817
817
818 $ hg update --clean
818 $ hg update --clean
819 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
819 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
820 getting changed largefiles
820 getting changed largefiles
821 1 largefiles updated, 0 removed
821 1 largefiles updated, 0 removed
822 $ cat normal3
822 $ cat normal3
823 normal3-modified
823 normal3-modified
824 $ cat sub/normal4
824 $ cat sub/normal4
825 normal4-modified
825 normal4-modified
826 $ cat sub/large4
826 $ cat sub/large4
827 large4-modified
827 large4-modified
828 $ cat sub2/large6
828 $ cat sub2/large6
829 large6-modified
829 large6-modified
830 $ cat sub2/large7
830 $ cat sub2/large7
831 large7
831 large7
832
832
833 Now "update check" is happy.
833 Now "update check" is happy.
834 $ hg update --check 8
834 $ hg update --check 8
835 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
835 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
836 getting changed largefiles
836 getting changed largefiles
837 1 largefiles updated, 0 removed
837 1 largefiles updated, 0 removed
838 $ hg update --check
838 $ hg update --check
839 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
839 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
840 getting changed largefiles
840 getting changed largefiles
841 1 largefiles updated, 0 removed
841 1 largefiles updated, 0 removed
842
842
843 Test removing empty largefiles directories on update
843 Test removing empty largefiles directories on update
844 $ test -d sub2 && echo "sub2 exists"
844 $ test -d sub2 && echo "sub2 exists"
845 sub2 exists
845 sub2 exists
846 $ hg update -q null
846 $ hg update -q null
847 $ test -d sub2 && echo "error: sub2 should not exist anymore"
847 $ test -d sub2 && echo "error: sub2 should not exist anymore"
848 [1]
848 [1]
849 $ hg update -q
849 $ hg update -q
850
850
851 Test hg remove removes empty largefiles directories
851 Test hg remove removes empty largefiles directories
852 $ test -d sub2 && echo "sub2 exists"
852 $ test -d sub2 && echo "sub2 exists"
853 sub2 exists
853 sub2 exists
854 $ hg remove sub2/*
854 $ hg remove sub2/*
855 $ test -d sub2 && echo "error: sub2 should not exist anymore"
855 $ test -d sub2 && echo "error: sub2 should not exist anymore"
856 [1]
856 [1]
857 $ hg revert sub2/large6 sub2/large7
857 $ hg revert sub2/large6 sub2/large7
858
858
859 "revert" works on largefiles (and normal files too).
859 "revert" works on largefiles (and normal files too).
860 $ echo hack3 >> normal3
860 $ echo hack3 >> normal3
861 $ echo hack4 >> sub/normal4
861 $ echo hack4 >> sub/normal4
862 $ echo hack4 >> sub/large4
862 $ echo hack4 >> sub/large4
863 $ rm sub2/large6
863 $ rm sub2/large6
864 $ hg revert sub2/large6
864 $ hg revert sub2/large6
865 $ hg rm sub2/large6
865 $ hg rm sub2/large6
866 $ echo new >> sub2/large8
866 $ echo new >> sub2/large8
867 $ hg add --large sub2/large8
867 $ hg add --large sub2/large8
868 # XXX we don't really want to report that we're reverting the standin;
868 # XXX we don't really want to report that we're reverting the standin;
869 # that's just an implementation detail. But I don't see an obvious fix. ;-(
869 # that's just an implementation detail. But I don't see an obvious fix. ;-(
870 $ hg revert sub
870 $ hg revert sub
871 reverting .hglf/sub/large4 (glob)
871 reverting .hglf/sub/large4 (glob)
872 reverting sub/normal4 (glob)
872 reverting sub/normal4 (glob)
873 $ hg status
873 $ hg status
874 M normal3
874 M normal3
875 A sub2/large8
875 A sub2/large8
876 R sub2/large6
876 R sub2/large6
877 ? sub/large4.orig
877 ? sub/large4.orig
878 ? sub/normal4.orig
878 ? sub/normal4.orig
879 $ cat sub/normal4
879 $ cat sub/normal4
880 normal4-modified
880 normal4-modified
881 $ cat sub/large4
881 $ cat sub/large4
882 large4-modified
882 large4-modified
883 $ hg revert -a --no-backup
883 $ hg revert -a --no-backup
884 undeleting .hglf/sub2/large6 (glob)
884 undeleting .hglf/sub2/large6 (glob)
885 forgetting .hglf/sub2/large8 (glob)
885 forgetting .hglf/sub2/large8 (glob)
886 reverting normal3
886 reverting normal3
887 $ hg status
887 $ hg status
888 ? sub/large4.orig
888 ? sub/large4.orig
889 ? sub/normal4.orig
889 ? sub/normal4.orig
890 ? sub2/large8
890 ? sub2/large8
891 $ cat normal3
891 $ cat normal3
892 normal3-modified
892 normal3-modified
893 $ cat sub2/large6
893 $ cat sub2/large6
894 large6-modified
894 large6-modified
895 $ rm sub/*.orig sub2/large8
895 $ rm sub/*.orig sub2/large8
896
896
897 revert some files to an older revision
897 revert some files to an older revision
898 $ hg revert --no-backup -r 8 sub2
898 $ hg revert --no-backup -r 8 sub2
899 reverting .hglf/sub2/large6 (glob)
899 reverting .hglf/sub2/large6 (glob)
900 $ cat sub2/large6
900 $ cat sub2/large6
901 large6
901 large6
902 $ hg revert --no-backup -C -r '.^' sub2
902 $ hg revert --no-backup -C -r '.^' sub2
903 reverting .hglf/sub2/large6 (glob)
903 reverting .hglf/sub2/large6 (glob)
904 $ hg revert --no-backup sub2
904 $ hg revert --no-backup sub2
905 reverting .hglf/sub2/large6 (glob)
905 reverting .hglf/sub2/large6 (glob)
906 $ hg status
906 $ hg status
907
907
908 "verify --large" actually verifies largefiles
908 "verify --large" actually verifies largefiles
909
909
910 $ hg verify --large
910 $ hg verify --large
911 checking changesets
911 checking changesets
912 checking manifests
912 checking manifests
913 crosschecking files in changesets and manifests
913 crosschecking files in changesets and manifests
914 checking files
914 checking files
915 10 files, 10 changesets, 28 total revisions
915 10 files, 10 changesets, 28 total revisions
916 searching 1 changesets for largefiles
916 searching 1 changesets for largefiles
917 verified existence of 3 revisions of 3 largefiles
917 verified existence of 3 revisions of 3 largefiles
918
918
919 Merging does not revert to old versions of largefiles and also check
919 Merging does not revert to old versions of largefiles and also check
920 that merging after having pulled from a non-default remote works
920 that merging after having pulled from a non-default remote works
921 correctly.
921 correctly.
922
922
923 $ cd ..
923 $ cd ..
924 $ hg clone -r 7 e temp
924 $ hg clone -r 7 e temp
925 adding changesets
925 adding changesets
926 adding manifests
926 adding manifests
927 adding file changes
927 adding file changes
928 added 8 changesets with 24 changes to 10 files
928 added 8 changesets with 24 changes to 10 files
929 updating to branch default
929 updating to branch default
930 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
930 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
931 getting changed largefiles
931 getting changed largefiles
932 3 largefiles updated, 0 removed
932 3 largefiles updated, 0 removed
933 $ hg clone temp f
933 $ hg clone temp f
934 updating to branch default
934 updating to branch default
935 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
935 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
936 getting changed largefiles
936 getting changed largefiles
937 3 largefiles updated, 0 removed
937 3 largefiles updated, 0 removed
938 # Delete the largefiles in the largefiles system cache so that we have an
938 # Delete the largefiles in the largefiles system cache so that we have an
939 # opportunity to test that caching after a pull works.
939 # opportunity to test that caching after a pull works.
940 $ rm "${USERCACHE}"/*
940 $ rm "${USERCACHE}"/*
941 $ cd f
941 $ cd f
942 $ echo "large4-merge-test" > sub/large4
942 $ echo "large4-merge-test" > sub/large4
943 $ hg commit -m "Modify large4 to test merge"
943 $ hg commit -m "Modify large4 to test merge"
944 Invoking status precommit hook
944 Invoking status precommit hook
945 M sub/large4
945 M sub/large4
946 $ hg pull ../e
946 $ hg pull ../e
947 pulling from ../e
947 pulling from ../e
948 searching for changes
948 searching for changes
949 adding changesets
949 adding changesets
950 adding manifests
950 adding manifests
951 adding file changes
951 adding file changes
952 added 2 changesets with 4 changes to 4 files (+1 heads)
952 added 2 changesets with 4 changes to 4 files (+1 heads)
953 (run 'hg heads' to see heads, 'hg merge' to merge)
953 (run 'hg heads' to see heads, 'hg merge' to merge)
954 caching new largefiles
954 caching new largefiles
955 2 largefiles cached
955 2 largefiles cached
956 $ hg merge
956 $ hg merge
957 merging sub/large4
957 merging sub/large4
958 largefile sub/large4 has a merge conflict
958 largefile sub/large4 has a merge conflict
959 keep (l)ocal or take (o)ther? l
959 keep (l)ocal or take (o)ther? l
960 3 files updated, 1 files merged, 0 files removed, 0 files unresolved
960 3 files updated, 1 files merged, 0 files removed, 0 files unresolved
961 (branch merge, don't forget to commit)
961 (branch merge, don't forget to commit)
962 getting changed largefiles
962 getting changed largefiles
963 1 largefiles updated, 0 removed
963 1 largefiles updated, 0 removed
964 $ hg commit -m "Merge repos e and f"
964 $ hg commit -m "Merge repos e and f"
965 Invoking status precommit hook
965 Invoking status precommit hook
966 M normal3
966 M normal3
967 M sub/normal4
967 M sub/normal4
968 M sub2/large6
968 M sub2/large6
969 $ cat normal3
969 $ cat normal3
970 normal3-modified
970 normal3-modified
971 $ cat sub/normal4
971 $ cat sub/normal4
972 normal4-modified
972 normal4-modified
973 $ cat sub/large4
973 $ cat sub/large4
974 large4-merge-test
974 large4-merge-test
975 $ cat sub2/large6
975 $ cat sub2/large6
976 large6-modified
976 large6-modified
977 $ cat sub2/large7
977 $ cat sub2/large7
978 large7
978 large7
979
979
980 Test status after merging with a branch that introduces a new largefile:
980 Test status after merging with a branch that introduces a new largefile:
981
981
982 $ echo large > large
982 $ echo large > large
983 $ hg add --large large
983 $ hg add --large large
984 $ hg commit -m 'add largefile'
984 $ hg commit -m 'add largefile'
985 Invoking status precommit hook
985 Invoking status precommit hook
986 A large
986 A large
987 $ hg update -q ".^"
987 $ hg update -q ".^"
988 $ echo change >> normal3
988 $ echo change >> normal3
989 $ hg commit -m 'some change'
989 $ hg commit -m 'some change'
990 Invoking status precommit hook
990 Invoking status precommit hook
991 M normal3
991 M normal3
992 created new head
992 created new head
993 $ hg merge
993 $ hg merge
994 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
994 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
995 (branch merge, don't forget to commit)
995 (branch merge, don't forget to commit)
996 getting changed largefiles
996 getting changed largefiles
997 1 largefiles updated, 0 removed
997 1 largefiles updated, 0 removed
998 $ hg status
998 $ hg status
999 M large
999 M large
1000
1000
1001 Test that a normal file and a largefile with the same name and path cannot
1001 Test that a normal file and a largefile with the same name and path cannot
1002 coexist.
1002 coexist.
1003
1003
1004 $ rm sub2/large7
1004 $ rm sub2/large7
1005 $ echo "largeasnormal" > sub2/large7
1005 $ echo "largeasnormal" > sub2/large7
1006 $ hg add sub2/large7
1006 $ hg add sub2/large7
1007 sub2/large7 already a largefile
1007 sub2/large7 already a largefile
1008
1008
1009 Test that transplanting a largefile change works correctly.
1009 Test that transplanting a largefile change works correctly.
1010
1010
1011 $ cd ..
1011 $ cd ..
1012 $ hg clone -r 8 d g
1012 $ hg clone -r 8 d g
1013 adding changesets
1013 adding changesets
1014 adding manifests
1014 adding manifests
1015 adding file changes
1015 adding file changes
1016 added 9 changesets with 26 changes to 10 files
1016 added 9 changesets with 26 changes to 10 files
1017 updating to branch default
1017 updating to branch default
1018 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
1018 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
1019 getting changed largefiles
1019 getting changed largefiles
1020 3 largefiles updated, 0 removed
1020 3 largefiles updated, 0 removed
1021 $ cd g
1021 $ cd g
1022 $ hg transplant -s ../d 598410d3eb9a
1022 $ hg transplant -s ../d 598410d3eb9a
1023 searching for changes
1023 searching for changes
1024 searching for changes
1024 searching for changes
1025 adding changesets
1025 adding changesets
1026 adding manifests
1026 adding manifests
1027 adding file changes
1027 adding file changes
1028 added 1 changesets with 2 changes to 2 files
1028 added 1 changesets with 2 changes to 2 files
1029 getting changed largefiles
1029 getting changed largefiles
1030 1 largefiles updated, 0 removed
1030 1 largefiles updated, 0 removed
1031 $ hg log --template '{rev}:{node|short} {desc|firstline}\n'
1031 $ hg log --template '{rev}:{node|short} {desc|firstline}\n'
1032 9:598410d3eb9a modify normal file largefile in repo d
1032 9:598410d3eb9a modify normal file largefile in repo d
1033 8:a381d2c8c80e modify normal file and largefile in repo b
1033 8:a381d2c8c80e modify normal file and largefile in repo b
1034 7:daea875e9014 add/edit more largefiles
1034 7:daea875e9014 add/edit more largefiles
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 3:9e8fbc4bce62 copy files
1038 3:9e8fbc4bce62 copy files
1039 2:51a0ae4d5864 remove files
1039 2:51a0ae4d5864 remove files
1040 1:ce8896473775 edit files
1040 1:ce8896473775 edit files
1041 0:30d30fe6a5be add files
1041 0:30d30fe6a5be add files
1042 $ cat normal3
1042 $ cat normal3
1043 normal3-modified
1043 normal3-modified
1044 $ cat sub/normal4
1044 $ cat sub/normal4
1045 normal4-modified
1045 normal4-modified
1046 $ cat sub/large4
1046 $ cat sub/large4
1047 large4-modified
1047 large4-modified
1048 $ cat sub2/large6
1048 $ cat sub2/large6
1049 large6-modified
1049 large6-modified
1050 $ cat sub2/large7
1050 $ cat sub2/large7
1051 large7
1051 large7
1052
1052
1053 Cat a largefile
1053 Cat a largefile
1054 $ hg cat normal3
1054 $ hg cat normal3
1055 normal3-modified
1055 normal3-modified
1056 $ hg cat sub/large4
1056 $ hg cat sub/large4
1057 large4-modified
1057 large4-modified
1058 $ rm "${USERCACHE}"/*
1058 $ rm "${USERCACHE}"/*
1059 $ hg cat -r a381d2c8c80e -o cat.out sub/large4
1059 $ hg cat -r a381d2c8c80e -o cat.out sub/large4
1060 $ cat cat.out
1060 $ cat cat.out
1061 large4-modified
1061 large4-modified
1062 $ rm cat.out
1062 $ rm cat.out
1063 $ hg cat -r a381d2c8c80e normal3
1063 $ hg cat -r a381d2c8c80e normal3
1064 normal3-modified
1064 normal3-modified
1065 $ hg cat -r '.^' normal3
1065 $ hg cat -r '.^' normal3
1066 normal3-modified
1066 normal3-modified
1067 $ hg cat -r '.^' sub/large4
1067 $ hg cat -r '.^' sub/large4
1068 large4-modified
1068 large4-modified
1069
1069
1070 Test that renaming a largefile results in correct output for status
1070 Test that renaming a largefile results in correct output for status
1071
1071
1072 $ hg rename sub/large4 large4-renamed
1072 $ hg rename sub/large4 large4-renamed
1073 $ hg commit -m "test rename output"
1073 $ hg commit -m "test rename output"
1074 Invoking status precommit hook
1074 Invoking status precommit hook
1075 A large4-renamed
1075 A large4-renamed
1076 R sub/large4
1076 R sub/large4
1077 $ cat large4-renamed
1077 $ cat large4-renamed
1078 large4-modified
1078 large4-modified
1079 $ cd sub2
1079 $ cd sub2
1080 $ hg rename large6 large6-renamed
1080 $ hg rename large6 large6-renamed
1081 $ hg st
1081 $ hg st
1082 A sub2/large6-renamed
1082 A sub2/large6-renamed
1083 R sub2/large6
1083 R sub2/large6
1084 $ cd ..
1084 $ cd ..
1085
1085
1086 Test --normal flag
1086 Test --normal flag
1087
1087
1088 $ dd if=/dev/zero bs=2k count=11k > new-largefile 2> /dev/null
1088 $ dd if=/dev/zero bs=2k count=11k > new-largefile 2> /dev/null
1089 $ hg add --normal --large new-largefile
1089 $ hg add --normal --large new-largefile
1090 abort: --normal cannot be used with --large
1090 abort: --normal cannot be used with --large
1091 [255]
1091 [255]
1092 $ hg add --normal new-largefile
1092 $ hg add --normal new-largefile
1093 new-largefile: up to 69 MB of RAM may be required to manage this file
1093 new-largefile: up to 69 MB of RAM may be required to manage this file
1094 (use 'hg revert new-largefile' to cancel the pending addition)
1094 (use 'hg revert new-largefile' to cancel the pending addition)
1095 $ cd ..
1095 $ cd ..
1096
1096
1097 #if serve
1097 #if serve
1098 vanilla clients not locked out from largefiles servers on vanilla repos
1098 vanilla clients not locked out from largefiles servers on vanilla repos
1099 $ mkdir r1
1099 $ mkdir r1
1100 $ cd r1
1100 $ cd r1
1101 $ hg init
1101 $ hg init
1102 $ echo c1 > f1
1102 $ echo c1 > f1
1103 $ hg add f1
1103 $ hg add f1
1104 $ hg commit -m "m1"
1104 $ hg commit -m "m1"
1105 Invoking status precommit hook
1105 Invoking status precommit hook
1106 A f1
1106 A f1
1107 $ cd ..
1107 $ cd ..
1108 $ hg serve -R r1 -d -p $HGPORT --pid-file hg.pid
1108 $ hg serve -R r1 -d -p $HGPORT --pid-file hg.pid
1109 $ cat hg.pid >> $DAEMON_PIDS
1109 $ cat hg.pid >> $DAEMON_PIDS
1110 $ hg --config extensions.largefiles=! clone http://localhost:$HGPORT r2
1110 $ hg --config extensions.largefiles=! clone http://localhost:$HGPORT r2
1111 requesting all changes
1111 requesting all changes
1112 adding changesets
1112 adding changesets
1113 adding manifests
1113 adding manifests
1114 adding file changes
1114 adding file changes
1115 added 1 changesets with 1 changes to 1 files
1115 added 1 changesets with 1 changes to 1 files
1116 updating to branch default
1116 updating to branch default
1117 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1117 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1118
1118
1119 largefiles clients still work with vanilla servers
1119 largefiles clients still work with vanilla servers
1120 $ hg --config extensions.largefiles=! serve -R r1 -d -p $HGPORT1 --pid-file hg.pid
1120 $ hg --config extensions.largefiles=! serve -R r1 -d -p $HGPORT1 --pid-file hg.pid
1121 $ cat hg.pid >> $DAEMON_PIDS
1121 $ cat hg.pid >> $DAEMON_PIDS
1122 $ hg clone http://localhost:$HGPORT1 r3
1122 $ hg clone http://localhost:$HGPORT1 r3
1123 requesting all changes
1123 requesting all changes
1124 adding changesets
1124 adding changesets
1125 adding manifests
1125 adding manifests
1126 adding file changes
1126 adding file changes
1127 added 1 changesets with 1 changes to 1 files
1127 added 1 changesets with 1 changes to 1 files
1128 updating to branch default
1128 updating to branch default
1129 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1129 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1130 #endif
1130 #endif
1131
1131
1132
1132
1133 vanilla clients locked out from largefiles http repos
1133 vanilla clients locked out from largefiles http repos
1134 $ mkdir r4
1134 $ mkdir r4
1135 $ cd r4
1135 $ cd r4
1136 $ hg init
1136 $ hg init
1137 $ echo c1 > f1
1137 $ echo c1 > f1
1138 $ hg add --large f1
1138 $ hg add --large f1
1139 $ hg commit -m "m1"
1139 $ hg commit -m "m1"
1140 Invoking status precommit hook
1140 Invoking status precommit hook
1141 A f1
1141 A f1
1142 $ cd ..
1142 $ cd ..
1143
1143
1144 #if serve
1144 #if serve
1145 $ hg serve -R r4 -d -p $HGPORT2 --pid-file hg.pid
1145 $ hg serve -R r4 -d -p $HGPORT2 --pid-file hg.pid
1146 $ cat hg.pid >> $DAEMON_PIDS
1146 $ cat hg.pid >> $DAEMON_PIDS
1147 $ hg --config extensions.largefiles=! clone http://localhost:$HGPORT2 r5
1147 $ hg --config extensions.largefiles=! clone http://localhost:$HGPORT2 r5
1148 abort: remote error:
1148 abort: remote error:
1149
1149
1150 This repository uses the largefiles extension.
1150 This repository uses the largefiles extension.
1151
1151
1152 Please enable it in your Mercurial config file.
1152 Please enable it in your Mercurial config file.
1153 [255]
1153 [255]
1154
1154
1155 used all HGPORTs, kill all daemons
1155 used all HGPORTs, kill all daemons
1156 $ "$TESTDIR/killdaemons.py"
1156 $ "$TESTDIR/killdaemons.py"
1157 #endif
1157 #endif
1158
1158
1159 vanilla clients locked out from largefiles ssh repos
1159 vanilla clients locked out from largefiles ssh repos
1160 $ hg --config extensions.largefiles=! clone -e "python \"$TESTDIR/dummyssh\"" ssh://user@dummy/r4 r5
1160 $ hg --config extensions.largefiles=! clone -e "python \"$TESTDIR/dummyssh\"" ssh://user@dummy/r4 r5
1161 abort: remote error:
1161 abort: remote error:
1162
1162
1163 This repository uses the largefiles extension.
1163 This repository uses the largefiles extension.
1164
1164
1165 Please enable it in your Mercurial config file.
1165 Please enable it in your Mercurial config file.
1166 [255]
1166 [255]
1167
1167
1168 #if serve
1168 #if serve
1169
1169
1170 largefiles clients refuse to push largefiles repos to vanilla servers
1170 largefiles clients refuse to push largefiles repos to vanilla servers
1171 $ mkdir r6
1171 $ mkdir r6
1172 $ cd r6
1172 $ cd r6
1173 $ hg init
1173 $ hg init
1174 $ echo c1 > f1
1174 $ echo c1 > f1
1175 $ hg add f1
1175 $ hg add f1
1176 $ hg commit -m "m1"
1176 $ hg commit -m "m1"
1177 Invoking status precommit hook
1177 Invoking status precommit hook
1178 A f1
1178 A f1
1179 $ cat >> .hg/hgrc <<!
1179 $ cat >> .hg/hgrc <<!
1180 > [web]
1180 > [web]
1181 > push_ssl = false
1181 > push_ssl = false
1182 > allow_push = *
1182 > allow_push = *
1183 > !
1183 > !
1184 $ cd ..
1184 $ cd ..
1185 $ hg clone r6 r7
1185 $ hg clone r6 r7
1186 updating to branch default
1186 updating to branch default
1187 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1187 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1188 $ cd r7
1188 $ cd r7
1189 $ echo c2 > f2
1189 $ echo c2 > f2
1190 $ hg add --large f2
1190 $ hg add --large f2
1191 $ hg commit -m "m2"
1191 $ hg commit -m "m2"
1192 Invoking status precommit hook
1192 Invoking status precommit hook
1193 A f2
1193 A f2
1194 $ hg --config extensions.largefiles=! -R ../r6 serve -d -p $HGPORT --pid-file ../hg.pid
1194 $ hg --config extensions.largefiles=! -R ../r6 serve -d -p $HGPORT --pid-file ../hg.pid
1195 $ cat ../hg.pid >> $DAEMON_PIDS
1195 $ cat ../hg.pid >> $DAEMON_PIDS
1196 $ hg push http://localhost:$HGPORT
1196 $ hg push http://localhost:$HGPORT
1197 pushing to http://localhost:$HGPORT/
1197 pushing to http://localhost:$HGPORT/
1198 searching for changes
1198 searching for changes
1199 abort: http://localhost:$HGPORT/ does not appear to be a largefile store
1199 abort: http://localhost:$HGPORT/ does not appear to be a largefile store
1200 [255]
1200 [255]
1201 $ cd ..
1201 $ cd ..
1202
1202
1203 putlfile errors are shown (issue3123)
1203 putlfile errors are shown (issue3123)
1204 Corrupt the cached largefile in r7 and in the usercache (required for testing on vfat)
1204 Corrupt the cached largefile in r7 and in the usercache (required for testing on vfat)
1205 $ echo corruption > "$TESTTMP/r7/.hg/largefiles/4cdac4d8b084d0b599525cf732437fb337d422a8"
1205 $ echo corruption > "$TESTTMP/r7/.hg/largefiles/4cdac4d8b084d0b599525cf732437fb337d422a8"
1206 $ echo corruption > "$USERCACHE/4cdac4d8b084d0b599525cf732437fb337d422a8"
1206 $ echo corruption > "$USERCACHE/4cdac4d8b084d0b599525cf732437fb337d422a8"
1207 $ hg init empty
1207 $ hg init empty
1208 $ hg serve -R empty -d -p $HGPORT1 --pid-file hg.pid \
1208 $ hg serve -R empty -d -p $HGPORT1 --pid-file hg.pid \
1209 > --config 'web.allow_push=*' --config web.push_ssl=False
1209 > --config 'web.allow_push=*' --config web.push_ssl=False
1210 $ cat hg.pid >> $DAEMON_PIDS
1210 $ cat hg.pid >> $DAEMON_PIDS
1211 $ hg push -R r7 http://localhost:$HGPORT1
1211 $ hg push -R r7 http://localhost:$HGPORT1
1212 pushing to http://localhost:$HGPORT1/
1212 pushing to http://localhost:$HGPORT1/
1213 searching for changes
1213 searching for changes
1214 remote: largefiles: failed to put 4cdac4d8b084d0b599525cf732437fb337d422a8 into store: largefile contents do not match hash
1214 remote: largefiles: failed to put 4cdac4d8b084d0b599525cf732437fb337d422a8 into store: largefile contents do not match hash
1215 abort: remotestore: could not put $TESTTMP/r7/.hg/largefiles/4cdac4d8b084d0b599525cf732437fb337d422a8 to remote store http://localhost:$HGPORT1/ (glob)
1215 abort: remotestore: could not put $TESTTMP/r7/.hg/largefiles/4cdac4d8b084d0b599525cf732437fb337d422a8 to remote store http://localhost:$HGPORT1/ (glob)
1216 [255]
1216 [255]
1217 $ rm -rf empty
1217 $ rm -rf empty
1218
1218
1219 Push a largefiles repository to a served empty repository
1219 Push a largefiles repository to a served empty repository
1220 $ hg init r8
1220 $ hg init r8
1221 $ echo c3 > r8/f1
1221 $ echo c3 > r8/f1
1222 $ hg add --large r8/f1 -R r8
1222 $ hg add --large r8/f1 -R r8
1223 $ hg commit -m "m1" -R r8
1223 $ hg commit -m "m1" -R r8
1224 Invoking status precommit hook
1224 Invoking status precommit hook
1225 A f1
1225 A f1
1226 $ hg init empty
1226 $ hg init empty
1227 $ hg serve -R empty -d -p $HGPORT2 --pid-file hg.pid \
1227 $ hg serve -R empty -d -p $HGPORT2 --pid-file hg.pid \
1228 > --config 'web.allow_push=*' --config web.push_ssl=False
1228 > --config 'web.allow_push=*' --config web.push_ssl=False
1229 $ cat hg.pid >> $DAEMON_PIDS
1229 $ cat hg.pid >> $DAEMON_PIDS
1230 $ rm "${USERCACHE}"/*
1230 $ rm "${USERCACHE}"/*
1231 $ hg push -R r8 http://localhost:$HGPORT2
1231 $ hg push -R r8 http://localhost:$HGPORT2
1232 pushing to http://localhost:$HGPORT2/
1232 pushing to http://localhost:$HGPORT2/
1233 searching for changes
1233 searching for changes
1234 searching for changes
1234 searching for changes
1235 remote: adding changesets
1235 remote: adding changesets
1236 remote: adding manifests
1236 remote: adding manifests
1237 remote: adding file changes
1237 remote: adding file changes
1238 remote: added 1 changesets with 1 changes to 1 files
1238 remote: added 1 changesets with 1 changes to 1 files
1239 $ rm -rf empty
1239 $ rm -rf empty
1240
1240
1241 used all HGPORTs, kill all daemons
1241 used all HGPORTs, kill all daemons
1242 $ "$TESTDIR/killdaemons.py"
1242 $ "$TESTDIR/killdaemons.py"
1243
1243
1244 #endif
1244 #endif
1245
1245
1246
1246
1247 #if unix-permissions
1247 #if unix-permissions
1248
1248
1249 Clone a local repository owned by another user
1249 Clone a local repository owned by another user
1250 We have to simulate that here by setting $HOME and removing write permissions
1250 We have to simulate that here by setting $HOME and removing write permissions
1251 $ ORIGHOME="$HOME"
1251 $ ORIGHOME="$HOME"
1252 $ mkdir alice
1252 $ mkdir alice
1253 $ HOME="`pwd`/alice"
1253 $ HOME="`pwd`/alice"
1254 $ cd alice
1254 $ cd alice
1255 $ hg init pubrepo
1255 $ hg init pubrepo
1256 $ cd pubrepo
1256 $ cd pubrepo
1257 $ dd if=/dev/zero bs=1k count=11k > a-large-file 2> /dev/null
1257 $ dd if=/dev/zero bs=1k count=11k > a-large-file 2> /dev/null
1258 $ hg add --large a-large-file
1258 $ hg add --large a-large-file
1259 $ hg commit -m "Add a large file"
1259 $ hg commit -m "Add a large file"
1260 Invoking status precommit hook
1260 Invoking status precommit hook
1261 A a-large-file
1261 A a-large-file
1262 $ cd ..
1262 $ cd ..
1263 $ chmod -R a-w pubrepo
1263 $ chmod -R a-w pubrepo
1264 $ cd ..
1264 $ cd ..
1265 $ mkdir bob
1265 $ mkdir bob
1266 $ HOME="`pwd`/bob"
1266 $ HOME="`pwd`/bob"
1267 $ cd bob
1267 $ cd bob
1268 $ hg clone --pull ../alice/pubrepo pubrepo
1268 $ hg clone --pull ../alice/pubrepo pubrepo
1269 requesting all changes
1269 requesting all changes
1270 adding changesets
1270 adding changesets
1271 adding manifests
1271 adding manifests
1272 adding file changes
1272 adding file changes
1273 added 1 changesets with 1 changes to 1 files
1273 added 1 changesets with 1 changes to 1 files
1274 updating to branch default
1274 updating to branch default
1275 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1275 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1276 getting changed largefiles
1276 getting changed largefiles
1277 1 largefiles updated, 0 removed
1277 1 largefiles updated, 0 removed
1278 $ cd ..
1278 $ cd ..
1279 $ chmod -R u+w alice/pubrepo
1279 $ chmod -R u+w alice/pubrepo
1280 $ HOME="$ORIGHOME"
1280 $ HOME="$ORIGHOME"
1281
1281
1282 #endif
1282 #endif
1283
1283
1284 #if symlink
1284 #if symlink
1285
1285
1286 Symlink to a large largefile should behave the same as a symlink to a normal file
1286 Symlink to a large largefile should behave the same as a symlink to a normal file
1287 $ hg init largesymlink
1287 $ hg init largesymlink
1288 $ cd largesymlink
1288 $ cd largesymlink
1289 $ dd if=/dev/zero bs=1k count=10k of=largefile 2>/dev/null
1289 $ dd if=/dev/zero bs=1k count=10k of=largefile 2>/dev/null
1290 $ hg add --large largefile
1290 $ hg add --large largefile
1291 $ hg commit -m "commit a large file"
1291 $ hg commit -m "commit a large file"
1292 Invoking status precommit hook
1292 Invoking status precommit hook
1293 A largefile
1293 A largefile
1294 $ ln -s largefile largelink
1294 $ ln -s largefile largelink
1295 $ hg add largelink
1295 $ hg add largelink
1296 $ hg commit -m "commit a large symlink"
1296 $ hg commit -m "commit a large symlink"
1297 Invoking status precommit hook
1297 Invoking status precommit hook
1298 A largelink
1298 A largelink
1299 $ rm -f largelink
1299 $ rm -f largelink
1300 $ hg up >/dev/null
1300 $ hg up >/dev/null
1301 $ test -f largelink
1301 $ test -f largelink
1302 [1]
1302 [1]
1303 $ test -L largelink
1303 $ test -L largelink
1304 [1]
1304 [1]
1305 $ rm -f largelink # make next part of the test independent of the previous
1305 $ rm -f largelink # make next part of the test independent of the previous
1306 $ hg up -C >/dev/null
1306 $ hg up -C >/dev/null
1307 $ test -f largelink
1307 $ test -f largelink
1308 $ test -L largelink
1308 $ test -L largelink
1309 $ cd ..
1309 $ cd ..
1310
1310
1311 #endif
1311 #endif
1312
1312
1313 test for pattern matching on 'hg status':
1313 test for pattern matching on 'hg status':
1314 to boost performance, largefiles checks whether specified patterns are
1314 to boost performance, largefiles checks whether specified patterns are
1315 related to largefiles in working directory (NOT to STANDIN) or not.
1315 related to largefiles in working directory (NOT to STANDIN) or not.
1316
1316
1317 $ hg init statusmatch
1317 $ hg init statusmatch
1318 $ cd statusmatch
1318 $ cd statusmatch
1319
1319
1320 $ mkdir -p a/b/c/d
1320 $ mkdir -p a/b/c/d
1321 $ echo normal > a/b/c/d/e.normal.txt
1321 $ echo normal > a/b/c/d/e.normal.txt
1322 $ hg add a/b/c/d/e.normal.txt
1322 $ hg add a/b/c/d/e.normal.txt
1323 $ echo large > a/b/c/d/e.large.txt
1323 $ echo large > a/b/c/d/e.large.txt
1324 $ hg add --large a/b/c/d/e.large.txt
1324 $ hg add --large a/b/c/d/e.large.txt
1325 $ mkdir -p a/b/c/x
1325 $ mkdir -p a/b/c/x
1326 $ echo normal > a/b/c/x/y.normal.txt
1326 $ echo normal > a/b/c/x/y.normal.txt
1327 $ hg add a/b/c/x/y.normal.txt
1327 $ hg add a/b/c/x/y.normal.txt
1328 $ hg commit -m 'add files'
1328 $ hg commit -m 'add files'
1329 Invoking status precommit hook
1329 Invoking status precommit hook
1330 A a/b/c/d/e.large.txt
1330 A a/b/c/d/e.large.txt
1331 A a/b/c/d/e.normal.txt
1331 A a/b/c/d/e.normal.txt
1332 A a/b/c/x/y.normal.txt
1332 A a/b/c/x/y.normal.txt
1333
1333
1334 (1) no pattern: no performance boost
1334 (1) no pattern: no performance boost
1335 $ hg status -A
1335 $ hg status -A
1336 C a/b/c/d/e.large.txt
1336 C a/b/c/d/e.large.txt
1337 C a/b/c/d/e.normal.txt
1337 C a/b/c/d/e.normal.txt
1338 C a/b/c/x/y.normal.txt
1338 C a/b/c/x/y.normal.txt
1339
1339
1340 (2) pattern not related to largefiles: performance boost
1340 (2) pattern not related to largefiles: performance boost
1341 $ hg status -A a/b/c/x
1341 $ hg status -A a/b/c/x
1342 C a/b/c/x/y.normal.txt
1342 C a/b/c/x/y.normal.txt
1343
1343
1344 (3) pattern related to largefiles: no performance boost
1344 (3) pattern related to largefiles: no performance boost
1345 $ hg status -A a/b/c/d
1345 $ hg status -A a/b/c/d
1346 C a/b/c/d/e.large.txt
1346 C a/b/c/d/e.large.txt
1347 C a/b/c/d/e.normal.txt
1347 C a/b/c/d/e.normal.txt
1348
1348
1349 (4) pattern related to STANDIN (not to largefiles): performance boost
1349 (4) pattern related to STANDIN (not to largefiles): performance boost
1350 $ hg status -A .hglf/a
1350 $ hg status -A .hglf/a
1351 C .hglf/a/b/c/d/e.large.txt
1351 C .hglf/a/b/c/d/e.large.txt
1352
1352
1353 (5) mixed case: no performance boost
1353 (5) mixed case: no performance boost
1354 $ hg status -A a/b/c/x a/b/c/d
1354 $ hg status -A a/b/c/x a/b/c/d
1355 C a/b/c/d/e.large.txt
1355 C a/b/c/d/e.large.txt
1356 C a/b/c/d/e.normal.txt
1356 C a/b/c/d/e.normal.txt
1357 C a/b/c/x/y.normal.txt
1357 C a/b/c/x/y.normal.txt
1358
1358
1359 verify that largefiles doesn't break filesets
1359 verify that largefiles doesn't break filesets
1360
1360
1361 $ hg log --rev . --exclude "set:binary()"
1361 $ hg log --rev . --exclude "set:binary()"
1362 changeset: 0:41bd42f10efa
1362 changeset: 0:41bd42f10efa
1363 tag: tip
1363 tag: tip
1364 user: test
1364 user: test
1365 date: Thu Jan 01 00:00:00 1970 +0000
1365 date: Thu Jan 01 00:00:00 1970 +0000
1366 summary: add files
1366 summary: add files
1367
1367
1368 verify that large files in subrepos handled properly
1368 verify that large files in subrepos handled properly
1369 $ hg init subrepo
1369 $ hg init subrepo
1370 $ echo "subrepo = subrepo" > .hgsub
1370 $ echo "subrepo = subrepo" > .hgsub
1371 $ hg add .hgsub
1371 $ hg add .hgsub
1372 $ hg ci -m "add subrepo"
1372 $ hg ci -m "add subrepo"
1373 Invoking status precommit hook
1373 Invoking status precommit hook
1374 A .hgsub
1374 A .hgsub
1375 ? .hgsubstate
1375 ? .hgsubstate
1376 $ echo "rev 1" > subrepo/large.txt
1376 $ echo "rev 1" > subrepo/large.txt
1377 $ hg -R subrepo add --large subrepo/large.txt
1377 $ hg -R subrepo add --large subrepo/large.txt
1378 $ hg sum
1378 $ hg sum
1379 parent: 1:8ee150ea2e9c tip
1379 parent: 1:8ee150ea2e9c tip
1380 add subrepo
1380 add subrepo
1381 branch: default
1381 branch: default
1382 commit: 1 subrepos
1382 commit: 1 subrepos
1383 update: (current)
1383 update: (current)
1384 $ hg st
1384 $ hg st
1385 $ hg st -S
1385 $ hg st -S
1386 A subrepo/large.txt
1386 A subrepo/large.txt
1387 $ hg ci -S -m "commit top repo"
1387 $ hg ci -S -m "commit top repo"
1388 committing subrepository subrepo
1388 committing subrepository subrepo
1389 Invoking status precommit hook
1389 Invoking status precommit hook
1390 A large.txt
1390 A large.txt
1391 Invoking status precommit hook
1391 Invoking status precommit hook
1392 M .hgsubstate
1392 M .hgsubstate
1393 # No differences
1393 # No differences
1394 $ hg st -S
1394 $ hg st -S
1395 $ hg sum
1395 $ hg sum
1396 parent: 2:ce4cd0c527a6 tip
1396 parent: 2:ce4cd0c527a6 tip
1397 commit top repo
1397 commit top repo
1398 branch: default
1398 branch: default
1399 commit: (clean)
1399 commit: (clean)
1400 update: (current)
1400 update: (current)
1401 $ echo "rev 2" > subrepo/large.txt
1401 $ echo "rev 2" > subrepo/large.txt
1402 $ hg st -S
1402 $ hg st -S
1403 M subrepo/large.txt
1403 M subrepo/large.txt
1404 $ hg sum
1404 $ hg sum
1405 parent: 2:ce4cd0c527a6 tip
1405 parent: 2:ce4cd0c527a6 tip
1406 commit top repo
1406 commit top repo
1407 branch: default
1407 branch: default
1408 commit: 1 subrepos
1408 commit: 1 subrepos
1409 update: (current)
1409 update: (current)
1410 $ hg ci -m "this commit should fail without -S"
1410 $ hg ci -m "this commit should fail without -S"
1411 abort: uncommitted changes in subrepo subrepo
1411 abort: uncommitted changes in subrepo subrepo
1412 (use --subrepos for recursive commit)
1412 (use --subrepos for recursive commit)
1413 [255]
1413 [255]
1414
1414
1415 Add a normal file to the subrepo, then test archiving
1415 Add a normal file to the subrepo, then test archiving
1416
1416
1417 $ echo 'normal file' > subrepo/normal.txt
1417 $ echo 'normal file' > subrepo/normal.txt
1418 $ hg -R subrepo add subrepo/normal.txt
1418 $ hg -R subrepo add subrepo/normal.txt
1419
1419
1420 Lock in subrepo, otherwise the change isn't archived
1420 Lock in subrepo, otherwise the change isn't archived
1421
1421
1422 $ hg ci -S -m "add normal file to top level"
1422 $ hg ci -S -m "add normal file to top level"
1423 committing subrepository subrepo
1423 committing subrepository subrepo
1424 Invoking status precommit hook
1424 Invoking status precommit hook
1425 M large.txt
1425 M large.txt
1426 A normal.txt
1426 A normal.txt
1427 Invoking status precommit hook
1427 Invoking status precommit hook
1428 M .hgsubstate
1428 M .hgsubstate
1429 $ hg archive -S lf_subrepo_archive
1429 $ hg archive -S lf_subrepo_archive
1430 $ find lf_subrepo_archive | sort
1430 $ find lf_subrepo_archive | sort
1431 lf_subrepo_archive
1431 lf_subrepo_archive
1432 lf_subrepo_archive/.hg_archival.txt
1432 lf_subrepo_archive/.hg_archival.txt
1433 lf_subrepo_archive/.hgsub
1433 lf_subrepo_archive/.hgsub
1434 lf_subrepo_archive/.hgsubstate
1434 lf_subrepo_archive/.hgsubstate
1435 lf_subrepo_archive/a
1435 lf_subrepo_archive/a
1436 lf_subrepo_archive/a/b
1436 lf_subrepo_archive/a/b
1437 lf_subrepo_archive/a/b/c
1437 lf_subrepo_archive/a/b/c
1438 lf_subrepo_archive/a/b/c/d
1438 lf_subrepo_archive/a/b/c/d
1439 lf_subrepo_archive/a/b/c/d/e.large.txt
1439 lf_subrepo_archive/a/b/c/d/e.large.txt
1440 lf_subrepo_archive/a/b/c/d/e.normal.txt
1440 lf_subrepo_archive/a/b/c/d/e.normal.txt
1441 lf_subrepo_archive/a/b/c/x
1441 lf_subrepo_archive/a/b/c/x
1442 lf_subrepo_archive/a/b/c/x/y.normal.txt
1442 lf_subrepo_archive/a/b/c/x/y.normal.txt
1443 lf_subrepo_archive/subrepo
1443 lf_subrepo_archive/subrepo
1444 lf_subrepo_archive/subrepo/large.txt
1444 lf_subrepo_archive/subrepo/large.txt
1445 lf_subrepo_archive/subrepo/normal.txt
1445 lf_subrepo_archive/subrepo/normal.txt
1446
1446
1447 $ cd ..
1447 $ cd ..
General Comments 0
You need to be logged in to leave comments. Login now