Skip to content

Commit a09ec43

Browse files
committed
feat: Sources in build manifest
1 parent 189f426 commit a09ec43

File tree

3 files changed

+89
-3
lines changed

3 files changed

+89
-3
lines changed

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,10 @@ serde = { version = "1.0.219", features = ["derive"] }
2727
serde_yaml = "0.9.34"
2828
tar = "0.4.44"
2929
tokio = { version = "1.47.1", optional = true, features = ["rt"] }
30+
temp-dir = "0.1.16"
3031
walkdir = "2.5.0"
3132

3233
[dev-dependencies]
33-
temp-dir = "0.1.16"
3434
httpmock = "0.7.0"
3535

3636
[features]

src/build/mod.rs

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,15 @@
1+
mod sources;
2+
13
use anyhow::{Context, Result, bail};
24
use std::{
35
fs,
46
path::{Path, PathBuf},
57
process::Command,
68
};
9+
use temp_dir::TempDir;
710

811
use crate::{
12+
build::sources::get_sources,
913
chunks::save_tree,
1014
repo::{self, Metadata, PackageManifest, insert_package, remove_package},
1115
};
@@ -28,6 +32,18 @@ struct BuildManifest {
2832
edition: String,
2933
/// Script to be run before packaging
3034
build_script: Option<PathBuf>,
35+
36+
sources: Option<Vec<Source>>,
37+
}
38+
39+
#[derive(serde::Deserialize, serde::Serialize, Clone)]
40+
struct Source {
41+
/// Should either be git, tar or local
42+
kind: String,
43+
/// URL to the source.
44+
url: String,
45+
/// Path to extract.
46+
path: Option<String>,
3147
}
3248

3349
/// Builds and inserts a package into a Repository from a `build_manifest`
@@ -37,6 +53,7 @@ struct BuildManifest {
3753
/// - Filesystem (Out of Space, Permissions)
3854
/// - Build Script Failure
3955
pub fn build(build_manifest_path: &Path, repo_path: &Path) -> Result<PackageManifest> {
56+
let build_dir = TempDir::new()?;
4057
let build_manifest_path = &build_manifest_path.canonicalize()?;
4158

4259
let build_manifest: BuildManifest =
@@ -49,11 +66,15 @@ pub fn build(build_manifest_path: &Path, repo_path: &Path) -> Result<PackageMani
4966
.parent()
5067
.unwrap_or_else(|| Path::new("/"));
5168

69+
if let Some(sources) = build_manifest.sources {
70+
get_sources(build_dir.path(), build_manifest_parent, &sources)?;
71+
}
72+
5273
if let Some(script) = build_manifest.build_script {
5374
let result = Command::new("sh")
5475
.arg("-c")
5576
.arg(build_manifest_parent.join(script))
56-
.current_dir(build_manifest_parent)
77+
.current_dir(build_dir.path())
5778
.status()?;
5879

5980
if !result.success() {
@@ -62,7 +83,7 @@ pub fn build(build_manifest_path: &Path, repo_path: &Path) -> Result<PackageMani
6283
}
6384

6485
let chunks = save_tree(
65-
&build_manifest_parent.join(build_manifest.directory),
86+
&build_dir.path().join(&build_manifest.directory),
6687
&repo_path.join("chunks"),
6788
repo_manifest.hash_kind,
6889
)?;

src/build/sources.rs

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
use crate::build::Source;
2+
use anyhow::Context;
3+
use anyhow::Result;
4+
use std::fs;
5+
use std::path::Path;
6+
use std::process::Command;
7+
8+
pub fn get_sources(path: &Path, source_path: &Path, sources: &[Source]) -> Result<()> {
9+
for source in sources {
10+
match source.kind.as_str() {
11+
"git" => pull_git(&source.url, path).with_context(|| {
12+
format!("Failed to pull git repo from {}", source_path.display())
13+
})?,
14+
"tar" => todo!("Tar is not implemented"),
15+
"local" => pull_local(source_path, path).with_context(|| {
16+
format!("Failed to copy local source from {}", source_path.display())
17+
})?,
18+
_ => {
19+
unimplemented!("No handler is implemented for source.kind.{}", source.kind)
20+
}
21+
}
22+
}
23+
24+
Ok(())
25+
}
26+
27+
/// Just copy files from a local path into the target.
28+
/// If target already exists, nuke it first.
29+
fn pull_local(source_path: &Path, target_path: &Path) -> Result<()> {
30+
fs::create_dir_all(target_path)
31+
.with_context(|| format!("Failed to create target dir {}", target_path.display()))?;
32+
33+
// Copy recursively
34+
for entry in walkdir::WalkDir::new(source_path) {
35+
let entry = entry?;
36+
let rel_path = entry.path().strip_prefix(source_path)?;
37+
let dest = target_path.join(rel_path);
38+
39+
if entry.file_type().is_dir() {
40+
fs::create_dir_all(&dest)?;
41+
} else {
42+
fs::copy(entry.path(), &dest)?;
43+
}
44+
}
45+
46+
Ok(())
47+
}
48+
49+
/// Clone or pull a git repo depending on whether it already exists.
50+
fn pull_git(source_path: &str, target_path: &Path) -> Result<()> {
51+
// Clone fresh
52+
let status = Command::new("git")
53+
.arg("clone")
54+
.arg(source_path)
55+
.arg(target_path)
56+
.status()
57+
.with_context(|| "Failed to run git clone")?;
58+
if !status.success() {
59+
anyhow::bail!("git clone failed");
60+
}
61+
62+
Ok(())
63+
}
64+
65+
// fn pull_tar(source_path: &Path, target_path: &Path) -> Result<()> {}

0 commit comments

Comments
 (0)