diff options
-rwxr-xr-x | main.py | 7 | ||||
-rw-r--r-- | manifest_xml.py | 12 | ||||
-rw-r--r-- | project.py | 82 | ||||
-rw-r--r-- | subcmds/forall.py | 13 | ||||
-rw-r--r-- | subcmds/sync.py | 21 |
5 files changed, 98 insertions, 37 deletions
@@ -45,6 +45,7 @@ from command import MirrorSafeCommand | |||
45 | from subcmds.version import Version | 45 | from subcmds.version import Version |
46 | from editor import Editor | 46 | from editor import Editor |
47 | from error import DownloadError | 47 | from error import DownloadError |
48 | from error import InvalidProjectGroupsError | ||
48 | from error import ManifestInvalidRevisionError | 49 | from error import ManifestInvalidRevisionError |
49 | from error import ManifestParseError | 50 | from error import ManifestParseError |
50 | from error import NoManifestException | 51 | from error import NoManifestException |
@@ -173,6 +174,12 @@ class _Repo(object): | |||
173 | else: | 174 | else: |
174 | print('error: no project in current directory', file=sys.stderr) | 175 | print('error: no project in current directory', file=sys.stderr) |
175 | result = 1 | 176 | result = 1 |
177 | except InvalidProjectGroupsError as e: | ||
178 | if e.name: | ||
179 | print('error: project group must be enabled for project %s' % e.name, file=sys.stderr) | ||
180 | else: | ||
181 | print('error: project group must be enabled for the project in the current directory', file=sys.stderr) | ||
182 | result = 1 | ||
176 | finally: | 183 | finally: |
177 | elapsed = time.time() - start | 184 | elapsed = time.time() - start |
178 | hours, remainder = divmod(elapsed, 3600) | 185 | hours, remainder = divmod(elapsed, 3600) |
diff --git a/manifest_xml.py b/manifest_xml.py index cfbd9efa..130e17c2 100644 --- a/manifest_xml.py +++ b/manifest_xml.py | |||
@@ -253,11 +253,13 @@ class XmlManifest(object): | |||
253 | else: | 253 | else: |
254 | value = p.work_git.rev_parse(HEAD + '^0') | 254 | value = p.work_git.rev_parse(HEAD + '^0') |
255 | e.setAttribute('revision', value) | 255 | e.setAttribute('revision', value) |
256 | if peg_rev_upstream and value != p.revisionExpr: | 256 | if peg_rev_upstream: |
257 | # Only save the origin if the origin is not a sha1, and the default | 257 | if p.upstream: |
258 | # isn't our value, and the if the default doesn't already have that | 258 | e.setAttribute('upstream', p.upstream) |
259 | # covered. | 259 | elif value != p.revisionExpr: |
260 | e.setAttribute('upstream', p.revisionExpr) | 260 | # Only save the origin if the origin is not a sha1, and the default |
261 | # isn't our value | ||
262 | e.setAttribute('upstream', p.revisionExpr) | ||
261 | else: | 263 | else: |
262 | revision = self.remotes[remoteName].revision or d.revisionExpr | 264 | revision = self.remotes[remoteName].revision or d.revisionExpr |
263 | if not revision or revision != p.revisionExpr: | 265 | if not revision or revision != p.revisionExpr: |
@@ -544,6 +544,12 @@ class RepoHook(object): | |||
544 | 544 | ||
545 | 545 | ||
546 | class Project(object): | 546 | class Project(object): |
547 | # These objects can be shared between several working trees. | ||
548 | shareable_files = ['description', 'info'] | ||
549 | shareable_dirs = ['hooks', 'objects', 'rr-cache', 'svn'] | ||
550 | # These objects can only be used by a single working tree. | ||
551 | working_tree_files = ['config', 'packed-refs', 'shallow'] | ||
552 | working_tree_dirs = ['logs', 'refs'] | ||
547 | def __init__(self, | 553 | def __init__(self, |
548 | manifest, | 554 | manifest, |
549 | name, | 555 | name, |
@@ -645,7 +651,7 @@ class Project(object): | |||
645 | 651 | ||
646 | @property | 652 | @property |
647 | def Exists(self): | 653 | def Exists(self): |
648 | return os.path.isdir(self.gitdir) | 654 | return os.path.isdir(self.gitdir) and os.path.isdir(self.objdir) |
649 | 655 | ||
650 | @property | 656 | @property |
651 | def CurrentBranch(self): | 657 | def CurrentBranch(self): |
@@ -1131,7 +1137,6 @@ class Project(object): | |||
1131 | "%s" % (tarpath, str(e)), file=sys.stderr) | 1137 | "%s" % (tarpath, str(e)), file=sys.stderr) |
1132 | self._CopyAndLinkFiles() | 1138 | self._CopyAndLinkFiles() |
1133 | return True | 1139 | return True |
1134 | |||
1135 | if is_new is None: | 1140 | if is_new is None: |
1136 | is_new = not self.Exists | 1141 | is_new = not self.Exists |
1137 | if is_new: | 1142 | if is_new: |
@@ -1876,8 +1881,6 @@ class Project(object): | |||
1876 | cmd.append('--quiet') | 1881 | cmd.append('--quiet') |
1877 | if not self.worktree: | 1882 | if not self.worktree: |
1878 | cmd.append('--update-head-ok') | 1883 | cmd.append('--update-head-ok') |
1879 | if self.manifest.IsMirror: | ||
1880 | cmd.append('--prune') | ||
1881 | cmd.append(name) | 1884 | cmd.append(name) |
1882 | 1885 | ||
1883 | # If using depth then we should not get all the tags since they may | 1886 | # If using depth then we should not get all the tags since they may |
@@ -1897,7 +1900,7 @@ class Project(object): | |||
1897 | 1900 | ||
1898 | if not self.manifest.IsMirror: | 1901 | if not self.manifest.IsMirror: |
1899 | branch = self.revisionExpr | 1902 | branch = self.revisionExpr |
1900 | if is_sha1 and depth: | 1903 | if is_sha1 and depth and git_require((1, 8, 3)): |
1901 | # Shallow checkout of a specific commit, fetch from that commit and not | 1904 | # Shallow checkout of a specific commit, fetch from that commit and not |
1902 | # the heads only as the commit might be deeper in the history. | 1905 | # the heads only as the commit might be deeper in the history. |
1903 | spec.append(branch) | 1906 | spec.append(branch) |
@@ -1960,8 +1963,15 @@ class Project(object): | |||
1960 | # got what we wanted, else trigger a second run of all | 1963 | # got what we wanted, else trigger a second run of all |
1961 | # refs. | 1964 | # refs. |
1962 | if not self._CheckForSha1(): | 1965 | if not self._CheckForSha1(): |
1963 | return self._RemoteFetch(name=name, current_branch_only=False, | 1966 | if not depth: |
1964 | initial=False, quiet=quiet, alt_dir=alt_dir) | 1967 | # Avoid infinite recursion when depth is True (since depth implies |
1968 | # current_branch_only) | ||
1969 | return self._RemoteFetch(name=name, current_branch_only=False, | ||
1970 | initial=False, quiet=quiet, alt_dir=alt_dir) | ||
1971 | if self.clone_depth: | ||
1972 | self.clone_depth = None | ||
1973 | return self._RemoteFetch(name=name, current_branch_only=current_branch_only, | ||
1974 | initial=False, quiet=quiet, alt_dir=alt_dir) | ||
1965 | 1975 | ||
1966 | return ok | 1976 | return ok |
1967 | 1977 | ||
@@ -2155,19 +2165,24 @@ class Project(object): | |||
2155 | raise GitError('%s merge %s ' % (self.name, head)) | 2165 | raise GitError('%s merge %s ' % (self.name, head)) |
2156 | 2166 | ||
2157 | def _InitGitDir(self, mirror_git=None): | 2167 | def _InitGitDir(self, mirror_git=None): |
2158 | if not os.path.exists(self.gitdir): | 2168 | init_git_dir = not os.path.exists(self.gitdir) |
2159 | 2169 | init_obj_dir = not os.path.exists(self.objdir) | |
2160 | # Initialize the bare repository, which contains all of the objects. | 2170 | # Initialize the bare repository, which contains all of the objects. |
2161 | if not os.path.exists(self.objdir): | 2171 | if init_obj_dir: |
2162 | os.makedirs(self.objdir) | 2172 | os.makedirs(self.objdir) |
2163 | self.bare_objdir.init() | 2173 | self.bare_objdir.init() |
2164 | 2174 | ||
2165 | # If we have a separate directory to hold refs, initialize it as well. | 2175 | # If we have a separate directory to hold refs, initialize it as well. |
2166 | if self.objdir != self.gitdir: | 2176 | if self.objdir != self.gitdir: |
2177 | if init_git_dir: | ||
2167 | os.makedirs(self.gitdir) | 2178 | os.makedirs(self.gitdir) |
2179 | |||
2180 | if init_obj_dir or init_git_dir: | ||
2168 | self._ReferenceGitDir(self.objdir, self.gitdir, share_refs=False, | 2181 | self._ReferenceGitDir(self.objdir, self.gitdir, share_refs=False, |
2169 | copy_all=True) | 2182 | copy_all=True) |
2183 | self._CheckDirReference(self.objdir, self.gitdir, share_refs=False) | ||
2170 | 2184 | ||
2185 | if init_git_dir: | ||
2171 | mp = self.manifest.manifestProject | 2186 | mp = self.manifest.manifestProject |
2172 | ref_dir = mp.config.GetString('repo.reference') or '' | 2187 | ref_dir = mp.config.GetString('repo.reference') or '' |
2173 | 2188 | ||
@@ -2273,6 +2288,21 @@ class Project(object): | |||
2273 | msg = 'manifest set to %s' % self.revisionExpr | 2288 | msg = 'manifest set to %s' % self.revisionExpr |
2274 | self.bare_git.symbolic_ref('-m', msg, ref, dst) | 2289 | self.bare_git.symbolic_ref('-m', msg, ref, dst) |
2275 | 2290 | ||
2291 | def _CheckDirReference(self, srcdir, destdir, share_refs): | ||
2292 | symlink_files = self.shareable_files | ||
2293 | symlink_dirs = self.shareable_dirs | ||
2294 | if share_refs: | ||
2295 | symlink_files += self.working_tree_files | ||
2296 | symlink_dirs += self.working_tree_dirs | ||
2297 | to_symlink = symlink_files + symlink_dirs | ||
2298 | for name in set(to_symlink): | ||
2299 | dst = os.path.realpath(os.path.join(destdir, name)) | ||
2300 | if os.path.lexists(dst): | ||
2301 | src = os.path.realpath(os.path.join(srcdir, name)) | ||
2302 | # Fail if the links are pointing to the wrong place | ||
2303 | if src != dst: | ||
2304 | raise GitError('cannot overwrite a local work tree') | ||
2305 | |||
2276 | def _ReferenceGitDir(self, gitdir, dotgit, share_refs, copy_all): | 2306 | def _ReferenceGitDir(self, gitdir, dotgit, share_refs, copy_all): |
2277 | """Update |dotgit| to reference |gitdir|, using symlinks where possible. | 2307 | """Update |dotgit| to reference |gitdir|, using symlinks where possible. |
2278 | 2308 | ||
@@ -2284,13 +2314,11 @@ class Project(object): | |||
2284 | copy_all: If true, copy all remaining files from |gitdir| -> |dotgit|. | 2314 | copy_all: If true, copy all remaining files from |gitdir| -> |dotgit|. |
2285 | This saves you the effort of initializing |dotgit| yourself. | 2315 | This saves you the effort of initializing |dotgit| yourself. |
2286 | """ | 2316 | """ |
2287 | # These objects can be shared between several working trees. | 2317 | symlink_files = self.shareable_files |
2288 | symlink_files = ['description', 'info'] | 2318 | symlink_dirs = self.shareable_dirs |
2289 | symlink_dirs = ['hooks', 'objects', 'rr-cache', 'svn'] | ||
2290 | if share_refs: | 2319 | if share_refs: |
2291 | # These objects can only be used by a single working tree. | 2320 | symlink_files += self.working_tree_files |
2292 | symlink_files += ['config', 'packed-refs', 'shallow'] | 2321 | symlink_dirs += self.working_tree_dirs |
2293 | symlink_dirs += ['logs', 'refs'] | ||
2294 | to_symlink = symlink_files + symlink_dirs | 2322 | to_symlink = symlink_files + symlink_dirs |
2295 | 2323 | ||
2296 | to_copy = [] | 2324 | to_copy = [] |
@@ -2302,8 +2330,8 @@ class Project(object): | |||
2302 | src = os.path.realpath(os.path.join(gitdir, name)) | 2330 | src = os.path.realpath(os.path.join(gitdir, name)) |
2303 | dst = os.path.realpath(os.path.join(dotgit, name)) | 2331 | dst = os.path.realpath(os.path.join(dotgit, name)) |
2304 | 2332 | ||
2305 | if os.path.lexists(dst) and not os.path.islink(dst): | 2333 | if os.path.lexists(dst): |
2306 | raise GitError('cannot overwrite a local work tree') | 2334 | continue |
2307 | 2335 | ||
2308 | # If the source dir doesn't exist, create an empty dir. | 2336 | # If the source dir doesn't exist, create an empty dir. |
2309 | if name in symlink_dirs and not os.path.lexists(src): | 2337 | if name in symlink_dirs and not os.path.lexists(src): |
@@ -2332,11 +2360,15 @@ class Project(object): | |||
2332 | 2360 | ||
2333 | def _InitWorkTree(self): | 2361 | def _InitWorkTree(self): |
2334 | dotgit = os.path.join(self.worktree, '.git') | 2362 | dotgit = os.path.join(self.worktree, '.git') |
2335 | if not os.path.exists(dotgit): | 2363 | init_dotgit = not os.path.exists(dotgit) |
2364 | if init_dotgit: | ||
2336 | os.makedirs(dotgit) | 2365 | os.makedirs(dotgit) |
2337 | self._ReferenceGitDir(self.gitdir, dotgit, share_refs=True, | 2366 | self._ReferenceGitDir(self.gitdir, dotgit, share_refs=True, |
2338 | copy_all=False) | 2367 | copy_all=False) |
2339 | 2368 | ||
2369 | self._CheckDirReference(self.gitdir, dotgit, share_refs=True) | ||
2370 | |||
2371 | if init_dotgit: | ||
2340 | _lwrite(os.path.join(dotgit, HEAD), '%s\n' % self.GetRevisionId()) | 2372 | _lwrite(os.path.join(dotgit, HEAD), '%s\n' % self.GetRevisionId()) |
2341 | 2373 | ||
2342 | cmd = ['read-tree', '--reset', '-u'] | 2374 | cmd = ['read-tree', '--reset', '-u'] |
diff --git a/subcmds/forall.py b/subcmds/forall.py index ebc8beca..b93cd6d0 100644 --- a/subcmds/forall.py +++ b/subcmds/forall.py | |||
@@ -151,11 +151,15 @@ without iterating through the remaining projects. | |||
151 | attributes that we need. | 151 | attributes that we need. |
152 | 152 | ||
153 | """ | 153 | """ |
154 | if not self.manifest.IsMirror: | ||
155 | lrev = project.GetRevisionId() | ||
156 | else: | ||
157 | lrev = None | ||
154 | return { | 158 | return { |
155 | 'name': project.name, | 159 | 'name': project.name, |
156 | 'relpath': project.relpath, | 160 | 'relpath': project.relpath, |
157 | 'remote_name': project.remote.name, | 161 | 'remote_name': project.remote.name, |
158 | 'lrev': project.GetRevisionId(), | 162 | 'lrev': lrev, |
159 | 'rrev': project.revisionExpr, | 163 | 'rrev': project.revisionExpr, |
160 | 'annotations': dict((a.name, a.value) for a in project.annotations), | 164 | 'annotations': dict((a.name, a.value) for a in project.annotations), |
161 | 'gitdir': project.gitdir, | 165 | 'gitdir': project.gitdir, |
@@ -201,6 +205,13 @@ without iterating through the remaining projects. | |||
201 | mirror = self.manifest.IsMirror | 205 | mirror = self.manifest.IsMirror |
202 | rc = 0 | 206 | rc = 0 |
203 | 207 | ||
208 | smart_sync_manifest_name = "smart_sync_override.xml" | ||
209 | smart_sync_manifest_path = os.path.join( | ||
210 | self.manifest.manifestProject.worktree, smart_sync_manifest_name) | ||
211 | |||
212 | if os.path.isfile(smart_sync_manifest_path): | ||
213 | self.manifest.Override(smart_sync_manifest_path) | ||
214 | |||
204 | if not opt.regex: | 215 | if not opt.regex: |
205 | projects = self.GetProjects(args) | 216 | projects = self.GetProjects(args) |
206 | else: | 217 | else: |
diff --git a/subcmds/sync.py b/subcmds/sync.py index b4546c15..ec333ae7 100644 --- a/subcmds/sync.py +++ b/subcmds/sync.py | |||
@@ -517,6 +517,9 @@ later is required to fix a server side protocol bug. | |||
517 | self.manifest.Override(opt.manifest_name) | 517 | self.manifest.Override(opt.manifest_name) |
518 | 518 | ||
519 | manifest_name = opt.manifest_name | 519 | manifest_name = opt.manifest_name |
520 | smart_sync_manifest_name = "smart_sync_override.xml" | ||
521 | smart_sync_manifest_path = os.path.join( | ||
522 | self.manifest.manifestProject.worktree, smart_sync_manifest_name) | ||
520 | 523 | ||
521 | if opt.smart_sync or opt.smart_tag: | 524 | if opt.smart_sync or opt.smart_tag: |
522 | if not self.manifest.manifest_server: | 525 | if not self.manifest.manifest_server: |
@@ -583,17 +586,16 @@ later is required to fix a server side protocol bug. | |||
583 | [success, manifest_str] = server.GetManifest(opt.smart_tag) | 586 | [success, manifest_str] = server.GetManifest(opt.smart_tag) |
584 | 587 | ||
585 | if success: | 588 | if success: |
586 | manifest_name = "smart_sync_override.xml" | 589 | manifest_name = smart_sync_manifest_name |
587 | manifest_path = os.path.join(self.manifest.manifestProject.worktree, | ||
588 | manifest_name) | ||
589 | try: | 590 | try: |
590 | f = open(manifest_path, 'w') | 591 | f = open(smart_sync_manifest_path, 'w') |
591 | try: | 592 | try: |
592 | f.write(manifest_str) | 593 | f.write(manifest_str) |
593 | finally: | 594 | finally: |
594 | f.close() | 595 | f.close() |
595 | except IOError: | 596 | except IOError as e: |
596 | print('error: cannot write manifest to %s' % manifest_path, | 597 | print('error: cannot write manifest to %s:\n%s' |
598 | % (smart_sync_manifest_path, e), | ||
597 | file=sys.stderr) | 599 | file=sys.stderr) |
598 | sys.exit(1) | 600 | sys.exit(1) |
599 | self._ReloadManifest(manifest_name) | 601 | self._ReloadManifest(manifest_name) |
@@ -610,6 +612,13 @@ later is required to fix a server side protocol bug. | |||
610 | % (self.manifest.manifest_server, e.errcode, e.errmsg), | 612 | % (self.manifest.manifest_server, e.errcode, e.errmsg), |
611 | file=sys.stderr) | 613 | file=sys.stderr) |
612 | sys.exit(1) | 614 | sys.exit(1) |
615 | else: # Not smart sync or smart tag mode | ||
616 | if os.path.isfile(smart_sync_manifest_path): | ||
617 | try: | ||
618 | os.remove(smart_sync_manifest_path) | ||
619 | except OSError as e: | ||
620 | print('error: failed to remove existing smart sync override manifest: %s' % | ||
621 | e, file=sys.stderr) | ||
613 | 622 | ||
614 | rp = self.manifest.repoProject | 623 | rp = self.manifest.repoProject |
615 | rp.PreSync() | 624 | rp.PreSync() |