Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

sync: handle docs, metadata, and filepaths #366

Merged
merged 200 commits into from
Dec 15, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
200 commits
Select commit Hold shift + click to select a range
015d46d
cli: sync: add `--docs`, `--filepaths`, `--metadata`, `--tests`
ee7 Jun 19, 2021
78ff713
sync(check): adapt for `--tests`
ee7 Jun 19, 2021
2c471c9
sync(check): begin adapting for `--docs`, `--filepaths`, `--metadata`
ee7 Jun 19, 2021
6acecea
continue adapting for new options
ee7 Jun 19, 2021
86b7552
sync(exercises, tracks): improve readability
ee7 Jun 19, 2021
7bb5fd9
sync: add docs checking
ee7 Jun 19, 2021
dae2be8
sync: rename `check` to `sync`, and `update` to `update_tests`
ee7 Jun 19, 2021
80761c3
sync: add docs updating
ee7 Jun 19, 2021
56586ae
sync: add metadata checking
ee7 Jun 19, 2021
075cb92
sync: add metadata updating
ee7 Jun 19, 2021
0c90f56
tests(binary): bump PS hash; add metadata output
ee7 Jun 24, 2021
a3f4590
sync: improve metadata syncing
ee7 Jun 24, 2021
6af02bb
sync: add filepaths checking and updating
ee7 Jun 24, 2021
bba4796
sync: split to `sync_docs.nim`
ee7 Jun 24, 2021
cd8d64c
sync: split to `sync_metadata.nim`
ee7 Jun 24, 2021
53e09f7
sync: split to `sync_tests.nim`
ee7 Jun 24, 2021
3fee157
sync: move `update_tests.nim` into `sync_tests.nim`
ee7 Jun 24, 2021
df8e815
sync(sync): fix message after updating docs
ee7 Jun 24, 2021
7bd9516
sync(sync): refactor scope handling
ee7 Jun 24, 2021
f75dce5
sync(sync): remove redundant condition
ee7 Jun 24, 2021
9480dc0
sync(sync): make `userSaysYes` take `SyncKind`
ee7 Jun 24, 2021
45eb9c2
sync(sync): DRY excl
ee7 Jun 24, 2021
35de22d
sync(sync): prep for DRYer filepaths/metadata updating
ee7 Jun 24, 2021
072b78b
sync(sync): DRYer filepaths/metadata updating
ee7 Jun 24, 2021
5dc509c
sync(sync): add an `assert`
ee7 Jun 24, 2021
fb5382e
sync: make parameter order more consistent
ee7 Jun 24, 2021
a38ac9a
tests(binary): test sync scope options
ee7 Oct 29, 2021
3723365
cli: improve help message for `--update`
ee7 Oct 29, 2021
22cb2a9
cli: clarify help message for `--yes`
ee7 Oct 29, 2021
372ee11
sync/sync: clarify comment
ee7 Oct 29, 2021
767e013
sync/sync: prefer built-in set
ee7 Oct 29, 2021
717dbcf
sync/sync: refactor
ee7 Oct 29, 2021
5630d13
sync/sync: move `explain` proc
ee7 Oct 29, 2021
ba50076
sync/sync: prefer `func`
ee7 Oct 29, 2021
47f78e6
cli: improve help message for `-e`
ee7 Oct 29, 2021
bd898e0
sync/sync: prefer singular
ee7 Oct 29, 2021
c8889d7
sync/sync: clarify "up to date"
ee7 Oct 29, 2021
75065d1
sync/sync: fix report when `-e` given
ee7 Oct 29, 2021
34c3779
sync/sync: make report more explicit
ee7 Oct 29, 2021
0e4ed32
tests(binary): rename "footer" variables
ee7 Oct 29, 2021
576e437
tests(binary): rename "body" variables
ee7 Oct 29, 2021
c1b4223
tests(binary): reduce duplication
ee7 Oct 29, 2021
285b481
sync/sync, tests(binary): fix report when `-e` and scope given
ee7 Oct 29, 2021
054a755
sync/sync: move variable
ee7 Oct 29, 2021
f460bc6
sync_docs: rename misleading proc
ee7 Oct 29, 2021
a8514b9
sync_docs: add TODO for optimizing
ee7 Oct 29, 2021
2f478c3
sync_docs: refactor into `checkIntroduction` proc
ee7 Oct 29, 2021
d045213
sync_docs: refactor into `checkInstructions` proc
ee7 Oct 29, 2021
f0c1ada
sync_docs, sync_filepaths: prefer `const`
ee7 Oct 29, 2021
544ae4e
sync_filepaths: inline some one-time-used declarations
ee7 Oct 29, 2021
0f59dea
sync_filepaths: move declaration closer to usage
ee7 Oct 29, 2021
837083e
sync_filepaths: re-order procs
ee7 Oct 29, 2021
5776ec5
sync_filepaths: tweak `snakeToCamel` and `snakeToPascal`
ee7 Oct 29, 2021
ea48524
sync_filepaths: fix doc comment
ee7 Oct 29, 2021
9b391e6
sync_filepaths: shorten long lines
ee7 Oct 29, 2021
69fd13d
sync_docs, sync_metadata: resolve `nimpretty` semicolon complaints
ee7 Oct 29, 2021
7599f9d
sync/sync: don't use/clone prob-specs when only `--filepaths` given
ee7 Oct 29, 2021
5ba3e13
sync_filepaths: add TODO for multiple placeholders
ee7 Oct 29, 2021
867d6a7
README: update help message
ee7 Oct 29, 2021
d7afdf4
cli: make `-uy` or e.g. `-uy --tests` an error
ee7 Oct 29, 2021
dac09e9
sync/sync: improve proc name
ee7 Nov 1, 2021
3ac1379
sync/sync: move code into `updateDocs` proc
ee7 Nov 1, 2021
7aef03e
sync_docs: better handle missing .docs dir
ee7 Nov 1, 2021
a263565
sync: refactor
ee7 Nov 1, 2021
43f2e5f
sync: refactor more; add some tests
ee7 Nov 2, 2021
0bd6c94
tests: rename cloned repos
ee7 Nov 3, 2021
0f1f420
test_tracks: use common track repo
ee7 Nov 3, 2021
e3686b3
tests: add timestamp comments for repo commit refs
ee7 Nov 3, 2021
8b739cc
sync_metadata: improve TOML parsing slightly
ee7 Nov 3, 2021
4f33d6e
sync_metadata: improve TOML parsing
ee7 Nov 3, 2021
3dc21bf
test_sync: show that custom TOML parsing is sufficient
ee7 Nov 3, 2021
9e5e94d
sync_metadata: serialize as pretty JSON again
ee7 Nov 3, 2021
229aa11
sync: fix `test_runner` field type
ee7 Nov 3, 2021
b362f8a
tests: bump `exercism/nim` git refs
ee7 Nov 3, 2021
0090aaa
test_binary: add more tests for exit code 0
ee7 Nov 3, 2021
de4fb97
test_binary: improve a test name
ee7 Nov 3, 2021
44f4859
test_binary: rearrange tests
ee7 Nov 3, 2021
789cfff
test_binary: improve test structure
ee7 Nov 3, 2021
e5c93d8
test_binary: add more tests for exit code 1
ee7 Nov 3, 2021
a9ece4a
test_binary: fix test name
ee7 Nov 3, 2021
f61fab0
test_binary: improve suite name
ee7 Nov 3, 2021
3599043
test_binary: add some `--update --metadata` tests
ee7 Nov 3, 2021
00be40b
sync_common: fix our `parseFile` when the file is empty
ee7 Nov 3, 2021
f1fddea
sync: fix `nimpretty` complaints
ee7 Nov 4, 2021
257d2de
sync_metadata, test_binary: add some more metadata tests
ee7 Nov 4, 2021
45699a5
sync_metadata, test_binary: better handle missing `.meta` dir
ee7 Nov 4, 2021
f1882e9
sync_filepaths, test_sync: add initial filepaths syncing
ee7 Nov 4, 2021
e034db6
sync_filepaths, test_sync: use `distinct string` for slug
ee7 Nov 4, 2021
66ea2d1
sync_filepaths: add parse-time `Slug` validation
ee7 Nov 4, 2021
8a17544
sync_common, sync_metadata: move `pretty` proc
ee7 Nov 4, 2021
5b32f4b
sync_common: refactor to support pretty `ConceptExerciseConfig`
ee7 Nov 4, 2021
b5e4ead
sync_common, sync_filepaths: serialize as pretty JSON
ee7 Nov 4, 2021
9918dbb
sync_common, sync_filepaths: move wrapper type
ee7 Nov 4, 2021
cf02ce6
sync: add sanity-checks for writing
ee7 Nov 4, 2021
42e3f04
sync_filepaths, test_sync: fix filepaths syncing
ee7 Nov 5, 2021
2dcf837
sync_filepaths: refactor `init`
ee7 Nov 5, 2021
cc51a37
sync_filepaths: refactor more
ee7 Nov 5, 2021
fe9cf08
sync_filepaths: move into `write` proc
ee7 Nov 5, 2021
26d0aca
sync_common, test_sync: allow `contributors: null`
ee7 Nov 5, 2021
c0bdbcc
sync_common, test_sync: allow `forked_from: null`
ee7 Nov 5, 2021
febdf64
sync_common: prompt user harder for yes/no
ee7 Nov 5, 2021
309e263
sync_metadata: prefer `logNormal` to `echo`
ee7 Nov 5, 2021
5b87b02
cli: fix double space
ee7 Nov 5, 2021
1f8f937
cli, test_binary: error for non-interactive update without `-y`
ee7 Nov 5, 2021
db7eebb
cli, README: bikeshed help message
ee7 Nov 5, 2021
599756e
cli, README: mention practice/concept exercise split
ee7 Nov 5, 2021
9b3f409
sync_common, test_sync: set default `test_runner` value
ee7 Nov 5, 2021
23839a8
Revert "sync_common, test_sync: set default `test_runner` value"
ee7 Nov 5, 2021
bbad1ae
sync_filepaths: remove unnecessary strformat.`&`
ee7 Nov 5, 2021
baa9bbf
sync_filepaths: try `postHook` for slug validation
ee7 Nov 5, 2021
a6aad54
sync_common: change property order for `.meta/config.json` serialization
ee7 Nov 5, 2021
0496a14
sync_common: serialize without round-trip via `JsonNode`
ee7 Nov 5, 2021
f1a6700
helpers, lint(track_config), sync_common: improve jsony parsing error
ee7 Nov 5, 2021
24a1de4
lint(track_config): workaround upstream breaking change in jsony
ee7 Nov 5, 2021
26d3cde
sync_common, test_binary: always include at least `"authors": []`
ee7 Nov 6, 2021
e68e6a6
sync_filepaths: fix for e.g. `files.solution = [""]`
ee7 Nov 6, 2021
ebc0236
sync_filepaths: refactor `isSynced`
ee7 Nov 6, 2021
61aa46b
sync_common: appease nimpretty
ee7 Nov 6, 2021
42f0ba5
sync_docs, sync_metadata: move into `write` proc
ee7 Nov 6, 2021
caa96b3
sync: print the number of successfully updated exercises
ee7 Nov 6, 2021
a603e62
sync: refactor towards jsony; fix bug for missing `-e` value
ee7 Nov 6, 2021
5391b3b
sync/sync, test_binary: test missing track `config.json`
ee7 Nov 6, 2021
88768de
test_binary: test `--exercise` value not found
ee7 Nov 6, 2021
b326a06
sync: improve doc comments
ee7 Nov 6, 2021
5255590
sync, test_binary: fix message
ee7 Nov 9, 2021
4666af2
sync_docs, sync_metadata: use `Slug`
ee7 Nov 9, 2021
7852147
cli, sync/sync: move sync `Conf` validation to sync
ee7 Nov 9, 2021
8ab90e3
sync/sync: refactor to use object
ee7 Nov 9, 2021
13a9bee
sync/sync: bikeshed placeholder directory name
ee7 Nov 9, 2021
379c619
sync/sync: add message for verbose mode
ee7 Nov 9, 2021
bb63216
sync/sync: fix a bad import alignment
ee7 Nov 9, 2021
a66206e
sync/sync, sync_tests: tweak parameter order
ee7 Nov 9, 2021
3cde434
sync_tests: fix typo in doc comment
ee7 Nov 9, 2021
ea5f340
cli, sync, README: fix incorrect usage of "up-to-date"
ee7 Nov 9, 2021
d40da55
sync_filepaths: refactor long condition
ee7 Nov 9, 2021
9468085
sync_metadata: reduce `joinPath` allocations
ee7 Nov 9, 2021
40df21d
sync_common, sync_filepaths, sync_metadata: reduce string allocations
ee7 Nov 9, 2021
ea5b239
sync_common, sync_docs: rewrite docs syncing
ee7 Nov 9, 2021
fb8995c
sync_common: move a `push`
ee7 Nov 9, 2021
0d9c67d
sync_common, sync_metadata: improve comments
ee7 Nov 9, 2021
0e332e3
sync: improve log readability
ee7 Nov 9, 2021
a8d0030
test_binary: update tests for the log changes
ee7 Nov 10, 2021
c6a2e41
sync_docs: fix message for missing directory
ee7 Nov 10, 2021
7f9cb68
sync_common: fix `test_runner` serialization
ee7 Nov 10, 2021
fba5723
sync_common: move `files.editor` to the end
ee7 Nov 10, 2021
1f4ad73
test_sync: test serialization against round-trip
ee7 Nov 10, 2021
bddd01d
test_sync: add basic JSON serialization tests
ee7 Nov 10, 2021
3447062
test_sync: make some initializations more consistent
ee7 Nov 10, 2021
8cf35c6
sync_docs, test_binary: fix Windows build
ee7 Nov 10, 2021
cc38a28
Revert "lint(track_config): workaround upstream breaking change in js…
ee7 Nov 20, 2021
a627049
sync: create missing dir only after confirmation
ee7 Nov 20, 2021
08eba8c
cli, tests: replace `--mode choose|include|exclude`
ee7 Nov 20, 2021
6e11b2d
cli: write default verbosity value in help message
ee7 Nov 20, 2021
da86618
cli: improve `--filepaths` help description
ee7 Nov 20, 2021
a4c4bf2
sync_metadata, test_sync: remove custom parsing of TOML subset
ee7 Nov 20, 2021
95965e9
sync/sync: fix error message for `sync -uy`
ee7 Nov 20, 2021
1be6781
sync_common, test_sync: support `custom` key in exercise config
ee7 Nov 20, 2021
e91278d
build: patch parseopt3
ee7 Nov 20, 2021
3e2141b
build: make patch work in CI
ee7 Nov 20, 2021
c8df795
sync_common, test_sync: fix serialization of `custom: {}`
ee7 Nov 20, 2021
5fa5c65
sync_common: refactor; reduce allocations
ee7 Nov 20, 2021
876420d
test_sync: appease `nimpretty`
ee7 Nov 20, 2021
66ca9d4
sync_common: refactor the loop over `pretty`
ee7 Nov 21, 2021
c5f4126
sync_common: inline `addObject` code again
ee7 Nov 21, 2021
f8150be
sync_common: refactor comma removal
ee7 Nov 21, 2021
63c486d
sync_common: refactor `addCustom` as `addObject`
ee7 Nov 21, 2021
9cd6681
sync_common: simplify `addObject`
ee7 Nov 24, 2021
4f02bd9
sync_common, test_sync: work towards preserving key order
ee7 Nov 24, 2021
2d8e9b8
sync_common, test_sync: use an enum instead for key order
ee7 Nov 24, 2021
f8d35b7
sync_common, test_sync: use jsony `renameHook` instead
ee7 Nov 24, 2021
48ebfa3
sync_common: remove `validKeys`
ee7 Nov 24, 2021
c73a2a3
sync: preserve order of exercise config keys
ee7 Nov 24, 2021
ffaa826
test_binary: add test for `parseopt3` patch
ee7 Nov 24, 2021
363ddc6
sync_common: rename `pmFormat` to `pmFmt`
ee7 Dec 6, 2021
6143aa2
cli: move `TestsMode` down
ee7 Dec 6, 2021
b2984cd
test_binary: tweak some long lines
ee7 Dec 6, 2021
57247bb
sync_metadata: add comment
ee7 Dec 6, 2021
44855bd
sync/sync: add an init func
ee7 Dec 6, 2021
b64c8a4
helpers, test_sync: prefer `func`
ee7 Dec 6, 2021
6324b44
sync_common: nitpick doc comments
ee7 Dec 6, 2021
fdf184f
sync/sync: fix grammar
ee7 Dec 6, 2021
9146efc
cli, README: improve `-u` description
ee7 Dec 6, 2021
5c80620
cli, README: bikeshed help message backticks/quotes
ee7 Dec 6, 2021
e86bffc
README: add initial documentation for the new `sync`
ee7 Dec 6, 2021
906e6cc
test_sync: remove now-unused `formatViaRoundtrip` code
ee7 Dec 6, 2021
e942bf8
sync_common: remove some `fmt` code
ee7 Dec 6, 2021
11ac707
README: improve new `sync` documentation
ee7 Dec 8, 2021
61c0858
sync_common: expand `renameHook` comment
ee7 Dec 8, 2021
e96004d
sync_common: temporarily remove more `fmt` code
ee7 Dec 8, 2021
4c3e0f6
cli, README: improve description of `--update` and `--yes`
ee7 Dec 10, 2021
512e849
cli: DRY printing of an option
ee7 Dec 10, 2021
e539e96
sync_common: allocate larger initial string in `pretty`
ee7 Dec 10, 2021
94ceca1
sync: improve write-time assertions
ee7 Dec 14, 2021
75f6b8f
sync: replace `doAssert`s with if/else
ee7 Dec 14, 2021
991590a
sync_common: remove another `assert` from release
ee7 Dec 14, 2021
6c5ef5c
sync/sync, sync_filepaths: improve `init` style
ee7 Dec 14, 2021
3ddc936
sync_common: add comment
ee7 Dec 14, 2021
4d613e1
sync: improve comments around `truncateAndAdd` call sites
ee7 Dec 14, 2021
467e66c
README: nitpick `-e` examples
ee7 Dec 14, 2021
da000b9
configlet.nimble: improve patch comments
ee7 Dec 15, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,6 @@

