Skip to content

Make check50 and submit50 works with git passphrase #84

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 29 additions & 2 deletions lib50/_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import threading
import time
import functools
from getpass import getpass

import jellyfish
import pexpect
Expand Down Expand Up @@ -844,6 +845,7 @@ class ProgressBar:
"""
DISABLED = False
TICKS_PER_SECOND = 2
GLOBAL_STOP_SIGNAL = False

def __init__(self, message, output_stream=None):
"""
Expand All @@ -853,6 +855,8 @@ def __init__(self, message, output_stream=None):
:type output_stream: a stream or file-like object
"""

ProgressBar.GLOBAL_STOP_SIGNAL = False

if output_stream is None:
output_stream = sys.stderr

Expand All @@ -871,6 +875,9 @@ def __enter__(self):
def progress_runner():
self._print(f"{self._message}...", end="", flush=True)
while self._progressing:
if ProgressBar.GLOBAL_STOP_SIGNAL:
ProgressBar.GLOBAL_STOP_SIGNAL = False
break
self._print(".", end="", flush=True)
time.sleep(1 / ProgressBar.TICKS_PER_SECOND if ProgressBar.TICKS_PER_SECOND else 0)
self._print()
Expand Down Expand Up @@ -934,17 +941,37 @@ def spawn(command, quiet=False, timeout=None):


def run(command, quiet=False, timeout=None):
"""Run a command, returns command output."""
"""Run a command. Automatically handles SSH passphrase prompts."""
try:
with spawn(command, quiet, timeout) as child:
command_output = child.read().strip().replace("\r\n", "\n")
# Try to catch passphrase prompt automatically
try:
child.expect(r"^Enter passphrase .*:")
ProgressBar.GLOBAL_STOP_SIGNAL = True
time.sleep(1)
passphrase = getpass("🔐 SSH Key Passphrase: ")
child.sendline(passphrase)
except pexpect.exceptions.EOF:
pass # No prompt, continue

# Ensure full output is captured, including final line with no trailing newline
# `expect(EOF)` may miss the last line if it doesn't end with a newline (e.g., git rev-parse)
command_output = child.before + child.read()
command_output = command_output.strip().replace("\r\n", "\n")

# If a fatal error appears in output, print it and exit
if any(line.startswith("fatal:") for line in command_output.splitlines()):
print(termcolor.colored(command_output, "red", attrs=["bold"]))
exit(1)

except pexpect.TIMEOUT:
logger.info(f"command {command} timed out")
raise TimeoutError(timeout)

return command_output



def _glob(pattern, skip_dirs=False, limit=DEFAULT_FILE_LIMIT):
"""
Glob pattern, expand directories, return iterator over matching files.
Expand Down