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