libsalmo/migration_data/
committed.rs1use std::{path::Path, fs::{read_to_string, self}, io::ErrorKind, collections::HashMap};
2
3use anyhow::{Context, anyhow};
4use log::{info, trace};
5use serde::{Serialize, Deserialize};
6use toml_edit::{Document, value, array, Table};
7
8use crate::salmo_contex::SalmoContext;
9
10use super::migrations::Migration;
11
12#[derive(Debug, Serialize, Deserialize, Clone)]
13pub struct CommittedFile {
14 pub commits: Vec<Commit>
15}
16
17#[derive(Debug, Serialize, Deserialize, Clone)]
18pub struct Commit {
19 pub id: String,
20 pub hash: String
22}
23
24impl CommittedFile {
25 pub fn load(dir: &Path) -> anyhow::Result<Self> {
26 trace!("loading committed file at {:?}", dir);
27 let file = match read_to_string(dir.join("committed.toml")) {
28 Ok(s) => s,
29 Err(e) => match e.kind() {
30 ErrorKind::NotFound => {
31 info!("No committed file. Assuming no commits, this is fine.");
32 return Ok(CommittedFile { commits: Vec::new() })
33 },
34 _ => return Err(e.into()),
35 },
36 };
37
38 toml_edit::de::from_str(&file).context("parsing committed.toml")
39 }
40
41 pub fn add_commit(ctx: &SalmoContext, migration_id: &str) -> anyhow::Result<Commit> {
42 let dir = ctx.config.migrations_directory.join("committed.toml");
43 let file = read_to_string(&dir).or_else(|e| match e.kind() {
44 ErrorKind::NotFound => Ok("".to_string()),
45 _ => Err(e)
46 })?;
47 let mut doc = file.parse::<Document>()?;
48 doc.entry("version").or_insert(value("1"));
49 let commits = doc.entry("commits")
50 .or_insert(array())
51 .as_array_of_tables_mut()
52 .ok_or_else(|| anyhow!("corrupt committed.toml: the [commits] value must be an array of tables"))?;
53
54 let migrations = ctx.migrations()?;
55 let m = migrations.db.get(migration_id).ok_or_else(|| anyhow!("migration with id `{}` does not exist!", migration_id))?;
56 let hash = m.migrate_hash()?;
57
58 let mut commit_table = Table::new();
59 commit_table.insert("id", value(migration_id));
60 commit_table.insert("hash", value(&hash));
61
62 commits.push(commit_table);
63 fs::write(dir, doc.to_string())?;
64
65 Ok(Commit { id: migration_id.to_string(), hash })
66 }
67
68 pub fn commits_hash(&self) -> HashMap<String, Commit> {
69 self.commits.iter().map(|c| (c.id.clone(), c.clone())).collect()
70 }
71
72 pub fn contains_migration(&self, m: &Migration) -> bool {
73 self.commits.iter().any(|c| c.id == m.id )
74 }
75}