committed by
GitHub
parent
0e8926453a
commit
cdfcea6ba8
@@ -1,7 +1,7 @@
|
|||||||
use crate::error::TopgradeError;
|
use crate::error::{SkipStep, TopgradeError};
|
||||||
use crate::executor::{CommandExt, RunType};
|
use crate::executor::{CommandExt, RunType};
|
||||||
use crate::terminal::print_separator;
|
use crate::terminal::print_separator;
|
||||||
use crate::utils::{which, HumanizedPath};
|
use crate::utils::which;
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use console::style;
|
use console::style;
|
||||||
use futures::future::{join_all, Future};
|
use futures::future::{join_all, Future};
|
||||||
@@ -14,6 +14,9 @@ use std::process::Command;
|
|||||||
use tokio::runtime::Runtime;
|
use tokio::runtime::Runtime;
|
||||||
use tokio_process::CommandExt as TokioCommandExt;
|
use tokio_process::CommandExt as TokioCommandExt;
|
||||||
|
|
||||||
|
#[cfg(windows)]
|
||||||
|
static PATH_PREFIX: &str = "\\\\?\\";
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Git {
|
pub struct Git {
|
||||||
git: Option<PathBuf>,
|
git: Option<PathBuf>,
|
||||||
@@ -56,6 +59,18 @@ impl Git {
|
|||||||
|
|
||||||
debug!("Checking if {} is a git repository", path.display());
|
debug!("Checking if {} is a git repository", path.display());
|
||||||
|
|
||||||
|
#[cfg(windows)]
|
||||||
|
let path = {
|
||||||
|
let mut path_string = path.into_os_string().to_string_lossy().into_owned();
|
||||||
|
if path_string.starts_with(PATH_PREFIX) {
|
||||||
|
path_string.replace_range(0..PATH_PREFIX.len(), "");
|
||||||
|
}
|
||||||
|
|
||||||
|
debug!("Transformed path to {}", path_string);
|
||||||
|
|
||||||
|
path_string
|
||||||
|
};
|
||||||
|
|
||||||
if let Some(git) = &self.git {
|
if let Some(git) = &self.git {
|
||||||
let output = Command::new(&git)
|
let output = Command::new(&git)
|
||||||
.args(&["rev-parse", "--show-toplevel"])
|
.args(&["rev-parse", "--show-toplevel"])
|
||||||
@@ -82,7 +97,7 @@ impl Git {
|
|||||||
extra_arguments: &Option<String>,
|
extra_arguments: &Option<String>,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
if repositories.repositories.is_empty() {
|
if repositories.repositories.is_empty() {
|
||||||
return Ok(());
|
return Err(SkipStep.into());
|
||||||
}
|
}
|
||||||
|
|
||||||
let git = self.git.as_ref().unwrap();
|
let git = self.git.as_ref().unwrap();
|
||||||
@@ -93,7 +108,7 @@ impl Git {
|
|||||||
repositories
|
repositories
|
||||||
.repositories
|
.repositories
|
||||||
.iter()
|
.iter()
|
||||||
.for_each(|repo| println!("Would pull {}", HumanizedPath::from(std::path::Path::new(&repo))));
|
.for_each(|repo| println!("Would pull {}", &repo));
|
||||||
|
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
@@ -103,7 +118,7 @@ impl Git {
|
|||||||
.iter()
|
.iter()
|
||||||
.map(|repo| {
|
.map(|repo| {
|
||||||
let repo = repo.clone();
|
let repo = repo.clone();
|
||||||
let path = format!("{}", HumanizedPath::from(std::path::Path::new(&repo)));
|
let path = repo.to_string();
|
||||||
let before_revision = get_head_revision(git, &repo);
|
let before_revision = get_head_revision(git, &repo);
|
||||||
let cloned_git = git.to_owned();
|
let cloned_git = git.to_owned();
|
||||||
|
|
||||||
|
|||||||
87
src/utils.rs
87
src/utils.rs
@@ -4,8 +4,8 @@ use anyhow::Result;
|
|||||||
use log::{debug, error};
|
use log::{debug, error};
|
||||||
use std::env;
|
use std::env;
|
||||||
use std::ffi::OsStr;
|
use std::ffi::OsStr;
|
||||||
use std::fmt::{self, Debug};
|
use std::fmt::Debug;
|
||||||
use std::path::{Component, Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
use std::process::{ExitStatus, Output};
|
use std::process::{ExitStatus, Output};
|
||||||
use which_crate;
|
use which_crate;
|
||||||
|
|
||||||
@@ -93,93 +93,10 @@ pub fn sudo() -> Option<PathBuf> {
|
|||||||
which("sudo").or_else(|| which("pkexec"))
|
which("sudo").or_else(|| which("pkexec"))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// `std::fmt::Display` implementation for `std::path::Path`.
|
|
||||||
///
|
|
||||||
/// This struct differs from `std::path::Display` in that in Windows it takes care of printing backslashes
|
|
||||||
/// instead of slashes and don't print the `\\?` prefix in long paths.
|
|
||||||
pub struct HumanizedPath<'a> {
|
|
||||||
path: &'a Path,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> From<&'a Path> for HumanizedPath<'a> {
|
|
||||||
fn from(path: &'a Path) -> Self {
|
|
||||||
Self { path }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> fmt::Display for HumanizedPath<'a> {
|
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
||||||
if cfg!(windows) {
|
|
||||||
let mut iterator = self.path.components().peekable();
|
|
||||||
|
|
||||||
while let Some(component) = iterator.next() {
|
|
||||||
let mut print_seperator = iterator.peek().is_some();
|
|
||||||
|
|
||||||
match &component {
|
|
||||||
Component::Normal(c) if *c == "?" => {
|
|
||||||
print_seperator = false;
|
|
||||||
}
|
|
||||||
Component::RootDir | Component::CurDir => {
|
|
||||||
print_seperator = false;
|
|
||||||
}
|
|
||||||
Component::ParentDir => {
|
|
||||||
write!(f, "..")?;
|
|
||||||
}
|
|
||||||
Component::Prefix(p) => {
|
|
||||||
write!(f, "{}", p.as_os_str().to_string_lossy())?;
|
|
||||||
print_seperator = true;
|
|
||||||
}
|
|
||||||
Component::Normal(c) => {
|
|
||||||
write!(f, "{}", c.to_string_lossy())?;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
if print_seperator {
|
|
||||||
write!(f, "{}", std::path::MAIN_SEPARATOR)?;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
write!(f, "{}", self.path.display())?;
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn editor() -> String {
|
pub fn editor() -> String {
|
||||||
env::var("EDITOR").unwrap_or_else(|_| String::from(if cfg!(windows) { "notepad" } else { "vi" }))
|
env::var("EDITOR").unwrap_or_else(|_| String::from(if cfg!(windows) { "notepad" } else { "vi" }))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
#[cfg(windows)]
|
|
||||||
mod tests {
|
|
||||||
use super::*;
|
|
||||||
|
|
||||||
fn humanize<P: AsRef<Path>>(path: P) -> String {
|
|
||||||
format!("{}", HumanizedPath::from(path.as_ref()))
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_just_drive() {
|
|
||||||
assert_eq!("C:\\", humanize("C:\\"));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_path() {
|
|
||||||
assert_eq!("C:\\hi", humanize("C:\\hi"));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_unc() {
|
|
||||||
assert_eq!("\\\\server\\share\\", humanize("\\\\server\\share"));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_long_path() {
|
|
||||||
assert_eq!("C:\\hi", humanize("//?/C:/hi"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn require<T: AsRef<OsStr> + Debug>(binary_name: T) -> Result<PathBuf> {
|
pub fn require<T: AsRef<OsStr> + Debug>(binary_name: T) -> Result<PathBuf> {
|
||||||
match which_crate::which(&binary_name) {
|
match which_crate::which(&binary_name) {
|
||||||
Ok(path) => {
|
Ok(path) => {
|
||||||
|
|||||||
Reference in New Issue
Block a user