remote diff with new opti remote enumerater

This commit is contained in:
grimhilt
2023-07-21 17:10:57 +02:00
parent f01983b29d
commit 4e20ec94f9
5 changed files with 97 additions and 70 deletions

View File

@@ -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)

View File

@@ -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 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![]
}
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 {
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());
}
}
}
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())
});
for folder in folders {
println!("should pull {}", folder.clone().relative_s.unwrap());
}
for file in files {
println!("should pull {}", file.clone().relative_s.unwrap());
}
}
fn should_skip(obj: ObjProps) -> bool {
let mut o = Object::new(&obj.clone().relative_s.unwrap());
let exist = o.exists();
// 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()
}

View File

@@ -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

View File

@@ -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,20 +44,42 @@ 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 {
files.push(object.clone());
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());
}
}
}
}