Skip to content

Commit 53d2066

Browse files
authored
Merge pull request #26 from alerque/camino
Limit to Unicode, but accept more path types
2 parents 9441654 + 7d58177 commit 53d2066

File tree

4 files changed

+28
-22
lines changed

4 files changed

+28
-22
lines changed

Cargo.lock

+1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ zsh = ["completions"]
3131
lto = true
3232

3333
[dependencies]
34+
camino = "1.1"
3435
filetime = "0.2"
3536
snafu = "0.8"
3637

README.md

+1-2
Original file line numberDiff line numberDiff line change
@@ -57,11 +57,10 @@ Then use the crate functions and types in your project something like this:
5757
```rust
5858
use git_warp_time::{get_repo, reset_mtimes};
5959
use git_warp_time::{FileSet, Options};
60-
use std::path::PathBuf;
6160

6261
let repo = get_repo().unwrap();
6362
let mut paths = FileSet::new();
64-
paths.insert(PathBuf::from("foo.txt"));
63+
paths.insert("foo.txt".into());
6564
let mut opts = Options::new();
6665
opts.verbose(true).paths(Some(paths));
6766
let files = reset_mtimes(repo, opts).unwrap();

src/lib.rs

+25-20
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,11 @@
22

33
use snafu::prelude::*;
44

5+
use camino::{Utf8Path, Utf8PathBuf};
56
use filetime::FileTime;
67
use git2::{Diff, Oid, Repository};
78
use std::collections::{HashMap, HashSet};
8-
use std::path::{Path, PathBuf};
9+
use std::convert::TryInto;
910
use std::sync::{Arc, RwLock};
1011
use std::{env, fs};
1112

@@ -30,6 +31,10 @@ pub enum Error {
3031
PathError {
3132
source: std::path::StripPrefixError,
3233
},
34+
#[snafu(display("Path contains invalid Unicode:\n{}", source))]
35+
PathEncodingError {
36+
source: camino::FromPathBufError,
37+
},
3338
UnresolvedError {},
3439
}
3540

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

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

46-
pub type FileSet = HashSet<PathBuf>;
51+
pub type FileSet = HashSet<Utf8PathBuf>;
4752

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

146151
/// Convert a path relative to the current working directory to be relative to the repository root
147-
pub fn resolve_repo_path(repo: &Repository, path: &String) -> Result<PathBuf> {
148-
let cwd = env::current_dir().context(IoSnafu)?;
149-
let root = repo.workdir().context(UnresolvedSnafu)?.to_path_buf();
150-
let prefix = cwd.strip_prefix(&root).context(PathSnafu)?;
151-
let resolved_path = if Path::new(&path).is_absolute() {
152-
PathBuf::from(path.clone())
152+
pub fn resolve_repo_path(repo: &Repository, path: impl Into<Utf8PathBuf>) -> Result<Utf8PathBuf> {
153+
let path: Utf8PathBuf = path.into();
154+
let cwd: Utf8PathBuf = env::current_dir()
155+
.context(IoSnafu)?
156+
.try_into()
157+
.context(PathEncodingSnafu)?;
158+
let root = repo.workdir().context(UnresolvedSnafu)?;
159+
let prefix: Utf8PathBuf = cwd.strip_prefix(root).context(PathSnafu)?.into();
160+
let resolved_path = if path.is_absolute() {
161+
path
153162
} else {
154-
prefix.join(path.clone())
163+
prefix.join(path)
155164
};
156165
Ok(resolved_path)
157166
}
@@ -204,7 +213,7 @@ fn gather_workdir_files(repo: &Repository) -> Result<FileSet> {
204213
tree.walk(git2::TreeWalkMode::PostOrder, |dir, entry| {
205214
if let Some(name) = entry.name() {
206215
let file = format!("{}{}", dir, name);
207-
let path = Path::new(&file);
216+
let path = Utf8Path::new(&file);
208217
if path.is_dir() {
209218
return git2::TreeWalkResult::Skip;
210219
}
@@ -216,7 +225,7 @@ fn gather_workdir_files(repo: &Repository) -> Result<FileSet> {
216225
Ok(workdir_files)
217226
}
218227

219-
fn diff_affects_oid(diff: &Diff, oid: &Oid, touchable_path: &mut PathBuf) -> bool {
228+
fn diff_affects_oid(diff: &Diff, oid: &Oid, touchable_path: &mut Utf8PathBuf) -> bool {
220229
diff.deltas().any(|delta| {
221230
delta.new_file().id() == *oid
222231
&& delta
@@ -227,18 +236,14 @@ fn diff_affects_oid(diff: &Diff, oid: &Oid, touchable_path: &mut PathBuf) -> boo
227236
})
228237
}
229238

230-
fn touch_if_older(path: PathBuf, time: i64, verbose: bool) -> Result<bool> {
239+
fn touch_if_older(path: Utf8PathBuf, time: i64, verbose: bool) -> Result<bool> {
231240
let commit_time = FileTime::from_unix_time(time, 0);
232241
let metadata = fs::metadata(&path).context(IoSnafu)?;
233242
let file_mtime = FileTime::from_last_modification_time(&metadata);
234243
if file_mtime != commit_time {
235244
filetime::set_file_mtime(&path, commit_time).context(IoSnafu)?;
236245
if verbose {
237-
if let Ok(pathstring) = path.clone().into_os_string().into_string() {
238-
println!("Rewound the clock: {pathstring}");
239-
} else {
240-
return UnresolvedSnafu {}.fail();
241-
}
246+
println!("Rewound the clock: {path}");
242247
}
243248
return Ok(true);
244249
}
@@ -247,7 +252,7 @@ fn touch_if_older(path: PathBuf, time: i64, verbose: bool) -> Result<bool> {
247252

248253
fn process_touchables(repo: &Repository, touchables: FileSet, opts: &Options) -> Result<FileSet> {
249254
let touched = Arc::new(RwLock::new(FileSet::new()));
250-
let mut touchable_oids: HashMap<Oid, PathBuf> = HashMap::new();
255+
let mut touchable_oids: HashMap<Oid, Utf8PathBuf> = HashMap::new();
251256
let mut revwalk = repo.revwalk().context(LibGitSnafu)?;
252257
// See https://github.com/arkark/git-hist/blob/main/src/app/git.rs
253258
revwalk.push_head().context(LibGitSnafu)?;
@@ -261,9 +266,9 @@ fn process_touchables(repo: &Repository, touchables: FileSet, opts: &Options) ->
261266
.tree()
262267
.context(LibGitSnafu)?;
263268
touchables.iter().for_each(|path| {
264-
let touchable_path = Path::new(&path).to_path_buf();
269+
let touchable_path: Utf8PathBuf = path.into();
265270
let current_oid = latest_tree
266-
.get_path(&touchable_path)
271+
.get_path(&touchable_path.clone().into_std_path_buf())
267272
.and_then(|entry| {
268273
if let Some(git2::ObjectType::Blob) = entry.kind() {
269274
Ok(entry)

0 commit comments

Comments
 (0)