Supporting version splitting in Daml Assistant and Daml Compiler (#17682)

* initial implementation supporting version splitting in assistant

stubbed out implementations of resolveReleaseVersion/other resolution

* implement resolveReleaseVersionFromGithub

* continue work on fixing SDK/release version split

* First commit that successfully runs `daml-head install <split version>`

* fix tests

* Ignore snapshot/metadata for isHeadVersion

* remove log debugging

* Fix tests for getSdk

* refactor DA.Daml.Project.Types.defaultSdkPath

* enable incremental changes to version cache

* Allow resolveReleaseVersionFromGithub to fail via Either

* Split getSdkVersionFromSdkPath into get{Sdk,Release}VersionFromSdkPath

* Add resolveReleaseVersionFromDamlPath/Github to resolveReleaseVersion

* Add mock sdk config with version

* Remove getInstalledSdkVersions dependency on Cache

* add override for github version api endpoint, useful for mocking

* Add alternate-download to provide alternate tarball install resolution

* initial work on comprehensive autotester

* Copyright header

* fix build generation to have valid Main.daml

* improve error message for check_daml_install_nonzero

* Make killing miniserve processes more robust

* remove breakpoint

* Implement `daml build` tests

* Solve TODO in installExtracted to resolve sourceSdkVersion coherently

Supply useful error message with it.

* Return SdkVersion from sdkVersionFromReleaseVersion for typechecking

* Finish tests for tarball build, drop installed_already_behaviour

* Try to force-reload cache on tar failure, fix `Possible fix:` notes

* Add AllowInstallNonRelease as a flag

* Test allow_nonrelease, refactor, clean up setup_sandbox

* Move no_cache_override_github_endpoint API response into file

* Remove dead code, vestigial code

* Remove TODOs that no longer are relevant

* fix iAllowInstallNonRelease in InstallOptions for autoInstall

* Refactor alternateVersionLocation

* (Try to) lint language-support/ts/codegen/BUILD.bazel

* fix daml-assistant/test

* Enable allow_nonrelease post-build checks

* Remove writeFile debugging from DA.Daml.Assistant.Version

* Replace ../test-daml-yaml-install/test.sh with test-all-installs.sh

* lint

* more lint

run-full-compat: true

* Stop tracking API response in test-daml-yaml-install

* Move ReleaseResolution into Version

* remove extra deps, fixes daml-project-config-cabal-file-matches

* Move InstallLocation to minimize changes to DA.Daml.Project.Types

run-full-compat: true

* Create cachePath in daml-assistant tests that need it

* Bind to unused ports in test-all-installs.sh

run-full-compat: true

* Override via files instead of just URLs

run-full-compat: true

* Remove unused RELEASES_ENDPOINT

* Use dict keys instead of hardcoding in test-all-installs listing

* Refactor to remove check_daml_install_from_tarball_after_cache_reload

* Improve comment on update_cache

* Move shift before cases

* Add comment for unsafeParseReleaseVersion

* Rename unsafeParseReleaseVersion into unsafeParseOldReleaseVersion

* remove done todo

* Add some hungarian notation to resolveReleaseVersionFromDamlPath

* drop redundant let

* Define ordering over ReleaseVersion

run-full-compat: true

* use sdkVersion for codegen

* Use `urls` attribute in http_file, `url` is unsupported on Windows (!)

run-full-compat: true

* Remove unnecessary check for cache reload

run-full-compat: true

* Try use daml executable directly without daml-sdk-0.0.0

run-full-compat: true

* try force daml.exe to daml

run-full-compat: true

* Use daml.exe when windows is detected

* add windows tarballs for snapshots

* Fix most tests on windows, "line too long" breaks some tarball tests

run-full-compat: true

* Point to more recent snapshot post Moises's fixes

* Add os-specific tarball paths and alternate-download

run-full-compat: true

* Fix windows autoinstall with 0.0.0

run-full-compat: true

* Fix error message, remove daml_install_output catching

* Detect "The input line is too long" in other post_failed commands

* Fix missing releases endpoint, handle "cannot find the path specified"

run-full-compat: true
This commit is contained in:
dylant-da 2023-11-22 14:24:13 +00:00 committed by GitHub
parent 8e3ab3be0b
commit 234d003f0c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
23 changed files with 25307 additions and 374 deletions

View File

@ -159,3 +159,78 @@ first_post_7587_trigger_version = "1.7.0-snapshot.20201012.5405.0.af92198d"
# supported SDK is 1.18.0
if versions.is_at_least("1.18.0", old_sdk_version)
]
os_name = "linux" if not is_windows else "windows"
command_targets = {
"install_from_version": [
"2.8.0-snapshot.20231109.2",
"0.0.0",
"latest",
"2.7.1",
],
"build_from_version": [
"2.8.0-snapshot.20231109.2",
"2.7.1",
"0.0.0",
],
"install_and_build_from_tarball": [
"v2.8.0-snapshot.20231109.2/daml-sdk-2.8.0-snapshot.20231107.12319.0.v03a51e65-{}.tar.gz".format(os_name),
"v2.7.5/daml-sdk-2.7.5-{}.tar.gz".format(os_name),
"v2.7.1/daml-sdk-2.7.1-{}.tar.gz".format(os_name),
],
}
command_post_failure_behaviours = {
"install_from_version": [
"do_nothing",
],
"build_from_version": [
"do_nothing",
],
"install_and_build_from_tarball": [
"allow_nonrelease",
"update_cache",
"do_nothing",
],
}
[
sh_test(
name = "test-all-installs-{}-{}-{}-{}".format(
command[:10],
command_target.split("/")[0][:11],
version_cache_behaviour[:8],
post_failure_behaviour[:5],
),
size = "enormous",
srcs = ["test-all-installs.sh"],
args = [
os_name,
command,
command_target,
version_cache_behaviour,
post_failure_behaviour,
],
data = [
":new_cache",
":old_cache",
":releases-github-api.json",
"@daml-sdk-2.7.1-tarball//file",
"@daml-sdk-2.7.4-tarball//file",
"@daml-sdk-2.7.5-tarball//file",
"@daml-sdk-2.8.0-snapshot.20231107.12319.0.v03a51e65-tarball//file",
"@head_sdk//:daml" if not is_windows else "@head_sdk//:daml.exe",
"@head_sdk//:sdk-release-tarball-ce.tar.gz",
],
deps = ["@bazel_tools//tools/bash/runfiles"],
)
for command in command_targets.keys()
for command_target in command_targets[command]
for version_cache_behaviour in [
"init_new_cache",
"init_old_cache",
"no_cache_override_github_endpoint",
]
for post_failure_behaviour in command_post_failure_behaviours[command]
]

View File

