##// END OF EJS Templates
hg: introduce "wirepeersetupfuncs" to setup wire peer by extensions (issue4109)...
FUJIWARA Katsunori -
r20858:bc56ec9e stable
parent child Browse files
Show More
@@ -1,128 +1,130 b''
1 1 # Copyright 2009-2010 Gregory P. Ward
2 2 # Copyright 2009-2010 Intelerad Medical Systems Incorporated
3 3 # Copyright 2010-2011 Fog Creek Software
4 4 # Copyright 2010-2011 Unity Technologies
5 5 #
6 6 # This software may be used and distributed according to the terms of the
7 7 # GNU General Public License version 2 or any later version.
8 8
9 9 '''track large binary files
10 10
11 11 Large binary files tend to be not very compressible, not very
12 12 diffable, and not at all mergeable. Such files are not handled
13 13 efficiently by Mercurial's storage format (revlog), which is based on
14 14 compressed binary deltas; storing large binary files as regular
15 15 Mercurial files wastes bandwidth and disk space and increases
16 16 Mercurial's memory usage. The largefiles extension addresses these
17 17 problems by adding a centralized client-server layer on top of
18 18 Mercurial: largefiles live in a *central store* out on the network
19 19 somewhere, and you only fetch the revisions that you need when you
20 20 need them.
21 21
22 22 largefiles works by maintaining a "standin file" in .hglf/ for each
23 23 largefile. The standins are small (41 bytes: an SHA-1 hash plus
24 24 newline) and are tracked by Mercurial. Largefile revisions are
25 25 identified by the SHA-1 hash of their contents, which is written to
26 26 the standin. largefiles uses that revision ID to get/put largefile
27 27 revisions from/to the central store. This saves both disk space and
28 28 bandwidth, since you don't need to retrieve all historical revisions
29 29 of large files when you clone or pull.
30 30
31 31 To start a new repository or add new large binary files, just add
32 32 --large to your :hg:`add` command. For example::
33 33
34 34 $ dd if=/dev/urandom of=randomdata count=2000
35 35 $ hg add --large randomdata
36 36 $ hg commit -m 'add randomdata as a largefile'
37 37
38 38 When you push a changeset that adds/modifies largefiles to a remote
39 39 repository, its largefile revisions will be uploaded along with it.
40 40 Note that the remote Mercurial must also have the largefiles extension
41 41 enabled for this to work.
42 42
43 43 When you pull a changeset that affects largefiles from a remote
44 44 repository, the largefiles for the changeset will by default not be
45 45 pulled down. However, when you update to such a revision, any
46 46 largefiles needed by that revision are downloaded and cached (if
47 47 they have never been downloaded before). One way to pull largefiles
48 48 when pulling is thus to use --update, which will update your working
49 49 copy to the latest pulled revision (and thereby downloading any new
50 50 largefiles).
51 51
52 52 If you want to pull largefiles you don't need for update yet, then
53 53 you can use pull with the `--lfrev` option or the :hg:`lfpull` command.
54 54
55 55 If you know you are pulling from a non-default location and want to
56 56 download all the largefiles that correspond to the new changesets at
57 57 the same time, then you can pull with `--lfrev "pulled()"`.
58 58
59 59 If you just want to ensure that you will have the largefiles needed to
60 60 merge or rebase with new heads that you are pulling, then you can pull
61 61 with `--lfrev "head(pulled())"` flag to pre-emptively download any largefiles
62 62 that are new in the heads you are pulling.
63 63
64 64 Keep in mind that network access may now be required to update to
65 65 changesets that you have not previously updated to. The nature of the
66 66 largefiles extension means that updating is no longer guaranteed to
67 67 be a local-only operation.
68 68
69 69 If you already have large files tracked by Mercurial without the
70 70 largefiles extension, you will need to convert your repository in
71 71 order to benefit from largefiles. This is done with the
72 72 :hg:`lfconvert` command::
73 73
74 74 $ hg lfconvert --size 10 oldrepo newrepo
75 75
76 76 In repositories that already have largefiles in them, any new file
77 77 over 10MB will automatically be added as a largefile. To change this
78 78 threshold, set ``largefiles.minsize`` in your Mercurial config file
79 79 to the minimum size in megabytes to track as a largefile, or use the
80 80 --lfsize option to the add command (also in megabytes)::
81 81
82 82 [largefiles]
83 83 minsize = 2
84 84
85 85 $ hg add --lfsize 2
86 86
87 87 The ``largefiles.patterns`` config option allows you to specify a list
88 88 of filename patterns (see :hg:`help patterns`) that should always be
89 89 tracked as largefiles::
90 90
91 91 [largefiles]
92 92 patterns =
93 93 *.jpg
94 94 re:.*\.(png|bmp)$
95 95 library.zip
96 96 content/audio/*
97 97
98 98 Files that match one of these patterns will be added as largefiles
99 99 regardless of their size.
100 100
101 101 The ``largefiles.minsize`` and ``largefiles.patterns`` config options
102 102 will be ignored for any repositories not already containing a
103 103 largefile. To add the first largefile to a repository, you must
104 104 explicitly do so with the --large flag passed to the :hg:`add`
105 105 command.
106 106 '''
107 107
108 from mercurial import commands, localrepo
108 from mercurial import commands, hg, localrepo
109 109
110 110 import lfcommands
111 import proto
111 112 import reposetup
112 113 import uisetup as uisetupmod
113 114
114 115 testedwith = 'internal'
115 116
116 117 reposetup = reposetup.reposetup
117 118
118 119 def featuresetup(ui, supported):
119 120 # don't die on seeing a repo with the largefiles requirement
120 121 supported |= set(['largefiles'])
121 122
122 123 def uisetup(ui):
123 124 localrepo.localrepository.featuresetupfuncs.add(featuresetup)
125 hg.wirepeersetupfuncs.append(proto.wirereposetup)
124 126 uisetupmod.uisetup(ui)
125 127
126 128 commands.norepo += " lfconvert"
127 129
128 130 cmdtable = lfcommands.cmdtable
@@ -1,514 +1,513 b''
1 1 # Copyright 2009-2010 Gregory P. Ward
2 2 # Copyright 2009-2010 Intelerad Medical Systems Incorporated
3 3 # Copyright 2010-2011 Fog Creek Software
4 4 # Copyright 2010-2011 Unity Technologies
5 5 #
6 6 # This software may be used and distributed according to the terms of the
7 7 # GNU General Public License version 2 or any later version.
8 8
9 9 '''setup for largefiles repositories: reposetup'''
10 10 import copy
11 11 import os
12 12
13 13 from mercurial import error, manifest, match as match_, util, discovery
14 14 from mercurial import node as node_
15 15 from mercurial.i18n import _
16 16 from mercurial import localrepo
17 17
18 18 import lfcommands
19 import proto
20 19 import lfutil
21 20
22 21 def reposetup(ui, repo):
23 # wire repositories should be given new wireproto functions but not the
24 # other largefiles modifications
22 # wire repositories should be given new wireproto functions
23 # by "proto.wirereposetup()" via "hg.wirepeersetupfuncs"
25 24 if not repo.local():
26 return proto.wirereposetup(ui, repo)
25 return
27 26
28 27 class lfilesrepo(repo.__class__):
29 28 lfstatus = False
30 29 def status_nolfiles(self, *args, **kwargs):
31 30 return super(lfilesrepo, self).status(*args, **kwargs)
32 31
33 32 # When lfstatus is set, return a context that gives the names
34 33 # of largefiles instead of their corresponding standins and
35 34 # identifies the largefiles as always binary, regardless of
36 35 # their actual contents.
37 36 def __getitem__(self, changeid):
38 37 ctx = super(lfilesrepo, self).__getitem__(changeid)
39 38 if self.lfstatus:
40 39 class lfilesmanifestdict(manifest.manifestdict):
41 40 def __contains__(self, filename):
42 41 if super(lfilesmanifestdict,
43 42 self).__contains__(filename):
44 43 return True
45 44 return super(lfilesmanifestdict,
46 45 self).__contains__(lfutil.standin(filename))
47 46 class lfilesctx(ctx.__class__):
48 47 def files(self):
49 48 filenames = super(lfilesctx, self).files()
50 49 return [lfutil.splitstandin(f) or f for f in filenames]
51 50 def manifest(self):
52 51 man1 = super(lfilesctx, self).manifest()
53 52 man1.__class__ = lfilesmanifestdict
54 53 return man1
55 54 def filectx(self, path, fileid=None, filelog=None):
56 55 try:
57 56 if filelog is not None:
58 57 result = super(lfilesctx, self).filectx(
59 58 path, fileid, filelog)
60 59 else:
61 60 result = super(lfilesctx, self).filectx(
62 61 path, fileid)
63 62 except error.LookupError:
64 63 # Adding a null character will cause Mercurial to
65 64 # identify this as a binary file.
66 65 if filelog is not None:
67 66 result = super(lfilesctx, self).filectx(
68 67 lfutil.standin(path), fileid, filelog)
69 68 else:
70 69 result = super(lfilesctx, self).filectx(
71 70 lfutil.standin(path), fileid)
72 71 olddata = result.data
73 72 result.data = lambda: olddata() + '\0'
74 73 return result
75 74 ctx.__class__ = lfilesctx
76 75 return ctx
77 76
78 77 # Figure out the status of big files and insert them into the
79 78 # appropriate list in the result. Also removes standin files
80 79 # from the listing. Revert to the original status if
81 80 # self.lfstatus is False.
82 81 # XXX large file status is buggy when used on repo proxy.
83 82 # XXX this needs to be investigated.
84 83 @localrepo.unfilteredmethod
85 84 def status(self, node1='.', node2=None, match=None, ignored=False,
86 85 clean=False, unknown=False, listsubrepos=False):
87 86 listignored, listclean, listunknown = ignored, clean, unknown
88 87 if not self.lfstatus:
89 88 return super(lfilesrepo, self).status(node1, node2, match,
90 89 listignored, listclean, listunknown, listsubrepos)
91 90 else:
92 91 # some calls in this function rely on the old version of status
93 92 self.lfstatus = False
94 93 ctx1 = self[node1]
95 94 ctx2 = self[node2]
96 95 working = ctx2.rev() is None
97 96 parentworking = working and ctx1 == self['.']
98 97
99 98 def inctx(file, ctx):
100 99 try:
101 100 if ctx.rev() is None:
102 101 return file in ctx.manifest()
103 102 ctx[file]
104 103 return True
105 104 except KeyError:
106 105 return False
107 106
108 107 if match is None:
109 108 match = match_.always(self.root, self.getcwd())
110 109
111 110 wlock = None
112 111 try:
113 112 try:
114 113 # updating the dirstate is optional
115 114 # so we don't wait on the lock
116 115 wlock = self.wlock(False)
117 116 except error.LockError:
118 117 pass
119 118
120 119 # First check if there were files specified on the
121 120 # command line. If there were, and none of them were
122 121 # largefiles, we should just bail here and let super
123 122 # handle it -- thus gaining a big performance boost.
124 123 lfdirstate = lfutil.openlfdirstate(ui, self)
125 124 if match.files() and not match.anypats():
126 125 for f in lfdirstate:
127 126 if match(f):
128 127 break
129 128 else:
130 129 return super(lfilesrepo, self).status(node1, node2,
131 130 match, listignored, listclean,
132 131 listunknown, listsubrepos)
133 132
134 133 # Create a copy of match that matches standins instead
135 134 # of largefiles.
136 135 def tostandins(files):
137 136 if not working:
138 137 return files
139 138 newfiles = []
140 139 dirstate = self.dirstate
141 140 for f in files:
142 141 sf = lfutil.standin(f)
143 142 if sf in dirstate:
144 143 newfiles.append(sf)
145 144 elif sf in dirstate.dirs():
146 145 # Directory entries could be regular or
147 146 # standin, check both
148 147 newfiles.extend((f, sf))
149 148 else:
150 149 newfiles.append(f)
151 150 return newfiles
152 151
153 152 m = copy.copy(match)
154 153 m._files = tostandins(m._files)
155 154
156 155 result = super(lfilesrepo, self).status(node1, node2, m,
157 156 ignored, clean, unknown, listsubrepos)
158 157 if working:
159 158
160 159 def sfindirstate(f):
161 160 sf = lfutil.standin(f)
162 161 dirstate = self.dirstate
163 162 return sf in dirstate or sf in dirstate.dirs()
164 163
165 164 match._files = [f for f in match._files
166 165 if sfindirstate(f)]
167 166 # Don't waste time getting the ignored and unknown
168 167 # files from lfdirstate
169 168 s = lfdirstate.status(match, [], False,
170 169 listclean, False)
171 170 (unsure, modified, added, removed, missing, _unknown,
172 171 _ignored, clean) = s
173 172 if parentworking:
174 173 for lfile in unsure:
175 174 standin = lfutil.standin(lfile)
176 175 if standin not in ctx1:
177 176 # from second parent
178 177 modified.append(lfile)
179 178 elif ctx1[standin].data().strip() \
180 179 != lfutil.hashfile(self.wjoin(lfile)):
181 180 modified.append(lfile)
182 181 else:
183 182 clean.append(lfile)
184 183 lfdirstate.normal(lfile)
185 184 else:
186 185 tocheck = unsure + modified + added + clean
187 186 modified, added, clean = [], [], []
188 187
189 188 for lfile in tocheck:
190 189 standin = lfutil.standin(lfile)
191 190 if inctx(standin, ctx1):
192 191 if ctx1[standin].data().strip() != \
193 192 lfutil.hashfile(self.wjoin(lfile)):
194 193 modified.append(lfile)
195 194 else:
196 195 clean.append(lfile)
197 196 else:
198 197 added.append(lfile)
199 198
200 199 # Standins no longer found in lfdirstate has been
201 200 # removed
202 201 for standin in ctx1.manifest():
203 202 if not lfutil.isstandin(standin):
204 203 continue
205 204 lfile = lfutil.splitstandin(standin)
206 205 if not match(lfile):
207 206 continue
208 207 if lfile not in lfdirstate:
209 208 removed.append(lfile)
210 209
211 210 # Filter result lists
212 211 result = list(result)
213 212
214 213 # Largefiles are not really removed when they're
215 214 # still in the normal dirstate. Likewise, normal
216 215 # files are not really removed if they are still in
217 216 # lfdirstate. This happens in merges where files
218 217 # change type.
219 218 removed = [f for f in removed
220 219 if f not in self.dirstate]
221 220 result[2] = [f for f in result[2]
222 221 if f not in lfdirstate]
223 222
224 223 lfiles = set(lfdirstate._map)
225 224 # Unknown files
226 225 result[4] = set(result[4]).difference(lfiles)
227 226 # Ignored files
228 227 result[5] = set(result[5]).difference(lfiles)
229 228 # combine normal files and largefiles
230 229 normals = [[fn for fn in filelist
231 230 if not lfutil.isstandin(fn)]
232 231 for filelist in result]
233 232 lfiles = (modified, added, removed, missing, [], [],
234 233 clean)
235 234 result = [sorted(list1 + list2)
236 235 for (list1, list2) in zip(normals, lfiles)]
237 236 else:
238 237 def toname(f):
239 238 if lfutil.isstandin(f):
240 239 return lfutil.splitstandin(f)
241 240 return f
242 241 result = [[toname(f) for f in items]
243 242 for items in result]
244 243
245 244 if wlock:
246 245 lfdirstate.write()
247 246
248 247 finally:
249 248 if wlock:
250 249 wlock.release()
251 250
252 251 if not listunknown:
253 252 result[4] = []
254 253 if not listignored:
255 254 result[5] = []
256 255 if not listclean:
257 256 result[6] = []
258 257 self.lfstatus = True
259 258 return result
260 259
261 260 # As part of committing, copy all of the largefiles into the
262 261 # cache.
263 262 def commitctx(self, *args, **kwargs):
264 263 node = super(lfilesrepo, self).commitctx(*args, **kwargs)
265 264 lfutil.copyalltostore(self, node)
266 265 return node
267 266
268 267 # Before commit, largefile standins have not had their
269 268 # contents updated to reflect the hash of their largefile.
270 269 # Do that here.
271 270 def commit(self, text="", user=None, date=None, match=None,
272 271 force=False, editor=False, extra={}):
273 272 orig = super(lfilesrepo, self).commit
274 273
275 274 wlock = self.wlock()
276 275 try:
277 276 # Case 0: Rebase or Transplant
278 277 # We have to take the time to pull down the new largefiles now.
279 278 # Otherwise, any largefiles that were modified in the
280 279 # destination changesets get overwritten, either by the rebase
281 280 # or in the first commit after the rebase or transplant.
282 281 # updatelfiles will update the dirstate to mark any pulled
283 282 # largefiles as modified
284 283 if getattr(self, "_isrebasing", False) or \
285 284 getattr(self, "_istransplanting", False):
286 285 lfcommands.updatelfiles(self.ui, self, filelist=None,
287 286 printmessage=False)
288 287 result = orig(text=text, user=user, date=date, match=match,
289 288 force=force, editor=editor, extra=extra)
290 289 return result
291 290 # Case 1: user calls commit with no specific files or
292 291 # include/exclude patterns: refresh and commit all files that
293 292 # are "dirty".
294 293 if ((match is None) or
295 294 (not match.anypats() and not match.files())):
296 295 # Spend a bit of time here to get a list of files we know
297 296 # are modified so we can compare only against those.
298 297 # It can cost a lot of time (several seconds)
299 298 # otherwise to update all standins if the largefiles are
300 299 # large.
301 300 lfdirstate = lfutil.openlfdirstate(ui, self)
302 301 dirtymatch = match_.always(self.root, self.getcwd())
303 302 s = lfdirstate.status(dirtymatch, [], False, False, False)
304 303 (unsure, modified, added, removed, _missing, _unknown,
305 304 _ignored, _clean) = s
306 305 modifiedfiles = unsure + modified + added + removed
307 306 lfiles = lfutil.listlfiles(self)
308 307 # this only loops through largefiles that exist (not
309 308 # removed/renamed)
310 309 for lfile in lfiles:
311 310 if lfile in modifiedfiles:
312 311 if os.path.exists(
313 312 self.wjoin(lfutil.standin(lfile))):
314 313 # this handles the case where a rebase is being
315 314 # performed and the working copy is not updated
316 315 # yet.
317 316 if os.path.exists(self.wjoin(lfile)):
318 317 lfutil.updatestandin(self,
319 318 lfutil.standin(lfile))
320 319 lfdirstate.normal(lfile)
321 320
322 321 result = orig(text=text, user=user, date=date, match=match,
323 322 force=force, editor=editor, extra=extra)
324 323
325 324 if result is not None:
326 325 for lfile in lfdirstate:
327 326 if lfile in modifiedfiles:
328 327 if (not os.path.exists(self.wjoin(
329 328 lfutil.standin(lfile)))) or \
330 329 (not os.path.exists(self.wjoin(lfile))):
331 330 lfdirstate.drop(lfile)
332 331
333 332 # This needs to be after commit; otherwise precommit hooks
334 333 # get the wrong status
335 334 lfdirstate.write()
336 335 return result
337 336
338 337 lfiles = lfutil.listlfiles(self)
339 338 match._files = self._subdirlfs(match.files(), lfiles)
340 339
341 340 # Case 2: user calls commit with specified patterns: refresh
342 341 # any matching big files.
343 342 smatcher = lfutil.composestandinmatcher(self, match)
344 343 standins = self.dirstate.walk(smatcher, [], False, False)
345 344
346 345 # No matching big files: get out of the way and pass control to
347 346 # the usual commit() method.
348 347 if not standins:
349 348 return orig(text=text, user=user, date=date, match=match,
350 349 force=force, editor=editor, extra=extra)
351 350
352 351 # Refresh all matching big files. It's possible that the
353 352 # commit will end up failing, in which case the big files will
354 353 # stay refreshed. No harm done: the user modified them and
355 354 # asked to commit them, so sooner or later we're going to
356 355 # refresh the standins. Might as well leave them refreshed.
357 356 lfdirstate = lfutil.openlfdirstate(ui, self)
358 357 for standin in standins:
359 358 lfile = lfutil.splitstandin(standin)
360 359 if lfdirstate[lfile] != 'r':
361 360 lfutil.updatestandin(self, standin)
362 361 lfdirstate.normal(lfile)
363 362 else:
364 363 lfdirstate.drop(lfile)
365 364
366 365 # Cook up a new matcher that only matches regular files or
367 366 # standins corresponding to the big files requested by the
368 367 # user. Have to modify _files to prevent commit() from
369 368 # complaining "not tracked" for big files.
370 369 match = copy.copy(match)
371 370 origmatchfn = match.matchfn
372 371
373 372 # Check both the list of largefiles and the list of
374 373 # standins because if a largefile was removed, it
375 374 # won't be in the list of largefiles at this point
376 375 match._files += sorted(standins)
377 376
378 377 actualfiles = []
379 378 for f in match._files:
380 379 fstandin = lfutil.standin(f)
381 380
382 381 # ignore known largefiles and standins
383 382 if f in lfiles or fstandin in standins:
384 383 continue
385 384
386 385 # append directory separator to avoid collisions
387 386 if not fstandin.endswith(os.sep):
388 387 fstandin += os.sep
389 388
390 389 actualfiles.append(f)
391 390 match._files = actualfiles
392 391
393 392 def matchfn(f):
394 393 if origmatchfn(f):
395 394 return f not in lfiles
396 395 else:
397 396 return f in standins
398 397
399 398 match.matchfn = matchfn
400 399 result = orig(text=text, user=user, date=date, match=match,
401 400 force=force, editor=editor, extra=extra)
402 401 # This needs to be after commit; otherwise precommit hooks
403 402 # get the wrong status
404 403 lfdirstate.write()
405 404 return result
406 405 finally:
407 406 wlock.release()
408 407
409 408 def push(self, remote, force=False, revs=None, newbranch=False):
410 409 if remote.local():
411 410 missing = set(self.requirements) - remote.local().supported
412 411 if missing:
413 412 msg = _("required features are not"
414 413 " supported in the destination:"
415 414 " %s") % (', '.join(sorted(missing)))
416 415 raise util.Abort(msg)
417 416
418 417 outgoing = discovery.findcommonoutgoing(repo, remote.peer(),
419 418 force=force)
420 419 if outgoing.missing:
421 420 toupload = set()
422 421 o = self.changelog.nodesbetween(outgoing.missing, revs)[0]
423 422 for n in o:
424 423 parents = [p for p in self.changelog.parents(n)
425 424 if p != node_.nullid]
426 425 ctx = self[n]
427 426 files = set(ctx.files())
428 427 if len(parents) == 2:
429 428 mc = ctx.manifest()
430 429 mp1 = ctx.parents()[0].manifest()
431 430 mp2 = ctx.parents()[1].manifest()
432 431 for f in mp1:
433 432 if f not in mc:
434 433 files.add(f)
435 434 for f in mp2:
436 435 if f not in mc:
437 436 files.add(f)
438 437 for f in mc:
439 438 if mc[f] != mp1.get(f, None) or mc[f] != mp2.get(f,
440 439 None):
441 440 files.add(f)
442 441
443 442 toupload = toupload.union(
444 443 set([ctx[f].data().strip()
445 444 for f in files
446 445 if lfutil.isstandin(f) and f in ctx]))
447 446 lfcommands.uploadlfiles(ui, self, remote, toupload)
448 447 return super(lfilesrepo, self).push(remote, force=force, revs=revs,
449 448 newbranch=newbranch)
450 449
451 450 def _subdirlfs(self, files, lfiles):
452 451 '''
453 452 Adjust matched file list
454 453 If we pass a directory to commit whose only commitable files
455 454 are largefiles, the core commit code aborts before finding
456 455 the largefiles.
457 456 So we do the following:
458 457 For directories that only have largefiles as matches,
459 458 we explicitly add the largefiles to the match list and remove
460 459 the directory.
461 460 In other cases, we leave the match list unmodified.
462 461 '''
463 462 actualfiles = []
464 463 dirs = []
465 464 regulars = []
466 465
467 466 for f in files:
468 467 if lfutil.isstandin(f + '/'):
469 468 raise util.Abort(
470 469 _('file "%s" is a largefile standin') % f,
471 470 hint=('commit the largefile itself instead'))
472 471 # Scan directories
473 472 if os.path.isdir(self.wjoin(f)):
474 473 dirs.append(f)
475 474 else:
476 475 regulars.append(f)
477 476
478 477 for f in dirs:
479 478 matcheddir = False
480 479 d = self.dirstate.normalize(f) + '/'
481 480 # Check for matched normal files
482 481 for mf in regulars:
483 482 if self.dirstate.normalize(mf).startswith(d):
484 483 actualfiles.append(f)
485 484 matcheddir = True
486 485 break
487 486 if not matcheddir:
488 487 # If no normal match, manually append
489 488 # any matching largefiles
490 489 for lf in lfiles:
491 490 if self.dirstate.normalize(lf).startswith(d):
492 491 actualfiles.append(lf)
493 492 if not matcheddir:
494 493 actualfiles.append(lfutil.standin(f))
495 494 matcheddir = True
496 495 # Nothing in dir, so readd it
497 496 # and let commit reject it
498 497 if not matcheddir:
499 498 actualfiles.append(f)
500 499
501 500 # Always add normal files
502 501 actualfiles += regulars
503 502 return actualfiles
504 503
505 504 repo.__class__ = lfilesrepo
506 505
507 506 def checkrequireslfiles(ui, repo, **kwargs):
508 507 if 'largefiles' not in repo.requirements and util.any(
509 508 lfutil.shortname+'/' in f[0] for f in repo.store.datafiles()):
510 509 repo.requirements.add('largefiles')
511 510 repo._writerequirements()
512 511
513 512 ui.setconfig('hooks', 'changegroup.lfiles', checkrequireslfiles)
514 513 ui.setconfig('hooks', 'commit.lfiles', checkrequireslfiles)
@@ -1,633 +1,639 b''
1 1 # hg.py - repository classes for mercurial
2 2 #
3 3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
4 4 # Copyright 2006 Vadim Gelfer <vadim.gelfer@gmail.com>
5 5 #
6 6 # This software may be used and distributed according to the terms of the
7 7 # GNU General Public License version 2 or any later version.
8 8
9 9 from i18n import _
10 10 from lock import release
11 11 from node import hex, nullid
12 12 import localrepo, bundlerepo, unionrepo, httppeer, sshpeer, statichttprepo
13 13 import bookmarks, lock, util, extensions, error, node, scmutil, phases, url
14 14 import cmdutil, discovery
15 15 import merge as mergemod
16 16 import verify as verifymod
17 17 import errno, os, shutil
18 18
19 19 def _local(path):
20 20 path = util.expandpath(util.urllocalpath(path))
21 21 return (os.path.isfile(path) and bundlerepo or localrepo)
22 22
23 23 def addbranchrevs(lrepo, other, branches, revs):
24 24 peer = other.peer() # a courtesy to callers using a localrepo for other
25 25 hashbranch, branches = branches
26 26 if not hashbranch and not branches:
27 27 return revs or None, revs and revs[0] or None
28 28 revs = revs and list(revs) or []
29 29 if not peer.capable('branchmap'):
30 30 if branches:
31 31 raise util.Abort(_("remote branch lookup not supported"))
32 32 revs.append(hashbranch)
33 33 return revs, revs[0]
34 34 branchmap = peer.branchmap()
35 35
36 36 def primary(branch):
37 37 if branch == '.':
38 38 if not lrepo:
39 39 raise util.Abort(_("dirstate branch not accessible"))
40 40 branch = lrepo.dirstate.branch()
41 41 if branch in branchmap:
42 42 revs.extend(node.hex(r) for r in reversed(branchmap[branch]))
43 43 return True
44 44 else:
45 45 return False
46 46
47 47 for branch in branches:
48 48 if not primary(branch):
49 49 raise error.RepoLookupError(_("unknown branch '%s'") % branch)
50 50 if hashbranch:
51 51 if not primary(hashbranch):
52 52 revs.append(hashbranch)
53 53 return revs, revs[0]
54 54
55 55 def parseurl(path, branches=None):
56 56 '''parse url#branch, returning (url, (branch, branches))'''
57 57
58 58 u = util.url(path)
59 59 branch = None
60 60 if u.fragment:
61 61 branch = u.fragment
62 62 u.fragment = None
63 63 return str(u), (branch, branches or [])
64 64
65 65 schemes = {
66 66 'bundle': bundlerepo,
67 67 'union': unionrepo,
68 68 'file': _local,
69 69 'http': httppeer,
70 70 'https': httppeer,
71 71 'ssh': sshpeer,
72 72 'static-http': statichttprepo,
73 73 }
74 74
75 75 def _peerlookup(path):
76 76 u = util.url(path)
77 77 scheme = u.scheme or 'file'
78 78 thing = schemes.get(scheme) or schemes['file']
79 79 try:
80 80 return thing(path)
81 81 except TypeError:
82 82 return thing
83 83
84 84 def islocal(repo):
85 85 '''return true if repo (or path pointing to repo) is local'''
86 86 if isinstance(repo, str):
87 87 try:
88 88 return _peerlookup(repo).islocal(repo)
89 89 except AttributeError:
90 90 return False
91 91 return repo.local()
92 92
93 93 def openpath(ui, path):
94 94 '''open path with open if local, url.open if remote'''
95 95 pathurl = util.url(path, parsequery=False, parsefragment=False)
96 96 if pathurl.islocal():
97 97 return util.posixfile(pathurl.localpath(), 'rb')
98 98 else:
99 99 return url.open(ui, path)
100 100
101 # a list of (ui, repo) functions called for wire peer initialization
102 wirepeersetupfuncs = []
103
101 104 def _peerorrepo(ui, path, create=False):
102 105 """return a repository object for the specified path"""
103 106 obj = _peerlookup(path).instance(ui, path, create)
104 107 ui = getattr(obj, "ui", ui)
105 108 for name, module in extensions.extensions(ui):
106 109 hook = getattr(module, 'reposetup', None)
107 110 if hook:
108 111 hook(ui, obj)
112 if not obj.local():
113 for f in wirepeersetupfuncs:
114 f(ui, obj)
109 115 return obj
110 116
111 117 def repository(ui, path='', create=False):
112 118 """return a repository object for the specified path"""
113 119 peer = _peerorrepo(ui, path, create)
114 120 repo = peer.local()
115 121 if not repo:
116 122 raise util.Abort(_("repository '%s' is not local") %
117 123 (path or peer.url()))
118 124 return repo.filtered('visible')
119 125
120 126 def peer(uiorrepo, opts, path, create=False):
121 127 '''return a repository peer for the specified path'''
122 128 rui = remoteui(uiorrepo, opts)
123 129 return _peerorrepo(rui, path, create).peer()
124 130
125 131 def defaultdest(source):
126 132 '''return default destination of clone if none is given'''
127 133 return os.path.basename(os.path.normpath(util.url(source).path or ''))
128 134
129 135 def share(ui, source, dest=None, update=True):
130 136 '''create a shared repository'''
131 137
132 138 if not islocal(source):
133 139 raise util.Abort(_('can only share local repositories'))
134 140
135 141 if not dest:
136 142 dest = defaultdest(source)
137 143 else:
138 144 dest = ui.expandpath(dest)
139 145
140 146 if isinstance(source, str):
141 147 origsource = ui.expandpath(source)
142 148 source, branches = parseurl(origsource)
143 149 srcrepo = repository(ui, source)
144 150 rev, checkout = addbranchrevs(srcrepo, srcrepo, branches, None)
145 151 else:
146 152 srcrepo = source.local()
147 153 origsource = source = srcrepo.url()
148 154 checkout = None
149 155
150 156 sharedpath = srcrepo.sharedpath # if our source is already sharing
151 157
152 158 root = os.path.realpath(dest)
153 159 roothg = os.path.join(root, '.hg')
154 160
155 161 if os.path.exists(roothg):
156 162 raise util.Abort(_('destination already exists'))
157 163
158 164 if not os.path.isdir(root):
159 165 os.mkdir(root)
160 166 util.makedir(roothg, notindexed=True)
161 167
162 168 requirements = ''
163 169 try:
164 170 requirements = srcrepo.opener.read('requires')
165 171 except IOError, inst:
166 172 if inst.errno != errno.ENOENT:
167 173 raise
168 174
169 175 requirements += 'shared\n'
170 176 util.writefile(os.path.join(roothg, 'requires'), requirements)
171 177 util.writefile(os.path.join(roothg, 'sharedpath'), sharedpath)
172 178
173 179 r = repository(ui, root)
174 180
175 181 default = srcrepo.ui.config('paths', 'default')
176 182 if default:
177 183 fp = r.opener("hgrc", "w", text=True)
178 184 fp.write("[paths]\n")
179 185 fp.write("default = %s\n" % default)
180 186 fp.close()
181 187
182 188 if update:
183 189 r.ui.status(_("updating working directory\n"))
184 190 if update is not True:
185 191 checkout = update
186 192 for test in (checkout, 'default', 'tip'):
187 193 if test is None:
188 194 continue
189 195 try:
190 196 uprev = r.lookup(test)
191 197 break
192 198 except error.RepoLookupError:
193 199 continue
194 200 _update(r, uprev)
195 201
196 202 def copystore(ui, srcrepo, destpath):
197 203 '''copy files from store of srcrepo in destpath
198 204
199 205 returns destlock
200 206 '''
201 207 destlock = None
202 208 try:
203 209 hardlink = None
204 210 num = 0
205 211 srcpublishing = srcrepo.ui.configbool('phases', 'publish', True)
206 212 srcvfs = scmutil.vfs(srcrepo.sharedpath)
207 213 dstvfs = scmutil.vfs(destpath)
208 214 for f in srcrepo.store.copylist():
209 215 if srcpublishing and f.endswith('phaseroots'):
210 216 continue
211 217 dstbase = os.path.dirname(f)
212 218 if dstbase and not dstvfs.exists(dstbase):
213 219 dstvfs.mkdir(dstbase)
214 220 if srcvfs.exists(f):
215 221 if f.endswith('data'):
216 222 # 'dstbase' may be empty (e.g. revlog format 0)
217 223 lockfile = os.path.join(dstbase, "lock")
218 224 # lock to avoid premature writing to the target
219 225 destlock = lock.lock(dstvfs, lockfile)
220 226 hardlink, n = util.copyfiles(srcvfs.join(f), dstvfs.join(f),
221 227 hardlink)
222 228 num += n
223 229 if hardlink:
224 230 ui.debug("linked %d files\n" % num)
225 231 else:
226 232 ui.debug("copied %d files\n" % num)
227 233 return destlock
228 234 except: # re-raises
229 235 release(destlock)
230 236 raise
231 237
232 238 def clone(ui, peeropts, source, dest=None, pull=False, rev=None,
233 239 update=True, stream=False, branch=None):
234 240 """Make a copy of an existing repository.
235 241
236 242 Create a copy of an existing repository in a new directory. The
237 243 source and destination are URLs, as passed to the repository
238 244 function. Returns a pair of repository peers, the source and
239 245 newly created destination.
240 246
241 247 The location of the source is added to the new repository's
242 248 .hg/hgrc file, as the default to be used for future pulls and
243 249 pushes.
244 250
245 251 If an exception is raised, the partly cloned/updated destination
246 252 repository will be deleted.
247 253
248 254 Arguments:
249 255
250 256 source: repository object or URL
251 257
252 258 dest: URL of destination repository to create (defaults to base
253 259 name of source repository)
254 260
255 261 pull: always pull from source repository, even in local case
256 262
257 263 stream: stream raw data uncompressed from repository (fast over
258 264 LAN, slow over WAN)
259 265
260 266 rev: revision to clone up to (implies pull=True)
261 267
262 268 update: update working directory after clone completes, if
263 269 destination is local repository (True means update to default rev,
264 270 anything else is treated as a revision)
265 271
266 272 branch: branches to clone
267 273 """
268 274
269 275 if isinstance(source, str):
270 276 origsource = ui.expandpath(source)
271 277 source, branch = parseurl(origsource, branch)
272 278 srcpeer = peer(ui, peeropts, source)
273 279 else:
274 280 srcpeer = source.peer() # in case we were called with a localrepo
275 281 branch = (None, branch or [])
276 282 origsource = source = srcpeer.url()
277 283 rev, checkout = addbranchrevs(srcpeer, srcpeer, branch, rev)
278 284
279 285 if dest is None:
280 286 dest = defaultdest(source)
281 287 ui.status(_("destination directory: %s\n") % dest)
282 288 else:
283 289 dest = ui.expandpath(dest)
284 290
285 291 dest = util.urllocalpath(dest)
286 292 source = util.urllocalpath(source)
287 293
288 294 if not dest:
289 295 raise util.Abort(_("empty destination path is not valid"))
290 296 if os.path.exists(dest):
291 297 if not os.path.isdir(dest):
292 298 raise util.Abort(_("destination '%s' already exists") % dest)
293 299 elif os.listdir(dest):
294 300 raise util.Abort(_("destination '%s' is not empty") % dest)
295 301
296 302 srclock = destlock = cleandir = None
297 303 srcrepo = srcpeer.local()
298 304 try:
299 305 abspath = origsource
300 306 if islocal(origsource):
301 307 abspath = os.path.abspath(util.urllocalpath(origsource))
302 308
303 309 if islocal(dest):
304 310 cleandir = dest
305 311
306 312 copy = False
307 313 if (srcrepo and srcrepo.cancopy() and islocal(dest)
308 314 and not phases.hassecret(srcrepo)):
309 315 copy = not pull and not rev
310 316
311 317 if copy:
312 318 try:
313 319 # we use a lock here because if we race with commit, we
314 320 # can end up with extra data in the cloned revlogs that's
315 321 # not pointed to by changesets, thus causing verify to
316 322 # fail
317 323 srclock = srcrepo.lock(wait=False)
318 324 except error.LockError:
319 325 copy = False
320 326
321 327 if copy:
322 328 srcrepo.hook('preoutgoing', throw=True, source='clone')
323 329 hgdir = os.path.realpath(os.path.join(dest, ".hg"))
324 330 if not os.path.exists(dest):
325 331 os.mkdir(dest)
326 332 else:
327 333 # only clean up directories we create ourselves
328 334 cleandir = hgdir
329 335 try:
330 336 destpath = hgdir
331 337 util.makedir(destpath, notindexed=True)
332 338 except OSError, inst:
333 339 if inst.errno == errno.EEXIST:
334 340 cleandir = None
335 341 raise util.Abort(_("destination '%s' already exists")
336 342 % dest)
337 343 raise
338 344
339 345 destlock = copystore(ui, srcrepo, destpath)
340 346
341 347 # Recomputing branch cache might be slow on big repos,
342 348 # so just copy it
343 349 dstcachedir = os.path.join(destpath, 'cache')
344 350 srcbranchcache = srcrepo.sjoin('cache/branch2')
345 351 dstbranchcache = os.path.join(dstcachedir, 'branch2')
346 352 if os.path.exists(srcbranchcache):
347 353 if not os.path.exists(dstcachedir):
348 354 os.mkdir(dstcachedir)
349 355 util.copyfile(srcbranchcache, dstbranchcache)
350 356
351 357 # we need to re-init the repo after manually copying the data
352 358 # into it
353 359 destpeer = peer(srcrepo, peeropts, dest)
354 360 srcrepo.hook('outgoing', source='clone',
355 361 node=node.hex(node.nullid))
356 362 else:
357 363 try:
358 364 destpeer = peer(srcrepo or ui, peeropts, dest, create=True)
359 365 # only pass ui when no srcrepo
360 366 except OSError, inst:
361 367 if inst.errno == errno.EEXIST:
362 368 cleandir = None
363 369 raise util.Abort(_("destination '%s' already exists")
364 370 % dest)
365 371 raise
366 372
367 373 revs = None
368 374 if rev:
369 375 if not srcpeer.capable('lookup'):
370 376 raise util.Abort(_("src repository does not support "
371 377 "revision lookup and so doesn't "
372 378 "support clone by revision"))
373 379 revs = [srcpeer.lookup(r) for r in rev]
374 380 checkout = revs[0]
375 381 if destpeer.local():
376 382 destpeer.local().clone(srcpeer, heads=revs, stream=stream)
377 383 elif srcrepo:
378 384 srcrepo.push(destpeer, revs=revs)
379 385 else:
380 386 raise util.Abort(_("clone from remote to remote not supported"))
381 387
382 388 cleandir = None
383 389
384 390 # clone all bookmarks except divergent ones
385 391 destrepo = destpeer.local()
386 392 if destrepo and srcpeer.capable("pushkey"):
387 393 rb = srcpeer.listkeys('bookmarks')
388 394 marks = destrepo._bookmarks
389 395 for k, n in rb.iteritems():
390 396 try:
391 397 m = destrepo.lookup(n)
392 398 marks[k] = m
393 399 except error.RepoLookupError:
394 400 pass
395 401 if rb:
396 402 marks.write()
397 403 elif srcrepo and destpeer.capable("pushkey"):
398 404 for k, n in srcrepo._bookmarks.iteritems():
399 405 destpeer.pushkey('bookmarks', k, '', hex(n))
400 406
401 407 if destrepo:
402 408 fp = destrepo.opener("hgrc", "w", text=True)
403 409 fp.write("[paths]\n")
404 410 u = util.url(abspath)
405 411 u.passwd = None
406 412 defaulturl = str(u)
407 413 fp.write("default = %s\n" % defaulturl)
408 414 fp.close()
409 415
410 416 destrepo.ui.setconfig('paths', 'default', defaulturl)
411 417
412 418 if update:
413 419 if update is not True:
414 420 checkout = srcpeer.lookup(update)
415 421 uprev = None
416 422 status = None
417 423 if checkout is not None:
418 424 try:
419 425 uprev = destrepo.lookup(checkout)
420 426 except error.RepoLookupError:
421 427 pass
422 428 if uprev is None:
423 429 try:
424 430 uprev = destrepo._bookmarks['@']
425 431 update = '@'
426 432 bn = destrepo[uprev].branch()
427 433 if bn == 'default':
428 434 status = _("updating to bookmark @\n")
429 435 else:
430 436 status = _("updating to bookmark @ on branch %s\n"
431 437 % bn)
432 438 except KeyError:
433 439 try:
434 440 uprev = destrepo.branchtip('default')
435 441 except error.RepoLookupError:
436 442 uprev = destrepo.lookup('tip')
437 443 if not status:
438 444 bn = destrepo[uprev].branch()
439 445 status = _("updating to branch %s\n") % bn
440 446 destrepo.ui.status(status)
441 447 _update(destrepo, uprev)
442 448 if update in destrepo._bookmarks:
443 449 bookmarks.setcurrent(destrepo, update)
444 450 finally:
445 451 release(srclock, destlock)
446 452 if cleandir is not None:
447 453 shutil.rmtree(cleandir, True)
448 454 if srcpeer is not None:
449 455 srcpeer.close()
450 456 return srcpeer, destpeer
451 457
452 458 def _showstats(repo, stats):
453 459 repo.ui.status(_("%d files updated, %d files merged, "
454 460 "%d files removed, %d files unresolved\n") % stats)
455 461
456 462 def updaterepo(repo, node, overwrite):
457 463 """Update the working directory to node.
458 464
459 465 When overwrite is set, changes are clobbered, merged else
460 466
461 467 returns stats (see pydoc mercurial.merge.applyupdates)"""
462 468 return mergemod.update(repo, node, False, overwrite, None)
463 469
464 470 def update(repo, node):
465 471 """update the working directory to node, merging linear changes"""
466 472 stats = updaterepo(repo, node, False)
467 473 _showstats(repo, stats)
468 474 if stats[3]:
469 475 repo.ui.status(_("use 'hg resolve' to retry unresolved file merges\n"))
470 476 return stats[3] > 0
471 477
472 478 # naming conflict in clone()
473 479 _update = update
474 480
475 481 def clean(repo, node, show_stats=True):
476 482 """forcibly switch the working directory to node, clobbering changes"""
477 483 stats = updaterepo(repo, node, True)
478 484 util.unlinkpath(repo.join('graftstate'), ignoremissing=True)
479 485 if show_stats:
480 486 _showstats(repo, stats)
481 487 return stats[3] > 0
482 488
483 489 def merge(repo, node, force=None, remind=True):
484 490 """Branch merge with node, resolving changes. Return true if any
485 491 unresolved conflicts."""
486 492 stats = mergemod.update(repo, node, True, force, False)
487 493 _showstats(repo, stats)
488 494 if stats[3]:
489 495 repo.ui.status(_("use 'hg resolve' to retry unresolved file merges "
490 496 "or 'hg update -C .' to abandon\n"))
491 497 elif remind:
492 498 repo.ui.status(_("(branch merge, don't forget to commit)\n"))
493 499 return stats[3] > 0
494 500
495 501 def _incoming(displaychlist, subreporecurse, ui, repo, source,
496 502 opts, buffered=False):
497 503 """
498 504 Helper for incoming / gincoming.
499 505 displaychlist gets called with
500 506 (remoterepo, incomingchangesetlist, displayer) parameters,
501 507 and is supposed to contain only code that can't be unified.
502 508 """
503 509 source, branches = parseurl(ui.expandpath(source), opts.get('branch'))
504 510 other = peer(repo, opts, source)
505 511 ui.status(_('comparing with %s\n') % util.hidepassword(source))
506 512 revs, checkout = addbranchrevs(repo, other, branches, opts.get('rev'))
507 513
508 514 if revs:
509 515 revs = [other.lookup(rev) for rev in revs]
510 516 other, chlist, cleanupfn = bundlerepo.getremotechanges(ui, repo, other,
511 517 revs, opts["bundle"], opts["force"])
512 518 try:
513 519 if not chlist:
514 520 ui.status(_("no changes found\n"))
515 521 return subreporecurse()
516 522
517 523 displayer = cmdutil.show_changeset(ui, other, opts, buffered)
518 524 displaychlist(other, chlist, displayer)
519 525 displayer.close()
520 526 finally:
521 527 cleanupfn()
522 528 subreporecurse()
523 529 return 0 # exit code is zero since we found incoming changes
524 530
525 531 def incoming(ui, repo, source, opts):
526 532 def subreporecurse():
527 533 ret = 1
528 534 if opts.get('subrepos'):
529 535 ctx = repo[None]
530 536 for subpath in sorted(ctx.substate):
531 537 sub = ctx.sub(subpath)
532 538 ret = min(ret, sub.incoming(ui, source, opts))
533 539 return ret
534 540
535 541 def display(other, chlist, displayer):
536 542 limit = cmdutil.loglimit(opts)
537 543 if opts.get('newest_first'):
538 544 chlist.reverse()
539 545 count = 0
540 546 for n in chlist:
541 547 if limit is not None and count >= limit:
542 548 break
543 549 parents = [p for p in other.changelog.parents(n) if p != nullid]
544 550 if opts.get('no_merges') and len(parents) == 2:
545 551 continue
546 552 count += 1
547 553 displayer.show(other[n])
548 554 return _incoming(display, subreporecurse, ui, repo, source, opts)
549 555
550 556 def _outgoing(ui, repo, dest, opts):
551 557 dest = ui.expandpath(dest or 'default-push', dest or 'default')
552 558 dest, branches = parseurl(dest, opts.get('branch'))
553 559 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
554 560 revs, checkout = addbranchrevs(repo, repo, branches, opts.get('rev'))
555 561 if revs:
556 562 revs = [repo.lookup(rev) for rev in scmutil.revrange(repo, revs)]
557 563
558 564 other = peer(repo, opts, dest)
559 565 outgoing = discovery.findcommonoutgoing(repo.unfiltered(), other, revs,
560 566 force=opts.get('force'))
561 567 o = outgoing.missing
562 568 if not o:
563 569 scmutil.nochangesfound(repo.ui, repo, outgoing.excluded)
564 570 return None
565 571 return o
566 572
567 573 def outgoing(ui, repo, dest, opts):
568 574 def recurse():
569 575 ret = 1
570 576 if opts.get('subrepos'):
571 577 ctx = repo[None]
572 578 for subpath in sorted(ctx.substate):
573 579 sub = ctx.sub(subpath)
574 580 ret = min(ret, sub.outgoing(ui, dest, opts))
575 581 return ret
576 582
577 583 limit = cmdutil.loglimit(opts)
578 584 o = _outgoing(ui, repo, dest, opts)
579 585 if o is None:
580 586 return recurse()
581 587
582 588 if opts.get('newest_first'):
583 589 o.reverse()
584 590 displayer = cmdutil.show_changeset(ui, repo, opts)
585 591 count = 0
586 592 for n in o:
587 593 if limit is not None and count >= limit:
588 594 break
589 595 parents = [p for p in repo.changelog.parents(n) if p != nullid]
590 596 if opts.get('no_merges') and len(parents) == 2:
591 597 continue
592 598 count += 1
593 599 displayer.show(repo[n])
594 600 displayer.close()
595 601 recurse()
596 602 return 0 # exit code is zero since we found outgoing changes
597 603
598 604 def revert(repo, node, choose):
599 605 """revert changes to revision in node without updating dirstate"""
600 606 return mergemod.update(repo, node, False, True, choose)[3] > 0
601 607
602 608 def verify(repo):
603 609 """verify the consistency of a repository"""
604 610 return verifymod.verify(repo)
605 611
606 612 def remoteui(src, opts):
607 613 'build a remote ui from ui or repo and opts'
608 614 if util.safehasattr(src, 'baseui'): # looks like a repository
609 615 dst = src.baseui.copy() # drop repo-specific config
610 616 src = src.ui # copy target options from repo
611 617 else: # assume it's a global ui object
612 618 dst = src.copy() # keep all global options
613 619
614 620 # copy ssh-specific options
615 621 for o in 'ssh', 'remotecmd':
616 622 v = opts.get(o) or src.config('ui', o)
617 623 if v:
618 624 dst.setconfig("ui", o, v)
619 625
620 626 # copy bundle-specific options
621 627 r = src.config('bundle', 'mainreporoot')
622 628 if r:
623 629 dst.setconfig('bundle', 'mainreporoot', r)
624 630
625 631 # copy selected local settings to the remote ui
626 632 for sect in ('auth', 'hostfingerprints', 'http_proxy'):
627 633 for key, val in src.configitems(sect):
628 634 dst.setconfig(sect, key, val)
629 635 v = src.config('web', 'cacerts')
630 636 if v:
631 637 dst.setconfig('web', 'cacerts', util.expandpath(v))
632 638
633 639 return dst
@@ -1,2288 +1,2314 b''
1 1 $ USERCACHE="$TESTTMP/cache"; export USERCACHE
2 2 $ mkdir "${USERCACHE}"
3 3 $ cat >> $HGRCPATH <<EOF
4 4 > [extensions]
5 5 > largefiles=
6 6 > purge=
7 7 > rebase=
8 8 > transplant=
9 9 > [phases]
10 10 > publish=False
11 11 > [largefiles]
12 12 > minsize=2
13 13 > patterns=glob:**.dat
14 14 > usercache=${USERCACHE}
15 15 > [hooks]
16 16 > precommit=sh -c "echo \\"Invoking status precommit hook\\"; hg status"
17 17 > EOF
18 18
19 19 Create the repo with a couple of revisions of both large and normal
20 20 files.
21 21 Test status and dirstate of largefiles and that summary output is correct.
22 22
23 23 $ hg init a
24 24 $ cd a
25 25 $ mkdir sub
26 26 $ echo normal1 > normal1
27 27 $ echo normal2 > sub/normal2
28 28 $ echo large1 > large1
29 29 $ echo large2 > sub/large2
30 30 $ hg add normal1 sub/normal2
31 31 $ hg add --large large1 sub/large2
32 32 $ hg commit -m "add files"
33 33 Invoking status precommit hook
34 34 A large1
35 35 A normal1
36 36 A sub/large2
37 37 A sub/normal2
38 38 $ touch large1 sub/large2
39 39 $ sleep 1
40 40 $ hg st
41 41 $ hg debugstate --nodates
42 42 n 644 41 .hglf/large1
43 43 n 644 41 .hglf/sub/large2
44 44 n 644 8 normal1
45 45 n 644 8 sub/normal2
46 46 $ hg debugstate --large
47 47 n 644 7 large1
48 48 n 644 7 sub/large2
49 49 $ echo normal11 > normal1
50 50 $ echo normal22 > sub/normal2
51 51 $ echo large11 > large1
52 52 $ echo large22 > sub/large2
53 53 $ hg commit -m "edit files"
54 54 Invoking status precommit hook
55 55 M large1
56 56 M normal1
57 57 M sub/large2
58 58 M sub/normal2
59 59 $ hg sum --large
60 60 parent: 1:ce8896473775 tip
61 61 edit files
62 62 branch: default
63 63 commit: (clean)
64 64 update: (current)
65 65 largefiles: (no remote repo)
66 66
67 67 Commit preserved largefile contents.
68 68
69 69 $ cat normal1
70 70 normal11
71 71 $ cat large1
72 72 large11
73 73 $ cat sub/normal2
74 74 normal22
75 75 $ cat sub/large2
76 76 large22
77 77
78 78 Test status, subdir and unknown files
79 79
80 80 $ echo unknown > sub/unknown
81 81 $ hg st --all
82 82 ? sub/unknown
83 83 C large1
84 84 C normal1
85 85 C sub/large2
86 86 C sub/normal2
87 87 $ hg st --all sub
88 88 ? sub/unknown
89 89 C sub/large2
90 90 C sub/normal2
91 91 $ rm sub/unknown
92 92
93 93 Test messages and exit codes for remove warning cases
94 94
95 95 $ hg remove -A large1
96 96 not removing large1: file still exists
97 97 [1]
98 98 $ echo 'modified' > large1
99 99 $ hg remove large1
100 100 not removing large1: file is modified (use -f to force removal)
101 101 [1]
102 102 $ echo 'new' > normalnew
103 103 $ hg add normalnew
104 104 $ echo 'new' > largenew
105 105 $ hg add --large normalnew
106 106 normalnew already tracked!
107 107 $ hg remove normalnew largenew
108 108 not removing largenew: file is untracked
109 109 not removing normalnew: file has been marked for add (use forget to undo)
110 110 [1]
111 111 $ rm normalnew largenew
112 112 $ hg up -Cq
113 113
114 114 Remove both largefiles and normal files.
115 115
116 116 $ hg remove normal1 large1
117 117 $ hg status large1
118 118 R large1
119 119 $ hg commit -m "remove files"
120 120 Invoking status precommit hook
121 121 R large1
122 122 R normal1
123 123 $ ls
124 124 sub
125 125 $ echo "testlargefile" > large1-test
126 126 $ hg add --large large1-test
127 127 $ hg st
128 128 A large1-test
129 129 $ hg rm large1-test
130 130 not removing large1-test: file has been marked for add (use forget to undo)
131 131 [1]
132 132 $ hg st
133 133 A large1-test
134 134 $ hg forget large1-test
135 135 $ hg st
136 136 ? large1-test
137 137 $ hg remove large1-test
138 138 not removing large1-test: file is untracked
139 139 [1]
140 140 $ hg forget large1-test
141 141 not removing large1-test: file is already untracked
142 142 [1]
143 143 $ rm large1-test
144 144
145 145 Copy both largefiles and normal files (testing that status output is correct).
146 146
147 147 $ hg cp sub/normal2 normal1
148 148 $ hg cp sub/large2 large1
149 149 $ hg commit -m "copy files"
150 150 Invoking status precommit hook
151 151 A large1
152 152 A normal1
153 153 $ cat normal1
154 154 normal22
155 155 $ cat large1
156 156 large22
157 157
158 158 Test moving largefiles and verify that normal files are also unaffected.
159 159
160 160 $ hg mv normal1 normal3
161 161 $ hg mv large1 large3
162 162 $ hg mv sub/normal2 sub/normal4
163 163 $ hg mv sub/large2 sub/large4
164 164 $ hg commit -m "move files"
165 165 Invoking status precommit hook
166 166 A large3
167 167 A normal3
168 168 A sub/large4
169 169 A sub/normal4
170 170 R large1
171 171 R normal1
172 172 R sub/large2
173 173 R sub/normal2
174 174 $ cat normal3
175 175 normal22
176 176 $ cat large3
177 177 large22
178 178 $ cat sub/normal4
179 179 normal22
180 180 $ cat sub/large4
181 181 large22
182 182
183 183 Test copies and moves from a directory other than root (issue3516)
184 184
185 185 $ cd ..
186 186 $ hg init lf_cpmv
187 187 $ cd lf_cpmv
188 188 $ mkdir dira
189 189 $ mkdir dira/dirb
190 190 $ touch dira/dirb/largefile
191 191 $ hg add --large dira/dirb/largefile
192 192 $ hg commit -m "added"
193 193 Invoking status precommit hook
194 194 A dira/dirb/largefile
195 195 $ cd dira
196 196 $ hg cp dirb/largefile foo/largefile
197 197 $ hg ci -m "deep copy"
198 198 Invoking status precommit hook
199 199 A dira/foo/largefile
200 200 $ find . | sort
201 201 .
202 202 ./dirb
203 203 ./dirb/largefile
204 204 ./foo
205 205 ./foo/largefile
206 206 $ hg mv foo/largefile baz/largefile
207 207 $ hg ci -m "moved"
208 208 Invoking status precommit hook
209 209 A dira/baz/largefile
210 210 R dira/foo/largefile
211 211 $ find . | sort
212 212 .
213 213 ./baz
214 214 ./baz/largefile
215 215 ./dirb
216 216 ./dirb/largefile
217 217 ./foo
218 218 $ cd ../../a
219 219
220 220 #if serve
221 221 Test display of largefiles in hgweb
222 222
223 223 $ hg serve -d -p $HGPORT --pid-file ../hg.pid
224 224 $ cat ../hg.pid >> $DAEMON_PIDS
225 225 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT 'file/tip/?style=raw'
226 226 200 Script output follows
227 227
228 228
229 229 drwxr-xr-x sub
230 230 -rw-r--r-- 41 large3
231 231 -rw-r--r-- 9 normal3
232 232
233 233
234 234 $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT 'file/tip/sub/?style=raw'
235 235 200 Script output follows
236 236
237 237
238 238 -rw-r--r-- 41 large4
239 239 -rw-r--r-- 9 normal4
240 240
241 241
242 242 $ "$TESTDIR/killdaemons.py" $DAEMON_PIDS
243 243 #endif
244 244
245 245 Test archiving the various revisions. These hit corner cases known with
246 246 archiving.
247 247
248 248 $ hg archive -r 0 ../archive0
249 249 $ hg archive -r 1 ../archive1
250 250 $ hg archive -r 2 ../archive2
251 251 $ hg archive -r 3 ../archive3
252 252 $ hg archive -r 4 ../archive4
253 253 $ cd ../archive0
254 254 $ cat normal1
255 255 normal1
256 256 $ cat large1
257 257 large1
258 258 $ cat sub/normal2
259 259 normal2
260 260 $ cat sub/large2
261 261 large2
262 262 $ cd ../archive1
263 263 $ cat normal1
264 264 normal11
265 265 $ cat large1
266 266 large11
267 267 $ cat sub/normal2
268 268 normal22
269 269 $ cat sub/large2
270 270 large22
271 271 $ cd ../archive2
272 272 $ ls
273 273 sub
274 274 $ cat sub/normal2
275 275 normal22
276 276 $ cat sub/large2
277 277 large22
278 278 $ cd ../archive3
279 279 $ cat normal1
280 280 normal22
281 281 $ cat large1
282 282 large22
283 283 $ cat sub/normal2
284 284 normal22
285 285 $ cat sub/large2
286 286 large22
287 287 $ cd ../archive4
288 288 $ cat normal3
289 289 normal22
290 290 $ cat large3
291 291 large22
292 292 $ cat sub/normal4
293 293 normal22
294 294 $ cat sub/large4
295 295 large22
296 296
297 297 Commit corner case: specify files to commit.
298 298
299 299 $ cd ../a
300 300 $ echo normal3 > normal3
301 301 $ echo large3 > large3
302 302 $ echo normal4 > sub/normal4
303 303 $ echo large4 > sub/large4
304 304 $ hg commit normal3 large3 sub/normal4 sub/large4 -m "edit files again"
305 305 Invoking status precommit hook
306 306 M large3
307 307 M normal3
308 308 M sub/large4
309 309 M sub/normal4
310 310 $ cat normal3
311 311 normal3
312 312 $ cat large3
313 313 large3
314 314 $ cat sub/normal4
315 315 normal4
316 316 $ cat sub/large4
317 317 large4
318 318
319 319 One more commit corner case: commit from a subdirectory.
320 320
321 321 $ cd ../a
322 322 $ echo normal33 > normal3
323 323 $ echo large33 > large3
324 324 $ echo normal44 > sub/normal4
325 325 $ echo large44 > sub/large4
326 326 $ cd sub
327 327 $ hg commit -m "edit files yet again"
328 328 Invoking status precommit hook
329 329 M large3
330 330 M normal3
331 331 M sub/large4
332 332 M sub/normal4
333 333 $ cat ../normal3
334 334 normal33
335 335 $ cat ../large3
336 336 large33
337 337 $ cat normal4
338 338 normal44
339 339 $ cat large4
340 340 large44
341 341
342 342 Committing standins is not allowed.
343 343
344 344 $ cd ..
345 345 $ echo large3 > large3
346 346 $ hg commit .hglf/large3 -m "try to commit standin"
347 347 abort: file ".hglf/large3" is a largefile standin
348 348 (commit the largefile itself instead)
349 349 [255]
350 350
351 351 Corner cases for adding largefiles.
352 352
353 353 $ echo large5 > large5
354 354 $ hg add --large large5
355 355 $ hg add --large large5
356 356 large5 already a largefile
357 357 $ mkdir sub2
358 358 $ echo large6 > sub2/large6
359 359 $ echo large7 > sub2/large7
360 360 $ hg add --large sub2
361 361 adding sub2/large6 as a largefile (glob)
362 362 adding sub2/large7 as a largefile (glob)
363 363 $ hg st
364 364 M large3
365 365 A large5
366 366 A sub2/large6
367 367 A sub2/large7
368 368
369 369 Committing directories containing only largefiles.
370 370
371 371 $ mkdir -p z/y/x/m
372 372 $ touch z/y/x/m/large1
373 373 $ touch z/y/x/large2
374 374 $ hg add --large z/y/x/m/large1 z/y/x/large2
375 375 $ hg commit -m "Subdir with directory only containing largefiles" z
376 376 Invoking status precommit hook
377 377 M large3
378 378 A large5
379 379 A sub2/large6
380 380 A sub2/large7
381 381 A z/y/x/large2
382 382 A z/y/x/m/large1
383 383 $ hg rollback --quiet
384 384 $ touch z/y/x/m/normal
385 385 $ hg add z/y/x/m/normal
386 386 $ hg commit -m "Subdir with mixed contents" z
387 387 Invoking status precommit hook
388 388 M large3
389 389 A large5
390 390 A sub2/large6
391 391 A sub2/large7
392 392 A z/y/x/large2
393 393 A z/y/x/m/large1
394 394 A z/y/x/m/normal
395 395 $ hg st
396 396 M large3
397 397 A large5
398 398 A sub2/large6
399 399 A sub2/large7
400 400 $ hg rollback --quiet
401 401 $ hg revert z/y/x/large2 z/y/x/m/large1
402 402 $ rm z/y/x/large2 z/y/x/m/large1
403 403 $ hg commit -m "Subdir with normal contents" z
404 404 Invoking status precommit hook
405 405 M large3
406 406 A large5
407 407 A sub2/large6
408 408 A sub2/large7
409 409 A z/y/x/m/normal
410 410 $ hg st
411 411 M large3
412 412 A large5
413 413 A sub2/large6
414 414 A sub2/large7
415 415 $ hg rollback --quiet
416 416 $ hg revert --quiet z
417 417 $ hg commit -m "Empty subdir" z
418 418 abort: z: no match under directory!
419 419 [255]
420 420 $ rm -rf z
421 421 $ hg ci -m "standin" .hglf
422 422 abort: file ".hglf" is a largefile standin
423 423 (commit the largefile itself instead)
424 424 [255]
425 425
426 426 Test "hg status" with combination of 'file pattern' and 'directory
427 427 pattern' for largefiles:
428 428
429 429 $ hg status sub2/large6 sub2
430 430 A sub2/large6
431 431 A sub2/large7
432 432
433 433 Config settings (pattern **.dat, minsize 2 MB) are respected.
434 434
435 435 $ echo testdata > test.dat
436 436 $ dd bs=1k count=2k if=/dev/zero of=reallylarge > /dev/null 2> /dev/null
437 437 $ hg add
438 438 adding reallylarge as a largefile
439 439 adding test.dat as a largefile
440 440
441 441 Test that minsize and --lfsize handle float values;
442 442 also tests that --lfsize overrides largefiles.minsize.
443 443 (0.250 MB = 256 kB = 262144 B)
444 444
445 445 $ dd if=/dev/zero of=ratherlarge bs=1024 count=256 > /dev/null 2> /dev/null
446 446 $ dd if=/dev/zero of=medium bs=1024 count=128 > /dev/null 2> /dev/null
447 447 $ hg --config largefiles.minsize=.25 add
448 448 adding ratherlarge as a largefile
449 449 adding medium
450 450 $ hg forget medium
451 451 $ hg --config largefiles.minsize=.25 add --lfsize=.125
452 452 adding medium as a largefile
453 453 $ dd if=/dev/zero of=notlarge bs=1024 count=127 > /dev/null 2> /dev/null
454 454 $ hg --config largefiles.minsize=.25 add --lfsize=.125
455 455 adding notlarge
456 456 $ hg forget notlarge
457 457
458 458 Test forget on largefiles.
459 459
460 460 $ hg forget large3 large5 test.dat reallylarge ratherlarge medium
461 461 $ hg commit -m "add/edit more largefiles"
462 462 Invoking status precommit hook
463 463 A sub2/large6
464 464 A sub2/large7
465 465 R large3
466 466 ? large5
467 467 ? medium
468 468 ? notlarge
469 469 ? ratherlarge
470 470 ? reallylarge
471 471 ? test.dat
472 472 $ hg st
473 473 ? large3
474 474 ? large5
475 475 ? medium
476 476 ? notlarge
477 477 ? ratherlarge
478 478 ? reallylarge
479 479 ? test.dat
480 480
481 481 Purge with largefiles: verify that largefiles are still in the working
482 482 dir after a purge.
483 483
484 484 $ hg purge --all
485 485 $ cat sub/large4
486 486 large44
487 487 $ cat sub2/large6
488 488 large6
489 489 $ cat sub2/large7
490 490 large7
491 491
492 492 Test addremove: verify that files that should be added as largfiles are added as
493 493 such and that already-existing largfiles are not added as normal files by
494 494 accident.
495 495
496 496 $ rm normal3
497 497 $ rm sub/large4
498 498 $ echo "testing addremove with patterns" > testaddremove.dat
499 499 $ echo "normaladdremove" > normaladdremove
500 500 $ hg addremove
501 501 removing sub/large4
502 502 adding testaddremove.dat as a largefile
503 503 removing normal3
504 504 adding normaladdremove
505 505
506 506 Test addremove with -R
507 507
508 508 $ hg up -C
509 509 getting changed largefiles
510 510 1 largefiles updated, 0 removed
511 511 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
512 512 $ rm normal3
513 513 $ rm sub/large4
514 514 $ echo "testing addremove with patterns" > testaddremove.dat
515 515 $ echo "normaladdremove" > normaladdremove
516 516 $ cd ..
517 517 $ hg -R a addremove
518 518 removing sub/large4
519 519 adding a/testaddremove.dat as a largefile (glob)
520 520 removing normal3
521 521 adding normaladdremove
522 522 $ cd a
523 523
524 524 Test 3364
525 525 $ hg clone . ../addrm
526 526 updating to branch default
527 527 getting changed largefiles
528 528 3 largefiles updated, 0 removed
529 529 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
530 530 $ cd ../addrm
531 531 $ cat >> .hg/hgrc <<EOF
532 532 > [hooks]
533 533 > post-commit.stat=sh -c "echo \\"Invoking status postcommit hook\\"; hg status -A"
534 534 > EOF
535 535 $ touch foo
536 536 $ hg add --large foo
537 537 $ hg ci -m "add foo"
538 538 Invoking status precommit hook
539 539 A foo
540 540 Invoking status postcommit hook
541 541 C foo
542 542 C normal3
543 543 C sub/large4
544 544 C sub/normal4
545 545 C sub2/large6
546 546 C sub2/large7
547 547 $ rm foo
548 548 $ hg st
549 549 ! foo
550 550 hmm.. no precommit invoked, but there is a postcommit??
551 551 $ hg ci -m "will not checkin"
552 552 nothing changed
553 553 Invoking status postcommit hook
554 554 ! foo
555 555 C normal3
556 556 C sub/large4
557 557 C sub/normal4
558 558 C sub2/large6
559 559 C sub2/large7
560 560 [1]
561 561 $ hg addremove
562 562 removing foo
563 563 $ hg st
564 564 R foo
565 565 $ hg ci -m "used to say nothing changed"
566 566 Invoking status precommit hook
567 567 R foo
568 568 Invoking status postcommit hook
569 569 C normal3
570 570 C sub/large4
571 571 C sub/normal4
572 572 C sub2/large6
573 573 C sub2/large7
574 574 $ hg st
575 575
576 576 Test 3507 (both normal files and largefiles were a problem)
577 577
578 578 $ touch normal
579 579 $ touch large
580 580 $ hg add normal
581 581 $ hg add --large large
582 582 $ hg ci -m "added"
583 583 Invoking status precommit hook
584 584 A large
585 585 A normal
586 586 Invoking status postcommit hook
587 587 C large
588 588 C normal
589 589 C normal3
590 590 C sub/large4
591 591 C sub/normal4
592 592 C sub2/large6
593 593 C sub2/large7
594 594 $ hg remove normal
595 595 $ hg addremove --traceback
596 596 $ hg ci -m "addremoved normal"
597 597 Invoking status precommit hook
598 598 R normal
599 599 Invoking status postcommit hook
600 600 C large
601 601 C normal3
602 602 C sub/large4
603 603 C sub/normal4
604 604 C sub2/large6
605 605 C sub2/large7
606 606 $ hg up -C '.^'
607 607 getting changed largefiles
608 608 0 largefiles updated, 0 removed
609 609 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
610 610 $ hg remove large
611 611 $ hg addremove --traceback
612 612 $ hg ci -m "removed large"
613 613 Invoking status precommit hook
614 614 R large
615 615 created new head
616 616 Invoking status postcommit hook
617 617 C normal
618 618 C normal3
619 619 C sub/large4
620 620 C sub/normal4
621 621 C sub2/large6
622 622 C sub2/large7
623 623
624 624 Test commit -A (issue 3542)
625 625 $ echo large8 > large8
626 626 $ hg add --large large8
627 627 $ hg ci -Am 'this used to add large8 as normal and commit both'
628 628 Invoking status precommit hook
629 629 A large8
630 630 Invoking status postcommit hook
631 631 C large8
632 632 C normal
633 633 C normal3
634 634 C sub/large4
635 635 C sub/normal4
636 636 C sub2/large6
637 637 C sub2/large7
638 638 $ rm large8
639 639 $ hg ci -Am 'this used to not notice the rm'
640 640 removing large8
641 641 Invoking status precommit hook
642 642 R large8
643 643 Invoking status postcommit hook
644 644 C normal
645 645 C normal3
646 646 C sub/large4
647 647 C sub/normal4
648 648 C sub2/large6
649 649 C sub2/large7
650 650
651 651 Test that a standin can't be added as a large file
652 652
653 653 $ touch large
654 654 $ hg add --large large
655 655 $ hg ci -m "add"
656 656 Invoking status precommit hook
657 657 A large
658 658 Invoking status postcommit hook
659 659 C large
660 660 C normal
661 661 C normal3
662 662 C sub/large4
663 663 C sub/normal4
664 664 C sub2/large6
665 665 C sub2/large7
666 666 $ hg remove large
667 667 $ touch large
668 668 $ hg addremove --config largefiles.patterns=**large --traceback
669 669 adding large as a largefile
670 670
671 671 Test that outgoing --large works (with revsets too)
672 672 $ hg outgoing --rev '.^' --large
673 673 comparing with $TESTTMP/a (glob)
674 674 searching for changes
675 675 changeset: 8:c02fd3b77ec4
676 676 user: test
677 677 date: Thu Jan 01 00:00:00 1970 +0000
678 678 summary: add foo
679 679
680 680 changeset: 9:289dd08c9bbb
681 681 user: test
682 682 date: Thu Jan 01 00:00:00 1970 +0000
683 683 summary: used to say nothing changed
684 684
685 685 changeset: 10:34f23ac6ac12
686 686 user: test
687 687 date: Thu Jan 01 00:00:00 1970 +0000
688 688 summary: added
689 689
690 690 changeset: 12:710c1b2f523c
691 691 parent: 10:34f23ac6ac12
692 692 user: test
693 693 date: Thu Jan 01 00:00:00 1970 +0000
694 694 summary: removed large
695 695
696 696 changeset: 13:0a3e75774479
697 697 user: test
698 698 date: Thu Jan 01 00:00:00 1970 +0000
699 699 summary: this used to add large8 as normal and commit both
700 700
701 701 changeset: 14:84f3d378175c
702 702 user: test
703 703 date: Thu Jan 01 00:00:00 1970 +0000
704 704 summary: this used to not notice the rm
705 705
706 706 searching for changes
707 707 largefiles to upload:
708 708 foo
709 709 large
710 710 large8
711 711
712 712 $ cd ../a
713 713
714 714 Clone a largefiles repo.
715 715
716 716 $ hg clone . ../b
717 717 updating to branch default
718 718 getting changed largefiles
719 719 3 largefiles updated, 0 removed
720 720 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
721 721 $ cd ../b
722 722 $ hg log --template '{rev}:{node|short} {desc|firstline}\n'
723 723 7:daea875e9014 add/edit more largefiles
724 724 6:4355d653f84f edit files yet again
725 725 5:9d5af5072dbd edit files again
726 726 4:74c02385b94c move files
727 727 3:9e8fbc4bce62 copy files
728 728 2:51a0ae4d5864 remove files
729 729 1:ce8896473775 edit files
730 730 0:30d30fe6a5be add files
731 731 $ cat normal3
732 732 normal33
733 733 $ cat sub/normal4
734 734 normal44
735 735 $ cat sub/large4
736 736 large44
737 737 $ cat sub2/large6
738 738 large6
739 739 $ cat sub2/large7
740 740 large7
741 741 $ hg log -qf sub2/large7
742 742 7:daea875e9014
743 743 $ cd ..
744 744 $ hg clone a -r 3 c
745 745 adding changesets
746 746 adding manifests
747 747 adding file changes
748 748 added 4 changesets with 10 changes to 4 files
749 749 updating to branch default
750 750 getting changed largefiles
751 751 2 largefiles updated, 0 removed
752 752 4 files updated, 0 files merged, 0 files removed, 0 files unresolved
753 753 $ cd c
754 754 $ hg log --template '{rev}:{node|short} {desc|firstline}\n'
755 755 3:9e8fbc4bce62 copy files
756 756 2:51a0ae4d5864 remove files
757 757 1:ce8896473775 edit files
758 758 0:30d30fe6a5be add files
759 759 $ cat normal1
760 760 normal22
761 761 $ cat large1
762 762 large22
763 763 $ cat sub/normal2
764 764 normal22
765 765 $ cat sub/large2
766 766 large22
767 767
768 768 Old revisions of a clone have correct largefiles content (this also
769 769 tests update).
770 770
771 771 $ hg update -r 1
772 772 getting changed largefiles
773 773 1 largefiles updated, 0 removed
774 774 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
775 775 $ cat large1
776 776 large11
777 777 $ cat sub/large2
778 778 large22
779 779 $ cd ..
780 780
781 781 Test cloning with --all-largefiles flag
782 782
783 783 $ rm "${USERCACHE}"/*
784 784 $ hg clone --all-largefiles a a-backup
785 785 updating to branch default
786 786 getting changed largefiles
787 787 3 largefiles updated, 0 removed
788 788 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
789 789 8 additional largefiles cached
790 790
791 791 $ rm "${USERCACHE}"/*
792 792 $ hg clone --all-largefiles -u 0 a a-clone0
793 793 updating to branch default
794 794 getting changed largefiles
795 795 2 largefiles updated, 0 removed
796 796 4 files updated, 0 files merged, 0 files removed, 0 files unresolved
797 797 9 additional largefiles cached
798 798 $ hg -R a-clone0 sum
799 799 parent: 0:30d30fe6a5be
800 800 add files
801 801 branch: default
802 802 commit: (clean)
803 803 update: 7 new changesets (update)
804 804
805 805 $ rm "${USERCACHE}"/*
806 806 $ hg clone --all-largefiles -u 1 a a-clone1
807 807 updating to branch default
808 808 getting changed largefiles
809 809 2 largefiles updated, 0 removed
810 810 4 files updated, 0 files merged, 0 files removed, 0 files unresolved
811 811 8 additional largefiles cached
812 812 $ hg -R a-clone1 verify --large --lfa --lfc
813 813 checking changesets
814 814 checking manifests
815 815 crosschecking files in changesets and manifests
816 816 checking files
817 817 10 files, 8 changesets, 24 total revisions
818 818 searching 8 changesets for largefiles
819 819 verified contents of 13 revisions of 6 largefiles
820 820 $ hg -R a-clone1 sum
821 821 parent: 1:ce8896473775
822 822 edit files
823 823 branch: default
824 824 commit: (clean)
825 825 update: 6 new changesets (update)
826 826
827 827 $ rm "${USERCACHE}"/*
828 828 $ hg clone --all-largefiles -U a a-clone-u
829 829 11 additional largefiles cached
830 830 $ hg -R a-clone-u sum
831 831 parent: -1:000000000000 (no revision checked out)
832 832 branch: default
833 833 commit: (clean)
834 834 update: 8 new changesets (update)
835 835
836 836 Show computed destination directory:
837 837
838 838 $ mkdir xyz
839 839 $ cd xyz
840 840 $ hg clone ../a
841 841 destination directory: a
842 842 updating to branch default
843 843 getting changed largefiles
844 844 3 largefiles updated, 0 removed
845 845 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
846 846 $ cd ..
847 847
848 848 Clone URL without path:
849 849
850 850 $ hg clone file://
851 851 abort: repository / not found!
852 852 [255]
853 853
854 854 Ensure base clone command argument validation
855 855
856 856 $ hg clone -U -u 0 a a-clone-failure
857 857 abort: cannot specify both --noupdate and --updaterev
858 858 [255]
859 859
860 860 $ hg clone --all-largefiles a ssh://localhost/a
861 861 abort: --all-largefiles is incompatible with non-local destination ssh://localhost/a
862 862 [255]
863 863
864 864 Test pulling with --all-largefiles flag. Also test that the largefiles are
865 865 downloaded from 'default' instead of 'default-push' when no source is specified
866 866 (issue3584)
867 867
868 868 $ rm -Rf a-backup
869 869 $ hg clone -r 1 a a-backup
870 870 adding changesets
871 871 adding manifests
872 872 adding file changes
873 873 added 2 changesets with 8 changes to 4 files
874 874 updating to branch default
875 875 getting changed largefiles
876 876 2 largefiles updated, 0 removed
877 877 4 files updated, 0 files merged, 0 files removed, 0 files unresolved
878 878 $ rm "${USERCACHE}"/*
879 879 $ cd a-backup
880 880 $ hg pull --all-largefiles --config paths.default-push=bogus/path
881 881 pulling from $TESTTMP/a (glob)
882 882 searching for changes
883 883 adding changesets
884 884 adding manifests
885 885 adding file changes
886 886 added 6 changesets with 16 changes to 8 files
887 887 (run 'hg update' to get a working copy)
888 888 6 largefiles cached
889 889
890 890 redo pull with --lfrev and check it pulls largefiles for the right revs
891 891
892 892 $ hg rollback
893 893 repository tip rolled back to revision 1 (undo pull)
894 894 $ hg pull -v --lfrev 'heads(pulled())+min(pulled())'
895 895 pulling from $TESTTMP/a (glob)
896 896 searching for changes
897 897 all local heads known remotely
898 898 6 changesets found
899 899 adding changesets
900 900 adding manifests
901 901 adding file changes
902 902 added 6 changesets with 16 changes to 8 files
903 903 calling hook changegroup.lfiles: <function checkrequireslfiles at *> (glob)
904 904 (run 'hg update' to get a working copy)
905 905 pulling largefiles for revision 7
906 906 found 971fb41e78fea4f8e0ba5244784239371cb00591 in store
907 907 found 0d6d75887db61b2c7e6c74b5dd8fc6ad50c0cc30 in store
908 908 found bb3151689acb10f0c3125c560d5e63df914bc1af in store
909 909 pulling largefiles for revision 2
910 910 found eb7338044dc27f9bc59b8dd5a246b065ead7a9c4 in store
911 911 0 largefiles cached
912 912
913 913 lfpull
914 914
915 915 $ hg lfpull -r : --config largefiles.usercache=usercache-lfpull
916 916 2 largefiles cached
917 917 $ hg lfpull -v -r 4+2 --config largefiles.usercache=usercache-lfpull
918 918 pulling largefiles for revision 4
919 919 found eb7338044dc27f9bc59b8dd5a246b065ead7a9c4 in store
920 920 found eb7338044dc27f9bc59b8dd5a246b065ead7a9c4 in store
921 921 pulling largefiles for revision 2
922 922 found eb7338044dc27f9bc59b8dd5a246b065ead7a9c4 in store
923 923 0 largefiles cached
924 924
925 925 $ ls usercache-lfpull/* | sort
926 926 usercache-lfpull/1deebade43c8c498a3c8daddac0244dc55d1331d
927 927 usercache-lfpull/4669e532d5b2c093a78eca010077e708a071bb64
928 928
929 929 $ cd ..
930 930
931 931 Rebasing between two repositories does not revert largefiles to old
932 932 revisions (this was a very bad bug that took a lot of work to fix).
933 933
934 934 $ hg clone a d
935 935 updating to branch default
936 936 getting changed largefiles
937 937 3 largefiles updated, 0 removed
938 938 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
939 939 $ cd b
940 940 $ echo large4-modified > sub/large4
941 941 $ echo normal3-modified > normal3
942 942 $ hg commit -m "modify normal file and largefile in repo b"
943 943 Invoking status precommit hook
944 944 M normal3
945 945 M sub/large4
946 946 $ cd ../d
947 947 $ echo large6-modified > sub2/large6
948 948 $ echo normal4-modified > sub/normal4
949 949 $ hg commit -m "modify normal file largefile in repo d"
950 950 Invoking status precommit hook
951 951 M sub/normal4
952 952 M sub2/large6
953 953 $ cd ..
954 954 $ hg clone d e
955 955 updating to branch default
956 956 getting changed largefiles
957 957 3 largefiles updated, 0 removed
958 958 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
959 959 $ cd d
960 960
961 961 More rebase testing, but also test that the largefiles are downloaded from
962 962 'default-push' when no source is specified (issue3584). (The largefile from the
963 963 pulled revision is however not downloaded but found in the local cache.)
964 964 Largefiles are fetched for the new pulled revision, not for existing revisions,
965 965 rebased or not.
966 966
967 967 $ [ ! -f .hg/largefiles/e166e74c7303192238d60af5a9c4ce9bef0b7928 ]
968 968 $ hg pull --rebase --all-largefiles --config paths.default-push=bogus/path --config paths.default=../b
969 969 pulling from $TESTTMP/b (glob)
970 970 searching for changes
971 971 adding changesets
972 972 adding manifests
973 973 adding file changes
974 974 added 1 changesets with 2 changes to 2 files (+1 heads)
975 975 Invoking status precommit hook
976 976 M sub/normal4
977 977 M sub2/large6
978 978 saved backup bundle to $TESTTMP/d/.hg/strip-backup/f574fb32bb45-backup.hg (glob)
979 979 0 largefiles cached
980 980 nothing to rebase - working directory parent is also destination
981 981 $ [ -f .hg/largefiles/e166e74c7303192238d60af5a9c4ce9bef0b7928 ]
982 982 $ hg log --template '{rev}:{node|short} {desc|firstline}\n'
983 983 9:598410d3eb9a modify normal file largefile in repo d
984 984 8:a381d2c8c80e modify normal file and largefile in repo b
985 985 7:daea875e9014 add/edit more largefiles
986 986 6:4355d653f84f edit files yet again
987 987 5:9d5af5072dbd edit files again
988 988 4:74c02385b94c move files
989 989 3:9e8fbc4bce62 copy files
990 990 2:51a0ae4d5864 remove files
991 991 1:ce8896473775 edit files
992 992 0:30d30fe6a5be add files
993 993 $ cat normal3
994 994 normal3-modified
995 995 $ cat sub/normal4
996 996 normal4-modified
997 997 $ cat sub/large4
998 998 large4-modified
999 999 $ cat sub2/large6
1000 1000 large6-modified
1001 1001 $ cat sub2/large7
1002 1002 large7
1003 1003 $ cd ../e
1004 1004 $ hg pull ../b
1005 1005 pulling from ../b
1006 1006 searching for changes
1007 1007 adding changesets
1008 1008 adding manifests
1009 1009 adding file changes
1010 1010 added 1 changesets with 2 changes to 2 files (+1 heads)
1011 1011 (run 'hg heads' to see heads, 'hg merge' to merge)
1012 1012 $ hg rebase
1013 1013 Invoking status precommit hook
1014 1014 M sub/normal4
1015 1015 M sub2/large6
1016 1016 saved backup bundle to $TESTTMP/e/.hg/strip-backup/f574fb32bb45-backup.hg (glob)
1017 1017 $ hg log --template '{rev}:{node|short} {desc|firstline}\n'
1018 1018 9:598410d3eb9a modify normal file largefile in repo d
1019 1019 8:a381d2c8c80e modify normal file and largefile in repo b
1020 1020 7:daea875e9014 add/edit more largefiles
1021 1021 6:4355d653f84f edit files yet again
1022 1022 5:9d5af5072dbd edit files again
1023 1023 4:74c02385b94c move files
1024 1024 3:9e8fbc4bce62 copy files
1025 1025 2:51a0ae4d5864 remove files
1026 1026 1:ce8896473775 edit files
1027 1027 0:30d30fe6a5be add files
1028 1028 $ cat normal3
1029 1029 normal3-modified
1030 1030 $ cat sub/normal4
1031 1031 normal4-modified
1032 1032 $ cat sub/large4
1033 1033 large4-modified
1034 1034 $ cat sub2/large6
1035 1035 large6-modified
1036 1036 $ cat sub2/large7
1037 1037 large7
1038 1038
1039 1039 Log on largefiles
1040 1040
1041 1041 - same output
1042 1042 $ hg log --template '{rev}:{node|short} {desc|firstline}\n' .hglf/sub/large4
1043 1043 8:a381d2c8c80e modify normal file and largefile in repo b
1044 1044 6:4355d653f84f edit files yet again
1045 1045 5:9d5af5072dbd edit files again
1046 1046 4:74c02385b94c move files
1047 1047 $ hg log --template '{rev}:{node|short} {desc|firstline}\n' sub/large4
1048 1048 8:a381d2c8c80e modify normal file and largefile in repo b
1049 1049 6:4355d653f84f edit files yet again
1050 1050 5:9d5af5072dbd edit files again
1051 1051 4:74c02385b94c move files
1052 1052
1053 1053 - .hglf only matches largefiles, without .hglf it matches 9 bco sub/normal
1054 1054 $ hg log --template '{rev}:{node|short} {desc|firstline}\n' .hglf/sub
1055 1055 8:a381d2c8c80e modify normal file and largefile in repo b
1056 1056 6:4355d653f84f edit files yet again
1057 1057 5:9d5af5072dbd edit files again
1058 1058 4:74c02385b94c move files
1059 1059 1:ce8896473775 edit files
1060 1060 0:30d30fe6a5be add files
1061 1061 $ hg log --template '{rev}:{node|short} {desc|firstline}\n' sub
1062 1062 9:598410d3eb9a modify normal file largefile in repo d
1063 1063 8:a381d2c8c80e modify normal file and largefile in repo b
1064 1064 6:4355d653f84f edit files yet again
1065 1065 5:9d5af5072dbd edit files again
1066 1066 4:74c02385b94c move files
1067 1067 1:ce8896473775 edit files
1068 1068 0:30d30fe6a5be add files
1069 1069
1070 1070 - globbing gives same result
1071 1071 $ hg log --template '{rev}:{node|short} {desc|firstline}\n' 'glob:sub/*'
1072 1072 9:598410d3eb9a modify normal file largefile in repo d
1073 1073 8:a381d2c8c80e modify normal file and largefile in repo b
1074 1074 6:4355d653f84f edit files yet again
1075 1075 5:9d5af5072dbd edit files again
1076 1076 4:74c02385b94c move files
1077 1077 1:ce8896473775 edit files
1078 1078 0:30d30fe6a5be add files
1079 1079
1080 1080 Rollback on largefiles.
1081 1081
1082 1082 $ echo large4-modified-again > sub/large4
1083 1083 $ hg commit -m "Modify large4 again"
1084 1084 Invoking status precommit hook
1085 1085 M sub/large4
1086 1086 $ hg rollback
1087 1087 repository tip rolled back to revision 9 (undo commit)
1088 1088 working directory now based on revision 9
1089 1089 $ hg st
1090 1090 M sub/large4
1091 1091 $ hg log --template '{rev}:{node|short} {desc|firstline}\n'
1092 1092 9:598410d3eb9a modify normal file largefile in repo d
1093 1093 8:a381d2c8c80e modify normal file and largefile in repo b
1094 1094 7:daea875e9014 add/edit more largefiles
1095 1095 6:4355d653f84f edit files yet again
1096 1096 5:9d5af5072dbd edit files again
1097 1097 4:74c02385b94c move files
1098 1098 3:9e8fbc4bce62 copy files
1099 1099 2:51a0ae4d5864 remove files
1100 1100 1:ce8896473775 edit files
1101 1101 0:30d30fe6a5be add files
1102 1102 $ cat sub/large4
1103 1103 large4-modified-again
1104 1104
1105 1105 "update --check" refuses to update with uncommitted changes.
1106 1106 $ hg update --check 8
1107 1107 abort: uncommitted changes
1108 1108 [255]
1109 1109
1110 1110 "update --clean" leaves correct largefiles in working copy, even when there is
1111 1111 .orig files from revert in .hglf.
1112 1112
1113 1113 $ echo mistake > sub2/large7
1114 1114 $ hg revert sub2/large7
1115 1115 $ hg -q update --clean -r null
1116 1116 $ hg update --clean
1117 1117 getting changed largefiles
1118 1118 3 largefiles updated, 0 removed
1119 1119 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
1120 1120 $ cat normal3
1121 1121 normal3-modified
1122 1122 $ cat sub/normal4
1123 1123 normal4-modified
1124 1124 $ cat sub/large4
1125 1125 large4-modified
1126 1126 $ cat sub2/large6
1127 1127 large6-modified
1128 1128 $ cat sub2/large7
1129 1129 large7
1130 1130 $ cat sub2/large7.orig
1131 1131 mistake
1132 1132 $ cat .hglf/sub2/large7.orig
1133 1133 9dbfb2c79b1c40981b258c3efa1b10b03f18ad31
1134 1134
1135 1135 demonstrate misfeature: .orig file is overwritten on every update -C,
1136 1136 also when clean:
1137 1137 $ hg update --clean
1138 1138 getting changed largefiles
1139 1139 0 largefiles updated, 0 removed
1140 1140 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
1141 1141 $ cat sub2/large7.orig
1142 1142 large7
1143 1143 $ rm sub2/large7.orig .hglf/sub2/large7.orig
1144 1144
1145 1145 Now "update check" is happy.
1146 1146 $ hg update --check 8
1147 1147 getting changed largefiles
1148 1148 1 largefiles updated, 0 removed
1149 1149 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
1150 1150 $ hg update --check
1151 1151 getting changed largefiles
1152 1152 1 largefiles updated, 0 removed
1153 1153 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
1154 1154
1155 1155 Test removing empty largefiles directories on update
1156 1156 $ test -d sub2 && echo "sub2 exists"
1157 1157 sub2 exists
1158 1158 $ hg update -q null
1159 1159 $ test -d sub2 && echo "error: sub2 should not exist anymore"
1160 1160 [1]
1161 1161 $ hg update -q
1162 1162
1163 1163 Test hg remove removes empty largefiles directories
1164 1164 $ test -d sub2 && echo "sub2 exists"
1165 1165 sub2 exists
1166 1166 $ hg remove sub2/*
1167 1167 $ test -d sub2 && echo "error: sub2 should not exist anymore"
1168 1168 [1]
1169 1169 $ hg revert sub2/large6 sub2/large7
1170 1170
1171 1171 "revert" works on largefiles (and normal files too).
1172 1172 $ echo hack3 >> normal3
1173 1173 $ echo hack4 >> sub/normal4
1174 1174 $ echo hack4 >> sub/large4
1175 1175 $ rm sub2/large6
1176 1176 $ hg revert sub2/large6
1177 1177 $ hg rm sub2/large6
1178 1178 $ echo new >> sub2/large8
1179 1179 $ hg add --large sub2/large8
1180 1180 # XXX we don't really want to report that we're reverting the standin;
1181 1181 # that's just an implementation detail. But I don't see an obvious fix. ;-(
1182 1182 $ hg revert sub
1183 1183 reverting .hglf/sub/large4 (glob)
1184 1184 reverting sub/normal4 (glob)
1185 1185 $ hg status
1186 1186 M normal3
1187 1187 A sub2/large8
1188 1188 R sub2/large6
1189 1189 ? sub/large4.orig
1190 1190 ? sub/normal4.orig
1191 1191 $ cat sub/normal4
1192 1192 normal4-modified
1193 1193 $ cat sub/large4
1194 1194 large4-modified
1195 1195 $ hg revert -a --no-backup
1196 1196 undeleting .hglf/sub2/large6 (glob)
1197 1197 forgetting .hglf/sub2/large8 (glob)
1198 1198 reverting normal3
1199 1199 $ hg status
1200 1200 ? sub/large4.orig
1201 1201 ? sub/normal4.orig
1202 1202 ? sub2/large8
1203 1203 $ cat normal3
1204 1204 normal3-modified
1205 1205 $ cat sub2/large6
1206 1206 large6-modified
1207 1207 $ rm sub/*.orig sub2/large8
1208 1208
1209 1209 revert some files to an older revision
1210 1210 $ hg revert --no-backup -r 8 sub2
1211 1211 reverting .hglf/sub2/large6 (glob)
1212 1212 $ cat sub2/large6
1213 1213 large6
1214 1214 $ hg revert --no-backup -C -r '.^' sub2
1215 1215 reverting .hglf/sub2/large6 (glob)
1216 1216 $ hg revert --no-backup sub2
1217 1217 reverting .hglf/sub2/large6 (glob)
1218 1218 $ hg status
1219 1219
1220 1220 "verify --large" actually verifies largefiles
1221 1221
1222 1222 - Where Do We Come From? What Are We? Where Are We Going?
1223 1223 $ pwd
1224 1224 $TESTTMP/e
1225 1225 $ hg paths
1226 1226 default = $TESTTMP/d (glob)
1227 1227
1228 1228 $ hg verify --large
1229 1229 checking changesets
1230 1230 checking manifests
1231 1231 crosschecking files in changesets and manifests
1232 1232 checking files
1233 1233 10 files, 10 changesets, 28 total revisions
1234 1234 searching 1 changesets for largefiles
1235 1235 verified existence of 3 revisions of 3 largefiles
1236 1236
1237 1237 - introduce missing blob in local store repo and make sure that this is caught:
1238 1238 $ mv $TESTTMP/d/.hg/largefiles/e166e74c7303192238d60af5a9c4ce9bef0b7928 .
1239 1239 $ hg verify --large
1240 1240 checking changesets
1241 1241 checking manifests
1242 1242 crosschecking files in changesets and manifests
1243 1243 checking files
1244 1244 10 files, 10 changesets, 28 total revisions
1245 1245 searching 1 changesets for largefiles
1246 1246 changeset 9:598410d3eb9a: sub/large4 references missing $TESTTMP/d/.hg/largefiles/e166e74c7303192238d60af5a9c4ce9bef0b7928 (glob)
1247 1247 verified existence of 3 revisions of 3 largefiles
1248 1248 [1]
1249 1249
1250 1250 - introduce corruption and make sure that it is caught when checking content:
1251 1251 $ echo '5 cents' > $TESTTMP/d/.hg/largefiles/e166e74c7303192238d60af5a9c4ce9bef0b7928
1252 1252 $ hg verify -q --large --lfc
1253 1253 changeset 9:598410d3eb9a: sub/large4 references corrupted $TESTTMP/d/.hg/largefiles/e166e74c7303192238d60af5a9c4ce9bef0b7928 (glob)
1254 1254 [1]
1255 1255
1256 1256 - cleanup
1257 1257 $ mv e166e74c7303192238d60af5a9c4ce9bef0b7928 $TESTTMP/d/.hg/largefiles/
1258 1258
1259 1259 - verifying all revisions will fail because we didn't clone all largefiles to d:
1260 1260 $ echo 'T-shirt' > $TESTTMP/d/.hg/largefiles/eb7338044dc27f9bc59b8dd5a246b065ead7a9c4
1261 1261 $ hg verify -q --lfa --lfc
1262 1262 changeset 0:30d30fe6a5be: large1 references missing $TESTTMP/d/.hg/largefiles/4669e532d5b2c093a78eca010077e708a071bb64 (glob)
1263 1263 changeset 0:30d30fe6a5be: sub/large2 references missing $TESTTMP/d/.hg/largefiles/1deebade43c8c498a3c8daddac0244dc55d1331d (glob)
1264 1264 changeset 1:ce8896473775: large1 references missing $TESTTMP/d/.hg/largefiles/5f78770c0e77ba4287ad6ef3071c9bf9c379742f (glob)
1265 1265 changeset 1:ce8896473775: sub/large2 references corrupted $TESTTMP/d/.hg/largefiles/eb7338044dc27f9bc59b8dd5a246b065ead7a9c4 (glob)
1266 1266 changeset 3:9e8fbc4bce62: large1 references corrupted $TESTTMP/d/.hg/largefiles/eb7338044dc27f9bc59b8dd5a246b065ead7a9c4 (glob)
1267 1267 changeset 4:74c02385b94c: large3 references corrupted $TESTTMP/d/.hg/largefiles/eb7338044dc27f9bc59b8dd5a246b065ead7a9c4 (glob)
1268 1268 changeset 4:74c02385b94c: sub/large4 references corrupted $TESTTMP/d/.hg/largefiles/eb7338044dc27f9bc59b8dd5a246b065ead7a9c4 (glob)
1269 1269 changeset 5:9d5af5072dbd: large3 references missing $TESTTMP/d/.hg/largefiles/baaf12afde9d8d67f25dab6dced0d2bf77dba47c (glob)
1270 1270 changeset 5:9d5af5072dbd: sub/large4 references missing $TESTTMP/d/.hg/largefiles/aeb2210d19f02886dde00dac279729a48471e2f9 (glob)
1271 1271 changeset 6:4355d653f84f: large3 references missing $TESTTMP/d/.hg/largefiles/7838695e10da2bb75ac1156565f40a2595fa2fa0 (glob)
1272 1272 [1]
1273 1273
1274 1274 - cleanup
1275 1275 $ rm $TESTTMP/d/.hg/largefiles/eb7338044dc27f9bc59b8dd5a246b065ead7a9c4
1276 1276 $ rm -f .hglf/sub/*.orig
1277 1277
1278 1278 Update to revision with missing largefile - and make sure it really is missing
1279 1279
1280 1280 $ rm ${USERCACHE}/7838695e10da2bb75ac1156565f40a2595fa2fa0
1281 1281 $ hg up -r 6
1282 1282 getting changed largefiles
1283 1283 large3: largefile 7838695e10da2bb75ac1156565f40a2595fa2fa0 not available from file://$TESTTMP/d (glob)
1284 1284 1 largefiles updated, 2 removed
1285 1285 4 files updated, 0 files merged, 2 files removed, 0 files unresolved
1286 1286 $ rm normal3
1287 1287 $ echo >> sub/normal4
1288 1288 $ hg ci -m 'commit with missing files'
1289 1289 Invoking status precommit hook
1290 1290 M sub/normal4
1291 1291 ! large3
1292 1292 ! normal3
1293 1293 created new head
1294 1294 $ hg st
1295 1295 ! large3
1296 1296 ! normal3
1297 1297 $ hg up -r.
1298 1298 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
1299 1299 $ hg st
1300 1300 ! large3
1301 1301 ! normal3
1302 1302 $ hg up -Cr.
1303 1303 getting changed largefiles
1304 1304 large3: largefile 7838695e10da2bb75ac1156565f40a2595fa2fa0 not available from file://$TESTTMP/d (glob)
1305 1305 0 largefiles updated, 0 removed
1306 1306 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1307 1307 $ hg st
1308 1308 ! large3
1309 1309 $ hg rollback
1310 1310 repository tip rolled back to revision 9 (undo commit)
1311 1311 working directory now based on revision 6
1312 1312
1313 1313 Merge with revision with missing largefile - and make sure it tries to fetch it.
1314 1314
1315 1315 $ hg up -Cqr null
1316 1316 $ echo f > f
1317 1317 $ hg ci -Am branch
1318 1318 adding f
1319 1319 Invoking status precommit hook
1320 1320 A f
1321 1321 created new head
1322 1322 $ hg merge -r 6
1323 1323 4 files updated, 0 files merged, 0 files removed, 0 files unresolved
1324 1324 (branch merge, don't forget to commit)
1325 1325 getting changed largefiles
1326 1326 large3: largefile 7838695e10da2bb75ac1156565f40a2595fa2fa0 not available from file://$TESTTMP/d (glob)
1327 1327 1 largefiles updated, 0 removed
1328 1328
1329 1329 $ hg rollback -q
1330 1330 $ hg up -Cq
1331 1331
1332 1332 Pulling 0 revisions with --all-largefiles should not fetch for all revisions
1333 1333
1334 1334 $ hg pull --all-largefiles
1335 1335 pulling from $TESTTMP/d (glob)
1336 1336 searching for changes
1337 1337 no changes found
1338 1338
1339 1339 Merging does not revert to old versions of largefiles and also check
1340 1340 that merging after having pulled from a non-default remote works
1341 1341 correctly.
1342 1342
1343 1343 $ cd ..
1344 1344 $ hg clone -r 7 e temp
1345 1345 adding changesets
1346 1346 adding manifests
1347 1347 adding file changes
1348 1348 added 8 changesets with 24 changes to 10 files
1349 1349 updating to branch default
1350 1350 getting changed largefiles
1351 1351 3 largefiles updated, 0 removed
1352 1352 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
1353 1353 $ hg clone temp f
1354 1354 updating to branch default
1355 1355 getting changed largefiles
1356 1356 3 largefiles updated, 0 removed
1357 1357 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
1358 1358 # Delete the largefiles in the largefiles system cache so that we have an
1359 1359 # opportunity to test that caching after a pull works.
1360 1360 $ rm "${USERCACHE}"/*
1361 1361 $ cd f
1362 1362 $ echo "large4-merge-test" > sub/large4
1363 1363 $ hg commit -m "Modify large4 to test merge"
1364 1364 Invoking status precommit hook
1365 1365 M sub/large4
1366 1366 # Test --cache-largefiles flag
1367 1367 $ hg pull --lfrev 'heads(pulled())' ../e
1368 1368 pulling from ../e
1369 1369 searching for changes
1370 1370 adding changesets
1371 1371 adding manifests
1372 1372 adding file changes
1373 1373 added 2 changesets with 4 changes to 4 files (+1 heads)
1374 1374 (run 'hg heads' to see heads, 'hg merge' to merge)
1375 1375 2 largefiles cached
1376 1376 $ hg merge
1377 1377 largefile sub/large4 has a merge conflict
1378 1378 ancestor was 971fb41e78fea4f8e0ba5244784239371cb00591
1379 1379 keep (l)ocal d846f26643bfa8ec210be40cc93cc6b7ff1128ea or
1380 1380 take (o)ther e166e74c7303192238d60af5a9c4ce9bef0b7928? l
1381 1381 3 files updated, 1 files merged, 0 files removed, 0 files unresolved
1382 1382 (branch merge, don't forget to commit)
1383 1383 getting changed largefiles
1384 1384 1 largefiles updated, 0 removed
1385 1385 $ hg commit -m "Merge repos e and f"
1386 1386 Invoking status precommit hook
1387 1387 M normal3
1388 1388 M sub/normal4
1389 1389 M sub2/large6
1390 1390 $ cat normal3
1391 1391 normal3-modified
1392 1392 $ cat sub/normal4
1393 1393 normal4-modified
1394 1394 $ cat sub/large4
1395 1395 large4-merge-test
1396 1396 $ cat sub2/large6
1397 1397 large6-modified
1398 1398 $ cat sub2/large7
1399 1399 large7
1400 1400
1401 1401 Test status after merging with a branch that introduces a new largefile:
1402 1402
1403 1403 $ echo large > large
1404 1404 $ hg add --large large
1405 1405 $ hg commit -m 'add largefile'
1406 1406 Invoking status precommit hook
1407 1407 A large
1408 1408 $ hg update -q ".^"
1409 1409 $ echo change >> normal3
1410 1410 $ hg commit -m 'some change'
1411 1411 Invoking status precommit hook
1412 1412 M normal3
1413 1413 created new head
1414 1414 $ hg merge
1415 1415 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1416 1416 (branch merge, don't forget to commit)
1417 1417 getting changed largefiles
1418 1418 1 largefiles updated, 0 removed
1419 1419 $ hg status
1420 1420 M large
1421 1421
1422 1422 - make sure update of merge with removed largefiles fails as expected
1423 1423 $ hg rm sub2/large6
1424 1424 $ hg up -r.
1425 1425 abort: outstanding uncommitted merges
1426 1426 [255]
1427 1427
1428 1428 - revert should be able to revert files introduced in a pending merge
1429 1429 $ hg revert --all -r .
1430 1430 removing .hglf/large (glob)
1431 1431 undeleting .hglf/sub2/large6 (glob)
1432 1432
1433 1433 Test that a normal file and a largefile with the same name and path cannot
1434 1434 coexist.
1435 1435
1436 1436 $ rm sub2/large7
1437 1437 $ echo "largeasnormal" > sub2/large7
1438 1438 $ hg add sub2/large7
1439 1439 sub2/large7 already a largefile
1440 1440
1441 1441 Test that transplanting a largefile change works correctly.
1442 1442
1443 1443 $ cd ..
1444 1444 $ hg clone -r 8 d g
1445 1445 adding changesets
1446 1446 adding manifests
1447 1447 adding file changes
1448 1448 added 9 changesets with 26 changes to 10 files
1449 1449 updating to branch default
1450 1450 getting changed largefiles
1451 1451 3 largefiles updated, 0 removed
1452 1452 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
1453 1453 $ cd g
1454 1454 $ hg transplant -s ../d 598410d3eb9a
1455 1455 searching for changes
1456 1456 searching for changes
1457 1457 adding changesets
1458 1458 adding manifests
1459 1459 adding file changes
1460 1460 added 1 changesets with 2 changes to 2 files
1461 1461 getting changed largefiles
1462 1462 1 largefiles updated, 0 removed
1463 1463 $ hg log --template '{rev}:{node|short} {desc|firstline}\n'
1464 1464 9:598410d3eb9a modify normal file largefile in repo d
1465 1465 8:a381d2c8c80e modify normal file and largefile in repo b
1466 1466 7:daea875e9014 add/edit more largefiles
1467 1467 6:4355d653f84f edit files yet again
1468 1468 5:9d5af5072dbd edit files again
1469 1469 4:74c02385b94c move files
1470 1470 3:9e8fbc4bce62 copy files
1471 1471 2:51a0ae4d5864 remove files
1472 1472 1:ce8896473775 edit files
1473 1473 0:30d30fe6a5be add files
1474 1474 $ cat normal3
1475 1475 normal3-modified
1476 1476 $ cat sub/normal4
1477 1477 normal4-modified
1478 1478 $ cat sub/large4
1479 1479 large4-modified
1480 1480 $ cat sub2/large6
1481 1481 large6-modified
1482 1482 $ cat sub2/large7
1483 1483 large7
1484 1484
1485 1485 Cat a largefile
1486 1486 $ hg cat normal3
1487 1487 normal3-modified
1488 1488 $ hg cat sub/large4
1489 1489 large4-modified
1490 1490 $ rm "${USERCACHE}"/*
1491 1491 $ hg cat -r a381d2c8c80e -o cat.out sub/large4
1492 1492 $ cat cat.out
1493 1493 large4-modified
1494 1494 $ rm cat.out
1495 1495 $ hg cat -r a381d2c8c80e normal3
1496 1496 normal3-modified
1497 1497 $ hg cat -r '.^' normal3
1498 1498 normal3-modified
1499 1499 $ hg cat -r '.^' sub/large4 doesntexist
1500 1500 large4-modified
1501 1501 doesntexist: no such file in rev a381d2c8c80e
1502 1502 $ hg --cwd sub cat -r '.^' large4
1503 1503 large4-modified
1504 1504 $ hg --cwd sub cat -r '.^' ../normal3
1505 1505 normal3-modified
1506 1506
1507 1507 Test that renaming a largefile results in correct output for status
1508 1508
1509 1509 $ hg rename sub/large4 large4-renamed
1510 1510 $ hg commit -m "test rename output"
1511 1511 Invoking status precommit hook
1512 1512 A large4-renamed
1513 1513 R sub/large4
1514 1514 $ cat large4-renamed
1515 1515 large4-modified
1516 1516 $ cd sub2
1517 1517 $ hg rename large6 large6-renamed
1518 1518 $ hg st
1519 1519 A sub2/large6-renamed
1520 1520 R sub2/large6
1521 1521 $ cd ..
1522 1522
1523 1523 Test --normal flag
1524 1524
1525 1525 $ dd if=/dev/zero bs=2k count=11k > new-largefile 2> /dev/null
1526 1526 $ hg add --normal --large new-largefile
1527 1527 abort: --normal cannot be used with --large
1528 1528 [255]
1529 1529 $ hg add --normal new-largefile
1530 1530 new-largefile: up to 69 MB of RAM may be required to manage this file
1531 1531 (use 'hg revert new-largefile' to cancel the pending addition)
1532 1532 $ cd ..
1533 1533
1534 1534 #if serve
1535 1535 vanilla clients not locked out from largefiles servers on vanilla repos
1536 1536 $ mkdir r1
1537 1537 $ cd r1
1538 1538 $ hg init
1539 1539 $ echo c1 > f1
1540 1540 $ hg add f1
1541 1541 $ hg commit -m "m1"
1542 1542 Invoking status precommit hook
1543 1543 A f1
1544 1544 $ cd ..
1545 1545 $ hg serve -R r1 -d -p $HGPORT --pid-file hg.pid
1546 1546 $ cat hg.pid >> $DAEMON_PIDS
1547 1547 $ hg --config extensions.largefiles=! clone http://localhost:$HGPORT r2
1548 1548 requesting all changes
1549 1549 adding changesets
1550 1550 adding manifests
1551 1551 adding file changes
1552 1552 added 1 changesets with 1 changes to 1 files
1553 1553 updating to branch default
1554 1554 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1555 1555
1556 1556 largefiles clients still work with vanilla servers
1557 1557 $ hg --config extensions.largefiles=! serve -R r1 -d -p $HGPORT1 --pid-file hg.pid
1558 1558 $ cat hg.pid >> $DAEMON_PIDS
1559 1559 $ hg clone http://localhost:$HGPORT1 r3
1560 1560 requesting all changes
1561 1561 adding changesets
1562 1562 adding manifests
1563 1563 adding file changes
1564 1564 added 1 changesets with 1 changes to 1 files
1565 1565 updating to branch default
1566 1566 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1567 1567 #endif
1568 1568
1569 1569
1570 1570 vanilla clients locked out from largefiles http repos
1571 1571 $ mkdir r4
1572 1572 $ cd r4
1573 1573 $ hg init
1574 1574 $ echo c1 > f1
1575 1575 $ hg add --large f1
1576 1576 $ hg commit -m "m1"
1577 1577 Invoking status precommit hook
1578 1578 A f1
1579 1579 $ cd ..
1580 1580
1581 1581 largefiles can be pushed locally (issue3583)
1582 1582 $ hg init dest
1583 1583 $ cd r4
1584 1584 $ hg outgoing ../dest
1585 1585 comparing with ../dest
1586 1586 searching for changes
1587 1587 changeset: 0:639881c12b4c
1588 1588 tag: tip
1589 1589 user: test
1590 1590 date: Thu Jan 01 00:00:00 1970 +0000
1591 1591 summary: m1
1592 1592
1593 1593 $ hg push ../dest
1594 1594 pushing to ../dest
1595 1595 searching for changes
1596 1596 searching for changes
1597 1597 adding changesets
1598 1598 adding manifests
1599 1599 adding file changes
1600 1600 added 1 changesets with 1 changes to 1 files
1601 1601
1602 1602 exit code with nothing outgoing (issue3611)
1603 1603 $ hg outgoing ../dest
1604 1604 comparing with ../dest
1605 1605 searching for changes
1606 1606 no changes found
1607 1607 [1]
1608 1608 $ cd ..
1609 1609
1610 1610 #if serve
1611 1611 $ hg serve -R r4 -d -p $HGPORT2 --pid-file hg.pid
1612 1612 $ cat hg.pid >> $DAEMON_PIDS
1613 1613 $ hg --config extensions.largefiles=! clone http://localhost:$HGPORT2 r5
1614 1614 abort: remote error:
1615 1615
1616 1616 This repository uses the largefiles extension.
1617 1617
1618 1618 Please enable it in your Mercurial config file.
1619 1619 [255]
1620 1620
1621 1621 used all HGPORTs, kill all daemons
1622 1622 $ "$TESTDIR/killdaemons.py" $DAEMON_PIDS
1623 1623 #endif
1624 1624
1625 1625 vanilla clients locked out from largefiles ssh repos
1626 1626 $ hg --config extensions.largefiles=! clone -e "python \"$TESTDIR/dummyssh\"" ssh://user@dummy/r4 r5
1627 1627 abort: remote error:
1628 1628
1629 1629 This repository uses the largefiles extension.
1630 1630
1631 1631 Please enable it in your Mercurial config file.
1632 1632 [255]
1633 1633
1634 1634 #if serve
1635 1635
1636 1636 largefiles clients refuse to push largefiles repos to vanilla servers
1637 1637 $ mkdir r6
1638 1638 $ cd r6
1639 1639 $ hg init
1640 1640 $ echo c1 > f1
1641 1641 $ hg add f1
1642 1642 $ hg commit -m "m1"
1643 1643 Invoking status precommit hook
1644 1644 A f1
1645 1645 $ cat >> .hg/hgrc <<!
1646 1646 > [web]
1647 1647 > push_ssl = false
1648 1648 > allow_push = *
1649 1649 > !
1650 1650 $ cd ..
1651 1651 $ hg clone r6 r7
1652 1652 updating to branch default
1653 1653 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1654 1654 $ cd r7
1655 1655 $ echo c2 > f2
1656 1656 $ hg add --large f2
1657 1657 $ hg commit -m "m2"
1658 1658 Invoking status precommit hook
1659 1659 A f2
1660 1660 $ hg --config extensions.largefiles=! -R ../r6 serve -d -p $HGPORT --pid-file ../hg.pid
1661 1661 $ cat ../hg.pid >> $DAEMON_PIDS
1662 1662 $ hg push http://localhost:$HGPORT
1663 1663 pushing to http://localhost:$HGPORT/
1664 1664 searching for changes
1665 1665 abort: http://localhost:$HGPORT/ does not appear to be a largefile store
1666 1666 [255]
1667 1667 $ cd ..
1668 1668
1669 1669 putlfile errors are shown (issue3123)
1670 1670 Corrupt the cached largefile in r7 and move it out of the servers usercache
1671 1671 $ mv r7/.hg/largefiles/4cdac4d8b084d0b599525cf732437fb337d422a8 .
1672 1672 $ echo 'client side corruption' > r7/.hg/largefiles/4cdac4d8b084d0b599525cf732437fb337d422a8
1673 1673 $ rm "$USERCACHE/4cdac4d8b084d0b599525cf732437fb337d422a8"
1674 1674 $ hg init empty
1675 1675 $ hg serve -R empty -d -p $HGPORT1 --pid-file hg.pid \
1676 1676 > --config 'web.allow_push=*' --config web.push_ssl=False
1677 1677 $ cat hg.pid >> $DAEMON_PIDS
1678 1678 $ hg push -R r7 http://localhost:$HGPORT1
1679 1679 pushing to http://localhost:$HGPORT1/
1680 1680 searching for changes
1681 1681 remote: largefiles: failed to put 4cdac4d8b084d0b599525cf732437fb337d422a8 into store: largefile contents do not match hash
1682 1682 abort: remotestore: could not put $TESTTMP/r7/.hg/largefiles/4cdac4d8b084d0b599525cf732437fb337d422a8 to remote store http://localhost:$HGPORT1/ (glob)
1683 1683 [255]
1684 1684 $ mv 4cdac4d8b084d0b599525cf732437fb337d422a8 r7/.hg/largefiles/4cdac4d8b084d0b599525cf732437fb337d422a8
1685 1685 Push of file that exists on server but is corrupted - magic healing would be nice ... but too magic
1686 1686 $ echo "server side corruption" > empty/.hg/largefiles/4cdac4d8b084d0b599525cf732437fb337d422a8
1687 1687 $ hg push -R r7 http://localhost:$HGPORT1
1688 1688 pushing to http://localhost:$HGPORT1/
1689 1689 searching for changes
1690 1690 searching for changes
1691 1691 remote: adding changesets
1692 1692 remote: adding manifests
1693 1693 remote: adding file changes
1694 1694 remote: added 2 changesets with 2 changes to 2 files
1695 1695 $ cat empty/.hg/largefiles/4cdac4d8b084d0b599525cf732437fb337d422a8
1696 1696 server side corruption
1697 1697 $ rm -rf empty
1698 1698
1699 1699 Push a largefiles repository to a served empty repository
1700 1700 $ hg init r8
1701 1701 $ echo c3 > r8/f1
1702 1702 $ hg add --large r8/f1 -R r8
1703 1703 $ hg commit -m "m1" -R r8
1704 1704 Invoking status precommit hook
1705 1705 A f1
1706 1706 $ hg init empty
1707 1707 $ hg serve -R empty -d -p $HGPORT2 --pid-file hg.pid \
1708 1708 > --config 'web.allow_push=*' --config web.push_ssl=False
1709 1709 $ cat hg.pid >> $DAEMON_PIDS
1710 1710 $ rm "${USERCACHE}"/*
1711 1711 $ hg push -R r8 http://localhost:$HGPORT2/#default
1712 1712 pushing to http://localhost:$HGPORT2/
1713 1713 searching for changes
1714 1714 searching for changes
1715 1715 remote: adding changesets
1716 1716 remote: adding manifests
1717 1717 remote: adding file changes
1718 1718 remote: added 1 changesets with 1 changes to 1 files
1719 1719 $ [ -f "${USERCACHE}"/02a439e5c31c526465ab1a0ca1f431f76b827b90 ]
1720 1720 $ [ -f empty/.hg/largefiles/02a439e5c31c526465ab1a0ca1f431f76b827b90 ]
1721 1721
1722 1722 Clone over http, no largefiles pulled on clone.
1723 1723
1724 1724 $ hg clone http://localhost:$HGPORT2/#default http-clone -U
1725 1725 adding changesets
1726 1726 adding manifests
1727 1727 adding file changes
1728 1728 added 1 changesets with 1 changes to 1 files
1729 1729
1730 1730 test 'verify' with remotestore:
1731 1731
1732 1732 $ rm "${USERCACHE}"/02a439e5c31c526465ab1a0ca1f431f76b827b90
1733 1733 $ mv empty/.hg/largefiles/02a439e5c31c526465ab1a0ca1f431f76b827b90 .
1734 1734 $ hg -R http-clone verify --large --lfa
1735 1735 checking changesets
1736 1736 checking manifests
1737 1737 crosschecking files in changesets and manifests
1738 1738 checking files
1739 1739 1 files, 1 changesets, 1 total revisions
1740 1740 searching 1 changesets for largefiles
1741 1741 changeset 0:cf03e5bb9936: f1 missing
1742 1742 verified existence of 1 revisions of 1 largefiles
1743 1743 [1]
1744 1744 $ mv 02a439e5c31c526465ab1a0ca1f431f76b827b90 empty/.hg/largefiles/
1745 1745 $ hg -R http-clone -q verify --large --lfa
1746 1746
1747 1747 largefiles pulled on update - a largefile missing on the server:
1748 1748 $ mv empty/.hg/largefiles/02a439e5c31c526465ab1a0ca1f431f76b827b90 .
1749 1749 $ hg -R http-clone up --config largefiles.usercache=http-clone-usercache
1750 1750 getting changed largefiles
1751 1751 f1: largefile 02a439e5c31c526465ab1a0ca1f431f76b827b90 not available from http://localhost:$HGPORT2/
1752 1752 0 largefiles updated, 0 removed
1753 1753 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1754 1754 $ hg -R http-clone st
1755 1755 ! f1
1756 1756 $ hg -R http-clone up -Cqr null
1757 1757
1758 1758 largefiles pulled on update - a largefile corrupted on the server:
1759 1759 $ echo corruption > empty/.hg/largefiles/02a439e5c31c526465ab1a0ca1f431f76b827b90
1760 1760 $ hg -R http-clone up --config largefiles.usercache=http-clone-usercache
1761 1761 getting changed largefiles
1762 1762 f1: data corruption (expected 02a439e5c31c526465ab1a0ca1f431f76b827b90, got 6a7bb2556144babe3899b25e5428123735bb1e27)
1763 1763 0 largefiles updated, 0 removed
1764 1764 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1765 1765 $ hg -R http-clone st
1766 1766 ! f1
1767 1767 $ [ ! -f http-clone/.hg/largefiles/02a439e5c31c526465ab1a0ca1f431f76b827b90 ]
1768 1768 $ [ ! -f http-clone/f1 ]
1769 1769 $ [ ! -f http-clone-usercache ]
1770 1770 $ hg -R http-clone verify --large --lfc
1771 1771 checking changesets
1772 1772 checking manifests
1773 1773 crosschecking files in changesets and manifests
1774 1774 checking files
1775 1775 1 files, 1 changesets, 1 total revisions
1776 1776 searching 1 changesets for largefiles
1777 1777 verified contents of 1 revisions of 1 largefiles
1778 1778 $ hg -R http-clone up -Cqr null
1779 1779
1780 1780 largefiles pulled on update - no server side problems:
1781 1781 $ mv 02a439e5c31c526465ab1a0ca1f431f76b827b90 empty/.hg/largefiles/
1782 1782 $ hg -R http-clone --debug up --config largefiles.usercache=http-clone-usercache
1783 1783 resolving manifests
1784 1784 branchmerge: False, force: False, partial: False
1785 1785 ancestor: 000000000000, local: 000000000000+, remote: cf03e5bb9936
1786 1786 .hglf/f1: remote created -> g
1787 1787 getting .hglf/f1
1788 1788 updating: .hglf/f1 1/1 files (100.00%)
1789 1789 getting changed largefiles
1790 1790 using http://localhost:$HGPORT2/
1791 1791 sending capabilities command
1792 1792 sending batch command
1793 1793 getting largefiles: 0/1 lfile (0.00%)
1794 1794 getting f1:02a439e5c31c526465ab1a0ca1f431f76b827b90
1795 1795 sending getlfile command
1796 1796 found 02a439e5c31c526465ab1a0ca1f431f76b827b90 in store
1797 1797 1 largefiles updated, 0 removed
1798 1798 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1799 1799
1800 1800 $ ls http-clone-usercache/*
1801 1801 http-clone-usercache/02a439e5c31c526465ab1a0ca1f431f76b827b90
1802 1802
1803 1803 $ rm -rf empty http-clone*
1804 1804
1805 1805 used all HGPORTs, kill all daemons
1806 1806 $ "$TESTDIR/killdaemons.py" $DAEMON_PIDS
1807 1807
1808 1808 #endif
1809 1809
1810 1810
1811 1811 #if unix-permissions
1812 1812
1813 1813 Clone a local repository owned by another user
1814 1814 We have to simulate that here by setting $HOME and removing write permissions
1815 1815 $ ORIGHOME="$HOME"
1816 1816 $ mkdir alice
1817 1817 $ HOME="`pwd`/alice"
1818 1818 $ cd alice
1819 1819 $ hg init pubrepo
1820 1820 $ cd pubrepo
1821 1821 $ dd if=/dev/zero bs=1k count=11k > a-large-file 2> /dev/null
1822 1822 $ hg add --large a-large-file
1823 1823 $ hg commit -m "Add a large file"
1824 1824 Invoking status precommit hook
1825 1825 A a-large-file
1826 1826 $ cd ..
1827 1827 $ chmod -R a-w pubrepo
1828 1828 $ cd ..
1829 1829 $ mkdir bob
1830 1830 $ HOME="`pwd`/bob"
1831 1831 $ cd bob
1832 1832 $ hg clone --pull ../alice/pubrepo pubrepo
1833 1833 requesting all changes
1834 1834 adding changesets
1835 1835 adding manifests
1836 1836 adding file changes
1837 1837 added 1 changesets with 1 changes to 1 files
1838 1838 updating to branch default
1839 1839 getting changed largefiles
1840 1840 1 largefiles updated, 0 removed
1841 1841 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1842 1842 $ cd ..
1843 1843 $ chmod -R u+w alice/pubrepo
1844 1844 $ HOME="$ORIGHOME"
1845 1845
1846 1846 #endif
1847 1847
1848 1848 #if symlink
1849 1849
1850 1850 Symlink to a large largefile should behave the same as a symlink to a normal file
1851 1851 $ hg init largesymlink
1852 1852 $ cd largesymlink
1853 1853 $ dd if=/dev/zero bs=1k count=10k of=largefile 2>/dev/null
1854 1854 $ hg add --large largefile
1855 1855 $ hg commit -m "commit a large file"
1856 1856 Invoking status precommit hook
1857 1857 A largefile
1858 1858 $ ln -s largefile largelink
1859 1859 $ hg add largelink
1860 1860 $ hg commit -m "commit a large symlink"
1861 1861 Invoking status precommit hook
1862 1862 A largelink
1863 1863 $ rm -f largelink
1864 1864 $ hg up >/dev/null
1865 1865 $ test -f largelink
1866 1866 [1]
1867 1867 $ test -L largelink
1868 1868 [1]
1869 1869 $ rm -f largelink # make next part of the test independent of the previous
1870 1870 $ hg up -C >/dev/null
1871 1871 $ test -f largelink
1872 1872 $ test -L largelink
1873 1873 $ cd ..
1874 1874
1875 1875 #endif
1876 1876
1877 1877 test for pattern matching on 'hg status':
1878 1878 to boost performance, largefiles checks whether specified patterns are
1879 1879 related to largefiles in working directory (NOT to STANDIN) or not.
1880 1880
1881 1881 $ hg init statusmatch
1882 1882 $ cd statusmatch
1883 1883
1884 1884 $ mkdir -p a/b/c/d
1885 1885 $ echo normal > a/b/c/d/e.normal.txt
1886 1886 $ hg add a/b/c/d/e.normal.txt
1887 1887 $ echo large > a/b/c/d/e.large.txt
1888 1888 $ hg add --large a/b/c/d/e.large.txt
1889 1889 $ mkdir -p a/b/c/x
1890 1890 $ echo normal > a/b/c/x/y.normal.txt
1891 1891 $ hg add a/b/c/x/y.normal.txt
1892 1892 $ hg commit -m 'add files'
1893 1893 Invoking status precommit hook
1894 1894 A a/b/c/d/e.large.txt
1895 1895 A a/b/c/d/e.normal.txt
1896 1896 A a/b/c/x/y.normal.txt
1897 1897
1898 1898 (1) no pattern: no performance boost
1899 1899 $ hg status -A
1900 1900 C a/b/c/d/e.large.txt
1901 1901 C a/b/c/d/e.normal.txt
1902 1902 C a/b/c/x/y.normal.txt
1903 1903
1904 1904 (2) pattern not related to largefiles: performance boost
1905 1905 $ hg status -A a/b/c/x
1906 1906 C a/b/c/x/y.normal.txt
1907 1907
1908 1908 (3) pattern related to largefiles: no performance boost
1909 1909 $ hg status -A a/b/c/d
1910 1910 C a/b/c/d/e.large.txt
1911 1911 C a/b/c/d/e.normal.txt
1912 1912
1913 1913 (4) pattern related to STANDIN (not to largefiles): performance boost
1914 1914 $ hg status -A .hglf/a
1915 1915 C .hglf/a/b/c/d/e.large.txt
1916 1916
1917 1917 (5) mixed case: no performance boost
1918 1918 $ hg status -A a/b/c/x a/b/c/d
1919 1919 C a/b/c/d/e.large.txt
1920 1920 C a/b/c/d/e.normal.txt
1921 1921 C a/b/c/x/y.normal.txt
1922 1922
1923 1923 verify that largefiles doesn't break filesets
1924 1924
1925 1925 $ hg log --rev . --exclude "set:binary()"
1926 1926 changeset: 0:41bd42f10efa
1927 1927 tag: tip
1928 1928 user: test
1929 1929 date: Thu Jan 01 00:00:00 1970 +0000
1930 1930 summary: add files
1931 1931
1932 1932 verify that large files in subrepos handled properly
1933 1933 $ hg init subrepo
1934 1934 $ echo "subrepo = subrepo" > .hgsub
1935 1935 $ hg add .hgsub
1936 1936 $ hg ci -m "add subrepo"
1937 1937 Invoking status precommit hook
1938 1938 A .hgsub
1939 1939 ? .hgsubstate
1940 1940 $ echo "rev 1" > subrepo/large.txt
1941 1941 $ hg -R subrepo add --large subrepo/large.txt
1942 1942 $ hg sum
1943 1943 parent: 1:8ee150ea2e9c tip
1944 1944 add subrepo
1945 1945 branch: default
1946 1946 commit: 1 subrepos
1947 1947 update: (current)
1948 1948 $ hg st
1949 1949 $ hg st -S
1950 1950 A subrepo/large.txt
1951 1951 $ hg ci -S -m "commit top repo"
1952 1952 committing subrepository subrepo
1953 1953 Invoking status precommit hook
1954 1954 A large.txt
1955 1955 Invoking status precommit hook
1956 1956 M .hgsubstate
1957 1957 # No differences
1958 1958 $ hg st -S
1959 1959 $ hg sum
1960 1960 parent: 2:ce4cd0c527a6 tip
1961 1961 commit top repo
1962 1962 branch: default
1963 1963 commit: (clean)
1964 1964 update: (current)
1965 1965 $ echo "rev 2" > subrepo/large.txt
1966 1966 $ hg st -S
1967 1967 M subrepo/large.txt
1968 1968 $ hg sum
1969 1969 parent: 2:ce4cd0c527a6 tip
1970 1970 commit top repo
1971 1971 branch: default
1972 1972 commit: 1 subrepos
1973 1973 update: (current)
1974 1974 $ hg ci -m "this commit should fail without -S"
1975 1975 abort: uncommitted changes in subrepo subrepo
1976 1976 (use --subrepos for recursive commit)
1977 1977 [255]
1978 1978
1979 1979 Add a normal file to the subrepo, then test archiving
1980 1980
1981 1981 $ echo 'normal file' > subrepo/normal.txt
1982 1982 $ hg -R subrepo add subrepo/normal.txt
1983 1983
1984 1984 Lock in subrepo, otherwise the change isn't archived
1985 1985
1986 1986 $ hg ci -S -m "add normal file to top level"
1987 1987 committing subrepository subrepo
1988 1988 Invoking status precommit hook
1989 1989 M large.txt
1990 1990 A normal.txt
1991 1991 Invoking status precommit hook
1992 1992 M .hgsubstate
1993 1993 $ hg archive -S ../lf_subrepo_archive
1994 1994 $ find ../lf_subrepo_archive | sort
1995 1995 ../lf_subrepo_archive
1996 1996 ../lf_subrepo_archive/.hg_archival.txt
1997 1997 ../lf_subrepo_archive/.hgsub
1998 1998 ../lf_subrepo_archive/.hgsubstate
1999 1999 ../lf_subrepo_archive/a
2000 2000 ../lf_subrepo_archive/a/b
2001 2001 ../lf_subrepo_archive/a/b/c
2002 2002 ../lf_subrepo_archive/a/b/c/d
2003 2003 ../lf_subrepo_archive/a/b/c/d/e.large.txt
2004 2004 ../lf_subrepo_archive/a/b/c/d/e.normal.txt
2005 2005 ../lf_subrepo_archive/a/b/c/x
2006 2006 ../lf_subrepo_archive/a/b/c/x/y.normal.txt
2007 2007 ../lf_subrepo_archive/subrepo
2008 2008 ../lf_subrepo_archive/subrepo/large.txt
2009 2009 ../lf_subrepo_archive/subrepo/normal.txt
2010 2010
2011 2011 Test update with subrepos.
2012 2012
2013 2013 $ hg update 0
2014 2014 getting changed largefiles
2015 2015 0 largefiles updated, 1 removed
2016 2016 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
2017 2017 $ hg status -S
2018 2018 $ hg update tip
2019 2019 getting changed largefiles
2020 2020 1 largefiles updated, 0 removed
2021 2021 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
2022 2022 $ hg status -S
2023 2023 # modify a large file
2024 2024 $ echo "modified" > subrepo/large.txt
2025 2025 $ hg st -S
2026 2026 M subrepo/large.txt
2027 2027 # update -C should revert the change.
2028 2028 $ hg update -C
2029 2029 getting changed largefiles
2030 2030 1 largefiles updated, 0 removed
2031 2031 getting changed largefiles
2032 2032 0 largefiles updated, 0 removed
2033 2033 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
2034 2034 $ hg status -S
2035 2035
2036 2036 Test archiving a revision that references a subrepo that is not yet
2037 2037 cloned (see test-subrepo-recursion.t):
2038 2038
2039 2039 $ hg clone -U . ../empty
2040 2040 $ cd ../empty
2041 2041 $ hg archive --subrepos -r tip ../archive.tar.gz
2042 2042 cloning subrepo subrepo from $TESTTMP/statusmatch/subrepo
2043 2043 $ cd ..
2044 2044
2045 2045 Test that addremove picks up largefiles prior to the initial commit (issue3541)
2046 2046
2047 2047 $ hg init addrm2
2048 2048 $ cd addrm2
2049 2049 $ touch large.dat
2050 2050 $ touch large2.dat
2051 2051 $ touch normal
2052 2052 $ hg add --large large.dat
2053 2053 $ hg addremove -v
2054 2054 adding large2.dat as a largefile
2055 2055 adding normal
2056 2056
2057 2057 Test that forgetting all largefiles reverts to islfilesrepo() == False
2058 2058 (addremove will add *.dat as normal files now)
2059 2059 $ hg forget large.dat
2060 2060 $ hg forget large2.dat
2061 2061 $ hg addremove -v
2062 2062 adding large.dat
2063 2063 adding large2.dat
2064 2064
2065 2065 Test commit's addremove option prior to the first commit
2066 2066 $ hg forget large.dat
2067 2067 $ hg forget large2.dat
2068 2068 $ hg add --large large.dat
2069 2069 $ hg ci -Am "commit"
2070 2070 adding large2.dat as a largefile
2071 2071 Invoking status precommit hook
2072 2072 A large.dat
2073 2073 A large2.dat
2074 2074 A normal
2075 2075 $ find .hglf | sort
2076 2076 .hglf
2077 2077 .hglf/large.dat
2078 2078 .hglf/large2.dat
2079 2079
2080 2080 Test actions on largefiles using relative paths from subdir
2081 2081
2082 2082 $ mkdir sub
2083 2083 $ cd sub
2084 2084 $ echo anotherlarge > anotherlarge
2085 2085 $ hg add --large anotherlarge
2086 2086 $ hg st
2087 2087 A sub/anotherlarge
2088 2088 $ hg st anotherlarge
2089 2089 A anotherlarge
2090 2090 $ hg commit -m anotherlarge anotherlarge
2091 2091 Invoking status precommit hook
2092 2092 A sub/anotherlarge
2093 2093 $ hg log anotherlarge
2094 2094 changeset: 1:9627a577c5e9
2095 2095 tag: tip
2096 2096 user: test
2097 2097 date: Thu Jan 01 00:00:00 1970 +0000
2098 2098 summary: anotherlarge
2099 2099
2100 2100 $ echo more >> anotherlarge
2101 2101 $ hg st .
2102 2102 M anotherlarge
2103 2103 $ hg cat anotherlarge
2104 2104 anotherlarge
2105 2105 $ hg revert anotherlarge
2106 2106 $ hg st
2107 2107 ? sub/anotherlarge.orig
2108 2108 $ cd ..
2109 2109
2110 2110 $ cd ..
2111 2111
2112 2112 issue3651: summary/outgoing with largefiles shows "no remote repo"
2113 2113 unexpectedly
2114 2114
2115 2115 $ mkdir issue3651
2116 2116 $ cd issue3651
2117 2117
2118 2118 $ hg init src
2119 2119 $ echo a > src/a
2120 2120 $ hg -R src add --large src/a
2121 2121 $ hg -R src commit -m '#0'
2122 2122 Invoking status precommit hook
2123 2123 A a
2124 2124
2125 2125 check messages when no remote repository is specified:
2126 2126 "no remote repo" route for "hg outgoing --large" is not tested here,
2127 2127 because it can't be reproduced easily.
2128 2128
2129 2129 $ hg init clone1
2130 2130 $ hg -R clone1 -q pull src
2131 2131 $ hg -R clone1 -q update
2132 2132 $ hg -R clone1 paths | grep default
2133 2133 [1]
2134 2134
2135 2135 $ hg -R clone1 summary --large
2136 2136 parent: 0:fc0bd45326d3 tip
2137 2137 #0
2138 2138 branch: default
2139 2139 commit: (clean)
2140 2140 update: (current)
2141 2141 largefiles: (no remote repo)
2142 2142
2143 2143 check messages when there is no files to upload:
2144 2144
2145 2145 $ hg -q clone src clone2
2146 2146 $ hg -R clone2 paths | grep default
2147 2147 default = $TESTTMP/issue3651/src (glob)
2148 2148
2149 2149 $ hg -R clone2 summary --large
2150 2150 parent: 0:fc0bd45326d3 tip
2151 2151 #0
2152 2152 branch: default
2153 2153 commit: (clean)
2154 2154 update: (current)
2155 2155 searching for changes
2156 2156 largefiles: (no files to upload)
2157 2157 $ hg -R clone2 outgoing --large
2158 2158 comparing with $TESTTMP/issue3651/src (glob)
2159 2159 searching for changes
2160 2160 no changes found
2161 2161 searching for changes
2162 2162 largefiles: no files to upload
2163 2163 [1]
2164 2164
2165 2165 check messages when there are files to upload:
2166 2166
2167 2167 $ echo b > clone2/b
2168 2168 $ hg -R clone2 add --large clone2/b
2169 2169 $ hg -R clone2 commit -m '#1'
2170 2170 Invoking status precommit hook
2171 2171 A b
2172 2172 $ hg -R clone2 summary --large
2173 2173 parent: 1:1acbe71ce432 tip
2174 2174 #1
2175 2175 branch: default
2176 2176 commit: (clean)
2177 2177 update: (current)
2178 2178 searching for changes
2179 2179 largefiles: 1 to upload
2180 2180 $ hg -R clone2 outgoing --large
2181 2181 comparing with $TESTTMP/issue3651/src (glob)
2182 2182 searching for changes
2183 2183 changeset: 1:1acbe71ce432
2184 2184 tag: tip
2185 2185 user: test
2186 2186 date: Thu Jan 01 00:00:00 1970 +0000
2187 2187 summary: #1
2188 2188
2189 2189 searching for changes
2190 2190 largefiles to upload:
2191 2191 b
2192 2192
2193 2193
2194 2194 $ cd ..
2195 2195
2196 2196 merge action 'd' for 'local renamed directory to d2/g' which has no filename
2197 2197
2198 2198 $ hg init merge-action
2199 2199 $ cd merge-action
2200 2200 $ touch l
2201 2201 $ hg add --large l
2202 2202 $ mkdir d1
2203 2203 $ touch d1/f
2204 2204 $ hg ci -Aqm0
2205 2205 Invoking status precommit hook
2206 2206 A d1/f
2207 2207 A l
2208 2208 $ echo > d1/f
2209 2209 $ touch d1/g
2210 2210 $ hg ci -Aqm1
2211 2211 Invoking status precommit hook
2212 2212 M d1/f
2213 2213 A d1/g
2214 2214 $ hg up -qr0
2215 2215 $ hg mv d1 d2
2216 2216 moving d1/f to d2/f (glob)
2217 2217 $ hg ci -qm2
2218 2218 Invoking status precommit hook
2219 2219 A d2/f
2220 2220 R d1/f
2221 2221 $ hg merge
2222 2222 merging d2/f and d1/f to d2/f
2223 2223 1 files updated, 1 files merged, 0 files removed, 0 files unresolved
2224 2224 (branch merge, don't forget to commit)
2225 2225 getting changed largefiles
2226 2226 0 largefiles updated, 0 removed
2227 2227 $ cd ..
2228 2228
2229 2229 Check whether "largefiles" feature is supported only in repositories
2230 2230 enabling largefiles extension.
2231 2231
2232 2232 $ mkdir individualenabling
2233 2233 $ cd individualenabling
2234 2234
2235 2235 $ hg init enabledlocally
2236 2236 $ echo large > enabledlocally/large
2237 2237 $ hg -R enabledlocally add --large enabledlocally/large
2238 2238 $ hg -R enabledlocally commit -m '#0'
2239 2239 Invoking status precommit hook
2240 2240 A large
2241 2241
2242 2242 $ hg init notenabledlocally
2243 2243 $ echo large > notenabledlocally/large
2244 2244 $ hg -R notenabledlocally add --large notenabledlocally/large
2245 2245 $ hg -R notenabledlocally commit -m '#0'
2246 2246 Invoking status precommit hook
2247 2247 A large
2248 2248
2249 2249 $ cat >> $HGRCPATH <<EOF
2250 2250 > [extensions]
2251 2251 > # disable globally
2252 2252 > largefiles=!
2253 2253 > EOF
2254 2254 $ cat >> enabledlocally/.hg/hgrc <<EOF
2255 2255 > [extensions]
2256 2256 > # enable locally
2257 2257 > largefiles=
2258 2258 > EOF
2259 2259 $ hg -R enabledlocally root
2260 2260 $TESTTMP/individualenabling/enabledlocally (glob)
2261 2261 $ hg -R notenabledlocally root
2262 2262 abort: unknown repository format: requires features 'largefiles' (upgrade Mercurial)!
2263 2263 [255]
2264 2264
2265 2265 $ hg init push-dst
2266 2266 $ hg -R enabledlocally push push-dst
2267 2267 pushing to push-dst
2268 2268 abort: required features are not supported in the destination: largefiles
2269 2269 [255]
2270 2270
2271 2271 $ hg init pull-src
2272 2272 $ hg -R pull-src pull enabledlocally
2273 2273 pulling from enabledlocally
2274 2274 abort: required features are not supported in the destination: largefiles
2275 2275 [255]
2276 2276
2277 2277 $ hg clone enabledlocally clone-dst
2278 2278 abort: unknown repository format: requires features 'largefiles' (upgrade Mercurial)!
2279 2279 [255]
2280 2280 $ test -d clone-dst
2281 2281 [1]
2282 2282 $ hg clone --pull enabledlocally clone-pull-dst
2283 2283 abort: required features are not supported in the destination: largefiles
2284 2284 [255]
2285 2285 $ test -d clone-pull-dst
2286 2286 [1]
2287 2287
2288 #if serve
2289
2290 Test largefiles specific peer setup, when largefiles is enabled
2291 locally (issue4109)
2292
2293 $ hg showconfig extensions | grep largefiles
2294 extensions.largefiles=!
2295 $ mkdir -p $TESTTMP/individualenabling/usercache
2296
2297 $ hg serve -R enabledlocally -d -p $HGPORT --pid-file hg.pid
2298 $ cat hg.pid >> $DAEMON_PIDS
2299
2300 $ hg init pull-dst
2301 $ cat > pull-dst/.hg/hgrc <<EOF
2302 > [extensions]
2303 > # enable locally
2304 > largefiles=
2305 > [largefiles]
2306 > # ignore system cache to force largefiles specific wire proto access
2307 > usercache=$TESTTMP/individualenabling/usercache
2308 > EOF
2309 $ hg -R pull-dst -q pull -u http://localhost:$HGPORT
2310
2311 $ "$TESTDIR/killdaemons.py" $DAEMON_PIDS
2312 #endif
2313
2288 2314 $ cd ..
General Comments 0
You need to be logged in to leave comments. Login now