summary refs log tree commit diff stats
path: root/tools/atlas
diff options
context:
space:
mode:
Diffstat (limited to 'tools/atlas')
-rw-r--r--tools/atlas/atlas.md77
-rw-r--r--tools/atlas/atlas.nim559
-rw-r--r--tools/atlas/osutils.nim51
-rw-r--r--tools/atlas/packagesjson.nim114
-rw-r--r--tools/atlas/parse_requires.nim2
-rw-r--r--tools/atlas/testdata.nim63
-rw-r--r--tools/atlas/tests/balls.nimble32
-rw-r--r--tools/atlas/tests/grok.nimble5
-rw-r--r--tools/atlas/tests/nim-bytes2human.nimble7
-rw-r--r--tools/atlas/tests/nim.cfg11
-rw-r--r--tools/atlas/tests/npeg.nimble48
-rw-r--r--tools/atlas/tests/packages/packages.json36
-rw-r--r--tools/atlas/tests/sync.nimble10
-rw-r--r--tools/atlas/tests/testes.nimble23
-rw-r--r--tools/atlas/tests/ups.nimble13
15 files changed, 1 insertions, 1050 deletions
diff --git a/tools/atlas/atlas.md b/tools/atlas/atlas.md
deleted file mode 100644
index a36817dc5..000000000
--- a/tools/atlas/atlas.md
+++ /dev/null
@@ -1,77 +0,0 @@
-# Atlas Package Cloner
-
-Atlas is a simple package cloner tool that automates some of the
-workflows and needs for Nim's stdlib evolution.
-
-Atlas is compatible with Nimble in the sense that it supports the Nimble
-file format.
-
-
-## How it works
-
-Atlas uses git commits internally; version requirements are translated
-to git commits via `git show-ref --tags`.
-
-Atlas uses URLs internally; Nimble package names are translated to URLs
-via Nimble's  `packages.json` file.
-
-Atlas does not call the Nim compiler for a build, instead it creates/patches
-a `nim.cfg` file for the compiler. For example:
-
-```
-############# begin Atlas config section ##########
---noNimblePath
---path:"../nimx"
---path:"../sdl2/src"
---path:"../opengl/src"
-############# end Atlas config section   ##########
-```
-
-The version selection is deterministic, it picks up the *minimum* required
-version. Thanks to this design, lock files are not required.
-
-
-## Dependencies
-
-Dependencies are neither installed globally, nor locally into the current
-project. Instead a "workspace" is used. The workspace is the nearest parent
-directory of the current directory that does not contain a `.git` subdirectory.
-Dependencies are managed as **siblings**, not as children. Dependencies are
-kept as git repositories.
-
-Thanks to this setup, it's easy to develop multiple projects at the same time.
-
-A project plus its dependencies are stored in a workspace:
-
-  $workspace / main project
-  $workspace / dependency A
-  $workspace / dependency B
-
-
-No attempts are being made at keeping directory hygiene inside the
-workspace, you're supposed to create appropriate `$workspace` directories
-at your own leisure.
-
-
-## Commands
-
-Atlas supports the following commands:
-
-
-### Clone <url>
-
-Clones a URL and all of its dependencies (recursively) into the workspace.
-Creates or patches a `nim.cfg` file with the required `--path` entries.
-
-
-### Clone <package name>
-
-The `<package name>` is translated into an URL via `packages.json` and
-then `clone <url>` is performed.
-
-
-### Search <term term2 term3 ...>
-
-Search the package index `packages.json` for a package that the given terms
-in its description (or name or list of tags).
-
diff --git a/tools/atlas/atlas.nim b/tools/atlas/atlas.nim
deleted file mode 100644
index 274e94517..000000000
--- a/tools/atlas/atlas.nim
+++ /dev/null
@@ -1,559 +0,0 @@
-#
-#           Atlas Package Cloner
-#        (c) Copyright 2021 Andreas Rumpf
-#
-#    See the file "copying.txt", included in this
-#    distribution, for details about the copyright.
-#
-
-## Simple tool to automate frequent workflows: Can "clone"
-## a Nimble dependency and its dependencies recursively.
-
-import std/[parseopt, strutils, os, osproc, unicode, tables, sets, json, jsonutils]
-import parse_requires, osutils, packagesjson
-
-const
-  Version = "0.2"
-  Usage = "atlas - Nim Package Cloner Version " & Version & """
-
-  (c) 2021 Andreas Rumpf
-Usage:
-  atlas [options] [command] [arguments]
-Command:
-  clone url|pkgname     clone a package and all of its dependencies
-  install proj.nimble   use the .nimble file to setup the project's dependencies
-  search keyw keywB...  search for package that contains the given keywords
-  extract file.nimble   extract the requirements and custom commands from
-                        the given Nimble file
-
-Options:
-  --keepCommits         do not perform any `git checkouts`
-  --cfgHere             also create/maintain a nim.cfg in the current
-                        working directory
-  --workspace=DIR       use DIR as workspace
-  --version             show the version
-  --help                show this help
-"""
-
-proc writeHelp() =
-  stdout.write(Usage)
-  stdout.flushFile()
-  quit(0)
-
-proc writeVersion() =
-  stdout.write(Version & "\n")
-  stdout.flushFile()
-  quit(0)
-
-const
-  MockupRun = defined(atlasTests)
-  TestsDir = "tools/atlas/tests"
-
-type
-  PackageName = distinct string
-  DepRelation = enum
-    normal, strictlyLess, strictlyGreater
-
-  Dependency = object
-    name: PackageName
-    url, commit: string
-    rel: DepRelation # "requires x < 1.0" is silly, but Nimble allows it so we have too.
-  AtlasContext = object
-    projectDir, workspace: string
-    hasPackageList: bool
-    keepCommits: bool
-    cfgHere: bool
-    p: Table[string, string] # name -> url mapping
-    processed: HashSet[string] # the key is (url / commit)
-    errors: int
-    when MockupRun:
-      currentDir: string
-      step: int
-      mockupSuccess: bool
-
-const
-  InvalidCommit = "<invalid commit>"
-  ProduceTest = false
-
-type
-  Command = enum
-    GitDiff = "git diff",
-    GitTags = "git show-ref --tags",
-    GitRevParse = "git rev-parse",
-    GitCheckout = "git checkout",
-    GitPull = "git pull",
-    GitCurrentCommit = "git log -n 1 --format=%H"
-    GitMergeBase = "git merge-base"
-
-include testdata
-
-proc exec(c: var AtlasContext; cmd: Command; args: openArray[string]): (string, int) =
-  when MockupRun:
-    assert TestLog[c.step].cmd == cmd, $(TestLog[c.step].cmd, cmd)
-    case cmd
-    of GitDiff, GitTags, GitRevParse, GitPull, GitCurrentCommit:
-      result = (TestLog[c.step].output, TestLog[c.step].exitCode)
-    of GitCheckout:
-      assert args[0] == TestLog[c.step].output
-    of GitMergeBase:
-      let tmp = TestLog[c.step].output.splitLines()
-      assert tmp.len == 4, $tmp.len
-      assert tmp[0] == args[0]
-      assert tmp[1] == args[1]
-      assert tmp[3] == ""
-      result[0] = tmp[2]
-      result[1] = TestLog[c.step].exitCode
-    inc c.step
-  else:
-    var cmdLine = $cmd
-    for i in 0..<args.len:
-      cmdLine.add ' '
-      cmdLine.add quoteShell(args[i])
-    result = osproc.execCmdEx(cmdLine)
-    when ProduceTest:
-      echo "cmd ", cmd, " args ", args, " --> ", result
-
-proc cloneUrl(c: var AtlasContext; url, dest: string; cloneUsingHttps: bool): string =
-  when MockupRun:
-    result = ""
-  else:
-    result = osutils.cloneUrl(url, dest, cloneUsingHttps)
-    when ProduceTest:
-      echo "cloned ", url, " into ", dest
-
-template withDir*(c: var AtlasContext; dir: string; body: untyped) =
-  when MockupRun:
-    c.currentDir = dir
-    body
-  else:
-    let oldDir = getCurrentDir()
-    try:
-      when ProduceTest:
-        echo "Current directory is now ", dir
-      setCurrentDir(dir)
-      body
-    finally:
-      setCurrentDir(oldDir)
-
-proc extractRequiresInfo(c: var AtlasContext; nimbleFile: string): NimbleFileInfo =
-  result = extractRequiresInfo(nimbleFile)
-  when ProduceTest:
-    echo "nimble ", nimbleFile, " info ", result
-
-proc toDepRelation(s: string): DepRelation =
-  case s
-  of "<": strictlyLess
-  of ">": strictlyGreater
-  else: normal
-
-proc isCleanGit(c: var AtlasContext; dir: string): string =
-  result = ""
-  let (outp, status) = exec(c, GitDiff, [])
-  if outp.len != 0:
-    result = "'git diff' not empty"
-  elif status != 0:
-    result = "'git diff' returned non-zero"
-
-proc message(c: var AtlasContext; category: string; p: PackageName; args: varargs[string]) =
-  var msg = category & "(" & p.string & ")"
-  for a in args:
-    msg.add ' '
-    msg.add a
-  stdout.writeLine msg
-  inc c.errors
-
-proc warn(c: var AtlasContext; p: PackageName; args: varargs[string]) =
-  message(c, "[Warning] ", p, args)
-
-proc error(c: var AtlasContext; p: PackageName; args: varargs[string]) =
-  message(c, "[Error] ", p, args)
-
-proc sameVersionAs(tag, ver: string): bool =
-  const VersionChars = {'0'..'9', '.'}
-
-  proc safeCharAt(s: string; i: int): char {.inline.} =
-    if i >= 0 and i < s.len: s[i] else: '\0'
-
-  let idx = find(tag, ver)
-  if idx >= 0:
-    # we found the version as a substring inside the `tag`. But we
-    # need to watch out the the boundaries are not part of a
-    # larger/different version number:
-    result = safeCharAt(tag, idx-1) notin VersionChars and
-      safeCharAt(tag, idx+ver.len) notin VersionChars
-
-proc versionToCommit(c: var AtlasContext; d: Dependency): string =
-  let (outp, status) = exec(c, GitTags, [])
-  if status == 0:
-    var useNextOne = false
-    for line in splitLines(outp):
-      let commitsAndTags = strutils.splitWhitespace(line)
-      if commitsAndTags.len == 2:
-        case d.rel
-        of normal:
-          if commitsAndTags[1].sameVersionAs(d.commit):
-            return commitsAndTags[0]
-        of strictlyLess:
-          if d.commit == InvalidCommit or not commitsAndTags[1].sameVersionAs(d.commit):
-            return commitsAndTags[0]
-        of strictlyGreater:
-          if commitsAndTags[1].sameVersionAs(d.commit):
-            useNextOne = true
-          elif useNextOne:
-            return commitsAndTags[0]
-
-  return ""
-
-proc shortToCommit(c: var AtlasContext; short: string): string =
-  let (cc, status) = exec(c, GitRevParse, [short])
-  result = if status == 0: strutils.strip(cc) else: ""
-
-proc checkoutGitCommit(c: var AtlasContext; p: PackageName; commit: string) =
-  let (_, status) = exec(c, GitCheckout, [commit])
-  if status != 0:
-    error(c, p, "could not checkout commit", commit)
-
-proc gitPull(c: var AtlasContext; p: PackageName) =
-  let (_, status) = exec(c, GitPull, [])
-  if status != 0:
-    error(c, p, "could not 'git pull'")
-
-proc updatePackages(c: var AtlasContext) =
-  if dirExists(c.workspace / PackagesDir):
-    withDir(c, c.workspace / PackagesDir):
-      gitPull(c, PackageName PackagesDir)
-  else:
-    withDir c, c.workspace:
-      let err = cloneUrl(c, "https://github.com/nim-lang/packages", PackagesDir, false)
-      if err != "":
-        error c, PackageName(PackagesDir), err
-
-proc fillPackageLookupTable(c: var AtlasContext) =
-  if not c.hasPackageList:
-    c.hasPackageList = true
-    when not MockupRun:
-      updatePackages(c)
-    let plist = getPackages(when MockupRun: TestsDir else: c.workspace)
-    for entry in plist:
-      c.p[unicode.toLower entry.name] = entry.url
-
-proc toUrl(c: var AtlasContext; p: string): string =
-  if p.isUrl:
-    result = p
-  else:
-    fillPackageLookupTable(c)
-    result = c.p.getOrDefault(unicode.toLower p)
-  if result.len == 0:
-    inc c.errors
-
-proc toName(p: string): PackageName =
-  if p.isUrl:
-    result = PackageName splitFile(p).name
-  else:
-    result = PackageName p
-
-proc needsCommitLookup(commit: string): bool {.inline.} =
-  '.' in commit or commit == InvalidCommit
-
-proc isShortCommitHash(commit: string): bool {.inline.} =
-  commit.len >= 4 and commit.len < 40
-
-proc checkoutCommit(c: var AtlasContext; w: Dependency) =
-  let dir = c.workspace / w.name.string
-  withDir c, dir:
-    if w.commit.len == 0 or cmpIgnoreCase(w.commit, "head") == 0:
-      gitPull(c, w.name)
-    else:
-      let err = isCleanGit(c, dir)
-      if err != "":
-        warn c, w.name, err
-      else:
-        let requiredCommit =
-          if needsCommitLookup(w.commit): versionToCommit(c, w)
-          elif isShortCommitHash(w.commit): shortToCommit(c, w.commit)
-          else: w.commit
-        let (cc, status) = exec(c, GitCurrentCommit, [])
-        let currentCommit = strutils.strip(cc)
-        if requiredCommit == "" or status != 0:
-          if requiredCommit == "" and w.commit == InvalidCommit:
-            warn c, w.name, "package has no tagged releases"
-          else:
-            warn c, w.name, "cannot find specified version/commit", w.commit
-        else:
-          if currentCommit != requiredCommit:
-            # checkout the later commit:
-            # git merge-base --is-ancestor <commit> <commit>
-            let (cc, status) = exec(c, GitMergeBase, [currentCommit, requiredCommit])
-            let mergeBase = strutils.strip(cc)
-            if status == 0 and (mergeBase == currentCommit or mergeBase == requiredCommit):
-              # conflict resolution: pick the later commit:
-              if mergeBase == currentCommit:
-                checkoutGitCommit(c, w.name, requiredCommit)
-            else:
-              checkoutGitCommit(c, w.name, requiredCommit)
-              when false:
-                warn c, w.name, "do not know which commit is more recent:",
-                  currentCommit, "(current) or", w.commit, " =", requiredCommit, "(required)"
-
-proc findNimbleFile(c: AtlasContext; dep: Dependency): string =
-  when MockupRun:
-    result = TestsDir / dep.name.string & ".nimble"
-    doAssert fileExists(result), "file does not exist " & result
-  else:
-    result = c.workspace / dep.name.string / (dep.name.string & ".nimble")
-    if not fileExists(result):
-      result = ""
-      for x in walkFiles(c.workspace / dep.name.string / "*.nimble"):
-        if result.len == 0:
-          result = x
-        else:
-          # ambiguous .nimble file
-          return ""
-
-proc addUniqueDep(c: var AtlasContext; work: var seq[Dependency];
-                  tokens: seq[string]) =
-  let oldErrors = c.errors
-  let url = toUrl(c, tokens[0])
-  if oldErrors != c.errors:
-    warn c, toName(tokens[0]), "cannot resolve package name"
-  elif not c.processed.containsOrIncl(url / tokens[2]):
-    work.add Dependency(name: toName(tokens[0]), url: url, commit: tokens[2],
-                        rel: toDepRelation(tokens[1]))
-
-template toDestDir(p: PackageName): string = p.string
-
-proc collectDeps(c: var AtlasContext; work: var seq[Dependency];
-                 dep: Dependency; nimbleFile: string): string =
-  # If there is a .nimble file, return the dependency path & srcDir
-  # else return "".
-  assert nimbleFile != ""
-  let nimbleInfo = extractRequiresInfo(c, nimbleFile)
-  for r in nimbleInfo.requires:
-    var tokens: seq[string] = @[]
-    for token in tokenizeRequires(r):
-      tokens.add token
-    if tokens.len == 1:
-      # nimx uses dependencies like 'requires "sdl2"'.
-      # Via this hack we map them to the first tagged release.
-      # (See the `isStrictlySmallerThan` logic.)
-      tokens.add "<"
-      tokens.add InvalidCommit
-    elif tokens.len == 2 and tokens[1].startsWith("#"):
-      # Dependencies can also look like 'requires "sdl2#head"
-      var commit = tokens[1][1 .. ^1]
-      tokens[1] = "=="
-      tokens.add commit
-
-    if tokens.len >= 3 and cmpIgnoreCase(tokens[0], "nim") != 0:
-      c.addUniqueDep work, tokens
-  result = toDestDir(dep.name) / nimbleInfo.srcDir
-
-proc collectNewDeps(c: var AtlasContext; work: var seq[Dependency];
-                    dep: Dependency; result: var seq[string];
-                    isMainProject: bool) =
-  let nimbleFile = findNimbleFile(c, dep)
-  if nimbleFile != "":
-    let x = collectDeps(c, work, dep, nimbleFile)
-    result.add x
-  else:
-    result.add toDestDir(dep.name)
-
-proc cloneLoop(c: var AtlasContext; work: var seq[Dependency]): seq[string] =
-  result = @[]
-  var i = 0
-  while i < work.len:
-    let w = work[i]
-    let destDir = toDestDir(w.name)
-    let oldErrors = c.errors
-
-    if not dirExists(c.workspace / destDir):
-      withDir c, c.workspace:
-        let err = cloneUrl(c, w.url, destDir, false)
-        if err != "":
-          error c, w.name, err
-    if oldErrors == c.errors:
-      if not c.keepCommits: checkoutCommit(c, w)
-      # even if the checkout fails, we can make use of the somewhat
-      # outdated .nimble file to clone more of the most likely still relevant
-      # dependencies:
-      collectNewDeps(c, work, w, result, i == 0)
-    inc i
-
-proc clone(c: var AtlasContext; start: string): seq[string] =
-  # non-recursive clone.
-  let url = toUrl(c, start)
-  var work = @[Dependency(name: toName(start), url: url, commit: "")]
-
-  if url == "":
-    error c, toName(start), "cannot resolve package name"
-    return
-
-  c.projectDir = c.workspace / toDestDir(work[0].name)
-  result = cloneLoop(c, work)
-
-const
-  configPatternBegin = "############# begin Atlas config section ##########\n"
-  configPatternEnd =   "############# end Atlas config section   ##########\n"
-
-proc patchNimCfg(c: var AtlasContext; deps: seq[string]; cfgPath: string) =
-  var paths = "--noNimblePath\n"
-  for d in deps:
-    let pkgname = toDestDir d.PackageName
-    let x = relativePath(c.workspace / pkgname, cfgPath, '/')
-    paths.add "--path:\"" & x & "\"\n"
-  var cfgContent = configPatternBegin & paths & configPatternEnd
-
-  when MockupRun:
-    assert readFile(TestsDir / "nim.cfg") == cfgContent
-    c.mockupSuccess = true
-  else:
-    let cfg = cfgPath / "nim.cfg"
-    if cfgPath.len > 0 and not dirExists(cfgPath):
-      error(c, c.projectDir.PackageName, "could not write the nim.cfg")
-    elif not fileExists(cfg):
-      writeFile(cfg, cfgContent)
-    else:
-      let content = readFile(cfg)
-      let start = content.find(configPatternBegin)
-      if start >= 0:
-        cfgContent = content.substr(0, start-1) & cfgContent
-        let theEnd = content.find(configPatternEnd, start)
-        if theEnd >= 0:
-          cfgContent.add content.substr(theEnd+len(configPatternEnd))
-      else:
-        cfgContent = content & "\n" & cfgContent
-      if cfgContent != content:
-        # do not touch the file if nothing changed
-        # (preserves the file date information):
-        writeFile(cfg, cfgContent)
-
-proc error*(msg: string) =
-  when defined(debug):
-    writeStackTrace()
-  quit "[Error] " & msg
-
-proc findSrcDir(c: var AtlasContext): string =
-  for nimbleFile in walkPattern("*.nimble"):
-    let nimbleInfo = extractRequiresInfo(c, nimbleFile)
-    return nimbleInfo.srcDir
-  return ""
-
-proc installDependencies(c: var AtlasContext; nimbleFile: string) =
-  # 1. find .nimble file in CWD
-  # 2. install deps from .nimble
-  var work: seq[Dependency] = @[]
-  let (path, pkgname, _) = splitFile(nimbleFile)
-  let dep = Dependency(name: toName(pkgname), url: "", commit: "")
-  discard collectDeps(c, work, dep, nimbleFile)
-  let paths = cloneLoop(c, work)
-  patchNimCfg(c, paths, if c.cfgHere: getCurrentDir() else: findSrcDir(c))
-
-proc main =
-  var action = ""
-  var args: seq[string] = @[]
-  template singleArg() =
-    if args.len != 1:
-      error action & " command takes a single package name"
-
-  template noArgs() =
-    if args.len != 0:
-      error action & " command takes no arguments"
-
-  var c = AtlasContext(
-    projectDir: getCurrentDir(),
-    workspace: "")
-
-  for kind, key, val in getopt():
-    case kind
-    of cmdArgument:
-      if action.len == 0:
-        action = key.normalize
-      else:
-        args.add key
-    of cmdLongOption, cmdShortOption:
-      case normalize(key)
-      of "help", "h": writeHelp()
-      of "version", "v": writeVersion()
-      of "keepcommits": c.keepCommits = true
-      of "workspace":
-        if val.len > 0:
-          c.workspace = val
-          createDir(val)
-        else:
-          writeHelp()
-      of "cfghere": c.cfgHere = true
-      else: writeHelp()
-    of cmdEnd: assert false, "cannot happen"
-
-  if c.workspace.len > 0:
-    if not dirExists(c.workspace): error "Workspace directory '" & c.workspace & "' not found."
-  else:
-    c.workspace = getCurrentDir()
-    while c.workspace.len > 0 and dirExists(c.workspace / ".git"):
-      c.workspace = c.workspace.parentDir()
-  echo "Using workspace ", c.workspace
-
-  case action
-  of "":
-    error "No action."
-  of "clone":
-    singleArg()
-    let deps = clone(c, args[0])
-    patchNimCfg c, deps, if c.cfgHere: getCurrentDir() else: findSrcDir(c)
-    when MockupRun:
-      if not c.mockupSuccess:
-        error "There were problems."
-    else:
-      if c.errors > 0:
-        error "There were problems."
-  of "install":
-    if args.len > 1:
-      error "install command takes a single argument"
-    var nimbleFile = ""
-    if args.len == 1:
-      nimbleFile = args[0]
-    else:
-      for x in walkPattern("*.nimble"):
-        nimbleFile = x
-        break
-    if nimbleFile.len == 0:
-      error "could not find a .nimble file"
-    installDependencies(c, nimbleFile)
-  of "refresh":
-    noArgs()
-    updatePackages(c)
-  of "search", "list":
-    updatePackages(c)
-    search getPackages(c.workspace), args
-  of "extract":
-    singleArg()
-    if fileExists(args[0]):
-      echo toJson(extractRequiresInfo(args[0]))
-    else:
-      error "File does not exist: " & args[0]
-  else:
-    error "Invalid action: " & action
-
-when isMainModule:
-  main()
-
-when false:
-  # some testing code for the `patchNimCfg` logic:
-  var c = AtlasContext(
-    projectDir: getCurrentDir(),
-    workspace: getCurrentDir().parentDir)
-
-  patchNimCfg(c, @[PackageName"abc", PackageName"xyz"])
-
-when false:
-  assert sameVersionAs("v0.2.0", "0.2.0")
-  assert sameVersionAs("v1", "1")
-
-  assert sameVersionAs("1.90", "1.90")
-
-  assert sameVersionAs("v1.2.3-zuzu", "1.2.3")
-  assert sameVersionAs("foo-1.2.3.4", "1.2.3.4")
-
-  assert not sameVersionAs("foo-1.2.3.4", "1.2.3")
-  assert not sameVersionAs("foo", "1.2.3")
-  assert not sameVersionAs("", "1.2.3")
diff --git a/tools/atlas/osutils.nim b/tools/atlas/osutils.nim
deleted file mode 100644
index 6134830b5..000000000
--- a/tools/atlas/osutils.nim
+++ /dev/null
@@ -1,51 +0,0 @@
-## OS utilities like 'withDir'.
-## (c) 2021 Andreas Rumpf
-
-import os, strutils, osproc
-
-proc isUrl*(x: string): bool =
-  x.startsWith("git://") or x.startsWith("https://") or x.startsWith("http://")
-
-proc cloneUrl*(url, dest: string; cloneUsingHttps: bool): string =
-  ## Returns an error message on error or else "".
-  result = ""
-  var modUrl =
-    if url.startsWith("git://") and cloneUsingHttps:
-      "https://" & url[6 .. ^1]
-    else: url
-
-  # github + https + trailing url slash causes a
-  # checkout/ls-remote to fail with Repository not found
-  var isGithub = false
-  if modUrl.contains("github.com") and modUrl.endsWith("/"):
-    modUrl = modUrl[0 .. ^2]
-    isGithub = true
-
-  let (_, exitCode) = execCmdEx("git ls-remote --quiet --tags " & modUrl)
-  var xcode = exitCode
-  if isGithub and exitCode != QuitSuccess:
-    # retry multiple times to avoid annoying github timeouts:
-    for i in 0..4:
-      os.sleep(4000)
-      xcode = execCmdEx("git ls-remote --quiet --tags " & modUrl)[1]
-      if xcode == QuitSuccess: break
-
-  if xcode == QuitSuccess:
-    # retry multiple times to avoid annoying github timeouts:
-    let cmd = "git clone " & modUrl & " " & dest
-    for i in 0..4:
-      if execShellCmd(cmd) == 0: return ""
-      os.sleep(4000)
-    result = "exernal program failed: " & cmd
-  elif not isGithub:
-    let (_, exitCode) = execCmdEx("hg identify " & modUrl)
-    if exitCode == QuitSuccess:
-      let cmd = "hg clone " & modUrl & " " & dest
-      for i in 0..4:
-        if execShellCmd(cmd) == 0: return ""
-        os.sleep(4000)
-      result = "exernal program failed: " & cmd
-    else:
-      result = "Unable to identify url: " & modUrl
-  else:
-    result = "Unable to identify url: " & modUrl
diff --git a/tools/atlas/packagesjson.nim b/tools/atlas/packagesjson.nim
deleted file mode 100644
index 0b8599769..000000000
--- a/tools/atlas/packagesjson.nim
+++ /dev/null
@@ -1,114 +0,0 @@
-
-import std / [json, os, sets, strutils]
-
-type
-  Package* = ref object
-    # Required fields in a package.
-    name*: string
-    url*: string # Download location.
-    license*: string
-    downloadMethod*: string
-    description*: string
-    tags*: seq[string] # \
-    # From here on, optional fields set to the empty string if not available.
-    version*: string
-    dvcsTag*: string
-    web*: string # Info url for humans.
-
-proc optionalField(obj: JsonNode, name: string, default = ""): string =
-  if hasKey(obj, name) and obj[name].kind == JString:
-    result = obj[name].str
-  else:
-    result = default
-
-proc requiredField(obj: JsonNode, name: string): string =
-  result = optionalField(obj, name, "")
-
-proc fromJson*(obj: JSonNode): Package =
-  result = Package()
-  result.name = obj.requiredField("name")
-  if result.name.len == 0: return nil
-  result.version = obj.optionalField("version")
-  result.url = obj.requiredField("url")
-  if result.url.len == 0: return nil
-  result.downloadMethod = obj.requiredField("method")
-  if result.downloadMethod.len == 0: return nil
-  result.dvcsTag = obj.optionalField("dvcs-tag")
-  result.license = obj.optionalField("license")
-  result.tags = @[]
-  for t in obj["tags"]:
-    result.tags.add(t.str)
-  result.description = obj.requiredField("description")
-  result.web = obj.optionalField("web")
-
-const PackagesDir* = "packages"
-
-proc getPackages*(workspaceDir: string): seq[Package] =
-  result = @[]
-  var uniqueNames = initHashSet[string]()
-  var jsonFiles = 0
-  for kind, path in walkDir(workspaceDir / PackagesDir):
-    if kind == pcFile and path.endsWith(".json"):
-      inc jsonFiles
-      let packages = json.parseFile(path)
-      for p in packages:
-        let pkg = p.fromJson()
-        if pkg != nil and not uniqueNames.containsOrIncl(pkg.name):
-          result.add(pkg)
-
-proc `$`*(pkg: Package): string =
-  result = pkg.name & ":\n"
-  result &= "  url:         " & pkg.url & " (" & pkg.downloadMethod & ")\n"
-  result &= "  tags:        " & pkg.tags.join(", ") & "\n"
-  result &= "  description: " & pkg.description & "\n"
-  result &= "  license:     " & pkg.license & "\n"
-  if pkg.web.len > 0:
-    result &= "  website:     " & pkg.web & "\n"
-
-proc search*(pkgList: seq[Package]; terms: seq[string]) =
-  var found = false
-  template onFound =
-    echo pkg
-    found = true
-    break forPackage
-
-  for pkg in pkgList:
-    if terms.len > 0:
-      block forPackage:
-        for term in terms:
-          let word = term.toLower
-          # Search by name.
-          if word in pkg.name.toLower:
-            onFound()
-          # Search by tag.
-          for tag in pkg.tags:
-            if word in tag.toLower:
-              onFound()
-    else:
-      echo(pkg)
-
-  if not found and terms.len > 0:
-    echo("No package found.")
-
-type PkgCandidates* = array[3, seq[Package]]
-
-proc determineCandidates*(pkgList: seq[Package];
-                         terms: seq[string]): PkgCandidates =
-  result[0] = @[]
-  result[1] = @[]
-  result[2] = @[]
-  for pkg in pkgList:
-    block termLoop:
-      for term in terms:
-        let word = term.toLower
-        if word == pkg.name.toLower:
-          result[0].add pkg
-          break termLoop
-        elif word in pkg.name.toLower:
-          result[1].add pkg
-          break termLoop
-        else:
-          for tag in pkg.tags:
-            if word in tag.toLower:
-              result[2].add pkg
-              break termLoop
diff --git a/tools/atlas/parse_requires.nim b/tools/atlas/parse_requires.nim
index 7e26a1656..66879d04f 100644
--- a/tools/atlas/parse_requires.nim
+++ b/tools/atlas/parse_requires.nim
@@ -2,7 +2,7 @@
 ## (c) 2021 Andreas Rumpf
 
 import std / strutils
