init STORAGESFILE and DEVICESFILE at repo init and change Storages.read

- return Err instead of new object when there is no STORAGESFILE
- setup empty DEVICESFILE and STORAGESFILE at repository initialization
- update readme
This commit is contained in:
qwjyh 2024-03-11 08:22:35 +09:00
parent 7e026ec229
commit 8eb7d1179d
5 changed files with 36 additions and 57 deletions

View file

@ -1,10 +1,10 @@
# TODO: # TODO:
- [x] split subcommands to functions - [x] split subcommands to functions
- [ ] write test for init subcommand - [x] write test for init subcommand
- [ ] write test with existing repo - [ ] write test with existing repo
- [ ] with ssh credential - [x] with ssh credential
- [ ] ssh-agent - [x] ssh-agent
- [ ] specify key - [x] specify key
- [ ] add storage remove command - [ ] add storage remove command
- [ ] add sync subcommand - [ ] add sync subcommand
- [ ] add check subcommand - [ ] add check subcommand

View file

@ -1,6 +1,7 @@
//! Init subcommand. //! Init subcommand.
//! Initialize xdbm for the device. //! Initialize xdbm for the device.
use crate::storages::{Storages, STORAGESFILE};
use crate::{add_and_commit, full_status, get_devices, write_devices, Device, DEVICESFILE}; use crate::{add_and_commit, full_status, get_devices, write_devices, Device, DEVICESFILE};
use anyhow::{anyhow, Context, Ok, Result}; use anyhow::{anyhow, Context, Ok, Result};
use core::panic; use core::panic;
@ -81,11 +82,11 @@ pub(crate) fn cmd_init(
return Err(anyhow!("Device name is empty")); return Err(anyhow!("Device name is empty"));
} }
// get repo or initialize it // get repo or initialize it
let (is_first_device, repo) = match repo_url { let repo = match repo_url {
Some(repo_url) => { Some(repo_url) => {
trace!("repo: {}", repo_url); trace!("repo: {}", repo_url);
let repo = clone_repo(&repo_url, use_sshagent, ssh_key, config_dir)?; let repo = clone_repo(&repo_url, use_sshagent, ssh_key, config_dir)?;
(false, repo) repo
} }
None => { None => {
trace!("No repo provided"); trace!("No repo provided");
@ -104,7 +105,26 @@ pub(crate) fn cmd_init(
add_and_commit(&repo, Path::new(".gitignore"), "Add devname to gitignore.")?; add_and_commit(&repo, Path::new(".gitignore"), "Add devname to gitignore.")?;
full_status(&repo)?; full_status(&repo)?;
} }
(true, repo)
// TDOO: wrap up below into one commit?
// set up devices.yml
let devices: Vec<Device> = vec![];
write_devices(&config_dir, devices)?;
add_and_commit(
&repo,
Path::new(DEVICESFILE),
&format!("Initialize {}", DEVICESFILE),
)?;
// set up storages.yml
let storages = Storages::new();
storages.write(&config_dir)?;
add_and_commit(
&repo,
Path::new(STORAGESFILE),
&format!("Initialize {}", STORAGESFILE),
)?;
repo
} }
}; };
full_status(&repo)?; full_status(&repo)?;
@ -126,11 +146,7 @@ pub(crate) fn cmd_init(
// Add new device to devices.yml // Add new device to devices.yml
{ {
let mut devices: Vec<Device> = if is_first_device { let mut devices: Vec<Device> = get_devices(&config_dir)?;
vec![]
} else {
get_devices(&config_dir)?
};
trace!("devices: {:?}", devices); trace!("devices: {:?}", devices);
if devices.iter().any(|x| x.name() == device.name()) { if devices.iter().any(|x| x.name() == device.name()) {
return Err(anyhow!("device name is already used.")); return Err(anyhow!("device name is already used."));
@ -145,7 +161,7 @@ pub(crate) fn cmd_init(
add_and_commit( add_and_commit(
&repo, &repo,
&Path::new(DEVICESFILE), &Path::new(DEVICESFILE),
&format!("Add new devname: {}", &device.name()), &format!("Add new device: {}", &device.name()),
)?; )?;
println!("Device added"); println!("Device added");
full_status(&repo)?; full_status(&repo)?;

View file

@ -33,7 +33,6 @@ pub(crate) fn cmd_storage_add(
) -> Result<()> { ) -> Result<()> {
trace!("Storage Add {:?}, {:?}", storage_type, path); trace!("Storage Add {:?}, {:?}", storage_type, path);
// Get storages // Get storages
// let mut storages: Vec<Storage> = get_storages(&config_dir)?;
let mut storages = Storages::read(&config_dir)?; let mut storages = Storages::read(&config_dir)?;
trace!("found storages: {:?}", storages); trace!("found storages: {:?}", storages);
@ -109,7 +108,7 @@ pub(crate) fn cmd_storage_add(
StorageType::S => { StorageType::S => {
if storages.list.is_empty() { if storages.list.is_empty() {
return Err(anyhow!( return Err(anyhow!(
"No storages found. Please add at least 1 physical storage first." "No storages found. Please add at least 1 physical/online storage first to add sub directory."
)); ));
} }
let path = path.unwrap_or_else(|| { let path = path.unwrap_or_else(|| {
@ -325,7 +324,7 @@ fn ask_unique_name(storages: &Storages, target: String) -> Result<String> {
let mut disk_name = String::new(); let mut disk_name = String::new();
loop { loop {
disk_name = Text::new(format!("Name for {}:", target).as_str()).prompt()?; disk_name = Text::new(format!("Name for {}:", target).as_str()).prompt()?;
if storages.list.iter().all(|(k, v)| k != &disk_name) { if storages.list.iter().all(|(k, _v)| k != &disk_name) {
break; break;
} }
println!("The name {} is already used.", disk_name); println!("The name {} is already used.", disk_name);

View file

@ -18,16 +18,15 @@ use git2::{Commit, Oid, Repository};
use inquire::{min_length, Confirm, CustomType, Select}; use inquire::{min_length, Confirm, CustomType, Select};
use inquire::{validator::Validation, Text}; use inquire::{validator::Validation, Text};
use serde_yaml; use serde_yaml;
use storages::Storages;
use std::collections::HashMap; use std::collections::HashMap;
use std::path::Path; use std::path::Path;
use std::path::{self, PathBuf}; use std::path::{self, PathBuf};
use storages::Storages;
use crate::cmd_args::{Cli, Commands, StorageCommands}; use crate::cmd_args::{Cli, Commands, StorageCommands};
use crate::storages::online_storage; use crate::storages::online_storage;
use crate::storages::{ use crate::storages::{
directory, local_info, physical_drive_partition, Storage, directory, local_info, physical_drive_partition, Storage, StorageExt, StorageType, STORAGESFILE,
StorageExt, StorageType, STORAGESFILE,
}; };
use devices::{Device, DEVICESFILE, *}; use devices::{Device, DEVICESFILE, *};
@ -97,8 +96,7 @@ fn main() -> Result<()> {
} }
Commands::Check {} => { Commands::Check {} => {
println!("Config dir: {}", &config_dir.display()); println!("Config dir: {}", &config_dir.display());
let _storages = let _storages = Storages::read(&config_dir)?;
Storages::read(&config_dir)?;
todo!() todo!()
} }
} }

View file

@ -225,8 +225,8 @@ impl Storages {
pub fn read(config_dir: &path::Path) -> Result<Self> { pub fn read(config_dir: &path::Path) -> Result<Self> {
let storages_file = config_dir.join(STORAGESFILE); let storages_file = config_dir.join(STORAGESFILE);
if !storages_file.exists() { if !storages_file.exists() {
trace!("No storages file found. Returning new `Storages` object."); warn!("No storages file found.");
return Ok(Storages::new()); return Err(anyhow!("Couln't find {}", STORAGESFILE))
} }
trace!("Reading {:?}", storages_file); trace!("Reading {:?}", storages_file);
let f = fs::File::open(storages_file)?; let f = fs::File::open(storages_file)?;
@ -242,37 +242,3 @@ impl Storages {
serde_yaml::to_writer(writer, &self).context(format!("Failed to writing to {:?}", STORAGESFILE)) serde_yaml::to_writer(writer, &self).context(format!("Failed to writing to {:?}", STORAGESFILE))
} }
} }
// /// Get `HashMap<String, Storage>` from devices.yml([devices::DEVICESFILE]).
// /// If [devices::DEVICESFILE] isn't found, return empty vec.
// pub fn get_storages(config_dir: &path::Path) -> Result<HashMap<String, Storage>> {
// if let Some(storages_file) = fs::read_dir(&config_dir)?
// .filter(|f| {
// f.as_ref().map_or_else(
// |_e| false,
// |f| {
// let storagesfile: ffi::OsString = STORAGESFILE.into();
// f.path().file_name() == Some(&storagesfile)
// },
// )
// })
// .next()
// {
// trace!("{} found: {:?}", STORAGESFILE, storages_file);
// let f = fs::File::open(config_dir.join(STORAGESFILE))?;
// let reader = io::BufReader::new(f);
// let yaml: HashMap<String, Storage> =
// serde_yaml::from_reader(reader).context("Failed to read devices.yml")?;
// Ok(yaml)
// } else {
// trace!("No {} found", STORAGESFILE);
// Ok(HashMap::new())
// }
// }
//
// /// Write `storages` to yaml file in `config_dir`.
// pub fn write_storages(config_dir: &path::Path, storages: HashMap<String, Storage>) -> Result<()> {
// let f = fs::File::create(config_dir.join(STORAGESFILE))?;
// let writer = io::BufWriter::new(f);
// serde_yaml::to_writer(writer, &storages).map_err(|e| anyhow!(e))
// }