##// END OF EJS Templates
largefiles: fix revert on missing largefile (issue3217)
Na'Tosha Bard -
r15983:32b9aee3 stable
parent child Browse files
Show More
@@ -1,962 +1,964 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 override_match(ctx, pats=[], opts={}, globbed=False,
29 def override_match(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 orig_matchfn = m.matchfn
37 orig_matchfn = m.matchfn
38 m.matchfn = lambda f: notlfile(f) and orig_matchfn(f) or None
38 m.matchfn = lambda f: notlfile(f) and orig_matchfn(f) or None
39 return m
39 return m
40 oldmatch = installmatchfn(override_match)
40 oldmatch = installmatchfn(override_match)
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 add_largefiles(ui, repo, *pats, **opts):
56 def add_largefiles(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.repo_add(repo, standins)
112 for f in lfutil.repo_add(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 remove_largefiles(ui, repo, *pats, **opts):
118 def remove_largefiles(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.repo_forget(repo, forget)
167 lfutil.repo_forget(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.repo_remove(repo, remove, unlink=True)
171 lfutil.repo_remove(repo, remove, unlink=True)
172 finally:
172 finally:
173 wlock.release()
173 wlock.release()
174
174
175 # -- Wrappers: modify existing commands --------------------------------
175 # -- Wrappers: modify existing commands --------------------------------
176
176
177 # Add works by going through the files that the user wanted to add and
177 # Add works by going through the files that the user wanted to add and
178 # checking if they should be added as largefiles. Then it makes a new
178 # checking if they should be added as largefiles. Then it makes a new
179 # matcher which matches only the normal files and runs the original
179 # matcher which matches only the normal files and runs the original
180 # version of add.
180 # version of add.
181 def override_add(orig, ui, repo, *pats, **opts):
181 def override_add(orig, ui, repo, *pats, **opts):
182 normal = opts.pop('normal')
182 normal = opts.pop('normal')
183 if normal:
183 if normal:
184 if opts.get('large'):
184 if opts.get('large'):
185 raise util.Abort(_('--normal cannot be used with --large'))
185 raise util.Abort(_('--normal cannot be used with --large'))
186 return orig(ui, repo, *pats, **opts)
186 return orig(ui, repo, *pats, **opts)
187 bad = add_largefiles(ui, repo, *pats, **opts)
187 bad = add_largefiles(ui, repo, *pats, **opts)
188 installnormalfilesmatchfn(repo[None].manifest())
188 installnormalfilesmatchfn(repo[None].manifest())
189 result = orig(ui, repo, *pats, **opts)
189 result = orig(ui, repo, *pats, **opts)
190 restorematchfn()
190 restorematchfn()
191
191
192 return (result == 1 or bad) and 1 or 0
192 return (result == 1 or bad) and 1 or 0
193
193
194 def override_remove(orig, ui, repo, *pats, **opts):
194 def override_remove(orig, ui, repo, *pats, **opts):
195 installnormalfilesmatchfn(repo[None].manifest())
195 installnormalfilesmatchfn(repo[None].manifest())
196 orig(ui, repo, *pats, **opts)
196 orig(ui, repo, *pats, **opts)
197 restorematchfn()
197 restorematchfn()
198 remove_largefiles(ui, repo, *pats, **opts)
198 remove_largefiles(ui, repo, *pats, **opts)
199
199
200 def override_status(orig, ui, repo, *pats, **opts):
200 def override_status(orig, ui, repo, *pats, **opts):
201 try:
201 try:
202 repo.lfstatus = True
202 repo.lfstatus = True
203 return orig(ui, repo, *pats, **opts)
203 return orig(ui, repo, *pats, **opts)
204 finally:
204 finally:
205 repo.lfstatus = False
205 repo.lfstatus = False
206
206
207 def override_log(orig, ui, repo, *pats, **opts):
207 def override_log(orig, ui, repo, *pats, **opts):
208 try:
208 try:
209 repo.lfstatus = True
209 repo.lfstatus = True
210 orig(ui, repo, *pats, **opts)
210 orig(ui, repo, *pats, **opts)
211 finally:
211 finally:
212 repo.lfstatus = False
212 repo.lfstatus = False
213
213
214 def override_verify(orig, ui, repo, *pats, **opts):
214 def override_verify(orig, ui, repo, *pats, **opts):
215 large = opts.pop('large', False)
215 large = opts.pop('large', False)
216 all = opts.pop('lfa', False)
216 all = opts.pop('lfa', False)
217 contents = opts.pop('lfc', False)
217 contents = opts.pop('lfc', False)
218
218
219 result = orig(ui, repo, *pats, **opts)
219 result = orig(ui, repo, *pats, **opts)
220 if large:
220 if large:
221 result = result or lfcommands.verifylfiles(ui, repo, all, contents)
221 result = result or lfcommands.verifylfiles(ui, repo, all, contents)
222 return result
222 return result
223
223
224 # Override needs to refresh standins so that update's normal merge
224 # Override needs to refresh standins so that update's normal merge
225 # will go through properly. Then the other update hook (overriding repo.update)
225 # will go through properly. Then the other update hook (overriding repo.update)
226 # will get the new files. Filemerge is also overriden so that the merge
226 # will get the new files. Filemerge is also overriden so that the merge
227 # will merge standins correctly.
227 # will merge standins correctly.
228 def override_update(orig, ui, repo, *pats, **opts):
228 def override_update(orig, ui, repo, *pats, **opts):
229 lfdirstate = lfutil.openlfdirstate(ui, repo)
229 lfdirstate = lfutil.openlfdirstate(ui, repo)
230 s = lfdirstate.status(match_.always(repo.root, repo.getcwd()), [], False,
230 s = lfdirstate.status(match_.always(repo.root, repo.getcwd()), [], False,
231 False, False)
231 False, False)
232 (unsure, modified, added, removed, missing, unknown, ignored, clean) = s
232 (unsure, modified, added, removed, missing, unknown, ignored, clean) = s
233
233
234 # Need to lock between the standins getting updated and their
234 # Need to lock between the standins getting updated and their
235 # largefiles getting updated
235 # largefiles getting updated
236 wlock = repo.wlock()
236 wlock = repo.wlock()
237 try:
237 try:
238 if opts['check']:
238 if opts['check']:
239 mod = len(modified) > 0
239 mod = len(modified) > 0
240 for lfile in unsure:
240 for lfile in unsure:
241 standin = lfutil.standin(lfile)
241 standin = lfutil.standin(lfile)
242 if repo['.'][standin].data().strip() != \
242 if repo['.'][standin].data().strip() != \
243 lfutil.hashfile(repo.wjoin(lfile)):
243 lfutil.hashfile(repo.wjoin(lfile)):
244 mod = True
244 mod = True
245 else:
245 else:
246 lfdirstate.normal(lfile)
246 lfdirstate.normal(lfile)
247 lfdirstate.write()
247 lfdirstate.write()
248 if mod:
248 if mod:
249 raise util.Abort(_('uncommitted local changes'))
249 raise util.Abort(_('uncommitted local changes'))
250 # XXX handle removed differently
250 # XXX handle removed differently
251 if not opts['clean']:
251 if not opts['clean']:
252 for lfile in unsure + modified + added:
252 for lfile in unsure + modified + added:
253 lfutil.updatestandin(repo, lfutil.standin(lfile))
253 lfutil.updatestandin(repo, lfutil.standin(lfile))
254 finally:
254 finally:
255 wlock.release()
255 wlock.release()
256 return orig(ui, repo, *pats, **opts)
256 return orig(ui, repo, *pats, **opts)
257
257
258 # Before starting the manifest merge, merge.updates will call
258 # Before starting the manifest merge, merge.updates will call
259 # _checkunknown to check if there are any files in the merged-in
259 # _checkunknown to check if there are any files in the merged-in
260 # changeset that collide with unknown files in the working copy.
260 # changeset that collide with unknown files in the working copy.
261 #
261 #
262 # The largefiles are seen as unknown, so this prevents us from merging
262 # The largefiles are seen as unknown, so this prevents us from merging
263 # in a file 'foo' if we already have a largefile with the same name.
263 # in a file 'foo' if we already have a largefile with the same name.
264 #
264 #
265 # The overridden function filters the unknown files by removing any
265 # The overridden function filters the unknown files by removing any
266 # largefiles. This makes the merge proceed and we can then handle this
266 # largefiles. This makes the merge proceed and we can then handle this
267 # case further in the overridden manifestmerge function below.
267 # case further in the overridden manifestmerge function below.
268 def override_checkunknown(origfn, wctx, mctx, folding):
268 def override_checkunknown(origfn, wctx, mctx, folding):
269 origunknown = wctx.unknown()
269 origunknown = wctx.unknown()
270 wctx._unknown = filter(lambda f: lfutil.standin(f) not in wctx, origunknown)
270 wctx._unknown = filter(lambda f: lfutil.standin(f) not in wctx, origunknown)
271 try:
271 try:
272 return origfn(wctx, mctx, folding)
272 return origfn(wctx, mctx, folding)
273 finally:
273 finally:
274 wctx._unknown = origunknown
274 wctx._unknown = origunknown
275
275
276 # The manifest merge handles conflicts on the manifest level. We want
276 # The manifest merge handles conflicts on the manifest level. We want
277 # to handle changes in largefile-ness of files at this level too.
277 # to handle changes in largefile-ness of files at this level too.
278 #
278 #
279 # The strategy is to run the original manifestmerge and then process
279 # The strategy is to run the original manifestmerge and then process
280 # the action list it outputs. There are two cases we need to deal with:
280 # the action list it outputs. There are two cases we need to deal with:
281 #
281 #
282 # 1. Normal file in p1, largefile in p2. Here the largefile is
282 # 1. Normal file in p1, largefile in p2. Here the largefile is
283 # detected via its standin file, which will enter the working copy
283 # detected via its standin file, which will enter the working copy
284 # with a "get" action. It is not "merge" since the standin is all
284 # with a "get" action. It is not "merge" since the standin is all
285 # Mercurial is concerned with at this level -- the link to the
285 # Mercurial is concerned with at this level -- the link to the
286 # existing normal file is not relevant here.
286 # existing normal file is not relevant here.
287 #
287 #
288 # 2. Largefile in p1, normal file in p2. Here we get a "merge" action
288 # 2. Largefile in p1, normal file in p2. Here we get a "merge" action
289 # since the largefile will be present in the working copy and
289 # since the largefile will be present in the working copy and
290 # different from the normal file in p2. Mercurial therefore
290 # different from the normal file in p2. Mercurial therefore
291 # triggers a merge action.
291 # triggers a merge action.
292 #
292 #
293 # In both cases, we prompt the user and emit new actions to either
293 # In both cases, we prompt the user and emit new actions to either
294 # remove the standin (if the normal file was kept) or to remove the
294 # remove the standin (if the normal file was kept) or to remove the
295 # normal file and get the standin (if the largefile was kept). The
295 # normal file and get the standin (if the largefile was kept). The
296 # default prompt answer is to use the largefile version since it was
296 # default prompt answer is to use the largefile version since it was
297 # presumably changed on purpose.
297 # presumably changed on purpose.
298 #
298 #
299 # Finally, the merge.applyupdates function will then take care of
299 # Finally, the merge.applyupdates function will then take care of
300 # writing the files into the working copy and lfcommands.updatelfiles
300 # writing the files into the working copy and lfcommands.updatelfiles
301 # will update the largefiles.
301 # will update the largefiles.
302 def override_manifestmerge(origfn, repo, p1, p2, pa, overwrite, partial):
302 def override_manifestmerge(origfn, repo, p1, p2, pa, overwrite, partial):
303 actions = origfn(repo, p1, p2, pa, overwrite, partial)
303 actions = origfn(repo, p1, p2, pa, overwrite, partial)
304 processed = []
304 processed = []
305
305
306 for action in actions:
306 for action in actions:
307 if overwrite:
307 if overwrite:
308 processed.append(action)
308 processed.append(action)
309 continue
309 continue
310 f, m = action[:2]
310 f, m = action[:2]
311
311
312 choices = (_('&Largefile'), _('&Normal file'))
312 choices = (_('&Largefile'), _('&Normal file'))
313 if m == "g" and lfutil.splitstandin(f) in p1 and f in p2:
313 if m == "g" and lfutil.splitstandin(f) in p1 and f in p2:
314 # Case 1: normal file in the working copy, largefile in
314 # Case 1: normal file in the working copy, largefile in
315 # the second parent
315 # the second parent
316 lfile = lfutil.splitstandin(f)
316 lfile = lfutil.splitstandin(f)
317 standin = f
317 standin = f
318 msg = _('%s has been turned into a largefile\n'
318 msg = _('%s has been turned into a largefile\n'
319 'use (l)argefile or keep as (n)ormal file?') % lfile
319 'use (l)argefile or keep as (n)ormal file?') % lfile
320 if repo.ui.promptchoice(msg, choices, 0) == 0:
320 if repo.ui.promptchoice(msg, choices, 0) == 0:
321 processed.append((lfile, "r"))
321 processed.append((lfile, "r"))
322 processed.append((standin, "g", p2.flags(standin)))
322 processed.append((standin, "g", p2.flags(standin)))
323 else:
323 else:
324 processed.append((standin, "r"))
324 processed.append((standin, "r"))
325 elif m == "m" and lfutil.standin(f) in p1 and f in p2:
325 elif m == "m" and lfutil.standin(f) in p1 and f in p2:
326 # Case 2: largefile in the working copy, normal file in
326 # Case 2: largefile in the working copy, normal file in
327 # the second parent
327 # the second parent
328 standin = lfutil.standin(f)
328 standin = lfutil.standin(f)
329 lfile = f
329 lfile = f
330 msg = _('%s has been turned into a normal file\n'
330 msg = _('%s has been turned into a normal file\n'
331 'keep as (l)argefile or use (n)ormal file?') % lfile
331 'keep as (l)argefile or use (n)ormal file?') % lfile
332 if repo.ui.promptchoice(msg, choices, 0) == 0:
332 if repo.ui.promptchoice(msg, choices, 0) == 0:
333 processed.append((lfile, "r"))
333 processed.append((lfile, "r"))
334 else:
334 else:
335 processed.append((standin, "r"))
335 processed.append((standin, "r"))
336 processed.append((lfile, "g", p2.flags(lfile)))
336 processed.append((lfile, "g", p2.flags(lfile)))
337 else:
337 else:
338 processed.append(action)
338 processed.append(action)
339
339
340 return processed
340 return processed
341
341
342 # Override filemerge to prompt the user about how they wish to merge
342 # Override filemerge to prompt the user about how they wish to merge
343 # largefiles. This will handle identical edits, and copy/rename +
343 # largefiles. This will handle identical edits, and copy/rename +
344 # edit without prompting the user.
344 # edit without prompting the user.
345 def override_filemerge(origfn, repo, mynode, orig, fcd, fco, fca):
345 def override_filemerge(origfn, repo, mynode, orig, fcd, fco, fca):
346 # Use better variable names here. Because this is a wrapper we cannot
346 # Use better variable names here. Because this is a wrapper we cannot
347 # change the variable names in the function declaration.
347 # change the variable names in the function declaration.
348 fcdest, fcother, fcancestor = fcd, fco, fca
348 fcdest, fcother, fcancestor = fcd, fco, fca
349 if not lfutil.isstandin(orig):
349 if not lfutil.isstandin(orig):
350 return origfn(repo, mynode, orig, fcdest, fcother, fcancestor)
350 return origfn(repo, mynode, orig, fcdest, fcother, fcancestor)
351 else:
351 else:
352 if not fcother.cmp(fcdest): # files identical?
352 if not fcother.cmp(fcdest): # files identical?
353 return None
353 return None
354
354
355 # backwards, use working dir parent as ancestor
355 # backwards, use working dir parent as ancestor
356 if fcancestor == fcother:
356 if fcancestor == fcother:
357 fcancestor = fcdest.parents()[0]
357 fcancestor = fcdest.parents()[0]
358
358
359 if orig != fcother.path():
359 if orig != fcother.path():
360 repo.ui.status(_('merging %s and %s to %s\n')
360 repo.ui.status(_('merging %s and %s to %s\n')
361 % (lfutil.splitstandin(orig),
361 % (lfutil.splitstandin(orig),
362 lfutil.splitstandin(fcother.path()),
362 lfutil.splitstandin(fcother.path()),
363 lfutil.splitstandin(fcdest.path())))
363 lfutil.splitstandin(fcdest.path())))
364 else:
364 else:
365 repo.ui.status(_('merging %s\n')
365 repo.ui.status(_('merging %s\n')
366 % lfutil.splitstandin(fcdest.path()))
366 % lfutil.splitstandin(fcdest.path()))
367
367
368 if fcancestor.path() != fcother.path() and fcother.data() == \
368 if fcancestor.path() != fcother.path() and fcother.data() == \
369 fcancestor.data():
369 fcancestor.data():
370 return 0
370 return 0
371 if fcancestor.path() != fcdest.path() and fcdest.data() == \
371 if fcancestor.path() != fcdest.path() and fcdest.data() == \
372 fcancestor.data():
372 fcancestor.data():
373 repo.wwrite(fcdest.path(), fcother.data(), fcother.flags())
373 repo.wwrite(fcdest.path(), fcother.data(), fcother.flags())
374 return 0
374 return 0
375
375
376 if repo.ui.promptchoice(_('largefile %s has a merge conflict\n'
376 if repo.ui.promptchoice(_('largefile %s has a merge conflict\n'
377 'keep (l)ocal or take (o)ther?') %
377 'keep (l)ocal or take (o)ther?') %
378 lfutil.splitstandin(orig),
378 lfutil.splitstandin(orig),
379 (_('&Local'), _('&Other')), 0) == 0:
379 (_('&Local'), _('&Other')), 0) == 0:
380 return 0
380 return 0
381 else:
381 else:
382 repo.wwrite(fcdest.path(), fcother.data(), fcother.flags())
382 repo.wwrite(fcdest.path(), fcother.data(), fcother.flags())
383 return 0
383 return 0
384
384
385 # Copy first changes the matchers to match standins instead of
385 # Copy first changes the matchers to match standins instead of
386 # largefiles. Then it overrides util.copyfile in that function it
386 # largefiles. Then it overrides util.copyfile in that function it
387 # checks if the destination largefile already exists. It also keeps a
387 # checks if the destination largefile already exists. It also keeps a
388 # list of copied files so that the largefiles can be copied and the
388 # list of copied files so that the largefiles can be copied and the
389 # dirstate updated.
389 # dirstate updated.
390 def override_copy(orig, ui, repo, pats, opts, rename=False):
390 def override_copy(orig, ui, repo, pats, opts, rename=False):
391 # doesn't remove largefile on rename
391 # doesn't remove largefile on rename
392 if len(pats) < 2:
392 if len(pats) < 2:
393 # this isn't legal, let the original function deal with it
393 # this isn't legal, let the original function deal with it
394 return orig(ui, repo, pats, opts, rename)
394 return orig(ui, repo, pats, opts, rename)
395
395
396 def makestandin(relpath):
396 def makestandin(relpath):
397 path = scmutil.canonpath(repo.root, repo.getcwd(), relpath)
397 path = scmutil.canonpath(repo.root, repo.getcwd(), relpath)
398 return os.path.join(repo.wjoin(lfutil.standin(path)))
398 return os.path.join(repo.wjoin(lfutil.standin(path)))
399
399
400 fullpats = scmutil.expandpats(pats)
400 fullpats = scmutil.expandpats(pats)
401 dest = fullpats[-1]
401 dest = fullpats[-1]
402
402
403 if os.path.isdir(dest):
403 if os.path.isdir(dest):
404 if not os.path.isdir(makestandin(dest)):
404 if not os.path.isdir(makestandin(dest)):
405 os.makedirs(makestandin(dest))
405 os.makedirs(makestandin(dest))
406 # This could copy both lfiles and normal files in one command,
406 # This could copy both lfiles and normal files in one command,
407 # but we don't want to do that. First replace their matcher to
407 # but we don't want to do that. First replace their matcher to
408 # only match normal files and run it, then replace it to just
408 # only match normal files and run it, then replace it to just
409 # match largefiles and run it again.
409 # match largefiles and run it again.
410 nonormalfiles = False
410 nonormalfiles = False
411 nolfiles = False
411 nolfiles = False
412 try:
412 try:
413 try:
413 try:
414 installnormalfilesmatchfn(repo[None].manifest())
414 installnormalfilesmatchfn(repo[None].manifest())
415 result = orig(ui, repo, pats, opts, rename)
415 result = orig(ui, repo, pats, opts, rename)
416 except util.Abort, e:
416 except util.Abort, e:
417 if str(e) != 'no files to copy':
417 if str(e) != 'no files to copy':
418 raise e
418 raise e
419 else:
419 else:
420 nonormalfiles = True
420 nonormalfiles = True
421 result = 0
421 result = 0
422 finally:
422 finally:
423 restorematchfn()
423 restorematchfn()
424
424
425 # The first rename can cause our current working directory to be removed.
425 # The first rename can cause our current working directory to be removed.
426 # In that case there is nothing left to copy/rename so just quit.
426 # In that case there is nothing left to copy/rename so just quit.
427 try:
427 try:
428 repo.getcwd()
428 repo.getcwd()
429 except OSError:
429 except OSError:
430 return result
430 return result
431
431
432 try:
432 try:
433 try:
433 try:
434 # When we call orig below it creates the standins but we don't add them
434 # When we call orig below it creates the standins but we don't add them
435 # to the dir state until later so lock during that time.
435 # to the dir state until later so lock during that time.
436 wlock = repo.wlock()
436 wlock = repo.wlock()
437
437
438 manifest = repo[None].manifest()
438 manifest = repo[None].manifest()
439 oldmatch = None # for the closure
439 oldmatch = None # for the closure
440 def override_match(ctx, pats=[], opts={}, globbed=False,
440 def override_match(ctx, pats=[], opts={}, globbed=False,
441 default='relpath'):
441 default='relpath'):
442 newpats = []
442 newpats = []
443 # The patterns were previously mangled to add the standin
443 # The patterns were previously mangled to add the standin
444 # directory; we need to remove that now
444 # directory; we need to remove that now
445 for pat in pats:
445 for pat in pats:
446 if match_.patkind(pat) is None and lfutil.shortname in pat:
446 if match_.patkind(pat) is None and lfutil.shortname in pat:
447 newpats.append(pat.replace(lfutil.shortname, ''))
447 newpats.append(pat.replace(lfutil.shortname, ''))
448 else:
448 else:
449 newpats.append(pat)
449 newpats.append(pat)
450 match = oldmatch(ctx, newpats, opts, globbed, default)
450 match = oldmatch(ctx, newpats, opts, globbed, default)
451 m = copy.copy(match)
451 m = copy.copy(match)
452 lfile = lambda f: lfutil.standin(f) in manifest
452 lfile = lambda f: lfutil.standin(f) in manifest
453 m._files = [lfutil.standin(f) for f in m._files if lfile(f)]
453 m._files = [lfutil.standin(f) for f in m._files if lfile(f)]
454 m._fmap = set(m._files)
454 m._fmap = set(m._files)
455 orig_matchfn = m.matchfn
455 orig_matchfn = m.matchfn
456 m.matchfn = lambda f: (lfutil.isstandin(f) and
456 m.matchfn = lambda f: (lfutil.isstandin(f) and
457 lfile(lfutil.splitstandin(f)) and
457 lfile(lfutil.splitstandin(f)) and
458 orig_matchfn(lfutil.splitstandin(f)) or
458 orig_matchfn(lfutil.splitstandin(f)) or
459 None)
459 None)
460 return m
460 return m
461 oldmatch = installmatchfn(override_match)
461 oldmatch = installmatchfn(override_match)
462 listpats = []
462 listpats = []
463 for pat in pats:
463 for pat in pats:
464 if match_.patkind(pat) is not None:
464 if match_.patkind(pat) is not None:
465 listpats.append(pat)
465 listpats.append(pat)
466 else:
466 else:
467 listpats.append(makestandin(pat))
467 listpats.append(makestandin(pat))
468
468
469 try:
469 try:
470 origcopyfile = util.copyfile
470 origcopyfile = util.copyfile
471 copiedfiles = []
471 copiedfiles = []
472 def override_copyfile(src, dest):
472 def override_copyfile(src, dest):
473 if (lfutil.shortname in src and
473 if (lfutil.shortname in src and
474 dest.startswith(repo.wjoin(lfutil.shortname))):
474 dest.startswith(repo.wjoin(lfutil.shortname))):
475 destlfile = dest.replace(lfutil.shortname, '')
475 destlfile = dest.replace(lfutil.shortname, '')
476 if not opts['force'] and os.path.exists(destlfile):
476 if not opts['force'] and os.path.exists(destlfile):
477 raise IOError('',
477 raise IOError('',
478 _('destination largefile already exists'))
478 _('destination largefile already exists'))
479 copiedfiles.append((src, dest))
479 copiedfiles.append((src, dest))
480 origcopyfile(src, dest)
480 origcopyfile(src, dest)
481
481
482 util.copyfile = override_copyfile
482 util.copyfile = override_copyfile
483 result += orig(ui, repo, listpats, opts, rename)
483 result += orig(ui, repo, listpats, opts, rename)
484 finally:
484 finally:
485 util.copyfile = origcopyfile
485 util.copyfile = origcopyfile
486
486
487 lfdirstate = lfutil.openlfdirstate(ui, repo)
487 lfdirstate = lfutil.openlfdirstate(ui, repo)
488 for (src, dest) in copiedfiles:
488 for (src, dest) in copiedfiles:
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 srclfile = src.replace(repo.wjoin(lfutil.standin('')), '')
491 srclfile = src.replace(repo.wjoin(lfutil.standin('')), '')
492 destlfile = dest.replace(repo.wjoin(lfutil.standin('')), '')
492 destlfile = dest.replace(repo.wjoin(lfutil.standin('')), '')
493 destlfiledir = os.path.dirname(destlfile) or '.'
493 destlfiledir = os.path.dirname(destlfile) or '.'
494 if not os.path.isdir(destlfiledir):
494 if not os.path.isdir(destlfiledir):
495 os.makedirs(destlfiledir)
495 os.makedirs(destlfiledir)
496 if rename:
496 if rename:
497 os.rename(repo.wjoin(srclfile), repo.wjoin(destlfile))
497 os.rename(repo.wjoin(srclfile), repo.wjoin(destlfile))
498 lfdirstate.remove(srclfile)
498 lfdirstate.remove(srclfile)
499 else:
499 else:
500 util.copyfile(srclfile, destlfile)
500 util.copyfile(srclfile, destlfile)
501 lfdirstate.add(destlfile)
501 lfdirstate.add(destlfile)
502 lfdirstate.write()
502 lfdirstate.write()
503 except util.Abort, e:
503 except util.Abort, e:
504 if str(e) != 'no files to copy':
504 if str(e) != 'no files to copy':
505 raise e
505 raise e
506 else:
506 else:
507 nolfiles = True
507 nolfiles = True
508 finally:
508 finally:
509 restorematchfn()
509 restorematchfn()
510 wlock.release()
510 wlock.release()
511
511
512 if nolfiles and nonormalfiles:
512 if nolfiles and nonormalfiles:
513 raise util.Abort(_('no files to copy'))
513 raise util.Abort(_('no files to copy'))
514
514
515 return result
515 return result
516
516
517 # When the user calls revert, we have to be careful to not revert any
517 # When the user calls revert, we have to be careful to not revert any
518 # changes to other largefiles accidentally. This means we have to keep
518 # changes to other largefiles accidentally. This means we have to keep
519 # track of the largefiles that are being reverted so we only pull down
519 # track of the largefiles that are being reverted so we only pull down
520 # the necessary largefiles.
520 # the necessary largefiles.
521 #
521 #
522 # Standins are only updated (to match the hash of largefiles) before
522 # Standins are only updated (to match the hash of largefiles) before
523 # commits. Update the standins then run the original revert, changing
523 # commits. Update the standins then run the original revert, changing
524 # the matcher to hit standins instead of largefiles. Based on the
524 # the matcher to hit standins instead of largefiles. Based on the
525 # resulting standins update the largefiles. Then return the standins
525 # resulting standins update the largefiles. Then return the standins
526 # to their proper state
526 # to their proper state
527 def override_revert(orig, ui, repo, *pats, **opts):
527 def override_revert(orig, ui, repo, *pats, **opts):
528 # Because we put the standins in a bad state (by updating them)
528 # Because we put the standins in a bad state (by updating them)
529 # and then return them to a correct state we need to lock to
529 # and then return them to a correct state we need to lock to
530 # prevent others from changing them in their incorrect state.
530 # prevent others from changing them in their incorrect state.
531 wlock = repo.wlock()
531 wlock = repo.wlock()
532 try:
532 try:
533 lfdirstate = lfutil.openlfdirstate(ui, repo)
533 lfdirstate = lfutil.openlfdirstate(ui, repo)
534 (modified, added, removed, missing, unknown, ignored, clean) = \
534 (modified, added, removed, missing, unknown, ignored, clean) = \
535 lfutil.lfdirstate_status(lfdirstate, repo, repo['.'].rev())
535 lfutil.lfdirstate_status(lfdirstate, repo, repo['.'].rev())
536 for lfile in modified:
536 for lfile in modified:
537 lfutil.updatestandin(repo, lfutil.standin(lfile))
537 lfutil.updatestandin(repo, lfutil.standin(lfile))
538 for lfile in missing:
539 os.unlink(repo.wjoin(lfutil.standin(lfile)))
538
540
539 try:
541 try:
540 ctx = repo[opts.get('rev')]
542 ctx = repo[opts.get('rev')]
541 oldmatch = None # for the closure
543 oldmatch = None # for the closure
542 def override_match(ctx, pats=[], opts={}, globbed=False,
544 def override_match(ctx, pats=[], opts={}, globbed=False,
543 default='relpath'):
545 default='relpath'):
544 match = oldmatch(ctx, pats, opts, globbed, default)
546 match = oldmatch(ctx, pats, opts, globbed, default)
545 m = copy.copy(match)
547 m = copy.copy(match)
546 def tostandin(f):
548 def tostandin(f):
547 if lfutil.standin(f) in ctx or lfutil.standin(f) in ctx:
549 if lfutil.standin(f) in ctx or lfutil.standin(f) in ctx:
548 return lfutil.standin(f)
550 return lfutil.standin(f)
549 elif lfutil.standin(f) in repo[None]:
551 elif lfutil.standin(f) in repo[None]:
550 return None
552 return None
551 return f
553 return f
552 m._files = [tostandin(f) for f in m._files]
554 m._files = [tostandin(f) for f in m._files]
553 m._files = [f for f in m._files if f is not None]
555 m._files = [f for f in m._files if f is not None]
554 m._fmap = set(m._files)
556 m._fmap = set(m._files)
555 orig_matchfn = m.matchfn
557 orig_matchfn = m.matchfn
556 def matchfn(f):
558 def matchfn(f):
557 if lfutil.isstandin(f):
559 if lfutil.isstandin(f):
558 # We need to keep track of what largefiles are being
560 # We need to keep track of what largefiles are being
559 # matched so we know which ones to update later --
561 # matched so we know which ones to update later --
560 # otherwise we accidentally revert changes to other
562 # otherwise we accidentally revert changes to other
561 # largefiles. This is repo-specific, so duckpunch the
563 # largefiles. This is repo-specific, so duckpunch the
562 # repo object to keep the list of largefiles for us
564 # repo object to keep the list of largefiles for us
563 # later.
565 # later.
564 if orig_matchfn(lfutil.splitstandin(f)) and \
566 if orig_matchfn(lfutil.splitstandin(f)) and \
565 (f in repo[None] or f in ctx):
567 (f in repo[None] or f in ctx):
566 lfileslist = getattr(repo, '_lfilestoupdate', [])
568 lfileslist = getattr(repo, '_lfilestoupdate', [])
567 lfileslist.append(lfutil.splitstandin(f))
569 lfileslist.append(lfutil.splitstandin(f))
568 repo._lfilestoupdate = lfileslist
570 repo._lfilestoupdate = lfileslist
569 return True
571 return True
570 else:
572 else:
571 return False
573 return False
572 return orig_matchfn(f)
574 return orig_matchfn(f)
573 m.matchfn = matchfn
575 m.matchfn = matchfn
574 return m
576 return m
575 oldmatch = installmatchfn(override_match)
577 oldmatch = installmatchfn(override_match)
576 scmutil.match
578 scmutil.match
577 matches = override_match(repo[None], pats, opts)
579 matches = override_match(repo[None], pats, opts)
578 orig(ui, repo, *pats, **opts)
580 orig(ui, repo, *pats, **opts)
579 finally:
581 finally:
580 restorematchfn()
582 restorematchfn()
581 lfileslist = getattr(repo, '_lfilestoupdate', [])
583 lfileslist = getattr(repo, '_lfilestoupdate', [])
582 lfcommands.updatelfiles(ui, repo, filelist=lfileslist,
584 lfcommands.updatelfiles(ui, repo, filelist=lfileslist,
583 printmessage=False)
585 printmessage=False)
584
586
585 # empty out the largefiles list so we start fresh next time
587 # empty out the largefiles list so we start fresh next time
586 repo._lfilestoupdate = []
588 repo._lfilestoupdate = []
587 for lfile in modified:
589 for lfile in modified:
588 if lfile in lfileslist:
590 if lfile in lfileslist:
589 if os.path.exists(repo.wjoin(lfutil.standin(lfile))) and lfile\
591 if os.path.exists(repo.wjoin(lfutil.standin(lfile))) and lfile\
590 in repo['.']:
592 in repo['.']:
591 lfutil.writestandin(repo, lfutil.standin(lfile),
593 lfutil.writestandin(repo, lfutil.standin(lfile),
592 repo['.'][lfile].data().strip(),
594 repo['.'][lfile].data().strip(),
593 'x' in repo['.'][lfile].flags())
595 'x' in repo['.'][lfile].flags())
594 lfdirstate = lfutil.openlfdirstate(ui, repo)
596 lfdirstate = lfutil.openlfdirstate(ui, repo)
595 for lfile in added:
597 for lfile in added:
596 standin = lfutil.standin(lfile)
598 standin = lfutil.standin(lfile)
597 if standin not in ctx and (standin in matches or opts.get('all')):
599 if standin not in ctx and (standin in matches or opts.get('all')):
598 if lfile in lfdirstate:
600 if lfile in lfdirstate:
599 lfdirstate.drop(lfile)
601 lfdirstate.drop(lfile)
600 util.unlinkpath(repo.wjoin(standin))
602 util.unlinkpath(repo.wjoin(standin))
601 lfdirstate.write()
603 lfdirstate.write()
602 finally:
604 finally:
603 wlock.release()
605 wlock.release()
604
606
605 def hg_update(orig, repo, node):
607 def hg_update(orig, repo, node):
606 result = orig(repo, node)
608 result = orig(repo, node)
607 lfcommands.updatelfiles(repo.ui, repo)
609 lfcommands.updatelfiles(repo.ui, repo)
608 return result
610 return result
609
611
610 def hg_clean(orig, repo, node, show_stats=True):
612 def hg_clean(orig, repo, node, show_stats=True):
611 result = orig(repo, node, show_stats)
613 result = orig(repo, node, show_stats)
612 lfcommands.updatelfiles(repo.ui, repo)
614 lfcommands.updatelfiles(repo.ui, repo)
613 return result
615 return result
614
616
615 def hg_merge(orig, repo, node, force=None, remind=True):
617 def hg_merge(orig, repo, node, force=None, remind=True):
616 # Mark the repo as being in the middle of a merge, so that
618 # Mark the repo as being in the middle of a merge, so that
617 # updatelfiles() will know that it needs to trust the standins in
619 # updatelfiles() will know that it needs to trust the standins in
618 # the working copy, not in the standins in the current node
620 # the working copy, not in the standins in the current node
619 repo._ismerging = True
621 repo._ismerging = True
620 try:
622 try:
621 result = orig(repo, node, force, remind)
623 result = orig(repo, node, force, remind)
622 lfcommands.updatelfiles(repo.ui, repo)
624 lfcommands.updatelfiles(repo.ui, repo)
623 finally:
625 finally:
624 repo._ismerging = False
626 repo._ismerging = False
625 return result
627 return result
626
628
627 # When we rebase a repository with remotely changed largefiles, we need to
629 # When we rebase a repository with remotely changed largefiles, we need to
628 # take some extra care so that the largefiles are correctly updated in the
630 # take some extra care so that the largefiles are correctly updated in the
629 # working copy
631 # working copy
630 def override_pull(orig, ui, repo, source=None, **opts):
632 def override_pull(orig, ui, repo, source=None, **opts):
631 if opts.get('rebase', False):
633 if opts.get('rebase', False):
632 repo._isrebasing = True
634 repo._isrebasing = True
633 try:
635 try:
634 if opts.get('update'):
636 if opts.get('update'):
635 del opts['update']
637 del opts['update']
636 ui.debug('--update and --rebase are not compatible, ignoring '
638 ui.debug('--update and --rebase are not compatible, ignoring '
637 'the update flag\n')
639 'the update flag\n')
638 del opts['rebase']
640 del opts['rebase']
639 cmdutil.bailifchanged(repo)
641 cmdutil.bailifchanged(repo)
640 revsprepull = len(repo)
642 revsprepull = len(repo)
641 origpostincoming = commands.postincoming
643 origpostincoming = commands.postincoming
642 def _dummy(*args, **kwargs):
644 def _dummy(*args, **kwargs):
643 pass
645 pass
644 commands.postincoming = _dummy
646 commands.postincoming = _dummy
645 repo.lfpullsource = source
647 repo.lfpullsource = source
646 if not source:
648 if not source:
647 source = 'default'
649 source = 'default'
648 try:
650 try:
649 result = commands.pull(ui, repo, source, **opts)
651 result = commands.pull(ui, repo, source, **opts)
650 finally:
652 finally:
651 commands.postincoming = origpostincoming
653 commands.postincoming = origpostincoming
652 revspostpull = len(repo)
654 revspostpull = len(repo)
653 if revspostpull > revsprepull:
655 if revspostpull > revsprepull:
654 result = result or rebase.rebase(ui, repo)
656 result = result or rebase.rebase(ui, repo)
655 finally:
657 finally:
656 repo._isrebasing = False
658 repo._isrebasing = False
657 else:
659 else:
658 repo.lfpullsource = source
660 repo.lfpullsource = source
659 if not source:
661 if not source:
660 source = 'default'
662 source = 'default'
661 result = orig(ui, repo, source, **opts)
663 result = orig(ui, repo, source, **opts)
662 # If we do not have the new largefiles for any new heads we pulled, we
664 # If we do not have the new largefiles for any new heads we pulled, we
663 # will run into a problem later if we try to merge or rebase with one of
665 # will run into a problem later if we try to merge or rebase with one of
664 # these heads, so cache the largefiles now direclty into the system
666 # these heads, so cache the largefiles now direclty into the system
665 # cache.
667 # cache.
666 ui.status(_("caching new largefiles\n"))
668 ui.status(_("caching new largefiles\n"))
667 numcached = 0
669 numcached = 0
668 branches = repo.branchmap()
670 branches = repo.branchmap()
669 for branch in branches:
671 for branch in branches:
670 heads = repo.branchheads(branch)
672 heads = repo.branchheads(branch)
671 for head in heads:
673 for head in heads:
672 (cached, missing) = lfcommands.cachelfiles(ui, repo, head)
674 (cached, missing) = lfcommands.cachelfiles(ui, repo, head)
673 numcached += len(cached)
675 numcached += len(cached)
674 ui.status(_("%d largefiles cached\n" % numcached))
676 ui.status(_("%d largefiles cached\n" % numcached))
675 return result
677 return result
676
678
677 def override_rebase(orig, ui, repo, **opts):
679 def override_rebase(orig, ui, repo, **opts):
678 repo._isrebasing = True
680 repo._isrebasing = True
679 try:
681 try:
680 orig(ui, repo, **opts)
682 orig(ui, repo, **opts)
681 finally:
683 finally:
682 repo._isrebasing = False
684 repo._isrebasing = False
683
685
684 def override_archive(orig, repo, dest, node, kind, decode=True, matchfn=None,
686 def override_archive(orig, repo, dest, node, kind, decode=True, matchfn=None,
685 prefix=None, mtime=None, subrepos=None):
687 prefix=None, mtime=None, subrepos=None):
686 # No need to lock because we are only reading history and
688 # No need to lock because we are only reading history and
687 # largefile caches, neither of which are modified.
689 # largefile caches, neither of which are modified.
688 lfcommands.cachelfiles(repo.ui, repo, node)
690 lfcommands.cachelfiles(repo.ui, repo, node)
689
691
690 if kind not in archival.archivers:
692 if kind not in archival.archivers:
691 raise util.Abort(_("unknown archive type '%s'") % kind)
693 raise util.Abort(_("unknown archive type '%s'") % kind)
692
694
693 ctx = repo[node]
695 ctx = repo[node]
694
696
695 if kind == 'files':
697 if kind == 'files':
696 if prefix:
698 if prefix:
697 raise util.Abort(
699 raise util.Abort(
698 _('cannot give prefix when archiving to files'))
700 _('cannot give prefix when archiving to files'))
699 else:
701 else:
700 prefix = archival.tidyprefix(dest, kind, prefix)
702 prefix = archival.tidyprefix(dest, kind, prefix)
701
703
702 def write(name, mode, islink, getdata):
704 def write(name, mode, islink, getdata):
703 if matchfn and not matchfn(name):
705 if matchfn and not matchfn(name):
704 return
706 return
705 data = getdata()
707 data = getdata()
706 if decode:
708 if decode:
707 data = repo.wwritedata(name, data)
709 data = repo.wwritedata(name, data)
708 archiver.addfile(prefix + name, mode, islink, data)
710 archiver.addfile(prefix + name, mode, islink, data)
709
711
710 archiver = archival.archivers[kind](dest, mtime or ctx.date()[0])
712 archiver = archival.archivers[kind](dest, mtime or ctx.date()[0])
711
713
712 if repo.ui.configbool("ui", "archivemeta", True):
714 if repo.ui.configbool("ui", "archivemeta", True):
713 def metadata():
715 def metadata():
714 base = 'repo: %s\nnode: %s\nbranch: %s\n' % (
716 base = 'repo: %s\nnode: %s\nbranch: %s\n' % (
715 hex(repo.changelog.node(0)), hex(node), ctx.branch())
717 hex(repo.changelog.node(0)), hex(node), ctx.branch())
716
718
717 tags = ''.join('tag: %s\n' % t for t in ctx.tags()
719 tags = ''.join('tag: %s\n' % t for t in ctx.tags()
718 if repo.tagtype(t) == 'global')
720 if repo.tagtype(t) == 'global')
719 if not tags:
721 if not tags:
720 repo.ui.pushbuffer()
722 repo.ui.pushbuffer()
721 opts = {'template': '{latesttag}\n{latesttagdistance}',
723 opts = {'template': '{latesttag}\n{latesttagdistance}',
722 'style': '', 'patch': None, 'git': None}
724 'style': '', 'patch': None, 'git': None}
723 cmdutil.show_changeset(repo.ui, repo, opts).show(ctx)
725 cmdutil.show_changeset(repo.ui, repo, opts).show(ctx)
724 ltags, dist = repo.ui.popbuffer().split('\n')
726 ltags, dist = repo.ui.popbuffer().split('\n')
725 tags = ''.join('latesttag: %s\n' % t for t in ltags.split(':'))
727 tags = ''.join('latesttag: %s\n' % t for t in ltags.split(':'))
726 tags += 'latesttagdistance: %s\n' % dist
728 tags += 'latesttagdistance: %s\n' % dist
727
729
728 return base + tags
730 return base + tags
729
731
730 write('.hg_archival.txt', 0644, False, metadata)
732 write('.hg_archival.txt', 0644, False, metadata)
731
733
732 for f in ctx:
734 for f in ctx:
733 ff = ctx.flags(f)
735 ff = ctx.flags(f)
734 getdata = ctx[f].data
736 getdata = ctx[f].data
735 if lfutil.isstandin(f):
737 if lfutil.isstandin(f):
736 path = lfutil.findfile(repo, getdata().strip())
738 path = lfutil.findfile(repo, getdata().strip())
737 if path is None:
739 if path is None:
738 raise util.Abort(
740 raise util.Abort(
739 _('largefile %s not found in repo store or system cache')
741 _('largefile %s not found in repo store or system cache')
740 % lfutil.splitstandin(f))
742 % lfutil.splitstandin(f))
741 f = lfutil.splitstandin(f)
743 f = lfutil.splitstandin(f)
742
744
743 def getdatafn():
745 def getdatafn():
744 fd = None
746 fd = None
745 try:
747 try:
746 fd = open(path, 'rb')
748 fd = open(path, 'rb')
747 return fd.read()
749 return fd.read()
748 finally:
750 finally:
749 if fd:
751 if fd:
750 fd.close()
752 fd.close()
751
753
752 getdata = getdatafn
754 getdata = getdatafn
753 write(f, 'x' in ff and 0755 or 0644, 'l' in ff, getdata)
755 write(f, 'x' in ff and 0755 or 0644, 'l' in ff, getdata)
754
756
755 if subrepos:
757 if subrepos:
756 for subpath in ctx.substate:
758 for subpath in ctx.substate:
757 sub = ctx.sub(subpath)
759 sub = ctx.sub(subpath)
758 sub.archive(repo.ui, archiver, prefix)
760 sub.archive(repo.ui, archiver, prefix)
759
761
760 archiver.done()
762 archiver.done()
761
763
762 # If a largefile is modified, the change is not reflected in its
764 # If a largefile is modified, the change is not reflected in its
763 # standin until a commit. cmdutil.bailifchanged() raises an exception
765 # standin until a commit. cmdutil.bailifchanged() raises an exception
764 # if the repo has uncommitted changes. Wrap it to also check if
766 # if the repo has uncommitted changes. Wrap it to also check if
765 # largefiles were changed. This is used by bisect and backout.
767 # largefiles were changed. This is used by bisect and backout.
766 def override_bailifchanged(orig, repo):
768 def override_bailifchanged(orig, repo):
767 orig(repo)
769 orig(repo)
768 repo.lfstatus = True
770 repo.lfstatus = True
769 modified, added, removed, deleted = repo.status()[:4]
771 modified, added, removed, deleted = repo.status()[:4]
770 repo.lfstatus = False
772 repo.lfstatus = False
771 if modified or added or removed or deleted:
773 if modified or added or removed or deleted:
772 raise util.Abort(_('outstanding uncommitted changes'))
774 raise util.Abort(_('outstanding uncommitted changes'))
773
775
774 # Fetch doesn't use cmdutil.bail_if_changed so override it to add the check
776 # Fetch doesn't use cmdutil.bail_if_changed so override it to add the check
775 def override_fetch(orig, ui, repo, *pats, **opts):
777 def override_fetch(orig, ui, repo, *pats, **opts):
776 repo.lfstatus = True
778 repo.lfstatus = True
777 modified, added, removed, deleted = repo.status()[:4]
779 modified, added, removed, deleted = repo.status()[:4]
778 repo.lfstatus = False
780 repo.lfstatus = False
779 if modified or added or removed or deleted:
781 if modified or added or removed or deleted:
780 raise util.Abort(_('outstanding uncommitted changes'))
782 raise util.Abort(_('outstanding uncommitted changes'))
781 return orig(ui, repo, *pats, **opts)
783 return orig(ui, repo, *pats, **opts)
782
784
783 def override_forget(orig, ui, repo, *pats, **opts):
785 def override_forget(orig, ui, repo, *pats, **opts):
784 installnormalfilesmatchfn(repo[None].manifest())
786 installnormalfilesmatchfn(repo[None].manifest())
785 orig(ui, repo, *pats, **opts)
787 orig(ui, repo, *pats, **opts)
786 restorematchfn()
788 restorematchfn()
787 m = scmutil.match(repo[None], pats, opts)
789 m = scmutil.match(repo[None], pats, opts)
788
790
789 try:
791 try:
790 repo.lfstatus = True
792 repo.lfstatus = True
791 s = repo.status(match=m, clean=True)
793 s = repo.status(match=m, clean=True)
792 finally:
794 finally:
793 repo.lfstatus = False
795 repo.lfstatus = False
794 forget = sorted(s[0] + s[1] + s[3] + s[6])
796 forget = sorted(s[0] + s[1] + s[3] + s[6])
795 forget = [f for f in forget if lfutil.standin(f) in repo[None].manifest()]
797 forget = [f for f in forget if lfutil.standin(f) in repo[None].manifest()]
796
798
797 for f in forget:
799 for f in forget:
798 if lfutil.standin(f) not in repo.dirstate and not \
800 if lfutil.standin(f) not in repo.dirstate and not \
799 os.path.isdir(m.rel(lfutil.standin(f))):
801 os.path.isdir(m.rel(lfutil.standin(f))):
800 ui.warn(_('not removing %s: file is already untracked\n')
802 ui.warn(_('not removing %s: file is already untracked\n')
801 % m.rel(f))
803 % m.rel(f))
802
804
803 for f in forget:
805 for f in forget:
804 if ui.verbose or not m.exact(f):
806 if ui.verbose or not m.exact(f):
805 ui.status(_('removing %s\n') % m.rel(f))
807 ui.status(_('removing %s\n') % m.rel(f))
806
808
807 # Need to lock because standin files are deleted then removed from the
809 # Need to lock because standin files are deleted then removed from the
808 # repository and we could race inbetween.
810 # repository and we could race inbetween.
809 wlock = repo.wlock()
811 wlock = repo.wlock()
810 try:
812 try:
811 lfdirstate = lfutil.openlfdirstate(ui, repo)
813 lfdirstate = lfutil.openlfdirstate(ui, repo)
812 for f in forget:
814 for f in forget:
813 if lfdirstate[f] == 'a':
815 if lfdirstate[f] == 'a':
814 lfdirstate.drop(f)
816 lfdirstate.drop(f)
815 else:
817 else:
816 lfdirstate.remove(f)
818 lfdirstate.remove(f)
817 lfdirstate.write()
819 lfdirstate.write()
818 lfutil.repo_remove(repo, [lfutil.standin(f) for f in forget],
820 lfutil.repo_remove(repo, [lfutil.standin(f) for f in forget],
819 unlink=True)
821 unlink=True)
820 finally:
822 finally:
821 wlock.release()
823 wlock.release()
822
824
823 def getoutgoinglfiles(ui, repo, dest=None, **opts):
825 def getoutgoinglfiles(ui, repo, dest=None, **opts):
824 dest = ui.expandpath(dest or 'default-push', dest or 'default')
826 dest = ui.expandpath(dest or 'default-push', dest or 'default')
825 dest, branches = hg.parseurl(dest, opts.get('branch'))
827 dest, branches = hg.parseurl(dest, opts.get('branch'))
826 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
828 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
827 if revs:
829 if revs:
828 revs = [repo.lookup(rev) for rev in revs]
830 revs = [repo.lookup(rev) for rev in revs]
829
831
830 remoteui = hg.remoteui
832 remoteui = hg.remoteui
831
833
832 try:
834 try:
833 remote = hg.repository(remoteui(repo, opts), dest)
835 remote = hg.repository(remoteui(repo, opts), dest)
834 except error.RepoError:
836 except error.RepoError:
835 return None
837 return None
836 o = lfutil.findoutgoing(repo, remote, False)
838 o = lfutil.findoutgoing(repo, remote, False)
837 if not o:
839 if not o:
838 return None
840 return None
839 o = repo.changelog.nodesbetween(o, revs)[0]
841 o = repo.changelog.nodesbetween(o, revs)[0]
840 if opts.get('newest_first'):
842 if opts.get('newest_first'):
841 o.reverse()
843 o.reverse()
842
844
843 toupload = set()
845 toupload = set()
844 for n in o:
846 for n in o:
845 parents = [p for p in repo.changelog.parents(n) if p != node.nullid]
847 parents = [p for p in repo.changelog.parents(n) if p != node.nullid]
846 ctx = repo[n]
848 ctx = repo[n]
847 files = set(ctx.files())
849 files = set(ctx.files())
848 if len(parents) == 2:
850 if len(parents) == 2:
849 mc = ctx.manifest()
851 mc = ctx.manifest()
850 mp1 = ctx.parents()[0].manifest()
852 mp1 = ctx.parents()[0].manifest()
851 mp2 = ctx.parents()[1].manifest()
853 mp2 = ctx.parents()[1].manifest()
852 for f in mp1:
854 for f in mp1:
853 if f not in mc:
855 if f not in mc:
854 files.add(f)
856 files.add(f)
855 for f in mp2:
857 for f in mp2:
856 if f not in mc:
858 if f not in mc:
857 files.add(f)
859 files.add(f)
858 for f in mc:
860 for f in mc:
859 if mc[f] != mp1.get(f, None) or mc[f] != mp2.get(f, None):
861 if mc[f] != mp1.get(f, None) or mc[f] != mp2.get(f, None):
860 files.add(f)
862 files.add(f)
861 toupload = toupload.union(
863 toupload = toupload.union(
862 set([f for f in files if lfutil.isstandin(f) and f in ctx]))
864 set([f for f in files if lfutil.isstandin(f) and f in ctx]))
863 return toupload
865 return toupload
864
866
865 def override_outgoing(orig, ui, repo, dest=None, **opts):
867 def override_outgoing(orig, ui, repo, dest=None, **opts):
866 orig(ui, repo, dest, **opts)
868 orig(ui, repo, dest, **opts)
867
869
868 if opts.pop('large', None):
870 if opts.pop('large', None):
869 toupload = getoutgoinglfiles(ui, repo, dest, **opts)
871 toupload = getoutgoinglfiles(ui, repo, dest, **opts)
870 if toupload is None:
872 if toupload is None:
871 ui.status(_('largefiles: No remote repo\n'))
873 ui.status(_('largefiles: No remote repo\n'))
872 else:
874 else:
873 ui.status(_('largefiles to upload:\n'))
875 ui.status(_('largefiles to upload:\n'))
874 for file in toupload:
876 for file in toupload:
875 ui.status(lfutil.splitstandin(file) + '\n')
877 ui.status(lfutil.splitstandin(file) + '\n')
876 ui.status('\n')
878 ui.status('\n')
877
879
878 def override_summary(orig, ui, repo, *pats, **opts):
880 def override_summary(orig, ui, repo, *pats, **opts):
879 try:
881 try:
880 repo.lfstatus = True
882 repo.lfstatus = True
881 orig(ui, repo, *pats, **opts)
883 orig(ui, repo, *pats, **opts)
882 finally:
884 finally:
883 repo.lfstatus = False
885 repo.lfstatus = False
884
886
885 if opts.pop('large', None):
887 if opts.pop('large', None):
886 toupload = getoutgoinglfiles(ui, repo, None, **opts)
888 toupload = getoutgoinglfiles(ui, repo, None, **opts)
887 if toupload is None:
889 if toupload is None:
888 ui.status(_('largefiles: No remote repo\n'))
890 ui.status(_('largefiles: No remote repo\n'))
889 else:
891 else:
890 ui.status(_('largefiles: %d to upload\n') % len(toupload))
892 ui.status(_('largefiles: %d to upload\n') % len(toupload))
891
893
892 def override_addremove(orig, ui, repo, *pats, **opts):
894 def override_addremove(orig, ui, repo, *pats, **opts):
893 # Get the list of missing largefiles so we can remove them
895 # Get the list of missing largefiles so we can remove them
894 lfdirstate = lfutil.openlfdirstate(ui, repo)
896 lfdirstate = lfutil.openlfdirstate(ui, repo)
895 s = lfdirstate.status(match_.always(repo.root, repo.getcwd()), [], False,
897 s = lfdirstate.status(match_.always(repo.root, repo.getcwd()), [], False,
896 False, False)
898 False, False)
897 (unsure, modified, added, removed, missing, unknown, ignored, clean) = s
899 (unsure, modified, added, removed, missing, unknown, ignored, clean) = s
898
900
899 # Call into the normal remove code, but the removing of the standin, we want
901 # Call into the normal remove code, but the removing of the standin, we want
900 # to have handled by original addremove. Monkey patching here makes sure
902 # to have handled by original addremove. Monkey patching here makes sure
901 # we don't remove the standin in the largefiles code, preventing a very
903 # we don't remove the standin in the largefiles code, preventing a very
902 # confused state later.
904 # confused state later.
903 if missing:
905 if missing:
904 repo._isaddremove = True
906 repo._isaddremove = True
905 remove_largefiles(ui, repo, *missing, **opts)
907 remove_largefiles(ui, repo, *missing, **opts)
906 repo._isaddremove = False
908 repo._isaddremove = False
907 # Call into the normal add code, and any files that *should* be added as
909 # Call into the normal add code, and any files that *should* be added as
908 # largefiles will be
910 # largefiles will be
909 add_largefiles(ui, repo, *pats, **opts)
911 add_largefiles(ui, repo, *pats, **opts)
910 # Now that we've handled largefiles, hand off to the original addremove
912 # Now that we've handled largefiles, hand off to the original addremove
911 # function to take care of the rest. Make sure it doesn't do anything with
913 # function to take care of the rest. Make sure it doesn't do anything with
912 # largefiles by installing a matcher that will ignore them.
914 # largefiles by installing a matcher that will ignore them.
913 installnormalfilesmatchfn(repo[None].manifest())
915 installnormalfilesmatchfn(repo[None].manifest())
914 result = orig(ui, repo, *pats, **opts)
916 result = orig(ui, repo, *pats, **opts)
915 restorematchfn()
917 restorematchfn()
916 return result
918 return result
917
919
918 # Calling purge with --all will cause the largefiles to be deleted.
920 # Calling purge with --all will cause the largefiles to be deleted.
919 # Override repo.status to prevent this from happening.
921 # Override repo.status to prevent this from happening.
920 def override_purge(orig, ui, repo, *dirs, **opts):
922 def override_purge(orig, ui, repo, *dirs, **opts):
921 oldstatus = repo.status
923 oldstatus = repo.status
922 def override_status(node1='.', node2=None, match=None, ignored=False,
924 def override_status(node1='.', node2=None, match=None, ignored=False,
923 clean=False, unknown=False, listsubrepos=False):
925 clean=False, unknown=False, listsubrepos=False):
924 r = oldstatus(node1, node2, match, ignored, clean, unknown,
926 r = oldstatus(node1, node2, match, ignored, clean, unknown,
925 listsubrepos)
927 listsubrepos)
926 lfdirstate = lfutil.openlfdirstate(ui, repo)
928 lfdirstate = lfutil.openlfdirstate(ui, repo)
927 modified, added, removed, deleted, unknown, ignored, clean = r
929 modified, added, removed, deleted, unknown, ignored, clean = r
928 unknown = [f for f in unknown if lfdirstate[f] == '?']
930 unknown = [f for f in unknown if lfdirstate[f] == '?']
929 ignored = [f for f in ignored if lfdirstate[f] == '?']
931 ignored = [f for f in ignored if lfdirstate[f] == '?']
930 return modified, added, removed, deleted, unknown, ignored, clean
932 return modified, added, removed, deleted, unknown, ignored, clean
931 repo.status = override_status
933 repo.status = override_status
932 orig(ui, repo, *dirs, **opts)
934 orig(ui, repo, *dirs, **opts)
933 repo.status = oldstatus
935 repo.status = oldstatus
934
936
935 def override_rollback(orig, ui, repo, **opts):
937 def override_rollback(orig, ui, repo, **opts):
936 result = orig(ui, repo, **opts)
938 result = orig(ui, repo, **opts)
937 merge.update(repo, node=None, branchmerge=False, force=True,
939 merge.update(repo, node=None, branchmerge=False, force=True,
938 partial=lfutil.isstandin)
940 partial=lfutil.isstandin)
939 wlock = repo.wlock()
941 wlock = repo.wlock()
940 try:
942 try:
941 lfdirstate = lfutil.openlfdirstate(ui, repo)
943 lfdirstate = lfutil.openlfdirstate(ui, repo)
942 lfiles = lfutil.listlfiles(repo)
944 lfiles = lfutil.listlfiles(repo)
943 oldlfiles = lfutil.listlfiles(repo, repo[None].parents()[0].rev())
945 oldlfiles = lfutil.listlfiles(repo, repo[None].parents()[0].rev())
944 for file in lfiles:
946 for file in lfiles:
945 if file in oldlfiles:
947 if file in oldlfiles:
946 lfdirstate.normallookup(file)
948 lfdirstate.normallookup(file)
947 else:
949 else:
948 lfdirstate.add(file)
950 lfdirstate.add(file)
949 lfdirstate.write()
951 lfdirstate.write()
950 finally:
952 finally:
951 wlock.release()
953 wlock.release()
952 return result
954 return result
953
955
954 def override_transplant(orig, ui, repo, *revs, **opts):
956 def override_transplant(orig, ui, repo, *revs, **opts):
955 try:
957 try:
956 repo._istransplanting = True
958 repo._istransplanting = True
957 result = orig(ui, repo, *revs, **opts)
959 result = orig(ui, repo, *revs, **opts)
958 lfcommands.updatelfiles(ui, repo, filelist=None,
960 lfcommands.updatelfiles(ui, repo, filelist=None,
959 printmessage=False)
961 printmessage=False)
960 finally:
962 finally:
961 repo._istransplanting = False
963 repo._istransplanting = False
962 return result
964 return result
@@ -1,949 +1,951 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 Remove both largefiles and normal files.
68 Remove both largefiles and normal files.
69
69
70 $ hg remove normal1 large1
70 $ hg remove normal1 large1
71 $ hg commit -m "remove files"
71 $ hg commit -m "remove files"
72 Invoking status precommit hook
72 Invoking status precommit hook
73 R large1
73 R large1
74 R normal1
74 R normal1
75 $ ls
75 $ ls
76 sub
76 sub
77 $ echo "testlargefile" > large1-test
77 $ echo "testlargefile" > large1-test
78 $ hg add --large large1-test
78 $ hg add --large large1-test
79 $ hg st
79 $ hg st
80 A large1-test
80 A large1-test
81 $ hg rm large1-test
81 $ hg rm large1-test
82 not removing large1-test: file has been marked for add (use forget to undo)
82 not removing large1-test: file has been marked for add (use forget to undo)
83 $ hg st
83 $ hg st
84 A large1-test
84 A large1-test
85 $ hg forget large1-test
85 $ hg forget large1-test
86 $ hg st
86 $ hg st
87 ? large1-test
87 ? large1-test
88 $ rm large1-test
88 $ rm large1-test
89
89
90 Copy both largefiles and normal files (testing that status output is correct).
90 Copy both largefiles and normal files (testing that status output is correct).
91
91
92 $ hg cp sub/normal2 normal1
92 $ hg cp sub/normal2 normal1
93 $ hg cp sub/large2 large1
93 $ hg cp sub/large2 large1
94 $ hg commit -m "copy files"
94 $ hg commit -m "copy files"
95 Invoking status precommit hook
95 Invoking status precommit hook
96 A large1
96 A large1
97 A normal1
97 A normal1
98 $ cat normal1
98 $ cat normal1
99 normal22
99 normal22
100 $ cat large1
100 $ cat large1
101 large22
101 large22
102
102
103 Test moving largefiles and verify that normal files are also unaffected.
103 Test moving largefiles and verify that normal files are also unaffected.
104
104
105 $ hg mv normal1 normal3
105 $ hg mv normal1 normal3
106 $ hg mv large1 large3
106 $ hg mv large1 large3
107 $ hg mv sub/normal2 sub/normal4
107 $ hg mv sub/normal2 sub/normal4
108 $ hg mv sub/large2 sub/large4
108 $ hg mv sub/large2 sub/large4
109 $ hg commit -m "move files"
109 $ hg commit -m "move files"
110 Invoking status precommit hook
110 Invoking status precommit hook
111 A large3
111 A large3
112 A normal3
112 A normal3
113 A sub/large4
113 A sub/large4
114 A sub/normal4
114 A sub/normal4
115 R large1
115 R large1
116 R normal1
116 R normal1
117 R sub/large2
117 R sub/large2
118 R sub/normal2
118 R sub/normal2
119 $ cat normal3
119 $ cat normal3
120 normal22
120 normal22
121 $ cat large3
121 $ cat large3
122 large22
122 large22
123 $ cat sub/normal4
123 $ cat sub/normal4
124 normal22
124 normal22
125 $ cat sub/large4
125 $ cat sub/large4
126 large22
126 large22
127
127
128 Test archiving the various revisions. These hit corner cases known with
128 Test archiving the various revisions. These hit corner cases known with
129 archiving.
129 archiving.
130
130
131 $ hg archive -r 0 ../archive0
131 $ hg archive -r 0 ../archive0
132 $ hg archive -r 1 ../archive1
132 $ hg archive -r 1 ../archive1
133 $ hg archive -r 2 ../archive2
133 $ hg archive -r 2 ../archive2
134 $ hg archive -r 3 ../archive3
134 $ hg archive -r 3 ../archive3
135 $ hg archive -r 4 ../archive4
135 $ hg archive -r 4 ../archive4
136 $ cd ../archive0
136 $ cd ../archive0
137 $ cat normal1
137 $ cat normal1
138 normal1
138 normal1
139 $ cat large1
139 $ cat large1
140 large1
140 large1
141 $ cat sub/normal2
141 $ cat sub/normal2
142 normal2
142 normal2
143 $ cat sub/large2
143 $ cat sub/large2
144 large2
144 large2
145 $ cd ../archive1
145 $ cd ../archive1
146 $ cat normal1
146 $ cat normal1
147 normal11
147 normal11
148 $ cat large1
148 $ cat large1
149 large11
149 large11
150 $ cat sub/normal2
150 $ cat sub/normal2
151 normal22
151 normal22
152 $ cat sub/large2
152 $ cat sub/large2
153 large22
153 large22
154 $ cd ../archive2
154 $ cd ../archive2
155 $ ls
155 $ ls
156 sub
156 sub
157 $ cat sub/normal2
157 $ cat sub/normal2
158 normal22
158 normal22
159 $ cat sub/large2
159 $ cat sub/large2
160 large22
160 large22
161 $ cd ../archive3
161 $ cd ../archive3
162 $ cat normal1
162 $ cat normal1
163 normal22
163 normal22
164 $ cat large1
164 $ cat large1
165 large22
165 large22
166 $ cat sub/normal2
166 $ cat sub/normal2
167 normal22
167 normal22
168 $ cat sub/large2
168 $ cat sub/large2
169 large22
169 large22
170 $ cd ../archive4
170 $ cd ../archive4
171 $ cat normal3
171 $ cat normal3
172 normal22
172 normal22
173 $ cat large3
173 $ cat large3
174 large22
174 large22
175 $ cat sub/normal4
175 $ cat sub/normal4
176 normal22
176 normal22
177 $ cat sub/large4
177 $ cat sub/large4
178 large22
178 large22
179
179
180 Commit corner case: specify files to commit.
180 Commit corner case: specify files to commit.
181
181
182 $ cd ../a
182 $ cd ../a
183 $ echo normal3 > normal3
183 $ echo normal3 > normal3
184 $ echo large3 > large3
184 $ echo large3 > large3
185 $ echo normal4 > sub/normal4
185 $ echo normal4 > sub/normal4
186 $ echo large4 > sub/large4
186 $ echo large4 > sub/large4
187 $ hg commit normal3 large3 sub/normal4 sub/large4 -m "edit files again"
187 $ hg commit normal3 large3 sub/normal4 sub/large4 -m "edit files again"
188 Invoking status precommit hook
188 Invoking status precommit hook
189 M large3
189 M large3
190 M normal3
190 M normal3
191 M sub/large4
191 M sub/large4
192 M sub/normal4
192 M sub/normal4
193 $ cat normal3
193 $ cat normal3
194 normal3
194 normal3
195 $ cat large3
195 $ cat large3
196 large3
196 large3
197 $ cat sub/normal4
197 $ cat sub/normal4
198 normal4
198 normal4
199 $ cat sub/large4
199 $ cat sub/large4
200 large4
200 large4
201
201
202 One more commit corner case: commit from a subdirectory.
202 One more commit corner case: commit from a subdirectory.
203
203
204 $ cd ../a
204 $ cd ../a
205 $ echo normal33 > normal3
205 $ echo normal33 > normal3
206 $ echo large33 > large3
206 $ echo large33 > large3
207 $ echo normal44 > sub/normal4
207 $ echo normal44 > sub/normal4
208 $ echo large44 > sub/large4
208 $ echo large44 > sub/large4
209 $ cd sub
209 $ cd sub
210 $ hg commit -m "edit files yet again"
210 $ hg commit -m "edit files yet again"
211 Invoking status precommit hook
211 Invoking status precommit hook
212 M large3
212 M large3
213 M normal3
213 M normal3
214 M sub/large4
214 M sub/large4
215 M sub/normal4
215 M sub/normal4
216 $ cat ../normal3
216 $ cat ../normal3
217 normal33
217 normal33
218 $ cat ../large3
218 $ cat ../large3
219 large33
219 large33
220 $ cat normal4
220 $ cat normal4
221 normal44
221 normal44
222 $ cat large4
222 $ cat large4
223 large44
223 large44
224
224
225 Committing standins is not allowed.
225 Committing standins is not allowed.
226
226
227 $ cd ..
227 $ cd ..
228 $ echo large3 > large3
228 $ echo large3 > large3
229 $ hg commit .hglf/large3 -m "try to commit standin"
229 $ hg commit .hglf/large3 -m "try to commit standin"
230 abort: file ".hglf/large3" is a largefile standin
230 abort: file ".hglf/large3" is a largefile standin
231 (commit the largefile itself instead)
231 (commit the largefile itself instead)
232 [255]
232 [255]
233
233
234 Corner cases for adding largefiles.
234 Corner cases for adding largefiles.
235
235
236 $ echo large5 > large5
236 $ echo large5 > large5
237 $ hg add --large large5
237 $ hg add --large large5
238 $ hg add --large large5
238 $ hg add --large large5
239 large5 already a largefile
239 large5 already a largefile
240 $ mkdir sub2
240 $ mkdir sub2
241 $ echo large6 > sub2/large6
241 $ echo large6 > sub2/large6
242 $ echo large7 > sub2/large7
242 $ echo large7 > sub2/large7
243 $ hg add --large sub2
243 $ hg add --large sub2
244 adding sub2/large6 as a largefile (glob)
244 adding sub2/large6 as a largefile (glob)
245 adding sub2/large7 as a largefile (glob)
245 adding sub2/large7 as a largefile (glob)
246 $ hg st
246 $ hg st
247 M large3
247 M large3
248 A large5
248 A large5
249 A sub2/large6
249 A sub2/large6
250 A sub2/large7
250 A sub2/large7
251
251
252 Config settings (pattern **.dat, minsize 2 MB) are respected.
252 Config settings (pattern **.dat, minsize 2 MB) are respected.
253
253
254 $ echo testdata > test.dat
254 $ echo testdata > test.dat
255 $ dd bs=1k count=2k if=/dev/zero of=reallylarge > /dev/null 2> /dev/null
255 $ dd bs=1k count=2k if=/dev/zero of=reallylarge > /dev/null 2> /dev/null
256 $ hg add
256 $ hg add
257 adding reallylarge as a largefile
257 adding reallylarge as a largefile
258 adding test.dat as a largefile
258 adding test.dat as a largefile
259
259
260 Test that minsize and --lfsize handle float values;
260 Test that minsize and --lfsize handle float values;
261 also tests that --lfsize overrides largefiles.minsize.
261 also tests that --lfsize overrides largefiles.minsize.
262 (0.250 MB = 256 kB = 262144 B)
262 (0.250 MB = 256 kB = 262144 B)
263
263
264 $ dd if=/dev/zero of=ratherlarge bs=1024 count=256 > /dev/null 2> /dev/null
264 $ dd if=/dev/zero of=ratherlarge bs=1024 count=256 > /dev/null 2> /dev/null
265 $ dd if=/dev/zero of=medium bs=1024 count=128 > /dev/null 2> /dev/null
265 $ dd if=/dev/zero of=medium bs=1024 count=128 > /dev/null 2> /dev/null
266 $ hg --config largefiles.minsize=.25 add
266 $ hg --config largefiles.minsize=.25 add
267 adding ratherlarge as a largefile
267 adding ratherlarge as a largefile
268 adding medium
268 adding medium
269 $ hg forget medium
269 $ hg forget medium
270 $ hg --config largefiles.minsize=.25 add --lfsize=.125
270 $ hg --config largefiles.minsize=.25 add --lfsize=.125
271 adding medium as a largefile
271 adding medium as a largefile
272 $ dd if=/dev/zero of=notlarge bs=1024 count=127 > /dev/null 2> /dev/null
272 $ dd if=/dev/zero of=notlarge bs=1024 count=127 > /dev/null 2> /dev/null
273 $ hg --config largefiles.minsize=.25 add --lfsize=.125
273 $ hg --config largefiles.minsize=.25 add --lfsize=.125
274 adding notlarge
274 adding notlarge
275 $ hg forget notlarge
275 $ hg forget notlarge
276
276
277 Test forget on largefiles.
277 Test forget on largefiles.
278
278
279 $ hg forget large3 large5 test.dat reallylarge ratherlarge medium
279 $ hg forget large3 large5 test.dat reallylarge ratherlarge medium
280 $ hg commit -m "add/edit more largefiles"
280 $ hg commit -m "add/edit more largefiles"
281 Invoking status precommit hook
281 Invoking status precommit hook
282 A sub2/large6
282 A sub2/large6
283 A sub2/large7
283 A sub2/large7
284 R large3
284 R large3
285 ? large5
285 ? large5
286 ? medium
286 ? medium
287 ? notlarge
287 ? notlarge
288 ? ratherlarge
288 ? ratherlarge
289 ? reallylarge
289 ? reallylarge
290 ? test.dat
290 ? test.dat
291 $ hg st
291 $ hg st
292 ? large3
292 ? large3
293 ? large5
293 ? large5
294 ? medium
294 ? medium
295 ? notlarge
295 ? notlarge
296 ? ratherlarge
296 ? ratherlarge
297 ? reallylarge
297 ? reallylarge
298 ? test.dat
298 ? test.dat
299
299
300 Purge with largefiles: verify that largefiles are still in the working
300 Purge with largefiles: verify that largefiles are still in the working
301 dir after a purge.
301 dir after a purge.
302
302
303 $ hg purge --all
303 $ hg purge --all
304 $ cat sub/large4
304 $ cat sub/large4
305 large44
305 large44
306 $ cat sub2/large6
306 $ cat sub2/large6
307 large6
307 large6
308 $ cat sub2/large7
308 $ cat sub2/large7
309 large7
309 large7
310
310
311 Test addremove: verify that files that should be added as largfiles are added as
311 Test addremove: verify that files that should be added as largfiles are added as
312 such and that already-existing largfiles are not added as normal files by
312 such and that already-existing largfiles are not added as normal files by
313 accident.
313 accident.
314
314
315 $ rm normal3
315 $ rm normal3
316 $ rm sub/large4
316 $ rm sub/large4
317 $ echo "testing addremove with patterns" > testaddremove.dat
317 $ echo "testing addremove with patterns" > testaddremove.dat
318 $ echo "normaladdremove" > normaladdremove
318 $ echo "normaladdremove" > normaladdremove
319 $ hg addremove
319 $ hg addremove
320 removing sub/large4
320 removing sub/large4
321 adding testaddremove.dat as a largefile
321 adding testaddremove.dat as a largefile
322 removing normal3
322 removing normal3
323 adding normaladdremove
323 adding normaladdremove
324
324
325 Clone a largefiles repo.
325 Clone a largefiles repo.
326
326
327 $ hg clone . ../b
327 $ hg clone . ../b
328 updating to branch default
328 updating to branch default
329 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
329 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
330 getting changed largefiles
330 getting changed largefiles
331 3 largefiles updated, 0 removed
331 3 largefiles updated, 0 removed
332 $ cd ../b
332 $ cd ../b
333 $ hg log --template '{rev}:{node|short} {desc|firstline}\n'
333 $ hg log --template '{rev}:{node|short} {desc|firstline}\n'
334 7:daea875e9014 add/edit more largefiles
334 7:daea875e9014 add/edit more largefiles
335 6:4355d653f84f edit files yet again
335 6:4355d653f84f edit files yet again
336 5:9d5af5072dbd edit files again
336 5:9d5af5072dbd edit files again
337 4:74c02385b94c move files
337 4:74c02385b94c move files
338 3:9e8fbc4bce62 copy files
338 3:9e8fbc4bce62 copy files
339 2:51a0ae4d5864 remove files
339 2:51a0ae4d5864 remove files
340 1:ce8896473775 edit files
340 1:ce8896473775 edit files
341 0:30d30fe6a5be add files
341 0:30d30fe6a5be add files
342 $ cat normal3
342 $ cat normal3
343 normal33
343 normal33
344 $ cat sub/normal4
344 $ cat sub/normal4
345 normal44
345 normal44
346 $ cat sub/large4
346 $ cat sub/large4
347 large44
347 large44
348 $ cat sub2/large6
348 $ cat sub2/large6
349 large6
349 large6
350 $ cat sub2/large7
350 $ cat sub2/large7
351 large7
351 large7
352 $ cd ..
352 $ cd ..
353 $ hg clone a -r 3 c
353 $ hg clone a -r 3 c
354 adding changesets
354 adding changesets
355 adding manifests
355 adding manifests
356 adding file changes
356 adding file changes
357 added 4 changesets with 10 changes to 4 files
357 added 4 changesets with 10 changes to 4 files
358 updating to branch default
358 updating to branch default
359 4 files updated, 0 files merged, 0 files removed, 0 files unresolved
359 4 files updated, 0 files merged, 0 files removed, 0 files unresolved
360 getting changed largefiles
360 getting changed largefiles
361 2 largefiles updated, 0 removed
361 2 largefiles updated, 0 removed
362 $ cd c
362 $ cd c
363 $ hg log --template '{rev}:{node|short} {desc|firstline}\n'
363 $ hg log --template '{rev}:{node|short} {desc|firstline}\n'
364 3:9e8fbc4bce62 copy files
364 3:9e8fbc4bce62 copy files
365 2:51a0ae4d5864 remove files
365 2:51a0ae4d5864 remove files
366 1:ce8896473775 edit files
366 1:ce8896473775 edit files
367 0:30d30fe6a5be add files
367 0:30d30fe6a5be add files
368 $ cat normal1
368 $ cat normal1
369 normal22
369 normal22
370 $ cat large1
370 $ cat large1
371 large22
371 large22
372 $ cat sub/normal2
372 $ cat sub/normal2
373 normal22
373 normal22
374 $ cat sub/large2
374 $ cat sub/large2
375 large22
375 large22
376
376
377 Old revisions of a clone have correct largefiles content (this also
377 Old revisions of a clone have correct largefiles content (this also
378 tests update).
378 tests update).
379
379
380 $ hg update -r 1
380 $ hg update -r 1
381 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
381 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
382 getting changed largefiles
382 getting changed largefiles
383 1 largefiles updated, 0 removed
383 1 largefiles updated, 0 removed
384 $ cat large1
384 $ cat large1
385 large11
385 large11
386 $ cat sub/large2
386 $ cat sub/large2
387 large22
387 large22
388
388
389 Rebasing between two repositories does not revert largefiles to old
389 Rebasing between two repositories does not revert largefiles to old
390 revisions (this was a very bad bug that took a lot of work to fix).
390 revisions (this was a very bad bug that took a lot of work to fix).
391
391
392 $ cd ..
392 $ cd ..
393 $ hg clone a d
393 $ hg clone a d
394 updating to branch default
394 updating to branch default
395 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
395 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
396 getting changed largefiles
396 getting changed largefiles
397 3 largefiles updated, 0 removed
397 3 largefiles updated, 0 removed
398 $ cd b
398 $ cd b
399 $ echo large4-modified > sub/large4
399 $ echo large4-modified > sub/large4
400 $ echo normal3-modified > normal3
400 $ echo normal3-modified > normal3
401 $ hg commit -m "modify normal file and largefile in repo b"
401 $ hg commit -m "modify normal file and largefile in repo b"
402 Invoking status precommit hook
402 Invoking status precommit hook
403 M normal3
403 M normal3
404 M sub/large4
404 M sub/large4
405 $ cd ../d
405 $ cd ../d
406 $ echo large6-modified > sub2/large6
406 $ echo large6-modified > sub2/large6
407 $ echo normal4-modified > sub/normal4
407 $ echo normal4-modified > sub/normal4
408 $ hg commit -m "modify normal file largefile in repo d"
408 $ hg commit -m "modify normal file largefile in repo d"
409 Invoking status precommit hook
409 Invoking status precommit hook
410 M sub/normal4
410 M sub/normal4
411 M sub2/large6
411 M sub2/large6
412 $ cd ..
412 $ cd ..
413 $ hg clone d e
413 $ hg clone d e
414 updating to branch default
414 updating to branch default
415 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
415 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
416 getting changed largefiles
416 getting changed largefiles
417 3 largefiles updated, 0 removed
417 3 largefiles updated, 0 removed
418 $ cd d
418 $ cd d
419 $ hg pull --rebase ../b
419 $ hg pull --rebase ../b
420 pulling from ../b
420 pulling from ../b
421 searching for changes
421 searching for changes
422 adding changesets
422 adding changesets
423 adding manifests
423 adding manifests
424 adding file changes
424 adding file changes
425 added 1 changesets with 2 changes to 2 files (+1 heads)
425 added 1 changesets with 2 changes to 2 files (+1 heads)
426 Invoking status precommit hook
426 Invoking status precommit hook
427 M sub/normal4
427 M sub/normal4
428 M sub2/large6
428 M sub2/large6
429 saved backup bundle to $TESTTMP/d/.hg/strip-backup/f574fb32bb45-backup.hg
429 saved backup bundle to $TESTTMP/d/.hg/strip-backup/f574fb32bb45-backup.hg
430 nothing to rebase
430 nothing to rebase
431 $ hg log --template '{rev}:{node|short} {desc|firstline}\n'
431 $ hg log --template '{rev}:{node|short} {desc|firstline}\n'
432 9:598410d3eb9a modify normal file largefile in repo d
432 9:598410d3eb9a modify normal file largefile in repo d
433 8:a381d2c8c80e modify normal file and largefile in repo b
433 8:a381d2c8c80e modify normal file and largefile in repo b
434 7:daea875e9014 add/edit more largefiles
434 7:daea875e9014 add/edit more largefiles
435 6:4355d653f84f edit files yet again
435 6:4355d653f84f edit files yet again
436 5:9d5af5072dbd edit files again
436 5:9d5af5072dbd edit files again
437 4:74c02385b94c move files
437 4:74c02385b94c move files
438 3:9e8fbc4bce62 copy files
438 3:9e8fbc4bce62 copy files
439 2:51a0ae4d5864 remove files
439 2:51a0ae4d5864 remove files
440 1:ce8896473775 edit files
440 1:ce8896473775 edit files
441 0:30d30fe6a5be add files
441 0:30d30fe6a5be add files
442 $ cat normal3
442 $ cat normal3
443 normal3-modified
443 normal3-modified
444 $ cat sub/normal4
444 $ cat sub/normal4
445 normal4-modified
445 normal4-modified
446 $ cat sub/large4
446 $ cat sub/large4
447 large4-modified
447 large4-modified
448 $ cat sub2/large6
448 $ cat sub2/large6
449 large6-modified
449 large6-modified
450 $ cat sub2/large7
450 $ cat sub2/large7
451 large7
451 large7
452 $ cd ../e
452 $ cd ../e
453 $ hg pull ../b
453 $ hg pull ../b
454 pulling from ../b
454 pulling from ../b
455 searching for changes
455 searching for changes
456 adding changesets
456 adding changesets
457 adding manifests
457 adding manifests
458 adding file changes
458 adding file changes
459 added 1 changesets with 2 changes to 2 files (+1 heads)
459 added 1 changesets with 2 changes to 2 files (+1 heads)
460 (run 'hg heads' to see heads, 'hg merge' to merge)
460 (run 'hg heads' to see heads, 'hg merge' to merge)
461 caching new largefiles
461 caching new largefiles
462 0 largefiles cached
462 0 largefiles cached
463 $ hg rebase
463 $ hg rebase
464 Invoking status precommit hook
464 Invoking status precommit hook
465 M sub/normal4
465 M sub/normal4
466 M sub2/large6
466 M sub2/large6
467 saved backup bundle to $TESTTMP/e/.hg/strip-backup/f574fb32bb45-backup.hg
467 saved backup bundle to $TESTTMP/e/.hg/strip-backup/f574fb32bb45-backup.hg
468 $ hg log --template '{rev}:{node|short} {desc|firstline}\n'
468 $ hg log --template '{rev}:{node|short} {desc|firstline}\n'
469 9:598410d3eb9a modify normal file largefile in repo d
469 9:598410d3eb9a modify normal file largefile in repo d
470 8:a381d2c8c80e modify normal file and largefile in repo b
470 8:a381d2c8c80e modify normal file and largefile in repo b
471 7:daea875e9014 add/edit more largefiles
471 7:daea875e9014 add/edit more largefiles
472 6:4355d653f84f edit files yet again
472 6:4355d653f84f edit files yet again
473 5:9d5af5072dbd edit files again
473 5:9d5af5072dbd edit files again
474 4:74c02385b94c move files
474 4:74c02385b94c move files
475 3:9e8fbc4bce62 copy files
475 3:9e8fbc4bce62 copy files
476 2:51a0ae4d5864 remove files
476 2:51a0ae4d5864 remove files
477 1:ce8896473775 edit files
477 1:ce8896473775 edit files
478 0:30d30fe6a5be add files
478 0:30d30fe6a5be add files
479 $ cat normal3
479 $ cat normal3
480 normal3-modified
480 normal3-modified
481 $ cat sub/normal4
481 $ cat sub/normal4
482 normal4-modified
482 normal4-modified
483 $ cat sub/large4
483 $ cat sub/large4
484 large4-modified
484 large4-modified
485 $ cat sub2/large6
485 $ cat sub2/large6
486 large6-modified
486 large6-modified
487 $ cat sub2/large7
487 $ cat sub2/large7
488 large7
488 large7
489
489
490 Rollback on largefiles.
490 Rollback on largefiles.
491
491
492 $ echo large4-modified-again > sub/large4
492 $ echo large4-modified-again > sub/large4
493 $ hg commit -m "Modify large4 again"
493 $ hg commit -m "Modify large4 again"
494 Invoking status precommit hook
494 Invoking status precommit hook
495 M sub/large4
495 M sub/large4
496 $ hg rollback
496 $ hg rollback
497 repository tip rolled back to revision 9 (undo commit)
497 repository tip rolled back to revision 9 (undo commit)
498 working directory now based on revision 9
498 working directory now based on revision 9
499 $ hg st
499 $ hg st
500 M sub/large4
500 M sub/large4
501 $ hg log --template '{rev}:{node|short} {desc|firstline}\n'
501 $ hg log --template '{rev}:{node|short} {desc|firstline}\n'
502 9:598410d3eb9a modify normal file largefile in repo d
502 9:598410d3eb9a modify normal file largefile in repo d
503 8:a381d2c8c80e modify normal file and largefile in repo b
503 8:a381d2c8c80e modify normal file and largefile in repo b
504 7:daea875e9014 add/edit more largefiles
504 7:daea875e9014 add/edit more largefiles
505 6:4355d653f84f edit files yet again
505 6:4355d653f84f edit files yet again
506 5:9d5af5072dbd edit files again
506 5:9d5af5072dbd edit files again
507 4:74c02385b94c move files
507 4:74c02385b94c move files
508 3:9e8fbc4bce62 copy files
508 3:9e8fbc4bce62 copy files
509 2:51a0ae4d5864 remove files
509 2:51a0ae4d5864 remove files
510 1:ce8896473775 edit files
510 1:ce8896473775 edit files
511 0:30d30fe6a5be add files
511 0:30d30fe6a5be add files
512 $ cat sub/large4
512 $ cat sub/large4
513 large4-modified-again
513 large4-modified-again
514
514
515 "update --check" refuses to update with uncommitted changes.
515 "update --check" refuses to update with uncommitted changes.
516 $ hg update --check 8
516 $ hg update --check 8
517 abort: uncommitted local changes
517 abort: uncommitted local changes
518 [255]
518 [255]
519
519
520 "update --clean" leaves correct largefiles in working copy.
520 "update --clean" leaves correct largefiles in working copy.
521
521
522 $ hg update --clean
522 $ hg update --clean
523 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
523 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
524 getting changed largefiles
524 getting changed largefiles
525 1 largefiles updated, 0 removed
525 1 largefiles updated, 0 removed
526 $ cat normal3
526 $ cat normal3
527 normal3-modified
527 normal3-modified
528 $ cat sub/normal4
528 $ cat sub/normal4
529 normal4-modified
529 normal4-modified
530 $ cat sub/large4
530 $ cat sub/large4
531 large4-modified
531 large4-modified
532 $ cat sub2/large6
532 $ cat sub2/large6
533 large6-modified
533 large6-modified
534 $ cat sub2/large7
534 $ cat sub2/large7
535 large7
535 large7
536
536
537 Now "update check" is happy.
537 Now "update check" is happy.
538 $ hg update --check 8
538 $ hg update --check 8
539 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
539 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
540 getting changed largefiles
540 getting changed largefiles
541 1 largefiles updated, 0 removed
541 1 largefiles updated, 0 removed
542 $ hg update --check
542 $ hg update --check
543 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
543 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
544 getting changed largefiles
544 getting changed largefiles
545 1 largefiles updated, 0 removed
545 1 largefiles updated, 0 removed
546
546
547 Test removing empty largefiles directories on update
547 Test removing empty largefiles directories on update
548 $ test -d sub2 && echo "sub2 exists"
548 $ test -d sub2 && echo "sub2 exists"
549 sub2 exists
549 sub2 exists
550 $ hg update -q null
550 $ hg update -q null
551 $ test -d sub2 && echo "error: sub2 should not exist anymore"
551 $ test -d sub2 && echo "error: sub2 should not exist anymore"
552 [1]
552 [1]
553 $ hg update -q
553 $ hg update -q
554
554
555 Test hg remove removes empty largefiles directories
555 Test hg remove removes empty largefiles directories
556 $ test -d sub2 && echo "sub2 exists"
556 $ test -d sub2 && echo "sub2 exists"
557 sub2 exists
557 sub2 exists
558 $ hg remove sub2/*
558 $ hg remove sub2/*
559 $ test -d sub2 && echo "error: sub2 should not exist anymore"
559 $ test -d sub2 && echo "error: sub2 should not exist anymore"
560 [1]
560 [1]
561 $ hg revert sub2/large6 sub2/large7
561 $ hg revert sub2/large6 sub2/large7
562
562
563 "revert" works on largefiles (and normal files too).
563 "revert" works on largefiles (and normal files too).
564 $ echo hack3 >> normal3
564 $ echo hack3 >> normal3
565 $ echo hack4 >> sub/normal4
565 $ echo hack4 >> sub/normal4
566 $ echo hack4 >> sub/large4
566 $ echo hack4 >> sub/large4
567 $ rm sub2/large6
568 $ hg revert sub2/large6
567 $ hg rm sub2/large6
569 $ hg rm sub2/large6
568 $ echo new >> sub2/large8
570 $ echo new >> sub2/large8
569 $ hg add --large sub2/large8
571 $ hg add --large sub2/large8
570 # XXX we don't really want to report that we're reverting the standin;
572 # XXX we don't really want to report that we're reverting the standin;
571 # that's just an implementation detail. But I don't see an obvious fix. ;-(
573 # that's just an implementation detail. But I don't see an obvious fix. ;-(
572 $ hg revert sub
574 $ hg revert sub
573 reverting .hglf/sub/large4 (glob)
575 reverting .hglf/sub/large4 (glob)
574 reverting sub/normal4 (glob)
576 reverting sub/normal4 (glob)
575 $ hg status
577 $ hg status
576 M normal3
578 M normal3
577 A sub2/large8
579 A sub2/large8
578 R sub2/large6
580 R sub2/large6
579 ? sub/large4.orig
581 ? sub/large4.orig
580 ? sub/normal4.orig
582 ? sub/normal4.orig
581 $ cat sub/normal4
583 $ cat sub/normal4
582 normal4-modified
584 normal4-modified
583 $ cat sub/large4
585 $ cat sub/large4
584 large4-modified
586 large4-modified
585 $ hg revert -a --no-backup
587 $ hg revert -a --no-backup
586 undeleting .hglf/sub2/large6 (glob)
588 undeleting .hglf/sub2/large6 (glob)
587 forgetting .hglf/sub2/large8 (glob)
589 forgetting .hglf/sub2/large8 (glob)
588 reverting normal3
590 reverting normal3
589 $ hg status
591 $ hg status
590 ? sub/large4.orig
592 ? sub/large4.orig
591 ? sub/normal4.orig
593 ? sub/normal4.orig
592 ? sub2/large8
594 ? sub2/large8
593 $ cat normal3
595 $ cat normal3
594 normal3-modified
596 normal3-modified
595 $ cat sub2/large6
597 $ cat sub2/large6
596 large6-modified
598 large6-modified
597 $ rm sub/*.orig sub2/large8
599 $ rm sub/*.orig sub2/large8
598
600
599 revert some files to an older revision
601 revert some files to an older revision
600 $ hg revert --no-backup -r 8 sub2
602 $ hg revert --no-backup -r 8 sub2
601 reverting .hglf/sub2/large6 (glob)
603 reverting .hglf/sub2/large6 (glob)
602 $ cat sub2/large6
604 $ cat sub2/large6
603 large6
605 large6
604 $ hg revert --no-backup sub2
606 $ hg revert --no-backup sub2
605 reverting .hglf/sub2/large6 (glob)
607 reverting .hglf/sub2/large6 (glob)
606 $ hg status
608 $ hg status
607
609
608 "verify --large" actually verifies largefiles
610 "verify --large" actually verifies largefiles
609
611
610 $ hg verify --large
612 $ hg verify --large
611 checking changesets
613 checking changesets
612 checking manifests
614 checking manifests
613 crosschecking files in changesets and manifests
615 crosschecking files in changesets and manifests
614 checking files
616 checking files
615 10 files, 10 changesets, 28 total revisions
617 10 files, 10 changesets, 28 total revisions
616 searching 1 changesets for largefiles
618 searching 1 changesets for largefiles
617 verified existence of 3 revisions of 3 largefiles
619 verified existence of 3 revisions of 3 largefiles
618
620
619 Merging does not revert to old versions of largefiles and also check
621 Merging does not revert to old versions of largefiles and also check
620 that merging after having pulled from a non-default remote works
622 that merging after having pulled from a non-default remote works
621 correctly.
623 correctly.
622
624
623 $ cd ..
625 $ cd ..
624 $ hg clone -r 7 e temp
626 $ hg clone -r 7 e temp
625 adding changesets
627 adding changesets
626 adding manifests
628 adding manifests
627 adding file changes
629 adding file changes
628 added 8 changesets with 24 changes to 10 files
630 added 8 changesets with 24 changes to 10 files
629 updating to branch default
631 updating to branch default
630 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
632 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
631 getting changed largefiles
633 getting changed largefiles
632 3 largefiles updated, 0 removed
634 3 largefiles updated, 0 removed
633 $ hg clone temp f
635 $ hg clone temp f
634 updating to branch default
636 updating to branch default
635 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
637 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
636 getting changed largefiles
638 getting changed largefiles
637 3 largefiles updated, 0 removed
639 3 largefiles updated, 0 removed
638 # Delete the largefiles in the largefiles system cache so that we have an
640 # Delete the largefiles in the largefiles system cache so that we have an
639 # opportunity to test that caching after a pull works.
641 # opportunity to test that caching after a pull works.
640 $ rm ${USERCACHE}/*
642 $ rm ${USERCACHE}/*
641 $ cd f
643 $ cd f
642 $ echo "large4-merge-test" > sub/large4
644 $ echo "large4-merge-test" > sub/large4
643 $ hg commit -m "Modify large4 to test merge"
645 $ hg commit -m "Modify large4 to test merge"
644 Invoking status precommit hook
646 Invoking status precommit hook
645 M sub/large4
647 M sub/large4
646 $ hg pull ../e
648 $ hg pull ../e
647 pulling from ../e
649 pulling from ../e
648 searching for changes
650 searching for changes
649 adding changesets
651 adding changesets
650 adding manifests
652 adding manifests
651 adding file changes
653 adding file changes
652 added 2 changesets with 4 changes to 4 files (+1 heads)
654 added 2 changesets with 4 changes to 4 files (+1 heads)
653 (run 'hg heads' to see heads, 'hg merge' to merge)
655 (run 'hg heads' to see heads, 'hg merge' to merge)
654 caching new largefiles
656 caching new largefiles
655 2 largefiles cached
657 2 largefiles cached
656 $ hg merge
658 $ hg merge
657 merging sub/large4
659 merging sub/large4
658 largefile sub/large4 has a merge conflict
660 largefile sub/large4 has a merge conflict
659 keep (l)ocal or take (o)ther? l
661 keep (l)ocal or take (o)ther? l
660 3 files updated, 1 files merged, 0 files removed, 0 files unresolved
662 3 files updated, 1 files merged, 0 files removed, 0 files unresolved
661 (branch merge, don't forget to commit)
663 (branch merge, don't forget to commit)
662 getting changed largefiles
664 getting changed largefiles
663 1 largefiles updated, 0 removed
665 1 largefiles updated, 0 removed
664 $ hg commit -m "Merge repos e and f"
666 $ hg commit -m "Merge repos e and f"
665 Invoking status precommit hook
667 Invoking status precommit hook
666 M normal3
668 M normal3
667 M sub/normal4
669 M sub/normal4
668 M sub2/large6
670 M sub2/large6
669 $ cat normal3
671 $ cat normal3
670 normal3-modified
672 normal3-modified
671 $ cat sub/normal4
673 $ cat sub/normal4
672 normal4-modified
674 normal4-modified
673 $ cat sub/large4
675 $ cat sub/large4
674 large4-merge-test
676 large4-merge-test
675 $ cat sub2/large6
677 $ cat sub2/large6
676 large6-modified
678 large6-modified
677 $ cat sub2/large7
679 $ cat sub2/large7
678 large7
680 large7
679
681
680 Test status after merging with a branch that introduces a new largefile:
682 Test status after merging with a branch that introduces a new largefile:
681
683
682 $ echo large > large
684 $ echo large > large
683 $ hg add --large large
685 $ hg add --large large
684 $ hg commit -m 'add largefile'
686 $ hg commit -m 'add largefile'
685 Invoking status precommit hook
687 Invoking status precommit hook
686 A large
688 A large
687 $ hg update -q ".^"
689 $ hg update -q ".^"
688 $ echo change >> normal3
690 $ echo change >> normal3
689 $ hg commit -m 'some change'
691 $ hg commit -m 'some change'
690 Invoking status precommit hook
692 Invoking status precommit hook
691 M normal3
693 M normal3
692 created new head
694 created new head
693 $ hg merge
695 $ hg merge
694 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
696 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
695 (branch merge, don't forget to commit)
697 (branch merge, don't forget to commit)
696 getting changed largefiles
698 getting changed largefiles
697 1 largefiles updated, 0 removed
699 1 largefiles updated, 0 removed
698 $ hg status
700 $ hg status
699 M large
701 M large
700
702
701 Test that a normal file and a largefile with the same name and path cannot
703 Test that a normal file and a largefile with the same name and path cannot
702 coexist.
704 coexist.
703
705
704 $ rm sub2/large7
706 $ rm sub2/large7
705 $ echo "largeasnormal" > sub2/large7
707 $ echo "largeasnormal" > sub2/large7
706 $ hg add sub2/large7
708 $ hg add sub2/large7
707 sub2/large7 already a largefile
709 sub2/large7 already a largefile
708
710
709 Test that transplanting a largefile change works correctly.
711 Test that transplanting a largefile change works correctly.
710
712
711 $ cd ..
713 $ cd ..
712 $ hg clone -r 8 d g
714 $ hg clone -r 8 d g
713 adding changesets
715 adding changesets
714 adding manifests
716 adding manifests
715 adding file changes
717 adding file changes
716 added 9 changesets with 26 changes to 10 files
718 added 9 changesets with 26 changes to 10 files
717 updating to branch default
719 updating to branch default
718 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
719 getting changed largefiles
721 getting changed largefiles
720 3 largefiles updated, 0 removed
722 3 largefiles updated, 0 removed
721 $ cd g
723 $ cd g
722 $ hg transplant -s ../d 598410d3eb9a
724 $ hg transplant -s ../d 598410d3eb9a
723 searching for changes
725 searching for changes
724 searching for changes
726 searching for changes
725 adding changesets
727 adding changesets
726 adding manifests
728 adding manifests
727 adding file changes
729 adding file changes
728 added 1 changesets with 2 changes to 2 files
730 added 1 changesets with 2 changes to 2 files
729 $ hg log --template '{rev}:{node|short} {desc|firstline}\n'
731 $ hg log --template '{rev}:{node|short} {desc|firstline}\n'
730 9:598410d3eb9a modify normal file largefile in repo d
732 9:598410d3eb9a modify normal file largefile in repo d
731 8:a381d2c8c80e modify normal file and largefile in repo b
733 8:a381d2c8c80e modify normal file and largefile in repo b
732 7:daea875e9014 add/edit more largefiles
734 7:daea875e9014 add/edit more largefiles
733 6:4355d653f84f edit files yet again
735 6:4355d653f84f edit files yet again
734 5:9d5af5072dbd edit files again
736 5:9d5af5072dbd edit files again
735 4:74c02385b94c move files
737 4:74c02385b94c move files
736 3:9e8fbc4bce62 copy files
738 3:9e8fbc4bce62 copy files
737 2:51a0ae4d5864 remove files
739 2:51a0ae4d5864 remove files
738 1:ce8896473775 edit files
740 1:ce8896473775 edit files
739 0:30d30fe6a5be add files
741 0:30d30fe6a5be add files
740 $ cat normal3
742 $ cat normal3
741 normal3-modified
743 normal3-modified
742 $ cat sub/normal4
744 $ cat sub/normal4
743 normal4-modified
745 normal4-modified
744 $ cat sub/large4
746 $ cat sub/large4
745 large4-modified
747 large4-modified
746 $ cat sub2/large6
748 $ cat sub2/large6
747 large6-modified
749 large6-modified
748 $ cat sub2/large7
750 $ cat sub2/large7
749 large7
751 large7
750
752
751 Test that renaming a largefile results in correct output for status
753 Test that renaming a largefile results in correct output for status
752
754
753 $ hg rename sub/large4 large4-renamed
755 $ hg rename sub/large4 large4-renamed
754 $ hg commit -m "test rename output"
756 $ hg commit -m "test rename output"
755 Invoking status precommit hook
757 Invoking status precommit hook
756 A large4-renamed
758 A large4-renamed
757 R sub/large4
759 R sub/large4
758 $ cat large4-renamed
760 $ cat large4-renamed
759 large4-modified
761 large4-modified
760 $ cd sub2
762 $ cd sub2
761 $ hg rename large6 large6-renamed
763 $ hg rename large6 large6-renamed
762 $ hg st
764 $ hg st
763 A sub2/large6-renamed
765 A sub2/large6-renamed
764 R sub2/large6
766 R sub2/large6
765 $ cd ..
767 $ cd ..
766
768
767 Test --normal flag
769 Test --normal flag
768
770
769 $ dd if=/dev/urandom bs=2k count=11k > new-largefile 2> /dev/null
771 $ dd if=/dev/urandom bs=2k count=11k > new-largefile 2> /dev/null
770 $ hg add --normal --large new-largefile
772 $ hg add --normal --large new-largefile
771 abort: --normal cannot be used with --large
773 abort: --normal cannot be used with --large
772 [255]
774 [255]
773 $ hg add --normal new-largefile
775 $ hg add --normal new-largefile
774 new-largefile: up to 69 MB of RAM may be required to manage this file
776 new-largefile: up to 69 MB of RAM may be required to manage this file
775 (use 'hg revert new-largefile' to cancel the pending addition)
777 (use 'hg revert new-largefile' to cancel the pending addition)
776 $ cd ..
778 $ cd ..
777
779
778 vanilla clients not locked out from largefiles servers on vanilla repos
780 vanilla clients not locked out from largefiles servers on vanilla repos
779 $ mkdir r1
781 $ mkdir r1
780 $ cd r1
782 $ cd r1
781 $ hg init
783 $ hg init
782 $ echo c1 > f1
784 $ echo c1 > f1
783 $ hg add f1
785 $ hg add f1
784 $ hg commit -m "m1"
786 $ hg commit -m "m1"
785 Invoking status precommit hook
787 Invoking status precommit hook
786 A f1
788 A f1
787 $ cd ..
789 $ cd ..
788 $ hg serve -R r1 -d -p $HGPORT --pid-file hg.pid
790 $ hg serve -R r1 -d -p $HGPORT --pid-file hg.pid
789 $ cat hg.pid >> $DAEMON_PIDS
791 $ cat hg.pid >> $DAEMON_PIDS
790 $ hg --config extensions.largefiles=! clone http://localhost:$HGPORT r2
792 $ hg --config extensions.largefiles=! clone http://localhost:$HGPORT r2
791 requesting all changes
793 requesting all changes
792 adding changesets
794 adding changesets
793 adding manifests
795 adding manifests
794 adding file changes
796 adding file changes
795 added 1 changesets with 1 changes to 1 files
797 added 1 changesets with 1 changes to 1 files
796 updating to branch default
798 updating to branch default
797 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
799 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
798
800
799 largefiles clients still work with vanilla servers
801 largefiles clients still work with vanilla servers
800 $ hg --config extensions.largefiles=! serve -R r1 -d -p $HGPORT1 --pid-file hg.pid
802 $ hg --config extensions.largefiles=! serve -R r1 -d -p $HGPORT1 --pid-file hg.pid
801 $ cat hg.pid >> $DAEMON_PIDS
803 $ cat hg.pid >> $DAEMON_PIDS
802 $ hg clone http://localhost:$HGPORT1 r3
804 $ hg clone http://localhost:$HGPORT1 r3
803 requesting all changes
805 requesting all changes
804 adding changesets
806 adding changesets
805 adding manifests
807 adding manifests
806 adding file changes
808 adding file changes
807 added 1 changesets with 1 changes to 1 files
809 added 1 changesets with 1 changes to 1 files
808 updating to branch default
810 updating to branch default
809 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
811 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
810
812
811 vanilla clients locked out from largefiles http repos
813 vanilla clients locked out from largefiles http repos
812 $ mkdir r4
814 $ mkdir r4
813 $ cd r4
815 $ cd r4
814 $ hg init
816 $ hg init
815 $ echo c1 > f1
817 $ echo c1 > f1
816 $ hg add --large f1
818 $ hg add --large f1
817 $ hg commit -m "m1"
819 $ hg commit -m "m1"
818 Invoking status precommit hook
820 Invoking status precommit hook
819 A f1
821 A f1
820 $ cd ..
822 $ cd ..
821 $ hg serve -R r4 -d -p $HGPORT2 --pid-file hg.pid
823 $ hg serve -R r4 -d -p $HGPORT2 --pid-file hg.pid
822 $ cat hg.pid >> $DAEMON_PIDS
824 $ cat hg.pid >> $DAEMON_PIDS
823 $ hg --config extensions.largefiles=! clone http://localhost:$HGPORT2 r5
825 $ hg --config extensions.largefiles=! clone http://localhost:$HGPORT2 r5
824 abort: remote error:
826 abort: remote error:
825
827
826 This repository uses the largefiles extension.
828 This repository uses the largefiles extension.
827
829
828 Please enable it in your Mercurial config file.
830 Please enable it in your Mercurial config file.
829 [255]
831 [255]
830
832
831 used all HGPORTs, kill all daemons
833 used all HGPORTs, kill all daemons
832 $ "$TESTDIR/killdaemons.py"
834 $ "$TESTDIR/killdaemons.py"
833
835
834 vanilla clients locked out from largefiles ssh repos
836 vanilla clients locked out from largefiles ssh repos
835 $ hg --config extensions.largefiles=! clone -e "python $TESTDIR/dummyssh" ssh://user@dummy/r4 r5
837 $ hg --config extensions.largefiles=! clone -e "python $TESTDIR/dummyssh" ssh://user@dummy/r4 r5
836 abort: remote error:
838 abort: remote error:
837
839
838 This repository uses the largefiles extension.
840 This repository uses the largefiles extension.
839
841
840 Please enable it in your Mercurial config file.
842 Please enable it in your Mercurial config file.
841 [255]
843 [255]
842
844
843 largefiles clients refuse to push largefiles repos to vanilla servers
845 largefiles clients refuse to push largefiles repos to vanilla servers
844 $ mkdir r6
846 $ mkdir r6
845 $ cd r6
847 $ cd r6
846 $ hg init
848 $ hg init
847 $ echo c1 > f1
849 $ echo c1 > f1
848 $ hg add f1
850 $ hg add f1
849 $ hg commit -m "m1"
851 $ hg commit -m "m1"
850 Invoking status precommit hook
852 Invoking status precommit hook
851 A f1
853 A f1
852 $ cat >> .hg/hgrc <<!
854 $ cat >> .hg/hgrc <<!
853 > [web]
855 > [web]
854 > push_ssl = false
856 > push_ssl = false
855 > allow_push = *
857 > allow_push = *
856 > !
858 > !
857 $ cd ..
859 $ cd ..
858 $ hg clone r6 r7
860 $ hg clone r6 r7
859 updating to branch default
861 updating to branch default
860 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
862 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
861 $ cd r7
863 $ cd r7
862 $ echo c2 > f2
864 $ echo c2 > f2
863 $ hg add --large f2
865 $ hg add --large f2
864 $ hg commit -m "m2"
866 $ hg commit -m "m2"
865 Invoking status precommit hook
867 Invoking status precommit hook
866 A f2
868 A f2
867 $ hg --config extensions.largefiles=! -R ../r6 serve -d -p $HGPORT --pid-file ../hg.pid
869 $ hg --config extensions.largefiles=! -R ../r6 serve -d -p $HGPORT --pid-file ../hg.pid
868 $ cat ../hg.pid >> $DAEMON_PIDS
870 $ cat ../hg.pid >> $DAEMON_PIDS
869 $ hg push http://localhost:$HGPORT
871 $ hg push http://localhost:$HGPORT
870 pushing to http://localhost:$HGPORT/
872 pushing to http://localhost:$HGPORT/
871 searching for changes
873 searching for changes
872 abort: http://localhost:$HGPORT/ does not appear to be a largefile store
874 abort: http://localhost:$HGPORT/ does not appear to be a largefile store
873 [255]
875 [255]
874 $ cd ..
876 $ cd ..
875
877
876 putlfile errors are shown (issue3123)
878 putlfile errors are shown (issue3123)
877 Corrupt the cached largefile in r7
879 Corrupt the cached largefile in r7
878 $ echo corruption > $USERCACHE/4cdac4d8b084d0b599525cf732437fb337d422a8
880 $ echo corruption > $USERCACHE/4cdac4d8b084d0b599525cf732437fb337d422a8
879 $ hg init empty
881 $ hg init empty
880 $ hg serve -R empty -d -p $HGPORT1 --pid-file hg.pid \
882 $ hg serve -R empty -d -p $HGPORT1 --pid-file hg.pid \
881 > --config 'web.allow_push=*' --config web.push_ssl=False
883 > --config 'web.allow_push=*' --config web.push_ssl=False
882 $ cat hg.pid >> $DAEMON_PIDS
884 $ cat hg.pid >> $DAEMON_PIDS
883 $ hg push -R r7 http://localhost:$HGPORT1
885 $ hg push -R r7 http://localhost:$HGPORT1
884 pushing to http://localhost:$HGPORT1/
886 pushing to http://localhost:$HGPORT1/
885 searching for changes
887 searching for changes
886 remote: largefiles: failed to put 4cdac4d8b084d0b599525cf732437fb337d422a8 into store: largefile contents do not match hash
888 remote: largefiles: failed to put 4cdac4d8b084d0b599525cf732437fb337d422a8 into store: largefile contents do not match hash
887 abort: remotestore: could not put $TESTTMP/r7/.hg/largefiles/4cdac4d8b084d0b599525cf732437fb337d422a8 to remote store http://localhost:$HGPORT1/
889 abort: remotestore: could not put $TESTTMP/r7/.hg/largefiles/4cdac4d8b084d0b599525cf732437fb337d422a8 to remote store http://localhost:$HGPORT1/
888 [255]
890 [255]
889 $ rm -rf empty
891 $ rm -rf empty
890
892
891 Clone a local repository owned by another user
893 Clone a local repository owned by another user
892 We have to simulate that here by setting $HOME and removing write permissions
894 We have to simulate that here by setting $HOME and removing write permissions
893 $ ORIGHOME="$HOME"
895 $ ORIGHOME="$HOME"
894 $ mkdir alice
896 $ mkdir alice
895 $ HOME="`pwd`/alice"
897 $ HOME="`pwd`/alice"
896 $ cd alice
898 $ cd alice
897 $ hg init pubrepo
899 $ hg init pubrepo
898 $ cd pubrepo
900 $ cd pubrepo
899 $ dd if=/dev/urandom bs=1k count=11k > a-large-file 2> /dev/null
901 $ dd if=/dev/urandom bs=1k count=11k > a-large-file 2> /dev/null
900 $ hg add --large a-large-file
902 $ hg add --large a-large-file
901 $ hg commit -m "Add a large file"
903 $ hg commit -m "Add a large file"
902 Invoking status precommit hook
904 Invoking status precommit hook
903 A a-large-file
905 A a-large-file
904 $ cd ..
906 $ cd ..
905 $ chmod -R a-w pubrepo
907 $ chmod -R a-w pubrepo
906 $ cd ..
908 $ cd ..
907 $ mkdir bob
909 $ mkdir bob
908 $ HOME="`pwd`/bob"
910 $ HOME="`pwd`/bob"
909 $ cd bob
911 $ cd bob
910 $ hg clone --pull ../alice/pubrepo pubrepo
912 $ hg clone --pull ../alice/pubrepo pubrepo
911 requesting all changes
913 requesting all changes
912 adding changesets
914 adding changesets
913 adding manifests
915 adding manifests
914 adding file changes
916 adding file changes
915 added 1 changesets with 1 changes to 1 files
917 added 1 changesets with 1 changes to 1 files
916 updating to branch default
918 updating to branch default
917 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
919 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
918 getting changed largefiles
920 getting changed largefiles
919 1 largefiles updated, 0 removed
921 1 largefiles updated, 0 removed
920 $ cd ..
922 $ cd ..
921 $ chmod -R u+w alice/pubrepo
923 $ chmod -R u+w alice/pubrepo
922 $ HOME="$ORIGHOME"
924 $ HOME="$ORIGHOME"
923
925
924 Symlink to a large largefile should behave the same as a symlink to a normal file
926 Symlink to a large largefile should behave the same as a symlink to a normal file
925 $ hg init largesymlink
927 $ hg init largesymlink
926 $ cd largesymlink
928 $ cd largesymlink
927 $ dd if=/dev/zero bs=1k count=10k of=largefile 2>/dev/null
929 $ dd if=/dev/zero bs=1k count=10k of=largefile 2>/dev/null
928 $ hg add --large largefile
930 $ hg add --large largefile
929 $ hg commit -m "commit a large file"
931 $ hg commit -m "commit a large file"
930 Invoking status precommit hook
932 Invoking status precommit hook
931 A largefile
933 A largefile
932 $ ln -s largefile largelink
934 $ ln -s largefile largelink
933 $ hg add largelink
935 $ hg add largelink
934 $ hg commit -m "commit a large symlink"
936 $ hg commit -m "commit a large symlink"
935 Invoking status precommit hook
937 Invoking status precommit hook
936 A largelink
938 A largelink
937 $ rm -f largelink
939 $ rm -f largelink
938 $ hg up >/dev/null
940 $ hg up >/dev/null
939 $ test -f largelink
941 $ test -f largelink
940 [1]
942 [1]
941 $ test -L largelink
943 $ test -L largelink
942 [1]
944 [1]
943 $ rm -f largelink # make next part of the test independent of the previous
945 $ rm -f largelink # make next part of the test independent of the previous
944 $ hg up -C >/dev/null
946 $ hg up -C >/dev/null
945 $ test -f largelink
947 $ test -f largelink
946 $ test -L largelink
948 $ test -L largelink
947 $ cd ..
949 $ cd ..
948
950
949
951
General Comments 0
You need to be logged in to leave comments. Login now