Skip to main content

trident/package/registry/
store_integration.rs

1use crate::hash::ContentHash;
2use crate::store::{Codebase, Definition};
3
4use super::client::RegistryClient;
5use super::types::*;
6
7pub fn publish_codebase(
8    codebase: &Codebase,
9    client: &RegistryClient,
10    tags: &[String],
11) -> Result<Vec<PublishResult>, String> {
12    let names = codebase.list_names();
13    let mut results = Vec::new();
14
15    for (name, hash) in &names {
16        let def = match codebase.lookup_hash(hash) {
17            Some(d) => d,
18            None => continue,
19        };
20
21        let pub_def = PublishedDefinition {
22            hash: hash.to_hex(),
23            source: def.source.clone(),
24            module: def.module.clone(),
25            is_pub: def.is_pub,
26            params: def.params.clone(),
27            return_ty: def.return_ty.clone(),
28            dependencies: def.dependencies.iter().map(|h| h.to_hex()).collect(),
29            requires: def.requires.clone(),
30            ensures: def.ensures.clone(),
31            name: Some(name.to_string()),
32            tags: tags.to_vec(),
33            verified: false,
34            verification_cert: None,
35        };
36
37        match client.publish(&pub_def) {
38            Ok(result) => results.push(result),
39            Err(e) => {
40                return Err(format!("failed to publish '{}': {}", name, e));
41            }
42        }
43    }
44
45    Ok(results)
46}
47
48/// Pull a definition from a registry into the local store.
49pub fn pull_into_codebase(
50    codebase: &mut Codebase,
51    client: &RegistryClient,
52    name_or_hash: &str,
53) -> Result<PullResult, String> {
54    let pull = if name_or_hash.len() == 64 && name_or_hash.chars().all(|c| c.is_ascii_hexdigit()) {
55        client.pull(name_or_hash)?
56    } else {
57        client.pull_by_name(name_or_hash)?
58    };
59
60    let hash = ContentHash::from_hex(&pull.hash)
61        .ok_or_else(|| "invalid hash in pull response".to_string())?;
62
63    if codebase.lookup_hash(&hash).is_some() {
64        return Ok(pull);
65    }
66
67    let deps: Vec<ContentHash> = pull
68        .dependencies
69        .iter()
70        .filter_map(|h| ContentHash::from_hex(h))
71        .collect();
72
73    let def = Definition {
74        source: pull.source.clone(),
75        module: pull.module.clone(),
76        is_pub: true,
77        params: pull.params.clone(),
78        return_ty: pull.return_ty.clone(),
79        dependencies: deps,
80        requires: pull.requires.clone(),
81        ensures: pull.ensures.clone(),
82        first_seen: crate::package::unix_timestamp(),
83    };
84
85    codebase.store_definition(hash, def);
86
87    if name_or_hash.len() != 64 || !name_or_hash.chars().all(|c| c.is_ascii_hexdigit()) {
88        codebase.bind_name(name_or_hash, hash);
89    }
90
91    codebase.save().map_err(|e| e.to_string())?;
92
93    Ok(pull)
94}