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'] |