~iptq/garbage

ref: 02ba29053be29149ec4ca4f73cd375f02f2cf21b garbage/src/utils.rs -rw-r--r-- 2.4 KiB
02ba2905Michael Zhang fix panic problem by not converting to utf-8 all the time 1 year, 3 months ago
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
use std::env;
use std::ffi::{OsStr, OsString};
use std::fs;
use std::os::unix::ffi::OsStrExt;
use std::path::{Path, PathBuf, MAIN_SEPARATOR};

use anyhow::Result;
use percent_encoding::{AsciiSet};
use walkdir::WalkDir;

const MASK: &AsciiSet = percent_encoding::CONTROLS;

pub fn into_absolute(path: impl AsRef<Path>) -> Result<PathBuf> {
    let path = path.as_ref();

    Ok(if !path.is_absolute() {
        env::current_dir()?.canonicalize()?.join(path)
    } else {
        path.to_path_buf()
    })
}

pub fn get_uid() -> u64 {
    unsafe { libc::getuid().into() }
}

/// This function recursively copies all the contents of src into dst.
pub fn recursive_copy(src: impl AsRef<Path>, dst: impl AsRef<Path>) -> Result<()> {
    let src = src.as_ref();
    let dst = dst.as_ref();

    for entry in WalkDir::new(src)
        .contents_first(false)
        .follow_links(false)
        .same_file_system(true)
    {
        let entry = entry?;
        let path = entry.path();
        let relative_path = path.strip_prefix(src)?;

        // this must be the root
        if let None = relative_path.file_name() {
            fs::create_dir(dst)?;
            continue;
        }

        let target_name = dst.join(relative_path);
        if path.is_dir() {
            fs::create_dir(&target_name)?;
        } else {
            fs::copy(path, &target_name)?;
        }
    }

    Ok(())
}

/// Percent-encodes a path, but only the file names, not the separators.
pub fn percent_encode(path: impl AsRef<Path>) -> String {
    let path = path.as_ref();
    path.iter()
        .map(|segment| {
            percent_encoding::percent_encode(segment.as_bytes(), MASK).to_string()
        })
        .collect::<Vec<_>>()
        .join(&MAIN_SEPARATOR.to_string())
}

pub(crate) fn concat_os_str_iter<'a>(ss: &Vec<&'a OsStr>) -> OsString {
    let mut len = 0;
    for s in ss {
        len += s.len();
    }

    let mut buf = vec![0; len];
    let mut c = 0;
    for s in ss {
        let segment = &mut buf[c..c + s.len()];
        segment.copy_from_slice(s.as_bytes());
        c += s.len();
    }

    OsStr::from_bytes(&buf).to_os_string()
}

/// Concatenates an arbitrary number of OsStrs
#[macro_export]
macro_rules! concat_os_str {
    ($($str:expr),* $(,)?) => {
        {
            let _wtf = vec![
                $($str.as_ref(),)*
            ];
            crate::utils::concat_os_str_iter(&_wtf)
        }
    };
}