-import ".." / compiler / [ast, idents, msgs, syntaxes, options, pathutils]
+import ".." / ".." / compiler / [ast, idents, msgs, syntaxes, options, pathutils]
 
 type
   NimbleFileInfo* = object
diff --git a/tools/atlas/testdata.nim b/tools/atlas/testdata.nim
deleted file mode 100644
index aefaeacd2..000000000
--- a/tools/atlas/testdata.nim
+++ /dev/null
@@ -1,63 +0,0 @@
-
-type
-  PerDirData = object
-    dirname: string
-    cmd: Command
-    exitCode: int
-    output: string
-
-template toData(a, b, c, d): untyped =
-  PerDirData(dirname: a, cmd: b, exitCode: c, output: d)
-
-const
-  TestLog = [
-    toData("balls", GitPull, 0, "Already up to date.\n"),
-    toData("grok", GitDiff, 0, ""),
-    toData("grok", GitTags, 0, "2ca193c31fa2377c1e991a080d60ca3215ff6cf0 refs/tags/0.0.1\n48007554b21ba2f65c726ae2fdda88d621865b4a refs/tags/0.0.2\n7092a0286421c7818cd335cca9ebc72d03d866c2 refs/tags/0.0.3\n62707b8ac684efac35d301dbde57dc750880268e refs/tags/0.0.4\n876f2504e0c2f785ffd2cf65a78e2aea474fa8aa refs/tags/0.0.5\nb7eb1f2501aa2382cb3a38353664a13af62a9888 refs/tags/0.0.6\nf5d818bfd6038884b3d8b531c58484ded20a58a4 refs/tags/0.1.0\n961eaddea49c3144d130d105195583d3f11fb6c6 refs/tags/0.2.0\n15ab8ed8d4f896232a976a9008548bd53af72a66 refs/tags/0.2.1\n426a7d7d4603f77ced658e73ad7f3f582413f6cd refs/tags/0.3.0\n83cf7a39b2fe897786fb0fe01a7a5933c3add286 refs/tags/0.3.1\n8d2e3c900edbc95fa0c036fd76f8e4f814aef2c1 refs/tags/0.3.2\n48b43372f49a3bb4dc0969d82a0fca183fb94662 refs/tags/0.3.3\n9ca947a3009ea6ba17814b20eb953272064eb2e6 refs/tags/0.4.0\n1b5643d04fba6d996a16d1ffc13d034a40003f8f refs/tags/0.5.0\n486b0eb580b1c465453d264ac758cc490c19c33e refs/tags/0.5.1\naedb0d9497390e20b9d2541cef2bb05a5cda7a71 refs/tags/0.5.2\n"),
-    toData("grok", GitCurrentCommit, 0, "349c15fd1e03f1fcdd81a1edefba3fa6116ab911\n"),
-    toData("grok", GitMergeBase, 0, "349c15fd1e03f1fcdd81a1edefba3fa6116ab911\n1b5643d04fba6d996a16d1ffc13d034a40003f8f\n349c15fd1e03f1fcdd81a1edefba3fa6116ab911\n"),
-    toData("grok", GitCheckout, 0, "1b5643d04fba6d996a16d1ffc13d034a40003f8f"), # watch out!
-
-    toData("ups", GitDiff, 0, ""),
-    toData("ups", GitTags, 0, "4008f9339cd22b30e180bc87a6cca7270fd28ac1 refs/tags/0.0.2\n19bc490c22b4f5b0628c31cdedead1375b279356 refs/tags/0.0.3\nff34602aaea824cb46d6588cd5fe1178132e9702 refs/tags/0.0.4\n09de599138f20b745133b6e4fe563e204415a7e8 refs/tags/0.0.5\n85fee3b74798311108a105635df31f892150f5d0 refs/tags/0.0.6\nfd303913b22b121dc42f332109e9c44950b9acd4 refs/tags/0.0.7\n"),
-    toData("ups", GitCurrentCommit, 0, "74c31af8030112dac758440aa51ef175992f71f3\n"),
-    toData("ups", GitMergeBase, 0, "74c31af8030112dac758440aa51ef175992f71f3\n4008f9339cd22b30e180bc87a6cca7270fd28ac1\n74c31af8030112dac758440aa51ef175992f71f3\n"),
-    toData("ups", GitCheckout, 0, "4008f9339cd22b30e180bc87a6cca7270fd28ac1"),
-
-    toData("sync", GitDiff, 0, ""),
-    toData("sync", GitRevParse, 0, "810bd2d75e9f6e182534ae2488670b51a9f13fc3\n"),
-    toData("sync", GitCurrentCommit, 0, "de5c7337ebc22422190e8aeca37d05651735f440\n"),
-    toData("sync", GitMergeBase, 0, "de5c7337ebc22422190e8aeca37d05651735f440\n810bd2d75e9f6e182534ae2488670b51a9f13fc3\n810bd2d75e9f6e182534ae2488670b51a9f13fc3\n"),
-
-    toData("npeg", GitDiff, 0, ""),
-    toData("npeg", GitTags, 0, "8df2f0c9391995fd086b8aab00e8ab7aded1e8f0 refs/tags/0.1.0\n4c959a72db5283b55eeef491076eefb5e02316f1 refs/tags/0.10.0\n802f47c0f7f4318a4f0858ba5a6a6ed2333bde71 refs/tags/0.11.0\n82c8d92837108dce225358ace2c416bf9a3f30ce refs/tags/0.12.0\n87d2f2c4f6ef7da350d45beb5a336611bde7f518 refs/tags/0.13.0\n39964f0d220bfaade47a568bf03c1cf28aa2bc37 refs/tags/0.14.0\nbe9f03f92304cbeab70572944a8563db9b23b2fb refs/tags/0.14.1\na933fb9832566fc95273e417597bfb4faf564ca6 refs/tags/0.15.0\n6aad2e438c52ff0636c7bfb64338e444ac3e83ba refs/tags/0.16.0\nf4ddffb5848c42c6151743dd9c7eddcaaabc56cc refs/tags/0.17.0\n30b446b39442cdbc53a97018ab8a54149aa7c3b7 refs/tags/0.17.1\n1a9d36aa3b34a6169d4530463f1c17a3fe1e075e refs/tags/0.18.0\ndd34f903a9a63b876cb2db19b7a4ce0bcc252134 refs/tags/0.19.0\nd93d49c81fc8722d7929ac463b435c0f2e10c53b refs/tags/0.2.0\neeae7746c9b1118bcf27744ab2aee26969051256 refs/tags/0.20.0\n8c3471a548129f3bf62df15cd0fd8cca1787d852 refs/tags/0.21.0\nc0e873a17bc713c80e74fec3c30cb62dcd5d194a refs/tags/0.21.1\nbae84c47a1bb259b209b6f6be1582327b784539d refs/tags/0.21.2\nbfcb4bcae76a917c3c88736ca773e4cb67dbb2d8 refs/tags/0.21.3\n0eabb7c462d30932049f0b7e6a030c1562cf9fee refs/tags/0.22.0\n2e75367095f54d4351005078bad98041a55b14c1 refs/tags/0.22.1\n814ea235dd398108d7b18f966694c3d951575701 refs/tags/0.22.2\na812064587d983c129737f8500bf74990e6b8dab refs/tags/0.23.0\nbd969ad3745db0d66022564cac76cf9424651104 refs/tags/0.23.1\na037c646a47623b92718efadc2bb74d03664b360 refs/tags/0.23.2\n078475ccceeaca0fac947492acdd24514da8d863 refs/tags/0.24.0\ne7bd87dc992512fd5825a557a56907647e03c979 refs/tags/0.24.1\n45ea601e1c7f64fb857bc99df984b86673621d2c refs/tags/0.3.0\n1ea9868a3fee3aa487ab7ec9129208a4dd483d0d refs/tags/0.4.0\n39afdb5733d3245386d29d08c5ff61c89268f499 refs/tags/0.5.0\n458c7b5910fcb157af3fc51bc3b3e663fdb3ed4a refs/tags/0.6.0\n06c38bd8563d822455bc237c2a98c153d938ed1b refs/tags/0.7.0\nf446b6056eef6d8dc9d8b47a79aca93d17dc8230 refs/tags/0.8.0\nbb25a195133f9f7af06386d0809793923cc5e8ab refs/tags/0.9.0\n"),
-    toData("npeg", GitCurrentCommit, 0, "5d80f93aa720898936668b3bc47d0fff101ec414\n"),
-    toData("npeg", GitMergeBase, 0, "5d80f93aa720898936668b3bc47d0fff101ec414\na037c646a47623b92718efadc2bb74d03664b360\na037c646a47623b92718efadc2bb74d03664b360\n"),
-
-    toData("testes", GitDiff, 0, ""),
-    toData("testes", GitTags, 0, "3ce9b2968b5f644755a0ced1baa3eece88c2f12e refs/tags/0.1.0\nf73af8318b54737678fab8b54bdcd8a451015e0d refs/tags/0.1.1\nd21d84d37b161a123a43318bae353108755916de refs/tags/0.1.2\n5c36b6095353ed03b08ac939d00aff2d73f79a35 refs/tags/0.1.3\na1220d11237ee8f135f772ff9731c11b2d91ba31 refs/tags/0.1.4\n574f741b90d04a7ce8c9b990e6077708d7ad076e refs/tags/0.1.5\nced0a9e58234b680def6931578e09165a32e6291 refs/tags/0.1.6\nbb248952e8742a6011eb1a45a9d2059aeb0341d7 refs/tags/0.1.7\nabb7d7c552da0a8e0ddc586c15ccf7e74b0d068b refs/tags/0.10.0\n6e42a768a90d6442196b344bcdcb6f834b76e7b7 refs/tags/0.2.0\n9d136c3a0851ca2c021f5fb4f7b63f0a0ef77232 refs/tags/0.2.1\ndcb282b2da863fd2939e1969cec7a99788feb456 refs/tags/0.2.2\nf708a632afaa40a322a1a61c1c13722edac8e8c5 refs/tags/0.3.0\n3213f59e3f9ba052452c59f01d1418360d856af6 refs/tags/0.3.1\nf7bb1743dffd327958dfcebae4cfb6f61cc1cb8c refs/tags/0.3.2\n6b64569ebecad6bc60cc8697713701e7659204f4 refs/tags/0.3.3\nb51c25a4367bd17f419f78cb5a27f319e9d820f5 refs/tags/0.3.4\nb265612710cbd5ddb1b173c94ece8ec5c7ceccac refs/tags/0.3.5\ne404bcfe42e92d7509717a2dfa115cacb4964c5d refs/tags/0.3.6\n5e4d0d5b7e7f314dde701c546c4365c59782d3dc refs/tags/0.3.7\ne13f91c9c913d2b81c59adeaad687efa2b35293a refs/tags/0.3.8\n17599625f09af0ae4b525e63ab726a3002540702 refs/tags/0.3.9\n13e907f70571dd146d8dc29ddec4599b40ba4e85 refs/tags/0.4.0\n155a74cf676495df1e0674dd07b5e4a0291a9a4a refs/tags/0.4.1\nf37abccdc148cb02ca637a6f0bc8821491cce358 refs/tags/0.4.2\n0250d29ebdd02f28f9020445adb5a4e51fd1902c refs/tags/0.5.0\n2fb87db6d9f34109a70205876030c53f815739b7 refs/tags/0.5.1\n629d17ba8d6a1a4eca8145eb089ed5bca4473dfc refs/tags/0.6.0\ne926130f5f1b7903f68be49cc1563225bd9d948d refs/tags/0.7.0\n7365303897e6185796c274425c079916047e3f14 refs/tags/0.7.1\na735c4adabeba637409f41c4325dd8fc5fb91e2d refs/tags/0.7.10\nfe023fd27404889c5122f902456cbba14b767405 refs/tags/0.7.11\n4430e72972c77a5e9c1555d59bba11d840682691 refs/tags/0.7.12\nf0e53eb490a9558c7f594d2e095b70665e36ca88 refs/tags/0.7.13\nf6520e25e7c329c2957cda447f149fc6a930db0d refs/tags/0.7.2\nd509762f7191757c240d3c79c9ecda53f8c0cfe3 refs/tags/0.7.3\nc02e7a783d1c42fd1f91bca7142f7c3733950c05 refs/tags/0.7.4\n8c8a9e496e9b86ba7602709438980ca31e6989d9 refs/tags/0.7.5\n29839c18b4ac83c0111a178322b57ebb8a8d402c refs/tags/0.7.6\n3b62973cf74fafd8ea906644d89ac34d29a8a6cf refs/tags/0.7.7\ne67ff99dc43c391e89a37f97a9d298c3428bbde2 refs/tags/0.7.8\n4b72ecda0d40ed8e5ab8ad4095a0691d30ec6cd0 refs/tags/0.7.9\n2512b8cc3d7f001d277e89978da2049a5feee5c4 refs/tags/0.8.0\n86c47029690bd2731d204245f3f54462227bba0d refs/tags/0.9.0\n9a7f94f78588e9b5ba7ca077e1f7eae0607c6cf6 refs/tags/0.9.1\n08c915dc016d16c1dfa9a77d0b045ec29c9f2074 refs/tags/0.9.2\n3fb658b1ce1e1efa37d6f9f14322bdac8def02a5 refs/tags/0.9.3\n738fda0add962379ffe6aa6ca5f01a6943a98a2e refs/tags/0.9.4\n48d821add361f7ad768ecb35a0b19c38f90c919e refs/tags/0.9.5\nff9ae890f597dac301b2ac6e6805eb9ac5afd49a refs/tags/0.9.6\n483c78f06e60b0ec5e79fc3476df075ee7286890 refs/tags/0.9.7\n416eec87a5ae39a1a6035552e9e9a47d76b13026 refs/tags/1.0.0\na935cfe9445cc5218fbdd7e0afb35aa1587fff61 refs/tags/1.0.1\n4b83863a9181f054bb695b11b5d663406dfd85d2 refs/tags/1.0.2\n295145fddaa4fe29c1e71a5044d968a84f9dbf69 refs/tags/1.1.0\n8f74ea4e5718436c47305b4488842e6458a13dac refs/tags/1.1.1\n4135bb291e53d615a976e997c44fb2bd9e1ad343 refs/tags/1.1.10\n8c09dbcd16612f5989065db02ea2e7a752dd2656 refs/tags/1.1.11\naedfebdb6c016431d84b0c07cf181b957a900640 refs/tags/1.1.12\n2c2e958366ef6998115740bdf110588d730e5738 refs/tags/1.1.2\nbecc77258321e6ec40d89efdddf37bafd0d07fc3 refs/tags/1.1.3\ne070d7c9853bf94c35b81cf0c0a8980c2449bb22 refs/tags/1.1.4\n12c986cbbf65e8571a486e9230808bf887e5f04f refs/tags/1.1.5\n63df8986f5b56913b02d26954fa033eeaf43714c refs/tags/1.1.6\n38e02c9c6bd728b043036fe0d1894d774cab3108 refs/tags/1.1.7\n3c3879fff16450d28ade79a6b08982bf5cefc061 refs/tags/1.1.8\ne32b811b3b2e70a1d189d7a663bc2583e9c18f96 refs/tags/1.1.9\n0c1b4277c08197ce7e7e0aa2bad91d909fcd96ac refs/tags/2.0.0\n"),
-    toData("testes", GitCurrentCommit, 0, "d9db2ad09aa38fc26625341e1b666602959e144f\n"),
-    toData("testes", GitMergeBase, 0, "d9db2ad09aa38fc26625341e1b666602959e144f\n416eec87a5ae39a1a6035552e9e9a47d76b13026\nd9db2ad09aa38fc26625341e1b666602959e144f\n"),
-    toData("testes", GitCheckout, 0, "416eec87a5ae39a1a6035552e9e9a47d76b13026"),
-
-    toData("grok", GitDiff, 0, ""),
-    toData("grok", GitTags, 0, "2ca193c31fa2377c1e991a080d60ca3215ff6cf0 refs/tags/0.0.1\n48007554b21ba2f65c726ae2fdda88d621865b4a refs/tags/0.0.2\n7092a0286421c7818cd335cca9ebc72d03d866c2 refs/tags/0.0.3\n62707b8ac684efac35d301dbde57dc750880268e refs/tags/0.0.4\n876f2504e0c2f785ffd2cf65a78e2aea474fa8aa refs/tags/0.0.5\nb7eb1f2501aa2382cb3a38353664a13af62a9888 refs/tags/0.0.6\nf5d818bfd6038884b3d8b531c58484ded20a58a4 refs/tags/0.1.0\n961eaddea49c3144d130d105195583d3f11fb6c6 refs/tags/0.2.0\n15ab8ed8d4f896232a976a9008548bd53af72a66 refs/tags/0.2.1\n426a7d7d4603f77ced658e73ad7f3f582413f6cd refs/tags/0.3.0\n83cf7a39b2fe897786fb0fe01a7a5933c3add286 refs/tags/0.3.1\n8d2e3c900edbc95fa0c036fd76f8e4f814aef2c1 refs/tags/0.3.2\n48b43372f49a3bb4dc0969d82a0fca183fb94662 refs/tags/0.3.3\n9ca947a3009ea6ba17814b20eb953272064eb2e6 refs/tags/0.4.0\n1b5643d04fba6d996a16d1ffc13d034a40003f8f refs/tags/0.5.0\n486b0eb580b1c465453d264ac758cc490c19c33e refs/tags/0.5.1\naedb0d9497390e20b9d2541cef2bb05a5cda7a71 refs/tags/0.5.2\n"),
-    toData("grok", GitCurrentCommit, 0, "4e6526a91a23eaec778184e16ce9a34d25d48bdc\n"),
-    toData("grok", GitMergeBase, 0, "4e6526a91a23eaec778184e16ce9a34d25d48bdc\n62707b8ac684efac35d301dbde57dc750880268e\n349c15fd1e03f1fcdd81a1edefba3fa6116ab911\n"),
-    toData("grok", GitCheckout, 0, "62707b8ac684efac35d301dbde57dc750880268e"),
-
-    toData("nim-bytes2human", GitDiff, 0, ""),
-    toData("nim-bytes2human", GitTags, 0, ""),
-    toData("nim-bytes2human", GitCurrentcommit, 0, "ec2c1a758cabdd4751a06c8ebf2b923f19e32731\n")
-  ]
-
-#[
-Current directory is now E:\atlastest\nim-bytes2human
-cmd git diff args [] --> ("", 0)
-cmd git show-ref --tags args [] --> ("", 1)
-cmd git log -n 1 --format=%H args [] --> (, 0)
-[Warning] (nim-bytes2human) package has no tagged releases
-nimble E:\atlastest\nim-bytes2human\bytes2human.nimble info (requires: @["nim >= 1.0.0"], srcDir: "src", tasks: @[])
-[Error] There were problems.
-Error: execution of an external program failed: 'E:\nim\tools\atlas\atlas.exe clone https://github.com/disruptek/balls'
-]#
diff --git a/tools/atlas/tests/balls.nimble b/tools/atlas/tests/balls.nimble
deleted file mode 100644
index 143e757e9..000000000
--- a/tools/atlas/tests/balls.nimble
+++ /dev/null
@@ -1,32 +0,0 @@
-version = "3.4.1"
-author = "disruptek"
-description = "a unittest framework with balls 🔴🟡🟢"
-license = "MIT"
-
-# requires newTreeFrom
-requires "https://github.com/disruptek/grok >= 0.5.0 & < 1.0.0"
-requires "https://github.com/disruptek/ups < 1.0.0"
-requires "https://github.com/planetis-m/sync#810bd2d"
-#requires "https://github.com/c-blake/cligen < 2.0.0"
-
-bin = @["balls"]            # build the binary for basic test running
-installExt = @["nim"]       # we need to install balls.nim also
-skipDirs = @["tests"]       # so stupid...  who doesn't want tests?
-#installFiles = @["balls.nim"] # https://github.com/nim-lang/Nim/issues/16661
-
-task test, "run tests for ci":
-  when defined(windows):
-    exec "balls.cmd"
-  else:
-    exec "balls"
-
-task demo, "produce a demo":
-  exec "nim c --define:release balls.nim"
-  when (NimMajor, NimMinor) != (1, 0):
-    echo "due to nim bug #16307, use nim-1.0"
-    quit 1
-  exec """demo docs/demo.svg "nim c --out=\$1 examples/fails.nim""""
-  exec """demo docs/clean.svg "nim c --define:danger -f --out=\$1 tests/test.nim""""
-  exec "nim c --define:release --define:ballsDry balls.nim"
-  exec """demo docs/runner.svg "balls""""
-
diff --git a/tools/atlas/tests/grok.nimble b/tools/atlas/tests/grok.nimble
deleted file mode 100644
index 1b6d77c08..000000000
--- a/tools/atlas/tests/grok.nimble
+++ /dev/null
@@ -1,5 +0,0 @@
-version = "0.0.4"
-author = "disruptek"
-description = "don't read too much into it"
-license = "MIT"
-requires "nim >= 1.0.0"
diff --git a/tools/atlas/tests/nim-bytes2human.nimble b/tools/atlas/tests/nim-bytes2human.nimble
deleted file mode 100644
index 9f3ae2479..000000000
--- a/tools/atlas/tests/nim-bytes2human.nimble
+++ /dev/null
@@ -1,7 +0,0 @@
-version     = "0.2.2"
-author      = "Juan Carlos"
-description = "Convert bytes to kilobytes, megabytes, gigabytes, etc."
-license     = "MIT"
-srcDir      = "src"
-
-requires "nim >= 1.0.0"  # https://github.com/juancarlospaco/nim-bytes2human/issues/2#issue-714338524
diff --git a/tools/atlas/tests/nim.cfg b/tools/atlas/tests/nim.cfg
deleted file mode 100644
index 5f568569b..000000000
--- a/tools/atlas/tests/nim.cfg
+++ /dev/null
@@ -1,11 +0,0 @@
-############# begin Atlas config section ##########
---noNimblePath
---path:"../balls"
---path:"../grok"
---path:"../ups"
---path:"../sync"
---path:"../npeg/src"
---path:"../testes"
---path:"../grok"
---path:"../nim-bytes2human/src"
-############# end Atlas config section   ##########
diff --git a/tools/atlas/tests/npeg.nimble b/tools/atlas/tests/npeg.nimble
deleted file mode 100644
index e71fc5aa5..000000000
--- a/tools/atlas/tests/npeg.nimble
+++ /dev/null
@@ -1,48 +0,0 @@
-# Package
-
-version       = "0.24.1"
-author        = "Ico Doornekamp"
-description   = "a PEG library"
-license       = "MIT"
-srcDir        = "src"
-installExt    = @["nim"]
-
-# Dependencies
-
-requires "nim >= 0.19.0"
-
-# Test
-
-task test, "Runs the test suite":
-  exec "nimble testc && nimble testcpp && nimble testarc && nimble testjs"
-
-task testc, "C tests":
-  exec "nim c -r tests/tests.nim"
-
-task testcpp, "CPP tests":
-  exec "nim cpp -r tests/tests.nim"
-
-task testjs, "JS tests":
-  exec "nim js -r tests/tests.nim"
-
-task testdanger, "Runs the test suite in danger mode":
-  exec "nim c -d:danger -r tests/tests.nim"
-
-task testwin, "Mingw tests":
-  exec "nim c -d:mingw tests/tests.nim && wine tests/tests.exe"
-
-task test32, "32 bit tests":
-  exec "nim c --cpu:i386 --passC:-m32 --passL:-m32 tests/tests.nim && tests/tests"
-
-task testall, "Test all":
-  exec "nimble test && nimble testcpp && nimble testdanger && nimble testjs && nimble testwin"
-
-when (NimMajor, NimMinor) >= (1, 1):
-  task testarc, "--gc:arc tests":
-    exec "nim c --gc:arc -r tests/tests.nim"
-else:
-  task testarc, "--gc:arc tests":
-    exec "true"
-
-task perf, "Test performance":
-  exec "nim cpp -r -d:danger tests/performance.nim"
diff --git a/tools/atlas/tests/packages/packages.json b/tools/atlas/tests/packages/packages.json
deleted file mode 100644
index d054a201b..000000000
--- a/tools/atlas/tests/packages/packages.json
+++ /dev/null
@@ -1,36 +0,0 @@
-[
-  {
-    "name": "bytes2human",
-    "url": "https://github.com/juancarlospaco/nim-bytes2human",
-    "method": "git",
-    "tags": [
-      "bytes",
-      "human",
-      "minimalism",
-      "size"
-    ],
-    "description": "Convert bytes to kilobytes, megabytes, gigabytes, etc.",
-    "license": "LGPLv3",
-    "web": "https://github.com/juancarlospaco/nim-bytes2human"
-  },
-  {
-    "name": "npeg",
-    "url": "https://github.com/zevv/npeg",
-    "method": "git",
-    "tags": [
-      "PEG",
-      "parser",
-      "parsing",
-      "regexp",
-      "regular",
-      "grammar",
-      "lexer",
-      "lexing",
-      "pattern",
-      "matching"
-    ],
-    "description": "PEG (Parsing Expression Grammars) string matching library for Nim",
-    "license": "MIT",
-    "web": "https://github.com/zevv/npeg"
-  }
-]
diff --git a/tools/atlas/tests/sync.nimble b/tools/atlas/tests/sync.nimble
deleted file mode 100644
index a07ae8925..000000000
--- a/tools/atlas/tests/sync.nimble
+++ /dev/null
@@ -1,10 +0,0 @@
-# Package
-
-version     = "1.4.0"
-author      = "Antonis Geralis"
-description = "Useful synchronization primitives."
-license     = "MIT"
-
-# Deps
-
-requires "nim >= 1.0.0"
diff --git a/tools/atlas/tests/testes.nimble b/tools/atlas/tests/testes.nimble
deleted file mode 100644
index 60fe1d508..000000000
--- a/tools/atlas/tests/testes.nimble
+++ /dev/null
@@ -1,23 +0,0 @@
-version = "1.0.0"
-author = "disruptek"
-description = "a cure for salty testes"
-license = "MIT"
-
-#requires "cligen >= 0.9.41 & <= 0.9.45"
-#requires "bump >= 1.8.18 & < 2.0.0"
-requires "https://github.com/disruptek/grok >= 0.0.4 & < 1.0.0"
-requires "https://github.com/juancarlospaco/nim-bytes2human"
-
-bin = @["testes"]           # build the binary for basic test running
-installExt = @["nim"]       # we need to install testes.nim also
-skipDirs = @["tests"]       # so stupid...  who doesn't want tests?
-
-task test, "run tests for ci":
-  exec "nim c --run testes.nim"
-
-task demo, "produce a demo":
-  when (NimMajor, NimMinor) != (1, 0):
-    echo "due to nim bug #16307, use nim-1.0"
-    quit 1
-  exec """demo docs/demo.svg "nim c --out=\$1 examples/balls.nim""""
-  exec """demo docs/clean.svg "nim c --define:danger --out=\$1 tests/testicles.nim""""
diff --git a/tools/atlas/tests/ups.nimble b/tools/atlas/tests/ups.nimble
deleted file mode 100644
index d91abbe60..000000000
--- a/tools/atlas/tests/ups.nimble
+++ /dev/null
@@ -1,13 +0,0 @@
-version = "0.0.2"
-author = "disruptek"
-description = "a package handler"
-license = "MIT"
-
-requires "npeg >= 0.23.2 & < 1.0.0"
-requires "https://github.com/disruptek/testes >= 1.0.0 & < 2.0.0"
-
-task test, "run tests":
-  when defined(windows):
-    exec "testes.cmd"
-  else:
-    exec findExe"testes"