diff --git a/.github/workflows/release_build.yml b/.github/workflows/release_build.yml index fa8b1853..7a0ddda2 100644 --- a/.github/workflows/release_build.yml +++ b/.github/workflows/release_build.yml @@ -1,93 +1,132 @@ # This workflow will automatically upload a binary artifact when a release/tag is created name: Build and upload binary -on: - # allow to build manually +on: + # allow to build manually workflow_dispatch: - # build automatically when pushing a tag + # build automatically when pushing a tag push: branches: - "!*" tags: - "v*" +env: + ZIG_SYSTEM_LINKER_HACK: 1 + jobs: - # ---------------------------------------------------------------------------- - # this will checkout and build nim stable from gh repository on manylinux2014 / CentOS 7 - build-linux: - runs-on: ubuntu-latest - container: - image: quay.io/pypa/manylinux2014_x86_64 + build: + timeout-minutes: 45 + strategy: + fail-fast: false + matrix: + include: + # Windows builds + - os: windows-latest + target: x86_64-windows-gnu + suffix: windows_amd64 + cpu: amd64 + - os: windows-latest + target: aarch64-windows-gnu + suffix: windows_arm64 + cpu: arm64 + # Linux builds + - os: ubuntu-latest + target: aarch64-linux-gnu + suffix: linux_arm64 + cpu: arm64 + - os: ubuntu-latest + target: x86_64-linux-gnu + suffix: linux_amd64 + cpu: amd64 + # MacOS builds + - os: macos-latest + target: aarch64-macos-none + suffix: macosx_arm64 + cpu: arm64 + - os: macos-latest + target: x86_64-macos-none + suffix: macosx_amd64 + cpu: amd64 + runs-on: ${{ matrix.os }} + name: Build ${{ matrix.target }} steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 + - name: Setup Nim + uses: jiro4989/setup-nim-action@v1 + with: + repo-token: ${{ secrets.GITHUB_TOKEN }} + - name: Install zig + uses: korandoru/setup-zig@v1 + with: + zig-version: 0.11.0 + - name: Install dependencies + run: | + nimble install -y zigcc + - name: Build proxy + run: | + nimble -y c src/choosenimpkg/proxyexe -d:zig.target="${{ matrix.target }}" --cpu:"${{ matrix.cpu }}" -d:release --opt:size - name: Build binary run: | - CHOOSENIM_DIR=`pwd` - # checking out and compiling nim last stable from git tag - mkdir -p nimDir - STABLE_NIM=`curl -sSL http://nim-lang.org/channels/stable | xargs` - git clone --depth 1 --branch v$STABLE_NIM https://github.com/nim-lang/Nim.git nimDir - cd nimDir - sh build_all.sh - bin/nim c koch - ./koch boot -d:release - ./koch tools - PATH=$PATH:`pwd`/bin - # compile choosenim - cd $CHOOSENIM_DIR - nimble install -y - nimble build - ls bin/* - + nimble -y build -d:noBuildProxy -d:zig.target="${{ matrix.target }}" --cpu:"${{ matrix.cpu }}" -d:release --opt:size + + - name: Update file name + if: ${{ matrix.os == 'ubuntu-latest' || matrix.os == 'macos-latest' }} + run: mv bin/choosenim bin/choosenim-${{ github.ref_name }}_${{ matrix.suffix }} + - name: Update file name + if: ${{ matrix.os == 'windows-latest' }} + run: mv bin\choosenim.exe bin\choosenim-${{ github.ref_name }}_${{ matrix.suffix }}.exe + - name: Upload binaries to release/tag uses: svenstaro/upload-release-action@v2 with: repo_token: ${{ secrets.GITHUB_TOKEN }} - overwrite: true + overwrite: true + file_glob: true tag: ${{ github.ref }} - asset_name: choosenim-manylinux2014 - file: ${{ runner.workspace }}/choosenim/bin/choosenim + file: bin/choosenim-${{ github.ref_name }}_${{ matrix.suffix }}* + - name: Upload artefacts + uses: actions/upload-artifact@v4 + with: + name: choosenim-${{ github.ref_name }}_${{ matrix.suffix }} + path: bin/choosenim-${{ github.ref_name }}_${{ matrix.suffix }}* + retention-days: 1 - # ---------------------------------------------------------------------------- - # this uses choosenim by itself - you may need to build manually if you break choosenim - build-win32: - runs-on: windows-latest + deploy-site: + name: Deploy site + needs: build + permissions: + pages: write + id-token: write + runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 - - uses: iffy/install-nim@v4.0.1 - - name: Build binary - run: | - nimble install -y - nimble build - dir bin/* - - - name: Upload binaries to release/tag - uses: svenstaro/upload-release-action@v2 + - uses: actions/checkout@v4 + + - name: Download workflow artifact + uses: actions/download-artifact@v4 with: - repo_token: ${{ secrets.GITHUB_TOKEN }} - overwrite: true - tag: ${{ github.ref }} - asset_name: choosenim-windows - file: ${{ runner.workspace }}/choosenim/bin/choosenim.exe + path: site/ - # ---------------------------------------------------------------------------- - # this uses choosenim by itself - you may need to build manually if you break choosenim - build-macos: - runs-on: macos-latest - steps: - - uses: actions/checkout@v2 - - uses: iffy/install-nim@v4.0.1 - - name: Build binary - run: | - nimble install -y - nimble build - ls bin/* - - - name: Upload binaries to release/tag - uses: svenstaro/upload-release-action@v2 + - name: Add latest version + run: echo "${{ github.ref_name }}" >> site/stable + + - name: Setup Nim + uses: jiro4989/setup-nim-action@v1 with: - repo_token: ${{ secrets.GITHUB_TOKEN }} - overwrite: true - tag: ${{ github.ref }} - asset_name: choosenim-macos - file: ${{ runner.workspace }}/choosenim/bin/choosenim + nim-version: devel + repo-token: ${{ secrets.GITHUB_TOKEN }} + + - name: Create index + run: nim md2html --out:site/index.html readme.md + + - name: Add init script + run: mv scripts/choosenim-unix-init.sh site/init.sh + + - name: Create pages artefact + uses: actions/upload-pages-artifact@v3 + with: + path: site/ + + - name: Deploy site + uses: actions/deploy-pages@v4 + diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 00000000..f52efbef --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,52 @@ +name: Run tests + +on: + push: + branches: + - master + pull_request: + +jobs: + nim-tests: + name: Nim tests + timeout-minutes: 60 + strategy: + matrix: + os: + - ubuntu-latest + - windows-latest + - macos-latest + runs-on: ${{ matrix.os }} + steps: + - uses: actions/checkout@v4 + + - name: Setup Nim + uses: jiro4989/setup-nim-action@v1 + with: + repo-token: ${{ secrets.GITHUB_TOKEN }} + + - name: Can build + run: nimble -y build + + - name: Run tests + run: nimble -y test + + unix-test: + name: Install script test (Unix like) + strategy: + matrix: + os: + - ubuntu-latest + - macos-latest + runs-on: ${{ matrix.os }} + steps: + - uses: actions/checkout@v4 + + - name: Run script + run: bash scripts/choosenim-unix-init.sh -y + + - name: Update path + run: echo "~/.nimble/bin" >> $GITHUB_PATH + + - name: Test Nim works + run: nim --version diff --git a/analytics.md b/analytics.md deleted file mode 100644 index c7c74697..00000000 --- a/analytics.md +++ /dev/null @@ -1,98 +0,0 @@ -# Anonymous gathering of user analytics - -Starting with version 0.3.0, choosenim has the ability to gather anonymous -aggregate user behaviour analytics and to report them to Google Analytics. - -This is entirely optional and is "opt-neutral", that is choosenim will -ask you to decide whether you want to participate in this data gathering -without offering a default option. You must choose. - -## Why? - -This is the most straightforward way to gather information about Nim's users -directly. It allows us to be aware of the platforms where Nim is being used -and any installation issues that our users are facing. - -Overall the data we collect allows us to prioritise fixes and features based on -how people are using choosenim. For example: - -* If there is a high exception count on specific platforms, we can prioritise -fixing it for the next release. -* Collecting the OS version allows us to decide which platforms to prioritise -and support. - -## What is collected? - -At a high level we currently collect a number of events, exception counts and -build and download timings. - -To be more specific, we record the following information: - -* OS information, for example: ``Mac OS X v10.11 El Capitan`` or - ``Linux 4.11.6-041106-generic x86_64``. -* The command-line arguments passed to choosenim, for example - ``choosenim --nimbleDir:~/myNimbleDir stable``. -* Events when a build is started, when it fails and when it succeeds. -* Build time in seconds and download time in seconds (including the - URL that was downloaded). -* The choosenim version. - -For each user a new UUID is generated so there is no way for us or Google -to identify you. The UUID is used to measure user counts. - -## Where is the data sent? - -The recorded data is sent to Google Analytics over HTTPS. - -## Who has access? - -The analytics are currently only accessible to the maintainers of choosenim. -At the minute this only includes [@dom96](https://github.com/dom96). - -Summaries of the data may be released in the future to the public. - -## Where is the code? - -The code is viewable in [telemetry.nim](https://github.com/dom96/choosenim/blob/master/src/choosenimpkg/telemetry.nim). - -The reporting is done asynchronously and will fail fast to avoid any -delay in execution. - -## Opting in - -To opt-in simply answer "yes" or "y" to the following question: - -``` -Prompt: Can choosenim record and send anonymised telemetry data? [y/n] - ... Anonymous aggregate user analytics allow us to prioritise - ... fixes and features based on how, where and when people use Nim. - ... For more details see: https://goo.gl/NzUEPf. -Answer: -``` - -If you answer "no" and then change your mind, you can always have choosenim -ask you again by removing the ``analytics`` file in the choosenim directory, -usually ``rm ~/.choosenim/analytics`` should do the trick. - -## Opting out - -Choosenim analytics help us and leaving them on is appreciated. However, -we understand if you don't feel comfortable having them on. - -To opt out simply answer "no" or "n" to the following question: - -``` -Prompt: Can choosenim record and send anonymised telemetry data? [y/n] - ... Anonymous aggregate user analytics allow us to prioritise - ... fixes and features based on how, where and when people use Nim. - ... For more details see: https://goo.gl/NzUEPf. -Answer: -``` - -You can also set the ``CHOOSENIM_NO_ANALYTICS`` or ``DO_NOT_TRACK`` variable in your environment: - -``` -export CHOOSENIM_NO_ANALYTICS=1 -# or -export DO_NOT_TRACK=1 -``` diff --git a/bin/.gitkeep b/bin/.gitkeep deleted file mode 100644 index 8b137891..00000000 --- a/bin/.gitkeep +++ /dev/null @@ -1 +0,0 @@ - diff --git a/choosenim.nimble b/choosenim.nimble index 8ac20ddf..7c79e920 100644 --- a/choosenim.nimble +++ b/choosenim.nimble @@ -1,4 +1,5 @@ # Package +import std/[os, strutils] version = "0.8.4" author = "Dominik Picheta" @@ -15,13 +16,8 @@ skipExt = @["nim"] # Note: https://github.com/dom96/choosenim/issues/233 (need to resolve when updating Nimble) requires "nim >= 1.2.6", "nimble#8f7af86" -when defined(macosx): - requires "libcurl >= 1.0.0" -requires "analytics >= 0.3.0" -requires "osinfo >= 0.3.0" +requires "libcurl >= 1.0.0" +requires "https://github.com/ire4ever1190/osinfo#aa7d296" requires "zippy >= 0.7.2" when defined(windows): - requires "puppy 1.5.4" - -task release, "Build a release binary": - exec "nimble build -d:release" + requires "puppy >= 1.5.4" diff --git a/config.nims b/config.nims new file mode 100644 index 00000000..70ee47f8 --- /dev/null +++ b/config.nims @@ -0,0 +1,18 @@ +const target {.strdefine: "zig.target".} = "" +if target != "": + switch("cc", "clang") + let zigCmd = "zigcc" & (if defined(windows): ".cmd" else: "") + switch("clang.exe", zigCmd) + switch("clang.linkerexe", zigCmd) + let targetArgs = "-target " & target + switch("passL", targetArgs) + switch("passC", targetArgs) + + when defined(macosx): + # We need to define extra search paths + # Found via the default paths here + # https://discussions.apple.com/thread/2390561?sortBy=best#11330927022 + switch("passL", "-F/Library/Frameworks -F/System/Library/Frameworks -F/System/Library/Frameworks/Security.framework -L/usr/lib -L/usr/local/lib") + switch("passL", "--sysroot=/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk") + +switch("d", "zippyNoSimd") diff --git a/readme.md b/readme.md index abe055e6..690b6cb0 100644 --- a/readme.md +++ b/readme.md @@ -1,4 +1,4 @@ -# choosenim +# Choosenim choosenim installs the [Nim programming language](https://nim-lang.org) from official downloads and sources, enabling you to easily switch between stable @@ -54,7 +54,7 @@ Versions can be selected via `choosenim 1.6.6` or by branch/tag name via `choose ### Windows Download the latest Windows version from the -[releases](https://github.com/dom96/choosenim/releases) page (the .zip file, for example here is [``v0.7.4``](https://github.com/dom96/choosenim/releases/download/v0.7.4/choosenim-0.7.4_windows_amd64.zip)). +[releases](https://github.com/ire4ever1190/choosenim/releases) page (the .zip file, for example here is [``v0.7.4``](https://github.com/dom96/choosenim/releases/download/v0.7.4/choosenim-0.7.4_windows_amd64.zip)). Extract the zip archive and run the ``runme.bat`` script. Follow any on screen prompts and enjoy your new Nim and choosenim installation. @@ -67,11 +67,11 @@ this isn't vetted by the Nim team so you do so at your own risk). ### Unix +```cmd +curl https://choosenim.leahy.dev/init.sh -sSf | sh ``` -curl https://nim-lang.org/choosenim/init.sh -sSf | sh -``` -``` -wget -qO - https://nim-lang.org/choosenim/init.sh | sh +```cmd +wget -qO - https://choosenim.leahy.dev/init.sh | sh ``` **Optional:** You can specify the initial version you would like the `init.sh` @@ -106,16 +106,17 @@ install them accordingly. ## Dependencies -| | Windows | Linux | macOS (*) | -|------------|:-----------------------------:|:-----------------------:|:---------------------:| +| 📦 | Windows | Linux | macOS (\*) | +|------------|-------------------------------|-------------------------|-----------------------| | C compiler | *Downloaded automatically* | gcc/clang | gcc/clang | | OpenSSL | N/A | N/A | N/A | | curl | N/A | Any recent version (※) | Any recent version | + \* Many macOS dependencies should already be installed. You may need to install a C compiler however. More information on dependencies is available [here](https://nim-lang.org/install_unix.html). - + ※ Some users needed to install `libcurl4-gnutls-dev` (see [here](https://github.com/dom96/choosenim/issues/303)) Git is required when installing #HEAD or a specific commit of Nim. The `unxz` @@ -180,12 +181,6 @@ Options: --firstInstall Used by install script. ``` -## Analytics - -Check out the -[analytics](https://github.com/dom96/choosenim/blob/master/analytics.md) -document for details. - ## License MIT diff --git a/scripts/choosenim-unix-init.sh b/scripts/choosenim-unix-init.sh index af9187b1..56e6f114 100755 --- a/scripts/choosenim-unix-init.sh +++ b/scripts/choosenim-unix-init.sh @@ -9,7 +9,7 @@ set -u set -e -url_prefix="https://github.com/dom96/choosenim/releases/download/" +url_prefix="https://github.com/ire4ever1190/choosenim/releases/download/" temp_prefix="${TMPDIR:-/tmp}" @@ -31,16 +31,16 @@ install() { local platform=$RET_VAL local stable_version= if has_curl; then - stable_version=`curl -sSfL https://nim-lang.org/choosenim/stable` + stable_version=`curl -sSfL https://choosenim.leahy.dev/stable` elif has_wget; then - stable_version=`wget -qO - https://nim-lang.org/choosenim/stable` + stable_version=`wget -qO - https://choosenim.leahy.dev/stable` fi local filename="choosenim-$stable_version"_"$platform" - local url="$url_prefix"v"$stable_version/$filename" + local url="$url_prefix$stable_version/$filename" local ext="" case $platform in - *macosx_amd64* | *linux_amd64* ) + *macosx_amd64* | *linux_amd64* | *linux_arm*) ;; *windows_amd64* ) # Download ZIP for Windows diff --git a/src/choosenim.nim b/src/choosenim.nim index 74938781..ed561a97 100644 --- a/src/choosenim.nim +++ b/src/choosenim.nim @@ -7,7 +7,7 @@ import nimblepkg/common as nimbleCommon from nimblepkg/packageinfo import getNameVersion import choosenimpkg/[download, builder, switcher, common, cliparams, versions] -import choosenimpkg/[utils, channel, telemetry] +import choosenimpkg/[utils, channel] when defined(windows): import choosenimpkg/env @@ -55,14 +55,16 @@ proc safeSwitchTo(version: Version, params: CliParams, wasInstalled: bool) = except Exception as exc: display("Warning:", "Cleaning failed: " & exc.msg, Warning) - # Report telemetry. - report(initEvent(ErrorEvent, label=exc.msg), params) raise newException(ChooseNimError, "Installation failed") proc chooseVersion(version: string, params: CliParams) = # Command is a version. - let version = parseVersion(version) + var parsedVer = parseVersion(version) + # We need to build for ARM from source for normal releases + # TODO: Figure out who controls the website and ask if they could upload ARM builds + if getArch().startsWith("arm") and not (parsedVer.isSpecial or parsedVer.isDevel): + parsedVer = newVersion("#v" & version) # Verify that C compiler is installed. if params.needsCCInstall(): when defined(windows): @@ -106,11 +108,11 @@ proc chooseVersion(version: string, params: CliParams) = else: display("Info:", "DLLs already installed", priority = MediumPriority) - var wasInstalled = params.isVersionInstalled(version) + var wasInstalled = params.isVersionInstalled(parsedVer) if not wasInstalled: - installVersion(version, params) + installVersion(parsedVer, params) - safeSwitchTo(version, params, wasInstalled) + safeSwitchTo(parsedVer, params, wasInstalled) proc choose(params: CliParams) = if dirExists(params.command): @@ -324,8 +326,6 @@ proc remove(params: CliParams) = proc performAction(params: CliParams) = - # Report telemetry. - report(initEvent(ActionEvent), params) case params.command.normalize of "update": @@ -346,14 +346,10 @@ when isMainModule: try: parseCliParams(params) createDir(params.chooseNimDir) - discard loadAnalytics(params) performAction(params) except NimbleError: let currentExc = (ref NimbleError)(getCurrentException()) (error, hint) = getOutputInfo(currentExc) - # Report telemetry. - report(currentExc, params) - report(initEvent(ErrorEvent, label=currentExc.msg), params) if error.len > 0: displayTip() diff --git a/src/choosenim.nims b/src/choosenim.nims index 616b54b3..068aeb3f 100644 --- a/src/choosenim.nims +++ b/src/choosenim.nims @@ -5,3 +5,6 @@ elif not defined(windows): when defined(staticBuild): import "choosenimpkg/proxyexe.nims" + +# We don't need it, but nimble does for SslError import +switch("define", "ssl") diff --git a/src/choosenimpkg/builder.nim b/src/choosenimpkg/builder.nim index fd3119c6..b7c34160 100644 --- a/src/choosenimpkg/builder.nim +++ b/src/choosenimpkg/builder.nim @@ -3,7 +3,7 @@ import os, times import nimblepkg/[version, cli] import nimblepkg/common as nimble_common -import cliparams, download, utils, common, telemetry +import cliparams, download, utils, common when defined(windows): import switcher @@ -109,7 +109,6 @@ proc setPermissions() = proc build*(extractDir: string, version: Version, params: CliParams) = # Report telemetry. - report(initEvent(BuildEvent), params) let startTime = epochTime() let currentDir = getCurrentDir() @@ -161,10 +160,6 @@ proc build*(extractDir: string, version: Version, params: CliParams) = except Exception as exc: display("Warning:", "Cleaning c_code failed: " & exc.msg, Warning) - # Report telemetry. - report(initEvent(BuildSuccessEvent), params) - report(initTiming(BuildTime, $version, startTime, $LabelSuccess), params) - if not success and not params.skipClean: # Perform clean up. display("Cleaning", "failed build", priority = HighPriority) @@ -174,7 +169,3 @@ proc build*(extractDir: string, version: Version, params: CliParams) = removeDir(extractDir) except Exception as exc: display("Warning:", "Cleaning failed: " & exc.msg, Warning) - - # Report telemetry. - report(initEvent(BuildFailureEvent), params) - report(initTiming(BuildTime, $version, startTime, $LabelFailure), params) diff --git a/src/choosenimpkg/channel.nim b/src/choosenimpkg/channel.nim index ca1ff521..ac8d0a80 100644 --- a/src/choosenimpkg/channel.nim +++ b/src/choosenimpkg/channel.nim @@ -59,4 +59,4 @@ proc setCurrentChannel*(channel: string, params: CliParams) = proc getCurrentChannel*(params: CliParams): string = if not fileExists(params.getCurrentChannelFile()): return "" - return readFile(params.getCurrentChannelFile()).strip() \ No newline at end of file + return readFile(params.getCurrentChannelFile()).strip() diff --git a/src/choosenimpkg/cliparams.nim b/src/choosenimpkg/cliparams.nim index a4b998c7..d09e11ae 100644 --- a/src/choosenimpkg/cliparams.nim +++ b/src/choosenimpkg/cliparams.nim @@ -2,7 +2,6 @@ import parseopt, strutils, os import nimblepkg/[cli, options, config] import nimblepkg/common as nimble_common -import analytics import common @@ -13,7 +12,6 @@ type choosenimDir*: string firstInstall*: bool nimbleOptions*: Options - analytics*: PuppyAnalytics pendingReports*: int ## Count of pending telemetry reports. force*: bool latest*: bool diff --git a/src/choosenimpkg/common.nim b/src/choosenimpkg/common.nim index f2f39213..0b9a0b78 100644 --- a/src/choosenimpkg/common.nim +++ b/src/choosenimpkg/common.nim @@ -14,6 +14,8 @@ const "nimsuggest", "testament", "nim-gdb", + "atlas", + "nim_dbg" ] mingwProxies* = [ diff --git a/src/choosenimpkg/download.nim b/src/choosenimpkg/download.nim index 9a1c3112..3827f9d9 100644 --- a/src/choosenimpkg/download.nim +++ b/src/choosenimpkg/download.nim @@ -7,7 +7,7 @@ import nimblepkg/[version, cli] when defined(curl): import libcurl except Version -import cliparams, common, telemetry, utils +import cliparams, common, utils const githubTagReleasesUrl = "https://api.github.com/repos/nim-lang/Nim/tags" @@ -69,7 +69,7 @@ proc addGithubAuthentication(url: string): string = when defined(curl): proc checkCurl(code: Code) = if code != E_OK: - raise newException(AssertionError, "CURL failed: " & $easy_strerror(code)) + raise newException(CatchableError, "CURL failed: " & $easy_strerror(code)) proc downloadFileCurl(url, outputPath: string) = displayDebug("Downloading using Curl") @@ -218,7 +218,6 @@ proc downloadFile*(url, outputPath: string, params: CliParams) = let msg = "Couldn't download file from $1.\nResponse was: $2" % [url, getCurrentExceptionMsg()] display("Info:", msg, Warning, MediumPriority) - report(initTiming(DownloadTime, url, startTime, $LabelFailure), params) raise moveFile(tempOutputPath, outputPath) @@ -226,8 +225,6 @@ proc downloadFile*(url, outputPath: string, params: CliParams) = showBar(1, 0) echo("") - report(initTiming(DownloadTime, url, startTime, $LabelSuccess), params) - proc needsDownload(params: CliParams, downloadUrl: string, outputPath: var string): bool = ## Returns whether the download should commence. @@ -252,7 +249,7 @@ proc downloadImpl(version: Version, params: CliParams): string = try: let rawContents = retrieveUrl(githubNightliesReleasesUrl.addGithubAuthentication()) let parsedContents = parseJson(rawContents) - (url, reference) = getNightliesUrl(parsedContents, arch) + (url, reference) = getNightliesUrl(parsedContents) if url.len == 0: display( "Warning", "Recent nightly release not found, installing latest devel commit.", diff --git a/src/choosenimpkg/switcher.nim b/src/choosenimpkg/switcher.nim index c6510ae8..9c1ef4ee 100644 --- a/src/choosenimpkg/switcher.nim +++ b/src/choosenimpkg/switcher.nim @@ -8,23 +8,29 @@ import cliparams, common when defined(windows): import env +const target {.strdefine: "zig.target".} = "" + proc compileProxyexe() = var cmd = when defined(windows): "cmd /C \"cd ../../ && nimble c" else: "cd ../../ && nimble c" + cmd &= " -y" when defined(release): cmd.add " -d:release" when defined(staticBuild): cmd.add " -d:staticBuild" + when target != "": + cmd.add " -d:zig.target=" & target cmd.add " src/choosenimpkg/proxyexe" when defined(windows): cmd.add("\"") let (output, exitCode) = gorgeEx(cmd) doAssert exitCode == 0, $(output, cmd) -static: compileProxyexe() +when not defined(noBuildProxy): + static: compileProxyexe() const proxyExe = staticRead("proxyexe".addFileExt(ExeExt)) diff --git a/src/choosenimpkg/telemetry.nim b/src/choosenimpkg/telemetry.nim deleted file mode 100644 index 0f3a79c6..00000000 --- a/src/choosenimpkg/telemetry.nim +++ /dev/null @@ -1,170 +0,0 @@ -# Copyright (C) Dominik Picheta. All rights reserved. -# BSD-3-Clause License. Look at license.txt for more info. - -import os, strutils, options, times, asyncdispatch - -import analytics, nimblepkg/cli - -when defined(windows): - import osinfo/win -else: - import osinfo/posix - -import cliparams, common, utils - -type - EventCategory* = enum - ActionEvent, - BuildEvent, BuildSuccessEvent, BuildFailureEvent, - ErrorEvent, - OSInfoEvent - - Event* = object - category*: EventCategory - action*: string - label*: string - value*: Option[int] - - TimingCategory* = enum - BuildTime, - DownloadTime - - Timing* = object - category*: TimingCategory - name*: string - time*: int - label*: string - - LabelCategory* = enum - LabelSuccess, LabelFailure - - - -proc initEvent*(category: EventCategory, action="", label="", - value=none(int)): Event = - let cmd = "choosenim " & commandLineParams().join(" ") - return Event(category: category, - action: if action.len == 0: cmd else: action, - label: label, value: value) - -proc initTiming*(category: TimingCategory, name: string, startTime: float, - label=""): Timing = - ## The `startTime` is the Unix epoch timestamp for when the timing started - ## (from `epochTime`). - ## This function will automatically calculate the elapsed time based on that. - let elapsed = int((epochTime() - startTime)*1000) - return Timing(category: category, - name: name, - label: label, time: elapsed) - -proc promptCustom(msg: string, params: CliParams): string = - if params.nimbleOptions.forcePrompts == forcePromptYes: - display("Prompt:", msg, Warning, HighPriority) - display("Answer:", "Forced Yes", Warning, HighPriority) - return "y" - else: - return promptCustom(msg, "") - -proc analyticsPrompt(params: CliParams) = - let msg = ("Can choosenim record and send anonymised telemetry " & - "data? [y/n]\n" & - "Anonymous aggregate user analytics allow us to prioritise\n" & - "fixes and features based on how, where and when people " & - "use Nim.\n" & - "For more details see: https://goo.gl/NzUEPf.") - - let resp = promptCustom(msg, params) - let analyticsFile = params.getAnalyticsFile() - case resp.normalize - of "y", "yes": - let clientID = analytics.genClientID() - writeFile(analyticsFile, clientID) - display("Info:", "Your client ID is " & clientID, priority=LowPriority) - of "n", "no": - # Write an empty file to signify that the user answered "No". - writeFile(analyticsFile, "") - return - else: - # Force the user to answer. - analyticsPrompt(params) - -proc report*(obj: Event | Timing | ref Exception, params: CliParams) -proc loadAnalytics*(params: CliParams): bool = - ## Returns ``true`` if ``analytics`` object has been loaded successfully. - if getEnv("CHOOSENIM_NO_ANALYTICS") == "1" or getEnv("DO_NOT_TRACK") == "1": - display("Info:", - "Not sending analytics because either CHOOSENIM_NO_ANALYTICS or DO_NOT_TRACK is set.", - priority=MediumPriority) - return false - - if params.isNil: - raise newException(ValueError, "Params is nil.") - - if not params.analytics.isNil: - return true - - let analyticsFile = params.getAnalyticsFile() - var prompted = false - if not fileExists(analyticsFile): - params.analyticsPrompt() - prompted = true - - let clientID = readFile(analyticsFile) - if clientID.len == 0: - display("Info:", - "No client ID found in '$1', not sending analytics." % - analyticsFile, - priority=LowPriority) - return false - - params.analytics = newPuppyAnalytics("UA-105812497-1", clientID, "choosenim", - chooseNimVersion, proxy = getProxy(), - timeout=5) - - # Report OS info only once. - if prompted: - when defined(windows): - let systemVersion = $getVersionInfo() - else: - let systemVersion = getSystemVersion() - report(initEvent(OSInfoEvent, systemVersion), params) - - return true - -proc reportAsyncError(fut: Future[void], params: CliParams) = - fut.callback = - proc (fut: Future[void]) {.gcsafe.} = - {.gcsafe.}: - if fut.failed: - display("Warning: ", "Could not report analytics due to error: " & - fut.error.msg, Warning, MediumPriority) - params.pendingReports.dec() - -proc hasPendingReports*(params: CliParams): bool = params.pendingReports > 0 - - -proc report*(obj: Event | Timing | ref Exception, params: CliParams) = - try: - if not loadAnalytics(params): - return - except Exception as exc: - display("Warning:", "Could not load analytics reporter due to error:" & - exc.msg, Warning, MediumPriority) - return - - displayDebug("Reporting to analytics...") - - try: - when obj is Event: - params.analytics.reportEvent($obj.category, obj.action, - obj.label, obj.value) - elif obj is Timing: - params.analytics.reportTiming($obj.category, obj.name, - obj.time, obj.label) - else: - params.analytics.reportException(obj.msg) - - except Exception as exc: - display("Warning:", "Could not report to analytics due to error:" & - exc.msg, Warning, MediumPriority) - diff --git a/src/choosenimpkg/utils.nim b/src/choosenimpkg/utils.nim index 9bacb8d0..b63996f7 100644 --- a/src/choosenimpkg/utils.nim +++ b/src/choosenimpkg/utils.nim @@ -171,12 +171,24 @@ proc getLatestCommit*(repo, branch: string): string = else: display("Warning", outp & "\ngit ls-remote failed", Warning, HighPriority) -proc getNightliesUrl*(parsedContents: JsonNode, arch: int): (string, string) = +func getArch*(): string = + ## Gets CPU arch. This is based on what system choosenim was compiled for. + ## See https://github.com/nim-lang/nightlies/releases for why we need to map this + case hostCPU + of "i386": "x32" + of "amd64": "x64" + of "arm": "arm7vl" + of "arm64": "arm64" + else: + raise (ref Defect)(msg: "Unsupported architecture") + +proc getNightliesUrl*(parsedContents: JsonNode): (string, string) = let os = when defined(windows): "windows" elif defined(linux): "linux" elif defined(macosx): "osx" elif defined(freebsd): "freebsd" + const arch = getArch() for jn in parsedContents.getElems(): if jn["name"].getStr().contains("devel"): let tagName = jn{"tag_name"}.getStr("") @@ -185,7 +197,7 @@ proc getNightliesUrl*(parsedContents: JsonNode, arch: int): (string, string) = let url = asset{"browser_download_url"}.getStr("") if os in aname: when not defined(macosx): - if "x" & $arch in aname: + if $arch in aname: result = (url, tagName) else: result = (url, tagName)