History

feat: add a `gix editor` command

<!-- agent --> Provide a small plumbing command that opens zero or more paths with `Repository::editor()`'s Git-compatible selection. Prepare editor definitions with command-aware argument splitting so PATH-resolved programs run directly while actual shell syntax still uses the shell, reject explicitly empty settings, and honor ':' as the no-op editor.

Byron committed 2 months ago

Commit d9306531 parent b76cc285 files · +60 −2Browse files

Unified · Split

5 files
  1. gitoxide-core/src/repository/editor.rs +21 −0
  2. gitoxide-core/src/repository/mod.rs +4 −2
  3. src/plumbing/main.rs +1 −0
  4. src/plumbing/options/mod.rs +5 −0
  5. tests/journey/gix.sh +29 −0
gitoxide-core/src/repository/editor.rs+21−0
@@ -0,0 +1,21 @@
1+use std::path::PathBuf;
2+
3+use anyhow::{Context, Result, bail};
4+
5+pub fn function(repo: gix::Repository, paths: Vec<PathBuf>) -> Result<()> {
6+ let editor = repo
7+ .editor_command()
8+ .context("Could not prepare editor")?
9+ .context("No editor is configured and the terminal is not capable of running one")?;
10+ let editor_display = editor.command.to_string_lossy().into_owned();
11+ let status = editor
12+ .args(paths)
13+ .spawn()
14+ .with_context(|| format!("Could not launch editor {editor_display}"))?
15+ .wait()
16+ .with_context(|| format!("Could not wait for editor {editor_display}"))?;
17+ if !status.success() {
18+ bail!("Editor {editor_display} exited with {status}");
19+ }
20+ Ok(())
21+}
gitoxide-core/src/repository/mod.rs+4−2
@@ -17,11 +17,13 @@ pub use credential::function as credential; · 16 unmodified lines
1717 pub mod attributes;
1818 #[cfg(feature = "clean")]
1919 pub mod clean;
20+#[cfg(feature = "clean")]
21+pub use clean::function::clean;
2022 pub mod diff;
2123 pub mod dirty;
2224 pub mod dirwalk;
23−#[cfg(feature = "clean")]
24−pub use clean::function::clean;
25+mod editor;
26+pub use editor::function as editor;
2527 #[cfg(feature = "blocking-client")]
2628 pub mod clone;
2729 pub mod exclude;
src/plumbing/main.rs+1−0
@@ -168,6 +168,7 @@ pub fn main() -> Result<()> { · 167 unmodified lines
168168 None,
169169 move |_progress, out, _err| core::env(out, format),
170170 ),
171+ Subcommands::Editor { paths } => core::repository::editor(repository(Mode::Lenient)?, paths),
171172 Subcommands::Merge(merge::Platform { cmd }) => match cmd {
172173 merge::SubCommands::File {
173174 resolve_with,
src/plumbing/options/mod.rs+5−0
@@ -161,6 +161,11 @@ pub enum Subcommands { · 160 unmodified lines
161161 Merge(merge::Platform),
162162 /// Print paths relevant to the Git installation.
163163 Env,
164+ /// Open paths in the editor selected by Git's precedence rules.
165+ Editor {
166+ /// Paths to open, or none to start the editor without a file.
167+ paths: Vec<PathBuf>,
168+ },
164169 Diff(diff::Platform),
165170 Log(log::Platform),
166171 /// Interactively browse commits and their graph.
tests/journey/gix.sh+29−0
@@ -54,6 +54,35 @@ title "gix (with repository)" · 53 unmodified lines
5454 (with "a git repository"
5555 snapshot="$snapshot/repository"
5656
57+ title "gix editor"
58+ (sandbox
59+ git init -q
60+ touch first second
61+ printf '%s\n' '#!/bin/sh' \
62+ 'test "$#" = 2 && test "$1" = first && test "$2" = second' >check-editor
63+ cp check-editor "check editor"
64+ chmod +x "check editor"
65+
66+ it "launches the configured editor with all paths" && {
67+ expect_run $SUCCESSFULLY "$exe_plumbing" --no-verbose -c "core.editor=sh check-editor" editor first second
68+ }
69+ it "preserves shell execution for editor command strings" && {
70+ expect_run $SUCCESSFULLY env GIT_EDITOR='exec true' "$exe_plumbing" --no-verbose editor first second
71+ }
72+ it "launches an existing editor path with spaces directly" && {
73+ expect_run $SUCCESSFULLY env GIT_EDITOR="$PWD/check editor" "$exe_plumbing" --no-verbose editor first second
74+ }
75+ it "launches a trusted relative editor path from the repository directly" && {
76+ expect_run $SUCCESSFULLY env GIT_EDITOR='./check editor' "$exe_plumbing" --no-verbose editor first second
77+ }
78+ it "rejects an explicitly empty editor" && {
79+ expect_run $WITH_FAILURE env GIT_EDITOR= "$exe_plumbing" --no-verbose editor
80+ }
81+ it "honors the whitespace-padded no-op editor" && {
82+ expect_run $SUCCESSFULLY env 'GIT_EDITOR=: ' "$exe_plumbing" --no-verbose editor first second
83+ }
84+ )
85+
5786 title "gix index"
5887 (with "the 'entries' sub-command"
5988 snapshot="$snapshot/index/entries"

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t