summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--error.py4
-rw-r--r--git_command.py7
-rw-r--r--git_config.py2
-rw-r--r--project.py65
-rw-r--r--subcmds/forall.py27
-rw-r--r--subcmds/init.py4
6 files changed, 84 insertions, 25 deletions
diff --git a/error.py b/error.py
index ff948f9c..f2a7c4e4 100644
--- a/error.py
+++ b/error.py
@@ -80,7 +80,7 @@ class NoSuchProjectError(Exception):
80 self.name = name 80 self.name = name
81 81
82 def __str__(self): 82 def __str__(self):
83 if self.Name is None: 83 if self.name is None:
84 return 'in current directory' 84 return 'in current directory'
85 return self.name 85 return self.name
86 86
@@ -93,7 +93,7 @@ class InvalidProjectGroupsError(Exception):
93 self.name = name 93 self.name = name
94 94
95 def __str__(self): 95 def __str__(self):
96 if self.Name is None: 96 if self.name is None:
97 return 'in current directory' 97 return 'in current directory'
98 return self.name 98 return self.name
99 99
diff --git a/git_command.py b/git_command.py
index 259fb02c..0893bff7 100644
--- a/git_command.py
+++ b/git_command.py
@@ -92,7 +92,10 @@ class _GitCall(object):
92 def version(self): 92 def version(self):
93 p = GitCommand(None, ['--version'], capture_stdout=True) 93 p = GitCommand(None, ['--version'], capture_stdout=True)
94 if p.Wait() == 0: 94 if p.Wait() == 0:
95 return p.stdout.decode('utf-8') 95 if hasattr(p.stdout, 'decode'):
96 return p.stdout.decode('utf-8')
97 else:
98 return p.stdout
96 return None 99 return None
97 100
98 def version_tuple(self): 101 def version_tuple(self):
@@ -263,6 +266,8 @@ class GitCommand(object):
263 if not buf: 266 if not buf:
264 s_in.remove(s) 267 s_in.remove(s)
265 continue 268 continue
269 if not hasattr(buf, 'encode'):
270 buf = buf.decode()
266 if s.std_name == 'stdout': 271 if s.std_name == 'stdout':
267 self.stdout += buf 272 self.stdout += buf
268 else: 273 else:
diff --git a/git_config.py b/git_config.py
index c4c31e18..8ded7c25 100644
--- a/git_config.py
+++ b/git_config.py
@@ -280,7 +280,7 @@ class GitConfig(object):
280 finally: 280 finally:
281 fd.close() 281 fd.close()
282 except (IOError, TypeError): 282 except (IOError, TypeError):
283 if os.path.exists(self.json): 283 if os.path.exists(self._json):
284 os.remove(self._json) 284 os.remove(self._json)
285 285
286 def _ReadGit(self): 286 def _ReadGit(self):
diff --git a/project.py b/project.py
index 00e41ada..3f1e3b65 100644
--- a/project.py
+++ b/project.py
@@ -16,6 +16,7 @@ from __future__ import print_function
16import contextlib 16import contextlib
17import errno 17import errno
18import filecmp 18import filecmp
19import glob
19import os 20import os
20import random 21import random
21import re 22import re
@@ -233,28 +234,60 @@ class _CopyFile(object):
233 _error('Cannot copy file %s to %s', src, dest) 234 _error('Cannot copy file %s to %s', src, dest)
234 235
235class _LinkFile(object): 236class _LinkFile(object):
236 def __init__(self, src, dest, abssrc, absdest): 237 def __init__(self, git_worktree, src, dest, relsrc, absdest):
238 self.git_worktree = git_worktree
237 self.src = src 239 self.src = src
238 self.dest = dest 240 self.dest = dest
239 self.abs_src = abssrc 241 self.src_rel_to_dest = relsrc
240 self.abs_dest = absdest 242 self.abs_dest = absdest
241 243
242 def _Link(self): 244 def __linkIt(self, relSrc, absDest):
243 src = self.abs_src
244 dest = self.abs_dest
245 # link file if it does not exist or is out of date 245 # link file if it does not exist or is out of date
246 if not os.path.islink(dest) or os.readlink(dest) != src: 246 if not os.path.islink(absDest) or (os.readlink(absDest) != relSrc):
247 try: 247 try:
248 # remove existing file first, since it might be read-only 248 # remove existing file first, since it might be read-only
249 if os.path.exists(dest): 249 if os.path.exists(absDest):
250 os.remove(dest) 250 os.remove(absDest)
251 else: 251 else:
252 dest_dir = os.path.dirname(dest) 252 dest_dir = os.path.dirname(absDest)
253 if not os.path.isdir(dest_dir): 253 if not os.path.isdir(dest_dir):
254 os.makedirs(dest_dir) 254 os.makedirs(dest_dir)
255 os.symlink(src, dest) 255 os.symlink(relSrc, absDest)
256 except IOError: 256 except IOError:
257 _error('Cannot link file %s to %s', src, dest) 257 _error('Cannot link file %s to %s', relSrc, absDest)
258
259 def _Link(self):
260 """Link the self.rel_src_to_dest and self.abs_dest. Handles wild cards
261 on the src linking all of the files in the source in to the destination
262 directory.
263 """
264 # We use the absSrc to handle the situation where the current directory
265 # is not the root of the repo
266 absSrc = os.path.join(self.git_worktree, self.src)
267 if os.path.exists(absSrc):
268 # Entity exists so just a simple one to one link operation
269 self.__linkIt(self.src_rel_to_dest, self.abs_dest)
270 else:
271 # Entity doesn't exist assume there is a wild card
272 absDestDir = self.abs_dest
273 if os.path.exists(absDestDir) and not os.path.isdir(absDestDir):
274 _error('Link error: src with wildcard, %s must be a directory',
275 absDestDir)
276 else:
277 absSrcFiles = glob.glob(absSrc)
278 for absSrcFile in absSrcFiles:
279 # Create a releative path from source dir to destination dir
280 absSrcDir = os.path.dirname(absSrcFile)
281 relSrcDir = os.path.relpath(absSrcDir, absDestDir)
282
283 # Get the source file name
284 srcFile = os.path.basename(absSrcFile)
285
286 # Now form the final full paths to srcFile. They will be
287 # absolute for the desintaiton and relative for the srouce.
288 absDest = os.path.join(absDestDir, srcFile)
289 relSrc = os.path.join(relSrcDir, srcFile)
290 self.__linkIt(relSrc, absDest)
258 291
259class RemoteSpec(object): 292class RemoteSpec(object):
260 def __init__(self, 293 def __init__(self,
@@ -1359,9 +1392,10 @@ class Project(object):
1359 1392
1360 def AddLinkFile(self, src, dest, absdest): 1393 def AddLinkFile(self, src, dest, absdest):
1361 # dest should already be an absolute path, but src is project relative 1394 # dest should already be an absolute path, but src is project relative
1362 # make src an absolute path 1395 # make src relative path to dest
1363 abssrc = os.path.join(self.worktree, src) 1396 absdestdir = os.path.dirname(absdest)
1364 self.linkfiles.append(_LinkFile(src, dest, abssrc, absdest)) 1397 relsrc = os.path.relpath(os.path.join(self.worktree, src), absdestdir)
1398 self.linkfiles.append(_LinkFile(self.worktree, src, dest, relsrc, absdest))
1365 1399
1366 def AddAnnotation(self, name, value, keep): 1400 def AddAnnotation(self, name, value, keep):
1367 self.annotations.append(_Annotation(name, value, keep)) 1401 self.annotations.append(_Annotation(name, value, keep))
@@ -1908,6 +1942,9 @@ class Project(object):
1908 # mode, we just tried sync'ing from the upstream field; it doesn't exist, thus 1942 # mode, we just tried sync'ing from the upstream field; it doesn't exist, thus
1909 # abort the optimization attempt and do a full sync. 1943 # abort the optimization attempt and do a full sync.
1910 break 1944 break
1945 elif ret < 0:
1946 # Git died with a signal, exit immediately
1947 break
1911 time.sleep(random.randint(30, 45)) 1948 time.sleep(random.randint(30, 45))
1912 1949
1913 if initial: 1950 if initial:
diff --git a/subcmds/forall.py b/subcmds/forall.py
index 88b23fbd..ebc8beca 100644
--- a/subcmds/forall.py
+++ b/subcmds/forall.py
@@ -20,6 +20,7 @@ import multiprocessing
20import re 20import re
21import os 21import os
22import select 22import select
23import signal
23import sys 24import sys
24import subprocess 25import subprocess
25 26
@@ -207,14 +208,12 @@ without iterating through the remaining projects.
207 208
208 os.environ['REPO_COUNT'] = str(len(projects)) 209 os.environ['REPO_COUNT'] = str(len(projects))
209 210
210 pool = multiprocessing.Pool(opt.jobs) 211 pool = multiprocessing.Pool(opt.jobs, InitWorker)
211 try: 212 try:
212 config = self.manifest.manifestProject.config 213 config = self.manifest.manifestProject.config
213 results_it = pool.imap( 214 results_it = pool.imap(
214 DoWorkWrapper, 215 DoWorkWrapper,
215 ([mirror, opt, cmd, shell, cnt, config, self._SerializeProject(p)] 216 self.ProjectArgs(projects, mirror, opt, cmd, shell, config))
216 for cnt, p in enumerate(projects))
217 )
218 pool.close() 217 pool.close()
219 for r in results_it: 218 for r in results_it:
220 rc = rc or r 219 rc = rc or r
@@ -236,12 +235,28 @@ without iterating through the remaining projects.
236 if rc != 0: 235 if rc != 0:
237 sys.exit(rc) 236 sys.exit(rc)
238 237
238 def ProjectArgs(self, projects, mirror, opt, cmd, shell, config):
239 for cnt, p in enumerate(projects):
240 try:
241 project = self._SerializeProject(p)
242 except Exception as e:
243 print('Project list error: %r' % e,
244 file=sys.stderr)
245 return
246 except KeyboardInterrupt:
247 print('Project list interrupted',
248 file=sys.stderr)
249 return
250 yield [mirror, opt, cmd, shell, cnt, config, project]
239 251
240class WorkerKeyboardInterrupt(Exception): 252class WorkerKeyboardInterrupt(Exception):
241 """ Keyboard interrupt exception for worker processes. """ 253 """ Keyboard interrupt exception for worker processes. """
242 pass 254 pass
243 255
244 256
257def InitWorker():
258 signal.signal(signal.SIGINT, signal.SIG_IGN)
259
245def DoWorkWrapper(args): 260def DoWorkWrapper(args):
246 """ A wrapper around the DoWork() method. 261 """ A wrapper around the DoWork() method.
247 262
@@ -263,7 +278,9 @@ def DoWork(project, mirror, opt, cmd, shell, cnt, config):
263 def setenv(name, val): 278 def setenv(name, val):
264 if val is None: 279 if val is None:
265 val = '' 280 val = ''
266 env[name] = val.encode() 281 if hasattr(val, 'encode'):
282 val = val.encode()
283 env[name] = val
267 284
268 setenv('REPO_PROJECT', project['name']) 285 setenv('REPO_PROJECT', project['name'])
269 setenv('REPO_PATH', project['relpath']) 286 setenv('REPO_PATH', project['relpath'])
diff --git a/subcmds/init.py b/subcmds/init.py
index b73de71c..dbb6ddda 100644
--- a/subcmds/init.py
+++ b/subcmds/init.py
@@ -27,7 +27,7 @@ else:
27 import imp 27 import imp
28 import urlparse 28 import urlparse
29 urllib = imp.new_module('urllib') 29 urllib = imp.new_module('urllib')
30 urllib.parse = urlparse.urlparse 30 urllib.parse = urlparse
31 31
32from color import Coloring 32from color import Coloring
33from command import InteractiveCommand, MirrorSafeCommand 33from command import InteractiveCommand, MirrorSafeCommand
@@ -153,7 +153,7 @@ to update the working directory files.
153 # server where this git is located, so let's save that here. 153 # server where this git is located, so let's save that here.
154 mirrored_manifest_git = None 154 mirrored_manifest_git = None
155 if opt.reference: 155 if opt.reference:
156 manifest_git_path = urllib.parse(opt.manifest_url).path[1:] 156 manifest_git_path = urllib.parse.urlparse(opt.manifest_url).path[1:]
157 mirrored_manifest_git = os.path.join(opt.reference, manifest_git_path) 157 mirrored_manifest_git = os.path.join(opt.reference, manifest_git_path)
158 if not mirrored_manifest_git.endswith(".git"): 158 if not mirrored_manifest_git.endswith(".git"):
159 mirrored_manifest_git += ".git" 159 mirrored_manifest_git += ".git"