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