logo
  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
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
use serde::{Deserialize, Serialize};
use std::fmt::Debug;

/// Generic and plain dependency without any extra information.
/// Language agnostic, just holds the name and the version.
#[derive(Serialize, Deserialize, Debug, Clone, Eq, Ord, PartialEq, PartialOrd, Default)]
pub struct Dependency {
    /// Dependency name
    pub name: String,
    /// Dependency version
    pub version: String,
}

/// A dependency that has been retrieved from its source.
/// The source can be anything, from a third party API (i.e. npm, pub.dev or crates.io APIs) to the file system.
/// It holds information about licenses, errors while validating...
#[derive(Serialize, Deserialize, Debug, Eq, Ord, PartialEq, PartialOrd, Clone, Default)]
pub struct RetrievedDependency {
    /// Dependency name.
    pub name: String,
    /// Dependency version.
    pub version: String,
    /// Dependency type (npm, dart, rust, go, python...)
    pub dependency_type: String,
    /// Url of the dependency if available.
    pub url: Option<String>,
    /// List of licenses of the dependency.
    pub licenses: Option<Vec<String>>,
    /// Set to true if the dependency has been validated against the licrc.
    pub validated: bool,
    /// Indicates if the license is valid for our project or not according to our .licrc configuration file.
    pub is_valid: bool,
    /// Indicates if the dependency has been ignored according to our .licrc configuration file.
    pub is_ignored: bool,
    /// Contains information about any error that may have happened during the validation process.
    pub error: Option<String>,
    /// Comments about the license validation process.
    pub comment: Option<Comment>,
}

impl RetrievedDependency {
    /// Creates a new `RetrievedDependency` with the given parameters.
    /// Note that some properties will be automatically set depending on the other ones.
    /// For example, if the `licenses` parameter is `None`, the `is_valid` property will be set to `false`.
    /// Use the default method if you just want to create an instance with all  the defaults.
    /// This method it's intended to be used once you have retrieved the dependency from its source (i.e. npm, github, etc).
    #[must_use]
    pub fn new(
        name: String,
        version: String,
        dependency_type: String,
        url: Option<String>,
        licenses: Option<Vec<String>>,
        error: Option<String>,
        comment: Option<Comment>,
    ) -> Self {
        let has_licenses = licenses.is_some();

        Self {
            name,
            version,
            dependency_type,
            url,
            licenses,
            validated: false,
            is_valid: has_licenses && error.is_none(),
            is_ignored: false,
            error: error.or_else(|| {
                if has_licenses {
                    None
                } else {
                    Some("No License".to_owned())
                }
            }),
            comment: comment.or_else(|| {
                if has_licenses {
                    None
                } else {
                    Some(Comment::removable("Consider manually checking this dependency's license. Remember this: https://choosealicense.com/no-permission/ and ignore it if you feel confident about it to avoid this warning."))
                }
            }),
        }
    }
}

/// A comment to be added in a [`RetrievedDependency`] once it has been retrieved or validated.
/// It normally adds information about what went wrong.
#[derive(Serialize, Deserialize, Debug, Default, Eq, Ord, PartialEq, PartialOrd, Clone)]
pub struct Comment {
    /// The comment text.
    pub text: String,
    /// If true, the comment won't be shown if the dependency is valid.
    pub remove_when_valid: bool,
}

impl Comment {
    /// Builds a removable comment.
    /// This basically mean it won't be shown if the dependency is flagged as valid.
    pub fn removable(text: impl Into<String>) -> Self {
        Self {
            text: text.into(),
            remove_when_valid: true,
        }
    }

    /// Builds a non removable comment.
    /// This comment will be shown no matter if the dependency is valid or not.
    pub fn non_removable(text: impl Into<String>) -> Self {
        Self {
            text: text.into(),
            remove_when_valid: false,
        }
    }
}