Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: exercism/configlet
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 4.0.0-beta.14
Choose a base ref
...
head repository: exercism/configlet
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 4.0.0-beta.16
Choose a head ref
  • 19 commits
  • 38 files changed
  • 3 contributors

Commits on Aug 22, 2023

  1. fetch-configlet: support fetching arm64 assets (#805)

    The most recent configlet release [1] includes pre-built binaries for:
    
    - arm64 Linux [2]
    - arm64 macOS [3]
    - arm64 Windows [4]
    - riscv64 Linux [5]
    
    Support arm64 in the bash fetch-configlet script.
    
    Refs: #122
    
    [1] https://github.com/exercism/configlet/releases/tag/4.0.0-beta.14
    [2] 0e8d665, 2023-08-16, ".github, config: use Zig to cross-compile arm64 Linux asset"
    [3] f280445, 2023-08-17, ".github: cross-compile arm64 macOS asset"
    [4] 3824299, 2023-08-18, ".github, cli, completion: cross-compile arm64 Windows asset"
    [5] a962b18, 2023-08-17, ".github: cross-compile riscv64 Linux asset"
    ee7 authored Aug 22, 2023
    Copy the full SHA
    98095a5 View commit details
  2. .github(fetch-configlet): pass in GITHUB_TOKEN (#806)

    Try to resolve errors due to rate limiting.
    
    Closes: #803
    ee7 authored Aug 22, 2023
    Copy the full SHA
    731c6ad View commit details
  3. fetch-configlet: remove wildcard from some patterns (#807)

    Better communicate to the reader that, on Windows:
    
    - "${os}" is exactly 'zip'
    - "${ext}" is exactly '.exe'
    ee7 authored Aug 22, 2023
    Copy the full SHA
    4d387e9 View commit details
  4. fetch-configlet: explicitly pass -s to uname (#808)

    I believe that a bare `uname` should do the same thing as `uname -s`
    everywhere. But let's not rely on the reader knowing this, and instead
    better communicate that we want the operating system name.
    
    With GNU coreutils 9.3:
    
        $ uname --help
        Usage: uname [OPTION]...
        Print certain system information.  With no OPTION, same as -s.
    
          -a, --all                print all information, in the following order,
                                     except omit -p and -i if unknown:
          -s, --kernel-name        print the kernel name
        [...]
    
    And on OpenBSD [1]:
    
        If no options are specified, uname prints the operating system name as if the -s option had been specified.
    
    [1] https://man.openbsd.org/uname
    ee7 authored Aug 22, 2023
    Copy the full SHA
    f18d69c View commit details

Commits on Sep 1, 2023

  1. Copy the full SHA
    265c702 View commit details

Commits on Sep 13, 2023

  1. Copy the full SHA
    0ac2979 View commit details

Commits on Sep 15, 2023

  1. create, fmt, sync: move formatting code into fmt directory (#770)

    The formatting code was overly spread out, partly because `fmt` was
    added after other commands that needed to check/write formatted JSON.
    
    Try to move all the formatting code into the src/fmt directory.
    ErikSchierboom authored Sep 15, 2023
    Copy the full SHA
    95833ac View commit details

Commits on Oct 1, 2023

  1. Copy the full SHA
    1fa7dc6 View commit details
  2. Copy the full SHA
    f528157 View commit details
  3. Copy the full SHA
    4015ff9 View commit details

Commits on Oct 5, 2023

  1. fmt: support formatting track config (#772)

    And add integration tests for `fmt`.
    
    Refs: #478
    Closes: #479
    ErikSchierboom authored Oct 5, 2023
    Copy the full SHA
    6691484 View commit details

Commits on Oct 6, 2023

  1. all: replace jsony imports with an export (#823)

    Remove jsony imports where helpers is imported.
    
    Closes: #817
    ee7 authored Oct 6, 2023
    Copy the full SHA
    0f6ffe6 View commit details
  2. create, fmt, info: remove unused imports (#825)

    Aside: with this commit, there is exactly one file (`helpers.nim`) that
    imports `jsony`, and it also exports `jsony`. This makes the codebase
    more robust to the problem of `parseHook`s not being visible.
    ee7 authored Oct 6, 2023
    Copy the full SHA
    77fd69e View commit details
  3. Copy the full SHA
    9251cb4 View commit details
  4. release: 4.0.0-beta.15 (#830)

    ee7 authored Oct 6, 2023
    Copy the full SHA
    9514f3b View commit details
  5. lint(track_config): allow omitting concepts and exercises.concept (#832)

    A recent commit [1] caused `configlet fmt -uy` to remove these keys from
    the track-level `config.json` file when the corresponding value was
    empty. This would cause a subsequent `configlet lint` to indicate an
    error, in line with the spec. But we'll change the spec so that omitting
    these keys is allowed, because:
    
    - It's fine for tracks to lack concepts, or to lack concept exercises
    
    - There is little value in keeping empty arrays around
    
    - In practice the keys _are_ optional, because Exercism gracefully
      handles them being omitted 
    
    Fixes: #831
    
    [1] 6691484, 2023-10-05, "fmt: support formatting track config"
    ee7 authored Oct 6, 2023
    Copy the full SHA
    685d871 View commit details

Commits on Oct 19, 2023

  1. tests: split up binary tests (#827)

    This commit splits up the binary tests into separate files for 
    maintenance purposes.
    ErikSchierboom authored Oct 19, 2023
    Copy the full SHA
    fbdc59a View commit details
  2. lint: verify analyzer tag format (#833)

    This commit ensures that linting verifies the format of analyzer tags,
    which should be: `<category>:<value>`.
    
    The `<category>` value must be one of:
    - `paradigm`
    - `technique`
    - `construct`
    - `uses`
    ErikSchierboom authored Oct 19, 2023
    Copy the full SHA
    b348ff9 View commit details

Commits on Oct 20, 2023

  1. release: 4.0.0-beta.16 (#834)

    ee7 authored Oct 20, 2023
    Copy the full SHA
    84406a5 View commit details
12 changes: 6 additions & 6 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
@@ -13,7 +13,7 @@ jobs:
contents: write
steps:
- name: Checkout code
uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9
uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608
with:
fetch-depth: 0 # Allows using `git log` to set initial release notes.

@@ -47,14 +47,14 @@ jobs:
contents: write
steps:
- name: Checkout code
uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9
uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608

- name: On Linux, install musl
if: matrix.os == 'linux'
run: ./.github/bin/linux-install-musl

- name: Install Nim
uses: iffy/install-nim@ac410af52523f06e0fa037ee81d06ead7b95692c
uses: iffy/install-nim@96e44cd5d6df83f65cd844a8631e8301944bc958
with:
version: "binary:2.0.0"
env:
@@ -96,10 +96,10 @@ jobs:
contents: write
steps:
- name: Checkout code
uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9
uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608

- name: Install Nim
uses: iffy/install-nim@ac410af52523f06e0fa037ee81d06ead7b95692c
uses: iffy/install-nim@96e44cd5d6df83f65cd844a8631e8301944bc958
with:
version: "binary:2.0.0"
env:
@@ -124,7 +124,7 @@ jobs:
contents: write
steps:
- name: Checkout code
uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9
uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608

- name: Install minisign
run: ./.github/bin/linux-install-minisign
6 changes: 5 additions & 1 deletion .github/workflows/fetch-configlet.yml
Original file line number Diff line number Diff line change
@@ -28,11 +28,13 @@ jobs:
runs-on: ${{ matrix.runs-on }}
steps:
- name: Checkout
uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9
uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608

- name: Run fetch-configlet
shell: bash
run: ./scripts/fetch-configlet
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

- name: Run the downloaded configlet
env:
@@ -49,3 +51,5 @@ jobs:
Remove-Item bin/configlet.exe
scripts/fetch-configlet.ps1
bin/configlet.exe --version
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
2 changes: 1 addition & 1 deletion .github/workflows/lint-whitespace.yml
Original file line number Diff line number Diff line change
@@ -8,7 +8,7 @@ jobs:
runs-on: ubuntu-22.04
steps:
- name: Checkout
uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9
uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608

- name: Check that every file has no trailing whitespace, and exactly one final newline
run: ./.github/bin/lint-whitespace
4 changes: 2 additions & 2 deletions .github/workflows/markdownlint.yml
Original file line number Diff line number Diff line change
@@ -8,9 +8,9 @@ jobs:
runs-on: ubuntu-22.04
steps:
- name: Checkout
uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9
uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608

- name: Run markdownlint
uses: DavidAnson/markdownlint-cli2-action@8f3516061301755c97ff833a8e933f09282cc5b5
uses: DavidAnson/markdownlint-cli2-action@ed4dec634fd2ef689c7061d5647371d8248064f1
with:
globs: "**/*.md"
2 changes: 1 addition & 1 deletion .github/workflows/shellcheck.yml
Original file line number Diff line number Diff line change
@@ -8,7 +8,7 @@ jobs:
runs-on: ubuntu-22.04
steps:
- name: Checkout
uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9
uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608

- name: Run shellcheck
uses: ludeeus/action-shellcheck@00cae500b08a931fb5698e11e79bfbd38e612a38
9 changes: 7 additions & 2 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
@@ -35,14 +35,19 @@ jobs:
contents: read
steps:
- name: Checkout code
uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9
uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608

- name: Configure the git user # Required to create a commit in our binary tests
run: |
git config --global user.email "66069679+exercism-bot@users.noreply.github.com"
git config --global user.name "Exercism Bot"
- name: On Linux, install musl
if: matrix.os == 'linux'
run: ./.github/bin/linux-install-musl

- name: Install Nim
uses: iffy/install-nim@ac410af52523f06e0fa037ee81d06ead7b95692c
uses: iffy/install-nim@96e44cd5d6df83f65cd844a8631e8301944bc958
with:
version: "binary:2.0.0"
env:
2 changes: 1 addition & 1 deletion configlet.version
Original file line number Diff line number Diff line change
@@ -1 +1 @@
4.0.0-beta.14
4.0.0-beta.16
23 changes: 12 additions & 11 deletions scripts/fetch-configlet
Original file line number Diff line number Diff line change
@@ -24,10 +24,11 @@ get_download_url() {
local latest='https://api.github.com/repos/exercism/configlet/releases/latest'
local arch
case "$(uname -m)" in
x86_64) arch='x86-64' ;;
*686*) arch='i386' ;;
*386*) arch='i386' ;;
*) arch='x86-64' ;;
aarch64|arm64) arch='arm64' ;;
x86_64) arch='x86-64' ;;
*686*) arch='i386' ;;
*386*) arch='i386' ;;
*) arch='x86-64' ;;
esac
local suffix="${os}_${arch}.${ext}"
curl "${curlopts[@]}" --header 'Accept: application/vnd.github.v3+json' "${latest}" |
@@ -47,7 +48,7 @@ main() {
fi

local os
case "$(uname)" in
case "$(uname -s)" in
Darwin*) os='macos' ;;
Linux*) os='linux' ;;
Windows*) os='windows' ;;
@@ -58,8 +59,8 @@ main() {

local ext
case "${os}" in
windows*) ext='zip' ;;
*) ext='tar.gz' ;;
windows) ext='zip' ;;
*) ext='tar.gz' ;;
esac

