Skip to content

Commit d0cd08c

Browse files
lint: error on missing concept/exercise files (#522)
* lint(track_config): check concepts with missing dir With this commit, `configlet lint` now checks if there are concepts in the `config.json` file's `concepts` array that don't have a corresponding `concepts/<slug>` directory (which causes the track to crash during syncing). * lint(track_config): check exercises with missing dir With this commit, `configlet lint` now checks if there are exercises in the `config.json` file's `exercises.practice` or `exercises.concept` array that don't have a corresponding `exercises/<kind>/<slug>` directory (which causes the track to crash during syncing).
1 parent 02ee5ca commit d0cd08c

1 file changed

Lines changed: 48 additions & 31 deletions

File tree

src/lint/track_config.nim

Lines changed: 48 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -785,24 +785,33 @@ proc getExerciseSlugs(data: JsonNode; k: string): HashSet[string] =
785785
if slugStr.len > 0:
786786
result.incl slugStr
787787

788-
proc checkExerciseDirsAreInTrackConfig(trackDir: Path; data: JsonNode;
789-
b: var bool; path: Path) =
788+
proc checkExerciseDirsAndTrackConfigAreInSync(trackDir: Path; data: JsonNode;
789+
b: var bool; path: Path) =
790790
## Sets `b` to `false` if there is an exercise directory that is
791-
## not an exercise `slug` in `data`.
791+
## not an exercise `slug` in `data` and vice versa.
792792
for exerciseKind in ["concept", "practice"]:
793-
let exerciseSlugs = getExerciseSlugs(data, exerciseKind)
794-
if exerciseSlugs.len > 0:
795-
let exercisesDir = trackDir / "exercises" / exerciseKind
796-
if dirExists(exercisesDir):
797-
for exerciseDir in getSortedSubdirs(exercisesDir):
798-
let dirSlug = lastPathPart(exerciseDir.string)
799-
if dirSlug notin exerciseSlugs:
800-
let msg = &"{q $exercisesDir} contains a directory named {q dirSlug}, " &
801-
&"which is not a `slug` in the array of {exerciseKind} " &
802-
"exercises. Please add the exercise to that array. " &
803-
"If the exercise is not ready to be shown on the " &
804-
"website, please set its `status` value to \"wip\""
805-
b.setFalseAndPrint(msg, path)
793+
let exerciseSlugs = getExerciseSlugs(data, exerciseKind)
794+
let exercisesDir = trackDir / "exercises" / exerciseKind
795+
var exerciseDirSlugs = initHashSet[string]()
796+
797+
if dirExists(exercisesDir):
798+
for exerciseDir in getSortedSubdirs(exercisesDir):
799+
exerciseDirSlugs.incl lastPathPart(exerciseDir.string)
800+
801+
for exerciseSlug in exerciseDirSlugs - exerciseSlugs:
802+
let msg = &"{q $exercisesDir} contains a directory named {q exerciseSlug}, " &
803+
&"which is not a `slug` in the array of {exerciseKind} " &
804+
"exercises. Please add the exercise to that array. " &
805+
"If the exercise is not ready to be shown on the " &
806+
"website, please set its `status` value to \"wip\""
807+
b.setFalseAndPrint(msg, path)
808+
809+
for exerciseSlug in exerciseSlugs - exerciseDirSlugs:
810+
let exerciseDir = exercisesDir / exerciseSlug
811+
let msg = &"The {q exerciseSlug} {exerciseKind} exercise is missing its " &
812+
&"required files. Please create the {q $exerciseDir} directory with " &
813+
"its required files"
814+
b.setFalseAndPrint(msg, path)
806815

807816
proc getConceptSlugs(data: JsonNode): HashSet[string] =
808817
result = initHashSet[string]()
@@ -822,21 +831,29 @@ proc getConceptSlugs(data: JsonNode): HashSet[string] =
822831
if slugStr.len > 0:
823832
result.incl slugStr
824833

825-
proc checkConceptDirsAreInTrackConfig(trackDir: Path; data: JsonNode;
826-
b: var bool; path: Path) =
834+
proc checkConceptDirsAndTrackConfigAreInSync(trackDir: Path; data: JsonNode;
835+
b: var bool; path: Path) =
827836
## Sets `b` to `false` if there is a concept directory that is
828-
## not a concept `slug` in `data`.
837+
## not a concept `slug` in `data` or vice versa.
829838
let conceptSlugs = getConceptSlugs(data)
830-
if conceptSlugs.len > 0:
831-
let conceptsDir = trackDir / "concepts"
832-
if dirExists(conceptsDir):
833-
for conceptDir in getSortedSubdirs(conceptsDir):
834-
let dirSlug = lastPathPart(conceptDir.string)
835-
if dirSlug notin conceptSlugs:
836-
let msg = &"{q $conceptsDir} contains a directory named {q dirSlug}, " &
837-
&"which is not a `slug` in the concepts array. " &
838-
"Please add the concept to that array"
839-
b.setFalseAndPrint(msg, path)
839+
let conceptsDir = trackDir / "concepts"
840+
var conceptDirSlugs = initHashSet[string]()
841+
842+
if dirExists(conceptsDir):
843+
for conceptDir in getSortedSubdirs(conceptsDir):
844+
conceptDirSlugs.incl lastPathPart(conceptDir.string)
845+
846+
for conceptSlug in conceptDirSlugs - conceptSlugs:
847+
let msg = &"{q $conceptsDir} contains a directory named {q conceptSlug}, " &
848+
&"which is not a `slug` in the concepts array. " &
849+
"Please add the concept to that array"
850+
b.setFalseAndPrint(msg, path)
851+
852+
for conceptSlug in conceptSlugs - conceptDirSlugs:
853+
let conceptDir = conceptsDir / conceptSlug
854+
let msg = &"The {q conceptSlug} concept is missing its required files. " &
855+
&"Please create the {q $conceptDir} directory with its required files"
856+
b.setFalseAndPrint(msg, path)
840857

841858
proc isTrackConfigValid*(trackDir: Path): bool =
842859
result = true
@@ -852,5 +869,5 @@ proc isTrackConfigValid*(trackDir: Path): bool =
852869
result = satisfiesSecondPass(trackConfigContents, trackConfigPath)
853870

854871
if j != nil:
855-
checkExerciseDirsAreInTrackConfig(trackDir, j, result, trackConfigPath)
856-
checkConceptDirsAreInTrackConfig(trackDir, j, result, trackConfigPath)
872+
checkExerciseDirsAndTrackConfigAreInSync(trackDir, j, result, trackConfigPath)
873+
checkConceptDirsAndTrackConfigAreInSync(trackDir, j, result, trackConfigPath)

0 commit comments

Comments
 (0)