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