echo "Fetching configlet..." >&2
@@ -69,16 +70,16 @@ main() {
curl "${curlopts[@]}" --output "${output_path}" "${download_url}"

case "${ext}" in
*zip) unzip "${output_path}" -d "${output_dir}" ;;
*) tar xzf "${output_path}" -C "${output_dir}" ;;
zip) unzip "${output_path}" -d "${output_dir}" ;;
*) tar xzf "${output_path}" -C "${output_dir}" ;;
esac

rm -f "${output_path}"

local executable_ext
case "${os}" in
windows*) executable_ext='.exe' ;;
*) executable_ext='' ;;
windows) executable_ext='.exe' ;;
*) executable_ext='' ;;
esac

local configlet_path="${output_dir}/configlet${executable_ext}"
3 changes: 1 addition & 2 deletions src/create/approaches.nim
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import std/[os, strformat, strutils]
import pkg/jsony
import ".."/[helpers, sync/sync_common, types_track_config, types_approaches_config, uuid/uuid]
import ".."/[fmt/approaches, helpers, types_track_config, types_approaches_config, uuid/uuid]

func kebabToTitleCase(slug: Slug): string =
result = newStringOfCap(slug.len)
3 changes: 1 addition & 2 deletions src/create/articles.nim
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import std/[os, strformat, strutils]
import pkg/jsony
import ".."/[helpers, sync/sync_common, types_track_config, types_articles_config, uuid/uuid]
import ".."/[fmt/articles, helpers, types_track_config, types_articles_config, uuid/uuid]

