summaryrefslogtreecommitdiffstats
path: root/asyncgit/src/sync/tree.rs
diff options
context:
space:
mode:
Diffstat (limited to 'asyncgit/src/sync/tree.rs')
-rw-r--r--asyncgit/src/sync/tree.rs402
1 files changed, 201 insertions, 201 deletions
diff --git a/asyncgit/src/sync/tree.rs b/asyncgit/src/sync/tree.rs
index c975689a..5f4a4081 100644
--- a/asyncgit/src/sync/tree.rs
+++ b/asyncgit/src/sync/tree.rs
@@ -1,250 +1,250 @@
use super::CommitId;
use crate::{
- error::{Error, Result},
- sync::utils::repo,
+ error::{Error, Result},
+ sync::utils::repo,
};
use git2::{Oid, Repository, Tree};
use scopetime::scope_time;
use std::{
- cmp::Ordering,
- path::{Path, PathBuf},
+ cmp::Ordering,
+ path::{Path, PathBuf},
};
/// `tree_files` returns a list of `FileTree`
#[derive(Debug, PartialEq, Clone)]
pub struct TreeFile {
- /// path of this file
- pub path: PathBuf,
- /// unix filemode
- pub filemode: i32,
- // internal object id
- id: Oid,
+ /// path of this file
+ pub path: PathBuf,
+ /// unix filemode
+ pub filemode: i32,
+ // internal object id
+ id: Oid,
}
/// guarantees sorting the result
pub fn tree_files(
- repo_path: &str,
- commit: CommitId,
+ repo_path: &str,
+ commit: CommitId,
) -> Result<Vec<TreeFile>> {
- scope_time!("tree_files");
+ scope_time!("tree_files");
- let repo = repo(repo_path)?;
+ let repo = repo(repo_path)?;
- let commit = repo.find_commit(commit.into())?;
- let tree = commit.tree()?;
+ let commit = repo.find_commit(commit.into())?;
+ let tree = commit.tree()?;
- let mut files: Vec<TreeFile> = Vec::new();
+ let mut files: Vec<TreeFile> = Vec::new();
- tree_recurse(&repo, &PathBuf::from("./"), &tree, &mut files)?;
+ tree_recurse(&repo, &PathBuf::from("./"), &tree, &mut files)?;
- sort_file_list(&mut files);
+ sort_file_list(&mut files);
- Ok(files)
+ Ok(files)
}
fn sort_file_list(files: &mut Vec<TreeFile>) {
- files.sort_by(|a, b| path_cmp(&a.path, &b.path));
+ files.sort_by(|a, b| path_cmp(&a.path, &b.path));
}
// applies topologically order on paths sorting
fn path_cmp(a: &Path, b: &Path) -> Ordering {
- let mut comp_a = a.components().into_iter().peekable();
- let mut comp_b = b.components().into_iter().peekable();
-
- loop {
- let a = comp_a.next();
- let b = comp_b.next();
-
- let a_is_file = comp_a.peek().is_none();
- let b_is_file = comp_b.peek().is_none();
-
- if a_is_file && !b_is_file {
- return Ordering::Greater;
- } else if !a_is_file && b_is_file {
- return Ordering::Less;
- }
-
- let cmp = a.cmp(&b);
- if cmp != Ordering::Equal {
- return cmp;
- }
- }
+ let mut comp_a = a.components().into_iter().peekable();
+ let mut comp_b = b.components().into_iter().peekable();
+
+ loop {
+ let a = comp_a.next();
+ let b = comp_b.next();
+
+ let a_is_file = comp_a.peek().is_none();
+ let b_is_file = comp_b.peek().is_none();
+
+ if a_is_file && !b_is_file {
+ return Ordering::Greater;
+ } else if !a_is_file && b_is_file {
+ return Ordering::Less;
+ }
+
+ let cmp = a.cmp(&b);
+ if cmp != Ordering::Equal {
+ return cmp;
+ }
+ }
}
/// will only work on utf8 content
pub fn tree_file_content(
- repo_path: &str,
- file: &TreeFile,
+ repo_path: &str,
+ file: &TreeFile,
) -> Result<String> {
- scope_time!("tree_file_content");
+ scope_time!("tree_file_content");
- let repo = repo(repo_path)?;
+ let repo = repo(repo_path)?;
- let blob = repo.find_blob(file.id)?;
+ let blob = repo.find_blob(file.id)?;
- if blob.is_binary() {
- return Err(Error::BinaryFile);
- }
+ if blob.is_binary() {
+ return Err(Error::BinaryFile);
+ }
- let content = String::from_utf8_lossy(blob.content()).to_string();
+ let content = String::from_utf8_lossy(blob.content()).to_string();
- Ok(content)
+ Ok(content)
}
///
fn tree_recurse(
- repo: &Repository,
- path: &Path,
- tree: &Tree,
- out: &mut Vec<TreeFile>,
+ repo: &Repository,
+ path: &Path,
+ tree: &Tree,
+ out: &mut Vec<TreeFile>,
) -> Result<()> {
- out.reserve(tree.len());
-
- for e in tree {
- let p = String::from_utf8_lossy(e.name_bytes());
- let path = path.join(p.to_string());
- match e.kind() {
- Some(git2::ObjectType::Blob) => {
- let id = e.id();
- let filemode = e.filemode();
- out.push(TreeFile { path, filemode, id });
- }
- Some(git2::ObjectType::Tree) => {
- let obj = e.to_object(repo)?;
- let tree = obj.peel_to_tree()?;
- tree_recurse(repo, &path, &tree, out)?;
- }
- Some(_) | None => (),
- }
- }
- Ok(())
+ out.reserve(tree.len());
+
+ for e in tree {
+ let p = String::from_utf8_lossy(e.name_bytes());
+ let path = path.join(p.to_string());
+ match e.kind() {
+ Some(git2::ObjectType::Blob) => {
+ let id = e.id();
+ let filemode = e.filemode();
+ out.push(TreeFile { path, filemode, id });
+ }
+ Some(git2::ObjectType::Tree) => {
+ let obj = e.to_object(repo)?;
+ let tree = obj.peel_to_tree()?;
+ tree_recurse(repo, &path, &tree, out)?;
+ }
+ Some(_) | None => (),
+ }
+ }
+ Ok(())
}
#[cfg(test)]
mod tests {
- use super::*;
- use crate::sync::tests::{repo_init, write_commit_file};
- use pretty_assertions::{assert_eq, assert_ne};
-
- #[test]
- fn test_smoke() {
- let (_td, repo) = repo_init().unwrap();
- let root = repo.path().parent().unwrap();
- let repo_path = root.as_os_str().to_str().unwrap();
-
- let c1 =
- write_commit_file(&repo, "test.txt", "content", "c1");
-
- let files = tree_files(repo_path, c1).unwrap();
-
- assert_eq!(files.len(), 1);
- assert_eq!(files[0].path, PathBuf::from("./test.txt"));
-
- let c2 =
- write_commit_file(&repo, "test.txt", "content2", "c2");
-
- let content =
- tree_file_content(repo_path, &files[0]).unwrap();
- assert_eq!(&content, "content");
-
- let files_c2 = tree_files(repo_path, c2).unwrap();
-
- assert_eq!(files_c2.len(), 1);
- assert_ne!(files_c2[0], files[0]);
- }
-
- #[test]
- fn test_sorting() {
- let mut list = vec!["file", "folder/file", "folder/afile"]
- .iter()
- .map(|f| TreeFile {
- path: PathBuf::from(f),
- filemode: 0,
- id: Oid::zero(),
- })
- .collect();
-
- sort_file_list(&mut list);
-
- assert_eq!(
- list.iter()
- .map(|f| f.path.to_string_lossy())
- .collect::<Vec<_>>(),
- vec![
- String::from("folder/afile"),
- String::from("folder/file"),
- String::from("file")
- ]
- );
- }
-
- #[test]
- fn test_sorting_folders() {
- let mut list = vec!["bfolder/file", "afolder/file"]
- .iter()
- .map(|f| TreeFile {
- path: PathBuf::from(f),
- filemode: 0,
- id: Oid::zero(),
- })
- .collect();
-
- sort_file_list(&mut list);
-
- assert_eq!(
- list.iter()
- .map(|f| f.path.to_string_lossy())
- .collect::<Vec<_>>(),
- vec![
- String::from("afolder/file"),
- String::from("bfolder/file"),
- ]
- );
- }
-
- #[test]
- fn test_sorting_folders2() {
- let mut list = vec!["bfolder/sub/file", "afolder/file"]
- .iter()
- .map(|f| TreeFile {
- path: PathBuf::from(f),
- filemode: 0,
- id: Oid::zero(),
- })
- .collect();
-
- sort_file_list(&mut list);
-
- assert_eq!(
- list.iter()
- .map(|f| f.path.to_string_lossy())
- .collect::<Vec<_>>(),
- vec![
- String::from("afolder/file"),
- String::from("bfolder/sub/file"),
- ]
- );
- }
-
- #[test]
- fn test_path_cmp() {
- assert_eq!(
- path_cmp(
- &PathBuf::from("bfolder/sub/file"),
- &PathBuf::from("afolder/file")
- ),
- Ordering::Greater
- );
- }
-
- #[test]
- fn test_path_file_cmp() {
- assert_eq!(
- path_cmp(
- &PathBuf::from("a"),
- &PathBuf::from("afolder/file")
- ),
- Ordering::Greater
- );
- }
+ use super::*;
+ use crate::sync::tests::{repo_init, write_commit_file};
+ use pretty_assertions::{assert_eq, assert_ne};
+
+ #[test]
+ fn test_smoke() {
+ let (_td, repo) = repo_init().unwrap();
+ let root = repo.path().parent().unwrap();
+ let repo_path = root.as_os_str().to_str().unwrap();
+
+ let c1 =
+ write_commit_file(&repo, "test.txt", "content", "c1");
+
+ let files = tree_files(repo_path, c1).unwrap();
+
+ assert_eq!(files.len(), 1);
+ assert_eq!(files[0].path, PathBuf::from("./test.txt"));
+
+ let c2 =
+ write_commit_file(&repo, "test.txt", "content2", "c2");
+
+ let content =
+ tree_file_content(repo_path, &files[0]).unwrap();
+ assert_eq!(&content, "content");
+
+ let files_c2 = tree_files(repo_path, c2).unwrap();
+
+ assert_eq!(files_c2.len(), 1);
+ assert_ne!(files_c2[0], files[0]);
+ }
+
+ #[test]
+ fn test_sorting() {
+ let mut list = vec!["file", "folder/file", "folder/afile"]
+ .iter()
+ .map(|f| TreeFile {
+ path: PathBuf::from(f),
+ filemode: 0,
+ id: Oid::zero(),
+ })
+ .collect();
+
+ sort_file_list(&mut list);
+
+ assert_eq!(
+ list.iter()
+ .map(|f| f.path.to_string_lossy())
+ .collect::<Vec<_>>(),
+ vec![
+ String::from("folder/afile"),
+ String::from("folder/file"),
+ String::from("file")
+ ]
+ );
+ }
+
+ #[test]
+ fn test_sorting_folders() {
+ let mut list = vec!["bfolder/file", "afolder/file"]
+ .iter()
+ .map(|f| TreeFile {
+ path: PathBuf::from(f),
+ filemode: 0,
+ id: Oid::zero(),
+ })
+ .collect();
+
+ sort_file_list(&mut list);
+
+ assert_eq!(
+ list.iter()
+ .map(|f| f.path.to_string_lossy())
+ .collect::<Vec<_>>(),
+ vec![
+ String::from("afolder/file"),
+ String::from("bfolder/file"),
+ ]
+ );
+ }
+
+ #[test]
+ fn test_sorting_folders2() {
+ let mut list = vec!["bfolder/sub/file", "afolder/file"]
+ .iter()
+ .map(|f| TreeFile {
+ path: PathBuf::from(f),
+ filemode: 0,
+ id: Oid::zero(),
+ })
+ .collect();
+
+ sort_file_list(&mut list);
+
+ assert_eq!(
+ list.iter()
+ .map(|f| f.path.to_string_lossy())
+ .collect::<Vec<_>>(),
+ vec![
+ String::from("afolder/file"),
+ String::from("bfolder/sub/file"),
+ ]
+ );
+ }
+
+ #[test]
+ fn test_path_cmp() {
+ assert_eq!(
+ path_cmp(
+ &PathBuf::from("bfolder/sub/file"),
+ &PathBuf::from("afolder/file")
+ ),
+ Ordering::Greater
+ );
+ }
+
+ #[test]
+ fn test_path_file_cmp() {
+ assert_eq!(
+ path_cmp(
+ &PathBuf::from("a"),
+ &PathBuf::from("afolder/file")
+ ),
+ Ordering::Greater
+ );
+ }
}