datman 0.1.0

A chunked and deduplicated backup system using Yama
Documentation
/*
This file is part of Yama.

Yama is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

Yama is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with Yama.  If not, see <https://www.gnu.org/licenses/>.
*/


use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use std::fs::File;
use std::io::Read;
use std::path::{Path, PathBuf};

// TODO how do we handle?:
//      - (important) yama push of one pile to another
//      - backup policy stuff like 'minimum backup frequency' ... show when it's not been done
//      - backup policy stuff like 'minimum on two different disks, not powered at the same time...'

#[derive(Clone, Serialize, Deserialize, Debug)]
pub struct Descriptor {
    /// Dataset labels
    pub labels: Vec<String>,

    /// Sources
    pub source: HashMap<String, SourceDescriptor>,

    /// Paths to destination Yama Piles. Remote Piles need a local virtual pile to specify the layers.
    pub piles: HashMap<String, DestPileDescriptor>,
}

#[derive(Clone, Serialize, Deserialize, Debug)]
#[serde(untagged)]
pub enum SourceDescriptor {
    DirectorySource {
        hostname: String,
        directory: PathBuf,
    },
    VirtualSource {
        /// The name of the helper program that will be used to do this backup.
        helper: String,

        /// The label that will be assigned to this source.
        label: String,

        /// The kind of virtual source (how it operates).
        kind: VirtualSourceKind,

        #[serde(flatten)]
        extra_args: HashMap<String, toml::Value>,
    },
}

#[derive(Clone, Serialize, Deserialize, Debug)]
#[serde(untagged)]
pub enum VirtualSourceKind {
    Stdout {
        #[serde(rename = "stdout")]
        filename: String,
    },
    // TODO(feature) TempDir
}

#[derive(Clone, Serialize, Deserialize, Debug)]
pub struct DestPileDescriptor {
    pub path: PathBuf,
    pub included_labels: Vec<String>,
}

pub fn load_descriptor(path: &Path) -> anyhow::Result<Descriptor> {
    let descriptor_file = path.join("datman.toml");
    let mut buf = Vec::new();
    File::open(descriptor_file)?.read_to_end(&mut buf)?;
    Ok(toml::de::from_slice(&buf)?)
}