mercurial/hg.py
changeset 46663 a4c19a162615
parent 46314 95a615dd77bf
child 46720 66fb04552122
equal deleted inserted replaced
46662:db8037e38085 46663:a4c19a162615
   676         srcpeer = peer(ui, peeropts, source)
   676         srcpeer = peer(ui, peeropts, source)
   677     else:
   677     else:
   678         srcpeer = source.peer()  # in case we were called with a localrepo
   678         srcpeer = source.peer()  # in case we were called with a localrepo
   679         branches = (None, branch or [])
   679         branches = (None, branch or [])
   680         origsource = source = srcpeer.url()
   680         origsource = source = srcpeer.url()
   681     revs, checkout = addbranchrevs(srcpeer, srcpeer, branches, revs)
   681     srclock = destlock = cleandir = None
   682 
   682     destpeer = None
   683     if dest is None:
   683     try:
   684         dest = defaultdest(source)
   684         revs, checkout = addbranchrevs(srcpeer, srcpeer, branches, revs)
   685         if dest:
   685 
   686             ui.status(_(b"destination directory: %s\n") % dest)
   686         if dest is None:
   687     else:
   687             dest = defaultdest(source)
   688         dest = ui.expandpath(dest)
   688             if dest:
   689 
   689                 ui.status(_(b"destination directory: %s\n") % dest)
   690     dest = util.urllocalpath(dest)
   690         else:
   691     source = util.urllocalpath(source)
   691             dest = ui.expandpath(dest)
   692 
   692 
   693     if not dest:
   693         dest = util.urllocalpath(dest)
   694         raise error.InputError(_(b"empty destination path is not valid"))
   694         source = util.urllocalpath(source)
   695 
   695 
   696     destvfs = vfsmod.vfs(dest, expandpath=True)
   696         if not dest:
   697     if destvfs.lexists():
   697             raise error.InputError(_(b"empty destination path is not valid"))
   698         if not destvfs.isdir():
   698 
   699             raise error.InputError(_(b"destination '%s' already exists") % dest)
   699         destvfs = vfsmod.vfs(dest, expandpath=True)
   700         elif destvfs.listdir():
   700         if destvfs.lexists():
   701             raise error.InputError(_(b"destination '%s' is not empty") % dest)
   701             if not destvfs.isdir():
   702 
   702                 raise error.InputError(
   703     createopts = {}
   703                     _(b"destination '%s' already exists") % dest
   704     narrow = False
       
   705 
       
   706     if storeincludepats is not None:
       
   707         narrowspec.validatepatterns(storeincludepats)
       
   708         narrow = True
       
   709 
       
   710     if storeexcludepats is not None:
       
   711         narrowspec.validatepatterns(storeexcludepats)
       
   712         narrow = True
       
   713 
       
   714     if narrow:
       
   715         # Include everything by default if only exclusion patterns defined.
       
   716         if storeexcludepats and not storeincludepats:
       
   717             storeincludepats = {b'path:.'}
       
   718 
       
   719         createopts[b'narrowfiles'] = True
       
   720 
       
   721     if depth:
       
   722         createopts[b'shallowfilestore'] = True
       
   723 
       
   724     if srcpeer.capable(b'lfs-serve'):
       
   725         # Repository creation honors the config if it disabled the extension, so
       
   726         # we can't just announce that lfs will be enabled.  This check avoids
       
   727         # saying that lfs will be enabled, and then saying it's an unknown
       
   728         # feature.  The lfs creation option is set in either case so that a
       
   729         # requirement is added.  If the extension is explicitly disabled but the
       
   730         # requirement is set, the clone aborts early, before transferring any
       
   731         # data.
       
   732         createopts[b'lfs'] = True
       
   733 
       
   734         if extensions.disabled_help(b'lfs'):
       
   735             ui.status(
       
   736                 _(
       
   737                     b'(remote is using large file support (lfs), but it is '
       
   738                     b'explicitly disabled in the local configuration)\n'
       
   739                 )
   704                 )
   740             )
   705             elif destvfs.listdir():
   741         else:
   706                 raise error.InputError(
   742             ui.status(
   707                     _(b"destination '%s' is not empty") % dest
   743                 _(
       
   744                     b'(remote is using large file support (lfs); lfs will '
       
   745                     b'be enabled for this repository)\n'
       
   746                 )
   708                 )
   747             )
   709 
   748 
   710         createopts = {}
   749     shareopts = shareopts or {}
   711         narrow = False
   750     sharepool = shareopts.get(b'pool')
   712 
   751     sharenamemode = shareopts.get(b'mode')
   713         if storeincludepats is not None:
   752     if sharepool and islocal(dest):
   714             narrowspec.validatepatterns(storeincludepats)
   753         sharepath = None
   715             narrow = True
   754         if sharenamemode == b'identity':
   716 
   755             # Resolve the name from the initial changeset in the remote
   717         if storeexcludepats is not None:
   756             # repository. This returns nullid when the remote is empty. It
   718             narrowspec.validatepatterns(storeexcludepats)
   757             # raises RepoLookupError if revision 0 is filtered or otherwise
   719             narrow = True
   758             # not available. If we fail to resolve, sharing is not enabled.
   720 
   759             try:
   721         if narrow:
   760                 with srcpeer.commandexecutor() as e:
   722             # Include everything by default if only exclusion patterns defined.
   761                     rootnode = e.callcommand(
   723             if storeexcludepats and not storeincludepats:
   762                         b'lookup',
   724                 storeincludepats = {b'path:.'}
   763                         {
   725 
   764                             b'key': b'0',
   726             createopts[b'narrowfiles'] = True
   765                         },
   727 
   766                     ).result()
   728         if depth:
   767 
   729             createopts[b'shallowfilestore'] = True
   768                 if rootnode != nullid:
   730 
   769                     sharepath = os.path.join(sharepool, hex(rootnode))
   731         if srcpeer.capable(b'lfs-serve'):
   770                 else:
   732             # Repository creation honors the config if it disabled the extension, so
       
   733             # we can't just announce that lfs will be enabled.  This check avoids
       
   734             # saying that lfs will be enabled, and then saying it's an unknown
       
   735             # feature.  The lfs creation option is set in either case so that a
       
   736             # requirement is added.  If the extension is explicitly disabled but the
       
   737             # requirement is set, the clone aborts early, before transferring any
       
   738             # data.
       
   739             createopts[b'lfs'] = True
       
   740 
       
   741             if extensions.disabled_help(b'lfs'):
       
   742                 ui.status(
       
   743                     _(
       
   744                         b'(remote is using large file support (lfs), but it is '
       
   745                         b'explicitly disabled in the local configuration)\n'
       
   746                     )
       
   747                 )
       
   748             else:
       
   749                 ui.status(
       
   750                     _(
       
   751                         b'(remote is using large file support (lfs); lfs will '
       
   752                         b'be enabled for this repository)\n'
       
   753                     )
       
   754                 )
       
   755 
       
   756         shareopts = shareopts or {}
       
   757         sharepool = shareopts.get(b'pool')
       
   758         sharenamemode = shareopts.get(b'mode')
       
   759         if sharepool and islocal(dest):
       
   760             sharepath = None
       
   761             if sharenamemode == b'identity':
       
   762                 # Resolve the name from the initial changeset in the remote
       
   763                 # repository. This returns nullid when the remote is empty. It
       
   764                 # raises RepoLookupError if revision 0 is filtered or otherwise
       
   765                 # not available. If we fail to resolve, sharing is not enabled.
       
   766                 try:
       
   767                     with srcpeer.commandexecutor() as e:
       
   768                         rootnode = e.callcommand(
       
   769                             b'lookup',
       
   770                             {
       
   771                                 b'key': b'0',
       
   772                             },
       
   773                         ).result()
       
   774 
       
   775                     if rootnode != nullid:
       
   776                         sharepath = os.path.join(sharepool, hex(rootnode))
       
   777                     else:
       
   778                         ui.status(
       
   779                             _(
       
   780                                 b'(not using pooled storage: '
       
   781                                 b'remote appears to be empty)\n'
       
   782                             )
       
   783                         )
       
   784                 except error.RepoLookupError:
   771                     ui.status(
   785                     ui.status(
   772                         _(
   786                         _(
   773                             b'(not using pooled storage: '
   787                             b'(not using pooled storage: '
   774                             b'remote appears to be empty)\n'
   788                             b'unable to resolve identity of remote)\n'
   775                         )
   789                         )
   776                     )
   790                     )
   777             except error.RepoLookupError:
   791             elif sharenamemode == b'remote':
       
   792                 sharepath = os.path.join(
       
   793                     sharepool, hex(hashutil.sha1(source).digest())
       
   794                 )
       
   795             else:
       
   796                 raise error.Abort(
       
   797                     _(b'unknown share naming mode: %s') % sharenamemode
       
   798                 )
       
   799 
       
   800             # TODO this is a somewhat arbitrary restriction.
       
   801             if narrow:
   778                 ui.status(
   802                 ui.status(
   779                     _(
   803                     _(b'(pooled storage not supported for narrow clones)\n')
   780                         b'(not using pooled storage: '
       
   781                         b'unable to resolve identity of remote)\n'
       
   782                     )
       
   783                 )
   804                 )
   784         elif sharenamemode == b'remote':
   805                 sharepath = None
   785             sharepath = os.path.join(
   806 
   786                 sharepool, hex(hashutil.sha1(source).digest())
   807             if sharepath:
   787             )
   808                 return clonewithshare(
   788         else:
   809                     ui,
   789             raise error.Abort(
   810                     peeropts,
   790                 _(b'unknown share naming mode: %s') % sharenamemode
   811                     sharepath,
   791             )
   812                     source,
   792 
   813                     srcpeer,
   793         # TODO this is a somewhat arbitrary restriction.
   814                     dest,
   794         if narrow:
   815                     pull=pull,
   795             ui.status(_(b'(pooled storage not supported for narrow clones)\n'))
   816                     rev=revs,
   796             sharepath = None
   817                     update=update,
   797 
   818                     stream=stream,
   798         if sharepath:
   819                 )
   799             return clonewithshare(
   820 
   800                 ui,
   821         srcrepo = srcpeer.local()
   801                 peeropts,
   822 
   802                 sharepath,
       
   803                 source,
       
   804                 srcpeer,
       
   805                 dest,
       
   806                 pull=pull,
       
   807                 rev=revs,
       
   808                 update=update,
       
   809                 stream=stream,
       
   810             )
       
   811 
       
   812     srclock = destlock = cleandir = None
       
   813     srcrepo = srcpeer.local()
       
   814     try:
       
   815         abspath = origsource
   823         abspath = origsource
   816         if islocal(origsource):
   824         if islocal(origsource):
   817             abspath = os.path.abspath(util.urllocalpath(origsource))
   825             abspath = os.path.abspath(util.urllocalpath(origsource))
   818 
   826 
   819         if islocal(dest):
   827         if islocal(dest):
  1050         release(srclock, destlock)
  1058         release(srclock, destlock)
  1051         if cleandir is not None:
  1059         if cleandir is not None:
  1052             shutil.rmtree(cleandir, True)
  1060             shutil.rmtree(cleandir, True)
  1053         if srcpeer is not None:
  1061         if srcpeer is not None:
  1054             srcpeer.close()
  1062             srcpeer.close()
       
  1063         if destpeer and destpeer.local() is None:
       
  1064             destpeer.close()
  1055     return srcpeer, destpeer
  1065     return srcpeer, destpeer
  1056 
  1066 
  1057 
  1067 
  1058 def _showstats(repo, stats, quietempty=False):
  1068 def _showstats(repo, stats, quietempty=False):
  1059     if quietempty and stats.isempty():
  1069     if quietempty and stats.isempty():
  1251         (remoterepo, incomingchangesetlist, displayer) parameters,
  1261         (remoterepo, incomingchangesetlist, displayer) parameters,
  1252     and is supposed to contain only code that can't be unified.
  1262     and is supposed to contain only code that can't be unified.
  1253     """
  1263     """
  1254     source, branches = parseurl(ui.expandpath(source), opts.get(b'branch'))
  1264     source, branches = parseurl(ui.expandpath(source), opts.get(b'branch'))
  1255     other = peer(repo, opts, source)
  1265     other = peer(repo, opts, source)
  1256     ui.status(_(b'comparing with %s\n') % util.hidepassword(source))
  1266     cleanupfn = other.close
  1257     revs, checkout = addbranchrevs(repo, other, branches, opts.get(b'rev'))
       
  1258 
       
  1259     if revs:
       
  1260         revs = [other.lookup(rev) for rev in revs]
       
  1261     other, chlist, cleanupfn = bundlerepo.getremotechanges(
       
  1262         ui, repo, other, revs, opts[b"bundle"], opts[b"force"]
       
  1263     )
       
  1264     try:
  1267     try:
       
  1268         ui.status(_(b'comparing with %s\n') % util.hidepassword(source))
       
  1269         revs, checkout = addbranchrevs(repo, other, branches, opts.get(b'rev'))
       
  1270 
       
  1271         if revs:
       
  1272             revs = [other.lookup(rev) for rev in revs]
       
  1273         other, chlist, cleanupfn = bundlerepo.getremotechanges(
       
  1274             ui, repo, other, revs, opts[b"bundle"], opts[b"force"]
       
  1275         )
       
  1276 
  1265         if not chlist:
  1277         if not chlist:
  1266             ui.status(_(b"no changes found\n"))
  1278             ui.status(_(b"no changes found\n"))
  1267             return subreporecurse()
  1279             return subreporecurse()
  1268         ui.pager(b'incoming')
  1280         ui.pager(b'incoming')
  1269         displayer = logcmdutil.changesetdisplayer(
  1281         displayer = logcmdutil.changesetdisplayer(
  1318     revs, checkout = addbranchrevs(repo, repo, branches, opts.get(b'rev'))
  1330     revs, checkout = addbranchrevs(repo, repo, branches, opts.get(b'rev'))
  1319     if revs:
  1331     if revs:
  1320         revs = [repo[rev].node() for rev in scmutil.revrange(repo, revs)]
  1332         revs = [repo[rev].node() for rev in scmutil.revrange(repo, revs)]
  1321 
  1333 
  1322     other = peer(repo, opts, dest)
  1334     other = peer(repo, opts, dest)
  1323     outgoing = discovery.findcommonoutgoing(
  1335     try:
  1324         repo, other, revs, force=opts.get(b'force')
  1336         outgoing = discovery.findcommonoutgoing(
  1325     )
  1337             repo, other, revs, force=opts.get(b'force')
  1326     o = outgoing.missing
  1338         )
  1327     if not o:
  1339         o = outgoing.missing
  1328         scmutil.nochangesfound(repo.ui, repo, outgoing.excluded)
  1340         if not o:
  1329     return o, other
  1341             scmutil.nochangesfound(repo.ui, repo, outgoing.excluded)
       
  1342         return o, other
       
  1343     except:  # re-raises
       
  1344         other.close()
       
  1345         raise
  1330 
  1346 
  1331 
  1347 
  1332 def outgoing(ui, repo, dest, opts):
  1348 def outgoing(ui, repo, dest, opts):
  1333     def recurse():
  1349     def recurse():
  1334         ret = 1
  1350         ret = 1
  1339                 ret = min(ret, sub.outgoing(ui, dest, opts))
  1355                 ret = min(ret, sub.outgoing(ui, dest, opts))
  1340         return ret
  1356         return ret
  1341 
  1357 
  1342     limit = logcmdutil.getlimit(opts)
  1358     limit = logcmdutil.getlimit(opts)
  1343     o, other = _outgoing(ui, repo, dest, opts)
  1359     o, other = _outgoing(ui, repo, dest, opts)
  1344     if not o:
  1360     try:
       
  1361         if not o:
       
  1362             cmdutil.outgoinghooks(ui, repo, other, opts, o)
       
  1363             return recurse()
       
  1364 
       
  1365         if opts.get(b'newest_first'):
       
  1366             o.reverse()
       
  1367         ui.pager(b'outgoing')
       
  1368         displayer = logcmdutil.changesetdisplayer(ui, repo, opts)
       
  1369         count = 0
       
  1370         for n in o:
       
  1371             if limit is not None and count >= limit:
       
  1372                 break
       
  1373             parents = [p for p in repo.changelog.parents(n) if p != nullid]
       
  1374             if opts.get(b'no_merges') and len(parents) == 2:
       
  1375                 continue
       
  1376             count += 1
       
  1377             displayer.show(repo[n])
       
  1378         displayer.close()
  1345         cmdutil.outgoinghooks(ui, repo, other, opts, o)
  1379         cmdutil.outgoinghooks(ui, repo, other, opts, o)
  1346         return recurse()
  1380         recurse()
  1347 
  1381         return 0  # exit code is zero since we found outgoing changes
  1348     if opts.get(b'newest_first'):
  1382     finally:
  1349         o.reverse()
  1383         other.close()
  1350     ui.pager(b'outgoing')
       
  1351     displayer = logcmdutil.changesetdisplayer(ui, repo, opts)
       
  1352     count = 0
       
  1353     for n in o:
       
  1354         if limit is not None and count >= limit:
       
  1355             break
       
  1356         parents = [p for p in repo.changelog.parents(n) if p != nullid]
       
  1357         if opts.get(b'no_merges') and len(parents) == 2:
       
  1358             continue
       
  1359         count += 1
       
  1360         displayer.show(repo[n])
       
  1361     displayer.close()
       
  1362     cmdutil.outgoinghooks(ui, repo, other, opts, o)
       
  1363     recurse()
       
  1364     return 0  # exit code is zero since we found outgoing changes
       
  1365 
  1384 
  1366 
  1385 
  1367 def verify(repo, level=None):
  1386 def verify(repo, level=None):
  1368     """verify the consistency of a repository"""
  1387     """verify the consistency of a repository"""
  1369     ret = verifymod.verify(repo, level=level)
  1388     ret = verifymod.verify(repo, level=level)