From df699bf5bdc1d528757d4d8a710a8fd491c15f62 Mon Sep 17 00:00:00 2001 From: Jerry Zhang Date: Sat, 28 Dec 2024 15:41:23 -0500 Subject: [PATCH] git: Don't swallow all push output In certain situations "git push" will need to auth interactively. However we don't show the user any output from git push because of github's automatic "create a pr test" that is generally not what we want since revup handles pr creation. This does make these auth situations confusing though. Instead of hiding all output, default to showing output except for lines prefixed with "remote:" which will get hidden. Topic: outpush3 Closes: #33 Reviewers: aaron, brian-k --- revup/shell.py | 19 ++++++++++++++----- revup/topic_stack.py | 10 +++++++++- 2 files changed, 23 insertions(+), 6 deletions(-) diff --git a/revup/shell.py b/revup/shell.py index 654bdfe..63df56f 100644 --- a/revup/shell.py +++ b/revup/shell.py @@ -8,6 +8,7 @@ from typing import ( IO, Any, + Callable, Coroutine, Dict, List, @@ -45,7 +46,10 @@ def merge_dicts(x: Dict[K, V], y: Dict[K, V]) -> Dict[K, V]: async def process_stream( - proc_stream: Optional[asyncio.StreamReader], setting: _HANDLE, default_stream: IO[str] + proc_stream: Optional[asyncio.StreamReader], + setting: _HANDLE, + default_stream: IO[str], + transform: Optional[Callable[[bytes], bytes]], ) -> bytes: # The things we do for logging... # @@ -68,14 +72,16 @@ async def process_stream( line = await proc_stream.readexactly(e.consumed) except asyncio.IncompleteReadError as e: line = e.partial + if transform: + line = transform(line) if not line: - if isinstance(setting, int) and setting != -1: + if isinstance(setting, int) and setting not in (-1, subprocess.PIPE, subprocess.STDOUT): os.close(setting) break if setting == subprocess.PIPE: output.append(line) elif setting == subprocess.STDOUT: - sys.stdout.buffer.write(line) + logging.info(line.decode("utf-8").strip()) elif isinstance(setting, int) and setting != -1: os.write(setting, line) elif setting is None: @@ -137,6 +143,7 @@ async def create_sh_task( input_str: Optional[str] = None, stdin: _HANDLE = None, stdout: _HANDLE = subprocess.PIPE, + output_transform: Optional[Callable[[bytes], bytes]] = None, ) -> Tuple[ Coroutine[Any, Any, None], Coroutine[Any, Any, bytes], @@ -163,8 +170,8 @@ async def create_sh_task( return ( feed_input(ret.stdin, input_str), - process_stream(ret.stdout, stdout, sys.stdout), - process_stream(ret.stderr, stderr, sys.stderr), + process_stream(ret.stdout, stdout, sys.stdout, output_transform), + process_stream(ret.stderr, stderr, sys.stderr, output_transform), ret.wait(), ) @@ -179,6 +186,7 @@ async def sh( stdout: _HANDLE = subprocess.PIPE, raiseonerror: bool = True, quiet: bool = False, + output_transform: Optional[Callable[[bytes], bytes]] = None, ) -> Tuple[int, str]: """ Run a command specified by args, and return string representing @@ -210,6 +218,7 @@ async def sh( input_str=input_str, stdin=stdin, stdout=stdout, + output_transform=output_transform, ) _, out, err, ret = await asyncio.gather(*tasks) diff --git a/revup/topic_stack.py b/revup/topic_stack.py index 6b04295..9491819 100644 --- a/revup/topic_stack.py +++ b/revup/topic_stack.py @@ -1029,7 +1029,15 @@ async def push_git_refs(self, uploader: str, create_local_branches: bool) -> Non self.git_ctx.remote_name, *push_targets, ] - await self.git_ctx.git(*push_args, stderr=subprocess.PIPE) + await self.git_ctx.git( + *push_args, + stdout=subprocess.STDOUT, + stderr=subprocess.STDOUT, + # Hide the remote output that says "Create a pull request for '' on GitHub" + output_transform=lambda l: ( + b"" if (l.startswith(b"remote: ") and self.git_ctx.sh.quiet) else l + ), + ) async def query_github(self) -> None: """