@ -1,5 +1,7 @@
workspace(name = "compatibility")
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive", "http_file")
# We import the main workspace for nix stuff and some shared Bazel rules.
# This is mainly so we dont have to symlink a bunch of files.
# Note that you should never depend on targets from @daml.
@ -388,3 +390,65 @@ scala_repositories(
load("@io_bazel_rules_scala//scala:toolchains.bzl", "scala_register_toolchains")
register_toolchains("@daml//bazel_tools/scala:toolchain")
# Copies of SDKs at correct versions for daml testing
http_file(
name = "daml-sdk-2.7.5-tarball",
sha256 = "ea2730b1b50075686c82369a20da5a6b93c899e792d0db756218702427884148",
urls = ["https://github.com/digital-asset/daml/releases/download/v2.7.5/daml-sdk-2.7.5-linux.tar.gz"],
) if is_linux else None
http_file(
name = "daml-sdk-2.7.5-tarball",
sha256 = "b8e8bdff694a075431686048311d3a2ad9b62a2c88bf8ef927123c1b5b2addfa",
urls = ["https://github.com/digital-asset/daml/releases/download/v2.7.5/daml-sdk-2.7.5-windows.tar.gz"],
) if is_windows else None
http_file(
name = "daml-sdk-2.7.4-tarball",
sha256 = "c8625a752006821998b49b48d4c734b41dcedfda5ae72d6d5d6ce3eab443f625",
urls = ["https://github.com/digital-asset/daml/releases/download/v2.7.4/daml-sdk-2.7.4-linux.tar.gz"],
) if is_linux else None
http_file(
name = "daml-sdk-2.7.4-tarball",
sha256 = "8040d524d487cfe260b0f94bdcfee1556548875b33666200e9d599f22c31e51c",
urls = ["https://github.com/digital-asset/daml/releases/download/v2.7.4/daml-sdk-2.7.4-windows.tar.gz"],
) if is_windows else None
http_file(
name = "daml-sdk-2.7.1-tarball",
sha256 = "72b6151168b8229e040cf4ed033c9838c1f0d986e63f18186091280dc82f4ea9",
urls = ["https://github.com/digital-asset/daml/releases/download/v2.7.1/daml-sdk-2.7.1-linux.tar.gz"],
) if is_linux else None
http_file(
name = "daml-sdk-2.7.1-tarball",
sha256 = "200d358103daaf3cd58910966f4a5059bf4bbd3a98964bf65c3414fb3ec6cd92",
urls = ["https://github.com/digital-asset/daml/releases/download/v2.7.1/daml-sdk-2.7.1-windows.tar.gz"],
) if is_windows else None
#http_file(
# name = "daml-sdk-2.8.0-snapshot.20231026.12262.0.vb12eb2ad-tarball",
# sha256 = "80fffb3698d99d22a93387e0b3a4b85077159cca52470745d70ed4ffb5a6bdcb",
# urls = ["https://github.com/digital-asset/daml/releases/download/v2.8.0-snapshot.20231101.0/daml-sdk-2.8.0-snapshot.20231026.12262.0.vb12eb2ad-linux.tar.gz"],
#) if is_linux else None
#
#http_file(
# name = "daml-sdk-2.8.0-snapshot.20231026.12262.0.vb12eb2ad-tarball",
# sha256 = "98af3f68ebe65880610ff95f1b5fcf104a3bcad15779913d3b040f0ac09f42b1",
# urls = ["https://github.com/digital-asset/daml/releases/download/v2.8.0-snapshot.20231101.0/daml-sdk-2.8.0-snapshot.20231026.12262.0.vb12eb2ad-windows.tar.gz"],
#) if is_windows else None
http_file(
name = "daml-sdk-2.8.0-snapshot.20231107.12319.0.v03a51e65-tarball",
sha256 = "cf7b706076fa874b2913547bd6b064890155e656523ad94417300ead72ee19f4",
urls = ["https://github.com/digital-asset/daml/releases/download/v2.8.0-snapshot.20231109.2/daml-sdk-2.8.0-snapshot.20231107.12319.0.v03a51e65-linux.tar.gz"],
) if is_linux else None
http_file(
name = "daml-sdk-2.8.0-snapshot.20231107.12319.0.v03a51e65-tarball",
sha256 = "d2260542d3d63178dc879f96dfd72fcbe703366ce02b3520c28b29ac3817b70f",
urls = ["https://github.com/digital-asset/daml/releases/download/v2.8.0-snapshot.20231109.2/daml-sdk-2.8.0-snapshot.20231107.12319.0.v03a51e65-windows.tar.gz"],
) if is_windows else None

View File

@ -41,10 +41,12 @@ bazel fetch @nodejs_dev_env//...
bazel build `
`-`-experimental_execution_log_file ${ARTIFACT_DIRS}/build_execution_windows.log `
//release:sdk-release-tarball `
//ledger-test-tool/tool:ledger-api-test-tool_distribute.jar
//ledger-test-tool/tool:ledger-api-test-tool_distribute.jar `
//daml-assistant:daml
git clean -fxd -e 'daml-*.tgz' compatibility/head_sdk
cp -Force bazel-bin\release\sdk-release-tarball-ce.tar.gz compatibility/head_sdk
cp -Force bazel-bin\ledger-test-tool\tool\ledger-api-test-tool_distribute.jar compatibility/head_sdk
cp -Force bazel-bin\daml-assistant\daml.exe compatibility/head_sdk
cp -Force templates\create-daml-app-test-resources\messaging.patch compatibility/head_sdk

View File

@ -25,8 +25,10 @@ bazel build \
--tool_java_runtime_version=nixpkgs_java_11 \
--tool_java_language_version=11 \
//release:sdk-release-tarball \
//ledger-test-tool/tool:ledger-api-test-tool_distribute.jar
//ledger-test-tool/tool:ledger-api-test-tool_distribute.jar \
//daml-assistant:daml
cp -f bazel-bin/release/sdk-release-tarball-ce.tar.gz "$HEAD_TARGET_DIR"
cp -f bazel-bin/ledger-test-tool/tool/ledger-api-test-tool_distribute.jar "$HEAD_TARGET_DIR"
cp -f bazel-bin/daml-assistant/daml "$HEAD_TARGET_DIR"
cp -f templates/create-daml-app-test-resources/messaging.patch "$HEAD_TARGET_DIR"

View File

@ -1,4 +1,7 @@
load("@os_info//:os_info.bzl", "is_windows")
exports_files([
"daml" if not is_windows else "daml.exe",
"sdk-release-tarball-ce.tar.gz",
"ledger-api-test-tool_deploy.jar",
])

388
compatibility/new_cache Normal file
View File

@ -0,0 +1,388 @@
2.8.0-snapshot.20231109.2 2.8.0-snapshot.20231107.12319.0.v03a51e65
2.8.0-snapshot.20231018.0 2.8.0-snapshot.20231016.12209.0.v28eadc6e
2.8.0-snapshot.20231011.0 2.8.0-snapshot.20231009.12181.0.v623a064c
2.8.0-snapshot.20231005.2 2.8.0-snapshot.20230929.12167.0.v44c0c51b
2.8.0-snapshot.20231005.1 2.8.0-snapshot.20230929.12167.0.v44c0c51b
2.8.0-snapshot.20230929.12167.0.v44c0c51b
2.8.0-snapshot.20230928.12164.0.ve6bf0171
2.8.0-snapshot.20230927.12158.0.vb863e65a
2.8.0-snapshot.20230925.12146.0.v5ac74bc8
2.7.5
2.7.4
2.7.3
2.3.17
2.3.16
2.8.0-snapshot.20230913.12113.0.vf71b764f
2.8.0-snapshot.20230908.12101.0.v1bee52e4
2.8.0-snapshot.20230830.12083.0.v20330329
2.8.0-snapshot.20230828.12078.0.v99f466d4
2.7.2-rc1
2.7.1
2.7.1-rc2
2.8.0-snapshot.20230821.12054.0.v9f9ecb20
2.8.0-snapshot.20230811.12033.0.v2aad9b4e
2.7.0
2.7.0-snapshot.20230808.11990.0.vb6c93df1
2.8.0-snapshot.20230807.12017.0.v7ba1e675
2.7.0-snapshot.20230719.11983.0.vd999a21a
2.7.0-snapshot.20230717.11972.0.vc71b781c
2.7.0-snapshot.20230710.11943.0.v20c0149b
2.7.0-snapshot.20230703.11931.0.vc04c7ac9
2.7.0-snapshot.20230626.11909.0.v5979774e
2.7.0-snapshot.20230619.11890.0.vedd1a5f6
2.7.0-snapshot.20230612.11864.0.v3514a4a0
2.7.0-snapshot.20230604.11848.0.v9f55d679
2.7.0-snapshot.20230529.11827.0.v3fbe7d01
2.6.5
2.7.0-snapshot.20230518.11799.0.50b2c595
2.7.0-snapshot.20230515.11783.0.36293a4e
2.7.0-snapshot.20230427.11728.0.1f3c22cf
2.7.0-snapshot.20230424.11710.0.2f27f987
2.6.4
2.3.15
2.3.14
2.3.13
2.3.12
2.6.3
2.6.2
2.7.0-snapshot.20230417.11682.0.ac68bdf4
2.7.0-snapshot.20230403.11641.0.1a58e9aa
2.7.0-snapshot.20230331.11634.0.c20fc05d
2.6.1
2.3.11
2.7.0-snapshot.20230327.11615.0.9aa586fb
2.7.0-snapshot.20230317.11591.0.4df21fe6
2.7.0-snapshot.20230310.11563.0.861d9175
2.5.5
2.3.10
2.7.0-snapshot.20230302.11525.0.15e10bbc
2.6.0
2.6.0-snapshot.20230302.11477.0.f98e37e8
2.3.9
2.6.0-snapshot.20230222.11475.0.ec147a82
2.6.0-snapshot.20230222.11471.0.d1a33784
2.6.0-snapshot.20230216.11444.0.59bc473b
2.5.4
2.6.0-snapshot.20230210.11415.0.5c00481a
2.6.0-snapshot.20230206.11376.0.2713e2b4
2.5.3
2.6.0-snapshot.20230126.11324.0.a87412b6
2.5.2
2.4.3
2.6.0-snapshot.20230123.11292.0.b3f84bfc
2.6.0-snapshot.20230116.11260.0.94327f5d
2.5.1
2.6.0-snapshot.20221226.11190.0.71548477
2.6.0-snapshot.20221218.11169.0.9d007b31
2.3.8
2.6.0-snapshot.20221212.11134.0.1ac41995
2.5.0
2.5.0-snapshot.20221208.11077.0.53b7db71
2.6.0-snapshot.20221205.11091.0.c24c17d5
2.5.0-snapshot.20221201.11065.0.caac1d10
2.5.0-snapshot.20221120.10983.0.218a6a8a
2.5.0-snapshot.20221111.10938.0.bb67fb7f
2.4.2
2.5.0-snapshot.20221107.10906.0.346bb489
2.3.7
2.5.0-snapshot.20221028.10865.0.1b726fe8
2.5.0-snapshot.20221024.10827.0.c8adc54a
2.5.0-snapshot.20221017.10775.0.61e85b19
2.5.0-snapshot.20221010.10736.0.2f453a14
2.5.0-snapshot.20221003.10705.0.a55ccc38
2.3.6
2.5.0-snapshot.20220925.10653.0.0db37eca
2.5.0-snapshot.20220919.10619.0.86cff50d
2.4.0
2.4.0-snapshot.20220914.10592.0.cf7c2b5c
2.5.0-snapshot.20220912.10598.0.f801cd46
2.4.0-snapshot.20220909.10591.0.33f2ea59
2.4.0-snapshot.20220905.10544.0.a2ea3ce6
2.4.0-snapshot.20220830.10494.0.4622de48
2.4.0-snapshot.20220823.10466.0.1ab16059
2.4.0-snapshot.20220809.10365.0.7d59e3d4
2.4.0-snapshot.20220805.10346.0.454fc397
2.4.0-snapshot.20220801.10312.0.d2c7be9d
2.4.0-snapshot.20220722.10254.0.9744c4ed
2.3.4
2.3.3
2.3.2
2.3.1
2.4.0-snapshot.20220712.10212.0.0bf28176
2.4.0-snapshot.20220708.10196.0.7dfbc582
2.3.0
2.3.0-snapshot.20220707.10108.0.f4098846
2.2.1
2.4.0-snapshot.20220703.10163.0.89b068ec
1.18.3
2.4.0-snapshot.20220628.10133.0.6f31303a
2.3.0-snapshot.20220621.10121.0.2ea1c740
1.18.3-snapshot.20220620.8442.0.c7424302
2.3.0-snapshot.20220619.10104.0.253b0b18
2.3.0-snapshot.20220611.10066.0.458cfc43
2.3.0-snapshot.20220606.10031.0.ce98be86
2.3.0-snapshot.20220528.9973.0.012e3ac6
2.3.0-snapshot.20220519.9931.0.385504fd
2.0.1
2.3.0-snapshot.20220517.9906.0.de6da710
2.2.0
2.3.0-snapshot.20220509.9874.0.0798fe15
2.2.0-snapshot.20220504.9851.0.4c8e027d
2.2.0-snapshot.20220425.9780.0.f4d60375
2.2.0-snapshot.20220420.9744.0.e193f421
2.0.1-snapshot.20220419.9374.0.44df8f12
2.1.0-snapshot.20220411.9707.0.f6fed6ea
2.1.1
2.1.0
2.1.0-snapshot.20220404.9660.0.4b71431b
2.1.0-snapshot.20220331.9659.0.4bf0de89
2.0.1-snapshot.20220331.9373.0.4a445be6
2.1.0-snapshot.20220325.9626.0.4a483381
1.18.2
1.18.2-snapshot.20220324.8440.0.5cfb1a21
2.0.1-snapshot.20220322.9371.1.d9f46c43
2.1.0-snapshot.20220318.9568.0.d37a63f5
2.1.0-snapshot.20220311.9514.0.ab6e085f
1.18.2-snapshot.20220310.8437.1.5221a5d1
2.1.0-snapshot.20220308.9472.0.1f24348e
2.1.0-snapshot.20220228.9413.0.ef8a0e66
2.0.0
2.0.0-snapshot.20220225.9368.0.b291a57e
2.0.0-snapshot.20220222.9362.0.1af680cd
2.0.0-snapshot.20220215.9307.0.55fef9cf
2.0.0-snapshot.20220209.9212.0.b7fc9f57
2.0.0-snapshot.20220204.9165.0.225c58f4
2.0.0-snapshot.20220201.9108.0.aa2494f1
2.0.0-snapshot.20220127.9042.0.4038d0a7
2.0.0-snapshot.20220118.8919.0.d0813e61
1.18.1
1.18.1-snapshot.20220113.8434.1.1724373f
1.18.1-snapshot.20220113.8434.0.1724373f
2.0.0-snapshot.20220110.8812.0.3a08380b
1.18.1-snapshot.20220110.8433.0.e8e25a11
1.18.1-snapshot.20220106.8429.0.ea344666
2.0.0-snapshot.20220104.8767.0.d3101e01
2.0.0-snapshot.20211220.8735.0.606a8ef0
2.0.0-snapshot.20211207.8608.0.c4d82f72
1.18.0
1.18.0-snapshot.20211206.8423.0.2c945fcb
2.0.0-snapshot.20211201.8538.0.1d0ff3cc
1.18.0-snapshot.20211124.8419.0.39d9afcd
1.17.2-snapshot.20211124.7857.0.b33b94b8
2.0.0-snapshot.20211123.8463.0.bd2a6852
1.11.3
1.11.3-snapshot.20211123.6448.0.c679b4ab
1.18.0-snapshot.20211117.8399.0.a05a40ae
1.18.0-snapshot.20211111.8349.0.d938a44c
1.11.3-snapshot.20211111.6441.0.eed4ad32
1.18.0-snapshot.20211110.8337.0.c5a1f0bb
1.18.0-snapshot.20211109.8328.0.92181161
1.18.0-snapshot.20211102.8257.0.7391a3cd
1.18.0-snapshot.20211026.8179.0.e474b2d1
1.18.0-snapshot.20211019.8113.0.8ff347d8
1.18.0-snapshot.20211013.8071.0.514e8b50
1.17.1
1.17.1-snapshot.20211006.7853.0.e05be365
1.17.1-snapshot.20211006.7852.0.fbc4bc00
1.18.0-snapshot.20211006.8003.0.cfcdc13c
1.18.0-snapshot.20210928.7948.0.b4d00317
1.18.0-snapshot.20210922.7908.0.ced4a272
1.17.0
1.17.0-snapshot.20210922.7849.0.49a75801
1.17.0-snapshot.20210915.7841.0.b4328b3d
1.17.0-snapshot.20210910.7786.0.976ca400
1.17.0-snapshot.20210831.7702.0.f058c2f1
1.17.0-snapshot.20210824.7647.0.640fb683
1.17.0-snapshot.20210817.7604.0.0c187853
1.17.0-snapshot.20210811.7565.0.f1a55aa4
1.16.0
1.16.0-snapshot.20210805.7501.0.48050ad7
1.16.0-snapshot.20210802.7499.0.5157ad6d
1.16.0-snapshot.20210727.7476.0.b5e9d861
1.16.0-snapshot.20210720.7404.0.b7cf42d1
1.15.0
1.16.0-snapshot.20210713.7343.0.1f35db17
1.14.2
1.14.2-snapshot.20210708.7135.0.aa297840
1.14.1-snapshot.20210706.7133.0.8ec16e94
1.15.0-snapshot.20210705.7286.0.62aabcc4
1.15.0-snapshot.20210630.7261.0.84e1f3a7
1.15.0-snapshot.20210623.7217.0.5b73813d
1.15.0-snapshot.20210615.7169.0.adeba206
1.14.0
1.14.0-snapshot.20210615.7124.0.d1b54ff0
1.11.2
1.11.2-snapshot.20210610.6433.1.a08f6ea2
1.14.0-snapshot.20210608.7123.0.3cb8d5c2
1.14.0-snapshot.20210602.7086.0.f36f556b
1.14.0-snapshot.20210526.7024.0.aedb9a82
1.14.0-snapshot.20210518.6953.0.a6c7b86a
1.13.1
1.13.1-snapshot.20210512.6834.1.5f532380
1.14.0-snapshot.20210511.6892.0.ca9e89b3
1.13.0
1.13.0-snapshot.20210504.6833.0.9ae787d0
1.13.0-snapshot.20210503.6809.0.ca012c3b
1.13.0-snapshot.20210426.6770.0.ca66061b
1.13.0-snapshot.20210419.6730.0.8c3a8c04
1.13.0-snapshot.20210413.6706.0.2dc09ba2
1.12.0
1.12.0-snapshot.20210406.6646.0.631db446
1.12.0-snapshot.20210331.6640.0.4b807899
1.12.0-snapshot.20210323.6567.0.90c5ce70
1.12.0-snapshot.20210317.6528.0.493e2154
1.12.0-snapshot.20210312.6498.0.707c86aa
1.11.1
1.11.1-snapshot.20210312.6429.1.7cd6380e
1.12.0-snapshot.20210309.6463.0.f7abca91
1.11.0
1.11.0-snapshot.20210304.6422.0.d3d5042a
1.11.0-snapshot.20210303.6421.0.145ddaa8
1.10.2
1.8.0-snapshot.20210303.5843.0.d443707c
1.11.0-snapshot.20210225.6390.0.0617fbde
1.10.1
1.11.0-snapshot.20210217.6338.0.ba6ba901
1.11.0-snapshot.20210212.6300.0.ad161d7f
1.10.0
1.10.0-snapshot.20210209.6265.0.19bf4031
1.10.0-snapshot.20210208.6257.0.61feb5bf
1.10.0-snapshot.20210202.6218.0.c0573678
1.10.0-snapshot.20210201.6207.0.7cf1914d
1.10.0-snapshot.20210125.6143.0.550aa48f
1.10.0-snapshot.20210120.6106.0.58ef725a
1.9.0
1.9.0-snapshot.20210119.6062.0.5b3663a5
1.8.1
1.8.1-snapshot.20210115.5842.0.59f5d407
1.9.0-snapshot.20210113.6060.0.9ed787cb
1.9.0-snapshot.20210112.6040.0.7171cb38
1.9.0-snapshot.20210111.6034.0.7855b023
1.9.0-snapshot.20210106.5986.0.c6995a9c
1.8.0
1.9.0-snapshot.20201215.5907.0.a6ed34c5
1.6.1
1.6.1-snapshot.20201215.5318.0.547abc97
1.8.0-snapshot.20201214.5841.0.a8ae8e4a
1.8.0-snapshot.20201208.5840.0.38455e8c
1.8.0-snapshot.20201201.5776.0.4b91f2a6
1.8.0-snapshot.20201124.5709.0.dabd55d0
1.8.0-snapshot.20201117.5661.0.76fae40c
1.8.0-snapshot.20201110.5615.0.b35c9fcb
1.7.0
1.7.0-snapshot.20201103.5565.0.e75d42dd
1.7.0-snapshot.20201027.5530.0.bdbf8977
1.7.0-snapshot.20201023.5508.0.9dec6689
1.6.1-snapshot.20201021.5317.0.aafe46a5
1.7.0-snapshot.20201013.5418.0.bda13392
1.7.0-snapshot.20201012.5405.0.af92198d
1.6.0
1.6.0-snapshot.20201012.5316.0.d21cb496
1.6.0-snapshot.20201007.5314.0.b4a47d0b
1.7.0-snapshot.20201006.5358.0.0c1cadcf
1.6.0-snapshot.20200930.5312.0.b9a1905d
1.6.0-snapshot.20200922.5258.0.cd4a06db
1.6.0-snapshot.20200915.5208.0.09014dc6
1.6.0-snapshot.20200908.5166.0.1623baec
1.5.0
1.5.0-snapshot.20200907.5151.0.eb68e680
1.5.0-snapshot.20200902.5118.0.2b3cf1b3
1.5.0-snapshot.20200825.5071.0.d33e130f
1.5.0-snapshot.20200818.5027.0.1b33d374
1.5.0-snapshot.20200811.4959.0.bbc2fe56
1.5.0-snapshot.20200804.4902.0.de2fef6b
1.4.0
1.4.0-snapshot.20200729.4851.0.224ab362
1.4.0-snapshot.20200724.4812.0.818a52b0
1.4.0-snapshot.20200722.4800.0.21a16eef
1.4.0-snapshot.20200722.4796.0.28ab504b
1.4.0-snapshot.20200715.4733.0.d6e58626
1.3.0
1.3.0-snapshot.20200714.4687.0.8e10c7a7
1.3.0-snapshot.20200708.4686.0.95dfa18e
1.3.0-snapshot.20200706.4664.0.5db06051
1.3.0-snapshot.20200610.4413.0.11b5c362
1.3.0-snapshot.20200701.4616.0.bdbefd11
1.3.0-snapshot.20200623.4546.0.4f68cfc4
1.3.0-snapshot.20200617.4484.0.7e0a6848
1.3.0-snapshot.20200617.4474.0.53bddb54
1.3.0-snapshot.20200610.4412.0.0544323d
1.3.0-snapshot.20200603.4345.0.1386abc0
1.2.0
1.2.0-snapshot.20200602.4310.0.1c18058f
1.2.0-snapshot.20200528.4309.0.f619dea3
1.2.0-snapshot.20200527.4268.0.acc5a21c
1.2.0-snapshot.20200520.4228.0.595f1e27
1.2.0-snapshot.20200520.4224.0.2af134ca
1.2.0-snapshot.20200513.4172.0.021f4af3
1.1.1
1.1.0-snapshot.20200506.4107.0.7e448d81
1.1.0-snapshot.20200430.4057.0.681c862d
1.0.1
1.0.1-snapshot.20200424.3917.0.16093690
1.1.0-snapshot.20200422.3991.0.6391ee9f
1.0.1-snapshot.20200417.3908.1.722bac90
1.0.0
0.13.56-snapshot.20200411.3905.0.f050da78
0.13.56-snapshot.20200408.3877.0.1ddcd3c0
0.13.56-snapshot.20200408.3871.0.b3ccacc0
0.13.56-snapshot.20200407.3859.0.b488b353
0.13.56-snapshot.20200407.3843.0.10bac143
0.13.56-snapshot.20200404.3816.0.30f2c742
0.13.56-snapshot.20200331.3729.0.b43b8d86
0.13.56-snapshot.20200325.3626.0.a3ddde3a
0.13.56-snapshot.20200318.3529.0.6ea118d6
0.13.55
0.13.55-snapshot.20200309.3401.0.6f8c3ad8
0.13.55-snapshot.20200304.3329.6a1c75cf
0.13.55-snapshot.20200226.3267.c9b9293d
0.13.54
0.13.53
0.13.52
0.13.51
0.13.50
0.13.46
0.13.43
0.13.42
0.13.41
0.13.40
0.13.39
0.13.38
0.13.37
0.13.36
0.13.34
0.13.33
0.13.32
0.13.31
0.13.30
0.13.29
0.13.27
0.13.25
0.13.24
0.13.23
0.13.22
0.13.21
0.13.20
0.13.19
0.13.18
0.13.16
0.13.15
0.13.14
0.13.13
0.13.12
0.13.10
0.13.5
0.13.0
0.12.25
0.12.24
0.12.22
0.12.21
0.12.20
0.12.19
0.12.18
0.12.17
0.12.16
0.12.15
0.12.12
0.12.11
0.12.3

121
compatibility/old_cache Normal file
View File

@ -0,0 +1,121 @@
2.7.4
2.7.3
2.3.17
2.3.16
2.7.1
2.7.0
2.6.5
2.6.4
2.3.15
2.3.14
2.3.13
2.3.12
2.6.3
2.6.2
2.6.1
2.3.11
2.5.5
2.3.10
2.6.0
2.5.3
2.5.2
2.4.3
2.5.1
2.3.8
2.5.0
2.4.2
2.3.7
2.3.6
2.4.0
2.3.4
2.3.3
2.3.2
2.3.1
2.3.0
1.18.3
2.0.1
2.2.0
2.1.1
2.1.0
1.18.2
2.0.0
1.18.1
1.18.0
1.11.3
1.17.1
1.17.0
1.16.0
1.15.0
1.14.2
1.14.0
1.11.2
1.13.1
1.13.0
1.12.0
1.11.1
1.11.0
1.10.0
1.9.0
1.8.1
1.8.0
1.6.1
1.7.0
1.6.0
1.5.0
1.4.0
1.3.0
1.2.0
1.1.1
1.0.1
1.0.0
0.13.55
0.13.54
0.13.53
0.13.52
0.13.51
0.13.50
0.13.46
0.13.43
0.13.42
0.13.41
0.13.40
0.13.39
0.13.38
0.13.37
0.13.36
0.13.34
0.13.33
0.13.32
0.13.31
0.13.30
0.13.29
0.13.27
0.13.25
0.13.24
0.13.23
0.13.22
0.13.21
0.13.20
0.13.19
0.13.18
0.13.16
0.13.15
0.13.14
0.13.13
0.13.12
0.13.10
0.13.5
0.13.0
0.12.25
0.12.24
0.12.22
0.12.21
0.12.20
0.12.19
0.12.18
0.12.17
0.12.16
0.12.15
0.12.12
0.12.11
0.12.3

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,322 @@
# Copyright (c) 2023 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
# SPDX-License-Identifier: Apache-2.0
# Copy-pasted from the Bazel Bash runfiles library v2.
set -uo pipefail; f=bazel_tools/tools/bash/runfiles/runfiles.bash
source "${RUNFILES_DIR:-/dev/null}/$f" 2>/dev/null || \
source "$(grep -sm1 "^$f " "${RUNFILES_MANIFEST_FILE:-/dev/null}" | cut -f2- -d' ')" 2>/dev/null || \
source "$0.runfiles/$f" 2>/dev/null || \
source "$(grep -sm1 "^$f " "$0.runfiles_manifest" | cut -f2- -d' ')" 2>/dev/null || \
source "$(grep -sm1 "^$f " "$0.exe.runfiles_manifest" | cut -f2- -d' ')" 2>/dev/null || \
{ echo>&2 "ERROR: cannot find $f"; exit 1; }; f=; set -e
# --- end runfiles.bash initialization v2 ---
error_echo () {
echo "$@"
exit 1
}
echo_eval () {
echo "$*"
eval "$*"
return $?
}
check_daml_version_indicates_correct () {
target_version=$1
daml_version_output=$($daml_exe version | grep -ve "^SDK versions:$" -e 'not installed')
output_line_count=$(echo "$daml_version_output" | wc -l)
if echo "$daml_version_output" | grep -qv -e "0.0.0" -e "$target_version"; then
error_echo -e "ERROR! \`daml version\` output a version that isn't 0.0.0 or the input version $target_version.\n$daml_version_output"
fi
if ! echo "$daml_version_output" | grep -q "$target_version"; then
error_echo -e "ERROR! \`daml version\` did not output the version.\n$daml_version_output"
fi
}
check_daml_init_creates_daml_yaml_with () {
$daml_exe init
if ! grep -q "sdk-version: $1" daml.yaml; then
error_echo "ERROR! \`daml init\` did not create a daml.yaml with 'sdk-version: $1'"
fi
}
check_dar_has_correct_metadata_version () {
unzip .daml/dist/test-daml-yaml-install-1.0.0.dar META-INF/MANIFEST.MF
if ! grep -q "Sdk-Version: $1" META-INF/MANIFEST.MF; then
error_echo "ERROR! \`daml build\` produced a dar whose META-INF/MANIFEST.MF contains the wrong SDK version"
error_echo "ERROR! This likely means it was compiled with the wrong daml version"
grep "Sdk-Version:" META-INF/MANIFEST.MF
fi
}
daml_install_from_tarball_should_succeed () {
tarball_path=$1
version_cache_behaviour=$2
if [[ "$version_cache_behaviour" == "no_cache_override_github_endpoint" ]]; then
return 1
elif [[ "$version_cache_behaviour" == "init_new_cache" ]]; then
return 0
elif [[ $tarball_path == "v2.7.1/daml-sdk-2.7.1-$os.tar.gz" ]]; then
return 0
else
return 1
fi
}
check_recommend_cache_reload () {
output_file=$1
if ! grep -q 'Possible fix: `daml version --force-reload yes`' "$output_file"; then
error_echo -e "ERROR: Output of \`daml install\` does not mention 'Possible fix: \`daml version --force-reload yes\`' despite failure\n$(cat "$output_file")"
fi
}
# If failure occurred under old cache, try updating the cache then retrying
# install
update_cache () {
if [[ $version_cache_behaviour == init_old_cache ]]; then
no_cache_override_github_endpoint $1
echo_eval $daml_exe version --force-reload yes
if $daml_exe install --install-assistant yes $absolute_github_mirror_directory/$tarball_path >daml_install_output 2>&1 || grep -q "The input line is too long" daml_install_output; then
cat daml_install_output
echo_eval init_daml_package $tarball_release_version
if echo_eval $daml_exe build; then
echo_eval check_daml_version_indicates_correct $tarball_release_version
echo_eval check_dar_has_correct_metadata_version $tarball_release_version
else
error_echo "ERROR! \`daml build\` on version installed from path $tarball_path failed"
fi
else
cat daml_install_output
error_echo "ERROR: Tried to install version from tarball '$tarball_path' with cache forcibly reloaded, but \`daml install\` failed."
fi
fi
}
allow_nonrelease () {
if echo_eval $daml_exe install --install-assistant yes --allow-install-non-release yes $absolute_github_mirror_directory/$tarball_path >daml_install_output 2>&1 || grep -q "The input line is too long" daml_install_output; then
cat daml_install_output
echo_eval init_daml_package $tarball_sdk_version
if echo_eval $daml_exe build; then
echo_eval check_daml_version_indicates_correct $tarball_sdk_version
echo_eval check_dar_has_correct_metadata_version $tarball_sdk_version
else
error_echo "ERROR! \`daml build\` failed for version installed from path $tarball_path"
fi
else
cat daml_install_output
error_echo "ERROR: Tried to install version from tarball '$tarball_path' with --allow-install-non-release, but \`daml install\` failed."
fi
}
init_daml_package () {
echo """
sdk-version: $1
name: test-daml-yaml-install
version: 1.0.0
source: Main.daml
scenario: Main:main
parties:
- Alice
- Bob
dependencies:
- daml-prim
- daml-stdlib
""" > daml.yaml
echo """
module Main where
""" > Main.daml
}
do_post_failed_tarball_install_behaviour () {
behaviour=$1
shift
case "$behaviour" in
allow_nonrelease)
allow_nonrelease "$@"
;;
update_cache)
update_cache "$@"
;;
do_nothing)
;;
*)
error_echo "ERROR: Unrecognized caching behaviour '$1'"
;;
esac
}
do_version_cache_behaviour () {
behaviour=$1
shift
case "$behaviour" in
init_new_cache)
init_new_cache "$@"
;;
init_old_cache)
init_old_cache "$@"
;;
no_cache_override_github_endpoint)
no_cache_override_github_endpoint "$@"
;;
*)
error_echo "ERROR: Unrecognized caching behaviour '$1'"
;;
esac
}
init_new_cache () {
cp $(rlocation compatibility/new_cache) $DAML_CACHE/versions.txt
}
init_old_cache () {
cp $(rlocation compatibility/old_cache) $DAML_CACHE/versions.txt
}
no_cache_override_github_endpoint () {
rm $DAML_CACHE/versions.txt || true # don't fail if file doesn't exist
export releases_endpoint="$(mktemp -d -p "$PWD" "releases_endpoint.XXXXXXXX")"
mkdir -p "$releases_endpoint"
cp "$1" "$releases_endpoint/releases"
absolute_releases_endpoint=$(realpath "$releases_endpoint/releases")
if [[ $os == windows ]]; then
absolute_releases_endpoint="$(cygpath -d "$absolute_releases_endpoint")"
fi
echo "NO CACHE OVERRIDE $absolute_releases_endpoint"
echo "releases-endpoint: $absolute_releases_endpoint" >> $DAML_HOME/daml-config.yaml
}
# serve a mirror of github's API to avoid usage limits
absolute_github_api_file=$(rlocation compatibility/releases-github-api.json)
if [[ ! -e "$absolute_github_api_file" ]]; then
error_echo "ERROR: You must supply a file to be used to resolve API requests in no_cache_override_github_endpoint"
exit 1
fi
export os=$1; shift
# Serve a mirror directory of github for more speed
export github_mirror_directory="$(mktemp -d -p "$PWD" "github-mirror-directory.XXXXXXXX")"
echo "$github_mirror_directory"
mkdir -p $github_mirror_directory/{v2.7.1,v2.7.4,v2.7.5,v2.8.0-snapshot.20231109.2}
cp --no-dereference $(rlocation daml-sdk-2.7.5-tarball/file/downloaded) "$github_mirror_directory/v2.7.5/daml-sdk-2.7.5-$os.tar.gz"
cp --no-dereference $(rlocation daml-sdk-2.7.4-tarball/file/downloaded) "$github_mirror_directory/v2.7.4/daml-sdk-2.7.4-$os.tar.gz"
cp --no-dereference $(rlocation daml-sdk-2.7.1-tarball/file/downloaded) "$github_mirror_directory/v2.7.1/daml-sdk-2.7.1-$os.tar.gz"
cp --no-dereference $(rlocation daml-sdk-2.8.0-snapshot.20231107.12319.0.v03a51e65-tarball/file/downloaded) "$github_mirror_directory/v2.8.0-snapshot.20231109.2/daml-sdk-2.8.0-snapshot.20231107.12319.0.v03a51e65-$os.tar.gz"
absolute_github_mirror_directory=$(realpath "$github_mirror_directory")
if [[ $os == windows ]]; then
alternate_download_line="alternate-download: $(cygpath -d "$github_mirror_directory")"
else
alternate_download_line="alternate-download: $absolute_github_mirror_directory"
fi
# Create sandbox with a daml root and daml cache, use temp dirs because windows sandboxing is poor
export DAML_CACHE="$(mktemp -d -p "$PWD" "cache.XXXXXXXX")"
export DAML_HOME="$(mktemp -d -p "$PWD" "daml_home.XXXXXXXX")"
if [[ "$os" == windows ]]; then
export daml_exe=daml.exe
else
export daml_exe=daml
fi
"$(rlocation "head_sdk/$daml_exe")" install --install-assistant yes "$(rlocation head_sdk/sdk-release-tarball-ce.tar.gz)"
if [[ "$daml_exe" == "daml.exe" ]]; then
# on windows, fully qualify daml command
export daml_exe="$DAML_HOME/bin/daml.cmd"
else
export daml_exe="daml"
export PATH="$DAML_HOME/bin:$PATH"
fi
echo "$alternate_download_line" >> $DAML_HOME/daml-config.yaml
[[ "$#" -gt 0 ]] || error_echo "No command to run supplied via args"
command_to_run=$1
shift
case "$command_to_run" in
install_from_version)
[[ "$#" -gt 0 ]] || error_echo "No install_version supplied via args"
install_version=$1
shift
[[ "$#" -gt 0 ]] || error_echo "No version_cache_behaviour supplied via args"
version_cache_behaviour=$1
shift
do_version_cache_behaviour $version_cache_behaviour $absolute_github_api_file
if echo_eval $daml_exe install --install-assistant yes $install_version >daml_install_output 2>&1 || grep -q "The system cannot find the path specified" daml_install_output; then
if [[ "$install_version" != "0.0.0" && "$install_version" != "latest" ]]; then
echo_eval check_daml_version_indicates_correct $install_version
echo_eval check_daml_init_creates_daml_yaml_with $install_version
fi
else
if [[ "$1" != "0.0.0" ]]; then
error_echo "ERROR! Exit code for \`daml install $install_version\` is nonzero."
fi
fi
;;
build_from_version)
[[ "$#" -gt 0 ]] || error_echo "No build_version supplied via args"
build_version=$1
shift
[[ "$#" -gt 0 ]] || error_echo "No version_cache_behaviour supplied via args"
version_cache_behaviour=$1
shift
do_version_cache_behaviour $version_cache_behaviour $absolute_github_api_file
echo_eval init_daml_package $build_version
if echo_eval $daml_exe build; then
if [[ "$os" == windows && "$build_version" != "0.0.0" ]]; then
error_echo "\`daml build\` on $build_version succeeded. This shouldn't succeed because Windows does not support autoinstalling from alternate-download."
else
echo_eval check_daml_version_indicates_correct $build_version
echo_eval check_dar_has_correct_metadata_version $build_version
fi
else
if [[ "$os" == windows && "$build_version" != "0.0.0" ]]; then
echo "Exit code for \`daml build\` on version $build_version is nonzero. This is OK because Windows does not support autoinstall from alternate-download."
else
error_echo "ERROR! Exit code for \`daml build\` on version $build_version is nonzero"
fi
fi
;;
install_and_build_from_tarball)
[[ "$#" -gt 0 ]] || error_echo "No tarball_path supplied via args"
tarball_path=$1
shift
[[ "$#" -gt 0 ]] || error_echo "No version_cache_behaviour supplied via args"
version_cache_behaviour=$1
shift
[[ "$#" -gt 0 ]] || error_echo "No post_failed_tarball_install_behaviour supplied via args"
post_failed_tarball_install_behaviour=$1
shift
tarball_release_version=${tarball_path%%/*}
tarball_release_version=${tarball_release_version#v}
tarball_sdk_version=${tarball_path%-$os.tar.gz}
tarball_sdk_version=${tarball_sdk_version#*/daml-sdk-}
do_version_cache_behaviour $version_cache_behaviour $absolute_github_api_file
if echo_eval $daml_exe install --install-assistant yes "$absolute_github_mirror_directory/$tarball_path" >daml_install_output 2>&1 || grep -q "The input line is too long" daml_install_output; then
cat daml_install_output
if ! echo_eval daml_install_from_tarball_should_succeed $tarball_path $version_cache_behaviour; then
error_echo "ERROR: Tried to install version from tarball '$tarball_path' with cache behaviour $version_cache_behaviour, but \`daml install\` succeeded where it should have failed."
fi
echo_eval init_daml_package $tarball_release_version
if echo_eval $daml_exe build; then
echo_eval check_daml_version_indicates_correct $tarball_release_version
echo_eval check_dar_has_correct_metadata_version $tarball_release_version
else
error_echo "ERROR! Exit code for \`daml build\` on version installed from path $tarball_path is nonzero."
fi
else
cat daml_install_output
if echo_eval daml_install_from_tarball_should_succeed $tarball_path $version_cache_behaviour; then
error_echo "ERROR: Tried to install version from tarball '$tarball_path' with cache behaviour $version_cache_behaviour, but \`daml install\` failed."
fi
echo_eval check_recommend_cache_reload daml_install_output
echo_eval do_post_failed_tarball_install_behaviour $post_failed_tarball_install_behaviour $absolute_github_api_file
fi
;;
*)
error_echo "ERROR: Unrecognized command $1"
exit 1
;;
esac

