##// END OF EJS Templates
clone: don't save user's password in .hg/hgrc (Issue3122)
Augie Fackler -
r15552:62c9183a stable
parent child Browse files
Show More
@@ -1,578 +1,581
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, httprepo, sshrepo, statichttprepo, bookmarks
13 13 import lock, util, extensions, error, node
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, repo, branches, revs):
24 24 hashbranch, branches = branches
25 25 if not hashbranch and not branches:
26 26 return revs or None, revs and revs[0] or None
27 27 revs = revs and list(revs) or []
28 28 if not repo.capable('branchmap'):
29 29 if branches:
30 30 raise util.Abort(_("remote branch lookup not supported"))
31 31 revs.append(hashbranch)
32 32 return revs, revs[0]
33 33 branchmap = repo.branchmap()
34 34
35 35 def primary(branch):
36 36 if branch == '.':
37 37 if not lrepo or not lrepo.local():
38 38 raise util.Abort(_("dirstate branch not accessible"))
39 39 branch = lrepo.dirstate.branch()
40 40 if branch in branchmap:
41 41 revs.extend(node.hex(r) for r in reversed(branchmap[branch]))
42 42 return True
43 43 else:
44 44 return False
45 45
46 46 for branch in branches:
47 47 if not primary(branch):
48 48 raise error.RepoLookupError(_("unknown branch '%s'") % branch)
49 49 if hashbranch:
50 50 if not primary(hashbranch):
51 51 revs.append(hashbranch)
52 52 return revs, revs[0]
53 53
54 54 def parseurl(path, branches=None):
55 55 '''parse url#branch, returning (url, (branch, branches))'''
56 56
57 57 u = util.url(path)
58 58 branch = None
59 59 if u.fragment:
60 60 branch = u.fragment
61 61 u.fragment = None
62 62 return str(u), (branch, branches or [])
63 63
64 64 schemes = {
65 65 'bundle': bundlerepo,
66 66 'file': _local,
67 67 'http': httprepo,
68 68 'https': httprepo,
69 69 'ssh': sshrepo,
70 70 'static-http': statichttprepo,
71 71 }
72 72
73 73 def _peerlookup(path):
74 74 u = util.url(path)
75 75 scheme = u.scheme or 'file'
76 76 thing = schemes.get(scheme) or schemes['file']
77 77 try:
78 78 return thing(path)
79 79 except TypeError:
80 80 return thing
81 81
82 82 def islocal(repo):
83 83 '''return true if repo or path is local'''
84 84 if isinstance(repo, str):
85 85 try:
86 86 return _peerlookup(repo).islocal(repo)
87 87 except AttributeError:
88 88 return False
89 89 return repo.local()
90 90
91 91 def repository(ui, path='', create=False):
92 92 """return a repository object for the specified path"""
93 93 repo = _peerlookup(path).instance(ui, path, create)
94 94 ui = getattr(repo, "ui", ui)
95 95 for name, module in extensions.extensions():
96 96 hook = getattr(module, 'reposetup', None)
97 97 if hook:
98 98 hook(ui, repo)
99 99 return repo
100 100
101 101 def peer(uiorrepo, opts, path, create=False):
102 102 '''return a repository peer for the specified path'''
103 103 rui = remoteui(uiorrepo, opts)
104 104 return repository(rui, path, create)
105 105
106 106 def defaultdest(source):
107 107 '''return default destination of clone if none is given'''
108 108 return os.path.basename(os.path.normpath(source))
109 109
110 110 def share(ui, source, dest=None, update=True):
111 111 '''create a shared repository'''
112 112
113 113 if not islocal(source):
114 114 raise util.Abort(_('can only share local repositories'))
115 115
116 116 if not dest:
117 117 dest = defaultdest(source)
118 118 else:
119 119 dest = ui.expandpath(dest)
120 120
121 121 if isinstance(source, str):
122 122 origsource = ui.expandpath(source)
123 123 source, branches = parseurl(origsource)
124 124 srcrepo = repository(ui, source)
125 125 rev, checkout = addbranchrevs(srcrepo, srcrepo, branches, None)
126 126 else:
127 127 srcrepo = source
128 128 origsource = source = srcrepo.url()
129 129 checkout = None
130 130
131 131 sharedpath = srcrepo.sharedpath # if our source is already sharing
132 132
133 133 root = os.path.realpath(dest)
134 134 roothg = os.path.join(root, '.hg')
135 135
136 136 if os.path.exists(roothg):
137 137 raise util.Abort(_('destination already exists'))
138 138
139 139 if not os.path.isdir(root):
140 140 os.mkdir(root)
141 141 util.makedir(roothg, notindexed=True)
142 142
143 143 requirements = ''
144 144 try:
145 145 requirements = srcrepo.opener.read('requires')
146 146 except IOError, inst:
147 147 if inst.errno != errno.ENOENT:
148 148 raise
149 149
150 150 requirements += 'shared\n'
151 151 util.writefile(os.path.join(roothg, 'requires'), requirements)
152 152 util.writefile(os.path.join(roothg, 'sharedpath'), sharedpath)
153 153
154 154 r = repository(ui, root)
155 155
156 156 default = srcrepo.ui.config('paths', 'default')
157 157 if default:
158 158 fp = r.opener("hgrc", "w", text=True)
159 159 fp.write("[paths]\n")
160 160 fp.write("default = %s\n" % default)
161 161 fp.close()
162 162
163 163 if update:
164 164 r.ui.status(_("updating working directory\n"))
165 165 if update is not True:
166 166 checkout = update
167 167 for test in (checkout, 'default', 'tip'):
168 168 if test is None:
169 169 continue
170 170 try:
171 171 uprev = r.lookup(test)
172 172 break
173 173 except error.RepoLookupError:
174 174 continue
175 175 _update(r, uprev)
176 176
177 177 def copystore(ui, srcrepo, destpath):
178 178 '''copy files from store of srcrepo in destpath
179 179
180 180 returns destlock
181 181 '''
182 182 destlock = None
183 183 try:
184 184 hardlink = None
185 185 num = 0
186 186 for f in srcrepo.store.copylist():
187 187 src = os.path.join(srcrepo.sharedpath, f)
188 188 dst = os.path.join(destpath, f)
189 189 dstbase = os.path.dirname(dst)
190 190 if dstbase and not os.path.exists(dstbase):
191 191 os.mkdir(dstbase)
192 192 if os.path.exists(src):
193 193 if dst.endswith('data'):
194 194 # lock to avoid premature writing to the target
195 195 destlock = lock.lock(os.path.join(dstbase, "lock"))
196 196 hardlink, n = util.copyfiles(src, dst, hardlink)
197 197 num += n
198 198 if hardlink:
199 199 ui.debug("linked %d files\n" % num)
200 200 else:
201 201 ui.debug("copied %d files\n" % num)
202 202 return destlock
203 203 except:
204 204 release(destlock)
205 205 raise
206 206
207 207 def clone(ui, peeropts, source, dest=None, pull=False, rev=None,
208 208 update=True, stream=False, branch=None):
209 209 """Make a copy of an existing repository.
210 210
211 211 Create a copy of an existing repository in a new directory. The
212 212 source and destination are URLs, as passed to the repository
213 213 function. Returns a pair of repository objects, the source and
214 214 newly created destination.
215 215
216 216 The location of the source is added to the new repository's
217 217 .hg/hgrc file, as the default to be used for future pulls and
218 218 pushes.
219 219
220 220 If an exception is raised, the partly cloned/updated destination
221 221 repository will be deleted.
222 222
223 223 Arguments:
224 224
225 225 source: repository object or URL
226 226
227 227 dest: URL of destination repository to create (defaults to base
228 228 name of source repository)
229 229
230 230 pull: always pull from source repository, even in local case
231 231
232 232 stream: stream raw data uncompressed from repository (fast over
233 233 LAN, slow over WAN)
234 234
235 235 rev: revision to clone up to (implies pull=True)
236 236
237 237 update: update working directory after clone completes, if
238 238 destination is local repository (True means update to default rev,
239 239 anything else is treated as a revision)
240 240
241 241 branch: branches to clone
242 242 """
243 243
244 244 if isinstance(source, str):
245 245 origsource = ui.expandpath(source)
246 246 source, branch = parseurl(origsource, branch)
247 247 srcrepo = repository(remoteui(ui, peeropts), source)
248 248 else:
249 249 srcrepo = source
250 250 branch = (None, branch or [])
251 251 origsource = source = srcrepo.url()
252 252 rev, checkout = addbranchrevs(srcrepo, srcrepo, branch, rev)
253 253
254 254 if dest is None:
255 255 dest = defaultdest(source)
256 256 ui.status(_("destination directory: %s\n") % dest)
257 257 else:
258 258 dest = ui.expandpath(dest)
259 259
260 260 dest = util.urllocalpath(dest)
261 261 source = util.urllocalpath(source)
262 262
263 263 if os.path.exists(dest):
264 264 if not os.path.isdir(dest):
265 265 raise util.Abort(_("destination '%s' already exists") % dest)
266 266 elif os.listdir(dest):
267 267 raise util.Abort(_("destination '%s' is not empty") % dest)
268 268
269 269 class DirCleanup(object):
270 270 def __init__(self, dir_):
271 271 self.rmtree = shutil.rmtree
272 272 self.dir_ = dir_
273 273 def close(self):
274 274 self.dir_ = None
275 275 def cleanup(self):
276 276 if self.dir_:
277 277 self.rmtree(self.dir_, True)
278 278
279 279 srclock = destlock = dircleanup = None
280 280 try:
281 281 abspath = origsource
282 282 if islocal(origsource):
283 283 abspath = os.path.abspath(util.urllocalpath(origsource))
284 284
285 285 if islocal(dest):
286 286 dircleanup = DirCleanup(dest)
287 287
288 288 copy = False
289 289 if srcrepo.cancopy() and islocal(dest):
290 290 copy = not pull and not rev
291 291
292 292 if copy:
293 293 try:
294 294 # we use a lock here because if we race with commit, we
295 295 # can end up with extra data in the cloned revlogs that's
296 296 # not pointed to by changesets, thus causing verify to
297 297 # fail
298 298 srclock = srcrepo.lock(wait=False)
299 299 except error.LockError:
300 300 copy = False
301 301
302 302 if copy:
303 303 srcrepo.hook('preoutgoing', throw=True, source='clone')
304 304 hgdir = os.path.realpath(os.path.join(dest, ".hg"))
305 305 if not os.path.exists(dest):
306 306 os.mkdir(dest)
307 307 else:
308 308 # only clean up directories we create ourselves
309 309 dircleanup.dir_ = hgdir
310 310 try:
311 311 destpath = hgdir
312 312 util.makedir(destpath, notindexed=True)
313 313 except OSError, inst:
314 314 if inst.errno == errno.EEXIST:
315 315 dircleanup.close()
316 316 raise util.Abort(_("destination '%s' already exists")
317 317 % dest)
318 318 raise
319 319
320 320 destlock = copystore(ui, srcrepo, destpath)
321 321
322 322 # we need to re-init the repo after manually copying the data
323 323 # into it
324 324 destrepo = repository(remoteui(ui, peeropts), dest)
325 325 srcrepo.hook('outgoing', source='clone',
326 326 node=node.hex(node.nullid))
327 327 else:
328 328 try:
329 329 destrepo = repository(remoteui(ui, peeropts), dest,
330 330 create=True)
331 331 except OSError, inst:
332 332 if inst.errno == errno.EEXIST:
333 333 dircleanup.close()
334 334 raise util.Abort(_("destination '%s' already exists")
335 335 % dest)
336 336 raise
337 337
338 338 revs = None
339 339 if rev:
340 340 if not srcrepo.capable('lookup'):
341 341 raise util.Abort(_("src repository does not support "
342 342 "revision lookup and so doesn't "
343 343 "support clone by revision"))
344 344 revs = [srcrepo.lookup(r) for r in rev]
345 345 checkout = revs[0]
346 346 if destrepo.local():
347 347 destrepo.clone(srcrepo, heads=revs, stream=stream)
348 348 elif srcrepo.local():
349 349 srcrepo.push(destrepo, revs=revs)
350 350 else:
351 351 raise util.Abort(_("clone from remote to remote not supported"))
352 352
353 353 if dircleanup:
354 354 dircleanup.close()
355 355
356 356 if destrepo.local():
357 357 fp = destrepo.opener("hgrc", "w", text=True)
358 358 fp.write("[paths]\n")
359 fp.write("default = %s\n" % abspath)
359 u = util.url(abspath)
360 u.passwd = None
361 defaulturl = str(u)
362 fp.write("default = %s\n" % defaulturl)
360 363 fp.close()
361 364
362 destrepo.ui.setconfig('paths', 'default', abspath)
365 destrepo.ui.setconfig('paths', 'default', defaulturl)
363 366
364 367 if update:
365 368 if update is not True:
366 369 checkout = update
367 370 if srcrepo.local():
368 371 checkout = srcrepo.lookup(update)
369 372 for test in (checkout, 'default', 'tip'):
370 373 if test is None:
371 374 continue
372 375 try:
373 376 uprev = destrepo.lookup(test)
374 377 break
375 378 except error.RepoLookupError:
376 379 continue
377 380 bn = destrepo[uprev].branch()
378 381 destrepo.ui.status(_("updating to branch %s\n") % bn)
379 382 _update(destrepo, uprev)
380 383
381 384 # clone all bookmarks
382 385 if destrepo.local() and srcrepo.capable("pushkey"):
383 386 rb = srcrepo.listkeys('bookmarks')
384 387 for k, n in rb.iteritems():
385 388 try:
386 389 m = destrepo.lookup(n)
387 390 destrepo._bookmarks[k] = m
388 391 except error.RepoLookupError:
389 392 pass
390 393 if rb:
391 394 bookmarks.write(destrepo)
392 395 elif srcrepo.local() and destrepo.capable("pushkey"):
393 396 for k, n in srcrepo._bookmarks.iteritems():
394 397 destrepo.pushkey('bookmarks', k, '', hex(n))
395 398
396 399 return srcrepo, destrepo
397 400 finally:
398 401 release(srclock, destlock)
399 402 if dircleanup is not None:
400 403 dircleanup.cleanup()
401 404
402 405 def _showstats(repo, stats):
403 406 repo.ui.status(_("%d files updated, %d files merged, "
404 407 "%d files removed, %d files unresolved\n") % stats)
405 408
406 409 def update(repo, node):
407 410 """update the working directory to node, merging linear changes"""
408 411 stats = mergemod.update(repo, node, False, False, None)
409 412 _showstats(repo, stats)
410 413 if stats[3]:
411 414 repo.ui.status(_("use 'hg resolve' to retry unresolved file merges\n"))
412 415 return stats[3] > 0
413 416
414 417 # naming conflict in clone()
415 418 _update = update
416 419
417 420 def clean(repo, node, show_stats=True):
418 421 """forcibly switch the working directory to node, clobbering changes"""
419 422 stats = mergemod.update(repo, node, False, True, None)
420 423 if show_stats:
421 424 _showstats(repo, stats)
422 425 return stats[3] > 0
423 426
424 427 def merge(repo, node, force=None, remind=True):
425 428 """Branch merge with node, resolving changes. Return true if any
426 429 unresolved conflicts."""
427 430 stats = mergemod.update(repo, node, True, force, False)
428 431 _showstats(repo, stats)
429 432 if stats[3]:
430 433 repo.ui.status(_("use 'hg resolve' to retry unresolved file merges "
431 434 "or 'hg update -C .' to abandon\n"))
432 435 elif remind:
433 436 repo.ui.status(_("(branch merge, don't forget to commit)\n"))
434 437 return stats[3] > 0
435 438
436 439 def _incoming(displaychlist, subreporecurse, ui, repo, source,
437 440 opts, buffered=False):
438 441 """
439 442 Helper for incoming / gincoming.
440 443 displaychlist gets called with
441 444 (remoterepo, incomingchangesetlist, displayer) parameters,
442 445 and is supposed to contain only code that can't be unified.
443 446 """
444 447 source, branches = parseurl(ui.expandpath(source), opts.get('branch'))
445 448 other = peer(repo, opts, source)
446 449 ui.status(_('comparing with %s\n') % util.hidepassword(source))
447 450 revs, checkout = addbranchrevs(repo, other, branches, opts.get('rev'))
448 451
449 452 if revs:
450 453 revs = [other.lookup(rev) for rev in revs]
451 454 other, chlist, cleanupfn = bundlerepo.getremotechanges(ui, repo, other,
452 455 revs, opts["bundle"], opts["force"])
453 456 try:
454 457 if not chlist:
455 458 ui.status(_("no changes found\n"))
456 459 return subreporecurse()
457 460
458 461 displayer = cmdutil.show_changeset(ui, other, opts, buffered)
459 462
460 463 # XXX once graphlog extension makes it into core,
461 464 # should be replaced by a if graph/else
462 465 displaychlist(other, chlist, displayer)
463 466
464 467 displayer.close()
465 468 finally:
466 469 cleanupfn()
467 470 subreporecurse()
468 471 return 0 # exit code is zero since we found incoming changes
469 472
470 473 def incoming(ui, repo, source, opts):
471 474 def subreporecurse():
472 475 ret = 1
473 476 if opts.get('subrepos'):
474 477 ctx = repo[None]
475 478 for subpath in sorted(ctx.substate):
476 479 sub = ctx.sub(subpath)
477 480 ret = min(ret, sub.incoming(ui, source, opts))
478 481 return ret
479 482
480 483 def display(other, chlist, displayer):
481 484 limit = cmdutil.loglimit(opts)
482 485 if opts.get('newest_first'):
483 486 chlist.reverse()
484 487 count = 0
485 488 for n in chlist:
486 489 if limit is not None and count >= limit:
487 490 break
488 491 parents = [p for p in other.changelog.parents(n) if p != nullid]
489 492 if opts.get('no_merges') and len(parents) == 2:
490 493 continue
491 494 count += 1
492 495 displayer.show(other[n])
493 496 return _incoming(display, subreporecurse, ui, repo, source, opts)
494 497
495 498 def _outgoing(ui, repo, dest, opts):
496 499 dest = ui.expandpath(dest or 'default-push', dest or 'default')
497 500 dest, branches = parseurl(dest, opts.get('branch'))
498 501 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
499 502 revs, checkout = addbranchrevs(repo, repo, branches, opts.get('rev'))
500 503 if revs:
501 504 revs = [repo.lookup(rev) for rev in revs]
502 505
503 506 other = peer(repo, opts, dest)
504 507 common, outheads = discovery.findcommonoutgoing(repo, other, revs,
505 508 force=opts.get('force'))
506 509 o = repo.changelog.findmissing(common, outheads)
507 510 if not o:
508 511 ui.status(_("no changes found\n"))
509 512 return None
510 513 return o
511 514
512 515 def outgoing(ui, repo, dest, opts):
513 516 def recurse():
514 517 ret = 1
515 518 if opts.get('subrepos'):
516 519 ctx = repo[None]
517 520 for subpath in sorted(ctx.substate):
518 521 sub = ctx.sub(subpath)
519 522 ret = min(ret, sub.outgoing(ui, dest, opts))
520 523 return ret
521 524
522 525 limit = cmdutil.loglimit(opts)
523 526 o = _outgoing(ui, repo, dest, opts)
524 527 if o is None:
525 528 return recurse()
526 529
527 530 if opts.get('newest_first'):
528 531 o.reverse()
529 532 displayer = cmdutil.show_changeset(ui, repo, opts)
530 533 count = 0
531 534 for n in o:
532 535 if limit is not None and count >= limit:
533 536 break
534 537 parents = [p for p in repo.changelog.parents(n) if p != nullid]
535 538 if opts.get('no_merges') and len(parents) == 2:
536 539 continue
537 540 count += 1
538 541 displayer.show(repo[n])
539 542 displayer.close()
540 543 recurse()
541 544 return 0 # exit code is zero since we found outgoing changes
542 545
543 546 def revert(repo, node, choose):
544 547 """revert changes to revision in node without updating dirstate"""
545 548 return mergemod.update(repo, node, False, True, choose)[3] > 0
546 549
547 550 def verify(repo):
548 551 """verify the consistency of a repository"""
549 552 return verifymod.verify(repo)
550 553
551 554 def remoteui(src, opts):
552 555 'build a remote ui from ui or repo and opts'
553 556 if util.safehasattr(src, 'baseui'): # looks like a repository
554 557 dst = src.baseui.copy() # drop repo-specific config
555 558 src = src.ui # copy target options from repo
556 559 else: # assume it's a global ui object
557 560 dst = src.copy() # keep all global options
558 561
559 562 # copy ssh-specific options
560 563 for o in 'ssh', 'remotecmd':
561 564 v = opts.get(o) or src.config('ui', o)
562 565 if v:
563 566 dst.setconfig("ui", o, v)
564 567
565 568 # copy bundle-specific options
566 569 r = src.config('bundle', 'mainreporoot')
567 570 if r:
568 571 dst.setconfig('bundle', 'mainreporoot', r)
569 572
570 573 # copy selected local settings to the remote ui
571 574 for sect in ('auth', 'hostfingerprints', 'http_proxy'):
572 575 for key, val in src.configitems(sect):
573 576 dst.setconfig(sect, key, val)
574 577 v = src.config('web', 'cacerts')
575 578 if v:
576 579 dst.setconfig('web', 'cacerts', util.expandpath(v))
577 580
578 581 return dst
@@ -1,45 +1,62
1 1
2 2 $ hg init test
3 3 $ cd test
4 4 $ echo a > a
5 5 $ hg ci -Ama
6 6 adding a
7 7 $ cd ..
8 8 $ hg clone test test2
9 9 updating to branch default
10 10 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
11 11 $ cd test2
12 12 $ echo a >> a
13 13 $ hg ci -mb
14 14
15 Cloning with a password in the URL should not save the password in .hg/hgrc:
16
17 $ hg serve -p $HGPORT -d --pid-file=hg.pid -E errors.log
18 $ cat hg.pid >> $DAEMON_PIDS
19 $ hg clone http://foo:xyzzy@localhost:$HGPORT/ test3
20 requesting all changes
21 adding changesets
22 adding manifests
23 adding file changes
24 added 2 changesets with 2 changes to 1 files
25 updating to branch default
26 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
27 $ cat test3/.hg/hgrc
28 [paths]
29 default = http://foo@localhost:$HGPORT/
30 $ "$TESTDIR/killdaemons.py"
31
15 32 expect error, cloning not allowed
16 33
17 34 $ echo '[web]' > .hg/hgrc
18 35 $ echo 'allowpull = false' >> .hg/hgrc
19 36 $ hg serve -p $HGPORT -d --pid-file=hg.pid -E errors.log
20 37 $ cat hg.pid >> $DAEMON_PIDS
21 $ hg clone http://localhost:$HGPORT/ test3
38 $ hg clone http://localhost:$HGPORT/ test4
22 39 requesting all changes
23 40 abort: authorization failed
24 41 [255]
25 42 $ "$TESTDIR/killdaemons.py"
26 43
27 44 serve errors
28 45
29 46 $ cat errors.log
30 47 $ req() {
31 48 > hg serve -p $HGPORT -d --pid-file=hg.pid -E errors.log
32 49 > cat hg.pid >> $DAEMON_PIDS
33 50 > hg --cwd ../test pull http://localhost:$HGPORT/
34 51 > kill `cat hg.pid`
35 52 > echo % serve errors
36 53 > cat errors.log
37 54 > }
38 55
39 56 expect error, pulling not allowed
40 57
41 58 $ req
42 59 pulling from http://localhost:$HGPORT/
43 60 searching for changes
44 61 abort: authorization failed
45 62 % serve errors
@@ -1,88 +1,88
1 1 $ hg init test
2 2 $ cd test
3 3
4 4 $ echo foo>foo
5 5 $ hg addremove
6 6 adding foo
7 7 $ hg commit -m 1
8 8
9 9 $ hg verify
10 10 checking changesets
11 11 checking manifests
12 12 crosschecking files in changesets and manifests
13 13 checking files
14 14 1 files, 1 changesets, 1 total revisions
15 15
16 16 $ hg serve -p $HGPORT -d --pid-file=hg.pid
17 17 $ cat hg.pid >> $DAEMON_PIDS
18 18 $ cd ..
19 19
20 20 $ hg clone --pull http://foo:bar@localhost:$HGPORT/ copy
21 21 requesting all changes
22 22 adding changesets
23 23 adding manifests
24 24 adding file changes
25 25 added 1 changesets with 1 changes to 1 files
26 26 updating to branch default
27 27 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
28 28
29 29 $ cd copy
30 30 $ hg verify
31 31 checking changesets
32 32 checking manifests
33 33 crosschecking files in changesets and manifests
34 34 checking files
35 35 1 files, 1 changesets, 1 total revisions
36 36
37 37 $ hg co
38 38 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
39 39 $ cat foo
40 40 foo
41 41
42 42 $ hg manifest --debug
43 43 2ed2a3912a0b24502043eae84ee4b279c18b90dd 644 foo
44 44
45 45 $ hg pull
46 pulling from http://foo:***@localhost:$HGPORT/
46 pulling from http://foo@localhost:$HGPORT/
47 47 searching for changes
48 48 no changes found
49 49
50 50 $ hg rollback --dry-run --verbose
51 51 repository tip rolled back to revision -1 (undo pull: http://foo:***@localhost:$HGPORT/)
52 52
53 53 Issue622: hg init && hg pull -u URL doesn't checkout default branch
54 54
55 55 $ cd ..
56 56 $ hg init empty
57 57 $ cd empty
58 58 $ hg pull -u ../test
59 59 pulling from ../test
60 60 requesting all changes
61 61 adding changesets
62 62 adding manifests
63 63 adding file changes
64 64 added 1 changesets with 1 changes to 1 files
65 65 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
66 66
67 67 Test 'file:' uri handling:
68 68
69 69 $ hg pull -q file://../test-doesnt-exist
70 70 abort: file:// URLs can only refer to localhost
71 71 [255]
72 72
73 73 $ hg pull -q file://../test
74 74 abort: file:// URLs can only refer to localhost
75 75 [255]
76 76
77 77 $ hg pull -q file:../test
78 78
79 79 It's tricky to make file:// URLs working on every platform with
80 80 regular shell commands.
81 81
82 82 $ URL=`python -c "import os; print 'file://foobar' + ('/' + os.getcwd().replace(os.sep, '/')).replace('//', '/') + '/../test'"`
83 83 $ hg pull -q "$URL"
84 84 abort: file:// URLs can only refer to localhost
85 85 [255]
86 86
87 87 $ URL=`python -c "import os; print 'file://localhost' + ('/' + os.getcwd().replace(os.sep, '/')).replace('//', '/') + '/../test'"`
88 88 $ hg pull -q "$URL"
General Comments 0
You need to be logged in to leave comments. Login now