summaryrefslogtreecommitdiff
path: root/rust/src/repository/manager.rs
blob: d20539c42b12ef45e88a435417e0adfd63be0e11 (plain)
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
use crate::rc::{Array, Ref};
use crate::repository::Repository;
use crate::string::IntoCStr;
use binaryninjacore_sys::{
    BNRepositoryGetRepositoryByPath, BNRepositoryManagerAddRepository,
    BNRepositoryManagerCheckForUpdates, BNRepositoryManagerGetDefaultRepository,
    BNRepositoryManagerGetRepositories,
};
use std::fmt::Debug;
use std::path::Path;
use std::ptr::NonNull;

/// Keeps track of all the repositories and keeps the `enabled_plugins.json`
/// file coherent with the plugins that are installed/uninstalled enabled/disabled
pub struct RepositoryManager;

impl RepositoryManager {
    /// Check for updates for all managed [`Repository`] objects
    pub fn check_for_updates() -> bool {
        unsafe { BNRepositoryManagerCheckForUpdates() }
    }

    /// List of [`Repository`] objects being managed
    pub fn repositories() -> Array<Repository> {
        let mut count = 0;
        let result = unsafe { BNRepositoryManagerGetRepositories(&mut count) };
        assert!(!result.is_null());
        unsafe { Array::new(result, count, ()) }
    }

    /// Adds a new plugin repository for the manager to track.
    ///
    /// To remove a repository, restart Binary Ninja (and don't re-add the repository!).
    /// File artifacts will remain on disk under repositories/ file in the User Folder.
    ///
    /// Before you can query plugin metadata from a repository, you need to call [`RepositoryManager::check_for_updates`].
    ///
    /// * `url` - URL to the plugins.json containing the records for this repository
    /// * `repository_path` - path to where the repository will be stored on disk locally
    ///
    /// Returns true if the repository was successfully added, false otherwise.
    pub fn add_repository(url: &str, repository_path: &Path) -> bool {
        let url = url.to_cstr();
        let repo_path = repository_path.to_cstr();
        unsafe { BNRepositoryManagerAddRepository(url.as_ptr(), repo_path.as_ptr()) }
    }

    pub fn repository_by_path(path: &Path) -> Option<Repository> {
        let path = path.to_cstr();
        let result = unsafe { BNRepositoryGetRepositoryByPath(path.as_ptr()) };
        NonNull::new(result).map(|raw| unsafe { Repository::from_raw(raw) })
    }

    /// Gets the default [`Repository`]
    pub fn default_repository() -> Ref<Repository> {
        let result = unsafe { BNRepositoryManagerGetDefaultRepository() };
        assert!(!result.is_null());
        unsafe { Repository::ref_from_raw(NonNull::new(result).unwrap()) }
    }
}

impl Debug for RepositoryManager {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        f.debug_struct("RepositoryManager")
            .field("repositories", &RepositoryManager::repositories().to_vec())
            .finish()
    }
}