View File

@ -10,7 +10,7 @@ module DA.Daml.Project.Config
, readProjectConfig
, readDamlConfig
, readMultiPackageConfig
, sdkVersionFromProjectConfig
, releaseVersionFromProjectConfig
, sdkVersionFromSdkConfig
, listSdkCommands
, queryDamlConfig
@ -64,8 +64,8 @@ readConfig name path = do
fromRightM (throwIO . ConfigFileInvalid name) configE
-- | Determine pinned sdk version from project config, if it exists.
sdkVersionFromProjectConfig :: ProjectConfig -> Either ConfigError (Maybe SdkVersion)
sdkVersionFromProjectConfig = queryProjectConfig ["sdk-version"]
releaseVersionFromProjectConfig :: ProjectConfig -> Either ConfigError (Maybe UnresolvedReleaseVersion)
releaseVersionFromProjectConfig = queryProjectConfig ["sdk-version"]
-- | Determine sdk version from sdk config, if it exists.
sdkVersionFromSdkConfig :: SdkConfig -> Either ConfigError SdkVersion

View File

@ -10,11 +10,13 @@ import qualified Data.Yaml as Y
import qualified Data.Text as T
import qualified Data.SemVer as V
import qualified Control.Lens as L
import Data.Text (Text)
import Data.Text (Text, pack, unpack)
import Data.Maybe
import System.FilePath
import Control.Monad
import Control.Exception.Safe
import Data.Either.Extra (eitherToMaybe)
import Data.Function (on)
data ConfigError
= ConfigFileInvalid Text Y.ParseException
@ -48,14 +50,55 @@ newtype MultiPackageConfig = MultiPackageConfig
{ unwrapMultiPackageConfig :: Y.Value
} deriving (Eq, Show, Y.FromJSON)
newtype UnresolvedReleaseVersion = UnresolvedReleaseVersion
{ unwrapUnresolvedReleaseVersion :: V.Version
} deriving (Eq, Ord, Show)
data ReleaseVersion
= SplitReleaseVersion
{ releaseReleaseVersion :: V.Version
, releaseSdkVersion :: V.Version
}
| OldReleaseVersion
{ bothVersion :: V.Version
}
deriving (Eq, Show)
instance Ord ReleaseVersion where
compare = compare `on` releaseVersionFromReleaseVersion
sdkVersionFromReleaseVersion :: ReleaseVersion -> SdkVersion
sdkVersionFromReleaseVersion (SplitReleaseVersion _ sdkVersion) = SdkVersion sdkVersion
sdkVersionFromReleaseVersion (OldReleaseVersion bothVersion) = SdkVersion bothVersion
releaseVersionFromReleaseVersion :: ReleaseVersion -> V.Version
releaseVersionFromReleaseVersion (SplitReleaseVersion releaseVersion _) = releaseVersion
releaseVersionFromReleaseVersion (OldReleaseVersion bothVersion) = bothVersion
mkReleaseVersion :: UnresolvedReleaseVersion -> SdkVersion -> ReleaseVersion
mkReleaseVersion release sdk =
let unwrappedRelease = unwrapUnresolvedReleaseVersion release
unwrappedSdk = unwrapSdkVersion sdk
in
if unwrappedSdk == unwrappedRelease
then OldReleaseVersion unwrappedSdk
else SplitReleaseVersion unwrappedRelease unwrappedSdk
newtype SdkVersion = SdkVersion
{ unwrapSdkVersion :: V.Version
} deriving (Eq, Ord, Show)
newtype DamlAssistantSdkVersion = DamlAssistantSdkVersion
{ unwrapDamlAssistantSdkVersion :: SdkVersion
{ unwrapDamlAssistantSdkVersion :: ReleaseVersion
} deriving (Eq, Ord, Show)
instance Y.FromJSON UnresolvedReleaseVersion where
parseJSON y = do
verE <- V.fromText <$> Y.parseJSON y
case verE of
Left e -> fail ("Invalid release version: " <> e)
Right v -> pure (UnresolvedReleaseVersion v)
instance Y.FromJSON SdkVersion where
parseJSON y = do
verE <- V.fromText <$> Y.parseJSON y
@ -63,14 +106,37 @@ instance Y.FromJSON SdkVersion where
Left e -> fail ("Invalid SDK version: " <> e)
Right v -> pure (SdkVersion v)
versionToString :: SdkVersion -> String
versionToString = V.toString . unwrapSdkVersion
versionToString :: ReleaseVersion -> String
versionToString (OldReleaseVersion bothVersion) = V.toString bothVersion
versionToString (SplitReleaseVersion releaseVersion _) = V.toString releaseVersion
versionToText :: SdkVersion -> Text
versionToText = V.toText . unwrapSdkVersion
versionToText :: ReleaseVersion -> Text
versionToText (OldReleaseVersion bothVersion) = V.toText bothVersion
versionToText (SplitReleaseVersion releaseVersion _) = V.toText releaseVersion
isHeadVersion :: SdkVersion -> Bool
isHeadVersion v = "0.0.0" == versionToString v
rawVersionToTextWithV :: V.Version -> Text
rawVersionToTextWithV v = "v" <> V.toText v
sdkVersionToText :: SdkVersion -> Text
sdkVersionToText = V.toText . unwrapSdkVersion
class IsVersion a where
isHeadVersion :: a -> Bool
instance IsVersion ReleaseVersion where
isHeadVersion v = isHeadVersion (releaseVersionFromReleaseVersion v)
instance IsVersion UnresolvedReleaseVersion where
isHeadVersion v = isHeadVersion (unwrapUnresolvedReleaseVersion v)
instance IsVersion SdkVersion where
isHeadVersion v = isHeadVersion (unwrapSdkVersion v)
instance IsVersion V.Version where
isHeadVersion v = V.initial == L.set V.release [] (L.set V.metadata [] v)
headReleaseVersion :: ReleaseVersion
headReleaseVersion = OldReleaseVersion V.initial
data InvalidVersion = InvalidVersion
{ ivSource :: !Text -- ^ invalid version
@ -81,12 +147,43 @@ instance Exception InvalidVersion where
displayException (InvalidVersion bad msg) =
"Invalid SDK version " <> show bad <> ": " <> msg
parseVersion :: Text -> Either InvalidVersion SdkVersion
parseVersion src =
parseVersion :: Text -> Either InvalidVersion UnresolvedReleaseVersion
parseVersion = parseUnresolvedVersion
parseUnresolvedVersion :: Text -> Either InvalidVersion UnresolvedReleaseVersion
parseUnresolvedVersion src =
case V.fromText src of
Left msg -> Left (InvalidVersion src msg)
Right v -> Right (UnresolvedReleaseVersion v)
parseSdkVersion :: Text -> Either InvalidVersion SdkVersion
parseSdkVersion src =
case V.fromText src of
Left msg -> Left (InvalidVersion src msg)
Right v -> Right (SdkVersion v)
-- This is unsafe because it converts a version straight into an
-- OldReleaseVersion without checking that release and sdk version are actually
-- the same for this release.
unsafeParseOldReleaseVersion :: Text -> Either InvalidVersion ReleaseVersion
unsafeParseOldReleaseVersion src = do
case V.fromText src of
Left msg -> Left (InvalidVersion src msg)
Right v -> Right (OldReleaseVersion v)
releaseVersionToCacheString :: ReleaseVersion -> String
releaseVersionToCacheString (SplitReleaseVersion release sdk) = V.toString release <> " " <> V.toString sdk
releaseVersionToCacheString (OldReleaseVersion both) = V.toString both
releaseVersionFromCacheString :: String -> Maybe ReleaseVersion
releaseVersionFromCacheString src =
let parseVersionM = eitherToMaybe . V.fromText . pack
in
case words src of
[both] -> OldReleaseVersion <$> parseVersionM both
[release, sdk] -> SplitReleaseVersion <$> parseVersionM release <*> parseVersionM sdk
_ -> Nothing
-- | File path of daml installation root (by default ~/.daml on unix, %APPDATA%/daml on windows).
newtype DamlPath = DamlPath
{ unwrapDamlPath :: FilePath
@ -113,9 +210,14 @@ newtype SdkPath = SdkPath
} deriving (Eq, Show)
-- | Default way of constructing sdk paths.
defaultSdkPath :: DamlPath -> SdkVersion -> SdkPath
defaultSdkPath (DamlPath root) (SdkVersion v) =
SdkPath (root </> "sdk" </> V.toString (L.set V.metadata [] v))
defaultSdkPath :: DamlPath -> ReleaseVersion -> SdkPath
defaultSdkPath damlPath releaseVersion =
mkSdkPath
damlPath
(V.toString (L.set V.metadata [] (releaseVersionFromReleaseVersion releaseVersion)))
mkSdkPath :: DamlPath -> String -> SdkPath
mkSdkPath (DamlPath root) str = SdkPath (root </> "sdk" </> str)
-- | File path of sdk command binary, relative to sdk root.
newtype SdkCommandPath = SdkCommandPath
@ -173,3 +275,35 @@ instance Y.FromJSON (SdkPath -> EnrichedCompletion -> SdkCommandInfo) where
desc
(if completion then Forward enriched else NoForward)
sdkPath
data AssistantError = AssistantError
{ errContext :: Maybe Text -- ^ Context in which error occurs.
, errMessage :: Maybe Text -- ^ User-friendly error message.
, errInternal :: Maybe Text -- ^ Internal error message, i.e. what actually happened.
} deriving (Eq, Show)
instance Exception AssistantError where
displayException AssistantError {..} = unpack . T.unlines . catMaybes $
[ Just ("daml: " <> fromMaybe "An unknown error has occured" errMessage)
, fmap (" context: " <>) errContext
, fmap (" details: " <>) errInternal
]
-- | Standard error message.
assistantError :: Text -> AssistantError
assistantError msg = AssistantError
{ errContext = Nothing
, errMessage = Just msg
, errInternal = Nothing
}
-- | Standard error message with additional internal cause.
assistantErrorBecause :: Text -> Text -> AssistantError
assistantErrorBecause msg e = (assistantError msg) { errInternal = Just e }
-- | Standard error message with additional details.
assistantErrorDetails :: String -> [(String, String)] -> AssistantError
assistantErrorDetails msg details =
assistantErrorBecause (pack msg) . pack . concat $
["\n " <> k <> ": " <> v | (k,v) <- details]

View File

@ -153,12 +153,13 @@ autoInstall env@Env{..} = do
, iSetPath = SetPath Auto
, iBashCompletions = BashCompletions Auto
, iZshCompletions = ZshCompletions Auto
, iAllowInstallNonRelease = AllowInstallNonRelease False
}
installEnv = InstallEnv
{ options = options
, damlPath = envDamlPath
, useCache = envUseCache env
, targetVersionM = Just sdkVersion
, targetVersionM = sdkVersion
, missingAssistant = False
, installingFromOutside = False
, projectPathM = Nothing
@ -171,7 +172,7 @@ autoInstall env@Env{..} = do
-- output / have the install messages be gobbled
-- up by a pipe.
}
versionInstall installEnv sdkVersion
versionInstall installEnv
pure env { envSdkPath = Just (defaultSdkPath envDamlPath sdkVersion) }
else
@ -201,10 +202,13 @@ runCommand env@Env{..} = \case
}
installedVersionsE <- tryAssistant $ getInstalledSdkVersions envDamlPath
snapshotVersionsEUnfiltered <- tryAssistant $ fst <$> getAvailableSdkSnapshotVersions useCache
case snapshotVersionsEUnfiltered of
Left e -> putStrLn $ "WARNING Couldn't update cache:\n" <> displayException e
_ -> pure ()
let snapshotVersionsE = if vSnapshots then snapshotVersionsEUnfiltered else pure []
availableVersionsE = extractReleasesFromSnapshots <$> snapshotVersionsEUnfiltered
defaultVersionM <- tryAssistantM $ getDefaultSdkVersion envDamlPath
projectVersionM <- mapM getSdkVersionFromProjectPath envProjectPath
projectVersionM <- mapM (getSdkVersionFromProjectPath useCache) envProjectPath
envSelectedVersionM <- lookupEnv sdkVersionEnvVar
let asstVersion = unwrapDamlAssistantSdkVersion <$> envDamlAssistantSdkVersion
@ -271,7 +275,8 @@ runCommand env@Env{..} = \case
Builtin (Install options) -> wrapErr "Installing the SDK." $ do
install options envDamlPath (envUseCache env) envProjectPath envDamlAssistantSdkVersion
Builtin (Uninstall version) -> do
Builtin (Uninstall unresolvedVersion) -> do
version <- resolveReleaseVersion (envUseCache env) unresolvedVersion
uninstallVersion env version
Builtin (Exec cmd args) -> do

View File

@ -60,9 +60,9 @@ data UseCache
cacheAvailableSdkVersions
:: UseCache
-> IO [SdkVersion]
-> IO ([SdkVersion], CacheAge)
cacheAvailableSdkVersions DontUseCache getVersions = (, Fresh) <$> getVersions
-> (Maybe [ReleaseVersion] -> IO [ReleaseVersion])
-> IO ([ReleaseVersion], CacheAge)
cacheAvailableSdkVersions DontUseCache getVersions = (, Fresh) <$> getVersions Nothing
cacheAvailableSdkVersions UseCache { overrideTimeout, cachePath, damlPath } getVersions = do
damlConfigE <- tryConfig $ readDamlConfig damlPath
let configUpdateCheckM = join $ eitherToMaybe (queryDamlConfig ["update-check"] =<< damlConfigE)
@ -82,13 +82,13 @@ cacheAvailableSdkVersions UseCache { overrideTimeout, cachePath, damlPath } getV
neverRefresh
pure (fromMaybe ([], Stale) mVal)
serializeVersions :: Serialize [SdkVersion]
serializeVersions :: Serialize [ReleaseVersion]
serializeVersions =
unlines . map versionToString
unlines . map releaseVersionToCacheString
deserializeVersions :: Deserialize [SdkVersion]
deserializeVersions :: Deserialize [ReleaseVersion]
deserializeVersions =
Just . mapMaybe (eitherToMaybe . parseVersion . pack) . lines
Just . mapMaybe releaseVersionFromCacheString . lines
cacheFilePath :: CachePath -> CacheKey -> FilePath
cacheFilePath cachePath (CacheKey key) = unwrapCachePath cachePath </> key
@ -99,7 +99,7 @@ cacheWith
-> CacheTimeout
-> Serialize t
-> Deserialize t
-> IO t
-> (Maybe t -> IO t)
-> Bool
-> IO (Maybe (t, CacheAge))
cacheWith cachePath key timeout serialize deserialize getFresh neverRefresh = do
@ -109,14 +109,16 @@ cacheWith cachePath key timeout serialize deserialize getFresh neverRefresh = do
else Just <$> case valueAgeM of
Just (value, Fresh) -> pure (value, Fresh)
Just (value, Stale) -> do
valueE <- tryAny getFresh
valueE <- tryAny (getFresh (Just value))
case valueE of
Left _ -> pure (value, Stale)
Left e -> do
putStrLn $ "WARNING Couldn't update cache:\n" <> displayException e
pure (value, Stale)
Right value' -> do
saveToCacheWith cachePath key serialize value'
pure (value', Fresh)
Nothing -> do
value <- getFresh
value <- getFresh Nothing
saveToCacheWith cachePath key serialize value
pure (value, Fresh)

View File

@ -120,14 +120,15 @@ installParser = InstallOptions
<*> fmap SetPath (flagYesNoAuto' "set-path" "Adjust PATH automatically" idm)
<*> fmap BashCompletions (flagYesNoAuto' "bash-completions" "Install bash completions for Daml assistant. Default is yes for linux and mac, no for windows." idm)
<*> fmap ZshCompletions (flagYesNoAuto' "zsh-completions" "Install Zsh completions for Daml assistant. Default is yes for linux and mac, no for windows." idm)
<*> fmap AllowInstallNonRelease (flagYesNoAuto "allow-install-non-release" False "Allow installing from a tarball that has no associated release by using the tarball's SDK version as its release version." internal)
where
iflag p name opts desc = fmap p (switch (long name <> help desc <> opts))
uninstallParser :: Parser SdkVersion
uninstallParser :: Parser UnresolvedReleaseVersion
uninstallParser =
argument readSdkVersion (metavar "VERSION" <> help "The SDK version to uninstall.")
readSdkVersion :: ReadM SdkVersion
readSdkVersion :: ReadM UnresolvedReleaseVersion
readSdkVersion =
eitherReader (mapLeft displayException . parseVersion . pack)

View File

@ -17,6 +17,7 @@ module DA.Daml.Assistant.Env
, getDispatchEnv
, envUseCache
, forceEnv
, mkUseCache
) where
import DA.Daml.Assistant.Types
@ -34,12 +35,13 @@ import Data.Maybe
-- | Calculate the environment variables in which to run daml commands.
getDamlEnv :: DamlPath -> LookForProjectPath -> IO Env
getDamlEnv envDamlPath lookForProjectPath = do
envDamlAssistantSdkVersion <- getDamlAssistantSdkVersion
envDamlAssistantPath <- getDamlAssistantPath envDamlPath
envProjectPath <- getProjectPath lookForProjectPath
(envSdkVersion, envSdkPath) <- getSdk envDamlPath envProjectPath
envCachePath <- getCachePath
envFreshStableSdkVersionForCheck <- getFreshStableSdkVersionForCheck (mkUseCache envCachePath envDamlPath)
let useCache = mkUseCache envCachePath envDamlPath
envDamlAssistantSdkVersion <- getDamlAssistantSdkVersion useCache
(envSdkVersion, envSdkPath) <- getSdk useCache envDamlPath envProjectPath
envFreshStableSdkVersionForCheck <- getFreshStableSdkVersionForCheck useCache
pure Env {..}
envUseCache :: Env -> UseCache
@ -71,29 +73,42 @@ overrideWithEnvVarMaybe
-> IO (Maybe t) -- ^ calculation to override
-> IO (Maybe t)
overrideWithEnvVarMaybe envVar normalize parse calculate = do
overrideWithEnvVarMaybeIO envVar normalize (pure . parse) calculate
-- | (internal) Same as overrideWithEnvVarMaybe but parser can run in IO
overrideWithEnvVarMaybeIO
:: Exception e
=> String -- ^ env var name
-> (String -> IO String) -- ^ normalize env var
-> (String -> IO (Either e t)) -- ^ parser for env var
-> IO (Maybe t) -- ^ calculation to override
-> IO (Maybe t)
overrideWithEnvVarMaybeIO envVar normalize parse calculate = do
valueM <- getEnv envVar
case valueM of
Nothing -> calculate
Just "" -> pure Nothing
Just value -> do
value <- normalize value
parsed <- parse value
Just <$> requiredE
("Invalid value for environment variable " <> pack envVar <> ".")
(parse value)
parsed
-- | Get the latest stable SDK version. Can be overriden with
-- DAML_SDK_LATEST_VERSION environment variable.
getFreshStableSdkVersionForCheck :: UseCache -> IO (IO (Maybe SdkVersion))
getFreshStableSdkVersionForCheck :: UseCache -> IO (IO (Maybe ReleaseVersion))
getFreshStableSdkVersionForCheck useCache = do
val <- getEnv sdkVersionLatestEnvVar
case val of
Nothing -> pure (freshMaximumOfVersions (getAvailableReleaseVersions useCache))
Nothing -> pure $
freshMaximumOfVersions (getAvailableReleaseVersions useCache)
Just "" -> pure (pure Nothing)
Just value -> do
parsed <- requiredE
("Invalid value for environment variable " <> pack sdkVersionLatestEnvVar <> ".")
(parseVersion (pack value))
pure (pure (Just parsed))
pure (Just <$> resolveReleaseVersion useCache parsed)
-- | Determine the viability of running sdk commands in the environment.
-- Returns the first failing test's error message.
@ -134,11 +149,11 @@ getDamlAssistantPathDefault (DamlPath damlPath) =
-- | Determine SDK version of running daml assistant. Can be overriden
-- with DAML_ASSISTANT_VERSION env var.
getDamlAssistantSdkVersion :: IO (Maybe DamlAssistantSdkVersion)
getDamlAssistantSdkVersion =
overrideWithEnvVarMaybe damlAssistantVersionEnvVar pure
(fmap DamlAssistantSdkVersion . parseVersion . pack)
(fmap DamlAssistantSdkVersion <$> tryAssistantM getAssistantSdkVersion)
getDamlAssistantSdkVersion :: UseCache -> IO (Maybe DamlAssistantSdkVersion)
getDamlAssistantSdkVersion useCache =
overrideWithEnvVarMaybeIO damlAssistantVersionEnvVar pure
(fmap (fmap DamlAssistantSdkVersion) . traverse (resolveReleaseVersion useCache) . parseVersion . pack)
(fmap DamlAssistantSdkVersion <$> tryAssistantM (getAssistantSdkVersion useCache))
-- | Determine absolute path of daml home directory.
--
@ -202,30 +217,31 @@ getProjectPath (LookForProjectPath True) = wrapErr "Detecting daml project." $ d
-- These can be overriden by the environment variables DAML_SDK_VERSION
-- and DAML_SDK_PATH (and it ought to be enough to supply one of these
-- and have the other be inferred).
getSdk :: DamlPath
getSdk :: UseCache
-> DamlPath
-> Maybe ProjectPath
-> IO (Maybe SdkVersion, Maybe SdkPath)
getSdk damlPath projectPathM =
-> IO (Maybe ReleaseVersion, Maybe SdkPath)
getSdk useCache damlPath projectPathM =
wrapErr "Determining SDK version and path." $ do
sdkVersion <- overrideWithEnvVarMaybe sdkVersionEnvVar pure (parseVersion . pack) $ firstJustM id
releaseVersion <- overrideWithEnvVarMaybeIO sdkVersionEnvVar pure (traverse (resolveReleaseVersion useCache) . parseVersion . pack) $ firstJustM id
[ maybeM (pure Nothing)
(tryAssistantM . getSdkVersionFromSdkPath . SdkPath)
(tryAssistantM . getReleaseVersionFromSdkPath useCache . SdkPath)
(getEnv sdkPathEnvVar)
, mapM getSdkVersionFromProjectPath projectPathM
, mapM (getSdkVersionFromProjectPath useCache) projectPathM
, tryAssistantM $ getDefaultSdkVersion damlPath
]
sdkPath <- overrideWithEnvVarMaybe @SomeException sdkPathEnvVar makeAbsolute (Right . SdkPath) $
useInstalledPath damlPath sdkVersion
useInstalledPath damlPath releaseVersion
return (sdkVersion, sdkPath)
return (releaseVersion, sdkPath)
where
useInstalledPath :: DamlPath -> Maybe SdkVersion -> IO (Maybe SdkPath)
useInstalledPath :: DamlPath -> Maybe ReleaseVersion -> IO (Maybe SdkPath)
useInstalledPath _ Nothing = pure Nothing
useInstalledPath damlPath (Just sdkVersion) = do
let sdkPath = defaultSdkPath damlPath sdkVersion
useInstalledPath damlPath (Just releaseVersion) = do
let sdkPath = defaultSdkPath damlPath releaseVersion
test <- doesDirectoryExist (unwrapSdkPath sdkPath)
pure (guard test >> Just sdkPath)

View File

@ -5,23 +5,24 @@
module DA.Daml.Assistant.Install
( InstallOptions (..)
, InstallEnv (..)
, Artifactory.ArtifactoryApiKey(..)
, InstallEnvF (..)
, InstallEnv
, InstallEnvWithoutVersion
, DAVersion.ArtifactoryApiKey(..)
, versionInstall
, install
, uninstallVersion
, Artifactory.queryArtifactoryApiKey
, DAVersion.queryArtifactoryApiKey
, pattern RawInstallTarget_Project
) where
import DA.Directory
import DA.Daml.Assistant.Types
import DA.Daml.Assistant.Util
import qualified DA.Daml.Assistant.Install.Artifactory as Artifactory
import qualified DA.Daml.Assistant.Install.Github as Github
import qualified DA.Daml.Assistant.Version as DAVersion
import DA.Daml.Assistant.Install.Path
import DA.Daml.Assistant.Install.Completion
import DA.Daml.Assistant.Version (getLatestSdkSnapshotVersion, getLatestReleaseVersion, UseCache (..))
import DA.Daml.Assistant.Version (getLatestSdkSnapshotVersion, getLatestReleaseVersion, UseCache (..), resolveSdkVersionToRelease)
import DA.Daml.Assistant.Cache (CacheTimeout (..))
import DA.Daml.Project.Consts
import DA.Daml.Project.Config
@ -32,7 +33,6 @@ import qualified Data.Conduit.List as List
import qualified Data.Conduit.Tar.Extra as Tar
import qualified Data.Conduit.Zlib as Zlib
import Data.Either.Extra
import qualified Data.SemVer as SemVer
import Network.HTTP.Simple
import qualified Data.ByteString as BS
import qualified Data.ByteString.UTF8 as BS.UTF8
@ -49,6 +49,9 @@ import Control.Exception.Safe
import System.ProgressBar
import System.Info.Extra (isWindows)
import Options.Applicative.Extended (determineAuto)
import qualified Data.SemVer as V
import qualified Data.Text as T
import qualified Control.Exception
-- unix specific
import System.PosixCompat.Types ( FileMode )
@ -68,10 +71,10 @@ import System.PosixCompat.Files
, otherReadMode
, otherExecuteMode)
data InstallEnv = InstallEnv
data InstallEnvF a = InstallEnv
{ options :: InstallOptions
-- ^ command-line options to daml install
, targetVersionM :: Maybe SdkVersion
, targetVersionM :: a
-- ^ target install version
, assistantVersion :: Maybe DamlAssistantSdkVersion
-- ^ version of running daml assistant
@ -86,14 +89,21 @@ data InstallEnv = InstallEnv
-- (e.g. when running install script).
, projectPathM :: Maybe ProjectPath
-- ^ project path (for "daml install project")
, artifactoryApiKeyM :: Maybe Artifactory.ArtifactoryApiKey
, artifactoryApiKeyM :: Maybe DAVersion.ArtifactoryApiKey
-- ^ Artifactoyr API key used to fetch SDK EE tarball.
, output :: String -> IO ()
-- ^ output an informative message
}
instance Functor InstallEnvF where
fmap f InstallEnv{..} = InstallEnv{targetVersionM = f targetVersionM, ..}
type InstallEnv = InstallEnvF (Maybe ReleaseVersion)
type InstallEnvWithoutVersion = InstallEnvF ()
type InstallEnvWithVersion = InstallEnvF ReleaseVersion
-- | Perform action unless user has passed --quiet flag.
unlessQuiet :: InstallEnv -> IO () -> IO ()
unlessQuiet :: InstallEnvF a -> IO () -> IO ()
unlessQuiet InstallEnv{..} | QuietInstall b <- iQuiet options =
unless b
@ -119,15 +129,31 @@ installExtracted :: InstallEnv -> SdkPath -> IO ()
installExtracted env@InstallEnv{..} sourcePath =
wrapErr "Installing extracted SDK release." $ do
sourceConfig <- readSdkConfig sourcePath
sourceVersion <- fromRightM throwIO (sdkVersionFromSdkConfig sourceConfig)
sourceSdkVersion <- fromRightM throwIO (sdkVersionFromSdkConfig sourceConfig)
-- Check that source version matches expected target version.
whenJust targetVersionM $ \targetVersion -> do
unless (sourceVersion == targetVersion) $ do
-- If there is no target version, that means we're installing directly
-- from a tarball, in which case we try to resolve the sdk version to a
-- release version using the cache, failing if we don't find anything.
sourceVersion <- case targetVersionM of
Just targetVersion -> do
unless (sourceSdkVersion == sdkVersionFromReleaseVersion targetVersion) $ do
throwIO $ assistantErrorBecause
"SDK release version mismatch."
("Expected " <> versionToText targetVersion
<> " but got version " <> versionToText sourceVersion)
("Expected " <> sdkVersionToText (sdkVersionFromReleaseVersion targetVersion)
<> " but got version " <> sdkVersionToText sourceSdkVersion)
pure targetVersion
Nothing -> do
sourceVersionOrErr <- resolveSdkVersionToRelease useCache sourceSdkVersion
let errMsg =
"Failed to retrieve release version for sdk version " <> V.toText (unwrapSdkVersion sourceSdkVersion)
<> " from sdk path " <> T.pack (unwrapSdkPath sourcePath)
if unAllowInstallNonRelease (iAllowInstallNonRelease options)
then -- NOTE: Using the SDK version as the release version is
-- only enabled by --allow-install-non-release, which is a
-- flag only for devs
pure (OldReleaseVersion (unwrapSdkVersion sourceSdkVersion))
else requiredE errMsg sourceVersionOrErr
-- Set file mode of files to install.
requiredIO "Failed to set file modes for extracted SDK files." $
@ -177,7 +203,7 @@ installExtracted env@InstallEnv{..} sourcePath =
requiredIO "Failed to set file mode of installed SDK directory." $
setSdkFileMode (unwrapSdkPath targetPath)
when (shouldInstallAssistant env sourceVersion) $
when (shouldInstallAssistant env { targetVersionM = sourceVersion }) $
activateDaml env targetPath
installedAssistantPath :: DamlPath -> FilePath
@ -185,7 +211,7 @@ installedAssistantPath damlPath =
let damlName = if isWindows then "daml.cmd" else "daml"
in unwrapDamlPath damlPath </> "bin" </> damlName
activateDaml :: InstallEnv -> SdkPath -> IO ()
activateDaml :: InstallEnvF a -> SdkPath -> IO ()
activateDaml env@InstallEnv{..} targetPath = do
let damlSourceName = if isWindows then "daml.exe" else "daml"
@ -278,7 +304,7 @@ fileModeMask = foldl1 unionFileModes
]
-- | Copy an extracted SDK release directory and install it.
copyAndInstall :: InstallEnv -> FilePath -> IO ()
copyAndInstall :: InstallEnvWithoutVersion -> FilePath -> IO ()
copyAndInstall env sourcePath =
wrapErr "Copying SDK release directory." $ do
withSystemTempDirectory "daml-update" $ \tmp -> do
@ -292,7 +318,7 @@ copyAndInstall env sourcePath =
, walkOnDirectoryPost = \_ -> pure ()
}
installExtracted env (SdkPath copyPath)
installExtracted (fmap (\() -> Nothing) env) (SdkPath copyPath)
-- | Extract a tarGz bytestring and install it.
extractAndInstall :: InstallEnv
@ -310,33 +336,48 @@ extractAndInstall env source =
where throwError msg e = liftIO $ throwIO $ assistantErrorBecause ("Invalid SDK release: " <> msg) e
-- | Download an sdk tarball and install it.
httpInstall :: InstallEnv -> SdkVersion -> IO ()
httpInstall env@InstallEnv{..} releaseVersion = do
httpInstall :: InstallEnvWithVersion -> IO ()
httpInstall env@InstallEnv{targetVersionM = releaseVersion, ..} = do
unlessQuiet env $ output "Downloading SDK release."
requiredAny "Failed to download SDK release." $ do
sdkVersion <- Github.getSdkVersionFromEnterpriseVersion releaseVersion
downloadLocation $ getLocation sdkVersion
downloadLocation =<< getLocation releaseVersion
where
getLocation :: SdkVersion -> InstallLocation
getLocation sdkVersion = case artifactoryApiKeyM of
Nothing -> Github.versionLocation releaseVersion sdkVersion
Just apiKey
| releaseVersion >= firstEEVersion -> Artifactory.versionLocation sdkVersion apiKey
| otherwise -> Github.versionLocation releaseVersion sdkVersion
getLocation :: ReleaseVersion -> IO DAVersion.InstallLocation
getLocation releaseVersion = do
damlConfigE <- tryConfig (readDamlConfig damlPath)
let alternateDownload =
join $ eitherToMaybe $ queryDamlConfig ["alternate-download"] =<< damlConfigE
case alternateDownload of
Just url -> do
eVersionLocation <- DAVersion.alternateVersionLocation releaseVersion url
case eVersionLocation of
Left triedEndpoint ->
throwIO $ assistantError ("Alternate download location in Daml config '" <> url <> "' combined with target release version to produce '" <> triedEndpoint <> "', which is neither a URL nor a file.")
Right location -> pure location
Nothing ->
case artifactoryApiKeyM of
Nothing -> pure $ DAVersion.githubVersionLocation releaseVersion
Just apiKey
-- TODO: Define ordering over release versions
| releaseVersion >= firstEEVersion -> pure $ DAVersion.artifactoryVersionLocation releaseVersion apiKey
| otherwise -> pure $ DAVersion.githubVersionLocation releaseVersion
firstEEVersion :: ReleaseVersion
!firstEEVersion =
let verStr = "1.12.0-snapshot.20210312.6498.0.707c86aa"
in SdkVersion (either error id (SemVer.fromText verStr))
downloadLocation :: InstallLocation -> IO ()
downloadLocation (InstallLocation url headers) = do
in either Control.Exception.throw id (unsafeParseOldReleaseVersion verStr)
downloadLocation :: DAVersion.InstallLocation -> IO ()
downloadLocation (DAVersion.HttpInstallLocation url headers) = do
request <- requiredAny "Failed to parse HTTPS request." $ parseRequest ("GET " <> unpack url)
withResponse (setRequestHeaders headers request) $ \response -> do
when (getResponseStatusCode response /= 200) $
throwIO . assistantErrorBecause "Failed to download release."
throwIO . assistantErrorBecause ("Failed to download release from " <> url <> ".")
. pack . show $ getResponseStatus response
let totalSizeM = readMay . BS.UTF8.toString =<< headMay (getResponseHeader "Content-Length" response)
extractAndInstall env
extractAndInstall (fmap Just env)
. maybe id (\s -> (.| observeProgress s)) totalSizeM
$ getResponseBody response
downloadLocation (DAVersion.FileInstallLocation file) =
extractAndInstall (fmap Just env) (sourceFileBS file)
observeProgress :: MonadResource m =>
Int -> ConduitT BS.ByteString BS.ByteString m ()
observeProgress totalSize = do
@ -352,7 +393,7 @@ httpInstall env@InstallEnv{..} releaseVersion = do
--
-- The lock is released after the action is performed, and is
-- automatically released if the process ends prematurely.
withInstallLock :: InstallEnv -> IO a -> IO a
withInstallLock :: InstallEnvF b -> IO a -> IO a
withInstallLock InstallEnv{..} action = do
let damlSdkPath = unwrapDamlPath damlPath </> "sdk"
lockFilePath = damlSdkPath </> ".lock"
@ -369,7 +410,7 @@ withInstallLock InstallEnv{..} action = do
-- This function takes the install file lock, so it can't be performed
-- concurrently with a versionInstall or another pathInstall, blocking
-- until the other process is finished.
pathInstall :: InstallEnv -> FilePath -> IO ()
pathInstall :: InstallEnvWithoutVersion -> FilePath -> IO ()
pathInstall env@InstallEnv{..} sourcePath = withInstallLock env $ do
isDirectory <- doesDirectoryExist sourcePath
if isDirectory
@ -378,15 +419,15 @@ pathInstall env@InstallEnv{..} sourcePath = withInstallLock env $ do
copyAndInstall env sourcePath
else do
unlessQuiet env $ output "Installing SDK release from tarball."
extractAndInstall env (sourceFileBS sourcePath)
extractAndInstall (fmap (\() -> Nothing) env) (sourceFileBS sourcePath)
-- | Install a specific SDK version.
--
-- This function takes the install file lock, so it can't be performed
-- concurrently with a pathInstall or another versionInstall, blocking
-- until the other process is finished.
versionInstall :: InstallEnv -> SdkVersion -> IO ()
versionInstall env@InstallEnv{..} version = withInstallLock env $ do
versionInstall :: InstallEnvWithVersion -> IO ()
versionInstall env@InstallEnv{targetVersionM = version, ..} = withInstallLock env $ do
let SdkPath path = defaultSdkPath damlPath version
alreadyInstalled <- doesDirectoryExist path
@ -408,17 +449,16 @@ versionInstall env@InstallEnv{..} version = withInstallLock env $ do
, versionToString version
]
when performInstall $
httpInstall env { targetVersionM = Just version } version
when performInstall $ httpInstall env
-- Need to activate here if we aren't performing the full install.
when (not performInstall && shouldInstallAssistant env version) $ do
when (not performInstall && shouldInstallAssistant env) $ do
unlessQuiet env . output $
"Activating assistant version " <> versionToString version
activateDaml env (SdkPath path)
-- | Install the latest version of the SDK.
latestInstall :: InstallEnv -> IO ()
latestInstall :: InstallEnvWithoutVersion -> IO ()
latestInstall env@InstallEnv{..} = do
version1 <- getLatestReleaseVersion useCache
-- override the cache if it's older than 1 day, even if daml-config.yaml says otherwise
@ -428,19 +468,20 @@ latestInstall env@InstallEnv{..} = do
then tryAssistantM $ getLatestSdkSnapshotVersion useCache
else pure Nothing
let version = maybe version1 (max version1) version2M
versionInstall env version
versionInstall env { targetVersionM = version }
-- | Install the SDK version of the current project.
projectInstall :: InstallEnv -> ProjectPath -> IO ()
projectInstall :: InstallEnvWithoutVersion -> ProjectPath -> IO ()
projectInstall env projectPath = do
projectConfig <- readProjectConfig projectPath
versionM <- fromRightM throwIO $ sdkVersionFromProjectConfig projectConfig
version <- required "SDK version missing from project config (daml.yaml)." versionM
versionInstall env version
unresolvedVersionM <- fromRightM throwIO $ releaseVersionFromProjectConfig projectConfig
unresolvedVersion <- required "SDK version missing from project config (daml.yaml)." unresolvedVersionM
version <- DAVersion.resolveReleaseVersion (useCache env) unresolvedVersion
versionInstall env { targetVersionM = version }
-- | Determine whether the assistant should be installed.
shouldInstallAssistant :: InstallEnv -> SdkVersion -> Bool
shouldInstallAssistant InstallEnv{..} versionToInstall =
shouldInstallAssistant :: InstallEnvWithVersion -> Bool
shouldInstallAssistant InstallEnv{targetVersionM = versionToInstall, ..} =
let isNewer = maybe True ((< versionToInstall) . unwrapDamlAssistantSdkVersion) assistantVersion
in unActivateInstall (iActivate options)
|| determineAuto (isNewer || missingAssistant || installingFromOutside)
@ -466,9 +507,9 @@ install options damlPath useCache projectPathM assistantVersion = do
damlConfigE <- tryConfig $ readDamlConfig damlPath
let installingFromOutside = not $
isPrefixOf (unwrapDamlPath damlPath </> "") execPath
targetVersionM = Nothing -- determined later
targetVersionM = () -- determined later
output = putStrLn -- Output install messages to stdout.
artifactoryApiKeyM = Artifactory.queryArtifactoryApiKey =<< eitherToMaybe damlConfigE
artifactoryApiKeyM = DAVersion.queryArtifactoryApiKey =<< eitherToMaybe damlConfigE
env = InstallEnv {..}
case iTargetM options of
Nothing -> do
@ -491,8 +532,9 @@ install options damlPath useCache projectPathM assistantVersion = do
Just RawInstallTarget_Latest ->
latestInstall env
Just (RawInstallTarget arg) | Right version <- parseVersion (pack arg) ->
versionInstall env version
Just (RawInstallTarget arg) | Right version <- parseVersion (pack arg) -> do
releaseVersion <- DAVersion.resolveReleaseVersion useCache version
versionInstall env { targetVersionM = releaseVersion }
Just (RawInstallTarget arg) -> do
testD <- doesDirectoryExist arg
@ -503,13 +545,13 @@ install options damlPath useCache projectPathM assistantVersion = do
throwIO (assistantErrorBecause "Invalid install target. Expected version, path, 'project' or 'latest'." ("target = " <> pack arg))
-- | Uninstall a specific SDK version.
uninstallVersion :: Env -> SdkVersion -> IO ()
uninstallVersion Env{..} sdkVersion = wrapErr "Uninstalling SDK version." $ do
let (SdkPath path) = defaultSdkPath envDamlPath sdkVersion
uninstallVersion :: Env -> ReleaseVersion -> IO ()
uninstallVersion Env{..} releaseVersion = wrapErr "Uninstalling SDK version." $ do
let (SdkPath path) = defaultSdkPath envDamlPath releaseVersion
exists <- doesDirectoryExist path
if exists then do
when (Just (DamlAssistantSdkVersion sdkVersion) == envDamlAssistantSdkVersion) $ do
when (Just (DamlAssistantSdkVersion releaseVersion) == envDamlAssistantSdkVersion) $ do
hPutStr stderr . unlines $
[ "Cannot uninstall SDK version of current daml assistant."
, "Please switch to a different version of daml assistant and try again."
@ -525,7 +567,7 @@ uninstallVersion Env{..} sdkVersion = wrapErr "Uninstalling SDK version." $ do
requiredIO "Failed to remove SDK files." $ do
removePathForcibly path
putStrLn ("SDK version " <> versionToString sdkVersion <> " has been uninstalled.")
putStrLn ("SDK version " <> versionToString releaseVersion <> " has been uninstalled.")
else do
putStrLn ("SDK version " <> versionToString sdkVersion <> " is not installed.")
putStrLn ("SDK version " <> versionToString releaseVersion <> " is not installed.")

View File

@ -1,43 +0,0 @@
-- Copyright (c) 2023 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
-- SPDX-License-Identifier: Apache-2.0
-- | Discover releases from the artifactory.
module DA.Daml.Assistant.Install.Artifactory
( versionLocation
, queryArtifactoryApiKey
, ArtifactoryApiKey(..)
) where
import DA.Daml.Assistant.Install.Github hiding (versionLocation)
import DA.Daml.Assistant.Types
import DA.Daml.Project.Config
import Data.Aeson
import Data.Either.Extra
import qualified Data.Text as T
import qualified Data.Text.Encoding as T
newtype ArtifactoryApiKey = ArtifactoryApiKey
{ unwrapArtifactoryApiKey :: Text
} deriving (Eq, Show, FromJSON)
queryArtifactoryApiKey :: DamlConfig -> Maybe ArtifactoryApiKey
queryArtifactoryApiKey damlConfig =
eitherToMaybe (queryDamlConfigRequired ["artifactory-api-key"] damlConfig)
-- | Install location for particular version.
-- NOTE THIS TAKES THE SDK VERSION, not the release version that `Github.versionLocation` uses
versionLocation :: SdkVersion -> ArtifactoryApiKey -> InstallLocation
versionLocation sdkVersion apiKey = InstallLocation
{ ilUrl = T.concat
[ "https://digitalasset.jfrog.io/artifactory/sdk-ee/"
, versionToText sdkVersion
, "/daml-sdk-"
, versionToText sdkVersion
, "-"
, osName
, "-ee.tar.gz"
]
, ilHeaders =
[("X-JFrog-Art-Api", T.encodeUtf8 (unwrapArtifactoryApiKey apiKey))]
}

View File

@ -1,88 +0,0 @@
-- Copyright (c) 2023 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
-- SPDX-License-Identifier: Apache-2.0
-- | Discover releases from the digital-asset/daml github.
module DA.Daml.Assistant.Install.Github
( versionLocation
, tagToVersion
, osName
, getSdkVersionFromEnterpriseVersion
) where
import Control.Exception.Safe
import DA.Daml.Assistant.Types
import Data.Aeson
import Data.Aeson.Types (explicitParseField, listParser)
import Data.Either.Extra
import Data.Maybe (fromMaybe, listToMaybe, mapMaybe)
import Network.HTTP.Simple (getResponseBody, httpJSON, parseRequest, setRequestHeaders)
import qualified System.Info
import qualified Data.Text as T
-- | General git tag. We only care about the tags of the form "v<VERSION>"
-- where <VERSION> is an SDK version. For example, "v0.11.1".
newtype Tag = Tag { unTag :: Text } deriving (Eq, Show, FromJSON)
-- | Convert a version to a git tag.
versionToTag :: SdkVersion -> Tag
versionToTag v = Tag ("v" <> versionToText v)
-- | Attempt to convert a git tag into an SDK version. Not all
-- git tags correspond to versions, resulting in an error. The
-- tags that do correspond to versions have the form "v<VERSION>"
-- where <VERSION> is a valid SDK version (i.e. a semantic
-- version).
tagToVersion :: Tag -> Either AssistantError SdkVersion
tagToVersion (Tag t) =
mapLeft (assistantErrorBecause ("Tag " <> t <> "does not represent a valid SDK version.")) $
if T.take 1 t == "v" then
mapLeft (pack . displayException) $ parseVersion (T.drop 1 t)
else
Left "Tag must start with v followed by semantic version."
-- | OS-specific part of the asset name.
osName :: Text
osName = case System.Info.os of
"darwin" -> "macos"
"linux" -> "linux"
"mingw32" -> "windows"
p -> error ("daml: Unknown operating system " ++ p)
-- | Install location for particular version.
versionLocation :: SdkVersion -> SdkVersion -> InstallLocation
versionLocation releaseVersion sdkVersion = InstallLocation
{ ilUrl = T.concat
[ "https://github.com/digital-asset/daml/releases/download/"
, unTag (versionToTag releaseVersion)
, "/daml-sdk-"
, versionToText sdkVersion
, "-"
, osName
, ".tar.gz"
]
, ilHeaders = []
}
-- | Subset of the github release response that we care about
data GithubReleaseResponseSubset = GithubReleaseResponseSubset
{ assetNames :: [T.Text] }
instance FromJSON GithubReleaseResponseSubset where
-- Akin to `GithubReleaseResponseSubset . fmap name . assets` but lifted into a parser over json
parseJSON = withObject "GithubReleaseResponse" $ \v ->
GithubReleaseResponseSubset <$> explicitParseField (listParser (withObject "GithubRelease" (.: "name"))) v "assets"
-- | Since ~2.8.snapshot, the "enterprise version" (the version the user inputs) and the daml sdk version (the version of the daml repo) can differ
-- As such, we derive the latter via the github api `assets` endpoint, looking for a file matching the expected `daml-sdk-$VERSION-$OS.tar.gz`
getSdkVersionFromEnterpriseVersion :: SdkVersion -> IO SdkVersion
getSdkVersionFromEnterpriseVersion v = do
req <- parseRequest $ "https://api.github.com/repos/digital-asset/daml/releases/tags/" <> T.unpack (unTag $ versionToTag v)
res <- httpJSON $ setRequestHeaders [("User-Agent", "request")] req
let mSdkVersionStr =
listToMaybe $ flip mapMaybe (assetNames $ getResponseBody res) $ \name -> do
withoutExt <- T.stripSuffix "-linux.tar.gz" name
T.stripPrefix "daml-sdk-" withoutExt
sdkVersionStr = fromMaybe (error "Failed to find linux sdk in release") mSdkVersionStr
either throwIO pure $ parseVersion sdkVersionStr

View File

@ -11,45 +11,10 @@ module DA.Daml.Assistant.Types
) where
import DA.Daml.Project.Types
import qualified Data.Text as T
import Data.Text (Text, pack, unpack)
import Data.Maybe
import Network.HTTP.Types.Header
import Options.Applicative.Extended (YesNoAuto (..))
import Control.Exception.Safe
import Data.Functor.Identity
data AssistantError = AssistantError
{ errContext :: Maybe Text -- ^ Context in which error occurs.
, errMessage :: Maybe Text -- ^ User-friendly error message.
, errInternal :: Maybe Text -- ^ Internal error message, i.e. what actually happened.
} deriving (Eq, Show)
instance Exception AssistantError where
displayException AssistantError {..} = unpack . T.unlines . catMaybes $
[ Just ("daml: " <> fromMaybe "An unknown error has occured" errMessage)
, fmap (" context: " <>) errContext
, fmap (" details: " <>) errInternal
]
-- | Standard error message.
assistantError :: Text -> AssistantError
assistantError msg = AssistantError
{ errContext = Nothing
, errMessage = Just msg
, errInternal = Nothing
}
-- | Standard error message with additional internal cause.
assistantErrorBecause :: Text -> Text -> AssistantError
assistantErrorBecause msg e = (assistantError msg) { errInternal = Just e }
-- | Standard error message with additional details.
assistantErrorDetails :: String -> [(String, String)] -> AssistantError
assistantErrorDetails msg details =
assistantErrorBecause (pack msg) . pack . concat $
["\n " <> k <> ": " <> v | (k,v) <- details]
data EnvF f = Env
{ envDamlPath :: DamlPath
, envCachePath :: CachePath
@ -57,12 +22,12 @@ data EnvF f = Env
, envDamlAssistantSdkVersion :: Maybe DamlAssistantSdkVersion
, envProjectPath :: Maybe ProjectPath
, envSdkPath :: Maybe SdkPath
, envSdkVersion :: Maybe SdkVersion
, envFreshStableSdkVersionForCheck :: f (Maybe SdkVersion)
, envSdkVersion :: Maybe ReleaseVersion
, envFreshStableSdkVersionForCheck :: f (Maybe ReleaseVersion)
}
deriving instance Eq (f (Maybe SdkVersion)) => Eq (EnvF f)
deriving instance Show (f (Maybe SdkVersion)) => Show (EnvF f)
deriving instance Eq (f (Maybe ReleaseVersion)) => Eq (EnvF f)
deriving instance Show (f (Maybe ReleaseVersion)) => Show (EnvF f)
type Env = EnvF IO
@ -75,7 +40,7 @@ data BuiltinCommand
= Version VersionOptions
| Exec String [String]
| Install InstallOptions
| Uninstall SdkVersion
| Uninstall UnresolvedReleaseVersion
deriving (Eq, Show)
newtype LookForProjectPath = LookForProjectPath
@ -109,16 +74,10 @@ data InstallOptions = InstallOptions
, iSetPath :: SetPath -- ^ set the user's PATH (on Windows)
, iBashCompletions :: BashCompletions -- ^ install bash completions for the daml assistant
, iZshCompletions :: ZshCompletions -- ^ install Zsh completions for the daml assistant
, iAllowInstallNonRelease :: AllowInstallNonRelease -- ^ install Zsh completions for the daml assistant
} deriving (Eq, Show)
-- | An install locations is a pair of fully qualified HTTP[S] URL to an SDK release tarball and headers
-- required to access that URL. For example:
-- "https://github.com/digital-asset/daml/releases/download/v0.11.1/daml-sdk-0.11.1-macos.tar.gz"
data InstallLocation = InstallLocation
{ ilUrl :: Text
, ilHeaders :: RequestHeaders
} deriving (Eq, Show)
newtype AllowInstallNonRelease = AllowInstallNonRelease { unAllowInstallNonRelease :: Bool } deriving (Eq, Show)
newtype RawInstallTarget = RawInstallTarget String deriving (Eq, Show)
newtype ForceInstall = ForceInstall { unForceInstall :: Bool } deriving (Eq, Show)
newtype QuietInstall = QuietInstall { unQuietInstall :: Bool } deriving (Eq, Show)