func kebabToTitleCase(slug: Slug): string =
result = newStringOfCap(slug.len)
19 changes: 19 additions & 0 deletions src/exec.nim
Original file line number Diff line number Diff line change
@@ -108,6 +108,20 @@ proc gitCheckout(dir, hash: string) =
let args = ["-C", dir, "checkout", "--force", hash]
discard gitCheck(0, args)

proc fixAverageRunTimeInConfigJson(file, oldValue, newValue: string) =
## For testing purposes, we clone track repos and checkout commits
## where the `average_run_time` value in the `config.json` file
## is a float, which has later since changed to an int.
## In order to not break existing tests, we manually change the value
## from a float to an int.
let configJson = readFile(file)
.replace(
&""""average_run_time": {oldValue}""",
&""""average_run_time": {newValue}""")
writeFile(file, configJson)
let args = ["-C", parentDir(file), "commit", "-a", "-m", "config: convert `average_run_time` to int"]
discard gitCheck(0, args)

proc setupExercismRepo*(repoName, dest, hash: string; shallow = false) =
## If there is no directory at `dest`, clones the Exercism repo named
## `repoName` to `dest`.
@@ -117,6 +131,11 @@ proc setupExercismRepo*(repoName, dest, hash: string; shallow = false) =
cloneExercismRepo(repoName, dest, shallow)
gitCheckout(dest, hash)

