From 3279870fcaac111df5f3a9fd03c10a45c063758c Mon Sep 17 00:00:00 2001 From: Patrick Balestra Date: Sat, 18 May 2019 21:07:09 +0200 Subject: [PATCH] Add Custom Script Engine (#185) --- .gitignore | 1 + .travis.yml | 8 +- README.md | 38 +- Rome.cabal | 3 + .../current-framework-engine-yml.bats | 274 ++++++++ .../current-framework-named-engine-yml.bats | 223 ++++++ ....bats => current-framework-named-yml.bats} | 0 ...k-yaml.bats => current-framework-yml.bats} | 0 .../dynamic-frameworks-engine-yml.bats | 282 ++++++++ integration-tests/engine.sh | 39 ++ .../static-frameworks-engine-yml.bats | 195 ++++++ src/Caches/Local/Uploading.hs | 2 +- src/Caches/S3/Downloading.hs | 2 +- src/Caches/S3/Uploading.hs | 2 +- src/Data/Romefile.hs | 16 +- src/Engine/Downloading.hs | 263 ++++++++ src/Engine/Probing.hs | 71 ++ src/Engine/Uploading.hs | 135 ++++ src/Lib.hs | 634 ++++++++++++++++-- src/Utils.hs | 2 +- 20 files changed, 2133 insertions(+), 57 deletions(-) create mode 100644 integration-tests/current-framework-engine-yml.bats create mode 100644 integration-tests/current-framework-named-engine-yml.bats rename integration-tests/{current-framework-named-yaml.bats => current-framework-named-yml.bats} (100%) rename integration-tests/{current-framework-yaml.bats => current-framework-yml.bats} (100%) create mode 100644 integration-tests/dynamic-frameworks-engine-yml.bats create mode 100755 integration-tests/engine.sh create mode 100644 integration-tests/static-frameworks-engine-yml.bats create mode 100644 src/Engine/Downloading.hs create mode 100644 src/Engine/Probing.hs create mode 100644 src/Engine/Uploading.hs diff --git a/.gitignore b/.gitignore index 93b996f..b3d841a 100644 --- a/.gitignore +++ b/.gitignore @@ -15,6 +15,7 @@ cabal.sandbox.config *.aux *.hp *.eventlog +*.orig .DS_Store .stack-work/ .vscode/ diff --git a/.travis.yml b/.travis.yml index f13bf69..f8f554e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -46,6 +46,7 @@ jobs: - stack $ARGS install - travis_wait 60 bats integration-tests/dynamic-frameworks-ini.bats - travis_wait 60 bats integration-tests/dynamic-frameworks-yml.bats + - travis_wait 60 bats integration-tests/dynamic-frameworks-engine-yml.bats - stage: "Build" name: "Build Rome & Test Current Frameworks" before_install: @@ -80,8 +81,10 @@ jobs: - stack $ARGS build -j 2 - stack $ARGS sdist - stack $ARGS install - - travis_wait 60 bats integration-tests/current-framework-yaml.bats - - travis_wait 60 bats integration-tests/current-framework-named-yaml.bats + - travis_wait 60 bats integration-tests/current-framework-yml.bats + - travis_wait 60 bats integration-tests/current-framework-engine-yml.bats + - travis_wait 60 bats integration-tests/current-framework-named-yml.bats + - travis_wait 60 bats integration-tests/current-framework-named-engine-yml.bats - stage: "Build" name: "Build Rome & Test Static Frameworks" before_install: @@ -118,6 +121,7 @@ jobs: - stack $ARGS install - travis_wait 60 bats integration-tests/static-frameworks-ini.bats - travis_wait 60 bats integration-tests/static-frameworks-yml.bats + - travis_wait 60 bats integration-tests/static-frameworks-engine-yml.bats env: - ARGS="--resolver=lts-13.10" diff --git a/README.md b/README.md index 8d1f4c1..a95c842 100644 --- a/README.md +++ b/README.md @@ -9,6 +9,7 @@ Rome is a tool that allows developers on Apple platforms to use: - [Ceph](https://ceph.com/ceph-storage/object-storage/) - other S3 compatible object stores - or/and a local folder +- [your own custom engine](#custom-engine) as a shared cache for frameworks built with [Carthage](https://github.com/Carthage/Carthage). @@ -34,6 +35,7 @@ Trusted by: - [Setting up AWS credentials](#setting-up-aws-credentials) - [Selecting the AWS Region](#selecting-the-aws-region) - [Setting up endpoint override for Minio, Ceph, or other S3 compatible stores](#setting-up-endpoint-override) + - [Custom Engine](#customengine) - [Romefile](#romefile) - [Cache](#cache) - [RepositoryMap](#repositorymap) @@ -257,6 +259,25 @@ Default port for `http` endpoints is __9000__ if the port is left unspecified. Alternatively the endpoint can also be specified by setting an `AWS_ENDPOINT` environment variable. +### Custom Engine +You can write your own script that Rome will use as engine to execute upload/download/list commands. You start by specifying the path to a script or executable in your [Romefile](#romefile) as shown in the example [structure](#structure). +Rome will invoke the specified script or executable with three commands and different parameters based on the action to perform: + +- `./script.sh upload local-path remote-path` +- `./script.sh download remote-path local-path` +- `./script.sh list remote-path` + +For example, if your [Romefile](#romefile) specifies `engine: script.sh`, Rome will execute the following command when uploading/downloading/listing a framework: +```sh +./script.sh upload Alamofire/iOS/Alamofire.framework-4.8.2.zip Alamofire/iOS/Alamofire.framework-4.8.2.zip +./script.sh download Alamofire/iOS/Alamofire.framework-4.8.2.zip Alamofire/iOS/Alamofire.framework-4.8.2.zip +./script.sh list Alamofire/iOS/Alamofire.framework-4.8.2.zip +``` + +The script should take the given `remote-path`, carry out its logic to retrieve the artifact and place it at `local-path`. Please refer to the [cache structure](#cachestructure) definition for more information on the cache is constructed. + +For an example of a custom engine, take a look at [engine.sh](https://github.com/blender/Rome/blob/master/integration-tests/engine.sh) which is used in the integration tests to simply copy artifacts in a different directory. Infinite uses cases are opened by using a custom engine, such as uploading artifacts to any non-compatible S3 storage system. + ### Romefile #### About the format @@ -299,10 +320,11 @@ A Romefile looks like this: ```yaml cache: # required - local: ~/Library/Caches/Rome # optional - # at least one between `local` and `s3Bucket` is required - s3Bucket: ios-dev-bucket # optional - # at least one between `local` and `s3Bucket` is required + # at least one of the following is required: + local: ~/Library/Caches/Rome # optional and can be combined with either a `s3Bucket` or `engine` + s3Bucket: ios-dev-bucket # optional and can be combined with `local` + engine: script.sh # optional and can be combined with `local` + repositoryMap: # optional - better-dog-names: # entry that does not follow # the "Organization/FrameworkName" convention. @@ -326,13 +348,16 @@ currentMap: The cache __must__ contain __at least one__ between: - the name of the S3 Bucket to upload/download to/from. The key `s3Bucket` is __optional__. - the path to local directory to use as an additional cache. The key `local` is __optional__. +- the path to a custom engine to use as an additional cache. The key `engine` is __optional__. ```yaml cache: # required local: ~/Library/Caches/Rome # optional - # at least one between `local` and `s3Bucket` is required + # at least one between `local`, `s3bucket` and `engine` is required s3Bucket: ios-dev-bucket # optional - # at least one between `local` and `s3Bucket` is required + # at least one between `local`, `s3bucket` and `engine` is required + engine: script.sh # optional + # at least one between `local`, `s3bucket` and `engine` is required ``` This is already a viable Romefile. @@ -491,7 +516,6 @@ The above means that `t1` is only available for `iOS` and `Mac`. The `--platforms` command line options can be used to futher limit the Rome command to a specific subset of the supported platfroms. - ### Cache Structure The following describes the structure of the cache that Rome creates and manages. diff --git a/Rome.cabal b/Rome.cabal index 55ed0bb..0a1c58d 100644 --- a/Rome.cabal +++ b/Rome.cabal @@ -36,6 +36,9 @@ library , Caches.Local.Downloading , Caches.Common , Network.AWS.Utils + , Engine.Probing + , Engine.Uploading + , Engine.Downloading build-depends: base >= 4.7 && < 5 , amazonka >= 1.6.1 diff --git a/integration-tests/current-framework-engine-yml.bats b/integration-tests/current-framework-engine-yml.bats new file mode 100644 index 0000000..3003808 --- /dev/null +++ b/integration-tests/current-framework-engine-yml.bats @@ -0,0 +1,274 @@ +#!/usr/bin/env bats + +setup() { + + export FRAMEWORK_VERSION=4.8.2 + + rm -rf $BATS_TMPDIR/Rome-Tests + + mkdir -p $BATS_TMPDIR/Rome-Tests + + cp integration-tests/engine.sh $BATS_TMPDIR/Rome-Tests/ + + cd $BATS_TMPDIR/Rome-Tests + + git clone https://github.com/Alamofire/Alamofire.git + cd Alamofire + git checkout ${FRAMEWORK_VERSION} + + if [ "$BATS_TEST_NUMBER" -eq 1 ]; then + + carthage build --no-use-binaries --no-skip-current --cache-builds + + rm -rf ../../_Carthage_build_bkp + cp -R Carthage/Build/ ../../_Carthage_build_bkp + + else + mkdir -p Carthage/Build + cp -R ../../_Carthage_build_bkp/ Carthage/Build + fi + + cat >> Romefile << EOF +cache: + local: rome-local-cache + engine: ../engine.sh +ignoreMap: + - Alamofire: + - name: Alamofire + platforms: [Mac] +currentMap: + - Alamofire: + - name: Alamofire +EOF + + IOS_DWARFDUMP_OUT=($(dwarfdump -u Carthage/Build/iOS/Alamofire.framework/Alamofire)) + TVOS_DWARFDUMP_OUT=($(dwarfdump -u Carthage/Build/tvOS/Alamofire.framework/Alamofire)) + WATCHOS_DWARFDUMP_OUT=($(dwarfdump -u Carthage/Build/watchOS/Alamofire.framework/Alamofire)) + + export IOS_ARMV7_DWARF_UUID=${IOS_DWARFDUMP_OUT[9]} + export IOS_ARM64_DWARF_UUID=${IOS_DWARFDUMP_OUT[13]} + export TVOS_ARM64_DWARF_UUID=${TVOS_DWARFDUMP_OUT[5]} + export WATCHOS_ARMV7K_DWARF_UUID=${WATCHOS_DWARFDUMP_OUT[5]} + + echo "# BATS_TMPDIR: ${BATS_TMPDIR}" >&3 + +} + +teardown() { + cd $BATS_TEST_DIRNAME +} + +@test "rome uploads all artifacts for current framework with engine (dynamic, yaml)" { + + run rome upload --concurrently --cache-prefix travis --no-skip-current + + [ "$status" -eq 0 ] + + # Version file + [ -f "server-cache/travis/Alamofire/.Alamofire.version-${FRAMEWORK_VERSION}" ] + [ -f "rome-local-cache/travis/Alamofire/.Alamofire.version-${FRAMEWORK_VERSION}" ] + + # macOS - No bitecode, No bcsymbolmap + [ ! -f "server-cache/travis/Alamofire/Mac/Alamofire.framework-${FRAMEWORK_VERSION}.zip" ] + [ ! -f "server-cache/travis/Alamofire/Mac/Alamofire.framework.dSYM-${FRAMEWORK_VERSION}.zip" ] + [ ! -f "rome-local-cache/travis/Alamofire/Mac/Alamofire.framework-${FRAMEWORK_VERSION}.zip" ] + [ ! -f "rome-local-cache/travis/Alamofire/Mac/Alamofire.framework.dSYM-${FRAMEWORK_VERSION}.zip" ] + + # iOS + [ -f "server-cache/travis/Alamofire/iOS/Alamofire.framework-${FRAMEWORK_VERSION}.zip" ] + [ -f "server-cache/travis/Alamofire/iOS/Alamofire.framework.dSYM-${FRAMEWORK_VERSION}.zip" ] + [ -f "server-cache/travis/Alamofire/iOS/${IOS_ARMV7_DWARF_UUID}.bcsymbolmap-${FRAMEWORK_VERSION}.zip" ] + [ -f "server-cache/travis/Alamofire/iOS/${IOS_ARM64_DWARF_UUID}.bcsymbolmap-${FRAMEWORK_VERSION}.zip" ] + [ -f "rome-local-cache/travis/Alamofire/iOS/Alamofire.framework-${FRAMEWORK_VERSION}.zip" ] + [ -f "rome-local-cache/travis/Alamofire/iOS/Alamofire.framework.dSYM-${FRAMEWORK_VERSION}.zip" ] + [ -f "rome-local-cache/travis/Alamofire/iOS/${IOS_ARMV7_DWARF_UUID}.bcsymbolmap-${FRAMEWORK_VERSION}.zip" ] + [ -f "rome-local-cache/travis/Alamofire/iOS/${IOS_ARM64_DWARF_UUID}.bcsymbolmap-${FRAMEWORK_VERSION}.zip" ] + + # tvOS + [ -f "server-cache/travis/Alamofire/tvOS/Alamofire.framework-${FRAMEWORK_VERSION}.zip" ] + [ -f "server-cache/travis/Alamofire/tvOS/Alamofire.framework.dSYM-${FRAMEWORK_VERSION}.zip" ] + [ -f "server-cache/travis/Alamofire/tvOS/${TVOS_ARM64_DWARF_UUID}.bcsymbolmap-${FRAMEWORK_VERSION}.zip" ] + [ -f "rome-local-cache/travis/Alamofire/tvOS/Alamofire.framework-${FRAMEWORK_VERSION}.zip" ] + [ -f "rome-local-cache/travis/Alamofire/tvOS/Alamofire.framework.dSYM-${FRAMEWORK_VERSION}.zip" ] + [ -f "rome-local-cache/travis/Alamofire/tvOS/${TVOS_ARM64_DWARF_UUID}.bcsymbolmap-${FRAMEWORK_VERSION}.zip" ] + + # watchOS + [ -f "server-cache/travis/Alamofire/watchOS/Alamofire.framework-${FRAMEWORK_VERSION}.zip" ] + [ -f "server-cache/travis/Alamofire/watchOS/Alamofire.framework.dSYM-${FRAMEWORK_VERSION}.zip" ] + [ -f "server-cache/travis/Alamofire/watchOS/${WATCHOS_ARMV7K_DWARF_UUID}.bcsymbolmap-${FRAMEWORK_VERSION}.zip" ] + [ -f "rome-local-cache/travis/Alamofire/watchOS/Alamofire.framework-${FRAMEWORK_VERSION}.zip" ] + [ -f "rome-local-cache/travis/Alamofire/watchOS/Alamofire.framework.dSYM-${FRAMEWORK_VERSION}.zip" ] + [ -f "rome-local-cache/travis/Alamofire/watchOS/${WATCHOS_ARMV7K_DWARF_UUID}.bcsymbolmap-${FRAMEWORK_VERSION}.zip" ] + + # save the server cache for later + rm -rf ../../_server-cache_bkp + cp -R server-cache/ ../../_server-cache_bkp + + # save the local cache for later + rm -rf ../../_rome-local-cache_bkp + cp -R rome-local-cache/ ../../_rome-local-cache_bkp +} + +@test "rome downloads all artifacts for current framework with engine skipping local cache (dynamic, yaml)" { + + # restore server cache + if [ -d "../../_server-cache_bkp" ]; then + echo "# Server cache restored" >&3 + cp -R ../../_server-cache_bkp server-cache/ + fi + + # restore local cache (even though it will be skipped, we want it to be there to simulate a real scenario) + if [ -d "../../_rome-local-cache_bkp" ]; then + echo "# Local cache restored" >&3 + cp -R ../../_rome-local-cache_bkp rome-local-cache/ + fi + + rm -rf Carthage/Build + run rome download --concurrently --cache-prefix travis --skip-local-cache --no-skip-current + + [ "$status" -eq 0 ] + + # Version file + [ -f "Carthage/Build/.Alamofire.version" ] + + # macOS - No bitcode, No bcsymbolmap + [ ! -d "Carthage/Build/Mac/Alamofire.framework" ] + [ ! -d "Carthage/Build/Mac/Alamofire.framework.dSYM" ] + + # iOS + [ -d "Carthage/Build/iOS/Alamofire.framework" ] + [ -d "Carthage/Build/iOS/Alamofire.framework.dSYM" ] + [ -f "Carthage/Build/iOS/${IOS_ARMV7_DWARF_UUID}.bcsymbolmap" ] + [ -f "Carthage/Build/iOS/${IOS_ARM64_DWARF_UUID}.bcsymbolmap" ] + + # tvOS + [ -d "Carthage/Build/tvOS/Alamofire.framework" ] + [ -d "Carthage/Build/tvOS/Alamofire.framework.dSYM" ] + [ -f "Carthage/Build/tvOS/${TVOS_ARM64_DWARF_UUID}.bcsymbolmap" ] + + # watchOS + [ -d "Carthage/Build/watchOS/Alamofire.framework" ] + [ -d "Carthage/Build/watchOS/Alamofire.framework.dSYM" ] + [ -f "Carthage/Build/watchOS/${WATCHOS_ARMV7K_DWARF_UUID}.bcsymbolmap" ] +} + +@test "rome downloads all artifacts for current framework with engine from the local cache (dynamic, yaml)" { + + # restore local cache + if [ -d "../../_rome-local-cache_bkp" ]; then + echo "# Local cache restored" >&3 + cp -R ../../_rome-local-cache_bkp rome-local-cache/ + fi + + rm -rf Carthage/Build + run rome download --concurrently --cache-prefix travis --no-skip-current + + [ "$status" -eq 0 ] + + # Version file + [ -f "Carthage/Build/.Alamofire.version" ] + + # macOS - No bitecode, No bcsymbolmap + [ ! -d "Carthage/Build/Mac/Alamofire.framework" ] + [ ! -d "Carthage/Build/Mac/Alamofire.framework.dSYM" ] + + # iOS + [ -d "Carthage/Build/iOS/Alamofire.framework" ] + [ -d "Carthage/Build/iOS/Alamofire.framework.dSYM" ] + [ -f "Carthage/Build/iOS/${IOS_ARMV7_DWARF_UUID}.bcsymbolmap" ] + [ -f "Carthage/Build/iOS/${IOS_ARM64_DWARF_UUID}.bcsymbolmap" ] + + # tvOS + [ -d "Carthage/Build/tvOS/Alamofire.framework" ] + [ -d "Carthage/Build/tvOS/Alamofire.framework.dSYM" ] + [ -f "Carthage/Build/tvOS/${TVOS_ARM64_DWARF_UUID}.bcsymbolmap" ] + + # watchOS + [ -d "Carthage/Build/watchOS/Alamofire.framework" ] + [ -d "Carthage/Build/watchOS/Alamofire.framework.dSYM" ] + [ -f "Carthage/Build/watchOS/${WATCHOS_ARMV7K_DWARF_UUID}.bcsymbolmap" ] +} + +@test "rome uploads named artifacts for current framework with engine (dynamic, yaml)" { + + run rome upload --concurrently --cache-prefix travis --no-skip-current Alamofire + + [ "$status" -eq 0 ] + + # Version file + [ -f "server-cache/travis/Alamofire/.Alamofire.version-${FRAMEWORK_VERSION}" ] + [ -f "rome-local-cache/travis/Alamofire/.Alamofire.version-${FRAMEWORK_VERSION}" ] + + # macOS - No bitecode, No bcsymbolmap + [ ! -f "server-cache/travis/Alamofire/Mac/Alamofire.framework-${FRAMEWORK_VERSION}.zip" ] + [ ! -f "server-cache/travis/Alamofire/Mac/Alamofire.framework.dSYM-${FRAMEWORK_VERSION}.zip" ] + [ ! -f "rome-local-cache/travis/Alamofire/Mac/Alamofire.framework-${FRAMEWORK_VERSION}.zip" ] + [ ! -f "rome-local-cache/travis/Alamofire/Mac/Alamofire.framework.dSYM-${FRAMEWORK_VERSION}.zip" ] + + # iOS + [ -f "server-cache/travis/Alamofire/iOS/Alamofire.framework-${FRAMEWORK_VERSION}.zip" ] + [ -f "server-cache/travis/Alamofire/iOS/Alamofire.framework.dSYM-${FRAMEWORK_VERSION}.zip" ] + [ -f "server-cache/travis/Alamofire/iOS/${IOS_ARMV7_DWARF_UUID}.bcsymbolmap-${FRAMEWORK_VERSION}.zip" ] + [ -f "server-cache/travis/Alamofire/iOS/${IOS_ARM64_DWARF_UUID}.bcsymbolmap-${FRAMEWORK_VERSION}.zip" ] + [ -f "rome-local-cache/travis/Alamofire/iOS/Alamofire.framework-${FRAMEWORK_VERSION}.zip" ] + [ -f "rome-local-cache/travis/Alamofire/iOS/Alamofire.framework.dSYM-${FRAMEWORK_VERSION}.zip" ] + [ -f "rome-local-cache/travis/Alamofire/iOS/${IOS_ARMV7_DWARF_UUID}.bcsymbolmap-${FRAMEWORK_VERSION}.zip" ] + [ -f "rome-local-cache/travis/Alamofire/iOS/${IOS_ARM64_DWARF_UUID}.bcsymbolmap-${FRAMEWORK_VERSION}.zip" ] + + # tvOS + [ -f "server-cache/travis/Alamofire/tvOS/Alamofire.framework-${FRAMEWORK_VERSION}.zip" ] + [ -f "server-cache/travis/Alamofire/tvOS/Alamofire.framework.dSYM-${FRAMEWORK_VERSION}.zip" ] + [ -f "server-cache/travis/Alamofire/tvOS/${TVOS_ARM64_DWARF_UUID}.bcsymbolmap-${FRAMEWORK_VERSION}.zip" ] + [ -f "rome-local-cache/travis/Alamofire/tvOS/Alamofire.framework-${FRAMEWORK_VERSION}.zip" ] + [ -f "rome-local-cache/travis/Alamofire/tvOS/Alamofire.framework.dSYM-${FRAMEWORK_VERSION}.zip" ] + [ -f "rome-local-cache/travis/Alamofire/tvOS/${TVOS_ARM64_DWARF_UUID}.bcsymbolmap-${FRAMEWORK_VERSION}.zip" ] + + # watchOS + [ -f "server-cache/travis/Alamofire/watchOS/Alamofire.framework-${FRAMEWORK_VERSION}.zip" ] + [ -f "server-cache/travis/Alamofire/watchOS/Alamofire.framework.dSYM-${FRAMEWORK_VERSION}.zip" ] + [ -f "server-cache/travis/Alamofire/watchOS/${WATCHOS_ARMV7K_DWARF_UUID}.bcsymbolmap-${FRAMEWORK_VERSION}.zip" ] + [ -f "rome-local-cache/travis/Alamofire/watchOS/Alamofire.framework-${FRAMEWORK_VERSION}.zip" ] + [ -f "rome-local-cache/travis/Alamofire/watchOS/Alamofire.framework.dSYM-${FRAMEWORK_VERSION}.zip" ] + [ -f "rome-local-cache/travis/Alamofire/watchOS/${WATCHOS_ARMV7K_DWARF_UUID}.bcsymbolmap-${FRAMEWORK_VERSION}.zip" ] + + # save the local cache for later + rm -rf ../../_rome-local-cache_bkp + cp -R rome-local-cache/ ../../_rome-local-cache_bkp +} + +@test "rome downloads named artifacts for current framework with engine skipping local cache (dynamic, yaml)" { + + # restore server cache + if [ -d "../../_server-cache_bkp" ]; then + echo "# Server cache restored" >&3 + cp -R ../../_server-cache_bkp server-cache/ + fi + + rm -rf Carthage/Build + run rome download --concurrently --cache-prefix travis --skip-local-cache --no-skip-current Alamofire + + [ "$status" -eq 0 ] + + # Version file + [ -f "Carthage/Build/.Alamofire.version" ] + + # macOS - No bitcode, No bcsymbolmap + [ ! -d "Carthage/Build/Mac/Alamofire.framework" ] + [ ! -d "Carthage/Build/Mac/Alamofire.framework.dSYM" ] + + # iOS + [ -d "Carthage/Build/iOS/Alamofire.framework" ] + [ -d "Carthage/Build/iOS/Alamofire.framework.dSYM" ] + [ -f "Carthage/Build/iOS/${IOS_ARMV7_DWARF_UUID}.bcsymbolmap" ] + [ -f "Carthage/Build/iOS/${IOS_ARM64_DWARF_UUID}.bcsymbolmap" ] + + # tvOS + [ -d "Carthage/Build/tvOS/Alamofire.framework" ] + [ -d "Carthage/Build/tvOS/Alamofire.framework.dSYM" ] + [ -f "Carthage/Build/tvOS/${TVOS_ARM64_DWARF_UUID}.bcsymbolmap" ] + + # watchOS + [ -d "Carthage/Build/watchOS/Alamofire.framework" ] + [ -d "Carthage/Build/watchOS/Alamofire.framework.dSYM" ] + [ -f "Carthage/Build/watchOS/${WATCHOS_ARMV7K_DWARF_UUID}.bcsymbolmap" ] +} \ No newline at end of file diff --git a/integration-tests/current-framework-named-engine-yml.bats b/integration-tests/current-framework-named-engine-yml.bats new file mode 100644 index 0000000..833fcc9 --- /dev/null +++ b/integration-tests/current-framework-named-engine-yml.bats @@ -0,0 +1,223 @@ +#!/usr/bin/env bats + +setup() { + + export FRAMEWORK_VERSION=0.4.0 + export FRAMEWORK_REPO_NAME=swift-tagged + export FRAMEWORK_ARTIFACT_NAME=Tagged + + rm -rf $BATS_TMPDIR/Rome-Tests + + mkdir -p $BATS_TMPDIR/Rome-Tests + + cp integration-tests/engine.sh $BATS_TMPDIR/Rome-Tests/ + + cd $BATS_TMPDIR/Rome-Tests + + git clone https://github.com/pointfreeco/swift-tagged.git + cd swift-tagged + git checkout ${FRAMEWORK_VERSION} + + if [ "$BATS_TEST_NUMBER" -eq 1 ]; then + + carthage build --no-use-binaries --no-skip-current --cache-builds + + rm -rf ../../_Carthage_build_bkp + cp -R Carthage/Build/ ../../_Carthage_build_bkp + + else + mkdir -p Carthage/Build + cp -R ../../_Carthage_build_bkp/ Carthage/Build + fi + + cat >> Romefile << EOF +cache: + local: rome-local-cache + engine: ../engine.sh +ignoreMap: + - swift-tagged: + - name: Tagged + platforms: [Mac] +currentMap: + - swift-tagged: + - name: Tagged +EOF + + IOS_DWARFDUMP_OUT=($(dwarfdump -u Carthage/Build/iOS/${FRAMEWORK_ARTIFACT_NAME}.framework/${FRAMEWORK_ARTIFACT_NAME})) + TVOS_DWARFDUMP_OUT=($(dwarfdump -u Carthage/Build/tvOS/${FRAMEWORK_ARTIFACT_NAME}.framework/${FRAMEWORK_ARTIFACT_NAME})) + WATCHOS_DWARFDUMP_OUT=($(dwarfdump -u Carthage/Build/watchOS/${FRAMEWORK_ARTIFACT_NAME}.framework/${FRAMEWORK_ARTIFACT_NAME})) + + export IOS_ARMV7_DWARF_UUID=${IOS_DWARFDUMP_OUT[9]} + export IOS_ARM64_DWARF_UUID=${IOS_DWARFDUMP_OUT[13]} + export TVOS_ARM64_DWARF_UUID=${TVOS_DWARFDUMP_OUT[5]} + export WATCHOS_ARMV7K_DWARF_UUID=${WATCHOS_DWARFDUMP_OUT[5]} + + echo "# BATS_TMPDIR: ${BATS_TMPDIR}" >&3 + +} + +teardown() { + cd $BATS_TEST_DIRNAME +} + +@test "rome uploads all named artifacts for current framework with engine (dynamic, yaml)" { + + run rome upload --concurrently --cache-prefix travis ${FRAMEWORK_REPO_NAME} + + [ "$status" -eq 0 ] + + # Version file + [ -f "server-cache/travis/${FRAMEWORK_REPO_NAME}/.${FRAMEWORK_REPO_NAME}.version-${FRAMEWORK_VERSION}" ] + [ -f "rome-local-cache/travis/${FRAMEWORK_REPO_NAME}/.${FRAMEWORK_REPO_NAME}.version-${FRAMEWORK_VERSION}" ] + + # macOS - No bitecode, No bcsymbolmap + [ ! -f "server-cache/travis/${FRAMEWORK_REPO_NAME}/Mac/${FRAMEWORK_ARTIFACT_NAME}.framework-${FRAMEWORK_VERSION}.zip" ] + [ ! -f "server-cache/travis/${FRAMEWORK_REPO_NAME}/Mac/${FRAMEWORK_ARTIFACT_NAME}.framework.dSYM-${FRAMEWORK_VERSION}.zip" ] + [ ! -f "rome-local-cache/travis/${FRAMEWORK_REPO_NAME}/Mac/${FRAMEWORK_ARTIFACT_NAME}.framework-${FRAMEWORK_VERSION}.zip" ] + [ ! -f "rome-local-cache/travis/${FRAMEWORK_REPO_NAME}/Mac/${FRAMEWORK_ARTIFACT_NAME}.framework.dSYM-${FRAMEWORK_VERSION}.zip" ] + + # iOS + [ -f "server-cache/travis/${FRAMEWORK_REPO_NAME}/iOS/${FRAMEWORK_ARTIFACT_NAME}.framework-${FRAMEWORK_VERSION}.zip" ] + [ -f "server-cache/travis/${FRAMEWORK_REPO_NAME}/iOS/${FRAMEWORK_ARTIFACT_NAME}.framework.dSYM-${FRAMEWORK_VERSION}.zip" ] + [ -f "server-cache/travis/${FRAMEWORK_REPO_NAME}/iOS/${IOS_ARMV7_DWARF_UUID}.bcsymbolmap-${FRAMEWORK_VERSION}.zip" ] + [ -f "server-cache/travis/${FRAMEWORK_REPO_NAME}/iOS/${IOS_ARM64_DWARF_UUID}.bcsymbolmap-${FRAMEWORK_VERSION}.zip" ] + [ -f "rome-local-cache/travis/${FRAMEWORK_REPO_NAME}/iOS/${FRAMEWORK_ARTIFACT_NAME}.framework-${FRAMEWORK_VERSION}.zip" ] + [ -f "rome-local-cache/travis/${FRAMEWORK_REPO_NAME}/iOS/${FRAMEWORK_ARTIFACT_NAME}.framework.dSYM-${FRAMEWORK_VERSION}.zip" ] + [ -f "rome-local-cache/travis/${FRAMEWORK_REPO_NAME}/iOS/${IOS_ARMV7_DWARF_UUID}.bcsymbolmap-${FRAMEWORK_VERSION}.zip" ] + [ -f "rome-local-cache/travis/${FRAMEWORK_REPO_NAME}/iOS/${IOS_ARM64_DWARF_UUID}.bcsymbolmap-${FRAMEWORK_VERSION}.zip" ] + + # tvOS + [ -f "server-cache/travis/${FRAMEWORK_REPO_NAME}/tvOS/${FRAMEWORK_ARTIFACT_NAME}.framework-${FRAMEWORK_VERSION}.zip" ] + [ -f "server-cache/travis/${FRAMEWORK_REPO_NAME}/tvOS/${FRAMEWORK_ARTIFACT_NAME}.framework.dSYM-${FRAMEWORK_VERSION}.zip" ] + [ -f "server-cache/travis/${FRAMEWORK_REPO_NAME}/tvOS/${TVOS_ARM64_DWARF_UUID}.bcsymbolmap-${FRAMEWORK_VERSION}.zip" ] + [ -f "rome-local-cache/travis/${FRAMEWORK_REPO_NAME}/tvOS/${FRAMEWORK_ARTIFACT_NAME}.framework-${FRAMEWORK_VERSION}.zip" ] + [ -f "rome-local-cache/travis/${FRAMEWORK_REPO_NAME}/tvOS/${FRAMEWORK_ARTIFACT_NAME}.framework.dSYM-${FRAMEWORK_VERSION}.zip" ] + [ -f "rome-local-cache/travis/${FRAMEWORK_REPO_NAME}/tvOS/${TVOS_ARM64_DWARF_UUID}.bcsymbolmap-${FRAMEWORK_VERSION}.zip" ] + + # watchOS + [ -f "server-cache/travis/${FRAMEWORK_REPO_NAME}/watchOS/${FRAMEWORK_ARTIFACT_NAME}.framework-${FRAMEWORK_VERSION}.zip" ] + [ -f "server-cache/travis/${FRAMEWORK_REPO_NAME}/watchOS/${FRAMEWORK_ARTIFACT_NAME}.framework.dSYM-${FRAMEWORK_VERSION}.zip" ] + [ -f "server-cache/travis/${FRAMEWORK_REPO_NAME}/watchOS/${WATCHOS_ARMV7K_DWARF_UUID}.bcsymbolmap-${FRAMEWORK_VERSION}.zip" ] + [ -f "rome-local-cache/travis/${FRAMEWORK_REPO_NAME}/watchOS/${FRAMEWORK_ARTIFACT_NAME}.framework-${FRAMEWORK_VERSION}.zip" ] + [ -f "rome-local-cache/travis/${FRAMEWORK_REPO_NAME}/watchOS/${FRAMEWORK_ARTIFACT_NAME}.framework.dSYM-${FRAMEWORK_VERSION}.zip" ] + [ -f "rome-local-cache/travis/${FRAMEWORK_REPO_NAME}/watchOS/${WATCHOS_ARMV7K_DWARF_UUID}.bcsymbolmap-${FRAMEWORK_VERSION}.zip" ] + + # save the server cache for later + rm -rf ../../_server-cache_bkp + cp -R server-cache/ ../../_server-cache_bkp + + # save the local cache for later + rm -rf ../../_rome-local-cache_bkp + cp -R rome-local-cache/ ../../_rome-local-cache_bkp +} + +@test "rome downloads all named artifacts for current framework with engine skipping local cache (dynamic, yaml)" { + + # restore server cache + if [ -d "../../_server-cache_bkp" ]; then + echo "# Server cache restored" >&3 + cp -R ../../_server-cache_bkp server-cache/ + fi + + rm -rf Carthage/Build + run rome download --concurrently --cache-prefix travis --skip-local-cache ${FRAMEWORK_REPO_NAME} + + [ "$status" -eq 0 ] + + # Version file + [ -f "Carthage/Build/.${FRAMEWORK_REPO_NAME}.version" ] + + # macOS - No bitcode, No bcsymbolmap + [ ! -d "Carthage/Build/Mac/${FRAMEWORK_ARTIFACT_NAME}.framework" ] + [ ! -d "Carthage/Build/Mac/${FRAMEWORK_ARTIFACT_NAME}.framework.dSYM" ] + + # iOS + [ -d "Carthage/Build/iOS/${FRAMEWORK_ARTIFACT_NAME}.framework" ] + [ -d "Carthage/Build/iOS/${FRAMEWORK_ARTIFACT_NAME}.framework.dSYM" ] + [ -f "Carthage/Build/iOS/${IOS_ARMV7_DWARF_UUID}.bcsymbolmap" ] + [ -f "Carthage/Build/iOS/${IOS_ARM64_DWARF_UUID}.bcsymbolmap" ] + + # tvOS + [ -d "Carthage/Build/tvOS/${FRAMEWORK_ARTIFACT_NAME}.framework" ] + [ -d "Carthage/Build/tvOS/${FRAMEWORK_ARTIFACT_NAME}.framework.dSYM" ] + [ -f "Carthage/Build/tvOS/${TVOS_ARM64_DWARF_UUID}.bcsymbolmap" ] + + # watchOS + [ -d "Carthage/Build/watchOS/${FRAMEWORK_ARTIFACT_NAME}.framework" ] + [ -d "Carthage/Build/watchOS/${FRAMEWORK_ARTIFACT_NAME}.framework.dSYM" ] + [ -f "Carthage/Build/watchOS/${WATCHOS_ARMV7K_DWARF_UUID}.bcsymbolmap" ] +} + +@test "rome downloads all named artifacts for current framework with engine from the local cache (dynamic, yaml)" { + + # restore local cache + if [ -d "../../_rome-local-cache_bkp" ]; then + echo "# Local cache restored" >&3 + cp -R ../../_rome-local-cache_bkp rome-local-cache/ + fi + + rm -rf Carthage/Build + run rome download --concurrently --cache-prefix travis ${FRAMEWORK_REPO_NAME} + + [ "$status" -eq 0 ] + + # Version file + [ -f "Carthage/Build/.${FRAMEWORK_REPO_NAME}.version" ] + + # macOS - No bitecode, No bcsymbolmap + [ ! -d "Carthage/Build/Mac/${FRAMEWORK_ARTIFACT_NAME}.framework" ] + [ ! -d "Carthage/Build/Mac/${FRAMEWORK_ARTIFACT_NAME}.framework.dSYM" ] + + # iOS + [ -d "Carthage/Build/iOS/${FRAMEWORK_ARTIFACT_NAME}.framework" ] + [ -d "Carthage/Build/iOS/${FRAMEWORK_ARTIFACT_NAME}.framework.dSYM" ] + [ -f "Carthage/Build/iOS/${IOS_ARMV7_DWARF_UUID}.bcsymbolmap" ] + [ -f "Carthage/Build/iOS/${IOS_ARM64_DWARF_UUID}.bcsymbolmap" ] + + # tvOS + [ -d "Carthage/Build/tvOS/${FRAMEWORK_ARTIFACT_NAME}.framework" ] + [ -d "Carthage/Build/tvOS/${FRAMEWORK_ARTIFACT_NAME}.framework.dSYM" ] + [ -f "Carthage/Build/tvOS/${TVOS_ARM64_DWARF_UUID}.bcsymbolmap" ] + + # watchOS + [ -d "Carthage/Build/watchOS/${FRAMEWORK_ARTIFACT_NAME}.framework" ] + [ -d "Carthage/Build/watchOS/${FRAMEWORK_ARTIFACT_NAME}.framework.dSYM" ] + [ -f "Carthage/Build/watchOS/${WATCHOS_ARMV7K_DWARF_UUID}.bcsymbolmap" ] +} + +@test "rome downloads named artifacts for current framework with engine skipping local cache (dynamic, yaml)" { + + # restore server cache + if [ -d "../../_server-cache_bkp" ]; then + echo "# Server cache restored" >&3 + cp -R ../../_server-cache_bkp server-cache/ + fi + + rm -rf Carthage/Build + run rome download --concurrently --cache-prefix travis --skip-local-cache ${FRAMEWORK_REPO_NAME} + + [ "$status" -eq 0 ] + + # Version file + [ -f "Carthage/Build/.${FRAMEWORK_REPO_NAME}.version" ] + + # macOS - No bitcode, No bcsymbolmap + [ ! -d "Carthage/Build/Mac/${FRAMEWORK_ARTIFACT_NAME}.framework" ] + [ ! -d "Carthage/Build/Mac/${FRAMEWORK_ARTIFACT_NAME}.framework.dSYM" ] + + # iOS + [ -d "Carthage/Build/iOS/${FRAMEWORK_ARTIFACT_NAME}.framework" ] + [ -d "Carthage/Build/iOS/${FRAMEWORK_ARTIFACT_NAME}.framework.dSYM" ] + [ -f "Carthage/Build/iOS/${IOS_ARMV7_DWARF_UUID}.bcsymbolmap" ] + [ -f "Carthage/Build/iOS/${IOS_ARM64_DWARF_UUID}.bcsymbolmap" ] + + # tvOS + [ -d "Carthage/Build/tvOS/${FRAMEWORK_ARTIFACT_NAME}.framework" ] + [ -d "Carthage/Build/tvOS/${FRAMEWORK_ARTIFACT_NAME}.framework.dSYM" ] + [ -f "Carthage/Build/tvOS/${TVOS_ARM64_DWARF_UUID}.bcsymbolmap" ] + + # watchOS + [ -d "Carthage/Build/watchOS/${FRAMEWORK_ARTIFACT_NAME}.framework" ] + [ -d "Carthage/Build/watchOS/${FRAMEWORK_ARTIFACT_NAME}.framework.dSYM" ] + [ -f "Carthage/Build/watchOS/${WATCHOS_ARMV7K_DWARF_UUID}.bcsymbolmap" ] +} diff --git a/integration-tests/current-framework-named-yaml.bats b/integration-tests/current-framework-named-yml.bats similarity index 100% rename from integration-tests/current-framework-named-yaml.bats rename to integration-tests/current-framework-named-yml.bats diff --git a/integration-tests/current-framework-yaml.bats b/integration-tests/current-framework-yml.bats similarity index 100% rename from integration-tests/current-framework-yaml.bats rename to integration-tests/current-framework-yml.bats diff --git a/integration-tests/dynamic-frameworks-engine-yml.bats b/integration-tests/dynamic-frameworks-engine-yml.bats new file mode 100644 index 0000000..8370306 --- /dev/null +++ b/integration-tests/dynamic-frameworks-engine-yml.bats @@ -0,0 +1,282 @@ +#!/usr/bin/env bats + +setup() { + + export ALAMOFIRE_VERSION="4.8.2" + export RESULT_VERSION="4.0.0" + + rm -rf $BATS_TMPDIR/Rome-Tests + + mkdir -p $BATS_TMPDIR/Rome-Tests + + cp integration-tests/engine.sh $BATS_TMPDIR/Rome-Tests/ + + cd $BATS_TMPDIR/Rome-Tests + + if [ "$BATS_TEST_NUMBER" -eq 1 ]; then + printf "github \"Alamofire/Alamofire\" == ${ALAMOFIRE_VERSION}\n" > Cartfile + printf "github \"antitypical/Result\" == ${RESULT_VERSION}\n" >> Cartfile + + carthage bootstrap --cache-builds --no-use-binaries + + rm -rf ../_Carthage_build_bkp + cp -R Carthage/Build/ ../_Carthage_build_bkp + + rm -f ../_Cartfile_bkp + rm -f ../_Cartfile.resolved_bkp + cp Cartfile ../_Cartfile_bkp + cp Cartfile.resolved ../_Cartfile.resolved_bkp + + else + mkdir -p Carthage/Build + cp -R ../_Carthage_build_bkp/ Carthage/Build + cp ../_Cartfile_bkp Cartfile + cp ../_Cartfile.resolved_bkp Cartfile.resolved + fi + + cat >> Romefile << EOF +cache: + local: rome-local-cache + engine: engine.sh +ignoreMap: + - Alamofire: + - name: Alamofire + platforms: [Mac] +EOF + + IOS_DWARFDUMP_OUT=($(dwarfdump -u Carthage/Build/iOS/Alamofire.framework/Alamofire)) + TVOS_DWARFDUMP_OUT=($(dwarfdump -u Carthage/Build/tvOS/Alamofire.framework/Alamofire)) + WATCHOS_DWARFDUMP_OUT=($(dwarfdump -u Carthage/Build/watchOS/Alamofire.framework/Alamofire)) + + export ALAMOFIRE_IOS_ARMV7_DWARF_UUID=${IOS_DWARFDUMP_OUT[9]} + export ALAMOFIRE_IOS_ARM64_DWARF_UUID=${IOS_DWARFDUMP_OUT[13]} + export ALAMOFIRE_TVOS_ARM64_DWARF_UUID=${TVOS_DWARFDUMP_OUT[5]} + export ALAMOFIRE_WATCHOS_ARMV7K_DWARF_UUID=${WATCHOS_DWARFDUMP_OUT[5]} + + IOS_DWARFDUMP_OUT=($(dwarfdump -u Carthage/Build/iOS/Result.framework/Result)) + TVOS_DWARFDUMP_OUT=($(dwarfdump -u Carthage/Build/tvOS/Result.framework/Result)) + WATCHOS_DWARFDUMP_OUT=($(dwarfdump -u Carthage/Build/watchOS/Result.framework/Result)) + + export RESULT_IOS_ARMV7_DWARF_UUID=${IOS_DWARFDUMP_OUT[9]} + export RESULT_IOS_ARM64_DWARF_UUID=${IOS_DWARFDUMP_OUT[13]} + export RESULT_TVOS_ARM64_DWARF_UUID=${TVOS_DWARFDUMP_OUT[5]} + export RESULT_WATCHOS_ARMV7K_DWARF_UUID=${WATCHOS_DWARFDUMP_OUT[5]} + + echo "# BATS_TMPDIR: ${BATS_TMPDIR}" >&3 + +} + + +teardown() { + cd $BATS_TEST_DIRNAME +} + +@test "rome uploads all artifacts with engine (dynamic, yml)" { + + run rome upload --concurrently --cache-prefix travis + + [ "$status" -eq 0 ] + + # Version file + [ -f "server-cache/travis/Alamofire/.Alamofire.version-${ALAMOFIRE_VERSION}" ] + [ -f "rome-local-cache/travis/Alamofire/.Alamofire.version-${ALAMOFIRE_VERSION}" ] + [ -f "server-cache/travis/Result/.Result.version-${RESULT_VERSION}" ] + [ -f "rome-local-cache/travis/Result/.Result.version-${RESULT_VERSION}" ] + + # macOS - No bitecode, No bcsymbolmap + + # macOS - Alamofire + [ ! -f "server-cache/travis/Alamofire/Mac/Alamofire.framework-${ALAMOFIRE_VERSION}.zip" ] + [ ! -f "server-cache/travis/Alamofire/Mac/Alamofire.framework.dSYM-${ALAMOFIRE_VERSION}.zip" ] + [ ! -f "rome-local-cache/travis/Alamofire/Mac/Alamofire.framework-${ALAMOFIRE_VERSION}.zip" ] + [ ! -f "rome-local-cache/travis/Alamofire/Mac/Alamofire.framework.dSYM-${ALAMOFIRE_VERSION}.zip" ] + + # macOS - Result + [ -f "server-cache/travis/Result/Mac/Result.framework-${RESULT_VERSION}.zip" ] + [ -f "server-cache/travis/Result/Mac/Result.framework.dSYM-${RESULT_VERSION}.zip" ] + [ -f "rome-local-cache/travis/Result/Mac/Result.framework-${RESULT_VERSION}.zip" ] + [ -f "rome-local-cache/travis/Result/Mac/Result.framework.dSYM-${RESULT_VERSION}.zip" ] + + # iOS - Alamofire + [ -f "server-cache/travis/Alamofire/iOS/Alamofire.framework-${ALAMOFIRE_VERSION}.zip" ] + [ -f "server-cache/travis/Alamofire/iOS/Alamofire.framework.dSYM-${ALAMOFIRE_VERSION}.zip" ] + [ -f "server-cache/travis/Alamofire/iOS/${ALAMOFIRE_IOS_ARMV7_DWARF_UUID}.bcsymbolmap-${ALAMOFIRE_VERSION}.zip" ] + [ -f "server-cache/travis/Alamofire/iOS/${ALAMOFIRE_IOS_ARM64_DWARF_UUID}.bcsymbolmap-${ALAMOFIRE_VERSION}.zip" ] + [ -f "rome-local-cache/travis/Alamofire/iOS/Alamofire.framework-${ALAMOFIRE_VERSION}.zip" ] + [ -f "rome-local-cache/travis/Alamofire/iOS/Alamofire.framework.dSYM-${ALAMOFIRE_VERSION}.zip" ] + [ -f "rome-local-cache/travis/Alamofire/iOS/${ALAMOFIRE_IOS_ARMV7_DWARF_UUID}.bcsymbolmap-${ALAMOFIRE_VERSION}.zip" ] + [ -f "rome-local-cache/travis/Alamofire/iOS/${ALAMOFIRE_IOS_ARM64_DWARF_UUID}.bcsymbolmap-${ALAMOFIRE_VERSION}.zip" ] + + # iOS - Result + [ -f "server-cache/travis/Result/iOS/Result.framework-${RESULT_VERSION}.zip" ] + [ -f "server-cache/travis/Result/iOS/Result.framework.dSYM-${RESULT_VERSION}.zip" ] + [ -f "server-cache/travis/Result/iOS/${RESULT_IOS_ARMV7_DWARF_UUID}.bcsymbolmap-${RESULT_VERSION}.zip" ] + [ -f "server-cache/travis/Result/iOS/${RESULT_IOS_ARM64_DWARF_UUID}.bcsymbolmap-${RESULT_VERSION}.zip" ] + [ -f "rome-local-cache/travis/Result/iOS/Result.framework-${RESULT_VERSION}.zip" ] + [ -f "rome-local-cache/travis/Result/iOS/Result.framework.dSYM-${RESULT_VERSION}.zip" ] + [ -f "rome-local-cache/travis/Result/iOS/${RESULT_IOS_ARMV7_DWARF_UUID}.bcsymbolmap-${RESULT_VERSION}.zip" ] + [ -f "rome-local-cache/travis/Result/iOS/${RESULT_IOS_ARM64_DWARF_UUID}.bcsymbolmap-${RESULT_VERSION}.zip" ] + + # tvOS - Alamofire + [ -f "server-cache/travis/Alamofire/tvOS/Alamofire.framework-${ALAMOFIRE_VERSION}.zip" ] + [ -f "server-cache/travis/Alamofire/tvOS/Alamofire.framework.dSYM-${ALAMOFIRE_VERSION}.zip" ] + [ -f "server-cache/travis/Alamofire/tvOS/${ALAMOFIRE_TVOS_ARM64_DWARF_UUID}.bcsymbolmap-${ALAMOFIRE_VERSION}.zip" ] + [ -f "rome-local-cache/travis/Alamofire/tvOS/Alamofire.framework-${ALAMOFIRE_VERSION}.zip" ] + [ -f "rome-local-cache/travis/Alamofire/tvOS/Alamofire.framework.dSYM-${ALAMOFIRE_VERSION}.zip" ] + [ -f "rome-local-cache/travis/Alamofire/tvOS/${ALAMOFIRE_TVOS_ARM64_DWARF_UUID}.bcsymbolmap-${ALAMOFIRE_VERSION}.zip" ] + + # tvOS - Result + [ -f "server-cache/travis/Result/tvOS/Result.framework-${RESULT_VERSION}.zip" ] + [ -f "server-cache/travis/Result/tvOS/Result.framework.dSYM-${RESULT_VERSION}.zip" ] + [ -f "server-cache/travis/Result/tvOS/${RESULT_TVOS_ARM64_DWARF_UUID}.bcsymbolmap-${RESULT_VERSION}.zip" ] + [ -f "rome-local-cache/travis/Result/tvOS/Result.framework-${RESULT_VERSION}.zip" ] + [ -f "rome-local-cache/travis/Result/tvOS/Result.framework.dSYM-${RESULT_VERSION}.zip" ] + [ -f "rome-local-cache/travis/Result/tvOS/${RESULT_TVOS_ARM64_DWARF_UUID}.bcsymbolmap-${RESULT_VERSION}.zip" ] + + # watchOS + [ -f "server-cache/travis/Alamofire/watchOS/Alamofire.framework-${ALAMOFIRE_VERSION}.zip" ] + [ -f "server-cache/travis/Alamofire/watchOS/Alamofire.framework.dSYM-${ALAMOFIRE_VERSION}.zip" ] + [ -f "server-cache/travis/Alamofire/watchOS/${ALAMOFIRE_WATCHOS_ARMV7K_DWARF_UUID}.bcsymbolmap-${ALAMOFIRE_VERSION}.zip" ] + [ -f "rome-local-cache/travis/Alamofire/watchOS/Alamofire.framework-${ALAMOFIRE_VERSION}.zip" ] + [ -f "rome-local-cache/travis/Alamofire/watchOS/Alamofire.framework.dSYM-${ALAMOFIRE_VERSION}.zip" ] + [ -f "rome-local-cache/travis/Alamofire/watchOS/${ALAMOFIRE_WATCHOS_ARMV7K_DWARF_UUID}.bcsymbolmap-${ALAMOFIRE_VERSION}.zip" ] + + [ -f "server-cache/travis/Result/watchOS/Result.framework-${RESULT_VERSION}.zip" ] + [ -f "server-cache/travis/Result/watchOS/Result.framework.dSYM-${RESULT_VERSION}.zip" ] + [ -f "server-cache/travis/Result/watchOS/${RESULT_WATCHOS_ARMV7K_DWARF_UUID}.bcsymbolmap-${RESULT_VERSION}.zip" ] + [ -f "rome-local-cache/travis/Result/watchOS/Result.framework-${RESULT_VERSION}.zip" ] + [ -f "rome-local-cache/travis/Result/watchOS/Result.framework.dSYM-${RESULT_VERSION}.zip" ] + [ -f "rome-local-cache/travis/Result/watchOS/${RESULT_WATCHOS_ARMV7K_DWARF_UUID}.bcsymbolmap-${RESULT_VERSION}.zip" ] + + # save the server cache for later + rm -rf ../_server-cache_bkp + cp -R server-cache/ ../_server-cache_bkp + + # save the local cache for later + rm -rf ../_rome-local-cache_bkp + cp -R rome-local-cache/ ../_rome-local-cache_bkp +} + +@test "rome downloads all artifacts with engine skipping local cache (dynamic, yml)" { + + # restore server cache + if [ -d "../_server-cache_bkp" ]; then + echo "# Server cache restored" >&3 + cp -R ../_server-cache_bkp server-cache/ + fi + + # restore local cache (even though it will be skipped, we want it to be there to simulate a real scenario) + if [ -d "../_server-cache_bkp" ]; then + echo "# Local cache restored" >&3 + cp -R ../_rome-local-cache_bkp rome-local-cache/ + fi + + rm -rf Carthage/Build + run rome download --concurrently --skip-local-cache --cache-prefix travis + + [ "$status" -eq 0 ] + + # Version file + [ -f "Carthage/Build/.Alamofire.version" ] + [ -f "Carthage/Build/.Result.version" ] + + # macOS - No bitcode, No bcsymbolmap + # macOS - Alamofire + [ ! -d "Carthage/Build/Mac/Alamofire.framework" ] + [ ! -d "Carthage/Build/Mac/Alamofire.framework.dSYM" ] + + # macOS - Result + [ -d "Carthage/Build/Mac/Result.framework" ] + [ -d "Carthage/Build/Mac/Result.framework.dSYM" ] + + # iOS - Alamofire + [ -d "Carthage/Build/iOS/Alamofire.framework" ] + [ -d "Carthage/Build/iOS/Alamofire.framework.dSYM" ] + [ -e "Carthage/Build/iOS/${ALAMOFIRE_IOS_ARMV7_DWARF_UUID}.bcsymbolmap" ] + [ -e "Carthage/Build/iOS/${ALAMOFIRE_IOS_ARM64_DWARF_UUID}.bcsymbolmap" ] + + # iOS - Result + [ -d "Carthage/Build/iOS/Result.framework" ] + [ -d "Carthage/Build/iOS/Result.framework.dSYM" ] + [ -f "Carthage/Build/iOS/${RESULT_IOS_ARMV7_DWARF_UUID}.bcsymbolmap" ] + [ -f "Carthage/Build/iOS/${RESULT_IOS_ARM64_DWARF_UUID}.bcsymbolmap" ] + + # tvOS - Alamofire + [ -d "Carthage/Build/tvOS/Alamofire.framework" ] + [ -d "Carthage/Build/tvOS/Alamofire.framework.dSYM" ] + [ -f "Carthage/Build/tvOS/${ALAMOFIRE_TVOS_ARM64_DWARF_UUID}.bcsymbolmap" ] + + # tvOS - Result + [ -d "Carthage/Build/tvOS/Result.framework" ] + [ -d "Carthage/Build/tvOS/Result.framework.dSYM" ] + [ -f "Carthage/Build/tvOS/${RESULT_TVOS_ARM64_DWARF_UUID}.bcsymbolmap" ] + + # watchOS - Alamofire + [ -d "Carthage/Build/watchOS/Alamofire.framework" ] + [ -d "Carthage/Build/watchOS/Alamofire.framework.dSYM" ] + [ -f "Carthage/Build/watchOS/${ALAMOFIRE_WATCHOS_ARMV7K_DWARF_UUID}.bcsymbolmap" ] + + # watchOS - Result + [ -d "Carthage/Build/watchOS/Result.framework" ] + [ -d "Carthage/Build/watchOS/Result.framework.dSYM" ] + [ -f "Carthage/Build/watchOS/${RESULT_WATCHOS_ARMV7K_DWARF_UUID}.bcsymbolmap" ] +} + +@test "rome downloads all artifacts with engine from the local cache (dynamic, yml)" { + + # restore local cache + if [ -d "../_server-cache_bkp" ]; then + echo "# Local cache restored" >&3 + cp -R ../_rome-local-cache_bkp rome-local-cache/ + fi + + rm -rf Carthage/Build + run rome download --concurrently --cache-prefix travis + + [ "$status" -eq 0 ] + + # Version file + [ -f "Carthage/Build/.Alamofire.version" ] + [ -f "Carthage/Build/.Result.version" ] + + # macOS - No bitecode, No bcsymbolmap + # macOS - Alamofire + [ ! -d "Carthage/Build/Mac/Alamofire.framework" ] + [ ! -d "Carthage/Build/Mac/Alamofire.framework.dSYM" ] + + # macOS - Result + [ -d "Carthage/Build/Mac/Result.framework" ] + [ -d "Carthage/Build/Mac/Result.framework.dSYM" ] + + # iOS - Alamofire + [ -d "Carthage/Build/iOS/Alamofire.framework" ] + [ -d "Carthage/Build/iOS/Alamofire.framework.dSYM" ] + [ -f "Carthage/Build/iOS/${ALAMOFIRE_IOS_ARMV7_DWARF_UUID}.bcsymbolmap" ] + [ -f "Carthage/Build/iOS/${ALAMOFIRE_IOS_ARM64_DWARF_UUID}.bcsymbolmap" ] + + # iOS - Result + [ -d "Carthage/Build/iOS/Result.framework" ] + [ -d "Carthage/Build/iOS/Result.framework.dSYM" ] + [ -f "Carthage/Build/iOS/${RESULT_IOS_ARMV7_DWARF_UUID}.bcsymbolmap" ] + [ -f "Carthage/Build/iOS/${RESULT_IOS_ARM64_DWARF_UUID}.bcsymbolmap" ] + + # tvOS - Alamofire + [ -d "Carthage/Build/tvOS/Alamofire.framework" ] + [ -d "Carthage/Build/tvOS/Alamofire.framework.dSYM" ] + [ -f "Carthage/Build/tvOS/${ALAMOFIRE_TVOS_ARM64_DWARF_UUID}.bcsymbolmap" ] + + # tvOS - Result + [ -d "Carthage/Build/tvOS/Result.framework" ] + [ -d "Carthage/Build/tvOS/Result.framework.dSYM" ] + [ -e "Carthage/Build/tvOS/${RESULT_TVOS_ARM64_DWARF_UUID}.bcsymbolmap" ] + + # watchOS - Alamofire + [ -d "Carthage/Build/watchOS/Alamofire.framework" ] + [ -d "Carthage/Build/watchOS/Alamofire.framework.dSYM" ] + [ -f "Carthage/Build/watchOS/${ALAMOFIRE_WATCHOS_ARMV7K_DWARF_UUID}.bcsymbolmap" ] + + # watchOS - Result + [ -d "Carthage/Build/watchOS/Result.framework" ] + [ -d "Carthage/Build/watchOS/Result.framework.dSYM" ] + [ -f "Carthage/Build/watchOS/${RESULT_WATCHOS_ARMV7K_DWARF_UUID}.bcsymbolmap" ] +} \ No newline at end of file diff --git a/integration-tests/engine.sh b/integration-tests/engine.sh new file mode 100755 index 0000000..a334717 --- /dev/null +++ b/integration-tests/engine.sh @@ -0,0 +1,39 @@ +#!/usr/bin/env bash + +set -e + +ACTION="$1" + +STORAGE_DIR="server-cache" + +if [ "$ACTION" == "upload" ]; then + LOCAL_PATH="$2" + REMOTE_PATH="$3" + # POST request to upload file to remote path + # create directory structure if it doesn't exist yet + mkdir -p $STORAGE_DIR/$(dirname $REMOTE_PATH) + # fake the upload of a file by just copying binary to the storage directory + cp $LOCAL_PATH $STORAGE_DIR/$REMOTE_PATH + +elif [ "$ACTION" == "download" ]; then + REMOTE_PATH="$2" + OUTPUT_PATH="$3" + # create directory structure if it doesn't exist yet + mkdir -p $(dirname $OUTPUT_PATH) + # fake download by just copying binary from the storage directory + # don't fail script if copy fails (some bcsymbolmap get requested wrongly at the moment, bug in Rome) + if [[ -f $STORAGE_DIR/$REMOTE_PATH ]]; then + cp $STORAGE_DIR/$REMOTE_PATH $OUTPUT_PATH + fi + +elif [ "$ACTION" == "list" ]; then + REMOTE_PATH="$2" + # fake list command by just checking if file exists + if [ ! -f "$STORAGE_DIR/$REMOTE_PATH" ]; then + exit 1 + fi + +else + # unsupported command + exit 1 +fi diff --git a/integration-tests/static-frameworks-engine-yml.bats b/integration-tests/static-frameworks-engine-yml.bats new file mode 100644 index 0000000..8a9fcae --- /dev/null +++ b/integration-tests/static-frameworks-engine-yml.bats @@ -0,0 +1,195 @@ +#!/usr/bin/env bats + +setup() { + + export STATICFIRE_COMMIT="ada9256edf4b6dfb63bd1f6d13441b1ab7fd6ffd" + export RESULT_VERSION="4.1.0" + + rm -rf $BATS_TMPDIR/Rome-Tests + + mkdir -p $BATS_TMPDIR/Rome-Tests + + cp integration-tests/engine.sh $BATS_TMPDIR/Rome-Tests/ + + cd $BATS_TMPDIR/Rome-Tests + + if [ "$BATS_TEST_NUMBER" -eq 1 ]; then + printf "github \"blender/Staticfire\" \"master\"\n" > Cartfile + printf "github \"antitypical/Result\" == ${RESULT_VERSION}\n" >> Cartfile + + carthage bootstrap --cache-builds --no-use-binaries + + rm -rf ../_Carthage_build_bkp + cp -R Carthage/Build/ ../_Carthage_build_bkp + + rm -f ../_Cartfile_bkp + rm -f ../_Cartfile.resolved_bkp + cp Cartfile ../_Cartfile_bkp + cp Cartfile.resolved ../_Cartfile.resolved_bkp + + else + mkdir -p Carthage/Build + cp -R ../_Carthage_build_bkp/ Carthage/Build + cp ../_Cartfile_bkp Cartfile + cp ../_Cartfile.resolved_bkp Cartfile.resolved + fi + + cat >> ../Romefile.yaml << EOF +cache: + local: rome-local-cache + engine: engine.sh +repositoryMap: +- Staticfire: + - name: Alamofire + type: static +ignoreMap: +- Staticfire: + - name: Alamofire + type: static + platforms: [Mac] +- Result: + - name: Result + platforms: [iOS,Mac,tvOS,watchOS] +EOF + + echo "# BATS_TMPDIR: ${BATS_TMPDIR}" >&3 + +} + +teardown() { + cd $BATS_TEST_DIRNAME +} + + +@test "rome uploads all artifacts with engine (static, yml)" { + + # No dSYMs nor bcsymbolmaps for Static Frameworks + + run rome upload --concurrently --cache-prefix travis --romefile ../Romefile.yaml + + [ "$status" -eq 0 ] + + # Version file + [ -f "server-cache/travis/Staticfire/.Staticfire.version-${STATICFIRE_COMMIT}" ] + [ -f "rome-local-cache/travis/Staticfire/.Staticfire.version-${STATICFIRE_COMMIT}" ] + [ ! -f "server-cache/travis/Result/.Result.version-${RESULT_VERSION}" ] + [ ! -f "rome-local-cache/travis/Result/.Result.version-${RESULT_VERSION}" ] + + # macOS - Staticfire + [ ! -f "server-cache/travis/Staticfire/Mac/Alamofire.framework-static-${STATICFIRE_COMMIT}.zip" ] + [ ! -f "rome-local-cache/travis/Staticfire/Mac/Alamofire.framework-static-${STATICFIRE_COMMIT}.zip" ] + # macOS - Result + [ ! -f "server-cache/travis/Result/Mac/Result.framework-${RESULT_VERSION}.zip" ] + [ ! -f "rome-local-cache/travis/Result/Mac/Result.framework-${RESULT_VERSION}.zip" ] + + # iOS - Staticfire + [ -f "server-cache/travis/Staticfire/iOS/Alamofire.framework-static-${STATICFIRE_COMMIT}.zip" ] + [ -f "rome-local-cache/travis/Staticfire/iOS/Alamofire.framework-static-${STATICFIRE_COMMIT}.zip" ] + # iOS - Result + [ ! -f "server-cache/travis/Result/iOS/Result.framework-${RESULT_VERSION}.zip" ] + [ ! -f "rome-local-cache/travis/Result/iOS/Result.framework-${RESULT_VERSION}.zip" ] + + # tvOS - Staticfire + [ -f "server-cache/travis/Staticfire/tvOS/Alamofire.framework-static-${STATICFIRE_COMMIT}.zip" ] + [ -f "rome-local-cache/travis/Staticfire/tvOS/Alamofire.framework-static-${STATICFIRE_COMMIT}.zip" ] + # tvOS - Result + [ ! -f "server-cache/travis/Result/tvOS/Result.framework-${RESULT_VERSION}.zip" ] + [ ! -f "rome-local-cache/travis/Result/tvOS/Result.framework-${RESULT_VERSION}.zip" ] + + # watchOS - Staticfire + [ -f "server-cache/travis/Staticfire/watchOS/Alamofire.framework-static-${STATICFIRE_COMMIT}.zip" ] + [ -f "rome-local-cache/travis/Staticfire/watchOS/Alamofire.framework-static-${STATICFIRE_COMMIT}.zip" ] + # watchOS - Result + [ ! -f "server-cache/travis/Result/watchOS/Result.framework-${RESULT_VERSION}.zip" ] + [ ! -f "rome-local-cache/travis/Result/watchOS/Result.framework-${RESULT_VERSION}.zip" ] + + # save the server cache for later + rm -rf ../_server-cache_bkp + cp -R server-cache/ ../_server-cache_bkp + + # save the local cache for later + rm -rf ../_rome-local-cache_bkp + cp -R rome-local-cache/ ../_rome-local-cache_bkp +} + +@test "rome downloads all artifacts with engine skipping local cache (static, yml)" { + + # No dSYMs nor bcsymbolmaps for Static Frameworks + + # restore server cache + if [ -d "../_server-cache_bkp" ]; then + echo "# Server cache restored" >&3 + cp -R ../_server-cache_bkp server-cache/ + fi + + rm -rf Carthage/Build + run rome download --concurrently --cache-prefix travis --skip-local-cache --romefile ../Romefile.yaml + + [ "$status" -eq 0 ] + + # Version file + [ -f "Carthage/Build/.Staticfire.version" ] + [ ! -f "Carthage/Build/.Result.version" ] + + + # macOS - Staticfire + [ ! -d "Carthage/Build/Mac/Static/Alamofire.framework" ] + # macOS - Result + [ ! -d "Carthage/Build/Mac/Result.framework" ] + + # iOS - Staticfire + [ -d "Carthage/Build/iOS/Static/Alamofire.framework" ] + # iOS - Result + [ ! -d "Carthage/Build/iOS/Result.framework" ] + + # tvOS - Staticfire + [ -d "Carthage/Build/tvOS/Static/Alamofire.framework" ] + # tvOS - Result + [ ! -d "Carthage/Build/tvOS/Result.framework" ] + + # watchOS - Staticfire + [ -d "Carthage/Build/watchOS/Static/Alamofire.framework" ] + # watchOS - Result + [ ! -d "Carthage/Build/watchOS/Result.framework" ] + +} + +@test "rome downloads all artifacts with engine from the local cache (static, yml)" { + + # No dSYMs nor bcsymbolmaps for Static Frameworks + + # restore local cache + if [ -d "../_rome-local-cache_bkp" ]; then + echo "# Local cache restored" >&3 + cp -R ../_rome-local-cache_bkp rome-local-cache/ + fi + + rm -rf Carthage/Build + run rome download --concurrently --cache-prefix travis --romefile ../Romefile.yaml + + [ "$status" -eq 0 ] + + # Version file + [ -f "Carthage/Build/.Staticfire.version" ] + + # macOS - No bitecode, No bcsymbolmap + # macOS - Staticfire + [ ! -d "Carthage/Build/Mac/Static/Alamofire.framework" ] + # macoS - Result + [ ! -d "Carthage/Build/Mac/Result.framework" ] + + # iOS - Staticfire + [ -d "Carthage/Build/iOS/Static/Alamofire.framework" ] + # iOS - Result + [ ! -d "Carthage/Build/iOS/Result.framework" ] + + # tvOS - Staticfire + [ -d "Carthage/Build/tvOS/Static/Alamofire.framework" ] + # tvOS - Result + [ ! -d "Carthage/Build/tvOS/Result.framework" ] + + # watchOS - Staticfire + [ -d "Carthage/Build/watchOS/Static/Alamofire.framework" ] + # watchOS - Result + [ ! -d "Carthage/Build/watchOS/Result.framework" ] +} diff --git a/src/Caches/Local/Uploading.hs b/src/Caches/Local/Uploading.hs index f50e69f..9cb55fa 100644 --- a/src/Caches/Local/Uploading.hs +++ b/src/Caches/Local/Uploading.hs @@ -96,7 +96,7 @@ saveBinaryToLocalCache -> LBS.ByteString -- ^ The `ByteString` to save. -> FilePath -- ^ The destination path inside the base directory. -> String -- ^ A colloquial name for the artifact printed when verbose is `True`. - -> Bool -- ^ A verbostiry flag. + -> Bool -- ^ A verbosity flag. -> m () saveBinaryToLocalCache cachePath binaryZip destinationPath objectName verbose = do diff --git a/src/Caches/S3/Downloading.hs b/src/Caches/S3/Downloading.hs index 73ef488..bd4f102 100644 --- a/src/Caches/S3/Downloading.hs +++ b/src/Caches/S3/Downloading.hs @@ -250,7 +250,7 @@ getArtifactFromS3 s3BucketName remotePath artifactName = do --- | Downloads an artificat stored at a given path from an `S3.BucketName`. +-- | Downloads an artifact stored at a given path from an `S3.BucketName`. downloadBinary :: S3.BucketName -> FilePath diff --git a/src/Caches/S3/Uploading.hs b/src/Caches/S3/Uploading.hs index d0e1469..d310c01 100644 --- a/src/Caches/S3/Uploading.hs +++ b/src/Caches/S3/Uploading.hs @@ -103,7 +103,7 @@ uploadVersionFileToS3 s3BucketName versionFileContent projectNameAndVersion = --- | Uploads an artificat to an `S3.BucketName` at a given path in the bucket. +-- | Uploads an artifact to an `S3.BucketName` at a given path in the bucket. uploadBinary :: AWS.ToBody a => S3.BucketName diff --git a/src/Data/Romefile.hs b/src/Data/Romefile.hs index 704fb4c..b70d221 100644 --- a/src/Data/Romefile.hs +++ b/src/Data/Romefile.hs @@ -19,6 +19,7 @@ module Data.Romefile , cacheInfo , bucket , localCacheDir + , enginePath , frameworkName , frameworkType , FrameworkType (..) @@ -174,7 +175,8 @@ cacheInfo :: Lens' Romefile RomeCacheInfo cacheInfo = lens _cacheInfo (\parseResult n -> parseResult { _cacheInfo = n }) data RomeCacheInfo = RomeCacheInfo { _bucket :: Maybe T.Text - , _localCacheDir :: Maybe FilePath -- relative path + , _localCacheDir :: Maybe FilePath -- relative or absolue path + , _enginePath :: Maybe FilePath -- relative or absolue path } deriving (Eq, Show, Generic) @@ -182,11 +184,14 @@ instance FromJSON RomeCacheInfo where parseJSON = withObject "RomeCacheInfo" $ \v -> RomeCacheInfo <$> v .:? "s3Bucket" <*> v .:? "local" + <*> v .:? "engine" instance ToJSON RomeCacheInfo where - toJSON (RomeCacheInfo b l) = object fields + toJSON (RomeCacheInfo b l e) = object fields where - fields = [T.pack "s3Bucket" .= b | isJust b] ++ [T.pack "local" .= l | isJust l] + fields = [T.pack "s3Bucket" .= b | isJust b] + ++ [T.pack "local" .= l | isJust l] + ++ [T.pack "engine" .= e| isJust e] bucket :: Lens' RomeCacheInfo (Maybe T.Text) bucket = lens _bucket (\cInfo n -> cInfo { _bucket = n }) @@ -194,6 +199,9 @@ bucket = lens _bucket (\cInfo n -> cInfo { _bucket = n }) localCacheDir :: Lens' RomeCacheInfo (Maybe FilePath) localCacheDir = lens _localCacheDir (\cInfo n -> cInfo { _localCacheDir = n }) +enginePath :: Lens' RomeCacheInfo (Maybe FilePath) +enginePath = lens _enginePath (\cInfo n -> cInfo { _enginePath = n }) + -- |The canonical name of the Romefile canonicalRomefileName :: String canonicalRomefileName = "Romefile" @@ -226,8 +234,10 @@ toRomefile :: INI.Ini -> Either T.Text Romefile toRomefile ini = do _bucket <- getBucket ini _localCacheDir <- getLocalCacheDir ini + let _engine = Nothing -- Engines are not supported in INI let _repositoryMapEntries = getRepositoryMapEntries ini _ignoreMapEntries = getIgnoreMapEntries ini + _enginePath = _engine _cacheInfo = RomeCacheInfo {..} Romefile <$> Right _cacheInfo diff --git a/src/Engine/Downloading.hs b/src/Engine/Downloading.hs new file mode 100644 index 0000000..ce1373b --- /dev/null +++ b/src/Engine/Downloading.hs @@ -0,0 +1,263 @@ +{-# LANGUAGE OverloadedStrings #-} +{-# LANGUAGE ScopedTypeVariables #-} + +module Engine.Downloading where + +import Caches.Common +import Configuration (carthageArtifactsBuildDirectoryForPlatform) +import Control.Exception (try) +import Control.Monad +import Control.Monad.Except +import Control.Monad.Reader (ReaderT, ask, runReaderT, + withReaderT) +import qualified Data.ByteString.Lazy as LBS +import Data.Carthage.TargetPlatform +import Data.Either (lefts) +import Data.Monoid ((<>)) +import Data.Romefile (Framework (..)) +import System.Directory +import System.FilePath (()) +import Types hiding (version) +import Utils +import Xcode.DWARF +import qualified Turtle + +-- | Retrieves a Framework using the engine and unzip the contents +getFrameworkFromEngine + :: FilePath -- ^ The `FilePath` to the engine + -> InvertedRepositoryMap -- ^ The map used to resolve from a `FrameworkVersion` to the path of the Framework in the cache + -> FrameworkVersion -- ^ The `FrameworkVersion` identifying the Framework + -> TargetPlatform -- ^ The `TargetPlatform` to limit the operation to + -> ExceptT String (ReaderT (CachePrefix, Bool) IO) LBS.ByteString +getFrameworkFromEngine enginePath reverseRomeMap (FrameworkVersion f@(Framework fwn _ _) version) platform + = do + (CachePrefix cachePrefix, verbose) <- ask + let frameworkLocalPath = cachePrefix remoteFrameworkUploadPath + mapExceptT + (withReaderT (const verbose)) + (getArtifactFromEngine enginePath frameworkLocalPath fwn + ) + where + remoteFrameworkUploadPath = remoteFrameworkPath platform reverseRomeMap f version + + +-- | Retrieves a .version file using the engine +getVersionFileFromEngine + :: FilePath -- ^ The `FilePath` to the engine + -> ProjectNameAndVersion + -> ExceptT + String + (ReaderT (CachePrefix, Bool) IO) + LBS.ByteString +getVersionFileFromEngine enginePath projectNameAndVersion = do + (CachePrefix prefix, verbose) <- ask + let finalVersionFileRemotePath = prefix versionFileRemotePath + mapExceptT (withReaderT (const verbose)) $ getArtifactFromEngine + enginePath + finalVersionFileRemotePath + versionFileName + where + versionFileName = versionFileNameForProjectName $ fst projectNameAndVersion + versionFileRemotePath = remoteVersionFilePath projectNameAndVersion + + +-- | Retrieves a bcsymbolmap using the engine +getBcsymbolmapWithEngine + :: FilePath -- ^ The `FilePath` to the engine + -> InvertedRepositoryMap -- ^ The map used to resolve from a `FrameworkVersion` to the path of the dSYM in the cache + -> FrameworkVersion -- ^ The `FrameworkVersion` identifying the dSYM + -> TargetPlatform -- ^ The `TargetPlatform` to limit the operation to + -> DwarfUUID -- ^ The UUID of the bcsymbolmap + -> ExceptT + String + (ReaderT (CachePrefix, Bool) IO) + LBS.ByteString +getBcsymbolmapWithEngine enginePath reverseRomeMap (FrameworkVersion f@(Framework fwn _ _) version) platform dwarfUUID + = do + (CachePrefix prefix, verbose) <- ask + let finalRemoteBcsymbolmaploadPath = prefix remoteBcSymbolmapUploadPath + mapExceptT (withReaderT (const verbose)) $ getArtifactFromEngine + enginePath + finalRemoteBcsymbolmaploadPath + symbolmapName + where + remoteBcSymbolmapUploadPath = + remoteBcsymbolmapPath dwarfUUID platform reverseRomeMap f version + symbolmapName = fwn <> "." <> bcsymbolmapNameFrom dwarfUUID + + +-- | Retrieves a dSYM using the engine +getDSYMFromEngine + :: FilePath -- ^ The `FilePath` to the engine + -> InvertedRepositoryMap -- ^ The map used to resolve from a `FrameworkVersion` to the path of the dSYM in the cache + -> FrameworkVersion -- ^ The `FrameworkVersion` identifying the dSYM + -> TargetPlatform -- ^ The `TargetPlatform` to limit the operation to + -> ExceptT + String + (ReaderT (CachePrefix, Bool) IO) + LBS.ByteString +getDSYMFromEngine enginePath reverseRomeMap (FrameworkVersion f@(Framework fwn _ _) version) platform + = do + (CachePrefix prefix, verbose) <- ask + let finalRemoteDSYMUploadPath = prefix remoteDSYMUploadPath + mapExceptT (withReaderT (const verbose)) + $ getArtifactFromEngine enginePath finalRemoteDSYMUploadPath dSYMName + where + remoteDSYMUploadPath = remoteDsymPath platform reverseRomeMap f version + dSYMName = fwn <> ".dSYM" + + +-- | Retrieves a bcsymbolmap using the engine and unzip the contents +getAndUnzipBcsymbolmapWithEngine + :: FilePath -- ^ The `FilePath` to the engine + -> InvertedRepositoryMap -- ^ The map used to resolve from a `FrameworkVersion` to the path of the dSYM in the cache + -> FrameworkVersion -- ^ The `FrameworkVersion` identifying the dSYM + -> TargetPlatform -- ^ The `TargetPlatform` to limit the operation to + -> DwarfUUID -- ^ The UUID of the bcsymbolmap + -> ExceptT String (ReaderT (CachePrefix, Bool) IO) () +getAndUnzipBcsymbolmapWithEngine enginePath reverseRomeMap fVersion@(FrameworkVersion f@(Framework fwn _ fwps) version) platform dwarfUUID + = when (platform `elem` fwps) $ do + (_, verbose) <- ask + let symbolmapName = fwn <> "." <> bcsymbolmapNameFrom dwarfUUID + binary <- getBcsymbolmapWithEngine enginePath + reverseRomeMap + fVersion + platform + dwarfUUID + deleteFile (bcsymbolmapPath dwarfUUID) verbose + unzipBinary binary symbolmapName (bcsymbolmapZipName dwarfUUID) verbose + where + platformBuildDirectory = + carthageArtifactsBuildDirectoryForPlatform platform f + bcsymbolmapZipName d = bcsymbolmapArchiveName d version + bcsymbolmapPath d = platformBuildDirectory bcsymbolmapNameFrom d + + +-- | Retrieves all the bcsymbolmap files using the engine and unzip the contents +getAndUnzipBcsymbolmapsWithEngine' + :: FilePath -- ^ The `FilePath` to the engine + -> InvertedRepositoryMap -- ^ The map used to resolve from a `FrameworkVersion` to the path of the dSYM in the cache + -> FrameworkVersion -- ^ The `FrameworkVersion` identifying the Framework + -> TargetPlatform -- ^ The `TargetPlatform` to limit the operation to + -> ExceptT + DWARFOperationError + (ReaderT (CachePrefix, Bool) IO) + () +getAndUnzipBcsymbolmapsWithEngine' enginePath reverseRomeMap fVersion@(FrameworkVersion f@(Framework fwn _ fwps) _) platform + = when (platform `elem` fwps) $ do + + dwarfUUIDs <- withExceptT (const ErrorGettingDwarfUUIDs) + $ dwarfUUIDsFrom (frameworkDirectory fwn) + eitherDwarfUUIDsOrSucces <- forM + dwarfUUIDs + (\dwarfUUID -> lift $ runExceptT + (withExceptT (\e -> (dwarfUUID, e)) $ getAndUnzipBcsymbolmapWithEngine + enginePath + reverseRomeMap + fVersion + platform + dwarfUUID + ) + ) + + let failedUUIDsAndErrors = lefts eitherDwarfUUIDsOrSucces + unless (null failedUUIDsAndErrors) $ throwError $ FailedDwarfUUIDs + failedUUIDsAndErrors + where + frameworkNameWithFrameworkExtension = appendFrameworkExtensionTo f + platformBuildDirectory = + carthageArtifactsBuildDirectoryForPlatform platform f + frameworkDirectory = + platformBuildDirectory frameworkNameWithFrameworkExtension + + +-- | Retrieves a Framework using the engine and unzip the contents +getAndUnzipFrameworkWithEngine + :: FilePath -- ^ The `FilePath` to the engine + -> InvertedRepositoryMap -- ^ The map used to resolve from a `FrameworkVersion` to the path of the Framework in the cache + -> FrameworkVersion -- ^ The `FrameworkVersion` identifying the Framework + -> TargetPlatform -- ^ The `TargetPlatform` to limit the operation to + -> ExceptT String (ReaderT (CachePrefix, Bool) IO) () +getAndUnzipFrameworkWithEngine enginePath reverseRomeMap fVersion@(FrameworkVersion f@(Framework fwn _ fwps) version) platform + = when (platform `elem` fwps) $ do + (_, verbose) <- ask + frameworkBinary <- getFrameworkFromEngine enginePath + reverseRomeMap + fVersion + platform + deleteFrameworkDirectory fVersion platform verbose + unzipBinary frameworkBinary fwn frameworkZipName verbose + <* ifExists + frameworkExecutablePath + (makeExecutable frameworkExecutablePath) + where + frameworkZipName = frameworkArchiveName f version + frameworkExecutablePath = frameworkBuildBundleForPlatform platform f fwn + + +-- | Retrieves a dSYM using the engine and unzip the contents +getAndUnzipDSYMWithEngine + :: FilePath -- ^ The `FilePath` to the engine + -> InvertedRepositoryMap -- ^ The map used to resolve from a `FrameworkVersion` to the path of the dSYM in the cache + -> FrameworkVersion -- ^ The `FrameworkVersion` identifying the dSYM + -> TargetPlatform -- ^ The `TargetPlatform` to limit the operation to + -> ExceptT String (ReaderT (CachePrefix, Bool) IO) () +getAndUnzipDSYMWithEngine enginePath reverseRomeMap fVersion@(FrameworkVersion f@(Framework fwn _ fwps) version) platform + = when (platform `elem` fwps) $ do + (_, verbose) <- ask + dSYMBinary <- getDSYMFromEngine enginePath reverseRomeMap fVersion platform + deleteDSYMDirectory fVersion platform verbose + unzipBinary dSYMBinary fwn dSYMZipName verbose + where dSYMZipName = dSYMArchiveName f version + +-- | Retrieves an artifact using the engine +getArtifactFromEngine + :: FilePath -- ^ The `FilePath` to the engine + -> FilePath -- ^ The remote path + -> String -- ^ A colloquial name for the artifact + -> ExceptT String (ReaderT Bool IO) LBS.ByteString +getArtifactFromEngine enginePath remotePath artifactName = do + readerEnv@(verbose) <- ask + eitherArtifact :: Either IOError LBS.ByteString <- liftIO $ try $ runReaderT + (downloadBinaryWithEngine enginePath remotePath artifactName) + readerEnv + case eitherArtifact of + Left e -> + throwError + $ "Error: could not download " + <> artifactName + <> " : " + <> show e + Right artifactBinary -> return artifactBinary + +-- | Downloads an artifact stored at a given path using the engine +downloadBinaryWithEngine + :: FilePath -- ^ The `FilePath` to the engine + -> FilePath + -> FilePath + -> (ReaderT Bool IO) LBS.ByteString +downloadBinaryWithEngine enginePath objectRemotePath objectName = do + verbose <- ask + let cmd = Turtle.fromString enginePath + let sayFunc = if verbose then sayLnWithTime else sayLn + when verbose + $ sayLnWithTime + $ "Invoking engine " + <> show enginePath + <> " to download " + <> objectName + <> " from: " + <> objectRemotePath + exitCode <- Turtle.proc + cmd + ["download", Turtle.fromString objectRemotePath, Turtle.fromString objectRemotePath] + (return $ Turtle.unsafeTextToLine "") + case exitCode of + Turtle.ExitSuccess -> return () + Turtle.ExitFailure n -> sayFunc + $ "Error: could not download " + <> objectRemotePath + binaryExists <- liftIO . doesFileExist $ objectRemotePath + if binaryExists + then liftIO $ LBS.readFile objectRemotePath + else fail "Binary was not downloaded by engine" diff --git a/src/Engine/Probing.hs b/src/Engine/Probing.hs new file mode 100644 index 0000000..1fabbc4 --- /dev/null +++ b/src/Engine/Probing.hs @@ -0,0 +1,71 @@ +{-# LANGUAGE OverloadedStrings #-} + +module Engine.Probing where + +import Control.Monad.IO.Class +import Data.Carthage.TargetPlatform +import Data.List (intersect) +import Data.Romefile (_frameworkPlatforms) +import Types hiding (version) +import Utils +import qualified Turtle + + +-- | Probes a `FilePath` to check if each `FrameworkVersion` exists for each `TargetPlatform` +probeEngineForFrameworks + :: MonadIO m + => FilePath -- ^ The `FilePath` to the engine + -> InvertedRepositoryMap -- ^ The map used to resolve `FrameworkName`s to `GitRepoName`s. + -> [FrameworkVersion] -- ^ A list of `FrameworkVersion` to probe for. + -> [TargetPlatform] -- ^ A list target platforms restricting the scope of this action. + -> m [FrameworkAvailability] +probeEngineForFrameworks lCacheDir reverseRomeMap frameworkVersions + = sequence . probeForEachFramework + where + probeForEachFramework = mapM + (probeEngineForFramework lCacheDir reverseRomeMap) + frameworkVersions + + +-- | Probes the engine at `FilePath` to check if a `FrameworkVersion` exists for each `TargetPlatform` +probeEngineForFramework + :: MonadIO m + => FilePath -- ^ The `FilePath` to the engine + -> InvertedRepositoryMap -- ^ The map used to resolve `FrameworkName`s to `GitRepoName`s. + -> FrameworkVersion -- ^ The `FrameworkVersion` to probe for. + -> [TargetPlatform] -- ^ A list target platforms restricting the scope of this action. + -> m FrameworkAvailability +probeEngineForFramework lCacheDir reverseRomeMap frameworkVersion platforms + = fmap (FrameworkAvailability frameworkVersion) probeForEachPlatform + where + probeForEachPlatform = mapM + (probeEngineForFrameworkOnPlatform lCacheDir + reverseRomeMap + frameworkVersion + ) + (platforms `intersect` (_frameworkPlatforms . _framework $ frameworkVersion)) + + +-- | Probes the engine at `FilePath` to check if a `FrameworkVersion` exists for a given `TargetPlatform` +probeEngineForFrameworkOnPlatform + :: MonadIO m + => FilePath -- ^ The `FilePath` to the engine + -> InvertedRepositoryMap -- ^ The map used to resolve `FrameworkName`s to `GitRepoName`s. + -> FrameworkVersion -- ^ The `FrameworkVersion` to probe for. + -> TargetPlatform -- ^ A target platforms restricting the scope of this action. + -> m PlatformAvailability +probeEngineForFrameworkOnPlatform enginePath reverseRomeMap (FrameworkVersion fwn version) platform + = do + let cmd = Turtle.fromString enginePath + exitCode <- Turtle.proc + cmd + ["list", Turtle.fromString remoteFrameworkUploadPath] + (return $ Turtle.unsafeTextToLine "") + case exitCode of + -- If engine exits with success, we assume the framework exists. + Turtle.ExitSuccess -> return (PlatformAvailability platform True) + Turtle.ExitFailure _ -> return (PlatformAvailability platform False) + where + remoteFrameworkUploadPath = + remoteFrameworkPath platform reverseRomeMap fwn version + diff --git a/src/Engine/Uploading.hs b/src/Engine/Uploading.hs new file mode 100644 index 0000000..fe511a3 --- /dev/null +++ b/src/Engine/Uploading.hs @@ -0,0 +1,135 @@ +{-# LANGUAGE OverloadedStrings #-} + +module Engine.Uploading where + +import qualified Codec.Archive.Zip as Zip +import Control.Monad (when) +import Control.Monad.Reader (ReaderT, ask, withReaderT) +import Control.Monad.IO.Class +import qualified Data.ByteString.Lazy as LBS +import Data.Carthage.TargetPlatform +import Data.Monoid ((<>)) +import Data.Romefile (Framework (..)) +import System.FilePath (()) +import Types hiding (version) +import Utils +import Xcode.DWARF +import qualified Turtle + + +-- | Uploads a Framework `Zip.Archive` to an engine. +uploadFrameworkToEngine + :: Zip.Archive -- ^ The `Zip.Archive` of the Framework. + -> FilePath -- ^ The `FilePath` to the engine. + -> InvertedRepositoryMap -- ^ The map used to resolve `FrameworkName`s to `GitRepoName`s. + -> FrameworkVersion -- ^ The `FrameworkVersion` identifying the Framework. + -> TargetPlatform -- ^ A `TargetPlatform`s restricting the scope of this action. + -> ReaderT (CachePrefix, Bool) IO () +uploadFrameworkToEngine frameworkArchive enginePath reverseRomeMap (FrameworkVersion f@(Framework fwn _ fwps) version) platform + = when (platform `elem` fwps) $ do + (CachePrefix prefix, verbose) <- ask + withReaderT (const verbose) $ uploadBinary + enginePath + (Zip.fromArchive frameworkArchive) + (prefix remoteFrameworkUploadPath) + fwn + where + remoteFrameworkUploadPath = + remoteFrameworkPath platform reverseRomeMap f version + + + +-- | Uploads a dSYM `Zip.Archive` to an engine. +uploadDsymToEngine + :: Zip.Archive -- ^ The `Zip.Archive` of the dSYM. + -> FilePath -- ^ The `FilePath` to the engine. + -> InvertedRepositoryMap -- ^ The map used to resolve `FrameworkName`s to `GitRepoName`s. + -> FrameworkVersion -- ^ The `FrameworkVersion` identifying the Framework and the dSYM. + -> TargetPlatform -- ^ A `TargetPlatform` restricting the scope of this action. + -> ReaderT (CachePrefix, Bool) IO () +uploadDsymToEngine dSYMArchive enginePath reverseRomeMap (FrameworkVersion f@(Framework fwn _ fwps) version) platform + = when (platform `elem` fwps) $ do + (CachePrefix prefix, verbose) <- ask + withReaderT (const verbose) $ uploadBinary + enginePath + (Zip.fromArchive dSYMArchive) + (prefix remoteDsymUploadPath) + (fwn <> ".dSYM") + where remoteDsymUploadPath = remoteDsymPath platform reverseRomeMap f version + + + +-- | Uploads a bcsymbolmap `Zip.Archive` to an engine. +uploadBcsymbolmapToEngine + :: DwarfUUID -- ^ The UUID of the bcsymbolmap + -> Zip.Archive -- ^ The `Zip.Archive` of the dSYM. + -> FilePath -- ^ The `FilePath` to the engine. + -> InvertedRepositoryMap -- ^ The map used to resolve `FrameworkName`s to `GitRepoName`s. + -> FrameworkVersion -- ^ The `FrameworkVersion` identifying the Framework and the dSYM. + -> TargetPlatform -- ^ A `TargetPlatform` restricting the scope of this action. + -> ReaderT (CachePrefix, Bool) IO () +uploadBcsymbolmapToEngine dwarfUUID dwarfArchive enginePath reverseRomeMap (FrameworkVersion f@(Framework fwn _ fwps) version) platform + = when (platform `elem` fwps) $ do + (CachePrefix prefix, verbose) <- ask + withReaderT (const verbose) $ uploadBinary + enginePath + (Zip.fromArchive dwarfArchive) + (prefix remoteBcsymbolmapUploadPath) + (fwn <> "." <> bcsymbolmapNameFrom dwarfUUID) + where + remoteBcsymbolmapUploadPath = + remoteBcsymbolmapPath dwarfUUID platform reverseRomeMap f version + + + +-- | Uploads a .version file using an engine +uploadVersionFileToEngine' + :: FilePath -- ^ The `FilePath` to the engine. + -> LBS.ByteString -- ^ The contents of the .version file. + -> ProjectNameAndVersion -- ^ The information used to derive the name and path for the .version file. + -> ReaderT (CachePrefix, Bool) IO () +uploadVersionFileToEngine' enginePath versionFileContent projectNameAndVersion = + do + (CachePrefix prefix, verbose) <- ask + withReaderT (const verbose) $ uploadBinary + enginePath + versionFileContent + (prefix versionFileRemotePath) + versionFileName + where + versionFileName = versionFileNameForProjectName $ fst projectNameAndVersion + versionFileRemotePath = remoteVersionFilePath projectNameAndVersion + + + +-- | Uploads an artifact using an engine +uploadBinary + :: MonadIO a + => FilePath -- ^ The `FilePath` to the engine. + -> LBS.ByteString + -> FilePath + -> FilePath + -> ReaderT Bool a () +uploadBinary enginePath binaryZip destinationPath objectName = + do + verbose <- ask + let cmd = Turtle.fromString enginePath + liftIO $ saveBinaryToFile binaryZip destinationPath + when verbose + $ sayLnWithTime + $ "Invoking engine " + <> show enginePath + <> " to upload " + <> destinationPath + exitCode <- Turtle.proc + cmd + ["upload", Turtle.fromString destinationPath, Turtle.fromString destinationPath] + (return $ Turtle.unsafeTextToLine "") + case exitCode of + Turtle.ExitSuccess -> return () + Turtle.ExitFailure n -> sayLn + $ "Error " + <> show n + <> ": could not upload " + <> destinationPath + diff --git a/src/Lib.hs b/src/Lib.hs index 51bf4f4..042a2c5 100644 --- a/src/Lib.hs +++ b/src/Lib.hs @@ -18,6 +18,9 @@ import Caches.Local.Uploading import Caches.S3.Downloading import Caches.S3.Probing import Caches.S3.Uploading +import Engine.Downloading +import Engine.Probing +import Engine.Uploading import Configuration import Control.Applicative ((<|>)) import Control.Concurrent.Async.Lifted.Safe (mapConcurrently_, mapConcurrently, concurrently_) @@ -33,8 +36,7 @@ import Data.Yaml (encodeFile) import Data.IORef (newIORef) import Data.Carthage.Cartfile import Data.Carthage.TargetPlatform -import Data.Either.Extra (maybeToEither, eitherToMaybe, isRight, mapLeft) -import Data.Either.Utils (fromLeft) +import Data.Either.Extra (maybeToEither, eitherToMaybe, mapLeft) import Data.Maybe (fromMaybe, maybe) import Data.Monoid ((<>)) import Data.Romefile @@ -61,7 +63,6 @@ import Utils import Xcode.DWARF - s3EndpointOverride :: URL -> AWS.Service s3EndpointOverride (URL (Absolute h) _ _) = let isSecure = secure h @@ -155,18 +156,23 @@ getAWSRegion = do <&> AWS.configure (maybe S3.s3 s3EndpointOverride endpointURL) ) -bothCacheKeysMissingMessage :: String -bothCacheKeysMissingMessage - = "Error: expected at least one of \"local\" or \ - \\"S3-Bucket\" key in the [Cache] section of your Romefile." +allCacheKeysMissingMessage :: String +allCacheKeysMissingMessage + = "Error: expected at least one of \"local\", \ + \\"s3Bucket\" or \"engine\" in the cache definition of your Romefile." + +conflictingCachesMessage :: String +conflictingCachesMessage + = "Error: both \"s3Bucket\" and \"engine\" defined. \ + \ Rome cannot use both, choose one." conflictingSkipLocalCacheOptionMessage :: String conflictingSkipLocalCacheOptionMessage - = "Error: only \"local\" key is present \ - \in the [Cache] section of your Romefile but you have asked Rome to skip \ + = "Error: only \"local\" defined as cache \ + \in your Romefile, but you have asked Rome to skip \ \this cache." --- | Runs Rome with `RomeOptions` on a given a `AWS.Env`. +-- | Runs Rome with a set of `RomeOptions`. runRomeWithOptions :: RomeOptions -- ^ The `RomeOptions` to run Rome with. -> RomeVersion @@ -203,11 +209,12 @@ runUDCCommand command absoluteRomefilePath verbose romeVersion = do let cInfo = romeFile ^. cacheInfo let mS3BucketName = S3.BucketName <$> cInfo ^. bucket - mlCacheDir <- liftIO $ traverse absolutizePath $ cInfo ^. localCacheDir + mlCacheDir <- liftIO $ traverse absolutizePath $ cInfo ^. localCacheDir + mEnginePath <- liftIO $ traverse absolutizePath $ cInfo ^. enginePath case command of - Upload (RomeUDCPayload gitRepoNames platforms cachePrefixString skipLocalCache noIgnoreFlag noSkipCurrentFlag concurrentlyFalg) + Upload (RomeUDCPayload gitRepoNames platforms cachePrefixString skipLocalCache noIgnoreFlag noSkipCurrentFlag concurrentlyFlag) -> sayVersionWarning romeVersion verbose *> performWithDefaultFlow uploadArtifacts @@ -215,7 +222,7 @@ runUDCCommand command absoluteRomefilePath verbose romeVersion = do , noIgnoreFlag , skipLocalCache , noSkipCurrentFlag - , concurrentlyFalg + , concurrentlyFlag ) (repositoryMapEntries, ignoreMapEntries, currentMapEntries) gitRepoNames @@ -223,9 +230,10 @@ runUDCCommand command absoluteRomefilePath verbose romeVersion = do cachePrefixString mS3BucketName mlCacheDir + mEnginePath platforms - Download (RomeUDCPayload gitRepoNames platforms cachePrefixString skipLocalCache noIgnoreFlag noSkipCurrentFlag concurrentlyFalg) + Download (RomeUDCPayload gitRepoNames platforms cachePrefixString skipLocalCache noIgnoreFlag noSkipCurrentFlag concurrentlyFlag) -> sayVersionWarning romeVersion verbose *> performWithDefaultFlow downloadArtifacts @@ -233,7 +241,7 @@ runUDCCommand command absoluteRomefilePath verbose romeVersion = do , noIgnoreFlag , skipLocalCache , noSkipCurrentFlag - , concurrentlyFalg + , concurrentlyFlag ) (repositoryMapEntries, ignoreMapEntries, currentMapEntries) gitRepoNames @@ -241,6 +249,7 @@ runUDCCommand command absoluteRomefilePath verbose romeVersion = do cachePrefixString mS3BucketName mlCacheDir + mEnginePath platforms List (RomeListPayload listMode platforms cachePrefixString printFormat noIgnoreFlag noSkipCurrentFlag) @@ -281,6 +290,7 @@ runUDCCommand command absoluteRomefilePath verbose romeVersion = do (listArtifacts mS3BucketName mlCacheDir + mEnginePath listMode (reverseRepositoryMap <> if _noSkipCurrent noSkipCurrentFlag then currentInvertedMap @@ -317,6 +327,7 @@ runUDCCommand command absoluteRomefilePath verbose romeVersion = do type FlowFunction = Maybe S3.BucketName -- ^ Just an S3 Bucket name or Nothing -> Maybe FilePath -- ^ Just the path to the local cache or Nothing + -> Maybe FilePath -- ^ Just the path to the engine or Nothing -> InvertedRepositoryMap -- ^ The map used to resolve `FrameworkName`s to `ProjectName`s. -> [FrameworkVersion] -- ^ A list of `FrameworkVersion` from which to derive Frameworks, dSYMs and .version files -> [TargetPlatform] -- ^ A list of `TargetPlatform` to restrict this operation to. @@ -341,9 +352,10 @@ performWithDefaultFlow -> String -- cachePrefixString -> Maybe S3.BucketName -- mS3BucketName -> Maybe String -- mlCacheDir + -> Maybe String -- mEnginePath -> [TargetPlatform] -- platforms -> RomeMonad () -performWithDefaultFlow flowFunc (verbose, noIgnoreFlag, skipLocalCache, noSkipCurrentFlag, concurrentlyFlag) (repositoryMapEntries, ignoreMapEntries, currentMapEntries) gitRepoNames cartfileEntries cachePrefixString mS3BucketName mlCacheDir platforms +performWithDefaultFlow flowFunc (verbose, noIgnoreFlag, skipLocalCache, noSkipCurrentFlag, concurrentlyFlag) (repositoryMapEntries, ignoreMapEntries, currentMapEntries) gitRepoNames cartfileEntries cachePrefixString mS3BucketName mlCacheDir mEnginePath platforms = do let ignoreFrameworks = concatMap _frameworks ignoreMapEntries @@ -374,6 +386,7 @@ performWithDefaultFlow flowFunc (verbose, noIgnoreFlag, skipLocalCache, noSkipCu (flowFunc mS3BucketName mlCacheDir + mEnginePath reverseRepositoryMap (derivedFrameworkVersions `filterOutFrameworksAndVersionsIfNotIn` finalIgnoreNames @@ -397,6 +410,7 @@ performWithDefaultFlow flowFunc (verbose, noIgnoreFlag, skipLocalCache, noSkipCu (flowFunc mS3BucketName mlCacheDir + mEnginePath currentInvertedMap (currentFrameworkVersions `filterOutFrameworksAndVersionsIfNotIn` finalIgnoreNames @@ -428,6 +442,7 @@ performWithDefaultFlow flowFunc (verbose, noIgnoreFlag, skipLocalCache, noSkipCu runReaderT (flowFunc mS3BucketName mlCacheDir + mEnginePath (reverseRepositoryMap <> currentInvertedMap) frameworkVersions platforms @@ -438,6 +453,7 @@ performWithDefaultFlow flowFunc (verbose, noIgnoreFlag, skipLocalCache, noSkipCu listArtifacts :: Maybe S3.BucketName -- ^ Just an S3 Bucket name or Nothing -> Maybe FilePath -- ^ Just the path to the local cache or Nothing + -> Maybe FilePath -- ^ Just the path to the engine or Nothing -> ListMode -- ^ A list mode to execute this operation in. -> InvertedRepositoryMap -- ^ The map used to resolve `FrameworkName`s to `ProjectName`s. -> [FrameworkVersion] -- ^ A list of `FrameworkVersion` from which to derive Frameworks @@ -447,13 +463,14 @@ listArtifacts (CachePrefix, SkipLocalCacheFlag, Bool) RomeMonad () -listArtifacts mS3BucketName mlCacheDir listMode reverseRepositoryMap frameworkVersions platforms format +listArtifacts mS3BucketName mlCacheDir mEnginePath listMode reverseRepositoryMap frameworkVersions platforms format = do (_, _, verbose) <- ask let sayFunc = if verbose then sayLnWithTime else sayLn repoAvailabilities <- getProjectAvailabilityFromCaches mS3BucketName mlCacheDir + mEnginePath reverseRepositoryMap frameworkVersions platforms @@ -471,6 +488,7 @@ listArtifacts mS3BucketName mlCacheDir listMode reverseRepositoryMap frameworkVe getProjectAvailabilityFromCaches :: Maybe S3.BucketName -- ^ Just an S3 Bucket name or Nothing -> Maybe FilePath -- ^ Just the path to the local cache or Nothing + -> Maybe FilePath -- ^ Just the path to the engine or Nothing -> InvertedRepositoryMap -- ^ The map used to resolve `FrameworkName`s to `ProjectName`s. -> [FrameworkVersion] -- ^ A list of `FrameworkVersion` from which to derive Frameworks, dSYMs and .version files -> [TargetPlatform] -- ^ A list of `TargetPlatform`s to limit the operation to. @@ -478,7 +496,7 @@ getProjectAvailabilityFromCaches (CachePrefix, SkipLocalCacheFlag, Bool) RomeMonad [ProjectAvailability] -getProjectAvailabilityFromCaches (Just s3BucketName) _ reverseRepositoryMap frameworkVersions platforms +getProjectAvailabilityFromCaches (Just s3BucketName) _ Nothing reverseRepositoryMap frameworkVersions platforms = do env <- lift getAWSEnv (cachePrefix, _, verbose) <- ask @@ -494,7 +512,7 @@ getProjectAvailabilityFromCaches (Just s3BucketName) _ reverseRepositoryMap fram reverseRepositoryMap availabilities -getProjectAvailabilityFromCaches Nothing (Just lCacheDir) reverseRepositoryMap frameworkVersions platforms +getProjectAvailabilityFromCaches Nothing (Just lCacheDir) Nothing reverseRepositoryMap frameworkVersions platforms = do (cachePrefix, SkipLocalCacheFlag skipLocalCache, _) <- ask when skipLocalCache $ throwError conflictingSkipLocalCacheOptionMessage @@ -508,8 +526,20 @@ getProjectAvailabilityFromCaches Nothing (Just lCacheDir) reverseRepositoryMap f reverseRepositoryMap availabilities -getProjectAvailabilityFromCaches Nothing Nothing _ _ _ = - throwError bothCacheKeysMissingMessage +getProjectAvailabilityFromCaches Nothing _ (Just ePath) reverseRepositoryMap frameworkVersions platforms + = do + availabilities <- probeEngineForFrameworks ePath + reverseRepositoryMap + frameworkVersions + platforms + return $ getMergedGitRepoAvailabilitiesFromFrameworkAvailabilities + reverseRepositoryMap + availabilities +getProjectAvailabilityFromCaches (Just _) _ (Just _) _ _ _ = + throwError conflictingCachesMessage +getProjectAvailabilityFromCaches Nothing Nothing Nothing _ _ _ = + throwError allCacheKeysMissingMessage + @@ -517,27 +547,32 @@ getProjectAvailabilityFromCaches Nothing Nothing _ _ _ = downloadArtifacts :: Maybe S3.BucketName -- ^ Just an S3 Bucket name or Nothing -> Maybe FilePath -- ^ Just the path to the local cache or Nothing + -> Maybe FilePath -- ^ Just the path to the engine or Nothing -> InvertedRepositoryMap -- ^ The map used to resolve `FrameworkName`s to `ProjectName`s. -> [FrameworkVersion] -- ^ A list of `FrameworkVersion` from which to derive Frameworks, dSYMs and .version files -> [TargetPlatform] -- ^ A list of `TargetPlatform`s to limit the operation to. -> ReaderT - (CachePrefix, SkipLocalCacheFlag, ConcurrentlyFlag, Bool) + ( CachePrefix + , SkipLocalCacheFlag + , ConcurrentlyFlag + , Bool + ) RomeMonad () -downloadArtifacts mS3BucketName mlCacheDir reverseRepositoryMap frameworkVersions platforms +downloadArtifacts mS3BucketName mlCacheDir mEnginePath reverseRepositoryMap frameworkVersions platforms = do - (cachePrefix, skipLocalCacheFlag@(SkipLocalCacheFlag skipLocalCache), conconrrentlyFlag@(ConcurrentlyFlag performConcurrently), verbose) <- + (cachePrefix, skipLocalCacheFlag@(SkipLocalCacheFlag skipLocalCache), concurrentlyFlag@(ConcurrentlyFlag performConcurrently), verbose) <- ask let sayFunc :: MonadIO m => String -> m () sayFunc = if verbose then sayLnWithTime else sayLn - case (mS3BucketName, mlCacheDir) of + case (mS3BucketName, mlCacheDir, mEnginePath) of - (Just s3BucketName, lCacheDir) -> do + (Just s3BucketName, lCacheDir, Nothing) -> do env <- lift getAWSEnv let uploadDownloadEnv = - (env, cachePrefix, skipLocalCacheFlag, conconrrentlyFlag, verbose) + (env, cachePrefix, skipLocalCacheFlag, concurrentlyFlag, verbose) let action1 = runReaderT (downloadFrameworksAndArtifactsFromCaches s3BucketName lCacheDir @@ -556,7 +591,7 @@ downloadArtifacts mS3BucketName mlCacheDir reverseRepositoryMap frameworkVersion then liftIO $ concurrently_ action1 action2 else liftIO $ action1 >> action2 - (Nothing, Just lCacheDir) -> do + (Nothing, Just lCacheDir, Nothing) -> do let readerEnv = (cachePrefix, verbose) when skipLocalCache $ throwError conflictingSkipLocalCacheOptionMessage @@ -582,8 +617,30 @@ downloadArtifacts mS3BucketName mlCacheDir reverseRepositoryMap frameworkVersion mapM_ (whenLeft sayFunc) errors ) readerEnv - - (Nothing, Nothing) -> throwError bothCacheKeysMissingMessage + -- Use engine + (Nothing, lCacheDir, Just ePath) -> do + let engineEnv = (cachePrefix, skipLocalCacheFlag, concurrentlyFlag, verbose) + let action1 = runReaderT + (downloadFrameworksAndArtifactsWithEngine ePath + lCacheDir + reverseRepositoryMap + frameworkVersions + platforms + ) + engineEnv + let action2 = runReaderT + (downloadVersionFilesWithEngine ePath + lCacheDir + gitRepoNamesAndVersions + ) + engineEnv + if performConcurrently + then liftIO $ concurrently_ action1 action2 + else liftIO $ action1 >> action2 + -- Misconfigured + (Nothing, Nothing, Nothing) -> throwError allCacheKeysMissingMessage + -- Misconfigured + (Just s3BucketName, _, Just ePath) -> throwError conflictingCachesMessage where gitRepoNamesAndVersions :: [ProjectNameAndVersion] @@ -597,19 +654,25 @@ downloadArtifacts mS3BucketName mlCacheDir reverseRepositoryMap frameworkVersion uploadArtifacts :: Maybe S3.BucketName -- ^ Just an S3 Bucket name or Nothing -> Maybe FilePath -- ^ Just the path to the local cache or Nothing + -> Maybe FilePath -- ^ Just the path to the engine or Nothing -> InvertedRepositoryMap -- ^ The map used to resolve `FrameworkName`s to `ProjectName`s. -> [FrameworkVersion] -- ^ A list of `FrameworkVersion` from which to derive Frameworks, dSYMs and .version files -> [TargetPlatform] -- ^ A list of `TargetPlatform` to restrict this operation to. -> ReaderT - (CachePrefix, SkipLocalCacheFlag, ConcurrentlyFlag, Bool) + ( CachePrefix + , SkipLocalCacheFlag + , ConcurrentlyFlag + , Bool + ) RomeMonad () -uploadArtifacts mS3BucketName mlCacheDir reverseRepositoryMap frameworkVersions platforms +uploadArtifacts mS3BucketName mlCacheDir mEnginePath reverseRepositoryMap frameworkVersions platforms = do (cachePrefix, skipLocalCacheFlag@(SkipLocalCacheFlag skipLocalCache), concurrentlyFlag@(ConcurrentlyFlag performConcurrently), verbose) <- ask - case (mS3BucketName, mlCacheDir) of - (Just s3BucketName, lCacheDir) -> do + case (mS3BucketName, mlCacheDir, mEnginePath) of + -- S3 Cache, but no engine + (Just s3BucketName, lCacheDir, Nothing) -> do awsEnv <- lift getAWSEnv let uploadDownloadEnv = ( awsEnv @@ -635,8 +698,8 @@ uploadArtifacts mS3BucketName mlCacheDir reverseRepositoryMap frameworkVersions if performConcurrently then liftIO $ concurrently_ action1 action2 else liftIO $ action1 >> action2 - - (Nothing, Just lCacheDir) -> do + -- No remotes, just local + (Nothing, Just lCacheDir, Nothing) -> do let readerEnv = (cachePrefix, verbose) when skipLocalCache $ throwError conflictingSkipLocalCacheOptionMessage liftIO @@ -650,8 +713,32 @@ uploadArtifacts mS3BucketName mlCacheDir reverseRepositoryMap frameworkVersions >> runReaderT (saveVersionFilesToLocalCache lCacheDir gitRepoNamesAndVersions) readerEnv - - (Nothing, Nothing) -> throwError bothCacheKeysMissingMessage + -- Engine, maybe Cache + (Nothing, lCacheDir, Just enginePath) -> do + let engineEnv = + ( cachePrefix + , skipLocalCacheFlag + , concurrentlyFlag + , verbose + ) + let action1 = runReaderT + (uploadFrameworksAndArtifactsToEngine enginePath + lCacheDir + reverseRepositoryMap + frameworkVersions + platforms + ) + engineEnv + let action2 = runReaderT + (uploadVersionFilesToEngine enginePath + lCacheDir + gitRepoNamesAndVersions + ) + engineEnv + if performConcurrently + then liftIO $ concurrently_ action1 action2 + else liftIO $ action1 >> action2 + (Nothing, Nothing, Nothing) -> throwError allCacheKeysMissingMessage where gitRepoNamesAndVersions :: [ProjectNameAndVersion] gitRepoNamesAndVersions = repoNamesAndVersionForFrameworkVersions @@ -659,6 +746,47 @@ uploadArtifacts mS3BucketName mlCacheDir reverseRepositoryMap frameworkVersions frameworkVersions +-- | Uploads a lest of .version files to the engine. +uploadVersionFilesToEngine + :: FilePath -- ^ The engine definition. + -> Maybe FilePath -- ^ Just the path to the local cache or Nothing. + -> [ProjectNameAndVersion] -- ^ A list of `ProjectName` and `Version` information. + -> ReaderT (CachePrefix, SkipLocalCacheFlag, ConcurrentlyFlag, Bool) IO () +uploadVersionFilesToEngine enginePath mlCacheDir = + mapM_ (uploadVersionFileToEngine enginePath mlCacheDir) + + +-- | Uploads a .version file to the engine. +uploadVersionFileToEngine + :: FilePath -- ^ The engine definition. + -> Maybe FilePath -- ^ Just the path to the local cache or Nothing. + -> ProjectNameAndVersion -- ^ The information used to derive the name and path for the .version file. + -> ReaderT (CachePrefix, SkipLocalCacheFlag, ConcurrentlyFlag, Bool) IO () +uploadVersionFileToEngine enginePath mlCacheDir projectNameAndVersion = do + (cachePrefix, SkipLocalCacheFlag skipLocalCache, _, verbose) <- ask + + versionFileExists <- liftIO $ doesFileExist versionFileLocalPath + + when versionFileExists $ do + versionFileContent <- liftIO $ LBS.readFile versionFileLocalPath + unless skipLocalCache + $ maybe (return ()) liftIO + $ saveVersionFileBinaryToLocalCache + <$> mlCacheDir + <*> Just cachePrefix + <*> Just versionFileContent + <*> Just projectNameAndVersion + <*> Just verbose + liftIO $ runReaderT + (uploadVersionFileToEngine' enginePath + versionFileContent + projectNameAndVersion + ) + (cachePrefix, verbose) + where + + versionFileName = versionFileNameForProjectName $ fst projectNameAndVersion + versionFileLocalPath = carthageBuildDirectory versionFileName -- | Uploads a lest of .version files to the caches. uploadVersionFilesToCaches @@ -918,6 +1046,134 @@ saveFrameworkAndArtifactsToLocalCache lCacheDir reverseRomeMap fVersion@(Framewo + +uploadFrameworksAndArtifactsToEngine + :: FilePath -- ^ The path to the engine or Nothing + -> Maybe FilePath -- ^ Just the path to the local cache or Nothing + -> InvertedRepositoryMap -- ^ The map used to resolve `FrameworkName`s to `ProjectName`s. + -> [FrameworkVersion] -- ^ A list of `FrameworkVersion` from which to derive Frameworks, dSYMs and .verison files + -> [TargetPlatform] -- ^ A list of `TargetPlatform` to restrict this operation to. + -> ReaderT (CachePrefix, SkipLocalCacheFlag, ConcurrentlyFlag, Bool) IO () +uploadFrameworksAndArtifactsToEngine enginePath mlCacheDir reverseRomeMap fvs platforms = do + (_, _, ConcurrentlyFlag performConcurrently, _) <- ask + if performConcurrently + then mapConcurrently_ uploadConcurrently fvs + else mapM_ (sequence . upload) platforms + where + uploadConcurrently f = mapConcurrently + (uploadFrameworkAndArtifactsWithEngine enginePath + mlCacheDir + reverseRomeMap + f + ) + platforms + upload = mapM + (uploadFrameworkAndArtifactsWithEngine enginePath mlCacheDir reverseRomeMap) + fvs + + +uploadFrameworkAndArtifactsWithEngine + :: FilePath -- ^ The path to the engine or Nothing + -> Maybe FilePath -- ^ Just the path to the local cache or Nothing + -> InvertedRepositoryMap -- ^ The map used to resolve `FrameworkName`s to `ProjectName`s. + -> FrameworkVersion -- ^ A`FrameworkVersion` from which to derive Frameworks, dSYMs and .verison files + -> TargetPlatform -- ^ A `TargetPlatform` to restrict this operation to. + -> ReaderT (CachePrefix, SkipLocalCacheFlag, ConcurrentlyFlag, Bool) IO () +uploadFrameworkAndArtifactsWithEngine enginePath mlCacheDir reverseRomeMap fVersion@(FrameworkVersion f@(Framework fwn fwt fwps) _) platform + = do + (cachePrefix, s@(SkipLocalCacheFlag skipLocalCache), ConcurrentlyFlag performConcurrently, verbose) <- ask + let readerEnv = (cachePrefix, verbose) + void . runExceptT $ do + frameworkArchive <- createZipArchive frameworkDirectory verbose + unless skipLocalCache + $ maybe (return ()) liftIO + $ runReaderT + <$> ( saveFrameworkToLocalCache + <$> mlCacheDir + <*> Just frameworkArchive + <*> Just reverseRomeMap + <*> Just fVersion + <*> Just platform + ) + <*> Just (cachePrefix, s, verbose) + liftIO $ runReaderT + (uploadFrameworkToEngine frameworkArchive + enginePath + reverseRomeMap + fVersion + platform + ) + readerEnv + + void . runExceptT $ do + dSYMArchive <- createZipArchive dSYMdirectory verbose + unless skipLocalCache + $ maybe (return ()) liftIO + $ runReaderT + <$> ( saveDsymToLocalCache + <$> mlCacheDir + <*> Just dSYMArchive + <*> Just reverseRomeMap + <*> Just fVersion + <*> Just platform + ) + <*> Just (cachePrefix, s, verbose) + liftIO $ runReaderT + (uploadDsymToEngine dSYMArchive + enginePath + reverseRomeMap + fVersion + platform + ) + readerEnv + + void . runExceptT $ do + dwarfUUIDs <- dwarfUUIDsFrom (frameworkDirectory fwn) + maybeUUIDsArchives <- liftIO $ forM dwarfUUIDs $ \dwarfUUID -> + runMaybeT $ do + dwarfArchive <- exceptToMaybeT + $ createZipArchive (bcSymbolMapPath dwarfUUID) verbose + return (dwarfUUID, dwarfArchive) + + unless skipLocalCache + $ forM_ maybeUUIDsArchives + $ mapM + $ \(dwarfUUID, dwarfArchive) -> + maybe (return ()) liftIO + $ runReaderT + <$> ( saveBcsymbolmapToLocalCache + <$> mlCacheDir + <*> Just dwarfUUID + <*> Just dwarfArchive + <*> Just reverseRomeMap + <*> Just fVersion + <*> Just platform + ) + <*> Just (cachePrefix, s, verbose) + + forM_ maybeUUIDsArchives $ mapM $ \(dwarfUUID, dwarfArchive) -> + liftIO $ runReaderT + (uploadBcsymbolmapToEngine dwarfUUID + dwarfArchive + enginePath + reverseRomeMap + fVersion + platform + ) + readerEnv + where + + frameworkNameWithFrameworkExtension = appendFrameworkExtensionTo f + platformBuildDirectory = + carthageArtifactsBuildDirectoryForPlatform platform f + frameworkDirectory = + platformBuildDirectory frameworkNameWithFrameworkExtension + dSYMNameWithDSYMExtension = frameworkNameWithFrameworkExtension <> ".dSYM" + dSYMdirectory = platformBuildDirectory dSYMNameWithDSYMExtension + bcSymbolMapPath d = platformBuildDirectory bcsymbolmapNameFrom d + + + -- | Downloads a list of .version files from an S3 Bucket or a local cache. downloadVersionFilesFromCaches :: S3.BucketName -- ^ The cache definition. @@ -1036,7 +1292,7 @@ downloadFrameworksAndArtifactsFromCaches s3BucketName mlCacheDir reverseRomeMap -- | Downloads a Framework and it's relative dSYM from and S3 Bucket or a local cache. -- | If the Framework and dSYM are not found in the local cache then they are downloaded from S3. --- | If SkipLocalCache is specified, th local cache is ignored. +-- | If SkipLocalCache is specified, the local cache is ignored. downloadFrameworkAndArtifactsFromCaches :: S3.BucketName -- ^ The cache definition. -> Maybe FilePath -- ^ Just the path to the local cache or Nothing. @@ -1181,8 +1437,6 @@ downloadFrameworkAndArtifactsFromCaches s3BucketName (Just lCacheDir) reverseRom dSYMName = fwn <> ".dSYM" frameworkExecutablePath = frameworkBuildBundleForPlatform platform f fwn - - downloadFrameworkAndArtifactsFromCaches s3BucketName Nothing reverseRomeMap fVersion@(FrameworkVersion (Framework fwn _ _) _) platform = do (env, cachePrefix, _, _, verbose) <- ask @@ -1221,6 +1475,304 @@ downloadFrameworkAndArtifactsFromCaches s3BucketName Nothing reverseRomeMap fVer +-- | Downloads a list of Frameworks and relative dSYMs with the engine or a local cache. +downloadFrameworksAndArtifactsWithEngine + :: FilePath -- ^ The path to the engine. + -> Maybe FilePath -- ^ Just the path to the local cache or Nothing. + -> InvertedRepositoryMap -- ^ The map used to resolve `FrameworkName`s to `ProjectName`s. + -> [FrameworkVersion] -- ^ A list of `FrameworkVersion` identifying the Frameworks and dSYMs + -> [TargetPlatform] -- ^ A list of target platforms restricting the scope of this action. + -> ReaderT (CachePrefix, SkipLocalCacheFlag, ConcurrentlyFlag, Bool) IO () +downloadFrameworksAndArtifactsWithEngine enginePath lCacheDir reverseRomeMap fvs platforms + = do + (_, _, ConcurrentlyFlag performConcurrently, _) <- ask + if performConcurrently + then mapConcurrently_ downloadConcurrently fvs + else mapM_ (sequence . download) platforms + where + downloadConcurrently f = mapConcurrently + (downloadFrameworkAndArtifactsWithEngine enginePath + lCacheDir + reverseRomeMap + f + ) + platforms + download = mapM + (downloadFrameworkAndArtifactsWithEngine enginePath + lCacheDir + reverseRomeMap + ) + fvs + + +-- | Downloads a Framework and it's relative dSYM with the engine or a local cache. +-- | If the Framework and dSYM are not found in the local cache then they are downloaded using the engine. +-- | If SkipLocalCache is specified, the local cache is ignored. +downloadFrameworkAndArtifactsWithEngine + :: FilePath -- ^ The path to the engine. + -> Maybe FilePath -- ^ Just the path to the local cache or Nothing. + -> InvertedRepositoryMap -- ^ The map used to resolve `FrameworkName`s to `ProjectName`s. + -> FrameworkVersion -- ^ The `FrameworkVersion` identifying the Framework and dSYM + -> TargetPlatform -- ^ A target platforms restricting the scope of this action. + -> ReaderT (CachePrefix, SkipLocalCacheFlag, ConcurrentlyFlag, Bool) IO () +downloadFrameworkAndArtifactsWithEngine enginePath (Just lCacheDir) reverseRomeMap fVersion@(FrameworkVersion f@(Framework fwn _ _) version) platform + = do + (cachePrefix@(CachePrefix prefix), SkipLocalCacheFlag skipLocalCache, _, verbose) <- ask + + let readerEnv = (cachePrefix, verbose) + + when skipLocalCache $ downloadFrameworkAndArtifactsWithEngine + enginePath + Nothing + reverseRomeMap + fVersion + platform + + unless skipLocalCache $ do + eitherFrameworkSuccess <- runReaderT + (runExceptT $ getAndUnzipFrameworkFromLocalCache lCacheDir + reverseRomeMap + fVersion + platform + ) + readerEnv + let sayFunc :: MonadIO m => String -> m () + sayFunc = if verbose then sayLnWithTime else sayLn + + case eitherFrameworkSuccess of + Right _ -> return () + Left e -> liftIO $ do + sayFunc e + runReaderT + (do + e2 <- runExceptT $ do + frameworkBinary <- getFrameworkFromEngine enginePath + reverseRomeMap + fVersion + platform + saveBinaryToLocalCache lCacheDir + frameworkBinary + (prefix remoteFrameworkUploadPath) + fwn + verbose + deleteFrameworkDirectory fVersion platform verbose + unzipBinary frameworkBinary fwn frameworkZipName verbose + <* ifExists + frameworkExecutablePath + (makeExecutable frameworkExecutablePath) + whenLeft sayFunc e2 + ) + readerEnv + + eitherBcsymbolmapsOrErrors <- runReaderT + (runExceptT $ getAndUnzipBcsymbolmapsFromLocalCache' lCacheDir + reverseRomeMap + fVersion + platform + ) + readerEnv + case eitherBcsymbolmapsOrErrors of + Right _ -> return () + Left ErrorGettingDwarfUUIDs -> + sayFunc $ "Error: Cannot retrieve symbolmaps ids for " <> fwn + Left (FailedDwarfUUIDs dwardUUIDsAndErrors) -> do + mapM_ (sayFunc . snd) dwardUUIDsAndErrors + forM_ (map fst dwardUUIDsAndErrors) + $ \dwarfUUID -> liftIO $ runReaderT + (do + e <- runExceptT $ do + let symbolmapLoggingName = + fwn <> "." <> bcsymbolmapNameFrom dwarfUUID + let bcsymbolmapZipName d = bcsymbolmapArchiveName d version + let localBcsymbolmapPathFrom d = + platformBuildDirectory bcsymbolmapNameFrom d + symbolmapBinary <- getBcsymbolmapWithEngine enginePath + reverseRomeMap + fVersion + platform + dwarfUUID + saveBinaryToLocalCache + lCacheDir + symbolmapBinary + (prefix remoteBcSymbolmapUploadPathFromDwarf dwarfUUID + ) + fwn + verbose + deleteFile (localBcsymbolmapPathFrom dwarfUUID) verbose + unzipBinary symbolmapBinary + symbolmapLoggingName + (bcsymbolmapZipName dwarfUUID) + verbose + whenLeft sayFunc e + ) + readerEnv + + eitherDSYMSuccess <- runReaderT + (runExceptT $ getAndUnzipDSYMFromLocalCache lCacheDir + reverseRomeMap + fVersion + platform + ) + readerEnv + case eitherDSYMSuccess of + Right _ -> return () + Left e -> liftIO $ do + sayFunc e + runReaderT + (do + e2 <- runExceptT $ do + dSYMBinary <- getDSYMFromEngine enginePath + reverseRomeMap + fVersion + platform + saveBinaryToLocalCache lCacheDir + dSYMBinary + (prefix remotedSYMUploadPath) + dSYMName + verbose + deleteDSYMDirectory fVersion platform verbose + unzipBinary dSYMBinary dSYMName dSYMZipName verbose + whenLeft sayFunc e2 + ) + readerEnv + where + frameworkZipName = frameworkArchiveName f version + remoteFrameworkUploadPath = + remoteFrameworkPath platform reverseRomeMap f version + remoteBcSymbolmapUploadPathFromDwarf dwarfUUID = + remoteBcsymbolmapPath dwarfUUID platform reverseRomeMap f version + dSYMZipName = dSYMArchiveName f version + remotedSYMUploadPath = remoteDsymPath platform reverseRomeMap f version + platformBuildDirectory = + carthageArtifactsBuildDirectoryForPlatform platform f + dSYMName = fwn <> ".dSYM" + frameworkExecutablePath = frameworkBuildBundleForPlatform platform f fwn + + +downloadFrameworkAndArtifactsWithEngine enginePath Nothing reverseRomeMap fVersion@(FrameworkVersion f@(Framework fwn _ _) version) platform + = do + (cachePrefix, _, _, verbose) <- ask + + let readerEnv = (cachePrefix, verbose) + let sayFunc = if verbose then sayLnWithTime else sayLn + + liftIO $ + runReaderT + (do + error <- + runExceptT + $ getAndUnzipFrameworkWithEngine + enginePath + reverseRomeMap + fVersion + platform + whenLeft sayFunc error + eitherDSYMError <- + runExceptT + $ getAndUnzipDSYMWithEngine + enginePath + reverseRomeMap + fVersion + platform + whenLeft sayFunc eitherDSYMError + eitherSymbolmapsOrErrors <- runExceptT $ getAndUnzipBcsymbolmapsWithEngine' enginePath + reverseRomeMap + fVersion + platform + flip whenLeft eitherSymbolmapsOrErrors $ \e -> case e of + ErrorGettingDwarfUUIDs -> + sayFunc $ "Error: Cannot retrieve symbolmaps ids for " <> fwn + (FailedDwarfUUIDs dwardUUIDsAndErrors) -> + mapM_ (sayFunc . snd) dwardUUIDsAndErrors + ) + readerEnv + + +-- | Downloads a list of .version files with the engine or a local cache. +downloadVersionFilesWithEngine + :: FilePath -- ^ The engine definition. + -> Maybe FilePath -- ^ Just the local cache path or Nothing + -> [ProjectNameAndVersion] -- ^ A list of `ProjectName`s and `Version`s information. + -> ReaderT (CachePrefix, SkipLocalCacheFlag, ConcurrentlyFlag, Bool) IO () +downloadVersionFilesWithEngine enginePath lDir = + mapM_ (downloadVersionFileWithEngine enginePath lDir) + + + +-- | Downloads one .version file with the engine or a local cache. +-- | If the .version file is not found in the local cache, it is downloaded with the engine. +-- | If SkipLocalCache is specified, the local cache is ignored. +downloadVersionFileWithEngine + :: FilePath -- ^ The engine definition. + -> Maybe FilePath -- ^ Just the local cache path or Nothing + -> ProjectNameAndVersion -- ^ The `ProjectName` and `Version` information. + -> ReaderT (CachePrefix, SkipLocalCacheFlag, ConcurrentlyFlag, Bool) IO () +downloadVersionFileWithEngine enginePath (Just lCacheDir) projectNameAndVersion + = do + (cachePrefix@(CachePrefix prefix), SkipLocalCacheFlag skipLocalCache, _, verbose) <- + ask + + when skipLocalCache $ downloadVersionFileWithEngine enginePath + Nothing + projectNameAndVersion + + unless skipLocalCache $ do + eitherSuccess <- runReaderT + (runExceptT $ getAndSaveVersionFileFromLocalCache + lCacheDir + projectNameAndVersion + ) + (cachePrefix, verbose) + case eitherSuccess of + Right _ -> return () + Left e -> liftIO $ do + let sayFunc :: MonadIO m => String -> m () + sayFunc = if verbose then sayLnWithTime else sayLn + sayFunc e + runReaderT + (do + e2 <- runExceptT $ do + versionFileBinary <- getVersionFileFromEngine + enginePath + projectNameAndVersion + saveBinaryToLocalCache lCacheDir + versionFileBinary + (prefix versionFileRemotePath) + versionFileName + verbose + liftIO $ saveBinaryToFile versionFileBinary versionFileLocalPath + sayFunc + $ "Copied " + <> versionFileName + <> " to: " + <> versionFileLocalPath + whenLeft sayFunc e2 + ) + (cachePrefix, verbose) + where + versionFileName = versionFileNameForProjectName $ fst projectNameAndVersion + versionFileLocalPath = carthageBuildDirectory versionFileName + versionFileRemotePath = remoteVersionFilePath projectNameAndVersion + +downloadVersionFileWithEngine enginePath Nothing projectNameAndVersion = do + (cachePrefix, _, _, verbose) <- ask + let sayFunc :: MonadIO m => String -> m () + sayFunc = if verbose then sayLnWithTime else sayLn + eitherError <- liftIO $ runReaderT + (runExceptT $ do + versionFileBinary <- getVersionFileFromEngine enginePath + projectNameAndVersion + liftIO $ saveBinaryToFile versionFileBinary versionFileLocalPath + sayFunc $ "Copied " <> versionFileName <> " to: " <> versionFileLocalPath + ) + (cachePrefix, verbose) + whenLeft sayFunc eitherError + where + versionFileName = versionFileNameForProjectName $ fst projectNameAndVersion + versionFileLocalPath = carthageBuildDirectory versionFileName + + + -- | Given a `ListMode` and a `ProjectAvailability` produces a `String` -- describing the `ProjectAvailability` for a given `ListMode`. formattedRepoAvailability diff --git a/src/Utils.hs b/src/Utils.hs index 602149f..1247793 100644 --- a/src/Utils.hs +++ b/src/Utils.hs @@ -741,7 +741,7 @@ whenLeft _ (Right _) = return () --- | Read a file as `Text` and pefrom an action +-- | Read a file as `Text` and perform an action fromFile :: MonadIO m => FilePath -- ^ The `FilePath` to the file to read