Skip to content

Commit

Permalink
info: use prob-specs cache (#605)
Browse files Browse the repository at this point in the history
This stops baking the prob-specs data into the binary, and makes
`configlet info` use the cached prob-specs directory as
`configlet sync` does.

Advantages:

- The prob-specs data is updated at run time - we no longer need
  commits like b54fe48 or 146d41c, and can remove
  `prob_specs_exercises.json`

- We reduce the size of the configlet executable by about 12 KiB (2.5%)

- Fewer lines of code: we can remove `bin/write_probspecs_info.nim`

Disadvantages:

- The user must now pass `-o` or `---offline` when running
  `configlet info` with no/limited network connectivity

- `configlet info` is a little slower, even when using `-o`, because we
  run a few `git` commands to validate the cache repo

Closes: #483
  • Loading branch information
ee7 committed May 20, 2022
1 parent 4e06d08 commit 07a0168
Show file tree
Hide file tree
Showing 6 changed files with 45 additions and 252 deletions.
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ Options for fmt:
-u, --update Prompt to write formatted files
-y, --yes Auto-confirm the prompt from --update
Options for info:
-o, --offline Do not update the cached 'problem-specifications' data
Options for sync:
-e, --exercise <slug> Only operate on this exercise
-o, --offline Do not update the cached 'problem-specifications' data
Expand Down
79 changes: 0 additions & 79 deletions bin/write_probspecs_info.nim

This file was deleted.

25 changes: 18 additions & 7 deletions src/cli.nim
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ type

Action* = object
case kind*: ActionKind
of actNil, actGenerate, actInfo, actLint:
of actNil, actGenerate, actLint:
discard
of actFmt:
# We can't name these fields `exercise`, `update`, and `yes` because we
Expand All @@ -33,6 +33,8 @@ type
exerciseFmt*: string
updateFmt*: bool
yesFmt*: bool
of actInfo:
offlineInfo*: bool
of actSync:
exercise*: string
offline*: bool
Expand Down Expand Up @@ -65,8 +67,9 @@ type
optFmtSyncUpdate = "update"
optFmtSyncYes = "yes"

# Options for `sync`
optSyncOffline = "offline"
# Options for both `info` and `sync`
optInfoSyncOffline = "offline"

# Scope to sync
optSyncDocs = "docs"
optSyncFilepaths = "filepaths"
Expand All @@ -90,7 +93,7 @@ const
configletVersion = staticRead(repoRootDir / "configlet.version").strip()
short = genShortKeys()
optsNoVal = {optHelp, optVersion, optFmtSyncUpdate, optFmtSyncYes,
optSyncOffline, optSyncDocs, optSyncFilepaths, optSyncMetadata}
optInfoSyncOffline, optSyncDocs, optSyncFilepaths, optSyncMetadata}