# Ignore temporary repos
.problem-specifications/
tests/.test_binary_elixir_track_repo/
tests/.test_binary_nim_track_repo/
tests/.test_binary_problem_specifications/
tests/.test_elixir_track_repo/
tests/.test_nim_track_repo/
tests/.test_problem_specifications/
163 changes: 154 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,17 @@ Commands:
lint, sync, uuid, generate, info

Options for sync:
-e, --exercise <slug> Only sync this exercise
-m, --mode <mode> What to do with missing test cases. Allowed values: c[hoose], i[nclude], e[xclude]
-p, --prob-specs-dir <dir> Use this `problem-specifications` directory, rather than cloning temporarily
-o, --offline Do not check that the directory specified by `-p, --prob-specs-dir` is up-to-date
-u, --update Prompt the user to include, exclude, or skip any missing tests
-e, --exercise <slug> Only operate on this exercise
-p, --prob-specs-dir <dir> Use this 'problem-specifications' directory, rather than cloning temporarily
-o, --offline Do not check that the directory specified by --prob-specs-dir is up to date
-u, --update Prompt to update the seen data that are unsynced
-y, --yes Auto-confirm prompts from --update for updating docs, filepaths, and metadata
--docs Sync Practice Exercise '.docs/introduction.md' and '.docs/instructions.md' files
--filepaths Populate empty 'files' values in Concept/Practice exercise '.meta/config.json' files
--metadata Sync Practice Exercise '.meta/config.json' metadata values
--tests [mode] Sync Practice Exercise '.meta/tests.toml' files.
The mode value specifies how missing tests are handled when using --update.
Allowed values: c[hoose], i[nclude], e[xclude] (default: choose)

