summaryrefslogtreecommitdiffstats
path: root/asyncgit/src/sync/utils.rs
diff options
context:
space:
mode:
Diffstat (limited to 'asyncgit/src/sync/utils.rs')
-rw-r--r--asyncgit/src/sync/utils.rs608
1 files changed, 304 insertions, 304 deletions
diff --git a/asyncgit/src/sync/utils.rs b/asyncgit/src/sync/utils.rs
index 1fbafff5..887194be 100644
--- a/asyncgit/src/sync/utils.rs
+++ b/asyncgit/src/sync/utils.rs
@@ -2,450 +2,450 @@
use super::CommitId;
use crate::{
- error::{Error, Result},
- sync::config::untracked_files_config_repo,
+ error::{Error, Result},
+ sync::config::untracked_files_config_repo,
};
use git2::{IndexAddOption, Repository, RepositoryOpenFlags};
use scopetime::scope_time;
use std::{
- fs::File,
- io::Write,
- path::{Path, PathBuf},
+ fs::File,
+ io::Write,
+ path::{Path, PathBuf},
};
///
#[derive(PartialEq, Debug, Clone)]
pub struct Head {
- ///
- pub name: String,
- ///
- pub id: CommitId,
+ ///
+ pub name: String,
+ ///
+ pub id: CommitId,
}
///
pub fn is_repo(repo_path: &str) -> bool {
- Repository::open_ext(
- repo_path,
- RepositoryOpenFlags::empty(),
- Vec::<&Path>::new(),
- )
- .is_ok()
+ Repository::open_ext(
+ repo_path,
+ RepositoryOpenFlags::empty(),
+ Vec::<&Path>::new(),
+ )
+ .is_ok()
}
/// checks if the git repo at path `repo_path` is a bare repo
pub fn is_bare_repo(repo_path: &str) -> Result<bool> {
- let repo = Repository::open_ext(
- repo_path,
- RepositoryOpenFlags::empty(),
- Vec::<&Path>::new(),
- )?;
+ let repo = Repository::open_ext(
+ repo_path,
+ RepositoryOpenFlags::empty(),
+ Vec::<&Path>::new(),
+ )?;
- Ok(repo.is_bare())
+ Ok(repo.is_bare())
}
///
pub(crate) fn repo(repo_path: &str) -> Result<Repository> {
- let repo = Repository::open_ext(
- repo_path,
- RepositoryOpenFlags::empty(),
- Vec::<&Path>::new(),
- )?;
+ let repo = Repository::open_ext(
+ repo_path,
+ RepositoryOpenFlags::empty(),
+ Vec::<&Path>::new(),
+ )?;
- if repo.is_bare() {
- return Err(Error::Generic("bare repo".to_string()));
- }
+ if repo.is_bare() {
+ return Err(Error::Generic("bare repo".to_string()));
+ }
- Ok(repo)
+ Ok(repo)
}
///
pub(crate) fn work_dir(repo: &Repository) -> Result<&Path> {
- repo.workdir().ok_or(Error::NoWorkDir)
+ repo.workdir().ok_or(Error::NoWorkDir)
}
/// path to .git folder
pub fn repo_dir(repo_path: &str) -> Result<PathBuf> {
- let repo = repo(repo_path)?;
- Ok(repo.path().to_owned())
+ let repo = repo(repo_path)?;
+ Ok(repo.path().to_owned())
}
///
pub fn repo_work_dir(repo_path: &str) -> Result<String> {
- let repo = repo(repo_path)?;
- work_dir(&repo)?.to_str().map_or_else(
- || Err(Error::Generic("invalid workdir".to_string())),
- |workdir| Ok(workdir.to_string()),
- )
+ let repo = repo(repo_path)?;
+ work_dir(&repo)?.to_str().map_or_else(
+ || Err(Error::Generic("invalid workdir".to_string())),
+ |workdir| Ok(workdir.to_string()),
+ )
}
///
pub fn get_head(repo_path: &str) -> Result<CommitId> {
- let repo = repo(repo_path)?;
- get_head_repo(&repo)
+ let repo = repo(repo_path)?;
+ get_head_repo(&repo)
}
///
pub fn get_head_tuple(repo_path: &str) -> Result<Head> {
- let repo = repo(repo_path)?;
- let id = get_head_repo(&repo)?;
- let name = get_head_refname(&repo)?;
+ let repo = repo(repo_path)?;
+ let id = get_head_repo(&repo)?;
+ let name = get_head_refname(&repo)?;
- Ok(Head { name, id })
+ Ok(Head { name, id })
}
///
pub fn get_head_refname(repo: &Repository) -> Result<String> {
- let head = repo.head()?;
- let ref_name = bytes2string(head.name_bytes())?;
+ let head = repo.head()?;
+ let ref_name = bytes2string(head.name_bytes())?;
- Ok(ref_name)
+ Ok(ref_name)
}
///
pub fn get_head_repo(repo: &Repository) -> Result<CommitId> {
- scope_time!("get_head_repo");
+ scope_time!("get_head_repo");
- let head = repo.head()?.target();
+ let head = repo.head()?.target();
- head.map_or(Err(Error::NoHead), |head_id| Ok(head_id.into()))
+ head.map_or(Err(Error::NoHead), |head_id| Ok(head_id.into()))
}
/// add a file diff from workingdir to stage (will not add removed files see `stage_addremoved`)
pub fn stage_add_file(repo_path: &str, path: &Path) -> Result<()> {
- scope_time!("stage_add_file");
+ scope_time!("stage_add_file");
- let repo = repo(repo_path)?;
+ let repo = repo(repo_path)?;
- let mut index = repo.index()?;
+ let mut index = repo.index()?;
- index.add_path(path)?;
- index.write()?;
+ index.add_path(path)?;
+ index.write()?;
- Ok(())
+ Ok(())
}
/// like `stage_add_file` but uses a pattern to match/glob multiple files/folders
pub fn stage_add_all(repo_path: &str, pattern: &str) -> Result<()> {
- scope_time!("stage_add_all");
+ scope_time!("stage_add_all");
- let repo = repo(repo_path)?;
+ let repo = repo(repo_path)?;
- let mut index = repo.index()?;
+ let mut index = repo.index()?;
- let config = untracked_files_config_repo(&repo)?;
+ let config = untracked_files_config_repo(&repo)?;
- if config.include_none() {
- index.update_all(vec![pattern], None)?;
- } else {
- index.add_all(
- vec![pattern],
- IndexAddOption::DEFAULT,
- None,
- )?;
- }
+ if config.include_none() {
+ index.update_all(vec![pattern], None)?;
+ } else {
+ index.add_all(
+ vec![pattern],
+ IndexAddOption::DEFAULT,
+ None,
+ )?;
+ }
- index.write()?;
+ index.write()?;
- Ok(())
+ Ok(())
}
/// Undo last commit in repo
pub fn undo_last_commit(repo_path: &str) -> Result<()> {
- let repo = repo(repo_path)?;
- let previous_commit = repo.revparse_single("HEAD~")?;
+ let repo = repo(repo_path)?;
+ let previous_commit = repo.revparse_single("HEAD~")?;
- Repository::reset(
- &repo,
- &previous_commit,
- git2::ResetType::Soft,
- None,
- )?;
+ Repository::reset(
+ &repo,
+ &previous_commit,
+ git2::ResetType::Soft,
+ None,
+ )?;
- Ok(())
+ Ok(())
}
/// stage a removed file
pub fn stage_addremoved(repo_path: &str, path: &Path) -> Result<()> {
- scope_time!("stage_addremoved");
+ scope_time!("stage_addremoved");
- let repo = repo(repo_path)?;
+ let repo = repo(repo_path)?;
- let mut index = repo.index()?;
+ let mut index = repo.index()?;
- index.remove_path(path)?;
- index.write()?;
+ index.remove_path(path)?;
+ index.write()?;
- Ok(())
+ Ok(())
}
pub(crate) fn bytes2string(bytes: &[u8]) -> Result<String> {
- Ok(String::from_utf8(bytes.to_vec())?)
+ Ok(String::from_utf8(bytes.to_vec())?)
}
/// write a file in repo
pub(crate) fn repo_write_file(
- repo: &Repository,
- file: &str,
- content: &str,
+ repo: &Repository,
+ file: &str,
+ content: &str,
) -> Result<()> {
- let dir = work_dir(repo)?.join(file);
- let file_path = dir.to_str().ok_or_else(|| {
- Error::Generic(String::from("invalid file path"))
- })?;
- let mut file = File::create(file_path)?;
- file.write_all(content.as_bytes())?;
- Ok(())
+ let dir = work_dir(repo)?.join(file);
+ let file_path = dir.to_str().ok_or_else(|| {
+ Error::Generic(String::from("invalid file path"))
+ })?;
+ let mut file = File::create(file_path)?;
+ file.write_all(content.as_bytes())?;
+ Ok(())
}
#[cfg(test)]
pub(crate) fn repo_read_file(
- repo: &Repository,
- file: &str,
+ repo: &Repository,
+ file: &str,
) -> Result<String> {
- use std::io::Read;
+ use std::io::Read;
- let dir = work_dir(repo)?.join(file);
- let file_path = dir.to_str().ok_or_else(|| {
- Error::Generic(String::from("invalid file path"))
- })?;
+ let dir = work_dir(repo)?.join(file);
+ let file_path = dir.to_str().ok_or_else(|| {
+ Error::Generic(String::from("invalid file path"))
+ })?;
- let mut file = File::open(file_path)?;
- let mut buffer = Vec::new();
- file.read_to_end(&mut buffer)?;
+ let mut file = File::open(file_path)?;
+ let mut buffer = Vec::new();
+ file.read_to_end(&mut buffer)?;
- Ok(String::from_utf8(buffer)?)
+ Ok(String::from_utf8(buffer)?)
}
#[cfg(test)]
mod tests {
- use super::*;
- use crate::sync::{
- commit,
- diff::get_diff,
- status::{get_status, StatusType},
- tests::{
- debug_cmd_print, get_statuses, repo_init,
- repo_init_empty, write_commit_file,
- },
- };
- use std::{
- fs::{self, remove_file, File},
- io::Write,
- path::Path,
- };
-
- #[test]
- fn test_stage_add_smoke() {
- let file_path = Path::new("foo");
- let (_td, repo) = repo_init_empty().unwrap();
- let root = repo.path().parent().unwrap();
- let repo_path = root.as_os_str().to_str().unwrap();
-
- assert_eq!(
- stage_add_file(repo_path, file_path).is_ok(),
- false
- );
- }
-
- #[test]
- fn test_staging_one_file() {
- let file_path = Path::new("file1.txt");
- let (_td, repo) = repo_init().unwrap();
- let root = repo.path().parent().unwrap();
- let repo_path = root.as_os_str().to_str().unwrap();
-
- File::create(&root.join(file_path))
- .unwrap()
- .write_all(b"test file1 content")
- .unwrap();
-
- File::create(&root.join(Path::new("file2.txt")))
- .unwrap()
- .write_all(b"test file2 content")
- .unwrap();
-
- assert_eq!(get_statuses(repo_path), (2, 0));
-
- stage_add_file(repo_path, file_path).unwrap();
-
- assert_eq!(get_statuses(repo_path), (1, 1));
- }
-
- #[test]
- fn test_staging_folder() -> Result<()> {
- let (_td, repo) = repo_init().unwrap();
- let root = repo.path().parent().unwrap();
- let repo_path = root.as_os_str().to_str().unwrap();
-
- let status_count = |s: StatusType| -> usize {
- get_status(repo_path, s).unwrap().len()
- };
-
- fs::create_dir_all(&root.join("a/d"))?;
- File::create(&root.join(Path::new("a/d/f1.txt")))?
- .write_all(b"foo")?;
- File::create(&root.join(Path::new("a/d/f2.txt")))?
- .write_all(b"foo")?;
- File::create(&root.join(Path::new("a/f3.txt")))?
- .write_all(b"foo")?;
-
- assert_eq!(status_count(StatusType::WorkingDir), 3);
-
- stage_add_all(repo_path, "a/d").unwrap();
-
- assert_eq!(status_count(StatusType::WorkingDir), 1);
- assert_eq!(status_count(StatusType::Stage), 2);
-
- Ok(())
- }
-
- #[test]
- fn test_undo_commit_empty_repo() {
- let (_td, repo) = repo_init().unwrap();
- let root = repo.path().parent().unwrap();
- let repo_path = root.as_os_str().to_str().unwrap();
-
- // expect to fail
- assert!(undo_last_commit(repo_path).is_err());
- }
-
- #[test]
- fn test_undo_commit() {
- let (_td, repo) = repo_init().unwrap();
- let root = repo.path().parent().unwrap();
- let repo_path = root.as_os_str().to_str().unwrap();
-
- // write commit file test.txt
- let c1 =
- write_commit_file(&repo, "test.txt", "content1", "c1");
- let _c2 =
- write_commit_file(&repo, "test.txt", "content2", "c2");
- assert!(undo_last_commit(repo_path).is_ok());
-
- // Make sure that HEAD points to c1
- assert_eq!(c1, get_head_repo(&repo).unwrap());
-
- // Make sure that now we have 1 file staged
- assert_eq!(get_statuses(repo_path), (0, 1));
+ use super::*;
+ use crate::sync::{
+ commit,
+ diff::get_diff,
+ status::{get_status, StatusType},
+ tests::{
+ debug_cmd_print, get_statuses, repo_init,
+ repo_init_empty, write_commit_file,
+ },
+ };
+ use std::{
+ fs::{self, remove_file, File},
+ io::Write,
+ path::Path,
+ };
+
+ #[test]
+ fn test_stage_add_smoke() {
+ let file_path = Path::new("foo");
+ let (_td, repo) = repo_init_empty().unwrap();
+ let root = repo.path().parent().unwrap();
+ let repo_path = root.as_os_str().to_str().unwrap();
+
+ assert_eq!(
+ stage_add_file(repo_path, file_path).is_ok(),
+ false
+ );
+ }
+
+ #[test]
+ fn test_staging_one_file() {
+ let file_path = Path::new("file1.txt");
+ let (_td, repo) = repo_init().unwrap();
+ let root = repo.path().parent().unwrap();
+ let repo_path = root.as_os_str().to_str().unwrap();
+
+ File::create(&root.join(file_path))
+ .unwrap()
+ .write_all(b"test file1 content")
+ .unwrap();
+
+ File::create(&root.join(Path::new("file2.txt")))
+ .unwrap()
+ .write_all(b"test file2 content")
+ .unwrap();
+
+ assert_eq!(get_statuses(repo_path), (2, 0));
+
+ stage_add_file(repo_path, file_path).unwrap();
+
+ assert_eq!(get_statuses(repo_path), (1, 1));
+ }
+
+ #[test]
+ fn test_staging_folder() -> Result<()> {
+ let (_td, repo) = repo_init().unwrap();
+ let root = repo.path().parent().unwrap();
+ let repo_path = root.as_os_str().to_str().unwrap();
+
+ let status_count = |s: StatusType| -> usize {
+ get_status(repo_path, s).unwrap().len()
+ };
+
+ fs::create_dir_all(&root.join("a/d"))?;
+ File::create(&root.join(Path::new("a/d/f1.txt")))?
+ .write_all(b"foo")?;
+ File::create(&root.join(Path::new("a/d/f2.txt")))?
+ .write_all(b"foo")?;
+ File::create(&root.join(Path::new("a/f3.txt")))?
+ .write_all(b"foo")?;
+
+ assert_eq!(status_count(StatusType::WorkingDir), 3);
+
+ stage_add_all(repo_path, "a/d").unwrap();
+
+ assert_eq!(status_count(StatusType::WorkingDir), 1);
+ assert_eq!(status_count(StatusType::Stage), 2);
+
+ Ok(())
+ }
+
+ #[test]
+ fn test_undo_commit_empty_repo() {
+ let (_td, repo) = repo_init().unwrap();
+ let root = repo.path().parent().unwrap();
+ let repo_path = root.as_os_str().to_str().unwrap();
+
+ // expect to fail
+ assert!(undo_last_commit(repo_path).is_err());
+ }
+
+ #[test]
+ fn test_undo_commit() {
+ let (_td, repo) = repo_init().unwrap();
+ let root = repo.path().parent().unwrap();
+ let repo_path = root.as_os_str().to_str().unwrap();
+
+ // write commit file test.txt
+ let c1 =
+ write_commit_file(&repo, "test.txt", "content1", "c1");
+ let _c2 =
+ write_commit_file(&repo, "test.txt", "content2", "c2");
+ assert!(undo_last_commit(repo_path).is_ok());
+
+ // Make sure that HEAD points to c1
+ assert_eq!(c1, get_head_repo(&repo).unwrap());
+
+ // Make sure that now we have 1 file staged
+ assert_eq!(get_statuses(repo_path), (0, 1));
- // And that file is test.txt
- let diff = get_diff(repo_path, "test.txt", true).unwrap();
- assert_eq!(
- diff.hunks[0].lines[0].content,
- String::from("@@ -1 +1 @@\n")
- );
- }
+ // And that file is test.txt
+ let diff = get_diff(repo_path, "test.txt", true).unwrap();
+ assert_eq!(
+ diff.hunks[0].lines[0].content,
+ String::from("@@ -1 +1 @@\n")
+ );
+ }
- #[test]
- fn test_not_staging_untracked_folder() -> Result<()> {
- let (_td, repo) = repo_init().unwrap();
- let root = repo.path().parent().unwrap();
- let repo_path = root.as_os_str().to_str().unwrap();
+ #[test]
+ fn test_not_staging_untracked_folder() -> Result<()> {
+ let (_td, repo) = repo_init().unwrap();
+ let root = repo.path().parent().unwrap();
+ let repo_path = root.as_os_str().to_str().unwrap();
- fs::create_dir_all(&root.join("a/d"))?;
- File::create(&root.join(Path::new("a/d/f1.txt")))?
- .write_all(b"foo")?;
- File::create(&root.join(Path::new("a/d/f2.txt")))?
- .write_all(b"foo")?;
- File::create(&root.join(Path::new("f3.txt")))?
- .write_all(b"foo")?;
+ fs::create_dir_all(&root.join("a/d"))?;
+ File::create(&root.join(Path::new("a/d/f1.txt")))?
+ .write_all(b"foo")?;
+ File::create(&root.join(Path::new("a/d/f2.txt")))?
+ .write_all(b"foo")?;
+ File::create(&root.join(Path::new("f3.txt")))?
+ .write_all(b"foo")?;
- assert_eq!(get_statuses(repo_path), (3, 0));
+ assert_eq!(get_statuses(repo_path), (3, 0));
- repo.config()?.set_str("status.showUntrackedFiles", "no")?;
+ repo.config()?.set_str("status.showUntrackedFiles", "no")?;
- assert_eq!(get_statuses(repo_path), (0, 0));
+ assert_eq!(get_statuses(repo_path), (0, 0));
- stage_add_all(repo_path, "*").unwrap();
+ stage_add_all(repo_path, "*").unwrap();
- assert_eq!(get_statuses(repo_path), (0, 0));
+ assert_eq!(get_statuses(repo_path), (0, 0));
- Ok(())
- }
+ Ok(())
+ }
- #[test]
- fn test_staging_deleted_file() {
- let file_path = Path::new("file1.txt");
- let (_td, repo) = repo_init().unwrap();
- let root = repo.path().parent().unwrap();
- let repo_path = root.as_os_str().to_str().unwrap();
+ #[test]
+ fn test_staging_deleted_file() {
+ let file_path = Path::new("file1.txt");
+ let (_td, repo) = repo_init().unwrap();
+ let root = repo.path().parent().unwrap();
+ let repo_path = root.as_os_str().to_str().unwrap();
- let status_count = |s: StatusType| -> usize {
- get_status(repo_path, s).unwrap().len()
- };
+ let status_count = |s: StatusType| -> usize {
+ get_status(repo_path, s).unwrap().len()
+ };
- let full_path = &root.join(file_path);
+ let full_path = &root.join(file_path);
- File::create(full_path)
- .unwrap()
- .write_all(b"test file1 content")
- .unwrap();
+ File::create(full_path)
+ .unwrap()
+ .write_all(b"test file1 content")
+ .unwrap();
- stage_add_file(repo_path, file_path).unwrap();
+ stage_add_file(repo_path, file_path).unwrap();
- commit(repo_path, "commit msg").unwrap();
+ commit(repo_path, "commit msg").unwrap();
- // delete the file now
- assert_eq!(remove_file(full_path).is_ok(), true);
+ // delete the file now
+ assert_eq!(remove_file(full_path).is_ok(), true);
- // deleted file in diff now
- assert_eq!(status_count(StatusType::WorkingDir), 1);
+ // deleted file in diff now
+ assert_eq!(status_count(StatusType::WorkingDir), 1);
- stage_addremoved(repo_path, file_path).unwrap();
+ stage_addremoved(repo_path, file_path).unwrap();
- assert_eq!(status_count(StatusType::WorkingDir), 0);
- assert_eq!(status_count(StatusType::Stage), 1);
- }
+ assert_eq!(status_count(StatusType::WorkingDir), 0);
+ assert_eq!(status_count(StatusType::Stage), 1);
+ }
- // see https://github.com/extrawurst/gitui/issues/108
- #[test]
- fn test_staging_sub_git_folder() -> Result<()> {
- let (_td, repo) = repo_init().unwrap();
- let root = repo.path().parent().unwrap();
- let repo_path = root.as_os_str().to_str().unwrap();
+ // see https://github.com/extrawurst/gitui/issues/108
+ #[test]
+ fn test_staging_sub_git_folder() -> Result<()> {
+ let (_td, repo) = repo_init().unwrap();
+ let root = repo.path().parent().unwrap();
+ let repo_path = root.as_os_str().to_str().unwrap();
- let status_count = |s: StatusType| -> usize {
- get_status(repo_path, s).unwrap().len()
- };
+ let status_count = |s: StatusType| -> usize {
+ get_status(repo_path, s).unwrap().len()
+ };
- let sub = &root.join("sub");
+ let sub = &root.join("sub");
- fs::create_dir_all(sub)?;
+ fs::create_dir_all(sub)?;
- debug_cmd_print(sub.to_str().unwrap(), "git init subgit");
+ debug_cmd_print(sub.to_str().unwrap(), "git init subgit");
- File::create(sub.join("subgit/foo.txt"))
- .unwrap()
- .write_all(b"content")
- .unwrap();
+ File::create(sub.join("subgit/foo.txt"))
+ .unwrap()
+ .write_all(b"content")
+ .unwrap();
- assert_eq!(status_count(StatusType::WorkingDir), 1);
+ assert_eq!(status_count(StatusType::WorkingDir), 1);
- //expect to fail
- assert!(stage_add_all(repo_path, "sub").is_err());
+ //expect to fail
+ assert!(stage_add_all(repo_path, "sub").is_err());
- Ok(())
- }
+ Ok(())
+ }
- #[test]
- fn test_head_empty() -> Result<()> {
- let (_td, repo) = repo_init_empty()?;
- let root = repo.path().parent().unwrap();
- let repo_path = root.as_os_str().to_str().unwrap();
+ #[test]
+ fn test_head_empty() -> Result<()> {
+ let (_td, repo) = repo_init_empty()?;
+ let root = repo.path().parent().unwrap();
+ let repo_path = root.as_os_str().to_str().unwrap();
- assert_eq!(get_head(repo_path).is_ok(), false);
+ assert_eq!(get_head(repo_path).is_ok(), false);
- Ok(())
- }
+ Ok(())
+ }
- #[test]
- fn test_head() -> Result<()> {
- let (_td, repo) = repo_init()?;
- let root = repo.path().parent().unwrap();
- let repo_path = root.as_os_str().to_str().unwrap();
+ #[test]
+ fn test_head() -> Result<()> {
+ let (_td, repo) = repo_init()?;
+ let root = repo.path().parent().unwrap();
+ let repo_path = root.as_os_str().to_str().unwrap();
- assert_eq!(get_head(repo_path).is_ok(), true);
+ assert_eq!(get_head(repo_path).is_ok(), true);
- Ok(())
- }
+ Ok(())
+ }
}