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