Skip to content
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

Limit to Unicode, but accept more path types #26

Merged
merged 1 commit into from
Jul 19, 2024
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
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ zsh = ["completions"]
lto = true

[dependencies]
camino = "1.1"
filetime = "0.2"
snafu = "0.8"
snafu-cli-debug = "0.1"
Expand Down
3 changes: 1 addition & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,11 +57,10 @@ Then use the crate functions and types in your project something like this:
```rust
use git_warp_time::{get_repo, reset_mtimes};
use git_warp_time::{FileSet, Options};
use std::path::PathBuf;

let repo = get_repo().unwrap();
let mut paths = FileSet::new();
paths.insert(PathBuf::from("foo.txt"));
paths.insert("foo.txt".into());
let mut opts = Options::new();
opts.verbose(true).paths(Some(paths));
let files = reset_mtimes(repo, opts).unwrap();
Expand Down
45 changes: 25 additions & 20 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@

use snafu::prelude::*;

use camino::{Utf8Path, Utf8PathBuf};
use filetime::FileTime;
use git2::{Diff, Oid, Repository};
use std::collections::{HashMap, HashSet};
use std::path::{Path, PathBuf};
use std::convert::TryInto;
use std::sync::{Arc, RwLock};
use std::{env, fs};

Expand All @@ -30,6 +31,10 @@ pub enum Error {
PathError {
source: std::path::StripPrefixError,
},
#[snafu(display("Path contains invalid Unicode:\n{}", source))]
PathEncodingError {
source: camino::FromPathBufError,
},
UnresolvedError {},
}

Expand All @@ -43,7 +48,7 @@ impl std::fmt::Debug for Error {

pub type Result<T, E = Error> = std::result::Result<T, E>;

pub type FileSet = HashSet<PathBuf>;
pub type FileSet = HashSet<Utf8PathBuf>;

/// Options passed to `reset_mtimes()`
#[derive(Clone, Debug)]
Expand Down Expand Up @@ -144,14 +149,18 @@ pub fn get_repo() -> Result<Repository> {
}

/// Convert a path relative to the current working directory to be relative to the repository root
pub fn resolve_repo_path(repo: &Repository, path: &String) -> Result<PathBuf> {
let cwd = env::current_dir().context(IoSnafu)?;
let root = repo.workdir().context(UnresolvedSnafu)?.to_path_buf();
let prefix = cwd.strip_prefix(&root).context(PathSnafu)?;
let resolved_path = if Path::new(&path).is_absolute() {
PathBuf::from(path.clone())
pub fn resolve_repo_path(repo: &Repository, path: impl Into<Utf8PathBuf>) -> Result<Utf8PathBuf> {
let path: Utf8PathBuf = path.into();
let cwd: Utf8PathBuf = env::current_dir()
.context(IoSnafu)?
.try_into()
.context(PathEncodingSnafu)?;
let root = repo.workdir().context(UnresolvedSnafu)?;
let prefix: Utf8PathBuf = cwd.strip_prefix(root).context(PathSnafu)?.into();
let resolved_path = if path.is_absolute() {
path
} else {
prefix.join(path.clone())
prefix.join(path)
};
Ok(resolved_path)
}
Expand Down Expand Up @@ -204,7 +213,7 @@ fn gather_workdir_files(repo: &Repository) -> Result<FileSet> {
tree.walk(git2::TreeWalkMode::PostOrder, |dir, entry| {
if let Some(name) = entry.name() {
let file = format!("{}{}", dir, name);
let path = Path::new(&file);
let path = Utf8Path::new(&file);
if path.is_dir() {
return git2::TreeWalkResult::Skip;
}
Expand All @@ -216,7 +225,7 @@ fn gather_workdir_files(repo: &Repository) -> Result<FileSet> {
Ok(workdir_files)
}

fn diff_affects_oid(diff: &Diff, oid: &Oid, touchable_path: &mut PathBuf) -> bool {
fn diff_affects_oid(diff: &Diff, oid: &Oid, touchable_path: &mut Utf8PathBuf) -> bool {
diff.deltas().any(|delta| {
delta.new_file().id() == *oid
&& delta
Expand All @@ -227,18 +236,14 @@ fn diff_affects_oid(diff: &Diff, oid: &Oid, touchable_path: &mut PathBuf) -> boo
})
}

fn touch_if_older(path: PathBuf, time: i64, verbose: bool) -> Result<bool> {
fn touch_if_older(path: Utf8PathBuf, time: i64, verbose: bool) -> Result<bool> {
let commit_time = FileTime::from_unix_time(time, 0);
let metadata = fs::metadata(&path).context(IoSnafu)?;
let file_mtime = FileTime::from_last_modification_time(&metadata);
if file_mtime != commit_time {
filetime::set_file_mtime(&path, commit_time).context(IoSnafu)?;
if verbose {
if let Ok(pathstring) = path.clone().into_os_string().into_string() {
println!("Rewound the clock: {pathstring}");
} else {
return UnresolvedSnafu {}.fail();
}
println!("Rewound the clock: {path}");
}
return Ok(true);
}
Expand All @@ -247,7 +252,7 @@ fn touch_if_older(path: PathBuf, time: i64, verbose: bool) -> Result<bool> {

fn process_touchables(repo: &Repository, touchables: FileSet, opts: &Options) -> Result<FileSet> {
let touched = Arc::new(RwLock::new(FileSet::new()));
let mut touchable_oids: HashMap<Oid, PathBuf> = HashMap::new();
let mut touchable_oids: HashMap<Oid, Utf8PathBuf> = HashMap::new();
let mut revwalk = repo.revwalk().context(LibGitSnafu)?;
// See https://github.com/arkark/git-hist/blob/main/src/app/git.rs
revwalk.push_head().context(LibGitSnafu)?;
Expand All @@ -261,9 +266,9 @@ fn process_touchables(repo: &Repository, touchables: FileSet, opts: &Options) ->
.tree()
.context(LibGitSnafu)?;
touchables.iter().for_each(|path| {
let touchable_path = Path::new(&path).to_path_buf();
let touchable_path: Utf8PathBuf = path.into();
let current_oid = latest_tree
.get_path(&touchable_path)
.get_path(&touchable_path.clone().into_std_path_buf())
.and_then(|entry| {
if let Some(git2::ObjectType::Blob) = entry.kind() {
Ok(entry)
Expand Down
Loading