cli icon indicating copy to clipboard operation
cli copied to clipboard

Download all items for given track

Open Jarvvski opened this issue 6 years ago • 16 comments

Did some quick searching and I see that the ability to download all items for a given track isn't currently in the CLI.

I'd really find this item useful, as it's great to have access to items to work on during a long flight etc.

In the mean time (because I've been searching for it in the issues here) I made a tiny script to be able to download all items for a given track: https://github.com/Jarvvski/exercism-downloader

Jarvvski avatar Aug 25 '18 18:08 Jarvvski

I think this would be a nice addition.

A few notes:

  • It would have to be "all unlocked", not "all"
  • In "independent mode", "all unlocked" would be equivalent to "all"

We would need some design/implementation on the backend API in https://github.com/exercism/website before we can start addressing this

kytrinyx avatar Aug 26 '18 17:08 kytrinyx

Before this task is completed, we can use this shell command to pull the list of go: curl -LS https://exercism.io/tracks/go/exercises | grep "/tracks/go/exercises/" | awk '{print $3}' | cut -d/ -f5 | cut -d\" -f1

raymondchen625 avatar Jan 08 '19 14:01 raymondchen625

@raymondchen625 awesome 1 liner!

Jarvvski avatar Jan 11 '19 19:01 Jarvvski

curl -LS https://exercism.io/tracks/rust/exercises | grep "/tracks/rust/exercises/" | awk '{print $3}' | cut -d/ -f5 | cut -d\" -f1 > exercises.txt
while read in; do exercism download --exercise="$in" --track=rust; done < exercises.txt

Change track as needed

tsoernes avatar Feb 12 '19 23:02 tsoernes

I also would massively appreciate a way to download full tracks. EDIT: I just realized I have to have exercises unlocked. @tsoernes script works beautifully though.

cocoonkid avatar Apr 01 '19 00:04 cocoonkid

If you're doing multiple tracks in parallel this might be helpful:

# "exercism download all" for specific tracks

function eda() {
  for trackname in "$@"; do
    echo https://exercism.io/tracks/$trackname/exercises
    curl -LS https://exercism.io/tracks/$trackname/exercises | grep "/tracks/$trackname/exercises/" | awk '{print $3}' | cut -d/ -f5 | cut -d\" -f1 > exercises.txt
    while read in; do exercism download --exercise="$in" --track=$trackname; done < exercises.txt
    rm exercises.txt
  done
}

# example usage:
# ❯ eda typescript reasonml ocaml racket nim

Thank you @tsoernes for doing the hard part. This is just a for loop around his code.

agentofuser avatar Jan 15 '20 17:01 agentofuser

I'm having issues using that @tsoernes code from a computer using WSL2 and redid some part of it:

TRACK=<TRACK-TO-BE-DOWNLOADED> && curl -LS https://exercism.io/tracks/$TRACK/exercises | grep "/tracks/$TRACK/exercises/" | awk '{print $3}' | cut -d/ -f5 | cut -d\" -f1 > exercises.txt
for word in `sed '/^$/d' exercises.txt`; do exercism download --exercise="$word" --track=$TRACK; done

Be careful when your home excercism workspace path has spaces.

Hope you all enjoy it! ;)

farv avatar Apr 18 '20 14:04 farv

If you're doing multiple tracks in parallel this might be helpful:

# "exercism download all" for specific tracks

function eda() {
  for trackname in "$@"; do
    echo https://exercism.io/tracks/$trackname/exercises
    curl -LS https://exercism.io/tracks/$trackname/exercises | grep "/tracks/$trackname/exercises/" | awk '{print $3}' | cut -d/ -f5 | cut -d\" -f1 > exercises.txt
    while read in; do exercism download --exercise="$in" --track=$trackname; done < exercises.txt
    rm exercises.txt
  done
}

# example usage:
# ❯ eda typescript reasonml ocaml racket nim

Thank you @tsoernes for doing the hard part. This is just a for loop around his code.

Note that it will overwrite all already downloaded folders

lcharles123 avatar Dec 27 '20 14:12 lcharles123

The previous scripts don't work on the new website anymore.

This works for me:

#!/usr/bin/env bash 

# You have to have `pup` and `jq` in your $PATH.
# Does `mkfifo` work on MacOS?
# example usage:
# ❯ eda typescript reasonml ocaml racket nim

arrow="\e[31;1m=>\e[0m"
pipe="/tmp/pipe-$$"

for trackname in "$@"; do
	mkfifo "$pipe"
	echo -e "$arrow Downloading ${trackname^} track..."
	curl -LSs https://exercism.org/tracks/"$trackname"/exercises |
		pup -p 'section[class=exercises] div attr{data-react-data}' |
		jq -r '.request.options.initial_data.exercises | .[].slug' >"$pipe" &
	while read in; do
		exercism download --exercise="$in" --track="$trackname"
	done <"$pipe"
	rm "$pipe"
