Skip to content

Commit f00246d

Browse files
committed
added update-exercise
1 parent 02ac4c9 commit f00246d

File tree

2 files changed

+100
-0
lines changed

2 files changed

+100
-0
lines changed

tmc-langs-cli/src/app.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -675,6 +675,10 @@ fn create_core_app() -> App<'static, 'static> {
675675
.required(true)
676676
.takes_value(true)))
677677

678+
.subcommand(SubCommand::with_name("update-exercises")
679+
.about("Updates all local exercises that have been updated on the server")
680+
.long_about(SCHEMA_NULL))
681+
678682
.subcommand(SubCommand::with_name("wait-for-submission")
679683
.about("Waits for a submission to finish")
680684
.long_about(schema_leaked::<SubmissionFinished>())

tmc-langs-cli/src/main.rs

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1514,6 +1514,102 @@ fn run_core(
15141514
print_output(&output, pretty, &warnings)?
15151515
}
15161516
}
1517+
("update-exercises", Some(_)) => {
1518+
let mut exercises_to_update = vec![];
1519+
let mut downloaded_exercises = vec![];
1520+
let mut skipped_exercises = vec![];
1521+
let mut course_data = HashMap::<String, Vec<(String, String, usize)>>::new();
1522+
1523+
let projects_dir = TmcConfig::load(client_name)?.projects_dir;
1524+
let mut projects_config = ProjectsConfig::load(&projects_dir)?;
1525+
let local_exercises = projects_config
1526+
.courses
1527+
.iter()
1528+
.map(|c| &c.1.exercises)
1529+
.flatten()
1530+
.map(|e| e.1)
1531+
.collect::<Vec<_>>();
1532+
let exercise_ids = local_exercises.iter().map(|e| e.id).collect::<Vec<_>>();
1533+
1534+
// request would error with 0 exercise ids
1535+
if !exercise_ids.is_empty() {
1536+
let server_exercises = client
1537+
.get_exercises_details(exercise_ids)?
1538+
.into_iter()
1539+
.map(|e| (e.id, e))
1540+
.collect::<HashMap<_, _>>();
1541+
for local_exercise in local_exercises {
1542+
let server_exercise =
1543+
server_exercises.get(&local_exercise.id).with_context(|| {
1544+
format!(
1545+
"Server did not return details for local exercise with id {}",
1546+
local_exercise.id
1547+
)
1548+
})?;
1549+
if server_exercise.checksum != local_exercise.checksum {
1550+
// server has an updated exercise
1551+
let target = ProjectsConfig::get_exercise_download_target(
1552+
&projects_dir,
1553+
&server_exercise.course_name,
1554+
&server_exercise.exercise_name,
1555+
);
1556+
let exercise_list = course_data
1557+
.entry(server_exercise.course_name.clone())
1558+
.or_default();
1559+
exercise_list.push((
1560+
server_exercise.exercise_name.clone(),
1561+
server_exercise.checksum.clone(),
1562+
server_exercise.id,
1563+
));
1564+
exercises_to_update.push((local_exercise.id, target));
1565+
downloaded_exercises.push(DownloadOrUpdateCourseExercise {
1566+
course_slug: server_exercise.course_name.clone(),
1567+
exercise_slug: server_exercise.exercise_name.clone(),
1568+
});
1569+
} else {
1570+
skipped_exercises.push(DownloadOrUpdateCourseExercise {
1571+
course_slug: server_exercise.course_name.clone(),
1572+
exercise_slug: server_exercise.exercise_name.clone(),
1573+
});
1574+
}
1575+
}
1576+
1577+
if !exercises_to_update.is_empty() {
1578+
client.download_or_update_exercises(exercises_to_update)?;
1579+
1580+
for (course_name, exercise_names) in course_data {
1581+
let mut exercises = BTreeMap::new();
1582+
for (exercise_name, checksum, id) in exercise_names {
1583+
exercises.insert(exercise_name, Exercise { id, checksum });
1584+
}
1585+
1586+
if let Some(course_config) = projects_config.courses.get_mut(&course_name) {
1587+
course_config.exercises.extend(exercises);
1588+
course_config.save_to_projects_dir(&projects_dir)?;
1589+
} else {
1590+
let course_config = CourseConfig {
1591+
course: course_name,
1592+
exercises,
1593+
};
1594+
course_config.save_to_projects_dir(&projects_dir)?;
1595+
};
1596+
}
1597+
}
1598+
}
1599+
1600+
let data = DownloadOrUpdateCourseExercisesResult {
1601+
downloaded: downloaded_exercises,
1602+
skipped: skipped_exercises,
1603+
};
1604+
let output = Output::OutputData(OutputData {
1605+
status: Status::Finished,
1606+
message: None,
1607+
result: OutputResult::RetrievedData,
1608+
percent_done: 1.0,
1609+
data: Some(data),
1610+
});
1611+
print_output(&output, pretty, &warnings)?
1612+
}
15171613
("wait-for-submission", Some(matches)) => {
15181614
let submission_url = matches.value_of("submission-url").unwrap();
15191615

0 commit comments

Comments
 (0)