summaryrefslogtreecommitdiffstats
path: root/subcmds/sync.py
diff options
context:
space:
mode:
Diffstat (limited to 'subcmds/sync.py')
-rw-r--r--subcmds/sync.py67
1 files changed, 50 insertions, 17 deletions
diff --git a/subcmds/sync.py b/subcmds/sync.py
index e9d52b7b..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
@@ -253,7 +272,7 @@ later is required to fix a server side protocol bug.
253 quiet=opt.quiet, 272 quiet=opt.quiet,
254 current_branch_only=opt.current_branch_only, 273 current_branch_only=opt.current_branch_only,
255 clone_bundle=not opt.no_clone_bundle, 274 clone_bundle=not opt.no_clone_bundle,
256 no_tags=opt.no_tags) 275 no_tags=opt.no_tags, archive=self.manifest.IsArchive)
257 self._fetch_times.Set(project, time.time() - start) 276 self._fetch_times.Set(project, time.time() - start)
258 277
259 # Lock around all the rest of the code, since printing, updating a set 278 # Lock around all the rest of the code, since printing, updating a set
@@ -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))
@@ -294,7 +315,8 @@ later is required to fix a server side protocol bug.
294 quiet=opt.quiet, 315 quiet=opt.quiet,
295 current_branch_only=opt.current_branch_only, 316 current_branch_only=opt.current_branch_only,
296 clone_bundle=not opt.no_clone_bundle, 317 clone_bundle=not opt.no_clone_bundle,
297 no_tags=opt.no_tags): 318 no_tags=opt.no_tags,
319 archive=self.manifest.IsArchive):
298 fetched.add(project.gitdir) 320 fetched.add(project.gitdir)
299 else: 321 else:
300 print('error: Cannot fetch %s' % project.name, file=sys.stderr) 322 print('error: Cannot fetch %s' % project.name, file=sys.stderr)
@@ -303,20 +325,24 @@ later is required to fix a server side protocol bug.
303 else: 325 else:
304 sys.exit(1) 326 sys.exit(1)
305 else: 327 else:
328 objdir_project_map = dict()
329 for project in projects:
330 objdir_project_map.setdefault(project.objdir, []).append(project)
331
306 threads = set() 332 threads = set()
307 lock = _threading.Lock() 333 lock = _threading.Lock()
308 sem = _threading.Semaphore(self.jobs) 334 sem = _threading.Semaphore(self.jobs)
309 err_event = _threading.Event() 335 err_event = _threading.Event()
310 for project in projects: 336 for project_list in objdir_project_map.values():
311 # Check for any errors before starting any new threads. 337 # Check for any errors before starting any new threads.
312 # ...we'll let existing threads finish, though. 338 # ...we'll let existing threads finish, though.
313 if err_event.isSet(): 339 if err_event.isSet():
314 break 340 break
315 341
316 sem.acquire() 342 sem.acquire()
317 t = _threading.Thread(target = self._FetchHelper, 343 t = _threading.Thread(target = self._FetchProjectList,
318 args = (opt, 344 args = (opt,
319 project, 345 project_list,
320 lock, 346 lock,
321 fetched, 347 fetched,
322 pm, 348 pm,
@@ -338,10 +364,16 @@ later is required to fix a server side protocol bug.
338 pm.end() 364 pm.end()
339 self._fetch_times.Save() 365 self._fetch_times.Save()
340 366
341 self._GCProjects(projects) 367 if not self.manifest.IsArchive:
368 self._GCProjects(projects)
369
342 return fetched 370 return fetched
343 371
344 def _GCProjects(self, projects): 372 def _GCProjects(self, projects):
373 gitdirs = {}
374 for project in projects:
375 gitdirs[project.gitdir] = project.bare_git
376
345 has_dash_c = git_require((1, 7, 2)) 377 has_dash_c = git_require((1, 7, 2))
346 if multiprocessing and has_dash_c: 378 if multiprocessing and has_dash_c:
347 cpu_count = multiprocessing.cpu_count() 379 cpu_count = multiprocessing.cpu_count()
@@ -350,8 +382,8 @@ later is required to fix a server side protocol bug.
350 jobs = min(self.jobs, cpu_count) 382 jobs = min(self.jobs, cpu_count)
351 383
352 if jobs < 2: 384 if jobs < 2:
353 for project in projects: 385 for bare_git in gitdirs.values():
354 project.bare_git.gc('--auto') 386 bare_git.gc('--auto')
355 return 387 return
356 388
357 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}
@@ -360,10 +392,10 @@ later is required to fix a server side protocol bug.
360 sem = _threading.Semaphore(jobs) 392 sem = _threading.Semaphore(jobs)
361 err_event = _threading.Event() 393 err_event = _threading.Event()
362 394
363 def GC(project): 395 def GC(bare_git):
364 try: 396 try:
365 try: 397 try:
366 project.bare_git.gc('--auto', config=config) 398 bare_git.gc('--auto', config=config)
367 except GitError: 399 except GitError:
368 err_event.set() 400 err_event.set()
369 except: 401 except:
@@ -372,11 +404,11 @@ later is required to fix a server side protocol bug.
372 finally: 404 finally:
373 sem.release() 405 sem.release()
374 406
375 for project in projects: 407 for bare_git in gitdirs.values():
376 if err_event.isSet(): 408 if err_event.isSet():
377 break 409 break
378 sem.acquire() 410 sem.acquire()
379 t = _threading.Thread(target=GC, args=(project,)) 411 t = _threading.Thread(target=GC, args=(bare_git,))
380 t.daemon = True 412 t.daemon = True
381 threads.add(t) 413 threads.add(t)
382 t.start() 414 t.start()
@@ -416,12 +448,13 @@ later is required to fix a server side protocol bug.
416 if path not in new_project_paths: 448 if path not in new_project_paths:
417 # 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
418 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')
419 project = Project( 452 project = Project(
420 manifest = self.manifest, 453 manifest = self.manifest,
421 name = path, 454 name = path,
422 remote = RemoteSpec('origin'), 455 remote = RemoteSpec('origin'),
423 gitdir = os.path.join(self.manifest.topdir, 456 gitdir = gitdir,
424 path, '.git'), 457 objdir = gitdir,
425 worktree = os.path.join(self.manifest.topdir, path), 458 worktree = os.path.join(self.manifest.topdir, path),
426 relpath = path, 459 relpath = path,
427 revisionExpr = 'HEAD', 460 revisionExpr = 'HEAD',
@@ -641,7 +674,7 @@ later is required to fix a server side protocol bug.
641 previously_missing_set = missing_set 674 previously_missing_set = missing_set
642 fetched.update(self._Fetch(missing, opt)) 675 fetched.update(self._Fetch(missing, opt))
643 676
644 if self.manifest.IsMirror: 677 if self.manifest.IsMirror or self.manifest.IsArchive:
645 # bail out now, we have no working tree 678 # bail out now, we have no working tree
646 return 679 return
647 680
@@ -761,7 +794,7 @@ class _FetchTimes(object):
761 def _Load(self): 794 def _Load(self):
762 if self._times is None: 795 if self._times is None:
763 try: 796 try:
764 f = open(self._path) 797 f = open(self._path, 'rb')
765 except IOError: 798 except IOError:
766 self._times = {} 799 self._times = {}
767 return self._times 800 return self._times