remote diff with new opti remote enumerater
This commit is contained in:
parent
f01983b29d
commit
4e20ec94f9
@ -2,7 +2,7 @@
|
||||
|
||||
A git-like command line tool to interact with Nextcloud.
|
||||
|
||||
This is **work in progress**.
|
||||
This is **in working progress**.
|
||||
|
||||
This should work pretty much like git with some adaptations to be more debuggable (for now) and easier to code. There is no history and with that no need to commit, to upload new files you have to add and push them.
|
||||
|
||||
|
@ -6,7 +6,7 @@ use clap::Values;
|
||||
use regex::Regex;
|
||||
use crate::services::downloader::Downloader;
|
||||
use crate::utils::api::ApiProps;
|
||||
use crate::utils::remote::enumerate_remote;
|
||||
use crate::utils::remote::{enumerate_remote, EnumerateOptions};
|
||||
use crate::global::global::{DIR_PATH, set_dir_path};
|
||||
use crate::services::api::ApiError;
|
||||
use crate::services::req_props::{ReqProps, ObjProps};
|
||||
@ -67,11 +67,13 @@ pub fn clone(args: CloneArgs) {
|
||||
}
|
||||
|
||||
let depth = &args.depth.clone().unwrap_or(DEPTH.to_string());
|
||||
let (folders, files) = enumerate_remote(|a| req(
|
||||
&api_props,
|
||||
depth,
|
||||
a
|
||||
), Some(depth));
|
||||
let (folders, files) = enumerate_remote(
|
||||
|a| req(&api_props, depth, a),
|
||||
&should_skip,
|
||||
EnumerateOptions {
|
||||
depth: Some(depth.to_owned()),
|
||||
relative_s: None
|
||||
});
|
||||
|
||||
for folder in folders {
|
||||
// create folder
|
||||
@ -104,6 +106,10 @@ fn save_blob(obj: ObjProps) {
|
||||
}
|
||||
}
|
||||
|
||||
fn should_skip(_: ObjProps) -> bool {
|
||||
return false;
|
||||
}
|
||||
|
||||
fn req(api_props: &ApiProps, depth: &str, relative_s: &str) -> Result<Vec<ObjProps>, ApiError> {
|
||||
ReqProps::new()
|
||||
.set_request(relative_s, &api_props)
|
||||
|
@ -1,7 +1,9 @@
|
||||
use crate::services::api::ApiError;
|
||||
use crate::services::req_props::{ReqProps, ObjProps};
|
||||
use crate::store::object::Object;
|
||||
use crate::store::object::{Object, self};
|
||||
use crate::utils::api::{ApiProps, get_api_props};
|
||||
use crate::utils::path;
|
||||
use crate::utils::remote::{enumerate_remote, EnumerateOptions};
|
||||
use std::fs::canonicalize;
|
||||
use std::path::PathBuf;
|
||||
|
||||
@ -16,9 +18,11 @@ pub fn remote_diff(args: RemoteDiffArgs) {
|
||||
cur.push(path);
|
||||
let canonic = canonicalize(cur).ok().unwrap();
|
||||
dbg!(&canonic);
|
||||
dbg!(path::repo_root());
|
||||
let ok = canonic.strip_prefix(path::repo_root());
|
||||
dbg!(&ok);
|
||||
|
||||
// todo
|
||||
PathBuf::from("/")
|
||||
} else {
|
||||
PathBuf::from("/")
|
||||
@ -33,62 +37,46 @@ pub fn remote_diff(args: RemoteDiffArgs) {
|
||||
}];
|
||||
let mut files: Vec<ObjProps> = vec![];
|
||||
|
||||
while folders.len() > 0 {
|
||||
let folder = folders.pop().unwrap();
|
||||
let depth = "2"; // todo
|
||||
// todo origin
|
||||
let api_props = get_api_props();
|
||||
let (folders, files) = enumerate_remote(
|
||||
|a| req(&api_props, depth, a),
|
||||
&should_skip,
|
||||
EnumerateOptions {
|
||||
depth: Some(depth.to_owned()),
|
||||
relative_s: Some(path.to_str().unwrap().to_owned())
|
||||
});
|
||||
|
||||
let res = ReqProps::new()
|
||||
.set_url(&folder.relative_s.unwrap())
|
||||
.gethref()
|
||||
.getlastmodified()
|
||||
.send_req_multiple();
|
||||
|
||||
let objs = match res {
|
||||
Ok(o) => o,
|
||||
Err(ApiError::IncorrectRequest(err)) => {
|
||||
eprintln!("fatal: {}", err.status());
|
||||
std::process::exit(1);
|
||||
},
|
||||
Err(ApiError::EmptyError(_)) => {
|
||||
eprintln!("Failed to get body");
|
||||
vec![]
|
||||
for folder in folders {
|
||||
println!("should pull {}", folder.clone().relative_s.unwrap());
|
||||
}
|
||||
for file in files {
|
||||
println!("should pull {}", file.clone().relative_s.unwrap());
|
||||
}
|
||||
Err(ApiError::RequestError(err)) => {
|
||||
eprintln!("fatal: {}", err);
|
||||
std::process::exit(1);
|
||||
},
|
||||
Err(ApiError::Unexpected(_)) => todo!()
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
let mut iter = objs.iter();
|
||||
// todo opti store date of root
|
||||
let root = iter.next();
|
||||
|
||||
for obj in iter {
|
||||
fn should_skip(obj: ObjProps) -> bool {
|
||||
let mut o = Object::new(&obj.clone().relative_s.unwrap());
|
||||
let exist = o.exists();
|
||||
|
||||
let should_pull = {
|
||||
if exist {
|
||||
o.read()
|
||||
.is_older(obj.lastmodified.unwrap().timestamp())
|
||||
} else {
|
||||
true
|
||||
}
|
||||
};
|
||||
|
||||
if should_pull {
|
||||
println!("should pull {}", obj.clone().relative_s.unwrap());
|
||||
if obj.href.clone().unwrap().chars().last().unwrap() == '/' {
|
||||
folders.push(obj.clone());
|
||||
} else {
|
||||
files.push(obj.clone());
|
||||
}
|
||||
// if doesn't exist locally when cannot skip it as we need to pull it
|
||||
if !exist {
|
||||
return false;
|
||||
}
|
||||
|
||||
// if local directory is older there is changes on the remote we cannot
|
||||
// skip this folder
|
||||
!o.read().is_older(obj.lastmodified.unwrap().timestamp())
|
||||
}
|
||||
|
||||
}
|
||||
fn req(api_props: &ApiProps, depth: &str, relative_s: &str) -> Result<Vec<ObjProps>, ApiError> {
|
||||
ReqProps::new()
|
||||
.set_request(relative_s, &api_props)
|
||||
.set_depth(depth)
|
||||
.gethref()
|
||||
.getlastmodified()
|
||||
.send_req_multiple()
|
||||
}
|
||||
|
||||
|
@ -76,6 +76,7 @@ impl Object {
|
||||
self.obj_p.exists()
|
||||
}
|
||||
|
||||
/// return true if the local file is older than the remote one
|
||||
pub fn is_older(&mut self, ts: i64) -> bool {
|
||||
// todo be aware of the diff of ts format
|
||||
ts > self.ts.expect("Should be read before used") / 1000
|
||||
|
@ -1,6 +1,16 @@
|
||||
use crate::services::{req_props::ObjProps, api::ApiError};
|
||||
|
||||
pub fn enumerate_remote(req: impl Fn(&str) -> Result<Vec<ObjProps>, ApiError>, depth: Option<&str>) -> (Vec<ObjProps>, Vec<ObjProps>) {
|
||||
pub struct EnumerateOptions {
|
||||
pub depth: Option<String>,
|
||||
pub relative_s: Option<String>,
|
||||
}
|
||||
|
||||
pub fn enumerate_remote(
|
||||
req: impl Fn(&str) -> Result<Vec<ObjProps>, ApiError>,
|
||||
should_skip: &dyn Fn(ObjProps) -> bool,
|
||||
options: EnumerateOptions
|
||||
) -> (Vec<ObjProps>, Vec<ObjProps>) {
|
||||
|
||||
let mut folders: Vec<ObjProps> = vec![ObjProps::new()];
|
||||
let mut all_folders: Vec<ObjProps> = vec![];
|
||||
let mut files: Vec<ObjProps> = vec![];
|
||||
@ -10,7 +20,7 @@ pub fn enumerate_remote(req: impl Fn(&str) -> Result<Vec<ObjProps>, ApiError>, d
|
||||
|
||||
let relative_s = match folder.relative_s {
|
||||
Some(relative_s) => relative_s,
|
||||
None => String::from(""),
|
||||
None => options.relative_s.clone().unwrap_or(String::from("")),
|
||||
};
|
||||
|
||||
// request folder content
|
||||
@ -34,23 +44,45 @@ pub fn enumerate_remote(req: impl Fn(&str) -> Result<Vec<ObjProps>, ApiError>, d
|
||||
};
|
||||
|
||||
// separate folders and files in response
|
||||
|
||||
let mut iter = objs.iter();
|
||||
// first element is not used as it is the fetched folder
|
||||
let default_depth = calc_depth(iter.next().unwrap());
|
||||
let d = depth.unwrap_or("0").parse::<u16>().unwrap();
|
||||
let d = options.depth.clone().unwrap_or("0".to_owned()).parse::<u16>().unwrap();
|
||||
let mut skip_depth = 0;
|
||||
for object in iter {
|
||||
if object.is_dir() {
|
||||
let current_depth = calc_depth(object);
|
||||
// skip children of skiped folder
|
||||
if skip_depth != 0 && skip_depth < current_depth {
|
||||
continue;
|
||||
}
|
||||
|
||||
let should_skip = should_skip(object.clone());
|
||||
if should_skip {
|
||||
skip_depth = current_depth;
|
||||
} else {
|
||||
skip_depth = 0;
|
||||
all_folders.push(object.clone());
|
||||
}
|
||||
|
||||
// should get content of this folder if it is not already in this reponse
|
||||
if calc_depth(object) - default_depth == d {
|
||||
if current_depth - default_depth == d && !should_skip {
|
||||
folders.push(object.clone());
|
||||
}
|
||||
all_folders.push(object.clone());
|
||||
} else {
|
||||
let current_depth = calc_depth(object);
|
||||
// skip children of skiped folder
|
||||
if skip_depth != 0 && skip_depth < current_depth {
|
||||
continue;
|
||||
}
|
||||
|
||||
if !should_skip(object.clone()) {
|
||||
skip_depth = 0;
|
||||
files.push(object.clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
(all_folders, files)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user