mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
Compare commits
16
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
796918c94e | ||
|
|
064ca3c279 | ||
|
|
26b20bce9d | ||
|
|
9451e17e7d | ||
|
|
f983624f37 | ||
|
|
9b43636198 | ||
|
|
e33688ef81 | ||
|
|
6ea6684ce2 | ||
|
|
1f6cd2d37d | ||
|
|
b12213d017 | ||
|
|
2da00fe871 | ||
|
|
e8d30c67d2 | ||
|
|
4c196aec90 | ||
|
|
87bc732ca7 | ||
|
|
4f709f7b93 | ||
|
|
63238f6add |
@@ -1,373 +0,0 @@
|
||||
aliases:
|
||||
- &restore-cache
|
||||
keys:
|
||||
- v1-dependencies-{{ .Branch }}-{{ checksum "package.json" }}
|
||||
# Fallback in case checksum fails
|
||||
- v1-dependencies-{{ .Branch }}-
|
||||
- &save-cache
|
||||
paths:
|
||||
- node_modules
|
||||
key: v1-dependencies-{{ .Branch }}-{{ checksum "package.json" }}
|
||||
|
||||
- &restore-cache-website
|
||||
keys:
|
||||
- v1-website-dependencies-{{ .Branch }}-{{ checksum "website/package.json" }}
|
||||
# Fallback in case checksum fails
|
||||
- v1-website-dependencies-{{ .Branch }}-
|
||||
- &save-cache-website
|
||||
paths:
|
||||
- website/node_modules
|
||||
key: v1-website-dependencies-{{ .Branch }}-{{ checksum "website/package.json" }}
|
||||
|
||||
- &restore-cache-danger
|
||||
keys:
|
||||
- v1-danger-dependencies-{{ .Branch }}-{{ checksum "danger/package.json" }}
|
||||
# Fallback in case checksum fails
|
||||
- v1-danger-dependencies-{{ .Branch }}-
|
||||
- &save-cache-danger
|
||||
paths:
|
||||
- danger/node_modules
|
||||
key: v1-danger-dependencies-{{ .Branch }}-{{ checksum "danger/package.json" }}
|
||||
|
||||
- &restore-cache-android-packages
|
||||
keys:
|
||||
- v1-android-sdkmanager-packages-{{ checksum "scripts/circle-ci-android-setup.sh" }}
|
||||
# Fallback in case checksum fails
|
||||
- v1-android-sdkmanager-packages-
|
||||
- &save-cache-android-packages
|
||||
paths:
|
||||
- /opt/android/sdk/system-images/android-23
|
||||
- /opt/android/sdk/system-images/android-19
|
||||
- /opt/android/sdk/platforms/android-26
|
||||
- /opt/android/sdk/platforms/android-23
|
||||
- /opt/android/sdk/platforms/android-19
|
||||
- /opt/android/sdk/build-tools/23.0.1
|
||||
- /opt/android/sdk/add-ons/addon-google_apis-google-23
|
||||
key: v1-android-sdkmanager-packages-{{ checksum "scripts/circle-ci-android-setup.sh" }}
|
||||
|
||||
- &restore-cache-ndk
|
||||
keys:
|
||||
- v1-android-ndk-r10e-32-64
|
||||
- &save-cache-ndk
|
||||
paths:
|
||||
- /opt/ndk
|
||||
key: v1-android-ndk-r10e-32-64
|
||||
|
||||
- &restore-cache-buck-downloads
|
||||
keys:
|
||||
- v1-buck-downloads-{{ .Branch }}-{{ checksum "ReactAndroid/build.gradle" }}
|
||||
# Fallback in case checksum fails
|
||||
- v1-buck-downloads-{{ .Branch }}-
|
||||
- &save-cache-buck-downloads
|
||||
paths:
|
||||
- "ReactAndroid/build/downloads"
|
||||
key: v1-buck-downloads-{{ .Branch }}-{{ checksum "ReactAndroid/build.gradle" }}
|
||||
|
||||
- &restore-cache-buck
|
||||
keys:
|
||||
- v1-buck-v2017.09.04.02
|
||||
- &save-cache-buck
|
||||
paths:
|
||||
- ~/buck
|
||||
key: v1-buck-v2017.09.04.02
|
||||
|
||||
- &restore-cache-watchman
|
||||
keys:
|
||||
- v1-watchman-v4.9.0
|
||||
- &save-cache-watchman
|
||||
paths:
|
||||
- ~/watchman
|
||||
key: v1-watchman-v4.9.0
|
||||
|
||||
defaults: &defaults
|
||||
working_directory: ~/react-native
|
||||
|
||||
version: 2
|
||||
jobs:
|
||||
test-node-8:
|
||||
<<: *defaults
|
||||
docker:
|
||||
- image: circleci/node:8
|
||||
steps:
|
||||
- checkout
|
||||
- run: npm install --no-package-lock
|
||||
- run: |
|
||||
npm run lint
|
||||
npm run flow -- check
|
||||
npm test -- --maxWorkers=2
|
||||
# eslint
|
||||
- run:
|
||||
name: Analyze Code
|
||||
command: |
|
||||
npm install github@0.2.4
|
||||
cat <(echo eslint; npm run lint --silent -- --format=json; echo flow; npm run flow --silent -- check --json) | GITHUB_TOKEN="af6ef0d15709bc91d""06a6217a5a826a226fb57b7" CI_USER=$CIRCLE_PROJECT_USERNAME CI_REPO=$CIRCLE_PROJECT_REPONAME PULL_REQUEST_NUMBER=$CIRCLE_PR_NUMBER node bots/code-analysis-bot.js
|
||||
|
||||
test-node-6:
|
||||
<<: *defaults
|
||||
docker:
|
||||
- image: circleci/node:6.11.0
|
||||
steps:
|
||||
- checkout
|
||||
- run: npm install
|
||||
- run: |
|
||||
npm run lint
|
||||
npm run flow -- check
|
||||
npm test -- --maxWorkers=2
|
||||
|
||||
test-node-4:
|
||||
<<: *defaults
|
||||
docker:
|
||||
- image: circleci/node:4.8.4
|
||||
steps:
|
||||
- checkout
|
||||
- run: npm install
|
||||
- run: |
|
||||
npm run lint
|
||||
npm run flow -- check
|
||||
npm test -- --maxWorkers=2
|
||||
|
||||
test-website:
|
||||
<<: *defaults
|
||||
docker:
|
||||
- image: circleci/node:8
|
||||
steps:
|
||||
- checkout
|
||||
- run:
|
||||
name: Install Dependencies
|
||||
command: |
|
||||
cd website
|
||||
npm install --no-package-lock
|
||||
- run:
|
||||
name: Test Website
|
||||
command: |
|
||||
cd website
|
||||
npm test
|
||||
- run:
|
||||
name: Test Build Static Website
|
||||
command: cd website && node ./server/generate.js
|
||||
|
||||
deploy-website:
|
||||
<<: *defaults
|
||||
docker:
|
||||
- image: circleci/node:8
|
||||
steps:
|
||||
- checkout
|
||||
- run:
|
||||
name: Install Dependencies
|
||||
command: |
|
||||
cd website
|
||||
npm install --no-package-lock
|
||||
- run:
|
||||
name: Build and Deploy Static Website
|
||||
command: |
|
||||
if [[ $CIRCLE_PROJECT_USERNAME == "facebook" && -z $CI_PULL_REQUEST && -z $CIRCLE_PR_USERNAME ]]; then
|
||||
git config --global user.email "reactjs-bot@users.noreply.github.com"
|
||||
git config --global user.name "Website Deployment Script"
|
||||
echo "machine github.com login reactjs-bot password $GITHUB_TOKEN" > ~/.netrc
|
||||
|
||||
echo "Deploying website..."
|
||||
cd website && GIT_USER=reactjs-bot npm run gh-pages
|
||||
else
|
||||
echo "Skipping deploy."
|
||||
fi
|
||||
|
||||
build-js-bundle:
|
||||
<<: *defaults
|
||||
docker:
|
||||
- image: circleci/node:8
|
||||
steps:
|
||||
- checkout
|
||||
- run: npm install --no-package-lock
|
||||
- run:
|
||||
name: Build JavaScript Bundle
|
||||
command: node local-cli/cli.js bundle --max-workers 2 --platform android --dev true --entry-file ReactAndroid/src/androidTest/js/TestBundle.js --bundle-output ReactAndroid/src/androidTest/assets/AndroidTestBundle.js
|
||||
- persist_to_workspace:
|
||||
root: ReactAndroid/src/androidTest/assets/
|
||||
paths:
|
||||
- AndroidTestBundle.js
|
||||
- store_artifacts:
|
||||
path: ReactAndroid/src/androidTest/assets/AndroidTestBundle.js
|
||||
|
||||
test-android:
|
||||
<<: *defaults
|
||||
docker:
|
||||
- image: circleci/android:api-26-alpha
|
||||
environment:
|
||||
- TERM: "dumb"
|
||||
- ADB_INSTALL_TIMEOUT: 10
|
||||
- GRADLE_OPTS: '-Dorg.gradle.jvmargs="-Xmx512m -XX:+HeapDumpOnOutOfMemoryError"'
|
||||
- ANDROID_NDK: '/opt/ndk/android-ndk-r10e'
|
||||
- BUILD_THREADS: 2
|
||||
steps:
|
||||
- checkout
|
||||
# CircleCI does not support interpolating env variables in the environment: step above.
|
||||
# https://circleci.com/docs/2.0/env-vars/#interpolating-environment-variables-to-set-other-environment-variables
|
||||
- run:
|
||||
name: Configure PATH
|
||||
command: |
|
||||
echo 'export PATH=${ANDROID_NDK}:~/react-native/gradle-2.9/bin:~/buck/bin:$PATH' >> $BASH_ENV
|
||||
source $BASH_ENV
|
||||
# Configure dependencies
|
||||
- run:
|
||||
name: Install Build Dependencies
|
||||
command: |
|
||||
sudo apt-get update -y
|
||||
sudo apt-get install ant autoconf automake g++ gcc libqt5widgets5 lib32z1 lib32stdc++6 make maven python-dev python3-dev qml-module-qtquick-controls qtdeclarative5-dev -y
|
||||
- restore-cache: *restore-cache-android-packages
|
||||
- run:
|
||||
name: Install Android Packages
|
||||
command: source scripts/circle-ci-android-setup.sh && getAndroidSDK
|
||||
- save-cache: *save-cache-android-packages
|
||||
- run:
|
||||
name: Create Android Virtual Device
|
||||
command: source scripts/circle-ci-android-setup.sh && createAVD
|
||||
# Starting emulator in advance as it takes some time to boot.
|
||||
- run:
|
||||
name: Launch Android Virtual Device in Background
|
||||
command: source scripts/circle-ci-android-setup.sh && launchAVD
|
||||
background: true
|
||||
# Continue configuring dependencies while AVD boots.
|
||||
- run:
|
||||
name: Create Android NDK Directory
|
||||
command: |
|
||||
if [[ ! -e /opt/ndk ]]; then
|
||||
sudo mkdir /opt/ndk
|
||||
fi
|
||||
sudo chown ${USER:=$(/usr/bin/id -run)}:$USER /opt/ndk
|
||||
- restore-cache: *restore-cache-ndk
|
||||
- run:
|
||||
name: Install Android NDK
|
||||
command: source scripts/circle-ci-android-setup.sh && getAndroidNDK
|
||||
- save-cache: *save-cache-ndk
|
||||
- restore-cache: *restore-cache-buck
|
||||
- run:
|
||||
name: Install Buck
|
||||
command: |
|
||||
if [[ ! -e ~/buck ]]; then
|
||||
git clone https://github.com/facebook/buck.git ~/buck --branch v2017.09.04.02 --depth=1
|
||||
fi
|
||||
cd ~/buck && ant
|
||||
buck --version
|
||||
- save-cache: *save-cache-buck
|
||||
- run:
|
||||
name: Install Node
|
||||
command: |
|
||||
curl -sL https://deb.nodesource.com/setup_8.x | sudo -E bash -
|
||||
sudo apt-get install -y nodejs
|
||||
- run: npm install
|
||||
# - restore-cache: *restore-cache-watchman
|
||||
# - run:
|
||||
# name: Install Watchman Dependencies
|
||||
# command: |
|
||||
# sudo apt-get update -y
|
||||
# sudo apt-get install libtool pkg-config -y
|
||||
# - run:
|
||||
# name: Install Watchman
|
||||
# command: |
|
||||
# if [[ ! -e ~/watchman ]]; then
|
||||
# mkdir ~/watchman
|
||||
# git clone https://github.com/facebook/watchman.git ~/watchman --branch v4.9.0 --depth=1
|
||||
# cd ~/watchman
|
||||
# ./autogen.sh
|
||||
# ./configure
|
||||
# make
|
||||
# fi
|
||||
# cd ~/watchman
|
||||
# sudo make install
|
||||
# - save-cache: *save-cache-watchman
|
||||
- restore-cache: *restore-cache-buck-downloads
|
||||
- run:
|
||||
name: Download Android App Dependencies
|
||||
command: |
|
||||
buck fetch ReactAndroid/src/test/java/com/facebook/react/modules
|
||||
buck fetch ReactAndroid/src/main/java/com/facebook/react
|
||||
buck fetch ReactAndroid/src/main/java/com/facebook/react/shell
|
||||
buck fetch ReactAndroid/src/test/...
|
||||
buck fetch ReactAndroid/src/androidTest/...
|
||||
./gradlew :ReactAndroid:downloadBoost :ReactAndroid:downloadDoubleConversion :ReactAndroid:downloadFolly :ReactAndroid:downloadGlog :ReactAndroid:downloadJSCHeaders
|
||||
- save-cache: *save-cache-buck-downloads
|
||||
- run:
|
||||
name: Build Android App
|
||||
command: |
|
||||
buck build ReactAndroid/src/main/java/com/facebook/react
|
||||
buck build ReactAndroid/src/main/java/com/facebook/react/shell
|
||||
# Wait for AVD to finish booting before running tests
|
||||
- run:
|
||||
name: Wait for Android Virtual Device
|
||||
command: source scripts/circle-ci-android-setup.sh && waitForAVD
|
||||
# The JavaScript Bundle is built as part of the build-js-bundle workflow, and is required for instrumentation tests.
|
||||
- attach_workspace:
|
||||
at: ReactAndroid/src/androidTest/assets/
|
||||
- run:
|
||||
name: Check for JavaScript Bundle
|
||||
command: |
|
||||
if [[ ! -e ReactAndroid/src/androidTest/assets/AndroidTestBundle.js ]]; then
|
||||
echo "JavaScript bundle missing, verify build-js-bundle step"; exit 1;
|
||||
else
|
||||
echo "JavaScript bundle found.";
|
||||
fi
|
||||
# Tests
|
||||
- run:
|
||||
name: Compile Native Libs for Unit and Integration Tests
|
||||
command: ./gradlew :ReactAndroid:packageReactNdkLibsForBuck -Pjobs=$BUILD_THREADS -Pcom.android.build.threadPoolSize=1
|
||||
no_output_timeout: 6m
|
||||
- run:
|
||||
name: Unit Tests
|
||||
command: buck test ReactAndroid/src/test/... --config build.threads=$BUILD_THREADS
|
||||
# Integration Tests
|
||||
- run:
|
||||
name: Build and Install Test APK
|
||||
command: source scripts/circle-ci-android-setup.sh && NO_BUCKD=1 retry3 buck install ReactAndroid/src/androidTest/buck-runner:instrumentation-tests --config build.threads=$BUILD_THREADS
|
||||
# Failing test is expected
|
||||
# - run:
|
||||
# name: Run Installed APK with Tests
|
||||
# command: node ./scripts/run-android-ci-instrumentation-tests.js --retries 3 --path ./ReactAndroid/src/androidTest/java/com/facebook/react/tests --package com.facebook.react.tests
|
||||
# Should be disabled pending on https://our.intern.facebook.com/intern/tasks?t=16912142
|
||||
# - run:
|
||||
# name: Run Android End to End Tests
|
||||
# command: source scripts/circle-ci-android-setup.sh && retry3 node ./scripts/run-ci-e2e-tests.js --android --js --retries 2
|
||||
|
||||
# post (always runs)
|
||||
- run:
|
||||
name: Collect Test Results
|
||||
command: |
|
||||
mkdir -p ~/junit/
|
||||
find . -type f -regex ".*/build/test-results/debug/.*xml" -exec cp {} ~/junit/ \;
|
||||
find . -type f -regex ".*/outputs/androidTest-results/connected/.*xml" -exec cp {} ~/junit/ \;
|
||||
# TODO circle does not understand Buck's report, maybe need to transform xml slightly
|
||||
# find . -type f -regex ".*/buck-out/gen/ReactAndroid/src/test/.*/.*xml" -exec cp {} ~/junit/ \;
|
||||
when: always
|
||||
- store_test_results:
|
||||
path: ~/junit
|
||||
- store_artifacts:
|
||||
path: ~/junit
|
||||
|
||||
# Workflows enables us to run multiple jobs in parallel
|
||||
workflows:
|
||||
version: 2
|
||||
test_node:
|
||||
jobs:
|
||||
- test-node-8
|
||||
- test-node-6
|
||||
# Node 4 tests are already failing on Circle 1.0
|
||||
# - test-node-4
|
||||
website:
|
||||
jobs:
|
||||
- test-website
|
||||
- deploy-website:
|
||||
requires:
|
||||
- test-website
|
||||
filters:
|
||||
branches:
|
||||
only:
|
||||
- /.*-stable/
|
||||
- master
|
||||
test_android:
|
||||
jobs:
|
||||
- build-js-bundle:
|
||||
filters:
|
||||
branches:
|
||||
ignore: gh-pages
|
||||
- test-android:
|
||||
requires:
|
||||
- build-js-bundle
|
||||
+2
-2
@@ -46,8 +46,8 @@ suppress_type=$FlowFixMeProps
|
||||
suppress_type=$FlowFixMeState
|
||||
suppress_type=$FixMe
|
||||
|
||||
suppress_comment=\\(.\\|\n\\)*\\$FlowFixMe\\($\\|[^(]\\|(\\(>=0\\.\\(5[0-6]\\|[1-4][0-9]\\|[0-9]\\).[0-9]\\)? *\\(site=[a-z,_]*react_native_oss[a-z,_]*\\)?)\\)
|
||||
suppress_comment=\\(.\\|\n\\)*\\$FlowIssue\\((\\(>=0\\.\\(5[0-6]\\|[1-4][0-9]\\|[0-9]\\).[0-9]\\)? *\\(site=[a-z,_]*react_native_oss[a-z,_]*\\)?)\\)?:? #[0-9]+
|
||||
suppress_comment=\\(.\\|\n\\)*\\$FlowFixMe\\($\\|[^(]\\|(\\(>=0\\.\\(5[0-6]\\|[1-4][0-9]\\|[0-9]\\).[0-9]\\)? *\\(site=[a-z,_]*[react_native_oss|react_native_fb][a-z,_]*\\)?)\\)
|
||||
suppress_comment=\\(.\\|\n\\)*\\$FlowIssue\\((\\(>=0\\.\\(5[0-6]\\|[1-4][0-9]\\|[0-9]\\).[0-9]\\)? *\\(site=[a-z,_]*[react_native_oss|react_native_fb][a-z,_]*\\)?)\\)?:? #[0-9]+
|
||||
suppress_comment=\\(.\\|\n\\)*\\$FlowFixedInNextDeploy
|
||||
suppress_comment=\\(.\\|\n\\)*\\$FlowExpectedError
|
||||
|
||||
|
||||
@@ -14,8 +14,9 @@
|
||||
const ColorPropType = require('ColorPropType');
|
||||
const NativeMethodsMixin = require('NativeMethodsMixin');
|
||||
const Platform = require('Platform');
|
||||
const React = require('React');
|
||||
const ProgressBarAndroid = require('ProgressBarAndroid');
|
||||
const PropTypes = require('prop-types');
|
||||
const React = require('React');
|
||||
const StyleSheet = require('StyleSheet');
|
||||
const View = require('View');
|
||||
const ViewPropTypes = require('ViewPropTypes');
|
||||
@@ -135,16 +136,20 @@ const ActivityIndicator = createReactClass({
|
||||
break;
|
||||
}
|
||||
|
||||
const nativeProps = {
|
||||
...props,
|
||||
style: sizeStyle,
|
||||
styleAttr: 'Normal',
|
||||
indeterminate: true,
|
||||
};
|
||||
|
||||
return (
|
||||
<View
|
||||
onLayout={onLayout}
|
||||
style={[styles.container, style]}>
|
||||
<RCTActivityIndicator
|
||||
{...props}
|
||||
style={sizeStyle}
|
||||
styleAttr="Normal"
|
||||
indeterminate
|
||||
/>
|
||||
<View onLayout={onLayout} style={[styles.container, style]}>
|
||||
{Platform.OS === 'ios' ? (
|
||||
<RCTActivityIndicator {...nativeProps} />
|
||||
) : (
|
||||
<ProgressBarAndroid {...nativeProps} />
|
||||
)}
|
||||
</View>
|
||||
);
|
||||
}
|
||||
@@ -169,18 +174,7 @@ if (Platform.OS === 'ios') {
|
||||
var RCTActivityIndicator = requireNativeComponent(
|
||||
'RCTActivityIndicatorView',
|
||||
ActivityIndicator,
|
||||
{nativeOnly: {activityIndicatorViewStyle: true}},
|
||||
);
|
||||
} else if (Platform.OS === 'android') {
|
||||
var RCTActivityIndicator = requireNativeComponent(
|
||||
'AndroidProgressBar',
|
||||
ActivityIndicator,
|
||||
// Ignore props that are specific to non inderterminate ProgressBar.
|
||||
{nativeOnly: {
|
||||
indeterminate: true,
|
||||
progress: true,
|
||||
styleAttr: true,
|
||||
}},
|
||||
{ nativeOnly: { activityIndicatorViewStyle: true } }
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -10,13 +10,14 @@
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
const ActivityIndicator = require('ActivityIndicator');
|
||||
const ColorPropType = require('ColorPropType');
|
||||
const PropTypes = require('prop-types');
|
||||
const React = require('React');
|
||||
const ReactNative = require('ReactNative');
|
||||
const ViewPropTypes = require('ViewPropTypes');
|
||||
|
||||
const requireNativeComponent = require('requireNativeComponent');
|
||||
|
||||
const STYLE_ATTRIBUTES = [
|
||||
'Horizontal',
|
||||
'Normal',
|
||||
@@ -78,6 +79,10 @@ class ProgressBarAndroid extends ReactNative.NativeComponent {
|
||||
* - LargeInverse
|
||||
*/
|
||||
styleAttr: PropTypes.oneOf(STYLE_ATTRIBUTES),
|
||||
/**
|
||||
* Whether to show the ProgressBar (true, the default) or hide it (false).
|
||||
*/
|
||||
animating: PropTypes.bool,
|
||||
/**
|
||||
* If the progress bar will show indeterminate progress. Note that this
|
||||
* can only be false if styleAttr is Horizontal.
|
||||
@@ -99,21 +104,23 @@ class ProgressBarAndroid extends ReactNative.NativeComponent {
|
||||
|
||||
static defaultProps = {
|
||||
styleAttr: 'Normal',
|
||||
indeterminate: true
|
||||
indeterminate: true,
|
||||
animating: true,
|
||||
};
|
||||
|
||||
componentDidMount() {
|
||||
if (this.props.indeterminate && this.props.styleAttr !== 'Horizontal') {
|
||||
console.warn(
|
||||
'Circular indeterminate `ProgressBarAndroid`' +
|
||||
'is deprecated. Use `ActivityIndicator` instead.'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
return <ActivityIndicator {...this.props} animating={true} />;
|
||||
return <AndroidProgressBar {...this.props} />;
|
||||
}
|
||||
}
|
||||
|
||||
const AndroidProgressBar = requireNativeComponent(
|
||||
'AndroidProgressBar',
|
||||
ProgressBarAndroid,
|
||||
{
|
||||
nativeOnly: {
|
||||
animating: true,
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
module.exports = ProgressBarAndroid;
|
||||
|
||||
@@ -659,10 +659,11 @@ const ScrollView = createReactClass({
|
||||
} else if (Platform.OS === 'android') {
|
||||
if (this.props.horizontal) {
|
||||
ScrollViewClass = AndroidHorizontalScrollView;
|
||||
ScrollContentContainerViewClass = AndroidHorizontalScrollContentView;
|
||||
} else {
|
||||
ScrollViewClass = AndroidScrollView;
|
||||
ScrollContentContainerViewClass = View;
|
||||
}
|
||||
ScrollContentContainerViewClass = View;
|
||||
}
|
||||
|
||||
invariant(
|
||||
@@ -879,6 +880,7 @@ const styles = StyleSheet.create({
|
||||
|
||||
let nativeOnlyProps,
|
||||
AndroidScrollView,
|
||||
AndroidHorizontalScrollContentView,
|
||||
AndroidHorizontalScrollView,
|
||||
RCTScrollView,
|
||||
RCTScrollContentView;
|
||||
@@ -898,6 +900,9 @@ if (Platform.OS === 'android') {
|
||||
(ScrollView: React.ComponentType<any>),
|
||||
nativeOnlyProps
|
||||
);
|
||||
AndroidHorizontalScrollContentView = requireNativeComponent(
|
||||
'AndroidHorizontalScrollContentView'
|
||||
);
|
||||
} else if (Platform.OS === 'ios') {
|
||||
nativeOnlyProps = {
|
||||
nativeOnly: {
|
||||
|
||||
@@ -116,25 +116,9 @@ if (!global.__fbDisableExceptionsManager) {
|
||||
ErrorUtils.setGlobalHandler(handleError);
|
||||
}
|
||||
|
||||
const {PlatformConstants} = require('NativeModules');
|
||||
if (PlatformConstants) {
|
||||
const formatVersion = version =>
|
||||
`${version.major}.${version.minor}.${version.patch}` +
|
||||
(version.prerelease !== null ? `-${version.prerelease}` : '');
|
||||
|
||||
const ReactNativeVersion = require('ReactNativeVersion');
|
||||
const nativeVersion = PlatformConstants.reactNativeVersion;
|
||||
if (ReactNativeVersion.version.major !== nativeVersion.major ||
|
||||
ReactNativeVersion.version.minor !== nativeVersion.minor) {
|
||||
throw new Error(
|
||||
`React Native version mismatch.\n\nJavaScript version: ${formatVersion(ReactNativeVersion.version)}\n` +
|
||||
`Native version: ${formatVersion(nativeVersion)}\n\n` +
|
||||
'Make sure that you have rebuilt the native code. If the problem persists ' +
|
||||
'try clearing the watchman and packager caches with `watchman watch-del-all ' +
|
||||
'&& react-native start --reset-cache`.'
|
||||
);
|
||||
}
|
||||
}
|
||||
// Check for compatibility between the JS and native code
|
||||
const ReactNativeVersionCheck = require('ReactNativeVersionCheck');
|
||||
ReactNativeVersionCheck.checkVersions();
|
||||
|
||||
// Set up collections
|
||||
const _shouldPolyfillCollection = require('_shouldPolyfillES6Collection');
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
|
||||
exports.version = {
|
||||
major: 0,
|
||||
minor: 0,
|
||||
patch: 0,
|
||||
minor: 50,
|
||||
patch: 3,
|
||||
prerelease: null,
|
||||
};
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
/**
|
||||
* Copyright (c) 2017-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*
|
||||
* @providesModule ReactNativeVersionCheck
|
||||
* @flow
|
||||
* @format
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
const {PlatformConstants} = require('NativeModules');
|
||||
const ReactNativeVersion = require('ReactNativeVersion');
|
||||
|
||||
/**
|
||||
* Checks that the version of this React Native JS is compatible with the native
|
||||
* code, throwing an error if it isn't.
|
||||
*
|
||||
* The existence of this module is part of the public interface of React Native
|
||||
* even though it is used only internally within React Native. React Native
|
||||
* implementations for other platforms (ex: Windows) may override this module
|
||||
* and rely on its existence as a separate module.
|
||||
*/
|
||||
exports.checkVersions = function checkVersions(): void {
|
||||
if (!PlatformConstants) {
|
||||
return;
|
||||
}
|
||||
|
||||
const nativeVersion = PlatformConstants.reactNativeVersion;
|
||||
if (
|
||||
ReactNativeVersion.version.major !== nativeVersion.major ||
|
||||
ReactNativeVersion.version.minor !== nativeVersion.minor
|
||||
) {
|
||||
throw new Error(
|
||||
`React Native version mismatch.\n\nJavaScript version: ${_formatVersion(
|
||||
ReactNativeVersion.version,
|
||||
)}\n` +
|
||||
`Native version: ${_formatVersion(nativeVersion)}\n\n` +
|
||||
'Make sure that you have rebuilt the native code. If the problem ' +
|
||||
'persists try clearing the Watchman and packager caches with ' +
|
||||
'`watchman watch-del-all && react-native start --reset-cache`.',
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
function _formatVersion(version): string {
|
||||
return (
|
||||
`${version.major}.${version.minor}.${version.patch}` +
|
||||
(version.prerelease !== null ? `-${version.prerelease}` : '')
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,117 @@
|
||||
/**
|
||||
* Copyright (c) 2017-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*
|
||||
* @format
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
describe('checkVersion', () => {
|
||||
describe('in development', () => {
|
||||
_setDevelopmentModeForTests(true);
|
||||
_defineCheckVersionTests();
|
||||
});
|
||||
|
||||
describe('in production', () => {
|
||||
_setDevelopmentModeForTests(false);
|
||||
_defineCheckVersionTests();
|
||||
});
|
||||
});
|
||||
|
||||
function _setDevelopmentModeForTests(dev) {
|
||||
let originalDev;
|
||||
|
||||
beforeAll(() => {
|
||||
originalDev = global.__DEV__;
|
||||
global.__DEV__ = dev;
|
||||
});
|
||||
|
||||
afterAll(() => {
|
||||
global.__DEV__ = originalDev;
|
||||
});
|
||||
}
|
||||
|
||||
function _defineCheckVersionTests() {
|
||||
afterEach(() => {
|
||||
jest.resetModules();
|
||||
});
|
||||
|
||||
it('passes when all the versions are zero', () => {
|
||||
_mockJsVersion(0, 0, 0);
|
||||
_mockNativeVersion(0, 0, 0);
|
||||
|
||||
const ReactNativeVersion = require('ReactNativeVersion');
|
||||
const ReactNativeVersionCheck = require('ReactNativeVersionCheck');
|
||||
expect(ReactNativeVersion).toMatchObject({
|
||||
version: {major: 0, minor: 0, patch: 0, prerelease: null},
|
||||
});
|
||||
expect(() => ReactNativeVersionCheck.checkVersions()).not.toThrow();
|
||||
});
|
||||
|
||||
it('passes when the minor matches when the major is zero', () => {
|
||||
_mockJsVersion(0, 1, 0);
|
||||
_mockNativeVersion(0, 1, 0);
|
||||
|
||||
const ReactNativeVersionCheck = require('ReactNativeVersionCheck');
|
||||
expect(() => ReactNativeVersionCheck.checkVersions()).not.toThrow();
|
||||
});
|
||||
|
||||
it("throws when the minor doesn't match when the major is zero", () => {
|
||||
_mockJsVersion(0, 1, 0);
|
||||
_mockNativeVersion(0, 2, 0);
|
||||
|
||||
const ReactNativeVersionCheck = require('ReactNativeVersionCheck');
|
||||
expect(() => ReactNativeVersionCheck.checkVersions()).toThrowError(
|
||||
/React Native version mismatch/,
|
||||
);
|
||||
});
|
||||
|
||||
it("throws when the major doesn't match", () => {
|
||||
_mockJsVersion(1, 0, 0);
|
||||
_mockNativeVersion(2, 0, 0);
|
||||
|
||||
const ReactNativeVersionCheck = require('ReactNativeVersionCheck');
|
||||
expect(() => ReactNativeVersionCheck.checkVersions()).toThrowError(
|
||||
/React Native version mismatch/,
|
||||
);
|
||||
});
|
||||
|
||||
it("doesn't throw if the patch doesn't match", () => {
|
||||
_mockJsVersion(0, 1, 0);
|
||||
_mockNativeVersion(0, 1, 2);
|
||||
|
||||
const ReactNativeVersionCheck = require('ReactNativeVersionCheck');
|
||||
expect(() => ReactNativeVersionCheck.checkVersions()).not.toThrow();
|
||||
});
|
||||
|
||||
it("doesn't throw if the prerelease doesn't match", () => {
|
||||
_mockJsVersion(0, 1, 0, 'beta.0');
|
||||
_mockNativeVersion(0, 1, 0, 'alpha.1');
|
||||
|
||||
const ReactNativeVersionCheck = require('ReactNativeVersionCheck');
|
||||
expect(() => ReactNativeVersionCheck.checkVersions()).not.toThrow();
|
||||
});
|
||||
}
|
||||
|
||||
function _mockJsVersion(major = 0, minor = 0, patch = 0, prerelease = null) {
|
||||
jest.doMock('ReactNativeVersion', () => ({
|
||||
version: {major, minor, patch, prerelease},
|
||||
}));
|
||||
}
|
||||
|
||||
function _mockNativeVersion(
|
||||
major = 0,
|
||||
minor = 0,
|
||||
patch = 0,
|
||||
prerelease = null,
|
||||
) {
|
||||
jest.doMock('NativeModules', () => ({
|
||||
PlatformConstants: {
|
||||
reactNativeVersion: {major, minor, patch, prerelease},
|
||||
},
|
||||
}));
|
||||
}
|
||||
@@ -23,7 +23,7 @@ import type {Props as VirtualizedSectionListProps} from 'VirtualizedSectionList'
|
||||
|
||||
type Item = any;
|
||||
|
||||
export type SectionBase<SectionItemT> = {
|
||||
type SectionBase<SectionItemT> = {
|
||||
/**
|
||||
* The data for rendering items in this section.
|
||||
*/
|
||||
@@ -187,11 +187,10 @@ type OptionalProps<SectionT: SectionBase<any>> = {
|
||||
legacyImplementation?: ?boolean,
|
||||
};
|
||||
|
||||
export type Props<SectionT> = {
|
||||
...$Exact<RequiredProps<SectionT>>,
|
||||
...$Exact<OptionalProps<SectionT>>,
|
||||
...$Exact<VirtualizedSectionListProps<SectionT>>,
|
||||
};
|
||||
export type Props<SectionT> = RequiredProps<SectionT> &
|
||||
OptionalProps<SectionT> &
|
||||
VirtualizedSectionListProps<SectionT>;
|
||||
|
||||
const defaultProps = {
|
||||
...VirtualizedSectionList.defaultProps,
|
||||
stickySectionHeadersEnabled: Platform.OS === 'ios',
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
const Platform = require('Platform');
|
||||
const ReactNativeBridgeEventPlugin = require('ReactNativeBridgeEventPlugin');
|
||||
const ReactNativeStyleAttributes = require('ReactNativeStyleAttributes');
|
||||
const UIManager = require('UIManager');
|
||||
@@ -47,35 +48,30 @@ const warning = require('fbjs/lib/warning');
|
||||
*/
|
||||
import type {ComponentInterface} from 'verifyPropTypes';
|
||||
|
||||
let hasAttachedDefaultEventTypes: boolean = false;
|
||||
|
||||
function requireNativeComponent(
|
||||
viewName: string,
|
||||
componentInterface?: ?ComponentInterface,
|
||||
extraConfig?: ?{nativeOnly?: Object},
|
||||
): React$ComponentType<any> | string {
|
||||
function attachBubblingEventTypes(viewConfig) {
|
||||
if (UIManager.genericBubblingEventTypes) {
|
||||
viewConfig.bubblingEventTypes = merge(
|
||||
viewConfig.bubblingEventTypes,
|
||||
UIManager.genericBubblingEventTypes,
|
||||
);
|
||||
// As genericBubblingEventTypes do not change over time, and there's
|
||||
// merge of all the events happening in Fiber, we need to pass
|
||||
// genericBubblingEventTypes to Fiber only once. Therefore, we can delete
|
||||
// it and forget about it.
|
||||
delete UIManager.genericBubblingEventTypes;
|
||||
}
|
||||
}
|
||||
|
||||
function attachDirectEventTypes(viewConfig) {
|
||||
if (UIManager.genericDirectEventTypes) {
|
||||
viewConfig.directEventTypes = merge(
|
||||
viewConfig.directEventTypes,
|
||||
UIManager.genericDirectEventTypes,
|
||||
);
|
||||
// As genericDirectEventTypes do not change over time, and there's merge
|
||||
// of all the events happening in Fiber, we need to pass genericDirectEventTypes
|
||||
// to Fiber only once. Therefore, we can delete it and forget about it.
|
||||
delete UIManager.genericDirectEventTypes;
|
||||
function attachDefaultEventTypes(viewConfig: any) {
|
||||
if (Platform.OS === 'android') {
|
||||
// This is supported on Android platform only,
|
||||
// as lazy view managers discovery is Android-specific.
|
||||
if (UIManager.ViewManagerNames) {
|
||||
// Lazy view managers enabled.
|
||||
viewConfig = merge(viewConfig, UIManager.getDefaultEventTypes());
|
||||
} else {
|
||||
viewConfig.bubblingEventTypes = merge(
|
||||
viewConfig.bubblingEventTypes,
|
||||
UIManager.genericBubblingEventTypes,
|
||||
);
|
||||
viewConfig.directEventTypes = merge(
|
||||
viewConfig.directEventTypes,
|
||||
UIManager.genericDirectEventTypes,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -184,8 +180,10 @@ function requireNativeComponent(
|
||||
);
|
||||
}
|
||||
|
||||
attachBubblingEventTypes(viewConfig);
|
||||
attachDirectEventTypes(viewConfig);
|
||||
if (!hasAttachedDefaultEventTypes) {
|
||||
attachDefaultEventTypes(viewConfig);
|
||||
hasAttachedDefaultEventTypes = true;
|
||||
}
|
||||
|
||||
// Register this view's event types with the ReactNative renderer.
|
||||
// This enables view managers to be initialized lazily, improving perf,
|
||||
|
||||
@@ -74,9 +74,7 @@ const SwipeableFlatListExample = createReactClass({
|
||||
<View style={styles.row}>
|
||||
<Image style={styles.rowIcon} source={item.icon} />
|
||||
<View style={styles.rowData}>
|
||||
<Text style={styles.rowDataText}>
|
||||
{item.data}
|
||||
</Text>
|
||||
<Text style={styles.rowDataText}>{item.data}</Text>
|
||||
</View>
|
||||
</View>
|
||||
);
|
||||
|
||||
@@ -109,6 +109,7 @@ Pod::Spec.new do |s|
|
||||
|
||||
s.subspec "jschelpers" do |ss|
|
||||
ss.dependency "Folly", "2016.09.26.00"
|
||||
ss.dependency "React/PrivateDatabase"
|
||||
ss.compiler_flags = folly_compiler_flags
|
||||
ss.source_files = "ReactCommon/jschelpers/*.{cpp,h}"
|
||||
ss.private_header_files = "ReactCommon/jschelpers/*.h"
|
||||
@@ -116,6 +117,12 @@ Pod::Spec.new do |s|
|
||||
ss.framework = "JavaScriptCore"
|
||||
end
|
||||
|
||||
s.subspec "PrivateDatabase" do |ss|
|
||||
ss.source_files = "ReactCommon/privatedata/*.{cpp,h}"
|
||||
ss.private_header_files = "ReactCommon/privatedata/*.h"
|
||||
ss.pod_target_xcconfig = { "HEADER_SEARCH_PATHS" => "\"$(PODS_TARGET_SRCROOT)/ReactCommon\"" }
|
||||
end
|
||||
|
||||
s.subspec "cxxreact" do |ss|
|
||||
ss.dependency "React/jschelpers"
|
||||
ss.dependency "boost"
|
||||
|
||||
@@ -47,7 +47,7 @@ RCT_EXPORT_MODULE(PlatformConstants)
|
||||
@"systemName": [device systemName],
|
||||
@"interfaceIdiom": interfaceIdiom([device userInterfaceIdiom]),
|
||||
@"isTesting": @(RCTRunningInTestEnvironment()),
|
||||
@"reactNativeVersion": REACT_NATIVE_VERSION,
|
||||
@"reactNativeVersion": RCT_REACT_NATIVE_VERSION,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -9,9 +9,9 @@
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*/
|
||||
|
||||
#define REACT_NATIVE_VERSION @{ \
|
||||
#define RCT_REACT_NATIVE_VERSION @{ \
|
||||
@"major": @(0), \
|
||||
@"minor": @(0), \
|
||||
@"patch": @(0), \
|
||||
@"minor": @(50), \
|
||||
@"patch": @(3), \
|
||||
@"prerelease": [NSNull null], \
|
||||
}
|
||||
|
||||
+2
-2
@@ -86,7 +86,7 @@ def rn_robolectric_test(name, srcs, vm_args = None, *args, **kwargs):
|
||||
'-XX:MaxPermSize=620m',
|
||||
'-Drobolectric.offline=true',
|
||||
]
|
||||
if os.path.isdir("/dev/shm") and not os.environ['CIRCLECI']:
|
||||
if os.path.isdir("/dev/shm"):
|
||||
extra_vm_args.append('-Djava.io.tmpdir=/dev/shm')
|
||||
else:
|
||||
extra_vm_args.append(
|
||||
@@ -110,4 +110,4 @@ def rn_robolectric_test(name, srcs, vm_args = None, *args, **kwargs):
|
||||
|
||||
original_cxx_library = cxx_library
|
||||
def cxx_library(allow_jni_merging=None, **kwargs):
|
||||
original_cxx_library(**kwargs)
|
||||
original_cxx_library(**kwargs)
|
||||
@@ -1,4 +1,4 @@
|
||||
VERSION_NAME=1000.0.0-master
|
||||
VERSION_NAME=0.50.3
|
||||
GROUP=com.facebook.react
|
||||
|
||||
POM_NAME=ReactNative
|
||||
|
||||
+2
-2
@@ -18,7 +18,7 @@ import java.util.Map;
|
||||
public class ReactNativeVersion {
|
||||
public static final Map<String, Object> VERSION = MapBuilder.<String, Object>of(
|
||||
"major", 0,
|
||||
"minor", 0,
|
||||
"patch", 0,
|
||||
"minor", 50,
|
||||
"patch", 3,
|
||||
"prerelease", null);
|
||||
}
|
||||
|
||||
@@ -61,6 +61,7 @@ import com.facebook.react.views.modal.ReactModalHostManager;
|
||||
import com.facebook.react.views.picker.ReactDialogPickerManager;
|
||||
import com.facebook.react.views.picker.ReactDropdownPickerManager;
|
||||
import com.facebook.react.views.progressbar.ReactProgressBarViewManager;
|
||||
import com.facebook.react.views.scroll.ReactHorizontalScrollContainerViewManager;
|
||||
import com.facebook.react.views.scroll.ReactHorizontalScrollViewManager;
|
||||
import com.facebook.react.views.scroll.ReactScrollViewManager;
|
||||
import com.facebook.react.views.slider.ReactSliderManager;
|
||||
@@ -315,6 +316,7 @@ public class MainReactPackage extends LazyReactPackage {
|
||||
viewManagers.add(new ReactDrawerLayoutManager());
|
||||
viewManagers.add(new ReactDropdownPickerManager());
|
||||
viewManagers.add(new ReactHorizontalScrollViewManager());
|
||||
viewManagers.add(new ReactHorizontalScrollContainerViewManager());
|
||||
viewManagers.add(new ReactProgressBarViewManager());
|
||||
viewManagers.add(new ReactScrollViewManager());
|
||||
viewManagers.add(new ReactSliderManager());
|
||||
|
||||
@@ -17,7 +17,6 @@ import android.content.res.Configuration;
|
||||
import com.facebook.common.logging.FLog;
|
||||
import com.facebook.debug.holder.PrinterHolder;
|
||||
import com.facebook.debug.tags.ReactDebugOverlayTags;
|
||||
import com.facebook.proguard.annotations.DoNotStrip;
|
||||
import com.facebook.react.animation.Animation;
|
||||
import com.facebook.react.bridge.Arguments;
|
||||
import com.facebook.react.bridge.Callback;
|
||||
@@ -43,7 +42,7 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
/**
|
||||
/**
|
||||
* <p>Native module to allow JS to create and update native Views.</p>
|
||||
*
|
||||
* <p>
|
||||
@@ -115,11 +114,6 @@ public class UIManagerModule extends ReactContextBaseJavaModule implements
|
||||
|
||||
private int mBatchId = 0;
|
||||
|
||||
// Defines if events were already exported to JS. We do not send them more
|
||||
// than once as they are stored and mixed in with Fiber for every ViewManager
|
||||
// on JS side.
|
||||
private boolean mEventsWereSentToJS = false;
|
||||
|
||||
public UIManagerModule(
|
||||
ReactApplicationContext reactContext,
|
||||
ViewManagerResolver viewManagerResolver,
|
||||
@@ -233,7 +227,6 @@ public class UIManagerModule extends ReactContextBaseJavaModule implements
|
||||
}
|
||||
}
|
||||
|
||||
@DoNotStrip
|
||||
@ReactMethod(isBlockingSynchronousMethod = true)
|
||||
public @Nullable WritableMap getConstantsForViewManager(final String viewManagerName) {
|
||||
ViewManager targetView =
|
||||
@@ -249,13 +242,8 @@ public class UIManagerModule extends ReactContextBaseJavaModule implements
|
||||
try {
|
||||
Map<String, Object> viewManagerConstants =
|
||||
UIManagerModuleConstantsHelper.createConstantsForViewManager(
|
||||
targetView,
|
||||
mEventsWereSentToJS ? null : UIManagerModuleConstants.getBubblingEventTypeConstants(),
|
||||
mEventsWereSentToJS ? null : UIManagerModuleConstants.getDirectEventTypeConstants(),
|
||||
null,
|
||||
mCustomDirectEvents);
|
||||
targetView, null, null, null, mCustomDirectEvents);
|
||||
if (viewManagerConstants != null) {
|
||||
mEventsWereSentToJS = true;
|
||||
return Arguments.makeNativeMap(viewManagerConstants);
|
||||
}
|
||||
return null;
|
||||
@@ -264,9 +252,12 @@ public class UIManagerModule extends ReactContextBaseJavaModule implements
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves Direct Event name exposed to JS from the one known to the Native side.
|
||||
*/
|
||||
@ReactMethod(isBlockingSynchronousMethod = true)
|
||||
public WritableMap getDefaultEventTypes() {
|
||||
return Arguments.makeNativeMap(UIManagerModuleConstantsHelper.getDefaultExportableEventTypes());
|
||||
}
|
||||
|
||||
/** Resolves Direct Event name exposed to JS from the one known to the Native side. */
|
||||
public CustomEventNamesResolver getDirectEventNamesResolver() {
|
||||
return new CustomEventNamesResolver() {
|
||||
@Override
|
||||
|
||||
+9
-3
@@ -24,6 +24,9 @@ import javax.annotation.Nullable;
|
||||
*/
|
||||
/* package */ class UIManagerModuleConstantsHelper {
|
||||
|
||||
private static final String BUBBLING_EVENTS_KEY = "bubblingEventTypes";
|
||||
private static final String DIRECT_EVENTS_KEY = "directEventTypes";
|
||||
|
||||
/**
|
||||
* Generates a lazy discovery enabled version of {@link UIManagerModule} constants. It only
|
||||
* contains a list of view manager names, so that JS side is aware of the managers there are.
|
||||
@@ -38,6 +41,12 @@ import javax.annotation.Nullable;
|
||||
return constants;
|
||||
}
|
||||
|
||||
/* package */ static Map<String, Object> getDefaultExportableEventTypes() {
|
||||
return MapBuilder.<String, Object>of(
|
||||
BUBBLING_EVENTS_KEY, UIManagerModuleConstants.getBubblingEventTypeConstants(),
|
||||
DIRECT_EVENTS_KEY, UIManagerModuleConstants.getDirectEventTypeConstants());
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates map of constants that is then exposed by {@link UIManagerModule}.
|
||||
* Provided list of {@param viewManagers} is then used to populate content of
|
||||
@@ -106,9 +115,6 @@ import javax.annotation.Nullable;
|
||||
@Nullable Map defaultDirectEvents,
|
||||
@Nullable Map cumulativeBubblingEventTypes,
|
||||
@Nullable Map cumulativeDirectEventTypes) {
|
||||
final String BUBBLING_EVENTS_KEY = "bubblingEventTypes";
|
||||
final String DIRECT_EVENTS_KEY = "directEventTypes";
|
||||
|
||||
Map<String, Object> viewManagerConstants = MapBuilder.newHashMap();
|
||||
|
||||
Map viewManagerBubblingEvents = viewManager.getExportedCustomBubblingEventTypeConstants();
|
||||
|
||||
@@ -16,6 +16,7 @@ android_library(
|
||||
react_native_target("java/com/facebook/react/bridge:bridge"),
|
||||
react_native_target("java/com/facebook/react/common:common"),
|
||||
react_native_target("java/com/facebook/react/module/annotations:annotations"),
|
||||
react_native_target("java/com/facebook/react/modules/i18nmanager:i18nmanager"),
|
||||
react_native_target("java/com/facebook/react/touch:touch"),
|
||||
react_native_target("java/com/facebook/react/uimanager:uimanager"),
|
||||
react_native_target("java/com/facebook/react/uimanager/annotations:annotations"),
|
||||
|
||||
+40
@@ -0,0 +1,40 @@
|
||||
// Copyright 2004-present Facebook. All Rights Reserved.
|
||||
|
||||
package com.facebook.react.views.scroll;
|
||||
|
||||
import android.content.Context;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.HorizontalScrollView;
|
||||
import com.facebook.react.modules.i18nmanager.I18nUtil;
|
||||
|
||||
/** Container of Horizontal scrollViews that supports RTL scrolling. */
|
||||
public class ReactHorizontalScrollContainerView extends ViewGroup {
|
||||
|
||||
private int mLayoutDirection;
|
||||
|
||||
public ReactHorizontalScrollContainerView(Context context) {
|
||||
super(context);
|
||||
mLayoutDirection =
|
||||
I18nUtil.getInstance().isRTL(context) ? LAYOUT_DIRECTION_RTL : LAYOUT_DIRECTION_LTR;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
|
||||
if (mLayoutDirection == LAYOUT_DIRECTION_RTL) {
|
||||
// When the layout direction is RTL, we expect Yoga to give us a layout
|
||||
// that extends off the screen to the left so we re-center it with left=0
|
||||
int newLeft = 0;
|
||||
int width = right - left;
|
||||
int newRight = newLeft + width;
|
||||
setLeft(newLeft);
|
||||
setRight(newRight);
|
||||
|
||||
// Fix the ScrollX position when using RTL language
|
||||
int offsetX = computeHorizontalScrollRange() - getScrollX();
|
||||
|
||||
// Call with the present values in order to re-layout if necessary
|
||||
HorizontalScrollView parent = (HorizontalScrollView) getParent();
|
||||
parent.scrollTo(offsetX, parent.getScrollY());
|
||||
}
|
||||
}
|
||||
}
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
// Copyright 2004-present Facebook. All Rights Reserved.
|
||||
|
||||
package com.facebook.react.views.scroll;
|
||||
|
||||
import com.facebook.react.module.annotations.ReactModule;
|
||||
import com.facebook.react.uimanager.ThemedReactContext;
|
||||
import com.facebook.react.uimanager.ViewGroupManager;
|
||||
|
||||
/** View manager for {@link ReactHorizontalScrollContainerView} components. */
|
||||
@ReactModule(name = ReactHorizontalScrollContainerViewManager.REACT_CLASS)
|
||||
public class ReactHorizontalScrollContainerViewManager
|
||||
extends ViewGroupManager<ReactHorizontalScrollContainerView> {
|
||||
|
||||
protected static final String REACT_CLASS = "AndroidHorizontalScrollContentView";
|
||||
|
||||
public ReactHorizontalScrollContainerViewManager() {}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return REACT_CLASS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ReactHorizontalScrollContainerView createViewInstance(ThemedReactContext context) {
|
||||
return new ReactHorizontalScrollContainerView(context);
|
||||
}
|
||||
}
|
||||
+122
@@ -0,0 +1,122 @@
|
||||
general:
|
||||
branches:
|
||||
ignore:
|
||||
- gh-pages # list of branches to ignore
|
||||
machine:
|
||||
node:
|
||||
version: 6.2.0
|
||||
environment:
|
||||
PATH: "~/$CIRCLE_PROJECT_REPONAME/gradle-2.9/bin:/home/ubuntu/buck/bin:$PATH"
|
||||
TERM: "dumb"
|
||||
ADB_INSTALL_TIMEOUT: 10
|
||||
GRADLE_OPTS: '-Dorg.gradle.jvmargs="-Xmx512m -XX:+HeapDumpOnOutOfMemoryError"'
|
||||
java:
|
||||
version: 'oraclejdk8'
|
||||
|
||||
dependencies:
|
||||
override:
|
||||
# BUCK and android
|
||||
- if [[ ! -e /home/ubuntu/buck ]]; then git clone https://github.com/facebook/buck.git /home/ubuntu/buck; fi
|
||||
- cd /home/ubuntu/buck && ant
|
||||
- buck --version
|
||||
- source scripts/circle-ci-android-setup.sh && getAndroidSDK
|
||||
- buck fetch ReactAndroid/src/test/java/com/facebook/react/modules
|
||||
- buck fetch ReactAndroid/src/main/java/com/facebook/react
|
||||
- buck fetch ReactAndroid/src/main/java/com/facebook/react/shell
|
||||
- buck fetch ReactAndroid/src/test/...
|
||||
- buck fetch ReactAndroid/src/androidTest/...
|
||||
- ./gradlew :ReactAndroid:downloadBoost :ReactAndroid:downloadDoubleConversion :ReactAndroid:downloadFolly :ReactAndroid:downloadGlog :ReactAndroid:downloadJSCHeaders
|
||||
# CIRCLE_NPM_TOKEN is in React Native project settings in Circle CI.
|
||||
# It was generated for bestander user, easy to replace with anyone's else
|
||||
- echo "//registry.npmjs.org/:_authToken=${CIRCLE_NPM_TOKEN}" > ~/.npmrc
|
||||
- npm config set spin=false
|
||||
- npm config set progress=false
|
||||
- npm install
|
||||
# for eslint bot
|
||||
- npm install github@0.2.4
|
||||
# for website, danger
|
||||
- cd website && npm install
|
||||
- cd danger && npm install
|
||||
cache_directories:
|
||||
- "ReactAndroid/build/downloads"
|
||||
- "/home/ubuntu/buck"
|
||||
- "website/node_modules"
|
||||
- "node_modules"
|
||||
- "danger/node_modules"
|
||||
|
||||
test:
|
||||
pre:
|
||||
# starting emulator in advance because it takes very long to boot
|
||||
- $ANDROID_HOME/tools/emulator -avd testAVD -no-skin -no-audio -no-window:
|
||||
background: true
|
||||
- source scripts/circle-ci-android-setup.sh && waitForAVD
|
||||
|
||||
override:
|
||||
# Run Danger against PRs. This GitHub token grants public_repo access scope. The associated account has no privileged access to the React Native repo. The token must be split in this manner to avoid revocation by GitHub.
|
||||
#- cd danger && DANGER_GITHUB_API_TOKEN="e622517d9f1136ea8900""07c6373666312cdfaa69" npm # run danger
|
||||
# eslint bot. This GitHub token grants public_repo access scope. The token must be split in this manner to avoid revocation by GitHub.
|
||||
- cat <(echo eslint; npm run lint --silent -- --format=json; echo flow; npm run flow --silent -- check --json) | GITHUB_TOKEN="af6ef0d15709bc91d""06a6217a5a826a226fb57b7" CI_USER=$CIRCLE_PROJECT_USERNAME CI_REPO=$CIRCLE_PROJECT_REPONAME PULL_REQUEST_NUMBER=$CIRCLE_PR_NUMBER node bots/code-analysis-bot.js
|
||||
- npm run lint
|
||||
# JS tests for dependencies installed with npm3
|
||||
# Commenting out Flow tests
|
||||
# - npm run flow -- check
|
||||
- npm test -- --maxWorkers=1
|
||||
|
||||
# build app
|
||||
- buck build ReactAndroid/src/main/java/com/facebook/react
|
||||
- buck build ReactAndroid/src/main/java/com/facebook/react/shell
|
||||
|
||||
# compile native libs with Gradle script, we need bridge for unit and
|
||||
# integration tests
|
||||
- ./gradlew :ReactAndroid:packageReactNdkLibsForBuck -Pjobs=1 -Pcom.android.build.threadPoolSize=1:
|
||||
timeout: 360
|
||||
|
||||
# unit tests
|
||||
- buck test ReactAndroid/src/test/... --config build.threads=1
|
||||
|
||||
# integration tests
|
||||
# build JS bundle for instrumentation tests
|
||||
- node local-cli/cli.js bundle --max-workers 1 --platform android --dev true --entry-file ReactAndroid/src/androidTest/js/TestBundle.js --bundle-output ReactAndroid/src/androidTest/assets/AndroidTestBundle.js
|
||||
|
||||
# build test APK
|
||||
# Commented out due to test failures. Please uncomment the next line once these have been fixed. See Issue #15726.
|
||||
# - buck install ReactAndroid/src/androidTest/buck-runner:instrumentation-tests --config build.threads=1
|
||||
|
||||
# run installed apk with tests
|
||||
# - node ./scripts/run-android-ci-instrumentation-tests.js --retries 3 --path ./ReactAndroid/src/androidTest/java/com/facebook/react/tests --package com.facebook.react.tests
|
||||
|
||||
# Android e2e test
|
||||
# disabled pending on https://our.intern.facebook.com/intern/tasks?t=16912142
|
||||
# - source scripts/circle-ci-android-setup.sh && retry3 node ./scripts/run-ci-e2e-tests.js --android --js --retries 2
|
||||
|
||||
# testing docs generation
|
||||
- cd website && npm test
|
||||
- cd website && node ./server/generate.js
|
||||
# if website can be built, deploy regardless of test failures
|
||||
- if [[ ($CIRCLE_BRANCH =~ .*-stable || $CIRCLE_BRANCH == "master") && $CIRCLE_PROJECT_USERNAME == "facebook" && -z $CI_PULL_REQUEST && -z $CIRCLE_PR_USERNAME ]]; then git config --global user.email "reactjs-bot@users.noreply.github.com" && git config --global user.name "Website Deployment Script" && echo "machine github.com login reactjs-bot password $GITHUB_TOKEN" > ~/.netrc && cd website && GIT_USER=reactjs-bot npm run gh-pages; fi
|
||||
|
||||
post:
|
||||
# copy test report for Circle CI to display
|
||||
- mkdir -p $CIRCLE_TEST_REPORTS/junit/
|
||||
- find . -type f -regex ".*/build/test-results/debug/.*xml" -exec cp {} $CIRCLE_TEST_REPORTS/junit/ \;
|
||||
- find . -type f -regex ".*/outputs/androidTest-results/connected/.*xml" -exec cp {} $CIRCLE_TEST_REPORTS/junit/ \;
|
||||
# TODO circle does not understand Buck's report, maybe need to transform xml slightly
|
||||
#- find . -type f -regex ".*/buck-out/gen/ReactAndroid/src/test/.*/.*xml" -exec cp {} $CIRCLE_TEST_REPORTS/junit/ \;
|
||||
|
||||
deployment:
|
||||
stable:
|
||||
branch: [/.*-stable/, /master/]
|
||||
owner: facebook
|
||||
commands:
|
||||
- git config --global user.email "reactjs-bot@users.noreply.github.com"
|
||||
- git config --global user.name "Website Deployment Script"
|
||||
- echo "machine github.com login reactjs-bot password $GITHUB_TOKEN" > ~/.netrc
|
||||
# publish to npm
|
||||
- node ./scripts/publish-npm.js
|
||||
|
||||
experimental:
|
||||
notify:
|
||||
branches:
|
||||
only:
|
||||
- master
|
||||
- /.*-stable/
|
||||
@@ -35,8 +35,8 @@ Install a library with native dependencies:
|
||||
$ npm install <library-with-native-dependencies> --save
|
||||
```
|
||||
|
||||
**Note:** _`--save` or `--save-dev` flag is very important for this step. React Native will link
|
||||
your libs based on `dependencies` and `devDependencies` in your `package.json` file._
|
||||
> ***Note:*** `--save` or `--save-dev` flag is very important for this step. React Native will link
|
||||
your libs based on `dependencies` and `devDependencies` in your `package.json` file.
|
||||
|
||||
#### Step 2
|
||||
|
||||
@@ -47,6 +47,10 @@ $ react-native link
|
||||
|
||||
Done! All libraries with native dependencies should be successfully linked to your iOS/Android project.
|
||||
|
||||
> ***Note:*** If your iOS project is using CocoaPods (contains `Podfile`) and linked library has `podspec` file,
|
||||
then `react-native link` will link library using Podfile. To support non-trivial Podfiles
|
||||
add `# Add new pods below this line` comment to places where you expect pods to be added.
|
||||
|
||||
### Manual linking
|
||||
|
||||
#### Step 1
|
||||
|
||||
@@ -94,6 +94,9 @@ fs.readFileSync.mockImplementation(function(filepath, encoding) {
|
||||
if (isDirNode(node)) {
|
||||
throw new Error('Error readFileSync a dir: ' + filepath);
|
||||
}
|
||||
if (Buffer.isBuffer(node) && typeof encoding !== 'undefined') {
|
||||
return node.toString();
|
||||
}
|
||||
return node;
|
||||
});
|
||||
|
||||
@@ -133,7 +136,12 @@ function fsError(code, message) {
|
||||
}
|
||||
|
||||
function isDirNode(node) {
|
||||
return node && typeof node === 'object' && node.SYMLINK == null;
|
||||
return (
|
||||
node &&
|
||||
typeof node === 'object' &&
|
||||
node.SYMLINK == null &&
|
||||
Buffer.isBuffer(node) === false
|
||||
);
|
||||
}
|
||||
|
||||
function readlinkSync(filepath) {
|
||||
@@ -1,4 +1,4 @@
|
||||
const fs = require('fs');
|
||||
const fs = require.requireActual('fs');
|
||||
const path = require('path');
|
||||
|
||||
const manifest = fs.readFileSync(path.join(__dirname, './files/AndroidManifest.xml'));
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
const fs = require('fs');
|
||||
const fs = require.requireActual('fs');
|
||||
const path = require('path');
|
||||
const android = require('./android');
|
||||
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
const fs = require('fs');
|
||||
const fs = require.requireActual('fs');
|
||||
const path = require('path');
|
||||
|
||||
exports.valid = {
|
||||
'demoProject.xcodeproj': {
|
||||
'project.pbxproj': fs.readFileSync(path.join(__dirname, './files/project.pbxproj')),
|
||||
},
|
||||
'TestPod.podspec': 'empty'
|
||||
};
|
||||
|
||||
exports.validTestName = {
|
||||
@@ -12,3 +13,7 @@ exports.validTestName = {
|
||||
'project.pbxproj': fs.readFileSync(path.join(__dirname, './files/project.pbxproj')),
|
||||
},
|
||||
};
|
||||
|
||||
exports.pod = {
|
||||
'TestPod.podspec': 'empty'
|
||||
};
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const android = require('./android');
|
||||
const ios = require('./ios');
|
||||
|
||||
const flat = {
|
||||
android: android.valid,
|
||||
ios: ios.valid,
|
||||
Podfile: 'empty'
|
||||
};
|
||||
|
||||
const nested = {
|
||||
@@ -21,4 +20,9 @@ const withExamples = {
|
||||
android: android.valid,
|
||||
};
|
||||
|
||||
module.exports = { flat, nested, withExamples };
|
||||
const withPods = {
|
||||
Podfile: 'content',
|
||||
ios: ios.pod
|
||||
};
|
||||
|
||||
module.exports = { flat, nested, withExamples, withPods };
|
||||
|
||||
@@ -11,13 +11,15 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
jest.mock('fs');
|
||||
|
||||
const fs = require('fs');
|
||||
const findAndroidAppFolder = require('../../android/findAndroidAppFolder');
|
||||
const mockFS = require('mock-fs');
|
||||
const mocks = require('../../__fixtures__/android');
|
||||
|
||||
describe('android::findAndroidAppFolder', () => {
|
||||
beforeAll(() => {
|
||||
mockFS({
|
||||
fs.__setMockFilesystem({
|
||||
empty: {},
|
||||
nested: {
|
||||
android: {
|
||||
@@ -31,15 +33,11 @@ describe('android::findAndroidAppFolder', () => {
|
||||
});
|
||||
|
||||
it('returns an android app folder if it exists in the given folder', () => {
|
||||
expect(findAndroidAppFolder('flat')).toBe('android');
|
||||
expect(findAndroidAppFolder('nested')).toBe('android/app');
|
||||
expect(findAndroidAppFolder('/flat')).toBe('android');
|
||||
expect(findAndroidAppFolder('/nested')).toBe('android/app');
|
||||
});
|
||||
|
||||
it('returns `null` if there is no android app folder', () => {
|
||||
expect(findAndroidAppFolder('empty')).toBeNull();
|
||||
});
|
||||
|
||||
afterAll(() => {
|
||||
mockFS.restore();
|
||||
expect(findAndroidAppFolder('/empty')).toBeNull();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -11,13 +11,15 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
jest.mock('fs');
|
||||
|
||||
const findManifest = require('../../android/findManifest');
|
||||
const mockFS = require('mock-fs');
|
||||
const fs = require('fs');
|
||||
const mocks = require('../../__fixtures__/android');
|
||||
|
||||
describe('android::findManifest', () => {
|
||||
beforeAll(() => {
|
||||
mockFS({
|
||||
fs.__setMockFilesystem({
|
||||
empty: {},
|
||||
flat: {
|
||||
android: mocks.valid,
|
||||
@@ -26,14 +28,10 @@ describe('android::findManifest', () => {
|
||||
});
|
||||
|
||||
it('returns a manifest path if file exists in the folder', () => {
|
||||
expect(typeof findManifest('flat')).toBe('string');
|
||||
expect(typeof findManifest('/flat')).toBe('string');
|
||||
});
|
||||
|
||||
it('returns `null` if there is no manifest in the folder', () => {
|
||||
expect(findManifest('empty')).toBeNull();
|
||||
});
|
||||
|
||||
afterAll(() => {
|
||||
mockFS.restore();
|
||||
expect(findManifest('/empty')).toBeNull();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -11,13 +11,15 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
jest.mock('fs');
|
||||
|
||||
const findPackageClassName = require('../../android/findPackageClassName');
|
||||
const mockFS = require('mock-fs');
|
||||
const fs = require('fs');
|
||||
const mocks = require('../../__fixtures__/android');
|
||||
|
||||
describe('android::findPackageClassName', () => {
|
||||
beforeAll(() => {
|
||||
mockFS({
|
||||
fs.__setMockFilesystem({
|
||||
empty: {},
|
||||
flatJava: {
|
||||
android: mocks.valid,
|
||||
@@ -29,22 +31,20 @@ describe('android::findPackageClassName', () => {
|
||||
});
|
||||
|
||||
it('returns manifest content if file exists in the folder', () => {
|
||||
expect(typeof findPackageClassName('flatJava')).toBe('string');
|
||||
expect(typeof findPackageClassName('/flatJava')).toBe('string');
|
||||
});
|
||||
|
||||
it('returns the name of the java class implementing ReactPackage', () => {
|
||||
expect(findPackageClassName('flatJava')).toBe('SomeExampleJavaPackage');
|
||||
expect(findPackageClassName('/flatJava')).toBe('SomeExampleJavaPackage');
|
||||
});
|
||||
|
||||
it('returns the name of the kotlin class implementing ReactPackage', () => {
|
||||
expect(findPackageClassName('flatKotlin')).toBe('SomeExampleKotlinPackage');
|
||||
expect(findPackageClassName('/flatKotlin')).toBe(
|
||||
'SomeExampleKotlinPackage',
|
||||
);
|
||||
});
|
||||
|
||||
it('returns `null` if there are no matches', () => {
|
||||
expect(findPackageClassName('empty')).toBeNull();
|
||||
});
|
||||
|
||||
afterAll(() => {
|
||||
mockFS.restore();
|
||||
expect(findPackageClassName('/empty')).toBeNull();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -11,15 +11,17 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
jest.mock('fs');
|
||||
|
||||
const getDependencyConfig = require('../../android').dependencyConfig;
|
||||
const mockFS = require('mock-fs');
|
||||
const fs = require('fs');
|
||||
const mocks = require('../../__fixtures__/android');
|
||||
|
||||
const userConfig = {};
|
||||
|
||||
describe('android::getDependencyConfig', () => {
|
||||
beforeAll(() => {
|
||||
mockFS({
|
||||
fs.__setMockFilesystem({
|
||||
empty: {},
|
||||
nested: {
|
||||
android: {
|
||||
@@ -38,27 +40,23 @@ describe('android::getDependencyConfig', () => {
|
||||
});
|
||||
|
||||
it('returns an object with android project configuration', () => {
|
||||
expect(getDependencyConfig('nested', userConfig)).not.toBeNull();
|
||||
expect(typeof getDependencyConfig('nested', userConfig)).toBe('object');
|
||||
expect(getDependencyConfig('/nested', userConfig)).not.toBeNull();
|
||||
expect(typeof getDependencyConfig('/nested', userConfig)).toBe('object');
|
||||
});
|
||||
|
||||
it('returns `null` if manifest file has not been found', () => {
|
||||
expect(getDependencyConfig('empty', userConfig)).toBeNull();
|
||||
expect(getDependencyConfig('/empty', userConfig)).toBeNull();
|
||||
});
|
||||
|
||||
it('returns `null` if android project was not found', () => {
|
||||
expect(getDependencyConfig('empty', userConfig)).toBeNull();
|
||||
expect(getDependencyConfig('/empty', userConfig)).toBeNull();
|
||||
});
|
||||
|
||||
it('returns `null` if android project does not contain ReactPackage', () => {
|
||||
expect(getDependencyConfig('noPackage', userConfig)).toBeNull();
|
||||
expect(getDependencyConfig('/noPackage', userConfig)).toBeNull();
|
||||
});
|
||||
|
||||
it('returns `null` if it cannot find a packageClassName', () => {
|
||||
expect(getDependencyConfig('corrupted', userConfig)).toBeNull();
|
||||
});
|
||||
|
||||
afterAll(() => {
|
||||
mockFS.restore();
|
||||
expect(getDependencyConfig('/corrupted', userConfig)).toBeNull();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -11,13 +11,15 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
jest.mock('fs');
|
||||
|
||||
const getProjectConfig = require('../../android').projectConfig;
|
||||
const mockFS = require('mock-fs');
|
||||
const fs = require('fs');
|
||||
const mocks = require('../../__fixtures__/android');
|
||||
|
||||
describe('android::getProjectConfig', () => {
|
||||
beforeAll(() => {
|
||||
mockFS({
|
||||
fs.__setMockFilesystem({
|
||||
empty: {},
|
||||
nested: {
|
||||
android: {
|
||||
@@ -38,7 +40,7 @@ describe('android::getProjectConfig', () => {
|
||||
|
||||
it("returns `null` if manifest file hasn't been found", () => {
|
||||
const userConfig = {};
|
||||
const folder = 'noManifest';
|
||||
const folder = '/noManifest';
|
||||
|
||||
expect(getProjectConfig(folder, userConfig)).toBeNull();
|
||||
});
|
||||
@@ -46,7 +48,7 @@ describe('android::getProjectConfig', () => {
|
||||
describe('returns an object with android project configuration for', () => {
|
||||
it('nested structure', () => {
|
||||
const userConfig = {};
|
||||
const folder = 'nested';
|
||||
const folder = '/nested';
|
||||
|
||||
expect(getProjectConfig(folder, userConfig)).not.toBeNull();
|
||||
expect(typeof getProjectConfig(folder, userConfig)).toBe('object');
|
||||
@@ -54,7 +56,7 @@ describe('android::getProjectConfig', () => {
|
||||
|
||||
it('flat structure', () => {
|
||||
const userConfig = {};
|
||||
const folder = 'flat';
|
||||
const folder = '/flat';
|
||||
|
||||
expect(getProjectConfig(folder, userConfig)).not.toBeNull();
|
||||
expect(typeof getProjectConfig(folder, userConfig)).toBe('object');
|
||||
@@ -64,7 +66,7 @@ describe('android::getProjectConfig', () => {
|
||||
const userConfig = {
|
||||
manifestPath: 'src/main/AndroidManifest.xml',
|
||||
};
|
||||
const folder = 'multiple';
|
||||
const folder = '/multiple';
|
||||
|
||||
expect(getProjectConfig(folder, userConfig)).not.toBeNull();
|
||||
expect(typeof getProjectConfig(folder, userConfig)).toBe('object');
|
||||
@@ -73,12 +75,8 @@ describe('android::getProjectConfig', () => {
|
||||
|
||||
it('should return `null` if android project was not found', () => {
|
||||
const userConfig = {};
|
||||
const folder = 'empty';
|
||||
const folder = '/empty';
|
||||
|
||||
expect(getProjectConfig(folder, userConfig)).toBeNull();
|
||||
});
|
||||
|
||||
afterAll(() => {
|
||||
mockFS.restore();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -11,14 +11,16 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
jest.mock('fs');
|
||||
|
||||
const findManifest = require('../../android/findManifest');
|
||||
const readManifest = require('../../android/readManifest');
|
||||
const mockFS = require('mock-fs');
|
||||
const fs = require('fs');
|
||||
const mocks = require('../../__fixtures__/android');
|
||||
|
||||
describe('android::readManifest', () => {
|
||||
beforeAll(() => {
|
||||
mockFS({
|
||||
fs.__setMockFilesystem({
|
||||
empty: {},
|
||||
nested: {
|
||||
android: {
|
||||
@@ -29,19 +31,15 @@ describe('android::readManifest', () => {
|
||||
});
|
||||
|
||||
it('returns manifest content if file exists in the folder', () => {
|
||||
const manifestPath = findManifest('nested');
|
||||
const manifestPath = findManifest('/nested');
|
||||
expect(readManifest(manifestPath)).not.toBeNull();
|
||||
expect(typeof readManifest(manifestPath)).toBe('object');
|
||||
});
|
||||
|
||||
it('throws an error if there is no manifest in the folder', () => {
|
||||
const fakeManifestPath = findManifest('empty');
|
||||
const fakeManifestPath = findManifest('/empty');
|
||||
expect(() => {
|
||||
readManifest(fakeManifestPath);
|
||||
}).toThrow();
|
||||
});
|
||||
|
||||
afterAll(() => {
|
||||
mockFS.restore();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -11,24 +11,26 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
jest.mock('fs');
|
||||
|
||||
const findAssets = require('../findAssets');
|
||||
const dependencies = require('../__fixtures__/dependencies');
|
||||
const mockFs = require('mock-fs');
|
||||
const fs = require('fs');
|
||||
|
||||
describe('findAssets', () => {
|
||||
beforeEach(() => {
|
||||
mockFs({testDir: dependencies.withAssets});
|
||||
fs.__setMockFilesystem({testDir: dependencies.withAssets});
|
||||
});
|
||||
|
||||
it('returns an array of all files in given folders', () => {
|
||||
const assets = findAssets('testDir', ['fonts', 'images']);
|
||||
const assets = findAssets('/testDir', ['fonts', 'images']);
|
||||
|
||||
expect(Array.isArray(assets)).toBeTruthy();
|
||||
expect(assets).toHaveLength(3);
|
||||
});
|
||||
|
||||
it('prepends assets paths with the folder path', () => {
|
||||
const assets = findAssets('testDir', ['fonts', 'images']);
|
||||
const assets = findAssets('/testDir', ['fonts', 'images']);
|
||||
|
||||
assets.forEach(assetPath => {
|
||||
expect(assetPath).toContain('testDir');
|
||||
@@ -36,10 +38,6 @@ describe('findAssets', () => {
|
||||
});
|
||||
|
||||
it('returns an empty array if given assets are null', () => {
|
||||
expect(findAssets('testDir', null)).toHaveLength(0);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
mockFs.restore();
|
||||
expect(findAssets('/testDir', null)).toHaveLength(0);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
'use strict';
|
||||
|
||||
jest.mock('fs');
|
||||
|
||||
const findPodfilePath = require('../../ios/findPodfilePath');
|
||||
const fs = require('fs');
|
||||
const projects = require('../../__fixtures__/projects');
|
||||
const ios = require('../../__fixtures__/ios');
|
||||
|
||||
describe('ios::findPodfilePath', () => {
|
||||
it('returns null if there is no Podfile', () => {
|
||||
fs.__setMockFilesystem(ios.valid);
|
||||
expect(findPodfilePath('')).toBeNull();
|
||||
});
|
||||
|
||||
it('returns Podfile path if it exists', () => {
|
||||
fs.__setMockFilesystem(projects.withPods);
|
||||
expect(findPodfilePath('/ios')).toContain('Podfile');
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,44 @@
|
||||
'use strict';
|
||||
|
||||
jest.mock('fs');
|
||||
|
||||
const findPodspecName = require('../../ios/findPodspecName');
|
||||
const fs = require('fs');
|
||||
const projects = require('../../__fixtures__/projects');
|
||||
const ios = require('../../__fixtures__/ios');
|
||||
|
||||
describe('ios::findPodspecName', () => {
|
||||
it('returns null if there is not podspec file', () => {
|
||||
fs.__setMockFilesystem(projects.flat);
|
||||
expect(findPodspecName('')).toBeNull();
|
||||
});
|
||||
|
||||
it('returns podspec name if only one exists', () => {
|
||||
fs.__setMockFilesystem(ios.pod);
|
||||
expect(findPodspecName('/')).toBe('TestPod');
|
||||
});
|
||||
|
||||
it('returns podspec name that match packet directory', () => {
|
||||
fs.__setMockFilesystem({
|
||||
user: {
|
||||
PacketName: {
|
||||
'Another.podspec': 'empty',
|
||||
'PacketName.podspec': 'empty'
|
||||
}
|
||||
}
|
||||
});
|
||||
expect(findPodspecName('/user/PacketName')).toBe('PacketName');
|
||||
});
|
||||
|
||||
it('returns first podspec name if not match in directory', () => {
|
||||
fs.__setMockFilesystem({
|
||||
user: {
|
||||
packet: {
|
||||
'Another.podspec': 'empty',
|
||||
'PacketName.podspec': 'empty'
|
||||
}
|
||||
}
|
||||
});
|
||||
expect(findPodspecName('/user/packet')).toBe('Another');
|
||||
});
|
||||
});
|
||||
@@ -11,49 +11,51 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
jest.mock('fs');
|
||||
|
||||
const findProject = require('../../ios/findProject');
|
||||
const mockFS = require('mock-fs');
|
||||
const fs = require('fs');
|
||||
const projects = require('../../__fixtures__/projects');
|
||||
const ios = require('../../__fixtures__/ios');
|
||||
|
||||
describe('ios::findProject', () => {
|
||||
it('returns path to xcodeproj if found', () => {
|
||||
mockFS(projects.flat);
|
||||
expect(findProject('')).not.toBeNull();
|
||||
fs.__setMockFilesystem(projects.flat);
|
||||
expect(findProject('/')).not.toBeNull();
|
||||
});
|
||||
|
||||
it('returns null if there are no projects', () => {
|
||||
mockFS({testDir: projects});
|
||||
expect(findProject('')).toBeNull();
|
||||
fs.__setMockFilesystem({testDir: projects});
|
||||
expect(findProject('/')).toBeNull();
|
||||
});
|
||||
|
||||
it('returns ios project regardless of its name', () => {
|
||||
mockFS({ios: ios.validTestName});
|
||||
expect(findProject('')).not.toBeNull();
|
||||
fs.__setMockFilesystem({ios: ios.validTestName});
|
||||
expect(findProject('/')).not.toBeNull();
|
||||
});
|
||||
|
||||
it('ignores node_modules', () => {
|
||||
mockFS({node_modules: projects.flat});
|
||||
expect(findProject('')).toBeNull();
|
||||
fs.__setMockFilesystem({node_modules: projects.flat});
|
||||
expect(findProject('/')).toBeNull();
|
||||
});
|
||||
|
||||
it('ignores Pods', () => {
|
||||
mockFS({Pods: projects.flat});
|
||||
expect(findProject('')).toBeNull();
|
||||
fs.__setMockFilesystem({Pods: projects.flat});
|
||||
expect(findProject('/')).toBeNull();
|
||||
});
|
||||
|
||||
it('ignores Pods inside `ios` folder', () => {
|
||||
mockFS({
|
||||
fs.__setMockFilesystem({
|
||||
ios: {
|
||||
Pods: projects.flat,
|
||||
DemoApp: projects.flat.ios,
|
||||
},
|
||||
});
|
||||
expect(findProject('')).toBe('ios/DemoApp/demoProject.xcodeproj');
|
||||
expect(findProject('/')).toBe('ios/DemoApp/demoProject.xcodeproj');
|
||||
});
|
||||
|
||||
it('ignores xcodeproj from example folders', () => {
|
||||
mockFS({
|
||||
fs.__setMockFilesystem({
|
||||
examples: projects.flat,
|
||||
Examples: projects.flat,
|
||||
example: projects.flat,
|
||||
@@ -61,11 +63,11 @@ describe('ios::findProject', () => {
|
||||
Zpp: projects.flat,
|
||||
});
|
||||
|
||||
expect(findProject('').toLowerCase()).not.toContain('example');
|
||||
expect(findProject('/').toLowerCase()).not.toContain('example');
|
||||
});
|
||||
|
||||
it('ignores xcodeproj from sample folders', () => {
|
||||
mockFS({
|
||||
fs.__setMockFilesystem({
|
||||
samples: projects.flat,
|
||||
Samples: projects.flat,
|
||||
sample: projects.flat,
|
||||
@@ -73,11 +75,11 @@ describe('ios::findProject', () => {
|
||||
Zpp: projects.flat,
|
||||
});
|
||||
|
||||
expect(findProject('').toLowerCase()).not.toContain('sample');
|
||||
expect(findProject('/').toLowerCase()).not.toContain('sample');
|
||||
});
|
||||
|
||||
it('ignores xcodeproj from test folders at any level', () => {
|
||||
mockFS({
|
||||
fs.__setMockFilesystem({
|
||||
test: projects.flat,
|
||||
IntegrationTests: projects.flat,
|
||||
tests: projects.flat,
|
||||
@@ -87,10 +89,6 @@ describe('ios::findProject', () => {
|
||||
},
|
||||
});
|
||||
|
||||
expect(findProject('').toLowerCase()).not.toContain('test');
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
mockFS.restore();
|
||||
expect(findProject('/').toLowerCase()).not.toContain('test');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -11,32 +11,34 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
jest.mock('fs');
|
||||
|
||||
const getProjectConfig = require('../../ios').projectConfig;
|
||||
const mockFS = require('mock-fs');
|
||||
const fs = require('fs');
|
||||
const projects = require('../../__fixtures__/projects');
|
||||
|
||||
describe('ios::getProjectConfig', () => {
|
||||
const userConfig = {};
|
||||
|
||||
beforeEach(() => {
|
||||
mockFS({testDir: projects});
|
||||
fs.__setMockFilesystem({testDir: projects});
|
||||
});
|
||||
|
||||
it('returns an object with ios project configuration', () => {
|
||||
const folder = 'testDir/nested';
|
||||
const folder = '/testDir/nested';
|
||||
|
||||
expect(getProjectConfig(folder, userConfig)).not.toBeNull();
|
||||
expect(typeof getProjectConfig(folder, userConfig)).toBe('object');
|
||||
});
|
||||
|
||||
it('returns `null` if ios project was not found', () => {
|
||||
const folder = 'testDir/empty';
|
||||
const folder = '/testDir/empty';
|
||||
|
||||
expect(getProjectConfig(folder, userConfig)).toBeNull();
|
||||
});
|
||||
|
||||
it('returns normalized shared library names', () => {
|
||||
const projectConfig = getProjectConfig('testDir/nested', {
|
||||
const projectConfig = getProjectConfig('/testDir/nested', {
|
||||
sharedLibraries: ['libc++', 'libz.tbd', 'HealthKit', 'HomeKit.framework'],
|
||||
});
|
||||
|
||||
@@ -47,8 +49,4 @@ describe('ios::getProjectConfig', () => {
|
||||
'HomeKit.framework',
|
||||
]);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
mockFS.restore();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
'use strict';
|
||||
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
module.exports = function findPodfilePath(projectFolder) {
|
||||
const podFilePath = path.join(projectFolder, '..', 'Podfile');
|
||||
const podFileExists = fs.existsSync(podFilePath);
|
||||
|
||||
return podFileExists ? podFilePath : null;
|
||||
};
|
||||
@@ -0,0 +1,28 @@
|
||||
'use strict';
|
||||
|
||||
const glob = require('glob');
|
||||
const path = require('path');
|
||||
|
||||
module.exports = function findPodspecName(folder) {
|
||||
const podspecs = glob.sync('*.podspec', { cwd: folder });
|
||||
let podspecFile = null;
|
||||
if (podspecs.length === 0) {
|
||||
return null;
|
||||
}
|
||||
else if (podspecs.length === 1) {
|
||||
podspecFile = podspecs[0];
|
||||
}
|
||||
else {
|
||||
const folderParts = folder.split(path.sep);
|
||||
const currentFolder = folderParts[folderParts.length - 1];
|
||||
const toSelect = podspecs.indexOf(currentFolder + '.podspec');
|
||||
if (toSelect === -1) {
|
||||
podspecFile = podspecs[0];
|
||||
}
|
||||
else {
|
||||
podspecFile = podspecs[toSelect];
|
||||
}
|
||||
}
|
||||
|
||||
return podspecFile.replace('.podspec', '');
|
||||
};
|
||||
@@ -9,6 +9,8 @@
|
||||
'use strict';
|
||||
|
||||
const findProject = require('./findProject');
|
||||
const findPodfilePath = require('./findPodfilePath');
|
||||
const findPodspecName = require('./findPodspecName');
|
||||
const path = require('path');
|
||||
|
||||
/**
|
||||
@@ -44,6 +46,8 @@ exports.projectConfig = function projectConfigIOS(folder, userConfig) {
|
||||
sourceDir: path.dirname(projectPath),
|
||||
folder: folder,
|
||||
pbxprojPath: path.join(projectPath, 'project.pbxproj'),
|
||||
podfile: findPodfilePath(projectPath),
|
||||
podspec: findPodspecName(folder),
|
||||
projectPath: projectPath,
|
||||
projectName: path.basename(projectPath),
|
||||
libraryFolder: userConfig.libraryFolder || 'Libraries',
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
source 'https://github.com/CocoaPods/Specs.git'
|
||||
platform :ios, '9.0'
|
||||
|
||||
target 'Testing' do
|
||||
pod 'TestPod', '~> 3.1'
|
||||
|
||||
# test should point to this line
|
||||
end
|
||||
@@ -0,0 +1,30 @@
|
||||
source 'https://github.com/CocoaPods/Specs.git'
|
||||
platform :ios, '9.0'
|
||||
|
||||
target 'none' do
|
||||
pod 'React',
|
||||
:path => "../node_modules/react-native",
|
||||
:subspecs => [
|
||||
"Core",
|
||||
"ART",
|
||||
"RCTActionSheet",
|
||||
"RCTAnimation",
|
||||
"RCTCameraRoll",
|
||||
"RCTGeolocation",
|
||||
"RCTImage",
|
||||
"RCTNetwork",
|
||||
"RCTText",
|
||||
"RCTVibration",
|
||||
"RCTWebSocket",
|
||||
"DevSupport",
|
||||
"BatchedBridge"
|
||||
]
|
||||
|
||||
pod 'Yoga',
|
||||
:path => "../node_modules/react-native/ReactCommon/yoga"
|
||||
|
||||
# test should point to this line
|
||||
post_install do |installer|
|
||||
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,34 @@
|
||||
source 'https://github.com/CocoaPods/Specs.git'
|
||||
# platform :ios, '9.0'
|
||||
|
||||
target 'None' do
|
||||
# Uncomment the next line if you're using Swift or would like to use dynamic frameworks
|
||||
# use_frameworks!
|
||||
# Your 'node_modules' directory is probably in the root of your project, # but if not, adjust the `:path` accordingly
|
||||
pod 'React', :path => '../node_modules/react-native', :subspecs => [
|
||||
'Core',
|
||||
'RCTText',
|
||||
'RCTNetwork',
|
||||
'BatchedBridge',
|
||||
'RCTImage',
|
||||
'RCTWebSocket', # needed for debugging
|
||||
# Add any other subspecs you want to use in your project
|
||||
]
|
||||
|
||||
# Add new pods below this line
|
||||
|
||||
# test should point to this line
|
||||
target 'NoneTests' do
|
||||
inherit! :search_paths
|
||||
# Pods for testing
|
||||
end
|
||||
end
|
||||
|
||||
target 'Second' do
|
||||
|
||||
target 'NoneUITests' do
|
||||
inherit! :search_paths
|
||||
# Add new pods below this line
|
||||
end
|
||||
|
||||
end
|
||||
@@ -0,0 +1,32 @@
|
||||
source 'https://github.com/CocoaPods/Specs.git'
|
||||
# platform :ios, '9.0'
|
||||
|
||||
target 'None' do
|
||||
# Uncomment the next line if you're using Swift or would like to use dynamic frameworks
|
||||
# use_frameworks!
|
||||
# Your 'node_modules' directory is probably in the root of your project, # but if not, adjust the `:path` accordingly
|
||||
pod 'React', :path => '../node_modules/react-native', :subspecs => [
|
||||
'Core',
|
||||
'RCTText',
|
||||
'RCTNetwork',
|
||||
'BatchedBridge',
|
||||
'RCTImage',
|
||||
'RCTWebSocket', # needed for debugging
|
||||
# Add any other subspecs you want to use in your project
|
||||
]
|
||||
|
||||
# Explicitly include Yoga if you are using RN >= 0.42.0
|
||||
pod "Yoga", :path => "../node_modules/react-native/ReactCommon/yoga"
|
||||
|
||||
# test should point to this line
|
||||
target 'NoneTests' do
|
||||
inherit! :search_paths
|
||||
# Pods for testing
|
||||
end
|
||||
|
||||
target 'NoneUITests' do
|
||||
inherit! :search_paths
|
||||
# Pods for testing
|
||||
end
|
||||
|
||||
end
|
||||
@@ -0,0 +1,30 @@
|
||||
'use strict';
|
||||
|
||||
const path = require('path');
|
||||
const findLineToAddPod = require('../../pods/findLineToAddPod');
|
||||
const readPodfile = require('../../pods/readPodfile');
|
||||
|
||||
const PODFILES_PATH = path.join(__dirname, '../../__fixtures__/pods');
|
||||
const LINE_AFTER_TARGET_IN_TEST_PODFILE = 4;
|
||||
|
||||
describe('pods::findLineToAddPod', () => {
|
||||
it('returns null if file is not Podfile', () => {
|
||||
const podfile = readPodfile(path.join(PODFILES_PATH, '../Info.plist'));
|
||||
expect(findLineToAddPod(podfile, LINE_AFTER_TARGET_IN_TEST_PODFILE)).toBeNull();
|
||||
});
|
||||
|
||||
it('returns correct line number for Simple Podfile', () => {
|
||||
const podfile = readPodfile(path.join(PODFILES_PATH, 'PodfileSimple'));
|
||||
expect(findLineToAddPod(podfile, LINE_AFTER_TARGET_IN_TEST_PODFILE)).toEqual({ line: 7, indentation: 2 });
|
||||
});
|
||||
|
||||
it('returns correct line number for Podfile with target', () => {
|
||||
const podfile = readPodfile(path.join(PODFILES_PATH, 'PodfileWithTarget'));
|
||||
expect(findLineToAddPod(podfile, LINE_AFTER_TARGET_IN_TEST_PODFILE)).toEqual({ line: 21, indentation: 2 });
|
||||
});
|
||||
|
||||
it('returns correct line number for Podfile with function', () => {
|
||||
const podfile = readPodfile(path.join(PODFILES_PATH, 'PodfileWithFunction'));
|
||||
expect(findLineToAddPod(podfile, LINE_AFTER_TARGET_IN_TEST_PODFILE)).toEqual({ line: 26, indentation: 2 });
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,26 @@
|
||||
'use strict';
|
||||
|
||||
const path = require('path');
|
||||
const readPodfile = require('../../pods/readPodfile');
|
||||
const findMarkedLinesInPodfile = require('../../pods/findMarkedLinesInPodfile');
|
||||
|
||||
const PODFILES_PATH = path.join(__dirname, '../../__fixtures__/pods');
|
||||
const LINE_AFTER_TARGET_IN_TEST_PODFILE = 4;
|
||||
|
||||
describe('pods::findMarkedLinesInPodfile', () => {
|
||||
it('returns empty array if file is not Podfile', () => {
|
||||
const podfile = readPodfile(path.join(PODFILES_PATH, '../Info.plist'));
|
||||
expect(findMarkedLinesInPodfile(podfile)).toEqual([]);
|
||||
});
|
||||
|
||||
it('returns empty array for Simple Podfile', () => {
|
||||
const podfile = readPodfile(path.join(PODFILES_PATH, 'PodfileSimple'));
|
||||
expect(findMarkedLinesInPodfile(podfile, LINE_AFTER_TARGET_IN_TEST_PODFILE)).toEqual([]);
|
||||
});
|
||||
|
||||
it('returns correct line numbers for Podfile with marker', () => {
|
||||
const podfile = readPodfile(path.join(PODFILES_PATH, 'PodfileWithMarkers'));
|
||||
const expectedObject = [{ line: 18, indentation: 2 }, { line: 31, indentation: 4 }];
|
||||
expect(findMarkedLinesInPodfile(podfile, LINE_AFTER_TARGET_IN_TEST_PODFILE)).toEqual(expectedObject);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,24 @@
|
||||
'use strict';
|
||||
|
||||
const path = require('path');
|
||||
const findPodTargetLine = require('../../pods/findPodTargetLine');
|
||||
const readPodfile = require('../../pods/readPodfile');
|
||||
|
||||
const PODFILES_PATH = path.join(__dirname, '../../__fixtures__/pods');
|
||||
|
||||
describe('pods::findPodTargetLine', () => {
|
||||
it('returns null if file is not Podfile', () => {
|
||||
const podfile = readPodfile(path.join(PODFILES_PATH, '../Info.plist'));
|
||||
expect(findPodTargetLine(podfile, 'name')).toBeNull();
|
||||
});
|
||||
|
||||
it('returns null if there is not matching project name', () => {
|
||||
const podfile = readPodfile(path.join(PODFILES_PATH, 'PodfileSimple'));
|
||||
expect(findPodTargetLine(podfile, 'invalidName')).toBeNull();
|
||||
});
|
||||
|
||||
it('returns null if there is not matching project name', () => {
|
||||
const podfile = readPodfile(path.join(PODFILES_PATH, 'PodfileSimple'));
|
||||
expect(findPodTargetLine(podfile, 'Testing')).toBe(4);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,32 @@
|
||||
'use strict';
|
||||
|
||||
const path = require('path');
|
||||
const isInstalled = require('../../pods/isInstalled');
|
||||
|
||||
const PODFILES_PATH = path.join(__dirname, '../../__fixtures__/pods');
|
||||
|
||||
describe('pods::isInstalled', () => {
|
||||
it('returns false if pod is missing', () => {
|
||||
const project = { podfile: path.join(PODFILES_PATH, 'PodfileSimple') };
|
||||
const podspecName = { podspec: 'NotExisting' };
|
||||
expect(isInstalled(project, podspecName)).toBe(false);
|
||||
});
|
||||
|
||||
it('returns true for existing pod with version number', () => {
|
||||
const project = { podfile: path.join(PODFILES_PATH, 'PodfileSimple') };
|
||||
const podspecName = { podspec: 'TestPod' };
|
||||
expect(isInstalled(project, podspecName)).toBe(true);
|
||||
});
|
||||
|
||||
it('returns true for existing pod with path', () => {
|
||||
const project = { podfile: path.join(PODFILES_PATH, 'PodfileWithTarget') };
|
||||
const podspecName = { podspec: 'Yoga' };
|
||||
expect(isInstalled(project, podspecName)).toBe(true);
|
||||
});
|
||||
|
||||
it('returns true for existing pod with multiline definition', () => {
|
||||
const project = { podfile: path.join(PODFILES_PATH, 'PodfileWithFunction') };
|
||||
const podspecName = { podspec: 'React' };
|
||||
expect(isInstalled(project, podspecName)).toBe(true);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,35 @@
|
||||
'use strict';
|
||||
|
||||
const path = require('path');
|
||||
const removePodEntry = require('../../pods/removePodEntry');
|
||||
const readPodfile = require('../../pods/readPodfile');
|
||||
|
||||
const PODFILES_PATH = path.join(__dirname, '../../__fixtures__/pods');
|
||||
|
||||
describe('pods::removePodEntry', () => {
|
||||
it('should remove one line from Podfile with TestPod', () => {
|
||||
const { podfileContent, podLinesCount } = readTestPodFile('PodfileSimple');
|
||||
const podFileWithRemoved = removePodEntry(podfileContent, 'TestPod');
|
||||
const newLineCount = podFileWithRemoved.split('\n').length;
|
||||
expect(newLineCount).toBe(podLinesCount - 1);
|
||||
});
|
||||
|
||||
it('should remove one line from Podfile with Yoga', () => {
|
||||
const { podfileContent, podLinesCount } = readTestPodFile('PodfileWithTarget');
|
||||
const podFileWithRemoved = removePodEntry(podfileContent, 'Yoga');
|
||||
const newLineCount = podFileWithRemoved.split('\n').length;
|
||||
expect(newLineCount).toBe(podLinesCount - 1);
|
||||
});
|
||||
|
||||
it('should remove whole reference to React pod from Podfile', () => {
|
||||
const { podfileContent, podLinesCount } = readTestPodFile('PodfileWithTarget');
|
||||
const podFileWithRemoved = removePodEntry(podfileContent, 'React');
|
||||
const newLineCount = podFileWithRemoved.split('\n').length;
|
||||
expect(newLineCount).toBe(podLinesCount - 9);
|
||||
});
|
||||
});
|
||||
|
||||
function readTestPodFile(fileName) {
|
||||
const podfileLines = readPodfile(path.join(PODFILES_PATH, fileName));
|
||||
return { podfileContent: podfileLines.join('\n'), podLinesCount: podfileLines.length };
|
||||
}
|
||||
@@ -29,9 +29,11 @@ const promiseWaterfall = require('./promiseWaterfall');
|
||||
const registerDependencyAndroid = require('./android/registerNativeModule');
|
||||
const registerDependencyWindows = require('./windows/registerNativeModule');
|
||||
const registerDependencyIOS = require('./ios/registerNativeModule');
|
||||
const registerDependencyPods = require('./pods/registerNativeModule');
|
||||
const isInstalledAndroid = require('./android/isInstalled');
|
||||
const isInstalledWindows = require('./windows/isInstalled');
|
||||
const isInstalledIOS = require('./ios/isInstalled');
|
||||
const isInstalledPods = require('./pods/isInstalled');
|
||||
const copyAssetsAndroid = require('./android/copyAssets');
|
||||
const copyAssetsIOS = require('./ios/copyAssets');
|
||||
const getProjectDependencies = require('./getProjectDependencies');
|
||||
@@ -106,17 +108,19 @@ const linkDependencyIOS = (iOSProject, dependency) => {
|
||||
return;
|
||||
}
|
||||
|
||||
const isInstalled = isInstalledIOS(iOSProject, dependency.config.ios);
|
||||
|
||||
const isInstalled = isInstalledIOS(iOSProject, dependency.config.ios) || isInstalledPods(iOSProject, dependency.config.ios);
|
||||
if (isInstalled) {
|
||||
log.info(chalk.grey(`iOS module ${dependency.name} is already linked`));
|
||||
return;
|
||||
}
|
||||
|
||||
log.info(`Linking ${dependency.name} ios dependency`);
|
||||
|
||||
registerDependencyIOS(dependency.config.ios, iOSProject);
|
||||
|
||||
if (iOSProject.podfile && dependency.config.ios.podspec) {
|
||||
registerDependencyPods(dependency, iOSProject);
|
||||
}
|
||||
else {
|
||||
registerDependencyIOS(dependency.config.ios, iOSProject);
|
||||
}
|
||||
log.info(`iOS module ${dependency.name} has been successfully linked`);
|
||||
};
|
||||
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
'use strict';
|
||||
|
||||
module.exports = function addPodEntry(podLines, linesToAddEntry, podName, nodePath) {
|
||||
const newEntry = `pod '${podName}', :path => '../node_modules/${nodePath}'\n`;
|
||||
|
||||
if (!linesToAddEntry) {
|
||||
return;
|
||||
} else if (Array.isArray(linesToAddEntry)) {
|
||||
linesToAddEntry.map(({ line, indentation }, idx) =>
|
||||
podLines.splice(line + idx, 0, getLineToAdd(newEntry, indentation))
|
||||
);
|
||||
} else {
|
||||
const { line, indentation } = linesToAddEntry;
|
||||
podLines.splice(line, 0, getLineToAdd(newEntry, indentation));
|
||||
}
|
||||
};
|
||||
|
||||
function getLineToAdd(newEntry, indentation) {
|
||||
const spaces = Array(indentation + 1).join(' ');
|
||||
return spaces + newEntry;
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
'use strict';
|
||||
|
||||
module.exports = function findLineToAddPod(podLines, firstTargetLine) {
|
||||
// match line with new target: target 'project_name' do (most likely target inside podfile main target)
|
||||
const nextTarget = /target (\'|\")\w+(\'|\") do/g;
|
||||
// match line that has only 'end' (if we don't catch new target or function, this would mean this is end of current target)
|
||||
const endOfCurrentTarget = /^\s*end\s*$/g;
|
||||
// match function definition, like: post_install do |installer| (some Podfiles have function defined inside main target
|
||||
const functionDefinition = /^\s*[a-z_]+\s+do(\s+\|[a-z]+\|)?/g;
|
||||
|
||||
for (let i = firstTargetLine, len = podLines.length; i < len; i++) {
|
||||
const matchNextConstruct = podLines[i].match(nextTarget) || podLines[i].match(functionDefinition);
|
||||
const matchEnd = podLines[i].match(endOfCurrentTarget);
|
||||
|
||||
if (matchNextConstruct || matchEnd) {
|
||||
const firstNonSpaceCharacter = podLines[i].search(/\S/);
|
||||
return {
|
||||
indentation: firstNonSpaceCharacter + (matchEnd ? 2 : 0),
|
||||
line: i
|
||||
};
|
||||
}
|
||||
}
|
||||
return null;
|
||||
};
|
||||
@@ -0,0 +1,12 @@
|
||||
'use strict';
|
||||
const MARKER_TEXT = '# Add new pods below this line';
|
||||
|
||||
module.exports = function findMarkedLinesInPodfile(podLines) {
|
||||
const result = [];
|
||||
for (let i = 0, len = podLines.length; i < len; i++) {
|
||||
if (podLines[i].includes(MARKER_TEXT)) {
|
||||
result.push({ line: i + 1, indentation: podLines[i].indexOf('#') });
|
||||
}
|
||||
}
|
||||
return result;
|
||||
};
|
||||
@@ -0,0 +1,14 @@
|
||||
'use strict';
|
||||
|
||||
module.exports = function findPodTargetLine(podLines, projectName) {
|
||||
const targetName = projectName.replace('.xcodeproj', '');
|
||||
//match first target definition in file: target 'target_name' do
|
||||
const targetRegex = new RegExp('target (\'|\")' + targetName + '(\'|\") do', 'g');
|
||||
for (let i = 0, len = podLines.length; i < len; i++) {
|
||||
const match = podLines[i].match(targetRegex);
|
||||
if (match) {
|
||||
return i + 1;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
};
|
||||
@@ -0,0 +1,19 @@
|
||||
'use strict';
|
||||
|
||||
const readPodfile = require('./readPodfile');
|
||||
|
||||
module.exports = function isInstalled(iOSProject, dependencyConfig) {
|
||||
if (!iOSProject.podfile) {
|
||||
return false;
|
||||
}
|
||||
// match line with pod declaration: pod 'dependencyPodName' (other possible parameters of pod are ignored)
|
||||
const dependencyRegExp = new RegExp('pod\\s+(\'|\")' + dependencyConfig.podspec + '(\'|\")', 'g');
|
||||
const podLines = readPodfile(iOSProject.podfile);
|
||||
for (let i = 0, len = podLines.length; i < len; i++) {
|
||||
const match = podLines[i].match(dependencyRegExp);
|
||||
if (match) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
@@ -0,0 +1,8 @@
|
||||
'use strict';
|
||||
|
||||
const fs = require('fs');
|
||||
|
||||
module.exports = function readPodfile(podfilePath) {
|
||||
const podContent = fs.readFileSync(podfilePath, 'utf8');
|
||||
return podContent.split(/\r?\n/g);
|
||||
};
|
||||
@@ -0,0 +1,25 @@
|
||||
'use strict';
|
||||
|
||||
const readPodfile = require('./readPodfile');
|
||||
const findPodTargetLine = require('./findPodTargetLine');
|
||||
const findLineToAddPod = require('./findLineToAddPod');
|
||||
const findMarkedLinesInPodfile = require('./findMarkedLinesInPodfile');
|
||||
const addPodEntry = require('./addPodEntry');
|
||||
const savePodFile = require('./savePodFile');
|
||||
|
||||
module.exports = function registerNativeModulePods(dependency, iOSProject) {
|
||||
const podLines = readPodfile(iOSProject.podfile);
|
||||
const linesToAddEntry = getLinesToAddEntry(podLines, iOSProject);
|
||||
addPodEntry(podLines, linesToAddEntry, dependency.config.ios.podspec, dependency.name);
|
||||
savePodFile(iOSProject.podfile, podLines);
|
||||
};
|
||||
|
||||
function getLinesToAddEntry(podLines, { projectName }) {
|
||||
const linesToAddPodWithMarker = findMarkedLinesInPodfile(podLines);
|
||||
if (linesToAddPodWithMarker.length > 0) {
|
||||
return linesToAddPodWithMarker;
|
||||
} else {
|
||||
const firstTargetLined = findPodTargetLine(podLines, projectName);
|
||||
return findLineToAddPod(podLines, firstTargetLined);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
'use strict';
|
||||
|
||||
module.exports = function removePodEntry(podfileContent, podName) {
|
||||
// this regex should catch line(s) with full pod definition, like: pod 'podname', :path => '../node_modules/podname', :subspecs => ['Sub2', 'Sub1']
|
||||
const podRegex = new RegExp("\\n( |\\t)*pod\\s+(\"|')" + podName + "(\"|')(,\\s*(:[a-z]+\\s*=>)?\\s*((\"|').*?(\"|')|\\[[\\s\\S]*?\\]))*\\n", 'g');
|
||||
return podfileContent.replace(podRegex, '\n');
|
||||
};
|
||||
@@ -0,0 +1,8 @@
|
||||
'use strict';
|
||||
|
||||
const fs = require('fs');
|
||||
|
||||
module.exports = function savePodFile(podfilePath, podLines) {
|
||||
const newPodfile = podLines.join('\n');
|
||||
fs.writeFileSync(podfilePath, newPodfile);
|
||||
};
|
||||
@@ -0,0 +1,13 @@
|
||||
'use strict';
|
||||
|
||||
const fs = require('fs');
|
||||
const removePodEntry = require('./removePodEntry');
|
||||
|
||||
/**
|
||||
* Unregister native module IOS with CocoaPods
|
||||
*/
|
||||
module.exports = function unregisterNativeModule(dependencyConfig, iOSProject) {
|
||||
const podContent = fs.readFileSync(iOSProject.podfile, 'utf8');
|
||||
const removed = removePodEntry(podContent, dependencyConfig.podspec);
|
||||
fs.writeFileSync(iOSProject.podfile, removed);
|
||||
};
|
||||
@@ -4,16 +4,17 @@ const getProjectDependencies = require('./getProjectDependencies');
|
||||
const unregisterDependencyAndroid = require('./android/unregisterNativeModule');
|
||||
const unregisterDependencyWindows = require('./windows/unregisterNativeModule');
|
||||
const unregisterDependencyIOS = require('./ios/unregisterNativeModule');
|
||||
const unregisterDependencyPods = require('./pods/unregisterNativeModule');
|
||||
const isInstalledAndroid = require('./android/isInstalled');
|
||||
const isInstalledWindows = require('./windows/isInstalled');
|
||||
const isInstalledIOS = require('./ios/isInstalled');
|
||||
const isInstalledPods = require('./pods/isInstalled');
|
||||
const unlinkAssetsAndroid = require('./android/unlinkAssets');
|
||||
const unlinkAssetsIOS = require('./ios/unlinkAssets');
|
||||
const getDependencyConfig = require('./getDependencyConfig');
|
||||
const compact = require('lodash').compact;
|
||||
const difference = require('lodash').difference;
|
||||
const filter = require('lodash').filter;
|
||||
const find = require('lodash').find;
|
||||
const flatten = require('lodash').flatten;
|
||||
const isEmpty = require('lodash').isEmpty;
|
||||
const promiseWaterfall = require('./promiseWaterfall');
|
||||
@@ -65,16 +66,21 @@ const unlinkDependencyIOS = (iOSProject, dependency, packageName, iOSDependencie
|
||||
return;
|
||||
}
|
||||
|
||||
const isInstalled = isInstalledIOS(iOSProject, dependency.ios);
|
||||
|
||||
if (!isInstalled) {
|
||||
const isIosInstalled = isInstalledIOS(iOSProject, dependency.ios);
|
||||
const isPodInstalled = isInstalledPods(iOSProject, dependency.ios);
|
||||
if (!isIosInstalled && !isPodInstalled) {
|
||||
log.info(`iOS module ${packageName} is not installed`);
|
||||
return;
|
||||
}
|
||||
|
||||
log.info(`Unlinking ${packageName} ios dependency`);
|
||||
|
||||
unregisterDependencyIOS(dependency.ios, iOSProject, iOSDependencies);
|
||||
if (isIosInstalled) {
|
||||
unregisterDependencyIOS(dependency.ios, iOSProject, iOSDependencies);
|
||||
}
|
||||
else if (isPodInstalled) {
|
||||
unregisterDependencyPods(dependency.ios, iOSProject);
|
||||
}
|
||||
|
||||
log.info(`iOS module ${packageName} has been successfully unlinked`);
|
||||
};
|
||||
|
||||
+3
-4
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "react-native",
|
||||
"version": "1000.0.0",
|
||||
"version": "0.50.3",
|
||||
"description": "A framework for building native apps using React",
|
||||
"license": "BSD-3-Clause",
|
||||
"repository": {
|
||||
@@ -162,7 +162,7 @@
|
||||
"graceful-fs": "^4.1.3",
|
||||
"inquirer": "^3.0.6",
|
||||
"lodash": "^4.16.6",
|
||||
"metro-bundler": "^0.19.0",
|
||||
"metro-bundler": "^0.20.1",
|
||||
"mime": "^1.3.4",
|
||||
"minimist": "^1.2.0",
|
||||
"mkdirp": "^0.5.1",
|
||||
@@ -200,11 +200,10 @@
|
||||
"eslint-plugin-react": "^7.2.1",
|
||||
"flow-bin": "^0.56.0",
|
||||
"jest": "^21",
|
||||
"mock-fs": "^4.4.1",
|
||||
"prettier": "1.7.0",
|
||||
"react": "16.0.0",
|
||||
"react-test-renderer": "16.0.0",
|
||||
"shelljs": "^0.7.8",
|
||||
"sinon": "^2.2.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
+45
-36
@@ -15,7 +15,7 @@
|
||||
* After changing the files it makes a commit and tags it.
|
||||
* All you have to do is push changes to remote and CI will make a new build.
|
||||
*/
|
||||
|
||||
const fs = require('fs');
|
||||
const {
|
||||
cat,
|
||||
echo,
|
||||
@@ -32,15 +32,15 @@ let argv = minimist(process.argv.slice(2), {
|
||||
});
|
||||
|
||||
// - check we are in release branch, e.g. 0.33-stable
|
||||
let branch = exec(`git symbolic-ref --short HEAD`, {silent: true}).stdout.trim();
|
||||
let branch = exec('git symbolic-ref --short HEAD', {silent: true}).stdout.trim();
|
||||
|
||||
if (branch.indexOf(`-stable`) === -1) {
|
||||
echo(`You must be in 0.XX-stable branch to bump a version`);
|
||||
if (branch.indexOf('-stable') === -1) {
|
||||
echo('You must be in 0.XX-stable branch to bump a version');
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// e.g. 0.33
|
||||
let versionMajor = branch.slice(0, branch.indexOf(`-stable`));
|
||||
let versionMajor = branch.slice(0, branch.indexOf('-stable'));
|
||||
|
||||
// - check that argument version matches branch
|
||||
// e.g. 0.33.1 or 0.33.0-rc4
|
||||
@@ -58,34 +58,43 @@ if (!match) {
|
||||
}
|
||||
let [, major, minor, patch, prerelease] = match;
|
||||
|
||||
cat('scripts/versiontemplates/ReactNativeVersion.java.template')
|
||||
.replace('${major}', major)
|
||||
.replace('${minor}', minor)
|
||||
.replace('${patch}', patch)
|
||||
.replace('${prerelease}', prerelease !== undefined ? `"${prerelease}"` : 'null')
|
||||
.to('ReactAndroid/src/main/java/com/facebook/react/modules/systeminfo/ReactNativeVersion.java');
|
||||
fs.writeFileSync(
|
||||
'ReactAndroid/src/main/java/com/facebook/react/modules/systeminfo/ReactNativeVersion.java',
|
||||
cat('scripts/versiontemplates/ReactNativeVersion.java.template')
|
||||
.replace('${major}', major)
|
||||
.replace('${minor}', minor)
|
||||
.replace('${patch}', patch)
|
||||
.replace('${prerelease}', prerelease !== undefined ? `"${prerelease}"` : 'null'),
|
||||
'utf-8'
|
||||
);
|
||||
|
||||
cat('scripts/versiontemplates/RCTVersion.h.template')
|
||||
.replace('${major}', `@(${major})`)
|
||||
.replace('${minor}', `@(${minor})`)
|
||||
.replace('${patch}', `@(${patch})`)
|
||||
.replace('${prerelease}', prerelease !== undefined ? `@"${prerelease}"` : '[NSNull null]')
|
||||
.to('React/Base/RCTVersion.h');
|
||||
fs.writeFileSync(
|
||||
'React/Base/RCTVersion.h',
|
||||
cat('scripts/versiontemplates/RCTVersion.h.template')
|
||||
.replace('${major}', `@(${major})`)
|
||||
.replace('${minor}', `@(${minor})`)
|
||||
.replace('${patch}', `@(${patch})`)
|
||||
.replace('${prerelease}', prerelease !== undefined ? `@"${prerelease}"` : '[NSNull null]'),
|
||||
'utf-8'
|
||||
);
|
||||
|
||||
cat('scripts/versiontemplates/ReactNativeVersion.js.template')
|
||||
.replace('${major}', major)
|
||||
.replace('${minor}', minor)
|
||||
.replace('${patch}', patch)
|
||||
.replace('${prerelease}', prerelease !== undefined ? `'${prerelease}'` : 'null')
|
||||
.to('Libraries/Core/ReactNativeVersion.js');
|
||||
fs.writeFileSync(
|
||||
'Libraries/Core/ReactNativeVersion.js',
|
||||
cat('scripts/versiontemplates/ReactNativeVersion.js.template')
|
||||
.replace('${major}', major)
|
||||
.replace('${minor}', minor)
|
||||
.replace('${patch}', patch)
|
||||
.replace('${prerelease}', prerelease !== undefined ? `'${prerelease}'` : 'null'),
|
||||
'utf-8'
|
||||
);
|
||||
|
||||
let packageJson = JSON.parse(cat(`package.json`));
|
||||
let packageJson = JSON.parse(cat('package.json'));
|
||||
packageJson.version = version;
|
||||
JSON.stringify(packageJson, null, 2).to(`package.json`);
|
||||
fs.writeFileSync('package.json', JSON.stringify(packageJson, null, 2), 'utf-8');
|
||||
|
||||
// - change ReactAndroid/gradle.properties
|
||||
if (sed(`-i`, /^VERSION_NAME=.*/, `VERSION_NAME=${version}`, `ReactAndroid/gradle.properties`).code) {
|
||||
echo(`Couldn't update version for Gradle`);
|
||||
if (sed('-i', /^VERSION_NAME=.*/, `VERSION_NAME=${version}`, 'ReactAndroid/gradle.properties').code) {
|
||||
echo('Couldn\'t update version for Gradle');
|
||||
exit(1);
|
||||
}
|
||||
|
||||
@@ -93,23 +102,23 @@ if (sed(`-i`, /^VERSION_NAME=.*/, `VERSION_NAME=${version}`, `ReactAndroid/gradl
|
||||
let numberOfChangedLinesWithNewVersion = exec(`git diff -U0 | grep '^[+]' | grep -c ${version} `, {silent: true})
|
||||
.stdout.trim();
|
||||
if (+numberOfChangedLinesWithNewVersion !== 2) {
|
||||
echo(`Failed to update all the files. package.json and gradle.properties must have versions in them`);
|
||||
echo(`Fix the issue, revert and try again`);
|
||||
exec(`git diff`);
|
||||
echo('Failed to update all the files. package.json and gradle.properties must have versions in them');
|
||||
echo('Fix the issue, revert and try again');
|
||||
exec('git diff');
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// - make commit [0.21.0-rc] Bump version numbers
|
||||
if (exec(`git commit -a -m "[${version}] Bump version numbers"`).code) {
|
||||
echo(`failed to commit`);
|
||||
echo('failed to commit');
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// - add tag v0.21.0-rc
|
||||
if (exec(`git tag v${version}`).code) {
|
||||
echo(`failed to tag the commit with v${version}, are you sure this release wasn't made earlier?`);
|
||||
echo(`You may want to rollback the last commit`);
|
||||
echo(`git reset --hard HEAD~1`);
|
||||
echo('You may want to rollback the last commit');
|
||||
echo('git reset --hard HEAD~1');
|
||||
exit(1);
|
||||
}
|
||||
|
||||
@@ -118,10 +127,10 @@ let remote = argv.remote;
|
||||
exec(`git push ${remote} v${version}`);
|
||||
|
||||
// Tag latest if doing stable release
|
||||
if (version.indexOf(`rc`) === -1) {
|
||||
exec(`git tag -d latest`);
|
||||
if (version.indexOf('rc') === -1) {
|
||||
exec('git tag -d latest');
|
||||
exec(`git push ${remote} :latest`);
|
||||
exec(`git tag latest`);
|
||||
exec('git tag latest');
|
||||
exec(`git push ${remote} latest`);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,77 +1,25 @@
|
||||
# inspired by https://github.com/Originate/guide/blob/master/android/guide/Continuous%20Integration.md
|
||||
|
||||
# SDK Built Tools revision, per http://facebook.github.io/react-native/docs/getting-started.html
|
||||
ANDROID_SDK_BUILD_TOOLS_REVISION=23.0.1
|
||||
# API Level we build with
|
||||
ANDROID_SDK_BUILD_API_LEVEL="23"
|
||||
# Minimum API Level we target, used for emulator image
|
||||
ANDROID_SDK_TARGET_API_LEVEL="19"
|
||||
# Emulator name
|
||||
AVD_NAME="testAVD"
|
||||
|
||||
function getAndroidSDK {
|
||||
export PATH="$ANDROID_HOME/platform-tools:$ANDROID_HOME/tools:$PATH"
|
||||
|
||||
DEPS="$ANDROID_HOME/installed-dependencies"
|
||||
|
||||
if [ ! -e $DEPS ]; then
|
||||
echo "Installing Android API level $ANDROID_SDK_TARGET_API_LEVEL, Google APIs, ARM EABI v7a system image..."
|
||||
sdkmanager "system-images;android-$ANDROID_SDK_TARGET_API_LEVEL;google_apis;armeabi-v7a"
|
||||
# x86 image requires hardware acceleration, which is not supported when running within the CircleCI Docker image
|
||||
# echo "Installing Android API level $ANDROID_SDK_TARGET_API_LEVEL, Google APIs, Intel x86 Atom system image..."
|
||||
# sdkmanager "system-images;android-$ANDROID_SDK_TARGET_API_LEVEL;google_apis;x86"
|
||||
echo "Installing build SDK for Android API level $ANDROID_SDK_BUILD_API_LEVEL..."
|
||||
sdkmanager "platforms;android-$ANDROID_SDK_BUILD_API_LEVEL"
|
||||
echo "Installing target SDK for Android API level $ANDROID_SDK_TARGET_API_LEVEL..."
|
||||
sdkmanager "platforms;android-$ANDROID_SDK_TARGET_API_LEVEL"
|
||||
echo "Installing SDK build tools, revision $ANDROID_SDK_BUILD_TOOLS_REVISION..."
|
||||
sdkmanager "build-tools;$ANDROID_SDK_BUILD_TOOLS_REVISION"
|
||||
echo "Installing Google APIs for Android API level $ANDROID_SDK_BUILD_API_LEVEL..."
|
||||
sdkmanager "add-ons;addon-google_apis-google-$ANDROID_SDK_BUILD_API_LEVEL"
|
||||
echo "Installing Android Support Repository"
|
||||
sdkmanager "extras;android;m2repository"
|
||||
echo y | android update sdk --no-ui --all --filter extra-android-m2repository
|
||||
echo no | android create avd -n testAVD -f -t android-19 --abi default/armeabi-v7a &&
|
||||
touch $DEPS
|
||||
fi
|
||||
}
|
||||
|
||||
function getAndroidNDK {
|
||||
NDK_HOME="/opt/ndk"
|
||||
DEPS="$NDK_HOME/installed-dependencies"
|
||||
|
||||
if [ ! -e $DEPS ]; then
|
||||
cd $NDK_HOME
|
||||
echo "Downloading NDK..."
|
||||
curl -o ndk.zip https://dl.google.com/android/repository/android-ndk-r10e-linux-x86.zip
|
||||
curl -o ndk_64.zip https://dl.google.com/android/repository/android-ndk-r10e-linux-x86_64.zip
|
||||
unzip -o -q ndk.zip
|
||||
unzip -o -q ndk_64.zip
|
||||
echo "Installed Android NDK at $NDK_HOME"
|
||||
touch $DEPS
|
||||
rm ndk.zip
|
||||
rm ndk_64.zip
|
||||
fi
|
||||
}
|
||||
|
||||
function createAVD {
|
||||
echo no | avdmanager create avd --name $AVD_NAME --force --package "system-images;android-$ANDROID_SDK_TARGET_API_LEVEL;google_apis;armeabi-v7a" --tag google_apis --abi armeabi-v7a
|
||||
}
|
||||
|
||||
function launchAVD {
|
||||
# The AVD name here should match the one created in createAVD
|
||||
# emulator64-arm -avd $AVD_NAME -no-audio -no-window -no-boot-anim -gpu off
|
||||
emulator -avd $AVD_NAME -no-audio -no-window
|
||||
}
|
||||
|
||||
function waitForAVD {
|
||||
echo "Waiting for Android Virtual Device to finish booting..."
|
||||
local bootanim=""
|
||||
export PATH=$(dirname $(dirname $(which android)))/platform-tools:$PATH
|
||||
until [[ "$bootanim" =~ "stopped" ]]; do
|
||||
sleep 5
|
||||
bootanim=$(adb -e shell getprop init.svc.bootanim 2>&1)
|
||||
echo "boot animation status=$bootanim"
|
||||
echo "emulator status=$bootanim"
|
||||
done
|
||||
echo "Android Virtual Device is ready."
|
||||
}
|
||||
|
||||
function retry3 {
|
||||
|
||||
@@ -48,10 +48,11 @@ try {
|
||||
const CLI_PACKAGE = path.join(ROOT, 'react-native-cli', 'react-native-cli-*.tgz');
|
||||
cd('..');
|
||||
|
||||
// can skip cli install for non sudo mode
|
||||
if (!argv['skip-cli-install']) {
|
||||
if (exec(`sudo npm install -g ${CLI_PACKAGE}`).code) {
|
||||
echo('Could not install react-native-cli globally.');
|
||||
echo('Run with --skip-cli-install to skip this step');
|
||||
if (exec(`npm install -g ${CLI_PACKAGE}`).code) {
|
||||
echo('Could not install react-native-cli globally, please run in su mode');
|
||||
echo('Or with --skip-cli-install to skip this step');
|
||||
exitCode = 1;
|
||||
throw Error(exitCode);
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*/
|
||||
|
||||
#define REACT_NATIVE_VERSION @{ \
|
||||
#define RCT_REACT_NATIVE_VERSION @{ \
|
||||
@"major": ${major}, \
|
||||
@"minor": ${minor}, \
|
||||
@"patch": ${patch}, \
|
||||
|
||||
Reference in New Issue
Block a user