diff options
| -rw-r--r-- | error.py | 4 | ||||
| -rw-r--r-- | git_command.py | 7 | ||||
| -rw-r--r-- | git_config.py | 2 | ||||
| -rw-r--r-- | project.py | 65 | ||||
| -rw-r--r-- | subcmds/forall.py | 27 | ||||
| -rw-r--r-- | subcmds/init.py | 4 |
6 files changed, 84 insertions, 25 deletions
| @@ -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): |
| @@ -16,6 +16,7 @@ from __future__ import print_function | |||
| 16 | import contextlib | 16 | import contextlib |
| 17 | import errno | 17 | import errno |
| 18 | import filecmp | 18 | import filecmp |
| 19 | import glob | ||
| 19 | import os | 20 | import os |
| 20 | import random | 21 | import random |
| 21 | import re | 22 | import 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 | ||
| 235 | class _LinkFile(object): | 236 | class _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 | ||
| 259 | class RemoteSpec(object): | 292 | class 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 | |||
| 20 | import re | 20 | import re |
| 21 | import os | 21 | import os |
| 22 | import select | 22 | import select |
| 23 | import signal | ||
| 23 | import sys | 24 | import sys |
| 24 | import subprocess | 25 | import 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 | ||
| 240 | class WorkerKeyboardInterrupt(Exception): | 252 | class WorkerKeyboardInterrupt(Exception): |
| 241 | """ Keyboard interrupt exception for worker processes. """ | 253 | """ Keyboard interrupt exception for worker processes. """ |
| 242 | pass | 254 | pass |
| 243 | 255 | ||
| 244 | 256 | ||
| 257 | def InitWorker(): | ||
| 258 | signal.signal(signal.SIGINT, signal.SIG_IGN) | ||
| 259 | |||
| 245 | def DoWorkWrapper(args): | 260 | def 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 | ||
| 32 | from color import Coloring | 32 | from color import Coloring |
| 33 | from command import InteractiveCommand, MirrorSafeCommand | 33 | from 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" |
