Remove "I AM NOT DONE" and the verify mode and add AppState

This commit is contained in:
mo8it 2024-04-11 02:51:02 +02:00
parent 4bb6bda9f6
commit fa1f239a70
113 changed files with 306 additions and 769 deletions

1
Cargo.lock generated
View file

@ -699,7 +699,6 @@ dependencies = [
"serde_json",
"toml_edit",
"which",
"winnow",
]
[[package]]

View file

@ -44,7 +44,6 @@ serde_json = "1.0.115"
serde.workspace = true
toml_edit.workspace = true
which = "6.0.1"
winnow = "0.6.5"
[dev-dependencies]
assert_cmd = "2.0.14"

View file

@ -101,13 +101,7 @@ The task is simple. Most exercises contain an error that keeps them from compili
rustlings watch
```
This will try to verify the completion of every exercise in a predetermined order (what we think is best for newcomers). It will also rerun automatically every time you change a file in the `exercises/` directory. If you want to only run it once, you can use:
```bash
rustlings verify
```
This will do the same as watch, but it'll quit after running.
This will try to verify the completion of every exercise in a predetermined order (what we think is best for newcomers). It will also rerun automatically every time you change a file in the `exercises/` directory.
In case you want to go by your own order, or want to only verify a single exercise, you can run:

View file

@ -1,6 +1,6 @@
// intro1.rs
//
// About this `I AM NOT DONE` thing:
// TODO: Update comment
// We sometimes encourage you to keep trying things on a given exercise, even
// after you already figured it out. If you got everything working and feel
// ready for the next exercise, remove the `I AM NOT DONE` comment below.
@ -13,8 +13,6 @@
// Execute `rustlings hint intro1` or use the `hint` watch subcommand for a
// hint.
// I AM NOT DONE
fn main() {
println!("Hello and");
println!(r#" welcome to... "#);

View file

@ -5,8 +5,6 @@
// Execute `rustlings hint intro2` or use the `hint` watch subcommand for a
// hint.
// I AM NOT DONE
fn main() {
printline!("Hello there!")
}

View file

@ -5,8 +5,6 @@
// Execute `rustlings hint variables1` or use the `hint` watch subcommand for a
// hint.
// I AM NOT DONE
fn main() {
x = 5;
println!("x has the value {}", x);

View file

@ -3,8 +3,6 @@
// Execute `rustlings hint variables2` or use the `hint` watch subcommand for a
// hint.
// I AM NOT DONE
fn main() {
let x;
if x == 10 {

View file

@ -3,8 +3,6 @@
// Execute `rustlings hint variables3` or use the `hint` watch subcommand for a
// hint.
// I AM NOT DONE
fn main() {
let x: i32;
println!("Number {}", x);

View file

@ -3,8 +3,6 @@
// Execute `rustlings hint variables4` or use the `hint` watch subcommand for a
// hint.
// I AM NOT DONE
fn main() {
let x = 3;
println!("Number {}", x);

View file

@ -3,8 +3,6 @@
// Execute `rustlings hint variables5` or use the `hint` watch subcommand for a
// hint.
// I AM NOT DONE
fn main() {
let number = "T-H-R-E-E"; // don't change this line
println!("Spell a Number : {}", number);

View file

@ -3,8 +3,6 @@
// Execute `rustlings hint variables6` or use the `hint` watch subcommand for a
// hint.
// I AM NOT DONE
const NUMBER = 3;
fn main() {
println!("Number {}", NUMBER);

View file

@ -3,8 +3,6 @@
// Execute `rustlings hint functions1` or use the `hint` watch subcommand for a
// hint.
// I AM NOT DONE
fn main() {
call_me();
}

View file

@ -3,8 +3,6 @@
// Execute `rustlings hint functions2` or use the `hint` watch subcommand for a
// hint.
// I AM NOT DONE
fn main() {
call_me(3);
}

View file

@ -3,8 +3,6 @@
// Execute `rustlings hint functions3` or use the `hint` watch subcommand for a
// hint.
// I AM NOT DONE
fn main() {
call_me();
}

View file

@ -8,8 +8,6 @@
// Execute `rustlings hint functions4` or use the `hint` watch subcommand for a
// hint.
// I AM NOT DONE
fn main() {
let original_price = 51;
println!("Your sale price is {}", sale_price(original_price));

View file

@ -3,8 +3,6 @@
// Execute `rustlings hint functions5` or use the `hint` watch subcommand for a
// hint.
// I AM NOT DONE
fn main() {
let answer = square(3);
println!("The square of 3 is {}", answer);

View file

@ -2,8 +2,6 @@
//
// Execute `rustlings hint if1` or use the `hint` watch subcommand for a hint.
// I AM NOT DONE
pub fn bigger(a: i32, b: i32) -> i32 {
// Complete this function to return the bigger number!
// If both numbers are equal, any of them can be returned.

View file

@ -5,8 +5,6 @@
//
// Execute `rustlings hint if2` or use the `hint` watch subcommand for a hint.
// I AM NOT DONE
pub fn foo_if_fizz(fizzish: &str) -> &str {
if fizzish == "fizz" {
"foo"

View file

@ -2,8 +2,6 @@
//
// Execute `rustlings hint if3` or use the `hint` watch subcommand for a hint.
// I AM NOT DONE
pub fn animal_habitat(animal: &str) -> &'static str {
let identifier = if animal == "crab" {
1

View file

@ -3,8 +3,6 @@
// Fill in the rest of the line that has code missing! No hints, there's no
// tricks, just get used to typing these :)
// I AM NOT DONE
fn main() {
// Booleans (`bool`)

View file

@ -3,8 +3,6 @@
// Fill in the rest of the line that has code missing! No hints, there's no
// tricks, just get used to typing these :)
// I AM NOT DONE
fn main() {
// Characters (`char`)

View file

@ -5,8 +5,6 @@
// Execute `rustlings hint primitive_types3` or use the `hint` watch subcommand
// for a hint.
// I AM NOT DONE
fn main() {
let a = ???

View file

@ -5,8 +5,6 @@
// Execute `rustlings hint primitive_types4` or use the `hint` watch subcommand
// for a hint.
// I AM NOT DONE
#[test]
fn slice_out_of_array() {
let a = [1, 2, 3, 4, 5];

View file

@ -5,8 +5,6 @@
// Execute `rustlings hint primitive_types5` or use the `hint` watch subcommand
// for a hint.
// I AM NOT DONE
fn main() {
let cat = ("Furry McFurson", 3.5);
let /* your pattern here */ = cat;

View file

@ -6,8 +6,6 @@
// Execute `rustlings hint primitive_types6` or use the `hint` watch subcommand
// for a hint.
// I AM NOT DONE
#[test]
fn indexing_tuple() {
let numbers = (1, 2, 3);

View file

@ -7,8 +7,6 @@
//
// Execute `rustlings hint vecs1` or use the `hint` watch subcommand for a hint.
// I AM NOT DONE
fn array_and_vec() -> ([i32; 4], Vec<i32>) {
let a = [10, 20, 30, 40]; // a plain array
let v = // TODO: declare your vector here with the macro for vectors

View file

@ -7,8 +7,6 @@
//
// Execute `rustlings hint vecs2` or use the `hint` watch subcommand for a hint.
// I AM NOT DONE
fn vec_loop(mut v: Vec<i32>) -> Vec<i32> {
for element in v.iter_mut() {
// TODO: Fill this up so that each element in the Vec `v` is

View file

@ -3,8 +3,6 @@
// Execute `rustlings hint move_semantics1` or use the `hint` watch subcommand
// for a hint.
// I AM NOT DONE
#[test]
fn main() {
let vec0 = vec![22, 44, 66];

View file

@ -5,8 +5,6 @@
// Execute `rustlings hint move_semantics2` or use the `hint` watch subcommand
// for a hint.
// I AM NOT DONE
#[test]
fn main() {
let vec0 = vec![22, 44, 66];

View file

@ -6,8 +6,6 @@
// Execute `rustlings hint move_semantics3` or use the `hint` watch subcommand
// for a hint.
// I AM NOT DONE
#[test]
fn main() {
let vec0 = vec![22, 44, 66];

View file

@ -7,8 +7,6 @@
// Execute `rustlings hint move_semantics4` or use the `hint` watch subcommand
// for a hint.
// I AM NOT DONE
#[test]
fn main() {
let vec0 = vec![22, 44, 66];

View file

@ -6,8 +6,6 @@
// Execute `rustlings hint move_semantics5` or use the `hint` watch subcommand
// for a hint.
// I AM NOT DONE
#[test]
fn main() {
let mut x = 100;

View file

@ -5,8 +5,6 @@
// Execute `rustlings hint move_semantics6` or use the `hint` watch subcommand
// for a hint.
// I AM NOT DONE
fn main() {
let data = "Rust is great!".to_string();

View file

@ -5,8 +5,6 @@
// Execute `rustlings hint structs1` or use the `hint` watch subcommand for a
// hint.
// I AM NOT DONE
struct ColorClassicStruct {
// TODO: Something goes here
}

View file

@ -5,8 +5,6 @@
// Execute `rustlings hint structs2` or use the `hint` watch subcommand for a
// hint.
// I AM NOT DONE
#[derive(Debug)]
struct Order {
name: String,

View file

@ -7,8 +7,6 @@
// Execute `rustlings hint structs3` or use the `hint` watch subcommand for a
// hint.
// I AM NOT DONE
#[derive(Debug)]
struct Package {
sender_country: String,

View file

@ -2,8 +2,6 @@
//
// No hints this time! ;)
// I AM NOT DONE
#[derive(Debug)]
enum Message {
// TODO: define a few types of messages as used below

View file

@ -3,8 +3,6 @@
// Execute `rustlings hint enums2` or use the `hint` watch subcommand for a
// hint.
// I AM NOT DONE
#[derive(Debug)]
enum Message {
// TODO: define the different variants used below

View file

@ -5,8 +5,6 @@
// Execute `rustlings hint enums3` or use the `hint` watch subcommand for a
// hint.
// I AM NOT DONE
enum Message {
// TODO: implement the message variant types based on their usage below
}

View file

@ -5,8 +5,6 @@
// Execute `rustlings hint strings1` or use the `hint` watch subcommand for a
// hint.
// I AM NOT DONE
fn main() {
let answer = current_favorite_color();
println!("My current favorite color is {}", answer);

View file

@ -5,8 +5,6 @@
// Execute `rustlings hint strings2` or use the `hint` watch subcommand for a
// hint.
// I AM NOT DONE
fn main() {
let word = String::from("green"); // Try not changing this line :)
if is_a_color_word(word) {

View file

@ -3,8 +3,6 @@
// Execute `rustlings hint strings3` or use the `hint` watch subcommand for a
// hint.
// I AM NOT DONE
fn trim_me(input: &str) -> String {
// TODO: Remove whitespace from both ends of a string!
???

View file

@ -7,8 +7,6 @@
//
// No hints this time!
// I AM NOT DONE
fn string_slice(arg: &str) {
println!("{}", arg);
}

View file

@ -3,8 +3,6 @@
// Execute `rustlings hint modules1` or use the `hint` watch subcommand for a
// hint.
// I AM NOT DONE
mod sausage_factory {
// Don't let anybody outside of this module see this!
fn get_secret_recipe() -> String {

View file

@ -7,8 +7,6 @@
// Execute `rustlings hint modules2` or use the `hint` watch subcommand for a
// hint.
// I AM NOT DONE
mod delicious_snacks {
// TODO: Fix these use statements
use self::fruits::PEAR as ???

View file

@ -8,8 +8,6 @@
// Execute `rustlings hint modules3` or use the `hint` watch subcommand for a
// hint.
// I AM NOT DONE
// TODO: Complete this use statement
use ???

View file

@ -11,8 +11,6 @@
// Execute `rustlings hint hashmaps1` or use the `hint` watch subcommand for a
// hint.
// I AM NOT DONE
use std::collections::HashMap;
fn fruit_basket() -> HashMap<String, u32> {

View file

@ -14,8 +14,6 @@
// Execute `rustlings hint hashmaps2` or use the `hint` watch subcommand for a
// hint.
// I AM NOT DONE
use std::collections::HashMap;
#[derive(Hash, PartialEq, Eq)]

View file

@ -15,8 +15,6 @@
// Execute `rustlings hint hashmaps3` or use the `hint` watch subcommand for a
// hint.
// I AM NOT DONE
use std::collections::HashMap;
// A structure to store the goal details of a team.

View file

@ -3,8 +3,6 @@
// Execute `rustlings hint options1` or use the `hint` watch subcommand for a
// hint.
// I AM NOT DONE
// This function returns how much icecream there is left in the fridge.
// If it's before 10PM, there's 5 scoops left. At 10PM, someone eats it
// all, so there'll be no more left :(

View file

@ -3,8 +3,6 @@
// Execute `rustlings hint options2` or use the `hint` watch subcommand for a
// hint.
// I AM NOT DONE
#[cfg(test)]
mod tests {
#[test]

View file

@ -3,8 +3,6 @@
// Execute `rustlings hint options3` or use the `hint` watch subcommand for a
// hint.
// I AM NOT DONE
struct Point {
x: i32,
y: i32,

View file

@ -9,8 +9,6 @@
// Execute `rustlings hint errors1` or use the `hint` watch subcommand for a
// hint.
// I AM NOT DONE
pub fn generate_nametag_text(name: String) -> Option<String> {
if name.is_empty() {
// Empty names aren't allowed.

View file

@ -19,8 +19,6 @@
// Execute `rustlings hint errors2` or use the `hint` watch subcommand for a
// hint.
// I AM NOT DONE
use std::num::ParseIntError;
pub fn total_cost(item_quantity: &str) -> Result<i32, ParseIntError> {

View file

@ -7,8 +7,6 @@
// Execute `rustlings hint errors3` or use the `hint` watch subcommand for a
// hint.
// I AM NOT DONE
use std::num::ParseIntError;
fn main() {

View file

@ -3,8 +3,6 @@
// Execute `rustlings hint errors4` or use the `hint` watch subcommand for a
// hint.
// I AM NOT DONE
#[derive(PartialEq, Debug)]
struct PositiveNonzeroInteger(u64);

View file

@ -22,8 +22,6 @@
// Execute `rustlings hint errors5` or use the `hint` watch subcommand for a
// hint.
// I AM NOT DONE
use std::error;
use std::fmt;
use std::num::ParseIntError;

View file

@ -9,8 +9,6 @@
// Execute `rustlings hint errors6` or use the `hint` watch subcommand for a
// hint.
// I AM NOT DONE
use std::num::ParseIntError;
// This is a custom error type that we will be using in `parse_pos_nonzero()`.

View file

@ -6,8 +6,6 @@
// Execute `rustlings hint generics1` or use the `hint` watch subcommand for a
// hint.
// I AM NOT DONE
fn main() {
let mut shopping_list: Vec<?> = Vec::new();
shopping_list.push("milk");

View file

@ -6,8 +6,6 @@
// Execute `rustlings hint generics2` or use the `hint` watch subcommand for a
// hint.
// I AM NOT DONE
struct Wrapper {
value: u32,
}

View file

@ -7,8 +7,6 @@
// Execute `rustlings hint traits1` or use the `hint` watch subcommand for a
// hint.
// I AM NOT DONE
trait AppendBar {
fn append_bar(self) -> Self;
}

View file

@ -8,8 +8,6 @@
//
// Execute `rustlings hint traits2` or use the `hint` watch subcommand for a hint.
// I AM NOT DONE
trait AppendBar {
fn append_bar(self) -> Self;
}

View file

@ -8,8 +8,6 @@
// Execute `rustlings hint traits3` or use the `hint` watch subcommand for a
// hint.
// I AM NOT DONE
pub trait Licensed {
fn licensing_info(&self) -> String;
}

View file

@ -7,8 +7,6 @@
// Execute `rustlings hint traits4` or use the `hint` watch subcommand for a
// hint.
// I AM NOT DONE
pub trait Licensed {
fn licensing_info(&self) -> String {
"some information".to_string()

View file

@ -7,8 +7,6 @@
// Execute `rustlings hint traits5` or use the `hint` watch subcommand for a
// hint.
// I AM NOT DONE
pub trait SomeTrait {
fn some_function(&self) -> bool {
true

View file

@ -8,8 +8,6 @@
// Execute `rustlings hint lifetimes1` or use the `hint` watch subcommand for a
// hint.
// I AM NOT DONE
fn longest(x: &str, y: &str) -> &str {
if x.len() > y.len() {
x

View file

@ -6,8 +6,6 @@
// Execute `rustlings hint lifetimes2` or use the `hint` watch subcommand for a
// hint.
// I AM NOT DONE
fn longest<'a>(x: &'a str, y: &'a str) -> &'a str {
if x.len() > y.len() {
x

View file

@ -5,8 +5,6 @@
// Execute `rustlings hint lifetimes3` or use the `hint` watch subcommand for a
// hint.
// I AM NOT DONE
struct Book {
author: &str,
title: &str,

View file

@ -10,8 +10,6 @@
// Execute `rustlings hint tests1` or use the `hint` watch subcommand for a
// hint.
// I AM NOT DONE
#[cfg(test)]
mod tests {
#[test]

View file

@ -6,8 +6,6 @@
// Execute `rustlings hint tests2` or use the `hint` watch subcommand for a
// hint.
// I AM NOT DONE
#[cfg(test)]
mod tests {
#[test]

View file

@ -7,8 +7,6 @@
// Execute `rustlings hint tests3` or use the `hint` watch subcommand for a
// hint.
// I AM NOT DONE
pub fn is_even(num: i32) -> bool {
num % 2 == 0
}

View file

@ -5,8 +5,6 @@
// Execute `rustlings hint tests4` or use the `hint` watch subcommand for a
// hint.
// I AM NOT DONE
struct Rectangle {
width: i32,
height: i32

View file

@ -9,8 +9,6 @@
// Execute `rustlings hint iterators1` or use the `hint` watch subcommand for a
// hint.
// I AM NOT DONE
#[test]
fn main() {
let my_fav_fruits = vec!["banana", "custard apple", "avocado", "peach", "raspberry"];

View file

@ -6,8 +6,6 @@
// Execute `rustlings hint iterators2` or use the `hint` watch subcommand for a
// hint.
// I AM NOT DONE
// Step 1.
// Complete the `capitalize_first` function.
// "hello" -> "Hello"

View file

@ -9,8 +9,6 @@
// Execute `rustlings hint iterators3` or use the `hint` watch subcommand for a
// hint.
// I AM NOT DONE
#[derive(Debug, PartialEq, Eq)]
pub enum DivisionError {
NotDivisible(NotDivisibleError),

View file

@ -3,8 +3,6 @@
// Execute `rustlings hint iterators4` or use the `hint` watch subcommand for a
// hint.
// I AM NOT DONE
pub fn factorial(num: u64) -> u64 {
// Complete this function to return the factorial of num
// Do not use:

View file

@ -11,8 +11,6 @@
// Execute `rustlings hint iterators5` or use the `hint` watch subcommand for a
// hint.
// I AM NOT DONE
use std::collections::HashMap;
#[derive(Clone, Copy, PartialEq, Eq)]

View file

@ -21,8 +21,6 @@
//
// Execute `rustlings hint arc1` or use the `hint` watch subcommand for a hint.
// I AM NOT DONE
#![forbid(unused_imports)] // Do not change this, (or the next) line.
use std::sync::Arc;
use std::thread;

View file

@ -18,8 +18,6 @@
//
// Execute `rustlings hint box1` or use the `hint` watch subcommand for a hint.
// I AM NOT DONE
#[derive(PartialEq, Debug)]
pub enum List {
Cons(i32, List),

View file

@ -12,8 +12,6 @@
//
// Execute `rustlings hint cow1` or use the `hint` watch subcommand for a hint.
// I AM NOT DONE
use std::borrow::Cow;
fn abs_all<'a, 'b>(input: &'a mut Cow<'b, [i32]>) -> &'a mut Cow<'b, [i32]> {

View file

@ -10,8 +10,6 @@
//
// Execute `rustlings hint rc1` or use the `hint` watch subcommand for a hint.
// I AM NOT DONE
use std::rc::Rc;
#[derive(Debug)]

View file

@ -8,8 +8,6 @@
// Execute `rustlings hint threads1` or use the `hint` watch subcommand for a
// hint.
// I AM NOT DONE
use std::thread;
use std::time::{Duration, Instant};

View file

@ -7,8 +7,6 @@
// Execute `rustlings hint threads2` or use the `hint` watch subcommand for a
// hint.
// I AM NOT DONE
use std::sync::Arc;
use std::thread;
use std::time::Duration;

View file

@ -3,8 +3,6 @@
// Execute `rustlings hint threads3` or use the `hint` watch subcommand for a
// hint.
// I AM NOT DONE
use std::sync::mpsc;
use std::sync::Arc;
use std::thread;

View file

@ -3,8 +3,6 @@
// Execute `rustlings hint macros1` or use the `hint` watch subcommand for a
// hint.
// I AM NOT DONE
macro_rules! my_macro {
() => {
println!("Check out my macro!");

View file

@ -3,8 +3,6 @@
// Execute `rustlings hint macros2` or use the `hint` watch subcommand for a
// hint.
// I AM NOT DONE
fn main() {
my_macro!();
}

View file

@ -5,8 +5,6 @@
// Execute `rustlings hint macros3` or use the `hint` watch subcommand for a
// hint.
// I AM NOT DONE
mod macros {
macro_rules! my_macro {
() => {

View file

@ -3,8 +3,6 @@
// Execute `rustlings hint macros4` or use the `hint` watch subcommand for a
// hint.
// I AM NOT DONE
#[rustfmt::skip]
macro_rules! my_macro {
() => {

View file

@ -9,8 +9,6 @@
// Execute `rustlings hint clippy1` or use the `hint` watch subcommand for a
// hint.
// I AM NOT DONE
use std::f32;
fn main() {

View file

@ -3,8 +3,6 @@
// Execute `rustlings hint clippy2` or use the `hint` watch subcommand for a
// hint.
// I AM NOT DONE
fn main() {
let mut res = 42;
let option = Some(12);

View file

@ -3,8 +3,6 @@
// Here's a couple more easy Clippy fixes, so you can see its utility.
// No hints.
// I AM NOT DONE
#[allow(unused_variables, unused_assignments)]
fn main() {
let my_option: Option<()> = None;

View file

@ -7,8 +7,6 @@
// Execute `rustlings hint as_ref_mut` or use the `hint` watch subcommand for a
// hint.
// I AM NOT DONE
// Obtain the number of bytes (not characters) in the given argument.
// TODO: Add the AsRef trait appropriately as a trait bound.
fn byte_counter<T>(arg: T) -> usize {

View file

@ -41,8 +41,6 @@ impl Default for Person {
// If while parsing the age, something goes wrong, then return the default of
// Person Otherwise, then return an instantiated Person object with the results
// I AM NOT DONE
impl From<&str> for Person {
fn from(s: &str) -> Person {}
}

View file

@ -31,8 +31,6 @@ enum ParsePersonError {
ParseInt(ParseIntError),
}
// I AM NOT DONE
// Steps:
// 1. If the length of the provided string is 0, an error should be returned
// 2. Split the given string on the commas present in it

View file

@ -27,8 +27,6 @@ enum IntoColorError {
IntConversion,
}
// I AM NOT DONE
// Your task is to complete this implementation and return an Ok result of inner
// type Color. You need to create an implementation for a tuple of three
// integers, an array of three integers, and a slice of integers.

View file

@ -10,8 +10,6 @@
// Execute `rustlings hint using_as` or use the `hint` watch subcommand for a
// hint.
// I AM NOT DONE
fn average(values: &[f64]) -> f64 {
let total = values.iter().sum::<f64>();
total / values.len()

View file

@ -13,8 +13,6 @@
//
// No hints this time ;)
// I AM NOT DONE
// Put your function here!
// fn calculate_price_of_apples {

View file

@ -20,8 +20,6 @@
//
// No hints this time!
// I AM NOT DONE
pub enum Command {
Uppercase,
Trim,

View file

@ -16,8 +16,6 @@
//
// Execute `rustlings hint quiz3` or use the `hint` watch subcommand for a hint.
// I AM NOT DONE
pub struct ReportCard {
pub grade: f32,
pub student_name: String,

View file

@ -4,6 +4,7 @@
name = "intro1"
path = "exercises/00_intro/intro1.rs"
mode = "compile"
# TODO: Fix hint
hint = """
Remove the `I AM NOT DONE` comment in the `exercises/intro00/intro1.rs` file
to move on to the next exercise."""
@ -129,11 +130,7 @@ path = "exercises/02_functions/functions3.rs"
mode = "compile"
hint = """
This time, the function *declaration* is okay, but there's something wrong
with the place where we're calling the function.
As a reminder, you can freely play around with different solutions in Rustlings!
Watch mode will only jump to the next exercise if you remove the `I AM NOT
DONE` comment."""
with the place where we're calling the function."""
[[exercises]]
name = "functions4"

Some files were not shown because too many files have changed in this diff Show more