Options for uuid:
-n, --num <int> Number of UUIDs to generate
Expand All @@ -27,7 +33,8 @@ Global options:
-h, --help Show this help message and exit
--version Show this tool's version information and exit
-t, --track-dir <dir> Specify a track directory to use instead of the current directory
-v, --verbosity <verbosity> The verbosity of output. Allowed values: q[uiet], n[ormal], d[etailed]
-v, --verbosity <verbosity> The verbosity of output.
Allowed values: q[uiet], n[ormal], d[etailed] (default: normal)
```

## `configlet lint`
Expand All @@ -38,6 +45,89 @@ The `configlet lint` command is still under development. The list of currently i

## `configlet sync`

A Practice Exercise on an Exercism track is often implemented from a specification in the [`exercism/problem-specifications`](https://github.com/exercism/problem-specifications) repo.

Exercism deliberately requires that every exercise has its own copy of certain files (like `.docs/instructions.md`), even when that exercise exists in `problem-specifications`.
Therefore configlet has a `sync` command, which can check that such Practice Exercises on a track are in sync with that upstream source, and can update them when updates are available.

There are three kinds of data that can be updated from `problem-specifications`: documentation, metadata, and tests.
There is also one kind of data that can be populated from the track-level `config.json` file: filepaths in exercise config files.

We describe the checking and updating of these data kinds in individual sections below, but as a quick summary:
- `configlet sync` only operates on exercises that exist in the track-level `config.json` file. Therefore if you are implementing a new exercise on a track and want to add the initial files with `configlet sync`, please add the exercise to the track-level `config.json` file first. If the exercise is not yet ready to be user-facing, please set its `status` value to `wip`.
- A plain `configlet sync` makes no changes to the track, and checks every data kind for every exercise.
- To operate on a subset of data kinds, use some combination of the `--docs`, `--filepaths`, `--metadata`, and `--tests` options.
- To interactively update data on the track, use the `--update` option.
- To non-interactively update docs, filepaths, and metadata on the track, use `--update --yes`.
- To non-interactively include every unseen test for a given exercise, use e.g. `--update --tests include --exercise prime-factors`.
- To skip downloading the `problem-specifications` repo, add `--offline --prob-specs-dir /path/to/local/problem-specifications`
- Note that `configlet sync` tries to maintain the key order in exercise `.meta/config.json` files when updating. To write these files in a canonical form without syncing, please use the upcoming `configlet fmt` command. However, `configlet sync` _does_ add (possibly empty) required keys (`authors`, `files`, `blurb`) when they are missing. This is less "sync-like", but more ergonomic: when implementing a new exercise, you can use `sync` to create a starter `.meta/config.json` file.
- `configlet sync` removes keys that are not in the spec. Custom key/value pairs are still supported: they must be written inside a JSON object named `custom`.
- The exit code is 0 when all the seen data are synced when configlet exits, and 1 otherwise.

Note that in `configlet` releases `4.0.0-alpha.34` and earlier, the `sync` command operated only on tests.

### Docs

A Practice Exercise that is derived from the `problem-specifications` repo must have a `.docs/instructions.md` file (and possibly a `.docs/introduction.md` file too) containing the exercise documentation from `problem-specifications`.

To check every Practice Exercise on the track for available documentation updates (exiting with a non-zero exit code if at least one update is available):

```
$ configlet sync --docs
```

To interactively update the docs for every Practice Exercise, add the `--update` option (or `-u` for short):

```
$ configlet sync --docs --update
```

To non-interactively update the docs for every Practice Exercise, add the `--yes` option (or `-y` for short):

```
$ configlet sync --docs --update --yes
```

To operate on a single Practice Exercise, use the `--exercise` option (or `-e` for short).
For example, to non-interactively update the docs for the `prime-factors` exercise:

```
$ configlet sync --docs -uy -e prime-factors
```

### Metadata

Every exercise on a track must have a `.meta/config.json` file.
For a Practice Exercise that is derived from the `problem-specifications` repo, this file should contain the `blurb`, `source` and `source_url` key/value pairs that exist in the corresponding upstream `metadata.toml` file.

To check every Practice Exercise for available metadata updates (exiting with a non-zero exit code if at least one update is available):

```
$ configlet sync --metadata
```

To interactively update the metadata for every Practice Exercise, add the `--update` option (or `-u` for short):

```
$ configlet sync --metadata --update
```

To non-interactively update the metadata for every Practice Exercise, add the `--yes` option (or `-y` for short):

```
$ configlet sync --metadata --update --yes
```

To operate on a single Practice Exercise, use the `--exercise` option (or `-e` for short).
For example, to non-interactively update the metadata for the `prime-factors` exercise:

```
$ configlet sync --metadata -uy -e prime-factors
```

### Tests

If a track implements an exercise for which test data exists in the [problem-specifications repo](https://github.com/exercism/problem-specifications), the exercise _must_ contain a `.meta/tests.toml` file. The goal of the `tests.toml` file is to keep track of which tests are implemented by the exercise. Tests in this file are identified by their UUID and each test has a boolean value that indicates if it is implemented by that exercise.

A `tests.toml` file has this format:
Expand Down Expand Up @@ -68,11 +158,66 @@ comment = "excluded because we don't want to add error handling to the exercise"

In this case, the track has chosen to implement two of the three available tests. If a track uses a _test generator_ to generate an exercise's test suite, it _must_ use the contents of the `tests.toml` file to determine which tests to include in the generated test suite.

The `sync` command allows tracks to keep `tests.toml` files up to date. A plain `configlet sync` performs no changes, and just compares the tests specified in the `tests.toml` files against the tests that are defined in the exercise's canonical data - if there are tests defined only in the latter, it prints a summary and exits with a non-zero exit code.
To check every Practice Exercise `tests.toml` file for available tests updates (exiting with a non-zero exit code if there is at least one test case that appears in the exercise's canonical data, but not in the `tests.toml`):

```
$ configlet sync --tests
```

To interactively update the `tests.toml` file for every Practice Exercise, add the `--update` option:

```
$ configlet sync --tests --update
```

For each missing test, this prompts the user to choose whether to include/exclude/skip it, and updates the corresponding `tests.toml` file accordingly.
Configlet writes an exercise's `tests.toml` file when the user has finished making choices for that exercise.
This means that you can terminate configlet at a prompt (for example, by pressing Ctrl-C in the terminal) and only lose the syncing decisions for at most one exercise.

To non-interactively include every unseen test case, use `--tests include`. For example, to do so for an exercise named `prime-factors`:

```
$ configlet sync --tests include -u -e prime-factors
```

Remember to actually implement these tests on the track!

### Filepaths

Finally, the `sync` command also handles "syncing" from a source that isn't `problem-specifications` - the track-level `config.json` file.
Every Concept Exercise and Practice Exercise must have a `.meta/config.json` file with a `files` object that specifies the (relative) locations of the files that the exercise uses.
Such filepaths usually follow a simple pattern, and so configlet can populate the exercise-level values from patterns in the `files` key of the track-level `config.json` file.

To check that every Concept Exercise and Practice Exercise on the track has a fully populated `files` key (or at least one that cannot be populated from the track-level `files` key):

```
$ configlet sync --filepaths
```

(Note that `configlet lint` will also produce an error when an exercise has a missing/empty `files` key.)

To populate empty/missing values of the exercise-level `files` key for every Concept Exercise and Practice Exercise from the patterns in the track-level `files` key:

```
$ configlet sync --filepaths --update
```

To do this non-interactively and for a single exercise named `prime-factors`:

```
$ configlet sync --filepaths -uy -e prime-factors
```

To interactively update the `tests.toml` files, use `configlet sync --update`. For each missing test, this prompts the user to choose whether to include/exclude/skip it, and updates the corresponding `tests.toml` file accordingly.
### Using `sync` when adding a new exercise to a track

The `configlet sync` command replaces the functionality of the older `canonical_data_syncer` application.
The `sync` command is useful when adding a new exercise to a track. If you are adding a Practice Exercise named `foo` that exists in `problem-specifications`, one possible workflow is:
1. Manually add an entry to the track-level `config.json` file for the exercise `foo`. This makes the exercise visible to `configlet sync`.
1. Run `configlet sync --docs --filepaths --metadata -uy -e foo` to create the exercise's documentation, and a starter `.meta/config.json` file with populated `files`, `blurb`, and perhaps `source` and `source_url` values.
1. Edit the exercise `.meta/config.json` file as desired. For example, add yourself to the `authors` array.
1. Run `configlet sync --tests include -u -e foo` to create a `.meta/tests.toml` file with every test included.
1. View that `.meta/tests.toml` file, and add `include = false` to any test case that the exercise will not implement.
1. Implement the tests for the exercise to match those included in `.meta/tests.toml`.
1. Add the other required files.

## `configlet uuid`

Expand Down
34 changes: 34 additions & 0 deletions configlet.nimble
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import std/[hashes, os, strutils]

# Package
version = "4.0.0"
author = "ee7"
Expand All @@ -15,3 +17,35 @@ requires "jsony >= 1.0.4"

task test, "Runs the test suite":
exec "nim r ./tests/all_tests.nim"

# Patch `cligen/parseopt3` so that "--foo --bar" is parsed as two long options,
# even when `longNoVal` is both non-empty and lacks `foo`.
before build:
# We want to support running `nimble build` before `cligen` is installed, so
# we can't `import cligen/parseopt3` and check the parsing directly.
# Instead, let's just hash the file and run `git apply` conditionally.
# First, get the path to `parseopt3.nim` in the `cligen` package.
let (output, exitCode) = gorgeEx("nimble path cligen")
if exitCode == 0:
let parseopt3Path = joinPath(output.strip(), "cligen", "parseopt3.nim")
if fileExists(parseopt3Path):
# Hash the file using `std/hashes`.
# Note that we can't import `std/md5` or `std/sha1` in a .nimble file.
let actualHash = parseopt3Path.readFile().hash()
const patchedHash = 1647921161 # Update when bumping `cligen` changes `parseopt3`.
if actualHash != patchedHash:
echo "Trying to patch parseopt3..."
echo "Found " & parseopt3Path
let patchPath = thisDir() / "parseopt3_allow_long_option_optional_value.patch"
let parseopt3Dir = parseopt3Path.parentDir()
# Apply the patch.
let cmd = "git -C " & parseopt3Dir & " apply --verbose " & patchPath
let (outp, exitCode) = gorgeEx(cmd)
echo outp
if exitCode != 0:
raise newException(AssertionDefect, "failed to apply patch")
else:
raise newException(AssertionDefect, "file does not exist: " & parseopt3Path)
else:
echo output
raise newException(AssertionDefect, "failed to get cligen path")
24 changes: 24 additions & 0 deletions parseopt3_allow_long_option_optional_value.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
diff --git a/parseopt3.nim b/parseopt3.nim
index a865952..850d016 100644
--- a/parseopt3.nim
+++ b/parseopt3.nim
@@ -267,8 +267,17 @@ proc doLong(p: var OptParser) =
p.kind = cmdError
return
if p.pos < p.cmd.len: # Take opt arg from next param
- p.val = p.cmd[p.pos]
- p.pos += 1
+ # If the next parameter begins with `-`, parse it as an option, even when
+ # `longNoVal` is both non-empty and lacks the given long option.
+ # This allows a long option `foo` to have an optional value, supporting both
+ # of the below forms:
+ # --foo val1 --bar val2
+ # --foo --bar val2
+ # Without the below line, `--bar` is parsed as the value of `--foo` in the
+ # latter case.
+ if not p.cmd[p.pos].startsWith("-"):
+ p.val = p.cmd[p.pos]
+ p.pos += 1
elif p.longNoVal.len != 0:
p.val = ""
p.pos += 1
Loading