1use std::collections::HashMap;
2use crate::{
3 storage::Secret,
4 sync::{ConflictInfo, SyncMetadata},
5 error::Result,
6};
7
8
9
10pub async fn detect_conflicts(
11 local_secrets: &HashMap<String, Secret>,
12 remote_metadata: &SyncMetadata,
13) -> Result<Vec<ConflictInfo>> {
14 let mut conflicts = Vec::new();
15
16 for (key, secret) in local_secrets {
18 if secret.metadata.version != remote_metadata.sync_version {
19 let parts: Vec<&str> = key.split(':').collect();
20 if parts.len() >= 4 {
21 conflicts.push(ConflictInfo {
22 secret_key: parts[3].to_string(),
23 namespace: parts[2].to_string(),
24 local_version: secret.metadata.version,
25 remote_version: remote_metadata.sync_version,
26 conflict_type: "ModifiedBoth".to_string(),
27 });
28 }
29 }
30 }
31
32 Ok(conflicts)
33}
34
35#[derive(Debug)]
36pub enum ConflictResolution {
37 UseLocal,
38 UseRemote,
39 Merge,
40 Skip,
41}
42
43pub struct ConflictResolver;
44
45impl ConflictResolver {
46 #[allow(dead_code)]
47 pub fn resolve_conflict(
48 local_secret: &Secret,
49 remote_secret: &Secret,
50 strategy: ConflictResolution,
51 ) -> Result<Secret> {
52 match strategy {
53 ConflictResolution::UseLocal => Ok(local_secret.clone()),
54 ConflictResolution::UseRemote => Ok(remote_secret.clone()),
55 ConflictResolution::Merge => {
56 if local_secret.metadata.updated_at > remote_secret.metadata.updated_at {
58 Ok(local_secret.clone())
59 } else {
60 Ok(remote_secret.clone())
61 }
62 }
63 ConflictResolution::Skip => Ok(local_secret.clone()),
64 }
65 }
66
67 pub fn auto_resolve_conflicts(
68 conflicts: &[ConflictInfo],
69 strategy: AutoResolveStrategy,
70 ) -> Result<Vec<(ConflictInfo, ConflictResolution)>> {
71 let mut resolutions = Vec::new();
72
73 for conflict in conflicts {
74 let resolution = match strategy {
75 AutoResolveStrategy::PreferLocal => ConflictResolution::UseLocal,
76 AutoResolveStrategy::PreferRemote => ConflictResolution::UseRemote,
77 AutoResolveStrategy::PreferNewer => ConflictResolution::Merge,
78 AutoResolveStrategy::Manual => ConflictResolution::Skip,
79 };
80 resolutions.push((conflict.clone(), resolution));
81 }
82
83 Ok(resolutions)
84 }
85}
86
87#[derive(Debug)]
88pub enum AutoResolveStrategy {
89 PreferLocal,
90 PreferRemote,
91 PreferNewer,
92 Manual,
93}