git login shell
Unified · Split
| @@ -318,7 +318,7 @@ jobs: · 317 unmodified lines | |||
| 318 | 318 | ||
| 319 | strategy: | 319 | strategy: |
| 320 | matrix: | 320 | matrix: |
| 321 | target: [ wasm32-unknown-unknown, wasm32-wasi ] | 321 | target: [ wasm32-unknown-unknown, wasm32-wasip1 ] |
| 322 | 322 | ||
| 323 | env: | 323 | env: |
| 324 | TARGET: ${{ matrix.target }} | 324 | TARGET: ${{ matrix.target }} |
| @@ -394,3 +394,4 @@ stable_sort_primitive = "allow" # x1 · 393 unmodified lines | |||
| 394 | no_effect_underscore_binding = "allow" # x1 | 394 | no_effect_underscore_binding = "allow" # x1 |
| 395 | empty_docs = "allow" | 395 | empty_docs = "allow" |
| 396 | too_long_first_doc_paragraph = "allow" | 396 | too_long_first_doc_paragraph = "allow" |
| 397 | large_stack_arrays = "allow" | ||
| @@ -89,7 +89,7 @@ pub(crate) mod function { · 88 unmodified lines | |||
| 89 | let entry = cache.at_entry( | 89 | let entry = cache.at_entry( |
| 90 | path, | 90 | path, |
| 91 | Some(is_dir_to_mode( | 91 | Some(is_dir_to_mode( |
| 92 | workdir.map_or(false, |wd| wd.join(gix::path::from_bstr(path)).is_dir()) | 92 | workdir.is_some_and(|wd| wd.join(gix::path::from_bstr(path)).is_dir()) |
| 93 | || pattern.signature.contains(gix::pathspec::MagicSignature::MUST_BE_DIR), | 93 | || pattern.signature.contains(gix::pathspec::MagicSignature::MUST_BE_DIR), |
| 94 | )), | 94 | )), |
| 95 | )?; | 95 | )?; |
| @@ -128,10 +128,10 @@ pub(crate) mod function { · 127 unmodified lines | |||
| 128 | let pathspec_includes_entry = match pathspec.as_mut() { | 128 | let pathspec_includes_entry = match pathspec.as_mut() { |
| 129 | None => entry | 129 | None => entry |
| 130 | .pathspec_match | 130 | .pathspec_match |
| 131 | .map_or(false, |m| m != gix::dir::entry::PathspecMatch::Excluded), | 131 | .is_some_and(|m| m != gix::dir::entry::PathspecMatch::Excluded), |
| 132 | Some(pathspec) => pathspec | 132 | Some(pathspec) => pathspec |
| 133 | .pattern_matching_relative_path(entry.rela_path.as_bstr(), entry.disk_kind.map(|k| k.is_dir())) | 133 | .pattern_matching_relative_path(entry.rela_path.as_bstr(), entry.disk_kind.map(|k| k.is_dir())) |
| 134 | .map_or(false, |m| !m.is_excluded()), | 134 | .is_some_and(|m| !m.is_excluded()), |
| 135 | }; | 135 | }; |
| 136 | pruned_entries += usize::from(!pathspec_includes_entry); | 136 | pruned_entries += usize::from(!pathspec_includes_entry); |
| 137 | if !pathspec_includes_entry && debug { | 137 | if !pathspec_includes_entry && debug { |
| @@ -32,7 +32,7 @@ pub fn list( · 31 unmodified lines | |||
| 32 | } | 32 | } |
| 33 | 33 | ||
| 34 | let meta = section.meta(); | 34 | let meta = section.meta(); |
| 35 | if last_meta.map_or(true, |last| last != meta) { | 35 | if last_meta != Some(meta) { |
| 36 | write_meta(meta, &mut out)?; | 36 | write_meta(meta, &mut out)?; |
| 37 | } | 37 | } |
| 38 | last_meta = Some(meta); | 38 | last_meta = Some(meta); |
| @@ -41,9 +41,10 @@ pub fn list( · 2 unmodified lines | |||
| 41 | for event in matter { | 41 | for event in matter { |
| 42 | event.write_to(&mut out)?; | 42 | event.write_to(&mut out)?; |
| 43 | } | 43 | } |
| 44 | if it.peek().map_or(false, |(next_section, _)| { | 44 | if it |
| 45 | next_section.header().name() != section.header().name() | 45 | .peek() |
| 46 | }) { | 46 | .is_some_and(|(next_section, _)| next_section.header().name() != section.header().name()) |
| 47 | { | ||
| 47 | writeln!(&mut out)?; | 48 | writeln!(&mut out)?; |
| 48 | } | 49 | } |
| 49 | } | 50 | } |
| @@ -93,7 +93,7 @@ pub fn query( · 92 unmodified lines | |||
| 93 | let entry = cache.at_entry( | 93 | let entry = cache.at_entry( |
| 94 | path, | 94 | path, |
| 95 | Some(is_dir_to_mode( | 95 | Some(is_dir_to_mode( |
| 96 | workdir.map_or(false, |wd| wd.join(gix::path::from_bstr(path)).is_dir()) | 96 | workdir.is_some_and(|wd| wd.join(gix::path::from_bstr(path)).is_dir()) |
| 97 | || pattern.signature.contains(gix::pathspec::MagicSignature::MUST_BE_DIR), | 97 | || pattern.signature.contains(gix::pathspec::MagicSignature::MUST_BE_DIR), |
| 98 | )), | 98 | )), |
| 99 | )?; | 99 | )?; |
| @@ -305,7 +305,7 @@ pub(crate) mod function { · 304 unmodified lines | |||
| 305 | for fix in &map.fixes { | 305 | for fix in &map.fixes { |
| 306 | match fix { | 306 | match fix { |
| 307 | Fix::MappingWithPartialDestinationRemoved { name, spec } => { | 307 | Fix::MappingWithPartialDestinationRemoved { name, spec } => { |
| 308 | if prev_spec.map_or(true, |prev_spec| prev_spec != spec) { | 308 | if prev_spec.is_some_and(|prev_spec| prev_spec != spec) { |
| 309 | prev_spec = spec.into(); | 309 | prev_spec = spec.into(); |
| 310 | spec.to_ref().write_to(&mut err)?; | 310 | spec.to_ref().write_to(&mut err)?; |
| 311 | writeln!(err)?; | 311 | writeln!(err)?; |
| @@ -198,7 +198,7 @@ pub(crate) mod function { · 197 unmodified lines | |||
| 198 | sms_by_path | 198 | sms_by_path |
| 199 | .iter() | 199 | .iter() |
| 200 | .find_map(|(path, sm)| (path == entry_path).then_some(sm)) | 200 | .find_map(|(path, sm)| (path == entry_path).then_some(sm)) |
| 201 | .filter(|sm| sm.git_dir_try_old_form().map_or(false, |dot_git| dot_git.exists())) | 201 | .filter(|sm| sm.git_dir_try_old_form().is_ok_and(|dot_git| dot_git.exists())) |
| 202 | }) | 202 | }) |
| 203 | { | 203 | { |
| 204 | let sm_path = gix::path::to_unix_separators_on_windows(sm.path()?); | 204 | let sm_path = gix::path::to_unix_separators_on_windows(sm.path()?); |
| @@ -190,7 +190,7 @@ mod refs_impl { · 189 unmodified lines | |||
| 190 | for fix in &map.fixes { | 190 | for fix in &map.fixes { |
| 191 | match fix { | 191 | match fix { |
| 192 | Fix::MappingWithPartialDestinationRemoved { name, spec } => { | 192 | Fix::MappingWithPartialDestinationRemoved { name, spec } => { |
| 193 | if prev_spec.map_or(true, |prev_spec| prev_spec != spec) { | 193 | if prev_spec.is_some_and(|prev_spec| prev_spec != spec) { |
| 194 | prev_spec = spec.into(); | 194 | prev_spec = spec.into(); |
| 195 | spec.to_ref().write_to(&mut err)?; | 195 | spec.to_ref().write_to(&mut err)?; |
| 196 | writeln!(err)?; | 196 | writeln!(err)?; |
| @@ -108,7 +108,7 @@ pub(crate) mod function { · 107 unmodified lines | |||
| 108 | } | 108 | } |
| 109 | } | 109 | } |
| 110 | progress.inc(); | 110 | progress.inc(); |
| 111 | if limit.map_or(false, |limit| limit == progress.step()) { | 111 | if limit.is_some_and(|limit| limit == progress.step()) { |
| 112 | break; | 112 | break; |
| 113 | } | 113 | } |
| 114 | } | 114 | } |
| @@ -215,7 +215,7 @@ pub fn path( · 214 unmodified lines | |||
| 215 | 215 | ||
| 216 | let is_dir = if symlinks_to_directories_are_ignored_like_directories | 216 | let is_dir = if symlinks_to_directories_are_ignored_like_directories |
| 217 | && ctx.excludes.is_some() | 217 | && ctx.excludes.is_some() |
| 218 | && kind.map_or(false, |ft| ft == entry::Kind::Symlink) | 218 | && kind == Some(entry::Kind::Symlink) |
| 219 | { | 219 | { |
| 220 | path.metadata().ok().map(|md| is_dir_to_mode(md.is_dir())) | 220 | path.metadata().ok().map(|md| is_dir_to_mode(md.is_dir())) |
| 221 | } else { | 221 | } else { |
| @@ -19,7 +19,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> { · 18 unmodified lines | |||
| 19 | 19 | ||
| 20 | match sub_command.as_str() { | 20 | match sub_command.as_str() { |
| 21 | "process" => { | 21 | "process" => { |
| 22 | let disallow_delay = next_arg.as_deref().map_or(false, |arg| arg == "disallow-delay"); | 22 | let disallow_delay = next_arg.as_deref() == Some("disallow-delay"); |
| 23 | let mut srv = gix_filter::driver::process::Server::handshake( | 23 | let mut srv = gix_filter::driver::process::Server::handshake( |
| 24 | stdin(), | 24 | stdin(), |
| 25 | stdout(), | 25 | stdout(), |
| @@ -83,7 +83,7 @@ impl Status { · 82 unmodified lines | |||
| 83 | 83 | ||
| 84 | /// Returns true if this is an `abort` status. | 84 | /// Returns true if this is an `abort` status. |
| 85 | pub fn is_abort(&self) -> bool { | 85 | pub fn is_abort(&self) -> bool { |
| 86 | self.message().map_or(false, |m| m == "abort") | 86 | self.message() == Some("abort") |
| 87 | } | 87 | } |
| 88 | 88 | ||
| 89 | /// Return true if the status is explicitly set to indicated delayed output processing | 89 | /// Return true if the status is explicitly set to indicated delayed output processing |
| @@ -69,7 +69,7 @@ pub mod index_names { · 68 unmodified lines | |||
| 69 | ascii_path.is_ascii(), | 69 | ascii_path.is_ascii(), |
| 70 | "must use ascii bytes for correct size computation" | 70 | "must use ascii bytes for correct size computation" |
| 71 | ); | 71 | ); |
| 72 | count += (ascii_path.as_bytes().len() + 1/* null byte */) as u64; | 72 | count += (ascii_path.len() + 1/* null byte */) as u64; |
| 73 | } | 73 | } |
| 74 | 74 | ||
| 75 | let needed_alignment = CHUNK_ALIGNMENT - (count % CHUNK_ALIGNMENT); | 75 | let needed_alignment = CHUNK_ALIGNMENT - (count % CHUNK_ALIGNMENT); |
| @@ -89,7 +89,7 @@ pub mod index_names { · 13 unmodified lines | |||
| 89 | let path = path.as_ref().to_str().expect("UTF-8 path"); | 89 | let path = path.as_ref().to_str().expect("UTF-8 path"); |
| 90 | out.write_all(path.as_bytes())?; | 90 | out.write_all(path.as_bytes())?; |
| 91 | out.write_all(&[0])?; | 91 | out.write_all(&[0])?; |
| 92 | written_bytes += path.as_bytes().len() as u64 + 1; | 92 | written_bytes += path.len() as u64 + 1; |
| 93 | } | 93 | } |
| 94 | 94 | ||
| 95 | let needed_alignment = CHUNK_ALIGNMENT - (written_bytes % CHUNK_ALIGNMENT); | 95 | let needed_alignment = CHUNK_ALIGNMENT - (written_bytes % CHUNK_ALIGNMENT); |
| @@ -6,7 +6,7 @@ use futures_io::AsyncWrite; · 5 unmodified lines | |||
| 6 | 6 | ||
| 7 | use crate::{encode, BandRef, Channel, ErrorRef, PacketLineRef, TextRef}; | 7 | use crate::{encode, BandRef, Channel, ErrorRef, PacketLineRef, TextRef}; |
| 8 | 8 | ||
| 9 | impl<'a> BandRef<'a> { | 9 | impl BandRef<'_> { |
| 10 | /// Serialize this instance to `out`, returning the amount of bytes written. | 10 | /// Serialize this instance to `out`, returning the amount of bytes written. |
| 11 | /// | 11 | /// |
| 12 | /// The data written to `out` can be decoded with [`Borrowed::decode_band()]`. | 12 | /// The data written to `out` can be decoded with [`Borrowed::decode_band()]`. |
| @@ -20,14 +20,14 @@ impl<'a> BandRef<'a> { · 7 unmodified lines | |||
| 20 | } | 20 | } |
| 21 | } | 21 | } |
| 22 | 22 | ||
| 23 | impl<'a> TextRef<'a> { | 23 | impl TextRef<'_> { |
| 24 | /// Serialize this instance to `out`, appending a newline if there is none, returning the amount of bytes written. | 24 | /// Serialize this instance to `out`, appending a newline if there is none, returning the amount of bytes written. |
| 25 | pub async fn write_to(&self, out: impl AsyncWrite + Unpin) -> io::Result<usize> { | 25 | pub async fn write_to(&self, out: impl AsyncWrite + Unpin) -> io::Result<usize> { |
| 26 | encode::text_to_write(self.0, out).await | 26 | encode::text_to_write(self.0, out).await |
| 27 | } | 27 | } |
| 28 | } | 28 | } |
| 29 | 29 | ||
| 30 | impl<'a> ErrorRef<'a> { | 30 | impl ErrorRef<'_> { |
| 31 | /// Serialize this line as error to `out`. | 31 | /// Serialize this line as error to `out`. |
| 32 | /// | 32 | /// |
| 33 | /// This includes a marker to allow decoding it outside of a side-band channel, returning the amount of bytes written. | 33 | /// This includes a marker to allow decoding it outside of a side-band channel, returning the amount of bytes written. |
| @@ -36,7 +36,7 @@ impl<'a> ErrorRef<'a> { · 2 unmodified lines | |||
| 36 | } | 36 | } |
| 37 | } | 37 | } |
| 38 | 38 | ||
| 39 | impl<'a> PacketLineRef<'a> { | 39 | impl PacketLineRef<'_> { |
| 40 | /// Serialize this instance to `out` in git `packetline` format, returning the amount of bytes written to `out`. | 40 | /// Serialize this instance to `out` in git `packetline` format, returning the amount of bytes written to `out`. |
| 41 | pub async fn write_to(&self, out: impl AsyncWrite + Unpin) -> io::Result<usize> { | 41 | pub async fn write_to(&self, out: impl AsyncWrite + Unpin) -> io::Result<usize> { |
| 42 | match self { | 42 | match self { |
| @@ -4,7 +4,7 @@ use futures_io::AsyncWrite; · 3 unmodified lines | |||
| 4 | 4 | ||
| 5 | use crate::{encode, BandRef, Channel, ErrorRef, PacketLineRef, TextRef}; | 5 | use crate::{encode, BandRef, Channel, ErrorRef, PacketLineRef, TextRef}; |
| 6 | 6 | ||
| 7 | impl<'a> BandRef<'a> { | 7 | impl BandRef<'_> { |
| 8 | /// Serialize this instance to `out`, returning the amount of bytes written. | 8 | /// Serialize this instance to `out`, returning the amount of bytes written. |
| 9 | /// | 9 | /// |
| 10 | /// The data written to `out` can be decoded with [`Borrowed::decode_band()]`. | 10 | /// The data written to `out` can be decoded with [`Borrowed::decode_band()]`. |
| @@ -18,14 +18,14 @@ impl<'a> BandRef<'a> { · 7 unmodified lines | |||
| 18 | } | 18 | } |
| 19 | } | 19 | } |
| 20 | 20 | ||
| 21 | impl<'a> TextRef<'a> { | 21 | impl TextRef<'_> { |
| 22 | /// Serialize this instance to `out`, appending a newline if there is none, returning the amount of bytes written. | 22 | /// Serialize this instance to `out`, appending a newline if there is none, returning the amount of bytes written. |
| 23 | pub async fn write_to(&self, out: impl AsyncWrite + Unpin) -> io::Result<usize> { | 23 | pub async fn write_to(&self, out: impl AsyncWrite + Unpin) -> io::Result<usize> { |
| 24 | encode::text_to_write(self.0, out).await | 24 | encode::text_to_write(self.0, out).await |
| 25 | } | 25 | } |
| 26 | } | 26 | } |
| 27 | 27 | ||
| 28 | impl<'a> ErrorRef<'a> { | 28 | impl ErrorRef<'_> { |
| 29 | /// Serialize this line as error to `out`. | 29 | /// Serialize this line as error to `out`. |
| 30 | /// | 30 | /// |
| 31 | /// This includes a marker to allow decoding it outside of a side-band channel, returning the amount of bytes written. | 31 | /// This includes a marker to allow decoding it outside of a side-band channel, returning the amount of bytes written. |
| @@ -34,7 +34,7 @@ impl<'a> ErrorRef<'a> { · 2 unmodified lines | |||
| 34 | } | 34 | } |
| 35 | } | 35 | } |
| 36 | 36 | ||
| 37 | impl<'a> PacketLineRef<'a> { | 37 | impl PacketLineRef<'_> { |
| 38 | /// Serialize this instance to `out` in git `packetline` format, returning the amount of bytes written to `out`. | 38 | /// Serialize this instance to `out` in git `packetline` format, returning the amount of bytes written to `out`. |
| 39 | pub async fn write_to(&self, out: impl AsyncWrite + Unpin) -> io::Result<usize> { | 39 | pub async fn write_to(&self, out: impl AsyncWrite + Unpin) -> io::Result<usize> { |
| 40 | match self { | 40 | match self { |
| @@ -28,6 +28,23 @@ pub fn installation_config_prefix() -> Option<&'static Path> { · 27 unmodified lines | |||
| 28 | installation_config().map(git::config_to_base_path) | 28 | installation_config().map(git::config_to_base_path) |
| 29 | } | 29 | } |
| 30 | 30 | ||
| 31 | /// Return the shell that Git would prefer as login shell, the shell to execute Git commands from. | ||
| 32 | /// | ||
| 33 | /// On Windows, this is the `bash.exe` bundled with it, and on Unix it's the shell specified by `SHELL`, | ||
| 34 | /// or `None` if it is truly unspecified. | ||
| 35 | pub fn login_shell() -> Option<&'static Path> { | ||
| 36 | static PATH: Lazy<Option<PathBuf>> = Lazy::new(|| { | ||
| 37 | if cfg!(windows) { | ||
| 38 | installation_config_prefix() | ||
| 39 | .and_then(|p| p.parent()) | ||
| 40 | .map(|p| p.join("usr").join("bin").join("bash.exe")) | ||
| 41 | } else { | ||
| 42 | std::env::var_os("SHELL").map(PathBuf::from) | ||
| 43 | } | ||
| 44 | }); | ||
| 45 | PATH.as_deref() | ||
| 46 | } | ||
| 47 | |||
| 31 | /// Return the name of the Git executable to invoke it. | 48 | /// Return the name of the Git executable to invoke it. |
| 32 | /// If it's in the `PATH`, it will always be a short name. | 49 | /// If it's in the `PATH`, it will always be a short name. |
| 33 | /// | 50 | /// |
| @@ -1,80 +0,0 @@ | |||
| 1 | pub type Result<T = ()> = std::result::Result<T, Box<dyn std::error::Error>>; | ||
| 2 | |||
| 3 | mod convert; | ||
| 4 | mod realpath; | ||
| 5 | mod home_dir { | ||
| 6 | #[test] | ||
| 7 | fn returns_existing_directory() { | ||
| 8 | if let Some(home) = gix_path::env::home_dir() { | ||
| 9 | assert!( | ||
| 10 | home.is_dir(), | ||
| 11 | "the home directory would typically exist, even though on unix we don't test for that." | ||
| 12 | ); | ||
| 13 | } | ||
| 14 | } | ||
| 15 | } | ||
| 16 | |||
| 17 | mod env { | ||
| 18 | #[test] | ||
| 19 | fn exe_invocation() { | ||
| 20 | let actual = gix_path::env::exe_invocation(); | ||
| 21 | assert!( | ||
| 22 | !actual.as_os_str().is_empty(), | ||
| 23 | "it finds something as long as git is installed somewhere on the system (or a default location)" | ||
| 24 | ); | ||
| 25 | } | ||
| 26 | |||
| 27 | #[test] | ||
| 28 | fn installation_config() { | ||
| 29 | assert_ne!( | ||
| 30 | gix_path::env::installation_config().map(|p| p.components().count()), | ||
| 31 | gix_path::env::installation_config_prefix().map(|p| p.components().count()), | ||
| 32 | "the prefix is a bit shorter than the installation config path itself" | ||
| 33 | ); | ||
| 34 | } | ||
| 35 | |||
| 36 | #[test] | ||
| 37 | fn system_prefix() { | ||
| 38 | assert_ne!( | ||
| 39 | gix_path::env::system_prefix(), | ||
| 40 | None, | ||
| 41 | "git should be present when running tests" | ||
| 42 | ); | ||
| 43 | } | ||
| 44 | |||
| 45 | #[test] | ||
| 46 | fn home_dir() { | ||
| 47 | assert_ne!( | ||
| 48 | gix_path::env::home_dir(), | ||
| 49 | None, | ||
| 50 | "we find a home on every system these tests execute" | ||
| 51 | ); | ||
| 52 | } | ||
| 53 | |||
| 54 | mod xdg_config { | ||
| 55 | use std::ffi::OsStr; | ||
| 56 | |||
| 57 | #[test] | ||
| 58 | fn prefers_xdg_config_bases() { | ||
| 59 | let actual = gix_path::env::xdg_config("test", &mut |n| { | ||
| 60 | (n == OsStr::new("XDG_CONFIG_HOME")).then(|| "marker".into()) | ||
| 61 | }) | ||
| 62 | .expect("set"); | ||
| 63 | #[cfg(unix)] | ||
| 64 | assert_eq!(actual.to_str(), Some("marker/git/test")); | ||
| 65 | #[cfg(windows)] | ||
| 66 | assert_eq!(actual.to_str(), Some("marker\\git\\test")); | ||
| 67 | } | ||
| 68 | |||
| 69 | #[test] | ||
| 70 | fn falls_back_to_home() { | ||
| 71 | let actual = gix_path::env::xdg_config("test", &mut |n| (n == OsStr::new("HOME")).then(|| "marker".into())) | ||
| 72 | .expect("set"); | ||
| 73 | #[cfg(unix)] | ||
| 74 | assert_eq!(actual.to_str(), Some("marker/.config/git/test")); | ||
| 75 | #[cfg(windows)] | ||
| 76 | assert_eq!(actual.to_str(), Some("marker\\.config\\git\\test")); | ||
| 77 | } | ||
| 78 | } | ||
| 79 | } | ||
| 80 | mod util; | ||
File renamed without changes.
File renamed without changes.
| @@ -0,0 +1,71 @@ | |||
| 1 | #[test] | ||
| 2 | fn exe_invocation() { | ||
| 3 | let actual = gix_path::env::exe_invocation(); | ||
| 4 | assert!( | ||
| 5 | !actual.as_os_str().is_empty(), | ||
| 6 | "it finds something as long as git is installed somewhere on the system (or a default location)" | ||
| 7 | ); | ||
| 8 | } | ||
| 9 | |||
| 10 | #[test] | ||
| 11 | fn login_shell() { | ||
| 12 | // On CI, the $SHELL variable isn't necessarily set. Maybe other ways to get the login shell should be used then. | ||
| 13 | if !gix_testtools::is_ci::cached() { | ||
| 14 | assert!(gix_path::env::login_shell() | ||
| 15 | .expect("There should always be the notion of a shell used by git") | ||
| 16 | .exists()); | ||
| 17 | } | ||
| 18 | } | ||
| 19 | |||
| 20 | #[test] | ||
| 21 | fn installation_config() { | ||
| 22 | assert_ne!( | ||
| 23 | gix_path::env::installation_config().map(|p| p.components().count()), | ||
| 24 | gix_path::env::installation_config_prefix().map(|p| p.components().count()), | ||
| 25 | "the prefix is a bit shorter than the installation config path itself" | ||
| 26 | ); | ||
| 27 | } | ||
| 28 | |||
| 29 | #[test] | ||
| 30 | fn system_prefix() { | ||
| 31 | assert_ne!( | ||
| 32 | gix_path::env::system_prefix(), | ||
| 33 | None, | ||
| 34 | "git should be present when running tests" | ||
| 35 | ); | ||
| 36 | } | ||
| 37 | |||
| 38 | #[test] | ||
| 39 | fn home_dir() { | ||
| 40 | assert_ne!( | ||
| 41 | gix_path::env::home_dir(), | ||
| 42 | None, | ||
| 43 | "we find a home on every system these tests execute" | ||
| 44 | ); | ||
| 45 | } | ||
| 46 | |||
| 47 | mod xdg_config { | ||
| 48 | use std::ffi::OsStr; | ||
| 49 | |||
| 50 | #[test] | ||
| 51 | fn prefers_xdg_config_bases() { | ||
| 52 | let actual = gix_path::env::xdg_config("test", &mut |n| { | ||
| 53 | (n == OsStr::new("XDG_CONFIG_HOME")).then(|| "marker".into()) | ||
| 54 | }) | ||
| 55 | .expect("set"); | ||
| 56 | #[cfg(unix)] | ||
| 57 | assert_eq!(actual.to_str(), Some("marker/git/test")); | ||
| 58 | #[cfg(windows)] | ||
| 59 | assert_eq!(actual.to_str(), Some("marker\\git\\test")); | ||
| 60 | } | ||
| 61 | |||
| 62 | #[test] | ||
| 63 | fn falls_back_to_home() { | ||
| 64 | let actual = gix_path::env::xdg_config("test", &mut |n| (n == OsStr::new("HOME")).then(|| "marker".into())) | ||
| 65 | .expect("set"); | ||
| 66 | #[cfg(unix)] | ||
| 67 | assert_eq!(actual.to_str(), Some("marker/.config/git/test")); | ||
| 68 | #[cfg(windows)] | ||
| 69 | assert_eq!(actual.to_str(), Some("marker\\.config\\git\\test")); | ||
| 70 | } | ||
| 71 | } | ||
| @@ -0,0 +1,18 @@ | |||
| 1 | pub type Result<T = ()> = std::result::Result<T, Box<dyn std::error::Error>>; | ||
| 2 | |||
| 3 | mod convert; | ||
| 4 | mod realpath; | ||
| 5 | mod home_dir { | ||
| 6 | #[test] | ||
| 7 | fn returns_existing_directory() { | ||
| 8 | if let Some(home) = gix_path::env::home_dir() { | ||
| 9 | assert!( | ||
| 10 | home.is_dir(), | ||
| 11 | "the home directory would typically exist, even though on unix we don't test for that." | ||
| 12 | ); | ||
| 13 | } | ||
| 14 | } | ||
| 15 | } | ||
| 16 | |||
| 17 | mod env; | ||
| 18 | mod util; | ||
File renamed without changes.
File renamed without changes.
| @@ -72,7 +72,7 @@ impl Transaction<'_, '_> { · 71 unmodified lines | |||
| 72 | } | 72 | } |
| 73 | }; | 73 | }; |
| 74 | if let Some((previous, new_oid)) = log_update { | 74 | if let Some((previous, new_oid)) = log_update { |
| 75 | let do_update = previous.as_ref().map_or(true, |previous| previous != new_oid); | 75 | let do_update = previous.as_ref() != Some(new_oid); |
| 76 | if do_update { | 76 | if do_update { |
| 77 | self.store.reflog_create_or_append( | 77 | self.store.reflog_create_or_append( |
| 78 | change.update.name.as_ref(), | 78 | change.update.name.as_ref(), |
| @@ -4,8 +4,6 @@ · 3 unmodified lines | |||
| 4 | 4 | ||
| 5 | use std::{borrow::Cow, collections::BTreeMap}; | 5 | use std::{borrow::Cow, collections::BTreeMap}; |
| 6 | 6 | ||
| 7 | use bstr::BStr; | ||
| 8 | |||
| 9 | /// All relevant information about a git module, typically from `.gitmodules` files. | 7 | /// All relevant information about a git module, typically from `.gitmodules` files. |
| 10 | /// | 8 | /// |
| 11 | /// Note that overrides from other configuration might be relevant, which is why this type | 9 | /// Note that overrides from other configuration might be relevant, which is why this type |
| @@ -64,7 +62,7 @@ impl File { · 52 unmodified lines | |||
| 64 | let mut config_to_append = gix_config::File::new(config.meta_owned()); | 62 | let mut config_to_append = gix_config::File::new(config.meta_owned()); |
| 65 | let mut prev_name = None; | 63 | let mut prev_name = None; |
| 66 | for ((module_name, field), values) in values { | 64 | for ((module_name, field), values) in values { |
| 67 | if prev_name.map_or(true, |pn: &BStr| pn != module_name) { | 65 | if prev_name != Some(module_name) { |
| 68 | config_to_append | 66 | config_to_append |
| 69 | .new_section("submodule", Some(Cow::Owned(module_name.to_owned()))) | 67 | .new_section("submodule", Some(Cow::Owned(module_name.to_owned()))) |
| 70 | .expect("all names come from valid configuration, so remain valid"); | 68 | .expect("all names come from valid configuration, so remain valid"); |
| @@ -185,7 +185,7 @@ fn check_win_devices_and_illegal_characters(input: &BStr) -> Option<component::E · 184 unmodified lines | |||
| 185 | } | 185 | } |
| 186 | 186 | ||
| 187 | fn is_symlink(mode: Option<component::Mode>) -> bool { | 187 | fn is_symlink(mode: Option<component::Mode>) -> bool { |
| 188 | mode.map_or(false, |m| m == component::Mode::Symlink) | 188 | mode == Some(component::Mode::Symlink) |
| 189 | } | 189 | } |
| 190 | 190 | ||
| 191 | fn is_dot_hfs(input: &BStr, search_case_insensitive: &str) -> bool { | 191 | fn is_dot_hfs(input: &BStr, search_case_insensitive: &str) -> bool { |
| @@ -1,3 +1,4 @@ | |||
| 1 | #![allow(clippy::unnecessary_literal_bound)] | ||
| 1 | #![allow(missing_docs)] | 2 | #![allow(missing_docs)] |
| 2 | 3 | ||
| 3 | /// The `author` top-level section. | 4 | /// The `author` top-level section. |
| @@ -63,7 +63,7 @@ impl SchemePermission { · 62 unmodified lines | |||
| 63 | .map(|value| Protocol::ALLOW.try_into_allow(value, None)) | 63 | .map(|value| Protocol::ALLOW.try_into_allow(value, None)) |
| 64 | .transpose()?; | 64 | .transpose()?; |
| 65 | 65 | ||
| 66 | let mut saw_user = allow.map_or(false, |allow| allow == Allow::User); | 66 | let mut saw_user = allow == Some(Allow::User); |
| 67 | let allow_per_scheme = match config.sections_by_name_and_filter("protocol", &mut filter) { | 67 | let allow_per_scheme = match config.sections_by_name_and_filter("protocol", &mut filter) { |
| 68 | Some(it) => { | 68 | Some(it) => { |
| 69 | let mut map = BTreeMap::default(); | 69 | let mut map = BTreeMap::default(); |
| @@ -652,6 +652,7 @@ fn configure_command<'a, I: IntoIterator<Item = S>, S: AsRef<OsStr>>( · 651 unmodified lines | |||
| 652 | } | 652 | } |
| 653 | 653 | ||
| 654 | fn bash_program() -> &'static Path { | 654 | fn bash_program() -> &'static Path { |
| 655 | // TODO: use `gix_path::env::login_shell()` when available. | ||
| 655 | if cfg!(windows) { | 656 | if cfg!(windows) { |
| 656 | static GIT_BASH: Lazy<Option<PathBuf>> = Lazy::new(|| { | 657 | static GIT_BASH: Lazy<Option<PathBuf>> = Lazy::new(|| { |
| 657 | GIT_CORE_DIR | 658 | GIT_CORE_DIR |
| @@ -685,8 +686,7 @@ fn is_lfs_pointer_file(path: &Path) -> bool { · 27 unmodified lines | |||
| 685 | std::fs::OpenOptions::new() | 686 | std::fs::OpenOptions::new() |
| 686 | .read(true) | 687 | .read(true) |
| 687 | .open(path) | 688 | .open(path) |
| 688 | .and_then(|mut f| f.read_exact(&mut buf)) | 689 | .is_ok_and(|mut f| f.read_exact(&mut buf).is_ok_and(|_| buf.starts_with(PREFIX))) |
| 689 | .map_or(false, |_| buf.starts_with(PREFIX)) | ||
| 690 | } | 690 | } |
| 691 | 691 | ||
| 692 | /// The `script_identity` will be baked into the soon to be created `archive` as it identifies the script | 692 | /// The `script_identity` will be baked into the soon to be created `archive` as it identifies the script |