diff options
Diffstat (limited to 'git_config.py')
-rw-r--r-- | git_config.py | 67 |
1 files changed, 52 insertions, 15 deletions
diff --git a/git_config.py b/git_config.py index 4a42c047..286e89ca 100644 --- a/git_config.py +++ b/git_config.py | |||
@@ -25,7 +25,10 @@ from signal import SIGTERM | |||
25 | from urllib2 import urlopen, HTTPError | 25 | from urllib2 import urlopen, HTTPError |
26 | from error import GitError, UploadError | 26 | from error import GitError, UploadError |
27 | from trace import Trace | 27 | from trace import Trace |
28 | from git_command import GitCommand, _ssh_sock | 28 | |
29 | from git_command import GitCommand | ||
30 | from git_command import ssh_sock | ||
31 | from git_command import terminate_ssh_clients | ||
29 | 32 | ||
30 | R_HEADS = 'refs/heads/' | 33 | R_HEADS = 'refs/heads/' |
31 | R_TAGS = 'refs/tags/' | 34 | R_TAGS = 'refs/tags/' |
@@ -365,18 +368,21 @@ class RefSpec(object): | |||
365 | return s | 368 | return s |
366 | 369 | ||
367 | 370 | ||
368 | _ssh_cache = {} | 371 | _master_processes = [] |
372 | _master_keys = set() | ||
369 | _ssh_master = True | 373 | _ssh_master = True |
370 | 374 | ||
371 | def _open_ssh(host, port=None): | 375 | def _open_ssh(host, port=None): |
372 | global _ssh_master | 376 | global _ssh_master |
373 | 377 | ||
378 | # Check to see whether we already think that the master is running; if we | ||
379 | # think it's already running, return right away. | ||
374 | if port is not None: | 380 | if port is not None: |
375 | key = '%s:%s' % (host, port) | 381 | key = '%s:%s' % (host, port) |
376 | else: | 382 | else: |
377 | key = host | 383 | key = host |
378 | 384 | ||
379 | if key in _ssh_cache: | 385 | if key in _master_keys: |
380 | return True | 386 | return True |
381 | 387 | ||
382 | if not _ssh_master \ | 388 | if not _ssh_master \ |
@@ -386,15 +392,39 @@ def _open_ssh(host, port=None): | |||
386 | # | 392 | # |
387 | return False | 393 | return False |
388 | 394 | ||
389 | command = ['ssh', | 395 | # We will make two calls to ssh; this is the common part of both calls. |
390 | '-o','ControlPath %s' % _ssh_sock(), | 396 | command_base = ['ssh', |
391 | '-M', | 397 | '-o','ControlPath %s' % ssh_sock(), |
392 | '-N', | 398 | host] |
393 | host] | ||
394 | |||
395 | if port is not None: | 399 | if port is not None: |
396 | command[3:3] = ['-p',str(port)] | 400 | command_base[1:1] = ['-p',str(port)] |
397 | 401 | ||
402 | # Since the key wasn't in _master_keys, we think that master isn't running. | ||
403 | # ...but before actually starting a master, we'll double-check. This can | ||
404 | # be important because we can't tell that that 'git@myhost.com' is the same | ||
405 | # as 'myhost.com' where "User git" is setup in the user's ~/.ssh/config file. | ||
406 | check_command = command_base + ['-O','check'] | ||
407 | try: | ||
408 | Trace(': %s', ' '.join(check_command)) | ||
409 | check_process = subprocess.Popen(check_command, | ||
410 | stdout=subprocess.PIPE, | ||
411 | stderr=subprocess.PIPE) | ||
412 | check_process.communicate() # read output, but ignore it... | ||
413 | isnt_running = check_process.wait() | ||
414 | |||
415 | if not isnt_running: | ||
416 | # Our double-check found that the master _was_ infact running. Add to | ||
417 | # the list of keys. | ||
418 | _master_keys.add(key) | ||
419 | return True | ||
420 | except Exception: | ||
421 | # Ignore excpetions. We we will fall back to the normal command and print | ||
422 | # to the log there. | ||
423 | pass | ||
424 | |||
425 | command = command_base[:1] + \ | ||
426 | ['-M', '-N'] + \ | ||
427 | command_base[1:] | ||
398 | try: | 428 | try: |
399 | Trace(': %s', ' '.join(command)) | 429 | Trace(': %s', ' '.join(command)) |
400 | p = subprocess.Popen(command) | 430 | p = subprocess.Popen(command) |
@@ -405,20 +435,24 @@ def _open_ssh(host, port=None): | |||
405 | % (host,port, str(e)) | 435 | % (host,port, str(e)) |
406 | return False | 436 | return False |
407 | 437 | ||
408 | _ssh_cache[key] = p | 438 | _master_processes.append(p) |
439 | _master_keys.add(key) | ||
409 | time.sleep(1) | 440 | time.sleep(1) |
410 | return True | 441 | return True |
411 | 442 | ||
412 | def close_ssh(): | 443 | def close_ssh(): |
413 | for key,p in _ssh_cache.iteritems(): | 444 | terminate_ssh_clients() |
445 | |||
446 | for p in _master_processes: | ||
414 | try: | 447 | try: |
415 | os.kill(p.pid, SIGTERM) | 448 | os.kill(p.pid, SIGTERM) |
416 | p.wait() | 449 | p.wait() |
417 | except OSError: | 450 | except OSError: |
418 | pass | 451 | pass |
419 | _ssh_cache.clear() | 452 | del _master_processes[:] |
453 | _master_keys.clear() | ||
420 | 454 | ||
421 | d = _ssh_sock(create=False) | 455 | d = ssh_sock(create=False) |
422 | if d: | 456 | if d: |
423 | try: | 457 | try: |
424 | os.rmdir(os.path.dirname(d)) | 458 | os.rmdir(os.path.dirname(d)) |
@@ -540,8 +574,11 @@ class Remote(object): | |||
540 | def SshReviewUrl(self, userEmail): | 574 | def SshReviewUrl(self, userEmail): |
541 | if self.ReviewProtocol != 'ssh': | 575 | if self.ReviewProtocol != 'ssh': |
542 | return None | 576 | return None |
577 | username = self._config.GetString('review.%s.username' % self.review) | ||
578 | if username is None: | ||
579 | username = userEmail.split("@")[0] | ||
543 | return 'ssh://%s@%s:%s/%s' % ( | 580 | return 'ssh://%s@%s:%s/%s' % ( |
544 | userEmail.split("@")[0], | 581 | username, |
545 | self._review_host, | 582 | self._review_host, |
546 | self._review_port, | 583 | self._review_port, |
547 | self.projectname) | 584 | self.projectname) |