From 1b874e6b69cf1b8a953ac4032be1db4b462b995d Mon Sep 17 00:00:00 2001 From: Avner Matan <137777701+avner-m@users.noreply.github.com> Date: Mon, 14 Sep 2026 15:30:41 +1200 Subject: [PATCH 1/2] fix(react-native-mdocs-holder-tutorial): repair Android debug build Remove expo-dev-client, whose kotlinx-datetime 0.7.x requirement is binary incompatible with the 0.6.0 the Holder AAR is built against, sync the stale lockfile, and derive the app scheme from config in withAndroidHolderSDK so renaming the package no longer breaks OAuth. --- .../package.json | 1 - .../withAndroidHolderSDK.js | 60 ++++++++++++++++--- .../yarn.lock | 57 ++---------------- 3 files changed, 56 insertions(+), 62 deletions(-) diff --git a/react-native-mdocs-holder-tutorial/react-native-mdocs-holder-tutorial-complete/package.json b/react-native-mdocs-holder-tutorial/react-native-mdocs-holder-tutorial-complete/package.json index 4034e61..3a521a1 100644 --- a/react-native-mdocs-holder-tutorial/react-native-mdocs-holder-tutorial-complete/package.json +++ b/react-native-mdocs-holder-tutorial/react-native-mdocs-holder-tutorial-complete/package.json @@ -17,7 +17,6 @@ "expo": "^55", "expo-build-properties": "~55.0.13", "expo-constants": "~55.0.15", - "expo-dev-client": "~55.0.28", "expo-linking": "~55.0.14", "expo-router": "~55.0.13", "expo-web-browser": "~55.0.14", diff --git a/react-native-mdocs-holder-tutorial/react-native-mdocs-holder-tutorial-complete/withAndroidHolderSDK.js b/react-native-mdocs-holder-tutorial/react-native-mdocs-holder-tutorial-complete/withAndroidHolderSDK.js index 3ca1441..dbad19f 100644 --- a/react-native-mdocs-holder-tutorial/react-native-mdocs-holder-tutorial-complete/withAndroidHolderSDK.js +++ b/react-native-mdocs-holder-tutorial/react-native-mdocs-holder-tutorial-complete/withAndroidHolderSDK.js @@ -2,7 +2,7 @@ * Expo Config Plugin for MATTR Mobile Credential Holder SDK (Android) * * This plugin configures the Android build for the MATTR Mobile Credential Holder SDK. - * It performs three critical tasks: + * It performs four critical tasks: * * 1. MAVEN REPOSITORY SETUP * - Adds the local Maven repository for the MATTR SDK native Android libraries @@ -19,6 +19,10 @@ * - Configures it to ONLY handle: appscheme://credentials/callback * - This activity processes OAuth responses and passes them to the SDK * + * 4. DEVELOPMENT LAUNCH INTENT FILTER + * - Registers appscheme://expo-development-client on MainActivity + * - Allows `expo run:android` to open the app once it has been installed + * * WHY THIS IS NEEDED: * - Without the Maven repo: SDK native libraries won't be found during build * - Without intent filter cleanup: MainActivity would catch appscheme://credentials/callback, @@ -65,6 +69,8 @@ function withAndroidHolderSDK(config) { const androidManifest = config.modResults; const application = androidManifest.manifest.application[0]; + const appScheme = config.android?.package; + // Find MainActivity and clean up its intent filters const mainActivity = application.activity?.find( (activity) => activity.$["android:name"] === ".MainActivity", @@ -84,11 +90,7 @@ function withAndroidHolderSDK(config) { // Remove the app scheme if it doesn't have a host // This prevents MainActivity from catching all app scheme URLs - if ( - scheme === - "io.mattrlabs.sample.reactnativemobilecredentialholdertutorialapp" && - !hasHost - ) { + if (scheme === appScheme && !hasHost) { return false; } @@ -115,6 +117,8 @@ function withAndroidHolderSDK(config) { const application = androidManifest.manifest.application[0]; + const appScheme = config.android?.package; + // Check if the activity already exists const activityExists = application.activity?.some( (activity) => @@ -155,8 +159,7 @@ function withAndroidHolderSDK(config) { data: [ { $: { - "android:scheme": - "io.mattrlabs.sample.reactnativemobilecredentialholdertutorialapp", + "android:scheme": appScheme, "android:host": "credentials", "android:pathPrefix": "/callback", }, @@ -176,6 +179,47 @@ function withAndroidHolderSDK(config) { return config; }); + // Register the development launch deep link on MainActivity + config = withAndroidManifest(config, (config) => { + const application = config.modResults.manifest.application[0]; + const appScheme = config.android?.package; + + const mainActivity = application.activity?.find( + (activity) => activity.$["android:name"] === ".MainActivity", + ); + + if (!appScheme || !mainActivity) { + return config; + } + + const alreadyRegistered = mainActivity["intent-filter"]?.some((filter) => + filter.data?.some( + (dataNode) => dataNode.$["android:host"] === "expo-development-client", + ), + ); + + if (!alreadyRegistered) { + mainActivity["intent-filter"] = mainActivity["intent-filter"] ?? []; + mainActivity["intent-filter"].push({ + action: [{ $: { "android:name": "android.intent.action.VIEW" } }], + category: [ + { $: { "android:name": "android.intent.category.DEFAULT" } }, + { $: { "android:name": "android.intent.category.BROWSABLE" } }, + ], + data: [ + { + $: { + "android:scheme": appScheme, + "android:host": "expo-development-client", + }, + }, + ], + }); + } + + return config; + }); + return config; } diff --git a/react-native-mdocs-holder-tutorial/react-native-mdocs-holder-tutorial-complete/yarn.lock b/react-native-mdocs-holder-tutorial/react-native-mdocs-holder-tutorial-complete/yarn.lock index ac6d24b..219c5a5 100644 --- a/react-native-mdocs-holder-tutorial/react-native-mdocs-holder-tutorial-complete/yarn.lock +++ b/react-native-mdocs-holder-tutorial/react-native-mdocs-holder-tutorial-complete/yarn.lock @@ -1348,10 +1348,10 @@ "@jridgewell/resolve-uri" "^3.1.0" "@jridgewell/sourcemap-codec" "^1.4.14" -"@mattrglobal/mobile-credential-holder-react-native@^8.1.1": - version "8.1.2" - resolved "https://registry.yarnpkg.com/@mattrglobal/mobile-credential-holder-react-native/-/mobile-credential-holder-react-native-8.1.2.tgz#6c9f0ed338c5d7fe0479a3d115680930bcf31c44" - integrity sha512-TzUH9CmBsy5PBDOuyMFT0lKAfkgrpI2ByDgZib4MCZohxmp9UnpqNmfOyfj1Z7dn2PX+Xbh+Lqcdz0Pf8cC13w== +"@mattrglobal/mobile-credential-holder-react-native@^10.0.0": + version "10.0.0" + resolved "https://registry.yarnpkg.com/@mattrglobal/mobile-credential-holder-react-native/-/mobile-credential-holder-react-native-10.0.0.tgz#7dff65f9728c1d840c5f35d8f3fad4534be4103d" + integrity sha512-phN0/6mC1gWf6NZnOs1UBHxhYK+hc94sWELikueJ1/hyvH7h65iVBTweLRAFl5fBXzJYNldCWZoS/WRk5LNAUQ== dependencies: neverthrow "4.3.0" zod "3.22.3" @@ -2726,38 +2726,6 @@ expo-constants@~55.0.15: dependencies: "@expo/env" "~2.1.1" -expo-dev-client@~55.0.28: - version "55.0.28" - resolved "https://registry.yarnpkg.com/expo-dev-client/-/expo-dev-client-55.0.28.tgz#0189f72ebb6540f668e62f65d8e4a49b596570e9" - integrity sha512-QZK6Ylx8Jg7lhOOHCxwC10g+i34ggMBAqV497JXFqla1tuuYiEw1poNJS5pD/60ZLe8kyy5PYPB4E9ezDHA9yQ== - dependencies: - expo-dev-launcher "55.0.29" - expo-dev-menu "55.0.24" - expo-dev-menu-interface "55.0.2" - expo-manifests "~55.0.16" - expo-updates-interface "~55.1.6" - -expo-dev-launcher@55.0.29: - version "55.0.29" - resolved "https://registry.yarnpkg.com/expo-dev-launcher/-/expo-dev-launcher-55.0.29.tgz#3a791e5cf5e95209fd8665ee928d5c635abc3a80" - integrity sha512-Rusz6VfVUAXPArkQhnxC5yY70RCfGNZv+06qCGIkm2boQ3wOiSUwJic8oIt7kW6yD2rkpm24q/7F/6r5joPfng== - dependencies: - "@expo/schema-utils" "^55.0.3" - expo-dev-menu "55.0.24" - expo-manifests "~55.0.16" - -expo-dev-menu-interface@55.0.2: - version "55.0.2" - resolved "https://registry.yarnpkg.com/expo-dev-menu-interface/-/expo-dev-menu-interface-55.0.2.tgz#aead1b9980c904d61c59e9182e13b2b37bcb2161" - integrity sha512-DomUNvGzY/xliwnMdbAYY780sCv19N7zIbifc0ClcoCzJZpNSCkvJ2qGIFRPyM/7DmqmlHGCKi8di7kYYLKNEg== - -expo-dev-menu@55.0.24: - version "55.0.24" - resolved "https://registry.yarnpkg.com/expo-dev-menu/-/expo-dev-menu-55.0.24.tgz#6af52133cd9de105d28317eb47938ffedb041e3b" - integrity sha512-/J93rADODlKpmaN9uywTd/RMywPDeUo/bAnrZNxlHrFUuO1VCGqYLhacITg2zebU8hucaou8pa8zVsTQaUCv6w== - dependencies: - expo-dev-menu-interface "55.0.2" - expo-file-system@~55.0.17: version "55.0.17" resolved "https://registry.yarnpkg.com/expo-file-system/-/expo-file-system-55.0.17.tgz#81e4bc15773ed0c0098edd26a8c2d31f3844219d" @@ -2782,11 +2750,6 @@ expo-image@^55.0.9: dependencies: sf-symbols-typescript "^2.2.0" -expo-json-utils@~55.0.2: - version "55.0.2" - resolved "https://registry.yarnpkg.com/expo-json-utils/-/expo-json-utils-55.0.2.tgz#ef79888b881ef5b92d27245d3a758bc5debcbccf" - integrity sha512-QJMOZOPOG7CTnKcrdVaiummn2va1MCO56z++eyWkDv3GBRODldM6MFMDf/jTREWthFc2Nxo6TuyWRrEV9S6n/Q== - expo-keep-awake@~55.0.6: version "55.0.6" resolved "https://registry.yarnpkg.com/expo-keep-awake/-/expo-keep-awake-55.0.6.tgz#b5bac9a811e0dfe77deefeaf57e9c73b5dbcc839" @@ -2800,13 +2763,6 @@ expo-linking@~55.0.14: expo-constants "~55.0.15" invariant "^2.2.4" -expo-manifests@~55.0.16: - version "55.0.16" - resolved "https://registry.yarnpkg.com/expo-manifests/-/expo-manifests-55.0.16.tgz#d10c4f259561d37bc2bd1ef3047d8ab8482c915b" - integrity sha512-BR9BPcNsSnCKlQ/d7ECywr+2T54+bTSr26HjRjSua949o4mO/iPIrLjK0lOAa1oIczju6a6oUFckZD2OljxP0g== - dependencies: - expo-json-utils "~55.0.2" - expo-modules-autolinking@55.0.18: version "55.0.18" resolved "https://registry.yarnpkg.com/expo-modules-autolinking/-/expo-modules-autolinking-55.0.18.tgz#a360b9d0fc0afb4cfba22233c67780f01cba6053" @@ -2869,11 +2825,6 @@ expo-symbols@^55.0.7: "@expo-google-fonts/material-symbols" "^0.4.1" sf-symbols-typescript "^2.0.0" -expo-updates-interface@~55.1.6: - version "55.1.6" - resolved "https://registry.yarnpkg.com/expo-updates-interface/-/expo-updates-interface-55.1.6.tgz#18a806d65a28229ed4a7f920fceb9dda678c5c09" - integrity sha512-evxNpagCkjT3lE6bGV570TFzRtKuIuLY8I37RYHoriXCJ+ZKCN1hbmklK29uAixya+BxGpeTI2K4FqYeJLvfrw== - expo-web-browser@~55.0.14: version "55.0.14" resolved "https://registry.yarnpkg.com/expo-web-browser/-/expo-web-browser-55.0.14.tgz#ce58dcf8103123fd4e812d6909e390255ee6373b" From e08ea4fbca15af8d265a28061e98330ea59b8283 Mon Sep 17 00:00:00 2001 From: Avner Matan <137777701+avner-m@users.noreply.github.com> Date: Mon, 14 Sep 2026 15:44:41 +1200 Subject: [PATCH 2/2] fix(react-native-mdocs-holder-tutorial): apply the same fixes to the starter The starter ships the same withAndroidHolderSDK.js and the same expo-dev-client dependency, so a reader following the tutorial hits the identical kotlinx-datetime conflict and package rename defects once they register the plugin. Its app.config.ts is left untouched, as the differences there are deliberate tutorial scaffolding. --- .../package.json | 1 - .../withAndroidHolderSDK.js | 60 ++++++++++++++++--- .../yarn.lock | 57 ++---------------- 3 files changed, 56 insertions(+), 62 deletions(-) diff --git a/react-native-mdocs-holder-tutorial/react-native-mdocs-holder-tutorial-starter/package.json b/react-native-mdocs-holder-tutorial/react-native-mdocs-holder-tutorial-starter/package.json index 5958230..6e79f9f 100644 --- a/react-native-mdocs-holder-tutorial/react-native-mdocs-holder-tutorial-starter/package.json +++ b/react-native-mdocs-holder-tutorial/react-native-mdocs-holder-tutorial-starter/package.json @@ -17,7 +17,6 @@ "expo": "^55", "expo-build-properties": "~55.0.13", "expo-constants": "~55.0.15", - "expo-dev-client": "~55.0.28", "expo-linking": "~55.0.14", "expo-router": "~55.0.13", "expo-web-browser": "~55.0.14", diff --git a/react-native-mdocs-holder-tutorial/react-native-mdocs-holder-tutorial-starter/withAndroidHolderSDK.js b/react-native-mdocs-holder-tutorial/react-native-mdocs-holder-tutorial-starter/withAndroidHolderSDK.js index 3ca1441..dbad19f 100644 --- a/react-native-mdocs-holder-tutorial/react-native-mdocs-holder-tutorial-starter/withAndroidHolderSDK.js +++ b/react-native-mdocs-holder-tutorial/react-native-mdocs-holder-tutorial-starter/withAndroidHolderSDK.js @@ -2,7 +2,7 @@ * Expo Config Plugin for MATTR Mobile Credential Holder SDK (Android) * * This plugin configures the Android build for the MATTR Mobile Credential Holder SDK. - * It performs three critical tasks: + * It performs four critical tasks: * * 1. MAVEN REPOSITORY SETUP * - Adds the local Maven repository for the MATTR SDK native Android libraries @@ -19,6 +19,10 @@ * - Configures it to ONLY handle: appscheme://credentials/callback * - This activity processes OAuth responses and passes them to the SDK * + * 4. DEVELOPMENT LAUNCH INTENT FILTER + * - Registers appscheme://expo-development-client on MainActivity + * - Allows `expo run:android` to open the app once it has been installed + * * WHY THIS IS NEEDED: * - Without the Maven repo: SDK native libraries won't be found during build * - Without intent filter cleanup: MainActivity would catch appscheme://credentials/callback, @@ -65,6 +69,8 @@ function withAndroidHolderSDK(config) { const androidManifest = config.modResults; const application = androidManifest.manifest.application[0]; + const appScheme = config.android?.package; + // Find MainActivity and clean up its intent filters const mainActivity = application.activity?.find( (activity) => activity.$["android:name"] === ".MainActivity", @@ -84,11 +90,7 @@ function withAndroidHolderSDK(config) { // Remove the app scheme if it doesn't have a host // This prevents MainActivity from catching all app scheme URLs - if ( - scheme === - "io.mattrlabs.sample.reactnativemobilecredentialholdertutorialapp" && - !hasHost - ) { + if (scheme === appScheme && !hasHost) { return false; } @@ -115,6 +117,8 @@ function withAndroidHolderSDK(config) { const application = androidManifest.manifest.application[0]; + const appScheme = config.android?.package; + // Check if the activity already exists const activityExists = application.activity?.some( (activity) => @@ -155,8 +159,7 @@ function withAndroidHolderSDK(config) { data: [ { $: { - "android:scheme": - "io.mattrlabs.sample.reactnativemobilecredentialholdertutorialapp", + "android:scheme": appScheme, "android:host": "credentials", "android:pathPrefix": "/callback", }, @@ -176,6 +179,47 @@ function withAndroidHolderSDK(config) { return config; }); + // Register the development launch deep link on MainActivity + config = withAndroidManifest(config, (config) => { + const application = config.modResults.manifest.application[0]; + const appScheme = config.android?.package; + + const mainActivity = application.activity?.find( + (activity) => activity.$["android:name"] === ".MainActivity", + ); + + if (!appScheme || !mainActivity) { + return config; + } + + const alreadyRegistered = mainActivity["intent-filter"]?.some((filter) => + filter.data?.some( + (dataNode) => dataNode.$["android:host"] === "expo-development-client", + ), + ); + + if (!alreadyRegistered) { + mainActivity["intent-filter"] = mainActivity["intent-filter"] ?? []; + mainActivity["intent-filter"].push({ + action: [{ $: { "android:name": "android.intent.action.VIEW" } }], + category: [ + { $: { "android:name": "android.intent.category.DEFAULT" } }, + { $: { "android:name": "android.intent.category.BROWSABLE" } }, + ], + data: [ + { + $: { + "android:scheme": appScheme, + "android:host": "expo-development-client", + }, + }, + ], + }); + } + + return config; + }); + return config; } diff --git a/react-native-mdocs-holder-tutorial/react-native-mdocs-holder-tutorial-starter/yarn.lock b/react-native-mdocs-holder-tutorial/react-native-mdocs-holder-tutorial-starter/yarn.lock index a5d4a4c..cc18562 100644 --- a/react-native-mdocs-holder-tutorial/react-native-mdocs-holder-tutorial-starter/yarn.lock +++ b/react-native-mdocs-holder-tutorial/react-native-mdocs-holder-tutorial-starter/yarn.lock @@ -1374,10 +1374,10 @@ "@jridgewell/resolve-uri" "^3.1.0" "@jridgewell/sourcemap-codec" "^1.4.14" -"@mattrglobal/mobile-credential-holder-react-native@^8.1.1": - version "8.1.2" - resolved "https://registry.yarnpkg.com/@mattrglobal/mobile-credential-holder-react-native/-/mobile-credential-holder-react-native-8.1.2.tgz#6c9f0ed338c5d7fe0479a3d115680930bcf31c44" - integrity sha512-TzUH9CmBsy5PBDOuyMFT0lKAfkgrpI2ByDgZib4MCZohxmp9UnpqNmfOyfj1Z7dn2PX+Xbh+Lqcdz0Pf8cC13w== +"@mattrglobal/mobile-credential-holder-react-native@^10.0.0": + version "10.0.0" + resolved "https://registry.yarnpkg.com/@mattrglobal/mobile-credential-holder-react-native/-/mobile-credential-holder-react-native-10.0.0.tgz#7dff65f9728c1d840c5f35d8f3fad4534be4103d" + integrity sha512-phN0/6mC1gWf6NZnOs1UBHxhYK+hc94sWELikueJ1/hyvH7h65iVBTweLRAFl5fBXzJYNldCWZoS/WRk5LNAUQ== dependencies: neverthrow "4.3.0" zod "3.22.3" @@ -2752,38 +2752,6 @@ expo-constants@~55.0.15: dependencies: "@expo/env" "~2.1.1" -expo-dev-client@~55.0.28: - version "55.0.28" - resolved "https://registry.yarnpkg.com/expo-dev-client/-/expo-dev-client-55.0.28.tgz#0189f72ebb6540f668e62f65d8e4a49b596570e9" - integrity sha512-QZK6Ylx8Jg7lhOOHCxwC10g+i34ggMBAqV497JXFqla1tuuYiEw1poNJS5pD/60ZLe8kyy5PYPB4E9ezDHA9yQ== - dependencies: - expo-dev-launcher "55.0.29" - expo-dev-menu "55.0.24" - expo-dev-menu-interface "55.0.2" - expo-manifests "~55.0.16" - expo-updates-interface "~55.1.6" - -expo-dev-launcher@55.0.29: - version "55.0.29" - resolved "https://registry.yarnpkg.com/expo-dev-launcher/-/expo-dev-launcher-55.0.29.tgz#3a791e5cf5e95209fd8665ee928d5c635abc3a80" - integrity sha512-Rusz6VfVUAXPArkQhnxC5yY70RCfGNZv+06qCGIkm2boQ3wOiSUwJic8oIt7kW6yD2rkpm24q/7F/6r5joPfng== - dependencies: - "@expo/schema-utils" "^55.0.3" - expo-dev-menu "55.0.24" - expo-manifests "~55.0.16" - -expo-dev-menu-interface@55.0.2: - version "55.0.2" - resolved "https://registry.yarnpkg.com/expo-dev-menu-interface/-/expo-dev-menu-interface-55.0.2.tgz#aead1b9980c904d61c59e9182e13b2b37bcb2161" - integrity sha512-DomUNvGzY/xliwnMdbAYY780sCv19N7zIbifc0ClcoCzJZpNSCkvJ2qGIFRPyM/7DmqmlHGCKi8di7kYYLKNEg== - -expo-dev-menu@55.0.24: - version "55.0.24" - resolved "https://registry.yarnpkg.com/expo-dev-menu/-/expo-dev-menu-55.0.24.tgz#6af52133cd9de105d28317eb47938ffedb041e3b" - integrity sha512-/J93rADODlKpmaN9uywTd/RMywPDeUo/bAnrZNxlHrFUuO1VCGqYLhacITg2zebU8hucaou8pa8zVsTQaUCv6w== - dependencies: - expo-dev-menu-interface "55.0.2" - expo-file-system@~55.0.17: version "55.0.17" resolved "https://registry.yarnpkg.com/expo-file-system/-/expo-file-system-55.0.17.tgz#81e4bc15773ed0c0098edd26a8c2d31f3844219d" @@ -2808,11 +2776,6 @@ expo-image@^55.0.9: dependencies: sf-symbols-typescript "^2.2.0" -expo-json-utils@~55.0.2: - version "55.0.2" - resolved "https://registry.yarnpkg.com/expo-json-utils/-/expo-json-utils-55.0.2.tgz#ef79888b881ef5b92d27245d3a758bc5debcbccf" - integrity sha512-QJMOZOPOG7CTnKcrdVaiummn2va1MCO56z++eyWkDv3GBRODldM6MFMDf/jTREWthFc2Nxo6TuyWRrEV9S6n/Q== - expo-keep-awake@~55.0.6: version "55.0.6" resolved "https://registry.yarnpkg.com/expo-keep-awake/-/expo-keep-awake-55.0.6.tgz#b5bac9a811e0dfe77deefeaf57e9c73b5dbcc839" @@ -2826,13 +2789,6 @@ expo-linking@~55.0.14: expo-constants "~55.0.15" invariant "^2.2.4" -expo-manifests@~55.0.16: - version "55.0.16" - resolved "https://registry.yarnpkg.com/expo-manifests/-/expo-manifests-55.0.16.tgz#d10c4f259561d37bc2bd1ef3047d8ab8482c915b" - integrity sha512-BR9BPcNsSnCKlQ/d7ECywr+2T54+bTSr26HjRjSua949o4mO/iPIrLjK0lOAa1oIczju6a6oUFckZD2OljxP0g== - dependencies: - expo-json-utils "~55.0.2" - expo-modules-autolinking@55.0.18: version "55.0.18" resolved "https://registry.yarnpkg.com/expo-modules-autolinking/-/expo-modules-autolinking-55.0.18.tgz#a360b9d0fc0afb4cfba22233c67780f01cba6053" @@ -2895,11 +2851,6 @@ expo-symbols@^55.0.7: "@expo-google-fonts/material-symbols" "^0.4.1" sf-symbols-typescript "^2.0.0" -expo-updates-interface@~55.1.6: - version "55.1.6" - resolved "https://registry.yarnpkg.com/expo-updates-interface/-/expo-updates-interface-55.1.6.tgz#18a806d65a28229ed4a7f920fceb9dda678c5c09" - integrity sha512-evxNpagCkjT3lE6bGV570TFzRtKuIuLY8I37RYHoriXCJ+ZKCN1hbmklK29uAixya+BxGpeTI2K4FqYeJLvfrw== - expo-web-browser@~55.0.14: version "55.0.14" resolved "https://registry.yarnpkg.com/expo-web-browser/-/expo-web-browser-55.0.14.tgz#ce58dcf8103123fd4e812d6909e390255ee6373b"