Initial Dever 0.0.1

This commit is contained in:
Codex committed 2026-11-03 03:32:07 +00:00
commit 81233d098c
1479 files changed
+163782

No files matched your search

+189
View File
@@ -0,0 +1,189 @@
//! 测试 key 只用于显式注入的 sumdb 对端,不进入产品公钥或项目设置。
use super::*;
use base64::{Engine, engine::general_purpose::STANDARD};
use ring::signature::{Ed25519KeyPair, KeyPair};
use sha2::{Digest, Sha256};
use std::{
cell::RefCell,
io::{Cursor, Write},
};
#[derive(Default)]
pub(super) struct Cache(pub RefCell<BTreeMap<String, Vec<u8>>>);
impl Store for Cache {
fn get(&self, hash: &str, _: u64) -> Result<Option<Vec<u8>>, String> {
Ok(self.0.borrow().get(hash).cloned())
}
fn put(&self, bytes: &[u8]) -> Result<(), String> {
self.0.borrow_mut().insert(
crate::compiler::project::dependency::digest(bytes),
bytes.to_vec(),
);
Ok(())
}
}
#[derive(Clone, Default)]
pub(super) struct Registry(pub BTreeMap<String, Vec<u8>>);
impl Transport for Registry {
fn get(&self, url: &str, limit: usize) -> Result<Vec<u8>, String> {
let bytes = self
.0
.get(url)
.ok_or_else(|| format!("missing owned registry response {url}"))?;
assert!(bytes.len() <= limit);
Ok(bytes.clone())
}
}
pub(super) fn runtime() -> Metadata {
serde_json::from_value(serde_json::json!({"pack":{"name":"go", "version":"1.25.0", "sha256":"0".repeat(64)},
"target":BuildTarget::host().unwrap().name(), "python_markers":null, "python_wheel_tags":[]})).unwrap()
}
pub(super) fn zip(module: &str, version: &str, contents: &str) -> Vec<u8> {
let mut archive = zip::ZipWriter::new(Cursor::new(Vec::new()));
archive
.start_file(
format!("{module}@v{version}/value.go"),
zip::write::SimpleFileOptions::default(),
)
.unwrap();
archive.write_all(contents.as_bytes()).unwrap();
archive.finish().unwrap().into_inner()
}
fn key() -> Ed25519KeyPair {
Ed25519KeyPair::from_seed_unchecked(&[47; 32]).unwrap()
}
fn key_id() -> Vec<u8> {
let mut hash = Sha256::new();
hash.update(b"dever-sumdb-test\n");
hash.update([1]);
hash.update(key().public_key().as_ref());
hash.finalize()[..4].to_vec()
}
pub(super) fn verifier() -> Verifier {
let mut bytes = vec![1];
bytes.extend_from_slice(key().public_key().as_ref());
Verifier::new(&format!(
"dever-sumdb-test+{}+{}",
key_id()
.iter()
.map(|byte| format!("{byte:02x}"))
.collect::<String>(),
STANDARD.encode(bytes)
))
.unwrap()
}
fn root(hashes: &[[u8; 32]]) -> [u8; 32] {
if hashes.is_empty() {
return Sha256::digest([]).into();
}
if hashes.len() == 1 {
return hashes[0];
}
let split = hashes.len().next_power_of_two() / 2;
let mut hash = Sha256::new();
hash.update([1]);
hash.update(root(&hashes[..split]));
hash.update(root(&hashes[split..]));
hash.finalize().into()
}
impl Registry {
pub fn module(&mut self, name: &str, version: &str, source: &str) {
let prefix = format!(
"https://proxy.golang.org/{}/@v/v{version}",
module::escape(name)
);
self.0
.insert(format!("{prefix}.mod"), source.as_bytes().to_vec());
self.0.insert(
format!("{prefix}.zip"),
zip(name, version, "package value\n"),
);
}
pub fn seal(&mut self) {
self.0
.retain(|path, _| !path.starts_with("https://sum.golang.org/"));
let records = self
.0
.iter()
.filter_map(|(path, source)| {
let path = path.strip_prefix("https://proxy.golang.org/")?;
let (name, version) = path.split_once("/@v/v")?;
let version = version.strip_suffix(".mod")?;
let archive =
&self.0[&format!("https://proxy.golang.org/{name}/@v/v{version}.zip")];
let text = format!(
"{name} v{version} {}\n{name} v{version}/go.mod {}\n",
sumdb::zip_hash(name, version, archive).unwrap(),
sumdb::mod_hash(source)
);
Some((
format!("https://sum.golang.org/lookup/{name}@v{version}"),
text,
))
})
.collect::<Vec<_>>();
let hashes = records
.iter()
.map(|(_, text)| {
let mut hash = Sha256::new();
hash.update([0]);
hash.update(text);
hash.finalize().into()
})
.collect::<Vec<[u8; 32]>>();
let text = format!(
"go.sum database tree\n{}\n{}\n",
hashes.len(),
STANDARD.encode(root(&hashes))
);
let mut signature = key_id();
signature.extend_from_slice(key().sign(text.as_bytes()).as_ref());
let note = format!(
"{text}\n— dever-sumdb-test {}\n",
STANDARD.encode(signature)
);
self.0.insert(
"https://sum.golang.org/latest".into(),
note.as_bytes().to_vec(),
);
for (id, (path, text)) in records.into_iter().enumerate() {
self.0
.insert(path, format!("{id}\n{text}\n{note}").into_bytes());
}
assert!(hashes.len() < 256);
self.0.insert(
format!("https://sum.golang.org/tile/8/0/000.p/{}", hashes.len()),
hashes.into_iter().flatten().collect(),
);
}
}
pub(super) fn graph() -> Registry {
let mut registry = Registry::default();
for (name, version, source) in [
(
"a",
"1.0.0",
"module example.com/a\nrequire (\nexample.com/b v1.0.0\nexample.com/c v1.0.0\n)\n",
),
("b", "1.0.0", "module example.com/b\n"),
("b", "1.2.0", "module example.com/b\n"),
(
"c",
"1.0.0",
"module example.com/c\nrequire example.com/b v1.2.0\n",
),
] {
registry.module(&format!("example.com/{name}"), version, source);
}
registry.seal();
registry
}