Scuffed Day 20

Ideally redo using `git2` later on
This commit is contained in:
Aadi Desai 2023-12-21 02:33:36 +00:00
parent ad1a1f013d
commit 74e65a2195
Signed by: supleed2
SSH key fingerprint: SHA256:CkbNRs0yVzXEiUp2zd0PSxsfRUMFF9bLlKXtE1xEbKM
4 changed files with 140 additions and 2 deletions

41
Cargo.lock generated
View file

@ -432,6 +432,7 @@ dependencies = [
"axum 0.7.2",
"axum-extra",
"base64",
"bytes",
"chrono",
"futures",
"image",
@ -444,6 +445,8 @@ dependencies = [
"shuttle-runtime",
"shuttle-shared-db",
"sqlx",
"tar",
"tempfile",
"tokio",
"tower-http 0.5.0",
"tracing",
@ -796,6 +799,18 @@ dependencies = [
"simd-adler32",
]
[[package]]
name = "filetime"
version = "0.2.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1ee447700ac8aa0b2f2bd7bc4462ad686ba06baa6727ac149a2d6277f0d240fd"
dependencies = [
"cfg-if",
"libc",
"redox_syscall",
"windows-sys 0.52.0",
]
[[package]]
name = "finl_unicode"
version = "1.2.0"
@ -2407,9 +2422,9 @@ checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
[[package]]
name = "rustix"
version = "0.38.26"
version = "0.38.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9470c4bf8246c8daf25f9598dca807fb6510347b1e1cfa55749113850c79d88a"
checksum = "72e572a5e8ca657d7366229cdde4bd14c4eb5499a9573d4d366fe1b599daa316"
dependencies = [
"bitflags 2.4.1",
"errno",
@ -3168,6 +3183,17 @@ dependencies = [
"libc",
]
[[package]]
name = "tar"
version = "0.4.40"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b16afcea1f22891c49a00c751c7b63b2233284064f11a200fc624137c51e2ddb"
dependencies = [
"filetime",
"libc",
"xattr",
]
[[package]]
name = "tempfile"
version = "3.8.1"
@ -4020,6 +4046,17 @@ dependencies = [
"windows-sys 0.48.0",
]
[[package]]
name = "xattr"
version = "1.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a7dae5072fe1f8db8f8d29059189ac175196e410e40ba42d5d4684ae2f750995"
dependencies = [
"libc",
"linux-raw-sys",
"rustix",
]
[[package]]
name = "zerocopy"
version = "0.7.30"

View file

@ -9,6 +9,7 @@ askama_axum = "0.4.0"
axum = { version = "0.7.2", features = ["macros", "multipart", "ws"] }
axum-extra = { version = "0.9.0", features = ["typed-header"] }
base64 = "0.21.5"
bytes = "1.5.0"
chrono = { version = "0.4.31", default-features = false, features = ["std"] }
futures = "0.3.29"
image = "0.24.7"
@ -21,6 +22,8 @@ shuttle-axum = { version = "0.35.0", default-features = false, features = ["axum
shuttle-runtime = "0.35.0"
shuttle-shared-db = { version = "0.35.1", features = ["postgres"] }
sqlx = { version = "0.7.3", features = ["postgres", "runtime-tokio-native-tls"] }
tar = "0.4.40"
tempfile = "3.8.1"
tokio = "1.34.0"
tower-http = { version = "0.5.0", features = ["fs","trace"] }
tracing = "0.1.40"

96
src/cal/day20.rs Normal file
View file

@ -0,0 +1,96 @@
use axum::{body::Bytes, http::StatusCode, response::IntoResponse, routing::post, Router};
use bytes::Buf;
use std::process::Command;
pub(crate) fn router() -> Router {
Router::new()
.route("/20/archive_files", post(archive_files))
.route("/20/archive_files_size", post(archive_files_size))
.route("/20/cookie", post(cookie))
}
async fn archive_files(body: Bytes) -> Result<impl IntoResponse, (StatusCode, String)> {
Ok(tar::Archive::new(body.reader())
.entries()
.map_err(|e| (StatusCode::BAD_REQUEST, e.to_string()))?
.count()
.to_string())
}
async fn archive_files_size(body: Bytes) -> Result<impl IntoResponse, (StatusCode, String)> {
Ok(tar::Archive::new(body.reader())
.entries()
.map_err(|e| (StatusCode::BAD_REQUEST, e.to_string()))?
.filter_map(Result::ok)
.map(|entry| entry.size())
.sum::<u64>()
.to_string())
}
async fn cookie(body: Bytes) -> Result<impl IntoResponse, (StatusCode, String)> {
let dir = tempfile::tempdir_in(".")
.map_err(|e| (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()))?;
let mut archive = tar::Archive::new(body.reader());
archive
.unpack(dir.path())
.map_err(|e| (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()))?;
let log = Command::new("git")
.args(["log", "christmas", "--format=%cn,%H"])
.current_dir(dir.path())
.output()
.map_err(|e| (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()))?;
if !log.status.success() {
return Err((
StatusCode::INTERNAL_SERVER_ERROR,
"Git log failed, christmas branch may not exist".to_string(),
));
}
let output = String::from_utf8(log.stdout)
.map_err(|e| (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()))?;
let commits = output
.lines()
.filter_map(|l| l.split_once(','))
.collect::<Vec<_>>();
for (author, hash) in commits {
let Ok(Ok(files)) = Command::new("git")
.args(["ls-tree", "-r", hash])
.current_dir(dir.path())
.output()
.map(|o| String::from_utf8(o.stdout))
else {
continue;
};
let Some(file) = files.lines().find(|s| s.contains("santa.txt")) else {
continue;
};
let Some(blob) = file.split_whitespace().nth(2) else {
continue;
};
let Ok(santatxt) = Command::new("git")
.args(["show", blob])
.current_dir(dir.path())
.output()
else {
continue;
};
if santatxt.status.success() {
if let Ok(s) = String::from_utf8(santatxt.stdout) {
if s.contains("COOKIE") {
return Ok(format!("{author} {hash}"));
}
}
}
}
Err((StatusCode::BAD_REQUEST, "Commit not found".to_string()))
}

View file

@ -11,6 +11,7 @@ mod day14;
mod day15;
mod day18;
mod day19;
mod day20;
pub(crate) fn router(pool: sqlx::PgPool) -> axum::Router {
axum::Router::new()
@ -27,4 +28,5 @@ pub(crate) fn router(pool: sqlx::PgPool) -> axum::Router {
.nest("/", day15::router())
.nest("/", day18::router(pool))
.nest("/", day19::router())
.nest("/", day20::router())
}