done

she3o avatar Sep 20 '21 00:09 she3o

This is a python script I just used.

import requests
import re
import os

# Replace this with your language
LANGUAGE = "java"

# Get the html from the exercism page
pageURL = 'https://exercism.org/tracks/' + LANGUAGE + '/exercises'
request = requests.get(pageURL)
pageHTML = request.content.decode('utf-8')

# Each exercise is in the form "/tracks/java/"exerciseName&
regexString = r'tracks/' + LANGUAGE + '/exercises/(.*?)&'
allMatches = re.findall(regexString, pageHTML)
numDownloads = 0
for exercise in allMatches:
    downloadCommand = 'exercism download --exercise=' + exercise + ' --track=' + LANGUAGE
    os.system(downloadCommand)
    numDownloads += 1

print("Total downloads: ", numDownloads)

robertpkoenig avatar Oct 08 '21 16:10 robertpkoenig

To add to this pageant of download scripts, here's a bash version of @robertpkoenig's Python script that doesn't need anything you don't already have (the exercism CLI, curl, and pretty standard *NIX/Posix stuff). Just change TRACK to whatever floats your boat.

(TRACK=rust; set -euo pipefail; trackdir="$(exercism workspace)/$TRACK"; mkdir -p "$trackdir"; curl --silent --fail "https://exercism.org/tracks/$TRACK/exercises" | grep -Eo 'tracks/'"$TRACK"'/exercises/[^&]+' | cut -d/ -f4 | tee "$trackdir/exercise-order.txt" | while read ex; do if test -d "$trackdir/$ex" ; then echo "$ex already downloaded"; else (set -x && exercism download --track "$TRACK" --exercise "$ex"); fi; done)

Works On My Machine™️

Edit: Now also works on other machines (Mac/bash and Alpine/ash at least)

gustafc avatar Nov 16 '22 08:11 gustafc

Here's a python script that asynchronously downloads a track from it's config.json:

import asyncio
import json
import requests


async def download_exercise(exercise: str, track: str, overwrite):
    cmd = f"exercism download --exercise={exercise} --track={track}"
    if overwrite:
        cmd += " --force"
    proc = await asyncio.create_subprocess_shell(
        cmd,
        stdout=asyncio.subprocess.PIPE,
        stderr=asyncio.subprocess.PIPE)

    stdout, stderr = await proc.communicate()

    print(f'[{cmd!r} exited with {proc.returncode}]')
    if stdout:
        print(f'[stdout]\n{stdout.decode()}')
    if stderr:
        print(f'[stderr]\n{stderr.decode()}')

async def download_track(track: str, overwrite=false):
    url = f"https://github.com/exercism/{track}/raw/main/config.json"
    content = json.loads(requests.get(url).content)

    await asyncio.gather(*(download_exercise(exercise['slug'], track, overwrite) for exercise in content["exercises"]["practice"]))

asyncio.run(download_track("dart"))

AmjadHD avatar Mar 18 '23 23:03 AmjadHD

Another Bash script, but using Exercism's API:

#!/usr/bin/env bash

set -e
set -u

export track="$1"

curl \
  --silent --fail \
  "https://exercism.org/api/v2/tracks/$track/exercises" \
  | sed 's/"slug":"/\n/g' \
  | sed 's/",.*$//' \
  | grep -v '"exercises":' \
  | while read -r slug; do
      exercism download --track="$track" --exercise="$slug"
    done

nihilismus avatar Apr 02 '23 04:04 nihilismus

So, my PR got automatically closed because of the pause of community contributions, which I wasn't aware of, but that doesn't mean you can't use the feature I've developed to list, filter, and download exercises. Just read the PR, it has all the examples. Until the pause gets lifted, happy coding!

PR - https://github.com/exercism/cli/pull/1113

baduker avatar Sep 19 '23 08:09 baduker

A shorter command than what I have seen here before. Uses jq as dependency which is pretty common.

  • downloads only exercises you don't already have (doesn't overwrite. But still can if you add --force)
  • only downloads unlocked exercises
track=go; curl "https://exercism.org/api/v2/tracks/$track/exercises" | \
  jq -r '.exercises[].slug' | \
  xargs -I {} -n1 sh -c "exercism download --track=$track --exercise {} || true"

jonnylangefeld avatar Nov 29 '23 09:11 jonnylangefeld

In case somone wants an out of the box solution: exer-h

screen-1

It's a small wrapper for the official exercism cli. Hope it helps.

Giveback007 avatar Jul 23 '24 20:07 Giveback007