aboutsummaryrefslogtreecommitdiff
path: root/modules/system-lib.el
diff options
context:
space:
mode:
authorCraig Jennings <c@cjennings.net>2026-05-10 14:17:25 -0500
committerCraig Jennings <c@cjennings.net>2026-05-10 14:17:25 -0500
commit57e558ce13fae77eed07095638a753ba75af55d4 (patch)
tree840a83d80c834efb808ebcf464715e85c89ea8b3 /modules/system-lib.el
parentf1e8f0898244bd2d834baf7541d10e5eff351d34 (diff)
downloaddotemacs-57e558ce13fae77eed07095638a753ba75af55d4.tar.gz
dotemacs-57e558ce13fae77eed07095638a753ba75af55d4.zip
refactor(system-lib): extract cj/process-output-or-error and cj/git-output-or-error from coverage-core
Phase 2.3 of utility-consolidation. `cj/--coverage-git-string' was a generic argv-based runner ("run program, return stdout, raise user-error on non-zero with status+output in the message") trapped inside coverage-core. Lift the generic shape into `cj/process-output-or-error' and add `cj/git-output-or-error' as a one-line wrapper that supplies "git" as the program. Both live in system-lib.el. Future callers I have in mind: reconcile-open-repos shell-style git calls (the high-priority data-safety task), vc-config clipboard cloning, mail integrations that touch git for commit signatures. Six Normal/Boundary/Error tests cover success/no-args/non-zero-exit for the generic runner, the user-error message content (program name, exit status, trimmed output), and the git wrapper's program argument routing. Migrate coverage-core's `cj/--coverage-git-merge-base' and `cj/--coverage-git-diff' to call the new git wrapper. Drop the local `cj/--coverage-git-string' definition. Add `(require \='system-lib)' to coverage-core.el per the Phase 2 exit criterion.
Diffstat (limited to 'modules/system-lib.el')
-rw-r--r--modules/system-lib.el26
1 files changed, 26 insertions, 0 deletions
diff --git a/modules/system-lib.el b/modules/system-lib.el
index dc1f8316..3ccec06b 100644
--- a/modules/system-lib.el
+++ b/modules/system-lib.el
@@ -54,6 +54,32 @@ interpolate."
argument
(shell-quote-argument argument)))
+(defun cj/process-output-or-error (program &rest args)
+ "Run PROGRAM with ARGS via `process-file' and return stdout, or signal error.
+
+On zero exit, returns the program's stdout as a string (including any
+trailing newline -- callers that need a trimmed value should call
+`string-trim' themselves). On non-zero exit, signals `user-error' with
+a message naming the program, the exit status, and the (trimmed) output
+so a user inspecting *Messages* can see what went wrong."
+ (with-temp-buffer
+ (let ((status (apply #'process-file program nil (current-buffer) nil args))
+ (output (buffer-string)))
+ (unless (zerop status)
+ (user-error "%s %s failed with status %s: %s"
+ program
+ (string-join args " ")
+ status
+ (string-trim output)))
+ output)))
+
+(defun cj/git-output-or-error (&rest args)
+ "Run git with ARGS and return stdout, or signal `user-error' on failure.
+
+Thin wrapper around `cj/process-output-or-error' with `git' as the
+program."
+ (apply #'cj/process-output-or-error "git" args))
+
(defun cj/log-silently (format-string &rest args)
"Append formatted message (FORMAT-STRING with ARGS) to *Messages* buffer.
This does so without echoing in the minibuffer."