Skip to content

control credential-helpers stderr #1156

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

Merged
merged 4 commits into from
Dec 6, 2023
Merged
Show file tree
Hide file tree
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
2 changes: 1 addition & 1 deletion build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ fn main() {
.and_then(|out| parse_describe(&out.stdout))
.unwrap_or_else(|| env!("CARGO_PKG_VERSION").into());

println!("cargo:rustc-env=GITOXIDE_VERSION={version}");
println!("cargo:rustc-env=GIX_VERSION={version}");
}

fn parse_describe(input: &[u8]) -> Option<String> {
Expand Down
2 changes: 1 addition & 1 deletion examples/log.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ fn main() {
}

#[derive(Debug, clap::Parser)]
#[clap(name = "log", about = "git log example", version = option_env!("GITOXIDE_VERSION"))]
#[clap(name = "log", about = "git log example", version = option_env!("GIX_VERSION"))]
struct Args {
/// Alternative git directory to use
#[clap(name = "dir", long = "git-dir")]
Expand Down
2 changes: 1 addition & 1 deletion examples/ls-tree.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ fn main() {
}

#[derive(Debug, clap::Parser)]
#[clap(name = "ls-tree", about = "git ls-tree example", version = option_env!("GITOXIDE_VERSION"))]
#[clap(name = "ls-tree", about = "git ls-tree example", version = option_env!("GIX_VERSION"))]
#[clap(arg_required_else_help = true)]
struct Args {
/// Recurse into subtrees
Expand Down
7 changes: 7 additions & 0 deletions gix-command/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,10 @@ pub struct Context {
/// If `true`, set `GIT_ICASE_PATHSPECS` to `1`, to let patterns match case-insensitively, or `0` otherwise.
/// If `None`, the variable won't be set.
pub icase_pathspecs: Option<bool>,
/// If `true`, inherit `stderr` just like it's the default when spawning processes.
/// If `false`, suppress all stderr output.
/// If not `None`, this will override any value set with [`Prepare::stderr()`].
pub stderr: Option<bool>,
}

mod prepare {
Expand Down Expand Up @@ -237,6 +241,9 @@ mod prepare {
if let Some(value) = ctx.icase_pathspecs {
cmd.env("GIT_ICASE_PATHSPECS", usize::from(value).to_string());
}
if let Some(stderr) = ctx.stderr {
cmd.stderr(if stderr { Stdio::inherit() } else { Stdio::null() });
}
}
cmd
}
Expand Down
2 changes: 1 addition & 1 deletion gix-discover/tests/upwards/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use std::path::PathBuf;
use gix_discover::repository::Kind;

fn expected_trust() -> gix_sec::Trust {
if std::env::var_os("GITOXIDE_TEST_EXPECT_REDUCED_TRUST").is_some() {
if std::env::var_os("GIX_TEST_EXPECT_REDUCED_TRUST").is_some() {
gix_sec::Trust::Reduced
} else {
gix_sec::Trust::Full
Expand Down
18 changes: 14 additions & 4 deletions gix/src/config/cache/init.rs
Original file line number Diff line number Diff line change
Expand Up @@ -402,10 +402,16 @@ fn apply_environment_overrides(
"gitoxide",
Some(Cow::Borrowed("credentials".into())),
git_prefix,
&[{
let key = &gitoxide::Credentials::TERMINAL_PROMPT;
(env(key), key.name)
}],
&[
{
let key = &gitoxide::Credentials::TERMINAL_PROMPT;
(env(key), key.name)
},
{
let key = &gitoxide::Credentials::HELPER_STDERR;
(env(key), key.name)
},
],
),
(
"gitoxide",
Expand Down Expand Up @@ -435,6 +441,10 @@ fn apply_environment_overrides(
let key = &gitoxide::Core::REFS_NAMESPACE;
(env(key), key.name)
},
{
let key = &gitoxide::Core::EXTERNAL_COMMAND_STDERR;
(env(key), key.name)
},
],
),
(
Expand Down
15 changes: 13 additions & 2 deletions gix/src/config/snapshot/credential_helpers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use std::{borrow::Cow, convert::TryFrom};

pub use error::Error;

use crate::config::cache::util::ApplyLeniency;
use crate::{
bstr::{ByteSlice, ByteVec},
config::{
Expand All @@ -25,6 +26,8 @@ mod error {
},
#[error("core.askpass could not be read")]
CoreAskpass(#[from] gix_config::path::interpolate::Error),
#[error(transparent)]
BooleanConfig(#[from] crate::config::boolean::Error),
}
}

Expand Down Expand Up @@ -145,7 +148,10 @@ impl Snapshot<'_> {
.ignore_empty()?
.map(|c| Cow::Owned(c.into_owned())),
mode: self
.boolean(Credentials::TERMINAL_PROMPT.logical_name().as_str())
.try_boolean(Credentials::TERMINAL_PROMPT.logical_name().as_str())
.map(|val| Credentials::TERMINAL_PROMPT.enrich_error(val))
.transpose()
.with_leniency(self.repo.config.lenient_config)?
.and_then(|val| (!val).then_some(gix_prompt::Mode::Disable))
.unwrap_or_default(),
}
Expand All @@ -156,7 +162,12 @@ impl Snapshot<'_> {
use_http_path,
// The default ssh implementation uses binaries that do their own auth, so our passwords aren't used.
query_user_only: url.scheme == gix_url::Scheme::Ssh,
..Default::default()
stderr: self
.try_boolean(Credentials::HELPER_STDERR.logical_name().as_str())
.map(|val| Credentials::HELPER_STDERR.enrich_error(val))
.transpose()
.with_leniency(self.repo.options.lenient_config)?
.unwrap_or(true),
},
gix_credentials::helper::Action::get_for_url(url.to_bstring()),
prompt_options,
Expand Down
2 changes: 1 addition & 1 deletion gix/src/config/tree/sections/core.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ impl Core {
/// The `core.deltaBaseCacheLimit` key.
pub const DELTA_BASE_CACHE_LIMIT: keys::UnsignedInteger =
keys::UnsignedInteger::new_unsigned_integer("deltaBaseCacheLimit", &config::Tree::CORE)
.with_environment_override("GITOXIDE_PACK_CACHE_MEMORY")
.with_environment_override("GIX_PACK_CACHE_MEMORY")
.with_note("if unset, we default to a small 64 slot fixed-size cache that holds at most 64 full delta base objects of any size. Set to 0 to deactivate it entirely");
/// The `core.disambiguate` key.
pub const DISAMBIGUATE: Disambiguate =
Expand Down
21 changes: 19 additions & 2 deletions gix/src/config/tree/sections/gitoxide.rs
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,15 @@ mod subsections {
pub const FILTER_PROCESS_DELAY: keys::Boolean =
keys::Boolean::new_boolean("filterProcessDelay", &Gitoxide::CORE);

/// The `gitoxide.core.externalCommandStderr` key (default `true`).
///
/// If `true`, the default, `stderr` of worktree filter programs, or any other git-context bearing command
/// invoked will be inherited.
/// If `false`, it will be suppressed completely.
pub const EXTERNAL_COMMAND_STDERR: keys::Boolean =
keys::Boolean::new_boolean("externalCommandStderr", &Gitoxide::CORE)
.with_environment_override("GIX_EXTERNAL_COMMAND_STDERR");

/// The `gitoxide.core.refsNamespace` key.
pub const REFS_NAMESPACE: RefsNamespace =
keys::Any::new_with_validate("refsNamespace", &Gitoxide::CORE, super::validate::RefsNamespace)
Expand All @@ -134,6 +143,7 @@ mod subsections {
&Self::USE_STDEV,
&Self::SHALLOW_FILE,
&Self::FILTER_PROCESS_DELAY,
&Self::EXTERNAL_COMMAND_STDERR,
&Self::REFS_NAMESPACE,
]
}
Expand Down Expand Up @@ -410,7 +420,7 @@ mod subsections {
pub const CACHE_LIMIT: keys::UnsignedInteger =
keys::UnsignedInteger::new_unsigned_integer("cacheLimit", &Gitoxide::OBJECTS)
.with_note("If unset or 0, there is no object cache")
.with_environment_override("GITOXIDE_OBJECT_CACHE_MEMORY");
.with_environment_override("GIX_OBJECT_CACHE_MEMORY");
/// The `gitoxide.objects.noReplace` key.
pub const NO_REPLACE: keys::Boolean = keys::Boolean::new_boolean("noReplace", &Gitoxide::OBJECTS);
/// The `gitoxide.objects.replaceRefBase` key.
Expand Down Expand Up @@ -467,6 +477,13 @@ mod subsections {
pub const TERMINAL_PROMPT: keys::Boolean = keys::Boolean::new_boolean("terminalPrompt", &Gitoxide::CREDENTIALS)
.with_note("This is a custom addition to provide an alternative to the respective environment variable.")
.with_environment_override("GIT_TERMINAL_PROMPT");

/// The `gitoxide.credentials.helperStderr` key to control what happens with the credential helpers `stderr`.
///
/// If `true`, the default, `stderr` of credential helper programs will be inherited, just like with `git`.
/// If `false`, will be suppressed completely.
pub const HELPER_STDERR: keys::Boolean = keys::Boolean::new_boolean("helperStderr", &Gitoxide::CREDENTIALS)
.with_environment_override("GIX_CREDENTIALS_HELPER_STDERR");
}

impl Section for Credentials {
Expand All @@ -475,7 +492,7 @@ mod subsections {
}

fn keys(&self) -> &[&dyn Key] {
&[&Self::TERMINAL_PROMPT]
&[&Self::TERMINAL_PROMPT, &Self::HELPER_STDERR]
}

fn parent(&self) -> Option<&dyn Section> {
Expand Down
21 changes: 17 additions & 4 deletions gix/src/repository/config/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -88,15 +88,27 @@ impl crate::Repository {
tree::{gitoxide, Key},
};

let boolean = |key: &dyn Key| {
let pathspec_boolean = |key: &'static config::tree::keys::Boolean| {
self.config
.resolved
.boolean("gitoxide", Some("pathspec".into()), key.name())
.map(|value| key.enrich_error(value))
.transpose()
.with_leniency(self.config.lenient_config)
};

Ok(gix_command::Context {
stderr: {
let key = &gitoxide::Core::EXTERNAL_COMMAND_STDERR;
self.config
.resolved
.boolean("gitoxide", Some("core".into()), key.name())
.map(|value| key.enrich_error(value))
.transpose()
.with_leniency(self.config.lenient_config)?
.unwrap_or(true)
.into()
},
git_dir: self.git_dir().to_owned().into(),
worktree_dir: self.work_dir().map(ToOwned::to_owned),
no_replace_objects: config::shared::is_replace_refs_enabled(
Expand All @@ -106,9 +118,10 @@ impl crate::Repository {
)?
.map(|enabled| !enabled),
ref_namespace: self.refs.namespace.as_ref().map(|ns| ns.as_bstr().to_owned()),
literal_pathspecs: boolean(&gitoxide::Pathspec::LITERAL)?,
glob_pathspecs: boolean(&gitoxide::Pathspec::GLOB)?.or(boolean(&gitoxide::Pathspec::NOGLOB)?),
icase_pathspecs: boolean(&gitoxide::Pathspec::ICASE)?,
literal_pathspecs: pathspec_boolean(&gitoxide::Pathspec::LITERAL)?,
glob_pathspecs: pathspec_boolean(&gitoxide::Pathspec::GLOB)?
.or(pathspec_boolean(&gitoxide::Pathspec::NOGLOB)?),
icase_pathspecs: pathspec_boolean(&gitoxide::Pathspec::ICASE)?,
})
}

Expand Down
2 changes: 1 addition & 1 deletion gix/tests/config/tree.rs
Original file line number Diff line number Diff line change
Expand Up @@ -448,7 +448,7 @@ mod core {
.try_into_usize(signed(-1))
.unwrap_err()
.to_string(),
"The value of key \"core.deltaBaseCacheLimit\" (possibly from GITOXIDE_PACK_CACHE_MEMORY) could not be parsed as unsigned integer"
"The value of key \"core.deltaBaseCacheLimit\" (possibly from GIX_PACK_CACHE_MEMORY) could not be parsed as unsigned integer"
);
assert!(Core::DELTA_BASE_CACHE_LIMIT.validate("-1".into()).is_err());
Ok(())
Expand Down
8 changes: 6 additions & 2 deletions gix/tests/gix-init.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,10 @@ mod with_overrides {
.set("GIT_AUTHOR_EMAIL", "author email")
.set("GIT_AUTHOR_DATE", default_date)
.set("EMAIL", "user email")
.set("GITOXIDE_PACK_CACHE_MEMORY", "0")
.set("GITOXIDE_OBJECT_CACHE_MEMORY", "5m")
.set("GIX_PACK_CACHE_MEMORY", "0")
.set("GIX_OBJECT_CACHE_MEMORY", "5m")
.set("GIX_CREDENTIALS_HELPER_STDERR", "creds-stderr")
.set("GIX_EXTERNAL_COMMAND_STDERR", "filter-stderr")
.set("GIT_SSL_CAINFO", "./env.pem")
.set("GIT_SSL_VERSION", "tlsv1.3")
.set("GIT_SSH_VARIANT", "ssh-variant-env")
Expand Down Expand Up @@ -254,6 +256,8 @@ mod with_overrides {
("gitoxide.pathspec.noglob", "pathspecs-noglob"),
("gitoxide.pathspec.literal", "pathspecs-literal"),
("gitoxide.credentials.terminalPrompt", "42"),
("gitoxide.credentials.helperStderr", "creds-stderr"),
("gitoxide.core.externalCommandStderr", "filter-stderr"),
] {
assert_eq!(
config
Expand Down
4 changes: 2 additions & 2 deletions src/plumbing/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -255,8 +255,8 @@ pub fn main() -> Result<()> {
let mut engine = core::corpus::Engine::open_or_create(
db,
core::corpus::engine::State {
gitoxide_version: option_env!("GITOXIDE_VERSION")
.ok_or_else(|| anyhow::anyhow!("GITOXIDE_VERSION must be set in build-script"))?
gitoxide_version: option_env!("GIX_VERSION")
.ok_or_else(|| anyhow::anyhow!("GIX_VERSION must be set in build-script"))?
.into(),
progress,
trace_to_progress: trace,
Expand Down
2 changes: 1 addition & 1 deletion src/plumbing/options/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use gitoxide_core as core;
use gix::bstr::BString;

#[derive(Debug, clap::Parser)]
#[clap(name = "gix", about = "The git underworld", version = option_env!("GITOXIDE_VERSION"))]
#[clap(name = "gix", about = "The git underworld", version = option_env!("GIX_VERSION"))]
#[clap(subcommand_required = true)]
#[clap(arg_required_else_help = true)]
pub struct Args {
Expand Down
2 changes: 1 addition & 1 deletion src/porcelain/options.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use std::path::PathBuf;

#[derive(Debug, clap::Parser)]
#[clap(about = "The rusty git", version = option_env!("GITOXIDE_VERSION"))]
#[clap(about = "The rusty git", version = option_env!("GIX_VERSION"))]
#[clap(subcommand_required = true)]
pub struct Args {
/// Do not display verbose messages and progress information
Expand Down
6 changes: 3 additions & 3 deletions tests/tools/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -262,7 +262,7 @@ fn fixture_bytes_inner(path: impl AsRef<Path>, root: DirectoryRoot) -> Vec<u8> {
/// In order to speed up CI and even local runs should the cache get purged, the result of each script run
/// is automatically placed into a compressed _tar_ archive.
/// If a script result doesn't exist, these will be checked first and extracted if present, which they are by default.
/// This behaviour can be prohibited by setting the `GITOXIDE_TEST_IGNORE_ARCHIVES` to any value.
/// This behaviour can be prohibited by setting the `GIX_TEST_IGNORE_ARCHIVES` to any value.
///
/// To speed CI up, one can add these archives to the repository. It's absolutely recommended to use `gix-lfs` for that to
/// not bloat the repository size.
Expand Down Expand Up @@ -631,11 +631,11 @@ fn extract_archive(
let archive_buf: Vec<u8> = {
let mut buf = Vec::new();
let input_archive = std::fs::File::open(archive)?;
if std::env::var_os("GITOXIDE_TEST_IGNORE_ARCHIVES").is_some() {
if std::env::var_os("GIX_TEST_IGNORE_ARCHIVES").is_some() {
return Err(std::io::Error::new(
std::io::ErrorKind::Other,
format!(
"Ignoring archive at '{}' as GITOXIDE_TEST_IGNORE_ARCHIVES is set.",
"Ignoring archive at '{}' as GIX_TEST_IGNORE_ARCHIVES is set.",
archive.display()
),
));
Expand Down