diff options
| author | Kevin Degi <kdegi@codeaurora.org> | 2014-10-16 16:02:58 -0600 |
|---|---|---|
| committer | Kevin Degi <kdegi@codeaurora.org> | 2015-05-12 09:15:53 -0600 |
| commit | 384b3c594831e79348a2eb98809ef9f3e34f6aa2 (patch) | |
| tree | 12c9b77879b0937358a9a5fa96d2a1c562180066 /project.py | |
| parent | 4ccad7554b958c701653c41a72442cccf301e71a (diff) | |
| download | git-repo-384b3c594831e79348a2eb98809ef9f3e34f6aa2.tar.gz | |
Fail if gitdir does not point to objdir during sync
There are a set of cases that can cause the git directory in
.repo/projects to point to a directory in .repo/project-objects that
is not the one specified in the manifest. This results in a tree that
is not sane, and so should cause a failure.
In order to reproduce the failure case:
1) Sync to any manifest
2) Change the 'name' of a project to a different repository. Leave the
'path' the same.
3) Resync the modified project. The project-objects directory will not
be created, and the projects directory will remain pointed at the old
project-objects.
Change-Id: Ie6711b1c773508850c5c9f748a27ff72d65e2bf2
Diffstat (limited to 'project.py')
| -rw-r--r-- | project.py | 67 |
1 files changed, 47 insertions, 20 deletions
| @@ -511,6 +511,12 @@ class RepoHook(object): | |||
| 511 | 511 | ||
| 512 | 512 | ||
| 513 | class Project(object): | 513 | class Project(object): |
| 514 | # These objects can be shared between several working trees. | ||
| 515 | shareable_files = ['description', 'info'] | ||
| 516 | shareable_dirs = ['hooks', 'objects', 'rr-cache', 'svn'] | ||
| 517 | # These objects can only be used by a single working tree. | ||
| 518 | working_tree_files = ['config', 'packed-refs', 'shallow'] | ||
| 519 | working_tree_dirs = ['logs', 'refs'] | ||
| 514 | def __init__(self, | 520 | def __init__(self, |
| 515 | manifest, | 521 | manifest, |
| 516 | name, | 522 | name, |
| @@ -608,7 +614,7 @@ class Project(object): | |||
| 608 | 614 | ||
| 609 | @property | 615 | @property |
| 610 | def Exists(self): | 616 | def Exists(self): |
| 611 | return os.path.isdir(self.gitdir) | 617 | return os.path.isdir(self.gitdir) and os.path.isdir(self.objdir) |
| 612 | 618 | ||
| 613 | @property | 619 | @property |
| 614 | def CurrentBranch(self): | 620 | def CurrentBranch(self): |
| @@ -1093,7 +1099,6 @@ class Project(object): | |||
| 1093 | "%s" % (tarpath, str(e)), file=sys.stderr) | 1099 | "%s" % (tarpath, str(e)), file=sys.stderr) |
| 1094 | self._CopyAndLinkFiles() | 1100 | self._CopyAndLinkFiles() |
| 1095 | return True | 1101 | return True |
| 1096 | |||
| 1097 | if is_new is None: | 1102 | if is_new is None: |
| 1098 | is_new = not self.Exists | 1103 | is_new = not self.Exists |
| 1099 | if is_new: | 1104 | if is_new: |
| @@ -2110,19 +2115,24 @@ class Project(object): | |||
| 2110 | raise GitError('%s merge %s ' % (self.name, head)) | 2115 | raise GitError('%s merge %s ' % (self.name, head)) |
| 2111 | 2116 | ||
| 2112 | def _InitGitDir(self, mirror_git=None): | 2117 | def _InitGitDir(self, mirror_git=None): |
| 2113 | if not os.path.exists(self.gitdir): | 2118 | init_git_dir = not os.path.exists(self.gitdir) |
| 2114 | 2119 | init_obj_dir = not os.path.exists(self.objdir) | |
| 2115 | # Initialize the bare repository, which contains all of the objects. | 2120 | # Initialize the bare repository, which contains all of the objects. |
| 2116 | if not os.path.exists(self.objdir): | 2121 | if init_obj_dir: |
| 2117 | os.makedirs(self.objdir) | 2122 | os.makedirs(self.objdir) |
| 2118 | self.bare_objdir.init() | 2123 | self.bare_objdir.init() |
| 2119 | 2124 | ||
| 2120 | # If we have a separate directory to hold refs, initialize it as well. | 2125 | # If we have a separate directory to hold refs, initialize it as well. |
| 2121 | if self.objdir != self.gitdir: | 2126 | if self.objdir != self.gitdir: |
| 2127 | if init_git_dir: | ||
| 2122 | os.makedirs(self.gitdir) | 2128 | os.makedirs(self.gitdir) |
| 2129 | |||
| 2130 | if init_obj_dir or init_git_dir: | ||
| 2123 | self._ReferenceGitDir(self.objdir, self.gitdir, share_refs=False, | 2131 | self._ReferenceGitDir(self.objdir, self.gitdir, share_refs=False, |
| 2124 | copy_all=True) | 2132 | copy_all=True) |
| 2133 | self._CheckDirReference(self.objdir, self.gitdir, share_refs=False) | ||
| 2125 | 2134 | ||
| 2135 | if init_git_dir: | ||
| 2126 | mp = self.manifest.manifestProject | 2136 | mp = self.manifest.manifestProject |
| 2127 | ref_dir = mp.config.GetString('repo.reference') or '' | 2137 | ref_dir = mp.config.GetString('repo.reference') or '' |
| 2128 | 2138 | ||
| @@ -2228,6 +2238,21 @@ class Project(object): | |||
| 2228 | msg = 'manifest set to %s' % self.revisionExpr | 2238 | msg = 'manifest set to %s' % self.revisionExpr |
| 2229 | self.bare_git.symbolic_ref('-m', msg, ref, dst) | 2239 | self.bare_git.symbolic_ref('-m', msg, ref, dst) |
| 2230 | 2240 | ||
| 2241 | def _CheckDirReference(self, srcdir, destdir, share_refs): | ||
| 2242 | symlink_files = self.shareable_files | ||
| 2243 | symlink_dirs = self.shareable_dirs | ||
| 2244 | if share_refs: | ||
| 2245 | symlink_files += self.working_tree_files | ||
| 2246 | symlink_dirs += self.working_tree_dirs | ||
| 2247 | to_symlink = symlink_files + symlink_dirs | ||
| 2248 | for name in set(to_symlink): | ||
| 2249 | dst = os.path.realpath(os.path.join(destdir, name)) | ||
| 2250 | if os.path.lexists(dst): | ||
| 2251 | src = os.path.realpath(os.path.join(srcdir, name)) | ||
| 2252 | # Fail if the links are pointing to the wrong place | ||
| 2253 | if src != dst: | ||
| 2254 | raise GitError('cannot overwrite a local work tree') | ||
| 2255 | |||
| 2231 | def _ReferenceGitDir(self, gitdir, dotgit, share_refs, copy_all): | 2256 | def _ReferenceGitDir(self, gitdir, dotgit, share_refs, copy_all): |
| 2232 | """Update |dotgit| to reference |gitdir|, using symlinks where possible. | 2257 | """Update |dotgit| to reference |gitdir|, using symlinks where possible. |
| 2233 | 2258 | ||
| @@ -2239,13 +2264,11 @@ class Project(object): | |||
| 2239 | copy_all: If true, copy all remaining files from |gitdir| -> |dotgit|. | 2264 | copy_all: If true, copy all remaining files from |gitdir| -> |dotgit|. |
| 2240 | This saves you the effort of initializing |dotgit| yourself. | 2265 | This saves you the effort of initializing |dotgit| yourself. |
| 2241 | """ | 2266 | """ |
| 2242 | # These objects can be shared between several working trees. | 2267 | symlink_files = self.shareable_files |
| 2243 | symlink_files = ['description', 'info'] | 2268 | symlink_dirs = self.shareable_dirs |
| 2244 | symlink_dirs = ['hooks', 'objects', 'rr-cache', 'svn'] | ||
| 2245 | if share_refs: | 2269 | if share_refs: |
| 2246 | # These objects can only be used by a single working tree. | 2270 | symlink_files += self.working_tree_files |
| 2247 | symlink_files += ['config', 'packed-refs', 'shallow'] | 2271 | symlink_dirs += self.working_tree_dirs |
| 2248 | symlink_dirs += ['logs', 'refs'] | ||
| 2249 | to_symlink = symlink_files + symlink_dirs | 2272 | to_symlink = symlink_files + symlink_dirs |
| 2250 | 2273 | ||
| 2251 | to_copy = [] | 2274 | to_copy = [] |
| @@ -2257,8 +2280,8 @@ class Project(object): | |||
| 2257 | src = os.path.realpath(os.path.join(gitdir, name)) | 2280 | src = os.path.realpath(os.path.join(gitdir, name)) |
| 2258 | dst = os.path.realpath(os.path.join(dotgit, name)) | 2281 | dst = os.path.realpath(os.path.join(dotgit, name)) |
| 2259 | 2282 | ||
| 2260 | if os.path.lexists(dst) and not os.path.islink(dst): | 2283 | if os.path.lexists(dst): |
| 2261 | raise GitError('cannot overwrite a local work tree') | 2284 | continue |
| 2262 | 2285 | ||
| 2263 | # If the source dir doesn't exist, create an empty dir. | 2286 | # If the source dir doesn't exist, create an empty dir. |
| 2264 | if name in symlink_dirs and not os.path.lexists(src): | 2287 | if name in symlink_dirs and not os.path.lexists(src): |
| @@ -2287,11 +2310,15 @@ class Project(object): | |||
| 2287 | 2310 | ||
| 2288 | def _InitWorkTree(self): | 2311 | def _InitWorkTree(self): |
| 2289 | dotgit = os.path.join(self.worktree, '.git') | 2312 | dotgit = os.path.join(self.worktree, '.git') |
| 2290 | if not os.path.exists(dotgit): | 2313 | init_dotgit = not os.path.exists(dotgit) |
| 2314 | if init_dotgit: | ||
| 2291 | os.makedirs(dotgit) | 2315 | os.makedirs(dotgit) |
| 2292 | self._ReferenceGitDir(self.gitdir, dotgit, share_refs=True, | 2316 | self._ReferenceGitDir(self.gitdir, dotgit, share_refs=True, |
| 2293 | copy_all=False) | 2317 | copy_all=False) |
| 2294 | 2318 | ||
| 2319 | self._CheckDirReference(self.gitdir, dotgit, share_refs=True) | ||
| 2320 | |||
| 2321 | if init_dotgit: | ||
| 2295 | _lwrite(os.path.join(dotgit, HEAD), '%s\n' % self.GetRevisionId()) | 2322 | _lwrite(os.path.join(dotgit, HEAD), '%s\n' % self.GetRevisionId()) |
| 2296 | 2323 | ||
| 2297 | cmd = ['read-tree', '--reset', '-u'] | 2324 | cmd = ['read-tree', '--reset', '-u'] |
