Skip to content

Commit 620308b

Browse files
committed
Fix up docs
1 parent b54b403 commit 620308b

File tree

4 files changed

+129
-90
lines changed

4 files changed

+129
-90
lines changed

src/lib.rs

+13-7
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,7 @@ pub use locator::*;
2222
pub use locator_package::*;
2323
pub use locator_strict::*;
2424

25-
/// [`Locator`](crate::Locator) is closely tied with the concept of Core's "fetchers",
26-
/// which are asynchronous jobs tasked with downloading the code
27-
/// referred to by a [`Locator`](crate::Locator) so that Core or some other service
28-
/// may analyze it.
29-
///
30-
/// For more information on the background of `Locator` and fetchers generally,
31-
/// refer to [Fetchers and Locators](https://go/fetchers-doc).
25+
/// `Fetcher` identifies a supported code host protocol.
3226
#[derive(
3327
Copy,
3428
Clone,
@@ -251,6 +245,14 @@ impl std::fmt::Debug for OrgId {
251245
}
252246

253247
/// The package section of the locator.
248+
///
249+
/// A "package" is generally the name of a project or dependency in a code host.
250+
/// However some fetcher protocols (such as `git`) embed additional information
251+
/// inside the `Package` of a locator, such as the URL of the `git` instance
252+
/// from which the project can be fetched.
253+
///
254+
/// Additionally, some fetcher protocols (such as `apk`, `rpm-generic`, and `deb`)
255+
/// further encode additional standardized information in the `Package` of the locator.
254256
#[derive(Clone, Eq, PartialEq, Hash, Serialize, Deserialize, Documented, ToSchema)]
255257
pub struct Package(String);
256258

@@ -304,6 +306,10 @@ impl std::cmp::PartialOrd for Package {
304306
}
305307

306308
/// The revision section of the locator.
309+
///
310+
/// A "revision" is the version of the project in the code host.
311+
/// Some fetcher protocols (such as `apk`, `rpm-generic`, and `deb`)
312+
/// encode additional standardized information in the `Revision` of the locator.
307313
#[derive(Clone, Eq, PartialEq, Hash, Documented, ToSchema)]
308314
#[schema(examples(json!("1.0.0"), json!("2.0.0-alpha.1"), json!("abcd1234")))]
309315
pub enum Revision {

src/locator.rs

+53-59
Original file line numberDiff line numberDiff line change
@@ -86,55 +86,61 @@ macro_rules! locator_regex {
8686
};
8787
}
8888

