mirror of
https://github.com/gitui-org/gitui
synced 2026-05-23 17:08:21 +00:00
fix working dir checkout (revert)
This commit is contained in:
parent
2b45a039d1
commit
c455f3e316
7 changed files with 222 additions and 52 deletions
8
Cargo.lock
generated
8
Cargo.lock
generated
|
|
@ -270,9 +270,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "git2"
|
||||
version = "0.10.2"
|
||||
version = "0.13.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7c1af51ea8a906616af45a4ce78eacf25860f7a13ae7bf8a814693f0f4037a26"
|
||||
checksum = "b7da16ceafe24cedd9ba02c4463a2b506b6493baf4317c79c5acb553134a3c15"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"libc",
|
||||
|
|
@ -379,9 +379,9 @@ checksum = "eb147597cdf94ed43ab7a9038716637d2d1bf2bc571da995d0028dec06bd3018"
|
|||
|
||||
[[package]]
|
||||
name = "libgit2-sys"
|
||||
version = "0.9.2"
|
||||
version = "0.12.0+0.99.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4870c781f6063efb83150cd22c1ddf6ecf58531419e7570cdcced46970f64a16"
|
||||
checksum = "05dff41ac39e7b653f5f1550886cf00ba52f8e7f57210b633cdeedb3de5b236c"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"libc",
|
||||
|
|
|
|||
|
|
@ -55,7 +55,6 @@ GITUI_LOGGING=true gitui
|
|||
|
||||
# todo for 0.1 (first release)
|
||||
|
||||
* [ ] fix: reset unstaged file also resets staged hunks
|
||||
* [ ] better help command
|
||||
* [ ] -> fix: dont show scroll option when any popup open
|
||||
* [ ] confirm destructive commands (revert/reset)
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ license = "MIT"
|
|||
categories = ["concurrency","asynchronous"]
|
||||
|
||||
[dependencies]
|
||||
git2 = "0.10"
|
||||
git2 = "0.13"
|
||||
rayon-core = "1.7"
|
||||
crossbeam-channel = "0.4"
|
||||
log = "0.4"
|
||||
|
|
|
|||
|
|
@ -1,7 +1,9 @@
|
|||
//! sync git api
|
||||
|
||||
pub mod diff;
|
||||
mod reset;
|
||||
pub mod status;
|
||||
pub mod utils;
|
||||
|
||||
pub use utils::{commit, index_reset, stage_add, stage_reset};
|
||||
pub use reset::{index_reset, stage_reset};
|
||||
pub use utils::{commit, stage_add};
|
||||
|
|
|
|||
191
asyncgit/src/sync/reset.rs
Normal file
191
asyncgit/src/sync/reset.rs
Normal file
|
|
@ -0,0 +1,191 @@
|
|||
use super::utils::repo_at;
|
||||
use git2::ObjectType;
|
||||
use scopetime::scope_time;
|
||||
use std::{path::Path, process::Command};
|
||||
|
||||
///
|
||||
pub fn stage_reset(path: &Path) -> bool {
|
||||
stage_reset_at("./", path)
|
||||
}
|
||||
|
||||
///
|
||||
pub fn stage_reset_at(repo_path: &str, path: &Path) -> bool {
|
||||
scope_time!("stage_reset_at");
|
||||
|
||||
let repo = repo_at(repo_path);
|
||||
|
||||
let reference = repo.head().unwrap();
|
||||
let obj = repo
|
||||
.find_object(
|
||||
reference.target().unwrap(),
|
||||
Some(ObjectType::Commit),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
if repo.reset_default(Some(&obj), &[path]).is_ok() {
|
||||
return true;
|
||||
}
|
||||
|
||||
false
|
||||
}
|
||||
|
||||
///
|
||||
pub fn index_reset(path: &Path) -> bool {
|
||||
index_reset_at("./", path)
|
||||
}
|
||||
|
||||
///
|
||||
pub fn index_reset_at(repo_path: &str, path: &Path) -> bool {
|
||||
let cmd = format!("git checkout {:?}", path);
|
||||
|
||||
let output = if cfg!(target_os = "windows") {
|
||||
Command::new("cmd")
|
||||
.args(&["/C", cmd.as_str()])
|
||||
.current_dir(repo_path)
|
||||
.output()
|
||||
} else {
|
||||
Command::new("sh")
|
||||
.arg("-c")
|
||||
.arg(cmd.as_str())
|
||||
.current_dir(repo_path)
|
||||
.output()
|
||||
};
|
||||
|
||||
output.is_ok()
|
||||
|
||||
//------------------------------------
|
||||
//TODO: why is this broken with libgit2 ???
|
||||
//------------------------------------
|
||||
|
||||
// scope_time!("index_reset");
|
||||
|
||||
// let repo = repo_at(repo_path);
|
||||
|
||||
// let mut checkout_opts = CheckoutBuilder::new();
|
||||
// checkout_opts
|
||||
// .remove_untracked(true)
|
||||
// .force()
|
||||
// .update_index(false)
|
||||
// .allow_conflicts(true)
|
||||
// .path(&path);
|
||||
|
||||
// if repo.checkout_head(Some(&mut checkout_opts)).is_ok() {
|
||||
// return true;
|
||||
// }
|
||||
|
||||
// false
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::index_reset_at;
|
||||
use crate::sync::{
|
||||
status::{get_index_at, StatusType},
|
||||
utils::stage_add_at,
|
||||
};
|
||||
use git2::Repository;
|
||||
use std::{fs::File, io::Write, path::Path};
|
||||
use tempfile::TempDir;
|
||||
|
||||
pub fn repo_init() -> (TempDir, Repository) {
|
||||
let td = TempDir::new().unwrap();
|
||||
let repo = Repository::init(td.path()).unwrap();
|
||||
{
|
||||
let mut config = repo.config().unwrap();
|
||||
config.set_str("user.name", "name").unwrap();
|
||||
config.set_str("user.email", "email").unwrap();
|
||||
|
||||
let mut index = repo.index().unwrap();
|
||||
let id = index.write_tree().unwrap();
|
||||
|
||||
let tree = repo.find_tree(id).unwrap();
|
||||
let sig = repo.signature().unwrap();
|
||||
repo.commit(
|
||||
Some("HEAD"),
|
||||
&sig,
|
||||
&sig,
|
||||
"initial",
|
||||
&tree,
|
||||
&[],
|
||||
)
|
||||
.unwrap();
|
||||
}
|
||||
(td, repo)
|
||||
}
|
||||
|
||||
static HUNK_A: &str = r"
|
||||
1 start
|
||||
2
|
||||
3
|
||||
4
|
||||
5
|
||||
6 middle
|
||||
7
|
||||
8
|
||||
9
|
||||
0
|
||||
1 end";
|
||||
|
||||
static HUNK_B: &str = r"
|
||||
1 start
|
||||
2 newa
|
||||
3
|
||||
4
|
||||
5
|
||||
6 middle
|
||||
7
|
||||
8
|
||||
9
|
||||
0 newb
|
||||
1 end";
|
||||
|
||||
#[test]
|
||||
fn test_reset_only_unstaged() {
|
||||
let (_td, repo) = repo_init();
|
||||
let root = repo.path().parent().unwrap();
|
||||
let repo_path = root.as_os_str().to_str().unwrap();
|
||||
|
||||
let res = get_index_at(repo_path, StatusType::WorkingDir);
|
||||
assert_eq!(res.len(), 0);
|
||||
|
||||
let file_path = root.join("bar.txt");
|
||||
|
||||
{
|
||||
File::create(&file_path)
|
||||
.unwrap()
|
||||
.write_all(HUNK_A.as_bytes())
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
stage_add_at(repo_path, Path::new("bar.txt"));
|
||||
|
||||
// overwrite with next content
|
||||
{
|
||||
File::create(&file_path)
|
||||
.unwrap()
|
||||
.write_all(HUNK_B.as_bytes())
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
assert_eq!(
|
||||
get_index_at(repo_path, StatusType::Stage).len(),
|
||||
1
|
||||
);
|
||||
assert_eq!(
|
||||
get_index_at(repo_path, StatusType::WorkingDir).len(),
|
||||
1
|
||||
);
|
||||
|
||||
let res = index_reset_at(repo_path, Path::new("bar.txt"));
|
||||
assert_eq!(res, true);
|
||||
|
||||
assert_eq!(
|
||||
get_index_at(repo_path, StatusType::Stage).len(),
|
||||
1
|
||||
);
|
||||
assert_eq!(
|
||||
get_index_at(repo_path, StatusType::WorkingDir).len(),
|
||||
0
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -64,9 +64,17 @@ impl Into<StatusShow> for StatusType {
|
|||
|
||||
///
|
||||
pub fn get_index(status_type: StatusType) -> Vec<StatusItem> {
|
||||
get_index_at("./", status_type)
|
||||
}
|
||||
|
||||
///
|
||||
pub fn get_index_at(
|
||||
repo_path: &str,
|
||||
status_type: StatusType,
|
||||
) -> Vec<StatusItem> {
|
||||
scope_time!("get_index");
|
||||
|
||||
let repo = utils::repo();
|
||||
let repo = utils::repo_at(repo_path);
|
||||
|
||||
let statuses = repo
|
||||
.statuses(Some(
|
||||
|
|
|
|||
|
|
@ -1,16 +1,19 @@
|
|||
//! sync git api (various methods)
|
||||
|
||||
use git2::{
|
||||
build::CheckoutBuilder, IndexAddOption, ObjectType, Repository,
|
||||
RepositoryOpenFlags,
|
||||
};
|
||||
use git2::{IndexAddOption, Repository, RepositoryOpenFlags};
|
||||
use scopetime::scope_time;
|
||||
use std::path::Path;
|
||||
|
||||
//TODO: get rid of this
|
||||
///
|
||||
pub fn repo() -> Repository {
|
||||
repo_at("./")
|
||||
}
|
||||
|
||||
///
|
||||
pub fn repo_at(repo_path: &str) -> Repository {
|
||||
let repo = Repository::open_ext(
|
||||
"./",
|
||||
repo_path,
|
||||
RepositoryOpenFlags::empty(),
|
||||
Vec::<&Path>::new(),
|
||||
)
|
||||
|
|
@ -50,9 +53,14 @@ pub fn commit(msg: &str) {
|
|||
|
||||
///
|
||||
pub fn stage_add(path: &Path) -> bool {
|
||||
stage_add_at("./", path)
|
||||
}
|
||||
|
||||
///
|
||||
pub fn stage_add_at(repo_path: &str, path: &Path) -> bool {
|
||||
scope_time!("stage_add");
|
||||
|
||||
let repo = repo();
|
||||
let repo = repo_at(repo_path);
|
||||
|
||||
let mut index = repo.index().unwrap();
|
||||
|
||||
|
|
@ -75,41 +83,3 @@ pub fn stage_add(path: &Path) -> bool {
|
|||
|
||||
false
|
||||
}
|
||||
|
||||
///
|
||||
pub fn stage_reset(path: &Path) -> bool {
|
||||
scope_time!("stage_reset");
|
||||
|
||||
let repo = repo();
|
||||
|
||||
let reference = repo.head().unwrap();
|
||||
let obj = repo
|
||||
.find_object(
|
||||
reference.target().unwrap(),
|
||||
Some(ObjectType::Commit),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
if repo.reset_default(Some(&obj), &[path]).is_ok() {
|
||||
return true;
|
||||
}
|
||||
|
||||
false
|
||||
}
|
||||
|
||||
///
|
||||
pub fn index_reset(path: &Path) -> bool {
|
||||
scope_time!("index_reset");
|
||||
|
||||
let repo = repo();
|
||||
|
||||
let mut checkout_opts = CheckoutBuilder::new();
|
||||
checkout_opts.remove_untracked(true);
|
||||
checkout_opts.path(&path).force();
|
||||
|
||||
if repo.checkout_head(Some(&mut checkout_opts)).is_ok() {
|
||||
return true;
|
||||
}
|
||||
|
||||
false
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue