summaryrefslogtreecommitdiff
path: root/crates/vcs_data/src/data/local/latest_file_data.rs
blob: 5248cfb62bc635ca8635ea994a2361d5b0788844 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
use std::{collections::HashMap, io::Error, path::PathBuf};

use cfg_file::ConfigFile;
use serde::{Deserialize, Serialize};

use crate::{
    constants::{CLIENT_FILE_LATEST_DATA, CLIENT_FILE_MEMBER_HELD_NOSET},
    current::current_local_path,
    data::{
        member::MemberId,
        vault::virtual_file::{VirtualFileId, VirtualFileVersion},
    },
};

const ACCOUNT: &str = "{account}";

/// # Latest file data
/// Records the file holder and the latest version for permission and update checks
#[derive(Debug, Default, Clone, Serialize, Deserialize, ConfigFile)]
#[cfg_file(path = CLIENT_FILE_MEMBER_HELD_NOSET)]
pub struct LatestFileData {
    /// File holding status
    #[serde(rename = "held")]
    held_status: HashMap<VirtualFileId, HeldStatus>,

    /// File version
    #[serde(rename = "ver")]
    versions: HashMap<VirtualFileId, VirtualFileVersion>,
}

#[derive(Debug, Default, Clone, Serialize, Deserialize)]
pub enum HeldStatus {
    #[serde(rename = "Hold")]
    HeldWith(MemberId), // Held, status changes are sync to the client

    #[serde(rename = "None")]
    NotHeld, // Not held, status changes are sync to the client

    #[default]
    #[serde(rename = "Unknown")]
    WantedToKnow, // Holding status is unknown, notify server must inform client
}

impl LatestFileData {
    /// Get the path to the file holding the held status information for the given member.
    pub fn data_path(account: &MemberId) -> Result<PathBuf, std::io::Error> {
        let Some(local_path) = current_local_path() else {
            return Err(Error::new(
                std::io::ErrorKind::NotFound,
                "Workspace not found.",
            ));
        };
        Ok(local_path.join(CLIENT_FILE_LATEST_DATA.replace(ACCOUNT, account)))
    }

    /// Get the member who holds the file with the given ID.
    pub fn file_holder(&self, vfid: &VirtualFileId) -> Option<&MemberId> {
        self.held_status.get(vfid).and_then(|status| match status {
            HeldStatus::HeldWith(id) => Some(id),
            _ => None,
        })
    }

    /// Get the version of the file with the given ID.
    pub fn file_version(&self, vfid: &VirtualFileId) -> Option<&VirtualFileVersion> {
        self.versions.get(vfid)
    }

    /// Update the held status of the files.
    pub fn update_info(
        &mut self,
        map: HashMap<VirtualFileId, (Option<MemberId>, VirtualFileVersion)>,
    ) {
        for (vfid, (member_id, version)) in map {
            self.held_status.insert(
                vfid.clone(),
                match member_id {
                    Some(member_id) => HeldStatus::HeldWith(member_id),
                    None => HeldStatus::NotHeld,
                },
            );
            self.versions.insert(vfid, version);
        }
    }
}