if repoName == "nim":
fixAverageRunTimeInConfigJson(dest / "config.json", "3.0", "3")
elif repoName == "elixir":
fixAverageRunTimeInConfigJson(dest / "config.json", "4.1", "4")

func conciseDiff(s: string): string =
## Returns the lines of `s` that begin with a `+` or `-` character.
result = newStringOfCap(s.len)
95 changes: 95 additions & 0 deletions src/fmt/approaches.nim
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
import std/[json, options, strformat]
import ".."/[helpers, sync/sync_common, types_approaches_config]

func approachesConfigKeyOrderForFmt(e: ApproachesConfig): seq[ApproachesConfigKey] =
result = @[]
if e.introduction.authors.len > 0:
result.add ackIntroduction
if e.approaches.len > 0:
result.add ackApproaches

func addApproachesIntroduction(result: var string;
val: ApproachesIntroductionConfig;
indentLevel = 1) =
## Appends the pretty-printed JSON for an `introduction` key with value `val` to
## `result`.
result.addNewlineAndIndent(indentLevel)
escapeJson("introduction", result)
result.add ": {"
result.addArray("authors", val.authors, indentLevel + 1)
if val.contributors.len > 0:
result.addArray("contributors", val.contributors, indentLevel + 1)
result.removeComma()
result.addNewlineAndIndent(indentLevel)
result.add "},"

func addApproachTags(result: var string; val: ApproachConfigTags; indentLevel = 2) =
result.addNewlineAndIndent(indentLevel)
escapeJson("tags", result)
result.add ": {"
if val.all.len > 0:
result.addArray("all", val.all, indentLevel + 1)
if val.`any`.len > 0:
result.addArray("any", val.`any`, indentLevel + 1)
if val.`not`.len > 0:
result.addArray("not", val.`not`, indentLevel + 1)
result.removeComma()
result.addNewlineAndIndent(indentLevel)
result.add "},"