func generateNoVals: tuple[shortNoVal: set[char], longNoVal: seq[string]] =
## Returns the short and long keys for the options in `optsNoVal`.
Expand Down Expand Up @@ -199,7 +202,7 @@ func genHelpText: string =
optFmtSyncExercise: "Only operate on this exercise",
optFmtSyncUpdate: "Prompt to update the unsynced track data",
optFmtSyncYes: &"Auto-confirm prompts from --{$optFmtSyncUpdate} for updating docs, filepaths, and metadata",
optSyncOffline: "Do not update the cached 'problem-specifications' data",
optInfoSyncOffline: "Do not update the cached 'problem-specifications' data",
optSyncDocs: "Sync Practice Exercise '.docs/introduction.md' and '.docs/instructions.md' files",
optSyncFilepaths: "Populate empty 'files' values in Concept/Practice exercise '.meta/config.json' files",
optSyncMetadata: "Sync Practice Exercise '.meta/config.json' metadata values",
Expand Down Expand Up @@ -252,6 +255,8 @@ func genHelpText: string =
optFmtSyncUpdate
of "yesFmt":
optFmtSyncYes
of "offlineInfo":
optInfoSyncOffline
else:
parseEnum[Opt](key)
# Set the description for `fmt` options.
Expand Down Expand Up @@ -456,7 +461,7 @@ proc handleOption(conf: var Conf; kind: CmdLineKind; key, val: string) =
# Process action-specific options
if not isGlobalOpt:
case conf.action.kind
of actNil, actGenerate, actInfo, actLint:
of actNil, actGenerate, actLint:
discard
of actFmt:
case opt
Expand All @@ -468,6 +473,12 @@ proc handleOption(conf: var Conf; kind: CmdLineKind; key, val: string) =
setActionOpt(yesFmt, true)
else:
discard
of actInfo:
case opt
of optInfoSyncOffline:
setActionOpt(offlineInfo, true)
else:
discard
of actSync:
case opt
of optFmtSyncExercise:
Expand All @@ -479,7 +490,7 @@ proc handleOption(conf: var Conf; kind: CmdLineKind; key, val: string) =
of optSyncTests:
setActionOpt(tests, parseVal[TestsMode](kind, key, val))
conf.action.scope.incl skTests
of optSyncOffline:
of optInfoSyncOffline:
setActionOpt(offline, true)
of optSyncDocs, optSyncMetadata, optSyncFilepaths:
conf.action.scope.incl parseEnum[SyncKind]($opt)
Expand Down
33 changes: 18 additions & 15 deletions src/info/info.nim
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import std/[algorithm, os, sequtils, sets, strformat, strutils, sugar, terminal]
import pkg/jsony
import ".."/[cli, types_track_config]
import ".."/[cli, sync/probspecs, types_track_config]

proc header(s: string): string =
if colorStdout:
Expand Down Expand Up @@ -60,22 +60,23 @@ type
withoutCanonicalData: HashSet[string]
deprecated: HashSet[string]

ProbSpecsState = object
lastUpdated: string
problemSpecificationsCommitRef: string
exercises: ProbSpecsExercises

proc init(T: typedesc[ProbSpecsExercises]): T =
## Reads the prob-specs data at compile-time, and returns an object containing
## every exercise in `exercism/problem-specifications`, grouped by kind.
const slugsPath = currentSourcePath().parentDir() / "prob_specs_exercises.json"
let contents = staticRead(slugsPath)
contents.fromJson(ProbSpecsState).exercises
proc init(T: typedesc[ProbSpecsExercises], probSpecsDir: ProbSpecsDir): T =
result = T()
for kind, path in walkDir(probSpecsDir / "exercises"):
if kind == pcDir:
let exerciseSlug = path.lastPathPart()
if fileExists(path / ".deprecated"):
result.deprecated.incl exerciseSlug
elif fileExists(path / "canonical-data.json"):
result.withCanonicalData.incl exerciseSlug
else:
result.withoutCanonicalData.incl exerciseSlug

proc unimplementedProbSpecsExercises(practiceExercises: seq[PracticeExercise],
foregone: HashSet[string]): string =
const probSpecsExercises = ProbSpecsExercises.init()
foregone: HashSet[string],
probSpecsDir: ProbSpecsDir): string =
let
probSpecsExercises = ProbSpecsExercises.init(probSpecsDir)
practiceExerciseSlugs = collect:
for p in practiceExercises:
{p.slug.`$`}
Expand Down Expand Up @@ -129,8 +130,10 @@ proc info*(conf: Conf) =

if fileExists(trackConfigPath):
let t = TrackConfig.init trackConfigPath.readFile()
let probSpecsDir = ProbSpecsDir.init(conf)
echo conceptsInfo(t.exercises.practice, t.concepts)
echo unimplementedProbSpecsExercises(t.exercises.practice, t.exercises.foregone)
echo unimplementedProbSpecsExercises(t.exercises.practice, t.exercises.foregone,
probSpecsDir)
echo trackSummary(t.exercises.`concept`, t.exercises.practice, t.concepts)
else:
var msg = &"file does not exist: {trackConfigPath}"
Expand Down
149 changes: 0 additions & 149 deletions src/info/prob_specs_exercises.json

This file was deleted.

Loading

0 comments on commit 07a0168

Please sign in to comment.