binaryninja/repository/
manager.rs

1use crate::rc::{Array, Ref};
2use crate::repository::Repository;
3use crate::string::IntoCStr;
4use binaryninjacore_sys::{
5    BNRepositoryGetRepositoryByPath, BNRepositoryManagerAddRepository,
6    BNRepositoryManagerCheckForUpdates, BNRepositoryManagerGetDefaultRepository,
7    BNRepositoryManagerGetRepositories,
8};
9use std::fmt::Debug;
10use std::path::Path;
11use std::ptr::NonNull;
12
13/// Keeps track of all the repositories and keeps the `enabled_plugins.json`
14/// file coherent with the plugins that are installed/uninstalled enabled/disabled
15pub struct RepositoryManager;
16
17impl RepositoryManager {
18    /// Check for updates for all managed [`Repository`] objects
19    pub fn check_for_updates() -> bool {
20        unsafe { BNRepositoryManagerCheckForUpdates() }
21    }
22
23    /// List of [`Repository`] objects being managed
24    pub fn repositories() -> Array<Repository> {
25        let mut count = 0;
26        let result = unsafe { BNRepositoryManagerGetRepositories(&mut count) };
27        assert!(!result.is_null());
28        unsafe { Array::new(result, count, ()) }
29    }
30
31    /// Adds a new plugin repository for the manager to track.
32    ///
33    /// To remove a repository, restart Binary Ninja (and don't re-add the repository!).
34    /// File artifacts will remain on disk under repositories/ file in the User Folder.
35    ///
36    /// Before you can query plugin metadata from a repository, you need to call [`RepositoryManager::check_for_updates`].
37    ///
38    /// * `url` - URL to the plugins.json containing the records for this repository
39    /// * `repository_path` - path to where the repository will be stored on disk locally
40    ///
41    /// Returns true if the repository was successfully added, false otherwise.
42    pub fn add_repository(url: &str, repository_path: &Path) -> bool {
43        let url = url.to_cstr();
44        let repo_path = repository_path.to_cstr();
45        unsafe { BNRepositoryManagerAddRepository(url.as_ptr(), repo_path.as_ptr()) }
46    }
47
48    pub fn repository_by_path(path: &Path) -> Option<Repository> {
49        let path = path.to_cstr();
50        let result = unsafe { BNRepositoryGetRepositoryByPath(path.as_ptr()) };
51        NonNull::new(result).map(|raw| unsafe { Repository::from_raw(raw) })
52    }
53
54    /// Gets the default [`Repository`]
55    pub fn default_repository() -> Ref<Repository> {
56        let result = unsafe { BNRepositoryManagerGetDefaultRepository() };
57        assert!(!result.is_null());
58        unsafe { Repository::ref_from_raw(NonNull::new(result).unwrap()) }
59    }
60}
61
62impl Debug for RepositoryManager {
63    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
64        f.debug_struct("RepositoryManager")
65            .field("repositories", &RepositoryManager::repositories().to_vec())
66            .finish()
67    }
68}