Skip to content

Commit 494dc33

Browse files
author
Philip Johansson
committed
Archive and unpack files instead of copying
1 parent bae6d61 commit 494dc33

File tree

3 files changed

+24
-78
lines changed

3 files changed

+24
-78
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/acap-build/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,3 +16,4 @@ serde_json = { workspace = true, features = ["preserve_order"] }
1616
tempfile = { workspace = true }
1717
regex = { workspace = true }
1818
tempdir = { workspace = true }
19+
tar = { workspace = true }

crates/acap-build/src/lib.rs

Lines changed: 22 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use std::{
55
env,
66
ffi::OsString,
77
fs,
8-
io::Write,
8+
io::{Cursor, Write},
99
os::unix::fs::PermissionsExt,
1010
path::{Path, PathBuf},
1111
process::Command,
@@ -18,6 +18,8 @@ use log::{debug, info};
1818
use semver::Version;
1919
use serde_json::Value;
2020

21+
use tar::{Builder, Archive};
22+
2123
use crate::files::{
2224
cgi_conf::CgiConf, manifest::Manifest, package_conf::PackageConf, param_conf::ParamConf,
2325
};
@@ -27,65 +29,6 @@ mod json_ext;
2729

2830
mod files;
2931

30-
// TODO: Find a better way to support reproducible builds
31-
fn copy<P: AsRef<Path>, Q: AsRef<Path>>(
32-
src: P,
33-
dst: Q,
34-
copy_permissions: bool,
35-
) -> anyhow::Result<()> {
36-
let src = src.as_ref();
37-
let dst = dst.as_ref();
38-
if dst.symlink_metadata().is_ok() {
39-
bail!("Path already exists {dst:?}");
40-
}
41-
if src.is_symlink() {
42-
// FIXME: Copy symlink in Rust
43-
let mut cp = Command::new("cp");
44-
45-
if copy_permissions {
46-
cp.arg("--preserve=mode");
47-
}
48-
49-
cp.arg("-dn").arg(src.as_os_str()).arg(dst.as_os_str());
50-
51-
if !cp.status()?.success() {
52-
bail!("Failed to copy symlink: {}", src.display());
53-
}
54-
} else if copy_permissions {
55-
fs::copy(src, dst)?;
56-
} else {
57-
let mut src = fs::File::open(src)?;
58-
let mut dst = fs::File::create(dst)?;
59-
std::io::copy(&mut src, &mut dst)?;
60-
}
61-
Ok(())
62-
}
63-
64-
fn copy_recursively(src: &Path, dst: &Path, copy_permissions: bool) -> anyhow::Result<()> {
65-
if !src.is_dir() {
66-
copy(src, dst, copy_permissions)?;
67-
debug!("Created reg {dst:?}");
68-
return Ok(());
69-
}
70-
match fs::create_dir(dst) {
71-
Ok(()) => {
72-
debug!("Created dir {dst:?}");
73-
Ok(())
74-
}
75-
Err(e) if e.kind() == std::io::ErrorKind::AlreadyExists => Ok(()),
76-
Err(e) => Err(e),
77-
}?;
78-
for entry in fs::read_dir(src)? {
79-
let entry = entry?;
80-
copy_recursively(
81-
&entry.path(),
82-
&dst.join(entry.file_name()),
83-
copy_permissions,
84-
)?;
85-
}
86-
Ok(())
87-
}
88-
8932
enum AcapBuildImpl {
9033
Reference,
9134
Equivalent,
@@ -111,6 +54,7 @@ pub struct AppBuilder<'a> {
11154
files: Vec<String>,
11255
default_architecture: Architecture,
11356
app_name: String,
57+
ar: Option<Builder::<Cursor::<Vec::<u8>>>>,
11458
}
11559

11660
impl<'a> AppBuilder<'a> {
@@ -123,13 +67,16 @@ impl<'a> AppBuilder<'a> {
12367
let manifest: Value = serde_json::from_reader(fs::File::open(manifest)?)?;
12468
let manifest = Manifest::new(manifest, default_architecture)?;
12569
let app_name = manifest.try_find_app_name()?.to_string();
70+
let mut ar = Builder::new(Cursor::new(Vec::new()));
71+
ar.follow_symlinks(false);
12672
Ok(Self {
12773
preserve_permissions,
12874
staging_dir,
12975
manifest,
13076
app_name,
13177
files: Vec::new(),
13278
default_architecture,
79+
ar: Some(ar),
13380
})
13481
}
13582

@@ -161,20 +108,15 @@ impl<'a> AppBuilder<'a> {
161108
Ok(self)
162109
}
163110

164-
// TODO: Remove the file system copy
165111
pub fn add_as(&mut self, path: &Path, name: &str) -> anyhow::Result<PathBuf> {
166-
let dst = self.staging_dir.join(name);
167-
if dst.symlink_metadata().is_ok() {
168-
bail!("Cannot add {path:?} because {name} already exists");
169-
}
170-
copy_recursively(path, &dst, self.preserve_permissions)?;
171-
self.files.push(name.to_string());
172-
if name == self.app_name && !self.preserve_permissions {
173-
let mut permissions = fs::metadata(&dst)?.permissions();
174-
let mode = permissions.mode();
175-
permissions.set_mode(mode | 0o111);
176-
fs::set_permissions(&dst, permissions)?;
112+
if path.symlink_metadata().unwrap().file_type().is_dir() {
113+
self.ar.as_mut().unwrap().append_dir_all(name, path)?;
114+
} else {
115+
self.ar.as_mut().unwrap().append_path_with_name(path, name)?;
177116
}
117+
118+
let dst = self.staging_dir.join(name);
119+
178120
debug!("Added {name} from {path:?}");
179121
Ok(dst)
180122
}
@@ -188,7 +130,13 @@ impl<'a> AppBuilder<'a> {
188130
}
189131

190132
/// Build the EAP and return its path.
191-
pub fn build(self) -> anyhow::Result<OsString> {
133+
pub fn build(mut self) -> anyhow::Result<OsString> {
134+
let cursor = Cursor::new(self.ar.take().unwrap().into_inner()?.into_inner());
135+
let mut archive = Archive::new(cursor);
136+
archive.set_preserve_permissions(self.preserve_permissions);
137+
archive.set_preserve_mtime(false);
138+
archive.unpack(self.staging_dir)?;
139+
192140
match AcapBuildImpl::from_env_or_default()? {
193141
AcapBuildImpl::Reference => {
194142
debug!("Using acap-build");
@@ -206,14 +154,9 @@ impl<'a> AppBuilder<'a> {
206154
let Self {
207155
staging_dir,
208156
default_architecture,
209-
manifest,
210157
..
211158
} = &self;
212159

213-
fs::File::create_new(staging_dir.join("manifest.json"))
214-
.context("creating manifest.json")?
215-
.write_all(manifest.try_to_string()?.as_bytes())?;
216-
217160
let mut acap_build = Command::new("acap-build");
218161
acap_build.args(["--build", "no-build"]);
219162
for file in self.additional_files() {
@@ -424,6 +367,7 @@ impl<'a> AppBuilder<'a> {
424367
[
425368
Some(self.app_name.as_str()),
426369
Some("LICENSE"),
370+
Some("manifest.json"),
427371
self.manifest.try_find_post_install_script().ok(),
428372
self.manifest.try_find_pre_uninstall_script().ok(),
429373
]

0 commit comments

Comments
 (0)