supergit: implement typed directory yields

Previously a Yield object was either a file dump, or a simple
enumeration on a directories children, with no associated type state
for them.  This commit implements a mechanism to internally fetch this
type information, to pass out to a user via the Yield type.

This way it is much easier to figure out which entries are
directories, and which are files.  Additional queries have to be
passed into the FileTree for lookups.  In a way, this commit gives up
on the idea of having a nested API structure for the time being, until
constructing sub-FileTrees becomes a real necessity
wip/yesman
Katharina Fey 3 years ago
parent 7a7c3f0adf
commit 17bb1561b3
  1. 1
      apps/servers/octopus/supergit/src/lib.rs
  2. 59
      apps/servers/octopus/supergit/src/old-files.rs

@ -35,3 +35,4 @@ pub mod prelude {
pub use crate::files::{EntryType, Explorer, TreeEntry};
pub use crate::{Commit, Diff, Repository};
}

@ -73,8 +73,8 @@ impl FileTree {
/// (returns `None`), because directories can't be loaded. If you
/// want to get a list of children for a directory, use
/// [`FileTree::enumerate()`]() instead!
pub fn load(&self, path: &str) -> Option<Yield> {
self.get_entry(path).and_then(|e| e.load(&self.repo))
pub fn load(self: &Arc<Self>, path: &str) -> Option<Yield> {
self.get_entry(path).and_then(|e| e.load(self))
}
/// Get the history of a path with a branch iterator
@ -103,18 +103,31 @@ impl FileTree {
///
/// This type is returned when fetching a path via `FileTree::load()`,
/// and can either be a single file read into memory, or an
/// enumeration of direct children of a directory.
/// enumeration of direct children of a directory. In this case, the
/// information about child status (file or directory) is fetched
/// during creation from the underlying repository.
///
/// To get all children of a subtree, use `Yield::into_tree()` to
/// create a new, recursive `FileTree` to enumerate.
/// In order to traverse the next level of the subtree, you need to
/// append a child name to the existing path, and run
/// [`FileTree::load()`](FileTree::load) again.
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub enum Yield {
/// Load a single file into a buffer
File(Vec<u8>),
/// Enumerate children in a directory
Dir(Vec<String>),
Dir(Vec<YieldEntry>),
}
/// Simple type to disambiguate between files and directories
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub enum YieldEntry {
/// A file name
File(String),
/// A directory name
Dir(String),
}
#[derive(Debug)]
enum TreeEntry {
/// A single file
File(File),
@ -135,15 +148,16 @@ impl TreeEntry {
}
}
fn load(&self, repo: &Arc<git2::Repository>) -> Option<Yield> {
fn load(&self, ft: &Arc<FileTree>) -> Option<Yield> {
let id = self.id();
let repo = &ft.repo;
match self {
Self::File(ref f) => repo
Self::File(_) => repo
.find_blob(id.into())
.ok()
.map(|b| Yield::File(b.content().into())),
Self::Dir(ref d) => repo
Self::Dir(_) => repo
.find_tree(id.into())
.ok()
.map(|tree| {
@ -156,14 +170,22 @@ impl TreeEntry {
if path_segs.len() > 0 {
TreeWalkResult::Skip
} else {
// Take the current tree path, and append the
// name of whatever we're currently iterating
// over is
// Take the current tree path and append
// the name of the current entry on it
let path = PathBuf::new().join(self.path()).join(entry.name().unwrap());
children.push(path.as_path().to_str().unwrap().into());
let s: String = path.as_path().to_str().unwrap().into();
// Construct a YieldEntry via a FileTree lookup
children.push(if ft.get_entry(s.as_str()).unwrap().is_directory() {
YieldEntry::Dir(s)
} else {
YieldEntry::File(s)
});
TreeWalkResult::Ok
}
});
})
.unwrap();
children
})
@ -171,10 +193,10 @@ impl TreeEntry {
}
}
fn is_file(&self) -> bool {
fn is_directory(&self) -> bool {
match self {
Self::File(_) => true,
Self::Dir(_) => false,
Self::Dir(_) => true,
Self::File(_) => false,
}
}
@ -201,6 +223,7 @@ impl TreeEntry {
}
}
#[derive(Debug)]
struct File {
id: HashId,
path: String,
@ -213,6 +236,7 @@ impl File {
}
}
#[derive(Debug)]
struct Directory {
id: HashId,
path: String,
@ -224,6 +248,7 @@ impl Directory {
Self { id, path, name }
}
#[allow(unused)]
fn enumerate(&self, repo: git2::Repository) -> Vec<String> {
vec![]
}

Loading…
Cancel
Save