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,
        }
    }
}