diff --git a/.gitignore b/.gitignore
index 4a5b0953..1a98f873 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,8 +1,8 @@
+*.pb.go
*.tar.*
.env
.vagrant
dist
packer_*_*_*.box
-rootfs
target
vorpal-*-*
diff --git a/Cargo.lock b/Cargo.lock
index 116bbbff..dbcf04e4 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -659,9 +659,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "bitflags"
-version = "2.8.0"
+version = "2.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8f68f53c83ab957f72c32642f3868eec03eb974d1fb82e453128456482613d36"
+checksum = "5c8214115b7bf84099f1309324e63141d4c5d7cc26862f97a0a857dbefe165bd"
[[package]]
name = "block-buffer"
@@ -732,21 +732,20 @@ dependencies = [
[[package]]
name = "bzip2"
-version = "0.5.1"
+version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "75b89e7c29231c673a61a46e722602bcd138298f6b9e81e71119693534585f5c"
+checksum = "49ecfb22d906f800d4fe833b6282cf4dc1c298f5057ca0b5445e5c209735ca47"
dependencies = [
"bzip2-sys",
]
[[package]]
name = "bzip2-sys"
-version = "0.1.12+1.0.8"
+version = "0.1.13+1.0.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "72ebc2f1a417f01e1da30ef264ee86ae31d2dcd2d603ea283d3c244a883ca2a9"
+checksum = "225bff33b2141874fe80d71e07d6eec4f85c5c216453dd96388240f96e1acc14"
dependencies = [
"cc",
- "libc",
"pkg-config",
]
@@ -761,9 +760,9 @@ dependencies = [
[[package]]
name = "cc"
-version = "1.2.15"
+version = "1.2.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c736e259eea577f443d5c86c304f9f4ae0295c43f3ba05c21f1d66b5f06001af"
+checksum = "be714c154be609ec7f5dad223a33bf1482fff90472de28f7362806e6d4832b8c"
dependencies = [
"jobserver",
"libc",
@@ -1008,7 +1007,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "33d852cb9b869c2a9b3df2f71a3074817f01e1844f839a144f5fcef059a4eb5d"
dependencies = [
"libc",
- "windows-sys 0.52.0",
+ "windows-sys 0.59.0",
]
[[package]]
@@ -1037,9 +1036,9 @@ checksum = "1d674e81391d1e1ab681a28d99df07927c6d4aa5b027d7da16ba32d1d21ecd99"
[[package]]
name = "flate2"
-version = "1.0.35"
+version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c936bfdafb507ebbf50b8074c54fa31c5be9a1e7e5f467dd659697041407d07c"
+checksum = "11faaf5a5236997af9848be0bef4db95824b1d534ebc64d0f0c6cf3e67bd38dc"
dependencies = [
"crc32fast",
"miniz_oxide",
@@ -1383,7 +1382,7 @@ dependencies = [
"rustls 0.23.23",
"rustls-pki-types",
"tokio",
- "tokio-rustls 0.26.1",
+ "tokio-rustls 0.26.2",
"tower-service",
"webpki-roots",
]
@@ -1694,7 +1693,7 @@ version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d"
dependencies = [
- "bitflags 2.8.0",
+ "bitflags 2.9.0",
"libc",
"redox_syscall 0.5.9",
]
@@ -1707,9 +1706,9 @@ checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab"
[[package]]
name = "litemap"
-version = "0.7.4"
+version = "0.7.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4ee93343901ab17bd981295f2cf0026d4ad018c7c31ba84549a4ddbb47a45104"
+checksum = "23fb14cb19457329c82206317a5663005a4d404783dc74f4252769b0d5f42856"
[[package]]
name = "log"
@@ -2137,7 +2136,7 @@ dependencies = [
"once_cell",
"socket2",
"tracing",
- "windows-sys 0.52.0",
+ "windows-sys 0.59.0",
]
[[package]]
@@ -2194,7 +2193,7 @@ version = "0.5.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "82b568323e98e49e2a0899dcee453dd679fae22d69adf9b11dd508d1549b7e2f"
dependencies = [
- "bitflags 2.8.0",
+ "bitflags 2.9.0",
]
[[package]]
@@ -2264,7 +2263,7 @@ dependencies = [
"serde_urlencoded",
"sync_wrapper",
"tokio",
- "tokio-rustls 0.26.1",
+ "tokio-rustls 0.26.2",
"tower 0.5.2",
"tower-service",
"url",
@@ -2337,11 +2336,11 @@ version = "0.38.44"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154"
dependencies = [
- "bitflags 2.8.0",
+ "bitflags 2.9.0",
"errno",
"libc",
"linux-raw-sys",
- "windows-sys 0.52.0",
+ "windows-sys 0.59.0",
]
[[package]]
@@ -2505,7 +2504,7 @@ version = "2.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02"
dependencies = [
- "bitflags 2.8.0",
+ "bitflags 2.9.0",
"core-foundation",
"core-foundation-sys",
"libc",
@@ -2750,7 +2749,7 @@ dependencies = [
"getrandom 0.3.1",
"once_cell",
"rustix",
- "windows-sys 0.52.0",
+ "windows-sys 0.59.0",
]
[[package]]
@@ -2898,9 +2897,9 @@ dependencies = [
[[package]]
name = "tokio-rustls"
-version = "0.26.1"
+version = "0.26.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5f6d0975eaace0cf0fcadee4e4aaa5da15b5c079146f2cffb67c113be122bf37"
+checksum = "8e727b36a1a0e8b74c376ac2211e40c2c8af09fb4013c60d910495810f008e9b"
dependencies = [
"rustls 0.23.23",
"tokio",
@@ -3236,6 +3235,7 @@ version = "0.1.0"
dependencies = [
"anyhow",
"tokio",
+ "vorpal-schema",
"vorpal-sdk",
]
@@ -3502,7 +3502,7 @@ version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb"
dependencies = [
- "windows-sys 0.52.0",
+ "windows-sys 0.59.0",
]
[[package]]
@@ -3638,7 +3638,7 @@ version = "0.33.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3268f3d866458b787f390cf61f4bbb563b922d091359f9608842999eaee3943c"
dependencies = [
- "bitflags 2.8.0",
+ "bitflags 2.9.0",
]
[[package]]
@@ -3706,18 +3706,18 @@ dependencies = [
[[package]]
name = "zerofrom"
-version = "0.1.5"
+version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cff3ee08c995dee1859d998dea82f7374f2826091dd9cd47def953cae446cd2e"
+checksum = "50cc42e0333e05660c3587f3bf9d0478688e15d870fab3346451ce7f8c9fbea5"
dependencies = [
"zerofrom-derive",
]
[[package]]
name = "zerofrom-derive"
-version = "0.1.5"
+version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "595eed982f7d355beb85837f651fa22e90b3c044842dc7f2c2842c086f295808"
+checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502"
dependencies = [
"proc-macro2",
"quote",
diff --git a/Cargo.toml b/Cargo.toml
index 08198bcb..79235a79 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,3 +1,12 @@
[workspace]
-members = ["cli", "config", "notary", "registry", "schema", "sdk", "store", "worker"]
+members = [
+ "cli",
+ "config",
+ "notary",
+ "registry",
+ "schema",
+ "sdk/rust",
+ "store",
+ "worker"
+]
resolver = "2"
diff --git a/README.md b/README.md
index 40e71115..65ddd3c9 100644
--- a/README.md
+++ b/README.md
@@ -2,7 +2,9 @@
Build and ship software with one powerful tool.
-
+
+
+
## Overview
@@ -14,20 +16,17 @@ Below are examples of a Rust application in Vorpal configured in different langu
```rust
use anyhow::Result;
-use vorpal_schema::vorpal::config::v0::Config;
use vorpal_sdk::config::{artifact::language::rust::rust_artifact, get_context};
#[tokio::main]
async fn main() -> Result<()> {
let context = &mut get_context().await?;
- let artifact = rust_artifact(context, "example-app").await?;
+ let example = rust_artifact(context, "example-app").await?;
- context
- .run(Config {
- artifacts: vec![artifact],
- })
- .await
+ let artifacts = vec![artifact];
+
+ context.run(artifacts).await
}
```
@@ -40,7 +39,6 @@ import (
"context"
"log"
- "github.com/vorpal-sdk/vorpal"
"github.com/vorpal-sdk/vorpal/config"
"github.com/vorpal-sdk/vorpal/config/artifact/language/rust"
)
@@ -51,20 +49,39 @@ func main() {
log.Fatal(err)
}
- artifact, err := rust.Artifact(context, "example-app")
+ example, err := rust.Artifact(context, "example-app")
if err != nil {
log.Fatal(err)
}
- err = context.Run(config.Config{
- Artifacts: []config.Artifact{artifact},
- })
+ artifacts := []config.Artifact{example}
+
+ err = context.Run(artifacts)
if err != nil {
log.Fatal(err)
}
}
```
+### Python
+
+```python
+from vorpal_sdk.config import get_context
+from vorpal_sdk.config.artifact.language.rust import rust_artifact
+
+def main():
+ context = get_context()
+
+ example = rust_artifact(context, "example-app")
+
+ artifacts = [example]
+
+ context.run(artifacts)
+
+if __name__ == "__main__":
+ main()
+```
+
### TypeScript
```typescript
@@ -74,17 +91,17 @@ import { rustArtifact } from '@vorpal/sdk/config/artifact/language/rust';
async function main() {
const context = await getContext();
- const artifact = await rustArtifact(context, 'example-app');
+ const example = await rustArtifact(context, 'example-app');
+
+ const artifacts = [example];
- await context.run({
- artifacts: [artifact],
- }));
+ await context.run(artifacts);
}
main().catch(console.error);
```
-## Infrastructure
+## Components
Below is the existing working diagram that illustrates the platform's design:
diff --git a/cli/Cargo.toml b/cli/Cargo.toml
index 65dd275a..dbdcd301 100644
--- a/cli/Cargo.toml
+++ b/cli/Cargo.toml
@@ -23,6 +23,6 @@ tracing-subscriber = { default-features = false, features = ["ansi", "fmt", "reg
vorpal-notary = { default-features = false, path = "../notary" }
vorpal-registry = { default-features = false, path = "../registry" }
vorpal-schema = { default-features = false, path = "../schema" }
-vorpal-sdk = { default-features = false, path = "../sdk" }
+vorpal-sdk = { default-features = false, path = "../sdk/rust" }
vorpal-store = { default-features = false, path = "../store" }
vorpal-worker = { default-features = false, path = "../worker" }
diff --git a/cli/src/main.rs b/cli/src/main.rs
index 5f41127e..6cf1abd1 100644
--- a/cli/src/main.rs
+++ b/cli/src/main.rs
@@ -30,9 +30,9 @@ use vorpal_schema::{
registry::v0::registry_service_server::RegistryServiceServer,
},
};
-use vorpal_sdk::config::{
- artifact::{language::rust, toolchain::protoc},
- ConfigContext,
+use vorpal_sdk::{
+ artifact::{language::rust, protoc},
+ context::ConfigContext,
};
use vorpal_store::paths::{get_artifact_path, get_public_key_path};
use vorpal_worker::artifact::ArtifactServer;
@@ -238,7 +238,7 @@ async fn get_config_file_path(
bail!("config toolchain not found: {}", toolchain_path.display());
}
- let toolchain_target = rust::get_toolchain_target(artifact_system)?;
+ let toolchain_target = rust::get_rust_toolchain_target(artifact_system)?;
let toolchain_version = get_rust_toolchain_version();
let toolchain_bin_path = Path::new(&format!(
diff --git a/config/Cargo.toml b/config/Cargo.toml
index 24abfa1d..bc73d0ba 100644
--- a/config/Cargo.toml
+++ b/config/Cargo.toml
@@ -10,4 +10,5 @@ path = "src/main.rs"
[dependencies]
anyhow = { default-features = false, version = "1" }
tokio = { default-features = false, features = ["rt-multi-thread"], version = "1" }
-vorpal-sdk = { default-features = false, path = "../sdk" }
+vorpal-schema = { default-features = false, path = "../schema" }
+vorpal-sdk = { default-features = false, path = "../sdk/rust" }
diff --git a/config/src/main.rs b/config/src/main.rs
index d2a385bf..80124579 100644
--- a/config/src/main.rs
+++ b/config/src/main.rs
@@ -1,20 +1,19 @@
use anyhow::Result;
-use vorpal_sdk::config::{
- artifact::language::rust::{rust_package, rust_shell},
- get_context,
-};
+use vorpal_sdk::context::get_context;
+
+mod vorpal;
#[tokio::main]
async fn main() -> Result<()> {
- // Get the context
+ // 1. Get the context
let context = &mut get_context().await?;
- // Create artifacts
+ // 2. Create artifacts
let artifacts = vec![
- rust_package(context, "vorpal").await?,
- rust_shell(context, "vorpal").await?,
+ vorpal::package(context).await?,
+ vorpal::shell(context).await?,
];
- // Run the context
+ // 3. Run the context
context.run(artifacts).await
}
diff --git a/config/src/vorpal.rs b/config/src/vorpal.rs
new file mode 100644
index 00000000..67d29254
--- /dev/null
+++ b/config/src/vorpal.rs
@@ -0,0 +1,82 @@
+use anyhow::Result;
+use vorpal_schema::vorpal::artifact::v0::ArtifactId;
+use vorpal_sdk::{
+ artifact::{
+ get_artifact_envkey, go, goimports, gopls,
+ language::rust::{
+ get_rust_toolchain_target, get_rust_toolchain_version, rust_package, toolchain_artifact,
+ },
+ protoc, protoc_gen_go, protoc_gen_go_grpc,
+ shell::shell_artifact,
+ },
+ context::ConfigContext,
+};
+
+pub async fn package(context: &mut ConfigContext) -> Result {
+ let excludes = vec![
+ ".env",
+ ".envrc",
+ ".github",
+ ".gitignore",
+ ".packer",
+ ".vagrant",
+ "Dockerfile",
+ "Vagrantfile",
+ "dist",
+ "makefile",
+ "script",
+ "sdk/go",
+ "shell.nix",
+ "vorpal-domains.svg",
+ "vorpal-purpose.jpg",
+ ];
+
+ rust_package(context, "vorpal", excludes).await
+}
+
+pub async fn shell(context: &mut ConfigContext) -> Result {
+ let name = "vorpal";
+
+ let go = go::artifact(context).await?;
+ let goimports = goimports::artifact(context).await?;
+ let gopls = gopls::artifact(context).await?;
+ let protoc = protoc::artifact(context).await?;
+ let protoc_gen_go = protoc_gen_go::artifact(context).await?;
+ let protoc_gen_go_grpc = protoc_gen_go_grpc::artifact(context).await?;
+ let rust_toolchain = toolchain_artifact(context, name).await?;
+ let rust_toolchain_target = get_rust_toolchain_target(context.get_target())?;
+
+ let artifacts = vec![
+ go.clone(),
+ goimports.clone(),
+ gopls.clone(),
+ protoc.clone(),
+ protoc_gen_go.clone(),
+ protoc_gen_go_grpc.clone(),
+ rust_toolchain.clone(),
+ ];
+
+ let envs = vec![
+ format!(
+ "PATH={}/bin:{}/bin:{}/bin:{}/bin:{}/bin:{}/bin:{}/toolchains/{}-{}/bin:$PATH",
+ get_artifact_envkey(&go),
+ get_artifact_envkey(&goimports),
+ get_artifact_envkey(&gopls),
+ get_artifact_envkey(&protoc),
+ get_artifact_envkey(&protoc_gen_go),
+ get_artifact_envkey(&protoc_gen_go_grpc),
+ get_artifact_envkey(&rust_toolchain),
+ get_rust_toolchain_version(),
+ rust_toolchain_target
+ ),
+ format!("RUSTUP_HOME={}", get_artifact_envkey(&rust_toolchain)),
+ format!(
+ "RUSTUP_TOOLCHAIN={}-{}",
+ get_rust_toolchain_version(),
+ rust_toolchain_target
+ ),
+ ];
+
+ // Create shell artifact
+ shell_artifact(context, artifacts, envs, name).await
+}
diff --git a/makefile b/makefile
index 13bcfbda..792f6bfb 100644
--- a/makefile
+++ b/makefile
@@ -46,6 +46,13 @@ dist: build
tar -czvf $(DIST_DIR)/vorpal-$(ARCH)-$(OS).tar.gz \
-C $(WORK_DIR)/target/$(TARGET) vorpal
+# Vorpal
+generate:
+ mkdir -p sdk/go/api
+ protoc --go_opt=paths=source_relative --go_out=sdk/go/api --go-grpc_opt=paths=source_relative --go-grpc_out=sdk/go/api --proto_path=schema/api v0/artifact/artifact.proto
+ protoc --go_opt=paths=source_relative --go_out=sdk/go/api --go-grpc_opt=paths=source_relative --go-grpc_out=sdk/go/api --proto_path=schema/api v0/registry/registry.proto
+ protoc --go_opt=paths=source_relative --go_out=sdk/go/api --go-grpc_opt=paths=source_relative --go-grpc_out=sdk/go/api --proto_path=schema/api v0/config/config.proto
+
# Development (with Vorpal)
vorpal-config:
diff --git a/schema/api/v0/artifact/artifact.proto b/schema/api/v0/artifact/artifact.proto
index 7f3c8fb9..aa616d45 100644
--- a/schema/api/v0/artifact/artifact.proto
+++ b/schema/api/v0/artifact/artifact.proto
@@ -2,6 +2,8 @@ syntax = "proto3";
package vorpal.artifact.v0;
+option go_package = "github.com/ALT-F4-LLC/vorpal/sdk/go/api/v0/artifact";
+
service ArtifactService {
rpc Build (ArtifactBuildRequest) returns (stream ArtifactBuildResponse);
}
diff --git a/schema/api/v0/config/config.proto b/schema/api/v0/config/config.proto
index 0582f291..53e742f7 100644
--- a/schema/api/v0/config/config.proto
+++ b/schema/api/v0/config/config.proto
@@ -2,6 +2,8 @@ syntax = "proto3";
package vorpal.config.v0;
+option go_package = "github.com/ALT-F4-LLC/vorpal/sdk/go/api/v0/config";
+
import "v0/artifact/artifact.proto";
service ConfigService {
diff --git a/schema/api/v0/registry/registry.proto b/schema/api/v0/registry/registry.proto
index d4e13e3c..0c109b7d 100644
--- a/schema/api/v0/registry/registry.proto
+++ b/schema/api/v0/registry/registry.proto
@@ -2,7 +2,7 @@ syntax = "proto3";
package vorpal.registry.v0;
-import "v0/artifact/artifact.proto";
+option go_package = "github.com/ALT-F4-LLC/vorpal/sdk/go/api/v0/registry";
service RegistryService {
rpc Exists(RegistryRequest) returns (RegistryResponse);
diff --git a/sdk/go/go.mod b/sdk/go/go.mod
new file mode 100644
index 00000000..d9eb0417
--- /dev/null
+++ b/sdk/go/go.mod
@@ -0,0 +1,35 @@
+module github.com/ALT-F4-LLC/vorpal/sdk/go
+
+go 1.23.5
+
+require (
+ github.com/google/uuid v1.6.0
+ github.com/h2non/filetype v1.1.3
+ github.com/mholt/archives v0.1.0
+ google.golang.org/grpc v1.70.0
+ google.golang.org/protobuf v1.36.3
+)
+
+require (
+ github.com/STARRY-S/zip v0.2.1 // indirect
+ github.com/andybalholm/brotli v1.1.1 // indirect
+ github.com/bodgit/plumbing v1.3.0 // indirect
+ github.com/bodgit/sevenzip v1.6.0 // indirect
+ github.com/bodgit/windows v1.0.1 // indirect
+ github.com/dsnet/compress v0.0.2-0.20230904184137-39efe44ab707 // indirect
+ github.com/hashicorp/errwrap v1.1.0 // indirect
+ github.com/hashicorp/go-multierror v1.1.1 // indirect
+ github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect
+ github.com/klauspost/compress v1.17.11 // indirect
+ github.com/klauspost/pgzip v1.2.6 // indirect
+ github.com/nwaples/rardecode/v2 v2.0.0-beta.4.0.20241112120701-034e449c6e78 // indirect
+ github.com/pierrec/lz4/v4 v4.1.21 // indirect
+ github.com/sorairolake/lzip-go v0.3.5 // indirect
+ github.com/therootcompany/xz v1.0.1 // indirect
+ github.com/ulikunitz/xz v0.5.12 // indirect
+ go4.org v0.0.0-20230225012048-214862532bf5 // indirect
+ golang.org/x/net v0.32.0 // indirect
+ golang.org/x/sys v0.28.0 // indirect
+ golang.org/x/text v0.21.0 // indirect
+ google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a // indirect
+)
diff --git a/sdk/go/go.sum b/sdk/go/go.sum
new file mode 100644
index 00000000..c4a9c4c2
--- /dev/null
+++ b/sdk/go/go.sum
@@ -0,0 +1,328 @@
+cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
+cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
+cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU=
+cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU=
+cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY=
+cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc=
+cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0=
+cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To=
+cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M=
+cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o=
+cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE=
+cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=
+cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I=
+cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw=
+cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw=
+cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos=
+dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
+github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
+github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
+github.com/STARRY-S/zip v0.2.1 h1:pWBd4tuSGm3wtpoqRZZ2EAwOmcHK6XFf7bU9qcJXyFg=
+github.com/STARRY-S/zip v0.2.1/go.mod h1:xNvshLODWtC4EJ702g7cTYn13G53o1+X9BWnPFpcWV4=
+github.com/andybalholm/brotli v1.1.1 h1:PR2pgnyFznKEugtsUo0xLdDop5SKXd5Qf5ysW+7XdTA=
+github.com/andybalholm/brotli v1.1.1/go.mod h1:05ib4cKhjx3OQYUY22hTVd34Bc8upXjOLL2rKwwZBoA=
+github.com/bodgit/plumbing v1.3.0 h1:pf9Itz1JOQgn7vEOE7v7nlEfBykYqvUYioC61TwWCFU=
+github.com/bodgit/plumbing v1.3.0/go.mod h1:JOTb4XiRu5xfnmdnDJo6GmSbSbtSyufrsyZFByMtKEs=
+github.com/bodgit/sevenzip v1.6.0 h1:a4R0Wu6/P1o1pP/3VV++aEOcyeBxeO/xE2Y9NSTrr6A=
+github.com/bodgit/sevenzip v1.6.0/go.mod h1:zOBh9nJUof7tcrlqJFv1koWRrhz3LbDbUNngkuZxLMc=
+github.com/bodgit/windows v1.0.1 h1:tF7K6KOluPYygXa3Z2594zxlkbKPAOvqr97etrGNIz4=
+github.com/bodgit/windows v1.0.1/go.mod h1:a6JLwrB4KrTR5hBpp8FI9/9W9jJfeQ2h4XDXU74ZCdM=
+github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
+github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
+github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
+github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
+github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
+github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
+github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/dsnet/compress v0.0.2-0.20230904184137-39efe44ab707 h1:2tV76y6Q9BB+NEBasnqvs7e49aEBFI8ejC89PSnWH+4=
+github.com/dsnet/compress v0.0.2-0.20230904184137-39efe44ab707/go.mod h1:qssHWj60/X5sZFNxpG4HBPDHVqxNm4DfnCKgrbZOT+s=
+github.com/dsnet/golib v0.0.0-20171103203638-1ea166775780/go.mod h1:Lj+Z9rebOhdfkVLjJ8T6VcRQv3SXugXy999NBtR9aFY=
+github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
+github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
+github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
+github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
+github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
+github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
+github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
+github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
+github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
+github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
+github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
+github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
+github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
+github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
+github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y=
+github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
+github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
+github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
+github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
+github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
+github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
+github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
+github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
+github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
+github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
+github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
+github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
+github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
+github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
+github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
+github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
+github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
+github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
+github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
+github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
+github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
+github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
+github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
+github.com/h2non/filetype v1.1.3 h1:FKkx9QbD7HR/zjK1Ia5XiBsq9zdLi5Kf3zGyFTAFkGg=
+github.com/h2non/filetype v1.1.3/go.mod h1:319b3zT68BvV+WRj7cwy856M2ehB3HqNOt6sy1HndBY=
+github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
+github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I=
+github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
+github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo=
+github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM=
+github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
+github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
+github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k=
+github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM=
+github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
+github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
+github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
+github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
+github.com/klauspost/compress v1.4.1/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
+github.com/klauspost/compress v1.17.11 h1:In6xLpyWOi1+C7tXUUWv2ot1QvBjxevKAaI6IXrJmUc=
+github.com/klauspost/compress v1.17.11/go.mod h1:pMDklpSncoRMuLFrf1W9Ss9KT+0rH90U12bZKk7uwG0=
+github.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
+github.com/klauspost/pgzip v1.2.6 h1:8RXeL5crjEUFnR2/Sn6GJNWtSQ3Dk8pq4CL3jvdDyjU=
+github.com/klauspost/pgzip v1.2.6/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs=
+github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
+github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
+github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
+github.com/mholt/archives v0.1.0 h1:FacgJyrjiuyomTuNA92X5GyRBRZjE43Y/lrzKIlF35Q=
+github.com/mholt/archives v0.1.0/go.mod h1:j/Ire/jm42GN7h90F5kzj6hf6ZFzEH66de+hmjEKu+I=
+github.com/nwaples/rardecode/v2 v2.0.0-beta.4.0.20241112120701-034e449c6e78 h1:MYzLheyVx1tJVDqfu3YnN4jtnyALNzLvwl+f58TcvQY=
+github.com/nwaples/rardecode/v2 v2.0.0-beta.4.0.20241112120701-034e449c6e78/go.mod h1:yntwv/HfMc/Hbvtq9I19D1n58te3h6KsqCf3GxyfBGY=
+github.com/pierrec/lz4/v4 v4.1.21 h1:yOVMLb6qSIDP67pl/5F7RepeKYu/VmTyEXvuMI5d9mQ=
+github.com/pierrec/lz4/v4 v4.1.21/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4=
+github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
+github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
+github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
+github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
+github.com/rwcarlsen/goexif v0.0.0-20190401172101-9e8deecbddbd/go.mod h1:hPqNNc0+uJM6H+SuU8sEs5K5IQeKccPqeSjfgcKGgPk=
+github.com/sorairolake/lzip-go v0.3.5 h1:ms5Xri9o1JBIWvOFAorYtUNik6HI3HgBTkISiqu0Cwg=
+github.com/sorairolake/lzip-go v0.3.5/go.mod h1:N0KYq5iWrMXI0ZEXKXaS9hCyOjZUQdBDEIbXfoUwbdk=
+github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
+github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
+github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
+github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
+github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
+github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
+github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
+github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
+github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
+github.com/therootcompany/xz v1.0.1 h1:CmOtsn1CbtmyYiusbfmhmkpAAETj0wBIH6kCYaX+xzw=
+github.com/therootcompany/xz v1.0.1/go.mod h1:3K3UH1yCKgBneZYhuQUvJ9HPD19UEXEI0BWbMn8qNMY=
+github.com/ulikunitz/xz v0.5.8/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=
+github.com/ulikunitz/xz v0.5.12 h1:37Nm15o69RwBkXM0J6A5OlE67RZTfzUxTj8fB3dfcsc=
+github.com/ulikunitz/xz v0.5.12/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=
+github.com/xyproto/randomstring v1.0.5 h1:YtlWPoRdgMu3NZtP45drfy1GKoojuR7hmRcnhZqKjWU=
+github.com/xyproto/randomstring v1.0.5/go.mod h1:rgmS5DeNXLivK7YprL0pY+lTuhNQW3iGxZ18UQApw/E=
+github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
+go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
+go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
+go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
+go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
+go.opentelemetry.io/otel v1.32.0 h1:WnBN+Xjcteh0zdk01SVqV55d/m62NJLJdIyb4y/WO5U=
+go.opentelemetry.io/otel v1.32.0/go.mod h1:00DCVSB0RQcnzlwyTfqtxSm+DRr9hpYrHjNGiBHVQIg=
+go.opentelemetry.io/otel/metric v1.32.0 h1:xV2umtmNcThh2/a/aCP+h64Xx5wsj8qqnkYZktzNa0M=
+go.opentelemetry.io/otel/metric v1.32.0/go.mod h1:jH7CIbbK6SH2V2wE16W05BHCtIDzauciCRLoc/SyMv8=
+go.opentelemetry.io/otel/sdk v1.32.0 h1:RNxepc9vK59A8XsgZQouW8ue8Gkb4jpWtJm9ge5lEG4=
+go.opentelemetry.io/otel/sdk v1.32.0/go.mod h1:LqgegDBjKMmb2GC6/PrTnteJG39I8/vJCAP9LlJXEjU=
+go.opentelemetry.io/otel/sdk/metric v1.32.0 h1:rZvFnvmvawYb0alrYkjraqJq0Z4ZUJAiyYCU9snn1CU=
+go.opentelemetry.io/otel/sdk/metric v1.32.0/go.mod h1:PWeZlq0zt9YkYAp3gjKZ0eicRYvOh1Gd+X99x6GHpCQ=
+go.opentelemetry.io/otel/trace v1.32.0 h1:WIC9mYrXf8TmY/EXuULKc8hR17vE+Hjv2cssQDe03fM=
+go.opentelemetry.io/otel/trace v1.32.0/go.mod h1:+i4rkvCraA+tG6AzwloGaCtkx53Fa+L+V8e9a7YvhT8=
+go4.org v0.0.0-20230225012048-214862532bf5 h1:nifaUDeh+rPaBCMPMQHZmvJf+QdpLFnuQPwx+LxVmtc=
+go4.org v0.0.0-20230225012048-214862532bf5/go.mod h1:F57wTi5Lrj6WLyswp5EYV1ncrEbFGHD4hhz6S1ZYeaU=
+golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
+golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
+golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
+golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
+golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
+golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
+golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
+golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
+golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek=
+golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY=
+golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
+golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
+golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
+golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
+golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
+golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
+golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
+golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
+golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
+golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
+golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
+golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
+golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs=
+golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
+golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
+golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
+golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
+golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
+golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
+golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
+golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
+golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
+golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
+golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
+golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
+golang.org/x/net v0.32.0 h1:ZqPmj8Kzc+Y6e0+skZsuACbx+wzMgo5MQsJh9Qd6aYI=
+golang.org/x/net v0.32.0/go.mod h1:CwU0IoeOlnQQWJ6ioyFrfRuomB8GKF6KbYXZVyeXNfs=
+golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
+golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
+golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
+golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
+golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
+golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ=
+golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
+golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA=
+golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
+golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
+golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
+golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
+golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
+golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
+golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
+golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
+golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
+golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
+golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
+golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo=
+golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
+golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
+golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
+golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
+golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
+golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
+golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
+golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
+golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
+golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
+golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
+golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
+golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
+golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
+golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
+golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
+golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
+golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
+golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
+golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
+golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
+golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
+google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M=
+google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
+google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
+google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
+google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
+google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
+google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
+google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
+google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
+google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
+google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
+google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
+google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
+google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
+google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
+google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
+google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
+google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
+google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
+google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8=
+google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
+google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
+google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
+google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
+google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
+google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a h1:hgh8P4EuoxpsuKMXX/To36nOFD7vixReXgn8lPGnt+o=
+google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a/go.mod h1:5uTbfoYQed2U9p3KIj2/Zzm02PYhndfdmML0qC3q3FU=
+google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
+google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
+google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
+google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
+google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
+google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
+google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
+google.golang.org/grpc v1.70.0 h1:pWFv03aZoHzlRKHWicjsZytKAiYCtNS0dHbXnIdq7jQ=
+google.golang.org/grpc v1.70.0/go.mod h1:ofIJqVKDXx/JiXrwr2IG4/zwdH9txy3IlF40RmcJSQw=
+google.golang.org/protobuf v1.36.3 h1:82DV7MYdb8anAVi3qge1wSnMDrnKK7ebr+I0hHRN1BU=
+google.golang.org/protobuf v1.36.3/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
+gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
+gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
+gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
+honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
+honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
+honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
+honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
+rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
+rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
+rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
diff --git a/sdk/go/internal/artifact/source.go b/sdk/go/internal/artifact/source.go
new file mode 100644
index 00000000..563441b7
--- /dev/null
+++ b/sdk/go/internal/artifact/source.go
@@ -0,0 +1,17 @@
+package artifact
+
+type ArtifactSource struct {
+ Excludes []string
+ Hash *string
+ Includes []string
+ Path string
+}
+
+type ArtifactSourceKind string
+
+const (
+ ArtifactSourceKind_GIT ArtifactSourceKind = "GIT"
+ ArtifactSourceKind_HTTP ArtifactSourceKind = "HTTP"
+ ArtifactSourceKind_LOCAL ArtifactSourceKind = "LOCAL"
+ ArtifactSourceKind_UNKNOWN ArtifactSourceKind = "UNKNOWN"
+)
diff --git a/sdk/go/internal/artifact/system.go b/sdk/go/internal/artifact/system.go
new file mode 100644
index 00000000..162bcc77
--- /dev/null
+++ b/sdk/go/internal/artifact/system.go
@@ -0,0 +1,20 @@
+package artifact
+
+import (
+ "github.com/ALT-F4-LLC/vorpal/sdk/go/api/v0/artifact"
+)
+
+func GetArtifactSystem(system string) artifact.ArtifactSystem {
+ switch system {
+ case "aarch64-linux":
+ return artifact.ArtifactSystem_AARCH64_LINUX
+ case "aarch64-macos":
+ return artifact.ArtifactSystem_AARCH64_MACOS
+ case "x86_64-linux":
+ return artifact.ArtifactSystem_X86_64_LINUX
+ case "x86_64-macos":
+ return artifact.ArtifactSystem_X86_64_MACOS
+ default:
+ return artifact.ArtifactSystem_UNKNOWN_SYSTEM
+ }
+}
diff --git a/sdk/go/internal/cli/command.go b/sdk/go/internal/cli/command.go
new file mode 100644
index 00000000..91c64527
--- /dev/null
+++ b/sdk/go/internal/cli/command.go
@@ -0,0 +1,74 @@
+package cli
+
+import (
+ "flag"
+ "fmt"
+ "os"
+ "runtime"
+
+ _artifact "github.com/ALT-F4-LLC/vorpal/sdk/go/api/v0/artifact"
+ "github.com/ALT-F4-LLC/vorpal/sdk/go/internal/artifact"
+)
+
+type startCommand struct {
+ Level string
+ Port int
+ Registry string
+ Target _artifact.ArtifactSystem
+}
+
+func getDefaultSystem() string {
+ arch := runtime.GOARCH
+ os := runtime.GOOS
+
+ if arch == "arm64" {
+ arch = "aarch64"
+ }
+
+ if os == "darwin" {
+ os = "macos"
+ }
+
+ return fmt.Sprintf("%s-%s", arch, os)
+}
+
+func NewStartCommand() (*startCommand, error) {
+ startCmd := flag.NewFlagSet("start", flag.ExitOnError)
+
+ startLevel := startCmd.String("level", "INFO", "logging level")
+ startPort := startCmd.Int("port", 0, "port to listen on")
+ startRegistry := startCmd.String("registry", "http://localhost:23151", "registry to use")
+ startTarget := startCmd.String("target", getDefaultSystem(), "target system")
+
+ switch os.Args[1] {
+ case "start":
+ startCmd.Parse(os.Args[2:])
+
+ if *startPort == 0 {
+ return nil, fmt.Errorf("port is required")
+ }
+
+ if *startRegistry == "" {
+ return nil, fmt.Errorf("registry is required")
+ }
+
+ if *startTarget == "" {
+ return nil, fmt.Errorf("target is required")
+ }
+
+ system := artifact.GetArtifactSystem(*startTarget)
+
+ if system == _artifact.ArtifactSystem_UNKNOWN_SYSTEM {
+ return nil, fmt.Errorf("unknown target system")
+ }
+
+ return &startCommand{
+ Level: *startLevel,
+ Port: *startPort,
+ Registry: *startRegistry,
+ Target: system,
+ }, nil
+ default:
+ return nil, fmt.Errorf("unknown command")
+ }
+}
diff --git a/sdk/go/internal/context/config.go b/sdk/go/internal/context/config.go
new file mode 100644
index 00000000..f4c04eec
--- /dev/null
+++ b/sdk/go/internal/context/config.go
@@ -0,0 +1,524 @@
+package context
+
+import (
+ "context"
+ "crypto/sha256"
+ "encoding/json"
+ "fmt"
+ "io"
+ "log"
+ "net"
+ "net/http"
+ "net/url"
+ "os"
+ "path/filepath"
+ "strings"
+
+ artifactApi "github.com/ALT-F4-LLC/vorpal/sdk/go/api/v0/artifact"
+ configApi "github.com/ALT-F4-LLC/vorpal/sdk/go/api/v0/config"
+ registryApi "github.com/ALT-F4-LLC/vorpal/sdk/go/api/v0/registry"
+ "github.com/ALT-F4-LLC/vorpal/sdk/go/internal/artifact"
+ "github.com/ALT-F4-LLC/vorpal/sdk/go/internal/cli"
+ "github.com/ALT-F4-LLC/vorpal/sdk/go/internal/store"
+ "github.com/h2non/filetype"
+ "github.com/mholt/archives"
+ "google.golang.org/grpc"
+ "google.golang.org/grpc/codes"
+ "google.golang.org/grpc/status"
+)
+
+type ConfigContext struct {
+ ArtifactId map[*artifactApi.ArtifactId]*artifactApi.Artifact
+ artifactSourceId map[string]*artifactApi.ArtifactSourceId
+ port int
+ registry string
+ system artifactApi.ArtifactSystem
+}
+
+type ConfigServer struct {
+ configApi.UnimplementedConfigServiceServer
+ Config *configApi.Config
+ Context *ConfigContext
+}
+
+func GetContext() *ConfigContext {
+ startCmd, err := cli.NewStartCommand()
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ return &ConfigContext{
+ system: startCmd.Target,
+ }
+}
+
+func NewConfigServer(context *ConfigContext, config *configApi.Config) *ConfigServer {
+ return &ConfigServer{
+ Config: config,
+ Context: context,
+ }
+}
+
+func handleFile(outputPath string) archives.FileHandler {
+ return func(ctx context.Context, info archives.FileInfo) error {
+ outputFilePath := filepath.Join(outputPath, filepath.Clean(info.NameInArchive))
+
+ if err := os.MkdirAll(filepath.Dir(outputFilePath), 0o755); err != nil {
+ return err
+ }
+
+ outputFile, err := os.Create(outputFilePath)
+ if err != nil {
+ return err
+ }
+
+ defer outputFile.Close()
+
+ r, err := info.Open()
+ if err != nil {
+ return err
+ }
+
+ defer r.Close()
+
+ if _, err := io.Copy(outputFile, r); err != nil {
+ return err
+ }
+
+ return nil
+ }
+}
+
+func (c *ConfigContext) AddArtifactSource(sourceName string, source artifact.ArtifactSource) (*artifactApi.ArtifactSourceId, error) {
+ // 1. If source is cached using '-', return the source id
+
+ // TODO: if any paths are relative, they should be expanded to the _artifact's source directory
+
+ // 1a. Determine source kind
+
+ sourcePathKind := artifact.ArtifactSourceKind_UNKNOWN
+
+ if _, err := os.Stat(source.Path); err == nil {
+ sourcePathKind = artifact.ArtifactSourceKind_LOCAL
+ }
+
+ if strings.HasPrefix(source.Path, "git://") {
+ sourcePathKind = artifact.ArtifactSourceKind_GIT
+ }
+
+ if strings.HasPrefix(source.Path, "http://") || strings.HasPrefix(source.Path, "https://") {
+ sourcePathKind = artifact.ArtifactSourceKind_HTTP
+ }
+
+ if sourcePathKind == artifact.ArtifactSourceKind_UNKNOWN {
+ return nil, fmt.Errorf("`source.%s.path` unknown kind: %v", sourceName, source.Path)
+ }
+
+ // 1b. process source path
+
+ if sourcePathKind == artifact.ArtifactSourceKind_GIT {
+ return nil, fmt.Errorf("`source.%s.path` git not supported", sourceName)
+ }
+
+ if sourcePathKind == artifact.ArtifactSourceKind_LOCAL {
+ path, err := filepath.Abs(source.Path)
+ if err != nil {
+ return nil, err
+ }
+
+ source.Path = path
+
+ // TODO: add logging library like in rust code
+ }
+
+ // 1c. process source id
+
+ sourceJsonBytes, err := json.Marshal(source)
+ if err != nil {
+ return nil, err
+ }
+
+ sourceKey := fmt.Sprintf("%s-%x", sourceName, sha256.Sum256(sourceJsonBytes))
+
+ if _, ok := c.artifactSourceId[sourceKey]; ok {
+ return c.artifactSourceId[sourceKey], nil
+ }
+
+ // 2. Check if source exists in registry or local cache
+
+ // TODO: check if source is also an empty value
+
+ if source.Hash != nil {
+ // 2a. Check if source exists in the registry
+
+ // TODO: put client at higher level with connection pooling
+
+ registryConnOpts := []grpc.DialOption{}
+
+ registryConn, err := grpc.NewClient(c.registry, registryConnOpts...)
+ if err != nil {
+ return nil, err
+ }
+
+ defer registryConn.Close()
+
+ registryClient := registryApi.NewRegistryServiceClient(registryConn)
+
+ registryRequest := ®istryApi.RegistryRequest{
+ Hash: *source.Hash,
+ Kind: registryApi.RegistryKind_ARTIFACT_SOURCE,
+ Name: sourceName,
+ }
+
+ registryResponse, err := registryClient.Exists(context.Background(), registryRequest)
+ if err != nil && status.Code(err) != codes.NotFound {
+ return nil, err
+ }
+
+ if registryResponse.Success {
+ return &artifactApi.ArtifactSourceId{
+ Hash: *source.Hash,
+ Name: sourceName,
+ }, nil
+ }
+
+ // 2b. Check if source exists in local cache
+
+ sourceCacheArchivePath := store.GetCacheArchivePath(*source.Hash, sourceName)
+
+ if _, err := os.Stat(sourceCacheArchivePath); err == nil {
+ return &artifactApi.ArtifactSourceId{
+ Hash: *source.Hash,
+ Name: sourceName,
+ }, nil
+ }
+ }
+
+ // 3. Prepare source if not cached
+
+ sourceSandboxPath, err := store.NewSandboxDir()
+ if err != nil {
+ return nil, err
+ }
+
+ if sourcePathKind == artifact.ArtifactSourceKind_HTTP {
+ if source.Hash == nil {
+ return nil, fmt.Errorf("`source.%s.hash` required for remote source", sourceName)
+ }
+
+ if source.Hash != nil && *source.Hash == "" {
+ return nil, fmt.Errorf("`source.%s.hash` cannot be empty for remote source", sourceName)
+ }
+
+ // 3a. Download source
+
+ sourceRemotePath, err := url.Parse(source.Path)
+ if err != nil {
+ return nil, err
+ }
+
+ if sourceRemotePath.Scheme != "http" && sourceRemotePath.Scheme != "https" {
+ return nil, fmt.Errorf("`source.%s.path` must be http or https", sourceName)
+ }
+
+ sourceResponse, err := http.Get(sourceRemotePath.String())
+ if err != nil {
+ return nil, err
+ }
+
+ defer sourceResponse.Body.Close()
+
+ if sourceResponse.StatusCode != http.StatusOK {
+ return nil, fmt.Errorf("HTTP request failed: %s", sourceResponse.Status)
+ }
+
+ sourceContentType, err := filetype.MatchReader(sourceResponse.Body)
+ if err != nil {
+ return nil, err
+ }
+
+ if sourceContentType == filetype.Unknown {
+ sourceFileName := filepath.Base(sourceRemotePath.Path)
+
+ sourceFilePath := filepath.Join(*sourceSandboxPath, sourceFileName)
+
+ sourceFile, err := os.Create(sourceFilePath)
+ if err != nil {
+ return nil, err
+ }
+
+ defer sourceFile.Close()
+
+ _, err = io.Copy(sourceFile, sourceResponse.Body)
+ if err != nil {
+ return nil, err
+ }
+ }
+
+ // 3b. Extract source
+
+ ctx := context.Background()
+
+ switch sourceContentType.MIME.Value {
+ case "application/gzip":
+ decoder := archives.Gz{}
+
+ decoderReader, err := decoder.OpenReader(sourceResponse.Body)
+ if err != nil {
+ return nil, err
+ }
+
+ defer decoderReader.Close()
+
+ archive := archives.Tar{}
+
+ err = archive.Extract(ctx, decoderReader, handleFile(*sourceSandboxPath))
+
+ case "application/x-bzip2":
+ decoder := archives.Bz2{}
+
+ decoderReader, err := decoder.OpenReader(sourceResponse.Body)
+ if err != nil {
+ return nil, err
+ }
+
+ defer decoderReader.Close()
+
+ archive := archives.Tar{}
+
+ err = archive.Extract(ctx, decoderReader, handleFile(*sourceSandboxPath))
+
+ case "application/x-xz":
+ decoder := archives.Xz{}
+
+ decoderReader, err := decoder.OpenReader(sourceResponse.Body)
+ if err != nil {
+ return nil, err
+ }
+
+ defer decoderReader.Close()
+
+ archive := archives.Tar{}
+
+ err = archive.Extract(ctx, decoderReader, handleFile(*sourceSandboxPath))
+
+ case "application/zip":
+ archive := archives.Zip{}
+
+ err = archive.Extract(ctx, sourceResponse.Body, handleFile(*sourceSandboxPath))
+
+ default:
+ return nil, fmt.Errorf("unsupported content type: %s", sourceContentType.MIME.Value)
+ }
+
+ if err != nil {
+ return nil, err
+ }
+ }
+
+ if sourcePathKind == artifact.ArtifactSourceKind_LOCAL {
+ sourcePaths, err := store.GetFilePaths(source.Path, source.Excludes, source.Includes)
+ if err != nil {
+ return nil, err
+ }
+
+ _, err = store.CopyFiles(source.Path, sourcePaths, *sourceSandboxPath)
+ if err != nil {
+ return nil, err
+ }
+ }
+
+ // 4. Calculate source hash
+
+ sourceSandboxFiles, err := store.GetFilePaths(*sourceSandboxPath, source.Excludes, source.Includes)
+ if err != nil {
+ return nil, err
+ }
+
+ if len(sourceSandboxFiles) == 0 {
+ return nil, fmt.Errorf("Artifact `source.%s.path` no files found: %s", sourceName, source.Path)
+ }
+
+ // 4a. Set timestamps
+
+ for _, file := range sourceSandboxFiles {
+ err := store.SetTimestamps(file)
+ if err != nil {
+ return nil, err
+ }
+ }
+
+ // 4b. Hash source files
+
+ sourceHash, err := store.HashFiles(sourceSandboxFiles)
+ if err != nil {
+ return nil, err
+ }
+
+ if source.Hash != nil && *source.Hash != sourceHash {
+ return nil, fmt.Errorf("`source.%s.hash` mismatch: %s != %s", sourceName, sourceHash, *source.Hash)
+ }
+
+ // 4c. Cache source
+
+ ctx := context.Background()
+
+ sourceCacheArchiveFiles := make(map[string]string)
+
+ for _, file := range sourceSandboxFiles {
+ relPath, err := filepath.Rel(*sourceSandboxPath, file)
+ if err != nil {
+ return nil, err
+ }
+
+ sourceCacheArchiveFiles[file] = relPath
+ }
+
+ files, err := archives.FilesFromDisk(ctx, nil, sourceCacheArchiveFiles)
+ if err != nil {
+ return nil, err
+ }
+
+ sourceCacheArchivePath := store.GetCacheArchivePath(sourceHash, sourceName)
+
+ out, err := os.Create(sourceCacheArchivePath)
+ if err != nil {
+ return nil, err
+ }
+
+ defer out.Close()
+
+ format := archives.CompressedArchive{
+ Archival: archives.Tar{},
+ Compression: archives.Zstd{},
+ }
+
+ err = format.Archive(ctx, out, files)
+ if err != nil {
+ return nil, err
+ }
+
+ err = os.RemoveAll(*sourceSandboxPath)
+ if err != nil {
+ return nil, err
+ }
+
+ sourceId := &artifactApi.ArtifactSourceId{
+ Hash: sourceHash,
+ Name: sourceName,
+ }
+
+ c.artifactSourceId[sourceKey] = sourceId
+
+ return sourceId, nil
+}
+
+func (c *ConfigContext) AddArtifact(name string, artifacts []*artifactApi.ArtifactId, sources []*artifactApi.ArtifactSourceId, steps []*artifactApi.ArtifactStep, systems []string) (*artifactApi.ArtifactId, error) {
+ // 1. Setup systems
+
+ systemsInt := make([]artifactApi.ArtifactSystem, len(systems))
+
+ for i, system := range systems {
+ systemType := artifact.GetArtifactSystem(system)
+ if systemType == artifactApi.ArtifactSystem_UNKNOWN_SYSTEM {
+ return nil, fmt.Errorf("Unsupported system: %s", system)
+ }
+
+ systemsInt[i] = systemType
+ }
+
+ // 2. Setup artifact id
+
+ artifact := &artifactApi.Artifact{
+ Artifacts: artifacts,
+ Name: name,
+ Sources: sources,
+ Steps: steps,
+ Systems: systemsInt,
+ }
+
+ artifactManifest := &artifactApi.ArtifactBuildRequest{
+ Artifact: artifact,
+ System: c.system,
+ }
+
+ artifactManifestBytes, err := json.Marshal(artifactManifest)
+ if err != nil {
+ return nil, err
+ }
+
+ artifactManifestHash := fmt.Sprintf("%x", sha256.Sum256(artifactManifestBytes))
+
+ artifactId := &artifactApi.ArtifactId{
+ Hash: artifactManifestHash,
+ Name: name,
+ }
+
+ if _, ok := c.ArtifactId[artifactId]; !ok {
+ c.ArtifactId[artifactId] = artifact
+ }
+
+ return artifactId, nil
+}
+
+func (c *ConfigContext) GetArtifact(hash string, name string) (*artifactApi.Artifact, error) {
+ artifactId := &artifactApi.ArtifactId{
+ Hash: hash,
+ Name: name,
+ }
+
+ // NOTE: this may be a bug as it requires a pointer to the artifactId
+ // instead, it may require a loop to find the artifactId
+
+ artifact, ok := c.ArtifactId[artifactId]
+ if !ok {
+ return nil, fmt.Errorf("Artifact not found: %s", name)
+ }
+
+ return artifact, nil
+}
+
+func (c *ConfigContext) GetTarget() artifactApi.ArtifactSystem {
+ return c.system
+}
+
+func (c *ConfigContext) Run(artifacts []*artifactApi.ArtifactId) error {
+ listener, err := net.Listen("tcp", fmt.Sprintf("[::]:%d", c.port))
+ if err != nil {
+ log.Fatalf("failed to listen: %v", err)
+ }
+
+ config := &configApi.Config{
+ Artifacts: artifacts,
+ }
+
+ var opts []grpc.ServerOption
+
+ grpcServer := grpc.NewServer(opts...)
+
+ configApi.RegisterConfigServiceServer(grpcServer, NewConfigServer(c, config))
+
+ err = grpcServer.Serve(listener)
+ if err != nil {
+ return err
+ }
+
+ return nil
+}
+
+func (s *ConfigServer) GetConfig(ctx context.Context, request *configApi.ConfigRequest) (*configApi.Config, error) {
+ return s.Config, nil
+}
+
+func (s *ConfigServer) GetArtifact(ctx context.Context, request *artifactApi.ArtifactId) (*artifactApi.Artifact, error) {
+ artifact, err := s.Context.GetArtifact(request.Hash, request.Name)
+ if err != nil {
+ return nil, err
+ }
+
+ if artifact == nil {
+ return nil, fmt.Errorf("Artifact not found: %s", request.Name)
+ }
+
+ return artifact, nil
+}
diff --git a/sdk/go/internal/store/hash.go b/sdk/go/internal/store/hash.go
new file mode 100644
index 00000000..ed14de39
--- /dev/null
+++ b/sdk/go/internal/store/hash.go
@@ -0,0 +1,124 @@
+package store
+
+import (
+ "crypto/sha256"
+ "encoding/hex"
+ "fmt"
+ "io"
+ "os"
+)
+
+// GetFileHash calculates the SHA-256 hash of a file
+func GetFileHash(path string) (string, error) {
+ // Check if path is a file
+ fileInfo, err := os.Stat(path)
+ if err != nil {
+ return "", err
+ }
+
+ if fileInfo.IsDir() {
+ return "", fmt.Errorf("path is not a file")
+ }
+
+ // Open the file
+ file, err := os.Open(path)
+ if err != nil {
+ return "", err
+ }
+ defer file.Close()
+
+ // Create a new SHA-256 hash
+ hash := sha256.New()
+
+ // Copy file content to hash
+ if _, err := io.Copy(hash, file); err != nil {
+ return "", fmt.Errorf("failed to get file hash: %w", err)
+ }
+
+ // Get the hash sum and convert to hex string
+ hashSum := hash.Sum(nil)
+ hashString := hex.EncodeToString(hashSum)
+
+ return hashString, nil
+}
+
+// GetFileHashes calculates SHA-256 hashes for multiple files
+func GetFileHashes(files []string) ([]string, error) {
+ var hashes []string
+
+ for _, file := range files {
+ // Check if path is a file
+ fileInfo, err := os.Stat(file)
+ if err != nil {
+ continue
+ }
+
+ if fileInfo.IsDir() {
+ continue
+ }
+
+ hash, err := GetFileHash(file)
+ if err != nil {
+ return nil, err
+ }
+
+ hashes = append(hashes, hash)
+ }
+
+ return hashes, nil
+}
+
+// GetHashesDigest combines multiple hashes and creates a digest
+func GetHashesDigest(hashes []string) (string, error) {
+ combined := ""
+
+ for _, hash := range hashes {
+ combined += hash
+ }
+
+ // Create a new SHA-256 hash
+ hash := sha256.New()
+
+ // Write the combined string to the hash
+ hash.Write([]byte(combined))
+
+ // Get the hash sum and convert to hex string
+ hashSum := hash.Sum(nil)
+ hashString := hex.EncodeToString(hashSum)
+
+ return hashString, nil
+}
+
+// HashFiles calculates a combined hash for multiple files
+func HashFiles(paths []string) (string, error) {
+ if len(paths) == 0 {
+ return "", fmt.Errorf("no source files found")
+ }
+
+ pathsHashes, err := GetFileHashes(paths)
+ if err != nil {
+ return "", err
+ }
+
+ pathsHashesJoined, err := GetHashesDigest(pathsHashes)
+ if err != nil {
+ return "", err
+ }
+
+ return pathsHashesJoined, nil
+}
+
+// GetHashDigest calculates the SHA-256 hash of a string
+func GetHashDigest(hash string) string {
+ // Create a new SHA-256 hash
+ hasher := sha256.New()
+
+ // Write the string to the hash
+ hasher.Write([]byte(hash))
+
+ // Get the hash sum and convert to hex string
+ hashSum := hasher.Sum(nil)
+ hashString := hex.EncodeToString(hashSum)
+
+ return hashString
+}
diff --git a/sdk/go/internal/store/path.go b/sdk/go/internal/store/path.go
new file mode 100644
index 00000000..89727475
--- /dev/null
+++ b/sdk/go/internal/store/path.go
@@ -0,0 +1,237 @@
+package store
+
+import (
+ "fmt"
+ "io"
+ "os"
+ "path/filepath"
+ "strings"
+ "syscall"
+ "time"
+
+ "github.com/google/uuid"
+)
+
+func GetStoreDirName(hash string, name string) string {
+ return fmt.Sprintf("%s-%s", name, hash)
+}
+
+func GetRootDirPath() string {
+ return "/var/lib/vorpal"
+}
+
+func GetCacheDirPath() string {
+ return fmt.Sprintf("%s/cache", GetRootDirPath())
+}
+
+func GetSandboxDirPath() string {
+ return fmt.Sprintf("%s/sandbox", GetRootDirPath())
+}
+
+func GetCacheArchivePath(hash string, name string) string {
+ return fmt.Sprintf("%s/%s.tar.zst", GetCacheDirPath(), GetStoreDirName(hash, name))
+}
+
+func GetSandboxPath() (*string, error) {
+ id, err := uuid.NewV7()
+ if err != nil {
+ return nil, err
+ }
+
+ path := fmt.Sprintf("%s/%s", GetSandboxDirPath(), id.String())
+
+ return &path, nil
+}
+
+func shouldExclude(path string, excludes []string) bool {
+ for _, ex := range excludes {
+ // NOTE: Here, you might use filepath.Match for glob-style patterns.
+ if strings.Contains(path, ex) {
+ return true
+ }
+ }
+
+ return false
+}
+
+func shouldInclude(path string, includes []string) bool {
+ // If no includes are provided, consider every file valid.
+ if len(includes) == 0 {
+ return true
+ }
+
+ for _, inc := range includes {
+ // NOTE: Again, you might use a more sophisticated matching mechanism.
+ if strings.Contains(path, inc) {
+ return true
+ }
+ }
+
+ return false
+}
+
+func GetFilePaths(inputPath string, excludes []string, includes []string) ([]string, error) {
+ paths := []string{}
+
+ err := filepath.WalkDir(inputPath, func(path string, d os.DirEntry, err error) error {
+ if err != nil {
+ return err
+ }
+
+ if shouldExclude(path, excludes) {
+ // If it's a directory, skip the entire directory tree.
+ if d.IsDir() {
+ return filepath.SkipDir
+ }
+
+ // Otherwise, just skip this file.
+ return nil
+ }
+
+ if d.IsDir() {
+ return nil
+ }
+
+ if !shouldInclude(path, includes) {
+ return nil
+ }
+
+ paths = append(paths, path)
+
+ return nil
+ })
+ if err != nil {
+ return nil, err
+ }
+
+ return paths, nil
+}
+
+func CopyFiles(sourcePath string, sourcePathFiles []string, targetPath string) ([]string, error) {
+ if len(sourcePathFiles) == 0 {
+ return nil, fmt.Errorf("no source files found")
+ }
+
+ for _, src := range sourcePathFiles {
+ if strings.HasSuffix(src, ".tar.zst") {
+ return nil, fmt.Errorf("source file is a tar.zst archive")
+ }
+
+ if _, err := os.Stat(src); os.IsNotExist(err) {
+ return nil, fmt.Errorf("source file not found: %s", src)
+ }
+
+ fileInfo, err := os.Lstat(src)
+ if err != nil {
+ return nil, fmt.Errorf("failed to read metadata: %w", err)
+ }
+
+ // Calculate destination path by removing source prefix
+ relPath, err := filepath.Rel(sourcePath, src)
+ if err != nil {
+ return nil, fmt.Errorf("failed to get relative path: %w", err)
+ }
+
+ dest := filepath.Join(targetPath, relPath)
+
+ if fileInfo.IsDir() {
+ if err := os.MkdirAll(dest, 0o755); err != nil {
+ return nil, fmt.Errorf("create directory fail: %w", err)
+ }
+ } else if fileInfo.Mode()&os.ModeSymlink != 0 {
+ // Handle symlink
+ linkTarget, err := os.Readlink(src)
+ if err != nil {
+ return nil, fmt.Errorf("failed to read symlink: %w", err)
+ }
+
+ // Ensure parent directory exists
+ parent := filepath.Dir(dest)
+ if err := os.MkdirAll(parent, 0o755); err != nil {
+ return nil, fmt.Errorf("create parent directory fail: %w", err)
+ }
+
+ // Remove existing symlink if it exists
+ if _, err := os.Lstat(dest); err == nil {
+ os.Remove(dest)
+ }
+
+ if err := os.Symlink(linkTarget, dest); err != nil {
+ return nil, fmt.Errorf("symlink file fail: %w", err)
+ }
+ } else if fileInfo.Mode().IsRegular() {
+ // Handle regular file
+ parent := filepath.Dir(dest)
+ if err := os.MkdirAll(parent, 0o755); err != nil {
+ return nil, fmt.Errorf("create parent directory fail: %w", err)
+ }
+
+ srcFile, err := os.Open(src)
+ if err != nil {
+ return nil, fmt.Errorf("open source file fail: %w", err)
+ }
+
+ defer srcFile.Close()
+
+ destFile, err := os.Create(dest)
+ if err != nil {
+ return nil, fmt.Errorf("create destination file fail: %w", err)
+ }
+
+ defer destFile.Close()
+
+ if _, err := io.Copy(destFile, srcFile); err != nil {
+ return nil, fmt.Errorf("copy file fail: %w", err)
+ }
+
+ // Set the same permissions
+ if err := os.Chmod(dest, fileInfo.Mode()); err != nil {
+ return nil, fmt.Errorf("set file permissions fail: %w", err)
+ }
+ } else {
+ return nil, fmt.Errorf("source file is not a file or directory: %s", src)
+ }
+ }
+
+ // Get all files in the target directory
+ targetPathFiles, err := GetFilePaths(targetPath, []string{}, []string{})
+ if err != nil {
+ return nil, err
+ }
+
+ return targetPathFiles, nil
+}
+
+// SetSymlinkTimestamps sets the access and modification times of a symlink
+func SetSymlinkTimestamps(path string) error {
+ // Create epoch time (January 1, 1970 UTC)
+ epoch := time.Unix(0, 0)
+
+ // Convert to syscall timespec
+ ts := []syscall.Timespec{
+ {Sec: epoch.Unix(), Nsec: 0}, // Access time
+ {Sec: epoch.Unix(), Nsec: 0}, // Modification time
+ }
+
+ // Use Utimesnano syscall to set symlink timestamps without following the link
+ return syscall.UtimesNano(path, ts)
+}
+
+// SetTimestamps sets the access and modification times of a file or symlink to epoch (0)
+func SetTimestamps(path string) error {
+ // Check if the path is a symlink
+ fileInfo, err := os.Lstat(path)
+ if err != nil {
+ return err
+ }
+
+ // Set timestamps based on whether it's a symlink or regular file
+ if fileInfo.Mode()&os.ModeSymlink != 0 {
+ return SetSymlinkTimestamps(path)
+ } else {
+ // Create epoch time (January 1, 1970 UTC)
+ epoch := time.Unix(0, 0)
+ // Set access and modification times for regular files
+ return os.Chtimes(path, epoch, epoch)
+ }
+}
diff --git a/sdk/go/internal/store/sandbox.go b/sdk/go/internal/store/sandbox.go
new file mode 100644
index 00000000..1a9ee0a5
--- /dev/null
+++ b/sdk/go/internal/store/sandbox.go
@@ -0,0 +1,35 @@
+package store
+
+import (
+ "fmt"
+ "os"
+)
+
+func NewSandboxDir() (*string, error) {
+ path, err := GetSandboxPath()
+ if err != nil {
+ return nil, err
+ }
+
+ if err := os.MkdirAll(*path, 0o755); err != nil {
+ return nil, err
+ }
+
+ return path, nil
+}
+
+func NewSandboxFile(extension string) (*os.File, error) {
+ path, err := GetSandboxPath()
+ if err != nil {
+ return nil, err
+ }
+
+ filename := fmt.Sprintf("%s%s", *path, extension)
+
+ file, err := os.Create(filename)
+ if err != nil {
+ return nil, err
+ }
+
+ return file, nil
+}
diff --git a/sdk/go/main.go b/sdk/go/main.go
new file mode 100644
index 00000000..050bdc59
--- /dev/null
+++ b/sdk/go/main.go
@@ -0,0 +1,13 @@
+package main
+
+import (
+ "log"
+
+ "github.com/ALT-F4-LLC/vorpal/sdk/go/internal/context"
+)
+
+func main() {
+ ctx := context.GetContext()
+
+ log.Printf("Context: %v", ctx)
+}
diff --git a/sdk/Cargo.toml b/sdk/rust/Cargo.toml
similarity index 89%
rename from sdk/Cargo.toml
rename to sdk/rust/Cargo.toml
index c63b8826..436caffb 100644
--- a/sdk/Cargo.toml
+++ b/sdk/rust/Cargo.toml
@@ -20,5 +20,5 @@ toml = { default-features = false, features = ["parse"], version = "0" }
tonic = { default-features = false, version = "0" }
tracing = { default-features = false, version = "0" }
url = { default-features = false, version = "2" }
-vorpal-schema = { default-features = false, path = "../schema" }
-vorpal-store = { default-features = false, path = "../store" }
+vorpal-schema = { default-features = false, path = "../../schema" }
+vorpal-store = { default-features = false, path = "../../store" }
diff --git a/sdk/src/config/artifact/toolchain/cargo.rs b/sdk/rust/src/artifact/cargo.rs
similarity index 70%
rename from sdk/src/config/artifact/toolchain/cargo.rs
rename to sdk/rust/src/artifact/cargo.rs
index d117d150..11dbe091 100644
--- a/sdk/src/config/artifact/toolchain/cargo.rs
+++ b/sdk/rust/src/artifact/cargo.rs
@@ -1,15 +1,19 @@
-use crate::config::{
- artifact::{add_artifact, language::rust::get_toolchain_target, ConfigContext},
- ArtifactSource,
+use crate::{
+ artifact::{add_artifact, language::rust::get_rust_toolchain_target, ArtifactSource},
+ context::ConfigContext,
};
use anyhow::{bail, Result};
use std::collections::BTreeMap;
use vorpal_schema::vorpal::artifact::v0::{
- ArtifactId,
+ ArtifactId, ArtifactSourceId,
ArtifactSystem::{Aarch64Linux, Aarch64Macos, UnknownSystem, X8664Linux, X8664Macos},
};
-pub async fn artifact(context: &mut ConfigContext, version: &str) -> Result {
+pub async fn source(
+ context: &mut ConfigContext,
+ target: &str,
+ version: &str,
+) -> Result {
let hash = match context.get_target() {
Aarch64Linux => "42781c7ae909a5cd01c955cb4343754ce33d75783b2599a3f1a3b3752a0947af",
Aarch64Macos => "e88e4babfc20e0546fe28bc2ba3f71a467f83e9fb1be76c9a078d327379ee4d0",
@@ -18,9 +22,25 @@ pub async fn artifact(context: &mut ConfigContext, version: &str) -> Result bail!("Invalid protoc system: {:?}", context.get_target()),
};
+ context
+ .add_artifact_source(
+ "cargo",
+ ArtifactSource {
+ excludes: vec![],
+ hash: Some(hash.to_string()),
+ includes: vec![],
+ path: format!("https://static.rust-lang.org/dist/cargo-{version}-{target}.tar.gz"),
+ },
+ )
+ .await
+}
+
+pub async fn artifact(context: &mut ConfigContext, version: &str) -> Result {
let name = "cargo";
- let target = get_toolchain_target(context.get_target())?;
+ let target = get_rust_toolchain_target(context.get_target())?;
+
+ let source = source(context, &target, version).await?;
add_artifact(
context,
@@ -30,15 +50,7 @@ pub async fn artifact(context: &mut ConfigContext, version: &str) -> Result Result {
+pub async fn source(
+ context: &mut ConfigContext,
+ target: &str,
+ version: &str,
+) -> Result {
let hash = match context.get_target() {
Aarch64Linux => "5e0b5cb7e8655501369a6f42cb10b1c5d4711a0edfcbe44483c5234da485819d",
Aarch64Macos => "fe82bf19b064f6fca648b9be6a53ae210a9934023df364d669fc7c4ee5ccd485",
@@ -18,9 +22,25 @@ pub async fn artifact(context: &mut ConfigContext, version: &str) -> Result bail!("Invalid protoc system: {:?}", context.get_target()),
};
+ context
+ .add_artifact_source(
+ "clippy",
+ ArtifactSource {
+ excludes: vec![],
+ hash: Some(hash.to_string()),
+ includes: vec![],
+ path: format!("https://static.rust-lang.org/dist/clippy-{version}-{target}.tar.gz"),
+ },
+ )
+ .await
+}
+
+pub async fn artifact(context: &mut ConfigContext, version: &str) -> Result {
let name = "clippy";
- let target = get_toolchain_target(context.get_target())?;
+ let target = get_rust_toolchain_target(context.get_target())?;
+
+ let source = source(context, &target, version).await?;
add_artifact(
context,
@@ -28,15 +48,7 @@ pub async fn artifact(context: &mut ConfigContext, version: &str) -> Result Result {
+ let target = context.get_target();
+
+ let hash = match target {
+ Aarch64Linux => "42cec86acdeb62f23b8a65afaa67c2d8c8818f28d7d3ca55430e10e8027a6234",
+ Aarch64Macos => "86c352c4ced8830cd92a9c85c2944eaa95ebb1e8908b3f01258962bcc94b9c14",
+ X8664Linux => "9037b22b154e44366e6a03963bd5584f76381070baa9cf6a548bd2bfcd28b72e",
+ X8664Macos => "123456789",
+ UnknownSystem => bail!("Invalid go system: {:?}", context.get_target()),
+ };
+
+ let target = match target {
+ Aarch64Linux => "linux-arm64",
+ Aarch64Macos => "darwin-arm64",
+ X8664Linux => "linux-386",
+ X8664Macos => "darwin-amd64",
+ UnknownSystem => bail!("Invalid go system: {:?}", target),
+ };
+
+ let version = "1.23.5";
+
+ context
+ .add_artifact_source(
+ "go",
+ ArtifactSource {
+ excludes: vec![],
+ hash: Some(hash.to_string()),
+ includes: vec![],
+ path: format!("https://go.dev/dl/go{}.{}.tar.gz", version, target),
+ },
+ )
+ .await
+}
+
+pub async fn artifact(context: &mut ConfigContext) -> Result {
+ let name = "go";
+
+ let source = source(context).await?;
+
+ add_artifact(
+ context,
+ vec![],
+ BTreeMap::new(),
+ name,
+ format!("cp -prv \"./source/{name}/go/.\" \"$VORPAL_OUTPUT\""),
+ vec![source],
+ vec![
+ "aarch64-linux",
+ "aarch64-macos",
+ "x86_64-linux",
+ "x86_64-macos",
+ ],
+ )
+ .await
+}
diff --git a/sdk/rust/src/artifact/goimports.rs b/sdk/rust/src/artifact/goimports.rs
new file mode 100644
index 00000000..81e9bcb6
--- /dev/null
+++ b/sdk/rust/src/artifact/goimports.rs
@@ -0,0 +1,45 @@
+use crate::{
+ artifact::{add_artifact, get_artifact_envkey, go},
+ context::ConfigContext,
+ source::go_tools,
+};
+use anyhow::Result;
+use indoc::formatdoc;
+use std::collections::BTreeMap;
+use vorpal_schema::vorpal::artifact::v0::ArtifactId;
+
+pub async fn artifact(context: &mut ConfigContext) -> Result {
+ let go = go::artifact(context).await?;
+
+ let name = "goimports";
+
+ let source = go_tools(context).await?;
+
+ add_artifact(
+ context,
+ vec![go.clone()],
+ BTreeMap::from([
+ ("GOCACHE", "$VORPAL_WORKSPACE/go/cache".to_string()),
+ ("GOPATH", "$VORPAL_WORKSPACE/go".to_string()),
+ ("PATH", format!("{}/bin", get_artifact_envkey(&go))),
+ ]),
+ name,
+ formatdoc! {"
+ pushd ./source/go-tools
+
+ mkdir -p $VORPAL_OUTPUT/bin
+
+ go build -o $VORPAL_OUTPUT/bin/goimports ./cmd/goimports
+
+ go clean -modcache
+ "},
+ vec![source],
+ vec![
+ "aarch64-linux",
+ "aarch64-macos",
+ "x86_64-linux",
+ "x86_64-macos",
+ ],
+ )
+ .await
+}
diff --git a/sdk/rust/src/artifact/gopls.rs b/sdk/rust/src/artifact/gopls.rs
new file mode 100644
index 00000000..13953e80
--- /dev/null
+++ b/sdk/rust/src/artifact/gopls.rs
@@ -0,0 +1,45 @@
+use crate::{
+ artifact::{add_artifact, get_artifact_envkey, go},
+ context::ConfigContext,
+ source::go_tools,
+};
+use anyhow::Result;
+use indoc::formatdoc;
+use std::collections::BTreeMap;
+use vorpal_schema::vorpal::artifact::v0::ArtifactId;
+
+pub async fn artifact(context: &mut ConfigContext) -> Result {
+ let go = go::artifact(context).await?;
+
+ let name = "gopls";
+
+ let source = go_tools(context).await?;
+
+ add_artifact(
+ context,
+ vec![go.clone()],
+ BTreeMap::from([
+ ("GOCACHE", "$VORPAL_WORKSPACE/go/cache".to_string()),
+ ("GOPATH", "$VORPAL_WORKSPACE/go".to_string()),
+ ("PATH", format!("{}/bin", get_artifact_envkey(&go))),
+ ]),
+ name,
+ formatdoc! {"
+ pushd ./source/go-tools/gopls
+
+ mkdir -p $VORPAL_OUTPUT/bin
+
+ go build -o $VORPAL_OUTPUT/bin/gopls .
+
+ go clean -modcache
+ "},
+ vec![source],
+ vec![
+ "aarch64-linux",
+ "aarch64-macos",
+ "x86_64-linux",
+ "x86_64-macos",
+ ],
+ )
+ .await
+}
diff --git a/sdk/src/config/artifact/language/mod.rs b/sdk/rust/src/artifact/language/mod.rs
similarity index 100%
rename from sdk/src/config/artifact/language/mod.rs
rename to sdk/rust/src/artifact/language/mod.rs
diff --git a/sdk/src/config/artifact/language/rust.rs b/sdk/rust/src/artifact/language/rust.rs
similarity index 87%
rename from sdk/src/config/artifact/language/rust.rs
rename to sdk/rust/src/artifact/language/rust.rs
index 0e99b706..adc2c57e 100644
--- a/sdk/src/config/artifact/language/rust.rs
+++ b/sdk/rust/src/artifact/language/rust.rs
@@ -1,11 +1,9 @@
-use crate::config::{
+use crate::{
artifact::{
- add_artifact, get_artifact_envkey,
- shell::shell_artifact,
- toolchain::{cargo, clippy, protoc, rust_analyzer, rust_src, rust_std, rustc, rustfmt},
- ArtifactSource,
+ add_artifact, cargo, clippy, get_artifact_envkey, protoc, rust_analyzer, rust_src,
+ rust_std, rustc, rustfmt, shell::shell_artifact, ArtifactSource,
},
- ConfigContext,
+ context::ConfigContext,
};
use anyhow::{bail, Result};
use indoc::formatdoc;
@@ -36,7 +34,7 @@ struct RustArtifactCargoTomlWorkspace {
members: Option>,
}
-pub fn get_toolchain_target(target: ArtifactSystem) -> Result {
+pub fn get_rust_toolchain_target(target: ArtifactSystem) -> Result {
let target = match target {
Aarch64Linux => "aarch64-unknown-linux-gnu",
Aarch64Macos => "aarch64-apple-darwin",
@@ -61,7 +59,7 @@ fn read_cargo_toml(path: &str) -> Result {
#[allow(clippy::too_many_arguments)]
pub async fn toolchain_artifact(context: &mut ConfigContext, name: &str) -> Result {
let version = get_rust_toolchain_version();
- let target = get_toolchain_target(context.get_target())?;
+ let target = get_rust_toolchain_target(context.get_target())?;
let cargo = cargo::artifact(context, &version).await?;
let clippy = clippy::artifact(context, &version).await?;
@@ -126,7 +124,7 @@ pub async fn toolchain_artifact(context: &mut ConfigContext, name: &str) -> Resu
EOF",
component_paths = component_paths.join(" "),
},
- BTreeMap::new(),
+ vec![],
vec![
"aarch64-linux",
"aarch64-macos",
@@ -144,7 +142,7 @@ pub async fn rust_shell(context: &mut ConfigContext, name: &str) -> Result Result(context: &mut ConfigContext, name: &'a str) -> Result {
+pub async fn rust_package<'a>(
+ context: &mut ConfigContext,
+ name: &'a str,
+ excludes: Vec<&'a str>,
+) -> Result {
let toolchain = toolchain_artifact(context, name).await?;
// 1. READ CARGO.TOML FILES
@@ -245,7 +247,7 @@ pub async fn rust_package<'a>(context: &mut ConfigContext, name: &'a str) -> Res
// Get protoc artifact
let protoc = protoc::artifact(context).await?;
- let toolchain_target = get_toolchain_target(context.get_target())?;
+ let toolchain_target = get_rust_toolchain_target(context.get_target())?;
let toolchain_version = get_rust_toolchain_version();
// Set environment variables
@@ -267,6 +269,18 @@ pub async fn rust_package<'a>(context: &mut ConfigContext, name: &'a str) -> Res
vendor_cargo_tomls.push(format!("{}/Cargo.toml", workspace));
}
+ let vendor_source = context
+ .add_artifact_source(
+ format!("{}-vendor", name).as_str(),
+ ArtifactSource {
+ excludes: vec![],
+ hash: None,
+ includes: vendor_cargo_tomls.clone(),
+ path: source_path.display().to_string(),
+ },
+ )
+ .await?;
+
let vendor = add_artifact(
context,
vec![toolchain.clone()],
@@ -280,7 +294,7 @@ pub async fn rust_package<'a>(context: &mut ConfigContext, name: &'a str) -> Res
formatdoc! {"
mkdir -pv $HOME
- pushd ./source/{name}
+ pushd ./source/{name}-vendor
target_paths=({target_paths})
@@ -296,15 +310,7 @@ pub async fn rust_package<'a>(context: &mut ConfigContext, name: &'a str) -> Res
echo \"$cargo_vendor\" > \"$VORPAL_OUTPUT/config.toml\"",
target_paths = workspaces_targets.join(" "),
},
- BTreeMap::from([(
- name,
- ArtifactSource {
- excludes: vec![],
- hash: None,
- includes: vendor_cargo_tomls.clone(),
- path: source_path.display().to_string(),
- },
- )]),
+ vec![vendor_source],
systems.clone(),
)
.await?;
@@ -317,6 +323,24 @@ pub async fn rust_package<'a>(context: &mut ConfigContext, name: &'a str) -> Res
env_paths.push(format!("{}/bin", get_artifact_envkey(&protoc)));
+ let mut excludes_defaults = vec!["target".to_string()];
+
+ for exclude in excludes {
+ excludes_defaults.push(exclude.to_string());
+ }
+
+ let artifact_source = context
+ .add_artifact_source(
+ name,
+ ArtifactSource {
+ excludes: excludes_defaults,
+ hash: None,
+ includes: vec![],
+ path: source_path.display().to_string(),
+ },
+ )
+ .await?;
+
add_artifact(
context,
artifacts,
@@ -353,31 +377,7 @@ pub async fn rust_package<'a>(context: &mut ConfigContext, name: &'a str) -> Res
bin_names = workspaces_bin_names.join(" "),
vendor = get_artifact_envkey(&vendor),
},
- BTreeMap::from([(
- name,
- ArtifactSource {
- excludes: vec![
- ".env".to_string(),
- ".envrc".to_string(),
- ".github".to_string(),
- ".gitignore".to_string(),
- ".packer".to_string(),
- ".vagrant".to_string(),
- "Dockerfile".to_string(),
- "Vagrantfile".to_string(),
- "dist".to_string(),
- "makefile".to_string(),
- "script".to_string(),
- "shell.nix".to_string(),
- "target".to_string(),
- "vorpal-domains.svg".to_string(),
- "vorpal-purpose.jpg".to_string(),
- ],
- hash: None,
- includes: vec![],
- path: source_path.display().to_string(),
- },
- )]),
+ vec![artifact_source],
systems,
)
.await
diff --git a/sdk/src/config/artifact/toolchain/linux/debian.rs b/sdk/rust/src/artifact/linux_debian.rs
similarity index 98%
rename from sdk/src/config/artifact/toolchain/linux/debian.rs
rename to sdk/rust/src/artifact/linux_debian.rs
index 6a3413c0..e32fb7c4 100644
--- a/sdk/src/config/artifact/toolchain/linux/debian.rs
+++ b/sdk/rust/src/artifact/linux_debian.rs
@@ -1,9 +1,9 @@
-use crate::config::{
+use crate::{
artifact::{
get_artifact_envkey,
- steps::{bash, docker},
+ step::{bash, docker},
},
- ConfigContext,
+ context::ConfigContext,
};
use anyhow::Result;
use indoc::formatdoc;
@@ -167,7 +167,7 @@ pub async fn artifact(context: &mut ConfigContext) -> Result {
.add_artifact(
"linux-debian-docker",
vec![],
- BTreeMap::new(),
+ vec![],
vec![bash(
BTreeMap::new(),
formatdoc! {"
@@ -190,7 +190,7 @@ pub async fn artifact(context: &mut ConfigContext) -> Result {
.add_artifact(
"linux-debian",
vec![dockerfile.clone()],
- BTreeMap::new(),
+ vec![],
vec![
docker(vec![
"buildx".to_string(),
diff --git a/sdk/src/config/artifact/toolchain/linux/vorpal/mod.rs b/sdk/rust/src/artifact/linux_vorpal.rs
similarity index 85%
rename from sdk/src/config/artifact/toolchain/linux/vorpal/mod.rs
rename to sdk/rust/src/artifact/linux_vorpal.rs
index 2b9f0002..e03c9444 100644
--- a/sdk/src/config/artifact/toolchain/linux/vorpal/mod.rs
+++ b/sdk/rust/src/artifact/linux_vorpal.rs
@@ -1,10 +1,201 @@
-use crate::config::artifact::{steps, ConfigContext};
+use crate::{
+ artifact::{step::bwrap, ArtifactSource},
+ context::ConfigContext,
+};
use anyhow::Result;
use indoc::formatdoc;
use std::collections::BTreeMap;
use vorpal_schema::vorpal::artifact::v0::ArtifactId;
-mod source;
+pub fn curl(version: &str, hash: &str) -> ArtifactSource {
+ ArtifactSource {
+ excludes: vec![],
+ hash: Some(hash.to_string()),
+ includes: vec![],
+ path: format!("https://curl.se/download/curl-{version}.tar.xz"),
+ }
+}
+
+pub fn curl_cacert(hash: &str) -> ArtifactSource {
+ ArtifactSource {
+ excludes: vec![],
+ hash: Some(hash.to_string()),
+ includes: vec![],
+ path: "https://curl.se/ca/cacert.pem".to_string(),
+ }
+}
+
+pub fn file(version: &str, hash: &str) -> ArtifactSource {
+ ArtifactSource {
+ excludes: vec![],
+ hash: Some(hash.to_string()),
+ includes: vec![],
+ path: format!("https://astron.com/pub/file/file-{version}.tar.gz"),
+ }
+}
+
+pub fn gnu(name: &str, version: &str, hash: &str) -> ArtifactSource {
+ ArtifactSource {
+ excludes: vec![],
+ hash: Some(hash.to_string()),
+ includes: vec![],
+ path: format!("https://ftpmirror.gnu.org/gnu/{name}/{name}-{version}.tar.gz"),
+ }
+}
+
+pub fn gnu_xz(name: &str, version: &str, hash: &str) -> ArtifactSource {
+ ArtifactSource {
+ excludes: vec![],
+ hash: Some(hash.to_string()),
+ includes: vec![],
+ path: format!("https://ftpmirror.gnu.org/gnu/{name}/{name}-{version}.tar.xz"),
+ }
+}
+
+pub fn gnu_gcc(version: &str, hash: &str) -> ArtifactSource {
+ ArtifactSource {
+ excludes: vec![],
+ hash: Some(hash.to_string()),
+ includes: vec![],
+ path: format!("https://ftpmirror.gnu.org/gnu/gcc/gcc-{version}/gcc-{version}.tar.xz"),
+ }
+}
+
+pub fn gnu_glibc_patch(version: &str, hash: &str) -> ArtifactSource {
+ ArtifactSource {
+ excludes: vec![],
+ hash: Some(hash.to_string()),
+ includes: vec![],
+ path: format!(
+ "https://www.linuxfromscratch.org/patches/lfs/12.2/glibc-{version}-fhs-1.patch",
+ ),
+ }
+}
+
+pub fn libidn2(version: &str, hash: &str) -> ArtifactSource {
+ ArtifactSource {
+ excludes: vec![],
+ hash: Some(hash.to_string()),
+ includes: vec![],
+ path: format!("https://ftpmirror.gnu.org/gnu/libidn/libidn2-{version}.tar.gz"),
+ }
+}
+
+pub fn libpsl(version: &str, hash: &str) -> ArtifactSource {
+ ArtifactSource {
+ excludes: vec![],
+ hash: Some(hash.to_string()),
+ includes: vec![],
+ path: format!(
+ "https://github.com/rockdaboot/libpsl/releases/download/{version}/libpsl-{version}.tar.gz",
+ ),
+ }
+}
+
+pub fn linux(version: &str, hash: &str) -> ArtifactSource {
+ ArtifactSource {
+ excludes: vec![],
+ hash: Some(hash.to_string()),
+ includes: vec![],
+ path: format!("https://cdn.kernel.org/pub/linux/kernel/v6.x/linux-{version}.tar.xz"),
+ }
+}
+
+pub fn ncurses(version: &str, hash: &str) -> ArtifactSource {
+ ArtifactSource {
+ excludes: vec![],
+ hash: Some(hash.to_string()),
+ includes: vec![],
+ path: format!("https://invisible-mirror.net/archives/ncurses/ncurses-{version}.tar.gz"),
+ }
+}
+
+pub fn openssl(version: &str, hash: &str) -> ArtifactSource {
+ ArtifactSource {
+ excludes: vec![],
+ hash: Some(hash.to_string()),
+ includes: vec![],
+ path: format!("https://www.openssl.org/source/openssl-{version}.tar.gz"),
+ }
+}
+
+pub fn perl(version: &str, hash: &str) -> ArtifactSource {
+ ArtifactSource {
+ excludes: vec![],
+ hash: Some(hash.to_string()),
+ includes: vec![],
+ path: format!("https://www.cpan.org/src/5.0/perl-{version}.tar.xz"),
+ }
+}
+
+pub fn python(version: &str, hash: &str) -> ArtifactSource {
+ ArtifactSource {
+ excludes: vec![],
+ hash: Some(hash.to_string()),
+ includes: vec![],
+ path: format!("https://www.python.org/ftp/python/{version}/Python-{version}.tar.xz"),
+ }
+}
+
+pub fn unzip_patch_fixes(version: &str, hash: &str) -> ArtifactSource {
+ ArtifactSource {
+ excludes: vec![],
+ hash: Some(hash.to_string()),
+ includes: vec![],
+ path: format!("https://www.linuxfromscratch.org/patches/blfs/12.2/unzip-{version}-consolidated_fixes-1.patch"),
+ }
+}
+
+pub fn unzip_patch_gcc14(version: &str, hash: &str) -> ArtifactSource {
+ ArtifactSource {
+ excludes: vec![],
+ hash: Some(hash.to_string()),
+ includes: vec![],
+ path: format!(
+ "https://www.linuxfromscratch.org/patches/blfs/12.2/unzip-{version}-gcc14-1.patch"
+ ),
+ }
+}
+
+pub fn unzip(version: &str, hash: &str) -> ArtifactSource {
+ let version = version.replace(".", "");
+
+ ArtifactSource {
+ excludes: vec![],
+ hash: Some(hash.to_string()),
+ includes: vec![],
+ path: format!("https://cfhcable.dl.sourceforge.net/project/infozip/UnZip%206.x%20%28latest%29/UnZip%206.0/unzip{version}.tar.gz?viasf=1",),
+ }
+}
+
+pub fn util_linux(version: &str, hash: &str) -> ArtifactSource {
+ ArtifactSource {
+ excludes: vec![],
+ hash: Some(hash.to_string()),
+ includes: vec![],
+ path: format!(
+ "https://www.kernel.org/pub/linux/utils/util-linux/v2.40/util-linux-{version}.tar.xz"
+ ),
+ }
+}
+
+pub fn xz(version: &str, hash: &str) -> ArtifactSource {
+ ArtifactSource {
+ excludes: vec![],
+ hash: Some(hash.to_string()),
+ includes: vec![],
+ path: format!("https://github.com/tukaani-project/xz/releases/download/v{version}/xz-{version}.tar.xz"),
+ }
+}
+
+pub fn zlib(version: &str, hash: &str) -> ArtifactSource {
+ ArtifactSource {
+ excludes: vec![],
+ hash: Some(hash.to_string()),
+ includes: vec![],
+ path: format!("https://zlib.net/fossils/zlib-{version}.tar.gz"),
+ }
+}
pub async fn artifact(
context: &mut ConfigContext,
@@ -17,229 +208,229 @@ pub async fn artifact(
// Setup sources
let bash_version = "5.2.32";
- let bash = source::gnu(
+ let bash = gnu(
"bash",
bash_version,
"19a8087c947a587b491508a6675a5349e23992d5dfca40a0bd0735bbd81e0438",
);
let binutils_version = "2.43.1";
- let binutils = source::gnu(
+ let binutils = gnu(
"binutils",
binutils_version,
"c0d3e5ee772ee201eefe17544b2b2cc3a0a3d6833a21b9ea56371efaad0c5528",
);
let bison_version = "3.8.2";
- let bison = source::gnu(
+ let bison = gnu(
"bison",
bison_version,
"cb18c2c8562fc01bf3ae17ffe9cf8274e3dd49d39f89397c1a8bac7ee14ce85f",
);
let coreutils_version = "9.5";
- let coreutils = source::gnu(
+ let coreutils = gnu(
"coreutils",
coreutils_version,
"af6d643afd6241ec35c7781b7f999b97a66c84bea4710ad2bb15e75a5caf11b4",
);
let curl_version = "8.11.0";
- let curl = source::curl(
+ let curl = curl(
curl_version,
"97dde4e45e89291bf5405b0363b16049333366f286a1989537441c261e9299fe",
);
let curl_cacert =
- source::curl_cacert("19c0bec2c9dc55ad5e63b008d55ef6021565cfa4ff25bb8b93cf96381b050386");
+ curl_cacert("19c0bec2c9dc55ad5e63b008d55ef6021565cfa4ff25bb8b93cf96381b050386");
let diffutils_version = "3.10";
- let diffutils = source::gnu_xz(
+ let diffutils = gnu_xz(
"diffutils",
diffutils_version,
"5045e29e7fa0ffe017f63da7741c800cbc0f89e04aebd78efcd661d6e5673326",
);
let file_version = "5.45";
- let file = source::file(
+ let file = file(
file_version,
"c118ab56efa05798022a5a488827594a82d844f65159e95b918d5501adf1e58f",
);
let findutils_version = "4.10.0";
- let findutils = source::gnu_xz(
+ let findutils = gnu_xz(
"findutils",
findutils_version,
"242f804d87a5036bb0fab99966227dc61e853e5a67e1b10c3cc45681c792657e",
);
let gawk_version = "5.3.0";
- let gawk = source::gnu(
+ let gawk = gnu(
"gawk",
gawk_version,
"a21e5899707ddc030a0fcc0a35c95a9602dca1a681fa52a1790a974509b40133",
);
let gcc_version = "14.2.0";
- let gcc = source::gnu_gcc(
+ let gcc = gnu_gcc(
gcc_version,
"cc20ef929f4a1c07594d606ca4f2ed091e69fac5c6779887927da82b0a62f583",
);
let gettext_version = "0.22.5";
- let gettext = source::gnu(
+ let gettext = gnu(
"gettext",
gettext_version,
"6e3ef842d1006a6af7778a8549a8e8048fc3b923e5cf48eaa5b82b5d142220ae",
);
let glibc_version = "2.40";
- let glibc = source::gnu(
+ let glibc = gnu(
"glibc",
glibc_version,
"da2594c64d61dacf80d85e568136bf31fba36c4ff1ececff59c6fb786a2a126b",
);
- let glibc_patch = source::gnu_glibc_patch(
+ let glibc_patch = gnu_glibc_patch(
glibc_version,
"69cf0653ad0a6a178366d291f30629d4e1cb633178aa4b8efbea0c851fb944ca",
);
let grep_version = "3.11";
- let grep = source::gnu(
+ let grep = gnu(
"grep",
grep_version,
"1625eae01f6e4dbc41b58545aa2326c74791b2010434f8241d41903a4ea5ff70",
);
let gzip_version = "1.13";
- let gzip = source::gnu(
+ let gzip = gnu(
"gzip",
gzip_version,
"25e51d46402bab819045d452ded6c4558ef980f5249c470d9499e9eae34b59b1",
);
let libidn2_version = "2.3.7";
- let libidn2 = source::libidn2(
+ let libidn2 = libidn2(
libidn2_version,
"cb09b889bc9e51a2f5ec9d04dbbf03582926a129340828271955d15a57da6a3c",
);
let libpsl_version = "0.21.5";
- let libpsl = source::libpsl(
+ let libpsl = libpsl(
libpsl_version,
"65ecfe61646c50119a018a2003149833c11387efd92462f974f1ff9f907c1d78",
);
let libunistring_version = "1.2";
- let libunistring = source::gnu(
+ let libunistring = gnu(
"libunistring",
libunistring_version,
"c621c94a94108095cfe08cc61f484d4b4cb97824c64a4e2bb1830d8984b542f3",
);
let linux_version = "6.10.5";
- let linux = source::linux(
+ let linux = linux(
linux_version,
"b1548c4f5bf63c5f44c1a8c3044842a49ef445deb1b3da55b8116200a25793be",
);
let m4_version = "1.4.19";
- let m4 = source::gnu(
+ let m4 = gnu(
"m4",
m4_version,
"fd793cdfc421fac76f4af23c7d960cbe4a29cbb18f5badf37b85e16a894b3b6d",
);
let make_version = "4.4.1";
- let make = source::gnu(
+ let make = gnu(
"make",
make_version,
"8dfe7b0e51b3e190cd75e046880855ac1be76cf36961e5cfcc82bfa91b2c3ba8",
);
let ncurses_version = "6.5";
- let ncurses = source::ncurses(
+ let ncurses = ncurses(
ncurses_version,
"aab234a3b7a22e2632151fbe550cb36e371d3ee5318a633ee43af057f9f112fb",
);
let openssl_version = "3.3.1";
- let openssl = source::openssl(
+ let openssl = openssl(
openssl_version,
"a53e2254e36124452582477935a680f07f9884fe1d6e9ec03c28ac71b750d84a",
);
let patch_version = "2.7.6";
- let patch = source::gnu(
+ let patch = gnu(
"patch",
"2.7.6",
"af8c281a05a6802075799c0c179e5fb3a218be6a21b726d8b672cd0f4c37eae9",
);
let perl_version = "5.40.0";
- let perl = source::perl(
+ let perl = perl(
perl_version,
"59b6437a3da1d9de0126135b31f1f16aee9c3b7a0f61f6364b2da3e8bb5f771f",
);
let python_version = "3.12.5";
- let python = source::python(
+ let python = python(
python_version,
"8359773924d33702ecd6f9fab01973e53d929d46d7cdc4b0df31eb1282c68b67",
);
let sed_version = "4.9";
- let sed = source::gnu(
+ let sed = gnu(
"sed",
sed_version,
"434ff552af89340088e0d8cb206c251761297909bbee401176bc8f655e8e7cf2",
);
let tar_version = "1.35";
- let tar = source::gnu(
+ let tar = gnu(
"tar",
tar_version,
"f9bb5f39ed45b1c6a324470515d2ef73e74422c5f345503106d861576d3f02f3",
);
let texinfo_version = "7.1.1";
- let texinfo = source::gnu(
+ let texinfo = gnu(
"texinfo",
texinfo_version,
"6e34604552af91db0b4ccf0bcceba63dd3073da2a492ebcf33c6e188a64d2b63",
);
let unzip_version = "6.0";
- let unzip = source::unzip(
+ let unzip = unzip(
unzip_version,
"4585067be297ae977da3f81587fcf0a141a8d6ceb6137d199255683ed189c3ed",
);
- let unzip_patch_fixes = source::unzip_patch_fixes(
+ let unzip_patch_fixes = unzip_patch_fixes(
"6.0",
"11350935be5bbb743f1a97ec069b78fc2904f92b24abbc7fb3d7f0ff8bb889ea",
);
- let unzip_patch_gcc14 = source::unzip_patch_gcc14(
+ let unzip_patch_gcc14 = unzip_patch_gcc14(
"6.0",
"d6ac941672086ea4c8d5047d550b40047825a685cc7c48626d2f0939e1a0c797",
);
let util_linux_version = "2.40.2";
- let util_linux = source::util_linux(
+ let util_linux = util_linux(
util_linux_version,
"7db19a1819ac5c743b52887a4571e42325b2bfded63d93b6a1797ae2b1f8019a",
);
let xz_version = "5.6.2";
- let xz = source::xz(
+ let xz = xz(
xz_version,
"7a02b1278ed9a59b332657d613c5549b39afe34e315197f4da95c5322524ec26",
);
let zlib_version = "1.3.1";
- let zlib = source::zlib(
+ let zlib = zlib(
zlib_version,
"3f7995d5f103719283f509c23624287ce95c349439e881ed935a3c2c807bb683",
);
@@ -283,12 +474,18 @@ pub async fn artifact(
("zlib", zlib),
]);
+ let mut source_ids = vec![];
+
+ for (source_name, source) in sources {
+ source_ids.push(context.add_artifact_source(source_name, source).await?);
+ }
+
context.add_artifact(
"linux-vorpal",
artifacts.clone(),
- sources,
+ source_ids,
vec![
- steps::bwrap(
+ bwrap(
vec![],
artifacts,
BTreeMap::from([("PATH", "/usr/bin:/usr/sbin".to_string())]),
@@ -933,7 +1130,7 @@ pub async fn artifact(
rm -rfv $VORPAL_OUTPUT/var",
}
),
- steps::bwrap(
+ bwrap(
vec![
// mount bin
"--bind".to_string(),
diff --git a/sdk/src/config/artifact/mod.rs b/sdk/rust/src/artifact/mod.rs
similarity index 75%
rename from sdk/src/config/artifact/mod.rs
rename to sdk/rust/src/artifact/mod.rs
index da56d157..52b55f82 100644
--- a/sdk/src/config/artifact/mod.rs
+++ b/sdk/rust/src/artifact/mod.rs
@@ -1,21 +1,46 @@
-use crate::config::{
- artifact::{
- steps::{bash, bwrap},
- toolchain::linux::{debian, vorpal},
- },
- ArtifactSource, ConfigContext,
-};
+use crate::context::ConfigContext;
use anyhow::{bail, Result};
+use serde::{Deserialize, Serialize};
use std::collections::BTreeMap;
use vorpal_schema::vorpal::artifact::v0::{
- ArtifactId, ArtifactStepEnvironment, ArtifactSystem,
+ ArtifactId, ArtifactSourceId, ArtifactStepEnvironment, ArtifactSystem,
ArtifactSystem::{Aarch64Linux, Aarch64Macos, X8664Linux, X8664Macos},
};
+pub mod cargo;
+pub mod clippy;
+pub mod go;
+pub mod goimports;
+pub mod gopls;
pub mod language;
+pub mod linux_debian;
+pub mod linux_vorpal;
+pub mod protoc;
+pub mod protoc_gen_go;
+pub mod protoc_gen_go_grpc;
+pub mod rust_analyzer;
+pub mod rust_src;
+pub mod rust_std;
+pub mod rustc;
+pub mod rustfmt;
pub mod shell;
-pub mod steps;
-pub mod toolchain;
+pub mod step;
+
+#[derive(Clone, Debug, Deserialize, Serialize)]
+pub struct ArtifactSource {
+ pub excludes: Vec,
+ pub hash: Option,
+ pub includes: Vec,
+ pub path: String,
+}
+
+#[derive(Debug, PartialEq)]
+pub enum ArtifactSourceKind {
+ UnknownSourceKind,
+ Git,
+ Http,
+ Local,
+}
pub fn get_artifact_envkey(artifact: &ArtifactId) -> String {
format!(
@@ -49,7 +74,7 @@ pub async fn add_artifact(
environment: BTreeMap<&str, String>,
name: &str,
script: String,
- source: BTreeMap<&str, ArtifactSource>,
+ sources: Vec,
systems: Vec<&str>,
) -> Result {
// Setup target
@@ -61,8 +86,8 @@ pub async fn add_artifact(
let mut artifacts = artifacts.clone();
if target == Aarch64Linux || target == X8664Linux {
- let linux_debian = debian::artifact(context).await?;
- let linux_vorpal = vorpal::artifact(context, &linux_debian).await?;
+ let linux_debian = linux_debian::artifact(context).await?;
+ let linux_vorpal = linux_vorpal::artifact(context, &linux_debian).await?;
artifacts.push(linux_vorpal.clone());
}
@@ -125,7 +150,7 @@ pub async fn add_artifact(
.find(|a| a.name == "linux-vorpal")
.expect("linux-vorpal artifact not found");
- steps.push(bwrap(
+ steps.push(step::bwrap(
vec![],
artifacts.clone(),
env.clone(),
@@ -135,12 +160,12 @@ pub async fn add_artifact(
}
if target == Aarch64Macos || target == X8664Macos {
- steps.push(bash(env.clone(), script.to_string()));
+ steps.push(step::bash(env.clone(), script.to_string()));
}
// Add artifact to context
context
- .add_artifact(name, artifacts, source, steps, systems)
+ .add_artifact(name, artifacts, sources, steps, systems)
.await
}
diff --git a/sdk/src/config/artifact/toolchain/protoc.rs b/sdk/rust/src/artifact/protoc.rs
similarity index 78%
rename from sdk/src/config/artifact/toolchain/protoc.rs
rename to sdk/rust/src/artifact/protoc.rs
index fea3e678..3793ae26 100644
--- a/sdk/src/config/artifact/toolchain/protoc.rs
+++ b/sdk/rust/src/artifact/protoc.rs
@@ -1,13 +1,16 @@
-use crate::config::{artifact::add_artifact, ArtifactSource, ConfigContext};
+use crate::{
+ artifact::{add_artifact, ArtifactSource},
+ context::ConfigContext,
+};
use anyhow::{bail, Result};
use indoc::formatdoc;
use std::collections::BTreeMap;
use vorpal_schema::vorpal::artifact::v0::{
- ArtifactId,
+ ArtifactId, ArtifactSourceId,
ArtifactSystem::{Aarch64Linux, Aarch64Macos, UnknownSystem, X8664Linux, X8664Macos},
};
-pub async fn artifact(context: &mut ConfigContext) -> Result {
+pub async fn source(context: &mut ConfigContext) -> Result {
let hash = match context.get_target() {
Aarch64Linux => "8a592a0dd590e92b1c0d77631e683fc743d1ed8158e0b093b6cfabf0685089af",
Aarch64Macos => "d105abb1c1d2c024f29df884f0592f1307984d63aeb10f0e61ccb94aee2c2feb",
@@ -16,8 +19,6 @@ pub async fn artifact(context: &mut ConfigContext) -> Result {
UnknownSystem => bail!("Invalid protoc system: {:?}", context.get_target()),
};
- let name = "protoc";
-
let target = match context.get_target() {
Aarch64Linux => "linux-aarch_64",
Aarch64Macos => "osx-aarch_64",
@@ -28,6 +29,24 @@ pub async fn artifact(context: &mut ConfigContext) -> Result {
let version = "25.4";
+ context
+ .add_artifact_source(
+ "protoc",
+ ArtifactSource {
+ excludes: vec![],
+ hash: Some(hash.to_string()),
+ includes: vec![],
+ path: format!("https://github.com/protocolbuffers/protobuf/releases/download/v{version}/protoc-{version}-{target}.zip"),
+ },
+ )
+ .await
+}
+
+pub async fn artifact(context: &mut ConfigContext) -> Result {
+ let name = "protoc";
+
+ let source = source(context).await?;
+
add_artifact(
context,
vec![],
@@ -40,20 +59,13 @@ pub async fn artifact(context: &mut ConfigContext) -> Result {
chmod +x \"$VORPAL_OUTPUT/bin/protoc\"",
},
- BTreeMap::from([(
- name,
- ArtifactSource {
- excludes: vec![],
- hash: Some(hash.to_string()),
- includes: vec![],
- path: format!("https://github.com/protocolbuffers/protobuf/releases/download/v{version}/{name}-{version}-{target}.zip"),
- }
- )]),
+ vec![source],
vec![
"aarch64-linux",
"aarch64-macos",
"x86_64-linux",
"x86_64-macos",
- ]
- ).await
+ ],
+ )
+ .await
}
diff --git a/sdk/rust/src/artifact/protoc_gen_go.rs b/sdk/rust/src/artifact/protoc_gen_go.rs
new file mode 100644
index 00000000..e95d2070
--- /dev/null
+++ b/sdk/rust/src/artifact/protoc_gen_go.rs
@@ -0,0 +1,71 @@
+use crate::{
+ artifact::{add_artifact, ArtifactSource},
+ context::ConfigContext,
+};
+use anyhow::{bail, Result};
+use indoc::formatdoc;
+use std::collections::BTreeMap;
+use vorpal_schema::vorpal::artifact::v0::{
+ ArtifactId, ArtifactSourceId,
+ ArtifactSystem::{Aarch64Linux, Aarch64Macos, UnknownSystem, X8664Linux, X8664Macos},
+};
+
+pub async fn source(context: &mut ConfigContext) -> Result {
+ let hash = match context.get_target() {
+ Aarch64Linux => "597aae8080d7e3e575198a5417ac2278ae49078d7fa3be56405ffb43bbb9f501",
+ Aarch64Macos => "55c2a0cc7137f3625bd1bf3be85ed940c643e56fa1ceaf51f94c6434980f65a5",
+ X8664Linux => "07f2ee9051854e2d240c56e47cfa9ac9b7d6a2dc2a9b2b6dbd79726f78c27bb1",
+ X8664Macos => "1234567890",
+ UnknownSystem => bail!("Invalid protoc-gen-go system: {:?}", context.get_target()),
+ };
+
+ let target = match context.get_target() {
+ Aarch64Linux => "linux.arm64",
+ Aarch64Macos => "darwin.arm64",
+ X8664Linux => "linux.amd64",
+ X8664Macos => "darwin.amd64",
+ UnknownSystem => bail!("Invalid protoc-gen-go system: {:?}", context.get_target()),
+ };
+
+ let version = "1.36.3";
+
+ context
+ .add_artifact_source(
+ "protoc-gen-go",
+ ArtifactSource {
+ excludes: vec![],
+ hash: Some(hash.to_string()),
+ includes: vec![],
+ path: format!("https://github.com/protocolbuffers/protobuf-go/releases/download/v{version}/protoc-gen-go.v{version}.{target}.tar.gz"),
+ },
+ )
+ .await
+}
+
+pub async fn artifact(context: &mut ConfigContext) -> Result {
+ let name = "protoc-gen-go";
+
+ let source = source(context).await?;
+
+ add_artifact(
+ context,
+ vec![],
+ BTreeMap::new(),
+ name,
+ formatdoc! {"
+ mkdir -pv \"$VORPAL_OUTPUT/bin\"
+
+ cp -prv \"source/protoc-gen-go/protoc-gen-go\" \"$VORPAL_OUTPUT/bin/protoc-gen-go\"
+
+ chmod +x \"$VORPAL_OUTPUT/bin/protoc-gen-go\"",
+ },
+ vec![source],
+ vec![
+ "aarch64-linux",
+ "aarch64-macos",
+ "x86_64-linux",
+ "x86_64-macos",
+ ],
+ )
+ .await
+}
diff --git a/sdk/rust/src/artifact/protoc_gen_go_grpc.rs b/sdk/rust/src/artifact/protoc_gen_go_grpc.rs
new file mode 100644
index 00000000..b33adfaf
--- /dev/null
+++ b/sdk/rust/src/artifact/protoc_gen_go_grpc.rs
@@ -0,0 +1,67 @@
+use crate::{
+ artifact::{add_artifact, get_artifact_envkey, go, ArtifactSource},
+ context::ConfigContext,
+};
+use anyhow::Result;
+use indoc::formatdoc;
+use std::collections::BTreeMap;
+use vorpal_schema::vorpal::artifact::v0::{ArtifactId, ArtifactSourceId};
+
+pub async fn source(context: &mut ConfigContext, version: &str) -> Result {
+ let hash = "eba0f83ab252cffe2c6209f894c4c8238b2473a403bbdbcb985af25140aac95d";
+
+ context
+ .add_artifact_source(
+ "protoc-gen-go-grpc",
+ ArtifactSource {
+ excludes: vec![],
+ hash: Some(hash.to_string()),
+ includes: vec![],
+ path: format!(
+ "https://github.com/grpc/grpc-go/archive/refs/tags/v{}.tar.gz",
+ version
+ ),
+ },
+ )
+ .await
+}
+
+pub async fn artifact(context: &mut ConfigContext) -> Result {
+ let go = go::artifact(context).await?;
+
+ let name = "protoc-gen-go-grpc";
+
+ let version = "1.70.0";
+
+ let source = source(context, version).await?;
+
+ add_artifact(
+ context,
+ vec![go.clone()],
+ BTreeMap::from([
+ ("GOCACHE", "$VORPAL_WORKSPACE/go/cache".to_string()),
+ ("GOPATH", "$VORPAL_WORKSPACE/go".to_string()),
+ ("PATH", format!("{}/bin", get_artifact_envkey(&go))),
+ ]),
+ name,
+ formatdoc! {"
+ pushd ./source/protoc-gen-go-grpc/grpc-go-{version}
+
+ mkdir -p $VORPAL_OUTPUT/bin
+
+ pushd ./cmd/protoc-gen-go-grpc
+
+ go build -o $VORPAL_OUTPUT/bin/protoc-gen-go-grpc .
+
+ go clean -modcache
+ "},
+ vec![source],
+ vec![
+ "aarch64-linux",
+ "aarch64-macos",
+ "x86_64-linux",
+ "x86_64-macos",
+ ],
+ )
+ .await
+}
diff --git a/sdk/src/config/artifact/toolchain/rust_analyzer.rs b/sdk/rust/src/artifact/rust_analyzer.rs
similarity index 64%
rename from sdk/src/config/artifact/toolchain/rust_analyzer.rs
rename to sdk/rust/src/artifact/rust_analyzer.rs
index c6b0afef..a5bf790e 100644
--- a/sdk/src/config/artifact/toolchain/rust_analyzer.rs
+++ b/sdk/rust/src/artifact/rust_analyzer.rs
@@ -1,15 +1,19 @@
-use crate::config::{
- artifact::{add_artifact, language::rust::get_toolchain_target, ConfigContext},
- ArtifactSource,
+use crate::{
+ artifact::{add_artifact, language::rust::get_rust_toolchain_target, ArtifactSource},
+ context::ConfigContext,
};
use anyhow::{bail, Result};
use std::collections::BTreeMap;
use vorpal_schema::vorpal::artifact::v0::{
- ArtifactId,
+ ArtifactId, ArtifactSourceId,
ArtifactSystem::{Aarch64Linux, Aarch64Macos, UnknownSystem, X8664Linux, X8664Macos},
};
-pub async fn artifact(context: &mut ConfigContext, version: &str) -> Result {
+pub async fn source(
+ context: &mut ConfigContext,
+ target: &str,
+ version: &str,
+) -> Result {
let hash = match context.get_target() {
Aarch64Linux => "79fbf7077b846a4b28935fa6a22259d589baed2197c08bfc5c362f1e3f54db44",
Aarch64Macos => "ba92aa08cdada8fad8d772623b0522cb3d6e659a8edb9e037453fab998772a19",
@@ -18,9 +22,27 @@ pub async fn artifact(context: &mut ConfigContext, version: &str) -> Result bail!("Invalid protoc system: {:?}", context.get_target()),
};
+ context
+ .add_artifact_source(
+ "rust-analyzer",
+ ArtifactSource {
+ excludes: vec![],
+ hash: Some(hash.to_string()),
+ includes: vec![],
+ path: format!(
+ "https://static.rust-lang.org/dist/rust-analyzer-{version}-{target}.tar.gz"
+ ),
+ },
+ )
+ .await
+}
+
+pub async fn artifact(context: &mut ConfigContext, version: &str) -> Result {
let name = "rust-analyzer";
- let target = get_toolchain_target(context.get_target())?;
+ let target = get_rust_toolchain_target(context.get_target())?;
+
+ let source = source(context, &target, version).await?;
add_artifact(
context,
@@ -28,15 +50,7 @@ pub async fn artifact(context: &mut ConfigContext, version: &str) -> Result Result {
+pub async fn source(context: &mut ConfigContext, version: &str) -> Result {
let hash = "5f0adbae49a5442bf3389f7798cbacba92a94b7fefe7810ce00d1356a861d305";
+ context
+ .add_artifact_source(
+ "rust-src",
+ ArtifactSource {
+ excludes: vec![],
+ hash: Some(hash.to_string()),
+ includes: vec![],
+ path: format!("https://static.rust-lang.org/dist/rust-src-{version}.tar.gz"),
+ },
+ )
+ .await
+}
+
+pub async fn artifact(context: &mut ConfigContext, version: &str) -> Result {
let name = "rust-src";
+ let source = source(context, version).await?;
+
add_artifact(
context,
vec![],
BTreeMap::new(),
name,
format!("cp -prv \"./source/{name}/{name}-{version}/{name}/.\" \"$VORPAL_OUTPUT\""),
- BTreeMap::from([(
- name,
- ArtifactSource {
- excludes: vec![],
- hash: Some(hash.to_string()),
- includes: vec![],
- path: format!("https://static.rust-lang.org/dist/{name}-{version}.tar.gz"),
- },
- )]),
+ vec![source],
vec![
"aarch64-linux",
"aarch64-macos",
diff --git a/sdk/src/config/artifact/toolchain/rust_std.rs b/sdk/rust/src/artifact/rust_std.rs
similarity index 65%
rename from sdk/src/config/artifact/toolchain/rust_std.rs
rename to sdk/rust/src/artifact/rust_std.rs
index 36ded36a..c85c9ac3 100644
--- a/sdk/src/config/artifact/toolchain/rust_std.rs
+++ b/sdk/rust/src/artifact/rust_std.rs
@@ -1,15 +1,19 @@
-use crate::config::{
- artifact::{add_artifact, language::rust::get_toolchain_target, ConfigContext},
- ArtifactSource,
+use crate::{
+ artifact::{add_artifact, language::rust::get_rust_toolchain_target, ArtifactSource},
+ context::ConfigContext,
};
use anyhow::{bail, Result};
use std::collections::BTreeMap;
use vorpal_schema::vorpal::artifact::v0::{
- ArtifactId,
+ ArtifactId, ArtifactSourceId,
ArtifactSystem::{Aarch64Linux, Aarch64Macos, UnknownSystem, X8664Linux, X8664Macos},
};
-pub async fn artifact(context: &mut ConfigContext, version: &str) -> Result {
+pub async fn source(
+ context: &mut ConfigContext,
+ target: &str,
+ version: &str,
+) -> Result {
let hash = match context.get_target() {
Aarch64Linux => "d560efe018be876f2d5a9106f4b37222f0d315f52aeb12ffb0bfbfc8071fc5b1",
Aarch64Macos => "6d636e93ec5f9a2e8a7c5bae381dc9a89808087b2eec1f987f8ed5a797fef556",
@@ -18,9 +22,27 @@ pub async fn artifact(context: &mut ConfigContext, version: &str) -> Result bail!("Invalid protoc system: {:?}", context.get_target()),
};
+ context
+ .add_artifact_source(
+ "rust-std",
+ ArtifactSource {
+ excludes: vec![],
+ hash: Some(hash.to_string()),
+ includes: vec![],
+ path: format!(
+ "https://static.rust-lang.org/dist/rust-std-{version}-{target}.tar.gz"
+ ),
+ },
+ )
+ .await
+}
+
+pub async fn artifact(context: &mut ConfigContext, version: &str) -> Result {
let name = "rust-std";
- let target = get_toolchain_target(context.get_target())?;
+ let target = get_rust_toolchain_target(context.get_target())?;
+
+ let source = source(context, &target, version).await?;
add_artifact(
context,
@@ -28,15 +50,7 @@ pub async fn artifact(context: &mut ConfigContext, version: &str) -> Result Result {
+pub async fn source(
+ context: &mut ConfigContext,
+ target: &str,
+ version: &str,
+) -> Result {
let hash = match context.get_target() {
Aarch64Linux => "f5e5eac428b2a62ffc14324e3a6e171fb3032921f24973b27959834e456388b1",
Aarch64Macos => "d022dd6d61a7039c12834f90a0a5410c884bfb9ef1e38b085ad4d3f59a5bf04a",
@@ -18,9 +22,25 @@ pub async fn artifact(context: &mut ConfigContext, version: &str) -> Result bail!("Invalid protoc system: {:?}", context.get_target()),
};
+ context
+ .add_artifact_source(
+ "rustc",
+ ArtifactSource {
+ excludes: vec![],
+ hash: Some(hash.to_string()),
+ includes: vec![],
+ path: format!("https://static.rust-lang.org/dist/rustc-{version}-{target}.tar.gz"),
+ },
+ )
+ .await
+}
+
+pub async fn artifact(context: &mut ConfigContext, version: &str) -> Result {
let name = "rustc";
- let target = get_toolchain_target(context.get_target())?;
+ let target = get_rust_toolchain_target(context.get_target())?;
+
+ let source = source(context, &target, version).await?;
add_artifact(
context,
@@ -30,15 +50,7 @@ pub async fn artifact(context: &mut ConfigContext, version: &str) -> Result Result {
+pub async fn source(
+ context: &mut ConfigContext,
+ target: &str,
+ version: &str,
+) -> Result {
let hash = match context.get_target() {
Aarch64Linux => "8a51bcfb496489a5fd6f2042617e84a35301d69325ce558e23589371729c75b2",
Aarch64Macos => "4feacdd0fe93196c893a48458f4c3b78bf50a515b2a37a8dd03ce8ba0ef3e065",
@@ -18,9 +22,27 @@ pub async fn artifact(context: &mut ConfigContext, version: &str) -> Result bail!("Invalid protoc system: {:?}", context.get_target()),
};
+ context
+ .add_artifact_source(
+ "rustfmt",
+ ArtifactSource {
+ excludes: vec![],
+ hash: Some(hash.to_string()),
+ includes: vec![],
+ path: format!(
+ "https://static.rust-lang.org/dist/rustfmt-{version}-{target}.tar.gz"
+ ),
+ },
+ )
+ .await
+}
+
+pub async fn artifact(context: &mut ConfigContext, version: &str) -> Result {
let name = "rustfmt";
- let target = get_toolchain_target(context.get_target())?;
+ let target = get_rust_toolchain_target(context.get_target())?;
+
+ let source = source(context, &target, version).await?;
add_artifact(
context,
@@ -28,15 +50,7 @@ pub async fn artifact(context: &mut ConfigContext, version: &str) -> Result(
restores = restores.join("\n"),
unsets = unsets.join("\n"),
},
- BTreeMap::new(),
+ vec![],
vec![
"aarch64-linux",
"aarch64-macos",
diff --git a/sdk/src/config/artifact/steps.rs b/sdk/rust/src/artifact/step.rs
similarity index 98%
rename from sdk/src/config/artifact/steps.rs
rename to sdk/rust/src/artifact/step.rs
index eb10fd06..a2844af7 100644
--- a/sdk/src/config/artifact/steps.rs
+++ b/sdk/rust/src/artifact/step.rs
@@ -1,4 +1,4 @@
-use crate::config::artifact::get_artifact_envkey;
+use crate::artifact::get_artifact_envkey;
use indoc::formatdoc;
use std::collections::BTreeMap;
use vorpal_schema::vorpal::artifact::v0::{ArtifactId, ArtifactStep, ArtifactStepEnvironment};
diff --git a/sdk/rust/src/cli.rs b/sdk/rust/src/cli.rs
new file mode 100644
index 00000000..1aa1a7e8
--- /dev/null
+++ b/sdk/rust/src/cli.rs
@@ -0,0 +1,32 @@
+use clap::{Parser, Subcommand};
+use std::env::consts::{ARCH, OS};
+use tracing::Level;
+
+#[derive(Parser)]
+#[command(author, version, about, long_about = None)]
+#[command(propagate_version = true)]
+pub struct Cli {
+ #[command(subcommand)]
+ pub command: Command,
+}
+
+fn get_default_system() -> String {
+ format!("{}-{}", ARCH, OS)
+}
+
+#[derive(Subcommand)]
+pub enum Command {
+ Start {
+ #[clap(default_value_t = Level::INFO, global = true, long)]
+ level: Level,
+
+ #[clap(long, short)]
+ port: u16,
+
+ #[clap(default_value = "http://localhost:23151", long, short)]
+ registry: String,
+
+ #[arg(default_value_t = get_default_system(), long, short)]
+ target: String,
+ },
+}
diff --git a/sdk/src/config/mod.rs b/sdk/rust/src/context.rs
similarity index 78%
rename from sdk/src/config/mod.rs
rename to sdk/rust/src/context.rs
index f1bd38bf..04cd25a9 100644
--- a/sdk/src/config/mod.rs
+++ b/sdk/rust/src/context.rs
@@ -1,17 +1,17 @@
-use crate::config::service::ConfigServer;
+use crate::{
+ artifact::{ArtifactSource, ArtifactSourceKind},
+ cli::{Cli, Command},
+};
use anyhow::{bail, Result};
use async_compression::tokio::bufread::{BzDecoder, GzipDecoder, XzDecoder};
-use clap::{Parser, Subcommand};
-use console::style;
+use clap::Parser;
use serde::{Deserialize, Serialize};
use sha256::digest;
-use std::collections::{BTreeMap, HashMap};
-use std::env::consts::{ARCH, OS};
-use std::path::Path;
+use std::{collections::HashMap, path::Path};
use tokio::fs::{remove_dir_all, remove_file, write};
use tokio_tar::Archive;
use tonic::{transport::Server, Code::NotFound};
-use tracing::{info, Level};
+use tracing::info;
use url::Url;
use vorpal_schema::{
get_artifact_system,
@@ -20,7 +20,10 @@ use vorpal_schema::{
Artifact, ArtifactBuildRequest, ArtifactId, ArtifactSourceId, ArtifactStep,
ArtifactSystem,
},
- config::v0::{config_service_server::ConfigServiceServer, Config},
+ config::v0::{
+ config_service_server::{ConfigService, ConfigServiceServer},
+ Config, ConfigRequest,
+ },
registry::v0::{
registry_service_client::RegistryServiceClient, RegistryKind, RegistryRequest,
},
@@ -33,42 +36,6 @@ use vorpal_store::{
temps::{create_sandbox_dir, create_sandbox_file},
};
-pub mod artifact;
-pub mod service;
-
-#[derive(Parser)]
-#[command(author, version, about, long_about = None)]
-#[command(propagate_version = true)]
-pub struct Cli {
- #[command(subcommand)]
- command: Command,
-}
-
-fn get_default_system() -> String {
- format!("{}-{}", ARCH, OS)
-}
-
-fn get_prefix(name: &str) -> String {
- style(format!("{} |>", name)).bold().to_string()
-}
-
-#[derive(Subcommand)]
-enum Command {
- Start {
- #[clap(default_value_t = Level::INFO, global = true, long)]
- level: Level,
-
- #[clap(long, short)]
- port: u16,
-
- #[clap(default_value = "http://localhost:23151", long, short)]
- registry: String,
-
- #[arg(default_value_t = get_default_system(), long, short)]
- target: String,
- },
-}
-
#[derive(Clone, Debug, Default)]
pub struct ConfigContext {
pub artifact_id: HashMap, // TOOD: make this private
@@ -78,25 +45,48 @@ pub struct ConfigContext {
system: ArtifactSystem,
}
+#[derive(Debug, Default)]
+pub struct ConfigServer {
+ pub config: Config,
+ pub context: ConfigContext,
+}
+
#[derive(Debug, Serialize, Deserialize)]
pub struct ArtifactMetadata {
pub system: ArtifactSystem,
}
-#[derive(Clone, Debug, Deserialize, Serialize)]
-pub struct ArtifactSource {
- pub excludes: Vec,
- pub hash: Option,
- pub includes: Vec,
- pub path: String,
+impl ConfigServer {
+ pub fn new(context: ConfigContext, config: Config) -> Self {
+ Self { context, config }
+ }
}
-#[derive(Debug, PartialEq)]
-pub enum ArtifactSourceKind {
- UnknownSourceKind,
- Git,
- Http,
- Local,
+#[tonic::async_trait]
+impl ConfigService for ConfigServer {
+ async fn get_config(
+ &self,
+ _request: tonic::Request,
+ ) -> Result, tonic::Status> {
+ Ok(tonic::Response::new(self.config.clone()))
+ }
+
+ async fn get_artifact(
+ &self,
+ request: tonic::Request,
+ ) -> Result, tonic::Status> {
+ let request = request.into_inner();
+
+ let artifact = self
+ .context
+ .get_artifact(request.hash.as_str(), request.name.as_str());
+
+ if artifact.is_none() {
+ return Err(tonic::Status::not_found("Artifact input not found"));
+ }
+
+ Ok(tonic::Response::new(artifact.unwrap().clone()))
+ }
}
pub async fn get_context() -> Result {
@@ -131,16 +121,71 @@ impl ConfigContext {
}
}
- async fn add_artifact_source(
+ pub async fn add_artifact_source(
&mut self,
- artifact_name: &str,
source_name: &str,
source: ArtifactSource,
) -> Result {
- // 1. If source is cached using '--', return the source id
+ // 1. If source is cached using '-', return the source id
+
+ // TODO: if any paths are relative, they should be expanded to the artifact's source directory
+
+ // 1a. determine the kind of source path
+
+ let source_path_kind = match &source.path {
+ s if Path::new(s).exists() => ArtifactSourceKind::Local,
+ s if s.starts_with("git") => ArtifactSourceKind::Git,
+ s if s.starts_with("http") => ArtifactSourceKind::Http,
+ _ => ArtifactSourceKind::UnknownSourceKind,
+ };
+
+ if source_path_kind == ArtifactSourceKind::UnknownSourceKind {
+ bail!(
+ "`source.{}.path` unknown kind: {:?}",
+ source_name,
+ source.path
+ );
+ }
+
+ // 1b. process source path
+
+ let mut source = ArtifactSource {
+ excludes: source.excludes.clone(),
+ hash: source.hash.clone(),
+ includes: source.includes.clone(),
+ path: source.path.clone(),
+ };
+
+ if source_path_kind == ArtifactSourceKind::Git {
+ bail!("`source.{}.path` git not supported", source_name);
+ }
+
+ if source_path_kind == ArtifactSourceKind::Local {
+ let local_path = Path::new(&source.path).to_path_buf();
+
+ if !local_path.exists() {
+ bail!("`source.{}.path` not found: {:?}", source_name, source.path);
+ }
+
+ source.path = local_path
+ .canonicalize()
+ .map_err(|e| anyhow::anyhow!(e))?
+ .to_str()
+ .unwrap()
+ .to_string();
+
+ info!(
+ "{} canonicalized source: {}",
+ source_name,
+ local_path.display()
+ );
+ }
+
+ // 1c. process source id
let source_json = serde_json::to_string(&source).map_err(|e| anyhow::anyhow!(e))?;
- let source_key = format!("{}-{}-{}", artifact_name, source_name, digest(source_json));
+
+ let source_key = format!("{}-{}", source_name, digest(source_json));
if let Some(source_id) = self.artifact_source_id.get(&source_key) {
return Ok(source_id.clone());
@@ -148,14 +193,18 @@ impl ConfigContext {
// 2. Check if source exists in registry or local cache
+ // TODO: check if source is also an empty value
+
if let Some(hash) = source.hash.clone() {
- let artifact_source_id = ArtifactSourceId {
+ let source_id = ArtifactSourceId {
hash: hash.clone(),
name: source_name.to_string(),
};
// 2a. Check if source exists in the registry
+ // TODO: put client at higher level with connection pooling
+
let registry_host = self.registry.clone();
let mut registry = RegistryServiceClient::connect(registry_host.to_owned())
@@ -176,60 +225,31 @@ impl ConfigContext {
}
Ok(_) => {
- info!(
- "{} pushed source: {}-{}",
- get_prefix(artifact_name),
- source_name,
- hash
- );
+ info!("{} pushed source: {}", source_name, hash);
self.artifact_source_id
- .insert(source_key, artifact_source_id.clone());
+ .insert(source_key, source_id.clone());
- return Ok(artifact_source_id);
+ return Ok(source_id);
}
}
// 2b. Check if source exists in local cache
- let cache_archive_path = get_cache_archive_path(&hash, source_name);
+ let source_cache_archive_path = get_cache_archive_path(&hash, source_name);
- if cache_archive_path.exists() {
- info!(
- "{} cached source: {}-{}",
- get_prefix(artifact_name),
- source_name,
- hash
- );
+ if source_cache_archive_path.exists() {
+ info!("{} cached source: {}", source_name, hash);
self.artifact_source_id
- .insert(source_key, artifact_source_id.clone());
+ .insert(source_key, source_id.clone());
- return Ok(artifact_source_id);
+ return Ok(source_id);
}
}
// 3. Prepare source if not cached
- let source_path_kind = match &source.path {
- s if Path::new(s).exists() => ArtifactSourceKind::Local,
- s if s.starts_with("git") => ArtifactSourceKind::Git,
- s if s.starts_with("http") => ArtifactSourceKind::Http,
- _ => ArtifactSourceKind::UnknownSourceKind,
- };
-
- if source_path_kind == ArtifactSourceKind::UnknownSourceKind {
- bail!(
- "`source.{}.path` unknown kind: {:?}",
- source_name,
- source.path
- );
- }
-
- if source_path_kind == ArtifactSourceKind::Git {
- bail!("`source.{}.path` git not supported", source_name);
- }
-
let source_sandbox_path = create_sandbox_dir().await?;
if source_path_kind == ArtifactSourceKind::Http {
@@ -249,6 +269,8 @@ impl ConfigContext {
);
}
+ // 3a. Download source
+
let remote_path = Url::parse(&source.path).map_err(|e| anyhow::anyhow!(e))?;
if remote_path.scheme() != "http" && remote_path.scheme() != "https" {
@@ -258,11 +280,7 @@ impl ConfigContext {
);
}
- info!(
- "{} downloading source: {}",
- get_prefix(artifact_name),
- source.path
- );
+ info!("{} downloading source: {}", source_name, source.path);
let remote_response = reqwest::get(remote_path.as_str())
.await
@@ -295,13 +313,9 @@ impl ConfigContext {
.map_err(|e| anyhow::anyhow!(e))?;
}
- // Unpack source data
+ // 3b. Extract source
- info!(
- "{} unpacking source: {}",
- get_prefix(artifact_name),
- source.path
- );
+ info!("{} unpacking source: {}", source_name, source.path);
if let Some(kind) = kind {
match kind.mime_type() {
@@ -377,7 +391,7 @@ impl ConfigContext {
info!(
"{} copying source: {}",
- get_prefix(artifact_name),
+ source_name,
local_path.canonicalize().unwrap().display()
);
@@ -411,11 +425,7 @@ impl ConfigContext {
set_timestamps(&file_path).await?;
}
- info!(
- "{} hashing source: {}",
- get_prefix(artifact_name),
- source.path
- );
+ info!("{} hashing source: {}", source_name, source.path);
// 4b. Hash source files
@@ -432,11 +442,9 @@ impl ConfigContext {
}
}
- info!(
- "{} caching source: {}",
- get_prefix(artifact_name),
- source.path
- );
+ // 4c. Cache source
+
+ info!("{} caching source: {}", source_name, source.path);
let cache_archive_path = get_cache_archive_path(&source_hash, source_name);
@@ -465,21 +473,11 @@ impl ConfigContext {
&mut self,
name: &str,
artifacts: Vec,
- source: BTreeMap<&str, ArtifactSource>,
+ sources: Vec,
steps: Vec,
systems: Vec<&str>,
) -> Result {
- // 1. Setup sources
-
- let mut sources = vec![];
-
- for (source_name, source) in source.into_iter() {
- let source = self.add_artifact_source(name, source_name, source).await?;
-
- sources.push(source);
- }
-
- // 2. Setup systems
+ // 1. Setup systems
let mut systems_int = vec![];
@@ -493,7 +491,7 @@ impl ConfigContext {
systems_int.push(system.into());
}
- // 3. Setup artifact id
+ // 2. Setup artifact id
let artifact = Artifact {
artifacts,
diff --git a/sdk/rust/src/lib.rs b/sdk/rust/src/lib.rs
new file mode 100644
index 00000000..b318fbd1
--- /dev/null
+++ b/sdk/rust/src/lib.rs
@@ -0,0 +1,4 @@
+pub mod artifact;
+pub mod cli;
+pub mod context;
+pub mod source;
diff --git a/sdk/rust/src/source/mod.rs b/sdk/rust/src/source/mod.rs
new file mode 100644
index 00000000..8fd43e50
--- /dev/null
+++ b/sdk/rust/src/source/mod.rs
@@ -0,0 +1,24 @@
+use crate::{artifact::ArtifactSource, context::ConfigContext};
+use anyhow::Result;
+use vorpal_schema::vorpal::artifact::v0::ArtifactSourceId;
+
+pub async fn go_tools(context: &mut ConfigContext) -> Result {
+ let hash = "b4faf133f053f372cfe8ea3189bf035d19ca1661cb3ac1e7cd34a465de5641c2";
+
+ let version = "0.29.0";
+
+ context
+ .add_artifact_source(
+ "go-tools",
+ ArtifactSource {
+ excludes: vec![],
+ hash: Some(hash.to_string()),
+ includes: vec![],
+ path: format!(
+ "https://go.googlesource.com/tools/+archive/refs/tags/v{}.tar.gz",
+ version
+ ),
+ },
+ )
+ .await
+}
diff --git a/sdk/src/config/artifact/toolchain/linux/mod.rs b/sdk/src/config/artifact/toolchain/linux/mod.rs
deleted file mode 100644
index 95cdfaf8..00000000
--- a/sdk/src/config/artifact/toolchain/linux/mod.rs
+++ /dev/null
@@ -1,2 +0,0 @@
-pub mod debian;
-pub mod vorpal;
diff --git a/sdk/src/config/artifact/toolchain/linux/vorpal/source.rs b/sdk/src/config/artifact/toolchain/linux/vorpal/source.rs
deleted file mode 100644
index 9e112f62..00000000
--- a/sdk/src/config/artifact/toolchain/linux/vorpal/source.rs
+++ /dev/null
@@ -1,191 +0,0 @@
-use crate::config::ArtifactSource;
-
-pub fn curl(version: &str, hash: &str) -> ArtifactSource {
- ArtifactSource {
- excludes: vec![],
- hash: Some(hash.to_string()),
- includes: vec![],
- path: format!("https://curl.se/download/curl-{version}.tar.xz"),
- }
-}
-
-pub fn curl_cacert(hash: &str) -> ArtifactSource {
- ArtifactSource {
- excludes: vec![],
- hash: Some(hash.to_string()),
- includes: vec![],
- path: "https://curl.se/ca/cacert.pem".to_string(),
- }
-}
-
-pub fn file(version: &str, hash: &str) -> ArtifactSource {
- ArtifactSource {
- excludes: vec![],
- hash: Some(hash.to_string()),
- includes: vec![],
- path: format!("https://astron.com/pub/file/file-{version}.tar.gz"),
- }
-}
-
-pub fn gnu(name: &str, version: &str, hash: &str) -> ArtifactSource {
- ArtifactSource {
- excludes: vec![],
- hash: Some(hash.to_string()),
- includes: vec![],
- path: format!("https://ftpmirror.gnu.org/gnu/{name}/{name}-{version}.tar.gz"),
- }
-}
-
-pub fn gnu_xz(name: &str, version: &str, hash: &str) -> ArtifactSource {
- ArtifactSource {
- excludes: vec![],
- hash: Some(hash.to_string()),
- includes: vec![],
- path: format!("https://ftpmirror.gnu.org/gnu/{name}/{name}-{version}.tar.xz"),
- }
-}
-
-pub fn gnu_gcc(version: &str, hash: &str) -> ArtifactSource {
- ArtifactSource {
- excludes: vec![],
- hash: Some(hash.to_string()),
- includes: vec![],
- path: format!("https://ftpmirror.gnu.org/gnu/gcc/gcc-{version}/gcc-{version}.tar.xz"),
- }
-}
-
-pub fn gnu_glibc_patch(version: &str, hash: &str) -> ArtifactSource {
- ArtifactSource {
- excludes: vec![],
- hash: Some(hash.to_string()),
- includes: vec![],
- path: format!(
- "https://www.linuxfromscratch.org/patches/lfs/12.2/glibc-{version}-fhs-1.patch",
- ),
- }
-}
-
-pub fn libidn2(version: &str, hash: &str) -> ArtifactSource {
- ArtifactSource {
- excludes: vec![],
- hash: Some(hash.to_string()),
- includes: vec![],
- path: format!("https://ftpmirror.gnu.org/gnu/libidn/libidn2-{version}.tar.gz"),
- }
-}
-
-pub fn libpsl(version: &str, hash: &str) -> ArtifactSource {
- ArtifactSource {
- excludes: vec![],
- hash: Some(hash.to_string()),
- includes: vec![],
- path: format!(
- "https://github.com/rockdaboot/libpsl/releases/download/{version}/libpsl-{version}.tar.gz",
- ),
- }
-}
-
-pub fn linux(version: &str, hash: &str) -> ArtifactSource {
- ArtifactSource {
- excludes: vec![],
- hash: Some(hash.to_string()),
- includes: vec![],
- path: format!("https://cdn.kernel.org/pub/linux/kernel/v6.x/linux-{version}.tar.xz"),
- }
-}
-
-pub fn ncurses(version: &str, hash: &str) -> ArtifactSource {
- ArtifactSource {
- excludes: vec![],
- hash: Some(hash.to_string()),
- includes: vec![],
- path: format!("https://invisible-mirror.net/archives/ncurses/ncurses-{version}.tar.gz"),
- }
-}
-
-pub fn openssl(version: &str, hash: &str) -> ArtifactSource {
- ArtifactSource {
- excludes: vec![],
- hash: Some(hash.to_string()),
- includes: vec![],
- path: format!("https://www.openssl.org/source/openssl-{version}.tar.gz"),
- }
-}
-
-pub fn perl(version: &str, hash: &str) -> ArtifactSource {
- ArtifactSource {
- excludes: vec![],
- hash: Some(hash.to_string()),
- includes: vec![],
- path: format!("https://www.cpan.org/src/5.0/perl-{version}.tar.xz"),
- }
-}
-
-pub fn python(version: &str, hash: &str) -> ArtifactSource {
- ArtifactSource {
- excludes: vec![],
- hash: Some(hash.to_string()),
- includes: vec![],
- path: format!("https://www.python.org/ftp/python/{version}/Python-{version}.tar.xz"),
- }
-}
-
-pub fn unzip_patch_fixes(version: &str, hash: &str) -> ArtifactSource {
- ArtifactSource {
- excludes: vec![],
- hash: Some(hash.to_string()),
- includes: vec![],
- path: format!("https://www.linuxfromscratch.org/patches/blfs/12.2/unzip-{version}-consolidated_fixes-1.patch"),
- }
-}
-
-pub fn unzip_patch_gcc14(version: &str, hash: &str) -> ArtifactSource {
- ArtifactSource {
- excludes: vec![],
- hash: Some(hash.to_string()),
- includes: vec![],
- path: format!(
- "https://www.linuxfromscratch.org/patches/blfs/12.2/unzip-{version}-gcc14-1.patch"
- ),
- }
-}
-
-pub fn unzip(version: &str, hash: &str) -> ArtifactSource {
- let version = version.replace(".", "");
-
- ArtifactSource {
- excludes: vec![],
- hash: Some(hash.to_string()),
- includes: vec![],
- path: format!("https://cfhcable.dl.sourceforge.net/project/infozip/UnZip%206.x%20%28latest%29/UnZip%206.0/unzip{version}.tar.gz?viasf=1",),
- }
-}
-
-pub fn util_linux(version: &str, hash: &str) -> ArtifactSource {
- ArtifactSource {
- excludes: vec![],
- hash: Some(hash.to_string()),
- includes: vec![],
- path: format!(
- "https://www.kernel.org/pub/linux/utils/util-linux/v2.40/util-linux-{version}.tar.xz"
- ),
- }
-}
-
-pub fn xz(version: &str, hash: &str) -> ArtifactSource {
- ArtifactSource {
- excludes: vec![],
- hash: Some(hash.to_string()),
- includes: vec![],
- path: format!("https://github.com/tukaani-project/xz/releases/download/v{version}/xz-{version}.tar.xz"),
- }
-}
-
-pub fn zlib(version: &str, hash: &str) -> ArtifactSource {
- ArtifactSource {
- excludes: vec![],
- hash: Some(hash.to_string()),
- includes: vec![],
- path: format!("https://zlib.net/fossils/zlib-{version}.tar.gz"),
- }
-}
diff --git a/sdk/src/config/artifact/toolchain/mod.rs b/sdk/src/config/artifact/toolchain/mod.rs
deleted file mode 100644
index 54ad22dc..00000000
--- a/sdk/src/config/artifact/toolchain/mod.rs
+++ /dev/null
@@ -1,9 +0,0 @@
-pub mod cargo;
-pub mod clippy;
-pub mod linux;
-pub mod protoc;
-pub mod rust_analyzer;
-pub mod rust_src;
-pub mod rust_std;
-pub mod rustc;
-pub mod rustfmt;
diff --git a/sdk/src/config/service.rs b/sdk/src/config/service.rs
deleted file mode 100644
index a147e744..00000000
--- a/sdk/src/config/service.rs
+++ /dev/null
@@ -1,45 +0,0 @@
-use crate::config::ConfigContext;
-use anyhow::Result;
-use vorpal_schema::vorpal::{
- artifact::v0::{Artifact, ArtifactId},
- config::v0::{config_service_server::ConfigService, Config, ConfigRequest},
-};
-
-#[derive(Debug, Default)]
-pub struct ConfigServer {
- pub context: ConfigContext,
- pub config: Config,
-}
-
-impl ConfigServer {
- pub fn new(context: ConfigContext, config: Config) -> Self {
- Self { context, config }
- }
-}
-
-#[tonic::async_trait]
-impl ConfigService for ConfigServer {
- async fn get_config(
- &self,
- _request: tonic::Request,
- ) -> Result, tonic::Status> {
- Ok(tonic::Response::new(self.config.clone()))
- }
-
- async fn get_artifact(
- &self,
- request: tonic::Request,
- ) -> Result, tonic::Status> {
- let request = request.into_inner();
-
- let artifact = self
- .context
- .get_artifact(request.hash.as_str(), request.name.as_str());
-
- if artifact.is_none() {
- return Err(tonic::Status::not_found("Artifact input not found"));
- }
-
- Ok(tonic::Response::new(artifact.unwrap().clone()))
- }
-}
diff --git a/sdk/src/lib.rs b/sdk/src/lib.rs
deleted file mode 100644
index ef68c369..00000000
--- a/sdk/src/lib.rs
+++ /dev/null
@@ -1 +0,0 @@
-pub mod config;
diff --git a/vorpal-purpose.jpg b/vorpal-purpose.jpg
index 5c41d7cd..369435bd 100644
Binary files a/vorpal-purpose.jpg and b/vorpal-purpose.jpg differ