libsalmo/migration_data/
committed.rs

1use 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  /// the hex encoded string of the hash
21  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}