mirror of
https://github.com/gitbutlerapp/gitbutler.git
synced 2024-12-25 02:26:14 +03:00
add more tests
This commit is contained in:
parent
56ae8a9888
commit
be8b3e7560
@ -238,9 +238,7 @@ impl App {
|
||||
.ok_or_else(|| anyhow::anyhow!("project {} not found", project_id))?;
|
||||
|
||||
let mut sessions = vec![];
|
||||
let mut iter = gb_repository.get_sessions_iterator()?.skip(1); // skip the first session,
|
||||
// as it's the initial
|
||||
// session
|
||||
let mut iter = gb_repository.get_sessions_iterator()?;
|
||||
while let Some(session) = iter.next() {
|
||||
if let Err(e) = session {
|
||||
return Err(e);
|
||||
|
@ -193,7 +193,7 @@ impl Repository {
|
||||
}
|
||||
|
||||
let wd_tree_oid = build_wd_tree(&self, &project_repository)
|
||||
.context("failed to build workign directory tree")?;
|
||||
.context("failed to build working directory tree")?;
|
||||
let session_tree_oid = build_session_tree(&self).context("failed to build session tree")?;
|
||||
let log_tree_oid =
|
||||
build_log_tree(&self, &project_repository).context("failed to build logs tree")?;
|
||||
@ -296,10 +296,6 @@ impl Repository {
|
||||
pub(crate) fn session_wd_path(&self) -> std::path::PathBuf {
|
||||
self.session_path().join("wd")
|
||||
}
|
||||
|
||||
pub(crate) fn wd_path(&self) -> std::path::PathBuf {
|
||||
self.root().join("wd")
|
||||
}
|
||||
}
|
||||
|
||||
// build wd index from the working directory files new session wd files
|
||||
@ -363,6 +359,7 @@ fn build_wd_tree(
|
||||
}
|
||||
|
||||
let file_path = std::path::Path::new(&file_path);
|
||||
|
||||
if project_repository
|
||||
.git_repository
|
||||
.is_path_ignored(&file_path)
|
||||
|
@ -57,7 +57,7 @@ fn test_get_current_session_writer_should_use_existing_session() -> Result<()> {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_must_flush_on_init() -> Result<()> {
|
||||
fn test_must_not_return_init_session() -> Result<()> {
|
||||
let repository = test_repository()?;
|
||||
let project = test_project(&repository)?;
|
||||
let gb_repo_path = tempdir()?.path().to_str().unwrap().to_string();
|
||||
@ -72,10 +72,11 @@ fn test_must_flush_on_init() -> Result<()> {
|
||||
user_store,
|
||||
)?;
|
||||
|
||||
let iter = gb_repo.get_sessions_iterator()?;
|
||||
assert_eq!(iter.count(), 1);
|
||||
assert!(gb_repo.get_current_session()?.is_none());
|
||||
|
||||
let iter = gb_repo.get_sessions_iterator()?;
|
||||
assert_eq!(iter.count(), 0);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@ -96,10 +97,10 @@ fn test_must_not_flush_without_current_session() -> Result<()> {
|
||||
)?;
|
||||
|
||||
let session = gb_repo.flush()?;
|
||||
assert!(session.is_none());
|
||||
|
||||
let iter = gb_repo.get_sessions_iterator()?;
|
||||
assert_eq!(iter.count(), 1);
|
||||
assert!(session.is_none());
|
||||
assert_eq!(iter.count(), 0);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@ -123,10 +124,9 @@ fn test_must_flush_current_session() -> Result<()> {
|
||||
gb_repo.get_or_create_current_session()?;
|
||||
|
||||
let session = gb_repo.flush()?;
|
||||
|
||||
let iter = gb_repo.get_sessions_iterator()?;
|
||||
assert_eq!(iter.count(), 2);
|
||||
assert!(session.is_some());
|
||||
let iter = gb_repo.get_sessions_iterator()?;
|
||||
assert_eq!(iter.count(), 1);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@ -209,3 +209,72 @@ fn test_list_deltas_from_flushed_session() -> Result<()> {
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_list_files_from_current_session() -> Result<()> {
|
||||
let repository = test_repository()?;
|
||||
let project = test_project(&repository)?;
|
||||
let gb_repo_path = tempdir()?.path().to_str().unwrap().to_string();
|
||||
let storage = storage::Storage::from_path(tempdir()?.path().to_path_buf());
|
||||
let project_store = projects::Storage::new(storage.clone());
|
||||
project_store.add_project(&project)?;
|
||||
let user_store = users::Storage::new(storage);
|
||||
|
||||
// files are there before the session is created
|
||||
std::fs::write(
|
||||
repository.path().parent().unwrap().join("test.txt"),
|
||||
"Hello World",
|
||||
)?;
|
||||
|
||||
let gb_repo = gb_repository::Repository::open(
|
||||
gb_repo_path,
|
||||
project.id.clone(),
|
||||
project_store.clone(),
|
||||
user_store,
|
||||
)?;
|
||||
|
||||
let session = gb_repo.get_or_create_current_session()?;
|
||||
|
||||
let reader = gb_repo.get_session_reader(session)?;
|
||||
let files = reader.files(None)?;
|
||||
|
||||
assert_eq!(files.len(), 1);
|
||||
assert_eq!(files.get("test.txt").unwrap(), "Hello World");
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_list_files_from_flushed_session() -> Result<()> {
|
||||
let repository = test_repository()?;
|
||||
let project = test_project(&repository)?;
|
||||
let gb_repo_path = tempdir()?.path().to_str().unwrap().to_string();
|
||||
let storage = storage::Storage::from_path(tempdir()?.path().to_path_buf());
|
||||
let project_store = projects::Storage::new(storage.clone());
|
||||
project_store.add_project(&project)?;
|
||||
let user_store = users::Storage::new(storage);
|
||||
|
||||
// files are there before the session is created
|
||||
std::fs::write(
|
||||
repository.path().parent().unwrap().join("test.txt"),
|
||||
"Hello World",
|
||||
)?;
|
||||
|
||||
let gb_repo = gb_repository::Repository::open(
|
||||
gb_repo_path,
|
||||
project.id.clone(),
|
||||
project_store.clone(),
|
||||
user_store,
|
||||
)?;
|
||||
|
||||
gb_repo.get_or_create_current_session()?;
|
||||
let session = gb_repo.flush()?.unwrap();
|
||||
|
||||
let reader = gb_repo.get_session_reader(session)?;
|
||||
let files = reader.files(None)?;
|
||||
|
||||
assert_eq!(files.len(), 1);
|
||||
assert_eq!(files.get("test.txt").unwrap(), "Hello World");
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
@ -144,32 +144,34 @@ impl Reader for CommitReader<'_> {
|
||||
|
||||
fn list_files(&self, dir_path: &str) -> Result<Vec<String>> {
|
||||
let mut files: Vec<String> = Vec::new();
|
||||
let repo_root = self.repository.path().parent().unwrap();
|
||||
let dir_path = std::path::Path::new(dir_path);
|
||||
self.tree
|
||||
.walk(git2::TreeWalkMode::PreOrder, |root, entry| {
|
||||
if entry.name().is_none() {
|
||||
return git2::TreeWalkResult::Ok;
|
||||
}
|
||||
|
||||
let abs_dir_path = repo_root.join(dir_path);
|
||||
let abs_entry_path = repo_root.join(root).join(entry.name().unwrap());
|
||||
if !abs_entry_path.starts_with(&abs_dir_path) {
|
||||
return git2::TreeWalkResult::Ok;
|
||||
}
|
||||
if abs_dir_path.eq(&abs_entry_path) {
|
||||
return git2::TreeWalkResult::Ok;
|
||||
}
|
||||
if entry.kind() == Some(git2::ObjectType::Tree) {
|
||||
return git2::TreeWalkResult::Ok;
|
||||
}
|
||||
|
||||
let relpath = abs_entry_path.strip_prefix(abs_dir_path).unwrap();
|
||||
if entry.name().is_none() {
|
||||
return git2::TreeWalkResult::Ok;
|
||||
}
|
||||
let entry_path = std::path::Path::new(root).join(entry.name().unwrap());
|
||||
|
||||
files.push(relpath.to_str().unwrap().to_string());
|
||||
if !entry_path.starts_with(dir_path) {
|
||||
return git2::TreeWalkResult::Ok;
|
||||
}
|
||||
|
||||
files.push(
|
||||
entry_path
|
||||
.strip_prefix(dir_path)
|
||||
.unwrap()
|
||||
.to_str()
|
||||
.unwrap()
|
||||
.to_string(),
|
||||
);
|
||||
|
||||
git2::TreeWalkResult::Ok
|
||||
})
|
||||
.with_context(|| format!("{}: tree walk failed", dir_path))?;
|
||||
.with_context(|| format!("{}: tree walk failed", dir_path.display()))?;
|
||||
|
||||
Ok(files)
|
||||
}
|
||||
|
@ -76,6 +76,22 @@ fn test_commit_reader_read_file() -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_reader_list_files_should_return_relative() -> Result<()> {
|
||||
let dir = tempdir()?;
|
||||
|
||||
std::fs::write(dir.path().join("test1.txt"), "test")?;
|
||||
std::fs::create_dir(dir.path().join("dir"))?;
|
||||
std::fs::write(dir.path().join("dir").join("test.txt"), "test")?;
|
||||
|
||||
let reader = super::reader::DirReader::open(dir.path().to_path_buf());
|
||||
let files = reader.list_files("dir")?;
|
||||
assert_eq!(files.len(), 1);
|
||||
assert!(files.contains(&"test.txt".to_string()));
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_reader_list_files() -> Result<()> {
|
||||
let dir = tempdir()?;
|
||||
@ -85,7 +101,7 @@ fn test_reader_list_files() -> Result<()> {
|
||||
std::fs::write(dir.path().join("dir").join("test.txt"), "test")?;
|
||||
|
||||
let reader = super::reader::DirReader::open(dir.path().to_path_buf());
|
||||
let files = reader.list_files(".")?;
|
||||
let files = reader.list_files("")?;
|
||||
assert_eq!(files.len(), 2);
|
||||
assert!(files.contains(&"test.txt".to_string()));
|
||||
assert!(files.contains(&"dir/test.txt".to_string()));
|
||||
@ -93,6 +109,38 @@ fn test_reader_list_files() -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_commit_reader_list_files_should_return_relative() -> Result<()> {
|
||||
let repository = test_repository()?;
|
||||
|
||||
std::fs::write(
|
||||
&repository.path().parent().unwrap().join("test1.txt"),
|
||||
"test",
|
||||
)?;
|
||||
std::fs::create_dir(&repository.path().parent().unwrap().join("dir"))?;
|
||||
std::fs::write(
|
||||
&repository
|
||||
.path()
|
||||
.parent()
|
||||
.unwrap()
|
||||
.join("dir")
|
||||
.join("test.txt"),
|
||||
"test",
|
||||
)?;
|
||||
|
||||
let oid = commit(&repository)?;
|
||||
|
||||
std::fs::remove_dir_all(&repository.path().parent().unwrap().join("dir"))?;
|
||||
|
||||
let reader =
|
||||
super::reader::CommitReader::from_commit(&repository, repository.find_commit(oid)?)?;
|
||||
let files = reader.list_files("dir")?;
|
||||
assert_eq!(files.len(), 1);
|
||||
assert!(files.contains(&"test.txt".to_string()));
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_commit_reader_list_files() -> Result<()> {
|
||||
let repository = test_repository()?;
|
||||
@ -118,7 +166,7 @@ fn test_commit_reader_list_files() -> Result<()> {
|
||||
|
||||
let reader =
|
||||
super::reader::CommitReader::from_commit(&repository, repository.find_commit(oid)?)?;
|
||||
let files = reader.list_files(".")?;
|
||||
let files = reader.list_files("")?;
|
||||
assert_eq!(files.len(), 2);
|
||||
assert!(files.contains(&"test.txt".to_string()));
|
||||
assert!(files.contains(&"dir/test.txt".to_string()));
|
||||
|
@ -6,7 +6,7 @@ use crate::{deltas, pty, sessions};
|
||||
|
||||
use super::{
|
||||
gb_repository,
|
||||
reader::{self, Reader},
|
||||
reader::{self, CommitReader, Reader},
|
||||
writer::{self, Writer},
|
||||
};
|
||||
|
||||
@ -191,8 +191,10 @@ impl<'writer> SessionWriter<'writer> {
|
||||
}
|
||||
|
||||
pub struct SessionReader<'reader> {
|
||||
repository: &'reader gb_repository::Repository,
|
||||
// reader for the current session. commit or wd
|
||||
reader: Box<dyn reader::Reader + 'reader>,
|
||||
// reader for the previous session's commit
|
||||
previous_reader: Option<CommitReader<'reader>>,
|
||||
}
|
||||
|
||||
impl Reader for SessionReader<'_> {
|
||||
@ -229,9 +231,13 @@ impl<'reader> SessionReader<'reader> {
|
||||
.unwrap(),
|
||||
);
|
||||
if current_session_id.is_ok() && current_session_id.as_ref().unwrap() == &session.id {
|
||||
let head_commit = repository.git_repository.head()?.peel_to_commit()?;
|
||||
return Ok(SessionReader {
|
||||
reader: Box::new(wd_reader),
|
||||
repository,
|
||||
previous_reader: Some(CommitReader::from_commit(
|
||||
&repository.git_repository,
|
||||
head_commit,
|
||||
)?),
|
||||
});
|
||||
}
|
||||
|
||||
@ -251,35 +257,49 @@ impl<'reader> SessionReader<'reader> {
|
||||
.git_repository
|
||||
.find_commit(oid)
|
||||
.context("failed to get commit")?;
|
||||
let commit_reader = reader::CommitReader::from_commit(&repository.git_repository, commit)?;
|
||||
let parents_count = commit.parent_count();
|
||||
let commit_reader =
|
||||
reader::CommitReader::from_commit(&repository.git_repository, commit.clone())?;
|
||||
|
||||
let previous_reader = if parents_count > 0 {
|
||||
Some(reader::CommitReader::from_commit(
|
||||
&repository.git_repository,
|
||||
commit.parent(0)?,
|
||||
)?)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
Ok(SessionReader {
|
||||
reader: Box::new(commit_reader),
|
||||
repository,
|
||||
previous_reader,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn files(&self, paths: Option<Vec<&str>>) -> Result<HashMap<String, String>> {
|
||||
let files = self
|
||||
.reader
|
||||
.list_files(&self.repository.wd_path().to_str().unwrap())?;
|
||||
let files_with_content = files
|
||||
.iter()
|
||||
.filter(|file| {
|
||||
if let Some(paths) = paths.as_ref() {
|
||||
paths.iter().any(|path| file.starts_with(path))
|
||||
} else {
|
||||
true
|
||||
match &self.previous_reader {
|
||||
None => Ok(HashMap::new()),
|
||||
Some(previous_reader) => {
|
||||
let files = previous_reader.list_files("wd")?;
|
||||
let mut files_with_content = HashMap::new();
|
||||
for file_path in files {
|
||||
if let Some(paths) = paths.as_ref() {
|
||||
if !paths.iter().any(|path| file_path.starts_with(path)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
let file_content = previous_reader.read_to_string(
|
||||
std::path::Path::new("wd")
|
||||
.join(file_path.clone())
|
||||
.to_str()
|
||||
.unwrap(),
|
||||
)?;
|
||||
files_with_content.insert(file_path, file_content);
|
||||
}
|
||||
})
|
||||
.map(|file| {
|
||||
let content = self
|
||||
.reader
|
||||
.read_to_string(&self.repository.wd_path().join(file).to_str().unwrap())
|
||||
.unwrap();
|
||||
(file.to_string(), content)
|
||||
})
|
||||
.collect();
|
||||
Ok(files_with_content)
|
||||
|
||||
Ok(files_with_content)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn file_deltas<P: AsRef<std::path::Path>>(
|
||||
@ -287,8 +307,11 @@ impl<'reader> SessionReader<'reader> {
|
||||
paths: P,
|
||||
) -> Result<Option<Vec<deltas::Delta>>> {
|
||||
let path = paths.as_ref();
|
||||
let deltas_path = self.repository.deltas_path().join(path);
|
||||
match self.reader.read_to_string(deltas_path.to_str().unwrap()) {
|
||||
let file_deltas_path = std::path::Path::new("session/deltas").join(path);
|
||||
match self
|
||||
.reader
|
||||
.read_to_string(file_deltas_path.to_str().unwrap())
|
||||
{
|
||||
Ok(content) => Ok(Some(serde_json::from_str(&content)?)),
|
||||
Err(reader::Error::NotFound) => Ok(None),
|
||||
Err(err) => Err(err.into()),
|
||||
@ -296,27 +319,20 @@ impl<'reader> SessionReader<'reader> {
|
||||
}
|
||||
|
||||
pub fn deltas(&self, paths: Option<Vec<&str>>) -> Result<HashMap<String, Vec<deltas::Delta>>> {
|
||||
let dir = std::path::Path::new("session/deltas");
|
||||
let files = self.reader.list_files(dir.to_str().unwrap())?;
|
||||
let files_with_content = files
|
||||
.iter()
|
||||
.filter(|file| {
|
||||
if let Some(paths) = paths.as_ref() {
|
||||
paths.iter().any(|path| file.starts_with(path))
|
||||
} else {
|
||||
true
|
||||
let deltas_dir = std::path::Path::new("session/deltas");
|
||||
let files = self.reader.list_files(deltas_dir.to_str().unwrap())?;
|
||||
let mut result = HashMap::new();
|
||||
for file_path in files {
|
||||
if let Some(paths) = paths.as_ref() {
|
||||
if !paths.iter().any(|path| file_path.starts_with(path)) {
|
||||
continue;
|
||||
}
|
||||
})
|
||||
.map(|file| {
|
||||
let content = self
|
||||
.reader
|
||||
.read_to_string(dir.join(file).to_str().unwrap())
|
||||
.unwrap();
|
||||
let deltas: Vec<deltas::Delta> = serde_json::from_str(&content).unwrap();
|
||||
(file.to_string(), deltas)
|
||||
})
|
||||
.collect();
|
||||
Ok(files_with_content)
|
||||
}
|
||||
if let Some(deltas) = self.file_deltas(file_path.clone())? {
|
||||
result.insert(file_path, deltas);
|
||||
}
|
||||
}
|
||||
Ok(result)
|
||||
}
|
||||
}
|
||||
|
||||
@ -350,6 +366,13 @@ impl<'iterator> Iterator for SessionsIterator<'iterator> {
|
||||
Result::Ok(commit) => commit,
|
||||
Err(err) => return Some(Err(err.into())),
|
||||
};
|
||||
|
||||
if commit.parent_count() == 0 {
|
||||
// skip initial commit, as it's impossible to get a list of files from it
|
||||
// it's only used to bootstrap the history
|
||||
return None;
|
||||
}
|
||||
|
||||
let commit_reader =
|
||||
match reader::CommitReader::from_commit(self.git_repository, commit) {
|
||||
Result::Ok(commit_reader) => commit_reader,
|
||||
|
@ -98,8 +98,7 @@ impl Deltas {
|
||||
pub fn reindex_project(&mut self, repository: &app::gb_repository::Repository) -> Result<()> {
|
||||
let mut sessions = repository
|
||||
.get_sessions_iterator()
|
||||
.with_context(|| "Could not list sessions for project")?
|
||||
.skip(1);
|
||||
.with_context(|| "Could not list sessions for project")?;
|
||||
|
||||
while let Some(session) = sessions.next() {
|
||||
let session = session.with_context(|| "Could not read session")?;
|
||||
|
Loading…
Reference in New Issue
Block a user