Initial Dever 0.0.1
This commit is contained in:
commit
81233d098c
1479 files changed
+163782
No files matched your search
@@ -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
|
||||
}
|
||||
Reference in new issue
Block a user