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