Skip to content

Commit

Permalink
lint(track_config): check exercise directory names are in config (#426)
Browse files Browse the repository at this point in the history
With this commit, `configlet lint` now produces an error if there is
a subdirectory in the `exercises/concept` directory or
`exercises/practice` directory of a track that does not have a
corresponding entry in the track-level `config.json` file.
  • Loading branch information
ee7 authored Sep 16, 2021
1 parent 476b198 commit e732894
Showing 1 changed file with 41 additions and 1 deletion.
42 changes: 41 additions & 1 deletion src/lint/track_config.nim
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import std/[json, sets, strformat, strscans, strutils, tables]
import std/[json, os, sets, strformat, strscans, strutils, tables]
import pkg/jsony
import ".."/[cli, helpers]
import "."/validators
Expand Down Expand Up @@ -669,6 +669,44 @@ proc satisfiesSecondPass(trackConfigContents: string; path: Path): bool =
checkExercisesPCP(practiceExercises, result, path)
checkExerciseSlugsAndForegone(exercises, result, path)

proc getExerciseSlugs(data: JsonNode; k: string): HashSet[string] =
result = initHashSet[string]()
if data.kind != JObject or "exercises" notin data:
return

let exercises = data["exercises"]

if exercises.kind != JObject or k notin exercises or exercises[k].kind != JArray:
return

for exercise in exercises[k]:
if exercise.kind == JObject:
if exercise.hasKey("slug"):
let slug = exercise["slug"]
if slug.kind == JString:
let slugStr = slug.getStr()
if slugStr.len > 0:
result.incl slugStr

proc checkExerciseDirsAreInTrackConfig(trackDir: Path; data: JsonNode;
b: var bool; path: Path) =
## Sets `b` to `false` if there is an exercise directory that is
## not an exercise `slug` in `data`.
for exerciseKind in ["concept", "practice"]:
let exerciseSlugs = getExerciseSlugs(data, exerciseKind)
if exerciseSlugs.len > 0:
let exercisesDir = trackDir / "exercises" / exerciseKind
if dirExists(exercisesDir):
for exerciseDir in getSortedSubdirs(exercisesDir):
let dirSlug = lastPathPart(exerciseDir.string)
if dirSlug notin exerciseSlugs:
let msg = &"{q $exercisesDir} contains a directory named {q dirSlug}, " &
&"which is not a `slug` in the array of {exerciseKind} " &
"exercises. Please add the exercise to that array. " &
"If the exercise is not ready to be shown on the " &
"website, please set its `status` value to \"wip\""
b.setFalseAndPrint(msg, path)

proc isTrackConfigValid*(trackDir: Path): bool =
result = true
let trackConfigPath = trackDir / "config.json"
Expand All @@ -681,3 +719,5 @@ proc isTrackConfigValid*(trackDir: Path): bool =
if result:
let trackConfigContents = readFile(trackConfigPath)
result = satisfiesSecondPass(trackConfigContents, trackConfigPath)

checkExerciseDirsAreInTrackConfig(trackDir, j, result, trackConfigPath)

0 comments on commit e732894

Please sign in to comment.