feat(push): save objects
This commit is contained in:
parent
8f636b4bf7
commit
a69a71d843
@ -2,3 +2,4 @@ pub mod add;
|
|||||||
pub mod init;
|
pub mod init;
|
||||||
pub mod status;
|
pub mod status;
|
||||||
pub mod reset;
|
pub mod reset;
|
||||||
|
pub mod push;
|
||||||
|
@ -2,7 +2,7 @@ use crate::config::config::Config;
|
|||||||
use crate::store::{
|
use crate::store::{
|
||||||
ignorer::Ignorer,
|
ignorer::Ignorer,
|
||||||
indexer::Indexer,
|
indexer::Indexer,
|
||||||
nsobject::{self, NsObject},
|
nsobject::NsObject,
|
||||||
structs::{self, to_obj_path},
|
structs::{self, to_obj_path},
|
||||||
};
|
};
|
||||||
use crate::utils::path::to_repo_relative;
|
use crate::utils::path::to_repo_relative;
|
||||||
|
20
src/commands/push.rs
Normal file
20
src/commands/push.rs
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
use crate::config::config::Config;
|
||||||
|
use crate::store::object::Obj;
|
||||||
|
use crate::store::{indexer::Indexer, structs};
|
||||||
|
|
||||||
|
pub struct PushArgs {}
|
||||||
|
|
||||||
|
pub fn exec(args: PushArgs, config: Config) {
|
||||||
|
structs::init(config.get_root());
|
||||||
|
|
||||||
|
let mut indexer = Indexer::new(config.get_root_unsafe());
|
||||||
|
let _ = indexer.load();
|
||||||
|
|
||||||
|
for indexed_obj in indexer.get_indexed_objs() {
|
||||||
|
let local_obj = Obj::from_local_path(&indexed_obj.path);
|
||||||
|
local_obj.save().unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
indexer.clear();
|
||||||
|
let _ = indexer.save();
|
||||||
|
}
|
@ -1,8 +1,7 @@
|
|||||||
use crate::config::config::Config;
|
use crate::config::config::Config;
|
||||||
use crate::store::indexer::Indexer;
|
use crate::store::indexer::Indexer;
|
||||||
|
|
||||||
pub struct ResetArgs {
|
pub struct ResetArgs {}
|
||||||
}
|
|
||||||
|
|
||||||
pub fn exec(args: ResetArgs, config: Config) {
|
pub fn exec(args: ResetArgs, config: Config) {
|
||||||
// Init ignorer
|
// Init ignorer
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
use std::env;
|
use std::env;
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
use std::sync::OnceLock;
|
use std::sync::OnceLock;
|
||||||
use crate::store::structs;
|
|
||||||
|
|
||||||
///
|
///
|
||||||
/// # Parameters
|
/// # Parameters
|
||||||
|
@ -16,6 +16,7 @@ fn main() {
|
|||||||
subcommands::add::create(),
|
subcommands::add::create(),
|
||||||
subcommands::status::create(),
|
subcommands::status::create(),
|
||||||
subcommands::reset::create(),
|
subcommands::reset::create(),
|
||||||
|
subcommands::push::create(),
|
||||||
]);
|
]);
|
||||||
// .setting(clap::AppSettings::SubcommandRequiredElseHelp);
|
// .setting(clap::AppSettings::SubcommandRequiredElseHelp);
|
||||||
|
|
||||||
@ -26,6 +27,7 @@ fn main() {
|
|||||||
Some(("add", args)) => subcommands::add::handler(args),
|
Some(("add", args)) => subcommands::add::handler(args),
|
||||||
Some(("status", args)) => subcommands::status::handler(args),
|
Some(("status", args)) => subcommands::status::handler(args),
|
||||||
Some(("reset", args)) => subcommands::reset::handler(args),
|
Some(("reset", args)) => subcommands::reset::handler(args),
|
||||||
|
Some(("push", args)) => subcommands::push::handler(args),
|
||||||
Some((_, _)) => {}
|
Some((_, _)) => {}
|
||||||
None => {}
|
None => {}
|
||||||
};
|
};
|
||||||
|
@ -1,9 +1,11 @@
|
|||||||
use crate::store::object::{Obj, ObjType};
|
use crate::store::{
|
||||||
|
object::{Obj, ObjType},
|
||||||
|
structs::{ObjPath, to_obj_path},
|
||||||
|
};
|
||||||
use crate::utils::path::normalize_path;
|
use crate::utils::path::normalize_path;
|
||||||
use std::cmp::Ordering;
|
use std::cmp::Ordering;
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::io::{self, Write};
|
use std::io::{self, Write, BufRead, BufReader};
|
||||||
use std::io::{BufRead, BufReader};
|
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
||||||
// Custom sorting function to handle paths hierarchically
|
// Custom sorting function to handle paths hierarchically
|
||||||
@ -28,8 +30,8 @@ fn sort_paths_hierarchically(paths: &mut Vec<PathBuf>) {
|
|||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct IndexedObj {
|
pub struct IndexedObj {
|
||||||
obj_type: ObjType,
|
pub obj_type: ObjType,
|
||||||
pub path: PathBuf,
|
pub path: ObjPath,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Indexer {
|
pub struct Indexer {
|
||||||
@ -64,7 +66,7 @@ impl Indexer {
|
|||||||
|
|
||||||
self.indexed_objs.push(IndexedObj {
|
self.indexed_objs.push(IndexedObj {
|
||||||
obj_type: ObjType::try_from(line[0]).unwrap(),
|
obj_type: ObjType::try_from(line[0]).unwrap(),
|
||||||
path,
|
path: to_obj_path(&path),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -92,7 +94,6 @@ impl Indexer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_staged(&self, obj: &Obj) -> bool {
|
pub fn is_staged(&self, obj: &Obj) -> bool {
|
||||||
dbg!(obj);
|
|
||||||
// self.indexed_objs.iter().position(|o| &o.obj_type == obj.get_obj_type() && &o.path == obj.get_obj_path()).is_some()
|
// self.indexed_objs.iter().position(|o| &o.obj_type == obj.get_obj_type() && &o.path == obj.get_obj_path()).is_some()
|
||||||
self.indexed_objs
|
self.indexed_objs
|
||||||
.iter()
|
.iter()
|
||||||
@ -115,7 +116,7 @@ impl Indexer {
|
|||||||
|
|
||||||
let indexed_obj = IndexedObj {
|
let indexed_obj = IndexedObj {
|
||||||
obj_type,
|
obj_type,
|
||||||
path: path.clone(),
|
path: to_obj_path(&path),
|
||||||
};
|
};
|
||||||
|
|
||||||
if self.is_indexed(&indexed_obj) {
|
if self.is_indexed(&indexed_obj) {
|
||||||
@ -138,12 +139,13 @@ impl Indexer {
|
|||||||
|
|
||||||
for obj in self.indexed_objs.iter() {
|
for obj in self.indexed_objs.iter() {
|
||||||
// write obj_type
|
// write obj_type
|
||||||
file.write_all(&[obj.obj_type.clone().into()])?;
|
file.write(&[obj.obj_type.clone().into()])?;
|
||||||
|
|
||||||
// write path
|
// write path
|
||||||
file.write_all(obj.path.to_str().unwrap().as_bytes())?;
|
file.write(obj.path.to_str().unwrap().as_bytes())?;
|
||||||
|
|
||||||
file.write_all(b"\n")?;
|
file.write(b"\n")?;
|
||||||
|
file.flush()?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -2,7 +2,6 @@ use crate::store::{
|
|||||||
object::{Obj, ObjMetadata, ObjType},
|
object::{Obj, ObjMetadata, ObjType},
|
||||||
structs::{NsObjPath, ObjPath},
|
structs::{NsObjPath, ObjPath},
|
||||||
};
|
};
|
||||||
use std::path::PathBuf;
|
|
||||||
use std::sync::OnceLock;
|
use std::sync::OnceLock;
|
||||||
|
|
||||||
type NsObjectChilds = Vec<Box<NsObject>>;
|
type NsObjectChilds = Vec<Box<NsObject>>;
|
||||||
|
@ -1,10 +1,14 @@
|
|||||||
use crate::store::{nsobject::NsObject, structs::ObjPath};
|
use crate::store::{
|
||||||
|
nsobject::NsObject,
|
||||||
|
structs::{NsObjPath, ObjPath},
|
||||||
|
};
|
||||||
use crate::utils::path;
|
use crate::utils::path;
|
||||||
use std::env;
|
use std::env;
|
||||||
use std::fs;
|
use std::fs::{self, File, OpenOptions};
|
||||||
|
use std::io::{self, Write};
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::sync::OnceLock;
|
use std::sync::OnceLock;
|
||||||
use std::time::SystemTime;
|
use std::time::{SystemTime, UNIX_EPOCH};
|
||||||
|
|
||||||
const MAX_SIZE_TO_USE_HASH: u64 = 12 * 1024 * 1024;
|
const MAX_SIZE_TO_USE_HASH: u64 = 12 * 1024 * 1024;
|
||||||
|
|
||||||
@ -60,11 +64,21 @@ pub struct Obj {
|
|||||||
|
|
||||||
impl Obj {
|
impl Obj {
|
||||||
pub fn from_local_path(path: &ObjPath) -> Self {
|
pub fn from_local_path(path: &ObjPath) -> Self {
|
||||||
// todo set state
|
let obj_path = path.clone();
|
||||||
Obj {
|
Obj {
|
||||||
obj_type: ObjType::Obj,
|
obj_type: {
|
||||||
|
if path.abs().exists() {
|
||||||
|
if path.abs().is_dir() {
|
||||||
|
ObjType::Tree
|
||||||
|
} else {
|
||||||
|
ObjType::Blob
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ObjType::Obj
|
||||||
|
}
|
||||||
|
},
|
||||||
status: OnceLock::new(),
|
status: OnceLock::new(),
|
||||||
obj_path: path.clone(),
|
obj_path,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -92,7 +106,7 @@ impl Obj {
|
|||||||
&self.obj_type
|
&self.obj_type
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_obj_path(&self) -> &PathBuf {
|
pub fn get_obj_path(&self) -> &ObjPath {
|
||||||
&self.obj_path
|
&self.obj_path
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -126,6 +140,83 @@ impl Obj {
|
|||||||
path::to_string(&self.obj_path)
|
path::to_string(&self.obj_path)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn get_nsobj_path(&self) -> NsObjPath {
|
||||||
|
NsObjPath::from(&self.obj_path)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn save(&self) -> io::Result<()> {
|
||||||
|
let nsobj_path = self.get_nsobj_path();
|
||||||
|
let mut file = {
|
||||||
|
if nsobj_path.exists() {
|
||||||
|
todo!("Edition of object")
|
||||||
|
} else {
|
||||||
|
let mut nsobj_dir = nsobj_path.clone();
|
||||||
|
nsobj_dir.pop();
|
||||||
|
if !nsobj_dir.exists() {
|
||||||
|
std::fs::create_dir_all(nsobj_dir)?;
|
||||||
|
}
|
||||||
|
File::create(&nsobj_path)?
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Write type
|
||||||
|
file.write(&[self.obj_type.clone().into()])?;
|
||||||
|
|
||||||
|
if self.obj_type == ObjType::Blob {
|
||||||
|
if let Some(metadata) = self.get_metadata() {
|
||||||
|
// Write size
|
||||||
|
file.write(&metadata.size.to_le_bytes())?;
|
||||||
|
|
||||||
|
// Write modified
|
||||||
|
file.write(
|
||||||
|
&metadata
|
||||||
|
.modified
|
||||||
|
.expect(&format!(
|
||||||
|
"Expect 'modified' in metadata of {} to save obj",
|
||||||
|
self.cpy_path()
|
||||||
|
))
|
||||||
|
.duration_since(UNIX_EPOCH)
|
||||||
|
.unwrap()
|
||||||
|
.as_secs()
|
||||||
|
.to_le_bytes(),
|
||||||
|
)?;
|
||||||
|
} else {
|
||||||
|
todo!("Cannot load metadata")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
file.write_all(b"\n")?;
|
||||||
|
// Write Path
|
||||||
|
file.write_all(self.obj_path.to_str().unwrap().as_bytes())?;
|
||||||
|
file.write_all(b"\n")?;
|
||||||
|
|
||||||
|
file.flush()?;
|
||||||
|
|
||||||
|
// Save itself inside its parent
|
||||||
|
let mut parent_path = self.obj_path.clone();
|
||||||
|
parent_path.pop();
|
||||||
|
let parent_obj = Obj::from_local_path(&parent_path);
|
||||||
|
parent_obj.add_child(&self)?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn add_child(&self, child: &Obj) -> io::Result<()> {
|
||||||
|
let mut file = OpenOptions::new()
|
||||||
|
.write(true)
|
||||||
|
.create(true)
|
||||||
|
.append(true)
|
||||||
|
.open(self.get_nsobj_path())?;
|
||||||
|
|
||||||
|
let child_type = &[child.get_obj_type().clone().into()];
|
||||||
|
let child_path = child.obj_path.to_str().unwrap().as_bytes();
|
||||||
|
file.write(child_type)?;
|
||||||
|
file.write(child_path)?;
|
||||||
|
file.write(b"\n")?;
|
||||||
|
file.flush()?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
pub fn get_metadata(&self) -> Option<ObjMetadata> {
|
pub fn get_metadata(&self) -> Option<ObjMetadata> {
|
||||||
let metadata = match fs::metadata(&*self.obj_path) {
|
let metadata = match fs::metadata(&*self.obj_path) {
|
||||||
Ok(m) => m,
|
Ok(m) => m,
|
||||||
|
@ -2,7 +2,7 @@ use crate::utils::{path, tests};
|
|||||||
use crypto::digest::Digest;
|
use crypto::digest::Digest;
|
||||||
use crypto::sha1::Sha1;
|
use crypto::sha1::Sha1;
|
||||||
use std::ops::{Deref, DerefMut};
|
use std::ops::{Deref, DerefMut};
|
||||||
use std::path::PathBuf;
|
use std::path::{PathBuf, Path};
|
||||||
use std::sync::{LazyLock, Mutex, OnceLock};
|
use std::sync::{LazyLock, Mutex, OnceLock};
|
||||||
|
|
||||||
// for tests only as it is mutable
|
// for tests only as it is mutable
|
||||||
@ -39,9 +39,30 @@ pub fn get_repo_root() -> PathBuf {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct ObjPath {
|
pub struct ObjPath {
|
||||||
path: PathBuf,
|
path: PathBuf,
|
||||||
|
abs: OnceLock<PathBuf>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ObjPath {
|
||||||
|
pub fn abs(&self) -> &PathBuf {
|
||||||
|
self.abs.get_or_init(|| {
|
||||||
|
let mut path = get_repo_root();
|
||||||
|
path.push(self.path.clone());
|
||||||
|
path
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PartialEq for ObjPath {
|
||||||
|
fn eq(&self, other: &Self) -> bool {
|
||||||
|
if self.abs.get().is_some() && other.abs.get().is_some() {
|
||||||
|
self.abs() == other.abs()
|
||||||
|
} else {
|
||||||
|
self.path == other.path
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Deref for ObjPath {
|
impl Deref for ObjPath {
|
||||||
@ -57,14 +78,21 @@ impl DerefMut for ObjPath {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl AsRef<Path> for ObjPath {
|
||||||
|
fn as_ref(&self) -> &Path {
|
||||||
|
&self.path
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn to_obj_path(path: &PathBuf) -> ObjPath {
|
pub fn to_obj_path(path: &PathBuf) -> ObjPath {
|
||||||
ObjPath { path: path.clone() }
|
ObjPath { path: path.clone(), abs: OnceLock::new() }
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Into<ObjPath> for &PathBuf {
|
impl Into<ObjPath> for &PathBuf {
|
||||||
fn into(self) -> ObjPath {
|
fn into(self) -> ObjPath {
|
||||||
ObjPath {
|
ObjPath {
|
||||||
path: path::to_repo_relative(self),
|
path: path::to_repo_relative(self),
|
||||||
|
abs: OnceLock::from(self.clone()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -73,6 +101,7 @@ impl Into<ObjPath> for PathBuf {
|
|||||||
fn into(self) -> ObjPath {
|
fn into(self) -> ObjPath {
|
||||||
ObjPath {
|
ObjPath {
|
||||||
path: path::to_repo_relative(&self),
|
path: path::to_repo_relative(&self),
|
||||||
|
abs: OnceLock::from(self.clone()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -95,11 +124,19 @@ impl DerefMut for NsObjPath {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl AsRef<Path> for NsObjPath {
|
||||||
|
fn as_ref(&self) -> &Path {
|
||||||
|
&self.path
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl From<&str> for NsObjPath {
|
impl From<&str> for NsObjPath {
|
||||||
fn from(hash: &str) -> Self {
|
fn from(hash: &str) -> Self {
|
||||||
let (dir, res) = hash.split_at(2);
|
let (dir, res) = hash.split_at(2);
|
||||||
|
|
||||||
let mut ns_obj_path = get_repo_root();
|
let mut ns_obj_path = get_repo_root();
|
||||||
|
ns_obj_path.push(".nextsync");
|
||||||
|
ns_obj_path.push("objects");
|
||||||
ns_obj_path.push(dir);
|
ns_obj_path.push(dir);
|
||||||
ns_obj_path.push(res);
|
ns_obj_path.push(res);
|
||||||
|
|
||||||
@ -109,6 +146,16 @@ impl From<&str> for NsObjPath {
|
|||||||
|
|
||||||
impl From<&ObjPath> for NsObjPath {
|
impl From<&ObjPath> for NsObjPath {
|
||||||
fn from(obj_path: &ObjPath) -> Self {
|
fn from(obj_path: &ObjPath) -> Self {
|
||||||
|
// NsObjPath of root is the HEAD file
|
||||||
|
if path::get_level(obj_path) == 0 {
|
||||||
|
let mut path = get_repo_root();
|
||||||
|
path.push(".nextsync");
|
||||||
|
path.push("HEAD");
|
||||||
|
return NsObjPath {
|
||||||
|
path
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
let mut hasher = Sha1::new();
|
let mut hasher = Sha1::new();
|
||||||
hasher.input_str(
|
hasher.input_str(
|
||||||
obj_path
|
obj_path
|
||||||
|
@ -2,3 +2,4 @@ pub mod add;
|
|||||||
pub mod init;
|
pub mod init;
|
||||||
pub mod reset;
|
pub mod reset;
|
||||||
pub mod status;
|
pub mod status;
|
||||||
|
pub mod push;
|
||||||
|
13
src/subcommands/push.rs
Normal file
13
src/subcommands/push.rs
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
use clap::{ArgMatches, Command};
|
||||||
|
|
||||||
|
use crate::commands;
|
||||||
|
use crate::commands::push::PushArgs;
|
||||||
|
use crate::config::config::Config;
|
||||||
|
|
||||||
|
pub fn create() -> Command {
|
||||||
|
Command::new("push").about("Push changes on nextcloud")
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn handler(args: &ArgMatches) {
|
||||||
|
commands::push::exec(PushArgs {}, Config::new());
|
||||||
|
}
|
@ -1,4 +1,4 @@
|
|||||||
use clap::{Arg, ArgAction, ArgMatches, Command};
|
use clap::{ArgMatches, Command};
|
||||||
|
|
||||||
use crate::commands;
|
use crate::commands;
|
||||||
use crate::commands::reset::ResetArgs;
|
use crate::commands::reset::ResetArgs;
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
mod common;
|
mod common;
|
||||||
|
|
||||||
use common::client::ClientTest;
|
use common::client::ClientTest;
|
||||||
use nextsync::store::indexer::Indexer;
|
use nextsync::store::{structs::to_obj_path, indexer::Indexer};
|
||||||
use nextsync::commands::status::{get_obj_changes, StatusArgs};
|
use nextsync::commands::status::{get_obj_changes, StatusArgs};
|
||||||
use nextsync::config::config::Config;
|
use nextsync::config::config::Config;
|
||||||
use std::io;
|
use std::io;
|
||||||
@ -17,7 +17,7 @@ fn indexed_expected(indexer: &Indexer, expected: Vec<&str>) {
|
|||||||
for obj in expected {
|
for obj in expected {
|
||||||
assert!(objs
|
assert!(objs
|
||||||
.iter()
|
.iter()
|
||||||
.position(|e| { e.path == PathBuf::from(obj) })
|
.position(|e| { e.path == to_obj_path(&PathBuf::from(obj)) })
|
||||||
.is_some());
|
.is_some());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,7 @@
|
|||||||
use nextsync::config::config::Config;
|
use nextsync::config::config::Config;
|
||||||
use std::fs::OpenOptions;
|
|
||||||
use rand::{distributions::Alphanumeric, Rng};
|
use rand::{distributions::Alphanumeric, Rng};
|
||||||
use std::env;
|
use std::env;
|
||||||
use std::fs::{self, File};
|
use std::fs::{self, File, OpenOptions};
|
||||||
use std::io::{self, Write};
|
use std::io::{self, Write};
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::process::{Command, Output};
|
use std::process::{Command, Output};
|
||||||
@ -140,7 +139,8 @@ impl ClientTest {
|
|||||||
.write(true)
|
.write(true)
|
||||||
.create(true)
|
.create(true)
|
||||||
.append(true)
|
.append(true)
|
||||||
.open(nsignore_path).unwrap();
|
.open(nsignore_path)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
let _ = writeln!(file, "{rule}").unwrap();
|
let _ = writeln!(file, "{rule}").unwrap();
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
mod common;
|
mod common;
|
||||||
|
|
||||||
use common::client::ClientTest;
|
use common::client::ClientTest;
|
||||||
|
use nextsync::store::object::Obj;
|
||||||
use nextsync::commands::status::{get_obj_changes, StatusArgs};
|
use nextsync::commands::status::{get_obj_changes, StatusArgs};
|
||||||
use nextsync::config::config::Config;
|
use nextsync::config::config::Config;
|
||||||
use std::io;
|
use std::io;
|
||||||
@ -8,43 +9,30 @@ use std::path::PathBuf;
|
|||||||
|
|
||||||
const DEFAULT_STATUS_ARG: StatusArgs = StatusArgs { nostyle: false };
|
const DEFAULT_STATUS_ARG: StatusArgs = StatusArgs { nostyle: false };
|
||||||
|
|
||||||
|
fn compare_vect(vec1: Vec<Obj>, vec2: Vec<&str>, config: &Config) {
|
||||||
|
for obj in vec2 {
|
||||||
|
assert!(
|
||||||
|
vec1.iter()
|
||||||
|
.position(|e| {
|
||||||
|
e.get_env_relative_path(config.get_root_unsafe()) == PathBuf::from(obj)
|
||||||
|
})
|
||||||
|
.is_some(),
|
||||||
|
"{:?}",
|
||||||
|
vec1.iter()
|
||||||
|
.map(|e| { e.get_env_relative_path(config.get_root_unsafe()) })
|
||||||
|
.collect::<Vec<PathBuf>>()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn status_expected(config: &Config, staged: Vec<&str>, not_staged: Vec<&str>) {
|
fn status_expected(config: &Config, staged: Vec<&str>, not_staged: Vec<&str>) {
|
||||||
let res = get_obj_changes(&DEFAULT_STATUS_ARG, config);
|
let res = get_obj_changes(&DEFAULT_STATUS_ARG, config);
|
||||||
|
|
||||||
assert_eq!(res.staged.len(), staged.len());
|
assert_eq!(res.staged.len(), staged.len());
|
||||||
assert_eq!(res.not_staged.len(), not_staged.len());
|
assert_eq!(res.not_staged.len(), not_staged.len());
|
||||||
|
|
||||||
for obj in staged {
|
compare_vect(res.staged, staged, &config);
|
||||||
assert!(
|
compare_vect(res.not_staged, not_staged, &config);
|
||||||
res.staged
|
|
||||||
.iter()
|
|
||||||
.position(|e| {
|
|
||||||
e.get_env_relative_path(config.get_root_unsafe()) == PathBuf::from(obj)
|
|
||||||
})
|
|
||||||
.is_some(),
|
|
||||||
"{:?}",
|
|
||||||
res.staged
|
|
||||||
.iter()
|
|
||||||
.map(|e| { e.get_env_relative_path(config.get_root_unsafe()) })
|
|
||||||
.collect::<Vec<PathBuf>>()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
for obj in not_staged {
|
|
||||||
assert!(
|
|
||||||
res.not_staged
|
|
||||||
.iter()
|
|
||||||
.position(|e| {
|
|
||||||
e.get_env_relative_path(config.get_root_unsafe()) == PathBuf::from(obj)
|
|
||||||
})
|
|
||||||
.is_some(),
|
|
||||||
"{:?}",
|
|
||||||
res.not_staged
|
|
||||||
.iter()
|
|
||||||
.map(|e| { e.get_env_relative_path(config.get_root_unsafe()) })
|
|
||||||
.collect::<Vec<PathBuf>>()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
Loading…
Reference in New Issue
Block a user