mirror of
https://github.com/facebook/sapling.git
synced 2024-10-06 06:47:41 +03:00
git: respect selective pull
Summary: Some git repos (ex. pytorch) has thousands of branches that won't scale well. Change no-argument pull to respect selective pull to mitigate it. Reviewed By: DurhamG Differential Revision: D33485186 fbshipit-source-id: b735704850847c49b0bfeb94972e4bb778e726a4
This commit is contained in:
parent
e6d1d7fa2b
commit
77cb1f9890
@ -1055,6 +1055,14 @@ class remotenames(dict):
|
||||
self._node2hoists.setdefault(node[0], []).append(name)
|
||||
return self._node2hoists
|
||||
|
||||
def get(self, name):
|
||||
"""Resolve a remote bookmark. Return None if the bookmark does not exist"""
|
||||
nodes = self["bookmarks"].get(name)
|
||||
if nodes:
|
||||
return nodes[0]
|
||||
else:
|
||||
return None
|
||||
|
||||
@property
|
||||
def changecount(self):
|
||||
return self._changecount
|
||||
|
@ -4584,6 +4584,8 @@ def pull(ui, repo, source="default", **opts):
|
||||
if source == "default":
|
||||
source = "origin"
|
||||
refspecs = (opts.get("bookmark") or []) + (opts.get("rev") or [])
|
||||
if not refspecs:
|
||||
refspecs = git.defaultpullrefspecs(repo, source)
|
||||
ret = git.pull(repo, source, refspecs)
|
||||
if ret == 0 and opts.get("update"):
|
||||
# Figure out the node to checkout
|
||||
|
@ -15,9 +15,9 @@ import subprocess
|
||||
import bindings
|
||||
from edenscm import tracing
|
||||
|
||||
from . import error, util
|
||||
from . import bookmarks as bookmod, error, util
|
||||
from .i18n import _
|
||||
from .node import hex, nullid
|
||||
from .node import bin, hex, nullid
|
||||
|
||||
GIT_DIR_FILE = "gitdir"
|
||||
GIT_REQUIREMENT = "git"
|
||||
@ -68,7 +68,8 @@ def clone(ui, url, destpath=None, update=True):
|
||||
raise error.Abort(_("git clone was not successful"))
|
||||
initgit(repo, "git")
|
||||
if url:
|
||||
pull(repo, "origin", [])
|
||||
refspecs = defaultpullrefspecs(repo, "origin")
|
||||
pull(repo, "origin", refspecs)
|
||||
except Exception:
|
||||
repo = None
|
||||
shutil.rmtree(destpath, ignore_errors=True)
|
||||
@ -186,6 +187,9 @@ def revparse(repo, revspec):
|
||||
|
||||
def pull(repo, source, refspecs):
|
||||
"""Run `git fetch` on the backing repo to perform a pull"""
|
||||
if not refspecs:
|
||||
# Nothing to pull
|
||||
return 0
|
||||
ret = rungit(
|
||||
repo,
|
||||
["fetch", "--no-write-fetch-head", "--no-tags", "--prune", source] + refspecs,
|
||||
@ -212,6 +216,41 @@ def push(repo, dest, pushnode, to, force=False):
|
||||
return ret
|
||||
|
||||
|
||||
def listremote(repo, source, patterns):
|
||||
"""List references of the remote peer
|
||||
Return a dict of name to node.
|
||||
"""
|
||||
out = callgit(repo, ["ls-remote", "--refs", source] + patterns)
|
||||
refs = {}
|
||||
for line in out.splitlines():
|
||||
if b"\t" not in line:
|
||||
continue
|
||||
hexnode, name = line.split(b"\t", 1)
|
||||
refs[name.decode("utf-8")] = bin(hexnode)
|
||||
return refs
|
||||
|
||||
|
||||
def defaultpullrefspecs(repo, source):
|
||||
"""default refspecs for 'git fetch' respecting selective pull"""
|
||||
names = bookmod.selectivepullbookmarknames(repo)
|
||||
|
||||
patterns = ["refs/heads/%s" % name for name in names]
|
||||
listed = listremote(repo, source, patterns)
|
||||
|
||||
refspecs = []
|
||||
for name in names:
|
||||
refspec = "refs/heads/%s" % name
|
||||
remotenode = listed.get(refspec)
|
||||
if repo._remotenames.get("%s/%s" % (source, name)) == remotenode:
|
||||
# not changed, skip
|
||||
continue
|
||||
if remotenode is None:
|
||||
# removed remotely
|
||||
refspec = ":refs/remotes/%s/heads/%s" % (source, name)
|
||||
refspecs.append(refspec)
|
||||
return refspecs
|
||||
|
||||
|
||||
def callgit(repo, args):
|
||||
"""Run git command in the backing git repo, return its output"""
|
||||
gitdir = readgitdir(repo)
|
||||
|
@ -22,6 +22,7 @@ autopullpattern=
|
||||
disallowedto=^origin/
|
||||
disallowhint=please don't specify 'origin/' prefix in remote bookmark's name
|
||||
hoist=origin
|
||||
selectivepulldefault=main,master
|
||||
|
||||
[smartlog]
|
||||
names=main,master
|
||||
|
@ -201,11 +201,10 @@ Test clone with flags (--noupdate, --updaterev):
|
||||
$ hg log -r . -T '{node|short}\n'
|
||||
000000000000
|
||||
$ hg bookmarks --remote
|
||||
origin/foo 5c9a5ee451a8
|
||||
origin/master 3f5848713286
|
||||
$ cd ..
|
||||
|
||||
$ hg clone "git+file://$TESTTMP/gitrepo" cloned1
|
||||
$ hg clone "git+file://$TESTTMP/gitrepo" cloned1 --config remotenames.selectivepulldefault=foo,master
|
||||
From file:/*/$TESTTMP/gitrepo (glob)
|
||||
* [new branch] foo -> origin/foo
|
||||
* [new branch] master -> origin/master
|
||||
@ -214,10 +213,9 @@ Test clone with flags (--noupdate, --updaterev):
|
||||
5c9a5ee451a8 origin/foo alpha3
|
||||
$ cd ..
|
||||
|
||||
$ hg clone --updaterev origin/foo "git+file://$TESTTMP/gitrepo" cloned2
|
||||
$ hg clone --updaterev origin/foo "git+file://$TESTTMP/gitrepo" cloned2 --config remotenames.selectivepulldefault=foo
|
||||
From file:/*/$TESTTMP/gitrepo (glob)
|
||||
* [new branch] foo -> origin/foo
|
||||
* [new branch] master -> origin/master
|
||||
2 files updated, 0 files merged, 0 files removed, 0 files unresolved
|
||||
$ hg --cwd cloned2 log -r . -T '{node|short} {remotenames} {desc}\n'
|
||||
5c9a5ee451a8 origin/foo alpha3
|
||||
|
Loading…
Reference in New Issue
Block a user