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