summaryrefslogtreecommitdiffstats
path: root/extra/git2/src/util.rs
diff options
context:
space:
mode:
Diffstat (limited to 'extra/git2/src/util.rs')
-rw-r--r--extra/git2/src/util.rs342
1 files changed, 0 insertions, 342 deletions
diff --git a/extra/git2/src/util.rs b/extra/git2/src/util.rs
deleted file mode 100644
index 5f735bc00..000000000
--- a/extra/git2/src/util.rs
+++ /dev/null
@@ -1,342 +0,0 @@
-use libc::{c_char, c_int, size_t};
-use std::cmp::Ordering;
-use std::ffi::{CString, OsStr, OsString};
-use std::iter::IntoIterator;
-use std::path::{Component, Path, PathBuf};
-
-use crate::{raw, Error};
-
-#[doc(hidden)]
-pub trait IsNull {
- fn is_ptr_null(&self) -> bool;
-}
-impl<T> IsNull for *const T {
- fn is_ptr_null(&self) -> bool {
- self.is_null()
- }
-}
-impl<T> IsNull for *mut T {
- fn is_ptr_null(&self) -> bool {
- self.is_null()
- }
-}
-
-#[doc(hidden)]
-pub trait Binding: Sized {
- type Raw;
-
- unsafe fn from_raw(raw: Self::Raw) -> Self;
- fn raw(&self) -> Self::Raw;
-
- unsafe fn from_raw_opt<T>(raw: T) -> Option<Self>
- where
- T: Copy + IsNull,
- Self: Binding<Raw = T>,
- {
- if raw.is_ptr_null() {
- None
- } else {
- Some(Binding::from_raw(raw))
- }
- }
-}
-
-/// Converts an iterator of repo paths into a git2-compatible array of cstrings.
-///
-/// Only use this for repo-relative paths or pathspecs.
-///
-/// See `iter2cstrs` for more details.
-pub fn iter2cstrs_paths<T, I>(
- iter: I,
-) -> Result<(Vec<CString>, Vec<*const c_char>, raw::git_strarray), Error>
-where
- T: IntoCString,
- I: IntoIterator<Item = T>,
-{
- let cstrs = iter
- .into_iter()
- .map(|i| fixup_windows_path(i.into_c_string()?))
- .collect::<Result<Vec<CString>, _>>()?;
- iter2cstrs(cstrs)
-}
-
-/// Converts an iterator of things into a git array of c-strings.
-///
-/// Returns a tuple `(cstrings, pointers, git_strarray)`. The first two values
-/// should not be dropped before `git_strarray`.
-pub fn iter2cstrs<T, I>(
- iter: I,
-) -> Result<(Vec<CString>, Vec<*const c_char>, raw::git_strarray), Error>
-where
- T: IntoCString,
- I: IntoIterator<Item = T>,
-{
- let cstrs = iter
- .into_iter()
- .map(|i| i.into_c_string())
- .collect::<Result<Vec<CString>, _>>()?;
- let ptrs = cstrs.iter().map(|i| i.as_ptr()).collect::<Vec<_>>();
- let raw = raw::git_strarray {
- strings: ptrs.as_ptr() as *mut _,
- count: ptrs.len() as size_t,
- };
- Ok((cstrs, ptrs, raw))
-}
-
-#[cfg(unix)]
-pub fn bytes2path(b: &[u8]) -> &Path {
- use std::os::unix::prelude::*;
- Path::new(OsStr::from_bytes(b))
-}
-#[cfg(windows)]
-pub fn bytes2path(b: &[u8]) -> &Path {
- use std::str;
- Path::new(str::from_utf8(b).unwrap())
-}
-
-/// A class of types that can be converted to C strings.
-///
-/// These types are represented internally as byte slices and it is quite rare
-/// for them to contain an interior 0 byte.
-pub trait IntoCString {
- /// Consume this container, converting it into a CString
- fn into_c_string(self) -> Result<CString, Error>;
-}
-
-impl<'a, T: IntoCString + Clone> IntoCString for &'a T {
- fn into_c_string(self) -> Result<CString, Error> {
- self.clone().into_c_string()
- }
-}
-
-impl<'a> IntoCString for &'a str {
- fn into_c_string(self) -> Result<CString, Error> {
- Ok(CString::new(self)?)
- }
-}
-
-impl IntoCString for String {
- fn into_c_string(self) -> Result<CString, Error> {
- Ok(CString::new(self.into_bytes())?)
- }
-}
-
-impl IntoCString for CString {
- fn into_c_string(self) -> Result<CString, Error> {
- Ok(self)
- }
-}
-
-impl<'a> IntoCString for &'a Path {
- fn into_c_string(self) -> Result<CString, Error> {
- let s: &OsStr = self.as_ref();
- s.into_c_string()
- }
-}
-
-impl IntoCString for PathBuf {
- fn into_c_string(self) -> Result<CString, Error> {
- let s: OsString = self.into();
- s.into_c_string()
- }
-}
-
-impl<'a> IntoCString for &'a OsStr {
- fn into_c_string(self) -> Result<CString, Error> {
- self.to_os_string().into_c_string()
- }
-}
-
-impl IntoCString for OsString {
- #[cfg(unix)]
- fn into_c_string(self) -> Result<CString, Error> {
- use std::os::unix::prelude::*;
- let s: &OsStr = self.as_ref();
- Ok(CString::new(s.as_bytes())?)
- }
- #[cfg(windows)]
- fn into_c_string(self) -> Result<CString, Error> {
- match self.to_str() {
- Some(s) => s.into_c_string(),
- None => Err(Error::from_str(
- "only valid unicode paths are accepted on windows",
- )),
- }
- }
-}
-
-impl<'a> IntoCString for &'a [u8] {
- fn into_c_string(self) -> Result<CString, Error> {
- Ok(CString::new(self)?)
- }
-}
-
-impl IntoCString for Vec<u8> {
- fn into_c_string(self) -> Result<CString, Error> {
- Ok(CString::new(self)?)
- }
-}
-
-pub fn into_opt_c_string<S>(opt_s: Option<S>) -> Result<Option<CString>, Error>
-where
- S: IntoCString,
-{
- match opt_s {
- None => Ok(None),
- Some(s) => Ok(Some(s.into_c_string()?)),
- }
-}
-
-pub fn c_cmp_to_ordering(cmp: c_int) -> Ordering {
- match cmp {
- 0 => Ordering::Equal,
- n if n < 0 => Ordering::Less,
- _ => Ordering::Greater,
- }
-}
-
-/// Converts a path to a CString that is usable by the libgit2 API.
-///
-/// Checks if it is a relative path.
-///
-/// On Windows, this also requires the path to be valid Unicode, and translates
-/// back slashes to forward slashes.
-pub fn path_to_repo_path(path: &Path) -> Result<CString, Error> {
- macro_rules! err {
- ($msg:literal, $path:expr) => {
- return Err(Error::from_str(&format!($msg, $path.display())))
- };
- }
- match path.components().next() {
- None => return Err(Error::from_str("repo path should not be empty")),
- Some(Component::Prefix(_)) => err!(
- "repo path `{}` should be relative, not a windows prefix",
- path
- ),
- Some(Component::RootDir) => err!("repo path `{}` should be relative", path),
- Some(Component::CurDir) => err!("repo path `{}` should not start with `.`", path),
- Some(Component::ParentDir) => err!("repo path `{}` should not start with `..`", path),
- Some(Component::Normal(_)) => {}
- }
- #[cfg(windows)]
- {
- match path.to_str() {
- None => {
- return Err(Error::from_str(
- "only valid unicode paths are accepted on windows",
- ))
- }
- Some(s) => return fixup_windows_path(s),
- }
- }
- #[cfg(not(windows))]
- {
- path.into_c_string()
- }
-}
-
-pub fn cstring_to_repo_path<T: IntoCString>(path: T) -> Result<CString, Error> {
- fixup_windows_path(path.into_c_string()?)
-}
-
-#[cfg(windows)]
-fn fixup_windows_path<P: Into<Vec<u8>>>(path: P) -> Result<CString, Error> {
- let mut bytes: Vec<u8> = path.into();
- for i in 0..bytes.len() {
- if bytes[i] == b'\\' {
- bytes[i] = b'/';
- }
- }
- Ok(CString::new(bytes)?)
-}
-
-#[cfg(not(windows))]
-fn fixup_windows_path(path: CString) -> Result<CString, Error> {
- Ok(path)
-}
-
-#[cfg(test)]
-mod tests {
- use super::*;
-
- macro_rules! assert_err {
- ($path:expr, $msg:expr) => {
- match path_to_repo_path(Path::new($path)) {
- Ok(_) => panic!("expected `{}` to err", $path),
- Err(e) => assert_eq!(e.message(), $msg),
- }
- };
- }
-
- macro_rules! assert_repo_path_ok {
- ($path:expr) => {
- assert_repo_path_ok!($path, $path)
- };
- ($path:expr, $expect:expr) => {
- assert_eq!(
- path_to_repo_path(Path::new($path)),
- Ok(CString::new($expect).unwrap())
- );
- };
- }
-
- #[test]
- #[cfg(windows)]
- fn path_to_repo_path_translate() {
- assert_repo_path_ok!("foo");
- assert_repo_path_ok!("foo/bar");
- assert_repo_path_ok!(r"foo\bar", "foo/bar");
- assert_repo_path_ok!(r"foo\bar\", "foo/bar/");
- }
-
- #[test]
- fn path_to_repo_path_no_weird() {
- assert_err!("", "repo path should not be empty");
- assert_err!("./foo", "repo path `./foo` should not start with `.`");
- assert_err!("../foo", "repo path `../foo` should not start with `..`");
- }
-
- #[test]
- #[cfg(not(windows))]
- fn path_to_repo_path_no_absolute() {
- assert_err!("/", "repo path `/` should be relative");
- assert_repo_path_ok!("foo/bar");
- }
-
- #[test]
- #[cfg(windows)]
- fn path_to_repo_path_no_absolute() {
- assert_err!(
- r"c:",
- r"repo path `c:` should be relative, not a windows prefix"
- );
- assert_err!(
- r"c:\",
- r"repo path `c:\` should be relative, not a windows prefix"
- );
- assert_err!(
- r"c:temp",
- r"repo path `c:temp` should be relative, not a windows prefix"
- );
- assert_err!(
- r"\\?\UNC\a\b\c",
- r"repo path `\\?\UNC\a\b\c` should be relative, not a windows prefix"
- );
- assert_err!(
- r"\\?\c:\foo",
- r"repo path `\\?\c:\foo` should be relative, not a windows prefix"
- );
- assert_err!(
- r"\\.\COM42",
- r"repo path `\\.\COM42` should be relative, not a windows prefix"
- );
- assert_err!(
- r"\\a\b",
- r"repo path `\\a\b` should be relative, not a windows prefix"
- );
- assert_err!(r"\", r"repo path `\` should be relative");
- assert_err!(r"/", r"repo path `/` should be relative");
- assert_err!(r"\foo", r"repo path `\foo` should be relative");
- assert_err!(r"/foo", r"repo path `/foo` should be relative");
- }
-}