View File

@ -5,6 +5,7 @@
module DA.Daml.Assistant.Version
( getInstalledSdkVersions
, getSdkVersionFromSdkPath
, getReleaseVersionFromSdkPath
, getSdkVersionFromProjectPath
, getAssistantSdkVersion
, getDefaultSdkVersion
@ -18,6 +19,15 @@ module DA.Daml.Assistant.Version
, extractReleasesFromSnapshots
, UseCache (..)
, freshMaximumOfVersions
, resolveReleaseVersion
, resolveSdkVersionToRelease
, githubVersionLocation
, artifactoryVersionLocation
, osName
, queryArtifactoryApiKey
, ArtifactoryApiKey(..)
, alternateVersionLocation
, InstallLocation(..)
) where
import DA.Daml.Assistant.Types
@ -25,16 +35,14 @@ import DA.Daml.Assistant.Util
import DA.Daml.Assistant.Cache
import DA.Daml.Project.Config
import DA.Daml.Project.Consts hiding (getDamlPath, getProjectPath)
import System.Directory
import System.FilePath
import System.Environment.Blank
import Control.Exception.Safe
import Control.Monad.Extra
import Data.Maybe
import Data.Either.Extra
import Data.Aeson (FromJSON(..), eitherDecodeStrict')
import Data.Aeson.Types (listParser, withObject, (.:), Parser)
import Data.Aeson.Types (listParser, withObject, (.:), Parser, Value(Object), explicitParseField)
import qualified Data.Text as T
import qualified Data.Text.Encoding as T
import Safe
import Network.HTTP.Simple
import Network.HTTP.Client
@ -43,28 +51,46 @@ import Network.HTTP.Client
)
import Data.ByteString (ByteString)
import qualified Data.ByteString as BS
import qualified Data.ByteString.Char8 as BSC
import qualified Data.ByteString.UTF8 as BSU
import qualified Data.SemVer as V
import Data.Function ((&))
import Control.Lens (view)
import System.Directory (listDirectory, doesFileExist)
import System.FilePath ((</>))
import Data.List (find)
import Data.Either.Extra (eitherToMaybe)
import qualified Data.Map.Strict as M
import qualified Data.List.NonEmpty as NonEmpty
import qualified System.Info
import GHC.Stack
-- | Determine SDK version of running daml assistant. Fails with an
-- AssistantError exception if the version cannot be determined.
getAssistantSdkVersion :: IO SdkVersion
getAssistantSdkVersion = do
getAssistantSdkVersion :: UseCache -> IO ReleaseVersion
getAssistantSdkVersion useCache = do
exePath <- requiredIO "Failed to determine executable path of assistant."
getExecutablePath
sdkPath <- required "Failed to determine SDK path of assistant." =<<
findM hasSdkConfig (ascendants exePath)
getSdkVersionFromSdkPath (SdkPath sdkPath)
getReleaseVersionFromSdkPath useCache (SdkPath sdkPath)
where
hasSdkConfig :: FilePath -> IO Bool
hasSdkConfig p = doesFileExist (p </> sdkConfigName)
-- | Determine SDK version from an SDK directory. Fails with an
-- AssistantError exception if the version cannot be determined.
getReleaseVersionFromSdkPath :: UseCache -> SdkPath -> IO ReleaseVersion
getReleaseVersionFromSdkPath useCache sdkPath = do
sdkVersion <- getSdkVersionFromSdkPath sdkPath
let errMsg =
"Failed to retrieve release version for sdk version " <> V.toText (unwrapSdkVersion sdkVersion)
<> " from sdk path " <> T.pack (unwrapSdkPath sdkPath)
requiredE errMsg =<< resolveSdkVersionToRelease useCache sdkVersion
-- | Determine SDK version from an SDK directory. Fails with an
-- AssistantError exception if the version cannot be determined.
getSdkVersionFromSdkPath :: SdkPath -> IO SdkVersion
@ -76,13 +102,13 @@ getSdkVersionFromSdkPath sdkPath = do
-- | Determine SDK version from project root. Fails with an
-- AssistantError exception if the version cannot be determined.
getSdkVersionFromProjectPath :: ProjectPath -> IO SdkVersion
getSdkVersionFromProjectPath projectPath =
getSdkVersionFromProjectPath :: UseCache -> ProjectPath -> IO ReleaseVersion
getSdkVersionFromProjectPath useCache projectPath =
requiredIO ("Failed to read SDK version from " <> pack projectConfigName) $ do
configE <- tryConfig $ readProjectConfig projectPath
case sdkVersionFromProjectConfig =<< configE of
case releaseVersionFromProjectConfig =<< configE of
Right (Just v) ->
pure v
resolveReleaseVersion useCache v
Left (ConfigFileInvalid _ raw) ->
throwIO $ assistantErrorDetails
(projectConfigName <> " is an invalid YAML file")
@ -105,13 +131,24 @@ getSdkVersionFromProjectPath projectPath =
-- | Get the list of installed SDK versions. Returned list is
-- in no particular order. Fails with an AssistantError exception
-- if this list cannot be obtained.
getInstalledSdkVersions :: DamlPath -> IO [SdkVersion]
getInstalledSdkVersions (DamlPath path) = do
let sdkdir = path </> "sdk"
subdirs <- requiredIO "Failed to list installed SDKs." $ do
dirlist <- listDirectory sdkdir
filterM (\p -> doesDirectoryExist (sdkdir </> p)) dirlist
pure (mapMaybe (eitherToMaybe . parseVersion . pack) subdirs)
getInstalledSdkVersions :: DamlPath -> IO [ReleaseVersion]
getInstalledSdkVersions damlPath = do
let sdkPath = SdkPath (unwrapDamlPath damlPath </> "sdk")
sdksOrErr <- try (listDirectory (unwrapSdkPath sdkPath))
case sdksOrErr of
Left SomeException{} -> pure []
Right sdks -> catMaybes <$> mapM resolveSdk sdks
where
resolveSdk :: String -> IO (Maybe ReleaseVersion)
resolveSdk path = do
case parseVersion (T.pack path) of
Left _ -> pure Nothing
Right unresolvedVersion -> do
let sdkPath = mkSdkPath damlPath path
sdkVersionOrErr <- tryAssistant (getSdkVersionFromSdkPath sdkPath)
pure $ case sdkVersionOrErr of
Left _ -> Nothing
Right sdkVersion -> Just (mkReleaseVersion unresolvedVersion sdkVersion)
-- | Get the default SDK version for commands run outside of a
-- project. This is defined as the latest installed version
@ -121,47 +158,47 @@ getInstalledSdkVersions (DamlPath path) = do
-- Raises an AssistantError exception if the version cannot be
-- obtained, either because we cannot determine the installed
-- versions or it is empty.
getDefaultSdkVersion :: DamlPath -> IO SdkVersion
getDefaultSdkVersion :: DamlPath -> IO ReleaseVersion
getDefaultSdkVersion damlPath = do
installedVersions <- getInstalledSdkVersions damlPath
required "There are no installed SDK versions." $
maximumMay installedVersions
isReleaseVersion :: SdkVersion -> Bool
isReleaseVersion :: ReleaseVersion -> Bool
isReleaseVersion sdkVersion =
let v = unwrapSdkVersion sdkVersion
let v = releaseVersionFromReleaseVersion sdkVersion
in
null (view V.release v) && null (view V.metadata v) && view V.major v > 0
-- | Get the list of available release versions. This will fetch all snapshot
-- versions and then prune them into releases
getAvailableReleaseVersions :: UseCache -> IO ([SdkVersion], CacheAge)
getAvailableReleaseVersions :: UseCache -> IO ([ReleaseVersion], CacheAge)
getAvailableReleaseVersions useCache = do
(versions, cacheAge) <- wrapErr "Fetching list of available SDK versions" $ getAvailableSdkSnapshotVersions useCache
pure (extractReleasesFromSnapshots versions, cacheAge)
extractReleasesFromSnapshots :: [SdkVersion] -> [SdkVersion]
extractReleasesFromSnapshots :: [ReleaseVersion] -> [ReleaseVersion]
extractReleasesFromSnapshots snapshots =
let -- For grouping things by their major or minor version
distinguishBy :: Ord k => (a -> k) -> [a] -> M.Map k (NonEmpty.NonEmpty a)
distinguishBy f as = M.fromListWith (<>) [(f a, pure a) | a <- as]
-- Group versions by their major version number, filtering out snapshots
majorMap :: M.Map Int (NonEmpty.NonEmpty SdkVersion)
majorMap = distinguishBy (view V.major . unwrapSdkVersion) (filter isReleaseVersion snapshots)
majorMap :: M.Map Int (NonEmpty.NonEmpty ReleaseVersion)
majorMap = distinguishBy (view V.major . releaseVersionFromReleaseVersion) (filter isReleaseVersion snapshots)
in
case M.maxView majorMap of
Just (latestMajorVersions, withoutLatestMajor) ->
let -- For old majors, only the latest stable patch
oldMajors :: [SdkVersion]
oldMajors :: [ReleaseVersion]
oldMajors = map maximum (M.elems withoutLatestMajor)
latestMajorMinorVersions :: M.Map Int (NonEmpty.NonEmpty SdkVersion)
latestMajorMinorVersions :: M.Map Int (NonEmpty.NonEmpty ReleaseVersion)
latestMajorMinorVersions =
distinguishBy (view V.minor . unwrapSdkVersion) (NonEmpty.toList latestMajorVersions)
distinguishBy (view V.minor . releaseVersionFromReleaseVersion) (NonEmpty.toList latestMajorVersions)
-- For the most recent major version, output the latest minor version
latestMajorLatestMinorVersions :: [SdkVersion]
latestMajorLatestMinorVersions :: [ReleaseVersion]
latestMajorLatestMinorVersions = map maximum (M.elems latestMajorMinorVersions)
in
oldMajors ++ latestMajorLatestMinorVersions
@ -170,22 +207,22 @@ extractReleasesFromSnapshots snapshots =
-- | Get the list of available snapshot versions, deferring to cache if
-- possible
getAvailableSdkSnapshotVersions :: UseCache -> IO ([SdkVersion], CacheAge)
getAvailableSdkSnapshotVersions :: UseCache -> IO ([ReleaseVersion], CacheAge)
getAvailableSdkSnapshotVersions useCache =
cacheAvailableSdkVersions useCache (getAvailableSdkSnapshotVersionsUncached >>= flattenSnapshotsList)
cacheAvailableSdkVersions useCache (\_ -> getAvailableSdkSnapshotVersionsUncached (damlPath useCache) >>= flattenSnapshotsList)
-- | Find the first occurence of a version on Github, without the cache. Keep in
-- mind that versions are not sorted.
findAvailableSdkSnapshotVersion :: (SdkVersion -> Bool) -> IO (Maybe SdkVersion)
findAvailableSdkSnapshotVersion pred =
getAvailableSdkSnapshotVersionsUncached >>= searchSnapshotsUntil pred
findAvailableSdkSnapshotVersion :: DamlPath -> (ReleaseVersion -> Bool) -> IO (Maybe ReleaseVersion)
findAvailableSdkSnapshotVersion damlPath pred =
getAvailableSdkSnapshotVersionsUncached damlPath >>= searchSnapshotsUntil pred
data SnapshotsList = SnapshotsList
{ versions :: IO [SdkVersion]
{ versions :: IO [ReleaseVersion]
, next :: Maybe (IO SnapshotsList)
}
flattenSnapshotsList :: SnapshotsList -> IO [SdkVersion]
flattenSnapshotsList :: SnapshotsList -> IO [ReleaseVersion]
flattenSnapshotsList SnapshotsList { versions, next } = do
versions <- versions
rest <- case next of
@ -193,7 +230,7 @@ flattenSnapshotsList SnapshotsList { versions, next } = do
Just io -> io >>= flattenSnapshotsList
return (versions ++ rest)
searchSnapshotsUntil :: (SdkVersion -> Bool) -> SnapshotsList -> IO (Maybe SdkVersion)
searchSnapshotsUntil :: (ReleaseVersion -> Bool) -> SnapshotsList -> IO (Maybe ReleaseVersion)
searchSnapshotsUntil pred SnapshotsList { versions, next } = do
versions <- versions
case filter pred versions of
@ -209,9 +246,26 @@ searchSnapshotsUntil pred SnapshotsList { versions, next } = do
-- https://docs.github.com/en/rest/releases/releases?apiVersion=2022-11-28#get-the-latest-release
-- because it sorts by time of upload, so a minor version bump like 2.5.15 may
-- supersede 2.7.2 if the minor release on 2.5.12 was released later
getAvailableSdkSnapshotVersionsUncached :: IO SnapshotsList
getAvailableSdkSnapshotVersionsUncached = do
requestReleasesSnapshotsList "https://api.github.com/repos/digital-asset/daml/releases"
getAvailableSdkSnapshotVersionsUncached :: DamlPath -> IO SnapshotsList
getAvailableSdkSnapshotVersionsUncached damlPath = do
damlConfigE <- tryConfig (readDamlConfig damlPath)
let releasesEndpoint =
case queryDamlConfig ["releases-endpoint"] =<< damlConfigE of
Right (Just url) -> url
_ -> "https://api.github.com/repos/digital-asset/daml/releases"
case parseRequest releasesEndpoint of
Just _ -> requestReleasesSnapshotsList releasesEndpoint
Nothing -> do
endpointContent <-
requiredAny ("Cannot read releases from releases-endpoint file specified in daml-config.yaml: " <> pack releasesEndpoint)
(BS.readFile releasesEndpoint)
pure SnapshotsList
{ versions =
fromRightM
(throwIO . assistantErrorBecause ("Snapshot versions list from " <> pack releasesEndpoint <> " does not contain valid JSON") . pack)
(extractVersions endpointContent)
, next = Nothing
}
where
requestReleasesSnapshotsList :: String -> IO SnapshotsList
requestReleasesSnapshotsList url = do
@ -226,7 +280,7 @@ getAvailableSdkSnapshotVersionsUncached = do
requestReleasesSinglePage :: String -> IO (ByteString, Maybe String)
requestReleasesSinglePage url =
requiredAny "HTTP connection to github.com failed" $ do
requiredAny "HTTP connection failed" $ do
urlRequest <- parseRequest url
let request =
urlRequest
@ -246,12 +300,15 @@ getAvailableSdkSnapshotVersionsUncached = do
| otherwise -> go rest
_ -> Nothing
extractVersions :: ByteString -> Either String [SdkVersion]
extractVersions :: ByteString -> Either String [ReleaseVersion]
extractVersions bs = map unParsedSdkVersion . unParsedSdkVersions <$> eitherDecodeStrict' bs
newtype ParsedSdkVersions = ParsedSdkVersions { unParsedSdkVersions :: [ParsedSdkVersion] }
data ParsedSdkVersion = ParsedSdkVersion { unParsedSdkVersion :: SdkVersion, isPrerelease :: Bool }
deriving (Show, Eq, Ord)
data ParsedSdkVersion = ParsedSdkVersion
{ unParsedSdkVersion :: ReleaseVersion
, isPrerelease :: Bool
}
deriving (Show, Eq)
instance FromJSON ParsedSdkVersions where
parseJSON v = ParsedSdkVersions <$> listParser parseJSON v
@ -260,12 +317,23 @@ instance FromJSON ParsedSdkVersion where
parseJSON =
withObject "Version" $ \v -> do
rawTagName <- (v .: "tag_name" :: Parser T.Text)
releaseVersion <- handleInvalidVersion "release version" (parseVersion (T.dropWhile ('v' ==) rawTagName))
isPrerelease <- (v .: "prerelease" :: Parser Bool)
case parseVersion (T.dropWhile ('v' ==) rawTagName) of
Left (InvalidVersion src msg) -> fail $ "Invalid version string `" <> unpack src <> "` for reason: " <> msg
Right sdkVersion -> pure ParsedSdkVersion { unParsedSdkVersion = sdkVersion, isPrerelease }
mbRawSdkVersion <- releaseResponseSubsetSdkVersion <$> parseJSON (Object v)
sdkVersion <- case mbRawSdkVersion of
Nothing -> fail $ "Couldn't find Linux SDK in release version: '" <> T.unpack rawTagName <> "'"
Just rawSdkVersion -> handleInvalidVersion "sdk version" (parseSdkVersion rawSdkVersion)
pure ParsedSdkVersion
{ unParsedSdkVersion = mkReleaseVersion releaseVersion sdkVersion
, isPrerelease
}
where
handleInvalidVersion :: String -> Either InvalidVersion a -> Parser a
handleInvalidVersion versionName (Left (InvalidVersion src msg)) =
fail $ "Invalid " <> versionName <> " string `" <> unpack src <> "` for reason: " <> msg
handleInvalidVersion _ (Right a) = pure a
maximumOfNonEmptyVersions :: IO ([SdkVersion], CacheAge) -> IO SdkVersion
maximumOfNonEmptyVersions :: IO ([ReleaseVersion], CacheAge) -> IO ReleaseVersion
maximumOfNonEmptyVersions getVersions = do
(versions, _cacheAge) <- getVersions
case maximumMay versions of
@ -273,7 +341,7 @@ maximumOfNonEmptyVersions getVersions = do
Just m -> pure m
-- | Get the latest released SDK version
freshMaximumOfVersions :: IO ([SdkVersion], CacheAge) -> IO (Maybe SdkVersion)
freshMaximumOfVersions :: IO ([ReleaseVersion], CacheAge) -> IO (Maybe ReleaseVersion)
freshMaximumOfVersions getVersions = do
(versions, cacheAge) <- getVersions
case cacheAge of
@ -281,10 +349,191 @@ freshMaximumOfVersions getVersions = do
Fresh -> pure (maximumMay versions)
-- | Get the latest snapshot SDK version.
getLatestSdkSnapshotVersion :: UseCache -> IO SdkVersion
getLatestSdkSnapshotVersion :: UseCache -> IO ReleaseVersion
getLatestSdkSnapshotVersion useCache = do
maximumOfNonEmptyVersions (getAvailableSdkSnapshotVersions useCache)
getLatestReleaseVersion :: UseCache -> IO SdkVersion
getLatestReleaseVersion :: UseCache -> IO ReleaseVersion
getLatestReleaseVersion useCache =
maximumOfNonEmptyVersions (getAvailableReleaseVersions useCache)
data CouldNotResolveVersion
= CouldNotResolveReleaseVersion UnresolvedReleaseVersion
| CouldNotResolveSdkVersion SdkVersion
deriving (Show, Eq, Ord)
instance Exception CouldNotResolveVersion where
displayException (CouldNotResolveReleaseVersion version) = "Could not resolve release version " <> T.unpack (V.toText (unwrapUnresolvedReleaseVersion version))
displayException (CouldNotResolveSdkVersion version) = "Could not resolve SDK version " <> T.unpack (V.toText (unwrapSdkVersion version)) <> " to a release version. Possible fix: `daml version --force-reload yes`?"
resolveReleaseVersion :: HasCallStack => UseCache -> UnresolvedReleaseVersion -> IO ReleaseVersion
resolveReleaseVersion _ targetVersion | isHeadVersion targetVersion = pure headReleaseVersion
resolveReleaseVersion useCache targetVersion = do
mbResolved <- resolveReleaseVersionFromDamlPath (damlPath useCache) targetVersion
case mbResolved of
Just resolved -> pure resolved
Nothing -> do
let isTargetVersion version =
unwrapUnresolvedReleaseVersion targetVersion == releaseVersionFromReleaseVersion version
(releaseVersions, _) <- getAvailableSdkSnapshotVersions useCache
case filter isTargetVersion releaseVersions of
(x:_) -> pure x
[] -> do
releasedVersionE <- resolveReleaseVersionFromGithub targetVersion
case releasedVersionE of
Left _ ->
throwIO (CouldNotResolveReleaseVersion targetVersion)
Right releasedVersion -> do
_ <- cacheAvailableSdkVersions useCache (\pre -> pure (releasedVersion : fromMaybe [] pre))
pure releasedVersion
resolveSdkVersionToRelease :: UseCache -> SdkVersion -> IO (Either CouldNotResolveVersion ReleaseVersion)
resolveSdkVersionToRelease _ targetVersion | isHeadVersion targetVersion = pure (Right headReleaseVersion)
resolveSdkVersionToRelease useCache targetVersion = do
resolved <- resolveSdkVersionFromDamlPath (damlPath useCache) targetVersion
case resolved of
Just resolved -> pure (Right resolved)
Nothing -> do
let isTargetVersion version =
targetVersion == sdkVersionFromReleaseVersion version
(releaseVersions, _) <- getAvailableSdkSnapshotVersions useCache
case filter isTargetVersion releaseVersions of
(x:_) -> pure $ Right x
[] -> pure $ Left $ CouldNotResolveSdkVersion targetVersion
resolveReleaseVersionFromDamlPath :: DamlPath -> UnresolvedReleaseVersion -> IO (Maybe ReleaseVersion)
resolveReleaseVersionFromDamlPath damlPath targetVersion = do
let isMatchingVersion releaseVersion =
unwrapUnresolvedReleaseVersion targetVersion == releaseVersionFromReleaseVersion releaseVersion
resolvedVersions <- getInstalledSdkVersions damlPath
pure (find isMatchingVersion resolvedVersions)
resolveSdkVersionFromDamlPath :: DamlPath -> SdkVersion -> IO (Maybe ReleaseVersion)
resolveSdkVersionFromDamlPath damlPath targetSdkVersion = do
let isMatchingVersion releaseVersion =
targetSdkVersion == sdkVersionFromReleaseVersion releaseVersion
resolvedVersions <- getInstalledSdkVersions damlPath
pure (find isMatchingVersion resolvedVersions)
-- | Subset of the github release response that we care about
data GithubReleaseResponseSubset = GithubReleaseResponseSubset
{ assetNames :: [T.Text] }
instance FromJSON GithubReleaseResponseSubset where
-- Akin to `GithubReleaseResponseSubset . fmap name . assets` but lifted into a parser over json
parseJSON = withObject "GithubReleaseResponse" $ \v ->
GithubReleaseResponseSubset <$> explicitParseField (listParser (withObject "GithubRelease" (.: "name"))) v "assets"
releaseResponseSubsetSdkVersion :: GithubReleaseResponseSubset -> Maybe T.Text
releaseResponseSubsetSdkVersion responseSubset =
let extractMatchingName :: T.Text -> Maybe T.Text
extractMatchingName name = do
withoutExt <- T.stripSuffix "-linux.tar.gz" name
T.stripPrefix "daml-sdk-" withoutExt
in
listToMaybe $ mapMaybe extractMatchingName (assetNames responseSubset)
data GithubReleaseError
= FailedToFindLinuxSdkInRelease String
| Couldn'tParseSdkVersion String InvalidVersion
deriving (Show, Eq)
instance Exception GithubReleaseError where
displayException (FailedToFindLinuxSdkInRelease url) =
"Couldn't find Linux SDK in release at url: '" <> url <> "'"
displayException (Couldn'tParseSdkVersion url v) =
"Couldn't parse SDK in release at url '" <> url <> "': " <> displayException v
-- | Since ~2.8.snapshot, the "enterprise version" (the version the user inputs) and the daml sdk version (the version of the daml repo) can differ
-- As such, we derive the latter via the github api `assets` endpoint, looking for a file matching the expected `daml-sdk-$VERSION-$OS.tar.gz`
resolveReleaseVersionFromGithub :: UnresolvedReleaseVersion -> IO (Either GithubReleaseError ReleaseVersion)
resolveReleaseVersionFromGithub unresolvedVersion = do
let tag = T.unpack (rawVersionToTextWithV (unwrapUnresolvedReleaseVersion unresolvedVersion))
url = "https://api.github.com/repos/digital-asset/daml/releases/tags/" <> tag
req <- parseRequest url
res <- httpJSON $ setRequestHeaders [("User-Agent", "request")] req
pure $
case releaseResponseSubsetSdkVersion (getResponseBody res) of
Nothing -> Left (FailedToFindLinuxSdkInRelease url)
Just sdkVersionStr ->
case parseSdkVersion sdkVersionStr of
Left issue -> Left (Couldn'tParseSdkVersion url issue)
Right sdkVersion -> Right (mkReleaseVersion unresolvedVersion sdkVersion)
-- | OS-specific part of the asset name.
osName :: Text
osName = case System.Info.os of
"darwin" -> "macos"
"linux" -> "linux"
"mingw32" -> "windows"
p -> error ("daml: Unknown operating system " ++ p)
newtype ArtifactoryApiKey = ArtifactoryApiKey
{ unwrapArtifactoryApiKey :: Text
} deriving (Eq, Show, FromJSON)
queryArtifactoryApiKey :: DamlConfig -> Maybe ArtifactoryApiKey
queryArtifactoryApiKey damlConfig =
eitherToMaybe (queryDamlConfigRequired ["artifactory-api-key"] damlConfig)
-- | Install location for particular version.
artifactoryVersionLocation :: ReleaseVersion -> ArtifactoryApiKey -> InstallLocation
artifactoryVersionLocation releaseVersion apiKey = HttpInstallLocation
{ ilUrl = T.concat
[ "https://digitalasset.jfrog.io/artifactory/sdk-ee/"
, sdkVersionToText (sdkVersionFromReleaseVersion releaseVersion)
, "/daml-sdk-"
, sdkVersionToText (sdkVersionFromReleaseVersion releaseVersion)
, "-"
, osName
, "-ee.tar.gz"
]
, ilHeaders =
[("X-JFrog-Art-Api", T.encodeUtf8 (unwrapArtifactoryApiKey apiKey))]
}
-- | Install location from Github for particular version.
githubVersionLocation :: ReleaseVersion -> InstallLocation
githubVersionLocation releaseVersion =
HttpInstallLocation
{ ilUrl = renderVersionLocation releaseVersion "https://github.com/digital-asset/daml/releases/download"
, ilHeaders = []
}
alternateVersionLocation :: ReleaseVersion -> Text -> IO (Either Text InstallLocation)
alternateVersionLocation releaseVersion prefix = do
let location = renderVersionLocation releaseVersion prefix
case parseRequest ("GET " <> unpack location) of
Nothing -> do
exists <- doesFileExist (T.unpack location)
pure $ if exists
then Right (FileInstallLocation (T.unpack location))
else Left location
Just _ -> pure (Right (HttpInstallLocation location []))
-- | Install location for particular version.
renderVersionLocation :: ReleaseVersion -> Text -> Text
renderVersionLocation releaseVersion prefix =
T.concat
[ prefix
, "/"
, rawVersionToTextWithV (releaseVersionFromReleaseVersion releaseVersion)
, "/daml-sdk-"
, V.toText (unwrapSdkVersion (sdkVersionFromReleaseVersion releaseVersion))
, "-"
, osName
, ".tar.gz"
]
-- | An install locations is a pair of fully qualified HTTP[S] URL to an SDK release tarball and headers
-- required to access that URL. For example:
-- "https://github.com/digital-asset/daml/releases/download/v0.11.1/daml-sdk-0.11.1-macos.tar.gz"
data InstallLocation
= HttpInstallLocation
{ ilUrl :: Text
, ilHeaders :: RequestHeaders
}
| FileInstallLocation
{ ilPath :: FilePath
} deriving (Eq, Show)

View File

@ -165,58 +165,71 @@ testGetSdk = Tasty.testGroup "DA.Daml.Assistant.Env.getSdk"
[ Tasty.testCase "getSdk returns DAML_SDK_VERSION and DAML_SDK" $ do
withSystemTempDirectory "test-getSdk" $ \base -> do
let damlPath = DamlPath (base </> "daml")
cachePath = CachePath (base </> "cache")
projectPath = Nothing
expected1 = "10.10.10"
expected2 = base </> "sdk"
createDirectoryIfMissing True (base </> "cache")
writeFileUTF8 (unwrapCachePath cachePath </> "versions.txt") expected1
createDirectory expected2
(Just got1, Just (SdkPath got2)) <-
withEnv [ (sdkVersionEnvVar, Just expected1)
, (sdkPathEnvVar, Just expected2)
] (getSdk damlPath projectPath)
] (getSdk (mkUseCache cachePath damlPath) damlPath projectPath)
Tasty.assertEqual "sdk version" expected1 (versionToString got1)
Tasty.assertEqual "sdk path" expected2 got2
, Tasty.testCase "getSdk determines DAML_SDK from DAML_SDK_VERSION" $ do
withSystemTempDirectory "test-getSdk" $ \base -> do
let damlPath = DamlPath (base </> "daml")
cachePath = CachePath (base </> "cache")
projectPath = Nothing
expected1 = "0.12.5-version"
expected2 = base </> "daml" </> "sdk" </> expected1
createDirectoryIfMissing True (base </> "daml" </> "sdk")
createDirectoryIfMissing True (base </> "cache")
writeFileUTF8 (unwrapCachePath cachePath </> "versions.txt") expected1
createDirectory expected2
writeFileUTF8 (expected2 </> sdkConfigName) ("version: " <> expected1 <> "\n")
(Just got1, Just (SdkPath got2)) <-
withEnv [ (sdkVersionEnvVar, Just expected1)
, (sdkPathEnvVar, Nothing)
] (getSdk damlPath projectPath)
] (getSdk (mkUseCache cachePath damlPath) damlPath projectPath)
Tasty.assertEqual "sdk version" expected1 (versionToString got1)
Tasty.assertEqual "sdk path" expected2 got2
, Tasty.testCase "getSdk determines DAML_SDK_VERSION from DAML_SDK" $ do
withSystemTempDirectory "test-getSdk" $ \base -> do
let damlPath = DamlPath (base </> "daml")
cachePath = CachePath (base </> "cache")
projectPath = Nothing
expected1 = "0.3.4"
expected2 = base </> "sdk2"
createDirectoryIfMissing True (base </> "cache")
writeFileUTF8 (unwrapCachePath cachePath </> "versions.txt") expected1
createDirectory expected2
writeFileUTF8 (expected2 </> sdkConfigName) ("version: " <> expected1 <> "\n")
(Just got1, Just (SdkPath got2)) <-
withEnv [ (sdkVersionEnvVar, Nothing)
, (sdkPathEnvVar, Just expected2)
] (getSdk damlPath projectPath)
] (getSdk (mkUseCache cachePath damlPath) damlPath projectPath)
Tasty.assertEqual "sdk version" expected1 (versionToString got1)
Tasty.assertEqual "sdk path" expected2 got2
, Tasty.testCase "getSdk determines DAML_SDK and DAML_SDK_VERSION from project config" $ do
withSystemTempDirectory "test-getSdk" $ \base -> do
let damlPath = DamlPath (base </> "daml")
cachePath = CachePath (base </> "cache")
projectPath = Just $ ProjectPath (base </> "project")
expected1 = "10.10.2-version.af29bef"
expected2 = base </> "daml" </> "sdk" </> expected1
createDirectoryIfMissing True (base </> "daml" </> "sdk")
createDirectoryIfMissing True (base </> "cache")
writeFileUTF8 (unwrapCachePath cachePath </> "versions.txt") expected1
createDirectory (base </> "project")
writeFileUTF8 (base </> "project" </> projectConfigName)
("sdk-version: " <> expected1)
@ -224,19 +237,22 @@ testGetSdk = Tasty.testGroup "DA.Daml.Assistant.Env.getSdk"
(Just got1, Just (SdkPath got2)) <-
withEnv [ (sdkVersionEnvVar, Nothing)
, (sdkPathEnvVar, Nothing)
] (getSdk damlPath projectPath)
] (getSdk (mkUseCache cachePath damlPath) damlPath projectPath)
Tasty.assertEqual "sdk version" expected1 (versionToString got1)
Tasty.assertEqual "sdk path" expected2 got2
, Tasty.testCase "getSdk: DAML_SDK overrides project config version" $ do
withSystemTempDirectory "test-getSdk" $ \base -> do
let damlPath = DamlPath (base </> "daml")
cachePath = CachePath (base </> "cache")
projectPath = Just $ ProjectPath (base </> "project")
expected1 = "0.9.8-ham"
expected2 = base </> "sdk3"
projVers = "5.2.1"
createDirectoryIfMissing True (base </> "daml" </> "sdk" </> projVers)
createDirectoryIfMissing True (base </> "cache")
writeFileUTF8 (unwrapCachePath cachePath </> "versions.txt") expected1
createDirectory (base </> "project")
writeFileUTF8 (base </> "project" </> projectConfigName)
("project:\n sdk-version: " <> projVers)
@ -245,19 +261,22 @@ testGetSdk = Tasty.testGroup "DA.Daml.Assistant.Env.getSdk"
(Just got1, Just (SdkPath got2)) <-
withEnv [ (sdkVersionEnvVar, Nothing)
, (sdkPathEnvVar, Just expected2)
] (getSdk damlPath projectPath)
] (getSdk (mkUseCache cachePath damlPath) damlPath projectPath)
Tasty.assertEqual "sdk version" expected1 (versionToString got1)
Tasty.assertEqual "sdk path" expected2 got2
, Tasty.testCase "getSdk: DAML_SDK_VERSION overrides project config version" $ do
withSystemTempDirectory "test-getSdk" $ \base -> do
let damlPath = DamlPath (base </> "daml")
cachePath = CachePath (base </> "cache")
projectPath = Just $ ProjectPath (base </> "project")
expected1 = "0.0.0"
expected2 = base </> "daml" </> "sdk" </> expected1
projVers = "0.0.1"
createDirectoryIfMissing True (base </> "daml" </> "sdk" </> projVers)
createDirectoryIfMissing True (base </> "cache")
writeFileUTF8 (unwrapCachePath cachePath </> "versions.txt") expected1
createDirectory (base </> "project")
writeFileUTF8 (base </> "project" </> projectConfigName)
("project:\n sdk-version: " <> projVers)
@ -265,19 +284,21 @@ testGetSdk = Tasty.testGroup "DA.Daml.Assistant.Env.getSdk"
(Just got1, Just (SdkPath got2)) <-
withEnv [ (sdkVersionEnvVar, Just expected1)
, (sdkPathEnvVar, Nothing)
] (getSdk damlPath projectPath)
] (getSdk (mkUseCache cachePath damlPath) damlPath projectPath)
Tasty.assertEqual "sdk version" expected1 (versionToString got1)
Tasty.assertEqual "sdk path" expected2 got2
, Tasty.testCase "getSdk: Returns Nothings if .daml/sdk is missing." $ do
withSystemTempDirectory "test-getSdk" $ \base -> do
let damlPath = DamlPath (base </> "daml")
cachePath = CachePath (base </> "cache")
projPath = Nothing
createDirectoryIfMissing True (base </> "daml")
createDirectoryIfMissing True (base </> "cache")
(Nothing, Nothing) <- withEnv
[ (sdkVersionEnvVar, Nothing)
, (sdkPathEnvVar, Nothing)
] (getSdk damlPath projPath)
] (getSdk (mkUseCache cachePath damlPath) damlPath projPath)
pure ()
]
@ -285,10 +306,13 @@ testGetDispatchEnv :: Tasty.TestTree
testGetDispatchEnv = Tasty.testGroup "DA.Daml.Assistant.Env.getDispatchEnv"
[ Tasty.testCase "getDispatchEnv should be idempotent" $ do
withSystemTempDirectory "test-getDispatchEnv" $ \base -> do
version <- requiredE "expected this to be valid version" $ parseVersion "1.0.1"
version <- requiredE "testGetDispatchEnv: expected a valid version" $ unsafeParseOldReleaseVersion "1.0.1"
let cachePath = CachePath (base </> ".cache")
createDirectoryIfMissing True (unwrapCachePath cachePath)
writeFileUTF8 (unwrapCachePath cachePath </> "versions.txt") "1.0.1"
let denv = Env
{ envDamlPath = DamlPath (base </> ".daml")
, envCachePath = CachePath (base </> ".daml")
, envCachePath = cachePath
, envDamlAssistantPath = DamlAssistantPath (base </> ".daml" </> "bin" </> "strange-daml")
, envDamlAssistantSdkVersion = Just $ DamlAssistantSdkVersion version
, envSdkVersion = Just version
@ -302,10 +326,13 @@ testGetDispatchEnv = Tasty.testGroup "DA.Daml.Assistant.Env.getDispatchEnv"
, Tasty.testCase "getDispatchEnv should override getDamlEnv" $ do
withSystemTempDirectory "test-getDispatchEnv" $ \base -> do
version <- requiredE "expected this to be valid version" $ parseVersion "1.0.1"
version <- requiredE "testGetDispatchEnv: expected a valid version" $ unsafeParseOldReleaseVersion "1.0.1"
let cachePath = CachePath (base </> ".cache")
createDirectoryIfMissing True (unwrapCachePath cachePath)
writeFileUTF8 (unwrapCachePath cachePath </> "versions.txt") "1.0.1"
let denv1 = Env
{ envDamlPath = DamlPath (base </> ".daml")
, envCachePath = CachePath (base </> ".daml")
, envCachePath = cachePath
, envDamlAssistantPath = DamlAssistantPath (base </> ".daml" </> "bin" </> "strange-daml")
, envDamlAssistantSdkVersion = Just $ DamlAssistantSdkVersion version
, envSdkVersion = Just version
@ -385,6 +412,7 @@ testInstall = Tasty.testGroup "DA.Daml.Assistant.Install"
, iSetPath = SetPath No
, iBashCompletions = BashCompletions No
, iZshCompletions = ZshCompletions No
, iAllowInstallNonRelease = AllowInstallNonRelease False
}
setCurrentDirectory base
@ -421,6 +449,7 @@ testInstallUnix = Tasty.testGroup "unix-specific tests"
, iSetPath = SetPath No
, iBashCompletions = BashCompletions No
, iZshCompletions = ZshCompletions No
, iAllowInstallNonRelease = AllowInstallNonRelease False
}
setCurrentDirectory base
@ -452,6 +481,7 @@ testInstallUnix = Tasty.testGroup "unix-specific tests"
, iSetPath = SetPath No
, iBashCompletions = BashCompletions No
, iZshCompletions = ZshCompletions No
, iAllowInstallNonRelease = AllowInstallNonRelease False
}
setCurrentDirectory base
@ -483,6 +513,7 @@ testInstallUnix = Tasty.testGroup "unix-specific tests"
, iSetPath = SetPath No
, iBashCompletions = BashCompletions No
, iZshCompletions = ZshCompletions No
, iAllowInstallNonRelease = AllowInstallNonRelease False
}
setCurrentDirectory base
@ -514,6 +545,7 @@ testInstallUnix = Tasty.testGroup "unix-specific tests"
, iSetPath = SetPath No
, iBashCompletions = BashCompletions No
, iZshCompletions = ZshCompletions No
, iAllowInstallNonRelease = AllowInstallNonRelease False
}
setCurrentDirectory base