func addApproach(result: var string; val: ApproachConfig; indentLevel = 1) =
## Appends the pretty-printed JSON for an `approach` object with value `val` to
## `result`.
result.addNewlineAndIndent(indentLevel)
result.add "{"
result.addString("uuid", val.uuid, indentLevel + 1)
result.addString("slug", val.slug, indentLevel + 1)
result.addString("title", val.title, indentLevel + 1)
result.addString("blurb", val.blurb, indentLevel + 1)
result.addArray("authors", val.authors, indentLevel + 1)
if val.contributors.len > 0:
result.addArray("contributors", val.contributors, indentLevel + 1)
if val.tags.isSome():
let tags = val.tags.get()
if tags.all.len + tags.`any`.len + tags.`not`.len > 0:
result.addApproachTags(tags, indentLevel + 1)
result.removeComma()
result.addNewlineAndIndent(indentLevel)
result.add "},"

func addApproaches(result: var string;
val: seq[ApproachConfig];
indentLevel = 1) =
## Appends the pretty-printed JSON for an `approaches` key with value `val` to
## `result`.
result.addNewlineAndIndent(indentLevel)
escapeJson("approaches", result)
result.add ": ["
for approach in val:
result.addApproach(approach, indentLevel + 1)
result.removeComma()
result.addNewlineAndIndent(indentLevel)
result.add "]"

func prettyApproachesConfig*(e: ApproachesConfig): string =
## Serializes `e` as pretty-printed JSON, using the canonical key order.
let keys = approachesConfigKeyOrderForFmt(e)

result = newStringOfCap(1000)
result.add '{'
for key in keys:
case key
of ackIntroduction:
if e.introduction.authors.len > 0 or e.introduction.contributors.len > 0:
result.addApproachesIntroduction(e.introduction)
of ackApproaches:
if e.approaches.len > 0:
result.addApproaches(e.approaches)
result.removeComma()
result.add "\n}\n"

proc formatApproachesConfigFile*(configPath: string): string =
## Parses the `.approaches/config.json` file at `configPath` and
## returns it in the canonical form.
let approachesConfig = ApproachesConfig.init(configPath)
prettyApproachesConfig(approachesConfig)
55 changes: 55 additions & 0 deletions src/fmt/articles.nim
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import std/[json, strformat]
import ".."/[helpers, sync/sync_common, types_articles_config]

func articlesConfigKeyOrderForFmt(e: ArticlesConfig): seq[ArticlesConfigKey] =
result = @[]
if e.articles.len > 0:
result.add ackArticles

func addArticle(result: var string; val: ArticleConfig; indentLevel = 1) =
## Appends the pretty-printed JSON for an `article` object with value `val` to
## `result`.
result.addNewlineAndIndent(indentLevel)
result.add "{"
result.addString("uuid", val.uuid, indentLevel + 1)
result.addString("slug", val.slug, indentLevel + 1)
result.addString("title", val.title, indentLevel + 1)
result.addString("blurb", val.blurb, indentLevel + 1)
result.addArray("authors", val.authors, indentLevel + 1)
if val.contributors.len > 0:
result.addArray("contributors", val.contributors, indentLevel + 1)
result.removeComma()
result.addNewlineAndIndent(indentLevel)
result.add "},"

func addArticles(result: var string; val: seq[ArticleConfig]; indentLevel = 1) =
## Appends the pretty-printed JSON for an `articles` key with value `val` to
## `result`.
result.addNewlineAndIndent(indentLevel)
escapeJson("articles", result)
result.add ": ["
for article in val:
result.addArticle(article, indentLevel + 1)
result.removeComma()
result.addNewlineAndIndent(indentLevel)
result.add "]"

func prettyArticlesConfig*(e: ArticlesConfig): string =
## Serializes `e` as pretty-printed JSON, using the canonical key order.
let keys = articlesConfigKeyOrderForFmt(e)

result = newStringOfCap(1000)
result.add '{'
for key in keys:
case key
of ackArticles:
if e.articles.len > 0:
result.addArticles(e.articles)
result.removeComma()
result.add "\n}\n"

proc formatArticlesConfigFile*(configPath: string): string =
## Parses the `.articles/config.json` file at `configPath` and
## returns it in the canonical form.
let articlesConfig = ArticlesConfig.init(configPath)
prettyArticlesConfig(articlesConfig)
Loading