use std::collections::HashSet; use std::env; use std::path::Path; use rusoto_core::Region; use rusoto_core::request::HttpClient; use rusoto_credential::StaticProvider; use rusoto_s3::ListObjectsRequest; use rusoto_s3::PutObjectRequest; use rusoto_s3::S3; use rusoto_s3::S3Client; fn main() { let region_name = env::var("NC_REGION").expect("export NC_REGION with the endpoint region"); let endpoint = env::var("NC_ENDPOINT").expect("export NC_ENDPOINT with the endpot URL"); let bucket = env::var("NC_BUCKET").expect("export NC_BUCKET with the bucket to be accessed"); let access_key = env::var("NC_ACCESS_KEY").expect("export NC_ACCESS_KEY with the access key to the bucket"); let secret_key = env::var("NC_SECRET_KEY").expect("export NC_SECRET_KEY with the secret key to the bucket"); println!("Accessing {}::{}", region_name, endpoint); let region = Region::Custom { name: region_name.to_owned(), endpoint: endpoint.to_owned() }; let client = S3Client::new_with( HttpClient::new().expect("Failed to create http client"), StaticProvider::new_minimal(access_key, secret_key), region ); let mut truncated = Some(true); let mut start_at = None; let mut files_dirs: HashSet = HashSet::new(); let mut directory_files: HashSet = HashSet::new(); while truncated.unwrap_or(false) { let list_objects_request = ListObjectsRequest { bucket: bucket.to_owned(), marker: start_at, ..Default::default() }; println!("Request: {:?}", list_objects_request); let result = client .list_objects(list_objects_request) .sync() .expect("Can't list contents of buckets"); truncated = result.is_truncated; start_at = result.next_marker; result.contents .expect("Didn't get any objects") .iter() .for_each(|item| { let filename = item.key.as_ref().unwrap(); if filename.ends_with("/") { files_dirs.insert(filename.clone()); } else { let mut path = Path::new(filename); while path.parent().is_some() { directory_files.insert(path.parent().unwrap().to_str().unwrap().to_string() + "/"); path = path.parent().unwrap(); } } }); } let missing: HashSet<_> = directory_files.difference(&files_dirs).collect(); println!("Directories with files:\n{:#?}", directory_files); println!("Directories with controllers:\n{:#?}", files_dirs); println!("Difference:\n{:#?}", directory_files.difference(&files_dirs)); for control in missing.iter() { println!("Creating {}", control); let control_file = PutObjectRequest { bucket: bucket.to_owned(), content_type: Some("httpd/unix-directory".to_owned()), content_length: Some(0), key: control.to_string(), ..Default::default() }; match client.put_object(control_file).sync() { Ok(_) => println!("Success!"), Err(error) => println!("Failed to create file: {}", error) } } }