diff --git a/atlas/atlas.nim b/atlas/atlas.nim deleted file mode 100644 index 2af1a3959c55..000000000000 --- a/atlas/atlas.nim +++ /dev/null @@ -1,1345 +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, tables, sets, json, jsonutils, - parsecfg, streams, terminal, strscans, hashes] -import parse_requires, osutils, packagesjson, compiledpatterns, versions, sat - -from unicode import nil - -const - AtlasVersion = "0.4" - LockFileName = "atlas.lock" - AtlasWorkspace = "atlas.workspace" - Usage = "atlas - Nim Package Cloner Version " & AtlasVersion & """ - - (c) 2021 Andreas Rumpf -Usage: - atlas [options] [command] [arguments] -Command: - init initializes the current directory as a workspace - --deps=DIR use DIR as the directory for dependencies - (default: store directly in the workspace) - - use url|pkgname clone a package and all of its dependencies and make - it importable for the current project - clone url|pkgname clone a package and all of its dependencies - update url|pkgname update 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 - updateProjects [filter] - update every project that has a remote - URL that matches `filter` if a filter is given - updateDeps [filter] - update every dependency that has a remote - URL that matches `filter` if a filter is given - tag [major|minor|patch] - add and push a new tag, input must be one of: - ['major'|'minor'|'patch'] or a SemVer tag like ['1.0.3'] - or a letter ['a'..'z']: a.b.c.d.e.f.g - outdated list the packages that are outdated - build|test|doc|tasks currently delegates to `nimble build|test|doc` - task currently delegates to `nimble ` - env setup a Nim virtual environment - --keep keep the c_code subdirectory - -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 - --project=DIR use DIR as the current project - --genlock generate a lock file (use with `clone` and `update`) - --uselock use the lock file for the build - --autoenv detect the minimal Nim $version and setup a - corresponding Nim virtual environment - --autoinit auto initialize a workspace - --colors=on|off turn on|off colored output - --resolver=minver|semver|maxver - which resolution algorithm to use, default is minver - --showGraph show the dependency graph - --version show the version - --help show this help -""" - -proc writeHelp() = - stdout.write(Usage) - stdout.flushFile() - quit(0) - -proc writeVersion() = - stdout.write(AtlasVersion & "\n") - stdout.flushFile() - quit(0) - -const - MockupRun = defined(atlasTests) - TestsDir = "atlas/tests" - -type - LockMode = enum - noLock, genLock, useLock - - LockFileEntry = object - url, commit: string - - PackageName = distinct string - CfgPath = distinct string # put into a config `--path:"../x"` - DepRelation = enum - normal, strictlyLess, strictlyGreater - - SemVerField = enum - major, minor, patch - - ResolutionAlgorithm = enum - MinVer, SemVer, MaxVer - - Dependency = object - name: PackageName - url, commit: string - query: VersionInterval - self: int # position in the graph - parents: seq[int] # why we need this dependency - active: bool - algo: ResolutionAlgorithm - DepGraph = object - nodes: seq[Dependency] - processed: Table[string, int] # the key is (url / commit) - byName: Table[PackageName, seq[int]] - availableVersions: Table[PackageName, seq[(string, Version)]] # sorted, latest version comes first - bestNimVersion: Version # Nim is a special snowflake - - LockFile = object # serialized as JSON so an object for extensibility - items: OrderedTable[string, LockFileEntry] - - Flag = enum - KeepCommits - CfgHere - UsesOverrides - Keep - NoColors - ShowGraph - AutoEnv - - AtlasContext = object - projectDir, workspace, depsDir, currentDir: string - hasPackageList: bool - flags: set[Flag] - p: Table[string, string] # name -> url mapping - errors, warnings: int - overrides: Patterns - lockMode: LockMode - lockFile: LockFile - defaultAlgo: ResolutionAlgorithm - when MockupRun: - step: int - mockupSuccess: bool - -proc `==`*(a, b: CfgPath): bool {.borrow.} - -proc `==`*(a, b: PackageName): bool {.borrow.} -proc hash*(a: PackageName): Hash {.borrow.} - -const - InvalidCommit = "#head" #"" - ProduceTest = false - -type - Command = enum - GitDiff = "git diff", - GitTag = "git tag", - GitTags = "git show-ref --tags", - GitLastTaggedRef = "git rev-list --tags --max-count=1", - GitDescribe = "git describe", - GitRevParse = "git rev-parse", - GitCheckout = "git checkout", - GitPush = "git push origin", - GitPull = "git pull", - GitCurrentCommit = "git log -n 1 --format=%H" - GitMergeBase = "git merge-base" - -include testdata - -proc silentExec(cmd: string; args: openArray[string]): (string, int) = - var cmdLine = cmd - for i in 0.. ", 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: - 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 isCleanGit(c: var AtlasContext): 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; arg: string) = - var msg = category & "(" & p.string & ") " & arg - stdout.writeLine msg - -proc warn(c: var AtlasContext; p: PackageName; arg: string) = - if NoColors in c.flags: - message(c, "[Warning] ", p, arg) - else: - stdout.styledWriteLine(fgYellow, styleBright, "[Warning] ", resetStyle, fgCyan, "(", p.string, ")", resetStyle, " ", arg) - inc c.warnings - -proc error(c: var AtlasContext; p: PackageName; arg: string) = - if NoColors in c.flags: - message(c, "[Error] ", p, arg) - else: - stdout.styledWriteLine(fgRed, styleBright, "[Error] ", resetStyle, fgCyan, "(", p.string, ")", resetStyle, " ", arg) - inc c.errors - -proc info(c: var AtlasContext; p: PackageName; arg: string) = - if NoColors in c.flags: - message(c, "[Info] ", p, arg) - else: - stdout.styledWriteLine(fgGreen, styleBright, "[Info] ", resetStyle, fgCyan, "(", p.string, ")", resetStyle, " ", arg) - -template projectFromCurrentDir(): PackageName = PackageName(c.currentDir.splitPath.tail) - -proc readableFile(s: string): string = relativePath(s, getCurrentDir()) - -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 gitDescribeRefTag(c: var AtlasContext; commit: string): string = - let (lt, status) = exec(c, GitDescribe, ["--tags", commit]) - result = if status == 0: strutils.strip(lt) else: "" - -proc getLastTaggedCommit(c: var AtlasContext): string = - let (ltr, status) = exec(c, GitLastTaggedRef, []) - if status == 0: - let lastTaggedRef = ltr.strip() - let lastTag = gitDescribeRefTag(c, lastTaggedRef) - if lastTag.len != 0: - result = lastTag - -proc collectTaggedVersions(c: var AtlasContext): seq[(string, Version)] = - let (outp, status) = exec(c, GitTags, []) - if status == 0: - result = parseTaggedVersions(outp) - else: - result = @[] - -proc versionToCommit(c: var AtlasContext; d: Dependency): string = - let allVersions = collectTaggedVersions(c) - case d.algo - of MinVer: - result = selectBestCommitMinVer(allVersions, d.query) - of SemVer: - result = selectBestCommitSemVer(allVersions, d.query) - of MaxVer: - result = selectBestCommitMaxVer(allVersions, d.query) - -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 gitTag(c: var AtlasContext; tag: string) = - let (_, status) = exec(c, GitTag, [tag]) - if status != 0: - error(c, c.projectDir.PackageName, "could not 'git tag " & tag & "'") - -proc pushTag(c: var AtlasContext; tag: string) = - let (outp, status) = exec(c, GitPush, [tag]) - if status != 0: - error(c, c.projectDir.PackageName, "could not 'git push " & tag & "'") - elif outp.strip() == "Everything up-to-date": - info(c, c.projectDir.PackageName, "is up-to-date") - else: - info(c, c.projectDir.PackageName, "successfully pushed tag: " & tag) - -proc incrementTag(c: var AtlasContext; lastTag: string; field: Natural): string = - var startPos = - if lastTag[0] in {'0'..'9'}: 0 - else: 1 - var endPos = lastTag.find('.', startPos) - if field >= 1: - for i in 1 .. field: - if endPos == -1: - error c, projectFromCurrentDir(), "the last tag '" & lastTag & "' is missing . periods" - return "" - startPos = endPos + 1 - endPos = lastTag.find('.', startPos) - if endPos == -1: - endPos = len(lastTag) - let patchNumber = parseInt(lastTag[startPos.. 0: return result - result = p - else: - # either the project name or the URL can be overwritten! - if UsesOverrides in c.flags: - result = c.overrides.substitute(p) - if result.len > 0: return result - - fillPackageLookupTable(c) - result = c.p.getOrDefault(unicode.toLower p) - - if result.len == 0: - result = getUrlFromGithub(p) - if result.len == 0: - inc c.errors - - if UsesOverrides in c.flags: - let newUrl = c.overrides.substitute(result) - if newUrl.len > 0: return newUrl - -proc toName(p: string): PackageName = - if p.isUrl: - result = PackageName splitFile(p).name - else: - result = PackageName p - -proc generateDepGraph(c: var AtlasContext; g: DepGraph) = - proc repr(w: Dependency): string = - if w.url.endsWith("/"): w.url & w.commit - else: w.url & "/" & w.commit - - var dotGraph = "" - for i in 0 ..< g.nodes.len: - dotGraph.addf("\"$1\" [label=\"$2\"];\n", [g.nodes[i].repr, if g.nodes[i].active: "" else: "unused"]) - for i in 0 ..< g.nodes.len: - for p in items g.nodes[i].parents: - if p >= 0: - dotGraph.addf("\"$1\" -> \"$2\";\n", [g.nodes[p].repr, g.nodes[i].repr]) - let dotFile = c.currentDir / "deps.dot" - writeFile(dotFile, "digraph deps {\n$1}\n" % dotGraph) - let graphvizDotPath = findExe("dot") - if graphvizDotPath.len == 0: - #echo("gendepend: Graphviz's tool dot is required, " & - # "see https://graphviz.org/download for downloading") - discard - else: - discard execShellCmd("dot -Tpng -odeps.png " & quoteShell(dotFile)) - -proc setupNimEnv(c: var AtlasContext; nimVersion: string) - -proc afterGraphActions(c: var AtlasContext; g: DepGraph) = - if ShowGraph in c.flags: - generateDepGraph c, g - if AutoEnv in c.flags and g.bestNimVersion != Version"": - setupNimEnv c, g.bestNimVersion.string - -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 getRequiredCommit(c: var AtlasContext; w: Dependency): string = - if needsCommitLookup(w.commit): versionToCommit(c, w) - elif isShortCommitHash(w.commit): shortToCommit(c, w.commit) - else: w.commit - -proc getRemoteUrl(): string = - execProcess("git config --get remote.origin.url").strip() - -proc genLockEntry(c: var AtlasContext; w: Dependency) = - let url = getRemoteUrl() - var commit = getRequiredCommit(c, w) - if commit.len == 0 or needsCommitLookup(commit): - commit = execProcess("git log -1 --pretty=format:%H").strip() - c.lockFile.items[w.name.string] = LockFileEntry(url: url, commit: commit) - -proc commitFromLockFile(c: var AtlasContext; w: Dependency): string = - let url = getRemoteUrl() - let entry = c.lockFile.items.getOrDefault(w.name.string) - if entry.commit.len > 0: - result = entry.commit - if entry.url != url: - error c, w.name, "remote URL has been compromised: got: " & - url & " but wanted: " & entry.url - else: - error c, w.name, "package is not listed in the lock file" - -proc dependencyDir(c: AtlasContext; w: Dependency): string = - result = c.workspace / w.name.string - if not dirExists(result): - result = c.depsDir / w.name.string - -const - FileProtocol = "file://" - ThisVersion = "current_version.atlas" - -proc selectNode(c: var AtlasContext; g: var DepGraph; w: Dependency) = - # all other nodes of the same project name are not active - for e in items g.byName[w.name]: - g.nodes[e].active = e == w.self - if c.lockMode == genLock: - if w.url.startsWith(FileProtocol): - c.lockFile.items[w.name.string] = LockFileEntry(url: w.url, commit: w.commit) - else: - genLockEntry(c, w) - -proc checkoutCommit(c: var AtlasContext; g: var DepGraph; w: Dependency) = - let dir = dependencyDir(c, w) - withDir c, dir: - if c.lockMode == useLock: - checkoutGitCommit(c, w.name, commitFromLockFile(c, w)) - elif w.commit.len == 0 or cmpIgnoreCase(w.commit, "head") == 0: - gitPull(c, w.name) - else: - let err = isCleanGit(c) - if err != "": - warn c, w.name, err - else: - let requiredCommit = getRequiredCommit(c, w) - 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 - 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) - selectNode c, g, w - else: - checkoutGitCommit(c, w.name, requiredCommit) - selectNode c, g, w - 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: - let dir = dependencyDir(c, dep) - result = dir / (dep.name.string & ".nimble") - if not fileExists(result): - result = "" - for x in walkFiles(dir / "*.nimble"): - if result.len == 0: - result = x - else: - # ambiguous .nimble file - return "" - -proc addUnique[T](s: var seq[T]; elem: sink T) = - if not s.contains(elem): s.add elem - -proc addUniqueDep(c: var AtlasContext; g: var DepGraph; parent: int; - pkg: string; query: VersionInterval) = - let commit = versionKey(query) - let oldErrors = c.errors - let url = toUrl(c, pkg) - if oldErrors != c.errors: - warn c, toName(pkg), "cannot resolve package name" - else: - let key = url / commit - if g.processed.hasKey(key): - g.nodes[g.processed[key]].parents.addUnique parent - else: - let self = g.nodes.len - g.byName.mgetOrPut(toName(pkg), @[]).add self - g.processed[key] = self - if c.lockMode == useLock: - if c.lockfile.items.contains(pkg): - g.nodes.add Dependency(name: toName(pkg), - url: c.lockfile.items[pkg].url, - commit: c.lockfile.items[pkg].commit, - self: self, - parents: @[parent], - algo: c.defaultAlgo) - else: - error c, toName(pkg), "package is not listed in the lock file" - else: - g.nodes.add Dependency(name: toName(pkg), url: url, commit: commit, - self: self, - query: query, - parents: @[parent], - algo: c.defaultAlgo) - -template toDestDir(p: PackageName): string = p.string - -proc readLockFile(filename: string): LockFile = - let jsonAsStr = readFile(filename) - let jsonTree = parseJson(jsonAsStr) - result = to(jsonTree, LockFile) - -proc rememberNimVersion(g: var DepGraph; q: VersionInterval) = - let v = extractGeQuery(q) - if v != Version"" and v > g.bestNimVersion: g.bestNimVersion = v - -proc collectDeps(c: var AtlasContext; g: var DepGraph; parent: int; - dep: Dependency; nimbleFile: string): CfgPath = - # 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 i = 0 - while i < r.len and r[i] notin {'#', '<', '=', '>'} + Whitespace: inc i - let pkgName = r.substr(0, i-1) - var err = pkgName.len == 0 - let query = parseVersionInterval(r, i, err) - if err: - error c, toName(nimbleFile), "invalid 'requires' syntax: " & r - else: - if cmpIgnoreCase(pkgName, "nim") != 0: - c.addUniqueDep g, parent, pkgName, query - else: - rememberNimVersion g, query - result = CfgPath(toDestDir(dep.name) / nimbleInfo.srcDir) - -proc collectNewDeps(c: var AtlasContext; g: var DepGraph; parent: int; - dep: Dependency): CfgPath = - let nimbleFile = findNimbleFile(c, dep) - if nimbleFile != "": - result = collectDeps(c, g, parent, dep, nimbleFile) - else: - result = CfgPath toDestDir(dep.name) - -proc selectDir(a, b: string): string = (if dirExists(a): a else: b) - -proc copyFromDisk(c: var AtlasContext; w: Dependency) = - let destDir = toDestDir(w.name) - var u = w.url.substr(FileProtocol.len) - if u.startsWith("./"): u = c.workspace / u.substr(2) - copyDir(selectDir(u & "@" & w.commit, u), destDir) - writeFile destDir / ThisVersion, w.commit - #echo "WRITTEN ", destDir / ThisVersion - -proc isLaterCommit(destDir, version: string): bool = - let oldVersion = try: readFile(destDir / ThisVersion).strip except: "0.0" - if isValidVersion(oldVersion) and isValidVersion(version): - result = Version(oldVersion) < Version(version) - else: - result = true - -proc collectAvailableVersions(c: var AtlasContext; g: var DepGraph; w: Dependency) = - when MockupRun: - # don't cache when doing the MockupRun: - g.availableVersions[w.name] = collectTaggedVersions(c) - else: - if not g.availableVersions.hasKey(w.name): - g.availableVersions[w.name] = collectTaggedVersions(c) - -proc resolve(c: var AtlasContext; g: var DepGraph) = - var b = sat.Builder() - b.openOpr(AndForm) - # Root must true: - b.add newVar(VarId 0) - - assert g.nodes.len > 0 - assert g.nodes[0].active - # Implications: - for i in 0..= 0: - b.openOpr(OrForm) - b.openOpr(NotForm) - b.add newVar(VarId j) - b.closeOpr - b.add newVar(VarId i) - b.closeOpr - var idgen = 0 - var mapping: seq[(string, string, Version)] = @[] - # Version selection: - for i in 0.. (exactly one of: A1, A2, A3) - b.openOpr(OrForm) - b.openOpr(NotForm) - b.add newVar(VarId i) - b.closeOpr - b.openOpr(ExactlyOneOfForm) - - let av {.cursor.} = g.availableVersions[g.nodes[i].name] - var q = g.nodes[i].query - if g.nodes[i].algo == SemVer: q = toSemVer(q) - if g.nodes[i].algo == MinVer: - for j in countup(0, av.len-1): - if q.matches(av[j][1]): - mapping.add (g.nodes[i].name.string, av[j][0], av[j][1]) - b.add newVar(VarId(idgen + g.nodes.len)) - inc idgen - else: - for j in countdown(av.len-1, 0): - if q.matches(av[j][1]): - mapping.add (g.nodes[i].name.string, av[j][0], av[j][1]) - b.add newVar(VarId(idgen + g.nodes.len)) - inc idgen - - b.closeOpr # ExactlyOneOfForm - b.closeOpr # OrForm - b.closeOpr() - let f = toForm(b) - var s = newSeq[BindingKind](idgen) - if satisfiable(f, s): - for i in g.nodes.len.. 0: - error c, toName(mapping[i - g.nodes.len][0]), $mapping[i - g.nodes.len][2] & " required" - -proc traverseLoop(c: var AtlasContext; g: var DepGraph; startIsDep: bool): seq[CfgPath] = - if c.lockMode == useLock: - let lockFilePath = dependencyDir(c, g.nodes[0]) / LockFileName - c.lockFile = readLockFile(lockFilePath) - - result = @[] - var i = 0 - while i < g.nodes.len: - let w = g.nodes[i] - let destDir = toDestDir(w.name) - let oldErrors = c.errors - - let dir = selectDir(c.workspace / destDir, c.depsDir / destDir) - if not dirExists(dir): - withDir c, (if i != 0 or startIsDep: c.depsDir else: c.workspace): - if w.url.startsWith(FileProtocol): - copyFromDisk c, w - else: - let err = cloneUrl(c, w.url, destDir, false) - if err != "": - error c, w.name, err - elif w.algo != MinVer: - collectAvailableVersions c, g, w - elif w.algo != MinVer: - withDir c, dir: - collectAvailableVersions c, g, w - - # assume this is the selected version, it might get overwritten later: - selectNode c, g, w - if oldErrors == c.errors: - if KeepCommits notin c.flags and w.algo == MinVer: - if not w.url.startsWith(FileProtocol): - checkoutCommit(c, g, w) - else: - withDir c, (if i != 0 or startIsDep: c.depsDir else: c.workspace): - if isLaterCommit(destDir, w.commit): - copyFromDisk c, w - selectNode c, g, 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: - result.addUnique collectNewDeps(c, g, i, w) - inc i - - if g.availableVersions.len > 0: - resolve c, g - if c.lockMode == genLock: - writeFile c.currentDir / LockFileName, toJson(c.lockFile).pretty - -proc createGraph(c: var AtlasContext; start, url: string): DepGraph = - result = DepGraph(nodes: @[Dependency(name: toName(start), url: url, commit: "", self: 0, - algo: c.defaultAlgo)]) - result.byName.mgetOrPut(toName(start), @[]).add 0 - -proc traverse(c: var AtlasContext; start: string; startIsDep: bool): seq[CfgPath] = - # returns the list of paths for the nim.cfg file. - let url = toUrl(c, start) - var g = createGraph(c, start, url) - - if url == "": - error c, toName(start), "cannot resolve package name" - return - - c.projectDir = c.workspace / toDestDir(g.nodes[0].name) - - result = traverseLoop(c, g, startIsDep) - afterGraphActions c, g - -const - configPatternBegin = "############# begin Atlas config section ##########\n" - configPatternEnd = "############# end Atlas config section ##########\n" - -proc patchNimCfg(c: var AtlasContext; deps: seq[CfgPath]; cfgPath: string) = - var paths = "--noNimblePath\n" - for d in deps: - let pkgname = toDestDir d.string.PackageName - let pkgdir = if dirExists(c.workspace / pkgname): c.workspace / pkgname - else: c.depsDir / pkgName - let x = relativePath(pkgdir, 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" - assert cfgPath.len > 0 - 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) - info(c, projectFromCurrentDir(), "created: " & cfg.readableFile) - 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) - info(c, projectFromCurrentDir(), "updated: " & cfg.readableFile) - -proc fatal*(msg: string) = - when defined(debug): - writeStackTrace() - quit "[Error] " & msg - -proc findSrcDir(c: var AtlasContext): string = - for nimbleFile in walkPattern(c.currentDir / "*.nimble"): - let nimbleInfo = extractRequiresInfo(c, nimbleFile) - return c.currentDir / nimbleInfo.srcDir - return c.currentDir - -proc installDependencies(c: var AtlasContext; nimbleFile: string; startIsDep: bool) = - # 1. find .nimble file in CWD - # 2. install deps from .nimble - var g = DepGraph(nodes: @[]) - let (_, pkgname, _) = splitFile(nimbleFile) - let dep = Dependency(name: toName(pkgname), url: "", commit: "", self: 0, - algo: c.defaultAlgo) - discard collectDeps(c, g, -1, dep, nimbleFile) - let paths = traverseLoop(c, g, startIsDep) - patchNimCfg(c, paths, if CfgHere in c.flags: c.currentDir else: findSrcDir(c)) - afterGraphActions c, g - -proc updateDir(c: var AtlasContext; dir, filter: string) = - for kind, file in walkDir(dir): - if kind == pcDir and dirExists(file / ".git"): - c.withDir file: - let pkg = PackageName(file) - let (remote, _) = osproc.execCmdEx("git remote -v") - if filter.len == 0 or filter in remote: - let diff = isCleanGit(c) - if diff != "": - warn(c, pkg, "has uncommitted changes; skipped") - else: - let (branch, _) = osproc.execCmdEx("git rev-parse --abbrev-ref HEAD") - if branch.strip.len > 0: - let (output, exitCode) = osproc.execCmdEx("git pull origin " & branch.strip) - if exitCode != 0: - error c, pkg, output - else: - info(c, pkg, "successfully updated") - else: - error c, pkg, "could not fetch current branch name" - -proc patchNimbleFile(c: var AtlasContext; dep: string): string = - let thisProject = c.currentDir.splitPath.tail - let oldErrors = c.errors - let url = toUrl(c, dep) - result = "" - if oldErrors != c.errors: - warn c, toName(dep), "cannot resolve package name" - else: - for x in walkFiles(c.currentDir / "*.nimble"): - if result.len == 0: - result = x - else: - # ambiguous .nimble file - warn c, toName(dep), "cannot determine `.nimble` file; there are multiple to choose from" - return "" - # see if we have this requirement already listed. If so, do nothing: - var found = false - if result.len > 0: - let nimbleInfo = extractRequiresInfo(c, result) - for r in nimbleInfo.requires: - var tokens: seq[string] = @[] - for token in tokenizeRequires(r): - tokens.add token - if tokens.len > 0: - let oldErrors = c.errors - let urlB = toUrl(c, tokens[0]) - if oldErrors != c.errors: - warn c, toName(tokens[0]), "cannot resolve package name; found in: " & result - if url == urlB: - found = true - break - - if not found: - let line = "requires \"$1\"\n" % dep.escape("", "") - if result.len > 0: - let oldContent = readFile(result) - writeFile result, oldContent & "\n" & line - info(c, toName(thisProject), "updated: " & result.readableFile) - else: - result = c.currentDir / thisProject & ".nimble" - writeFile result, line - info(c, toName(thisProject), "created: " & result.readableFile) - else: - info(c, toName(thisProject), "up to date: " & result.readableFile) - -proc detectWorkspace(currentDir: string): string = - result = currentDir - while result.len > 0: - if fileExists(result / AtlasWorkspace): - return result - result = result.parentDir() - -proc absoluteDepsDir(workspace, value: string): string = - if value == ".": - result = workspace - elif isAbsolute(value): - result = value - else: - result = workspace / value - -proc autoWorkspace(currentDir: string): string = - result = currentDir - while result.len > 0 and dirExists(result / ".git"): - result = result.parentDir() - -proc createWorkspaceIn(workspace, depsDir: string) = - if not fileExists(workspace / AtlasWorkspace): - writeFile workspace / AtlasWorkspace, "deps=\"$#\"" % escape(depsDir, "", "") - createDir absoluteDepsDir(workspace, depsDir) - -proc parseOverridesFile(c: var AtlasContext; filename: string) = - const Separator = " -> " - let path = c.workspace / filename - var f: File - if open(f, path): - c.flags.incl UsesOverrides - try: - var lineCount = 1 - for line in lines(path): - let splitPos = line.find(Separator) - if splitPos >= 0 and line[0] != '#': - let key = line.substr(0, splitPos-1) - let val = line.substr(splitPos+len(Separator)) - if key.len == 0 or val.len == 0: - error c, toName(path), "key/value must not be empty" - let err = c.overrides.addPattern(key, val) - if err.len > 0: - error c, toName(path), "(" & $lineCount & "): " & err - else: - discard "ignore the line" - inc lineCount - finally: - close f - else: - error c, toName(path), "cannot open: " & path - -proc readConfig(c: var AtlasContext) = - let configFile = c.workspace / AtlasWorkspace - var f = newFileStream(configFile, fmRead) - if f == nil: - error c, toName(configFile), "cannot open: " & configFile - return - var p: CfgParser - open(p, f, configFile) - while true: - var e = next(p) - case e.kind - of cfgEof: break - of cfgSectionStart: - discard "who cares about sections" - of cfgKeyValuePair: - case e.key.normalize - of "deps": - c.depsDir = absoluteDepsDir(c.workspace, e.value) - of "overrides": - parseOverridesFile(c, e.value) - of "resolver": - try: - c.defaultAlgo = parseEnum[ResolutionAlgorithm](e.value) - except ValueError: - warn c, toName(configFile), "ignored unknown resolver: " & e.key - else: - warn c, toName(configFile), "ignored unknown setting: " & e.key - of cfgOption: - discard "who cares about options" - of cfgError: - error c, toName(configFile), e.msg - close(p) - -const - BatchFile = """ -@echo off -set PATH="$1";%PATH% -""" - ShellFile = "export PATH=$1:$$PATH\n" - -const - ActivationFile = when defined(windows): "activate.bat" else: "activate.sh" - -proc infoAboutActivation(c: var AtlasContext; nimDest, nimVersion: string) = - when defined(windows): - info c, toName(nimDest), "RUN\nnim-" & nimVersion & "\\activate.bat" - else: - info c, toName(nimDest), "RUN\nsource nim-" & nimVersion & "/activate.sh" - -proc setupNimEnv(c: var AtlasContext; nimVersion: string) = - template isDevel(nimVersion: string): bool = nimVersion == "devel" - - template exec(c: var AtlasContext; command: string) = - let cmd = command # eval once - if os.execShellCmd(cmd) != 0: - error c, toName("nim-" & nimVersion), "failed: " & cmd - return - - let nimDest = "nim-" & nimVersion - if dirExists(c.workspace / nimDest): - if not fileExists(c.workspace / nimDest / ActivationFile): - info c, toName(nimDest), "already exists; remove or rename and try again" - else: - infoAboutActivation c, nimDest, nimVersion - return - - var major, minor, patch: int - if nimVersion != "devel": - if not scanf(nimVersion, "$i.$i.$i", major, minor, patch): - error c, toName("nim"), "cannot parse version requirement" - return - let csourcesVersion = - if nimVersion.isDevel or (major == 1 and minor >= 9) or major >= 2: - # already uses csources_v2 - "csources_v2" - elif major == 0: - "csources" # has some chance of working - else: - "csources_v1" - withDir c, c.workspace: - if not dirExists(csourcesVersion): - exec c, "git clone https://github.com/nim-lang/" & csourcesVersion - exec c, "git clone https://github.com/nim-lang/nim " & nimDest - withDir c, c.workspace / csourcesVersion: - when defined(windows): - exec c, "build.bat" - else: - let makeExe = findExe("make") - if makeExe.len == 0: - exec c, "sh build.sh" - else: - exec c, "make" - let nimExe0 = ".." / csourcesVersion / "bin" / "nim".addFileExt(ExeExt) - withDir c, c.workspace / nimDest: - let nimExe = "bin" / "nim".addFileExt(ExeExt) - copyFileWithPermissions nimExe0, nimExe - let dep = Dependency(name: toName(nimDest), commit: nimVersion, self: 0, - algo: c.defaultAlgo, - query: createQueryEq(if nimVersion.isDevel: Version"#head" else: Version(nimVersion))) - if not nimVersion.isDevel: - let commit = versionToCommit(c, dep) - if commit.len == 0: - error c, toName(nimDest), "cannot resolve version to a commit" - return - checkoutGitCommit(c, dep.name, commit) - exec c, nimExe & " c --noNimblePath --skipUserCfg --skipParentCfg --hints:off koch" - let kochExe = when defined(windows): "koch.exe" else: "./koch" - exec c, kochExe & " boot -d:release --skipUserCfg --skipParentCfg --hints:off" - exec c, kochExe & " tools --skipUserCfg --skipParentCfg --hints:off" - # remove any old atlas binary that we now would end up using: - if cmpPaths(getAppDir(), c.workspace / nimDest / "bin") != 0: - removeFile "bin" / "atlas".addFileExt(ExeExt) - # unless --keep is used delete the csources because it takes up about 2GB and - # is not necessary afterwards: - if Keep notin c.flags: - removeDir c.workspace / csourcesVersion / "c_code" - let pathEntry = (c.workspace / nimDest / "bin") - when defined(windows): - writeFile "activate.bat", BatchFile % pathEntry.replace('/', '\\') - else: - writeFile "activate.sh", ShellFile % pathEntry - infoAboutActivation c, nimDest, nimVersion - -proc extractVersion(s: string): string = - var i = 0 - while i < s.len and s[i] notin {'0'..'9'}: inc i - result = s.substr(i) - -proc listOutdated(c: var AtlasContext; dir: string) = - var updateable = 0 - for k, f in walkDir(dir, relative=true): - if k in {pcDir, pcLinkToDir} and dirExists(dir / f / ".git"): - withDir c, dir / f: - let (outp, status) = silentExec("git fetch", []) - if status == 0: - let (cc, status) = exec(c, GitLastTaggedRef, []) - let latestVersion = strutils.strip(cc) - if status == 0 and latestVersion.len > 0: - # see if we're past that commit: - let (cc, status) = exec(c, GitCurrentCommit, []) - if status == 0: - let currentCommit = strutils.strip(cc) - if currentCommit != latestVersion: - # checkout the later commit: - # git merge-base --is-ancestor - let (cc, status) = exec(c, GitMergeBase, [currentCommit, latestVersion]) - let mergeBase = strutils.strip(cc) - #if mergeBase != latestVersion: - # echo f, " I'm at ", currentCommit, " release is at ", latestVersion, " merge base is ", mergeBase - if status == 0 and mergeBase == currentCommit: - let v = extractVersion gitDescribeRefTag(c, latestVersion) - if v.len > 0: - info c, toName(f), "new version available: " & v - inc updateable - else: - warn c, toName(f), "`git fetch` failed: " & outp - if updateable == 0: - info c, toName(c.workspace), "all packages are up to date" - -proc listOutdated(c: var AtlasContext) = - if c.depsDir.len > 0 and c.depsDir != c.workspace: - listOutdated c, c.depsDir - listOutdated c, c.workspace - -proc main = - var action = "" - var args: seq[string] = @[] - template singleArg() = - if args.len != 1: - fatal action & " command takes a single package name" - - template noArgs() = - if args.len != 0: - fatal action & " command takes no arguments" - - template projectCmd() = - if c.projectDir == c.workspace or c.projectDir == c.depsDir: - fatal action & " command must be executed in a project, not in the workspace" - - var c = AtlasContext(projectDir: getCurrentDir(), currentDir: getCurrentDir(), workspace: "") - var autoinit = false - 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.flags.incl KeepCommits - of "workspace": - if val == ".": - c.workspace = getCurrentDir() - createWorkspaceIn c.workspace, c.depsDir - elif val.len > 0: - c.workspace = val - createDir(val) - createWorkspaceIn c.workspace, c.depsDir - else: - writeHelp() - of "project": - if isAbsolute(val): - c.currentDir = val - else: - c.currentDir = getCurrentDir() / val - of "deps": - if val.len > 0: - c.depsDir = val - else: - writeHelp() - of "cfghere": c.flags.incl CfgHere - of "autoinit": autoinit = true - of "showgraph": c.flags.incl ShowGraph - of "keep": c.flags.incl Keep - of "autoenv": c.flags.incl AutoEnv - of "genlock": - if c.lockMode != useLock: - c.lockMode = genLock - else: - writeHelp() - of "uselock": - if c.lockMode != genLock: - c.lockMode = useLock - else: - writeHelp() - of "colors": - case val.normalize - of "off": c.flags.incl NoColors - of "on": c.flags.excl NoColors - else: writeHelp() - of "resolver": - try: - c.defaultAlgo = parseEnum[ResolutionAlgorithm](val) - except ValueError: - quit "unknown resolver: " & val - else: writeHelp() - of cmdEnd: assert false, "cannot happen" - - if c.workspace.len > 0: - if not dirExists(c.workspace): fatal "Workspace directory '" & c.workspace & "' not found." - elif action != "init": - when MockupRun: - c.workspace = autoWorkspace(c.currentDir) - else: - c.workspace = detectWorkspace(c.currentDir) - if c.workspace.len > 0: - readConfig c - info c, toName(c.workspace.readableFile), "is the current workspace" - elif autoinit: - c.workspace = autoWorkspace(c.currentDir) - createWorkspaceIn c.workspace, c.depsDir - elif action notin ["search", "list"]: - fatal "No workspace found. Run `atlas init` if you want this current directory to be your workspace." - - when MockupRun: - c.depsDir = c.workspace - - case action - of "": - fatal "No action." - of "init": - c.workspace = getCurrentDir() - createWorkspaceIn c.workspace, c.depsDir - of "clone", "update": - singleArg() - let deps = traverse(c, args[0], startIsDep = false) - patchNimCfg c, deps, if CfgHere in c.flags: c.currentDir else: findSrcDir(c) - when MockupRun: - if not c.mockupSuccess: - fatal "There were problems." - else: - if c.errors > 0: - fatal "There were problems." - of "use": - projectCmd() - singleArg() - let nimbleFile = patchNimbleFile(c, args[0]) - if nimbleFile.len > 0: - installDependencies(c, nimbleFile, startIsDep = false) - of "install": - projectCmd() - if args.len > 1: - fatal "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: - fatal "could not find a .nimble file" - else: - installDependencies(c, nimbleFile, startIsDep = true) - of "refresh": - noArgs() - updatePackages(c) - of "search", "list": - if c.workspace.len != 0: - updatePackages(c) - search getPackages(c.workspace), args - else: search @[], args - of "updateprojects": - updateDir(c, c.workspace, if args.len == 0: "" else: args[0]) - of "updatedeps": - updateDir(c, c.depsDir, if args.len == 0: "" else: args[0]) - of "extract": - singleArg() - if fileExists(args[0]): - echo toJson(extractRequiresInfo(args[0])) - else: - fatal "File does not exist: " & args[0] - of "tag": - projectCmd() - if args.len == 0: - tag(c, ord(patch)) - elif args[0].len == 1 and args[0][0] in {'a'..'z'}: - let field = ord(args[0][0]) - ord('a') - tag(c, field) - elif args[0].len == 1 and args[0][0] in {'A'..'Z'}: - let field = ord(args[0][0]) - ord('A') - tag(c, field) - elif '.' in args[0]: - tag(c, args[0]) - else: - var field: SemVerField - try: field = parseEnum[SemVerField](args[0]) - except: fatal "tag command takes one of 'patch' 'minor' 'major', a SemVer tag, or a letter from 'a' to 'z'" - tag(c, ord(field)) - of "build", "test", "doc", "tasks": - projectCmd() - nimbleExec(action, args) - of "task": - projectCmd() - nimbleExec("", args) - of "env": - singleArg() - setupNimEnv c, args[0] - of "outdated": - listOutdated(c) - else: - fatal "Invalid action: " & action - -when isMainModule: - main() diff --git a/atlas/atlas.nim.cfg b/atlas/atlas.nim.cfg deleted file mode 100644 index fcace0579984..000000000000 --- a/atlas/atlas.nim.cfg +++ /dev/null @@ -1 +0,0 @@ ---define:ssl diff --git a/atlas/compiledpatterns.nim b/atlas/compiledpatterns.nim deleted file mode 100644 index 69751d82bf94..000000000000 --- a/atlas/compiledpatterns.nim +++ /dev/null @@ -1,246 +0,0 @@ -# -# Atlas Package Cloner -# (c) Copyright 2021 Andreas Rumpf -# -# See the file "copying.txt", included in this -# distribution, for details about the copyright. -# - -##[ - -Syntax taken from strscans.nim: - -================= ======================================================== -``$$`` Matches a single dollar sign. -``$*`` Matches until the token following the ``$*`` was found. - The match is allowed to be of 0 length. -``$+`` Matches until the token following the ``$+`` was found. - The match must consist of at least one char. -``$s`` Skips optional whitespace. -================= ======================================================== - -]## - -import tables -from strutils import continuesWith, Whitespace - -type - Opcode = enum - MatchVerbatim # needs verbatim match - Capture0Until - Capture1Until - Capture0UntilEnd - Capture1UntilEnd - SkipWhitespace - - Instr = object - opc: Opcode - arg1: uint8 - arg2: uint16 - - Pattern* = object - code: seq[Instr] - usedMatches: int - error: string - -# A rewrite rule looks like: -# -# foo$*bar -> https://gitlab.cross.de/$1 - -proc compile*(pattern: string; strings: var seq[string]): Pattern = - proc parseSuffix(s: string; start: int): int = - result = start - while result < s.len and s[result] != '$': - inc result - - result = Pattern(code: @[], usedMatches: 0, error: "") - var p = 0 - while p < pattern.len: - if pattern[p] == '$' and p+1 < pattern.len: - case pattern[p+1] - of '$': - if result.code.len > 0 and result.code[^1].opc in { - MatchVerbatim, Capture0Until, Capture1Until, Capture0UntilEnd, Capture1UntilEnd}: - # merge with previous opcode - let key = strings[result.code[^1].arg2] & "$" - var idx = find(strings, key) - if idx < 0: - idx = strings.len - strings.add key - result.code[^1].arg2 = uint16(idx) - else: - var idx = find(strings, "$") - if idx < 0: - idx = strings.len - strings.add "$" - result.code.add Instr(opc: MatchVerbatim, - arg1: uint8(0), arg2: uint16(idx)) - inc p, 2 - of '+', '*': - let isPlus = pattern[p+1] == '+' - - let pEnd = parseSuffix(pattern, p+2) - let suffix = pattern.substr(p+2, pEnd-1) - p = pEnd - if suffix.len == 0: - result.code.add Instr(opc: if isPlus: Capture1UntilEnd else: Capture0UntilEnd, - arg1: uint8(result.usedMatches), arg2: uint16(0)) - else: - var idx = find(strings, suffix) - if idx < 0: - idx = strings.len - strings.add suffix - result.code.add Instr(opc: if isPlus: Capture1Until else: Capture0Until, - arg1: uint8(result.usedMatches), arg2: uint16(idx)) - inc result.usedMatches - - of 's': - result.code.add Instr(opc: SkipWhitespace) - inc p, 2 - else: - result.error = "unknown syntax '$" & pattern[p+1] & "'" - break - elif pattern[p] == '$': - result.error = "unescaped '$'" - break - else: - let pEnd = parseSuffix(pattern, p) - let suffix = pattern.substr(p, pEnd-1) - var idx = find(strings, suffix) - if idx < 0: - idx = strings.len - strings.add suffix - result.code.add Instr(opc: MatchVerbatim, - arg1: uint8(0), arg2: uint16(idx)) - p = pEnd - -type - MatchObj = object - m: int - a: array[20, (int, int)] - -proc matches(s: Pattern; strings: seq[string]; input: string): MatchObj = - template failed = - result.m = -1 - return result - - var i = 0 - for instr in s.code: - case instr.opc - of MatchVerbatim: - if continuesWith(input, strings[instr.arg2], i): - inc i, strings[instr.arg2].len - else: - failed() - of Capture0Until, Capture1Until: - block searchLoop: - let start = i - while i < input.len: - if continuesWith(input, strings[instr.arg2], i): - if instr.opc == Capture1Until and i == start: - failed() - result.a[result.m] = (start, i-1) - inc result.m - inc i, strings[instr.arg2].len - break searchLoop - inc i - failed() - - of Capture0UntilEnd, Capture1UntilEnd: - if instr.opc == Capture1UntilEnd and i >= input.len: - failed() - result.a[result.m] = (i, input.len-1) - inc result.m - i = input.len - of SkipWhitespace: - while i < input.len and input[i] in Whitespace: inc i - if i < input.len: - # still unmatched stuff was left: - failed() - -proc translate(m: MatchObj; outputPattern, input: string): string = - result = newStringOfCap(outputPattern.len) - var i = 0 - var patternCount = 0 - while i < outputPattern.len: - if i+1 < outputPattern.len and outputPattern[i] == '$': - if outputPattern[i+1] == '#': - inc i, 2 - if patternCount < m.a.len: - let (a, b) = m.a[patternCount] - for j in a..b: result.add input[j] - inc patternCount - elif outputPattern[i+1] in {'1'..'9'}: - var n = ord(outputPattern[i+1]) - ord('0') - inc i, 2 - while i < outputPattern.len and outputPattern[i] in {'0'..'9'}: - n = n * 10 + (ord(outputPattern[i]) - ord('0')) - inc i - patternCount = n - if n-1 < m.a.len: - let (a, b) = m.a[n-1] - for j in a..b: result.add input[j] - else: - # just ignore the wrong pattern: - inc i - else: - result.add outputPattern[i] - inc i - -proc replace*(s: Pattern; outputPattern, input: string): string = - var strings: seq[string] = @[] - let m = s.matches(strings, input) - if m.m < 0: - result = "" - else: - result = translate(m, outputPattern, input) - - -type - Patterns* = object - s: seq[(Pattern, string)] - t: Table[string, string] - strings: seq[string] - -proc initPatterns*(): Patterns = - Patterns(s: @[], t: initTable[string, string](), strings: @[]) - -proc addPattern*(p: var Patterns; inputPattern, outputPattern: string): string = - if '$' notin inputPattern and '$' notin outputPattern: - p.t[inputPattern] = outputPattern - result = "" - else: - let code = compile(inputPattern, p.strings) - if code.error.len > 0: - result = code.error - else: - p.s.add (code, outputPattern) - result = "" - -proc substitute*(p: Patterns; input: string): string = - result = p.t.getOrDefault(input) - if result.len == 0: - for i in 0..= 0: - return translate(m, p.s[i][1], input) - -proc replacePattern*(inputPattern, outputPattern, input: string): string = - var strings: seq[string] = @[] - let code = compile(inputPattern, strings) - result = replace(code, outputPattern, input) - -when isMainModule: - # foo$*bar -> https://gitlab.cross.de/$1 - const realInput = "$fooXXbar$z00end" - var strings: seq[string] = @[] - let code = compile("$$foo$*bar$$$*z00$*", strings) - echo code - - let m = code.matches(strings, realInput) - echo m.m - - echo translate(m, "$1--$#-$#-", realInput) - - echo translate(m, "https://gitlab.cross.de/$1", realInput) - diff --git a/atlas/osutils.nim b/atlas/osutils.nim deleted file mode 100644 index 66cd29be5825..000000000000 --- a/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 --recursive " & 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/atlas/packagesjson.nim b/atlas/packagesjson.nim deleted file mode 100644 index 7e25c6934317..000000000000 --- a/atlas/packagesjson.nim +++ /dev/null @@ -1,161 +0,0 @@ - -import std / [json, os, sets, strutils, httpclient, uri] - -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 toTags(j: JsonNode): seq[string] = - result = @[] - if j.kind == JArray: - for elem in items j: - result.add elem.getStr("") - -proc singleGithubSearch(term: string): JsonNode = - # For example: - # https://api.github.com/search/repositories?q=weave+language:nim - var client = newHttpClient() - try: - let x = client.getContent("https://api.github.com/search/repositories?q=" & encodeUrl(term) & "+language:nim") - result = parseJson(x) - except: - result = parseJson("{\"items\": []}") - finally: - client.close() - -proc githubSearch(seen: var HashSet[string]; terms: seq[string]) = - for term in terms: - let results = singleGithubSearch(term) - for j in items(results.getOrDefault("items")): - let p = Package( - name: j.getOrDefault("name").getStr, - url: j.getOrDefault("html_url").getStr, - downloadMethod: "git", - tags: toTags(j.getOrDefault("topics")), - description: j.getOrDefault("description").getStr, - license: j.getOrDefault("license").getOrDefault("spdx_id").getStr, - web: j.getOrDefault("html_url").getStr - ) - if not seen.containsOrIncl(p.url): - echo p - -proc getUrlFromGithub*(term: string): string = - let results = singleGithubSearch(term) - var matches = 0 - result = "" - for j in items(results.getOrDefault("items")): - if cmpIgnoreCase(j.getOrDefault("name").getStr, term) == 0: - if matches == 0: - result = j.getOrDefault("html_url").getStr - inc matches - if matches != 1: - # ambiguous, not ok! - result = "" - -proc search*(pkgList: seq[Package]; terms: seq[string]) = - var seen = initHashSet[string]() - template onFound = - echo pkg - seen.incl pkg.url - 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) - githubSearch seen, terms - if seen.len == 0 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/atlas/sat.nim b/atlas/sat.nim deleted file mode 100644 index 12ad07803116..000000000000 --- a/atlas/sat.nim +++ /dev/null @@ -1,313 +0,0 @@ -## SAT solver -## (c) 2021 Andreas Rumpf -## Based on explanations and Haskell code from -## https://andrew.gibiansky.com/blog/verification/writing-a-sat-solver/ - -## Formulars as packed ASTs, no pointers no cry. Solves formulars with many -## thousands of variables in no time. - -type - FormKind* = enum - FalseForm, TrueForm, VarForm, NotForm, AndForm, OrForm, ExactlyOneOfForm # roughly 8 so the last 3 bits - BaseType = int32 - Atom = distinct BaseType - VarId* = distinct BaseType - Formular* = seq[Atom] # linear storage - -proc `==`*(a, b: VarId): bool {.borrow.} - -const - KindBits = 3 - KindMask = 0b111 - -template kind(a: Atom): FormKind = FormKind(BaseType(a) and KindMask) -template intVal(a: Atom): BaseType = BaseType(a) shr KindBits - -proc newVar*(val: VarId): Atom {.inline.} = - Atom((BaseType(val) shl KindBits) or BaseType(VarForm)) - -proc newOperation(k: FormKind; val: BaseType): Atom {.inline.} = - Atom((val shl KindBits) or BaseType(k)) - -proc trueLit(): Atom {.inline.} = Atom(TrueForm) -proc falseLit(): Atom {.inline.} = Atom(FalseForm) - -proc lit(k: FormKind): Atom {.inline.} = Atom(k) - -when false: - proc isTrueLit(a: Atom): bool {.inline.} = a.kind == TrueForm - proc isFalseLit(a: Atom): bool {.inline.} = a.kind == FalseForm - -proc varId(a: Atom): VarId = - assert a.kind == VarForm - result = VarId(BaseType(a) shr KindBits) - -type - PatchPos = distinct int - FormPos = distinct int - -proc prepare(dest: var Formular; source: Formular; sourcePos: FormPos): PatchPos = - result = PatchPos dest.len - dest.add source[sourcePos.int] - -proc patch(f: var Formular; pos: PatchPos) = - let pos = pos.int - let k = f[pos].kind - assert k > VarForm - let distance = int32(f.len - pos) - f[pos] = newOperation(k, distance) - -proc nextChild(f: Formular; pos: var int) {.inline.} = - let x = f[int pos] - pos += (if x.kind <= VarForm: 1 else: int(intVal(x))) - -iterator sonsReadonly(f: Formular; n: FormPos): FormPos = - var pos = n.int - assert f[pos].kind > VarForm - let last = pos + f[pos].intVal - inc pos - while pos < last: - yield FormPos pos - nextChild f, pos - -iterator sons(dest: var Formular; source: Formular; n: FormPos): FormPos = - let patchPos = prepare(dest, source, n) - for x in sonsReadonly(source, n): yield x - patch dest, patchPos - -# String representation - -proc toString(dest: var string; f: Formular; n: FormPos) = - assert n.int >= 0 - assert n.int < f.len - case f[n.int].kind - of FalseForm: dest.add 'F' - of TrueForm: dest.add 'T' - of VarForm: - dest.add 'v' - dest.addInt varId(f[n.int]).int - else: - case f[n.int].kind - of AndForm: - dest.add "(&" - of OrForm: - dest.add "(|" - of ExactlyOneOfForm: - dest.add "(1==" - of NotForm: - dest.add "(~" - else: assert false, "cannot happen" - for child in sonsReadonly(f, n): - toString(dest, f, child) - dest.add ' ' - dest[^1] = ')' - -proc `$`*(f: Formular): string = - assert f.len > 0 - toString(result, f, FormPos 0) - -type - Builder* = object - f: Formular - toPatch: seq[PatchPos] - -proc isEmpty*(b: Builder): bool {.inline.} = - b.f.len == 0 or b.f.len == 1 and b.f[0].kind in {NotForm, AndForm, OrForm, ExactlyOneOfForm} - -proc openOpr*(b: var Builder; k: FormKind) = - b.toPatch.add PatchPos b.f.len - b.f.add newOperation(k, 0) - -proc add*(b: var Builder; a: Atom) = - b.f.add a - -proc closeOpr*(b: var Builder) = - patch(b.f, b.toPatch.pop()) - -proc toForm*(b: var Builder): Formular = - assert b.toPatch.len == 0, "missing `closeOpr` calls" - result = move b.f - -# Code from the blog translated into Nim and into our representation - -const - NoVar = VarId(-1) - -proc freeVariable(f: Formular): VarId = - ## returns NoVar if there is no free variable. - for i in 0..= s.len: s.setLen v.int+1 - # try `setToFalse` first so that we don't end up with unnecessary dependencies: - s[v.int] = setToFalse - - var falseGuess: Formular - let res = simplify(falseGuess, f, FormPos 0, s) - - if res == TrueForm: - result = true - else: - result = satisfiable(falseGuess, s) - if not result: - s[v.int] = setToTrue - - var trueGuess: Formular - let res = simplify(trueGuess, f, FormPos 0, s) - - if res == TrueForm: - result = true - else: - result = satisfiable(trueGuess, s) - if not result: - # heuristic that provides a solution that comes closest to the "real" conflict: - s[v.int] = if trueGuess.len <= falseGuess.len: setToFalse else: setToTrue - -when isMainModule: - proc main = - var b: Builder - b.openOpr(AndForm) - - b.openOpr(OrForm) - b.add newVar(VarId 1) - b.add newVar(VarId 2) - b.add newVar(VarId 3) - b.add newVar(VarId 4) - b.closeOpr - - b.openOpr(ExactlyOneOfForm) - b.add newVar(VarId 5) - b.add newVar(VarId 6) - b.add newVar(VarId 7) - - #b.openOpr(NotForm) - b.add newVar(VarId 8) - #b.closeOpr - b.closeOpr - - b.add newVar(VarId 5) - b.add newVar(VarId 6) - b.closeOpr - - let f = toForm(b) - echo "original: " - echo f - - var s: Solution - echo satisfiable(f, s) - echo "solution" - for i in 0.. ("", 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/atlas/tester.nim b/atlas/tester.nim deleted file mode 100644 index ccc84f5ab374..000000000000 --- a/atlas/tester.nim +++ /dev/null @@ -1,46 +0,0 @@ -# Small program that runs the test cases - -import std / [strutils, os, sequtils] -from std/private/gitutils import diffFiles - -if execShellCmd("nim c -r atlas/versions.nim") != 0: - quit("FAILURE: unit tests in atlas/versions.nim failed") - -var failures = 0 - -when defined(develop): - const atlasExe = "bin" / "atlas".addFileExt(ExeExt) - if execShellCmd("nim c -o:$# atlas/atlas.nim" % [atlasExe]) != 0: - quit("FAILURE: compilation of atlas failed") -else: - const atlasExe = "atlas".addFileExt(ExeExt) - -proc exec(cmd: string) = - if execShellCmd(cmd) != 0: - quit "FAILURE: " & cmd - -proc sameDirContents(expected, given: string) = - for _, e in walkDir(expected): - let g = given / splitPath(e).tail - if fileExists(g): - if readFile(e) != readFile(g): - echo "FAILURE: files differ: ", e - echo diffFiles(e, g).output - inc failures - else: - echo "FAILURE: file does not exist: ", g - inc failures - -proc testWsConflict() = - const myproject = "atlas/tests/ws_conflict/myproject" - createDir(myproject) - exec atlasExe & " --project=" & myproject & " --showGraph --genLock use https://github.com/apkg" - sameDirContents("atlas/tests/ws_conflict/expected", myproject) - removeDir("atlas/tests/ws_conflict/apkg") - removeDir("atlas/tests/ws_conflict/bpkg") - removeDir("atlas/tests/ws_conflict/cpkg") - removeDir("atlas/tests/ws_conflict/dpkg") - removeDir(myproject) - -testWsConflict() -if failures > 0: quit($failures & " failures occurred.") diff --git a/atlas/tests/balls.nimble b/atlas/tests/balls.nimble deleted file mode 100644 index 143e757e9ce8..000000000000 --- a/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/atlas/tests/grok.nimble b/atlas/tests/grok.nimble deleted file mode 100644 index 1b6d77c08abf..000000000000 --- a/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/atlas/tests/nim-bytes2human.nimble b/atlas/tests/nim-bytes2human.nimble deleted file mode 100644 index 9f3ae2479c7b..000000000000 --- a/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/atlas/tests/nim.cfg b/atlas/tests/nim.cfg deleted file mode 100644 index 3982b12bb461..000000000000 --- a/atlas/tests/nim.cfg +++ /dev/null @@ -1,10 +0,0 @@ -############# begin Atlas config section ########## ---noNimblePath ---path:"../balls" ---path:"../grok" ---path:"../ups" ---path:"../sync" ---path:"../npeg/src" ---path:"../testes" ---path:"../nim-bytes2human/src" -############# end Atlas config section ########## diff --git a/atlas/tests/npeg.nimble b/atlas/tests/npeg.nimble deleted file mode 100644 index e71fc5aa5209..000000000000 --- a/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/atlas/tests/packages/packages.json b/atlas/tests/packages/packages.json deleted file mode 100644 index d054a201bef8..000000000000 --- a/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/atlas/tests/sync.nimble b/atlas/tests/sync.nimble deleted file mode 100644 index a07ae892504d..000000000000 --- a/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/atlas/tests/testes.nimble b/atlas/tests/testes.nimble deleted file mode 100644 index 60fe1d508084..000000000000 --- a/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/atlas/tests/ups.nimble b/atlas/tests/ups.nimble deleted file mode 100644 index d91abbe60e17..000000000000 --- a/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" diff --git a/atlas/tests/ws_conflict/atlas.workspace b/atlas/tests/ws_conflict/atlas.workspace deleted file mode 100644 index 21954fea1933..000000000000 --- a/atlas/tests/ws_conflict/atlas.workspace +++ /dev/null @@ -1,2 +0,0 @@ -deps="" -overrides="url.rules" diff --git a/atlas/tests/ws_conflict/expected/atlas.lock b/atlas/tests/ws_conflict/expected/atlas.lock deleted file mode 100644 index 2f809ace354e..000000000000 --- a/atlas/tests/ws_conflict/expected/atlas.lock +++ /dev/null @@ -1,20 +0,0 @@ -{ - "items": { - "apkg": { - "url": "file://./source/apkg", - "commit": "#head" - }, - "bpkg": { - "url": "file://./source/bpkg", - "commit": "1.0" - }, - "cpkg": { - "url": "file://./source/cpkg", - "commit": "2.0" - }, - "dpkg": { - "url": "file://./source/dpkg", - "commit": "1.0" - } - } -} \ No newline at end of file diff --git a/atlas/tests/ws_conflict/expected/deps.dot b/atlas/tests/ws_conflict/expected/deps.dot deleted file mode 100644 index dd2e452f1b7d..000000000000 --- a/atlas/tests/ws_conflict/expected/deps.dot +++ /dev/null @@ -1,11 +0,0 @@ -digraph deps { -"file://./source/apkg/#head" [label=""]; -"file://./source/bpkg/1.0" [label=""]; -"file://./source/cpkg/1.0" [label="unused"]; -"file://./source/cpkg/2.0" [label=""]; -"file://./source/dpkg/1.0" [label=""]; -"file://./source/apkg/#head" -> "file://./source/bpkg/1.0"; -"file://./source/apkg/#head" -> "file://./source/cpkg/1.0"; -"file://./source/bpkg/1.0" -> "file://./source/cpkg/2.0"; -"file://./source/cpkg/2.0" -> "file://./source/dpkg/1.0"; -} diff --git a/atlas/tests/ws_conflict/expected/myproject.nimble b/atlas/tests/ws_conflict/expected/myproject.nimble deleted file mode 100644 index 863e7c171a0a..000000000000 --- a/atlas/tests/ws_conflict/expected/myproject.nimble +++ /dev/null @@ -1 +0,0 @@ -requires "https://github.com/apkg" diff --git a/atlas/tests/ws_conflict/expected/nim.cfg b/atlas/tests/ws_conflict/expected/nim.cfg deleted file mode 100644 index 6f7c73055dd8..000000000000 --- a/atlas/tests/ws_conflict/expected/nim.cfg +++ /dev/null @@ -1,7 +0,0 @@ -############# begin Atlas config section ########## ---noNimblePath ---path:"../apkg" ---path:"../bpkg" ---path:"../cpkg" ---path:"../dpkg" -############# end Atlas config section ########## diff --git a/atlas/tests/ws_conflict/source/apkg/apkg.nimble b/atlas/tests/ws_conflict/source/apkg/apkg.nimble deleted file mode 100644 index 11065ec15164..000000000000 --- a/atlas/tests/ws_conflict/source/apkg/apkg.nimble +++ /dev/null @@ -1,4 +0,0 @@ -# require first b and then c - -requires "https://github.com/bpkg >= 1.0" -requires "https://github.com/cpkg >= 1.0" diff --git a/atlas/tests/ws_conflict/source/bpkg@1.0/bpkg.nimble b/atlas/tests/ws_conflict/source/bpkg@1.0/bpkg.nimble deleted file mode 100644 index f70ad45cb759..000000000000 --- a/atlas/tests/ws_conflict/source/bpkg@1.0/bpkg.nimble +++ /dev/null @@ -1 +0,0 @@ -requires "https://github.com/cpkg >= 2.0" diff --git a/atlas/tests/ws_conflict/source/cpkg@1.0/cpkg.nimble b/atlas/tests/ws_conflict/source/cpkg@1.0/cpkg.nimble deleted file mode 100644 index 0fbd587aa3c9..000000000000 --- a/atlas/tests/ws_conflict/source/cpkg@1.0/cpkg.nimble +++ /dev/null @@ -1 +0,0 @@ -# No dependency here! diff --git a/atlas/tests/ws_conflict/source/cpkg@2.0/cpkg.nimble b/atlas/tests/ws_conflict/source/cpkg@2.0/cpkg.nimble deleted file mode 100644 index 381fae111046..000000000000 --- a/atlas/tests/ws_conflict/source/cpkg@2.0/cpkg.nimble +++ /dev/null @@ -1 +0,0 @@ -requires "https://github.com/dpkg >= 1.0" diff --git a/atlas/tests/ws_conflict/source/dpkg/dpkg.nimble b/atlas/tests/ws_conflict/source/dpkg/dpkg.nimble deleted file mode 100644 index 9ed72bb4973a..000000000000 --- a/atlas/tests/ws_conflict/source/dpkg/dpkg.nimble +++ /dev/null @@ -1 +0,0 @@ -# empty for now diff --git a/atlas/tests/ws_conflict/url.rules b/atlas/tests/ws_conflict/url.rules deleted file mode 100644 index c641cf990c90..000000000000 --- a/atlas/tests/ws_conflict/url.rules +++ /dev/null @@ -1 +0,0 @@ -https://github.com/$+ -> file://./source/$# diff --git a/atlas/versions.nim b/atlas/versions.nim deleted file mode 100644 index f955846c26fe..000000000000 --- a/atlas/versions.nim +++ /dev/null @@ -1,348 +0,0 @@ -# -# Atlas Package Cloner -# (c) Copyright 2021 Andreas Rumpf -# -# See the file "copying.txt", included in this -# distribution, for details about the copyright. -# - -import std / [strutils, parseutils, algorithm] - -type - Version* = distinct string - - VersionRelation* = enum - verGe, # >= V -- Equal or later - verGt, # > V - verLe, # <= V -- Equal or earlier - verLt, # < V - verEq, # V - verAny, # * - verSpecial # #head - - VersionReq* = object - r: VersionRelation - v: Version - - VersionInterval* = object - a: VersionReq - b: VersionReq - isInterval: bool - -template versionKey*(i: VersionInterval): string = i.a.v.string - -proc createQueryEq*(v: Version): VersionInterval = - VersionInterval(a: VersionReq(r: verEq, v: v)) - -proc extractGeQuery*(i: VersionInterval): Version = - if i.a.r in {verGe, verGt, verEq}: - result = i.a.v - else: - result = Version"" - -proc `$`*(v: Version): string {.borrow.} - -proc isSpecial(v: Version): bool = - result = v.string.len > 0 and v.string[0] == '#' - -proc isValidVersion*(v: string): bool {.inline.} = - result = v.len > 0 and v[0] in {'#'} + Digits - -proc isHead(v: Version): bool {.inline.} = cmpIgnoreCase(v.string, "#head") == 0 - -template next(l, p, s: untyped) = - if l > 0: - inc p, l - if p < s.len and s[p] == '.': - inc p - else: - p = s.len - else: - p = s.len - -proc lt(a, b: string): bool {.inline.} = - var i = 0 - var j = 0 - while i < a.len or j < b.len: - var x = 0 - let l1 = parseSaturatedNatural(a, x, i) - - var y = 0 - let l2 = parseSaturatedNatural(b, y, j) - - if x < y: - return true - elif x == y: - discard "continue" - else: - return false - next l1, i, a - next l2, j, b - - result = false - -proc `<`*(a, b: Version): bool = - # Handling for special versions such as "#head" or "#branch". - if a.isSpecial or b.isSpecial: - if a.isHead: return false - if b.isHead: return true - # any order will do as long as the "sort" operation moves #thing - # to the bottom: - if a.isSpecial and b.isSpecial: - return a.string < b.string - return lt(a.string, b.string) - -proc eq(a, b: string): bool {.inline.} = - var i = 0 - var j = 0 - while i < a.len or j < b.len: - var x = 0 - let l1 = parseSaturatedNatural(a, x, i) - - var y = 0 - let l2 = parseSaturatedNatural(b, y, j) - - if x == y: - discard "continue" - else: - return false - next l1, i, a - next l2, j, b - - result = true - -proc `==`*(a, b: Version): bool = - if a.isSpecial or b.isSpecial: - result = a.string == b.string - else: - result = eq(a.string, b.string) - -proc parseVer(s: string; start: var int): Version = - if start < s.len and s[start] == '#': - var i = start - while i < s.len and s[i] notin Whitespace: inc i - result = Version s.substr(start, i-1) - start = i - elif start < s.len and s[start] in Digits: - var i = start - while i < s.len and s[i] in Digits+{'.'}: inc i - result = Version s.substr(start, i-1) - start = i - else: - result = Version"" - -proc parseVersion*(s: string; start: int): Version = - var i = start - result = parseVer(s, i) - -proc parseSuffix(s: string; start: int; result: var VersionInterval; err: var bool) = - # >= 1.5 & <= 1.8 - # ^ we are here - var i = start - while i < s.len and s[i] in Whitespace: inc i - # Nimble doesn't use the syntax `>= 1.5, < 1.6` but we do: - if i < s.len and s[i] in {'&', ','}: - inc i - while i < s.len and s[i] in Whitespace: inc i - if s[i] == '<': - inc i - var r = verLt - if s[i] == '=': - inc i - r = verLe - while i < s.len and s[i] in Whitespace: inc i - result.b = VersionReq(r: r, v: parseVer(s, i)) - result.isInterval = true - while i < s.len and s[i] in Whitespace: inc i - # we must have parsed everything: - if i < s.len: - err = true - -proc parseVersionInterval*(s: string; start: int; err: var bool): VersionInterval = - var i = start - while i < s.len and s[i] in Whitespace: inc i - result = VersionInterval(a: VersionReq(r: verAny, v: Version"")) - if i < s.len: - case s[i] - of '*': result = VersionInterval(a: VersionReq(r: verAny, v: Version"")) - of '#', '0'..'9': - result = VersionInterval(a: VersionReq(r: verEq, v: parseVer(s, i))) - if result.a.v.isHead: result.a.r = verAny - err = i < s.len - of '=': - inc i - if i < s.len and s[i] == '=': inc i - while i < s.len and s[i] in Whitespace: inc i - result = VersionInterval(a: VersionReq(r: verEq, v: parseVer(s, i))) - err = i < s.len - of '<': - inc i - var r = verLt - if i < s.len and s[i] == '=': - r = verLe - inc i - while i < s.len and s[i] in Whitespace: inc i - result = VersionInterval(a: VersionReq(r: r, v: parseVer(s, i))) - parseSuffix(s, i, result, err) - of '>': - inc i - var r = verGt - if i < s.len and s[i] == '=': - r = verGe - inc i - while i < s.len and s[i] in Whitespace: inc i - result = VersionInterval(a: VersionReq(r: r, v: parseVer(s, i))) - parseSuffix(s, i, result, err) - else: - err = true - else: - result = VersionInterval(a: VersionReq(r: verAny, v: Version"#head")) - -proc parseTaggedVersions*(outp: string): seq[(string, Version)] = - result = @[] - for line in splitLines(outp): - if not line.endsWith("^{}"): - var i = 0 - while i < line.len and line[i] notin Whitespace: inc i - let commitEnd = i - while i < line.len and line[i] in Whitespace: inc i - while i < line.len and line[i] notin Digits: inc i - let v = parseVersion(line, i) - if v != Version(""): - result.add (line.substr(0, commitEnd-1), v) - result.sort proc (a, b: (string, Version)): int = - (if a[1] < b[1]: 1 - elif a[1] == b[1]: 0 - else: -1) - -proc matches(pattern: VersionReq; v: Version): bool = - case pattern.r - of verGe: - result = pattern.v < v or pattern.v == v - of verGt: - result = pattern.v < v - of verLe: - result = v < pattern.v or pattern.v == v - of verLt: - result = v < pattern.v - of verEq, verSpecial: - result = pattern.v == v - of verAny: - result = true - -proc matches*(pattern: VersionInterval; v: Version): bool = - if pattern.isInterval: - result = matches(pattern.a, v) and matches(pattern.b, v) - else: - result = matches(pattern.a, v) - -proc selectBestCommitMinVer*(data: openArray[(string, Version)]; elem: VersionInterval): string = - for i in countdown(data.len-1, 0): - if elem.matches(data[i][1]): - return data[i][0] - return "" - -proc selectBestCommitMaxVer*(data: openArray[(string, Version)]; elem: VersionInterval): string = - for i in countup(0, data.len-1): - if elem.matches(data[i][1]): return data[i][0] - return "" - -proc toSemVer*(i: VersionInterval): VersionInterval = - result = i - if not result.isInterval and result.a.r in {verGe, verGt}: - var major = 0 - let l1 = parseSaturatedNatural(result.a.v.string, major, 0) - if l1 > 0: - result.isInterval = true - result.b = VersionReq(r: verLt, v: Version($(major+1))) - -proc selectBestCommitSemVer*(data: openArray[(string, Version)]; elem: VersionInterval): string = - result = selectBestCommitMaxVer(data, elem.toSemVer) - -when isMainModule: - template v(x): untyped = Version(x) - - assert v"1.0" < v"1.0.1" - assert v"1.0" < v"1.1" - assert v"1.2.3" < v"1.2.4" - assert v"2.0.0" < v"2.0.0.1" - assert v"2.0.0" < v"20.0" - assert not (v"1.10.0" < v"1.2.0") - assert v"1.0" < v"#head" - assert v"#branch" < v"#head" - assert v"#branch" < v"1.0" - assert not (v"#head" < v"#head") - assert not (v"#head" < v"10.0") - - const lines = """ -24870f48c40da2146ce12ff1e675e6e7b9748355 1.6.12 -b54236aaee2fc90200cb3a4e7070820ced9ce605 1.6.10 -f06dc8ee3baf8f64cce67a28a6e6e8a8cd9bf04b 1.6.8 -2f85924354af35278a801079b7ff3f8805ff1f5a 1.6.6 -007bf1cb52eac412bc88b3ca2283127ad578ec04 1.6.4 -ee18eda86eef2db0a49788bf0fc8e35996ba7f0d 1.6.2 -1a2a82e94269741b0d8ba012994dd85a53f36f2d 1.6.0 -074f7159752b0da5306bdedb3a4e0470af1f85c0 1.4.8 -4eb05ebab2b4d8b0cd00b19a72af35a2d767819a 1.4.6 -944c8e6d04a044611ed723391272f3c86781eadd 1.4.4 -cd090a6151b452b99d65c5173400d4685916f970 1.4.2 -01dd8c7a959adac4aa4d73abdf62cbc53ffed11b 1.4.0 -1420d508dc4a3e51137647926d4db2f3fa62f43c 1.2.18 -726e3bb1ffc6bacfaab0a0abf0209640acbac807 1.2.16 -80d2206e68cd74020f61e23065c7a22376af8de5 1.2.14 -ddfe3905964fe3db33d7798c6c6c4a493cbda6a3 1.2.12 -6d914b7e6edc29c3b8ab8c0e255bd3622bc58bba 1.2.10 -0d1a9f5933eab686ab3b527b36d0cebd3949a503 1.2.8 -a5a0a9e3cb14e79d572ba377b6116053fc621f6d 1.2.6 -f9829089b36806ac0129c421bf601cbb30c2842c 1.2.4 -8b03d39fd387f6a59c97c2acdec2518f0b18a230 1.2.2 -a8a4725850c443158f9cab38eae3e54a78a523fb 1.2.0 -8b5888e0545ee3d931b7dd45d15a1d8f3d6426ef 1.0.10 -7282e53cad6664d09e8c9efd0d7f263521eda238 1.0.8 -283a4137b6868f1c5bbf0dd9c36d850d086fa007 1.0.6 -e826ff9b48af376fdc65ba22f7aa1c56dc169b94 1.0.4 -4c33037ef9d01905130b22a37ddb13748e27bb7c 1.0.2 -0b6866c0dc48b5ba06a4ce57758932fbc71fe4c2 1.0.0 -a202715d182ce6c47e19b3202e0c4011bece65d8 0.20.2 -8ea451196bd8d77b3592b8b34e7a2c49eed784c9 0.20.0 -1b512cc259b262d06143c4b34d20ebe220d7fb5c 0.19.6 -be22a1f4e04b0fec14f7a668cbaf4e6d0be313cb 0.19.4 -5cbc7f6322de8460cc4d395ed0df6486ae68004e 0.19.2 -79934561e8dde609332239fbc8b410633e490c61 0.19.0 -9c53787087e36b1c38ffd670a077903640d988a8 0.18.0 -a713ffd346c376cc30f8cc13efaee7be1b8dfab9 0.17.2 -2084650f7bf6f0db6003920f085e1a86f1ea2d11 0.17.0 -f7f68de78e9f286b704304836ed8f20d65acc906 0.16.0 -48bd4d72c45f0f0202a0ab5ad9d851b05d363988 0.15.2 -dbee7d55bc107b2624ecb6acde7cabe4cb3f5de4 0.15.0 -0a4854a0b7bcef184f060632f756f83454e9f9de 0.14.2 -5333f2e4cb073f9102f30aacc7b894c279393318 0.14.0 -7e50c5b56d5b5b7b96e56b6c7ab5e104124ae81b 0.13.0 -49bce0ebe941aafe19314438fb724c081ae891aa 0.12.0 -70789ef9c8c4a0541ba24927f2d99e106a6fe6cc 0.11.2 -79cc0cc6e501c8984aeb5b217a274877ec5726bc 0.11.0 -46d829f65086b487c08d522b8d0d3ad36f9a2197 0.10.2 -9354d3de2e1ecc1747d6c42fbfa209fb824837c0 0.9.6 -6bf5b3d78c97ce4212e2dd4cf827d40800650c48 0.9.4 -220d35d9e19b0eae9e7cd1f1cac6e77e798dbc72 0.9.2 -7a70058005c6c76c92addd5fc21b9706717c75e3 0.9.0 -32b4192b3f0771af11e9d850046e5f3dd42a9a5f 0.8.14 -""" - - proc p(s: string): VersionInterval = - var err = false - result = parseVersionInterval(s, 0, err) - assert not err - - let tags = parseTaggedVersions(lines) - let query = p">= 1.2 & < 1.4" - assert selectBestCommitMinVer(tags, query) == "a8a4725850c443158f9cab38eae3e54a78a523fb" - - let query2 = p">= 1.2 & < 1.4" - assert selectBestCommitMaxVer(tags, query2) == "1420d508dc4a3e51137647926d4db2f3fa62f43c" - - let query3 = p">= 0.20.0" - assert selectBestCommitSemVer(tags, query3) == "a202715d182ce6c47e19b3202e0c4011bece65d8" - - let query4 = p"#head" - assert selectBestCommitSemVer(tags, query4) == "24870f48c40da2146ce12ff1e675e6e7b9748355" diff --git a/compiler/installer.ini b/compiler/installer.ini index 5f7747fc544e..49ee59b0d0c5 100644 --- a/compiler/installer.ini +++ b/compiler/installer.ini @@ -66,7 +66,6 @@ Files: "doc" Files: "doc/html" Files: "tools" Files: "tools/debug/nim-gdb.py" -Files: "atlas" Files: "nimpretty" Files: "testament" Files: "nimsuggest" diff --git a/doc/atlas.md b/doc/atlas.md deleted file mode 100644 index 9438546ba201..000000000000 --- a/doc/atlas.md +++ /dev/null @@ -1,188 +0,0 @@ -# Atlas Package Cloner - -Atlas is a simple package cloner tool. It manages an isolated workspace that -contains projects and dependencies. - -Atlas is compatible with Nimble in the sense that it supports the Nimble -file format. - - -## Concepts - -Atlas uses three concepts: - -1. Workspaces -2. Projects -3. Dependencies - -### Workspaces - -Every workspace is isolated, nothing is shared between workspaces. -A workspace is a directory that has a file `atlas.workspace` inside it. Use `atlas init` -to create a workspace out of the current working directory. - -Projects plus their dependencies are stored in a workspace: - -``` - $workspace / main project - $workspace / other project - $workspace / _deps / dependency A - $workspace / _deps / dependency B -``` - -The deps directory can be set via `--deps:DIR` during `atlas init`. - - -### Projects - -A workspace contains one or multiple "projects". These projects can use each other and it -is easy to develop multiple projects at the same time. - -### Dependencies - -Inside a workspace there can be a `_deps` directory where your dependencies are kept. It is -easy to move a dependency one level up and out the `_deps` directory, turning it into a project. -Likewise, you can move a project to the `_deps` directory, turning it into a dependency. - -The only distinction between a project and a dependency is its location. For dependency resolution -a project always has a higher priority than a dependency. - - -## No magic - -Atlas works by managing two files for you, the `project.nimble` file and the `nim.cfg` file. You can -edit these manually too, Atlas doesn't touch what should be left untouched. - - -## 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 much less important. - - - -## Commands - -Atlas supports the following commands: - - -## Use / - -Clone the package behind `url` or `package name` and its dependencies into -the `_deps` directory and make it available for your current project which -should be in the current working directory. Atlas will create or patch -the files `$project.nimble` and `nim.cfg` for you so that you can simply -import the required modules. - -For example: - -``` - mkdir newproject - cd newproject - git init - atlas use lexim - # add `import lexim` to your example.nim file - nim c example.nim - -``` - - -### Clone/Update / - -Clones a URL and all of its dependencies (recursively) into the workspace. -Creates or patches a `nim.cfg` file with the required `--path` entries. - -**Note**: Due to the used algorithms an `update` is the same as a `clone`. - - -If a `` is given instead the name is first translated into an URL -via `packages.json` or via a github search. - - -### Search - -Search the package index `packages.json` for a package that the given terms -in its description (or name or list of tags). - - -### Install - -Use the .nimble file to setup the project's dependencies. - -### UpdateProjects / updateDeps [filter] - -Update every project / dependency in the workspace that has a remote URL that -matches `filter` if a filter is given. The project / dependency is only updated -if there are no uncommitted changes. - -### Others - -Run `atlas --help` for more features. - - -### Overrides - -You can override how Atlas resolves a package name or a URL. The overrides use -a simple pattern matching language and are flexible enough to integrate private -gitlab repositories. - -To setup an override file, edit the `$workspace/atlas.workspace` file to contain -a line like `overrides="urls.rules"`. Then create a file `urls.rules` that can -contain lines like: - -``` -customProject -> https://gitlab.company.com/customProject -https://github.com/araq/ormin -> https://github.com/useMyForkInstead/ormin -``` - -The `$` has a special meaning in a pattern: - -================= ======================================================== -``$$`` Matches a single dollar sign. -``$*`` Matches until the token following the ``$*`` was found. - The match is allowed to be of 0 length. -``$+`` Matches until the token following the ``$+`` was found. - The match must consist of at least one char. -``$s`` Skips optional whitespace. -================= ======================================================== - -For example, here is how to override any github link: - -``` -https://github.com/$+ -> https://utopia.forall/$# -``` - -You can use `$1` or `$#` to refer to captures. - - -### Virtual Nim environments - -Atlas supports setting up a virtual Nim environment via the `env` command. You can -even install multiple different Nim versions into the same workspace. - -For example: - -``` -atlas env 1.6.12 -atlas env devel -``` - -When completed, run `source nim-1.6.12/activate.sh` on UNIX and `nim-1.6.12/activate.bat` on Windows. diff --git a/koch.nim b/koch.nim index e15215df0d18..b42987cad21c 100644 --- a/koch.nim +++ b/koch.nim @@ -11,6 +11,7 @@ const NimbleStableCommit = "168416290e49023894fc26106799d6f1fc964a2d" # master + AtlasStableCommit = "#head" # examples of possible values: #head, #ea82b54, 1.2.3 FusionStableHash = "#372ee4313827ef9f2ea388840f7d6b46c2b1b014" ChecksumsStableCommit = "b4c73320253f78e3a265aec6d9e8feb83f97c77b" @@ -72,6 +73,7 @@ Possible Commands: e.g. nimble) doesn't require network connectivity nimble builds the Nimble tool + atlas builds the Atlas tool fusion installs fusion via Nimble Boot options: @@ -156,6 +158,14 @@ proc bundleNimbleExe(latest: bool, args: string) = nimCompile("dist/nimble/src/nimble.nim", options = "-d:release --mm:refc --noNimblePath " & args) +proc bundleAtlasExe(latest: bool, args: string) = + let commit = if latest: "HEAD" else: AtlasStableCommit + cloneDependency(distDir, "https://github.com/nim-lang/atlas.git", + commit = commit, allowBundled = true) + # installer.ini expects it under $nim/bin + nimCompile("dist/atlas/src/atlas.nim", + options = "-d:release --noNimblePath " & args) + proc bundleNimsuggest(args: string) = nimCompileFold("Compile nimsuggest", "nimsuggest/nimsuggest.nim", options = "-d:danger " & args) @@ -179,7 +189,6 @@ proc bundleWinTools(args: string) = buildVccTool(args) nimCompile("tools/nimgrab.nim", options = "-d:ssl " & args) nimCompile("tools/nimgrep.nim", options = args) - nimCompile("atlas/atlas.nim", options = args) nimCompile("testament/testament.nim", options = args) when false: # not yet a tool worth including @@ -193,6 +202,7 @@ proc bundleChecksums(latest: bool) = proc zip(latest: bool; args: string) = bundleChecksums(latest) bundleNimbleExe(latest, args) + bundleAtlasExe(latest, args) bundleNimsuggest(args) bundleNimpretty(args) bundleWinTools(args) @@ -236,21 +246,17 @@ proc buildTools(args: string = "") = "--opt:speed --stacktrace -d:debug --stacktraceMsgs -d:nimCompilerStacktraceHints " & args, outputName = "nim_dbg") - nimCompileFold("Compile atlas", "atlas/atlas.nim", options = "-d:release " & args, - outputName = "atlas") - proc testTools(args: string = "") = nimCompileFold("Compile nimgrep", "tools/nimgrep.nim", options = "-d:release " & args) when defined(windows): buildVccTool(args) bundleNimpretty(args) nimCompileFold("Compile testament", "testament/testament.nim", options = "-d:release " & args) - nimCompileFold("Compile atlas", "atlas/atlas.nim", options = "-d:release " & args, - outputName = "atlas") proc nsis(latest: bool; args: string) = bundleChecksums(latest) bundleNimbleExe(latest, args) + bundleAtlasExe(latest, args) bundleNimsuggest(args) bundleWinTools(args) # make sure we have generated the niminst executables: @@ -612,12 +618,6 @@ proc runCI(cmd: string) = execFold("build nimsuggest_testing", "nim c -o:bin/nimsuggest_testing -d:release nimsuggest/nimsuggest") execFold("Run nimsuggest tests", "nim r nimsuggest/tester") - execFold("Run atlas tests", "nim c -r -d:atlasTests atlas/atlas.nim clone https://github.com/disruptek/balls") - # compile it again to get rid of `-d:atlasTests`: - nimCompileFold("Compile atlas", "atlas/atlas.nim", options = "-d:release ", - outputName = "atlas") - execFold("Run more atlas tests", "nim c -r atlas/tester.nim") - kochExecFold("Testing booting in refc", "boot -d:release --mm:refc -d:nimStrictMode --lib:lib") @@ -731,6 +731,7 @@ when isMainModule: of "xtemp": xtemp(op.cmdLineRest) of "wintools": bundleWinTools(op.cmdLineRest) of "nimble": bundleNimbleExe(latest, op.cmdLineRest) + of "atlas": bundleAtlasExe(latest, op.cmdLineRest) of "nimsuggest": bundleNimsuggest(op.cmdLineRest) # toolsNoNimble is kept for backward compatibility with build scripts of "toolsnonimble", "toolsnoexternal": @@ -738,6 +739,7 @@ when isMainModule: of "tools": buildTools(op.cmdLineRest) bundleNimbleExe(latest, op.cmdLineRest) + bundleAtlasExe(latest, op.cmdLineRest) of "checksums": bundleChecksums(latest) of "pushcsource": diff --git a/atlas/parse_requires.nim b/tools/atlas/parse_requires.nim similarity index 97% rename from atlas/parse_requires.nim rename to tools/atlas/parse_requires.nim index 7e26a16560fb..66879d04f247 100644 --- a/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