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
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
use cargo::core::{Dependency, InternedString, Source, SourceId};
use cargo::sources::RegistrySource;
use cargo::util::Config;
use log_derive::{logfn, logfn_inputs};
use serde::{Deserialize, Serialize};
use std::collections::HashSet;
use std::fs::File;
use std::time::SystemTime;
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct Package {
name: String,
version: String,
}
#[derive(Debug, Deserialize, Serialize)]
pub enum Crate {
Package(Package),
}
impl Crate {
pub fn name(&self) -> &str {
match self {
Crate::Package(Package { ref name, .. }) => name,
}
}
pub fn version(&self) -> &str {
match self {
Crate::Package(Package { ref version, .. }) => version,
}
}
}
#[derive(Debug, Deserialize, Serialize)]
pub struct CratesList {
creation_date: SystemTime,
crates: Vec<Crate>,
}
impl CratesList {
#[logfn(Trace)]
pub fn top_crates_by_download_count(count: usize, all_versions: bool) -> Self {
let config = Config::default().expect("Unable to create default Cargo config");
let _lock = config.acquire_package_cache_lock();
let crates_io = SourceId::crates_io(&config).expect("Unable to create crates.io source ID");
let mut source = RegistrySource::remote(crates_io, &HashSet::new(), &config);
source.update().expect("Unable to update registry");
let creation_date = SystemTime::now();
let mut crates = Vec::new();
for crate_name in super::top_crates::top_crates_by_download_count(count) {
let query = Dependency::new_override(InternedString::new(&crate_name), crates_io);
let summaries = source.query_vec(&query).unwrap_or_else(|err| {
panic!("Querying for {} failed: {}", crate_name, err);
});
if all_versions {
for summary in summaries {
let package = Package {
name: crate_name.clone(),
version: summary.version().to_string(),
};
crates.push(Crate::Package(package));
}
} else {
let maybe_summary = summaries
.into_iter()
.max_by_key(|summary| summary.version().clone());
if let Some(summary) = maybe_summary {
let package = Package {
name: crate_name.clone(),
version: summary.version().to_string(),
};
crates.push(Crate::Package(package));
}
}
}
Self {
creation_date: creation_date,
crates: crates,
}
}
#[logfn_inputs(Trace)]
pub fn all_crates(all_versions: bool) -> Self {
let creation_date = SystemTime::now();
let index = crates_index::Index::new_cargo_default();
index
.retrieve_or_update()
.expect("Unable to update registry");
let mut crates = Vec::new();
for krate in index.crates() {
if all_versions {
for version in krate.versions() {
let package = Package {
name: version.name().to_string(),
version: version.version().to_string(),
};
crates.push(Crate::Package(package));
}
} else {
let version = krate.latest_version();
let package = Package {
name: version.name().to_string(),
version: version.version().to_string(),
};
crates.push(Crate::Package(package));
}
}
Self {
creation_date: creation_date,
crates: crates,
}
}
#[logfn_inputs(Trace)]
pub fn save(&self, path: &std::path::Path) {
let mut file =
File::create(path).unwrap_or_else(|e| panic!("Unable to create {:?}: {}", path, e));
serde_json::to_writer_pretty(&mut file, self)
.unwrap_or_else(|e| panic!("Unable to write {:?}: {}", path, e));
}
pub fn load(path: &std::path::Path) -> Self {
let file =
File::open(path).unwrap_or_else(|e| panic!("Failed to load from {:?}: {}", path, e));
serde_json::from_reader(file).unwrap_or_else(|e| panic!("Invalid JSON {:?}: {}", path, e))
}
pub fn iter<'a>(&'a self) -> impl Iterator<Item = &'a Crate> {
self.crates.iter()
}
}