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
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
use std::path::PathBuf;
use crate::pg_errors::PgEmbedError;
use archiver_rs::{Archive, Compressed};
use futures::TryFutureExt;
fn unzip_txz(zip_file_path: &PathBuf, cache_dir: &PathBuf) -> Result<PathBuf, PgEmbedError> {
let mut zip =
archiver_rs::Zip::open(zip_file_path.as_path()).map_err(|e| PgEmbedError::ReadFileError(e))?;
let file_name = zip.files().map_err(|e| PgEmbedError::UnpackFailure(e))?
.into_iter()
.find(|name| {
name.ends_with(".txz")
});
match file_name {
Some(file_name) => {
let mut target_path = cache_dir.clone();
target_path.push(&file_name);
zip.extract_single(
&target_path.as_path(),
file_name.clone(),
).map_err(|e| PgEmbedError::UnpackFailure(e))?;
Ok(target_path)
}
None => { Err(PgEmbedError::InvalidPgPackage("no postgresql txz in zip".to_string())) }
}
}
fn decompress_xz(file_path: &PathBuf) -> Result<PathBuf, PgEmbedError> {
let mut xz =
archiver_rs::Xz::open(
file_path.as_path(),
).map_err(|e| PgEmbedError::ReadFileError(e))?;
let target_path = file_path.with_extension(".tar");
xz.decompress(&target_path.as_path()).map_err(|e| PgEmbedError::UnpackFailure(e))?;
Ok(target_path)
}
fn decompress_tar(file_path: &PathBuf, cache_dir: &PathBuf) -> Result<(), PgEmbedError> {
let mut tar =
archiver_rs::Tar::open(
&file_path.as_path(),
).map_err(|e| PgEmbedError::ReadFileError(e))?;
tar.extract(cache_dir.as_path()).map_err(|e| PgEmbedError::UnpackFailure(e))?;
Ok(())
}
pub async fn unpack_postgres(
zip_file_path: &PathBuf, cache_dir: &PathBuf,
) -> Result<(), PgEmbedError> {
let txz_file_path = unzip_txz(&zip_file_path, &cache_dir)?;
let tar_file_path = decompress_xz(&txz_file_path)?;
tokio::fs::remove_file(txz_file_path).map_err(|e| PgEmbedError::PgCleanUpFailure(e)).await?;
decompress_tar(&tar_file_path, &cache_dir);
tokio::fs::remove_file(tar_file_path).map_err(|e| PgEmbedError::PgCleanUpFailure(e)).await?;
Ok(())
}