summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rwxr-xr-xmain.py7
-rw-r--r--manifest_xml.py12
-rw-r--r--project.py82
-rw-r--r--subcmds/forall.py13
-rw-r--r--subcmds/sync.py21
5 files changed, 98 insertions, 37 deletions
diff --git a/main.py b/main.py
index 47f083df..6736abc9 100755
--- a/main.py
+++ b/main.py
@@ -45,6 +45,7 @@ from command import MirrorSafeCommand
45from subcmds.version import Version 45from subcmds.version import Version
46from editor import Editor 46from editor import Editor
47from error import DownloadError 47from error import DownloadError
48from error import InvalidProjectGroupsError
48from error import ManifestInvalidRevisionError 49from error import ManifestInvalidRevisionError
49from error import ManifestParseError 50from error import ManifestParseError
50from error import NoManifestException 51from 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:
diff --git a/project.py b/project.py
index 3f1e3b65..00f6b904 100644
--- a/project.py
+++ b/project.py
@@ -544,6 +544,12 @@ class RepoHook(object):
544 544
545 545
546class Project(object): 546class 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()