1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
use crate::WasmPlugin;
use proto_core::{
    async_trait, create_global_shim, create_global_shim_with_name, create_local_shim, Describable,
    Installable, ProtoError, ShimContext, Shimable,
};
use proto_pdk_api::{CreateShimsInput, CreateShimsOutput};
use std::path::Path;

#[async_trait]
impl Shimable<'_> for WasmPlugin {
    async fn create_shims(&mut self, find_only: bool) -> Result<(), ProtoError> {
        let install_dir = self.get_install_dir()?;
        let mut created_primary = false;

        if self.has_func("create_shims") {
            let shim_configs: CreateShimsOutput = self.cache_func_with(
                "create_shims",
                CreateShimsInput {
                    env: self.get_environment()?,
                },
            )?;

            if let Some(primary_config) = &shim_configs.primary {
                let mut context = ShimContext::new_global(self.get_id());
                context.parent_bin = primary_config.parent_bin.as_deref();
                context.before_args = primary_config.before_args.as_deref();
                context.after_args = primary_config.after_args.as_deref();

                create_global_shim(context)?;

                created_primary = true;
            }

            for (name, config) in &shim_configs.global_shims {
                let mut context = if let Some(alt_bin) = &config.bin_path {
                    ShimContext::new_global_alt(self.get_id(), name, alt_bin)
                } else {
                    ShimContext::new_global(self.get_id())
                };

                context.before_args = config.before_args.as_deref();
                context.after_args = config.after_args.as_deref();

                if config.bin_path.is_some() {
                    create_global_shim(context)?;
                } else {
                    create_global_shim_with_name(context, name)?;
                }
            }

            for (name, config) in &shim_configs.local_shims {
                let bin_path = install_dir.join(config.bin_path.as_ref().unwrap_or(name));

                let mut context = ShimContext::new_local(name, &bin_path);
                context.parent_bin = config.parent_bin.as_deref();
                context.before_args = config.before_args.as_deref();
                context.after_args = config.after_args.as_deref();
                context.tool_dir = Some(&install_dir);

                let shim_path = create_local_shim(context, find_only)?;

                if name == self.get_id() {
                    self.shim_path = Some(shim_path);
                }
            }
        }

        // We must always create a primary global shim, so if the plugin did not configure one,
        // we will create one automatically using the information we have.
        if !created_primary {
            create_global_shim(ShimContext::new_global(self.get_id()))?;
        }

        Ok(())
    }

    fn get_shim_path(&self) -> Option<&Path> {
        self.shim_path.as_deref()
    }
}