mirror of
https://gerrit.googlesource.com/git-repo
synced 2024-12-21 07:16:21 +00:00
Add 'repo init --mirror' to download a complete forrest
The mirror option downloads a complete forrest (as described by the manifest) and creates a replica of the remote repositories rather than a client working directory. This permits other clients to sync off the mirror site. A mirror can be positioned in a "DMZ", where the mirror executes "repo sync" to obtain changes from the external upstream and clients inside the protected zone operate off the mirror only, and therefore do not require direct git:// access to the external upstream repositories. Signed-off-by: Shawn O. Pearce <sop@google.com>
This commit is contained in:
parent
3e5481999d
commit
e284ad1d1a
@ -285,12 +285,14 @@ class Remote(object):
|
|||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def ResetFetch(self):
|
def ResetFetch(self, mirror=False):
|
||||||
"""Set the fetch refspec to its default value.
|
"""Set the fetch refspec to its default value.
|
||||||
"""
|
"""
|
||||||
self.fetch = [RefSpec(True,
|
if mirror:
|
||||||
'refs/heads/*',
|
dst = 'refs/heads/*'
|
||||||
'refs/remotes/%s/*' % self.name)]
|
else:
|
||||||
|
dst = 'refs/remotes/%s/*' % self.name
|
||||||
|
self.fetch = [RefSpec(True, 'refs/heads/*', dst)]
|
||||||
|
|
||||||
def Save(self):
|
def Save(self):
|
||||||
"""Save this remote to the configuration.
|
"""Save this remote to the configuration.
|
||||||
|
51
manifest.py
51
manifest.py
@ -88,6 +88,10 @@ class Manifest(object):
|
|||||||
self._Load()
|
self._Load()
|
||||||
return self._default
|
return self._default
|
||||||
|
|
||||||
|
@property
|
||||||
|
def IsMirror(self):
|
||||||
|
return self.manifestProject.config.GetBoolean('repo.mirror')
|
||||||
|
|
||||||
def _Unload(self):
|
def _Unload(self):
|
||||||
self._loaded = False
|
self._loaded = False
|
||||||
self._projects = {}
|
self._projects = {}
|
||||||
@ -114,6 +118,10 @@ class Manifest(object):
|
|||||||
finally:
|
finally:
|
||||||
self.manifestFile = real
|
self.manifestFile = real
|
||||||
|
|
||||||
|
if self.IsMirror:
|
||||||
|
self._AddMetaProjectMirror(self.repoProject)
|
||||||
|
self._AddMetaProjectMirror(self.manifestProject)
|
||||||
|
|
||||||
self._loaded = True
|
self._loaded = True
|
||||||
|
|
||||||
def _ParseManifest(self, is_root_file):
|
def _ParseManifest(self, is_root_file):
|
||||||
@ -157,6 +165,40 @@ class Manifest(object):
|
|||||||
(project.name, self.manifestFile)
|
(project.name, self.manifestFile)
|
||||||
self._projects[project.name] = project
|
self._projects[project.name] = project
|
||||||
|
|
||||||
|
def _AddMetaProjectMirror(self, m):
|
||||||
|
name = None
|
||||||
|
m_url = m.GetRemote(m.remote.name).url
|
||||||
|
if m_url.endswith('/.git'):
|
||||||
|
raise ManifestParseError, 'refusing to mirror %s' % m_url
|
||||||
|
|
||||||
|
if self._default and self._default.remote:
|
||||||
|
url = self._default.remote.fetchUrl
|
||||||
|
if not url.endswith('/'):
|
||||||
|
url += '/'
|
||||||
|
if m_url.startswith(url):
|
||||||
|
remote = self._default.remote
|
||||||
|
name = m_url[len(url):]
|
||||||
|
|
||||||
|
if name is None:
|
||||||
|
s = m_url.rindex('/') + 1
|
||||||
|
remote = Remote('origin', fetch = m_url[:s])
|
||||||
|
name = m_url[s:]
|
||||||
|
|
||||||
|
if name.endswith('.git'):
|
||||||
|
name = name[:-4]
|
||||||
|
|
||||||
|
if name not in self._projects:
|
||||||
|
m.PreSync()
|
||||||
|
gitdir = os.path.join(self.topdir, '%s.git' % name)
|
||||||
|
project = Project(manifest = self,
|
||||||
|
name = name,
|
||||||
|
remote = remote,
|
||||||
|
gitdir = gitdir,
|
||||||
|
worktree = None,
|
||||||
|
relpath = None,
|
||||||
|
revision = m.revision)
|
||||||
|
self._projects[project.name] = project
|
||||||
|
|
||||||
def _ParseRemote(self, node):
|
def _ParseRemote(self, node):
|
||||||
"""
|
"""
|
||||||
reads a <remote> element from the manifest file
|
reads a <remote> element from the manifest file
|
||||||
@ -214,6 +256,11 @@ class Manifest(object):
|
|||||||
"project %s path cannot be absolute in %s" % \
|
"project %s path cannot be absolute in %s" % \
|
||||||
(name, self.manifestFile)
|
(name, self.manifestFile)
|
||||||
|
|
||||||
|
if self.IsMirror:
|
||||||
|
relpath = None
|
||||||
|
worktree = None
|
||||||
|
gitdir = os.path.join(self.topdir, '%s.git' % name)
|
||||||
|
else:
|
||||||
worktree = os.path.join(self.topdir, path)
|
worktree = os.path.join(self.topdir, path)
|
||||||
gitdir = os.path.join(self.repodir, 'projects/%s.git' % path)
|
gitdir = os.path.join(self.repodir, 'projects/%s.git' % path)
|
||||||
|
|
||||||
@ -242,7 +289,9 @@ class Manifest(object):
|
|||||||
def _ParseCopyFile(self, project, node):
|
def _ParseCopyFile(self, project, node):
|
||||||
src = self._reqatt(node, 'src')
|
src = self._reqatt(node, 'src')
|
||||||
dest = self._reqatt(node, 'dest')
|
dest = self._reqatt(node, 'dest')
|
||||||
# src is project relative, and dest is relative to the top of the tree
|
if not self.IsMirror:
|
||||||
|
# src is project relative;
|
||||||
|
# dest is relative to the top of the tree
|
||||||
project.AddCopyFile(src, os.path.join(self.topdir, dest))
|
project.AddCopyFile(src, os.path.join(self.topdir, dest))
|
||||||
|
|
||||||
def _get_remote(self, node):
|
def _get_remote(self, node):
|
||||||
|
30
project.py
30
project.py
@ -211,7 +211,10 @@ class Project(object):
|
|||||||
gitdir = self.gitdir,
|
gitdir = self.gitdir,
|
||||||
defaults = self.manifest.globalConfig)
|
defaults = self.manifest.globalConfig)
|
||||||
|
|
||||||
|
if self.worktree:
|
||||||
self.work_git = self._GitGetByExec(self, bare=False)
|
self.work_git = self._GitGetByExec(self, bare=False)
|
||||||
|
else:
|
||||||
|
self.work_git = None
|
||||||
self.bare_git = self._GitGetByExec(self, bare=True)
|
self.bare_git = self._GitGetByExec(self, bare=True)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@ -489,14 +492,23 @@ class Project(object):
|
|||||||
print >>sys.stderr
|
print >>sys.stderr
|
||||||
print >>sys.stderr, 'Initializing project %s ...' % self.name
|
print >>sys.stderr, 'Initializing project %s ...' % self.name
|
||||||
self._InitGitDir()
|
self._InitGitDir()
|
||||||
|
|
||||||
self._InitRemote()
|
self._InitRemote()
|
||||||
for r in self.extraRemotes.values():
|
for r in self.extraRemotes.values():
|
||||||
if not self._RemoteFetch(r.name):
|
if not self._RemoteFetch(r.name):
|
||||||
return False
|
return False
|
||||||
if not self._RemoteFetch():
|
if not self._RemoteFetch():
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
if self.worktree:
|
||||||
self._RepairAndroidImportErrors()
|
self._RepairAndroidImportErrors()
|
||||||
self._InitMRef()
|
self._InitMRef()
|
||||||
|
else:
|
||||||
|
self._InitMirrorHead()
|
||||||
|
try:
|
||||||
|
os.remove(os.path.join(self.gitdir, 'FETCH_HEAD'))
|
||||||
|
except OSError:
|
||||||
|
pass
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def PostRepoUpgrade(self):
|
def PostRepoUpgrade(self):
|
||||||
@ -792,9 +804,11 @@ class Project(object):
|
|||||||
def _RemoteFetch(self, name=None):
|
def _RemoteFetch(self, name=None):
|
||||||
if not name:
|
if not name:
|
||||||
name = self.remote.name
|
name = self.remote.name
|
||||||
return GitCommand(self,
|
cmd = ['fetch']
|
||||||
['fetch', name],
|
if not self.worktree:
|
||||||
bare = True).Wait() == 0
|
cmd.append('--update-head-ok')
|
||||||
|
cmd.append(name)
|
||||||
|
return GitCommand(self, cmd, bare = True).Wait() == 0
|
||||||
|
|
||||||
def _Checkout(self, rev, quiet=False):
|
def _Checkout(self, rev, quiet=False):
|
||||||
cmd = ['checkout']
|
cmd = ['checkout']
|
||||||
@ -874,7 +888,10 @@ class Project(object):
|
|||||||
remote.url = url
|
remote.url = url
|
||||||
remote.review = self.remote.reviewUrl
|
remote.review = self.remote.reviewUrl
|
||||||
|
|
||||||
remote.ResetFetch()
|
if self.worktree:
|
||||||
|
remote.ResetFetch(mirror=False)
|
||||||
|
else:
|
||||||
|
remote.ResetFetch(mirror=True)
|
||||||
remote.Save()
|
remote.Save()
|
||||||
|
|
||||||
for r in self.extraRemotes.values():
|
for r in self.extraRemotes.values():
|
||||||
@ -897,6 +914,11 @@ class Project(object):
|
|||||||
dst = remote.ToLocal(self.revision)
|
dst = remote.ToLocal(self.revision)
|
||||||
self.bare_git.symbolic_ref('-m', msg, ref, dst)
|
self.bare_git.symbolic_ref('-m', msg, ref, dst)
|
||||||
|
|
||||||
|
def _InitMirrorHead(self):
|
||||||
|
dst = self.GetRemote(self.remote.name).ToLocal(self.revision)
|
||||||
|
msg = 'manifest set to %s' % self.revision
|
||||||
|
self.bare_git.SetHead(dst, message=msg)
|
||||||
|
|
||||||
def _InitWorkTree(self):
|
def _InitWorkTree(self):
|
||||||
dotgit = os.path.join(self.worktree, '.git')
|
dotgit = os.path.join(self.worktree, '.git')
|
||||||
if not os.path.exists(dotgit):
|
if not os.path.exists(dotgit):
|
||||||
|
5
repo
5
repo
@ -28,7 +28,7 @@ if __name__ == '__main__':
|
|||||||
del magic
|
del magic
|
||||||
|
|
||||||
# increment this whenever we make important changes to this script
|
# increment this whenever we make important changes to this script
|
||||||
VERSION = (1, 6)
|
VERSION = (1, 7)
|
||||||
|
|
||||||
# increment this if the MAINTAINER_KEYS block is modified
|
# increment this if the MAINTAINER_KEYS block is modified
|
||||||
KEYRING_VERSION = (1,0)
|
KEYRING_VERSION = (1,0)
|
||||||
@ -115,6 +115,9 @@ group.add_option('-b', '--manifest-branch',
|
|||||||
group.add_option('-m', '--manifest-name',
|
group.add_option('-m', '--manifest-name',
|
||||||
dest='manifest_name',
|
dest='manifest_name',
|
||||||
help='initial manifest file', metavar='NAME.xml')
|
help='initial manifest file', metavar='NAME.xml')
|
||||||
|
group.add_option('--mirror',
|
||||||
|
dest='mirror', action='store_true',
|
||||||
|
help='mirror the forrest')
|
||||||
|
|
||||||
# Tool
|
# Tool
|
||||||
group = init_optparse.add_option_group('Version options')
|
group = init_optparse.add_option_group('Version options')
|
||||||
|
@ -57,6 +57,10 @@ default.xml will be used.
|
|||||||
g.add_option('-m', '--manifest-name',
|
g.add_option('-m', '--manifest-name',
|
||||||
dest='manifest_name', default='default.xml',
|
dest='manifest_name', default='default.xml',
|
||||||
help='initial manifest file', metavar='NAME.xml')
|
help='initial manifest file', metavar='NAME.xml')
|
||||||
|
g.add_option('--mirror',
|
||||||
|
dest='mirror', action='store_true',
|
||||||
|
help='mirror the forrest')
|
||||||
|
|
||||||
|
|
||||||
# Tool
|
# Tool
|
||||||
g = p.add_option_group('Version options')
|
g = p.add_option_group('Version options')
|
||||||
@ -112,6 +116,9 @@ default.xml will be used.
|
|||||||
r.ResetFetch()
|
r.ResetFetch()
|
||||||
r.Save()
|
r.Save()
|
||||||
|
|
||||||
|
if opt.mirror:
|
||||||
|
m.config.SetString('repo.mirror', 'true')
|
||||||
|
|
||||||
m.Sync_NetworkHalf()
|
m.Sync_NetworkHalf()
|
||||||
m.Sync_LocalHalf()
|
m.Sync_LocalHalf()
|
||||||
m.StartBranch('default')
|
m.StartBranch('default')
|
||||||
@ -185,9 +192,14 @@ default.xml will be used.
|
|||||||
self._SyncManifest(opt)
|
self._SyncManifest(opt)
|
||||||
self._LinkManifest(opt.manifest_name)
|
self._LinkManifest(opt.manifest_name)
|
||||||
|
|
||||||
if os.isatty(0) and os.isatty(1):
|
if os.isatty(0) and os.isatty(1) and not opt.mirror:
|
||||||
self._ConfigureUser()
|
self._ConfigureUser()
|
||||||
self._ConfigureColor()
|
self._ConfigureColor()
|
||||||
|
|
||||||
|
if opt.mirror:
|
||||||
|
type = 'mirror '
|
||||||
|
else:
|
||||||
|
type = ''
|
||||||
|
|
||||||
print ''
|
print ''
|
||||||
print 'repo initialized in %s' % self.manifest.topdir
|
print 'repo %sinitialized in %s' % (type, self.manifest.topdir)
|
||||||
|
@ -102,6 +102,7 @@ the manifest.
|
|||||||
self._Fetch(*missing)
|
self._Fetch(*missing)
|
||||||
|
|
||||||
for project in all:
|
for project in all:
|
||||||
|
if project.worktree:
|
||||||
if not project.Sync_LocalHalf():
|
if not project.Sync_LocalHalf():
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user