aboutsummaryrefslogtreecommitdiff
path: root/apps
diff options
context:
space:
mode:
authorMx Kookie <kookie@spacekookie.de>2021-01-06 23:04:53 +0100
committerMx Kookie <kookie@spacekookie.de>2021-01-06 23:04:53 +0100
commitc8f3364c742c3528ee0709a44e82643fee2f8afe (patch)
tree8c63dc68b0b9af25a138083825de424546871f6f /apps
parentfcc89b1b5bcbcb00ce02cb461b186ef0337312e3 (diff)
octopus: supergit: add interface to query specific store paths
Diffstat (limited to 'apps')
-rw-r--r--apps/servers/octopus/supergit/src/bin/test.rs57
-rw-r--r--apps/servers/octopus/supergit/src/branch.rs6
-rw-r--r--apps/servers/octopus/supergit/src/commit.rs6
-rw-r--r--apps/servers/octopus/supergit/src/files/explorer.rs9
-rw-r--r--apps/servers/octopus/supergit/src/files/mod.rs15
-rw-r--r--apps/servers/octopus/supergit/src/files/tree.rs104
-rw-r--r--apps/servers/octopus/supergit/src/files/tree_utils.rs61
-rw-r--r--apps/servers/octopus/supergit/src/lib.rs14
-rw-r--r--apps/servers/octopus/supergit/src/old-files.rs (renamed from apps/servers/octopus/supergit/src/files.rs)36
-rw-r--r--apps/servers/octopus/supergit/src/repo.rs4
10 files changed, 237 insertions, 75 deletions
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 <path>");
- std::process::exit(2);
- }
- };
+// fn main() {
+// let path = match std::env::args().nth(1) {
+// Some(p) => p,
+// None => {
+// eprintln!("USAGE: supergit-test <path>");
+// 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::<Vec<_>>()
+// );
+// }
- 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::<Vec<_>>()
- );
}
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> {
- 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/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<Repository>,
+ c: HashId,
+}
+
+impl FileTree {
+ /// Construct a new FileTree with a repository
+ pub(crate) fn new(repo: Arc<Repository>, 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<TreeEntry> {
+ 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<Repository>, c: &HashId) -> Option<Tree<'r>> {
+ 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/files.rs b/apps/servers/octopus/supergit/src/old-files.rs
index c593a4923921..a4b10513c7fb 100644
--- a/apps/servers/octopus/supergit/src/files.rs
+++ b/apps/servers/octopus/supergit/src/old-files.rs
@@ -230,39 +230,3 @@ impl Directory {
}
////////////////////////////////
-
-/// 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/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<Branch> {
+ pub fn branch(&self, name: String) -> Option<Branch> {
self.branches().ok().and_then(|ok| {
ok.into_iter()
.filter(|b| b.name().is_some())