Skip to content

Commit c798a3b

Browse files
author
RogueMacro
committed
Update command for dependencies
1 parent b4382ef commit c798a3b

File tree

6 files changed

+174
-59
lines changed

6 files changed

+174
-59
lines changed

src/commands/update.rs

Lines changed: 90 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
use std::path::Path;
22

3-
use crate::prelude::*;
3+
use crate::{
4+
index,
5+
lock::{self, Lock},
6+
prelude::*,
7+
};
8+
use console::style;
49

510
pub fn cli() -> App {
611
App::new("update")
@@ -18,10 +23,91 @@ pub fn exec(args: &ArgMatches) -> Result<()> {
1823
if args.is_present("grill") {
1924
todo!()
2025
} else if args.is_present("index") {
21-
crate::index::update(!args.is_present("quiet"), false)
26+
index::update(!args.is_present("quiet"), false)
2227
} else {
23-
crate::index::update(!args.is_present("quiet"), false)?;
24-
crate::lock::generate(Path::new("."), true)?;
28+
index::update(!args.is_present("quiet"), false)?;
29+
30+
let lock_path = Path::new(".").join(crate::paths::LOCK_FILENAME);
31+
let old_lock = if lock_path.exists() {
32+
Some(lock::read(lock_path)?)
33+
} else {
34+
None
35+
};
36+
37+
let lock = lock::generate(Path::new("."), true, false)?;
38+
39+
if !args.is_present("quiet") {
40+
if let Some(old_lock) = old_lock {
41+
print_altered_deps(&old_lock, &lock);
42+
} else {
43+
for (dep, versions) in lock {
44+
for version in versions {
45+
println!(
46+
"{:>12} {} v{}",
47+
style("Added").bright().cyan(),
48+
dep,
49+
version
50+
);
51+
}
52+
}
53+
}
54+
}
55+
2556
Ok(())
2657
}
2758
}
59+
60+
fn print_altered_deps(old_lock: &Lock, new_lock: &Lock) {
61+
for (dep, versions) in new_lock {
62+
for version in versions {
63+
if old_lock.get(dep).map_or(true, |old_versions| {
64+
!old_versions.iter().any(|v| v.major == version.major)
65+
}) {
66+
println!(
67+
"{:>12} {} v{}",
68+
style("Added").bright().cyan(),
69+
dep,
70+
version
71+
);
72+
}
73+
}
74+
}
75+
76+
for (dep, new_versions) in new_lock {
77+
for new_version in new_versions {
78+
if let Some(old_version) = old_lock.get(dep).and_then(|old_versions| {
79+
if let Some(old_version) = old_versions
80+
.iter()
81+
.find(|&v| v.major == new_version.major && v != new_version)
82+
{
83+
Some(old_version)
84+
} else {
85+
None
86+
}
87+
}) {
88+
println!(
89+
"{:>12} {} v{} -> v{}",
90+
style("Updated").bright().green(),
91+
dep,
92+
old_version,
93+
new_version
94+
);
95+
}
96+
}
97+
}
98+
99+
for (dep, versions) in old_lock {
100+
for version in versions {
101+
if !new_lock.get(dep).map_or(false, |new_versions| {
102+
new_versions.iter().any(|v| v.major == version.major)
103+
}) {
104+
println!(
105+
"{:>12} {} v{}",
106+
style("Removed").bright().red(),
107+
dep,
108+
version
109+
);
110+
}
111+
}
112+
}
113+
}

src/index.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ pub struct VersionMetadata {
2626
pub fn update(with_spinner: bool, clear_after: bool) -> Result<()> {
2727
log::trace!("Updating index");
2828

29-
rm_rf::ensure_removed(paths::tmp())?;
29+
rm_rf::ensure_removed(paths::tmp()).context("Failed to remove tmp folder")?;
3030

3131
let spinner = ProgressBar::new_spinner();
3232
if with_spinner {
@@ -37,8 +37,10 @@ pub fn update(with_spinner: bool, clear_after: bool) -> Result<()> {
3737
spinner.enable_steady_tick(Duration::from_millis(100));
3838
}
3939

40-
Repository::clone("https://github.com/RogueMacro/grill-index", paths::tmp())?;
41-
fs::copy(paths::tmp().join("index.toml"), paths::index())?;
40+
Repository::clone("https://github.com/RogueMacro/grill-index", paths::tmp())
41+
.context("Failed to clone repository")?;
42+
fs::copy(paths::tmp().join("index.toml"), paths::index())
43+
.context("Failed to move index file")?;
4244

4345
if with_spinner {
4446
if clear_after {

src/lock.rs

Lines changed: 50 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,39 @@ use std::{
44
path::Path,
55
};
66

7-
use anyhow::Result;
7+
use anyhow::{Context, Result};
88
use semver::Version;
99

1010
use crate::{manifest::Manifest, resolver::resolve};
1111

1212
pub type Lock = HashMap<String, HashSet<Version>>;
1313

14+
pub fn read<P>(path: P) -> Result<Lock>
15+
where
16+
P: AsRef<Path>,
17+
{
18+
Ok(
19+
toml::from_str(&fs::read_to_string(path.as_ref()).with_context(|| {
20+
format!(
21+
"Failed to read lock file: {}",
22+
path.as_ref().to_string_lossy()
23+
)
24+
})?)
25+
.context("Failed to deserialize lock file")?,
26+
)
27+
}
28+
29+
pub fn write<P>(path: P, lock: &Lock) -> Result<()>
30+
where
31+
P: AsRef<Path>,
32+
{
33+
Ok(fs::write(
34+
path,
35+
toml::to_string(lock).context("Failed to serialize lock")?,
36+
)
37+
.context("Failed to write lock file")?)
38+
}
39+
1440
pub fn validate(pkg_path: &Path) -> Result<bool> {
1541
let manifest = Manifest::from_pkg(pkg_path)?;
1642

@@ -19,44 +45,48 @@ pub fn validate(pkg_path: &Path) -> Result<bool> {
1945
return Ok(false);
2046
}
2147

22-
let lock: Lock = toml::from_str(&fs::read_to_string(file_path)?)?;
48+
let lock: Lock = self::read(file_path)?;
2349
Ok(validate_lock(&manifest, &lock))
2450
}
2551

26-
fn validate_lock<'a>(manifest: &Manifest, lock: &Lock) -> bool {
52+
fn validate_lock(manifest: &Manifest, lock: &Lock) -> bool {
2753
log::trace!("Validating lock");
2854

29-
if manifest.dependencies.len() != lock.len() {
30-
log::trace!("Length doesn't match");
31-
return false;
32-
}
33-
3455
for (dep, req) in manifest.simple_deps() {
3556
if !lock.get(dep).map_or(false, |locked_versions| {
3657
locked_versions.iter().any(|v| req.matches(v))
3758
}) {
38-
log::trace!("No match for {} {} in lock", dep, req);
59+
log::trace!("Invalid lock: No match for {} {}", dep, req);
3960
return false;
4061
}
4162
}
4263

43-
for (_, versions) in lock {
44-
for v in versions.iter() {
45-
if versions.iter().any(|v2| v.major == v2.major) {
46-
return false;
64+
for (dep, versions) in lock {
65+
for v1 in versions.iter() {
66+
for v2 in versions.iter() {
67+
if v1.major == v2.major && v1 != v2 {
68+
log::trace!(
69+
"Invalid lock: {} v{} is incompatible with {} v{}",
70+
dep,
71+
v1,
72+
dep,
73+
v2
74+
);
75+
return false;
76+
}
4777
}
4878
}
4979
}
5080

5181
true
5282
}
5383

54-
pub fn generate(pkg_path: &Path, write_lock: bool) -> Result<Lock> {
55-
let manifest = Manifest::from_pkg(pkg_path)?;
84+
pub fn generate(pkg_path: &Path, write_lock: bool, try_keep_lock: bool) -> Result<Lock> {
85+
let manifest = Manifest::from_pkg(pkg_path).context("Failed to read manifest")?;
5686

5787
let lock_path = pkg_path.join(crate::paths::LOCK_FILENAME);
58-
let previous_lock = if lock_path.exists() {
59-
let lock = toml::from_str(&fs::read_to_string(lock_path)?)?;
88+
let previous_lock = if try_keep_lock && lock_path.exists() {
89+
let lock = self::read(lock_path)?;
6090
if validate_lock(&manifest, &lock) {
6191
Some(lock)
6292
} else {
@@ -68,12 +98,11 @@ pub fn generate(pkg_path: &Path, write_lock: bool) -> Result<Lock> {
6898

6999
let index = crate::index::parse(false, false)?;
70100

71-
let resolved = resolve(&manifest, previous_lock.as_ref(), &index)?;
101+
let lock = resolve(&manifest, previous_lock.as_ref(), &index)?;
72102

73103
if write_lock {
74-
let lock_file = toml::to_string(&resolved)?;
75-
fs::write(pkg_path.join(crate::paths::LOCK_FILENAME), lock_file)?;
104+
self::write(pkg_path.join(crate::paths::LOCK_FILENAME), &lock)?;
76105
}
77106

78-
Ok(resolved)
107+
Ok(lock)
79108
}

src/main.rs

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -41,11 +41,15 @@ fn main() -> Result<()> {
4141

4242
if let Err(err) = result {
4343
println!();
44-
if let Some(source) = err.source() {
45-
log::error!("{}\n\nCaused by:\n {}", err, source);
46-
} else {
47-
log::error!("{}", err);
48-
}
44+
45+
// if let Some(source) = err.source() {
46+
// log::error!("{}\n\nCaused by:\n {}", err, source);
47+
// } else {
48+
// log::error!("{}", err);
49+
// }
50+
51+
log::error!("{}\n\nCaused by:\n {}", err, err.root_cause());
52+
4953
println!();
5054
}
5155

src/ops/make.rs

Lines changed: 3 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,10 @@ use std::{
55
time::Duration,
66
};
77

8-
use anyhow::Context;
98
use console::Emoji;
109
use indicatif::{MultiProgress, ProgressBar, ProgressStyle};
1110

12-
use crate::{
13-
beef,
14-
index::{self},
15-
lock::{self, Lock},
16-
manifest::Manifest,
17-
prelude::*,
18-
};
11+
use crate::{beef, index, lock, manifest::Manifest, prelude::*};
1912

2013
const COMPASS: Emoji = Emoji("🧭 ", "");
2114
const LOOKING_GLASS: Emoji = Emoji("🔍 ", "");
@@ -61,12 +54,9 @@ pub fn make(path: &Path, silent: bool) -> Result<()> {
6154
silent,
6255
|_, _| {
6356
if !lock::validate(&path)? {
64-
lock::generate(&path, false)
57+
lock::generate(&path, false, true)
6558
} else {
66-
let lock: Lock =
67-
toml::from_str(&fs::read_to_string(path.join(crate::paths::LOCK_FILENAME))?)
68-
.context("Invalid lock")?;
69-
Ok(lock)
59+
lock::read(path.join(crate::paths::LOCK_FILENAME))
7060
}
7161
},
7262
)?;

src/resolver.rs

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,10 @@ use crate::{
1010
manifest::{self, Manifest},
1111
};
1212

13-
pub fn resolve(manifest: &Manifest, previous_lock: Option<&Lock>, index: &Index) -> Result<Lock> {
13+
pub fn resolve(manifest: &Manifest, lock: Option<&Lock>, index: &Index) -> Result<Lock> {
1414
log::trace!(
1515
"Resolving dependency tree{}",
16-
if previous_lock.is_some() {
17-
" with previous lock"
18-
} else {
19-
""
20-
}
16+
if lock.is_some() { " with lock" } else { "" }
2117
);
2218

2319
// Add the root dependencies.
@@ -26,7 +22,7 @@ pub fn resolve(manifest: &Manifest, previous_lock: Option<&Lock>, index: &Index)
2622
.iter()
2723
.filter_map(|(name, dep)| {
2824
if let manifest::Dependency::Simple(req) = dep {
29-
Some(Candidate::new(name, req, index))
25+
Some(Candidate::new(name, req, index, lock))
3026
} else {
3127
None
3228
}
@@ -85,7 +81,7 @@ pub fn resolve(manifest: &Manifest, previous_lock: Option<&Lock>, index: &Index)
8581

8682
candidates.extend(
8783
deps.iter()
88-
.map(|(dep, req)| Candidate::new(dep, req, index)),
84+
.map(|(dep, req)| Candidate::new(dep, req, index, lock)),
8985
);
9086

9187
// "Commit" this candidate to the list of candidates.
@@ -111,7 +107,7 @@ pub fn resolve(manifest: &Manifest, previous_lock: Option<&Lock>, index: &Index)
111107
// unset the version and make sure it is ready for
112108
// picking another version.
113109
candidates[i].version = None;
114-
candidates[i].update_available_versions(index);
110+
candidates[i].update_available_versions(index, lock);
115111
}
116112

117113
i -= 1;
@@ -162,7 +158,7 @@ pub fn resolve(manifest: &Manifest, previous_lock: Option<&Lock>, index: &Index)
162158
candidates.extend(
163159
missing_dependencies
164160
.iter()
165-
.map(|(dep, req)| Candidate::new(dep, req, index)),
161+
.map(|(dep, req)| Candidate::new(dep, req, index, lock)),
166162
);
167163
}
168164
}
@@ -192,18 +188,18 @@ struct Candidate {
192188
}
193189

194190
impl Candidate {
195-
pub fn new(name: &str, req: &VersionReq, index: &Index) -> Self {
191+
pub fn new(name: &str, req: &VersionReq, index: &Index, lock: Option<&Lock>) -> Self {
196192
let mut candidate = Self {
197193
name: name.to_owned(),
198194
req: req.clone(),
199195
version: None,
200196
available_versions: Vec::new(),
201197
};
202-
candidate.update_available_versions(index);
198+
candidate.update_available_versions(index, lock);
203199
candidate
204200
}
205201

206-
pub fn update_available_versions(&mut self, index: &Index) {
202+
pub fn update_available_versions(&mut self, index: &Index, lock: Option<&Lock>) {
207203
self.available_versions.clear();
208204
if let Some(entry) = index.get(&self.name) {
209205
self.available_versions.extend(
@@ -215,6 +211,14 @@ impl Candidate {
215211
.sorted_unstable_by(|v1, v2| v1.cmp(&v2)),
216212
);
217213
}
214+
215+
if let Some(version) = lock
216+
.and_then(|lock| lock.get(&self.name))
217+
.and_then(|locked_versions| locked_versions.iter().find(|&v| self.req.matches(v)))
218+
{
219+
// Push the locked version to the top so it gets tried first.
220+
self.available_versions.push(version.clone());
221+
}
218222
}
219223
}
220224

0 commit comments

Comments
 (0)