89-
/// Core, and most services that interact with Core,
90-
/// refer to open source packages via the `Locator` type.
89+
/// `Locator` identifies a package, optionally at a specific revision, in a code host.
9190
///
92-
/// This type is nearly universally rendered to a string
93-
/// before being serialized to the database or sent over the network.
91+
/// If the `revision` component is not specified, FOSSA services interpret this to mean
92+
/// that the "latest" version of the package should be used if the requested operation
93+
/// requires a concrete version of the package.
9494
///
95-
/// This type represents a _validly-constructed_ `Locator`, but does not
96-
/// validate whether a `Locator` is actually valid. This means that a
97-
/// given `Locator` is guaranteed to be correctly formatted data,
98-
/// but that the actual repository or revision to which the `Locator`
99-
/// refers is _not_ guaranteed to exist or be accessible.
100-
/// Currently the canonical method for validating whether a given `Locator` is
101-
/// accessible is to run it through the Core fetcher system.
95+
/// ## Guarantees
10296
///
103-
/// For more information on the background of `Locator` and fetchers generally,
104-
/// FOSSA employees may refer to
105-
/// [Fetchers and Locators](https://go/fetchers-doc).
97+
/// This type represents a _validly-constructed_ `Locator`, but does not
98+
/// guarantee whether a package or revision actually exists or is accessible
99+
/// in the code host.
106100
///
107101
/// ## Ordering
108102
///
109-
/// Locators order by:
103+
/// `Locator` orders by:
110104
/// 1. Fetcher, alphanumerically.
111105
/// 2. Organization ID, alphanumerically; missing organizations are sorted higher.
112106
/// 3. The package field, alphanumerically.
113107
/// 4. The revision field:
114-
/// If both comparing locators use semver, these are compared using semver rules;
115-
/// otherwise these are compared alphanumerically.
116-
/// Missing revisions are sorted higher.
108+
/// - If both comparing locators use semver, these are compared using semver rules.
109+
/// - Otherwise these are compared alphanumerically.
110+
/// - Missing revisions are sorted higher.
117111
///
118-
/// Importantly, there may be other metrics for ordering using the actual code host
119-
/// which contains the package (for example, ordering by release date).
120-
/// This library does not perform such ordering.
112+
/// **Important:** there may be other metrics for ordering using the actual code host
113+
/// which contains the package- for example ordering by release date, or code hosts
114+
/// such as `git` which have non-linear history (making flat ordering a lossy operation).
115+
/// `Locator` does not take such edge cases into account in any way.
121116
///
122117
/// ## Parsing
123118
///
124-
/// The input string must be in one of the following forms:
125-
/// - `{fetcher}+{package}`
126-
/// - `{fetcher}+{package}$`
127-
/// - `{fetcher}+{package}${revision}`
119+
/// This type is canonically rendered to a string before being serialized
120+
/// to the database or sent over the network according to the rules in this section.
121+
///
122+
/// The input string must be in one of the following formats:
123+
/// ```ignore
124+
/// {fetcher}+{package}${revision}
125+
/// {fetcher}+{package}
126+
/// ```
128127
///
129128
/// Packages may also be namespaced to a specific organization;
130129
/// in such cases the organization ID is at the start of the `{package}` field
131130
/// separated by a slash. The ID can be any non-negative integer.
132-
/// This yields the following formats:
133-
/// - `{fetcher}+{org_id}/{package}`
134-
/// - `{fetcher}+{org_id}/{package}$`
135-
/// - `{fetcher}+{org_id}/{package}${revision}`
131+
/// This yields the following optional formats:
132+
/// ```ignore
133+
/// {fetcher}+{org_id}/{package}${revision}
134+
/// {fetcher}+{org_id}/{package}
135+
/// ```
136136
///
137-
/// This parse function is based on the function used in FOSSA Core for maximal compatibility.
137+
/// Note that locators do not feature escaping: instead the _first_ instance
138+
/// of each delimiter (`+`, `/`, `$`) is used to split the fields. However,
139+
/// as a special case organization IDs are only extracted if the field content
140+
/// fully consists of a non-negative integer.
141+
//
142+
// For more information on the background of `Locator` and fetchers generally,
143+
// FOSSA employees may refer to the "fetchers and locators" doc: https://go/fetchers-doc.
138144
#[derive(
139145
Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug, Builder, Getters, CopyGetters, Documented,
140146
)]
@@ -189,55 +195,43 @@ impl Locator {
189195

190196
/// Parse a `Locator`.
191197
/// For details, see the parsing section on [`Locator`].
192-
pub fn parse(locator: &str) -> Result<Self, Error> {
198+
pub fn parse(input: &str) -> Result<Self, Error> {
199+
/// Convenience macro for fatal errors without needing to type out all the `.into()`s.
193200
macro_rules! fatal {
194-
(syntax; $inner:expr) => {
195-
ParseError::Syntax {
196-
input: $inner.into(),
197-
}
198-
};
199-
(field => $name:expr; $inner:expr) => {
200-
ParseError::Field {
201-
input: $inner.into(),
202-
field: $name.into(),
201+
($type:ident => $input:expr) => {
202+
ParseError::$type {
203+
input: $input.into(),
203204
}
204205
};
205-
(fetcher => $fetcher:expr, error => $err:expr; $inner:expr) => {
206-
ParseError::Fetcher {
207-
input: $inner.into(),
208-
fetcher: $fetcher.into(),
209-
error: $err.into(),
210-
}
211-
};
212-
(package => $package:expr, error => $err:expr; $inner:expr) => {
213-
ParseError::Package {
214-
input: $inner.into(),
215-
package: $package.into(),
216-
error: $err.into(),
206+
($type:ident => $input:expr, $($key:ident: $value:expr),+) => {
207+
ParseError::$type {
208+
input: $input.into(),
209+
$($key: $value.into()),*,
217210
}
218211
};
219212
}
220213

214+
/// Convenience macro for early returns.
221215
macro_rules! bail {
222216
($($tt:tt)*) => {
223217
return Err(Error::from(fatal!($($tt)*)))
224218
};
225219
}
226220

227-
let Some((_, fetcher, package, revision)) = locator_regex!(parse => locator) else {
228-
bail!(syntax; locator);
221+
let Some((_, fetcher, package, revision)) = locator_regex!(parse => input) else {
222+
bail!(Syntax => input);
229223
};
230224

231225
if fetcher.is_empty() {
232-
bail!(field => "fetcher"; locator);
226+
bail!(Field => input, field: "fetcher");
233227
}
234-
let fetcher = Fetcher::try_from(fetcher)
235-
.map_err(|err| fatal!(fetcher => fetcher, error => err; locator))?;
236-
237228
if package.is_empty() {
238-
bail!(field => "package"; locator);
229+
bail!(Field => input, field: "package");
239230
}
240231

232+
let fetcher = Fetcher::try_from(fetcher)
233+
.map_err(|err| fatal!(Fetcher => input, fetcher: fetcher, error: err))?;
234+
241235
let revision = if revision.is_empty() {
242236
None
243237
} else {

src/locator_package.rs

+33-16
Original file line numberDiff line numberDiff line change
@@ -39,38 +39,55 @@ macro_rules! package {
3939
};
4040
}
4141

42-
/// A [`Locator`] specialized to not include the `revision` component.
42+
/// `PackageLocator` identifies a package in a code host.
4343
///
44-
/// Any [`Locator`] may be converted to a `PackageLocator` by simply discarding the `revision` component.
45-
/// To create a [`Locator`] from a `PackageLocator`, the value for `revision` must be provided; see [`Locator`] for details.
44+
/// "Package" locators are similar to standard locators, except that they
45+
/// _never specify_ the `revision` field. If the `revision` field
46+
/// is provided in the input string, `PackageLocator` ignores it.
47+
///
48+
/// ## Guarantees
49+
///
50+
/// This type represents a _validly-constructed_ `PackageLocator`, but does not
51+
/// guarantee whether a package actually exists or is accessible in the code host.
4652
///
4753
/// ## Ordering
4854
///
49-
/// Locators order by:
55+
/// `PackageLocator` orders by:
5056
/// 1. Fetcher, alphanumerically.
5157
/// 2. Organization ID, alphanumerically; missing organizations are sorted higher.
5258
/// 3. The package field, alphanumerically.
5359
///
54-
/// Importantly, there may be other metrics for ordering using the actual code host
55-
/// which contains the package (for example, ordering by release date).
56-
/// This library does not perform such ordering.
60+
/// **Important:** there may be other metrics for ordering using the actual code host
61+
/// which contains the package- for example ordering by release date.
62+
/// `PackageLocator` does not take such edge cases into account in any way.
5763
///
5864
/// ## Parsing
5965
///
60-
/// The input string must be in one of the following forms:
61-
/// - `{fetcher}+{package}`
62-
/// - `{fetcher}+{package}$`
63-
/// - `{fetcher}+{package}${revision}`
66+
/// This type is canonically rendered to a string before being serialized
67+
/// to the database or sent over the network according to the rules in this section.
68+
///
69+
/// The input string must be in one of the following formats:
70+
/// ```ignore
71+
/// {fetcher}+{package}${revision}
72+
/// {fetcher}+{package}
73+
/// ```
6474
///
6575
/// Packages may also be namespaced to a specific organization;
6676
/// in such cases the organization ID is at the start of the `{package}` field
6777
/// separated by a slash. The ID can be any non-negative integer.
68-
/// This yields the following formats:
69-
/// - `{fetcher}+{org_id}/{package}`
70-
/// - `{fetcher}+{org_id}/{package}$`
71-
/// - `{fetcher}+{org_id}/{package}${revision}`
78+
/// This yields the following optional formats:
79+
/// ```ignore
80+
/// {fetcher}+{org_id}/{package}${revision}
81+
/// {fetcher}+{org_id}/{package}
82+
/// ```
7283
///
73-
/// This implementation ignores the `revision` segment if it exists. If this is not preferred, use [`Locator`] instead.
84+
/// Note that locators do not feature escaping: instead the _first_ instance
85+
/// of each delimiter (`+`, `/`, `$`) is used to split the fields. However,
86+
/// as a special case organization IDs are only extracted if the field content
87+
/// fully consists of a non-negative integer.
88+
//
89+
// For more information on the background of `Locator` and fetchers generally,
90+
// FOSSA employees may refer to the "fetchers and locators" doc: https://go/fetchers-doc.
7491
#[derive(
7592
Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug, Builder, Getters, CopyGetters, Documented,
7693
)]

src/locator_strict.rs

+30-8
Original file line numberDiff line numberDiff line change
@@ -41,24 +41,38 @@ macro_rules! strict {
4141
};
4242
}
4343

44-
/// A [`Locator`] specialized to **require** the `revision` component.
44+
/// `StrictLocator` identifies a package at a specific revision in a code host.
45+
///
46+
/// "Strict" locators are similar to standard locators, except that they
47+
/// _require_ the `revision` field to be specified. If the `revision` field
48+
/// is not specified, `StrictLocator` fails to parse.
49+
///
50+
/// ## Guarantees
51+
///
52+
/// This type represents a _validly-constructed_ `StrictLocator`, but does not
53+
/// guarantee whether a package or revision actually exists or is accessible
54+
/// in the code host.
4555
///
4656
/// ## Ordering
4757
///
48-
/// Locators order by:
58+
/// `StrictLocator` orders by:
4959
/// 1. Fetcher, alphanumerically.
5060
/// 2. Organization ID, alphanumerically; missing organizations are sorted higher.
5161
/// 3. The package field, alphanumerically.
5262
/// 4. The revision field:
53-
/// If both comparing locators use semver, these are compared using semver rules;
54-
/// otherwise these are compared alphanumerically.
63+
/// - If both comparing locators use semver, these are compared using semver rules.
64+
/// - Otherwise these are compared alphanumerically.
5565
///
56-
/// Importantly, there may be other metrics for ordering using the actual code host
57-
/// which contains the package (for example, ordering by release date).
58-
/// This library does not perform such ordering.
66+
/// **Important:** there may be other metrics for ordering using the actual code host
67+
/// which contains the package- for example ordering by release date, or code hosts
68+
/// such as `git` which have non-linear history (making flat ordering a lossy operation).
69+
/// `StrictLocator` does not take such edge cases into account in any way.
5970
///
6071
/// ## Parsing
6172
///
73+
/// This type is canonically rendered to a string before being serialized
74+
/// to the database or sent over the network according to the rules in this section.
75+
///
6276
/// The input string must be in the following format:
6377
/// ```ignore
6478
/// {fetcher}+{package}${revision}
@@ -67,10 +81,18 @@ macro_rules! strict {
6781
/// Packages may also be namespaced to a specific organization;
6882
/// in such cases the organization ID is at the start of the `{package}` field
6983
/// separated by a slash. The ID can be any non-negative integer.
70-
/// This yields the following format:
84+
/// This yields the following optional format:
7185
/// ```ignore
7286
/// {fetcher}+{org_id}/{package}${revision}
7387
/// ```
88+
///
89+
/// Note that locators do not feature escaping: instead the _first_ instance
90+
/// of each delimiter (`+`, `/`, `$`) is used to split the fields. However,
91+
/// as a special case organization IDs are only extracted if the field content
92+
/// fully consists of a non-negative integer.
93+
//
94+
// For more information on the background of `Locator` and fetchers generally,
95+
// FOSSA employees may refer to the "fetchers and locators" doc: https://go/fetchers-doc.
7496
#[derive(
7597
Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug, Builder, Getters, CopyGetters, Documented,
7698
)]

0 commit comments

Comments
 (0)