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
use super::prelude::{File, Index, IndexList, Pid, Project, Strategy, Timeline};
use std::collections::HashMap;
use std::path::Path;

/// Workspace interface
pub trait Workspace {
	type Project: Project;
	type File: File;

	fn projects(&self) -> &[Self::Project];

	/// Conflict handling strategy
	///
	/// Note that the strategy should not be determine from the content of the file but rather the *location* of the file.
	/// This is for keeping the handling strategy consistent across all project.
	fn strategy(&self, index: &Index) -> Strategy;

	fn file(path: &Path, pid: Pid) -> Option<Self::File>;

	fn formatter(pid: &Pid, filename: &str) -> String {
		format!("{}_{}", filename, pid.value())
	}

	fn resolve(&self) -> Timeline<Self>
	where
		Self: Sized,
	{
		let preview = preview(self);
		let projects = project_paths(self);

		let strategy = indexes(self)
			.map(|index| {
				let strategy = preview
					.get_different_pid(index)
					.map_or(Strategy::Replace, |_| self.strategy(index));
				(index, strategy)
			})
			.collect();

		Timeline::new(strategy, projects)
	}
}

/// Get an iterator over Workspace's projects
fn projects<W: Workspace>(workspace: &W) -> impl Iterator<Item = &W::Project> {
	workspace.projects().iter()
}

/// Get an iterator over every indexes in all projects
fn indexes<W: Workspace>(workspace: &W) -> impl Iterator<Item = &Index> {
	projects(workspace).flat_map(Project::indexes)
}

/// Get HashMap of 'Pid → Project's path'
fn project_paths<W: Workspace>(workspace: &W) -> HashMap<Pid, &Path> {
	projects(workspace).map(|p| (p.pid(), p.root())).collect()
}

/// Get IndexList of all indexes
fn preview<W: Workspace>(workspace: &W) -> IndexList {
	indexes(workspace).collect()
}