Skip to content

Commit

Permalink
Fix checksum formatting in ME
Browse files Browse the repository at this point in the history
This is to align with other tools, for example the CLI shasum utility on
linux.

The old format is still recognized and accepted for compatibility with
existing migration tables.

closes #1887
  • Loading branch information
tomhoule committed May 3, 2021
1 parent 60cc71d commit a7e3598
Show file tree
Hide file tree
Showing 2 changed files with 51 additions and 2 deletions.
37 changes: 37 additions & 0 deletions migration-engine/connectors/migration-connector/src/lib.rs
Expand Up @@ -93,11 +93,17 @@ fn checksum(script: &str) -> String {
checksum.format_checksum()
}

/// The length (in bytes, or equivalently ascii characters) of the checksum
/// strings.
const CHECKSUM_STR_LEN: usize = 64;

/// Format a checksum to a hexadecimal string. This is used to checksum
/// migration scripts with Sha256.
pub trait FormatChecksum {
/// Format a checksum to a hexadecimal string.
fn format_checksum(&self) -> String;
/// Obsolete checksum method, should only be used for compatibility.
fn format_checksum_old(&self) -> String;
}

impl FormatChecksum for [u8; 32] {
Expand All @@ -106,10 +112,41 @@ impl FormatChecksum for [u8; 32] {

let mut checksum_string = String::with_capacity(32 * 2);

for byte in self {
write!(checksum_string, "{:02x}", byte).unwrap();
}

assert_eq!(checksum_string.len(), CHECKSUM_STR_LEN);

checksum_string
}

// Due to an omission in a previous version of the migration engine,
// some migrations tables will have old migrations with checksum strings
// that have not been zero-padded.
//
// Corresponding issue:
// https://github.com/prisma/prisma-engines/issues/1887
fn format_checksum_old(&self) -> String {
use std::fmt::Write as _;

let mut checksum_string = String::with_capacity(32 * 2);

for byte in self {
write!(checksum_string, "{:x}", byte).unwrap();
}

checksum_string
}
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn format_checksum_does_not_strip_zeros() {
assert_eq!(checksum("hello"), "2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824");
assert_eq!(checksum("abcd").len(), CHECKSUM_STR_LEN);
}
}
Expand Up @@ -5,7 +5,7 @@
//! It also contains multiple subfolders, named after the migration id, and each containing:
//! - A migration script

use crate::{ConnectorError, ConnectorResult, FormatChecksum};
use crate::{CHECKSUM_STR_LEN, ConnectorError, ConnectorResult, FormatChecksum};
use sha2::{Digest, Sha256, Sha512};
use std::{
error::Error,
Expand Down Expand Up @@ -221,7 +221,19 @@ impl MigrationDirectory {
hasher.update(&filesystem_script);
let filesystem_script_checksum: [u8; 32] = hasher.finalize().into();

Ok(checksum_str == filesystem_script_checksum.format_checksum())
// Due to an omission in a previous version of the migration engine,
// some migrations tables will have old migrations with checksum strings
// that have not been zero-padded.
//
// Corresponding issue:
// https://github.com/prisma/prisma-engines/issues/1887
let filesystem_script_checksum_str = if checksum_str.len() > 0 && checksum_str.len() != CHECKSUM_STR_LEN {
filesystem_script_checksum.format_checksum_old()
} else {
filesystem_script_checksum.format_checksum()
};

Ok(checksum_str == filesystem_script_checksum_str)
}

/// Write the migration script to the directory.
Expand Down

0 comments on commit a7e3598

Please sign in to comment.