##// END OF EJS Templates
largefiles: avoid redundant "updatelfiles" invocation in "overridetransplant"...
FUJIWARA Katsunori -
r23273:236c978b default
parent child Browse files
Show More
@@ -1,576 +1,585 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 '''largefiles utility code: must not import other modules in this package.'''
9 '''largefiles utility code: must not import other modules in this package.'''
10
10
11 import os
11 import os
12 import platform
12 import platform
13 import shutil
13 import shutil
14 import stat
14 import stat
15 import copy
15 import copy
16
16
17 from mercurial import dirstate, httpconnection, match as match_, util, scmutil
17 from mercurial import dirstate, httpconnection, match as match_, util, scmutil
18 from mercurial.i18n import _
18 from mercurial.i18n import _
19 from mercurial import node
19 from mercurial import node
20
20
21 shortname = '.hglf'
21 shortname = '.hglf'
22 shortnameslash = shortname + '/'
22 shortnameslash = shortname + '/'
23 longname = 'largefiles'
23 longname = 'largefiles'
24
24
25
25
26 # -- Private worker functions ------------------------------------------
26 # -- Private worker functions ------------------------------------------
27
27
28 def getminsize(ui, assumelfiles, opt, default=10):
28 def getminsize(ui, assumelfiles, opt, default=10):
29 lfsize = opt
29 lfsize = opt
30 if not lfsize and assumelfiles:
30 if not lfsize and assumelfiles:
31 lfsize = ui.config(longname, 'minsize', default=default)
31 lfsize = ui.config(longname, 'minsize', default=default)
32 if lfsize:
32 if lfsize:
33 try:
33 try:
34 lfsize = float(lfsize)
34 lfsize = float(lfsize)
35 except ValueError:
35 except ValueError:
36 raise util.Abort(_('largefiles: size must be number (not %s)\n')
36 raise util.Abort(_('largefiles: size must be number (not %s)\n')
37 % lfsize)
37 % lfsize)
38 if lfsize is None:
38 if lfsize is None:
39 raise util.Abort(_('minimum size for largefiles must be specified'))
39 raise util.Abort(_('minimum size for largefiles must be specified'))
40 return lfsize
40 return lfsize
41
41
42 def link(src, dest):
42 def link(src, dest):
43 util.makedirs(os.path.dirname(dest))
43 util.makedirs(os.path.dirname(dest))
44 try:
44 try:
45 util.oslink(src, dest)
45 util.oslink(src, dest)
46 except OSError:
46 except OSError:
47 # if hardlinks fail, fallback on atomic copy
47 # if hardlinks fail, fallback on atomic copy
48 dst = util.atomictempfile(dest)
48 dst = util.atomictempfile(dest)
49 for chunk in util.filechunkiter(open(src, 'rb')):
49 for chunk in util.filechunkiter(open(src, 'rb')):
50 dst.write(chunk)
50 dst.write(chunk)
51 dst.close()
51 dst.close()
52 os.chmod(dest, os.stat(src).st_mode)
52 os.chmod(dest, os.stat(src).st_mode)
53
53
54 def usercachepath(ui, hash):
54 def usercachepath(ui, hash):
55 path = ui.configpath(longname, 'usercache', None)
55 path = ui.configpath(longname, 'usercache', None)
56 if path:
56 if path:
57 path = os.path.join(path, hash)
57 path = os.path.join(path, hash)
58 else:
58 else:
59 if os.name == 'nt':
59 if os.name == 'nt':
60 appdata = os.getenv('LOCALAPPDATA', os.getenv('APPDATA'))
60 appdata = os.getenv('LOCALAPPDATA', os.getenv('APPDATA'))
61 if appdata:
61 if appdata:
62 path = os.path.join(appdata, longname, hash)
62 path = os.path.join(appdata, longname, hash)
63 elif platform.system() == 'Darwin':
63 elif platform.system() == 'Darwin':
64 home = os.getenv('HOME')
64 home = os.getenv('HOME')
65 if home:
65 if home:
66 path = os.path.join(home, 'Library', 'Caches',
66 path = os.path.join(home, 'Library', 'Caches',
67 longname, hash)
67 longname, hash)
68 elif os.name == 'posix':
68 elif os.name == 'posix':
69 path = os.getenv('XDG_CACHE_HOME')
69 path = os.getenv('XDG_CACHE_HOME')
70 if path:
70 if path:
71 path = os.path.join(path, longname, hash)
71 path = os.path.join(path, longname, hash)
72 else:
72 else:
73 home = os.getenv('HOME')
73 home = os.getenv('HOME')
74 if home:
74 if home:
75 path = os.path.join(home, '.cache', longname, hash)
75 path = os.path.join(home, '.cache', longname, hash)
76 else:
76 else:
77 raise util.Abort(_('unknown operating system: %s\n') % os.name)
77 raise util.Abort(_('unknown operating system: %s\n') % os.name)
78 return path
78 return path
79
79
80 def inusercache(ui, hash):
80 def inusercache(ui, hash):
81 path = usercachepath(ui, hash)
81 path = usercachepath(ui, hash)
82 return path and os.path.exists(path)
82 return path and os.path.exists(path)
83
83
84 def findfile(repo, hash):
84 def findfile(repo, hash):
85 if instore(repo, hash):
85 if instore(repo, hash):
86 repo.ui.note(_('found %s in store\n') % hash)
86 repo.ui.note(_('found %s in store\n') % hash)
87 return storepath(repo, hash)
87 return storepath(repo, hash)
88 elif inusercache(repo.ui, hash):
88 elif inusercache(repo.ui, hash):
89 repo.ui.note(_('found %s in system cache\n') % hash)
89 repo.ui.note(_('found %s in system cache\n') % hash)
90 path = storepath(repo, hash)
90 path = storepath(repo, hash)
91 link(usercachepath(repo.ui, hash), path)
91 link(usercachepath(repo.ui, hash), path)
92 return path
92 return path
93 return None
93 return None
94
94
95 class largefilesdirstate(dirstate.dirstate):
95 class largefilesdirstate(dirstate.dirstate):
96 def __getitem__(self, key):
96 def __getitem__(self, key):
97 return super(largefilesdirstate, self).__getitem__(unixpath(key))
97 return super(largefilesdirstate, self).__getitem__(unixpath(key))
98 def normal(self, f):
98 def normal(self, f):
99 return super(largefilesdirstate, self).normal(unixpath(f))
99 return super(largefilesdirstate, self).normal(unixpath(f))
100 def remove(self, f):
100 def remove(self, f):
101 return super(largefilesdirstate, self).remove(unixpath(f))
101 return super(largefilesdirstate, self).remove(unixpath(f))
102 def add(self, f):
102 def add(self, f):
103 return super(largefilesdirstate, self).add(unixpath(f))
103 return super(largefilesdirstate, self).add(unixpath(f))
104 def drop(self, f):
104 def drop(self, f):
105 return super(largefilesdirstate, self).drop(unixpath(f))
105 return super(largefilesdirstate, self).drop(unixpath(f))
106 def forget(self, f):
106 def forget(self, f):
107 return super(largefilesdirstate, self).forget(unixpath(f))
107 return super(largefilesdirstate, self).forget(unixpath(f))
108 def normallookup(self, f):
108 def normallookup(self, f):
109 return super(largefilesdirstate, self).normallookup(unixpath(f))
109 return super(largefilesdirstate, self).normallookup(unixpath(f))
110 def _ignore(self, f):
110 def _ignore(self, f):
111 return False
111 return False
112
112
113 def openlfdirstate(ui, repo, create=True):
113 def openlfdirstate(ui, repo, create=True):
114 '''
114 '''
115 Return a dirstate object that tracks largefiles: i.e. its root is
115 Return a dirstate object that tracks largefiles: i.e. its root is
116 the repo root, but it is saved in .hg/largefiles/dirstate.
116 the repo root, but it is saved in .hg/largefiles/dirstate.
117 '''
117 '''
118 lfstoredir = repo.join(longname)
118 lfstoredir = repo.join(longname)
119 opener = scmutil.opener(lfstoredir)
119 opener = scmutil.opener(lfstoredir)
120 lfdirstate = largefilesdirstate(opener, ui, repo.root,
120 lfdirstate = largefilesdirstate(opener, ui, repo.root,
121 repo.dirstate._validate)
121 repo.dirstate._validate)
122
122
123 # If the largefiles dirstate does not exist, populate and create
123 # If the largefiles dirstate does not exist, populate and create
124 # it. This ensures that we create it on the first meaningful
124 # it. This ensures that we create it on the first meaningful
125 # largefiles operation in a new clone.
125 # largefiles operation in a new clone.
126 if create and not os.path.exists(os.path.join(lfstoredir, 'dirstate')):
126 if create and not os.path.exists(os.path.join(lfstoredir, 'dirstate')):
127 matcher = getstandinmatcher(repo)
127 matcher = getstandinmatcher(repo)
128 standins = repo.dirstate.walk(matcher, [], False, False)
128 standins = repo.dirstate.walk(matcher, [], False, False)
129
129
130 if len(standins) > 0:
130 if len(standins) > 0:
131 util.makedirs(lfstoredir)
131 util.makedirs(lfstoredir)
132
132
133 for standin in standins:
133 for standin in standins:
134 lfile = splitstandin(standin)
134 lfile = splitstandin(standin)
135 lfdirstate.normallookup(lfile)
135 lfdirstate.normallookup(lfile)
136 return lfdirstate
136 return lfdirstate
137
137
138 def lfdirstatestatus(lfdirstate, repo):
138 def lfdirstatestatus(lfdirstate, repo):
139 wctx = repo['.']
139 wctx = repo['.']
140 match = match_.always(repo.root, repo.getcwd())
140 match = match_.always(repo.root, repo.getcwd())
141 unsure, s = lfdirstate.status(match, [], False, False, False)
141 unsure, s = lfdirstate.status(match, [], False, False, False)
142 modified, clean = s.modified, s.clean
142 modified, clean = s.modified, s.clean
143 for lfile in unsure:
143 for lfile in unsure:
144 try:
144 try:
145 fctx = wctx[standin(lfile)]
145 fctx = wctx[standin(lfile)]
146 except LookupError:
146 except LookupError:
147 fctx = None
147 fctx = None
148 if not fctx or fctx.data().strip() != hashfile(repo.wjoin(lfile)):
148 if not fctx or fctx.data().strip() != hashfile(repo.wjoin(lfile)):
149 modified.append(lfile)
149 modified.append(lfile)
150 else:
150 else:
151 clean.append(lfile)
151 clean.append(lfile)
152 lfdirstate.normal(lfile)
152 lfdirstate.normal(lfile)
153 return s
153 return s
154
154
155 def listlfiles(repo, rev=None, matcher=None):
155 def listlfiles(repo, rev=None, matcher=None):
156 '''return a list of largefiles in the working copy or the
156 '''return a list of largefiles in the working copy or the
157 specified changeset'''
157 specified changeset'''
158
158
159 if matcher is None:
159 if matcher is None:
160 matcher = getstandinmatcher(repo)
160 matcher = getstandinmatcher(repo)
161
161
162 # ignore unknown files in working directory
162 # ignore unknown files in working directory
163 return [splitstandin(f)
163 return [splitstandin(f)
164 for f in repo[rev].walk(matcher)
164 for f in repo[rev].walk(matcher)
165 if rev is not None or repo.dirstate[f] != '?']
165 if rev is not None or repo.dirstate[f] != '?']
166
166
167 def instore(repo, hash):
167 def instore(repo, hash):
168 return os.path.exists(storepath(repo, hash))
168 return os.path.exists(storepath(repo, hash))
169
169
170 def storepath(repo, hash):
170 def storepath(repo, hash):
171 return repo.join(os.path.join(longname, hash))
171 return repo.join(os.path.join(longname, hash))
172
172
173 def copyfromcache(repo, hash, filename):
173 def copyfromcache(repo, hash, filename):
174 '''Copy the specified largefile from the repo or system cache to
174 '''Copy the specified largefile from the repo or system cache to
175 filename in the repository. Return true on success or false if the
175 filename in the repository. Return true on success or false if the
176 file was not found in either cache (which should not happened:
176 file was not found in either cache (which should not happened:
177 this is meant to be called only after ensuring that the needed
177 this is meant to be called only after ensuring that the needed
178 largefile exists in the cache).'''
178 largefile exists in the cache).'''
179 path = findfile(repo, hash)
179 path = findfile(repo, hash)
180 if path is None:
180 if path is None:
181 return False
181 return False
182 util.makedirs(os.path.dirname(repo.wjoin(filename)))
182 util.makedirs(os.path.dirname(repo.wjoin(filename)))
183 # The write may fail before the file is fully written, but we
183 # The write may fail before the file is fully written, but we
184 # don't use atomic writes in the working copy.
184 # don't use atomic writes in the working copy.
185 shutil.copy(path, repo.wjoin(filename))
185 shutil.copy(path, repo.wjoin(filename))
186 return True
186 return True
187
187
188 def copytostore(repo, rev, file, uploaded=False):
188 def copytostore(repo, rev, file, uploaded=False):
189 hash = readstandin(repo, file, rev)
189 hash = readstandin(repo, file, rev)
190 if instore(repo, hash):
190 if instore(repo, hash):
191 return
191 return
192 copytostoreabsolute(repo, repo.wjoin(file), hash)
192 copytostoreabsolute(repo, repo.wjoin(file), hash)
193
193
194 def copyalltostore(repo, node):
194 def copyalltostore(repo, node):
195 '''Copy all largefiles in a given revision to the store'''
195 '''Copy all largefiles in a given revision to the store'''
196
196
197 ctx = repo[node]
197 ctx = repo[node]
198 for filename in ctx.files():
198 for filename in ctx.files():
199 if isstandin(filename) and filename in ctx.manifest():
199 if isstandin(filename) and filename in ctx.manifest():
200 realfile = splitstandin(filename)
200 realfile = splitstandin(filename)
201 copytostore(repo, ctx.node(), realfile)
201 copytostore(repo, ctx.node(), realfile)
202
202
203
203
204 def copytostoreabsolute(repo, file, hash):
204 def copytostoreabsolute(repo, file, hash):
205 if inusercache(repo.ui, hash):
205 if inusercache(repo.ui, hash):
206 link(usercachepath(repo.ui, hash), storepath(repo, hash))
206 link(usercachepath(repo.ui, hash), storepath(repo, hash))
207 elif not getattr(repo, "_isconverting", False):
207 elif not getattr(repo, "_isconverting", False):
208 util.makedirs(os.path.dirname(storepath(repo, hash)))
208 util.makedirs(os.path.dirname(storepath(repo, hash)))
209 dst = util.atomictempfile(storepath(repo, hash),
209 dst = util.atomictempfile(storepath(repo, hash),
210 createmode=repo.store.createmode)
210 createmode=repo.store.createmode)
211 for chunk in util.filechunkiter(open(file, 'rb')):
211 for chunk in util.filechunkiter(open(file, 'rb')):
212 dst.write(chunk)
212 dst.write(chunk)
213 dst.close()
213 dst.close()
214 linktousercache(repo, hash)
214 linktousercache(repo, hash)
215
215
216 def linktousercache(repo, hash):
216 def linktousercache(repo, hash):
217 path = usercachepath(repo.ui, hash)
217 path = usercachepath(repo.ui, hash)
218 if path:
218 if path:
219 link(storepath(repo, hash), path)
219 link(storepath(repo, hash), path)
220
220
221 def getstandinmatcher(repo, pats=[], opts={}):
221 def getstandinmatcher(repo, pats=[], opts={}):
222 '''Return a match object that applies pats to the standin directory'''
222 '''Return a match object that applies pats to the standin directory'''
223 standindir = repo.wjoin(shortname)
223 standindir = repo.wjoin(shortname)
224 if pats:
224 if pats:
225 pats = [os.path.join(standindir, pat) for pat in pats]
225 pats = [os.path.join(standindir, pat) for pat in pats]
226 else:
226 else:
227 # no patterns: relative to repo root
227 # no patterns: relative to repo root
228 pats = [standindir]
228 pats = [standindir]
229 # no warnings about missing files or directories
229 # no warnings about missing files or directories
230 match = scmutil.match(repo[None], pats, opts)
230 match = scmutil.match(repo[None], pats, opts)
231 match.bad = lambda f, msg: None
231 match.bad = lambda f, msg: None
232 return match
232 return match
233
233
234 def composestandinmatcher(repo, rmatcher):
234 def composestandinmatcher(repo, rmatcher):
235 '''Return a matcher that accepts standins corresponding to the
235 '''Return a matcher that accepts standins corresponding to the
236 files accepted by rmatcher. Pass the list of files in the matcher
236 files accepted by rmatcher. Pass the list of files in the matcher
237 as the paths specified by the user.'''
237 as the paths specified by the user.'''
238 smatcher = getstandinmatcher(repo, rmatcher.files())
238 smatcher = getstandinmatcher(repo, rmatcher.files())
239 isstandin = smatcher.matchfn
239 isstandin = smatcher.matchfn
240 def composedmatchfn(f):
240 def composedmatchfn(f):
241 return isstandin(f) and rmatcher.matchfn(splitstandin(f))
241 return isstandin(f) and rmatcher.matchfn(splitstandin(f))
242 smatcher.matchfn = composedmatchfn
242 smatcher.matchfn = composedmatchfn
243
243
244 return smatcher
244 return smatcher
245
245
246 def standin(filename):
246 def standin(filename):
247 '''Return the repo-relative path to the standin for the specified big
247 '''Return the repo-relative path to the standin for the specified big
248 file.'''
248 file.'''
249 # Notes:
249 # Notes:
250 # 1) Some callers want an absolute path, but for instance addlargefiles
250 # 1) Some callers want an absolute path, but for instance addlargefiles
251 # needs it repo-relative so it can be passed to repo[None].add(). So
251 # needs it repo-relative so it can be passed to repo[None].add(). So
252 # leave it up to the caller to use repo.wjoin() to get an absolute path.
252 # leave it up to the caller to use repo.wjoin() to get an absolute path.
253 # 2) Join with '/' because that's what dirstate always uses, even on
253 # 2) Join with '/' because that's what dirstate always uses, even on
254 # Windows. Change existing separator to '/' first in case we are
254 # Windows. Change existing separator to '/' first in case we are
255 # passed filenames from an external source (like the command line).
255 # passed filenames from an external source (like the command line).
256 return shortnameslash + util.pconvert(filename)
256 return shortnameslash + util.pconvert(filename)
257
257
258 def isstandin(filename):
258 def isstandin(filename):
259 '''Return true if filename is a big file standin. filename must be
259 '''Return true if filename is a big file standin. filename must be
260 in Mercurial's internal form (slash-separated).'''
260 in Mercurial's internal form (slash-separated).'''
261 return filename.startswith(shortnameslash)
261 return filename.startswith(shortnameslash)
262
262
263 def splitstandin(filename):
263 def splitstandin(filename):
264 # Split on / because that's what dirstate always uses, even on Windows.
264 # Split on / because that's what dirstate always uses, even on Windows.
265 # Change local separator to / first just in case we are passed filenames
265 # Change local separator to / first just in case we are passed filenames
266 # from an external source (like the command line).
266 # from an external source (like the command line).
267 bits = util.pconvert(filename).split('/', 1)
267 bits = util.pconvert(filename).split('/', 1)
268 if len(bits) == 2 and bits[0] == shortname:
268 if len(bits) == 2 and bits[0] == shortname:
269 return bits[1]
269 return bits[1]
270 else:
270 else:
271 return None
271 return None
272
272
273 def updatestandin(repo, standin):
273 def updatestandin(repo, standin):
274 file = repo.wjoin(splitstandin(standin))
274 file = repo.wjoin(splitstandin(standin))
275 if os.path.exists(file):
275 if os.path.exists(file):
276 hash = hashfile(file)
276 hash = hashfile(file)
277 executable = getexecutable(file)
277 executable = getexecutable(file)
278 writestandin(repo, standin, hash, executable)
278 writestandin(repo, standin, hash, executable)
279
279
280 def readstandin(repo, filename, node=None):
280 def readstandin(repo, filename, node=None):
281 '''read hex hash from standin for filename at given node, or working
281 '''read hex hash from standin for filename at given node, or working
282 directory if no node is given'''
282 directory if no node is given'''
283 return repo[node][standin(filename)].data().strip()
283 return repo[node][standin(filename)].data().strip()
284
284
285 def writestandin(repo, standin, hash, executable):
285 def writestandin(repo, standin, hash, executable):
286 '''write hash to <repo.root>/<standin>'''
286 '''write hash to <repo.root>/<standin>'''
287 repo.wwrite(standin, hash + '\n', executable and 'x' or '')
287 repo.wwrite(standin, hash + '\n', executable and 'x' or '')
288
288
289 def copyandhash(instream, outfile):
289 def copyandhash(instream, outfile):
290 '''Read bytes from instream (iterable) and write them to outfile,
290 '''Read bytes from instream (iterable) and write them to outfile,
291 computing the SHA-1 hash of the data along the way. Return the hash.'''
291 computing the SHA-1 hash of the data along the way. Return the hash.'''
292 hasher = util.sha1('')
292 hasher = util.sha1('')
293 for data in instream:
293 for data in instream:
294 hasher.update(data)
294 hasher.update(data)
295 outfile.write(data)
295 outfile.write(data)
296 return hasher.hexdigest()
296 return hasher.hexdigest()
297
297
298 def hashrepofile(repo, file):
298 def hashrepofile(repo, file):
299 return hashfile(repo.wjoin(file))
299 return hashfile(repo.wjoin(file))
300
300
301 def hashfile(file):
301 def hashfile(file):
302 if not os.path.exists(file):
302 if not os.path.exists(file):
303 return ''
303 return ''
304 hasher = util.sha1('')
304 hasher = util.sha1('')
305 fd = open(file, 'rb')
305 fd = open(file, 'rb')
306 for data in util.filechunkiter(fd, 128 * 1024):
306 for data in util.filechunkiter(fd, 128 * 1024):
307 hasher.update(data)
307 hasher.update(data)
308 fd.close()
308 fd.close()
309 return hasher.hexdigest()
309 return hasher.hexdigest()
310
310
311 def getexecutable(filename):
311 def getexecutable(filename):
312 mode = os.stat(filename).st_mode
312 mode = os.stat(filename).st_mode
313 return ((mode & stat.S_IXUSR) and
313 return ((mode & stat.S_IXUSR) and
314 (mode & stat.S_IXGRP) and
314 (mode & stat.S_IXGRP) and
315 (mode & stat.S_IXOTH))
315 (mode & stat.S_IXOTH))
316
316
317 def urljoin(first, second, *arg):
317 def urljoin(first, second, *arg):
318 def join(left, right):
318 def join(left, right):
319 if not left.endswith('/'):
319 if not left.endswith('/'):
320 left += '/'
320 left += '/'
321 if right.startswith('/'):
321 if right.startswith('/'):
322 right = right[1:]
322 right = right[1:]
323 return left + right
323 return left + right
324
324
325 url = join(first, second)
325 url = join(first, second)
326 for a in arg:
326 for a in arg:
327 url = join(url, a)
327 url = join(url, a)
328 return url
328 return url
329
329
330 def hexsha1(data):
330 def hexsha1(data):
331 """hexsha1 returns the hex-encoded sha1 sum of the data in the file-like
331 """hexsha1 returns the hex-encoded sha1 sum of the data in the file-like
332 object data"""
332 object data"""
333 h = util.sha1()
333 h = util.sha1()
334 for chunk in util.filechunkiter(data):
334 for chunk in util.filechunkiter(data):
335 h.update(chunk)
335 h.update(chunk)
336 return h.hexdigest()
336 return h.hexdigest()
337
337
338 def httpsendfile(ui, filename):
338 def httpsendfile(ui, filename):
339 return httpconnection.httpsendfile(ui, filename, 'rb')
339 return httpconnection.httpsendfile(ui, filename, 'rb')
340
340
341 def unixpath(path):
341 def unixpath(path):
342 '''Return a version of path normalized for use with the lfdirstate.'''
342 '''Return a version of path normalized for use with the lfdirstate.'''
343 return util.pconvert(os.path.normpath(path))
343 return util.pconvert(os.path.normpath(path))
344
344
345 def islfilesrepo(repo):
345 def islfilesrepo(repo):
346 if ('largefiles' in repo.requirements and
346 if ('largefiles' in repo.requirements and
347 util.any(shortnameslash in f[0] for f in repo.store.datafiles())):
347 util.any(shortnameslash in f[0] for f in repo.store.datafiles())):
348 return True
348 return True
349
349
350 return util.any(openlfdirstate(repo.ui, repo, False))
350 return util.any(openlfdirstate(repo.ui, repo, False))
351
351
352 class storeprotonotcapable(Exception):
352 class storeprotonotcapable(Exception):
353 def __init__(self, storetypes):
353 def __init__(self, storetypes):
354 self.storetypes = storetypes
354 self.storetypes = storetypes
355
355
356 def getstandinsstate(repo):
356 def getstandinsstate(repo):
357 standins = []
357 standins = []
358 matcher = getstandinmatcher(repo)
358 matcher = getstandinmatcher(repo)
359 for standin in repo.dirstate.walk(matcher, [], False, False):
359 for standin in repo.dirstate.walk(matcher, [], False, False):
360 lfile = splitstandin(standin)
360 lfile = splitstandin(standin)
361 try:
361 try:
362 hash = readstandin(repo, lfile)
362 hash = readstandin(repo, lfile)
363 except IOError:
363 except IOError:
364 hash = None
364 hash = None
365 standins.append((lfile, hash))
365 standins.append((lfile, hash))
366 return standins
366 return standins
367
367
368 def synclfdirstate(repo, lfdirstate, lfile, normallookup):
368 def synclfdirstate(repo, lfdirstate, lfile, normallookup):
369 lfstandin = standin(lfile)
369 lfstandin = standin(lfile)
370 if lfstandin in repo.dirstate:
370 if lfstandin in repo.dirstate:
371 stat = repo.dirstate._map[lfstandin]
371 stat = repo.dirstate._map[lfstandin]
372 state, mtime = stat[0], stat[3]
372 state, mtime = stat[0], stat[3]
373 else:
373 else:
374 state, mtime = '?', -1
374 state, mtime = '?', -1
375 if state == 'n':
375 if state == 'n':
376 if normallookup or mtime < 0:
376 if normallookup or mtime < 0:
377 # state 'n' doesn't ensure 'clean' in this case
377 # state 'n' doesn't ensure 'clean' in this case
378 lfdirstate.normallookup(lfile)
378 lfdirstate.normallookup(lfile)
379 else:
379 else:
380 lfdirstate.normal(lfile)
380 lfdirstate.normal(lfile)
381 elif state == 'm':
381 elif state == 'm':
382 lfdirstate.normallookup(lfile)
382 lfdirstate.normallookup(lfile)
383 elif state == 'r':
383 elif state == 'r':
384 lfdirstate.remove(lfile)
384 lfdirstate.remove(lfile)
385 elif state == 'a':
385 elif state == 'a':
386 lfdirstate.add(lfile)
386 lfdirstate.add(lfile)
387 elif state == '?':
387 elif state == '?':
388 lfdirstate.drop(lfile)
388 lfdirstate.drop(lfile)
389
389
390 def markcommitted(orig, ctx, node):
390 def markcommitted(orig, ctx, node):
391 repo = ctx._repo
391 repo = ctx._repo
392
392
393 orig(node)
393 orig(node)
394
394
395 # ATTENTION: "ctx.files()" may differ from "repo[node].files()"
396 # because files coming from the 2nd parent are omitted in the latter.
397 #
398 # The former should be used to get targets of "synclfdirstate",
399 # because such files:
400 # - are marked as "a" by "patch.patch()" (e.g. via transplant), and
401 # - have to be marked as "n" after commit, but
402 # - aren't listed in "repo[node].files()"
403
395 lfdirstate = openlfdirstate(repo.ui, repo)
404 lfdirstate = openlfdirstate(repo.ui, repo)
396 for f in ctx.files():
405 for f in ctx.files():
397 if isstandin(f):
406 if isstandin(f):
398 lfile = splitstandin(f)
407 lfile = splitstandin(f)
399 synclfdirstate(repo, lfdirstate, lfile, False)
408 synclfdirstate(repo, lfdirstate, lfile, False)
400 lfdirstate.write()
409 lfdirstate.write()
401
410
402 def getlfilestoupdate(oldstandins, newstandins):
411 def getlfilestoupdate(oldstandins, newstandins):
403 changedstandins = set(oldstandins).symmetric_difference(set(newstandins))
412 changedstandins = set(oldstandins).symmetric_difference(set(newstandins))
404 filelist = []
413 filelist = []
405 for f in changedstandins:
414 for f in changedstandins:
406 if f[0] not in filelist:
415 if f[0] not in filelist:
407 filelist.append(f[0])
416 filelist.append(f[0])
408 return filelist
417 return filelist
409
418
410 def getlfilestoupload(repo, missing, addfunc):
419 def getlfilestoupload(repo, missing, addfunc):
411 for n in missing:
420 for n in missing:
412 parents = [p for p in repo.changelog.parents(n) if p != node.nullid]
421 parents = [p for p in repo.changelog.parents(n) if p != node.nullid]
413 ctx = repo[n]
422 ctx = repo[n]
414 files = set(ctx.files())
423 files = set(ctx.files())
415 if len(parents) == 2:
424 if len(parents) == 2:
416 mc = ctx.manifest()
425 mc = ctx.manifest()
417 mp1 = ctx.parents()[0].manifest()
426 mp1 = ctx.parents()[0].manifest()
418 mp2 = ctx.parents()[1].manifest()
427 mp2 = ctx.parents()[1].manifest()
419 for f in mp1:
428 for f in mp1:
420 if f not in mc:
429 if f not in mc:
421 files.add(f)
430 files.add(f)
422 for f in mp2:
431 for f in mp2:
423 if f not in mc:
432 if f not in mc:
424 files.add(f)
433 files.add(f)
425 for f in mc:
434 for f in mc:
426 if mc[f] != mp1.get(f, None) or mc[f] != mp2.get(f, None):
435 if mc[f] != mp1.get(f, None) or mc[f] != mp2.get(f, None):
427 files.add(f)
436 files.add(f)
428 for fn in files:
437 for fn in files:
429 if isstandin(fn) and fn in ctx:
438 if isstandin(fn) and fn in ctx:
430 addfunc(fn, ctx[fn].data().strip())
439 addfunc(fn, ctx[fn].data().strip())
431
440
432 def updatestandinsbymatch(repo, match):
441 def updatestandinsbymatch(repo, match):
433 '''Update standins in the working directory according to specified match
442 '''Update standins in the working directory according to specified match
434
443
435 This returns (possibly modified) ``match`` object to be used for
444 This returns (possibly modified) ``match`` object to be used for
436 subsequent commit process.
445 subsequent commit process.
437 '''
446 '''
438
447
439 ui = repo.ui
448 ui = repo.ui
440
449
441 # Case 0: Automated committing
450 # Case 0: Automated committing
442 #
451 #
443 # While automated committing (like rebase, transplant
452 # While automated committing (like rebase, transplant
444 # and so on), this code path is used to avoid:
453 # and so on), this code path is used to avoid:
445 # (1) updating standins, because standins should
454 # (1) updating standins, because standins should
446 # be already updated at this point
455 # be already updated at this point
447 # (2) aborting when standins are matched by "match",
456 # (2) aborting when standins are matched by "match",
448 # because automated committing may specify them directly
457 # because automated committing may specify them directly
449 #
458 #
450 if getattr(repo, "_istransplanting", False):
459 if getattr(repo, "_istransplanting", False):
451 return match
460 return match
452
461
453 # Case 1: user calls commit with no specific files or
462 # Case 1: user calls commit with no specific files or
454 # include/exclude patterns: refresh and commit all files that
463 # include/exclude patterns: refresh and commit all files that
455 # are "dirty".
464 # are "dirty".
456 if match is None or match.always():
465 if match is None or match.always():
457 # Spend a bit of time here to get a list of files we know
466 # Spend a bit of time here to get a list of files we know
458 # are modified so we can compare only against those.
467 # are modified so we can compare only against those.
459 # It can cost a lot of time (several seconds)
468 # It can cost a lot of time (several seconds)
460 # otherwise to update all standins if the largefiles are
469 # otherwise to update all standins if the largefiles are
461 # large.
470 # large.
462 lfdirstate = openlfdirstate(ui, repo)
471 lfdirstate = openlfdirstate(ui, repo)
463 dirtymatch = match_.always(repo.root, repo.getcwd())
472 dirtymatch = match_.always(repo.root, repo.getcwd())
464 unsure, s = lfdirstate.status(dirtymatch, [], False, False,
473 unsure, s = lfdirstate.status(dirtymatch, [], False, False,
465 False)
474 False)
466 modifiedfiles = unsure + s.modified + s.added + s.removed
475 modifiedfiles = unsure + s.modified + s.added + s.removed
467 lfiles = listlfiles(repo)
476 lfiles = listlfiles(repo)
468 # this only loops through largefiles that exist (not
477 # this only loops through largefiles that exist (not
469 # removed/renamed)
478 # removed/renamed)
470 for lfile in lfiles:
479 for lfile in lfiles:
471 if lfile in modifiedfiles:
480 if lfile in modifiedfiles:
472 if os.path.exists(
481 if os.path.exists(
473 repo.wjoin(standin(lfile))):
482 repo.wjoin(standin(lfile))):
474 # this handles the case where a rebase is being
483 # this handles the case where a rebase is being
475 # performed and the working copy is not updated
484 # performed and the working copy is not updated
476 # yet.
485 # yet.
477 if os.path.exists(repo.wjoin(lfile)):
486 if os.path.exists(repo.wjoin(lfile)):
478 updatestandin(repo,
487 updatestandin(repo,
479 standin(lfile))
488 standin(lfile))
480
489
481 return match
490 return match
482
491
483 lfiles = listlfiles(repo)
492 lfiles = listlfiles(repo)
484 match._files = repo._subdirlfs(match.files(), lfiles)
493 match._files = repo._subdirlfs(match.files(), lfiles)
485
494
486 # Case 2: user calls commit with specified patterns: refresh
495 # Case 2: user calls commit with specified patterns: refresh
487 # any matching big files.
496 # any matching big files.
488 smatcher = composestandinmatcher(repo, match)
497 smatcher = composestandinmatcher(repo, match)
489 standins = repo.dirstate.walk(smatcher, [], False, False)
498 standins = repo.dirstate.walk(smatcher, [], False, False)
490
499
491 # No matching big files: get out of the way and pass control to
500 # No matching big files: get out of the way and pass control to
492 # the usual commit() method.
501 # the usual commit() method.
493 if not standins:
502 if not standins:
494 return match
503 return match
495
504
496 # Refresh all matching big files. It's possible that the
505 # Refresh all matching big files. It's possible that the
497 # commit will end up failing, in which case the big files will
506 # commit will end up failing, in which case the big files will
498 # stay refreshed. No harm done: the user modified them and
507 # stay refreshed. No harm done: the user modified them and
499 # asked to commit them, so sooner or later we're going to
508 # asked to commit them, so sooner or later we're going to
500 # refresh the standins. Might as well leave them refreshed.
509 # refresh the standins. Might as well leave them refreshed.
501 lfdirstate = openlfdirstate(ui, repo)
510 lfdirstate = openlfdirstate(ui, repo)
502 for fstandin in standins:
511 for fstandin in standins:
503 lfile = splitstandin(fstandin)
512 lfile = splitstandin(fstandin)
504 if lfdirstate[lfile] != 'r':
513 if lfdirstate[lfile] != 'r':
505 updatestandin(repo, fstandin)
514 updatestandin(repo, fstandin)
506
515
507 # Cook up a new matcher that only matches regular files or
516 # Cook up a new matcher that only matches regular files or
508 # standins corresponding to the big files requested by the
517 # standins corresponding to the big files requested by the
509 # user. Have to modify _files to prevent commit() from
518 # user. Have to modify _files to prevent commit() from
510 # complaining "not tracked" for big files.
519 # complaining "not tracked" for big files.
511 match = copy.copy(match)
520 match = copy.copy(match)
512 origmatchfn = match.matchfn
521 origmatchfn = match.matchfn
513
522
514 # Check both the list of largefiles and the list of
523 # Check both the list of largefiles and the list of
515 # standins because if a largefile was removed, it
524 # standins because if a largefile was removed, it
516 # won't be in the list of largefiles at this point
525 # won't be in the list of largefiles at this point
517 match._files += sorted(standins)
526 match._files += sorted(standins)
518
527
519 actualfiles = []
528 actualfiles = []
520 for f in match._files:
529 for f in match._files:
521 fstandin = standin(f)
530 fstandin = standin(f)
522
531
523 # ignore known largefiles and standins
532 # ignore known largefiles and standins
524 if f in lfiles or fstandin in standins:
533 if f in lfiles or fstandin in standins:
525 continue
534 continue
526
535
527 actualfiles.append(f)
536 actualfiles.append(f)
528 match._files = actualfiles
537 match._files = actualfiles
529
538
530 def matchfn(f):
539 def matchfn(f):
531 if origmatchfn(f):
540 if origmatchfn(f):
532 return f not in lfiles
541 return f not in lfiles
533 else:
542 else:
534 return f in standins
543 return f in standins
535
544
536 match.matchfn = matchfn
545 match.matchfn = matchfn
537
546
538 return match
547 return match
539
548
540 class automatedcommithook(object):
549 class automatedcommithook(object):
541 '''Statefull hook to update standins at the 1st commit of resuming
550 '''Statefull hook to update standins at the 1st commit of resuming
542
551
543 For efficiency, updating standins in the working directory should
552 For efficiency, updating standins in the working directory should
544 be avoided while automated committing (like rebase, transplant and
553 be avoided while automated committing (like rebase, transplant and
545 so on), because they should be updated before committing.
554 so on), because they should be updated before committing.
546
555
547 But the 1st commit of resuming automated committing (e.g. ``rebase
556 But the 1st commit of resuming automated committing (e.g. ``rebase
548 --continue``) should update them, because largefiles may be
557 --continue``) should update them, because largefiles may be
549 modified manually.
558 modified manually.
550 '''
559 '''
551 def __init__(self, resuming):
560 def __init__(self, resuming):
552 self.resuming = resuming
561 self.resuming = resuming
553
562
554 def __call__(self, repo, match):
563 def __call__(self, repo, match):
555 if self.resuming:
564 if self.resuming:
556 self.resuming = False # avoids updating at subsequent commits
565 self.resuming = False # avoids updating at subsequent commits
557 return updatestandinsbymatch(repo, match)
566 return updatestandinsbymatch(repo, match)
558 else:
567 else:
559 return match
568 return match
560
569
561 def getstatuswriter(ui, repo, forcibly=None):
570 def getstatuswriter(ui, repo, forcibly=None):
562 '''Return the function to write largefiles specific status out
571 '''Return the function to write largefiles specific status out
563
572
564 If ``forcibly`` is ``None``, this returns the last element of
573 If ``forcibly`` is ``None``, this returns the last element of
565 ``repo._lfupdatereporters`` as "default" writer function.
574 ``repo._lfupdatereporters`` as "default" writer function.
566
575
567 Otherwise, this returns the function to always write out (or
576 Otherwise, this returns the function to always write out (or
568 ignore if ``not forcibly``) status.
577 ignore if ``not forcibly``) status.
569 '''
578 '''
570 if forcibly is None:
579 if forcibly is None:
571 return repo._lfstatuswriters[-1]
580 return repo._lfstatuswriters[-1]
572 else:
581 else:
573 if forcibly:
582 if forcibly:
574 return ui.status # forcibly WRITE OUT
583 return ui.status # forcibly WRITE OUT
575 else:
584 else:
576 return lambda *msg, **opts: None # forcibly IGNORE
585 return lambda *msg, **opts: None # forcibly IGNORE
@@ -1,1302 +1,1297 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, util, cmdutil, scmutil, match as match_, \
14 from mercurial import hg, util, cmdutil, scmutil, match as match_, \
15 archival, pathutil, revset
15 archival, pathutil, revset
16 from mercurial.i18n import _
16 from mercurial.i18n import _
17 from mercurial.node import hex
17 from mercurial.node import hex
18
18
19 import lfutil
19 import lfutil
20 import lfcommands
20 import lfcommands
21 import basestore
21 import basestore
22
22
23 # -- Utility functions: commonly/repeatedly needed functionality ---------------
23 # -- Utility functions: commonly/repeatedly needed functionality ---------------
24
24
25 def installnormalfilesmatchfn(manifest):
25 def installnormalfilesmatchfn(manifest):
26 '''installmatchfn with a matchfn that ignores all largefiles'''
26 '''installmatchfn with a matchfn that ignores all largefiles'''
27 def overridematch(ctx, pats=[], opts={}, globbed=False,
27 def overridematch(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 m._always = False
35 m._always = False
36 origmatchfn = m.matchfn
36 origmatchfn = m.matchfn
37 m.matchfn = lambda f: notlfile(f) and origmatchfn(f)
37 m.matchfn = lambda f: notlfile(f) and origmatchfn(f)
38 return m
38 return m
39 oldmatch = installmatchfn(overridematch)
39 oldmatch = installmatchfn(overridematch)
40
40
41 def installmatchfn(f):
41 def installmatchfn(f):
42 '''monkey patch the scmutil module with a custom match function.
42 '''monkey patch the scmutil module with a custom match function.
43 Warning: it is monkey patching the _module_ on runtime! Not thread safe!'''
43 Warning: it is monkey patching the _module_ on runtime! Not thread safe!'''
44 oldmatch = scmutil.match
44 oldmatch = scmutil.match
45 setattr(f, 'oldmatch', oldmatch)
45 setattr(f, 'oldmatch', oldmatch)
46 scmutil.match = f
46 scmutil.match = f
47 return oldmatch
47 return oldmatch
48
48
49 def restorematchfn():
49 def restorematchfn():
50 '''restores scmutil.match to what it was before installmatchfn
50 '''restores scmutil.match to what it was before installmatchfn
51 was called. no-op if scmutil.match is its original function.
51 was called. no-op if scmutil.match is its original function.
52
52
53 Note that n calls to installmatchfn will require n calls to
53 Note that n calls to installmatchfn will require n calls to
54 restore matchfn to reverse'''
54 restore matchfn to reverse'''
55 scmutil.match = getattr(scmutil.match, 'oldmatch')
55 scmutil.match = getattr(scmutil.match, 'oldmatch')
56
56
57 def installmatchandpatsfn(f):
57 def installmatchandpatsfn(f):
58 oldmatchandpats = scmutil.matchandpats
58 oldmatchandpats = scmutil.matchandpats
59 setattr(f, 'oldmatchandpats', oldmatchandpats)
59 setattr(f, 'oldmatchandpats', oldmatchandpats)
60 scmutil.matchandpats = f
60 scmutil.matchandpats = f
61 return oldmatchandpats
61 return oldmatchandpats
62
62
63 def restorematchandpatsfn():
63 def restorematchandpatsfn():
64 '''restores scmutil.matchandpats to what it was before
64 '''restores scmutil.matchandpats to what it was before
65 installmatchandpatsfn was called. No-op if scmutil.matchandpats
65 installmatchandpatsfn was called. No-op if scmutil.matchandpats
66 is its original function.
66 is its original function.
67
67
68 Note that n calls to installmatchandpatsfn will require n calls
68 Note that n calls to installmatchandpatsfn will require n calls
69 to restore matchfn to reverse'''
69 to restore matchfn to reverse'''
70 scmutil.matchandpats = getattr(scmutil.matchandpats, 'oldmatchandpats',
70 scmutil.matchandpats = getattr(scmutil.matchandpats, 'oldmatchandpats',
71 scmutil.matchandpats)
71 scmutil.matchandpats)
72
72
73 def addlargefiles(ui, repo, *pats, **opts):
73 def addlargefiles(ui, repo, *pats, **opts):
74 large = opts.pop('large', None)
74 large = opts.pop('large', None)
75 lfsize = lfutil.getminsize(
75 lfsize = lfutil.getminsize(
76 ui, lfutil.islfilesrepo(repo), opts.pop('lfsize', None))
76 ui, lfutil.islfilesrepo(repo), opts.pop('lfsize', None))
77
77
78 lfmatcher = None
78 lfmatcher = None
79 if lfutil.islfilesrepo(repo):
79 if lfutil.islfilesrepo(repo):
80 lfpats = ui.configlist(lfutil.longname, 'patterns', default=[])
80 lfpats = ui.configlist(lfutil.longname, 'patterns', default=[])
81 if lfpats:
81 if lfpats:
82 lfmatcher = match_.match(repo.root, '', list(lfpats))
82 lfmatcher = match_.match(repo.root, '', list(lfpats))
83
83
84 lfnames = []
84 lfnames = []
85 m = scmutil.match(repo[None], pats, opts)
85 m = scmutil.match(repo[None], pats, opts)
86 m.bad = lambda x, y: None
86 m.bad = lambda x, y: None
87 wctx = repo[None]
87 wctx = repo[None]
88 for f in repo.walk(m):
88 for f in repo.walk(m):
89 exact = m.exact(f)
89 exact = m.exact(f)
90 lfile = lfutil.standin(f) in wctx
90 lfile = lfutil.standin(f) in wctx
91 nfile = f in wctx
91 nfile = f in wctx
92 exists = lfile or nfile
92 exists = lfile or nfile
93
93
94 # Don't warn the user when they attempt to add a normal tracked file.
94 # Don't warn the user when they attempt to add a normal tracked file.
95 # The normal add code will do that for us.
95 # The normal add code will do that for us.
96 if exact and exists:
96 if exact and exists:
97 if lfile:
97 if lfile:
98 ui.warn(_('%s already a largefile\n') % f)
98 ui.warn(_('%s already a largefile\n') % f)
99 continue
99 continue
100
100
101 if (exact or not exists) and not lfutil.isstandin(f):
101 if (exact or not exists) and not lfutil.isstandin(f):
102 wfile = repo.wjoin(f)
102 wfile = repo.wjoin(f)
103
103
104 # In case the file was removed previously, but not committed
104 # In case the file was removed previously, but not committed
105 # (issue3507)
105 # (issue3507)
106 if not os.path.exists(wfile):
106 if not os.path.exists(wfile):
107 continue
107 continue
108
108
109 abovemin = (lfsize and
109 abovemin = (lfsize and
110 os.lstat(wfile).st_size >= lfsize * 1024 * 1024)
110 os.lstat(wfile).st_size >= lfsize * 1024 * 1024)
111 if large or abovemin or (lfmatcher and lfmatcher(f)):
111 if large or abovemin or (lfmatcher and lfmatcher(f)):
112 lfnames.append(f)
112 lfnames.append(f)
113 if ui.verbose or not exact:
113 if ui.verbose or not exact:
114 ui.status(_('adding %s as a largefile\n') % m.rel(f))
114 ui.status(_('adding %s as a largefile\n') % m.rel(f))
115
115
116 bad = []
116 bad = []
117
117
118 # Need to lock, otherwise there could be a race condition between
118 # Need to lock, otherwise there could be a race condition between
119 # when standins are created and added to the repo.
119 # when standins are created and added to the repo.
120 wlock = repo.wlock()
120 wlock = repo.wlock()
121 try:
121 try:
122 if not opts.get('dry_run'):
122 if not opts.get('dry_run'):
123 standins = []
123 standins = []
124 lfdirstate = lfutil.openlfdirstate(ui, repo)
124 lfdirstate = lfutil.openlfdirstate(ui, repo)
125 for f in lfnames:
125 for f in lfnames:
126 standinname = lfutil.standin(f)
126 standinname = lfutil.standin(f)
127 lfutil.writestandin(repo, standinname, hash='',
127 lfutil.writestandin(repo, standinname, hash='',
128 executable=lfutil.getexecutable(repo.wjoin(f)))
128 executable=lfutil.getexecutable(repo.wjoin(f)))
129 standins.append(standinname)
129 standins.append(standinname)
130 if lfdirstate[f] == 'r':
130 if lfdirstate[f] == 'r':
131 lfdirstate.normallookup(f)
131 lfdirstate.normallookup(f)
132 else:
132 else:
133 lfdirstate.add(f)
133 lfdirstate.add(f)
134 lfdirstate.write()
134 lfdirstate.write()
135 bad += [lfutil.splitstandin(f)
135 bad += [lfutil.splitstandin(f)
136 for f in repo[None].add(standins)
136 for f in repo[None].add(standins)
137 if f in m.files()]
137 if f in m.files()]
138 finally:
138 finally:
139 wlock.release()
139 wlock.release()
140 return bad
140 return bad
141
141
142 def removelargefiles(ui, repo, isaddremove, *pats, **opts):
142 def removelargefiles(ui, repo, isaddremove, *pats, **opts):
143 after = opts.get('after')
143 after = opts.get('after')
144 if not pats and not after:
144 if not pats and not after:
145 raise util.Abort(_('no files specified'))
145 raise util.Abort(_('no files specified'))
146 m = scmutil.match(repo[None], pats, opts)
146 m = scmutil.match(repo[None], pats, opts)
147 try:
147 try:
148 repo.lfstatus = True
148 repo.lfstatus = True
149 s = repo.status(match=m, clean=True)
149 s = repo.status(match=m, clean=True)
150 finally:
150 finally:
151 repo.lfstatus = False
151 repo.lfstatus = False
152 manifest = repo[None].manifest()
152 manifest = repo[None].manifest()
153 modified, added, deleted, clean = [[f for f in list
153 modified, added, deleted, clean = [[f for f in list
154 if lfutil.standin(f) in manifest]
154 if lfutil.standin(f) in manifest]
155 for list in (s.modified, s.added,
155 for list in (s.modified, s.added,
156 s.deleted, s.clean)]
156 s.deleted, s.clean)]
157
157
158 def warn(files, msg):
158 def warn(files, msg):
159 for f in files:
159 for f in files:
160 ui.warn(msg % m.rel(f))
160 ui.warn(msg % m.rel(f))
161 return int(len(files) > 0)
161 return int(len(files) > 0)
162
162
163 result = 0
163 result = 0
164
164
165 if after:
165 if after:
166 remove = deleted
166 remove = deleted
167 result = warn(modified + added + clean,
167 result = warn(modified + added + clean,
168 _('not removing %s: file still exists\n'))
168 _('not removing %s: file still exists\n'))
169 else:
169 else:
170 remove = deleted + clean
170 remove = deleted + clean
171 result = warn(modified, _('not removing %s: file is modified (use -f'
171 result = warn(modified, _('not removing %s: file is modified (use -f'
172 ' to force removal)\n'))
172 ' to force removal)\n'))
173 result = warn(added, _('not removing %s: file has been marked for add'
173 result = warn(added, _('not removing %s: file has been marked for add'
174 ' (use forget to undo)\n')) or result
174 ' (use forget to undo)\n')) or result
175
175
176 for f in sorted(remove):
176 for f in sorted(remove):
177 if ui.verbose or not m.exact(f):
177 if ui.verbose or not m.exact(f):
178 ui.status(_('removing %s\n') % m.rel(f))
178 ui.status(_('removing %s\n') % m.rel(f))
179
179
180 # Need to lock because standin files are deleted then removed from the
180 # Need to lock because standin files are deleted then removed from the
181 # repository and we could race in-between.
181 # repository and we could race in-between.
182 wlock = repo.wlock()
182 wlock = repo.wlock()
183 try:
183 try:
184 lfdirstate = lfutil.openlfdirstate(ui, repo)
184 lfdirstate = lfutil.openlfdirstate(ui, repo)
185 for f in remove:
185 for f in remove:
186 if not after:
186 if not after:
187 # If this is being called by addremove, notify the user that we
187 # If this is being called by addremove, notify the user that we
188 # are removing the file.
188 # are removing the file.
189 if isaddremove:
189 if isaddremove:
190 ui.status(_('removing %s\n') % f)
190 ui.status(_('removing %s\n') % f)
191 util.unlinkpath(repo.wjoin(f), ignoremissing=True)
191 util.unlinkpath(repo.wjoin(f), ignoremissing=True)
192 lfdirstate.remove(f)
192 lfdirstate.remove(f)
193 lfdirstate.write()
193 lfdirstate.write()
194 remove = [lfutil.standin(f) for f in remove]
194 remove = [lfutil.standin(f) for f in remove]
195 # If this is being called by addremove, let the original addremove
195 # If this is being called by addremove, let the original addremove
196 # function handle this.
196 # function handle this.
197 if not isaddremove:
197 if not isaddremove:
198 for f in remove:
198 for f in remove:
199 util.unlinkpath(repo.wjoin(f), ignoremissing=True)
199 util.unlinkpath(repo.wjoin(f), ignoremissing=True)
200 repo[None].forget(remove)
200 repo[None].forget(remove)
201 finally:
201 finally:
202 wlock.release()
202 wlock.release()
203
203
204 return result
204 return result
205
205
206 # For overriding mercurial.hgweb.webcommands so that largefiles will
206 # For overriding mercurial.hgweb.webcommands so that largefiles will
207 # appear at their right place in the manifests.
207 # appear at their right place in the manifests.
208 def decodepath(orig, path):
208 def decodepath(orig, path):
209 return lfutil.splitstandin(path) or path
209 return lfutil.splitstandin(path) or path
210
210
211 # -- Wrappers: modify existing commands --------------------------------
211 # -- Wrappers: modify existing commands --------------------------------
212
212
213 # Add works by going through the files that the user wanted to add and
213 # Add works by going through the files that the user wanted to add and
214 # checking if they should be added as largefiles. Then it makes a new
214 # checking if they should be added as largefiles. Then it makes a new
215 # matcher which matches only the normal files and runs the original
215 # matcher which matches only the normal files and runs the original
216 # version of add.
216 # version of add.
217 def overrideadd(orig, ui, repo, *pats, **opts):
217 def overrideadd(orig, ui, repo, *pats, **opts):
218 normal = opts.pop('normal')
218 normal = opts.pop('normal')
219 if normal:
219 if normal:
220 if opts.get('large'):
220 if opts.get('large'):
221 raise util.Abort(_('--normal cannot be used with --large'))
221 raise util.Abort(_('--normal cannot be used with --large'))
222 return orig(ui, repo, *pats, **opts)
222 return orig(ui, repo, *pats, **opts)
223 bad = addlargefiles(ui, repo, *pats, **opts)
223 bad = addlargefiles(ui, repo, *pats, **opts)
224 installnormalfilesmatchfn(repo[None].manifest())
224 installnormalfilesmatchfn(repo[None].manifest())
225 result = orig(ui, repo, *pats, **opts)
225 result = orig(ui, repo, *pats, **opts)
226 restorematchfn()
226 restorematchfn()
227
227
228 return (result == 1 or bad) and 1 or 0
228 return (result == 1 or bad) and 1 or 0
229
229
230 def overrideremove(orig, ui, repo, *pats, **opts):
230 def overrideremove(orig, ui, repo, *pats, **opts):
231 installnormalfilesmatchfn(repo[None].manifest())
231 installnormalfilesmatchfn(repo[None].manifest())
232 result = orig(ui, repo, *pats, **opts)
232 result = orig(ui, repo, *pats, **opts)
233 restorematchfn()
233 restorematchfn()
234 return removelargefiles(ui, repo, False, *pats, **opts) or result
234 return removelargefiles(ui, repo, False, *pats, **opts) or result
235
235
236 def overridestatusfn(orig, repo, rev2, **opts):
236 def overridestatusfn(orig, repo, rev2, **opts):
237 try:
237 try:
238 repo._repo.lfstatus = True
238 repo._repo.lfstatus = True
239 return orig(repo, rev2, **opts)
239 return orig(repo, rev2, **opts)
240 finally:
240 finally:
241 repo._repo.lfstatus = False
241 repo._repo.lfstatus = False
242
242
243 def overridestatus(orig, ui, repo, *pats, **opts):
243 def overridestatus(orig, ui, repo, *pats, **opts):
244 try:
244 try:
245 repo.lfstatus = True
245 repo.lfstatus = True
246 return orig(ui, repo, *pats, **opts)
246 return orig(ui, repo, *pats, **opts)
247 finally:
247 finally:
248 repo.lfstatus = False
248 repo.lfstatus = False
249
249
250 def overridedirty(orig, repo, ignoreupdate=False):
250 def overridedirty(orig, repo, ignoreupdate=False):
251 try:
251 try:
252 repo._repo.lfstatus = True
252 repo._repo.lfstatus = True
253 return orig(repo, ignoreupdate)
253 return orig(repo, ignoreupdate)
254 finally:
254 finally:
255 repo._repo.lfstatus = False
255 repo._repo.lfstatus = False
256
256
257 def overridelog(orig, ui, repo, *pats, **opts):
257 def overridelog(orig, ui, repo, *pats, **opts):
258 def overridematchandpats(ctx, pats=[], opts={}, globbed=False,
258 def overridematchandpats(ctx, pats=[], opts={}, globbed=False,
259 default='relpath'):
259 default='relpath'):
260 """Matcher that merges root directory with .hglf, suitable for log.
260 """Matcher that merges root directory with .hglf, suitable for log.
261 It is still possible to match .hglf directly.
261 It is still possible to match .hglf directly.
262 For any listed files run log on the standin too.
262 For any listed files run log on the standin too.
263 matchfn tries both the given filename and with .hglf stripped.
263 matchfn tries both the given filename and with .hglf stripped.
264 """
264 """
265 matchandpats = oldmatchandpats(ctx, pats, opts, globbed, default)
265 matchandpats = oldmatchandpats(ctx, pats, opts, globbed, default)
266 m, p = copy.copy(matchandpats)
266 m, p = copy.copy(matchandpats)
267
267
268 if m.always():
268 if m.always():
269 # We want to match everything anyway, so there's no benefit trying
269 # We want to match everything anyway, so there's no benefit trying
270 # to add standins.
270 # to add standins.
271 return matchandpats
271 return matchandpats
272
272
273 pats = set(p)
273 pats = set(p)
274 # TODO: handling of patterns in both cases below
274 # TODO: handling of patterns in both cases below
275 if m._cwd:
275 if m._cwd:
276 if os.path.isabs(m._cwd):
276 if os.path.isabs(m._cwd):
277 # TODO: handle largefile magic when invoked from other cwd
277 # TODO: handle largefile magic when invoked from other cwd
278 return matchandpats
278 return matchandpats
279 back = (m._cwd.count('/') + 1) * '../'
279 back = (m._cwd.count('/') + 1) * '../'
280 pats.update(back + lfutil.standin(m._cwd + '/' + f) for f in p)
280 pats.update(back + lfutil.standin(m._cwd + '/' + f) for f in p)
281 else:
281 else:
282 pats.update(lfutil.standin(f) for f in p)
282 pats.update(lfutil.standin(f) for f in p)
283
283
284 for i in range(0, len(m._files)):
284 for i in range(0, len(m._files)):
285 standin = lfutil.standin(m._files[i])
285 standin = lfutil.standin(m._files[i])
286 if standin in repo[ctx.node()]:
286 if standin in repo[ctx.node()]:
287 m._files[i] = standin
287 m._files[i] = standin
288 elif m._files[i] not in repo[ctx.node()]:
288 elif m._files[i] not in repo[ctx.node()]:
289 m._files.append(standin)
289 m._files.append(standin)
290 pats.add(standin)
290 pats.add(standin)
291
291
292 m._fmap = set(m._files)
292 m._fmap = set(m._files)
293 m._always = False
293 m._always = False
294 origmatchfn = m.matchfn
294 origmatchfn = m.matchfn
295 def lfmatchfn(f):
295 def lfmatchfn(f):
296 lf = lfutil.splitstandin(f)
296 lf = lfutil.splitstandin(f)
297 if lf is not None and origmatchfn(lf):
297 if lf is not None and origmatchfn(lf):
298 return True
298 return True
299 r = origmatchfn(f)
299 r = origmatchfn(f)
300 return r
300 return r
301 m.matchfn = lfmatchfn
301 m.matchfn = lfmatchfn
302
302
303 return m, pats
303 return m, pats
304
304
305 # For hg log --patch, the match object is used in two different senses:
305 # For hg log --patch, the match object is used in two different senses:
306 # (1) to determine what revisions should be printed out, and
306 # (1) to determine what revisions should be printed out, and
307 # (2) to determine what files to print out diffs for.
307 # (2) to determine what files to print out diffs for.
308 # The magic matchandpats override should be used for case (1) but not for
308 # The magic matchandpats override should be used for case (1) but not for
309 # case (2).
309 # case (2).
310 def overridemakelogfilematcher(repo, pats, opts):
310 def overridemakelogfilematcher(repo, pats, opts):
311 pctx = repo[None]
311 pctx = repo[None]
312 match, pats = oldmatchandpats(pctx, pats, opts)
312 match, pats = oldmatchandpats(pctx, pats, opts)
313 return lambda rev: match
313 return lambda rev: match
314
314
315 oldmatchandpats = installmatchandpatsfn(overridematchandpats)
315 oldmatchandpats = installmatchandpatsfn(overridematchandpats)
316 oldmakelogfilematcher = cmdutil._makenofollowlogfilematcher
316 oldmakelogfilematcher = cmdutil._makenofollowlogfilematcher
317 setattr(cmdutil, '_makenofollowlogfilematcher', overridemakelogfilematcher)
317 setattr(cmdutil, '_makenofollowlogfilematcher', overridemakelogfilematcher)
318
318
319 try:
319 try:
320 return orig(ui, repo, *pats, **opts)
320 return orig(ui, repo, *pats, **opts)
321 finally:
321 finally:
322 restorematchandpatsfn()
322 restorematchandpatsfn()
323 setattr(cmdutil, '_makenofollowlogfilematcher', oldmakelogfilematcher)
323 setattr(cmdutil, '_makenofollowlogfilematcher', oldmakelogfilematcher)
324
324
325 def overrideverify(orig, ui, repo, *pats, **opts):
325 def overrideverify(orig, ui, repo, *pats, **opts):
326 large = opts.pop('large', False)
326 large = opts.pop('large', False)
327 all = opts.pop('lfa', False)
327 all = opts.pop('lfa', False)
328 contents = opts.pop('lfc', False)
328 contents = opts.pop('lfc', False)
329
329
330 result = orig(ui, repo, *pats, **opts)
330 result = orig(ui, repo, *pats, **opts)
331 if large or all or contents:
331 if large or all or contents:
332 result = result or lfcommands.verifylfiles(ui, repo, all, contents)
332 result = result or lfcommands.verifylfiles(ui, repo, all, contents)
333 return result
333 return result
334
334
335 def overridedebugstate(orig, ui, repo, *pats, **opts):
335 def overridedebugstate(orig, ui, repo, *pats, **opts):
336 large = opts.pop('large', False)
336 large = opts.pop('large', False)
337 if large:
337 if large:
338 class fakerepo(object):
338 class fakerepo(object):
339 dirstate = lfutil.openlfdirstate(ui, repo)
339 dirstate = lfutil.openlfdirstate(ui, repo)
340 orig(ui, fakerepo, *pats, **opts)
340 orig(ui, fakerepo, *pats, **opts)
341 else:
341 else:
342 orig(ui, repo, *pats, **opts)
342 orig(ui, repo, *pats, **opts)
343
343
344 # Override needs to refresh standins so that update's normal merge
344 # Override needs to refresh standins so that update's normal merge
345 # will go through properly. Then the other update hook (overriding repo.update)
345 # will go through properly. Then the other update hook (overriding repo.update)
346 # will get the new files. Filemerge is also overridden so that the merge
346 # will get the new files. Filemerge is also overridden so that the merge
347 # will merge standins correctly.
347 # will merge standins correctly.
348 def overrideupdate(orig, ui, repo, *pats, **opts):
348 def overrideupdate(orig, ui, repo, *pats, **opts):
349 # Need to lock between the standins getting updated and their
349 # Need to lock between the standins getting updated and their
350 # largefiles getting updated
350 # largefiles getting updated
351 wlock = repo.wlock()
351 wlock = repo.wlock()
352 try:
352 try:
353 if opts['check']:
353 if opts['check']:
354 lfdirstate = lfutil.openlfdirstate(ui, repo)
354 lfdirstate = lfutil.openlfdirstate(ui, repo)
355 unsure, s = lfdirstate.status(
355 unsure, s = lfdirstate.status(
356 match_.always(repo.root, repo.getcwd()),
356 match_.always(repo.root, repo.getcwd()),
357 [], False, False, False)
357 [], False, False, False)
358
358
359 mod = len(s.modified) > 0
359 mod = len(s.modified) > 0
360 for lfile in unsure:
360 for lfile in unsure:
361 standin = lfutil.standin(lfile)
361 standin = lfutil.standin(lfile)
362 if repo['.'][standin].data().strip() != \
362 if repo['.'][standin].data().strip() != \
363 lfutil.hashfile(repo.wjoin(lfile)):
363 lfutil.hashfile(repo.wjoin(lfile)):
364 mod = True
364 mod = True
365 else:
365 else:
366 lfdirstate.normal(lfile)
366 lfdirstate.normal(lfile)
367 lfdirstate.write()
367 lfdirstate.write()
368 if mod:
368 if mod:
369 raise util.Abort(_('uncommitted changes'))
369 raise util.Abort(_('uncommitted changes'))
370 return orig(ui, repo, *pats, **opts)
370 return orig(ui, repo, *pats, **opts)
371 finally:
371 finally:
372 wlock.release()
372 wlock.release()
373
373
374 # Before starting the manifest merge, merge.updates will call
374 # Before starting the manifest merge, merge.updates will call
375 # _checkunknown to check if there are any files in the merged-in
375 # _checkunknown to check if there are any files in the merged-in
376 # changeset that collide with unknown files in the working copy.
376 # changeset that collide with unknown files in the working copy.
377 #
377 #
378 # The largefiles are seen as unknown, so this prevents us from merging
378 # The largefiles are seen as unknown, so this prevents us from merging
379 # in a file 'foo' if we already have a largefile with the same name.
379 # in a file 'foo' if we already have a largefile with the same name.
380 #
380 #
381 # The overridden function filters the unknown files by removing any
381 # The overridden function filters the unknown files by removing any
382 # largefiles. This makes the merge proceed and we can then handle this
382 # largefiles. This makes the merge proceed and we can then handle this
383 # case further in the overridden manifestmerge function below.
383 # case further in the overridden manifestmerge function below.
384 def overridecheckunknownfile(origfn, repo, wctx, mctx, f):
384 def overridecheckunknownfile(origfn, repo, wctx, mctx, f):
385 if lfutil.standin(repo.dirstate.normalize(f)) in wctx:
385 if lfutil.standin(repo.dirstate.normalize(f)) in wctx:
386 return False
386 return False
387 return origfn(repo, wctx, mctx, f)
387 return origfn(repo, wctx, mctx, f)
388
388
389 # The manifest merge handles conflicts on the manifest level. We want
389 # The manifest merge handles conflicts on the manifest level. We want
390 # to handle changes in largefile-ness of files at this level too.
390 # to handle changes in largefile-ness of files at this level too.
391 #
391 #
392 # The strategy is to run the original manifestmerge and then process
392 # The strategy is to run the original manifestmerge and then process
393 # the action list it outputs. There are two cases we need to deal with:
393 # the action list it outputs. There are two cases we need to deal with:
394 #
394 #
395 # 1. Normal file in p1, largefile in p2. Here the largefile is
395 # 1. Normal file in p1, largefile in p2. Here the largefile is
396 # detected via its standin file, which will enter the working copy
396 # detected via its standin file, which will enter the working copy
397 # with a "get" action. It is not "merge" since the standin is all
397 # with a "get" action. It is not "merge" since the standin is all
398 # Mercurial is concerned with at this level -- the link to the
398 # Mercurial is concerned with at this level -- the link to the
399 # existing normal file is not relevant here.
399 # existing normal file is not relevant here.
400 #
400 #
401 # 2. Largefile in p1, normal file in p2. Here we get a "merge" action
401 # 2. Largefile in p1, normal file in p2. Here we get a "merge" action
402 # since the largefile will be present in the working copy and
402 # since the largefile will be present in the working copy and
403 # different from the normal file in p2. Mercurial therefore
403 # different from the normal file in p2. Mercurial therefore
404 # triggers a merge action.
404 # triggers a merge action.
405 #
405 #
406 # In both cases, we prompt the user and emit new actions to either
406 # In both cases, we prompt the user and emit new actions to either
407 # remove the standin (if the normal file was kept) or to remove the
407 # remove the standin (if the normal file was kept) or to remove the
408 # normal file and get the standin (if the largefile was kept). The
408 # normal file and get the standin (if the largefile was kept). The
409 # default prompt answer is to use the largefile version since it was
409 # default prompt answer is to use the largefile version since it was
410 # presumably changed on purpose.
410 # presumably changed on purpose.
411 #
411 #
412 # Finally, the merge.applyupdates function will then take care of
412 # Finally, the merge.applyupdates function will then take care of
413 # writing the files into the working copy and lfcommands.updatelfiles
413 # writing the files into the working copy and lfcommands.updatelfiles
414 # will update the largefiles.
414 # will update the largefiles.
415 def overridecalculateupdates(origfn, repo, p1, p2, pas, branchmerge, force,
415 def overridecalculateupdates(origfn, repo, p1, p2, pas, branchmerge, force,
416 partial, acceptremote, followcopies):
416 partial, acceptremote, followcopies):
417 overwrite = force and not branchmerge
417 overwrite = force and not branchmerge
418 actions = origfn(repo, p1, p2, pas, branchmerge, force, partial,
418 actions = origfn(repo, p1, p2, pas, branchmerge, force, partial,
419 acceptremote, followcopies)
419 acceptremote, followcopies)
420
420
421 if overwrite:
421 if overwrite:
422 return actions
422 return actions
423
423
424 removes = set(a[0] for a in actions['r'])
424 removes = set(a[0] for a in actions['r'])
425
425
426 newglist = []
426 newglist = []
427 lfmr = [] # LargeFiles: Mark as Removed
427 lfmr = [] # LargeFiles: Mark as Removed
428 for action in actions['g']:
428 for action in actions['g']:
429 f, args, msg = action
429 f, args, msg = action
430 splitstandin = f and lfutil.splitstandin(f)
430 splitstandin = f and lfutil.splitstandin(f)
431 if (splitstandin is not None and
431 if (splitstandin is not None and
432 splitstandin in p1 and splitstandin not in removes):
432 splitstandin in p1 and splitstandin not in removes):
433 # Case 1: normal file in the working copy, largefile in
433 # Case 1: normal file in the working copy, largefile in
434 # the second parent
434 # the second parent
435 lfile = splitstandin
435 lfile = splitstandin
436 standin = f
436 standin = f
437 msg = _('remote turned local normal file %s into a largefile\n'
437 msg = _('remote turned local normal file %s into a largefile\n'
438 'use (l)argefile or keep (n)ormal file?'
438 'use (l)argefile or keep (n)ormal file?'
439 '$$ &Largefile $$ &Normal file') % lfile
439 '$$ &Largefile $$ &Normal file') % lfile
440 if repo.ui.promptchoice(msg, 0) == 0:
440 if repo.ui.promptchoice(msg, 0) == 0:
441 actions['r'].append((lfile, None, msg))
441 actions['r'].append((lfile, None, msg))
442 newglist.append((standin, (p2.flags(standin),), msg))
442 newglist.append((standin, (p2.flags(standin),), msg))
443 else:
443 else:
444 actions['r'].append((standin, None, msg))
444 actions['r'].append((standin, None, msg))
445 elif lfutil.standin(f) in p1 and lfutil.standin(f) not in removes:
445 elif lfutil.standin(f) in p1 and lfutil.standin(f) not in removes:
446 # Case 2: largefile in the working copy, normal file in
446 # Case 2: largefile in the working copy, normal file in
447 # the second parent
447 # the second parent
448 standin = lfutil.standin(f)
448 standin = lfutil.standin(f)
449 lfile = f
449 lfile = f
450 msg = _('remote turned local largefile %s into a normal file\n'
450 msg = _('remote turned local largefile %s into a normal file\n'
451 'keep (l)argefile or use (n)ormal file?'
451 'keep (l)argefile or use (n)ormal file?'
452 '$$ &Largefile $$ &Normal file') % lfile
452 '$$ &Largefile $$ &Normal file') % lfile
453 if repo.ui.promptchoice(msg, 0) == 0:
453 if repo.ui.promptchoice(msg, 0) == 0:
454 if branchmerge:
454 if branchmerge:
455 # largefile can be restored from standin safely
455 # largefile can be restored from standin safely
456 actions['r'].append((lfile, None, msg))
456 actions['r'].append((lfile, None, msg))
457 else:
457 else:
458 # "lfile" should be marked as "removed" without
458 # "lfile" should be marked as "removed" without
459 # removal of itself
459 # removal of itself
460 lfmr.append((lfile, None, msg))
460 lfmr.append((lfile, None, msg))
461
461
462 # linear-merge should treat this largefile as 're-added'
462 # linear-merge should treat this largefile as 're-added'
463 actions['a'].append((standin, None, msg))
463 actions['a'].append((standin, None, msg))
464 else:
464 else:
465 actions['r'].append((standin, None, msg))
465 actions['r'].append((standin, None, msg))
466 newglist.append((lfile, (p2.flags(lfile),), msg))
466 newglist.append((lfile, (p2.flags(lfile),), msg))
467 else:
467 else:
468 newglist.append(action)
468 newglist.append(action)
469
469
470 newglist.sort()
470 newglist.sort()
471 actions['g'] = newglist
471 actions['g'] = newglist
472 if lfmr:
472 if lfmr:
473 lfmr.sort()
473 lfmr.sort()
474 actions['lfmr'] = lfmr
474 actions['lfmr'] = lfmr
475
475
476 return actions
476 return actions
477
477
478 def mergerecordupdates(orig, repo, actions, branchmerge):
478 def mergerecordupdates(orig, repo, actions, branchmerge):
479 if 'lfmr' in actions:
479 if 'lfmr' in actions:
480 # this should be executed before 'orig', to execute 'remove'
480 # this should be executed before 'orig', to execute 'remove'
481 # before all other actions
481 # before all other actions
482 for lfile, args, msg in actions['lfmr']:
482 for lfile, args, msg in actions['lfmr']:
483 repo.dirstate.remove(lfile)
483 repo.dirstate.remove(lfile)
484
484
485 return orig(repo, actions, branchmerge)
485 return orig(repo, actions, branchmerge)
486
486
487
487
488 # Override filemerge to prompt the user about how they wish to merge
488 # Override filemerge to prompt the user about how they wish to merge
489 # largefiles. This will handle identical edits without prompting the user.
489 # largefiles. This will handle identical edits without prompting the user.
490 def overridefilemerge(origfn, repo, mynode, orig, fcd, fco, fca, labels=None):
490 def overridefilemerge(origfn, repo, mynode, orig, fcd, fco, fca, labels=None):
491 if not lfutil.isstandin(orig):
491 if not lfutil.isstandin(orig):
492 return origfn(repo, mynode, orig, fcd, fco, fca, labels=labels)
492 return origfn(repo, mynode, orig, fcd, fco, fca, labels=labels)
493
493
494 ahash = fca.data().strip().lower()
494 ahash = fca.data().strip().lower()
495 dhash = fcd.data().strip().lower()
495 dhash = fcd.data().strip().lower()
496 ohash = fco.data().strip().lower()
496 ohash = fco.data().strip().lower()
497 if (ohash != ahash and
497 if (ohash != ahash and
498 ohash != dhash and
498 ohash != dhash and
499 (dhash == ahash or
499 (dhash == ahash or
500 repo.ui.promptchoice(
500 repo.ui.promptchoice(
501 _('largefile %s has a merge conflict\nancestor was %s\n'
501 _('largefile %s has a merge conflict\nancestor was %s\n'
502 'keep (l)ocal %s or\ntake (o)ther %s?'
502 'keep (l)ocal %s or\ntake (o)ther %s?'
503 '$$ &Local $$ &Other') %
503 '$$ &Local $$ &Other') %
504 (lfutil.splitstandin(orig), ahash, dhash, ohash),
504 (lfutil.splitstandin(orig), ahash, dhash, ohash),
505 0) == 1)):
505 0) == 1)):
506 repo.wwrite(fcd.path(), fco.data(), fco.flags())
506 repo.wwrite(fcd.path(), fco.data(), fco.flags())
507 return 0
507 return 0
508
508
509 # Copy first changes the matchers to match standins instead of
509 # Copy first changes the matchers to match standins instead of
510 # largefiles. Then it overrides util.copyfile in that function it
510 # largefiles. Then it overrides util.copyfile in that function it
511 # checks if the destination largefile already exists. It also keeps a
511 # checks if the destination largefile already exists. It also keeps a
512 # list of copied files so that the largefiles can be copied and the
512 # list of copied files so that the largefiles can be copied and the
513 # dirstate updated.
513 # dirstate updated.
514 def overridecopy(orig, ui, repo, pats, opts, rename=False):
514 def overridecopy(orig, ui, repo, pats, opts, rename=False):
515 # doesn't remove largefile on rename
515 # doesn't remove largefile on rename
516 if len(pats) < 2:
516 if len(pats) < 2:
517 # this isn't legal, let the original function deal with it
517 # this isn't legal, let the original function deal with it
518 return orig(ui, repo, pats, opts, rename)
518 return orig(ui, repo, pats, opts, rename)
519
519
520 def makestandin(relpath):
520 def makestandin(relpath):
521 path = pathutil.canonpath(repo.root, repo.getcwd(), relpath)
521 path = pathutil.canonpath(repo.root, repo.getcwd(), relpath)
522 return os.path.join(repo.wjoin(lfutil.standin(path)))
522 return os.path.join(repo.wjoin(lfutil.standin(path)))
523
523
524 fullpats = scmutil.expandpats(pats)
524 fullpats = scmutil.expandpats(pats)
525 dest = fullpats[-1]
525 dest = fullpats[-1]
526
526
527 if os.path.isdir(dest):
527 if os.path.isdir(dest):
528 if not os.path.isdir(makestandin(dest)):
528 if not os.path.isdir(makestandin(dest)):
529 os.makedirs(makestandin(dest))
529 os.makedirs(makestandin(dest))
530 # This could copy both lfiles and normal files in one command,
530 # This could copy both lfiles and normal files in one command,
531 # but we don't want to do that. First replace their matcher to
531 # but we don't want to do that. First replace their matcher to
532 # only match normal files and run it, then replace it to just
532 # only match normal files and run it, then replace it to just
533 # match largefiles and run it again.
533 # match largefiles and run it again.
534 nonormalfiles = False
534 nonormalfiles = False
535 nolfiles = False
535 nolfiles = False
536 installnormalfilesmatchfn(repo[None].manifest())
536 installnormalfilesmatchfn(repo[None].manifest())
537 try:
537 try:
538 try:
538 try:
539 result = orig(ui, repo, pats, opts, rename)
539 result = orig(ui, repo, pats, opts, rename)
540 except util.Abort, e:
540 except util.Abort, e:
541 if str(e) != _('no files to copy'):
541 if str(e) != _('no files to copy'):
542 raise e
542 raise e
543 else:
543 else:
544 nonormalfiles = True
544 nonormalfiles = True
545 result = 0
545 result = 0
546 finally:
546 finally:
547 restorematchfn()
547 restorematchfn()
548
548
549 # The first rename can cause our current working directory to be removed.
549 # The first rename can cause our current working directory to be removed.
550 # In that case there is nothing left to copy/rename so just quit.
550 # In that case there is nothing left to copy/rename so just quit.
551 try:
551 try:
552 repo.getcwd()
552 repo.getcwd()
553 except OSError:
553 except OSError:
554 return result
554 return result
555
555
556 try:
556 try:
557 try:
557 try:
558 # When we call orig below it creates the standins but we don't add
558 # When we call orig below it creates the standins but we don't add
559 # them to the dir state until later so lock during that time.
559 # them to the dir state until later so lock during that time.
560 wlock = repo.wlock()
560 wlock = repo.wlock()
561
561
562 manifest = repo[None].manifest()
562 manifest = repo[None].manifest()
563 def overridematch(ctx, pats=[], opts={}, globbed=False,
563 def overridematch(ctx, pats=[], opts={}, globbed=False,
564 default='relpath'):
564 default='relpath'):
565 newpats = []
565 newpats = []
566 # The patterns were previously mangled to add the standin
566 # The patterns were previously mangled to add the standin
567 # directory; we need to remove that now
567 # directory; we need to remove that now
568 for pat in pats:
568 for pat in pats:
569 if match_.patkind(pat) is None and lfutil.shortname in pat:
569 if match_.patkind(pat) is None and lfutil.shortname in pat:
570 newpats.append(pat.replace(lfutil.shortname, ''))
570 newpats.append(pat.replace(lfutil.shortname, ''))
571 else:
571 else:
572 newpats.append(pat)
572 newpats.append(pat)
573 match = oldmatch(ctx, newpats, opts, globbed, default)
573 match = oldmatch(ctx, newpats, opts, globbed, default)
574 m = copy.copy(match)
574 m = copy.copy(match)
575 lfile = lambda f: lfutil.standin(f) in manifest
575 lfile = lambda f: lfutil.standin(f) in manifest
576 m._files = [lfutil.standin(f) for f in m._files if lfile(f)]
576 m._files = [lfutil.standin(f) for f in m._files if lfile(f)]
577 m._fmap = set(m._files)
577 m._fmap = set(m._files)
578 origmatchfn = m.matchfn
578 origmatchfn = m.matchfn
579 m.matchfn = lambda f: (lfutil.isstandin(f) and
579 m.matchfn = lambda f: (lfutil.isstandin(f) and
580 (f in manifest) and
580 (f in manifest) and
581 origmatchfn(lfutil.splitstandin(f)) or
581 origmatchfn(lfutil.splitstandin(f)) or
582 None)
582 None)
583 return m
583 return m
584 oldmatch = installmatchfn(overridematch)
584 oldmatch = installmatchfn(overridematch)
585 listpats = []
585 listpats = []
586 for pat in pats:
586 for pat in pats:
587 if match_.patkind(pat) is not None:
587 if match_.patkind(pat) is not None:
588 listpats.append(pat)
588 listpats.append(pat)
589 else:
589 else:
590 listpats.append(makestandin(pat))
590 listpats.append(makestandin(pat))
591
591
592 try:
592 try:
593 origcopyfile = util.copyfile
593 origcopyfile = util.copyfile
594 copiedfiles = []
594 copiedfiles = []
595 def overridecopyfile(src, dest):
595 def overridecopyfile(src, dest):
596 if (lfutil.shortname in src and
596 if (lfutil.shortname in src and
597 dest.startswith(repo.wjoin(lfutil.shortname))):
597 dest.startswith(repo.wjoin(lfutil.shortname))):
598 destlfile = dest.replace(lfutil.shortname, '')
598 destlfile = dest.replace(lfutil.shortname, '')
599 if not opts['force'] and os.path.exists(destlfile):
599 if not opts['force'] and os.path.exists(destlfile):
600 raise IOError('',
600 raise IOError('',
601 _('destination largefile already exists'))
601 _('destination largefile already exists'))
602 copiedfiles.append((src, dest))
602 copiedfiles.append((src, dest))
603 origcopyfile(src, dest)
603 origcopyfile(src, dest)
604
604
605 util.copyfile = overridecopyfile
605 util.copyfile = overridecopyfile
606 result += orig(ui, repo, listpats, opts, rename)
606 result += orig(ui, repo, listpats, opts, rename)
607 finally:
607 finally:
608 util.copyfile = origcopyfile
608 util.copyfile = origcopyfile
609
609
610 lfdirstate = lfutil.openlfdirstate(ui, repo)
610 lfdirstate = lfutil.openlfdirstate(ui, repo)
611 for (src, dest) in copiedfiles:
611 for (src, dest) in copiedfiles:
612 if (lfutil.shortname in src and
612 if (lfutil.shortname in src and
613 dest.startswith(repo.wjoin(lfutil.shortname))):
613 dest.startswith(repo.wjoin(lfutil.shortname))):
614 srclfile = src.replace(repo.wjoin(lfutil.standin('')), '')
614 srclfile = src.replace(repo.wjoin(lfutil.standin('')), '')
615 destlfile = dest.replace(repo.wjoin(lfutil.standin('')), '')
615 destlfile = dest.replace(repo.wjoin(lfutil.standin('')), '')
616 destlfiledir = os.path.dirname(repo.wjoin(destlfile)) or '.'
616 destlfiledir = os.path.dirname(repo.wjoin(destlfile)) or '.'
617 if not os.path.isdir(destlfiledir):
617 if not os.path.isdir(destlfiledir):
618 os.makedirs(destlfiledir)
618 os.makedirs(destlfiledir)
619 if rename:
619 if rename:
620 os.rename(repo.wjoin(srclfile), repo.wjoin(destlfile))
620 os.rename(repo.wjoin(srclfile), repo.wjoin(destlfile))
621
621
622 # The file is gone, but this deletes any empty parent
622 # The file is gone, but this deletes any empty parent
623 # directories as a side-effect.
623 # directories as a side-effect.
624 util.unlinkpath(repo.wjoin(srclfile), True)
624 util.unlinkpath(repo.wjoin(srclfile), True)
625 lfdirstate.remove(srclfile)
625 lfdirstate.remove(srclfile)
626 else:
626 else:
627 util.copyfile(repo.wjoin(srclfile),
627 util.copyfile(repo.wjoin(srclfile),
628 repo.wjoin(destlfile))
628 repo.wjoin(destlfile))
629
629
630 lfdirstate.add(destlfile)
630 lfdirstate.add(destlfile)
631 lfdirstate.write()
631 lfdirstate.write()
632 except util.Abort, e:
632 except util.Abort, e:
633 if str(e) != _('no files to copy'):
633 if str(e) != _('no files to copy'):
634 raise e
634 raise e
635 else:
635 else:
636 nolfiles = True
636 nolfiles = True
637 finally:
637 finally:
638 restorematchfn()
638 restorematchfn()
639 wlock.release()
639 wlock.release()
640
640
641 if nolfiles and nonormalfiles:
641 if nolfiles and nonormalfiles:
642 raise util.Abort(_('no files to copy'))
642 raise util.Abort(_('no files to copy'))
643
643
644 return result
644 return result
645
645
646 # When the user calls revert, we have to be careful to not revert any
646 # When the user calls revert, we have to be careful to not revert any
647 # changes to other largefiles accidentally. This means we have to keep
647 # changes to other largefiles accidentally. This means we have to keep
648 # track of the largefiles that are being reverted so we only pull down
648 # track of the largefiles that are being reverted so we only pull down
649 # the necessary largefiles.
649 # the necessary largefiles.
650 #
650 #
651 # Standins are only updated (to match the hash of largefiles) before
651 # Standins are only updated (to match the hash of largefiles) before
652 # commits. Update the standins then run the original revert, changing
652 # commits. Update the standins then run the original revert, changing
653 # the matcher to hit standins instead of largefiles. Based on the
653 # the matcher to hit standins instead of largefiles. Based on the
654 # resulting standins update the largefiles.
654 # resulting standins update the largefiles.
655 def overriderevert(orig, ui, repo, *pats, **opts):
655 def overriderevert(orig, ui, repo, *pats, **opts):
656 # Because we put the standins in a bad state (by updating them)
656 # Because we put the standins in a bad state (by updating them)
657 # and then return them to a correct state we need to lock to
657 # and then return them to a correct state we need to lock to
658 # prevent others from changing them in their incorrect state.
658 # prevent others from changing them in their incorrect state.
659 wlock = repo.wlock()
659 wlock = repo.wlock()
660 try:
660 try:
661 lfdirstate = lfutil.openlfdirstate(ui, repo)
661 lfdirstate = lfutil.openlfdirstate(ui, repo)
662 s = lfutil.lfdirstatestatus(lfdirstate, repo)
662 s = lfutil.lfdirstatestatus(lfdirstate, repo)
663 lfdirstate.write()
663 lfdirstate.write()
664 for lfile in s.modified:
664 for lfile in s.modified:
665 lfutil.updatestandin(repo, lfutil.standin(lfile))
665 lfutil.updatestandin(repo, lfutil.standin(lfile))
666 for lfile in s.deleted:
666 for lfile in s.deleted:
667 if (os.path.exists(repo.wjoin(lfutil.standin(lfile)))):
667 if (os.path.exists(repo.wjoin(lfutil.standin(lfile)))):
668 os.unlink(repo.wjoin(lfutil.standin(lfile)))
668 os.unlink(repo.wjoin(lfutil.standin(lfile)))
669
669
670 oldstandins = lfutil.getstandinsstate(repo)
670 oldstandins = lfutil.getstandinsstate(repo)
671
671
672 def overridematch(ctx, pats=[], opts={}, globbed=False,
672 def overridematch(ctx, pats=[], opts={}, globbed=False,
673 default='relpath'):
673 default='relpath'):
674 match = oldmatch(ctx, pats, opts, globbed, default)
674 match = oldmatch(ctx, pats, opts, globbed, default)
675 m = copy.copy(match)
675 m = copy.copy(match)
676 def tostandin(f):
676 def tostandin(f):
677 if lfutil.standin(f) in ctx:
677 if lfutil.standin(f) in ctx:
678 return lfutil.standin(f)
678 return lfutil.standin(f)
679 elif lfutil.standin(f) in repo[None]:
679 elif lfutil.standin(f) in repo[None]:
680 return None
680 return None
681 return f
681 return f
682 m._files = [tostandin(f) for f in m._files]
682 m._files = [tostandin(f) for f in m._files]
683 m._files = [f for f in m._files if f is not None]
683 m._files = [f for f in m._files if f is not None]
684 m._fmap = set(m._files)
684 m._fmap = set(m._files)
685 origmatchfn = m.matchfn
685 origmatchfn = m.matchfn
686 def matchfn(f):
686 def matchfn(f):
687 if lfutil.isstandin(f):
687 if lfutil.isstandin(f):
688 return (origmatchfn(lfutil.splitstandin(f)) and
688 return (origmatchfn(lfutil.splitstandin(f)) and
689 (f in repo[None] or f in ctx))
689 (f in repo[None] or f in ctx))
690 return origmatchfn(f)
690 return origmatchfn(f)
691 m.matchfn = matchfn
691 m.matchfn = matchfn
692 return m
692 return m
693 oldmatch = installmatchfn(overridematch)
693 oldmatch = installmatchfn(overridematch)
694 try:
694 try:
695 orig(ui, repo, *pats, **opts)
695 orig(ui, repo, *pats, **opts)
696 finally:
696 finally:
697 restorematchfn()
697 restorematchfn()
698
698
699 newstandins = lfutil.getstandinsstate(repo)
699 newstandins = lfutil.getstandinsstate(repo)
700 filelist = lfutil.getlfilestoupdate(oldstandins, newstandins)
700 filelist = lfutil.getlfilestoupdate(oldstandins, newstandins)
701 # lfdirstate should be 'normallookup'-ed for updated files,
701 # lfdirstate should be 'normallookup'-ed for updated files,
702 # because reverting doesn't touch dirstate for 'normal' files
702 # because reverting doesn't touch dirstate for 'normal' files
703 # when target revision is explicitly specified: in such case,
703 # when target revision is explicitly specified: in such case,
704 # 'n' and valid timestamp in dirstate doesn't ensure 'clean'
704 # 'n' and valid timestamp in dirstate doesn't ensure 'clean'
705 # of target (standin) file.
705 # of target (standin) file.
706 lfcommands.updatelfiles(ui, repo, filelist, printmessage=False,
706 lfcommands.updatelfiles(ui, repo, filelist, printmessage=False,
707 normallookup=True)
707 normallookup=True)
708
708
709 finally:
709 finally:
710 wlock.release()
710 wlock.release()
711
711
712 # after pulling changesets, we need to take some extra care to get
712 # after pulling changesets, we need to take some extra care to get
713 # largefiles updated remotely
713 # largefiles updated remotely
714 def overridepull(orig, ui, repo, source=None, **opts):
714 def overridepull(orig, ui, repo, source=None, **opts):
715 revsprepull = len(repo)
715 revsprepull = len(repo)
716 if not source:
716 if not source:
717 source = 'default'
717 source = 'default'
718 repo.lfpullsource = source
718 repo.lfpullsource = source
719 result = orig(ui, repo, source, **opts)
719 result = orig(ui, repo, source, **opts)
720 revspostpull = len(repo)
720 revspostpull = len(repo)
721 lfrevs = opts.get('lfrev', [])
721 lfrevs = opts.get('lfrev', [])
722 if opts.get('all_largefiles'):
722 if opts.get('all_largefiles'):
723 lfrevs.append('pulled()')
723 lfrevs.append('pulled()')
724 if lfrevs and revspostpull > revsprepull:
724 if lfrevs and revspostpull > revsprepull:
725 numcached = 0
725 numcached = 0
726 repo.firstpulled = revsprepull # for pulled() revset expression
726 repo.firstpulled = revsprepull # for pulled() revset expression
727 try:
727 try:
728 for rev in scmutil.revrange(repo, lfrevs):
728 for rev in scmutil.revrange(repo, lfrevs):
729 ui.note(_('pulling largefiles for revision %s\n') % rev)
729 ui.note(_('pulling largefiles for revision %s\n') % rev)
730 (cached, missing) = lfcommands.cachelfiles(ui, repo, rev)
730 (cached, missing) = lfcommands.cachelfiles(ui, repo, rev)
731 numcached += len(cached)
731 numcached += len(cached)
732 finally:
732 finally:
733 del repo.firstpulled
733 del repo.firstpulled
734 ui.status(_("%d largefiles cached\n") % numcached)
734 ui.status(_("%d largefiles cached\n") % numcached)
735 return result
735 return result
736
736
737 def pulledrevsetsymbol(repo, subset, x):
737 def pulledrevsetsymbol(repo, subset, x):
738 """``pulled()``
738 """``pulled()``
739 Changesets that just has been pulled.
739 Changesets that just has been pulled.
740
740
741 Only available with largefiles from pull --lfrev expressions.
741 Only available with largefiles from pull --lfrev expressions.
742
742
743 .. container:: verbose
743 .. container:: verbose
744
744
745 Some examples:
745 Some examples:
746
746
747 - pull largefiles for all new changesets::
747 - pull largefiles for all new changesets::
748
748
749 hg pull -lfrev "pulled()"
749 hg pull -lfrev "pulled()"
750
750
751 - pull largefiles for all new branch heads::
751 - pull largefiles for all new branch heads::
752
752
753 hg pull -lfrev "head(pulled()) and not closed()"
753 hg pull -lfrev "head(pulled()) and not closed()"
754
754
755 """
755 """
756
756
757 try:
757 try:
758 firstpulled = repo.firstpulled
758 firstpulled = repo.firstpulled
759 except AttributeError:
759 except AttributeError:
760 raise util.Abort(_("pulled() only available in --lfrev"))
760 raise util.Abort(_("pulled() only available in --lfrev"))
761 return revset.baseset([r for r in subset if r >= firstpulled])
761 return revset.baseset([r for r in subset if r >= firstpulled])
762
762
763 def overrideclone(orig, ui, source, dest=None, **opts):
763 def overrideclone(orig, ui, source, dest=None, **opts):
764 d = dest
764 d = dest
765 if d is None:
765 if d is None:
766 d = hg.defaultdest(source)
766 d = hg.defaultdest(source)
767 if opts.get('all_largefiles') and not hg.islocal(d):
767 if opts.get('all_largefiles') and not hg.islocal(d):
768 raise util.Abort(_(
768 raise util.Abort(_(
769 '--all-largefiles is incompatible with non-local destination %s') %
769 '--all-largefiles is incompatible with non-local destination %s') %
770 d)
770 d)
771
771
772 return orig(ui, source, dest, **opts)
772 return orig(ui, source, dest, **opts)
773
773
774 def hgclone(orig, ui, opts, *args, **kwargs):
774 def hgclone(orig, ui, opts, *args, **kwargs):
775 result = orig(ui, opts, *args, **kwargs)
775 result = orig(ui, opts, *args, **kwargs)
776
776
777 if result is not None:
777 if result is not None:
778 sourcerepo, destrepo = result
778 sourcerepo, destrepo = result
779 repo = destrepo.local()
779 repo = destrepo.local()
780
780
781 # Caching is implicitly limited to 'rev' option, since the dest repo was
781 # Caching is implicitly limited to 'rev' option, since the dest repo was
782 # truncated at that point. The user may expect a download count with
782 # truncated at that point. The user may expect a download count with
783 # this option, so attempt whether or not this is a largefile repo.
783 # this option, so attempt whether or not this is a largefile repo.
784 if opts.get('all_largefiles'):
784 if opts.get('all_largefiles'):
785 success, missing = lfcommands.downloadlfiles(ui, repo, None)
785 success, missing = lfcommands.downloadlfiles(ui, repo, None)
786
786
787 if missing != 0:
787 if missing != 0:
788 return None
788 return None
789
789
790 return result
790 return result
791
791
792 def overriderebase(orig, ui, repo, **opts):
792 def overriderebase(orig, ui, repo, **opts):
793 resuming = opts.get('continue')
793 resuming = opts.get('continue')
794 repo._lfcommithooks.append(lfutil.automatedcommithook(resuming))
794 repo._lfcommithooks.append(lfutil.automatedcommithook(resuming))
795 repo._lfstatuswriters.append(lambda *msg, **opts: None)
795 repo._lfstatuswriters.append(lambda *msg, **opts: None)
796 try:
796 try:
797 return orig(ui, repo, **opts)
797 return orig(ui, repo, **opts)
798 finally:
798 finally:
799 repo._lfstatuswriters.pop()
799 repo._lfstatuswriters.pop()
800 repo._lfcommithooks.pop()
800 repo._lfcommithooks.pop()
801
801
802 def overridearchive(orig, repo, dest, node, kind, decode=True, matchfn=None,
802 def overridearchive(orig, repo, dest, node, kind, decode=True, matchfn=None,
803 prefix=None, mtime=None, subrepos=None):
803 prefix=None, mtime=None, subrepos=None):
804 # No need to lock because we are only reading history and
804 # No need to lock because we are only reading history and
805 # largefile caches, neither of which are modified.
805 # largefile caches, neither of which are modified.
806 lfcommands.cachelfiles(repo.ui, repo, node)
806 lfcommands.cachelfiles(repo.ui, repo, node)
807
807
808 if kind not in archival.archivers:
808 if kind not in archival.archivers:
809 raise util.Abort(_("unknown archive type '%s'") % kind)
809 raise util.Abort(_("unknown archive type '%s'") % kind)
810
810
811 ctx = repo[node]
811 ctx = repo[node]
812
812
813 if kind == 'files':
813 if kind == 'files':
814 if prefix:
814 if prefix:
815 raise util.Abort(
815 raise util.Abort(
816 _('cannot give prefix when archiving to files'))
816 _('cannot give prefix when archiving to files'))
817 else:
817 else:
818 prefix = archival.tidyprefix(dest, kind, prefix)
818 prefix = archival.tidyprefix(dest, kind, prefix)
819
819
820 def write(name, mode, islink, getdata):
820 def write(name, mode, islink, getdata):
821 if matchfn and not matchfn(name):
821 if matchfn and not matchfn(name):
822 return
822 return
823 data = getdata()
823 data = getdata()
824 if decode:
824 if decode:
825 data = repo.wwritedata(name, data)
825 data = repo.wwritedata(name, data)
826 archiver.addfile(prefix + name, mode, islink, data)
826 archiver.addfile(prefix + name, mode, islink, data)
827
827
828 archiver = archival.archivers[kind](dest, mtime or ctx.date()[0])
828 archiver = archival.archivers[kind](dest, mtime or ctx.date()[0])
829
829
830 if repo.ui.configbool("ui", "archivemeta", True):
830 if repo.ui.configbool("ui", "archivemeta", True):
831 def metadata():
831 def metadata():
832 base = 'repo: %s\nnode: %s\nbranch: %s\n' % (
832 base = 'repo: %s\nnode: %s\nbranch: %s\n' % (
833 hex(repo.changelog.node(0)), hex(node), ctx.branch())
833 hex(repo.changelog.node(0)), hex(node), ctx.branch())
834
834
835 tags = ''.join('tag: %s\n' % t for t in ctx.tags()
835 tags = ''.join('tag: %s\n' % t for t in ctx.tags()
836 if repo.tagtype(t) == 'global')
836 if repo.tagtype(t) == 'global')
837 if not tags:
837 if not tags:
838 repo.ui.pushbuffer()
838 repo.ui.pushbuffer()
839 opts = {'template': '{latesttag}\n{latesttagdistance}',
839 opts = {'template': '{latesttag}\n{latesttagdistance}',
840 'style': '', 'patch': None, 'git': None}
840 'style': '', 'patch': None, 'git': None}
841 cmdutil.show_changeset(repo.ui, repo, opts).show(ctx)
841 cmdutil.show_changeset(repo.ui, repo, opts).show(ctx)
842 ltags, dist = repo.ui.popbuffer().split('\n')
842 ltags, dist = repo.ui.popbuffer().split('\n')
843 tags = ''.join('latesttag: %s\n' % t for t in ltags.split(':'))
843 tags = ''.join('latesttag: %s\n' % t for t in ltags.split(':'))
844 tags += 'latesttagdistance: %s\n' % dist
844 tags += 'latesttagdistance: %s\n' % dist
845
845
846 return base + tags
846 return base + tags
847
847
848 write('.hg_archival.txt', 0644, False, metadata)
848 write('.hg_archival.txt', 0644, False, metadata)
849
849
850 for f in ctx:
850 for f in ctx:
851 ff = ctx.flags(f)
851 ff = ctx.flags(f)
852 getdata = ctx[f].data
852 getdata = ctx[f].data
853 if lfutil.isstandin(f):
853 if lfutil.isstandin(f):
854 path = lfutil.findfile(repo, getdata().strip())
854 path = lfutil.findfile(repo, getdata().strip())
855 if path is None:
855 if path is None:
856 raise util.Abort(
856 raise util.Abort(
857 _('largefile %s not found in repo store or system cache')
857 _('largefile %s not found in repo store or system cache')
858 % lfutil.splitstandin(f))
858 % lfutil.splitstandin(f))
859 f = lfutil.splitstandin(f)
859 f = lfutil.splitstandin(f)
860
860
861 def getdatafn():
861 def getdatafn():
862 fd = None
862 fd = None
863 try:
863 try:
864 fd = open(path, 'rb')
864 fd = open(path, 'rb')
865 return fd.read()
865 return fd.read()
866 finally:
866 finally:
867 if fd:
867 if fd:
868 fd.close()
868 fd.close()
869
869
870 getdata = getdatafn
870 getdata = getdatafn
871 write(f, 'x' in ff and 0755 or 0644, 'l' in ff, getdata)
871 write(f, 'x' in ff and 0755 or 0644, 'l' in ff, getdata)
872
872
873 if subrepos:
873 if subrepos:
874 for subpath in sorted(ctx.substate):
874 for subpath in sorted(ctx.substate):
875 sub = ctx.sub(subpath)
875 sub = ctx.sub(subpath)
876 submatch = match_.narrowmatcher(subpath, matchfn)
876 submatch = match_.narrowmatcher(subpath, matchfn)
877 sub.archive(repo.ui, archiver, prefix, submatch)
877 sub.archive(repo.ui, archiver, prefix, submatch)
878
878
879 archiver.done()
879 archiver.done()
880
880
881 def hgsubrepoarchive(orig, repo, ui, archiver, prefix, match=None):
881 def hgsubrepoarchive(orig, repo, ui, archiver, prefix, match=None):
882 repo._get(repo._state + ('hg',))
882 repo._get(repo._state + ('hg',))
883 rev = repo._state[1]
883 rev = repo._state[1]
884 ctx = repo._repo[rev]
884 ctx = repo._repo[rev]
885
885
886 lfcommands.cachelfiles(ui, repo._repo, ctx.node())
886 lfcommands.cachelfiles(ui, repo._repo, ctx.node())
887
887
888 def write(name, mode, islink, getdata):
888 def write(name, mode, islink, getdata):
889 # At this point, the standin has been replaced with the largefile name,
889 # At this point, the standin has been replaced with the largefile name,
890 # so the normal matcher works here without the lfutil variants.
890 # so the normal matcher works here without the lfutil variants.
891 if match and not match(f):
891 if match and not match(f):
892 return
892 return
893 data = getdata()
893 data = getdata()
894
894
895 archiver.addfile(prefix + repo._path + '/' + name, mode, islink, data)
895 archiver.addfile(prefix + repo._path + '/' + name, mode, islink, data)
896
896
897 for f in ctx:
897 for f in ctx:
898 ff = ctx.flags(f)
898 ff = ctx.flags(f)
899 getdata = ctx[f].data
899 getdata = ctx[f].data
900 if lfutil.isstandin(f):
900 if lfutil.isstandin(f):
901 path = lfutil.findfile(repo._repo, getdata().strip())
901 path = lfutil.findfile(repo._repo, getdata().strip())
902 if path is None:
902 if path is None:
903 raise util.Abort(
903 raise util.Abort(
904 _('largefile %s not found in repo store or system cache')
904 _('largefile %s not found in repo store or system cache')
905 % lfutil.splitstandin(f))
905 % lfutil.splitstandin(f))
906 f = lfutil.splitstandin(f)
906 f = lfutil.splitstandin(f)
907
907
908 def getdatafn():
908 def getdatafn():
909 fd = None
909 fd = None
910 try:
910 try:
911 fd = open(os.path.join(prefix, path), 'rb')
911 fd = open(os.path.join(prefix, path), 'rb')
912 return fd.read()
912 return fd.read()
913 finally:
913 finally:
914 if fd:
914 if fd:
915 fd.close()
915 fd.close()
916
916
917 getdata = getdatafn
917 getdata = getdatafn
918
918
919 write(f, 'x' in ff and 0755 or 0644, 'l' in ff, getdata)
919 write(f, 'x' in ff and 0755 or 0644, 'l' in ff, getdata)
920
920
921 for subpath in sorted(ctx.substate):
921 for subpath in sorted(ctx.substate):
922 sub = ctx.sub(subpath)
922 sub = ctx.sub(subpath)
923 submatch = match_.narrowmatcher(subpath, match)
923 submatch = match_.narrowmatcher(subpath, match)
924 sub.archive(ui, archiver, os.path.join(prefix, repo._path) + '/',
924 sub.archive(ui, archiver, os.path.join(prefix, repo._path) + '/',
925 submatch)
925 submatch)
926
926
927 # If a largefile is modified, the change is not reflected in its
927 # If a largefile is modified, the change is not reflected in its
928 # standin until a commit. cmdutil.bailifchanged() raises an exception
928 # standin until a commit. cmdutil.bailifchanged() raises an exception
929 # if the repo has uncommitted changes. Wrap it to also check if
929 # if the repo has uncommitted changes. Wrap it to also check if
930 # largefiles were changed. This is used by bisect and backout.
930 # largefiles were changed. This is used by bisect and backout.
931 def overridebailifchanged(orig, repo):
931 def overridebailifchanged(orig, repo):
932 orig(repo)
932 orig(repo)
933 repo.lfstatus = True
933 repo.lfstatus = True
934 s = repo.status()
934 s = repo.status()
935 repo.lfstatus = False
935 repo.lfstatus = False
936 if s.modified or s.added or s.removed or s.deleted:
936 if s.modified or s.added or s.removed or s.deleted:
937 raise util.Abort(_('uncommitted changes'))
937 raise util.Abort(_('uncommitted changes'))
938
938
939 # Fetch doesn't use cmdutil.bailifchanged so override it to add the check
939 # Fetch doesn't use cmdutil.bailifchanged so override it to add the check
940 def overridefetch(orig, ui, repo, *pats, **opts):
940 def overridefetch(orig, ui, repo, *pats, **opts):
941 repo.lfstatus = True
941 repo.lfstatus = True
942 s = repo.status()
942 s = repo.status()
943 repo.lfstatus = False
943 repo.lfstatus = False
944 if s.modified or s.added or s.removed or s.deleted:
944 if s.modified or s.added or s.removed or s.deleted:
945 raise util.Abort(_('uncommitted changes'))
945 raise util.Abort(_('uncommitted changes'))
946 return orig(ui, repo, *pats, **opts)
946 return orig(ui, repo, *pats, **opts)
947
947
948 def overrideforget(orig, ui, repo, *pats, **opts):
948 def overrideforget(orig, ui, repo, *pats, **opts):
949 installnormalfilesmatchfn(repo[None].manifest())
949 installnormalfilesmatchfn(repo[None].manifest())
950 result = orig(ui, repo, *pats, **opts)
950 result = orig(ui, repo, *pats, **opts)
951 restorematchfn()
951 restorematchfn()
952 m = scmutil.match(repo[None], pats, opts)
952 m = scmutil.match(repo[None], pats, opts)
953
953
954 try:
954 try:
955 repo.lfstatus = True
955 repo.lfstatus = True
956 s = repo.status(match=m, clean=True)
956 s = repo.status(match=m, clean=True)
957 finally:
957 finally:
958 repo.lfstatus = False
958 repo.lfstatus = False
959 forget = sorted(s.modified + s.added + s.deleted + s.clean)
959 forget = sorted(s.modified + s.added + s.deleted + s.clean)
960 forget = [f for f in forget if lfutil.standin(f) in repo[None].manifest()]
960 forget = [f for f in forget if lfutil.standin(f) in repo[None].manifest()]
961
961
962 for f in forget:
962 for f in forget:
963 if lfutil.standin(f) not in repo.dirstate and not \
963 if lfutil.standin(f) not in repo.dirstate and not \
964 os.path.isdir(m.rel(lfutil.standin(f))):
964 os.path.isdir(m.rel(lfutil.standin(f))):
965 ui.warn(_('not removing %s: file is already untracked\n')
965 ui.warn(_('not removing %s: file is already untracked\n')
966 % m.rel(f))
966 % m.rel(f))
967 result = 1
967 result = 1
968
968
969 for f in forget:
969 for f in forget:
970 if ui.verbose or not m.exact(f):
970 if ui.verbose or not m.exact(f):
971 ui.status(_('removing %s\n') % m.rel(f))
971 ui.status(_('removing %s\n') % m.rel(f))
972
972
973 # Need to lock because standin files are deleted then removed from the
973 # Need to lock because standin files are deleted then removed from the
974 # repository and we could race in-between.
974 # repository and we could race in-between.
975 wlock = repo.wlock()
975 wlock = repo.wlock()
976 try:
976 try:
977 lfdirstate = lfutil.openlfdirstate(ui, repo)
977 lfdirstate = lfutil.openlfdirstate(ui, repo)
978 for f in forget:
978 for f in forget:
979 if lfdirstate[f] == 'a':
979 if lfdirstate[f] == 'a':
980 lfdirstate.drop(f)
980 lfdirstate.drop(f)
981 else:
981 else:
982 lfdirstate.remove(f)
982 lfdirstate.remove(f)
983 lfdirstate.write()
983 lfdirstate.write()
984 standins = [lfutil.standin(f) for f in forget]
984 standins = [lfutil.standin(f) for f in forget]
985 for f in standins:
985 for f in standins:
986 util.unlinkpath(repo.wjoin(f), ignoremissing=True)
986 util.unlinkpath(repo.wjoin(f), ignoremissing=True)
987 repo[None].forget(standins)
987 repo[None].forget(standins)
988 finally:
988 finally:
989 wlock.release()
989 wlock.release()
990
990
991 return result
991 return result
992
992
993 def _getoutgoings(repo, other, missing, addfunc):
993 def _getoutgoings(repo, other, missing, addfunc):
994 """get pairs of filename and largefile hash in outgoing revisions
994 """get pairs of filename and largefile hash in outgoing revisions
995 in 'missing'.
995 in 'missing'.
996
996
997 largefiles already existing on 'other' repository are ignored.
997 largefiles already existing on 'other' repository are ignored.
998
998
999 'addfunc' is invoked with each unique pairs of filename and
999 'addfunc' is invoked with each unique pairs of filename and
1000 largefile hash value.
1000 largefile hash value.
1001 """
1001 """
1002 knowns = set()
1002 knowns = set()
1003 lfhashes = set()
1003 lfhashes = set()
1004 def dedup(fn, lfhash):
1004 def dedup(fn, lfhash):
1005 k = (fn, lfhash)
1005 k = (fn, lfhash)
1006 if k not in knowns:
1006 if k not in knowns:
1007 knowns.add(k)
1007 knowns.add(k)
1008 lfhashes.add(lfhash)
1008 lfhashes.add(lfhash)
1009 lfutil.getlfilestoupload(repo, missing, dedup)
1009 lfutil.getlfilestoupload(repo, missing, dedup)
1010 if lfhashes:
1010 if lfhashes:
1011 lfexists = basestore._openstore(repo, other).exists(lfhashes)
1011 lfexists = basestore._openstore(repo, other).exists(lfhashes)
1012 for fn, lfhash in knowns:
1012 for fn, lfhash in knowns:
1013 if not lfexists[lfhash]: # lfhash doesn't exist on "other"
1013 if not lfexists[lfhash]: # lfhash doesn't exist on "other"
1014 addfunc(fn, lfhash)
1014 addfunc(fn, lfhash)
1015
1015
1016 def outgoinghook(ui, repo, other, opts, missing):
1016 def outgoinghook(ui, repo, other, opts, missing):
1017 if opts.pop('large', None):
1017 if opts.pop('large', None):
1018 lfhashes = set()
1018 lfhashes = set()
1019 if ui.debugflag:
1019 if ui.debugflag:
1020 toupload = {}
1020 toupload = {}
1021 def addfunc(fn, lfhash):
1021 def addfunc(fn, lfhash):
1022 if fn not in toupload:
1022 if fn not in toupload:
1023 toupload[fn] = []
1023 toupload[fn] = []
1024 toupload[fn].append(lfhash)
1024 toupload[fn].append(lfhash)
1025 lfhashes.add(lfhash)
1025 lfhashes.add(lfhash)
1026 def showhashes(fn):
1026 def showhashes(fn):
1027 for lfhash in sorted(toupload[fn]):
1027 for lfhash in sorted(toupload[fn]):
1028 ui.debug(' %s\n' % (lfhash))
1028 ui.debug(' %s\n' % (lfhash))
1029 else:
1029 else:
1030 toupload = set()
1030 toupload = set()
1031 def addfunc(fn, lfhash):
1031 def addfunc(fn, lfhash):
1032 toupload.add(fn)
1032 toupload.add(fn)
1033 lfhashes.add(lfhash)
1033 lfhashes.add(lfhash)
1034 def showhashes(fn):
1034 def showhashes(fn):
1035 pass
1035 pass
1036 _getoutgoings(repo, other, missing, addfunc)
1036 _getoutgoings(repo, other, missing, addfunc)
1037
1037
1038 if not toupload:
1038 if not toupload:
1039 ui.status(_('largefiles: no files to upload\n'))
1039 ui.status(_('largefiles: no files to upload\n'))
1040 else:
1040 else:
1041 ui.status(_('largefiles to upload (%d entities):\n')
1041 ui.status(_('largefiles to upload (%d entities):\n')
1042 % (len(lfhashes)))
1042 % (len(lfhashes)))
1043 for file in sorted(toupload):
1043 for file in sorted(toupload):
1044 ui.status(lfutil.splitstandin(file) + '\n')
1044 ui.status(lfutil.splitstandin(file) + '\n')
1045 showhashes(file)
1045 showhashes(file)
1046 ui.status('\n')
1046 ui.status('\n')
1047
1047
1048 def summaryremotehook(ui, repo, opts, changes):
1048 def summaryremotehook(ui, repo, opts, changes):
1049 largeopt = opts.get('large', False)
1049 largeopt = opts.get('large', False)
1050 if changes is None:
1050 if changes is None:
1051 if largeopt:
1051 if largeopt:
1052 return (False, True) # only outgoing check is needed
1052 return (False, True) # only outgoing check is needed
1053 else:
1053 else:
1054 return (False, False)
1054 return (False, False)
1055 elif largeopt:
1055 elif largeopt:
1056 url, branch, peer, outgoing = changes[1]
1056 url, branch, peer, outgoing = changes[1]
1057 if peer is None:
1057 if peer is None:
1058 # i18n: column positioning for "hg summary"
1058 # i18n: column positioning for "hg summary"
1059 ui.status(_('largefiles: (no remote repo)\n'))
1059 ui.status(_('largefiles: (no remote repo)\n'))
1060 return
1060 return
1061
1061
1062 toupload = set()
1062 toupload = set()
1063 lfhashes = set()
1063 lfhashes = set()
1064 def addfunc(fn, lfhash):
1064 def addfunc(fn, lfhash):
1065 toupload.add(fn)
1065 toupload.add(fn)
1066 lfhashes.add(lfhash)
1066 lfhashes.add(lfhash)
1067 _getoutgoings(repo, peer, outgoing.missing, addfunc)
1067 _getoutgoings(repo, peer, outgoing.missing, addfunc)
1068
1068
1069 if not toupload:
1069 if not toupload:
1070 # i18n: column positioning for "hg summary"
1070 # i18n: column positioning for "hg summary"
1071 ui.status(_('largefiles: (no files to upload)\n'))
1071 ui.status(_('largefiles: (no files to upload)\n'))
1072 else:
1072 else:
1073 # i18n: column positioning for "hg summary"
1073 # i18n: column positioning for "hg summary"
1074 ui.status(_('largefiles: %d entities for %d files to upload\n')
1074 ui.status(_('largefiles: %d entities for %d files to upload\n')
1075 % (len(lfhashes), len(toupload)))
1075 % (len(lfhashes), len(toupload)))
1076
1076
1077 def overridesummary(orig, ui, repo, *pats, **opts):
1077 def overridesummary(orig, ui, repo, *pats, **opts):
1078 try:
1078 try:
1079 repo.lfstatus = True
1079 repo.lfstatus = True
1080 orig(ui, repo, *pats, **opts)
1080 orig(ui, repo, *pats, **opts)
1081 finally:
1081 finally:
1082 repo.lfstatus = False
1082 repo.lfstatus = False
1083
1083
1084 def scmutiladdremove(orig, repo, pats=[], opts={}, dry_run=None,
1084 def scmutiladdremove(orig, repo, pats=[], opts={}, dry_run=None,
1085 similarity=None):
1085 similarity=None):
1086 if not lfutil.islfilesrepo(repo):
1086 if not lfutil.islfilesrepo(repo):
1087 return orig(repo, pats, opts, dry_run, similarity)
1087 return orig(repo, pats, opts, dry_run, similarity)
1088 # Get the list of missing largefiles so we can remove them
1088 # Get the list of missing largefiles so we can remove them
1089 lfdirstate = lfutil.openlfdirstate(repo.ui, repo)
1089 lfdirstate = lfutil.openlfdirstate(repo.ui, repo)
1090 unsure, s = lfdirstate.status(match_.always(repo.root, repo.getcwd()), [],
1090 unsure, s = lfdirstate.status(match_.always(repo.root, repo.getcwd()), [],
1091 False, False, False)
1091 False, False, False)
1092
1092
1093 # Call into the normal remove code, but the removing of the standin, we want
1093 # Call into the normal remove code, but the removing of the standin, we want
1094 # to have handled by original addremove. Monkey patching here makes sure
1094 # to have handled by original addremove. Monkey patching here makes sure
1095 # we don't remove the standin in the largefiles code, preventing a very
1095 # we don't remove the standin in the largefiles code, preventing a very
1096 # confused state later.
1096 # confused state later.
1097 if s.deleted:
1097 if s.deleted:
1098 m = [repo.wjoin(f) for f in s.deleted]
1098 m = [repo.wjoin(f) for f in s.deleted]
1099 removelargefiles(repo.ui, repo, True, *m, **opts)
1099 removelargefiles(repo.ui, repo, True, *m, **opts)
1100 # Call into the normal add code, and any files that *should* be added as
1100 # Call into the normal add code, and any files that *should* be added as
1101 # largefiles will be
1101 # largefiles will be
1102 addlargefiles(repo.ui, repo, *pats, **opts)
1102 addlargefiles(repo.ui, repo, *pats, **opts)
1103 # Now that we've handled largefiles, hand off to the original addremove
1103 # Now that we've handled largefiles, hand off to the original addremove
1104 # function to take care of the rest. Make sure it doesn't do anything with
1104 # function to take care of the rest. Make sure it doesn't do anything with
1105 # largefiles by installing a matcher that will ignore them.
1105 # largefiles by installing a matcher that will ignore them.
1106 installnormalfilesmatchfn(repo[None].manifest())
1106 installnormalfilesmatchfn(repo[None].manifest())
1107 result = orig(repo, pats, opts, dry_run, similarity)
1107 result = orig(repo, pats, opts, dry_run, similarity)
1108 restorematchfn()
1108 restorematchfn()
1109 return result
1109 return result
1110
1110
1111 # Calling purge with --all will cause the largefiles to be deleted.
1111 # Calling purge with --all will cause the largefiles to be deleted.
1112 # Override repo.status to prevent this from happening.
1112 # Override repo.status to prevent this from happening.
1113 def overridepurge(orig, ui, repo, *dirs, **opts):
1113 def overridepurge(orig, ui, repo, *dirs, **opts):
1114 # XXX large file status is buggy when used on repo proxy.
1114 # XXX large file status is buggy when used on repo proxy.
1115 # XXX this needs to be investigate.
1115 # XXX this needs to be investigate.
1116 repo = repo.unfiltered()
1116 repo = repo.unfiltered()
1117 oldstatus = repo.status
1117 oldstatus = repo.status
1118 def overridestatus(node1='.', node2=None, match=None, ignored=False,
1118 def overridestatus(node1='.', node2=None, match=None, ignored=False,
1119 clean=False, unknown=False, listsubrepos=False):
1119 clean=False, unknown=False, listsubrepos=False):
1120 r = oldstatus(node1, node2, match, ignored, clean, unknown,
1120 r = oldstatus(node1, node2, match, ignored, clean, unknown,
1121 listsubrepos)
1121 listsubrepos)
1122 lfdirstate = lfutil.openlfdirstate(ui, repo)
1122 lfdirstate = lfutil.openlfdirstate(ui, repo)
1123 unknown = [f for f in r.unknown if lfdirstate[f] == '?']
1123 unknown = [f for f in r.unknown if lfdirstate[f] == '?']
1124 ignored = [f for f in r.ignored if lfdirstate[f] == '?']
1124 ignored = [f for f in r.ignored if lfdirstate[f] == '?']
1125 return scmutil.status(r.modified, r.added, r.removed, r.deleted,
1125 return scmutil.status(r.modified, r.added, r.removed, r.deleted,
1126 unknown, ignored, r.clean)
1126 unknown, ignored, r.clean)
1127 repo.status = overridestatus
1127 repo.status = overridestatus
1128 orig(ui, repo, *dirs, **opts)
1128 orig(ui, repo, *dirs, **opts)
1129 repo.status = oldstatus
1129 repo.status = oldstatus
1130 def overriderollback(orig, ui, repo, **opts):
1130 def overriderollback(orig, ui, repo, **opts):
1131 wlock = repo.wlock()
1131 wlock = repo.wlock()
1132 try:
1132 try:
1133 before = repo.dirstate.parents()
1133 before = repo.dirstate.parents()
1134 orphans = set(f for f in repo.dirstate
1134 orphans = set(f for f in repo.dirstate
1135 if lfutil.isstandin(f) and repo.dirstate[f] != 'r')
1135 if lfutil.isstandin(f) and repo.dirstate[f] != 'r')
1136 result = orig(ui, repo, **opts)
1136 result = orig(ui, repo, **opts)
1137 after = repo.dirstate.parents()
1137 after = repo.dirstate.parents()
1138 if before == after:
1138 if before == after:
1139 return result # no need to restore standins
1139 return result # no need to restore standins
1140
1140
1141 pctx = repo['.']
1141 pctx = repo['.']
1142 for f in repo.dirstate:
1142 for f in repo.dirstate:
1143 if lfutil.isstandin(f):
1143 if lfutil.isstandin(f):
1144 orphans.discard(f)
1144 orphans.discard(f)
1145 if repo.dirstate[f] == 'r':
1145 if repo.dirstate[f] == 'r':
1146 repo.wvfs.unlinkpath(f, ignoremissing=True)
1146 repo.wvfs.unlinkpath(f, ignoremissing=True)
1147 elif f in pctx:
1147 elif f in pctx:
1148 fctx = pctx[f]
1148 fctx = pctx[f]
1149 repo.wwrite(f, fctx.data(), fctx.flags())
1149 repo.wwrite(f, fctx.data(), fctx.flags())
1150 else:
1150 else:
1151 # content of standin is not so important in 'a',
1151 # content of standin is not so important in 'a',
1152 # 'm' or 'n' (coming from the 2nd parent) cases
1152 # 'm' or 'n' (coming from the 2nd parent) cases
1153 lfutil.writestandin(repo, f, '', False)
1153 lfutil.writestandin(repo, f, '', False)
1154 for standin in orphans:
1154 for standin in orphans:
1155 repo.wvfs.unlinkpath(standin, ignoremissing=True)
1155 repo.wvfs.unlinkpath(standin, ignoremissing=True)
1156
1156
1157 lfdirstate = lfutil.openlfdirstate(ui, repo)
1157 lfdirstate = lfutil.openlfdirstate(ui, repo)
1158 orphans = set(lfdirstate)
1158 orphans = set(lfdirstate)
1159 lfiles = lfutil.listlfiles(repo)
1159 lfiles = lfutil.listlfiles(repo)
1160 for file in lfiles:
1160 for file in lfiles:
1161 lfutil.synclfdirstate(repo, lfdirstate, file, True)
1161 lfutil.synclfdirstate(repo, lfdirstate, file, True)
1162 orphans.discard(file)
1162 orphans.discard(file)
1163 for lfile in orphans:
1163 for lfile in orphans:
1164 lfdirstate.drop(lfile)
1164 lfdirstate.drop(lfile)
1165 lfdirstate.write()
1165 lfdirstate.write()
1166 finally:
1166 finally:
1167 wlock.release()
1167 wlock.release()
1168 return result
1168 return result
1169
1169
1170 def overridetransplant(orig, ui, repo, *revs, **opts):
1170 def overridetransplant(orig, ui, repo, *revs, **opts):
1171 try:
1171 try:
1172 oldstandins = lfutil.getstandinsstate(repo)
1173 repo._istransplanting = True
1172 repo._istransplanting = True
1174 result = orig(ui, repo, *revs, **opts)
1173 result = orig(ui, repo, *revs, **opts)
1175 newstandins = lfutil.getstandinsstate(repo)
1176 filelist = lfutil.getlfilestoupdate(oldstandins, newstandins)
1177 lfcommands.updatelfiles(repo.ui, repo, filelist=filelist,
1178 printmessage=True)
1179 finally:
1174 finally:
1180 repo._istransplanting = False
1175 repo._istransplanting = False
1181 return result
1176 return result
1182
1177
1183 def overridecat(orig, ui, repo, file1, *pats, **opts):
1178 def overridecat(orig, ui, repo, file1, *pats, **opts):
1184 ctx = scmutil.revsingle(repo, opts.get('rev'))
1179 ctx = scmutil.revsingle(repo, opts.get('rev'))
1185 err = 1
1180 err = 1
1186 notbad = set()
1181 notbad = set()
1187 m = scmutil.match(ctx, (file1,) + pats, opts)
1182 m = scmutil.match(ctx, (file1,) + pats, opts)
1188 origmatchfn = m.matchfn
1183 origmatchfn = m.matchfn
1189 def lfmatchfn(f):
1184 def lfmatchfn(f):
1190 if origmatchfn(f):
1185 if origmatchfn(f):
1191 return True
1186 return True
1192 lf = lfutil.splitstandin(f)
1187 lf = lfutil.splitstandin(f)
1193 if lf is None:
1188 if lf is None:
1194 return False
1189 return False
1195 notbad.add(lf)
1190 notbad.add(lf)
1196 return origmatchfn(lf)
1191 return origmatchfn(lf)
1197 m.matchfn = lfmatchfn
1192 m.matchfn = lfmatchfn
1198 origbadfn = m.bad
1193 origbadfn = m.bad
1199 def lfbadfn(f, msg):
1194 def lfbadfn(f, msg):
1200 if not f in notbad:
1195 if not f in notbad:
1201 origbadfn(f, msg)
1196 origbadfn(f, msg)
1202 m.bad = lfbadfn
1197 m.bad = lfbadfn
1203 for f in ctx.walk(m):
1198 for f in ctx.walk(m):
1204 fp = cmdutil.makefileobj(repo, opts.get('output'), ctx.node(),
1199 fp = cmdutil.makefileobj(repo, opts.get('output'), ctx.node(),
1205 pathname=f)
1200 pathname=f)
1206 lf = lfutil.splitstandin(f)
1201 lf = lfutil.splitstandin(f)
1207 if lf is None or origmatchfn(f):
1202 if lf is None or origmatchfn(f):
1208 # duplicating unreachable code from commands.cat
1203 # duplicating unreachable code from commands.cat
1209 data = ctx[f].data()
1204 data = ctx[f].data()
1210 if opts.get('decode'):
1205 if opts.get('decode'):
1211 data = repo.wwritedata(f, data)
1206 data = repo.wwritedata(f, data)
1212 fp.write(data)
1207 fp.write(data)
1213 else:
1208 else:
1214 hash = lfutil.readstandin(repo, lf, ctx.rev())
1209 hash = lfutil.readstandin(repo, lf, ctx.rev())
1215 if not lfutil.inusercache(repo.ui, hash):
1210 if not lfutil.inusercache(repo.ui, hash):
1216 store = basestore._openstore(repo)
1211 store = basestore._openstore(repo)
1217 success, missing = store.get([(lf, hash)])
1212 success, missing = store.get([(lf, hash)])
1218 if len(success) != 1:
1213 if len(success) != 1:
1219 raise util.Abort(
1214 raise util.Abort(
1220 _('largefile %s is not in cache and could not be '
1215 _('largefile %s is not in cache and could not be '
1221 'downloaded') % lf)
1216 'downloaded') % lf)
1222 path = lfutil.usercachepath(repo.ui, hash)
1217 path = lfutil.usercachepath(repo.ui, hash)
1223 fpin = open(path, "rb")
1218 fpin = open(path, "rb")
1224 for chunk in util.filechunkiter(fpin, 128 * 1024):
1219 for chunk in util.filechunkiter(fpin, 128 * 1024):
1225 fp.write(chunk)
1220 fp.write(chunk)
1226 fpin.close()
1221 fpin.close()
1227 fp.close()
1222 fp.close()
1228 err = 0
1223 err = 0
1229 return err
1224 return err
1230
1225
1231 def mercurialsinkbefore(orig, sink):
1226 def mercurialsinkbefore(orig, sink):
1232 sink.repo._isconverting = True
1227 sink.repo._isconverting = True
1233 orig(sink)
1228 orig(sink)
1234
1229
1235 def mercurialsinkafter(orig, sink):
1230 def mercurialsinkafter(orig, sink):
1236 sink.repo._isconverting = False
1231 sink.repo._isconverting = False
1237 orig(sink)
1232 orig(sink)
1238
1233
1239 def mergeupdate(orig, repo, node, branchmerge, force, partial,
1234 def mergeupdate(orig, repo, node, branchmerge, force, partial,
1240 *args, **kwargs):
1235 *args, **kwargs):
1241 wlock = repo.wlock()
1236 wlock = repo.wlock()
1242 try:
1237 try:
1243 # branch | | |
1238 # branch | | |
1244 # merge | force | partial | action
1239 # merge | force | partial | action
1245 # -------+-------+---------+--------------
1240 # -------+-------+---------+--------------
1246 # x | x | x | linear-merge
1241 # x | x | x | linear-merge
1247 # o | x | x | branch-merge
1242 # o | x | x | branch-merge
1248 # x | o | x | overwrite (as clean update)
1243 # x | o | x | overwrite (as clean update)
1249 # o | o | x | force-branch-merge (*1)
1244 # o | o | x | force-branch-merge (*1)
1250 # x | x | o | (*)
1245 # x | x | o | (*)
1251 # o | x | o | (*)
1246 # o | x | o | (*)
1252 # x | o | o | overwrite (as revert)
1247 # x | o | o | overwrite (as revert)
1253 # o | o | o | (*)
1248 # o | o | o | (*)
1254 #
1249 #
1255 # (*) don't care
1250 # (*) don't care
1256 # (*1) deprecated, but used internally (e.g: "rebase --collapse")
1251 # (*1) deprecated, but used internally (e.g: "rebase --collapse")
1257
1252
1258 linearmerge = not branchmerge and not force and not partial
1253 linearmerge = not branchmerge and not force and not partial
1259
1254
1260 if linearmerge or (branchmerge and force and not partial):
1255 if linearmerge or (branchmerge and force and not partial):
1261 # update standins for linear-merge or force-branch-merge,
1256 # update standins for linear-merge or force-branch-merge,
1262 # because largefiles in the working directory may be modified
1257 # because largefiles in the working directory may be modified
1263 lfdirstate = lfutil.openlfdirstate(repo.ui, repo)
1258 lfdirstate = lfutil.openlfdirstate(repo.ui, repo)
1264 unsure, s = lfdirstate.status(match_.always(repo.root,
1259 unsure, s = lfdirstate.status(match_.always(repo.root,
1265 repo.getcwd()),
1260 repo.getcwd()),
1266 [], False, False, False)
1261 [], False, False, False)
1267 for lfile in unsure + s.modified + s.added:
1262 for lfile in unsure + s.modified + s.added:
1268 lfutil.updatestandin(repo, lfutil.standin(lfile))
1263 lfutil.updatestandin(repo, lfutil.standin(lfile))
1269
1264
1270 if linearmerge:
1265 if linearmerge:
1271 # Only call updatelfiles on the standins that have changed
1266 # Only call updatelfiles on the standins that have changed
1272 # to save time
1267 # to save time
1273 oldstandins = lfutil.getstandinsstate(repo)
1268 oldstandins = lfutil.getstandinsstate(repo)
1274
1269
1275 result = orig(repo, node, branchmerge, force, partial, *args, **kwargs)
1270 result = orig(repo, node, branchmerge, force, partial, *args, **kwargs)
1276
1271
1277 filelist = None
1272 filelist = None
1278 if linearmerge:
1273 if linearmerge:
1279 newstandins = lfutil.getstandinsstate(repo)
1274 newstandins = lfutil.getstandinsstate(repo)
1280 filelist = lfutil.getlfilestoupdate(oldstandins, newstandins)
1275 filelist = lfutil.getlfilestoupdate(oldstandins, newstandins)
1281
1276
1282 printmessage = None
1277 printmessage = None
1283 if getattr(repo, "_istransplanting", False):
1278 if getattr(repo, "_istransplanting", False):
1284 # suppress status message while automated committing
1279 # suppress status message while automated committing
1285 printmessage = False
1280 printmessage = False
1286 lfcommands.updatelfiles(repo.ui, repo, filelist=filelist,
1281 lfcommands.updatelfiles(repo.ui, repo, filelist=filelist,
1287 printmessage=printmessage,
1282 printmessage=printmessage,
1288 normallookup=partial)
1283 normallookup=partial)
1289
1284
1290 return result
1285 return result
1291 finally:
1286 finally:
1292 wlock.release()
1287 wlock.release()
1293
1288
1294 def scmutilmarktouched(orig, repo, files, *args, **kwargs):
1289 def scmutilmarktouched(orig, repo, files, *args, **kwargs):
1295 result = orig(repo, files, *args, **kwargs)
1290 result = orig(repo, files, *args, **kwargs)
1296
1291
1297 filelist = [lfutil.splitstandin(f) for f in files if lfutil.isstandin(f)]
1292 filelist = [lfutil.splitstandin(f) for f in files if lfutil.isstandin(f)]
1298 if filelist:
1293 if filelist:
1299 lfcommands.updatelfiles(repo.ui, repo, filelist=filelist,
1294 lfcommands.updatelfiles(repo.ui, repo, filelist=filelist,
1300 printmessage=False, normallookup=True)
1295 printmessage=False, normallookup=True)
1301
1296
1302 return result
1297 return result
@@ -1,1823 +1,1821 b''
1 This file used to contains all largefile tests.
1 This file used to contains all largefile tests.
2 Do not add any new tests in this file as it his already far too long to run.
2 Do not add any new tests in this file as it his already far too long to run.
3
3
4 It contains all the testing of the basic concepts of large file in a single block.
4 It contains all the testing of the basic concepts of large file in a single block.
5
5
6 $ USERCACHE="$TESTTMP/cache"; export USERCACHE
6 $ USERCACHE="$TESTTMP/cache"; export USERCACHE
7 $ mkdir "${USERCACHE}"
7 $ mkdir "${USERCACHE}"
8 $ cat >> $HGRCPATH <<EOF
8 $ cat >> $HGRCPATH <<EOF
9 > [extensions]
9 > [extensions]
10 > largefiles=
10 > largefiles=
11 > purge=
11 > purge=
12 > rebase=
12 > rebase=
13 > transplant=
13 > transplant=
14 > [phases]
14 > [phases]
15 > publish=False
15 > publish=False
16 > [largefiles]
16 > [largefiles]
17 > minsize=2
17 > minsize=2
18 > patterns=glob:**.dat
18 > patterns=glob:**.dat
19 > usercache=${USERCACHE}
19 > usercache=${USERCACHE}
20 > [hooks]
20 > [hooks]
21 > precommit=sh -c "echo \\"Invoking status precommit hook\\"; hg status"
21 > precommit=sh -c "echo \\"Invoking status precommit hook\\"; hg status"
22 > EOF
22 > EOF
23
23
24 Create the repo with a couple of revisions of both large and normal
24 Create the repo with a couple of revisions of both large and normal
25 files.
25 files.
26 Test status and dirstate of largefiles and that summary output is correct.
26 Test status and dirstate of largefiles and that summary output is correct.
27
27
28 $ hg init a
28 $ hg init a
29 $ cd a
29 $ cd a
30 $ mkdir sub
30 $ mkdir sub
31 $ echo normal1 > normal1
31 $ echo normal1 > normal1
32 $ echo normal2 > sub/normal2
32 $ echo normal2 > sub/normal2
33 $ echo large1 > large1
33 $ echo large1 > large1
34 $ echo large2 > sub/large2
34 $ echo large2 > sub/large2
35 $ hg add normal1 sub/normal2
35 $ hg add normal1 sub/normal2
36 $ hg add --large large1 sub/large2
36 $ hg add --large large1 sub/large2
37 $ hg commit -m "add files"
37 $ hg commit -m "add files"
38 Invoking status precommit hook
38 Invoking status precommit hook
39 A large1
39 A large1
40 A normal1
40 A normal1
41 A sub/large2
41 A sub/large2
42 A sub/normal2
42 A sub/normal2
43 $ touch large1 sub/large2
43 $ touch large1 sub/large2
44 $ sleep 1
44 $ sleep 1
45 $ hg st
45 $ hg st
46 $ hg debugstate --nodates
46 $ hg debugstate --nodates
47 n 644 41 .hglf/large1
47 n 644 41 .hglf/large1
48 n 644 41 .hglf/sub/large2
48 n 644 41 .hglf/sub/large2
49 n 644 8 normal1
49 n 644 8 normal1
50 n 644 8 sub/normal2
50 n 644 8 sub/normal2
51 $ hg debugstate --large --nodates
51 $ hg debugstate --large --nodates
52 n 644 7 large1
52 n 644 7 large1
53 n 644 7 sub/large2
53 n 644 7 sub/large2
54 $ echo normal11 > normal1
54 $ echo normal11 > normal1
55 $ echo normal22 > sub/normal2
55 $ echo normal22 > sub/normal2
56 $ echo large11 > large1
56 $ echo large11 > large1
57 $ echo large22 > sub/large2
57 $ echo large22 > sub/large2
58 $ hg commit -m "edit files"
58 $ hg commit -m "edit files"
59 Invoking status precommit hook
59 Invoking status precommit hook
60 M large1
60 M large1
61 M normal1
61 M normal1
62 M sub/large2
62 M sub/large2
63 M sub/normal2
63 M sub/normal2
64 $ hg sum --large
64 $ hg sum --large
65 parent: 1:ce8896473775 tip
65 parent: 1:ce8896473775 tip
66 edit files
66 edit files
67 branch: default
67 branch: default
68 commit: (clean)
68 commit: (clean)
69 update: (current)
69 update: (current)
70 largefiles: (no remote repo)
70 largefiles: (no remote repo)
71
71
72 Commit preserved largefile contents.
72 Commit preserved largefile contents.
73
73
74 $ cat normal1
74 $ cat normal1
75 normal11
75 normal11
76 $ cat large1
76 $ cat large1
77 large11
77 large11
78 $ cat sub/normal2
78 $ cat sub/normal2
79 normal22
79 normal22
80 $ cat sub/large2
80 $ cat sub/large2
81 large22
81 large22
82
82
83 Test status, subdir and unknown files
83 Test status, subdir and unknown files
84
84
85 $ echo unknown > sub/unknown
85 $ echo unknown > sub/unknown
86 $ hg st --all
86 $ hg st --all
87 ? sub/unknown
87 ? sub/unknown
88 C large1
88 C large1
89 C normal1
89 C normal1
90 C sub/large2
90 C sub/large2
91 C sub/normal2
91 C sub/normal2
92 $ hg st --all sub
92 $ hg st --all sub
93 ? sub/unknown
93 ? sub/unknown
94 C sub/large2
94 C sub/large2
95 C sub/normal2
95 C sub/normal2
96 $ rm sub/unknown
96 $ rm sub/unknown
97
97
98 Test messages and exit codes for remove warning cases
98 Test messages and exit codes for remove warning cases
99
99
100 $ hg remove -A large1
100 $ hg remove -A large1
101 not removing large1: file still exists
101 not removing large1: file still exists
102 [1]
102 [1]
103 $ echo 'modified' > large1
103 $ echo 'modified' > large1
104 $ hg remove large1
104 $ hg remove large1
105 not removing large1: file is modified (use -f to force removal)
105 not removing large1: file is modified (use -f to force removal)
106 [1]
106 [1]
107 $ echo 'new' > normalnew
107 $ echo 'new' > normalnew
108 $ hg add normalnew
108 $ hg add normalnew
109 $ echo 'new' > largenew
109 $ echo 'new' > largenew
110 $ hg add --large normalnew
110 $ hg add --large normalnew
111 normalnew already tracked!
111 normalnew already tracked!
112 $ hg remove normalnew largenew
112 $ hg remove normalnew largenew
113 not removing largenew: file is untracked
113 not removing largenew: file is untracked
114 not removing normalnew: file has been marked for add (use forget to undo)
114 not removing normalnew: file has been marked for add (use forget to undo)
115 [1]
115 [1]
116 $ rm normalnew largenew
116 $ rm normalnew largenew
117 $ hg up -Cq
117 $ hg up -Cq
118
118
119 Remove both largefiles and normal files.
119 Remove both largefiles and normal files.
120
120
121 $ hg remove normal1 large1
121 $ hg remove normal1 large1
122 $ hg status large1
122 $ hg status large1
123 R large1
123 R large1
124 $ hg commit -m "remove files"
124 $ hg commit -m "remove files"
125 Invoking status precommit hook
125 Invoking status precommit hook
126 R large1
126 R large1
127 R normal1
127 R normal1
128 $ ls
128 $ ls
129 sub
129 sub
130 $ echo "testlargefile" > large1-test
130 $ echo "testlargefile" > large1-test
131 $ hg add --large large1-test
131 $ hg add --large large1-test
132 $ hg st
132 $ hg st
133 A large1-test
133 A large1-test
134 $ hg rm large1-test
134 $ hg rm large1-test
135 not removing large1-test: file has been marked for add (use forget to undo)
135 not removing large1-test: file has been marked for add (use forget to undo)
136 [1]
136 [1]
137 $ hg st
137 $ hg st
138 A large1-test
138 A large1-test
139 $ hg forget large1-test
139 $ hg forget large1-test
140 $ hg st
140 $ hg st
141 ? large1-test
141 ? large1-test
142 $ hg remove large1-test
142 $ hg remove large1-test
143 not removing large1-test: file is untracked
143 not removing large1-test: file is untracked
144 [1]
144 [1]
145 $ hg forget large1-test
145 $ hg forget large1-test
146 not removing large1-test: file is already untracked
146 not removing large1-test: file is already untracked
147 [1]
147 [1]
148 $ rm large1-test
148 $ rm large1-test
149
149
150 Copy both largefiles and normal files (testing that status output is correct).
150 Copy both largefiles and normal files (testing that status output is correct).
151
151
152 $ hg cp sub/normal2 normal1
152 $ hg cp sub/normal2 normal1
153 $ hg cp sub/large2 large1
153 $ hg cp sub/large2 large1
154 $ hg commit -m "copy files"
154 $ hg commit -m "copy files"
155 Invoking status precommit hook
155 Invoking status precommit hook
156 A large1
156 A large1
157 A normal1
157 A normal1
158 $ cat normal1
158 $ cat normal1
159 normal22
159 normal22
160 $ cat large1
160 $ cat large1
161 large22
161 large22
162
162
163 Test moving largefiles and verify that normal files are also unaffected.
163 Test moving largefiles and verify that normal files are also unaffected.
164
164
165 $ hg mv normal1 normal3
165 $ hg mv normal1 normal3
166 $ hg mv large1 large3
166 $ hg mv large1 large3
167 $ hg mv sub/normal2 sub/normal4
167 $ hg mv sub/normal2 sub/normal4
168 $ hg mv sub/large2 sub/large4
168 $ hg mv sub/large2 sub/large4
169 $ hg commit -m "move files"
169 $ hg commit -m "move files"
170 Invoking status precommit hook
170 Invoking status precommit hook
171 A large3
171 A large3
172 A normal3
172 A normal3
173 A sub/large4
173 A sub/large4
174 A sub/normal4
174 A sub/normal4
175 R large1
175 R large1
176 R normal1
176 R normal1
177 R sub/large2
177 R sub/large2
178 R sub/normal2
178 R sub/normal2
179 $ cat normal3
179 $ cat normal3
180 normal22
180 normal22
181 $ cat large3
181 $ cat large3
182 large22
182 large22
183 $ cat sub/normal4
183 $ cat sub/normal4
184 normal22
184 normal22
185 $ cat sub/large4
185 $ cat sub/large4
186 large22
186 large22
187
187
188
188
189 #if serve
189 #if serve
190 Test display of largefiles in hgweb
190 Test display of largefiles in hgweb
191
191
192 $ hg serve -d -p $HGPORT --pid-file ../hg.pid
192 $ hg serve -d -p $HGPORT --pid-file ../hg.pid
193 $ cat ../hg.pid >> $DAEMON_PIDS
193 $ cat ../hg.pid >> $DAEMON_PIDS
194 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT 'file/tip/?style=raw'
194 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT 'file/tip/?style=raw'
195 200 Script output follows
195 200 Script output follows
196
196
197
197
198 drwxr-xr-x sub
198 drwxr-xr-x sub
199 -rw-r--r-- 41 large3
199 -rw-r--r-- 41 large3
200 -rw-r--r-- 9 normal3
200 -rw-r--r-- 9 normal3
201
201
202
202
203 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT 'file/tip/sub/?style=raw'
203 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT 'file/tip/sub/?style=raw'
204 200 Script output follows
204 200 Script output follows
205
205
206
206
207 -rw-r--r-- 41 large4
207 -rw-r--r-- 41 large4
208 -rw-r--r-- 9 normal4
208 -rw-r--r-- 9 normal4
209
209
210
210
211 $ "$TESTDIR/killdaemons.py" $DAEMON_PIDS
211 $ "$TESTDIR/killdaemons.py" $DAEMON_PIDS
212 #endif
212 #endif
213
213
214 Test archiving the various revisions. These hit corner cases known with
214 Test archiving the various revisions. These hit corner cases known with
215 archiving.
215 archiving.
216
216
217 $ hg archive -r 0 ../archive0
217 $ hg archive -r 0 ../archive0
218 $ hg archive -r 1 ../archive1
218 $ hg archive -r 1 ../archive1
219 $ hg archive -r 2 ../archive2
219 $ hg archive -r 2 ../archive2
220 $ hg archive -r 3 ../archive3
220 $ hg archive -r 3 ../archive3
221 $ hg archive -r 4 ../archive4
221 $ hg archive -r 4 ../archive4
222 $ cd ../archive0
222 $ cd ../archive0
223 $ cat normal1
223 $ cat normal1
224 normal1
224 normal1
225 $ cat large1
225 $ cat large1
226 large1
226 large1
227 $ cat sub/normal2
227 $ cat sub/normal2
228 normal2
228 normal2
229 $ cat sub/large2
229 $ cat sub/large2
230 large2
230 large2
231 $ cd ../archive1
231 $ cd ../archive1
232 $ cat normal1
232 $ cat normal1
233 normal11
233 normal11
234 $ cat large1
234 $ cat large1
235 large11
235 large11
236 $ cat sub/normal2
236 $ cat sub/normal2
237 normal22
237 normal22
238 $ cat sub/large2
238 $ cat sub/large2
239 large22
239 large22
240 $ cd ../archive2
240 $ cd ../archive2
241 $ ls
241 $ ls
242 sub
242 sub
243 $ cat sub/normal2
243 $ cat sub/normal2
244 normal22
244 normal22
245 $ cat sub/large2
245 $ cat sub/large2
246 large22
246 large22
247 $ cd ../archive3
247 $ cd ../archive3
248 $ cat normal1
248 $ cat normal1
249 normal22
249 normal22
250 $ cat large1
250 $ cat large1
251 large22
251 large22
252 $ cat sub/normal2
252 $ cat sub/normal2
253 normal22
253 normal22
254 $ cat sub/large2
254 $ cat sub/large2
255 large22
255 large22
256 $ cd ../archive4
256 $ cd ../archive4
257 $ cat normal3
257 $ cat normal3
258 normal22
258 normal22
259 $ cat large3
259 $ cat large3
260 large22
260 large22
261 $ cat sub/normal4
261 $ cat sub/normal4
262 normal22
262 normal22
263 $ cat sub/large4
263 $ cat sub/large4
264 large22
264 large22
265
265
266 Commit corner case: specify files to commit.
266 Commit corner case: specify files to commit.
267
267
268 $ cd ../a
268 $ cd ../a
269 $ echo normal3 > normal3
269 $ echo normal3 > normal3
270 $ echo large3 > large3
270 $ echo large3 > large3
271 $ echo normal4 > sub/normal4
271 $ echo normal4 > sub/normal4
272 $ echo large4 > sub/large4
272 $ echo large4 > sub/large4
273 $ hg commit normal3 large3 sub/normal4 sub/large4 -m "edit files again"
273 $ hg commit normal3 large3 sub/normal4 sub/large4 -m "edit files again"
274 Invoking status precommit hook
274 Invoking status precommit hook
275 M large3
275 M large3
276 M normal3
276 M normal3
277 M sub/large4
277 M sub/large4
278 M sub/normal4
278 M sub/normal4
279 $ cat normal3
279 $ cat normal3
280 normal3
280 normal3
281 $ cat large3
281 $ cat large3
282 large3
282 large3
283 $ cat sub/normal4
283 $ cat sub/normal4
284 normal4
284 normal4
285 $ cat sub/large4
285 $ cat sub/large4
286 large4
286 large4
287
287
288 One more commit corner case: commit from a subdirectory.
288 One more commit corner case: commit from a subdirectory.
289
289
290 $ cd ../a
290 $ cd ../a
291 $ echo normal33 > normal3
291 $ echo normal33 > normal3
292 $ echo large33 > large3
292 $ echo large33 > large3
293 $ echo normal44 > sub/normal4
293 $ echo normal44 > sub/normal4
294 $ echo large44 > sub/large4
294 $ echo large44 > sub/large4
295 $ cd sub
295 $ cd sub
296 $ hg commit -m "edit files yet again"
296 $ hg commit -m "edit files yet again"
297 Invoking status precommit hook
297 Invoking status precommit hook
298 M large3
298 M large3
299 M normal3
299 M normal3
300 M sub/large4
300 M sub/large4
301 M sub/normal4
301 M sub/normal4
302 $ cat ../normal3
302 $ cat ../normal3
303 normal33
303 normal33
304 $ cat ../large3
304 $ cat ../large3
305 large33
305 large33
306 $ cat normal4
306 $ cat normal4
307 normal44
307 normal44
308 $ cat large4
308 $ cat large4
309 large44
309 large44
310
310
311 Committing standins is not allowed.
311 Committing standins is not allowed.
312
312
313 $ cd ..
313 $ cd ..
314 $ echo large3 > large3
314 $ echo large3 > large3
315 $ hg commit .hglf/large3 -m "try to commit standin"
315 $ hg commit .hglf/large3 -m "try to commit standin"
316 abort: file ".hglf/large3" is a largefile standin
316 abort: file ".hglf/large3" is a largefile standin
317 (commit the largefile itself instead)
317 (commit the largefile itself instead)
318 [255]
318 [255]
319
319
320 Corner cases for adding largefiles.
320 Corner cases for adding largefiles.
321
321
322 $ echo large5 > large5
322 $ echo large5 > large5
323 $ hg add --large large5
323 $ hg add --large large5
324 $ hg add --large large5
324 $ hg add --large large5
325 large5 already a largefile
325 large5 already a largefile
326 $ mkdir sub2
326 $ mkdir sub2
327 $ echo large6 > sub2/large6
327 $ echo large6 > sub2/large6
328 $ echo large7 > sub2/large7
328 $ echo large7 > sub2/large7
329 $ hg add --large sub2
329 $ hg add --large sub2
330 adding sub2/large6 as a largefile (glob)
330 adding sub2/large6 as a largefile (glob)
331 adding sub2/large7 as a largefile (glob)
331 adding sub2/large7 as a largefile (glob)
332 $ hg st
332 $ hg st
333 M large3
333 M large3
334 A large5
334 A large5
335 A sub2/large6
335 A sub2/large6
336 A sub2/large7
336 A sub2/large7
337
337
338 Committing directories containing only largefiles.
338 Committing directories containing only largefiles.
339
339
340 $ mkdir -p z/y/x/m
340 $ mkdir -p z/y/x/m
341 $ touch z/y/x/m/large1
341 $ touch z/y/x/m/large1
342 $ touch z/y/x/large2
342 $ touch z/y/x/large2
343 $ hg add --large z/y/x/m/large1 z/y/x/large2
343 $ hg add --large z/y/x/m/large1 z/y/x/large2
344 $ hg commit -m "Subdir with directory only containing largefiles" z
344 $ hg commit -m "Subdir with directory only containing largefiles" z
345 Invoking status precommit hook
345 Invoking status precommit hook
346 M large3
346 M large3
347 A large5
347 A large5
348 A sub2/large6
348 A sub2/large6
349 A sub2/large7
349 A sub2/large7
350 A z/y/x/large2
350 A z/y/x/large2
351 A z/y/x/m/large1
351 A z/y/x/m/large1
352
352
353 (and a bit of log testing)
353 (and a bit of log testing)
354
354
355 $ hg log -T '{rev}\n' z/y/x/m/large1
355 $ hg log -T '{rev}\n' z/y/x/m/large1
356 7
356 7
357 $ hg log -T '{rev}\n' z/y/x/m # with only a largefile
357 $ hg log -T '{rev}\n' z/y/x/m # with only a largefile
358 7
358 7
359
359
360 $ hg rollback --quiet
360 $ hg rollback --quiet
361 $ touch z/y/x/m/normal
361 $ touch z/y/x/m/normal
362 $ hg add z/y/x/m/normal
362 $ hg add z/y/x/m/normal
363 $ hg commit -m "Subdir with mixed contents" z
363 $ hg commit -m "Subdir with mixed contents" z
364 Invoking status precommit hook
364 Invoking status precommit hook
365 M large3
365 M large3
366 A large5
366 A large5
367 A sub2/large6
367 A sub2/large6
368 A sub2/large7
368 A sub2/large7
369 A z/y/x/large2
369 A z/y/x/large2
370 A z/y/x/m/large1
370 A z/y/x/m/large1
371 A z/y/x/m/normal
371 A z/y/x/m/normal
372 $ hg st
372 $ hg st
373 M large3
373 M large3
374 A large5
374 A large5
375 A sub2/large6
375 A sub2/large6
376 A sub2/large7
376 A sub2/large7
377 $ hg rollback --quiet
377 $ hg rollback --quiet
378 $ hg revert z/y/x/large2 z/y/x/m/large1
378 $ hg revert z/y/x/large2 z/y/x/m/large1
379 $ rm z/y/x/large2 z/y/x/m/large1
379 $ rm z/y/x/large2 z/y/x/m/large1
380 $ hg commit -m "Subdir with normal contents" z
380 $ hg commit -m "Subdir with normal contents" z
381 Invoking status precommit hook
381 Invoking status precommit hook
382 M large3
382 M large3
383 A large5
383 A large5
384 A sub2/large6
384 A sub2/large6
385 A sub2/large7
385 A sub2/large7
386 A z/y/x/m/normal
386 A z/y/x/m/normal
387 $ hg st
387 $ hg st
388 M large3
388 M large3
389 A large5
389 A large5
390 A sub2/large6
390 A sub2/large6
391 A sub2/large7
391 A sub2/large7
392 $ hg rollback --quiet
392 $ hg rollback --quiet
393 $ hg revert --quiet z
393 $ hg revert --quiet z
394 $ hg commit -m "Empty subdir" z
394 $ hg commit -m "Empty subdir" z
395 abort: z: no match under directory!
395 abort: z: no match under directory!
396 [255]
396 [255]
397 $ rm -rf z
397 $ rm -rf z
398 $ hg ci -m "standin" .hglf
398 $ hg ci -m "standin" .hglf
399 abort: file ".hglf" is a largefile standin
399 abort: file ".hglf" is a largefile standin
400 (commit the largefile itself instead)
400 (commit the largefile itself instead)
401 [255]
401 [255]
402
402
403 Test "hg status" with combination of 'file pattern' and 'directory
403 Test "hg status" with combination of 'file pattern' and 'directory
404 pattern' for largefiles:
404 pattern' for largefiles:
405
405
406 $ hg status sub2/large6 sub2
406 $ hg status sub2/large6 sub2
407 A sub2/large6
407 A sub2/large6
408 A sub2/large7
408 A sub2/large7
409
409
410 Config settings (pattern **.dat, minsize 2 MB) are respected.
410 Config settings (pattern **.dat, minsize 2 MB) are respected.
411
411
412 $ echo testdata > test.dat
412 $ echo testdata > test.dat
413 $ dd bs=1k count=2k if=/dev/zero of=reallylarge > /dev/null 2> /dev/null
413 $ dd bs=1k count=2k if=/dev/zero of=reallylarge > /dev/null 2> /dev/null
414 $ hg add
414 $ hg add
415 adding reallylarge as a largefile
415 adding reallylarge as a largefile
416 adding test.dat as a largefile
416 adding test.dat as a largefile
417
417
418 Test that minsize and --lfsize handle float values;
418 Test that minsize and --lfsize handle float values;
419 also tests that --lfsize overrides largefiles.minsize.
419 also tests that --lfsize overrides largefiles.minsize.
420 (0.250 MB = 256 kB = 262144 B)
420 (0.250 MB = 256 kB = 262144 B)
421
421
422 $ dd if=/dev/zero of=ratherlarge bs=1024 count=256 > /dev/null 2> /dev/null
422 $ dd if=/dev/zero of=ratherlarge bs=1024 count=256 > /dev/null 2> /dev/null
423 $ dd if=/dev/zero of=medium bs=1024 count=128 > /dev/null 2> /dev/null
423 $ dd if=/dev/zero of=medium bs=1024 count=128 > /dev/null 2> /dev/null
424 $ hg --config largefiles.minsize=.25 add
424 $ hg --config largefiles.minsize=.25 add
425 adding ratherlarge as a largefile
425 adding ratherlarge as a largefile
426 adding medium
426 adding medium
427 $ hg forget medium
427 $ hg forget medium
428 $ hg --config largefiles.minsize=.25 add --lfsize=.125
428 $ hg --config largefiles.minsize=.25 add --lfsize=.125
429 adding medium as a largefile
429 adding medium as a largefile
430 $ dd if=/dev/zero of=notlarge bs=1024 count=127 > /dev/null 2> /dev/null
430 $ dd if=/dev/zero of=notlarge bs=1024 count=127 > /dev/null 2> /dev/null
431 $ hg --config largefiles.minsize=.25 add --lfsize=.125
431 $ hg --config largefiles.minsize=.25 add --lfsize=.125
432 adding notlarge
432 adding notlarge
433 $ hg forget notlarge
433 $ hg forget notlarge
434
434
435 Test forget on largefiles.
435 Test forget on largefiles.
436
436
437 $ hg forget large3 large5 test.dat reallylarge ratherlarge medium
437 $ hg forget large3 large5 test.dat reallylarge ratherlarge medium
438 $ hg commit -m "add/edit more largefiles"
438 $ hg commit -m "add/edit more largefiles"
439 Invoking status precommit hook
439 Invoking status precommit hook
440 A sub2/large6
440 A sub2/large6
441 A sub2/large7
441 A sub2/large7
442 R large3
442 R large3
443 ? large5
443 ? large5
444 ? medium
444 ? medium
445 ? notlarge
445 ? notlarge
446 ? ratherlarge
446 ? ratherlarge
447 ? reallylarge
447 ? reallylarge
448 ? test.dat
448 ? test.dat
449 $ hg st
449 $ hg st
450 ? large3
450 ? large3
451 ? large5
451 ? large5
452 ? medium
452 ? medium
453 ? notlarge
453 ? notlarge
454 ? ratherlarge
454 ? ratherlarge
455 ? reallylarge
455 ? reallylarge
456 ? test.dat
456 ? test.dat
457
457
458 Purge with largefiles: verify that largefiles are still in the working
458 Purge with largefiles: verify that largefiles are still in the working
459 dir after a purge.
459 dir after a purge.
460
460
461 $ hg purge --all
461 $ hg purge --all
462 $ cat sub/large4
462 $ cat sub/large4
463 large44
463 large44
464 $ cat sub2/large6
464 $ cat sub2/large6
465 large6
465 large6
466 $ cat sub2/large7
466 $ cat sub2/large7
467 large7
467 large7
468
468
469 Test addremove: verify that files that should be added as largefiles are added as
469 Test addremove: verify that files that should be added as largefiles are added as
470 such and that already-existing largefiles are not added as normal files by
470 such and that already-existing largefiles are not added as normal files by
471 accident.
471 accident.
472
472
473 $ rm normal3
473 $ rm normal3
474 $ rm sub/large4
474 $ rm sub/large4
475 $ echo "testing addremove with patterns" > testaddremove.dat
475 $ echo "testing addremove with patterns" > testaddremove.dat
476 $ echo "normaladdremove" > normaladdremove
476 $ echo "normaladdremove" > normaladdremove
477 $ hg addremove
477 $ hg addremove
478 removing sub/large4
478 removing sub/large4
479 adding testaddremove.dat as a largefile
479 adding testaddremove.dat as a largefile
480 removing normal3
480 removing normal3
481 adding normaladdremove
481 adding normaladdremove
482
482
483 Test addremove with -R
483 Test addremove with -R
484
484
485 $ hg up -C
485 $ hg up -C
486 getting changed largefiles
486 getting changed largefiles
487 1 largefiles updated, 0 removed
487 1 largefiles updated, 0 removed
488 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
488 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
489 $ rm normal3
489 $ rm normal3
490 $ rm sub/large4
490 $ rm sub/large4
491 $ echo "testing addremove with patterns" > testaddremove.dat
491 $ echo "testing addremove with patterns" > testaddremove.dat
492 $ echo "normaladdremove" > normaladdremove
492 $ echo "normaladdremove" > normaladdremove
493 $ cd ..
493 $ cd ..
494 $ hg -R a addremove
494 $ hg -R a addremove
495 removing sub/large4
495 removing sub/large4
496 adding a/testaddremove.dat as a largefile (glob)
496 adding a/testaddremove.dat as a largefile (glob)
497 removing normal3
497 removing normal3
498 adding normaladdremove
498 adding normaladdremove
499 $ cd a
499 $ cd a
500
500
501 Test 3364
501 Test 3364
502 $ hg clone . ../addrm
502 $ hg clone . ../addrm
503 updating to branch default
503 updating to branch default
504 getting changed largefiles
504 getting changed largefiles
505 3 largefiles updated, 0 removed
505 3 largefiles updated, 0 removed
506 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
506 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
507 $ cd ../addrm
507 $ cd ../addrm
508 $ cat >> .hg/hgrc <<EOF
508 $ cat >> .hg/hgrc <<EOF
509 > [hooks]
509 > [hooks]
510 > post-commit.stat=sh -c "echo \\"Invoking status postcommit hook\\"; hg status -A"
510 > post-commit.stat=sh -c "echo \\"Invoking status postcommit hook\\"; hg status -A"
511 > EOF
511 > EOF
512 $ touch foo
512 $ touch foo
513 $ hg add --large foo
513 $ hg add --large foo
514 $ hg ci -m "add foo"
514 $ hg ci -m "add foo"
515 Invoking status precommit hook
515 Invoking status precommit hook
516 A foo
516 A foo
517 Invoking status postcommit hook
517 Invoking status postcommit hook
518 C foo
518 C foo
519 C normal3
519 C normal3
520 C sub/large4
520 C sub/large4
521 C sub/normal4
521 C sub/normal4
522 C sub2/large6
522 C sub2/large6
523 C sub2/large7
523 C sub2/large7
524 $ rm foo
524 $ rm foo
525 $ hg st
525 $ hg st
526 ! foo
526 ! foo
527 hmm.. no precommit invoked, but there is a postcommit??
527 hmm.. no precommit invoked, but there is a postcommit??
528 $ hg ci -m "will not checkin"
528 $ hg ci -m "will not checkin"
529 nothing changed
529 nothing changed
530 Invoking status postcommit hook
530 Invoking status postcommit hook
531 ! foo
531 ! foo
532 C normal3
532 C normal3
533 C sub/large4
533 C sub/large4
534 C sub/normal4
534 C sub/normal4
535 C sub2/large6
535 C sub2/large6
536 C sub2/large7
536 C sub2/large7
537 [1]
537 [1]
538 $ hg addremove
538 $ hg addremove
539 removing foo
539 removing foo
540 $ hg st
540 $ hg st
541 R foo
541 R foo
542 $ hg ci -m "used to say nothing changed"
542 $ hg ci -m "used to say nothing changed"
543 Invoking status precommit hook
543 Invoking status precommit hook
544 R foo
544 R foo
545 Invoking status postcommit hook
545 Invoking status postcommit hook
546 C normal3
546 C normal3
547 C sub/large4
547 C sub/large4
548 C sub/normal4
548 C sub/normal4
549 C sub2/large6
549 C sub2/large6
550 C sub2/large7
550 C sub2/large7
551 $ hg st
551 $ hg st
552
552
553 Test 3507 (both normal files and largefiles were a problem)
553 Test 3507 (both normal files and largefiles were a problem)
554
554
555 $ touch normal
555 $ touch normal
556 $ touch large
556 $ touch large
557 $ hg add normal
557 $ hg add normal
558 $ hg add --large large
558 $ hg add --large large
559 $ hg ci -m "added"
559 $ hg ci -m "added"
560 Invoking status precommit hook
560 Invoking status precommit hook
561 A large
561 A large
562 A normal
562 A normal
563 Invoking status postcommit hook
563 Invoking status postcommit hook
564 C large
564 C large
565 C normal
565 C normal
566 C normal3
566 C normal3
567 C sub/large4
567 C sub/large4
568 C sub/normal4
568 C sub/normal4
569 C sub2/large6
569 C sub2/large6
570 C sub2/large7
570 C sub2/large7
571 $ hg remove normal
571 $ hg remove normal
572 $ hg addremove --traceback
572 $ hg addremove --traceback
573 $ hg ci -m "addremoved normal"
573 $ hg ci -m "addremoved normal"
574 Invoking status precommit hook
574 Invoking status precommit hook
575 R normal
575 R normal
576 Invoking status postcommit hook
576 Invoking status postcommit hook
577 C large
577 C large
578 C normal3
578 C normal3
579 C sub/large4
579 C sub/large4
580 C sub/normal4
580 C sub/normal4
581 C sub2/large6
581 C sub2/large6
582 C sub2/large7
582 C sub2/large7
583 $ hg up -C '.^'
583 $ hg up -C '.^'
584 getting changed largefiles
584 getting changed largefiles
585 0 largefiles updated, 0 removed
585 0 largefiles updated, 0 removed
586 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
586 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
587 $ hg remove large
587 $ hg remove large
588 $ hg addremove --traceback
588 $ hg addremove --traceback
589 $ hg ci -m "removed large"
589 $ hg ci -m "removed large"
590 Invoking status precommit hook
590 Invoking status precommit hook
591 R large
591 R large
592 created new head
592 created new head
593 Invoking status postcommit hook
593 Invoking status postcommit hook
594 C normal
594 C normal
595 C normal3
595 C normal3
596 C sub/large4
596 C sub/large4
597 C sub/normal4
597 C sub/normal4
598 C sub2/large6
598 C sub2/large6
599 C sub2/large7
599 C sub2/large7
600
600
601 Test commit -A (issue3542)
601 Test commit -A (issue3542)
602 $ echo large8 > large8
602 $ echo large8 > large8
603 $ hg add --large large8
603 $ hg add --large large8
604 $ hg ci -Am 'this used to add large8 as normal and commit both'
604 $ hg ci -Am 'this used to add large8 as normal and commit both'
605 Invoking status precommit hook
605 Invoking status precommit hook
606 A large8
606 A large8
607 Invoking status postcommit hook
607 Invoking status postcommit hook
608 C large8
608 C large8
609 C normal
609 C normal
610 C normal3
610 C normal3
611 C sub/large4
611 C sub/large4
612 C sub/normal4
612 C sub/normal4
613 C sub2/large6
613 C sub2/large6
614 C sub2/large7
614 C sub2/large7
615 $ rm large8
615 $ rm large8
616 $ hg ci -Am 'this used to not notice the rm'
616 $ hg ci -Am 'this used to not notice the rm'
617 removing large8
617 removing large8
618 Invoking status precommit hook
618 Invoking status precommit hook
619 R large8
619 R large8
620 Invoking status postcommit hook
620 Invoking status postcommit hook
621 C normal
621 C normal
622 C normal3
622 C normal3
623 C sub/large4
623 C sub/large4
624 C sub/normal4
624 C sub/normal4
625 C sub2/large6
625 C sub2/large6
626 C sub2/large7
626 C sub2/large7
627
627
628 Test that a standin can't be added as a large file
628 Test that a standin can't be added as a large file
629
629
630 $ touch large
630 $ touch large
631 $ hg add --large large
631 $ hg add --large large
632 $ hg ci -m "add"
632 $ hg ci -m "add"
633 Invoking status precommit hook
633 Invoking status precommit hook
634 A large
634 A large
635 Invoking status postcommit hook
635 Invoking status postcommit hook
636 C large
636 C large
637 C normal
637 C normal
638 C normal3
638 C normal3
639 C sub/large4
639 C sub/large4
640 C sub/normal4
640 C sub/normal4
641 C sub2/large6
641 C sub2/large6
642 C sub2/large7
642 C sub2/large7
643 $ hg remove large
643 $ hg remove large
644 $ touch large
644 $ touch large
645 $ hg addremove --config largefiles.patterns=**large --traceback
645 $ hg addremove --config largefiles.patterns=**large --traceback
646 adding large as a largefile
646 adding large as a largefile
647
647
648 Test that outgoing --large works (with revsets too)
648 Test that outgoing --large works (with revsets too)
649 $ hg outgoing --rev '.^' --large
649 $ hg outgoing --rev '.^' --large
650 comparing with $TESTTMP/a (glob)
650 comparing with $TESTTMP/a (glob)
651 searching for changes
651 searching for changes
652 changeset: 8:c02fd3b77ec4
652 changeset: 8:c02fd3b77ec4
653 user: test
653 user: test
654 date: Thu Jan 01 00:00:00 1970 +0000
654 date: Thu Jan 01 00:00:00 1970 +0000
655 summary: add foo
655 summary: add foo
656
656
657 changeset: 9:289dd08c9bbb
657 changeset: 9:289dd08c9bbb
658 user: test
658 user: test
659 date: Thu Jan 01 00:00:00 1970 +0000
659 date: Thu Jan 01 00:00:00 1970 +0000
660 summary: used to say nothing changed
660 summary: used to say nothing changed
661
661
662 changeset: 10:34f23ac6ac12
662 changeset: 10:34f23ac6ac12
663 user: test
663 user: test
664 date: Thu Jan 01 00:00:00 1970 +0000
664 date: Thu Jan 01 00:00:00 1970 +0000
665 summary: added
665 summary: added
666
666
667 changeset: 12:710c1b2f523c
667 changeset: 12:710c1b2f523c
668 parent: 10:34f23ac6ac12
668 parent: 10:34f23ac6ac12
669 user: test
669 user: test
670 date: Thu Jan 01 00:00:00 1970 +0000
670 date: Thu Jan 01 00:00:00 1970 +0000
671 summary: removed large
671 summary: removed large
672
672
673 changeset: 13:0a3e75774479
673 changeset: 13:0a3e75774479
674 user: test
674 user: test
675 date: Thu Jan 01 00:00:00 1970 +0000
675 date: Thu Jan 01 00:00:00 1970 +0000
676 summary: this used to add large8 as normal and commit both
676 summary: this used to add large8 as normal and commit both
677
677
678 changeset: 14:84f3d378175c
678 changeset: 14:84f3d378175c
679 user: test
679 user: test
680 date: Thu Jan 01 00:00:00 1970 +0000
680 date: Thu Jan 01 00:00:00 1970 +0000
681 summary: this used to not notice the rm
681 summary: this used to not notice the rm
682
682
683 largefiles to upload (1 entities):
683 largefiles to upload (1 entities):
684 large8
684 large8
685
685
686 $ cd ../a
686 $ cd ../a
687
687
688 Clone a largefiles repo.
688 Clone a largefiles repo.
689
689
690 $ hg clone . ../b
690 $ hg clone . ../b
691 updating to branch default
691 updating to branch default
692 getting changed largefiles
692 getting changed largefiles
693 3 largefiles updated, 0 removed
693 3 largefiles updated, 0 removed
694 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
694 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
695 $ cd ../b
695 $ cd ../b
696 $ hg log --template '{rev}:{node|short} {desc|firstline}\n'
696 $ hg log --template '{rev}:{node|short} {desc|firstline}\n'
697 7:daea875e9014 add/edit more largefiles
697 7:daea875e9014 add/edit more largefiles
698 6:4355d653f84f edit files yet again
698 6:4355d653f84f edit files yet again
699 5:9d5af5072dbd edit files again
699 5:9d5af5072dbd edit files again
700 4:74c02385b94c move files
700 4:74c02385b94c move files
701 3:9e8fbc4bce62 copy files
701 3:9e8fbc4bce62 copy files
702 2:51a0ae4d5864 remove files
702 2:51a0ae4d5864 remove files
703 1:ce8896473775 edit files
703 1:ce8896473775 edit files
704 0:30d30fe6a5be add files
704 0:30d30fe6a5be add files
705 $ cat normal3
705 $ cat normal3
706 normal33
706 normal33
707
707
708 Test graph log
708 Test graph log
709
709
710 $ hg log -G --template '{rev}:{node|short} {desc|firstline}\n'
710 $ hg log -G --template '{rev}:{node|short} {desc|firstline}\n'
711 @ 7:daea875e9014 add/edit more largefiles
711 @ 7:daea875e9014 add/edit more largefiles
712 |
712 |
713 o 6:4355d653f84f edit files yet again
713 o 6:4355d653f84f edit files yet again
714 |
714 |
715 o 5:9d5af5072dbd edit files again
715 o 5:9d5af5072dbd edit files again
716 |
716 |
717 o 4:74c02385b94c move files
717 o 4:74c02385b94c move files
718 |
718 |
719 o 3:9e8fbc4bce62 copy files
719 o 3:9e8fbc4bce62 copy files
720 |
720 |
721 o 2:51a0ae4d5864 remove files
721 o 2:51a0ae4d5864 remove files
722 |
722 |
723 o 1:ce8896473775 edit files
723 o 1:ce8896473775 edit files
724 |
724 |
725 o 0:30d30fe6a5be add files
725 o 0:30d30fe6a5be add files
726
726
727
727
728 Test log with --patch
728 Test log with --patch
729
729
730 $ hg log --patch -r 6::7
730 $ hg log --patch -r 6::7
731 changeset: 6:4355d653f84f
731 changeset: 6:4355d653f84f
732 user: test
732 user: test
733 date: Thu Jan 01 00:00:00 1970 +0000
733 date: Thu Jan 01 00:00:00 1970 +0000
734 summary: edit files yet again
734 summary: edit files yet again
735
735
736 diff -r 9d5af5072dbd -r 4355d653f84f .hglf/large3
736 diff -r 9d5af5072dbd -r 4355d653f84f .hglf/large3
737 --- a/.hglf/large3 Thu Jan 01 00:00:00 1970 +0000
737 --- a/.hglf/large3 Thu Jan 01 00:00:00 1970 +0000
738 +++ b/.hglf/large3 Thu Jan 01 00:00:00 1970 +0000
738 +++ b/.hglf/large3 Thu Jan 01 00:00:00 1970 +0000
739 @@ -1,1 +1,1 @@
739 @@ -1,1 +1,1 @@
740 -baaf12afde9d8d67f25dab6dced0d2bf77dba47c
740 -baaf12afde9d8d67f25dab6dced0d2bf77dba47c
741 +7838695e10da2bb75ac1156565f40a2595fa2fa0
741 +7838695e10da2bb75ac1156565f40a2595fa2fa0
742 diff -r 9d5af5072dbd -r 4355d653f84f .hglf/sub/large4
742 diff -r 9d5af5072dbd -r 4355d653f84f .hglf/sub/large4
743 --- a/.hglf/sub/large4 Thu Jan 01 00:00:00 1970 +0000
743 --- a/.hglf/sub/large4 Thu Jan 01 00:00:00 1970 +0000
744 +++ b/.hglf/sub/large4 Thu Jan 01 00:00:00 1970 +0000
744 +++ b/.hglf/sub/large4 Thu Jan 01 00:00:00 1970 +0000
745 @@ -1,1 +1,1 @@
745 @@ -1,1 +1,1 @@
746 -aeb2210d19f02886dde00dac279729a48471e2f9
746 -aeb2210d19f02886dde00dac279729a48471e2f9
747 +971fb41e78fea4f8e0ba5244784239371cb00591
747 +971fb41e78fea4f8e0ba5244784239371cb00591
748 diff -r 9d5af5072dbd -r 4355d653f84f normal3
748 diff -r 9d5af5072dbd -r 4355d653f84f normal3
749 --- a/normal3 Thu Jan 01 00:00:00 1970 +0000
749 --- a/normal3 Thu Jan 01 00:00:00 1970 +0000
750 +++ b/normal3 Thu Jan 01 00:00:00 1970 +0000
750 +++ b/normal3 Thu Jan 01 00:00:00 1970 +0000
751 @@ -1,1 +1,1 @@
751 @@ -1,1 +1,1 @@
752 -normal3
752 -normal3
753 +normal33
753 +normal33
754 diff -r 9d5af5072dbd -r 4355d653f84f sub/normal4
754 diff -r 9d5af5072dbd -r 4355d653f84f sub/normal4
755 --- a/sub/normal4 Thu Jan 01 00:00:00 1970 +0000
755 --- a/sub/normal4 Thu Jan 01 00:00:00 1970 +0000
756 +++ b/sub/normal4 Thu Jan 01 00:00:00 1970 +0000
756 +++ b/sub/normal4 Thu Jan 01 00:00:00 1970 +0000
757 @@ -1,1 +1,1 @@
757 @@ -1,1 +1,1 @@
758 -normal4
758 -normal4
759 +normal44
759 +normal44
760
760
761 changeset: 7:daea875e9014
761 changeset: 7:daea875e9014
762 tag: tip
762 tag: tip
763 user: test
763 user: test
764 date: Thu Jan 01 00:00:00 1970 +0000
764 date: Thu Jan 01 00:00:00 1970 +0000
765 summary: add/edit more largefiles
765 summary: add/edit more largefiles
766
766
767 diff -r 4355d653f84f -r daea875e9014 .hglf/large3
767 diff -r 4355d653f84f -r daea875e9014 .hglf/large3
768 --- a/.hglf/large3 Thu Jan 01 00:00:00 1970 +0000
768 --- a/.hglf/large3 Thu Jan 01 00:00:00 1970 +0000
769 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
769 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
770 @@ -1,1 +0,0 @@
770 @@ -1,1 +0,0 @@
771 -7838695e10da2bb75ac1156565f40a2595fa2fa0
771 -7838695e10da2bb75ac1156565f40a2595fa2fa0
772 diff -r 4355d653f84f -r daea875e9014 .hglf/sub2/large6
772 diff -r 4355d653f84f -r daea875e9014 .hglf/sub2/large6
773 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
773 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
774 +++ b/.hglf/sub2/large6 Thu Jan 01 00:00:00 1970 +0000
774 +++ b/.hglf/sub2/large6 Thu Jan 01 00:00:00 1970 +0000
775 @@ -0,0 +1,1 @@
775 @@ -0,0 +1,1 @@
776 +0d6d75887db61b2c7e6c74b5dd8fc6ad50c0cc30
776 +0d6d75887db61b2c7e6c74b5dd8fc6ad50c0cc30
777 diff -r 4355d653f84f -r daea875e9014 .hglf/sub2/large7
777 diff -r 4355d653f84f -r daea875e9014 .hglf/sub2/large7
778 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
778 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
779 +++ b/.hglf/sub2/large7 Thu Jan 01 00:00:00 1970 +0000
779 +++ b/.hglf/sub2/large7 Thu Jan 01 00:00:00 1970 +0000
780 @@ -0,0 +1,1 @@
780 @@ -0,0 +1,1 @@
781 +bb3151689acb10f0c3125c560d5e63df914bc1af
781 +bb3151689acb10f0c3125c560d5e63df914bc1af
782
782
783
783
784 $ hg log --patch -r 6::7 sub/
784 $ hg log --patch -r 6::7 sub/
785 changeset: 6:4355d653f84f
785 changeset: 6:4355d653f84f
786 user: test
786 user: test
787 date: Thu Jan 01 00:00:00 1970 +0000
787 date: Thu Jan 01 00:00:00 1970 +0000
788 summary: edit files yet again
788 summary: edit files yet again
789
789
790 diff -r 9d5af5072dbd -r 4355d653f84f .hglf/sub/large4
790 diff -r 9d5af5072dbd -r 4355d653f84f .hglf/sub/large4
791 --- a/.hglf/sub/large4 Thu Jan 01 00:00:00 1970 +0000
791 --- a/.hglf/sub/large4 Thu Jan 01 00:00:00 1970 +0000
792 +++ b/.hglf/sub/large4 Thu Jan 01 00:00:00 1970 +0000
792 +++ b/.hglf/sub/large4 Thu Jan 01 00:00:00 1970 +0000
793 @@ -1,1 +1,1 @@
793 @@ -1,1 +1,1 @@
794 -aeb2210d19f02886dde00dac279729a48471e2f9
794 -aeb2210d19f02886dde00dac279729a48471e2f9
795 +971fb41e78fea4f8e0ba5244784239371cb00591
795 +971fb41e78fea4f8e0ba5244784239371cb00591
796 diff -r 9d5af5072dbd -r 4355d653f84f sub/normal4
796 diff -r 9d5af5072dbd -r 4355d653f84f sub/normal4
797 --- a/sub/normal4 Thu Jan 01 00:00:00 1970 +0000
797 --- a/sub/normal4 Thu Jan 01 00:00:00 1970 +0000
798 +++ b/sub/normal4 Thu Jan 01 00:00:00 1970 +0000
798 +++ b/sub/normal4 Thu Jan 01 00:00:00 1970 +0000
799 @@ -1,1 +1,1 @@
799 @@ -1,1 +1,1 @@
800 -normal4
800 -normal4
801 +normal44
801 +normal44
802
802
803
803
804 log with both --follow and --patch
804 log with both --follow and --patch
805
805
806 $ hg log --follow --patch --limit 2
806 $ hg log --follow --patch --limit 2
807 changeset: 7:daea875e9014
807 changeset: 7:daea875e9014
808 tag: tip
808 tag: tip
809 user: test
809 user: test
810 date: Thu Jan 01 00:00:00 1970 +0000
810 date: Thu Jan 01 00:00:00 1970 +0000
811 summary: add/edit more largefiles
811 summary: add/edit more largefiles
812
812
813 diff -r 4355d653f84f -r daea875e9014 .hglf/large3
813 diff -r 4355d653f84f -r daea875e9014 .hglf/large3
814 --- a/.hglf/large3 Thu Jan 01 00:00:00 1970 +0000
814 --- a/.hglf/large3 Thu Jan 01 00:00:00 1970 +0000
815 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
815 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
816 @@ -1,1 +0,0 @@
816 @@ -1,1 +0,0 @@
817 -7838695e10da2bb75ac1156565f40a2595fa2fa0
817 -7838695e10da2bb75ac1156565f40a2595fa2fa0
818 diff -r 4355d653f84f -r daea875e9014 .hglf/sub2/large6
818 diff -r 4355d653f84f -r daea875e9014 .hglf/sub2/large6
819 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
819 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
820 +++ b/.hglf/sub2/large6 Thu Jan 01 00:00:00 1970 +0000
820 +++ b/.hglf/sub2/large6 Thu Jan 01 00:00:00 1970 +0000
821 @@ -0,0 +1,1 @@
821 @@ -0,0 +1,1 @@
822 +0d6d75887db61b2c7e6c74b5dd8fc6ad50c0cc30
822 +0d6d75887db61b2c7e6c74b5dd8fc6ad50c0cc30
823 diff -r 4355d653f84f -r daea875e9014 .hglf/sub2/large7
823 diff -r 4355d653f84f -r daea875e9014 .hglf/sub2/large7
824 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
824 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
825 +++ b/.hglf/sub2/large7 Thu Jan 01 00:00:00 1970 +0000
825 +++ b/.hglf/sub2/large7 Thu Jan 01 00:00:00 1970 +0000
826 @@ -0,0 +1,1 @@
826 @@ -0,0 +1,1 @@
827 +bb3151689acb10f0c3125c560d5e63df914bc1af
827 +bb3151689acb10f0c3125c560d5e63df914bc1af
828
828
829 changeset: 6:4355d653f84f
829 changeset: 6:4355d653f84f
830 user: test
830 user: test
831 date: Thu Jan 01 00:00:00 1970 +0000
831 date: Thu Jan 01 00:00:00 1970 +0000
832 summary: edit files yet again
832 summary: edit files yet again
833
833
834 diff -r 9d5af5072dbd -r 4355d653f84f .hglf/large3
834 diff -r 9d5af5072dbd -r 4355d653f84f .hglf/large3
835 --- a/.hglf/large3 Thu Jan 01 00:00:00 1970 +0000
835 --- a/.hglf/large3 Thu Jan 01 00:00:00 1970 +0000
836 +++ b/.hglf/large3 Thu Jan 01 00:00:00 1970 +0000
836 +++ b/.hglf/large3 Thu Jan 01 00:00:00 1970 +0000
837 @@ -1,1 +1,1 @@
837 @@ -1,1 +1,1 @@
838 -baaf12afde9d8d67f25dab6dced0d2bf77dba47c
838 -baaf12afde9d8d67f25dab6dced0d2bf77dba47c
839 +7838695e10da2bb75ac1156565f40a2595fa2fa0
839 +7838695e10da2bb75ac1156565f40a2595fa2fa0
840 diff -r 9d5af5072dbd -r 4355d653f84f .hglf/sub/large4
840 diff -r 9d5af5072dbd -r 4355d653f84f .hglf/sub/large4
841 --- a/.hglf/sub/large4 Thu Jan 01 00:00:00 1970 +0000
841 --- a/.hglf/sub/large4 Thu Jan 01 00:00:00 1970 +0000
842 +++ b/.hglf/sub/large4 Thu Jan 01 00:00:00 1970 +0000
842 +++ b/.hglf/sub/large4 Thu Jan 01 00:00:00 1970 +0000
843 @@ -1,1 +1,1 @@
843 @@ -1,1 +1,1 @@
844 -aeb2210d19f02886dde00dac279729a48471e2f9
844 -aeb2210d19f02886dde00dac279729a48471e2f9
845 +971fb41e78fea4f8e0ba5244784239371cb00591
845 +971fb41e78fea4f8e0ba5244784239371cb00591
846 diff -r 9d5af5072dbd -r 4355d653f84f normal3
846 diff -r 9d5af5072dbd -r 4355d653f84f normal3
847 --- a/normal3 Thu Jan 01 00:00:00 1970 +0000
847 --- a/normal3 Thu Jan 01 00:00:00 1970 +0000
848 +++ b/normal3 Thu Jan 01 00:00:00 1970 +0000
848 +++ b/normal3 Thu Jan 01 00:00:00 1970 +0000
849 @@ -1,1 +1,1 @@
849 @@ -1,1 +1,1 @@
850 -normal3
850 -normal3
851 +normal33
851 +normal33
852 diff -r 9d5af5072dbd -r 4355d653f84f sub/normal4
852 diff -r 9d5af5072dbd -r 4355d653f84f sub/normal4
853 --- a/sub/normal4 Thu Jan 01 00:00:00 1970 +0000
853 --- a/sub/normal4 Thu Jan 01 00:00:00 1970 +0000
854 +++ b/sub/normal4 Thu Jan 01 00:00:00 1970 +0000
854 +++ b/sub/normal4 Thu Jan 01 00:00:00 1970 +0000
855 @@ -1,1 +1,1 @@
855 @@ -1,1 +1,1 @@
856 -normal4
856 -normal4
857 +normal44
857 +normal44
858
858
859 $ hg log --follow --patch sub/large4
859 $ hg log --follow --patch sub/large4
860 changeset: 6:4355d653f84f
860 changeset: 6:4355d653f84f
861 user: test
861 user: test
862 date: Thu Jan 01 00:00:00 1970 +0000
862 date: Thu Jan 01 00:00:00 1970 +0000
863 summary: edit files yet again
863 summary: edit files yet again
864
864
865 diff -r 9d5af5072dbd -r 4355d653f84f .hglf/sub/large4
865 diff -r 9d5af5072dbd -r 4355d653f84f .hglf/sub/large4
866 --- a/.hglf/sub/large4 Thu Jan 01 00:00:00 1970 +0000
866 --- a/.hglf/sub/large4 Thu Jan 01 00:00:00 1970 +0000
867 +++ b/.hglf/sub/large4 Thu Jan 01 00:00:00 1970 +0000
867 +++ b/.hglf/sub/large4 Thu Jan 01 00:00:00 1970 +0000
868 @@ -1,1 +1,1 @@
868 @@ -1,1 +1,1 @@
869 -aeb2210d19f02886dde00dac279729a48471e2f9
869 -aeb2210d19f02886dde00dac279729a48471e2f9
870 +971fb41e78fea4f8e0ba5244784239371cb00591
870 +971fb41e78fea4f8e0ba5244784239371cb00591
871
871
872 changeset: 5:9d5af5072dbd
872 changeset: 5:9d5af5072dbd
873 user: test
873 user: test
874 date: Thu Jan 01 00:00:00 1970 +0000
874 date: Thu Jan 01 00:00:00 1970 +0000
875 summary: edit files again
875 summary: edit files again
876
876
877 diff -r 74c02385b94c -r 9d5af5072dbd .hglf/sub/large4
877 diff -r 74c02385b94c -r 9d5af5072dbd .hglf/sub/large4
878 --- a/.hglf/sub/large4 Thu Jan 01 00:00:00 1970 +0000
878 --- a/.hglf/sub/large4 Thu Jan 01 00:00:00 1970 +0000
879 +++ b/.hglf/sub/large4 Thu Jan 01 00:00:00 1970 +0000
879 +++ b/.hglf/sub/large4 Thu Jan 01 00:00:00 1970 +0000
880 @@ -1,1 +1,1 @@
880 @@ -1,1 +1,1 @@
881 -eb7338044dc27f9bc59b8dd5a246b065ead7a9c4
881 -eb7338044dc27f9bc59b8dd5a246b065ead7a9c4
882 +aeb2210d19f02886dde00dac279729a48471e2f9
882 +aeb2210d19f02886dde00dac279729a48471e2f9
883
883
884 changeset: 4:74c02385b94c
884 changeset: 4:74c02385b94c
885 user: test
885 user: test
886 date: Thu Jan 01 00:00:00 1970 +0000
886 date: Thu Jan 01 00:00:00 1970 +0000
887 summary: move files
887 summary: move files
888
888
889 diff -r 9e8fbc4bce62 -r 74c02385b94c .hglf/sub/large4
889 diff -r 9e8fbc4bce62 -r 74c02385b94c .hglf/sub/large4
890 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
890 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
891 +++ b/.hglf/sub/large4 Thu Jan 01 00:00:00 1970 +0000
891 +++ b/.hglf/sub/large4 Thu Jan 01 00:00:00 1970 +0000
892 @@ -0,0 +1,1 @@
892 @@ -0,0 +1,1 @@
893 +eb7338044dc27f9bc59b8dd5a246b065ead7a9c4
893 +eb7338044dc27f9bc59b8dd5a246b065ead7a9c4
894
894
895 changeset: 1:ce8896473775
895 changeset: 1:ce8896473775
896 user: test
896 user: test
897 date: Thu Jan 01 00:00:00 1970 +0000
897 date: Thu Jan 01 00:00:00 1970 +0000
898 summary: edit files
898 summary: edit files
899
899
900 diff -r 30d30fe6a5be -r ce8896473775 .hglf/sub/large2
900 diff -r 30d30fe6a5be -r ce8896473775 .hglf/sub/large2
901 --- a/.hglf/sub/large2 Thu Jan 01 00:00:00 1970 +0000
901 --- a/.hglf/sub/large2 Thu Jan 01 00:00:00 1970 +0000
902 +++ b/.hglf/sub/large2 Thu Jan 01 00:00:00 1970 +0000
902 +++ b/.hglf/sub/large2 Thu Jan 01 00:00:00 1970 +0000
903 @@ -1,1 +1,1 @@
903 @@ -1,1 +1,1 @@
904 -1deebade43c8c498a3c8daddac0244dc55d1331d
904 -1deebade43c8c498a3c8daddac0244dc55d1331d
905 +eb7338044dc27f9bc59b8dd5a246b065ead7a9c4
905 +eb7338044dc27f9bc59b8dd5a246b065ead7a9c4
906
906
907 changeset: 0:30d30fe6a5be
907 changeset: 0:30d30fe6a5be
908 user: test
908 user: test
909 date: Thu Jan 01 00:00:00 1970 +0000
909 date: Thu Jan 01 00:00:00 1970 +0000
910 summary: add files
910 summary: add files
911
911
912 diff -r 000000000000 -r 30d30fe6a5be .hglf/sub/large2
912 diff -r 000000000000 -r 30d30fe6a5be .hglf/sub/large2
913 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
913 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
914 +++ b/.hglf/sub/large2 Thu Jan 01 00:00:00 1970 +0000
914 +++ b/.hglf/sub/large2 Thu Jan 01 00:00:00 1970 +0000
915 @@ -0,0 +1,1 @@
915 @@ -0,0 +1,1 @@
916 +1deebade43c8c498a3c8daddac0244dc55d1331d
916 +1deebade43c8c498a3c8daddac0244dc55d1331d
917
917
918 $ cat sub/normal4
918 $ cat sub/normal4
919 normal44
919 normal44
920 $ cat sub/large4
920 $ cat sub/large4
921 large44
921 large44
922 $ cat sub2/large6
922 $ cat sub2/large6
923 large6
923 large6
924 $ cat sub2/large7
924 $ cat sub2/large7
925 large7
925 large7
926 $ hg log -qf sub2/large7
926 $ hg log -qf sub2/large7
927 7:daea875e9014
927 7:daea875e9014
928 $ hg log -Gqf sub2/large7
928 $ hg log -Gqf sub2/large7
929 @ 7:daea875e9014
929 @ 7:daea875e9014
930 |
930 |
931 $ cd ..
931 $ cd ..
932
932
933 Test log from outside repo
933 Test log from outside repo
934
934
935 $ hg log b/sub -T '{rev}:{node|short} {desc|firstline}\n'
935 $ hg log b/sub -T '{rev}:{node|short} {desc|firstline}\n'
936 6:4355d653f84f edit files yet again
936 6:4355d653f84f edit files yet again
937 5:9d5af5072dbd edit files again
937 5:9d5af5072dbd edit files again
938 4:74c02385b94c move files
938 4:74c02385b94c move files
939 1:ce8896473775 edit files
939 1:ce8896473775 edit files
940 0:30d30fe6a5be add files
940 0:30d30fe6a5be add files
941
941
942 Test clone at revision
942 Test clone at revision
943
943
944 $ hg clone a -r 3 c
944 $ hg clone a -r 3 c
945 adding changesets
945 adding changesets
946 adding manifests
946 adding manifests
947 adding file changes
947 adding file changes
948 added 4 changesets with 10 changes to 4 files
948 added 4 changesets with 10 changes to 4 files
949 updating to branch default
949 updating to branch default
950 getting changed largefiles
950 getting changed largefiles
951 2 largefiles updated, 0 removed
951 2 largefiles updated, 0 removed
952 4 files updated, 0 files merged, 0 files removed, 0 files unresolved
952 4 files updated, 0 files merged, 0 files removed, 0 files unresolved
953 $ cd c
953 $ cd c
954 $ hg log --template '{rev}:{node|short} {desc|firstline}\n'
954 $ hg log --template '{rev}:{node|short} {desc|firstline}\n'
955 3:9e8fbc4bce62 copy files
955 3:9e8fbc4bce62 copy files
956 2:51a0ae4d5864 remove files
956 2:51a0ae4d5864 remove files
957 1:ce8896473775 edit files
957 1:ce8896473775 edit files
958 0:30d30fe6a5be add files
958 0:30d30fe6a5be add files
959 $ cat normal1
959 $ cat normal1
960 normal22
960 normal22
961 $ cat large1
961 $ cat large1
962 large22
962 large22
963 $ cat sub/normal2
963 $ cat sub/normal2
964 normal22
964 normal22
965 $ cat sub/large2
965 $ cat sub/large2
966 large22
966 large22
967
967
968 Old revisions of a clone have correct largefiles content (this also
968 Old revisions of a clone have correct largefiles content (this also
969 tests update).
969 tests update).
970
970
971 $ hg update -r 1
971 $ hg update -r 1
972 getting changed largefiles
972 getting changed largefiles
973 1 largefiles updated, 0 removed
973 1 largefiles updated, 0 removed
974 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
974 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
975 $ cat large1
975 $ cat large1
976 large11
976 large11
977 $ cat sub/large2
977 $ cat sub/large2
978 large22
978 large22
979 $ cd ..
979 $ cd ..
980
980
981 Test cloning with --all-largefiles flag
981 Test cloning with --all-largefiles flag
982
982
983 $ rm "${USERCACHE}"/*
983 $ rm "${USERCACHE}"/*
984 $ hg clone --all-largefiles a a-backup
984 $ hg clone --all-largefiles a a-backup
985 updating to branch default
985 updating to branch default
986 getting changed largefiles
986 getting changed largefiles
987 3 largefiles updated, 0 removed
987 3 largefiles updated, 0 removed
988 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
988 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
989 8 additional largefiles cached
989 8 additional largefiles cached
990
990
991 $ rm "${USERCACHE}"/*
991 $ rm "${USERCACHE}"/*
992 $ hg clone --all-largefiles -u 0 a a-clone0
992 $ hg clone --all-largefiles -u 0 a a-clone0
993 updating to branch default
993 updating to branch default
994 getting changed largefiles
994 getting changed largefiles
995 2 largefiles updated, 0 removed
995 2 largefiles updated, 0 removed
996 4 files updated, 0 files merged, 0 files removed, 0 files unresolved
996 4 files updated, 0 files merged, 0 files removed, 0 files unresolved
997 9 additional largefiles cached
997 9 additional largefiles cached
998 $ hg -R a-clone0 sum
998 $ hg -R a-clone0 sum
999 parent: 0:30d30fe6a5be
999 parent: 0:30d30fe6a5be
1000 add files
1000 add files
1001 branch: default
1001 branch: default
1002 commit: (clean)
1002 commit: (clean)
1003 update: 7 new changesets (update)
1003 update: 7 new changesets (update)
1004
1004
1005 $ rm "${USERCACHE}"/*
1005 $ rm "${USERCACHE}"/*
1006 $ hg clone --all-largefiles -u 1 a a-clone1
1006 $ hg clone --all-largefiles -u 1 a a-clone1
1007 updating to branch default
1007 updating to branch default
1008 getting changed largefiles
1008 getting changed largefiles
1009 2 largefiles updated, 0 removed
1009 2 largefiles updated, 0 removed
1010 4 files updated, 0 files merged, 0 files removed, 0 files unresolved
1010 4 files updated, 0 files merged, 0 files removed, 0 files unresolved
1011 8 additional largefiles cached
1011 8 additional largefiles cached
1012 $ hg -R a-clone1 verify --large --lfa --lfc
1012 $ hg -R a-clone1 verify --large --lfa --lfc
1013 checking changesets
1013 checking changesets
1014 checking manifests
1014 checking manifests
1015 crosschecking files in changesets and manifests
1015 crosschecking files in changesets and manifests
1016 checking files
1016 checking files
1017 10 files, 8 changesets, 24 total revisions
1017 10 files, 8 changesets, 24 total revisions
1018 searching 8 changesets for largefiles
1018 searching 8 changesets for largefiles
1019 verified contents of 13 revisions of 6 largefiles
1019 verified contents of 13 revisions of 6 largefiles
1020 $ hg -R a-clone1 sum
1020 $ hg -R a-clone1 sum
1021 parent: 1:ce8896473775
1021 parent: 1:ce8896473775
1022 edit files
1022 edit files
1023 branch: default
1023 branch: default
1024 commit: (clean)
1024 commit: (clean)
1025 update: 6 new changesets (update)
1025 update: 6 new changesets (update)
1026
1026
1027 $ rm "${USERCACHE}"/*
1027 $ rm "${USERCACHE}"/*
1028 $ hg clone --all-largefiles -U a a-clone-u
1028 $ hg clone --all-largefiles -U a a-clone-u
1029 11 additional largefiles cached
1029 11 additional largefiles cached
1030 $ hg -R a-clone-u sum
1030 $ hg -R a-clone-u sum
1031 parent: -1:000000000000 (no revision checked out)
1031 parent: -1:000000000000 (no revision checked out)
1032 branch: default
1032 branch: default
1033 commit: (clean)
1033 commit: (clean)
1034 update: 8 new changesets (update)
1034 update: 8 new changesets (update)
1035
1035
1036 Show computed destination directory:
1036 Show computed destination directory:
1037
1037
1038 $ mkdir xyz
1038 $ mkdir xyz
1039 $ cd xyz
1039 $ cd xyz
1040 $ hg clone ../a
1040 $ hg clone ../a
1041 destination directory: a
1041 destination directory: a
1042 updating to branch default
1042 updating to branch default
1043 getting changed largefiles
1043 getting changed largefiles
1044 3 largefiles updated, 0 removed
1044 3 largefiles updated, 0 removed
1045 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
1045 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
1046 $ cd ..
1046 $ cd ..
1047
1047
1048 Clone URL without path:
1048 Clone URL without path:
1049
1049
1050 $ hg clone file://
1050 $ hg clone file://
1051 abort: repository / not found!
1051 abort: repository / not found!
1052 [255]
1052 [255]
1053
1053
1054 Ensure base clone command argument validation
1054 Ensure base clone command argument validation
1055
1055
1056 $ hg clone -U -u 0 a a-clone-failure
1056 $ hg clone -U -u 0 a a-clone-failure
1057 abort: cannot specify both --noupdate and --updaterev
1057 abort: cannot specify both --noupdate and --updaterev
1058 [255]
1058 [255]
1059
1059
1060 $ hg clone --all-largefiles a ssh://localhost/a
1060 $ hg clone --all-largefiles a ssh://localhost/a
1061 abort: --all-largefiles is incompatible with non-local destination ssh://localhost/a
1061 abort: --all-largefiles is incompatible with non-local destination ssh://localhost/a
1062 [255]
1062 [255]
1063
1063
1064 Test pulling with --all-largefiles flag. Also test that the largefiles are
1064 Test pulling with --all-largefiles flag. Also test that the largefiles are
1065 downloaded from 'default' instead of 'default-push' when no source is specified
1065 downloaded from 'default' instead of 'default-push' when no source is specified
1066 (issue3584)
1066 (issue3584)
1067
1067
1068 $ rm -Rf a-backup
1068 $ rm -Rf a-backup
1069 $ hg clone -r 1 a a-backup
1069 $ hg clone -r 1 a a-backup
1070 adding changesets
1070 adding changesets
1071 adding manifests
1071 adding manifests
1072 adding file changes
1072 adding file changes
1073 added 2 changesets with 8 changes to 4 files
1073 added 2 changesets with 8 changes to 4 files
1074 updating to branch default
1074 updating to branch default
1075 getting changed largefiles
1075 getting changed largefiles
1076 2 largefiles updated, 0 removed
1076 2 largefiles updated, 0 removed
1077 4 files updated, 0 files merged, 0 files removed, 0 files unresolved
1077 4 files updated, 0 files merged, 0 files removed, 0 files unresolved
1078 $ rm "${USERCACHE}"/*
1078 $ rm "${USERCACHE}"/*
1079 $ cd a-backup
1079 $ cd a-backup
1080 $ hg pull --all-largefiles --config paths.default-push=bogus/path
1080 $ hg pull --all-largefiles --config paths.default-push=bogus/path
1081 pulling from $TESTTMP/a (glob)
1081 pulling from $TESTTMP/a (glob)
1082 searching for changes
1082 searching for changes
1083 adding changesets
1083 adding changesets
1084 adding manifests
1084 adding manifests
1085 adding file changes
1085 adding file changes
1086 added 6 changesets with 16 changes to 8 files
1086 added 6 changesets with 16 changes to 8 files
1087 (run 'hg update' to get a working copy)
1087 (run 'hg update' to get a working copy)
1088 6 largefiles cached
1088 6 largefiles cached
1089
1089
1090 redo pull with --lfrev and check it pulls largefiles for the right revs
1090 redo pull with --lfrev and check it pulls largefiles for the right revs
1091
1091
1092 $ hg rollback
1092 $ hg rollback
1093 repository tip rolled back to revision 1 (undo pull)
1093 repository tip rolled back to revision 1 (undo pull)
1094 $ hg pull -v --lfrev 'heads(pulled())+min(pulled())'
1094 $ hg pull -v --lfrev 'heads(pulled())+min(pulled())'
1095 pulling from $TESTTMP/a (glob)
1095 pulling from $TESTTMP/a (glob)
1096 searching for changes
1096 searching for changes
1097 all local heads known remotely
1097 all local heads known remotely
1098 6 changesets found
1098 6 changesets found
1099 adding changesets
1099 adding changesets
1100 adding manifests
1100 adding manifests
1101 adding file changes
1101 adding file changes
1102 added 6 changesets with 16 changes to 8 files
1102 added 6 changesets with 16 changes to 8 files
1103 calling hook changegroup.lfiles: hgext.largefiles.reposetup.checkrequireslfiles
1103 calling hook changegroup.lfiles: hgext.largefiles.reposetup.checkrequireslfiles
1104 (run 'hg update' to get a working copy)
1104 (run 'hg update' to get a working copy)
1105 pulling largefiles for revision 7
1105 pulling largefiles for revision 7
1106 found 971fb41e78fea4f8e0ba5244784239371cb00591 in store
1106 found 971fb41e78fea4f8e0ba5244784239371cb00591 in store
1107 found 0d6d75887db61b2c7e6c74b5dd8fc6ad50c0cc30 in store
1107 found 0d6d75887db61b2c7e6c74b5dd8fc6ad50c0cc30 in store
1108 found bb3151689acb10f0c3125c560d5e63df914bc1af in store
1108 found bb3151689acb10f0c3125c560d5e63df914bc1af in store
1109 pulling largefiles for revision 2
1109 pulling largefiles for revision 2
1110 found eb7338044dc27f9bc59b8dd5a246b065ead7a9c4 in store
1110 found eb7338044dc27f9bc59b8dd5a246b065ead7a9c4 in store
1111 0 largefiles cached
1111 0 largefiles cached
1112
1112
1113 lfpull
1113 lfpull
1114
1114
1115 $ hg lfpull -r : --config largefiles.usercache=usercache-lfpull
1115 $ hg lfpull -r : --config largefiles.usercache=usercache-lfpull
1116 2 largefiles cached
1116 2 largefiles cached
1117 $ hg lfpull -v -r 4+2 --config largefiles.usercache=usercache-lfpull
1117 $ hg lfpull -v -r 4+2 --config largefiles.usercache=usercache-lfpull
1118 pulling largefiles for revision 4
1118 pulling largefiles for revision 4
1119 found eb7338044dc27f9bc59b8dd5a246b065ead7a9c4 in store
1119 found eb7338044dc27f9bc59b8dd5a246b065ead7a9c4 in store
1120 found eb7338044dc27f9bc59b8dd5a246b065ead7a9c4 in store
1120 found eb7338044dc27f9bc59b8dd5a246b065ead7a9c4 in store
1121 pulling largefiles for revision 2
1121 pulling largefiles for revision 2
1122 found eb7338044dc27f9bc59b8dd5a246b065ead7a9c4 in store
1122 found eb7338044dc27f9bc59b8dd5a246b065ead7a9c4 in store
1123 0 largefiles cached
1123 0 largefiles cached
1124
1124
1125 $ ls usercache-lfpull/* | sort
1125 $ ls usercache-lfpull/* | sort
1126 usercache-lfpull/1deebade43c8c498a3c8daddac0244dc55d1331d
1126 usercache-lfpull/1deebade43c8c498a3c8daddac0244dc55d1331d
1127 usercache-lfpull/4669e532d5b2c093a78eca010077e708a071bb64
1127 usercache-lfpull/4669e532d5b2c093a78eca010077e708a071bb64
1128
1128
1129 $ cd ..
1129 $ cd ..
1130
1130
1131 Rebasing between two repositories does not revert largefiles to old
1131 Rebasing between two repositories does not revert largefiles to old
1132 revisions (this was a very bad bug that took a lot of work to fix).
1132 revisions (this was a very bad bug that took a lot of work to fix).
1133
1133
1134 $ hg clone a d
1134 $ hg clone a d
1135 updating to branch default
1135 updating to branch default
1136 getting changed largefiles
1136 getting changed largefiles
1137 3 largefiles updated, 0 removed
1137 3 largefiles updated, 0 removed
1138 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
1138 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
1139 $ cd b
1139 $ cd b
1140 $ echo large4-modified > sub/large4
1140 $ echo large4-modified > sub/large4
1141 $ echo normal3-modified > normal3
1141 $ echo normal3-modified > normal3
1142 $ hg commit -m "modify normal file and largefile in repo b"
1142 $ hg commit -m "modify normal file and largefile in repo b"
1143 Invoking status precommit hook
1143 Invoking status precommit hook
1144 M normal3
1144 M normal3
1145 M sub/large4
1145 M sub/large4
1146 $ cd ../d
1146 $ cd ../d
1147 $ echo large6-modified > sub2/large6
1147 $ echo large6-modified > sub2/large6
1148 $ echo normal4-modified > sub/normal4
1148 $ echo normal4-modified > sub/normal4
1149 $ hg commit -m "modify normal file largefile in repo d"
1149 $ hg commit -m "modify normal file largefile in repo d"
1150 Invoking status precommit hook
1150 Invoking status precommit hook
1151 M sub/normal4
1151 M sub/normal4
1152 M sub2/large6
1152 M sub2/large6
1153 $ cd ..
1153 $ cd ..
1154 $ hg clone d e
1154 $ hg clone d e
1155 updating to branch default
1155 updating to branch default
1156 getting changed largefiles
1156 getting changed largefiles
1157 3 largefiles updated, 0 removed
1157 3 largefiles updated, 0 removed
1158 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
1158 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
1159 $ cd d
1159 $ cd d
1160
1160
1161 More rebase testing, but also test that the largefiles are downloaded from
1161 More rebase testing, but also test that the largefiles are downloaded from
1162 'default-push' when no source is specified (issue3584). (The largefile from the
1162 'default-push' when no source is specified (issue3584). (The largefile from the
1163 pulled revision is however not downloaded but found in the local cache.)
1163 pulled revision is however not downloaded but found in the local cache.)
1164 Largefiles are fetched for the new pulled revision, not for existing revisions,
1164 Largefiles are fetched for the new pulled revision, not for existing revisions,
1165 rebased or not.
1165 rebased or not.
1166
1166
1167 $ [ ! -f .hg/largefiles/e166e74c7303192238d60af5a9c4ce9bef0b7928 ]
1167 $ [ ! -f .hg/largefiles/e166e74c7303192238d60af5a9c4ce9bef0b7928 ]
1168 $ hg pull --rebase --all-largefiles --config paths.default-push=bogus/path --config paths.default=../b
1168 $ hg pull --rebase --all-largefiles --config paths.default-push=bogus/path --config paths.default=../b
1169 pulling from $TESTTMP/b (glob)
1169 pulling from $TESTTMP/b (glob)
1170 searching for changes
1170 searching for changes
1171 adding changesets
1171 adding changesets
1172 adding manifests
1172 adding manifests
1173 adding file changes
1173 adding file changes
1174 added 1 changesets with 2 changes to 2 files (+1 heads)
1174 added 1 changesets with 2 changes to 2 files (+1 heads)
1175 0 largefiles cached
1175 0 largefiles cached
1176 Invoking status precommit hook
1176 Invoking status precommit hook
1177 M sub/normal4
1177 M sub/normal4
1178 M sub2/large6
1178 M sub2/large6
1179 saved backup bundle to $TESTTMP/d/.hg/strip-backup/f574fb32bb45-backup.hg (glob)
1179 saved backup bundle to $TESTTMP/d/.hg/strip-backup/f574fb32bb45-backup.hg (glob)
1180 $ [ -f .hg/largefiles/e166e74c7303192238d60af5a9c4ce9bef0b7928 ]
1180 $ [ -f .hg/largefiles/e166e74c7303192238d60af5a9c4ce9bef0b7928 ]
1181 $ hg log --template '{rev}:{node|short} {desc|firstline}\n'
1181 $ hg log --template '{rev}:{node|short} {desc|firstline}\n'
1182 9:598410d3eb9a modify normal file largefile in repo d
1182 9:598410d3eb9a modify normal file largefile in repo d
1183 8:a381d2c8c80e modify normal file and largefile in repo b
1183 8:a381d2c8c80e modify normal file and largefile in repo b
1184 7:daea875e9014 add/edit more largefiles
1184 7:daea875e9014 add/edit more largefiles
1185 6:4355d653f84f edit files yet again
1185 6:4355d653f84f edit files yet again
1186 5:9d5af5072dbd edit files again
1186 5:9d5af5072dbd edit files again
1187 4:74c02385b94c move files
1187 4:74c02385b94c move files
1188 3:9e8fbc4bce62 copy files
1188 3:9e8fbc4bce62 copy files
1189 2:51a0ae4d5864 remove files
1189 2:51a0ae4d5864 remove files
1190 1:ce8896473775 edit files
1190 1:ce8896473775 edit files
1191 0:30d30fe6a5be add files
1191 0:30d30fe6a5be add files
1192 $ hg log -G --template '{rev}:{node|short} {desc|firstline}\n'
1192 $ hg log -G --template '{rev}:{node|short} {desc|firstline}\n'
1193 @ 9:598410d3eb9a modify normal file largefile in repo d
1193 @ 9:598410d3eb9a modify normal file largefile in repo d
1194 |
1194 |
1195 o 8:a381d2c8c80e modify normal file and largefile in repo b
1195 o 8:a381d2c8c80e modify normal file and largefile in repo b
1196 |
1196 |
1197 o 7:daea875e9014 add/edit more largefiles
1197 o 7:daea875e9014 add/edit more largefiles
1198 |
1198 |
1199 o 6:4355d653f84f edit files yet again
1199 o 6:4355d653f84f edit files yet again
1200 |
1200 |
1201 o 5:9d5af5072dbd edit files again
1201 o 5:9d5af5072dbd edit files again
1202 |
1202 |
1203 o 4:74c02385b94c move files
1203 o 4:74c02385b94c move files
1204 |
1204 |
1205 o 3:9e8fbc4bce62 copy files
1205 o 3:9e8fbc4bce62 copy files
1206 |
1206 |
1207 o 2:51a0ae4d5864 remove files
1207 o 2:51a0ae4d5864 remove files
1208 |
1208 |
1209 o 1:ce8896473775 edit files
1209 o 1:ce8896473775 edit files
1210 |
1210 |
1211 o 0:30d30fe6a5be add files
1211 o 0:30d30fe6a5be add files
1212
1212
1213 $ cat normal3
1213 $ cat normal3
1214 normal3-modified
1214 normal3-modified
1215 $ cat sub/normal4
1215 $ cat sub/normal4
1216 normal4-modified
1216 normal4-modified
1217 $ cat sub/large4
1217 $ cat sub/large4
1218 large4-modified
1218 large4-modified
1219 $ cat sub2/large6
1219 $ cat sub2/large6
1220 large6-modified
1220 large6-modified
1221 $ cat sub2/large7
1221 $ cat sub2/large7
1222 large7
1222 large7
1223 $ cd ../e
1223 $ cd ../e
1224 $ hg pull ../b
1224 $ hg pull ../b
1225 pulling from ../b
1225 pulling from ../b
1226 searching for changes
1226 searching for changes
1227 adding changesets
1227 adding changesets
1228 adding manifests
1228 adding manifests
1229 adding file changes
1229 adding file changes
1230 added 1 changesets with 2 changes to 2 files (+1 heads)
1230 added 1 changesets with 2 changes to 2 files (+1 heads)
1231 (run 'hg heads' to see heads, 'hg merge' to merge)
1231 (run 'hg heads' to see heads, 'hg merge' to merge)
1232 $ hg rebase
1232 $ hg rebase
1233 Invoking status precommit hook
1233 Invoking status precommit hook
1234 M sub/normal4
1234 M sub/normal4
1235 M sub2/large6
1235 M sub2/large6
1236 saved backup bundle to $TESTTMP/e/.hg/strip-backup/f574fb32bb45-backup.hg (glob)
1236 saved backup bundle to $TESTTMP/e/.hg/strip-backup/f574fb32bb45-backup.hg (glob)
1237 $ hg log --template '{rev}:{node|short} {desc|firstline}\n'
1237 $ hg log --template '{rev}:{node|short} {desc|firstline}\n'
1238 9:598410d3eb9a modify normal file largefile in repo d
1238 9:598410d3eb9a modify normal file largefile in repo d
1239 8:a381d2c8c80e modify normal file and largefile in repo b
1239 8:a381d2c8c80e modify normal file and largefile in repo b
1240 7:daea875e9014 add/edit more largefiles
1240 7:daea875e9014 add/edit more largefiles
1241 6:4355d653f84f edit files yet again
1241 6:4355d653f84f edit files yet again
1242 5:9d5af5072dbd edit files again
1242 5:9d5af5072dbd edit files again
1243 4:74c02385b94c move files
1243 4:74c02385b94c move files
1244 3:9e8fbc4bce62 copy files
1244 3:9e8fbc4bce62 copy files
1245 2:51a0ae4d5864 remove files
1245 2:51a0ae4d5864 remove files
1246 1:ce8896473775 edit files
1246 1:ce8896473775 edit files
1247 0:30d30fe6a5be add files
1247 0:30d30fe6a5be add files
1248 $ cat normal3
1248 $ cat normal3
1249 normal3-modified
1249 normal3-modified
1250 $ cat sub/normal4
1250 $ cat sub/normal4
1251 normal4-modified
1251 normal4-modified
1252 $ cat sub/large4
1252 $ cat sub/large4
1253 large4-modified
1253 large4-modified
1254 $ cat sub2/large6
1254 $ cat sub2/large6
1255 large6-modified
1255 large6-modified
1256 $ cat sub2/large7
1256 $ cat sub2/large7
1257 large7
1257 large7
1258
1258
1259 Log on largefiles
1259 Log on largefiles
1260
1260
1261 - same output
1261 - same output
1262 $ hg log --template '{rev}:{node|short} {desc|firstline}\n' .hglf/sub/large4
1262 $ hg log --template '{rev}:{node|short} {desc|firstline}\n' .hglf/sub/large4
1263 8:a381d2c8c80e modify normal file and largefile in repo b
1263 8:a381d2c8c80e modify normal file and largefile in repo b
1264 6:4355d653f84f edit files yet again
1264 6:4355d653f84f edit files yet again
1265 5:9d5af5072dbd edit files again
1265 5:9d5af5072dbd edit files again
1266 4:74c02385b94c move files
1266 4:74c02385b94c move files
1267 $ hg log -G --template '{rev}:{node|short} {desc|firstline}\n' .hglf/sub/large4
1267 $ hg log -G --template '{rev}:{node|short} {desc|firstline}\n' .hglf/sub/large4
1268 o 8:a381d2c8c80e modify normal file and largefile in repo b
1268 o 8:a381d2c8c80e modify normal file and largefile in repo b
1269 |
1269 |
1270 o 6:4355d653f84f edit files yet again
1270 o 6:4355d653f84f edit files yet again
1271 |
1271 |
1272 o 5:9d5af5072dbd edit files again
1272 o 5:9d5af5072dbd edit files again
1273 |
1273 |
1274 o 4:74c02385b94c move files
1274 o 4:74c02385b94c move files
1275 |
1275 |
1276 $ hg log --template '{rev}:{node|short} {desc|firstline}\n' sub/large4
1276 $ hg log --template '{rev}:{node|short} {desc|firstline}\n' sub/large4
1277 8:a381d2c8c80e modify normal file and largefile in repo b
1277 8:a381d2c8c80e modify normal file and largefile in repo b
1278 6:4355d653f84f edit files yet again
1278 6:4355d653f84f edit files yet again
1279 5:9d5af5072dbd edit files again
1279 5:9d5af5072dbd edit files again
1280 4:74c02385b94c move files
1280 4:74c02385b94c move files
1281 $ hg log -G --template '{rev}:{node|short} {desc|firstline}\n' .hglf/sub/large4
1281 $ hg log -G --template '{rev}:{node|short} {desc|firstline}\n' .hglf/sub/large4
1282 o 8:a381d2c8c80e modify normal file and largefile in repo b
1282 o 8:a381d2c8c80e modify normal file and largefile in repo b
1283 |
1283 |
1284 o 6:4355d653f84f edit files yet again
1284 o 6:4355d653f84f edit files yet again
1285 |
1285 |
1286 o 5:9d5af5072dbd edit files again
1286 o 5:9d5af5072dbd edit files again
1287 |
1287 |
1288 o 4:74c02385b94c move files
1288 o 4:74c02385b94c move files
1289 |
1289 |
1290
1290
1291 - .hglf only matches largefiles, without .hglf it matches 9 bco sub/normal
1291 - .hglf only matches largefiles, without .hglf it matches 9 bco sub/normal
1292 $ hg log --template '{rev}:{node|short} {desc|firstline}\n' .hglf/sub
1292 $ hg log --template '{rev}:{node|short} {desc|firstline}\n' .hglf/sub
1293 8:a381d2c8c80e modify normal file and largefile in repo b
1293 8:a381d2c8c80e modify normal file and largefile in repo b
1294 6:4355d653f84f edit files yet again
1294 6:4355d653f84f edit files yet again
1295 5:9d5af5072dbd edit files again
1295 5:9d5af5072dbd edit files again
1296 4:74c02385b94c move files
1296 4:74c02385b94c move files
1297 1:ce8896473775 edit files
1297 1:ce8896473775 edit files
1298 0:30d30fe6a5be add files
1298 0:30d30fe6a5be add files
1299 $ hg log -G --template '{rev}:{node|short} {desc|firstline}\n' .hglf/sub
1299 $ hg log -G --template '{rev}:{node|short} {desc|firstline}\n' .hglf/sub
1300 o 8:a381d2c8c80e modify normal file and largefile in repo b
1300 o 8:a381d2c8c80e modify normal file and largefile in repo b
1301 |
1301 |
1302 o 6:4355d653f84f edit files yet again
1302 o 6:4355d653f84f edit files yet again
1303 |
1303 |
1304 o 5:9d5af5072dbd edit files again
1304 o 5:9d5af5072dbd edit files again
1305 |
1305 |
1306 o 4:74c02385b94c move files
1306 o 4:74c02385b94c move files
1307 |
1307 |
1308 o 1:ce8896473775 edit files
1308 o 1:ce8896473775 edit files
1309 |
1309 |
1310 o 0:30d30fe6a5be add files
1310 o 0:30d30fe6a5be add files
1311
1311
1312 $ hg log --template '{rev}:{node|short} {desc|firstline}\n' sub
1312 $ hg log --template '{rev}:{node|short} {desc|firstline}\n' sub
1313 9:598410d3eb9a modify normal file largefile in repo d
1313 9:598410d3eb9a modify normal file largefile in repo d
1314 8:a381d2c8c80e modify normal file and largefile in repo b
1314 8:a381d2c8c80e modify normal file and largefile in repo b
1315 6:4355d653f84f edit files yet again
1315 6:4355d653f84f edit files yet again
1316 5:9d5af5072dbd edit files again
1316 5:9d5af5072dbd edit files again
1317 4:74c02385b94c move files
1317 4:74c02385b94c move files
1318 1:ce8896473775 edit files
1318 1:ce8896473775 edit files
1319 0:30d30fe6a5be add files
1319 0:30d30fe6a5be add files
1320 $ hg log -G --template '{rev}:{node|short} {desc|firstline}\n' sub
1320 $ hg log -G --template '{rev}:{node|short} {desc|firstline}\n' sub
1321 @ 9:598410d3eb9a modify normal file largefile in repo d
1321 @ 9:598410d3eb9a modify normal file largefile in repo d
1322 |
1322 |
1323 o 8:a381d2c8c80e modify normal file and largefile in repo b
1323 o 8:a381d2c8c80e modify normal file and largefile in repo b
1324 |
1324 |
1325 o 6:4355d653f84f edit files yet again
1325 o 6:4355d653f84f edit files yet again
1326 |
1326 |
1327 o 5:9d5af5072dbd edit files again
1327 o 5:9d5af5072dbd edit files again
1328 |
1328 |
1329 o 4:74c02385b94c move files
1329 o 4:74c02385b94c move files
1330 |
1330 |
1331 o 1:ce8896473775 edit files
1331 o 1:ce8896473775 edit files
1332 |
1332 |
1333 o 0:30d30fe6a5be add files
1333 o 0:30d30fe6a5be add files
1334
1334
1335 - globbing gives same result
1335 - globbing gives same result
1336 $ hg log --template '{rev}:{node|short} {desc|firstline}\n' 'glob:sub/*'
1336 $ hg log --template '{rev}:{node|short} {desc|firstline}\n' 'glob:sub/*'
1337 9:598410d3eb9a modify normal file largefile in repo d
1337 9:598410d3eb9a modify normal file largefile in repo d
1338 8:a381d2c8c80e modify normal file and largefile in repo b
1338 8:a381d2c8c80e modify normal file and largefile in repo b
1339 6:4355d653f84f edit files yet again
1339 6:4355d653f84f edit files yet again
1340 5:9d5af5072dbd edit files again
1340 5:9d5af5072dbd edit files again
1341 4:74c02385b94c move files
1341 4:74c02385b94c move files
1342 1:ce8896473775 edit files
1342 1:ce8896473775 edit files
1343 0:30d30fe6a5be add files
1343 0:30d30fe6a5be add files
1344 $ hg log -G --template '{rev}:{node|short} {desc|firstline}\n' 'glob:sub/*'
1344 $ hg log -G --template '{rev}:{node|short} {desc|firstline}\n' 'glob:sub/*'
1345 @ 9:598410d3eb9a modify normal file largefile in repo d
1345 @ 9:598410d3eb9a modify normal file largefile in repo d
1346 |
1346 |
1347 o 8:a381d2c8c80e modify normal file and largefile in repo b
1347 o 8:a381d2c8c80e modify normal file and largefile in repo b
1348 |
1348 |
1349 o 6:4355d653f84f edit files yet again
1349 o 6:4355d653f84f edit files yet again
1350 |
1350 |
1351 o 5:9d5af5072dbd edit files again
1351 o 5:9d5af5072dbd edit files again
1352 |
1352 |
1353 o 4:74c02385b94c move files
1353 o 4:74c02385b94c move files
1354 |
1354 |
1355 o 1:ce8896473775 edit files
1355 o 1:ce8896473775 edit files
1356 |
1356 |
1357 o 0:30d30fe6a5be add files
1357 o 0:30d30fe6a5be add files
1358
1358
1359 Rollback on largefiles.
1359 Rollback on largefiles.
1360
1360
1361 $ echo large4-modified-again > sub/large4
1361 $ echo large4-modified-again > sub/large4
1362 $ hg commit -m "Modify large4 again"
1362 $ hg commit -m "Modify large4 again"
1363 Invoking status precommit hook
1363 Invoking status precommit hook
1364 M sub/large4
1364 M sub/large4
1365 $ hg rollback
1365 $ hg rollback
1366 repository tip rolled back to revision 9 (undo commit)
1366 repository tip rolled back to revision 9 (undo commit)
1367 working directory now based on revision 9
1367 working directory now based on revision 9
1368 $ hg st
1368 $ hg st
1369 M sub/large4
1369 M sub/large4
1370 $ hg log --template '{rev}:{node|short} {desc|firstline}\n'
1370 $ hg log --template '{rev}:{node|short} {desc|firstline}\n'
1371 9:598410d3eb9a modify normal file largefile in repo d
1371 9:598410d3eb9a modify normal file largefile in repo d
1372 8:a381d2c8c80e modify normal file and largefile in repo b
1372 8:a381d2c8c80e modify normal file and largefile in repo b
1373 7:daea875e9014 add/edit more largefiles
1373 7:daea875e9014 add/edit more largefiles
1374 6:4355d653f84f edit files yet again
1374 6:4355d653f84f edit files yet again
1375 5:9d5af5072dbd edit files again
1375 5:9d5af5072dbd edit files again
1376 4:74c02385b94c move files
1376 4:74c02385b94c move files
1377 3:9e8fbc4bce62 copy files
1377 3:9e8fbc4bce62 copy files
1378 2:51a0ae4d5864 remove files
1378 2:51a0ae4d5864 remove files
1379 1:ce8896473775 edit files
1379 1:ce8896473775 edit files
1380 0:30d30fe6a5be add files
1380 0:30d30fe6a5be add files
1381 $ cat sub/large4
1381 $ cat sub/large4
1382 large4-modified-again
1382 large4-modified-again
1383
1383
1384 "update --check" refuses to update with uncommitted changes.
1384 "update --check" refuses to update with uncommitted changes.
1385 $ hg update --check 8
1385 $ hg update --check 8
1386 abort: uncommitted changes
1386 abort: uncommitted changes
1387 [255]
1387 [255]
1388
1388
1389 "update --clean" leaves correct largefiles in working copy, even when there is
1389 "update --clean" leaves correct largefiles in working copy, even when there is
1390 .orig files from revert in .hglf.
1390 .orig files from revert in .hglf.
1391
1391
1392 $ echo mistake > sub2/large7
1392 $ echo mistake > sub2/large7
1393 $ hg revert sub2/large7
1393 $ hg revert sub2/large7
1394 $ cat sub2/large7
1394 $ cat sub2/large7
1395 large7
1395 large7
1396 $ cat sub2/large7.orig
1396 $ cat sub2/large7.orig
1397 mistake
1397 mistake
1398 $ test ! -f .hglf/sub2/large7.orig
1398 $ test ! -f .hglf/sub2/large7.orig
1399
1399
1400 $ hg -q update --clean -r null
1400 $ hg -q update --clean -r null
1401 $ hg update --clean
1401 $ hg update --clean
1402 getting changed largefiles
1402 getting changed largefiles
1403 3 largefiles updated, 0 removed
1403 3 largefiles updated, 0 removed
1404 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
1404 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
1405 $ cat normal3
1405 $ cat normal3
1406 normal3-modified
1406 normal3-modified
1407 $ cat sub/normal4
1407 $ cat sub/normal4
1408 normal4-modified
1408 normal4-modified
1409 $ cat sub/large4
1409 $ cat sub/large4
1410 large4-modified
1410 large4-modified
1411 $ cat sub2/large6
1411 $ cat sub2/large6
1412 large6-modified
1412 large6-modified
1413 $ cat sub2/large7
1413 $ cat sub2/large7
1414 large7
1414 large7
1415 $ cat sub2/large7.orig
1415 $ cat sub2/large7.orig
1416 mistake
1416 mistake
1417 $ test ! -f .hglf/sub2/large7.orig
1417 $ test ! -f .hglf/sub2/large7.orig
1418
1418
1419 verify that largefile .orig file no longer is overwritten on every update -C:
1419 verify that largefile .orig file no longer is overwritten on every update -C:
1420 $ hg update --clean
1420 $ hg update --clean
1421 getting changed largefiles
1421 getting changed largefiles
1422 0 largefiles updated, 0 removed
1422 0 largefiles updated, 0 removed
1423 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
1423 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
1424 $ cat sub2/large7.orig
1424 $ cat sub2/large7.orig
1425 mistake
1425 mistake
1426 $ rm sub2/large7.orig
1426 $ rm sub2/large7.orig
1427
1427
1428 Now "update check" is happy.
1428 Now "update check" is happy.
1429 $ hg update --check 8
1429 $ hg update --check 8
1430 getting changed largefiles
1430 getting changed largefiles
1431 1 largefiles updated, 0 removed
1431 1 largefiles updated, 0 removed
1432 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
1432 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
1433 $ hg update --check
1433 $ hg update --check
1434 getting changed largefiles
1434 getting changed largefiles
1435 1 largefiles updated, 0 removed
1435 1 largefiles updated, 0 removed
1436 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
1436 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
1437
1437
1438 Test removing empty largefiles directories on update
1438 Test removing empty largefiles directories on update
1439 $ test -d sub2 && echo "sub2 exists"
1439 $ test -d sub2 && echo "sub2 exists"
1440 sub2 exists
1440 sub2 exists
1441 $ hg update -q null
1441 $ hg update -q null
1442 $ test -d sub2 && echo "error: sub2 should not exist anymore"
1442 $ test -d sub2 && echo "error: sub2 should not exist anymore"
1443 [1]
1443 [1]
1444 $ hg update -q
1444 $ hg update -q
1445
1445
1446 Test hg remove removes empty largefiles directories
1446 Test hg remove removes empty largefiles directories
1447 $ test -d sub2 && echo "sub2 exists"
1447 $ test -d sub2 && echo "sub2 exists"
1448 sub2 exists
1448 sub2 exists
1449 $ hg remove sub2/*
1449 $ hg remove sub2/*
1450 $ test -d sub2 && echo "error: sub2 should not exist anymore"
1450 $ test -d sub2 && echo "error: sub2 should not exist anymore"
1451 [1]
1451 [1]
1452 $ hg revert sub2/large6 sub2/large7
1452 $ hg revert sub2/large6 sub2/large7
1453
1453
1454 "revert" works on largefiles (and normal files too).
1454 "revert" works on largefiles (and normal files too).
1455 $ echo hack3 >> normal3
1455 $ echo hack3 >> normal3
1456 $ echo hack4 >> sub/normal4
1456 $ echo hack4 >> sub/normal4
1457 $ echo hack4 >> sub/large4
1457 $ echo hack4 >> sub/large4
1458 $ rm sub2/large6
1458 $ rm sub2/large6
1459 $ hg revert sub2/large6
1459 $ hg revert sub2/large6
1460 $ hg rm sub2/large6
1460 $ hg rm sub2/large6
1461 $ echo new >> sub2/large8
1461 $ echo new >> sub2/large8
1462 $ hg add --large sub2/large8
1462 $ hg add --large sub2/large8
1463 # XXX we don't really want to report that we're reverting the standin;
1463 # XXX we don't really want to report that we're reverting the standin;
1464 # that's just an implementation detail. But I don't see an obvious fix. ;-(
1464 # that's just an implementation detail. But I don't see an obvious fix. ;-(
1465 $ hg revert sub
1465 $ hg revert sub
1466 reverting .hglf/sub/large4 (glob)
1466 reverting .hglf/sub/large4 (glob)
1467 reverting sub/normal4 (glob)
1467 reverting sub/normal4 (glob)
1468 $ hg status
1468 $ hg status
1469 M normal3
1469 M normal3
1470 A sub2/large8
1470 A sub2/large8
1471 R sub2/large6
1471 R sub2/large6
1472 ? sub/large4.orig
1472 ? sub/large4.orig
1473 ? sub/normal4.orig
1473 ? sub/normal4.orig
1474 $ cat sub/normal4
1474 $ cat sub/normal4
1475 normal4-modified
1475 normal4-modified
1476 $ cat sub/large4
1476 $ cat sub/large4
1477 large4-modified
1477 large4-modified
1478 $ hg revert -a --no-backup
1478 $ hg revert -a --no-backup
1479 undeleting .hglf/sub2/large6 (glob)
1479 undeleting .hglf/sub2/large6 (glob)
1480 forgetting .hglf/sub2/large8 (glob)
1480 forgetting .hglf/sub2/large8 (glob)
1481 reverting normal3
1481 reverting normal3
1482 $ hg status
1482 $ hg status
1483 ? sub/large4.orig
1483 ? sub/large4.orig
1484 ? sub/normal4.orig
1484 ? sub/normal4.orig
1485 ? sub2/large8
1485 ? sub2/large8
1486 $ cat normal3
1486 $ cat normal3
1487 normal3-modified
1487 normal3-modified
1488 $ cat sub2/large6
1488 $ cat sub2/large6
1489 large6-modified
1489 large6-modified
1490 $ rm sub/*.orig sub2/large8
1490 $ rm sub/*.orig sub2/large8
1491
1491
1492 revert some files to an older revision
1492 revert some files to an older revision
1493 $ hg revert --no-backup -r 8 sub2
1493 $ hg revert --no-backup -r 8 sub2
1494 reverting .hglf/sub2/large6 (glob)
1494 reverting .hglf/sub2/large6 (glob)
1495 $ cat sub2/large6
1495 $ cat sub2/large6
1496 large6
1496 large6
1497 $ hg revert --no-backup -C -r '.^' sub2
1497 $ hg revert --no-backup -C -r '.^' sub2
1498 $ hg revert --no-backup sub2
1498 $ hg revert --no-backup sub2
1499 reverting .hglf/sub2/large6 (glob)
1499 reverting .hglf/sub2/large6 (glob)
1500 $ hg status
1500 $ hg status
1501
1501
1502 "verify --large" actually verifies largefiles
1502 "verify --large" actually verifies largefiles
1503
1503
1504 - Where Do We Come From? What Are We? Where Are We Going?
1504 - Where Do We Come From? What Are We? Where Are We Going?
1505 $ pwd
1505 $ pwd
1506 $TESTTMP/e
1506 $TESTTMP/e
1507 $ hg paths
1507 $ hg paths
1508 default = $TESTTMP/d (glob)
1508 default = $TESTTMP/d (glob)
1509
1509
1510 $ hg verify --large
1510 $ hg verify --large
1511 checking changesets
1511 checking changesets
1512 checking manifests
1512 checking manifests
1513 crosschecking files in changesets and manifests
1513 crosschecking files in changesets and manifests
1514 checking files
1514 checking files
1515 10 files, 10 changesets, 28 total revisions
1515 10 files, 10 changesets, 28 total revisions
1516 searching 1 changesets for largefiles
1516 searching 1 changesets for largefiles
1517 verified existence of 3 revisions of 3 largefiles
1517 verified existence of 3 revisions of 3 largefiles
1518
1518
1519 - introduce missing blob in local store repo and make sure that this is caught:
1519 - introduce missing blob in local store repo and make sure that this is caught:
1520 $ mv $TESTTMP/d/.hg/largefiles/e166e74c7303192238d60af5a9c4ce9bef0b7928 .
1520 $ mv $TESTTMP/d/.hg/largefiles/e166e74c7303192238d60af5a9c4ce9bef0b7928 .
1521 $ hg verify --large
1521 $ hg verify --large
1522 checking changesets
1522 checking changesets
1523 checking manifests
1523 checking manifests
1524 crosschecking files in changesets and manifests
1524 crosschecking files in changesets and manifests
1525 checking files
1525 checking files
1526 10 files, 10 changesets, 28 total revisions
1526 10 files, 10 changesets, 28 total revisions
1527 searching 1 changesets for largefiles
1527 searching 1 changesets for largefiles
1528 changeset 9:598410d3eb9a: sub/large4 references missing $TESTTMP/d/.hg/largefiles/e166e74c7303192238d60af5a9c4ce9bef0b7928 (glob)
1528 changeset 9:598410d3eb9a: sub/large4 references missing $TESTTMP/d/.hg/largefiles/e166e74c7303192238d60af5a9c4ce9bef0b7928 (glob)
1529 verified existence of 3 revisions of 3 largefiles
1529 verified existence of 3 revisions of 3 largefiles
1530 [1]
1530 [1]
1531
1531
1532 - introduce corruption and make sure that it is caught when checking content:
1532 - introduce corruption and make sure that it is caught when checking content:
1533 $ echo '5 cents' > $TESTTMP/d/.hg/largefiles/e166e74c7303192238d60af5a9c4ce9bef0b7928
1533 $ echo '5 cents' > $TESTTMP/d/.hg/largefiles/e166e74c7303192238d60af5a9c4ce9bef0b7928
1534 $ hg verify -q --large --lfc
1534 $ hg verify -q --large --lfc
1535 changeset 9:598410d3eb9a: sub/large4 references corrupted $TESTTMP/d/.hg/largefiles/e166e74c7303192238d60af5a9c4ce9bef0b7928 (glob)
1535 changeset 9:598410d3eb9a: sub/large4 references corrupted $TESTTMP/d/.hg/largefiles/e166e74c7303192238d60af5a9c4ce9bef0b7928 (glob)
1536 [1]
1536 [1]
1537
1537
1538 - cleanup
1538 - cleanup
1539 $ mv e166e74c7303192238d60af5a9c4ce9bef0b7928 $TESTTMP/d/.hg/largefiles/
1539 $ mv e166e74c7303192238d60af5a9c4ce9bef0b7928 $TESTTMP/d/.hg/largefiles/
1540
1540
1541 - verifying all revisions will fail because we didn't clone all largefiles to d:
1541 - verifying all revisions will fail because we didn't clone all largefiles to d:
1542 $ echo 'T-shirt' > $TESTTMP/d/.hg/largefiles/eb7338044dc27f9bc59b8dd5a246b065ead7a9c4
1542 $ echo 'T-shirt' > $TESTTMP/d/.hg/largefiles/eb7338044dc27f9bc59b8dd5a246b065ead7a9c4
1543 $ hg verify -q --lfa --lfc
1543 $ hg verify -q --lfa --lfc
1544 changeset 0:30d30fe6a5be: large1 references missing $TESTTMP/d/.hg/largefiles/4669e532d5b2c093a78eca010077e708a071bb64 (glob)
1544 changeset 0:30d30fe6a5be: large1 references missing $TESTTMP/d/.hg/largefiles/4669e532d5b2c093a78eca010077e708a071bb64 (glob)
1545 changeset 0:30d30fe6a5be: sub/large2 references missing $TESTTMP/d/.hg/largefiles/1deebade43c8c498a3c8daddac0244dc55d1331d (glob)
1545 changeset 0:30d30fe6a5be: sub/large2 references missing $TESTTMP/d/.hg/largefiles/1deebade43c8c498a3c8daddac0244dc55d1331d (glob)
1546 changeset 1:ce8896473775: large1 references missing $TESTTMP/d/.hg/largefiles/5f78770c0e77ba4287ad6ef3071c9bf9c379742f (glob)
1546 changeset 1:ce8896473775: large1 references missing $TESTTMP/d/.hg/largefiles/5f78770c0e77ba4287ad6ef3071c9bf9c379742f (glob)
1547 changeset 1:ce8896473775: sub/large2 references corrupted $TESTTMP/d/.hg/largefiles/eb7338044dc27f9bc59b8dd5a246b065ead7a9c4 (glob)
1547 changeset 1:ce8896473775: sub/large2 references corrupted $TESTTMP/d/.hg/largefiles/eb7338044dc27f9bc59b8dd5a246b065ead7a9c4 (glob)
1548 changeset 3:9e8fbc4bce62: large1 references corrupted $TESTTMP/d/.hg/largefiles/eb7338044dc27f9bc59b8dd5a246b065ead7a9c4 (glob)
1548 changeset 3:9e8fbc4bce62: large1 references corrupted $TESTTMP/d/.hg/largefiles/eb7338044dc27f9bc59b8dd5a246b065ead7a9c4 (glob)
1549 changeset 4:74c02385b94c: large3 references corrupted $TESTTMP/d/.hg/largefiles/eb7338044dc27f9bc59b8dd5a246b065ead7a9c4 (glob)
1549 changeset 4:74c02385b94c: large3 references corrupted $TESTTMP/d/.hg/largefiles/eb7338044dc27f9bc59b8dd5a246b065ead7a9c4 (glob)
1550 changeset 4:74c02385b94c: sub/large4 references corrupted $TESTTMP/d/.hg/largefiles/eb7338044dc27f9bc59b8dd5a246b065ead7a9c4 (glob)
1550 changeset 4:74c02385b94c: sub/large4 references corrupted $TESTTMP/d/.hg/largefiles/eb7338044dc27f9bc59b8dd5a246b065ead7a9c4 (glob)
1551 changeset 5:9d5af5072dbd: large3 references missing $TESTTMP/d/.hg/largefiles/baaf12afde9d8d67f25dab6dced0d2bf77dba47c (glob)
1551 changeset 5:9d5af5072dbd: large3 references missing $TESTTMP/d/.hg/largefiles/baaf12afde9d8d67f25dab6dced0d2bf77dba47c (glob)
1552 changeset 5:9d5af5072dbd: sub/large4 references missing $TESTTMP/d/.hg/largefiles/aeb2210d19f02886dde00dac279729a48471e2f9 (glob)
1552 changeset 5:9d5af5072dbd: sub/large4 references missing $TESTTMP/d/.hg/largefiles/aeb2210d19f02886dde00dac279729a48471e2f9 (glob)
1553 changeset 6:4355d653f84f: large3 references missing $TESTTMP/d/.hg/largefiles/7838695e10da2bb75ac1156565f40a2595fa2fa0 (glob)
1553 changeset 6:4355d653f84f: large3 references missing $TESTTMP/d/.hg/largefiles/7838695e10da2bb75ac1156565f40a2595fa2fa0 (glob)
1554 [1]
1554 [1]
1555
1555
1556 - cleanup
1556 - cleanup
1557 $ rm $TESTTMP/d/.hg/largefiles/eb7338044dc27f9bc59b8dd5a246b065ead7a9c4
1557 $ rm $TESTTMP/d/.hg/largefiles/eb7338044dc27f9bc59b8dd5a246b065ead7a9c4
1558 $ rm -f .hglf/sub/*.orig
1558 $ rm -f .hglf/sub/*.orig
1559
1559
1560 Update to revision with missing largefile - and make sure it really is missing
1560 Update to revision with missing largefile - and make sure it really is missing
1561
1561
1562 $ rm ${USERCACHE}/7838695e10da2bb75ac1156565f40a2595fa2fa0
1562 $ rm ${USERCACHE}/7838695e10da2bb75ac1156565f40a2595fa2fa0
1563 $ hg up -r 6
1563 $ hg up -r 6
1564 getting changed largefiles
1564 getting changed largefiles
1565 large3: largefile 7838695e10da2bb75ac1156565f40a2595fa2fa0 not available from file:/*/$TESTTMP/d (glob)
1565 large3: largefile 7838695e10da2bb75ac1156565f40a2595fa2fa0 not available from file:/*/$TESTTMP/d (glob)
1566 1 largefiles updated, 2 removed
1566 1 largefiles updated, 2 removed
1567 4 files updated, 0 files merged, 2 files removed, 0 files unresolved
1567 4 files updated, 0 files merged, 2 files removed, 0 files unresolved
1568 $ rm normal3
1568 $ rm normal3
1569 $ echo >> sub/normal4
1569 $ echo >> sub/normal4
1570 $ hg ci -m 'commit with missing files'
1570 $ hg ci -m 'commit with missing files'
1571 Invoking status precommit hook
1571 Invoking status precommit hook
1572 M sub/normal4
1572 M sub/normal4
1573 ! large3
1573 ! large3
1574 ! normal3
1574 ! normal3
1575 created new head
1575 created new head
1576 $ hg st
1576 $ hg st
1577 ! large3
1577 ! large3
1578 ! normal3
1578 ! normal3
1579 $ hg up -r.
1579 $ hg up -r.
1580 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
1580 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
1581 $ hg st
1581 $ hg st
1582 ! large3
1582 ! large3
1583 ! normal3
1583 ! normal3
1584 $ hg up -Cr.
1584 $ hg up -Cr.
1585 getting changed largefiles
1585 getting changed largefiles
1586 large3: largefile 7838695e10da2bb75ac1156565f40a2595fa2fa0 not available from file:/*/$TESTTMP/d (glob)
1586 large3: largefile 7838695e10da2bb75ac1156565f40a2595fa2fa0 not available from file:/*/$TESTTMP/d (glob)
1587 0 largefiles updated, 0 removed
1587 0 largefiles updated, 0 removed
1588 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1588 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1589 $ hg st
1589 $ hg st
1590 ! large3
1590 ! large3
1591 $ hg rollback
1591 $ hg rollback
1592 repository tip rolled back to revision 9 (undo commit)
1592 repository tip rolled back to revision 9 (undo commit)
1593 working directory now based on revision 6
1593 working directory now based on revision 6
1594
1594
1595 Merge with revision with missing largefile - and make sure it tries to fetch it.
1595 Merge with revision with missing largefile - and make sure it tries to fetch it.
1596
1596
1597 $ hg up -Cqr null
1597 $ hg up -Cqr null
1598 $ echo f > f
1598 $ echo f > f
1599 $ hg ci -Am branch
1599 $ hg ci -Am branch
1600 adding f
1600 adding f
1601 Invoking status precommit hook
1601 Invoking status precommit hook
1602 A f
1602 A f
1603 created new head
1603 created new head
1604 $ hg merge -r 6
1604 $ hg merge -r 6
1605 getting changed largefiles
1605 getting changed largefiles
1606 large3: largefile 7838695e10da2bb75ac1156565f40a2595fa2fa0 not available from file:/*/$TESTTMP/d (glob)
1606 large3: largefile 7838695e10da2bb75ac1156565f40a2595fa2fa0 not available from file:/*/$TESTTMP/d (glob)
1607 1 largefiles updated, 0 removed
1607 1 largefiles updated, 0 removed
1608 4 files updated, 0 files merged, 0 files removed, 0 files unresolved
1608 4 files updated, 0 files merged, 0 files removed, 0 files unresolved
1609 (branch merge, don't forget to commit)
1609 (branch merge, don't forget to commit)
1610
1610
1611 $ hg rollback -q
1611 $ hg rollback -q
1612 $ hg up -Cq
1612 $ hg up -Cq
1613
1613
1614 Pulling 0 revisions with --all-largefiles should not fetch for all revisions
1614 Pulling 0 revisions with --all-largefiles should not fetch for all revisions
1615
1615
1616 $ hg pull --all-largefiles
1616 $ hg pull --all-largefiles
1617 pulling from $TESTTMP/d (glob)
1617 pulling from $TESTTMP/d (glob)
1618 searching for changes
1618 searching for changes
1619 no changes found
1619 no changes found
1620
1620
1621 Merging does not revert to old versions of largefiles and also check
1621 Merging does not revert to old versions of largefiles and also check
1622 that merging after having pulled from a non-default remote works
1622 that merging after having pulled from a non-default remote works
1623 correctly.
1623 correctly.
1624
1624
1625 $ cd ..
1625 $ cd ..
1626 $ hg clone -r 7 e temp
1626 $ hg clone -r 7 e temp
1627 adding changesets
1627 adding changesets
1628 adding manifests
1628 adding manifests
1629 adding file changes
1629 adding file changes
1630 added 8 changesets with 24 changes to 10 files
1630 added 8 changesets with 24 changes to 10 files
1631 updating to branch default
1631 updating to branch default
1632 getting changed largefiles
1632 getting changed largefiles
1633 3 largefiles updated, 0 removed
1633 3 largefiles updated, 0 removed
1634 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
1634 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
1635 $ hg clone temp f
1635 $ hg clone temp f
1636 updating to branch default
1636 updating to branch default
1637 getting changed largefiles
1637 getting changed largefiles
1638 3 largefiles updated, 0 removed
1638 3 largefiles updated, 0 removed
1639 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
1639 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
1640 # Delete the largefiles in the largefiles system cache so that we have an
1640 # Delete the largefiles in the largefiles system cache so that we have an
1641 # opportunity to test that caching after a pull works.
1641 # opportunity to test that caching after a pull works.
1642 $ rm "${USERCACHE}"/*
1642 $ rm "${USERCACHE}"/*
1643 $ cd f
1643 $ cd f
1644 $ echo "large4-merge-test" > sub/large4
1644 $ echo "large4-merge-test" > sub/large4
1645 $ hg commit -m "Modify large4 to test merge"
1645 $ hg commit -m "Modify large4 to test merge"
1646 Invoking status precommit hook
1646 Invoking status precommit hook
1647 M sub/large4
1647 M sub/large4
1648 # Test --cache-largefiles flag
1648 # Test --cache-largefiles flag
1649 $ hg pull --lfrev 'heads(pulled())' ../e
1649 $ hg pull --lfrev 'heads(pulled())' ../e
1650 pulling from ../e
1650 pulling from ../e
1651 searching for changes
1651 searching for changes
1652 adding changesets
1652 adding changesets
1653 adding manifests
1653 adding manifests
1654 adding file changes
1654 adding file changes
1655 added 2 changesets with 4 changes to 4 files (+1 heads)
1655 added 2 changesets with 4 changes to 4 files (+1 heads)
1656 (run 'hg heads' to see heads, 'hg merge' to merge)
1656 (run 'hg heads' to see heads, 'hg merge' to merge)
1657 2 largefiles cached
1657 2 largefiles cached
1658 $ hg merge
1658 $ hg merge
1659 largefile sub/large4 has a merge conflict
1659 largefile sub/large4 has a merge conflict
1660 ancestor was 971fb41e78fea4f8e0ba5244784239371cb00591
1660 ancestor was 971fb41e78fea4f8e0ba5244784239371cb00591
1661 keep (l)ocal d846f26643bfa8ec210be40cc93cc6b7ff1128ea or
1661 keep (l)ocal d846f26643bfa8ec210be40cc93cc6b7ff1128ea or
1662 take (o)ther e166e74c7303192238d60af5a9c4ce9bef0b7928? l
1662 take (o)ther e166e74c7303192238d60af5a9c4ce9bef0b7928? l
1663 getting changed largefiles
1663 getting changed largefiles
1664 1 largefiles updated, 0 removed
1664 1 largefiles updated, 0 removed
1665 3 files updated, 1 files merged, 0 files removed, 0 files unresolved
1665 3 files updated, 1 files merged, 0 files removed, 0 files unresolved
1666 (branch merge, don't forget to commit)
1666 (branch merge, don't forget to commit)
1667 $ hg commit -m "Merge repos e and f"
1667 $ hg commit -m "Merge repos e and f"
1668 Invoking status precommit hook
1668 Invoking status precommit hook
1669 M normal3
1669 M normal3
1670 M sub/normal4
1670 M sub/normal4
1671 M sub2/large6
1671 M sub2/large6
1672 $ cat normal3
1672 $ cat normal3
1673 normal3-modified
1673 normal3-modified
1674 $ cat sub/normal4
1674 $ cat sub/normal4
1675 normal4-modified
1675 normal4-modified
1676 $ cat sub/large4
1676 $ cat sub/large4
1677 large4-merge-test
1677 large4-merge-test
1678 $ cat sub2/large6
1678 $ cat sub2/large6
1679 large6-modified
1679 large6-modified
1680 $ cat sub2/large7
1680 $ cat sub2/large7
1681 large7
1681 large7
1682
1682
1683 Test status after merging with a branch that introduces a new largefile:
1683 Test status after merging with a branch that introduces a new largefile:
1684
1684
1685 $ echo large > large
1685 $ echo large > large
1686 $ hg add --large large
1686 $ hg add --large large
1687 $ hg commit -m 'add largefile'
1687 $ hg commit -m 'add largefile'
1688 Invoking status precommit hook
1688 Invoking status precommit hook
1689 A large
1689 A large
1690 $ hg update -q ".^"
1690 $ hg update -q ".^"
1691 $ echo change >> normal3
1691 $ echo change >> normal3
1692 $ hg commit -m 'some change'
1692 $ hg commit -m 'some change'
1693 Invoking status precommit hook
1693 Invoking status precommit hook
1694 M normal3
1694 M normal3
1695 created new head
1695 created new head
1696 $ hg merge
1696 $ hg merge
1697 getting changed largefiles
1697 getting changed largefiles
1698 1 largefiles updated, 0 removed
1698 1 largefiles updated, 0 removed
1699 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1699 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1700 (branch merge, don't forget to commit)
1700 (branch merge, don't forget to commit)
1701 $ hg status
1701 $ hg status
1702 M large
1702 M large
1703
1703
1704 - make sure update of merge with removed largefiles fails as expected
1704 - make sure update of merge with removed largefiles fails as expected
1705 $ hg rm sub2/large6
1705 $ hg rm sub2/large6
1706 $ hg up -r.
1706 $ hg up -r.
1707 abort: outstanding uncommitted merge
1707 abort: outstanding uncommitted merge
1708 [255]
1708 [255]
1709
1709
1710 - revert should be able to revert files introduced in a pending merge
1710 - revert should be able to revert files introduced in a pending merge
1711 $ hg revert --all -r .
1711 $ hg revert --all -r .
1712 removing .hglf/large (glob)
1712 removing .hglf/large (glob)
1713 undeleting .hglf/sub2/large6 (glob)
1713 undeleting .hglf/sub2/large6 (glob)
1714
1714
1715 Test that a normal file and a largefile with the same name and path cannot
1715 Test that a normal file and a largefile with the same name and path cannot
1716 coexist.
1716 coexist.
1717
1717
1718 $ rm sub2/large7
1718 $ rm sub2/large7
1719 $ echo "largeasnormal" > sub2/large7
1719 $ echo "largeasnormal" > sub2/large7
1720 $ hg add sub2/large7
1720 $ hg add sub2/large7
1721 sub2/large7 already a largefile
1721 sub2/large7 already a largefile
1722
1722
1723 Test that transplanting a largefile change works correctly.
1723 Test that transplanting a largefile change works correctly.
1724
1724
1725 $ cd ..
1725 $ cd ..
1726 $ hg clone -r 8 d g
1726 $ hg clone -r 8 d g
1727 adding changesets
1727 adding changesets
1728 adding manifests
1728 adding manifests
1729 adding file changes
1729 adding file changes
1730 added 9 changesets with 26 changes to 10 files
1730 added 9 changesets with 26 changes to 10 files
1731 updating to branch default
1731 updating to branch default
1732 getting changed largefiles
1732 getting changed largefiles
1733 3 largefiles updated, 0 removed
1733 3 largefiles updated, 0 removed
1734 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
1734 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
1735 $ cd g
1735 $ cd g
1736 $ hg transplant -s ../d 598410d3eb9a
1736 $ hg transplant -s ../d 598410d3eb9a
1737 searching for changes
1737 searching for changes
1738 searching for changes
1738 searching for changes
1739 adding changesets
1739 adding changesets
1740 adding manifests
1740 adding manifests
1741 adding file changes
1741 adding file changes
1742 added 1 changesets with 2 changes to 2 files
1742 added 1 changesets with 2 changes to 2 files
1743 getting changed largefiles
1744 0 largefiles updated, 0 removed
1745 $ hg log --template '{rev}:{node|short} {desc|firstline}\n'
1743 $ hg log --template '{rev}:{node|short} {desc|firstline}\n'
1746 9:598410d3eb9a modify normal file largefile in repo d
1744 9:598410d3eb9a modify normal file largefile in repo d
1747 8:a381d2c8c80e modify normal file and largefile in repo b
1745 8:a381d2c8c80e modify normal file and largefile in repo b
1748 7:daea875e9014 add/edit more largefiles
1746 7:daea875e9014 add/edit more largefiles
1749 6:4355d653f84f edit files yet again
1747 6:4355d653f84f edit files yet again
1750 5:9d5af5072dbd edit files again
1748 5:9d5af5072dbd edit files again
1751 4:74c02385b94c move files
1749 4:74c02385b94c move files
1752 3:9e8fbc4bce62 copy files
1750 3:9e8fbc4bce62 copy files
1753 2:51a0ae4d5864 remove files
1751 2:51a0ae4d5864 remove files
1754 1:ce8896473775 edit files
1752 1:ce8896473775 edit files
1755 0:30d30fe6a5be add files
1753 0:30d30fe6a5be add files
1756 $ cat normal3
1754 $ cat normal3
1757 normal3-modified
1755 normal3-modified
1758 $ cat sub/normal4
1756 $ cat sub/normal4
1759 normal4-modified
1757 normal4-modified
1760 $ cat sub/large4
1758 $ cat sub/large4
1761 large4-modified
1759 large4-modified
1762 $ cat sub2/large6
1760 $ cat sub2/large6
1763 large6-modified
1761 large6-modified
1764 $ cat sub2/large7
1762 $ cat sub2/large7
1765 large7
1763 large7
1766
1764
1767 Cat a largefile
1765 Cat a largefile
1768 $ hg cat normal3
1766 $ hg cat normal3
1769 normal3-modified
1767 normal3-modified
1770 $ hg cat sub/large4
1768 $ hg cat sub/large4
1771 large4-modified
1769 large4-modified
1772 $ rm "${USERCACHE}"/*
1770 $ rm "${USERCACHE}"/*
1773 $ hg cat -r a381d2c8c80e -o cat.out sub/large4
1771 $ hg cat -r a381d2c8c80e -o cat.out sub/large4
1774 $ cat cat.out
1772 $ cat cat.out
1775 large4-modified
1773 large4-modified
1776 $ rm cat.out
1774 $ rm cat.out
1777 $ hg cat -r a381d2c8c80e normal3
1775 $ hg cat -r a381d2c8c80e normal3
1778 normal3-modified
1776 normal3-modified
1779 $ hg cat -r '.^' normal3
1777 $ hg cat -r '.^' normal3
1780 normal3-modified
1778 normal3-modified
1781 $ hg cat -r '.^' sub/large4 doesntexist
1779 $ hg cat -r '.^' sub/large4 doesntexist
1782 large4-modified
1780 large4-modified
1783 doesntexist: no such file in rev a381d2c8c80e
1781 doesntexist: no such file in rev a381d2c8c80e
1784 $ hg --cwd sub cat -r '.^' large4
1782 $ hg --cwd sub cat -r '.^' large4
1785 large4-modified
1783 large4-modified
1786 $ hg --cwd sub cat -r '.^' ../normal3
1784 $ hg --cwd sub cat -r '.^' ../normal3
1787 normal3-modified
1785 normal3-modified
1788 Cat a standin
1786 Cat a standin
1789 $ hg cat .hglf/sub/large4
1787 $ hg cat .hglf/sub/large4
1790 e166e74c7303192238d60af5a9c4ce9bef0b7928
1788 e166e74c7303192238d60af5a9c4ce9bef0b7928
1791 $ hg cat .hglf/normal3
1789 $ hg cat .hglf/normal3
1792 .hglf/normal3: no such file in rev 598410d3eb9a
1790 .hglf/normal3: no such file in rev 598410d3eb9a
1793 [1]
1791 [1]
1794
1792
1795 Test that renaming a largefile results in correct output for status
1793 Test that renaming a largefile results in correct output for status
1796
1794
1797 $ hg rename sub/large4 large4-renamed
1795 $ hg rename sub/large4 large4-renamed
1798 $ hg commit -m "test rename output"
1796 $ hg commit -m "test rename output"
1799 Invoking status precommit hook
1797 Invoking status precommit hook
1800 A large4-renamed
1798 A large4-renamed
1801 R sub/large4
1799 R sub/large4
1802 $ cat large4-renamed
1800 $ cat large4-renamed
1803 large4-modified
1801 large4-modified
1804 $ cd sub2
1802 $ cd sub2
1805 $ hg rename large6 large6-renamed
1803 $ hg rename large6 large6-renamed
1806 $ hg st
1804 $ hg st
1807 A sub2/large6-renamed
1805 A sub2/large6-renamed
1808 R sub2/large6
1806 R sub2/large6
1809 $ cd ..
1807 $ cd ..
1810
1808
1811 Test --normal flag
1809 Test --normal flag
1812
1810
1813 $ dd if=/dev/zero bs=2k count=11k > new-largefile 2> /dev/null
1811 $ dd if=/dev/zero bs=2k count=11k > new-largefile 2> /dev/null
1814 $ hg add --normal --large new-largefile
1812 $ hg add --normal --large new-largefile
1815 abort: --normal cannot be used with --large
1813 abort: --normal cannot be used with --large
1816 [255]
1814 [255]
1817 $ hg add --normal new-largefile
1815 $ hg add --normal new-largefile
1818 new-largefile: up to 69 MB of RAM may be required to manage this file
1816 new-largefile: up to 69 MB of RAM may be required to manage this file
1819 (use 'hg revert new-largefile' to cancel the pending addition)
1817 (use 'hg revert new-largefile' to cancel the pending addition)
1820 $ cd ..
1818 $ cd ..
1821
1819
1822
1820
1823
1821
General Comments 0
You need to be logged in to leave comments. Login now