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 0279ff60..5e7385db 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)) |
@@ -304,20 +325,24 @@ later is required to fix a server side protocol bug. | |||
304 | else: | 325 | else: |
305 | sys.exit(1) | 326 | sys.exit(1) |
306 | else: | 327 | else: |
328 | objdir_project_map = dict() | ||
329 | for project in projects: | ||
330 | objdir_project_map.setdefault(project.objdir, []).append(project) | ||
331 | |||
307 | threads = set() | 332 | threads = set() |
308 | lock = _threading.Lock() | 333 | lock = _threading.Lock() |
309 | sem = _threading.Semaphore(self.jobs) | 334 | sem = _threading.Semaphore(self.jobs) |
310 | err_event = _threading.Event() | 335 | err_event = _threading.Event() |
311 | for project in projects: | 336 | for project_list in objdir_project_map.values(): |
312 | # Check for any errors before starting any new threads. | 337 | # Check for any errors before starting any new threads. |
313 | # ...we'll let existing threads finish, though. | 338 | # ...we'll let existing threads finish, though. |
314 | if err_event.isSet(): | 339 | if err_event.isSet(): |
315 | break | 340 | break |
316 | 341 | ||
317 | sem.acquire() | 342 | sem.acquire() |
318 | t = _threading.Thread(target = self._FetchHelper, | 343 | t = _threading.Thread(target = self._FetchProjectList, |
319 | args = (opt, | 344 | args = (opt, |
320 | project, | 345 | project_list, |
321 | lock, | 346 | lock, |
322 | fetched, | 347 | fetched, |
323 | pm, | 348 | pm, |
@@ -345,6 +370,10 @@ later is required to fix a server side protocol bug. | |||
345 | return fetched | 370 | return fetched |
346 | 371 | ||
347 | def _GCProjects(self, projects): | 372 | def _GCProjects(self, projects): |
373 | gitdirs = {} | ||
374 | for project in projects: | ||
375 | gitdirs[project.gitdir] = project.bare_git | ||
376 | |||
348 | has_dash_c = git_require((1, 7, 2)) | 377 | has_dash_c = git_require((1, 7, 2)) |
349 | if multiprocessing and has_dash_c: | 378 | if multiprocessing and has_dash_c: |
350 | cpu_count = multiprocessing.cpu_count() | 379 | cpu_count = multiprocessing.cpu_count() |
@@ -353,8 +382,8 @@ later is required to fix a server side protocol bug. | |||
353 | jobs = min(self.jobs, cpu_count) | 382 | jobs = min(self.jobs, cpu_count) |
354 | 383 | ||
355 | if jobs < 2: | 384 | if jobs < 2: |
356 | for project in projects: | 385 | for bare_git in gitdirs.values(): |
357 | project.bare_git.gc('--auto') | 386 | bare_git.gc('--auto') |
358 | return | 387 | return |
359 | 388 | ||
360 | config = {'pack.threads': cpu_count / jobs if cpu_count > jobs else 1} | 389 | config = {'pack.threads': cpu_count / jobs if cpu_count > jobs else 1} |
@@ -363,10 +392,10 @@ later is required to fix a server side protocol bug. | |||
363 | sem = _threading.Semaphore(jobs) | 392 | sem = _threading.Semaphore(jobs) |
364 | err_event = _threading.Event() | 393 | err_event = _threading.Event() |
365 | 394 | ||
366 | def GC(project): | 395 | def GC(bare_git): |
367 | try: | 396 | try: |
368 | try: | 397 | try: |
369 | project.bare_git.gc('--auto', config=config) | 398 | bare_git.gc('--auto', config=config) |
370 | except GitError: | 399 | except GitError: |
371 | err_event.set() | 400 | err_event.set() |
372 | except: | 401 | except: |
@@ -375,11 +404,11 @@ later is required to fix a server side protocol bug. | |||
375 | finally: | 404 | finally: |
376 | sem.release() | 405 | sem.release() |
377 | 406 | ||
378 | for project in projects: | 407 | for bare_git in gitdirs.values(): |
379 | if err_event.isSet(): | 408 | if err_event.isSet(): |
380 | break | 409 | break |
381 | sem.acquire() | 410 | sem.acquire() |
382 | t = _threading.Thread(target=GC, args=(project,)) | 411 | t = _threading.Thread(target=GC, args=(bare_git,)) |
383 | t.daemon = True | 412 | t.daemon = True |
384 | threads.add(t) | 413 | threads.add(t) |
385 | t.start() | 414 | t.start() |
@@ -419,12 +448,13 @@ later is required to fix a server side protocol bug. | |||
419 | if path not in new_project_paths: | 448 | if path not in new_project_paths: |
420 | # If the path has already been deleted, we don't need to do it | 449 | # If the path has already been deleted, we don't need to do it |
421 | if os.path.exists(self.manifest.topdir + '/' + path): | 450 | if os.path.exists(self.manifest.topdir + '/' + path): |
451 | gitdir = os.path.join(self.manifest.topdir, path, '.git') | ||
422 | project = Project( | 452 | project = Project( |
423 | manifest = self.manifest, | 453 | manifest = self.manifest, |
424 | name = path, | 454 | name = path, |
425 | remote = RemoteSpec('origin'), | 455 | remote = RemoteSpec('origin'), |
426 | gitdir = os.path.join(self.manifest.topdir, | 456 | gitdir = gitdir, |
427 | path, '.git'), | 457 | objdir = gitdir, |
428 | worktree = os.path.join(self.manifest.topdir, path), | 458 | worktree = os.path.join(self.manifest.topdir, path), |
429 | relpath = path, | 459 | relpath = path, |
430 | revisionExpr = 'HEAD', | 460 | revisionExpr = 'HEAD', |