View File

@ -31,6 +31,7 @@ da_haskell_binary(
"//compiler/daml-lf-ast",
"//compiler/daml-lf-proto",
"//compiler/daml-lf-reader",
"//daml-assistant:daml-lib",
"//daml-assistant:daml-project-config",
"//libs-haskell/bazel-runfiles",
"//libs-haskell/da-hs-base",

View File

@ -40,6 +40,8 @@ import System.FilePath hiding ((<.>))
import DA.Daml.Project.Consts
import DA.Daml.Project.Types
import qualified DA.Daml.Project.Types as DATypes
import qualified DA.Daml.Assistant.Version as DAVersion
import qualified DA.Daml.Assistant.Env as DAEnv
-- Version of the "@mojotech/json-type-validation" library we're using.
jtvVersion :: T.Text
@ -124,10 +126,12 @@ main = do
setRunfilesEnv
withProgName "daml codegen js" $ do
opts@Options{..} <- customExecParser (prefs showHelpOnError) optionsParserInfo
sdkVersionOrErr <- DATypes.parseVersion . T.pack . fromMaybe "0.0.0" <$> getSdkVersionMaybe
sdkVersion <- case sdkVersionOrErr of
unresolvedVersionOrErr <- DATypes.parseVersion . T.pack . fromMaybe "0.0.0" <$> getSdkVersionMaybe
releaseVersion <- case unresolvedVersionOrErr of
Left _ -> fail "Invalid SDK version"
Right v -> pure v
Right v -> do
useCache <- DAEnv.mkUseCache <$> DAEnv.getCachePath <*> DAEnv.getDamlPath
DAVersion.resolveReleaseVersion useCache v
pkgs <- readPackages optInputDars
case mergePackageMap pkgs of
Left err -> fail . T.unpack $ err
@ -154,7 +158,7 @@ data Daml2jsParams = Daml2jsParams
, pkgId :: PackageId
, pkg :: Package
, pkgName :: T.Text
, sdkVersion :: SdkVersion
, releaseVersion :: ReleaseVersion
}
-- Write the files for a single package.
@ -179,7 +183,7 @@ daml2js Daml2jsParams {..} = do
let dependencies = Set.toList (Set.unions dependenciesSets)
-- Now write package metadata.
writeTsConfig packageDir
writePackageJson packageDir sdkVersion scope dependencies
writePackageJson packageDir releaseVersion scope dependencies
where
-- Write the .ts file for a single Daml-LF module.
writeModuleTs :: FilePath -> Scope -> Module -> IO (Maybe ModuleName, Set.Set Dependency)
@ -1021,24 +1025,24 @@ packageJsonDependencies (Scope scope) dependencies = object $
] ++
[ Aeson.fromText (scope <> "/" <> pkgName) .= ("file:../" <> pkgName) | Dependency pkgName <- dependencies ]
packageJsonPeerDependencies:: SdkVersion -> Value
packageJsonPeerDependencies sdkVersion = object
[ "@daml/types" .= versionToText sdkVersion
, "@daml/ledger" .= versionToText sdkVersion
packageJsonPeerDependencies:: ReleaseVersion -> Value
packageJsonPeerDependencies releaseVersion = object
[ "@daml/types" .= sdkVersionToText (sdkVersionFromReleaseVersion releaseVersion)
, "@daml/ledger" .= sdkVersionToText (sdkVersionFromReleaseVersion releaseVersion)
]
writePackageJson :: FilePath -> SdkVersion -> Scope -> [Dependency] -> IO ()
writePackageJson packageDir sdkVersion scope dependencies =
writePackageJson :: FilePath -> ReleaseVersion -> Scope -> [Dependency] -> IO ()
writePackageJson packageDir releaseVersion scope dependencies =
let packageJson = object
[ "private" .= True
, "name" .= (unScope scope <> "/" <> T.pack (takeFileName packageDir))
, "version" .= versionToText sdkVersion
, "version" .= versionToText releaseVersion
, "license" .= ("UNLICENSED" :: T.Text)
, "main" .= ("lib/index.js" :: T.Text)
, "types" .= ("lib/index.d.ts" :: T.Text)
, "description" .= ("Generated by `daml codegen js` from SDK " <> versionToText sdkVersion)
, "description" .= ("Generated by `daml codegen js` from SDK " <> versionToText releaseVersion)
, "dependencies" .= packageJsonDependencies scope dependencies
, "peer-dependencies" .= packageJsonPeerDependencies sdkVersion
, "peer-dependencies" .= packageJsonPeerDependencies releaseVersion
]
in
BSL.writeFile (packageDir </> "package.json") (encodePretty packageJson)