summaryrefslogtreecommitdiffstats
path: root/subcmds/sync.py
diff options
context:
space:
mode:
Diffstat (limited to 'subcmds/sync.py')
-rw-r--r--subcmds/sync.py54
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',