diff options
Diffstat (limited to 'subcmds/sync.py')
| -rw-r--r-- | subcmds/sync.py | 54 |
1 files changed, 42 insertions, 12 deletions
diff --git a/subcmds/sync.py b/subcmds/sync.py index e9d52b7b..d1a06412 100644 --- a/subcmds/sync.py +++ b/subcmds/sync.py | |||
| @@ -219,9 +219,25 @@ later is required to fix a server side protocol bug. | |||
| 219 | dest='repo_upgraded', action='store_true', | 219 | dest='repo_upgraded', action='store_true', |
| 220 | help=SUPPRESS_HELP) | 220 | help=SUPPRESS_HELP) |
| 221 | 221 | ||
| 222 | def _FetchHelper(self, opt, project, lock, fetched, pm, sem, err_event): | 222 | def _FetchProjectList(self, opt, projects, *args): |
| 223 | """Main function of the fetch threads when jobs are > 1. | 223 | """Main function of the fetch threads when jobs are > 1. |
| 224 | 224 | ||
| 225 | Delegates most of the work to _FetchHelper. | ||
| 226 | |||
| 227 | Args: | ||
| 228 | opt: Program options returned from optparse. See _Options(). | ||
| 229 | projects: Projects to fetch. | ||
| 230 | *args: Remaining arguments to pass to _FetchHelper. See the | ||
| 231 | _FetchHelper docstring for details. | ||
| 232 | """ | ||
| 233 | for project in projects: | ||
| 234 | success = self._FetchHelper(opt, project, *args) | ||
| 235 | if not success and not opt.force_broken: | ||
| 236 | break | ||
| 237 | |||
| 238 | def _FetchHelper(self, opt, project, lock, fetched, pm, sem, err_event): | ||
| 239 | """Fetch git objects for a single project. | ||
| 240 | |||
| 225 | Args: | 241 | Args: |
| 226 | opt: Program options returned from optparse. See _Options(). | 242 | opt: Program options returned from optparse. See _Options(). |
| 227 | project: Project object for the project to fetch. | 243 | project: Project object for the project to fetch. |
| @@ -235,6 +251,9 @@ later is required to fix a server side protocol bug. | |||
| 235 | can be started up. | 251 | can be started up. |
| 236 | err_event: We'll set this event in the case of an error (after printing | 252 | err_event: We'll set this event in the case of an error (after printing |
| 237 | out info about the error). | 253 | out info about the error). |
| 254 | |||
| 255 | Returns: | ||
| 256 | Whether the fetch was successful. | ||
| 238 | """ | 257 | """ |
| 239 | # We'll set to true once we've locked the lock. | 258 | # We'll set to true once we've locked the lock. |
| 240 | did_lock = False | 259 | did_lock = False |
| @@ -281,6 +300,8 @@ later is required to fix a server side protocol bug. | |||
| 281 | lock.release() | 300 | lock.release() |
| 282 | sem.release() | 301 | sem.release() |
| 283 | 302 | ||
| 303 | return success | ||
| 304 | |||
| 284 | def _Fetch(self, projects, opt): | 305 | def _Fetch(self, projects, opt): |
| 285 | fetched = set() | 306 | fetched = set() |
| 286 | pm = Progress('Fetching projects', len(projects)) | 307 | pm = Progress('Fetching projects', len(projects)) |
| @@ -303,20 +324,24 @@ later is required to fix a server side protocol bug. | |||
| 303 | else: | 324 | else: |
| 304 | sys.exit(1) | 325 | sys.exit(1) |
| 305 | else: | 326 | else: |
| 327 | objdir_project_map = dict() | ||
| 328 | for project in projects: | ||
| 329 | objdir_project_map.setdefault(project.objdir, []).append(project) | ||
| 330 | |||
| 306 | threads = set() | 331 | threads = set() |
| 307 | lock = _threading.Lock() | 332 | lock = _threading.Lock() |
| 308 | sem = _threading.Semaphore(self.jobs) | 333 | sem = _threading.Semaphore(self.jobs) |
| 309 | err_event = _threading.Event() | 334 | err_event = _threading.Event() |
| 310 | for project in projects: | 335 | for project_list in objdir_project_map.values(): |
| 311 | # Check for any errors before starting any new threads. | 336 | # Check for any errors before starting any new threads. |
| 312 | # ...we'll let existing threads finish, though. | 337 | # ...we'll let existing threads finish, though. |
| 313 | if err_event.isSet(): | 338 | if err_event.isSet(): |
| 314 | break | 339 | break |
| 315 | 340 | ||
| 316 | sem.acquire() | 341 | sem.acquire() |
| 317 | t = _threading.Thread(target = self._FetchHelper, | 342 | t = _threading.Thread(target = self._FetchProjectList, |
| 318 | args = (opt, | 343 | args = (opt, |
| 319 | project, | 344 | project_list, |
| 320 | lock, | 345 | lock, |
| 321 | fetched, | 346 | fetched, |
| 322 | pm, | 347 | pm, |
| @@ -342,6 +367,10 @@ later is required to fix a server side protocol bug. | |||
| 342 | return fetched | 367 | return fetched |
| 343 | 368 | ||
| 344 | def _GCProjects(self, projects): | 369 | def _GCProjects(self, projects): |
| 370 | gitdirs = {} | ||
| 371 | for project in projects: | ||
| 372 | gitdirs[project.gitdir] = project.bare_git | ||
| 373 | |||
| 345 | has_dash_c = git_require((1, 7, 2)) | 374 | has_dash_c = git_require((1, 7, 2)) |
| 346 | if multiprocessing and has_dash_c: | 375 | if multiprocessing and has_dash_c: |
| 347 | cpu_count = multiprocessing.cpu_count() | 376 | cpu_count = multiprocessing.cpu_count() |
| @@ -350,8 +379,8 @@ later is required to fix a server side protocol bug. | |||
| 350 | jobs = min(self.jobs, cpu_count) | 379 | jobs = min(self.jobs, cpu_count) |
| 351 | 380 | ||
| 352 | if jobs < 2: | 381 | if jobs < 2: |
| 353 | for project in projects: | 382 | for bare_git in gitdirs.values(): |
| 354 | project.bare_git.gc('--auto') | 383 | bare_git.gc('--auto') |
| 355 | return | 384 | return |
| 356 | 385 | ||
| 357 | config = {'pack.threads': cpu_count / jobs if cpu_count > jobs else 1} | 386 | config = {'pack.threads': cpu_count / jobs if cpu_count > jobs else 1} |
| @@ -360,10 +389,10 @@ later is required to fix a server side protocol bug. | |||
| 360 | sem = _threading.Semaphore(jobs) | 389 | sem = _threading.Semaphore(jobs) |
| 361 | err_event = _threading.Event() | 390 | err_event = _threading.Event() |
| 362 | 391 | ||
| 363 | def GC(project): | 392 | def GC(bare_git): |
| 364 | try: | 393 | try: |
| 365 | try: | 394 | try: |
| 366 | project.bare_git.gc('--auto', config=config) | 395 | bare_git.gc('--auto', config=config) |
| 367 | except GitError: | 396 | except GitError: |
| 368 | err_event.set() | 397 | err_event.set() |
| 369 | except: | 398 | except: |
| @@ -372,11 +401,11 @@ later is required to fix a server side protocol bug. | |||
| 372 | finally: | 401 | finally: |
| 373 | sem.release() | 402 | sem.release() |
| 374 | 403 | ||
| 375 | for project in projects: | 404 | for bare_git in gitdirs.values(): |
| 376 | if err_event.isSet(): | 405 | if err_event.isSet(): |
| 377 | break | 406 | break |
| 378 | sem.acquire() | 407 | sem.acquire() |
| 379 | t = _threading.Thread(target=GC, args=(project,)) | 408 | t = _threading.Thread(target=GC, args=(bare_git,)) |
| 380 | t.daemon = True | 409 | t.daemon = True |
| 381 | threads.add(t) | 410 | threads.add(t) |
| 382 | t.start() | 411 | t.start() |
| @@ -416,12 +445,13 @@ later is required to fix a server side protocol bug. | |||
| 416 | if path not in new_project_paths: | 445 | if path not in new_project_paths: |
| 417 | # If the path has already been deleted, we don't need to do it | 446 | # If the path has already been deleted, we don't need to do it |
| 418 | if os.path.exists(self.manifest.topdir + '/' + path): | 447 | if os.path.exists(self.manifest.topdir + '/' + path): |
| 448 | gitdir = os.path.join(self.manifest.topdir, path, '.git') | ||
| 419 | project = Project( | 449 | project = Project( |
| 420 | manifest = self.manifest, | 450 | manifest = self.manifest, |
| 421 | name = path, | 451 | name = path, |
| 422 | remote = RemoteSpec('origin'), | 452 | remote = RemoteSpec('origin'), |
| 423 | gitdir = os.path.join(self.manifest.topdir, | 453 | gitdir = gitdir, |
| 424 | path, '.git'), | 454 | objdir = gitdir, |
| 425 | worktree = os.path.join(self.manifest.topdir, path), | 455 | worktree = os.path.join(self.manifest.topdir, path), |
| 426 | relpath = path, | 456 | relpath = path, |
| 427 | revisionExpr = 'HEAD', | 457 | revisionExpr = 'HEAD', |
