diff options
| -rw-r--r-- | git_config.py | 53 |
1 files changed, 41 insertions, 12 deletions
diff --git a/git_config.py b/git_config.py index 1382d5db..138470c5 100644 --- a/git_config.py +++ b/git_config.py | |||
| @@ -356,18 +356,21 @@ class RefSpec(object): | |||
| 356 | return s | 356 | return s |
| 357 | 357 | ||
| 358 | 358 | ||
| 359 | _ssh_cache = {} | 359 | _master_processes = [] |
| 360 | _master_keys = set() | ||
| 360 | _ssh_master = True | 361 | _ssh_master = True |
| 361 | 362 | ||
| 362 | def _open_ssh(host, port=None): | 363 | def _open_ssh(host, port=None): |
| 363 | global _ssh_master | 364 | global _ssh_master |
| 364 | 365 | ||
| 366 | # Check to see whether we already think that the master is running; if we | ||
| 367 | # think it's already running, return right away. | ||
| 365 | if port is not None: | 368 | if port is not None: |
| 366 | key = '%s:%s' % (host, port) | 369 | key = '%s:%s' % (host, port) |
| 367 | else: | 370 | else: |
| 368 | key = host | 371 | key = host |
| 369 | 372 | ||
| 370 | if key in _ssh_cache: | 373 | if key in _master_keys: |
| 371 | return True | 374 | return True |
| 372 | 375 | ||
| 373 | if not _ssh_master \ | 376 | if not _ssh_master \ |
| @@ -377,15 +380,39 @@ def _open_ssh(host, port=None): | |||
| 377 | # | 380 | # |
| 378 | return False | 381 | return False |
| 379 | 382 | ||
| 380 | command = ['ssh', | 383 | # We will make two calls to ssh; this is the common part of both calls. |
| 381 | '-o','ControlPath %s' % ssh_sock(), | 384 | command_base = ['ssh', |
| 382 | '-M', | 385 | '-o','ControlPath %s' % ssh_sock(), |
| 383 | '-N', | 386 | host] |
| 384 | host] | ||
| 385 | |||
| 386 | if port is not None: | 387 | if port is not None: |
| 387 | command[3:3] = ['-p',str(port)] | 388 | command_base[1:1] = ['-p',str(port)] |
| 388 | 389 | ||
| 390 | # Since the key wasn't in _master_keys, we think that master isn't running. | ||
| 391 | # ...but before actually starting a master, we'll double-check. This can | ||
| 392 | # be important because we can't tell that that 'git@myhost.com' is the same | ||
| 393 | # as 'myhost.com' where "User git" is setup in the user's ~/.ssh/config file. | ||
| 394 | check_command = command_base + ['-O','check'] | ||
| 395 | try: | ||
| 396 | Trace(': %s', ' '.join(check_command)) | ||
| 397 | check_process = subprocess.Popen(check_command, | ||
| 398 | stdout=subprocess.PIPE, | ||
| 399 | stderr=subprocess.PIPE) | ||
| 400 | check_process.communicate() # read output, but ignore it... | ||
| 401 | isnt_running = check_process.wait() | ||
| 402 | |||
| 403 | if not isnt_running: | ||
| 404 | # Our double-check found that the master _was_ infact running. Add to | ||
| 405 | # the list of keys. | ||
| 406 | _master_keys.add(key) | ||
| 407 | return True | ||
| 408 | except Exception: | ||
| 409 | # Ignore excpetions. We we will fall back to the normal command and print | ||
| 410 | # to the log there. | ||
| 411 | pass | ||
| 412 | |||
| 413 | command = command_base[:1] + \ | ||
| 414 | ['-M', '-N'] + \ | ||
| 415 | command_base[1:] | ||
| 389 | try: | 416 | try: |
| 390 | Trace(': %s', ' '.join(command)) | 417 | Trace(': %s', ' '.join(command)) |
| 391 | p = subprocess.Popen(command) | 418 | p = subprocess.Popen(command) |
| @@ -396,20 +423,22 @@ def _open_ssh(host, port=None): | |||
| 396 | % (host,port, str(e)) | 423 | % (host,port, str(e)) |
| 397 | return False | 424 | return False |
| 398 | 425 | ||
| 399 | _ssh_cache[key] = p | 426 | _master_processes.append(p) |
| 427 | _master_keys.add(key) | ||
| 400 | time.sleep(1) | 428 | time.sleep(1) |
| 401 | return True | 429 | return True |
| 402 | 430 | ||
| 403 | def close_ssh(): | 431 | def close_ssh(): |
| 404 | terminate_ssh_clients() | 432 | terminate_ssh_clients() |
| 405 | 433 | ||
| 406 | for key,p in _ssh_cache.iteritems(): | 434 | for p in _master_processes: |
| 407 | try: | 435 | try: |
| 408 | os.kill(p.pid, SIGTERM) | 436 | os.kill(p.pid, SIGTERM) |
| 409 | p.wait() | 437 | p.wait() |
| 410 | except OSError: | 438 | except OSError: |
| 411 | pass | 439 | pass |
| 412 | _ssh_cache.clear() | 440 | del _master_processes[:] |
| 441 | _master_keys.clear() | ||
| 413 | 442 | ||
| 414 | d = ssh_sock(create=False) | 443 | d = ssh_sock(create=False) |
| 415 | if d: | 444 | if d: |
