##// END OF EJS Templates
largefiles: show progress when checking standin hashes in outgoing changesets...
Mads Kiilerich -
r23892:f2b6f37d default
parent child Browse files
Show More
@@ -1,583 +1,586 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 else:
207 else:
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()"
395 # ATTENTION: "ctx.files()" may differ from "repo[node].files()"
396 # because files coming from the 2nd parent are omitted in the latter.
396 # because files coming from the 2nd parent are omitted in the latter.
397 #
397 #
398 # The former should be used to get targets of "synclfdirstate",
398 # The former should be used to get targets of "synclfdirstate",
399 # because such files:
399 # because such files:
400 # - are marked as "a" by "patch.patch()" (e.g. via transplant), and
400 # - are marked as "a" by "patch.patch()" (e.g. via transplant), and
401 # - have to be marked as "n" after commit, but
401 # - have to be marked as "n" after commit, but
402 # - aren't listed in "repo[node].files()"
402 # - aren't listed in "repo[node].files()"
403
403
404 lfdirstate = openlfdirstate(repo.ui, repo)
404 lfdirstate = openlfdirstate(repo.ui, repo)
405 for f in ctx.files():
405 for f in ctx.files():
406 if isstandin(f):
406 if isstandin(f):
407 lfile = splitstandin(f)
407 lfile = splitstandin(f)
408 synclfdirstate(repo, lfdirstate, lfile, False)
408 synclfdirstate(repo, lfdirstate, lfile, False)
409 lfdirstate.write()
409 lfdirstate.write()
410
410
411 # As part of committing, copy all of the largefiles into the cache.
411 # As part of committing, copy all of the largefiles into the cache.
412 copyalltostore(repo, node)
412 copyalltostore(repo, node)
413
413
414 def getlfilestoupdate(oldstandins, newstandins):
414 def getlfilestoupdate(oldstandins, newstandins):
415 changedstandins = set(oldstandins).symmetric_difference(set(newstandins))
415 changedstandins = set(oldstandins).symmetric_difference(set(newstandins))
416 filelist = []
416 filelist = []
417 for f in changedstandins:
417 for f in changedstandins:
418 if f[0] not in filelist:
418 if f[0] not in filelist:
419 filelist.append(f[0])
419 filelist.append(f[0])
420 return filelist
420 return filelist
421
421
422 def getlfilestoupload(repo, missing, addfunc):
422 def getlfilestoupload(repo, missing, addfunc):
423 for n in missing:
423 for i, n in enumerate(missing):
424 repo.ui.progress(_('finding outgoing largefiles'), i,
425 unit=_('revision'), total=len(missing))
424 parents = [p for p in repo.changelog.parents(n) if p != node.nullid]
426 parents = [p for p in repo.changelog.parents(n) if p != node.nullid]
425
427
426 oldlfstatus = repo.lfstatus
428 oldlfstatus = repo.lfstatus
427 repo.lfstatus = False
429 repo.lfstatus = False
428 try:
430 try:
429 ctx = repo[n]
431 ctx = repo[n]
430 finally:
432 finally:
431 repo.lfstatus = oldlfstatus
433 repo.lfstatus = oldlfstatus
432
434
433 files = set(ctx.files())
435 files = set(ctx.files())
434 if len(parents) == 2:
436 if len(parents) == 2:
435 mc = ctx.manifest()
437 mc = ctx.manifest()
436 mp1 = ctx.parents()[0].manifest()
438 mp1 = ctx.parents()[0].manifest()
437 mp2 = ctx.parents()[1].manifest()
439 mp2 = ctx.parents()[1].manifest()
438 for f in mp1:
440 for f in mp1:
439 if f not in mc:
441 if f not in mc:
440 files.add(f)
442 files.add(f)
441 for f in mp2:
443 for f in mp2:
442 if f not in mc:
444 if f not in mc:
443 files.add(f)
445 files.add(f)
444 for f in mc:
446 for f in mc:
445 if mc[f] != mp1.get(f, None) or mc[f] != mp2.get(f, None):
447 if mc[f] != mp1.get(f, None) or mc[f] != mp2.get(f, None):
446 files.add(f)
448 files.add(f)
447 for fn in files:
449 for fn in files:
448 if isstandin(fn) and fn in ctx:
450 if isstandin(fn) and fn in ctx:
449 addfunc(fn, ctx[fn].data().strip())
451 addfunc(fn, ctx[fn].data().strip())
452 repo.ui.progress(_('finding outgoing largefiles'), None)
450
453
451 def updatestandinsbymatch(repo, match):
454 def updatestandinsbymatch(repo, match):
452 '''Update standins in the working directory according to specified match
455 '''Update standins in the working directory according to specified match
453
456
454 This returns (possibly modified) ``match`` object to be used for
457 This returns (possibly modified) ``match`` object to be used for
455 subsequent commit process.
458 subsequent commit process.
456 '''
459 '''
457
460
458 ui = repo.ui
461 ui = repo.ui
459
462
460 # Case 1: user calls commit with no specific files or
463 # Case 1: user calls commit with no specific files or
461 # include/exclude patterns: refresh and commit all files that
464 # include/exclude patterns: refresh and commit all files that
462 # are "dirty".
465 # are "dirty".
463 if match is None or match.always():
466 if match is None or match.always():
464 # Spend a bit of time here to get a list of files we know
467 # Spend a bit of time here to get a list of files we know
465 # are modified so we can compare only against those.
468 # are modified so we can compare only against those.
466 # It can cost a lot of time (several seconds)
469 # It can cost a lot of time (several seconds)
467 # otherwise to update all standins if the largefiles are
470 # otherwise to update all standins if the largefiles are
468 # large.
471 # large.
469 lfdirstate = openlfdirstate(ui, repo)
472 lfdirstate = openlfdirstate(ui, repo)
470 dirtymatch = match_.always(repo.root, repo.getcwd())
473 dirtymatch = match_.always(repo.root, repo.getcwd())
471 unsure, s = lfdirstate.status(dirtymatch, [], False, False,
474 unsure, s = lfdirstate.status(dirtymatch, [], False, False,
472 False)
475 False)
473 modifiedfiles = unsure + s.modified + s.added + s.removed
476 modifiedfiles = unsure + s.modified + s.added + s.removed
474 lfiles = listlfiles(repo)
477 lfiles = listlfiles(repo)
475 # this only loops through largefiles that exist (not
478 # this only loops through largefiles that exist (not
476 # removed/renamed)
479 # removed/renamed)
477 for lfile in lfiles:
480 for lfile in lfiles:
478 if lfile in modifiedfiles:
481 if lfile in modifiedfiles:
479 if os.path.exists(
482 if os.path.exists(
480 repo.wjoin(standin(lfile))):
483 repo.wjoin(standin(lfile))):
481 # this handles the case where a rebase is being
484 # this handles the case where a rebase is being
482 # performed and the working copy is not updated
485 # performed and the working copy is not updated
483 # yet.
486 # yet.
484 if os.path.exists(repo.wjoin(lfile)):
487 if os.path.exists(repo.wjoin(lfile)):
485 updatestandin(repo,
488 updatestandin(repo,
486 standin(lfile))
489 standin(lfile))
487
490
488 return match
491 return match
489
492
490 lfiles = listlfiles(repo)
493 lfiles = listlfiles(repo)
491 match._files = repo._subdirlfs(match.files(), lfiles)
494 match._files = repo._subdirlfs(match.files(), lfiles)
492
495
493 # Case 2: user calls commit with specified patterns: refresh
496 # Case 2: user calls commit with specified patterns: refresh
494 # any matching big files.
497 # any matching big files.
495 smatcher = composestandinmatcher(repo, match)
498 smatcher = composestandinmatcher(repo, match)
496 standins = repo.dirstate.walk(smatcher, [], False, False)
499 standins = repo.dirstate.walk(smatcher, [], False, False)
497
500
498 # No matching big files: get out of the way and pass control to
501 # No matching big files: get out of the way and pass control to
499 # the usual commit() method.
502 # the usual commit() method.
500 if not standins:
503 if not standins:
501 return match
504 return match
502
505
503 # Refresh all matching big files. It's possible that the
506 # Refresh all matching big files. It's possible that the
504 # commit will end up failing, in which case the big files will
507 # commit will end up failing, in which case the big files will
505 # stay refreshed. No harm done: the user modified them and
508 # stay refreshed. No harm done: the user modified them and
506 # asked to commit them, so sooner or later we're going to
509 # asked to commit them, so sooner or later we're going to
507 # refresh the standins. Might as well leave them refreshed.
510 # refresh the standins. Might as well leave them refreshed.
508 lfdirstate = openlfdirstate(ui, repo)
511 lfdirstate = openlfdirstate(ui, repo)
509 for fstandin in standins:
512 for fstandin in standins:
510 lfile = splitstandin(fstandin)
513 lfile = splitstandin(fstandin)
511 if lfdirstate[lfile] != 'r':
514 if lfdirstate[lfile] != 'r':
512 updatestandin(repo, fstandin)
515 updatestandin(repo, fstandin)
513
516
514 # Cook up a new matcher that only matches regular files or
517 # Cook up a new matcher that only matches regular files or
515 # standins corresponding to the big files requested by the
518 # standins corresponding to the big files requested by the
516 # user. Have to modify _files to prevent commit() from
519 # user. Have to modify _files to prevent commit() from
517 # complaining "not tracked" for big files.
520 # complaining "not tracked" for big files.
518 match = copy.copy(match)
521 match = copy.copy(match)
519 origmatchfn = match.matchfn
522 origmatchfn = match.matchfn
520
523
521 # Check both the list of largefiles and the list of
524 # Check both the list of largefiles and the list of
522 # standins because if a largefile was removed, it
525 # standins because if a largefile was removed, it
523 # won't be in the list of largefiles at this point
526 # won't be in the list of largefiles at this point
524 match._files += sorted(standins)
527 match._files += sorted(standins)
525
528
526 actualfiles = []
529 actualfiles = []
527 for f in match._files:
530 for f in match._files:
528 fstandin = standin(f)
531 fstandin = standin(f)
529
532
530 # ignore known largefiles and standins
533 # ignore known largefiles and standins
531 if f in lfiles or fstandin in standins:
534 if f in lfiles or fstandin in standins:
532 continue
535 continue
533
536
534 actualfiles.append(f)
537 actualfiles.append(f)
535 match._files = actualfiles
538 match._files = actualfiles
536
539
537 def matchfn(f):
540 def matchfn(f):
538 if origmatchfn(f):
541 if origmatchfn(f):
539 return f not in lfiles
542 return f not in lfiles
540 else:
543 else:
541 return f in standins
544 return f in standins
542
545
543 match.matchfn = matchfn
546 match.matchfn = matchfn
544
547
545 return match
548 return match
546
549
547 class automatedcommithook(object):
550 class automatedcommithook(object):
548 '''Stateful hook to update standins at the 1st commit of resuming
551 '''Stateful hook to update standins at the 1st commit of resuming
549
552
550 For efficiency, updating standins in the working directory should
553 For efficiency, updating standins in the working directory should
551 be avoided while automated committing (like rebase, transplant and
554 be avoided while automated committing (like rebase, transplant and
552 so on), because they should be updated before committing.
555 so on), because they should be updated before committing.
553
556
554 But the 1st commit of resuming automated committing (e.g. ``rebase
557 But the 1st commit of resuming automated committing (e.g. ``rebase
555 --continue``) should update them, because largefiles may be
558 --continue``) should update them, because largefiles may be
556 modified manually.
559 modified manually.
557 '''
560 '''
558 def __init__(self, resuming):
561 def __init__(self, resuming):
559 self.resuming = resuming
562 self.resuming = resuming
560
563
561 def __call__(self, repo, match):
564 def __call__(self, repo, match):
562 if self.resuming:
565 if self.resuming:
563 self.resuming = False # avoids updating at subsequent commits
566 self.resuming = False # avoids updating at subsequent commits
564 return updatestandinsbymatch(repo, match)
567 return updatestandinsbymatch(repo, match)
565 else:
568 else:
566 return match
569 return match
567
570
568 def getstatuswriter(ui, repo, forcibly=None):
571 def getstatuswriter(ui, repo, forcibly=None):
569 '''Return the function to write largefiles specific status out
572 '''Return the function to write largefiles specific status out
570
573
571 If ``forcibly`` is ``None``, this returns the last element of
574 If ``forcibly`` is ``None``, this returns the last element of
572 ``repo._lfstatuswriters`` as "default" writer function.
575 ``repo._lfstatuswriters`` as "default" writer function.
573
576
574 Otherwise, this returns the function to always write out (or
577 Otherwise, this returns the function to always write out (or
575 ignore if ``not forcibly``) status.
578 ignore if ``not forcibly``) status.
576 '''
579 '''
577 if forcibly is None:
580 if forcibly is None:
578 return repo._lfstatuswriters[-1]
581 return repo._lfstatuswriters[-1]
579 else:
582 else:
580 if forcibly:
583 if forcibly:
581 return ui.status # forcibly WRITE OUT
584 return ui.status # forcibly WRITE OUT
582 else:
585 else:
583 return lambda *msg, **opts: None # forcibly IGNORE
586 return lambda *msg, **opts: None # forcibly IGNORE
@@ -1,931 +1,942 b''
1 This file contains testcases that tend to be related to special cases or less
1 This file contains testcases that tend to be related to special cases or less
2 common commands affecting largefile.
2 common commands affecting largefile.
3
3
4 Each sections should be independent of each others.
4 Each sections should be independent of each others.
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
24
25
25
26 Test copies and moves from a directory other than root (issue3516)
26 Test copies and moves from a directory other than root (issue3516)
27 =========================================================================
27 =========================================================================
28
28
29 $ hg init lf_cpmv
29 $ hg init lf_cpmv
30 $ cd lf_cpmv
30 $ cd lf_cpmv
31 $ mkdir dira
31 $ mkdir dira
32 $ mkdir dira/dirb
32 $ mkdir dira/dirb
33 $ touch dira/dirb/largefile
33 $ touch dira/dirb/largefile
34 $ hg add --large dira/dirb/largefile
34 $ hg add --large dira/dirb/largefile
35 $ hg commit -m "added"
35 $ hg commit -m "added"
36 Invoking status precommit hook
36 Invoking status precommit hook
37 A dira/dirb/largefile
37 A dira/dirb/largefile
38 $ cd dira
38 $ cd dira
39 $ hg cp dirb/largefile foo/largefile
39 $ hg cp dirb/largefile foo/largefile
40 $ hg ci -m "deep copy"
40 $ hg ci -m "deep copy"
41 Invoking status precommit hook
41 Invoking status precommit hook
42 A dira/foo/largefile
42 A dira/foo/largefile
43 $ find . | sort
43 $ find . | sort
44 .
44 .
45 ./dirb
45 ./dirb
46 ./dirb/largefile
46 ./dirb/largefile
47 ./foo
47 ./foo
48 ./foo/largefile
48 ./foo/largefile
49 $ hg mv foo/largefile baz/largefile
49 $ hg mv foo/largefile baz/largefile
50 $ hg ci -m "moved"
50 $ hg ci -m "moved"
51 Invoking status precommit hook
51 Invoking status precommit hook
52 A dira/baz/largefile
52 A dira/baz/largefile
53 R dira/foo/largefile
53 R dira/foo/largefile
54 $ find . | sort
54 $ find . | sort
55 .
55 .
56 ./baz
56 ./baz
57 ./baz/largefile
57 ./baz/largefile
58 ./dirb
58 ./dirb
59 ./dirb/largefile
59 ./dirb/largefile
60 $ cd ..
60 $ cd ..
61 $ hg mv dira dirc
61 $ hg mv dira dirc
62 moving .hglf/dira/baz/largefile to .hglf/dirc/baz/largefile (glob)
62 moving .hglf/dira/baz/largefile to .hglf/dirc/baz/largefile (glob)
63 moving .hglf/dira/dirb/largefile to .hglf/dirc/dirb/largefile (glob)
63 moving .hglf/dira/dirb/largefile to .hglf/dirc/dirb/largefile (glob)
64 $ find * | sort
64 $ find * | sort
65 dirc
65 dirc
66 dirc/baz
66 dirc/baz
67 dirc/baz/largefile
67 dirc/baz/largefile
68 dirc/dirb
68 dirc/dirb
69 dirc/dirb/largefile
69 dirc/dirb/largefile
70
70
71 $ hg clone -q . ../fetch
71 $ hg clone -q . ../fetch
72 $ hg --config extensions.fetch= fetch ../fetch
72 $ hg --config extensions.fetch= fetch ../fetch
73 abort: uncommitted changes
73 abort: uncommitted changes
74 [255]
74 [255]
75 $ hg up -qC
75 $ hg up -qC
76 $ cd ..
76 $ cd ..
77
77
78 Clone a local repository owned by another user
78 Clone a local repository owned by another user
79 ===================================================
79 ===================================================
80
80
81 #if unix-permissions
81 #if unix-permissions
82
82
83 We have to simulate that here by setting $HOME and removing write permissions
83 We have to simulate that here by setting $HOME and removing write permissions
84 $ ORIGHOME="$HOME"
84 $ ORIGHOME="$HOME"
85 $ mkdir alice
85 $ mkdir alice
86 $ HOME="`pwd`/alice"
86 $ HOME="`pwd`/alice"
87 $ cd alice
87 $ cd alice
88 $ hg init pubrepo
88 $ hg init pubrepo
89 $ cd pubrepo
89 $ cd pubrepo
90 $ dd if=/dev/zero bs=1k count=11k > a-large-file 2> /dev/null
90 $ dd if=/dev/zero bs=1k count=11k > a-large-file 2> /dev/null
91 $ hg add --large a-large-file
91 $ hg add --large a-large-file
92 $ hg commit -m "Add a large file"
92 $ hg commit -m "Add a large file"
93 Invoking status precommit hook
93 Invoking status precommit hook
94 A a-large-file
94 A a-large-file
95 $ cd ..
95 $ cd ..
96 $ chmod -R a-w pubrepo
96 $ chmod -R a-w pubrepo
97 $ cd ..
97 $ cd ..
98 $ mkdir bob
98 $ mkdir bob
99 $ HOME="`pwd`/bob"
99 $ HOME="`pwd`/bob"
100 $ cd bob
100 $ cd bob
101 $ hg clone --pull ../alice/pubrepo pubrepo
101 $ hg clone --pull ../alice/pubrepo pubrepo
102 requesting all changes
102 requesting all changes
103 adding changesets
103 adding changesets
104 adding manifests
104 adding manifests
105 adding file changes
105 adding file changes
106 added 1 changesets with 1 changes to 1 files
106 added 1 changesets with 1 changes to 1 files
107 updating to branch default
107 updating to branch default
108 getting changed largefiles
108 getting changed largefiles
109 1 largefiles updated, 0 removed
109 1 largefiles updated, 0 removed
110 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
110 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
111 $ cd ..
111 $ cd ..
112 $ chmod -R u+w alice/pubrepo
112 $ chmod -R u+w alice/pubrepo
113 $ HOME="$ORIGHOME"
113 $ HOME="$ORIGHOME"
114
114
115 #endif
115 #endif
116
116
117
117
118 Symlink to a large largefile should behave the same as a symlink to a normal file
118 Symlink to a large largefile should behave the same as a symlink to a normal file
119 =====================================================================================
119 =====================================================================================
120
120
121 #if symlink
121 #if symlink
122
122
123 $ hg init largesymlink
123 $ hg init largesymlink
124 $ cd largesymlink
124 $ cd largesymlink
125 $ dd if=/dev/zero bs=1k count=10k of=largefile 2>/dev/null
125 $ dd if=/dev/zero bs=1k count=10k of=largefile 2>/dev/null
126 $ hg add --large largefile
126 $ hg add --large largefile
127 $ hg commit -m "commit a large file"
127 $ hg commit -m "commit a large file"
128 Invoking status precommit hook
128 Invoking status precommit hook
129 A largefile
129 A largefile
130 $ ln -s largefile largelink
130 $ ln -s largefile largelink
131 $ hg add largelink
131 $ hg add largelink
132 $ hg commit -m "commit a large symlink"
132 $ hg commit -m "commit a large symlink"
133 Invoking status precommit hook
133 Invoking status precommit hook
134 A largelink
134 A largelink
135 $ rm -f largelink
135 $ rm -f largelink
136 $ hg up >/dev/null
136 $ hg up >/dev/null
137 $ test -f largelink
137 $ test -f largelink
138 [1]
138 [1]
139 $ test -L largelink
139 $ test -L largelink
140 [1]
140 [1]
141 $ rm -f largelink # make next part of the test independent of the previous
141 $ rm -f largelink # make next part of the test independent of the previous
142 $ hg up -C >/dev/null
142 $ hg up -C >/dev/null
143 $ test -f largelink
143 $ test -f largelink
144 $ test -L largelink
144 $ test -L largelink
145 $ cd ..
145 $ cd ..
146
146
147 #endif
147 #endif
148
148
149
149
150 test for pattern matching on 'hg status':
150 test for pattern matching on 'hg status':
151 ==============================================
151 ==============================================
152
152
153
153
154 to boost performance, largefiles checks whether specified patterns are
154 to boost performance, largefiles checks whether specified patterns are
155 related to largefiles in working directory (NOT to STANDIN) or not.
155 related to largefiles in working directory (NOT to STANDIN) or not.
156
156
157 $ hg init statusmatch
157 $ hg init statusmatch
158 $ cd statusmatch
158 $ cd statusmatch
159
159
160 $ mkdir -p a/b/c/d
160 $ mkdir -p a/b/c/d
161 $ echo normal > a/b/c/d/e.normal.txt
161 $ echo normal > a/b/c/d/e.normal.txt
162 $ hg add a/b/c/d/e.normal.txt
162 $ hg add a/b/c/d/e.normal.txt
163 $ echo large > a/b/c/d/e.large.txt
163 $ echo large > a/b/c/d/e.large.txt
164 $ hg add --large a/b/c/d/e.large.txt
164 $ hg add --large a/b/c/d/e.large.txt
165 $ mkdir -p a/b/c/x
165 $ mkdir -p a/b/c/x
166 $ echo normal > a/b/c/x/y.normal.txt
166 $ echo normal > a/b/c/x/y.normal.txt
167 $ hg add a/b/c/x/y.normal.txt
167 $ hg add a/b/c/x/y.normal.txt
168 $ hg commit -m 'add files'
168 $ hg commit -m 'add files'
169 Invoking status precommit hook
169 Invoking status precommit hook
170 A a/b/c/d/e.large.txt
170 A a/b/c/d/e.large.txt
171 A a/b/c/d/e.normal.txt
171 A a/b/c/d/e.normal.txt
172 A a/b/c/x/y.normal.txt
172 A a/b/c/x/y.normal.txt
173
173
174 (1) no pattern: no performance boost
174 (1) no pattern: no performance boost
175 $ hg status -A
175 $ hg status -A
176 C a/b/c/d/e.large.txt
176 C a/b/c/d/e.large.txt
177 C a/b/c/d/e.normal.txt
177 C a/b/c/d/e.normal.txt
178 C a/b/c/x/y.normal.txt
178 C a/b/c/x/y.normal.txt
179
179
180 (2) pattern not related to largefiles: performance boost
180 (2) pattern not related to largefiles: performance boost
181 $ hg status -A a/b/c/x
181 $ hg status -A a/b/c/x
182 C a/b/c/x/y.normal.txt
182 C a/b/c/x/y.normal.txt
183
183
184 (3) pattern related to largefiles: no performance boost
184 (3) pattern related to largefiles: no performance boost
185 $ hg status -A a/b/c/d
185 $ hg status -A a/b/c/d
186 C a/b/c/d/e.large.txt
186 C a/b/c/d/e.large.txt
187 C a/b/c/d/e.normal.txt
187 C a/b/c/d/e.normal.txt
188
188
189 (4) pattern related to STANDIN (not to largefiles): performance boost
189 (4) pattern related to STANDIN (not to largefiles): performance boost
190 $ hg status -A .hglf/a
190 $ hg status -A .hglf/a
191 C .hglf/a/b/c/d/e.large.txt
191 C .hglf/a/b/c/d/e.large.txt
192
192
193 (5) mixed case: no performance boost
193 (5) mixed case: no performance boost
194 $ hg status -A a/b/c/x a/b/c/d
194 $ hg status -A a/b/c/x a/b/c/d
195 C a/b/c/d/e.large.txt
195 C a/b/c/d/e.large.txt
196 C a/b/c/d/e.normal.txt
196 C a/b/c/d/e.normal.txt
197 C a/b/c/x/y.normal.txt
197 C a/b/c/x/y.normal.txt
198
198
199 verify that largefiles doesn't break filesets
199 verify that largefiles doesn't break filesets
200
200
201 $ hg log --rev . --exclude "set:binary()"
201 $ hg log --rev . --exclude "set:binary()"
202 changeset: 0:41bd42f10efa
202 changeset: 0:41bd42f10efa
203 tag: tip
203 tag: tip
204 user: test
204 user: test
205 date: Thu Jan 01 00:00:00 1970 +0000
205 date: Thu Jan 01 00:00:00 1970 +0000
206 summary: add files
206 summary: add files
207
207
208 verify that large files in subrepos handled properly
208 verify that large files in subrepos handled properly
209 $ hg init subrepo
209 $ hg init subrepo
210 $ echo "subrepo = subrepo" > .hgsub
210 $ echo "subrepo = subrepo" > .hgsub
211 $ hg add .hgsub
211 $ hg add .hgsub
212 $ hg ci -m "add subrepo"
212 $ hg ci -m "add subrepo"
213 Invoking status precommit hook
213 Invoking status precommit hook
214 A .hgsub
214 A .hgsub
215 ? .hgsubstate
215 ? .hgsubstate
216 $ echo "rev 1" > subrepo/large.txt
216 $ echo "rev 1" > subrepo/large.txt
217 $ hg add --large subrepo/large.txt
217 $ hg add --large subrepo/large.txt
218 $ hg sum
218 $ hg sum
219 parent: 1:8ee150ea2e9c tip
219 parent: 1:8ee150ea2e9c tip
220 add subrepo
220 add subrepo
221 branch: default
221 branch: default
222 commit: 1 subrepos
222 commit: 1 subrepos
223 update: (current)
223 update: (current)
224 $ hg st
224 $ hg st
225 $ hg st -S
225 $ hg st -S
226 A subrepo/large.txt
226 A subrepo/large.txt
227 $ hg ci -S -m "commit top repo"
227 $ hg ci -S -m "commit top repo"
228 committing subrepository subrepo
228 committing subrepository subrepo
229 Invoking status precommit hook
229 Invoking status precommit hook
230 A large.txt
230 A large.txt
231 Invoking status precommit hook
231 Invoking status precommit hook
232 M .hgsubstate
232 M .hgsubstate
233 # No differences
233 # No differences
234 $ hg st -S
234 $ hg st -S
235 $ hg sum
235 $ hg sum
236 parent: 2:ce4cd0c527a6 tip
236 parent: 2:ce4cd0c527a6 tip
237 commit top repo
237 commit top repo
238 branch: default
238 branch: default
239 commit: (clean)
239 commit: (clean)
240 update: (current)
240 update: (current)
241 $ echo "rev 2" > subrepo/large.txt
241 $ echo "rev 2" > subrepo/large.txt
242 $ hg st -S
242 $ hg st -S
243 M subrepo/large.txt
243 M subrepo/large.txt
244 $ hg sum
244 $ hg sum
245 parent: 2:ce4cd0c527a6 tip
245 parent: 2:ce4cd0c527a6 tip
246 commit top repo
246 commit top repo
247 branch: default
247 branch: default
248 commit: 1 subrepos
248 commit: 1 subrepos
249 update: (current)
249 update: (current)
250 $ hg ci -m "this commit should fail without -S"
250 $ hg ci -m "this commit should fail without -S"
251 abort: uncommitted changes in subrepo subrepo
251 abort: uncommitted changes in subrepo subrepo
252 (use --subrepos for recursive commit)
252 (use --subrepos for recursive commit)
253 [255]
253 [255]
254
254
255 Add a normal file to the subrepo, then test archiving
255 Add a normal file to the subrepo, then test archiving
256
256
257 $ echo 'normal file' > subrepo/normal.txt
257 $ echo 'normal file' > subrepo/normal.txt
258 $ touch large.dat
258 $ touch large.dat
259 $ mv subrepo/large.txt subrepo/renamed-large.txt
259 $ mv subrepo/large.txt subrepo/renamed-large.txt
260 $ hg addremove -S --dry-run
260 $ hg addremove -S --dry-run
261 adding large.dat as a largefile
261 adding large.dat as a largefile
262 removing subrepo/large.txt
262 removing subrepo/large.txt
263 adding subrepo/normal.txt
263 adding subrepo/normal.txt
264 adding subrepo/renamed-large.txt
264 adding subrepo/renamed-large.txt
265 $ hg status -S
265 $ hg status -S
266 ! subrepo/large.txt
266 ! subrepo/large.txt
267 ? large.dat
267 ? large.dat
268 ? subrepo/normal.txt
268 ? subrepo/normal.txt
269 ? subrepo/renamed-large.txt
269 ? subrepo/renamed-large.txt
270
270
271 $ hg addremove --dry-run subrepo
271 $ hg addremove --dry-run subrepo
272 removing subrepo/large.txt (glob)
272 removing subrepo/large.txt (glob)
273 adding subrepo/normal.txt (glob)
273 adding subrepo/normal.txt (glob)
274 adding subrepo/renamed-large.txt (glob)
274 adding subrepo/renamed-large.txt (glob)
275 $ hg status -S
275 $ hg status -S
276 ! subrepo/large.txt
276 ! subrepo/large.txt
277 ? large.dat
277 ? large.dat
278 ? subrepo/normal.txt
278 ? subrepo/normal.txt
279 ? subrepo/renamed-large.txt
279 ? subrepo/renamed-large.txt
280 $ cd ..
280 $ cd ..
281
281
282 $ hg -R statusmatch addremove --dry-run statusmatch/subrepo
282 $ hg -R statusmatch addremove --dry-run statusmatch/subrepo
283 removing statusmatch/subrepo/large.txt (glob)
283 removing statusmatch/subrepo/large.txt (glob)
284 adding statusmatch/subrepo/normal.txt (glob)
284 adding statusmatch/subrepo/normal.txt (glob)
285 adding statusmatch/subrepo/renamed-large.txt (glob)
285 adding statusmatch/subrepo/renamed-large.txt (glob)
286 $ hg -R statusmatch status -S
286 $ hg -R statusmatch status -S
287 ! subrepo/large.txt
287 ! subrepo/large.txt
288 ? large.dat
288 ? large.dat
289 ? subrepo/normal.txt
289 ? subrepo/normal.txt
290 ? subrepo/renamed-large.txt
290 ? subrepo/renamed-large.txt
291
291
292 $ hg -R statusmatch addremove --dry-run -S
292 $ hg -R statusmatch addremove --dry-run -S
293 adding large.dat as a largefile
293 adding large.dat as a largefile
294 removing subrepo/large.txt
294 removing subrepo/large.txt
295 adding subrepo/normal.txt
295 adding subrepo/normal.txt
296 adding subrepo/renamed-large.txt
296 adding subrepo/renamed-large.txt
297 $ cd statusmatch
297 $ cd statusmatch
298
298
299 $ mv subrepo/renamed-large.txt subrepo/large.txt
299 $ mv subrepo/renamed-large.txt subrepo/large.txt
300 $ hg addremove subrepo
300 $ hg addremove subrepo
301 adding subrepo/normal.txt (glob)
301 adding subrepo/normal.txt (glob)
302 $ hg forget subrepo/normal.txt
302 $ hg forget subrepo/normal.txt
303
303
304 $ hg addremove -S
304 $ hg addremove -S
305 adding large.dat as a largefile
305 adding large.dat as a largefile
306 adding subrepo/normal.txt
306 adding subrepo/normal.txt
307 $ rm large.dat
307 $ rm large.dat
308
308
309 $ hg addremove subrepo
309 $ hg addremove subrepo
310 $ hg addremove -S
310 $ hg addremove -S
311 removing large.dat
311 removing large.dat
312
312
313 Lock in subrepo, otherwise the change isn't archived
313 Lock in subrepo, otherwise the change isn't archived
314
314
315 $ hg ci -S -m "add normal file to top level"
315 $ hg ci -S -m "add normal file to top level"
316 committing subrepository subrepo
316 committing subrepository subrepo
317 Invoking status precommit hook
317 Invoking status precommit hook
318 M large.txt
318 M large.txt
319 A normal.txt
319 A normal.txt
320 Invoking status precommit hook
320 Invoking status precommit hook
321 M .hgsubstate
321 M .hgsubstate
322 $ hg archive -S ../lf_subrepo_archive
322 $ hg archive -S ../lf_subrepo_archive
323 $ find ../lf_subrepo_archive | sort
323 $ find ../lf_subrepo_archive | sort
324 ../lf_subrepo_archive
324 ../lf_subrepo_archive
325 ../lf_subrepo_archive/.hg_archival.txt
325 ../lf_subrepo_archive/.hg_archival.txt
326 ../lf_subrepo_archive/.hgsub
326 ../lf_subrepo_archive/.hgsub
327 ../lf_subrepo_archive/.hgsubstate
327 ../lf_subrepo_archive/.hgsubstate
328 ../lf_subrepo_archive/a
328 ../lf_subrepo_archive/a
329 ../lf_subrepo_archive/a/b
329 ../lf_subrepo_archive/a/b
330 ../lf_subrepo_archive/a/b/c
330 ../lf_subrepo_archive/a/b/c
331 ../lf_subrepo_archive/a/b/c/d
331 ../lf_subrepo_archive/a/b/c/d
332 ../lf_subrepo_archive/a/b/c/d/e.large.txt
332 ../lf_subrepo_archive/a/b/c/d/e.large.txt
333 ../lf_subrepo_archive/a/b/c/d/e.normal.txt
333 ../lf_subrepo_archive/a/b/c/d/e.normal.txt
334 ../lf_subrepo_archive/a/b/c/x
334 ../lf_subrepo_archive/a/b/c/x
335 ../lf_subrepo_archive/a/b/c/x/y.normal.txt
335 ../lf_subrepo_archive/a/b/c/x/y.normal.txt
336 ../lf_subrepo_archive/subrepo
336 ../lf_subrepo_archive/subrepo
337 ../lf_subrepo_archive/subrepo/large.txt
337 ../lf_subrepo_archive/subrepo/large.txt
338 ../lf_subrepo_archive/subrepo/normal.txt
338 ../lf_subrepo_archive/subrepo/normal.txt
339
339
340 Test update with subrepos.
340 Test update with subrepos.
341
341
342 $ hg update 0
342 $ hg update 0
343 getting changed largefiles
343 getting changed largefiles
344 0 largefiles updated, 1 removed
344 0 largefiles updated, 1 removed
345 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
345 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
346 $ hg status -S
346 $ hg status -S
347 $ hg update tip
347 $ hg update tip
348 getting changed largefiles
348 getting changed largefiles
349 1 largefiles updated, 0 removed
349 1 largefiles updated, 0 removed
350 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
350 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
351 $ hg status -S
351 $ hg status -S
352 # modify a large file
352 # modify a large file
353 $ echo "modified" > subrepo/large.txt
353 $ echo "modified" > subrepo/large.txt
354 $ hg st -S
354 $ hg st -S
355 M subrepo/large.txt
355 M subrepo/large.txt
356 # update -C should revert the change.
356 # update -C should revert the change.
357 $ hg update -C
357 $ hg update -C
358 getting changed largefiles
358 getting changed largefiles
359 1 largefiles updated, 0 removed
359 1 largefiles updated, 0 removed
360 getting changed largefiles
360 getting changed largefiles
361 0 largefiles updated, 0 removed
361 0 largefiles updated, 0 removed
362 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
362 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
363 $ hg status -S
363 $ hg status -S
364
364
365 $ hg rm -v subrepo/large.txt
365 $ hg rm -v subrepo/large.txt
366 removing subrepo/large.txt (glob)
366 removing subrepo/large.txt (glob)
367 $ hg revert -R subrepo subrepo/large.txt
367 $ hg revert -R subrepo subrepo/large.txt
368 $ rm subrepo/large.txt
368 $ rm subrepo/large.txt
369 $ hg addremove -S
369 $ hg addremove -S
370 removing subrepo/large.txt
370 removing subrepo/large.txt
371 $ hg st -S
371 $ hg st -S
372 R subrepo/large.txt
372 R subrepo/large.txt
373
373
374 Test archiving a revision that references a subrepo that is not yet
374 Test archiving a revision that references a subrepo that is not yet
375 cloned (see test-subrepo-recursion.t):
375 cloned (see test-subrepo-recursion.t):
376
376
377 $ hg clone -U . ../empty
377 $ hg clone -U . ../empty
378 $ cd ../empty
378 $ cd ../empty
379 $ hg archive --subrepos -r tip ../archive.tar.gz
379 $ hg archive --subrepos -r tip ../archive.tar.gz
380 cloning subrepo subrepo from $TESTTMP/statusmatch/subrepo
380 cloning subrepo subrepo from $TESTTMP/statusmatch/subrepo
381 $ cd ..
381 $ cd ..
382
382
383
383
384
384
385
385
386
386
387
387
388 Test addremove, forget and others
388 Test addremove, forget and others
389 ==============================================
389 ==============================================
390
390
391 Test that addremove picks up largefiles prior to the initial commit (issue3541)
391 Test that addremove picks up largefiles prior to the initial commit (issue3541)
392
392
393 $ hg init addrm2
393 $ hg init addrm2
394 $ cd addrm2
394 $ cd addrm2
395 $ touch large.dat
395 $ touch large.dat
396 $ touch large2.dat
396 $ touch large2.dat
397 $ touch normal
397 $ touch normal
398 $ hg add --large large.dat
398 $ hg add --large large.dat
399 $ hg addremove -v
399 $ hg addremove -v
400 adding large2.dat as a largefile
400 adding large2.dat as a largefile
401 adding normal
401 adding normal
402
402
403 Test that forgetting all largefiles reverts to islfilesrepo() == False
403 Test that forgetting all largefiles reverts to islfilesrepo() == False
404 (addremove will add *.dat as normal files now)
404 (addremove will add *.dat as normal files now)
405 $ hg forget large.dat
405 $ hg forget large.dat
406 $ hg forget large2.dat
406 $ hg forget large2.dat
407 $ hg addremove -v
407 $ hg addremove -v
408 adding large.dat
408 adding large.dat
409 adding large2.dat
409 adding large2.dat
410
410
411 Test commit's addremove option prior to the first commit
411 Test commit's addremove option prior to the first commit
412 $ hg forget large.dat
412 $ hg forget large.dat
413 $ hg forget large2.dat
413 $ hg forget large2.dat
414 $ hg add --large large.dat
414 $ hg add --large large.dat
415 $ hg ci -Am "commit"
415 $ hg ci -Am "commit"
416 adding large2.dat as a largefile
416 adding large2.dat as a largefile
417 Invoking status precommit hook
417 Invoking status precommit hook
418 A large.dat
418 A large.dat
419 A large2.dat
419 A large2.dat
420 A normal
420 A normal
421 $ find .hglf | sort
421 $ find .hglf | sort
422 .hglf
422 .hglf
423 .hglf/large.dat
423 .hglf/large.dat
424 .hglf/large2.dat
424 .hglf/large2.dat
425
425
426 Test actions on largefiles using relative paths from subdir
426 Test actions on largefiles using relative paths from subdir
427
427
428 $ mkdir sub
428 $ mkdir sub
429 $ cd sub
429 $ cd sub
430 $ echo anotherlarge > anotherlarge
430 $ echo anotherlarge > anotherlarge
431 $ hg add --large anotherlarge
431 $ hg add --large anotherlarge
432 $ hg st
432 $ hg st
433 A sub/anotherlarge
433 A sub/anotherlarge
434 $ hg st anotherlarge
434 $ hg st anotherlarge
435 A anotherlarge
435 A anotherlarge
436 $ hg commit -m anotherlarge anotherlarge
436 $ hg commit -m anotherlarge anotherlarge
437 Invoking status precommit hook
437 Invoking status precommit hook
438 A sub/anotherlarge
438 A sub/anotherlarge
439 $ hg log anotherlarge
439 $ hg log anotherlarge
440 changeset: 1:9627a577c5e9
440 changeset: 1:9627a577c5e9
441 tag: tip
441 tag: tip
442 user: test
442 user: test
443 date: Thu Jan 01 00:00:00 1970 +0000
443 date: Thu Jan 01 00:00:00 1970 +0000
444 summary: anotherlarge
444 summary: anotherlarge
445
445
446 $ hg log -G anotherlarge
446 $ hg log -G anotherlarge
447 @ changeset: 1:9627a577c5e9
447 @ changeset: 1:9627a577c5e9
448 | tag: tip
448 | tag: tip
449 | user: test
449 | user: test
450 | date: Thu Jan 01 00:00:00 1970 +0000
450 | date: Thu Jan 01 00:00:00 1970 +0000
451 | summary: anotherlarge
451 | summary: anotherlarge
452 |
452 |
453 $ echo more >> anotherlarge
453 $ echo more >> anotherlarge
454 $ hg st .
454 $ hg st .
455 M anotherlarge
455 M anotherlarge
456 $ hg cat anotherlarge
456 $ hg cat anotherlarge
457 anotherlarge
457 anotherlarge
458 $ hg revert anotherlarge
458 $ hg revert anotherlarge
459 $ hg st
459 $ hg st
460 ? sub/anotherlarge.orig
460 ? sub/anotherlarge.orig
461 $ cd ..
461 $ cd ..
462
462
463 $ cd ..
463 $ cd ..
464
464
465 Check error message while exchange
465 Check error message while exchange
466 =========================================================
466 =========================================================
467
467
468 issue3651: summary/outgoing with largefiles shows "no remote repo"
468 issue3651: summary/outgoing with largefiles shows "no remote repo"
469 unexpectedly
469 unexpectedly
470
470
471 $ mkdir issue3651
471 $ mkdir issue3651
472 $ cd issue3651
472 $ cd issue3651
473
473
474 $ hg init src
474 $ hg init src
475 $ echo a > src/a
475 $ echo a > src/a
476 $ hg -R src add --large src/a
476 $ hg -R src add --large src/a
477 $ hg -R src commit -m '#0'
477 $ hg -R src commit -m '#0'
478 Invoking status precommit hook
478 Invoking status precommit hook
479 A a
479 A a
480
480
481 check messages when no remote repository is specified:
481 check messages when no remote repository is specified:
482 "no remote repo" route for "hg outgoing --large" is not tested here,
482 "no remote repo" route for "hg outgoing --large" is not tested here,
483 because it can't be reproduced easily.
483 because it can't be reproduced easily.
484
484
485 $ hg init clone1
485 $ hg init clone1
486 $ hg -R clone1 -q pull src
486 $ hg -R clone1 -q pull src
487 $ hg -R clone1 -q update
487 $ hg -R clone1 -q update
488 $ hg -R clone1 paths | grep default
488 $ hg -R clone1 paths | grep default
489 [1]
489 [1]
490
490
491 $ hg -R clone1 summary --large
491 $ hg -R clone1 summary --large
492 parent: 0:fc0bd45326d3 tip
492 parent: 0:fc0bd45326d3 tip
493 #0
493 #0
494 branch: default
494 branch: default
495 commit: (clean)
495 commit: (clean)
496 update: (current)
496 update: (current)
497 largefiles: (no remote repo)
497 largefiles: (no remote repo)
498
498
499 check messages when there is no files to upload:
499 check messages when there is no files to upload:
500
500
501 $ hg -q clone src clone2
501 $ hg -q clone src clone2
502 $ hg -R clone2 paths | grep default
502 $ hg -R clone2 paths | grep default
503 default = $TESTTMP/issue3651/src (glob)
503 default = $TESTTMP/issue3651/src (glob)
504
504
505 $ hg -R clone2 summary --large
505 $ hg -R clone2 summary --large
506 parent: 0:fc0bd45326d3 tip
506 parent: 0:fc0bd45326d3 tip
507 #0
507 #0
508 branch: default
508 branch: default
509 commit: (clean)
509 commit: (clean)
510 update: (current)
510 update: (current)
511 largefiles: (no files to upload)
511 largefiles: (no files to upload)
512 $ hg -R clone2 outgoing --large
512 $ hg -R clone2 outgoing --large
513 comparing with $TESTTMP/issue3651/src (glob)
513 comparing with $TESTTMP/issue3651/src (glob)
514 searching for changes
514 searching for changes
515 no changes found
515 no changes found
516 largefiles: no files to upload
516 largefiles: no files to upload
517 [1]
517 [1]
518
518
519 $ hg -R clone2 outgoing --large --graph --template "{rev}"
519 $ hg -R clone2 outgoing --large --graph --template "{rev}"
520 comparing with $TESTTMP/issue3651/src (glob)
520 comparing with $TESTTMP/issue3651/src (glob)
521 searching for changes
521 searching for changes
522 no changes found
522 no changes found
523 largefiles: no files to upload
523 largefiles: no files to upload
524
524
525 check messages when there are files to upload:
525 check messages when there are files to upload:
526
526
527 $ echo b > clone2/b
527 $ echo b > clone2/b
528 $ hg -R clone2 add --large clone2/b
528 $ hg -R clone2 add --large clone2/b
529 $ hg -R clone2 commit -m '#1'
529 $ hg -R clone2 commit -m '#1'
530 Invoking status precommit hook
530 Invoking status precommit hook
531 A b
531 A b
532 $ hg -R clone2 summary --large
532 $ hg -R clone2 summary --large
533 parent: 1:1acbe71ce432 tip
533 parent: 1:1acbe71ce432 tip
534 #1
534 #1
535 branch: default
535 branch: default
536 commit: (clean)
536 commit: (clean)
537 update: (current)
537 update: (current)
538 largefiles: 1 entities for 1 files to upload
538 largefiles: 1 entities for 1 files to upload
539 $ hg -R clone2 outgoing --large
539 $ hg -R clone2 outgoing --large
540 comparing with $TESTTMP/issue3651/src (glob)
540 comparing with $TESTTMP/issue3651/src (glob)
541 searching for changes
541 searching for changes
542 changeset: 1:1acbe71ce432
542 changeset: 1:1acbe71ce432
543 tag: tip
543 tag: tip
544 user: test
544 user: test
545 date: Thu Jan 01 00:00:00 1970 +0000
545 date: Thu Jan 01 00:00:00 1970 +0000
546 summary: #1
546 summary: #1
547
547
548 largefiles to upload (1 entities):
548 largefiles to upload (1 entities):
549 b
549 b
550
550
551 $ hg -R clone2 outgoing --large --graph --template "{rev}"
551 $ hg -R clone2 outgoing --large --graph --template "{rev}"
552 comparing with $TESTTMP/issue3651/src (glob)
552 comparing with $TESTTMP/issue3651/src (glob)
553 searching for changes
553 searching for changes
554 @ 1
554 @ 1
555
555
556 largefiles to upload (1 entities):
556 largefiles to upload (1 entities):
557 b
557 b
558
558
559
559
560 $ cp clone2/b clone2/b1
560 $ cp clone2/b clone2/b1
561 $ cp clone2/b clone2/b2
561 $ cp clone2/b clone2/b2
562 $ hg -R clone2 add --large clone2/b1 clone2/b2
562 $ hg -R clone2 add --large clone2/b1 clone2/b2
563 $ hg -R clone2 commit -m '#2: add largefiles referring same entity'
563 $ hg -R clone2 commit -m '#2: add largefiles referring same entity'
564 Invoking status precommit hook
564 Invoking status precommit hook
565 A b1
565 A b1
566 A b2
566 A b2
567 $ hg -R clone2 summary --large
567 $ hg -R clone2 summary --large
568 parent: 2:6095d0695d70 tip
568 parent: 2:6095d0695d70 tip
569 #2: add largefiles referring same entity
569 #2: add largefiles referring same entity
570 branch: default
570 branch: default
571 commit: (clean)
571 commit: (clean)
572 update: (current)
572 update: (current)
573 largefiles: 1 entities for 3 files to upload
573 largefiles: 1 entities for 3 files to upload
574 $ hg -R clone2 outgoing --large -T "{rev}:{node|short}\n"
574 $ hg -R clone2 outgoing --large -T "{rev}:{node|short}\n"
575 comparing with $TESTTMP/issue3651/src (glob)
575 comparing with $TESTTMP/issue3651/src (glob)
576 searching for changes
576 searching for changes
577 1:1acbe71ce432
577 1:1acbe71ce432
578 2:6095d0695d70
578 2:6095d0695d70
579 largefiles to upload (1 entities):
579 largefiles to upload (1 entities):
580 b
580 b
581 b1
581 b1
582 b2
582 b2
583
583
584 $ hg -R clone2 cat -r 1 clone2/.hglf/b
584 $ hg -R clone2 cat -r 1 clone2/.hglf/b
585 89e6c98d92887913cadf06b2adb97f26cde4849b
585 89e6c98d92887913cadf06b2adb97f26cde4849b
586 $ hg -R clone2 outgoing --large -T "{rev}:{node|short}\n" --debug
586 $ hg -R clone2 outgoing --large -T "{rev}:{node|short}\n" --debug
587 comparing with $TESTTMP/issue3651/src (glob)
587 comparing with $TESTTMP/issue3651/src (glob)
588 query 1; heads
588 query 1; heads
589 searching for changes
589 searching for changes
590 all remote heads known locally
590 all remote heads known locally
591 1:1acbe71ce432
591 1:1acbe71ce432
592 2:6095d0695d70
592 2:6095d0695d70
593 finding outgoing largefiles: 0/2 revision (0.00%)
594 finding outgoing largefiles: 1/2 revision (50.00%)
593 largefiles to upload (1 entities):
595 largefiles to upload (1 entities):
594 b
596 b
595 89e6c98d92887913cadf06b2adb97f26cde4849b
597 89e6c98d92887913cadf06b2adb97f26cde4849b
596 b1
598 b1
597 89e6c98d92887913cadf06b2adb97f26cde4849b
599 89e6c98d92887913cadf06b2adb97f26cde4849b
598 b2
600 b2
599 89e6c98d92887913cadf06b2adb97f26cde4849b
601 89e6c98d92887913cadf06b2adb97f26cde4849b
600
602
601
603
602 $ echo bbb > clone2/b
604 $ echo bbb > clone2/b
603 $ hg -R clone2 commit -m '#3: add new largefile entity as existing file'
605 $ hg -R clone2 commit -m '#3: add new largefile entity as existing file'
604 Invoking status precommit hook
606 Invoking status precommit hook
605 M b
607 M b
606 $ echo bbbb > clone2/b
608 $ echo bbbb > clone2/b
607 $ hg -R clone2 commit -m '#4: add new largefile entity as existing file'
609 $ hg -R clone2 commit -m '#4: add new largefile entity as existing file'
608 Invoking status precommit hook
610 Invoking status precommit hook
609 M b
611 M b
610 $ cp clone2/b1 clone2/b
612 $ cp clone2/b1 clone2/b
611 $ hg -R clone2 commit -m '#5: refer existing largefile entity again'
613 $ hg -R clone2 commit -m '#5: refer existing largefile entity again'
612 Invoking status precommit hook
614 Invoking status precommit hook
613 M b
615 M b
614 $ hg -R clone2 summary --large
616 $ hg -R clone2 summary --large
615 parent: 5:036794ea641c tip
617 parent: 5:036794ea641c tip
616 #5: refer existing largefile entity again
618 #5: refer existing largefile entity again
617 branch: default
619 branch: default
618 commit: (clean)
620 commit: (clean)
619 update: (current)
621 update: (current)
620 largefiles: 3 entities for 3 files to upload
622 largefiles: 3 entities for 3 files to upload
621 $ hg -R clone2 outgoing --large -T "{rev}:{node|short}\n"
623 $ hg -R clone2 outgoing --large -T "{rev}:{node|short}\n"
622 comparing with $TESTTMP/issue3651/src (glob)
624 comparing with $TESTTMP/issue3651/src (glob)
623 searching for changes
625 searching for changes
624 1:1acbe71ce432
626 1:1acbe71ce432
625 2:6095d0695d70
627 2:6095d0695d70
626 3:7983dce246cc
628 3:7983dce246cc
627 4:233f12ada4ae
629 4:233f12ada4ae
628 5:036794ea641c
630 5:036794ea641c
629 largefiles to upload (3 entities):
631 largefiles to upload (3 entities):
630 b
632 b
631 b1
633 b1
632 b2
634 b2
633
635
634 $ hg -R clone2 cat -r 3 clone2/.hglf/b
636 $ hg -R clone2 cat -r 3 clone2/.hglf/b
635 c801c9cfe94400963fcb683246217d5db77f9a9a
637 c801c9cfe94400963fcb683246217d5db77f9a9a
636 $ hg -R clone2 cat -r 4 clone2/.hglf/b
638 $ hg -R clone2 cat -r 4 clone2/.hglf/b
637 13f9ed0898e315bf59dc2973fec52037b6f441a2
639 13f9ed0898e315bf59dc2973fec52037b6f441a2
638 $ hg -R clone2 outgoing --large -T "{rev}:{node|short}\n" --debug
640 $ hg -R clone2 outgoing --large -T "{rev}:{node|short}\n" --debug
639 comparing with $TESTTMP/issue3651/src (glob)
641 comparing with $TESTTMP/issue3651/src (glob)
640 query 1; heads
642 query 1; heads
641 searching for changes
643 searching for changes
642 all remote heads known locally
644 all remote heads known locally
643 1:1acbe71ce432
645 1:1acbe71ce432
644 2:6095d0695d70
646 2:6095d0695d70
645 3:7983dce246cc
647 3:7983dce246cc
646 4:233f12ada4ae
648 4:233f12ada4ae
647 5:036794ea641c
649 5:036794ea641c
650 finding outgoing largefiles: 0/5 revision (0.00%)
651 finding outgoing largefiles: 1/5 revision (20.00%)
652 finding outgoing largefiles: 2/5 revision (40.00%)
653 finding outgoing largefiles: 3/5 revision (60.00%)
654 finding outgoing largefiles: 4/5 revision (80.00%)
648 largefiles to upload (3 entities):
655 largefiles to upload (3 entities):
649 b
656 b
650 13f9ed0898e315bf59dc2973fec52037b6f441a2
657 13f9ed0898e315bf59dc2973fec52037b6f441a2
651 89e6c98d92887913cadf06b2adb97f26cde4849b
658 89e6c98d92887913cadf06b2adb97f26cde4849b
652 c801c9cfe94400963fcb683246217d5db77f9a9a
659 c801c9cfe94400963fcb683246217d5db77f9a9a
653 b1
660 b1
654 89e6c98d92887913cadf06b2adb97f26cde4849b
661 89e6c98d92887913cadf06b2adb97f26cde4849b
655 b2
662 b2
656 89e6c98d92887913cadf06b2adb97f26cde4849b
663 89e6c98d92887913cadf06b2adb97f26cde4849b
657
664
658
665
659 Pushing revision #1 causes uploading entity 89e6c98d9288, which is
666 Pushing revision #1 causes uploading entity 89e6c98d9288, which is
660 shared also by largefiles b1, b2 in revision #2 and b in revision #5.
667 shared also by largefiles b1, b2 in revision #2 and b in revision #5.
661
668
662 Then, entity 89e6c98d9288 is not treated as "outgoing entity" at "hg
669 Then, entity 89e6c98d9288 is not treated as "outgoing entity" at "hg
663 summary" and "hg outgoing", even though files in outgoing revision #2
670 summary" and "hg outgoing", even though files in outgoing revision #2
664 and #5 refer it.
671 and #5 refer it.
665
672
666 $ hg -R clone2 push -r 1 -q
673 $ hg -R clone2 push -r 1 -q
667 $ hg -R clone2 summary --large
674 $ hg -R clone2 summary --large
668 parent: 5:036794ea641c tip
675 parent: 5:036794ea641c tip
669 #5: refer existing largefile entity again
676 #5: refer existing largefile entity again
670 branch: default
677 branch: default
671 commit: (clean)
678 commit: (clean)
672 update: (current)
679 update: (current)
673 largefiles: 2 entities for 1 files to upload
680 largefiles: 2 entities for 1 files to upload
674 $ hg -R clone2 outgoing --large -T "{rev}:{node|short}\n"
681 $ hg -R clone2 outgoing --large -T "{rev}:{node|short}\n"
675 comparing with $TESTTMP/issue3651/src (glob)
682 comparing with $TESTTMP/issue3651/src (glob)
676 searching for changes
683 searching for changes
677 2:6095d0695d70
684 2:6095d0695d70
678 3:7983dce246cc
685 3:7983dce246cc
679 4:233f12ada4ae
686 4:233f12ada4ae
680 5:036794ea641c
687 5:036794ea641c
681 largefiles to upload (2 entities):
688 largefiles to upload (2 entities):
682 b
689 b
683
690
684 $ hg -R clone2 outgoing --large -T "{rev}:{node|short}\n" --debug
691 $ hg -R clone2 outgoing --large -T "{rev}:{node|short}\n" --debug
685 comparing with $TESTTMP/issue3651/src (glob)
692 comparing with $TESTTMP/issue3651/src (glob)
686 query 1; heads
693 query 1; heads
687 searching for changes
694 searching for changes
688 all remote heads known locally
695 all remote heads known locally
689 2:6095d0695d70
696 2:6095d0695d70
690 3:7983dce246cc
697 3:7983dce246cc
691 4:233f12ada4ae
698 4:233f12ada4ae
692 5:036794ea641c
699 5:036794ea641c
700 finding outgoing largefiles: 0/4 revision (0.00%)
701 finding outgoing largefiles: 1/4 revision (25.00%)
702 finding outgoing largefiles: 2/4 revision (50.00%)
703 finding outgoing largefiles: 3/4 revision (75.00%)
693 largefiles to upload (2 entities):
704 largefiles to upload (2 entities):
694 b
705 b
695 13f9ed0898e315bf59dc2973fec52037b6f441a2
706 13f9ed0898e315bf59dc2973fec52037b6f441a2
696 c801c9cfe94400963fcb683246217d5db77f9a9a
707 c801c9cfe94400963fcb683246217d5db77f9a9a
697
708
698
709
699 $ cd ..
710 $ cd ..
700
711
701 merge action 'd' for 'local renamed directory to d2/g' which has no filename
712 merge action 'd' for 'local renamed directory to d2/g' which has no filename
702 ==================================================================================
713 ==================================================================================
703
714
704 $ hg init merge-action
715 $ hg init merge-action
705 $ cd merge-action
716 $ cd merge-action
706 $ touch l
717 $ touch l
707 $ hg add --large l
718 $ hg add --large l
708 $ mkdir d1
719 $ mkdir d1
709 $ touch d1/f
720 $ touch d1/f
710 $ hg ci -Aqm0
721 $ hg ci -Aqm0
711 Invoking status precommit hook
722 Invoking status precommit hook
712 A d1/f
723 A d1/f
713 A l
724 A l
714 $ echo > d1/f
725 $ echo > d1/f
715 $ touch d1/g
726 $ touch d1/g
716 $ hg ci -Aqm1
727 $ hg ci -Aqm1
717 Invoking status precommit hook
728 Invoking status precommit hook
718 M d1/f
729 M d1/f
719 A d1/g
730 A d1/g
720 $ hg up -qr0
731 $ hg up -qr0
721 $ hg mv d1 d2
732 $ hg mv d1 d2
722 moving d1/f to d2/f (glob)
733 moving d1/f to d2/f (glob)
723 $ hg ci -qm2
734 $ hg ci -qm2
724 Invoking status precommit hook
735 Invoking status precommit hook
725 A d2/f
736 A d2/f
726 R d1/f
737 R d1/f
727 $ hg merge
738 $ hg merge
728 merging d2/f and d1/f to d2/f
739 merging d2/f and d1/f to d2/f
729 getting changed largefiles
740 getting changed largefiles
730 0 largefiles updated, 0 removed
741 0 largefiles updated, 0 removed
731 1 files updated, 1 files merged, 0 files removed, 0 files unresolved
742 1 files updated, 1 files merged, 0 files removed, 0 files unresolved
732 (branch merge, don't forget to commit)
743 (branch merge, don't forget to commit)
733 $ cd ..
744 $ cd ..
734
745
735
746
736 Merge conflicts:
747 Merge conflicts:
737 =====================
748 =====================
738
749
739 $ hg init merge
750 $ hg init merge
740 $ cd merge
751 $ cd merge
741 $ echo 0 > f-different
752 $ echo 0 > f-different
742 $ echo 0 > f-same
753 $ echo 0 > f-same
743 $ echo 0 > f-unchanged-1
754 $ echo 0 > f-unchanged-1
744 $ echo 0 > f-unchanged-2
755 $ echo 0 > f-unchanged-2
745 $ hg add --large *
756 $ hg add --large *
746 $ hg ci -m0
757 $ hg ci -m0
747 Invoking status precommit hook
758 Invoking status precommit hook
748 A f-different
759 A f-different
749 A f-same
760 A f-same
750 A f-unchanged-1
761 A f-unchanged-1
751 A f-unchanged-2
762 A f-unchanged-2
752 $ echo tmp1 > f-unchanged-1
763 $ echo tmp1 > f-unchanged-1
753 $ echo tmp1 > f-unchanged-2
764 $ echo tmp1 > f-unchanged-2
754 $ echo tmp1 > f-same
765 $ echo tmp1 > f-same
755 $ hg ci -m1
766 $ hg ci -m1
756 Invoking status precommit hook
767 Invoking status precommit hook
757 M f-same
768 M f-same
758 M f-unchanged-1
769 M f-unchanged-1
759 M f-unchanged-2
770 M f-unchanged-2
760 $ echo 2 > f-different
771 $ echo 2 > f-different
761 $ echo 0 > f-unchanged-1
772 $ echo 0 > f-unchanged-1
762 $ echo 1 > f-unchanged-2
773 $ echo 1 > f-unchanged-2
763 $ echo 1 > f-same
774 $ echo 1 > f-same
764 $ hg ci -m2
775 $ hg ci -m2
765 Invoking status precommit hook
776 Invoking status precommit hook
766 M f-different
777 M f-different
767 M f-same
778 M f-same
768 M f-unchanged-1
779 M f-unchanged-1
769 M f-unchanged-2
780 M f-unchanged-2
770 $ hg up -qr0
781 $ hg up -qr0
771 $ echo tmp2 > f-unchanged-1
782 $ echo tmp2 > f-unchanged-1
772 $ echo tmp2 > f-unchanged-2
783 $ echo tmp2 > f-unchanged-2
773 $ echo tmp2 > f-same
784 $ echo tmp2 > f-same
774 $ hg ci -m3
785 $ hg ci -m3
775 Invoking status precommit hook
786 Invoking status precommit hook
776 M f-same
787 M f-same
777 M f-unchanged-1
788 M f-unchanged-1
778 M f-unchanged-2
789 M f-unchanged-2
779 created new head
790 created new head
780 $ echo 1 > f-different
791 $ echo 1 > f-different
781 $ echo 1 > f-unchanged-1
792 $ echo 1 > f-unchanged-1
782 $ echo 0 > f-unchanged-2
793 $ echo 0 > f-unchanged-2
783 $ echo 1 > f-same
794 $ echo 1 > f-same
784 $ hg ci -m4
795 $ hg ci -m4
785 Invoking status precommit hook
796 Invoking status precommit hook
786 M f-different
797 M f-different
787 M f-same
798 M f-same
788 M f-unchanged-1
799 M f-unchanged-1
789 M f-unchanged-2
800 M f-unchanged-2
790 $ hg merge
801 $ hg merge
791 largefile f-different has a merge conflict
802 largefile f-different has a merge conflict
792 ancestor was 09d2af8dd22201dd8d48e5dcfcaed281ff9422c7
803 ancestor was 09d2af8dd22201dd8d48e5dcfcaed281ff9422c7
793 keep (l)ocal e5fa44f2b31c1fb553b6021e7360d07d5d91ff5e or
804 keep (l)ocal e5fa44f2b31c1fb553b6021e7360d07d5d91ff5e or
794 take (o)ther 7448d8798a4380162d4b56f9b452e2f6f9e24e7a? l
805 take (o)ther 7448d8798a4380162d4b56f9b452e2f6f9e24e7a? l
795 getting changed largefiles
806 getting changed largefiles
796 1 largefiles updated, 0 removed
807 1 largefiles updated, 0 removed
797 0 files updated, 4 files merged, 0 files removed, 0 files unresolved
808 0 files updated, 4 files merged, 0 files removed, 0 files unresolved
798 (branch merge, don't forget to commit)
809 (branch merge, don't forget to commit)
799 $ cat f-different
810 $ cat f-different
800 1
811 1
801 $ cat f-same
812 $ cat f-same
802 1
813 1
803 $ cat f-unchanged-1
814 $ cat f-unchanged-1
804 1
815 1
805 $ cat f-unchanged-2
816 $ cat f-unchanged-2
806 1
817 1
807 $ cd ..
818 $ cd ..
808
819
809 Test largefile insulation (do not enabled a side effect
820 Test largefile insulation (do not enabled a side effect
810 ========================================================
821 ========================================================
811
822
812 Check whether "largefiles" feature is supported only in repositories
823 Check whether "largefiles" feature is supported only in repositories
813 enabling largefiles extension.
824 enabling largefiles extension.
814
825
815 $ mkdir individualenabling
826 $ mkdir individualenabling
816 $ cd individualenabling
827 $ cd individualenabling
817
828
818 $ hg init enabledlocally
829 $ hg init enabledlocally
819 $ echo large > enabledlocally/large
830 $ echo large > enabledlocally/large
820 $ hg -R enabledlocally add --large enabledlocally/large
831 $ hg -R enabledlocally add --large enabledlocally/large
821 $ hg -R enabledlocally commit -m '#0'
832 $ hg -R enabledlocally commit -m '#0'
822 Invoking status precommit hook
833 Invoking status precommit hook
823 A large
834 A large
824
835
825 $ hg init notenabledlocally
836 $ hg init notenabledlocally
826 $ echo large > notenabledlocally/large
837 $ echo large > notenabledlocally/large
827 $ hg -R notenabledlocally add --large notenabledlocally/large
838 $ hg -R notenabledlocally add --large notenabledlocally/large
828 $ hg -R notenabledlocally commit -m '#0'
839 $ hg -R notenabledlocally commit -m '#0'
829 Invoking status precommit hook
840 Invoking status precommit hook
830 A large
841 A large
831
842
832 $ cat >> $HGRCPATH <<EOF
843 $ cat >> $HGRCPATH <<EOF
833 > [extensions]
844 > [extensions]
834 > # disable globally
845 > # disable globally
835 > largefiles=!
846 > largefiles=!
836 > EOF
847 > EOF
837 $ cat >> enabledlocally/.hg/hgrc <<EOF
848 $ cat >> enabledlocally/.hg/hgrc <<EOF
838 > [extensions]
849 > [extensions]
839 > # enable locally
850 > # enable locally
840 > largefiles=
851 > largefiles=
841 > EOF
852 > EOF
842 $ hg -R enabledlocally root
853 $ hg -R enabledlocally root
843 $TESTTMP/individualenabling/enabledlocally (glob)
854 $TESTTMP/individualenabling/enabledlocally (glob)
844 $ hg -R notenabledlocally root
855 $ hg -R notenabledlocally root
845 abort: repository requires features unknown to this Mercurial: largefiles!
856 abort: repository requires features unknown to this Mercurial: largefiles!
846 (see http://mercurial.selenic.com/wiki/MissingRequirement for more information)
857 (see http://mercurial.selenic.com/wiki/MissingRequirement for more information)
847 [255]
858 [255]
848
859
849 $ hg init push-dst
860 $ hg init push-dst
850 $ hg -R enabledlocally push push-dst
861 $ hg -R enabledlocally push push-dst
851 pushing to push-dst
862 pushing to push-dst
852 abort: required features are not supported in the destination: largefiles
863 abort: required features are not supported in the destination: largefiles
853 [255]
864 [255]
854
865
855 $ hg init pull-src
866 $ hg init pull-src
856 $ hg -R pull-src pull enabledlocally
867 $ hg -R pull-src pull enabledlocally
857 pulling from enabledlocally
868 pulling from enabledlocally
858 abort: required features are not supported in the destination: largefiles
869 abort: required features are not supported in the destination: largefiles
859 [255]
870 [255]
860
871
861 $ hg clone enabledlocally clone-dst
872 $ hg clone enabledlocally clone-dst
862 abort: repository requires features unknown to this Mercurial: largefiles!
873 abort: repository requires features unknown to this Mercurial: largefiles!
863 (see http://mercurial.selenic.com/wiki/MissingRequirement for more information)
874 (see http://mercurial.selenic.com/wiki/MissingRequirement for more information)
864 [255]
875 [255]
865 $ test -d clone-dst
876 $ test -d clone-dst
866 [1]
877 [1]
867 $ hg clone --pull enabledlocally clone-pull-dst
878 $ hg clone --pull enabledlocally clone-pull-dst
868 abort: required features are not supported in the destination: largefiles
879 abort: required features are not supported in the destination: largefiles
869 [255]
880 [255]
870 $ test -d clone-pull-dst
881 $ test -d clone-pull-dst
871 [1]
882 [1]
872
883
873 #if serve
884 #if serve
874
885
875 Test largefiles specific peer setup, when largefiles is enabled
886 Test largefiles specific peer setup, when largefiles is enabled
876 locally (issue4109)
887 locally (issue4109)
877
888
878 $ hg showconfig extensions | grep largefiles
889 $ hg showconfig extensions | grep largefiles
879 extensions.largefiles=!
890 extensions.largefiles=!
880 $ mkdir -p $TESTTMP/individualenabling/usercache
891 $ mkdir -p $TESTTMP/individualenabling/usercache
881
892
882 $ hg serve -R enabledlocally -d -p $HGPORT --pid-file hg.pid
893 $ hg serve -R enabledlocally -d -p $HGPORT --pid-file hg.pid
883 $ cat hg.pid >> $DAEMON_PIDS
894 $ cat hg.pid >> $DAEMON_PIDS
884
895
885 $ hg init pull-dst
896 $ hg init pull-dst
886 $ cat > pull-dst/.hg/hgrc <<EOF
897 $ cat > pull-dst/.hg/hgrc <<EOF
887 > [extensions]
898 > [extensions]
888 > # enable locally
899 > # enable locally
889 > largefiles=
900 > largefiles=
890 > [largefiles]
901 > [largefiles]
891 > # ignore system cache to force largefiles specific wire proto access
902 > # ignore system cache to force largefiles specific wire proto access
892 > usercache=$TESTTMP/individualenabling/usercache
903 > usercache=$TESTTMP/individualenabling/usercache
893 > EOF
904 > EOF
894 $ hg -R pull-dst -q pull -u http://localhost:$HGPORT
905 $ hg -R pull-dst -q pull -u http://localhost:$HGPORT
895
906
896 $ "$TESTDIR/killdaemons.py" $DAEMON_PIDS
907 $ "$TESTDIR/killdaemons.py" $DAEMON_PIDS
897 #endif
908 #endif
898
909
899 $ cd ..
910 $ cd ..
900
911
901
912
902 Test "pull --rebase" when rebase is enabled before largefiles (issue3861)
913 Test "pull --rebase" when rebase is enabled before largefiles (issue3861)
903 =========================================================================
914 =========================================================================
904
915
905 $ hg showconfig extensions | grep largefiles
916 $ hg showconfig extensions | grep largefiles
906 extensions.largefiles=!
917 extensions.largefiles=!
907
918
908 $ mkdir issue3861
919 $ mkdir issue3861
909 $ cd issue3861
920 $ cd issue3861
910 $ hg init src
921 $ hg init src
911 $ hg clone -q src dst
922 $ hg clone -q src dst
912 $ echo a > src/a
923 $ echo a > src/a
913 $ hg -R src commit -Aqm "#0"
924 $ hg -R src commit -Aqm "#0"
914 Invoking status precommit hook
925 Invoking status precommit hook
915 A a
926 A a
916
927
917 $ cat >> dst/.hg/hgrc <<EOF
928 $ cat >> dst/.hg/hgrc <<EOF
918 > [extensions]
929 > [extensions]
919 > largefiles=
930 > largefiles=
920 > EOF
931 > EOF
921 $ hg -R dst pull --rebase
932 $ hg -R dst pull --rebase
922 pulling from $TESTTMP/issue3861/src (glob)
933 pulling from $TESTTMP/issue3861/src (glob)
923 requesting all changes
934 requesting all changes
924 adding changesets
935 adding changesets
925 adding manifests
936 adding manifests
926 adding file changes
937 adding file changes
927 added 1 changesets with 1 changes to 1 files
938 added 1 changesets with 1 changes to 1 files
928 nothing to rebase - working directory parent is already an ancestor of destination bf5e395ced2c
939 nothing to rebase - working directory parent is already an ancestor of destination bf5e395ced2c
929 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
940 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
930
941
931 $ cd ..
942 $ cd ..
General Comments 0
You need to be logged in to leave comments. Login now