diff options
| author | Conley Owens <cco3@android.com> | 2014-01-10 01:20:12 +0000 |
|---|---|---|
| committer | Gerrit Code Review <noreply-gerritcodereview@google.com> | 2014-01-10 01:20:13 +0000 |
| commit | e695338e21080d3cbe20935db572e4cd0c7a620c (patch) | |
| tree | cc525f53929fa4ea24f108d24545c68c7c6cb5ba /project.py | |
| parent | bd80f7eedd5a74f6c5fad745091dcda53a6415bf (diff) | |
| parent | 8d20116038ff78b22069dd4e993b5819775f03d1 (diff) | |
| download | git-repo-e695338e21080d3cbe20935db572e4cd0c7a620c.tar.gz | |
Merge "repo: Support multiple branches for the same project."
Diffstat (limited to 'project.py')
| -rw-r--r-- | project.py | 118 |
1 files changed, 82 insertions, 36 deletions
| @@ -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, |
