summaryrefslogtreecommitdiffstats
path: root/project.py
diff options
context:
space:
mode:
authorConley Owens <cco3@android.com>2014-01-10 01:20:12 +0000
committerGerrit Code Review <noreply-gerritcodereview@google.com>2014-01-10 01:20:13 +0000
commite695338e21080d3cbe20935db572e4cd0c7a620c (patch)
treecc525f53929fa4ea24f108d24545c68c7c6cb5ba /project.py
parentbd80f7eedd5a74f6c5fad745091dcda53a6415bf (diff)
parent8d20116038ff78b22069dd4e993b5819775f03d1 (diff)
downloadgit-repo-e695338e21080d3cbe20935db572e4cd0c7a620c.tar.gz
Merge "repo: Support multiple branches for the same project."
Diffstat (limited to 'project.py')
-rw-r--r--project.py118
1 files changed, 82 insertions, 36 deletions
diff --git a/project.py b/project.py
index eb8bad3e..46f3b8f7 100644
--- a/project.py
+++ b/project.py
@@ -488,6 +488,7 @@ class Project(object):
488 name, 488 name,
489 remote, 489 remote,
490 gitdir, 490 gitdir,
491 objdir,
491 worktree, 492 worktree,
492 relpath, 493 relpath,
493 revisionExpr, 494 revisionExpr,
@@ -508,6 +509,7 @@ class Project(object):
508 name: The `name` attribute of manifest.xml's project element. 509 name: The `name` attribute of manifest.xml's project element.
509 remote: RemoteSpec object specifying its remote's properties. 510 remote: RemoteSpec object specifying its remote's properties.
510 gitdir: Absolute path of git directory. 511 gitdir: Absolute path of git directory.
512 objdir: Absolute path of directory to store git objects.
511 worktree: Absolute path of git working tree. 513 worktree: Absolute path of git working tree.
512 relpath: Relative path of git working tree to repo's top directory. 514 relpath: Relative path of git working tree to repo's top directory.
513 revisionExpr: The `revision` attribute of manifest.xml's project element. 515 revisionExpr: The `revision` attribute of manifest.xml's project element.
@@ -526,6 +528,7 @@ class Project(object):
526 self.name = name 528 self.name = name
527 self.remote = remote 529 self.remote = remote
528 self.gitdir = gitdir.replace('\\', '/') 530 self.gitdir = gitdir.replace('\\', '/')
531 self.objdir = objdir.replace('\\', '/')
529 if worktree: 532 if worktree:
530 self.worktree = worktree.replace('\\', '/') 533 self.worktree = worktree.replace('\\', '/')
531 else: 534 else:
@@ -558,11 +561,12 @@ class Project(object):
558 defaults = self.manifest.globalConfig) 561 defaults = self.manifest.globalConfig)
559 562
560 if self.worktree: 563 if self.worktree:
561 self.work_git = self._GitGetByExec(self, bare=False) 564 self.work_git = self._GitGetByExec(self, bare=False, gitdir=gitdir)
562 else: 565 else:
563 self.work_git = None 566 self.work_git = None
564 self.bare_git = self._GitGetByExec(self, bare=True) 567 self.bare_git = self._GitGetByExec(self, bare=True, gitdir=gitdir)
565 self.bare_ref = GitRefs(gitdir) 568 self.bare_ref = GitRefs(gitdir)
569 self.bare_objdir = self._GitGetByExec(self, bare=True, gitdir=objdir)
566 self.dest_branch = dest_branch 570 self.dest_branch = dest_branch
567 571
568 # This will be filled in if a project is later identified to be the 572 # This will be filled in if a project is later identified to be the
@@ -1117,6 +1121,7 @@ class Project(object):
1117 """Perform only the local IO portion of the sync process. 1121 """Perform only the local IO portion of the sync process.
1118 Network access is not required. 1122 Network access is not required.
1119 """ 1123 """
1124 self._InitWorkTree()
1120 all_refs = self.bare_ref.all 1125 all_refs = self.bare_ref.all
1121 self.CleanPublishedCache(all_refs) 1126 self.CleanPublishedCache(all_refs)
1122 revid = self.GetRevisionId(all_refs) 1127 revid = self.GetRevisionId(all_refs)
@@ -1125,7 +1130,6 @@ class Project(object):
1125 self._FastForward(revid) 1130 self._FastForward(revid)
1126 self._CopyFiles() 1131 self._CopyFiles()
1127 1132
1128 self._InitWorkTree()
1129 head = self.work_git.GetHead() 1133 head = self.work_git.GetHead()
1130 if head.startswith(R_HEADS): 1134 if head.startswith(R_HEADS):
1131 branch = head[len(R_HEADS):] 1135 branch = head[len(R_HEADS):]
@@ -1592,11 +1596,13 @@ class Project(object):
1592 return result 1596 return result
1593 for rev, path, url in self._GetSubmodules(): 1597 for rev, path, url in self._GetSubmodules():
1594 name = self.manifest.GetSubprojectName(self, path) 1598 name = self.manifest.GetSubprojectName(self, path)
1595 project = self.manifest.projects.get(name) 1599 relpath, worktree, gitdir, objdir = \
1600 self.manifest.GetSubprojectPaths(self, name, path)
1601 project = self.manifest.paths.get(relpath)
1596 if project: 1602 if project:
1597 result.extend(project.GetDerivedSubprojects()) 1603 result.extend(project.GetDerivedSubprojects())
1598 continue 1604 continue
1599 relpath, worktree, gitdir = self.manifest.GetSubprojectPaths(self, path) 1605
1600 remote = RemoteSpec(self.remote.name, 1606 remote = RemoteSpec(self.remote.name,
1601 url = url, 1607 url = url,
1602 review = self.remote.review) 1608 review = self.remote.review)
@@ -1604,6 +1610,7 @@ class Project(object):
1604 name = name, 1610 name = name,
1605 remote = remote, 1611 remote = remote,
1606 gitdir = gitdir, 1612 gitdir = gitdir,
1613 objdir = objdir,
1607 worktree = worktree, 1614 worktree = worktree,
1608 relpath = relpath, 1615 relpath = relpath,
1609 revisionExpr = self.revisionExpr, 1616 revisionExpr = self.revisionExpr,
@@ -1966,8 +1973,17 @@ class Project(object):
1966 1973
1967 def _InitGitDir(self, mirror_git=None): 1974 def _InitGitDir(self, mirror_git=None):
1968 if not os.path.exists(self.gitdir): 1975 if not os.path.exists(self.gitdir):
1969 os.makedirs(self.gitdir) 1976
1970 self.bare_git.init() 1977 # Initialize the bare repository, which contains all of the objects.
1978 if not os.path.exists(self.objdir):
1979 os.makedirs(self.objdir)
1980 self.bare_objdir.init()
1981
1982 # If we have a separate directory to hold refs, initialize it as well.
1983 if self.objdir != self.gitdir:
1984 os.makedirs(self.gitdir)
1985 self._ReferenceGitDir(self.objdir, self.gitdir, share_refs=False,
1986 copy_all=True)
1971 1987
1972 mp = self.manifest.manifestProject 1988 mp = self.manifest.manifestProject
1973 ref_dir = mp.config.GetString('repo.reference') or '' 1989 ref_dir = mp.config.GetString('repo.reference') or ''
@@ -2083,33 +2099,61 @@ class Project(object):
2083 msg = 'manifest set to %s' % self.revisionExpr 2099 msg = 'manifest set to %s' % self.revisionExpr
2084 self.bare_git.symbolic_ref('-m', msg, ref, dst) 2100 self.bare_git.symbolic_ref('-m', msg, ref, dst)
2085 2101
2102 def _ReferenceGitDir(self, gitdir, dotgit, share_refs, copy_all):
2103 """Update |dotgit| to reference |gitdir|, using symlinks where possible.
2104
2105 Args:
2106 gitdir: The bare git repository. Must already be initialized.
2107 dotgit: The repository you would like to initialize.
2108 share_refs: If true, |dotgit| will store its refs under |gitdir|.
2109 Only one work tree can store refs under a given |gitdir|.
2110 copy_all: If true, copy all remaining files from |gitdir| -> |dotgit|.
2111 This saves you the effort of initializing |dotgit| yourself.
2112 """
2113 # These objects can be shared between several working trees.
2114 symlink_files = ['description', 'info']
2115 symlink_dirs = ['hooks', 'objects', 'rr-cache', 'svn']
2116 if share_refs:
2117 # These objects can only be used by a single working tree.
2118 symlink_files += ['config', 'packed-refs']
2119 symlink_dirs += ['logs', 'refs']
2120 to_symlink = symlink_files + symlink_dirs
2121
2122 to_copy = []
2123 if copy_all:
2124 to_copy = os.listdir(gitdir)
2125
2126 for name in set(to_copy).union(to_symlink):
2127 try:
2128 src = os.path.realpath(os.path.join(gitdir, name))
2129 dst = os.path.realpath(os.path.join(dotgit, name))
2130
2131 if os.path.lexists(dst) and not os.path.islink(dst):
2132 raise GitError('cannot overwrite a local work tree')
2133
2134 # If the source dir doesn't exist, create an empty dir.
2135 if name in symlink_dirs and not os.path.lexists(src):
2136 os.makedirs(src)
2137
2138 if name in to_symlink:
2139 os.symlink(os.path.relpath(src, os.path.dirname(dst)), dst)
2140 elif copy_all and not os.path.islink(dst):
2141 if os.path.isdir(src):
2142 shutil.copytree(src, dst)
2143 elif os.path.isfile(src):
2144 shutil.copy(src, dst)
2145 except OSError as e:
2146 if e.errno == errno.EPERM:
2147 raise GitError('filesystem must support symlinks')
2148 else:
2149 raise
2150
2086 def _InitWorkTree(self): 2151 def _InitWorkTree(self):
2087 dotgit = os.path.join(self.worktree, '.git') 2152 dotgit = os.path.join(self.worktree, '.git')
2088 if not os.path.exists(dotgit): 2153 if not os.path.exists(dotgit):
2089 os.makedirs(dotgit) 2154 os.makedirs(dotgit)
2090 2155 self._ReferenceGitDir(self.gitdir, dotgit, share_refs=True,
2091 for name in ['config', 2156 copy_all=False)
2092 'description',
2093 'hooks',
2094 'info',
2095 'logs',
2096 'objects',
2097 'packed-refs',
2098 'refs',
2099 'rr-cache',
2100 'svn']:
2101 try:
2102 src = os.path.join(self.gitdir, name)
2103 dst = os.path.join(dotgit, name)
2104 if os.path.islink(dst) or not os.path.exists(dst):
2105 os.symlink(os.path.relpath(src, os.path.dirname(dst)), dst)
2106 else:
2107 raise GitError('cannot overwrite a local work tree')
2108 except OSError as e:
2109 if e.errno == errno.EPERM:
2110 raise GitError('filesystem must support symlinks')
2111 else:
2112 raise
2113 2157
2114 _lwrite(os.path.join(dotgit, HEAD), '%s\n' % self.GetRevisionId()) 2158 _lwrite(os.path.join(dotgit, HEAD), '%s\n' % self.GetRevisionId())
2115 2159
@@ -2119,14 +2163,10 @@ class Project(object):
2119 if GitCommand(self, cmd).Wait() != 0: 2163 if GitCommand(self, cmd).Wait() != 0:
2120 raise GitError("cannot initialize work tree") 2164 raise GitError("cannot initialize work tree")
2121 2165
2122 rr_cache = os.path.join(self.gitdir, 'rr-cache')
2123 if not os.path.exists(rr_cache):
2124 os.makedirs(rr_cache)
2125
2126 self._CopyFiles() 2166 self._CopyFiles()
2127 2167
2128 def _gitdir_path(self, path): 2168 def _gitdir_path(self, path):
2129 return os.path.join(self.gitdir, path) 2169 return os.path.realpath(os.path.join(self.gitdir, path))
2130 2170
2131 def _revlist(self, *args, **kw): 2171 def _revlist(self, *args, **kw):
2132 a = [] 2172 a = []
@@ -2139,9 +2179,10 @@ class Project(object):
2139 return self.bare_ref.all 2179 return self.bare_ref.all
2140 2180
2141 class _GitGetByExec(object): 2181 class _GitGetByExec(object):
2142 def __init__(self, project, bare): 2182 def __init__(self, project, bare, gitdir):
2143 self._project = project 2183 self._project = project
2144 self._bare = bare 2184 self._bare = bare
2185 self._gitdir = gitdir
2145 2186
2146 def LsOthers(self): 2187 def LsOthers(self):
2147 p = GitCommand(self._project, 2188 p = GitCommand(self._project,
@@ -2150,6 +2191,7 @@ class Project(object):
2150 '--others', 2191 '--others',
2151 '--exclude-standard'], 2192 '--exclude-standard'],
2152 bare = False, 2193 bare = False,
2194 gitdir=self._gitdir,
2153 capture_stdout = True, 2195 capture_stdout = True,
2154 capture_stderr = True) 2196 capture_stderr = True)
2155 if p.Wait() == 0: 2197 if p.Wait() == 0:
@@ -2165,6 +2207,7 @@ class Project(object):
2165 cmd.extend(args) 2207 cmd.extend(args)
2166 p = GitCommand(self._project, 2208 p = GitCommand(self._project,
2167 cmd, 2209 cmd,
2210 gitdir=self._gitdir,
2168 bare = False, 2211 bare = False,
2169 capture_stdout = True, 2212 capture_stdout = True,
2170 capture_stderr = True) 2213 capture_stderr = True)
@@ -2274,6 +2317,7 @@ class Project(object):
2274 p = GitCommand(self._project, 2317 p = GitCommand(self._project,
2275 cmdv, 2318 cmdv,
2276 bare = self._bare, 2319 bare = self._bare,
2320 gitdir=self._gitdir,
2277 capture_stdout = True, 2321 capture_stdout = True,
2278 capture_stderr = True) 2322 capture_stderr = True)
2279 r = [] 2323 r = []
@@ -2326,6 +2370,7 @@ class Project(object):
2326 p = GitCommand(self._project, 2370 p = GitCommand(self._project,
2327 cmdv, 2371 cmdv,
2328 bare = self._bare, 2372 bare = self._bare,
2373 gitdir=self._gitdir,
2329 capture_stdout = True, 2374 capture_stdout = True,
2330 capture_stderr = True) 2375 capture_stderr = True)
2331 if p.Wait() != 0: 2376 if p.Wait() != 0:
@@ -2459,6 +2504,7 @@ class MetaProject(Project):
2459 manifest = manifest, 2504 manifest = manifest,
2460 name = name, 2505 name = name,
2461 gitdir = gitdir, 2506 gitdir = gitdir,
2507 objdir = gitdir,
2462 worktree = worktree, 2508 worktree = worktree,
2463 remote = RemoteSpec('origin'), 2509 remote = RemoteSpec('origin'),
2464 relpath = '.repo/%s' % name, 2510 relpath = '.repo/%s' % name,