From c8f3364c742c3528ee0709a44e82643fee2f8afe Mon Sep 17 00:00:00 2001 From: Mx Kookie Date: Wed, 6 Jan 2021 23:04:53 +0100 Subject: octopus: supergit: add interface to query specific store paths --- apps/servers/octopus/supergit/src/bin/test.rs | 57 +++-- apps/servers/octopus/supergit/src/branch.rs | 6 +- apps/servers/octopus/supergit/src/commit.rs | 6 +- apps/servers/octopus/supergit/src/files.rs | 268 --------------------- .../servers/octopus/supergit/src/files/explorer.rs | 9 + apps/servers/octopus/supergit/src/files/mod.rs | 15 ++ apps/servers/octopus/supergit/src/files/tree.rs | 104 ++++++++ .../octopus/supergit/src/files/tree_utils.rs | 61 +++++ apps/servers/octopus/supergit/src/lib.rs | 14 +- apps/servers/octopus/supergit/src/old-files.rs | 232 ++++++++++++++++++ apps/servers/octopus/supergit/src/repo.rs | 4 +- 11 files changed, 469 insertions(+), 307 deletions(-) delete mode 100644 apps/servers/octopus/supergit/src/files.rs create mode 100644 apps/servers/octopus/supergit/src/files/explorer.rs create mode 100644 apps/servers/octopus/supergit/src/files/mod.rs create mode 100644 apps/servers/octopus/supergit/src/files/tree.rs create mode 100644 apps/servers/octopus/supergit/src/files/tree_utils.rs create mode 100644 apps/servers/octopus/supergit/src/old-files.rs (limited to 'apps/servers/octopus') diff --git a/apps/servers/octopus/supergit/src/bin/test.rs b/apps/servers/octopus/supergit/src/bin/test.rs index 6b9a67b75813..78367ea2c6bc 100644 --- a/apps/servers/octopus/supergit/src/bin/test.rs +++ b/apps/servers/octopus/supergit/src/bin/test.rs @@ -1,33 +1,38 @@ //! A test binary to use during development -use std::sync::mpsc::channel; -use supergit::{BranchCommit, Repository}; +// use std::sync::mpsc::channel; +// use supergit::{BranchCommit, Repository}; -fn main() { - let path = match std::env::args().nth(1) { - Some(p) => p, - None => { - eprintln!("USAGE: supergit-test "); - std::process::exit(2); - } - }; +// fn main() { +// let path = match std::env::args().nth(1) { +// Some(p) => p, +// None => { +// eprintln!("USAGE: supergit-test "); +// std::process::exit(2); +// } +// }; + +// let repo = Repository::open(path.as_str()).unwrap(); +// let branches = repo.branches().unwrap(); +// let main = branches +// .into_iter() +// .filter(|b| b.name() == Some("master".to_string())) +// .nth(0) +// .unwrap(); - let repo = Repository::open(path.as_str()).unwrap(); - let branches = repo.branches().unwrap(); - let main = branches - .into_iter() - .filter(|b| b.name() == Some("master".to_string())) - .nth(0) - .unwrap(); +// let head = main.get_head(); +// let tree = head.get_tree(); + +// println!( +// "{:#?}", +// tree.history(main.get_all(), "Cargo.toml") +// .into_iter() +// .map(|c| c.summary()) +// .collect::>() +// ); +// } - let head = main.get_head(); - let tree = head.get_tree(); + +fn main() { - println!( - "{:#?}", - tree.history(main.get_all(), "Cargo.toml") - .into_iter() - .map(|c| c.summary()) - .collect::>() - ); } diff --git a/apps/servers/octopus/supergit/src/branch.rs b/apps/servers/octopus/supergit/src/branch.rs index bbbf96dbf2c5..7d62941bdb51 100644 --- a/apps/servers/octopus/supergit/src/branch.rs +++ b/apps/servers/octopus/supergit/src/branch.rs @@ -1,3 +1,5 @@ +//! Type system for working with git branches + use crate::{Commit, HashId}; use atomptr::AtomPtr; use git2::Repository; @@ -114,7 +116,7 @@ impl Branch { } /// Get the current HEAD commit - pub fn get_head(&self) -> Commit { + pub fn head(&self) -> Commit { Commit::new(&self.repo, self.head.clone()).unwrap() } @@ -326,7 +328,7 @@ pub enum IterMode { BreadthFirst, } -/// the limit applied to a branch segment +/// Limiter applied to a branch segment pub enum SegLimit { /// No limit, enumerating all children None, diff --git a/apps/servers/octopus/supergit/src/commit.rs b/apps/servers/octopus/supergit/src/commit.rs index 99c4dbba6fce..58b57ce22f73 100644 --- a/apps/servers/octopus/supergit/src/commit.rs +++ b/apps/servers/octopus/supergit/src/commit.rs @@ -1,4 +1,4 @@ -use crate::{Diff, FileTree, HashId}; +use crate::{files::FileTree, Diff, HashId}; use git2::Repository; use std::sync::Arc; @@ -67,8 +67,8 @@ impl Commit { } /// Get the file tree for this commit - pub fn get_tree(&self) -> Arc { - FileTree::new(&self.repo, self.id.clone()) + pub fn tree(&self) -> FileTree { + FileTree::new(Arc::clone(&self.repo), self.id.clone()) } /// Get the list of paths in the repository touched by this commit diff --git a/apps/servers/octopus/supergit/src/files.rs b/apps/servers/octopus/supergit/src/files.rs deleted file mode 100644 index c593a4923921..000000000000 --- a/apps/servers/octopus/supergit/src/files.rs +++ /dev/null @@ -1,268 +0,0 @@ -use crate::{Branch, BranchIter, Commit, HashId}; -use atomptr::AtomPtr; -use git2::{ObjectType, TreeWalkMode, TreeWalkResult}; -use std::collections::{BTreeMap, BTreeSet}; -use std::{path::PathBuf, sync::Arc}; - -/// A tree of files -pub struct FileTree { - repo: Arc, - tree: AtomPtr>>, -} - -impl FileTree { - /// Utility function to create a tree, and then parse it too - pub(crate) fn new(repo: &Arc, commit: HashId) -> Arc { - Arc::new(Self { - repo: Arc::clone(repo), - tree: AtomPtr::new(BTreeMap::new()), - }) - .parse(commit) - } - - /// Parse a tree from a specific commit - pub(crate) fn parse(self: Arc, commit: HashId) -> Arc { - let mut new_tree = BTreeMap::new(); - - let tree = (&self.repo) - .find_commit(commit.to_oid()) - .unwrap() - .tree() - .unwrap(); - - tree.walk(TreeWalkMode::PreOrder, |p, entry| { - let path_segs: Vec<_> = p.split("/").filter(|s| s != &"").collect(); - let path = if path_segs.len() == 0 { - None - } else { - Some(path_segs) - }; - - let te = TreeEntry::generate(path, entry); - new_tree.insert(te.path(), Arc::new(te)); - TreeWalkResult::Ok - }) - .unwrap(); - - // Add a special entry for the root of the repo - new_tree.insert( - "".into(), - Arc::new(TreeEntry::Dir(Directory { - id: tree.id().into(), - path: "".into(), - name: "".into(), - })), - ); - - // This is needed to make borrowchk shut up - drop(tree); - - // Atomicly swap new tree into place - self.tree.swap(new_tree); - - self - } - - fn get_entry(&self, path: &str) -> Option> { - self.tree.get_ref().get(path).map(|e| Arc::clone(&e)) - } - - /// Load a file entry in this `FileTree` from disk - /// - /// When calling this function on a directory, nothing will happen - /// (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 { - self.get_entry(path).and_then(|e| e.load(&self.repo)) - } - - /// Get the history of a path with a branch iterator - /// - /// This function is very computationally intensive, because it - /// will step through the entire iterator to pull commits from, - /// and see if they touch the respective path. - pub fn history(&self, iter: BranchIter, path: &str) -> Vec { - iter.filter_map(|c| { - if c.commit() - .get_paths() - .into_iter() - .collect::>() - .contains(path) - { - Some(c.commit().clone()) - } else { - None - } - }) - .collect() - } -} - -/// Data yielded from loading a part of the file tree -/// -/// 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. -/// -/// To get all children of a subtree, use `Yield::into_tree()` to -/// create a new, recursive `FileTree` to enumerate. -#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)] -pub enum Yield { - /// Load a single file into a buffer - File(Vec), - /// Enumerate children in a directory - Dir(Vec), -} - -enum TreeEntry { - /// A single file - File(File), - /// A sub-tree - Dir(Directory), -} - -impl TreeEntry { - fn generate(path_segments: Option>, entry: &git2::TreeEntry) -> Self { - let path = path_segments.map_or("".into(), |p| path_segs_join(p)); - let id = entry.id().into(); - let name = entry.name().unwrap().into(); - - match entry.kind() { - Some(ObjectType::Blob) => Self::File(File::new(id, path, name)), - Some(ObjectType::Tree) => Self::Dir(Directory::new(id, path, name)), - _ => unimplemented!(), - } - } - - fn load(&self, repo: &Arc) -> Option { - let id = self.id(); - - match self { - Self::File(ref f) => repo - .find_blob(id.into()) - .ok() - .map(|b| Yield::File(b.content().into())), - Self::Dir(ref d) => repo - .find_tree(id.into()) - .ok() - .map(|tree| { - let mut children = vec![]; - - // Iterate the tree, but only as long as there are no - // additional path segments - tree.walk(TreeWalkMode::PreOrder, |p, entry| { - let path_segs: Vec<_> = p.split("/").filter(|s| s != &"").collect(); - 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 - let path = PathBuf::new().join(self.path()).join(entry.name().unwrap()); - children.push(path.as_path().to_str().unwrap().into()); - TreeWalkResult::Ok - } - }); - - children - }) - .map(|c| Yield::Dir(c)), - } - } - - fn is_file(&self) -> bool { - match self { - Self::File(_) => true, - Self::Dir(_) => false, - } - } - - fn id(&self) -> HashId { - match self { - Self::File(ref f) => f.id.clone(), - Self::Dir(ref d) => d.id.clone(), - } - } - - /// Get the repo-internal path (including name) - /// - /// This is used to index files in a file tree, to allow O(1) - /// access to deeply nested items. - fn path(&self) -> String { - match self { - Self::File(ref f) => PathBuf::new().join(&f.path).join(&f.name), - Self::Dir(ref d) => PathBuf::new().join(&d.path).join(&d.name), - } - .as_path() - .to_str() - .unwrap() - .into() - } -} - -struct File { - id: HashId, - path: String, - name: String, -} - -impl File { - fn new(id: HashId, path: String, name: String) -> Self { - Self { id, path, name } - } -} - -struct Directory { - id: HashId, - path: String, - name: String, -} - -impl Directory { - fn new(id: HashId, path: String, name: String) -> Self { - Self { id, path, name } - } - - fn enumerate(&self, repo: git2::Repository) -> Vec { - vec![] - } -} - -//////////////////////////////// - -/// Take a vector of path segments, and turn it into a valid offset path -/// -/// There are tests to make sure this function works properly. -/// Following are some example transformations. -/// -/// * vec![] -> "" -/// * vec!["foo"] -> "foo" -/// * vec!["foo", "bar", "baz"] -> "foo/bar/baz" -fn path_segs_join(segments: Vec<&str>) -> String { - segments - .into_iter() - .fold(PathBuf::new(), |buf, seg| buf.join(seg)) - .as_path() - .to_str() - .unwrap() - .to_owned() -} - -#[test] -fn empty_path() { - assert_eq!(path_segs_join(vec![]), String::from("")); -} - -#[test] -fn one_path() { - assert_eq!(path_segs_join(vec!["foo".into()]), String::from("foo")); -} - -#[test] -fn nested_path() { - assert_eq!( - path_segs_join(vec!["foo".into(), "bar".into(), "baz".into()]), - String::from("foo/bar/baz") - ); -} diff --git a/apps/servers/octopus/supergit/src/files/explorer.rs b/apps/servers/octopus/supergit/src/files/explorer.rs new file mode 100644 index 000000000000..89ad461b8ade --- /dev/null +++ b/apps/servers/octopus/supergit/src/files/explorer.rs @@ -0,0 +1,9 @@ + +/// +pub struct Explorer {} + +/// +pub struct Yield {} + +/// +pub enum YieldType {} diff --git a/apps/servers/octopus/supergit/src/files/mod.rs b/apps/servers/octopus/supergit/src/files/mod.rs new file mode 100644 index 000000000000..d278818b23ab --- /dev/null +++ b/apps/servers/octopus/supergit/src/files/mod.rs @@ -0,0 +1,15 @@ +//! File tree abstractions +//! +//! The supergit files API is split into two parts: `FileTree`, which +//! is mostly used internally and only exposed to allow external tools +//! to rely on the same indexing mechanism as supergit, and +//! `Explorer`, which is a high-level API for loading trees for +//! specific commits. +//! + +pub(self) mod tree_utils; +mod tree; +pub use tree::{FileTree, TreeEntry, EntryType}; + +mod explorer; +pub use explorer::{Explorer, Yield, YieldType}; diff --git a/apps/servers/octopus/supergit/src/files/tree.rs b/apps/servers/octopus/supergit/src/files/tree.rs new file mode 100644 index 000000000000..5f4fb6671aa5 --- /dev/null +++ b/apps/servers/octopus/supergit/src/files/tree.rs @@ -0,0 +1,104 @@ +//! Low-level abstraction over finding refs inside a commit tree + +use super::tree_utils as utils; +use crate::HashId; +use git2::{ObjectType, Repository, TreeWalkMode, TreeWalkResult}; +use std::sync::Arc; + +/// A git directory tree walker abstraction +/// +/// This type is meant to be used ephemerally, and internally uses the +/// libgit2 `Tree` abstraction to walk directory trees lazily to +/// resolve paths to [`TreeEntry`](self::TreeEntry)'s. +/// +/// Note: this type _may_ be removed in the future. For a more +/// high-level (and stable) API, check +/// [`Explorer`](crate::files::Explorer) +pub struct FileTree { + repo: Arc, + c: HashId, +} + +impl FileTree { + /// Construct a new FileTree with a repository + pub(crate) fn new(repo: Arc, c: HashId) -> Self { + Self { repo, c } + } + + /// Resolve a path inside this file tree + /// + /// Will return `None` if there is no tree for the selected + /// commit, or the file inside the tree does not exist. + pub fn resolve(&self, path: &str) -> Option { + let tree = utils::open_tree(&self.repo, &self.c)?; + let target = utils::path_split(path); + + // Initialise entry to None as a fallback + let mut entry = None; + + // Walk over tree and swallor errors (which we use to + // terminace traversal to speed up indexing time) + let _ = tree.walk(TreeWalkMode::PreOrder, |p, e| { + if utils::path_cmp(&target, p, e.name().unwrap()) { + entry = Some(TreeEntry::new(p, &e)); + TreeWalkResult::Ok + } else { + TreeWalkResult::Skip + } + }); + + // Return whatever the entry is now + entry + } +} + +/// An entry in a commit tree +/// +/// This type is lazily loaded, and can represent either a Blob or a +/// Directory. You can resolve its value by calling +/// [`resolve()`](Self::resolve) +pub struct TreeEntry { + tt: EntryType, + id: HashId, + path: String, +} + +impl TreeEntry { + fn new(path: &str, entry: &git2::TreeEntry) -> Self { + let tt = match entry.kind() { + Some(ObjectType::Blob) => EntryType::File, + Some(ObjectType::Tree) => EntryType::Dir, + _ => unimplemented!(), + }; + let id = entry.id().into(); + let path = path.into(); + + Self { tt, id, path } + } + + /// Resolve this type to a [`Yield`]() + pub fn resolve(&self) {} +} + +/// Type of a TreeEntry +pub enum EntryType { + /// A file that can be loaded + File, + /// A directory that can be indexed + Dir, +} + +#[test] +fn index_tree() { + let path = env!("CARGO_MANIFEST_DIR").to_owned() + "/test-repo"; + use crate::Repository as Repo; + + eprintln!("Path: `{}`", path); + + let r = Repo::open(&path).unwrap(); + let b = r.branch("master".into()).unwrap(); + let h = b.head(); + + let t = h.tree(); + t.resolve("README".into()).unwrap(); +} diff --git a/apps/servers/octopus/supergit/src/files/tree_utils.rs b/apps/servers/octopus/supergit/src/files/tree_utils.rs new file mode 100644 index 000000000000..55a6c2e0ffab --- /dev/null +++ b/apps/servers/octopus/supergit/src/files/tree_utils.rs @@ -0,0 +1,61 @@ +//! A set of tree utilities used internally in the tree.rs module + +use crate::HashId; +use git2::{Repository, Tree}; +use std::{path::PathBuf, sync::Arc}; + +/// Take a vector of path segments, and turn it into a valid offset path +/// +/// There are tests to make sure this function works properly. +/// Following are some example transformations. +/// +/// * vec![] -> "" +/// * vec!["foo"] -> "foo" +/// * vec!["foo", "bar", "baz"] -> "foo/bar/baz" +pub(super) fn path_segs_join(segments: Vec<&str>) -> String { + segments + .into_iter() + .fold(PathBuf::new(), |buf, seg| buf.join(seg)) + .as_path() + .to_str() + .unwrap() + .to_owned() +} + +/// Take an offset path inside the repository and split it into a vec +pub(super) fn path_split(path: &str) -> Vec<&str> { + path.split("/").filter(|s| s != &"").collect() +} + +/// Compare a path and entry to a target buffer +pub(super) fn path_cmp(target: &Vec<&str>, path: &str, entry: &str) -> bool { + let mut buf = path_split(path); + buf.push(entry); + + eprintln!("{:?}", buf); + + target == &buf +} + +/// Open a tree for a particular commit +pub(super) fn open_tree<'r>(repo: &'r Arc, c: &HashId) -> Option> { + repo.find_commit(c.to_oid()).unwrap().tree().ok() +} + +#[test] +fn empty_path() { + assert_eq!(path_segs_join(vec![]), String::from("")); +} + +#[test] +fn one_path() { + assert_eq!(path_segs_join(vec!["foo".into()]), String::from("foo")); +} + +#[test] +fn nested_path() { + assert_eq!( + path_segs_join(vec!["foo".into(), "bar".into(), "baz".into()]), + String::from("foo/bar/baz") + ); +} diff --git a/apps/servers/octopus/supergit/src/lib.rs b/apps/servers/octopus/supergit/src/lib.rs index 17c9094c32dd..e7414c2862a7 100644 --- a/apps/servers/octopus/supergit/src/lib.rs +++ b/apps/servers/octopus/supergit/src/lib.rs @@ -15,8 +15,7 @@ //! are very computationally intensive, and will be marked with their //! runtime cost. -mod branch; -pub use branch::{Branch, BranchIter, BranchCommit}; +pub mod branch; mod commit; pub use commit::Commit; @@ -28,8 +27,11 @@ mod repo; pub(crate) use repo::HashId; pub use repo::Repository; -mod files; -pub use files::{Yield, FileTree}; +pub mod files; -use async_std::sync::{Arc, RwLock}; -use std::sync::atomic::{AtomicUsize, Ordering}; +/// Contains all core functions and types in supergit +pub mod prelude { + pub use crate::branch::{Branch, BranchIter}; + pub use crate::files::{EntryType, Explorer, TreeEntry}; + pub use crate::{Commit, Diff, Repository}; +} diff --git a/apps/servers/octopus/supergit/src/old-files.rs b/apps/servers/octopus/supergit/src/old-files.rs new file mode 100644 index 000000000000..a4b10513c7fb --- /dev/null +++ b/apps/servers/octopus/supergit/src/old-files.rs @@ -0,0 +1,232 @@ +use crate::{Branch, BranchIter, Commit, HashId}; +use atomptr::AtomPtr; +use git2::{ObjectType, TreeWalkMode, TreeWalkResult}; +use std::collections::{BTreeMap, BTreeSet}; +use std::{path::PathBuf, sync::Arc}; + +/// A tree of files +pub struct FileTree { + repo: Arc, + tree: AtomPtr>>, +} + +impl FileTree { + /// Utility function to create a tree, and then parse it too + pub(crate) fn new(repo: &Arc, commit: HashId) -> Arc { + Arc::new(Self { + repo: Arc::clone(repo), + tree: AtomPtr::new(BTreeMap::new()), + }) + .parse(commit) + } + + /// Parse a tree from a specific commit + pub(crate) fn parse(self: Arc, commit: HashId) -> Arc { + let mut new_tree = BTreeMap::new(); + + let tree = (&self.repo) + .find_commit(commit.to_oid()) + .unwrap() + .tree() + .unwrap(); + + tree.walk(TreeWalkMode::PreOrder, |p, entry| { + let path_segs: Vec<_> = p.split("/").filter(|s| s != &"").collect(); + let path = if path_segs.len() == 0 { + None + } else { + Some(path_segs) + }; + + let te = TreeEntry::generate(path, entry); + new_tree.insert(te.path(), Arc::new(te)); + TreeWalkResult::Ok + }) + .unwrap(); + + // Add a special entry for the root of the repo + new_tree.insert( + "".into(), + Arc::new(TreeEntry::Dir(Directory { + id: tree.id().into(), + path: "".into(), + name: "".into(), + })), + ); + + // This is needed to make borrowchk shut up + drop(tree); + + // Atomicly swap new tree into place + self.tree.swap(new_tree); + + self + } + + fn get_entry(&self, path: &str) -> Option> { + self.tree.get_ref().get(path).map(|e| Arc::clone(&e)) + } + + /// Load a file entry in this `FileTree` from disk + /// + /// When calling this function on a directory, nothing will happen + /// (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 { + self.get_entry(path).and_then(|e| e.load(&self.repo)) + } + + /// Get the history of a path with a branch iterator + /// + /// This function is very computationally intensive, because it + /// will step through the entire iterator to pull commits from, + /// and see if they touch the respective path. + pub fn history(&self, iter: BranchIter, path: &str) -> Vec { + iter.filter_map(|c| { + if c.commit() + .get_paths() + .into_iter() + .collect::>() + .contains(path) + { + Some(c.commit().clone()) + } else { + None + } + }) + .collect() + } +} + +/// Data yielded from loading a part of the file tree +/// +/// 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. +/// +/// To get all children of a subtree, use `Yield::into_tree()` to +/// create a new, recursive `FileTree` to enumerate. +#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)] +pub enum Yield { + /// Load a single file into a buffer + File(Vec), + /// Enumerate children in a directory + Dir(Vec), +} + +enum TreeEntry { + /// A single file + File(File), + /// A sub-tree + Dir(Directory), +} + +impl TreeEntry { + fn generate(path_segments: Option>, entry: &git2::TreeEntry) -> Self { + let path = path_segments.map_or("".into(), |p| path_segs_join(p)); + let id = entry.id().into(); + let name = entry.name().unwrap().into(); + + match entry.kind() { + Some(ObjectType::Blob) => Self::File(File::new(id, path, name)), + Some(ObjectType::Tree) => Self::Dir(Directory::new(id, path, name)), + _ => unimplemented!(), + } + } + + fn load(&self, repo: &Arc) -> Option { + let id = self.id(); + + match self { + Self::File(ref f) => repo + .find_blob(id.into()) + .ok() + .map(|b| Yield::File(b.content().into())), + Self::Dir(ref d) => repo + .find_tree(id.into()) + .ok() + .map(|tree| { + let mut children = vec![]; + + // Iterate the tree, but only as long as there are no + // additional path segments + tree.walk(TreeWalkMode::PreOrder, |p, entry| { + let path_segs: Vec<_> = p.split("/").filter(|s| s != &"").collect(); + 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 + let path = PathBuf::new().join(self.path()).join(entry.name().unwrap()); + children.push(path.as_path().to_str().unwrap().into()); + TreeWalkResult::Ok + } + }); + + children + }) + .map(|c| Yield::Dir(c)), + } + } + + fn is_file(&self) -> bool { + match self { + Self::File(_) => true, + Self::Dir(_) => false, + } + } + + fn id(&self) -> HashId { + match self { + Self::File(ref f) => f.id.clone(), + Self::Dir(ref d) => d.id.clone(), + } + } + + /// Get the repo-internal path (including name) + /// + /// This is used to index files in a file tree, to allow O(1) + /// access to deeply nested items. + fn path(&self) -> String { + match self { + Self::File(ref f) => PathBuf::new().join(&f.path).join(&f.name), + Self::Dir(ref d) => PathBuf::new().join(&d.path).join(&d.name), + } + .as_path() + .to_str() + .unwrap() + .into() + } +} + +struct File { + id: HashId, + path: String, + name: String, +} + +impl File { + fn new(id: HashId, path: String, name: String) -> Self { + Self { id, path, name } + } +} + +struct Directory { + id: HashId, + path: String, + name: String, +} + +impl Directory { + fn new(id: HashId, path: String, name: String) -> Self { + Self { id, path, name } + } + + fn enumerate(&self, repo: git2::Repository) -> Vec { + vec![] + } +} + +//////////////////////////////// diff --git a/apps/servers/octopus/supergit/src/repo.rs b/apps/servers/octopus/supergit/src/repo.rs index 3d802a929e77..2edc78dcecf7 100644 --- a/apps/servers/octopus/supergit/src/repo.rs +++ b/apps/servers/octopus/supergit/src/repo.rs @@ -1,6 +1,6 @@ //! Raw representation wrappers for libgit2 -use crate::{Branch, BranchCommit}; +use crate::branch::{Branch, BranchCommit}; use git2::{self, Oid}; use std::{fmt, sync::Arc}; @@ -104,7 +104,7 @@ impl Repository { /// desired one. If you want to make repeated queries onto the /// branch set, it's recommended you call `branches()`, and cache /// the data yourself. - pub fn get_branch(&self, name: String) -> Option { + pub fn branch(&self, name: String) -> Option { self.branches().ok().and_then(|ok| { ok.into_iter() .filter(|b| b.name().is_some()) -- cgit v1.2.3