Add setting for skipping fbsource version check

Summary: Added a setting "Match local fbsource chekout", which inverserly corresponds to the `ignore_local_pin` setting in `flipper-launcher.toml`.

Reviewed By: passy

Differential Revision: D19030456

fbshipit-source-id: deaaf4e873a00bbc4e8bd3034353cf580df95a36
This commit is contained in:
Denis Nedelyaev
2019-12-16 06:59:48 -08:00
committed by Facebook Github Bot
parent 4db9388984
commit be53990613
8 changed files with 202 additions and 16 deletions

View File

@@ -76,7 +76,6 @@
"@types/react-redux": "^7.1.5", "@types/react-redux": "^7.1.5",
"@types/react-virtualized-auto-sizer": "^1.0.0", "@types/react-virtualized-auto-sizer": "^1.0.0",
"@types/react-window": "^1.8.1", "@types/react-window": "^1.8.1",
"@types/redux-persist": "^4.3.1",
"@types/rsocket-core": "^0.0.3", "@types/rsocket-core": "^0.0.3",
"@types/testing-library__react": "^9.1.2", "@types/testing-library__react": "^9.1.2",
"@types/tmp": "^0.1.0", "@types/tmp": "^0.1.0",
@@ -110,6 +109,7 @@
"dependencies": { "dependencies": {
"@emotion/core": "^10.0.22", "@emotion/core": "^10.0.22",
"@emotion/styled": "^10.0.23", "@emotion/styled": "^10.0.23",
"@iarna/toml": "^2.2.3",
"@types/promise-retry": "^1.1.3", "@types/promise-retry": "^1.1.3",
"@types/react-color": "^3.0.1", "@types/react-color": "^3.0.1",
"@types/react-test-renderer": "^16.9.1", "@types/react-test-renderer": "^16.9.1",

View File

@@ -10,6 +10,11 @@
import {FlexColumn, Button, styled, Text, FlexRow, Spacer} from 'flipper'; import {FlexColumn, Button, styled, Text, FlexRow, Spacer} from 'flipper';
import React, {Component} from 'react'; import React, {Component} from 'react';
import {updateSettings, Action} from '../reducers/settings'; import {updateSettings, Action} from '../reducers/settings';
import {
Action as LauncherAction,
LauncherSettings,
updateLauncherSettings,
} from '../reducers/launcherSettings';
import {connect} from 'react-redux'; import {connect} from 'react-redux';
import {State as Store} from '../reducers'; import {State as Store} from '../reducers';
import {Settings} from '../reducers/settings'; import {Settings} from '../reducers/settings';
@@ -38,25 +43,30 @@ type OwnProps = {
type StateFromProps = { type StateFromProps = {
settings: Settings; settings: Settings;
launcherSettings: LauncherSettings;
isXcodeDetected: boolean; isXcodeDetected: boolean;
}; };
type DispatchFromProps = { type DispatchFromProps = {
updateSettings: (settings: Settings) => Action; updateSettings: (settings: Settings) => Action;
updateLauncherSettings: (settings: LauncherSettings) => LauncherAction;
}; };
type State = { type State = {
updatedSettings: Settings; updatedSettings: Settings;
updatedLauncherSettings: LauncherSettings;
}; };
type Props = OwnProps & StateFromProps & DispatchFromProps; type Props = OwnProps & StateFromProps & DispatchFromProps;
class SettingsSheet extends Component<Props, State> { class SettingsSheet extends Component<Props, State> {
state: State = { state: State = {
updatedSettings: {...this.props.settings}, updatedSettings: {...this.props.settings},
updatedLauncherSettings: {...this.props.launcherSettings},
}; };
applyChanges = async () => { applyChanges = async () => {
this.props.updateSettings(this.state.updatedSettings); this.props.updateSettings(this.state.updatedSettings);
this.props.updateLauncherSettings(this.state.updatedLauncherSettings);
this.props.onHide(); this.props.onHide();
flush().then(() => { flush().then(() => {
restartFlipper(); restartFlipper();
@@ -104,8 +114,8 @@ class SettingsSheet extends Component<Props, State> {
/> />
</ToggledSection> </ToggledSection>
<LauncherSettingsPanel <LauncherSettingsPanel
enabledInConfig={this.state.updatedSettings.enablePrefetching} isPrefetchingEnabled={this.state.updatedSettings.enablePrefetching}
onChange={v => { onEnablePrefetchingChange={v => {
this.setState({ this.setState({
updatedSettings: { updatedSettings: {
...this.state.updatedSettings, ...this.state.updatedSettings,
@@ -113,6 +123,15 @@ class SettingsSheet extends Component<Props, State> {
}, },
}); });
}} }}
isLocalPinIgnored={this.state.updatedLauncherSettings.ignoreLocalPin}
onIgnoreLocalPinChange={v => {
this.setState({
updatedLauncherSettings: {
...this.state.updatedLauncherSettings,
ignoreLocalPin: v,
},
});
}}
/> />
<br /> <br />
<FlexRow> <FlexRow>
@@ -121,7 +140,13 @@ class SettingsSheet extends Component<Props, State> {
Cancel Cancel
</Button> </Button>
<Button <Button
disabled={isEqual(this.props.settings, this.state.updatedSettings)} disabled={
isEqual(this.props.settings, this.state.updatedSettings) &&
isEqual(
this.props.launcherSettings,
this.state.updatedLauncherSettings,
)
}
type="primary" type="primary"
compact compact
padded padded
@@ -135,9 +160,10 @@ class SettingsSheet extends Component<Props, State> {
} }
export default connect<StateFromProps, DispatchFromProps, OwnProps, Store>( export default connect<StateFromProps, DispatchFromProps, OwnProps, Store>(
({settingsState, application}) => ({ ({settingsState, launcherSettingsState, application}) => ({
settings: settingsState, settings: settingsState,
launcherSettings: launcherSettingsState,
isXcodeDetected: application.xcodeCommandLineToolsDetected, isXcodeDetected: application.xcodeCommandLineToolsDetected,
}), }),
{updateSettings}, {updateSettings, updateLauncherSettings},
)(SettingsSheet); )(SettingsSheet);

View File

@@ -10,8 +10,10 @@
import {Tristate} from 'src/reducers/settings'; import {Tristate} from 'src/reducers/settings';
export default function(_props: { export default function(_props: {
enabledInConfig: Tristate; isPrefetchingEnabled: Tristate;
onChange: (v: Tristate) => void; onEnablePrefetchingChange: (v: Tristate) => void;
isLocalPinIgnored: boolean;
onIgnoreLocalPinChange: (v: boolean) => void;
}) { }) {
return null; return null;
} }

View File

@@ -36,6 +36,10 @@ import settings, {
Settings as SettingsState, Settings as SettingsState,
Action as SettingsAction, Action as SettingsAction,
} from './settings'; } from './settings';
import launcherSettings, {
LauncherSettings as LauncherSettingsState,
Action as LauncherSettingsAction,
} from './launcherSettings';
import pluginManager, { import pluginManager, {
State as PluginManagerState, State as PluginManagerState,
Action as PluginManagerAction, Action as PluginManagerAction,
@@ -46,6 +50,8 @@ import healthchecks, {
} from './healthchecks'; } from './healthchecks';
import user, {State as UserState, Action as UserAction} from './user'; import user, {State as UserState, Action as UserAction} from './user';
import JsonFileStorage from '../utils/jsonFileReduxPersistStorage'; import JsonFileStorage from '../utils/jsonFileReduxPersistStorage';
import LauncherSettingsStorage from '../utils/launcherSettingsStorage';
import {launcherConfigDir} from '../utils/launcher';
import os from 'os'; import os from 'os';
import {resolve} from 'path'; import {resolve} from 'path';
import xdg from 'xdg-basedir'; import xdg from 'xdg-basedir';
@@ -63,6 +69,7 @@ export type Actions =
| PluginsAction | PluginsAction
| UserAction | UserAction
| SettingsAction | SettingsAction
| LauncherSettingsAction
| SupportFormAction | SupportFormAction
| PluginManagerAction | PluginManagerAction
| HealthcheckAction | HealthcheckAction
@@ -76,6 +83,7 @@ export type State = {
plugins: PluginsState; plugins: PluginsState;
user: UserState & PersistPartial; user: UserState & PersistPartial;
settingsState: SettingsState & PersistPartial; settingsState: SettingsState & PersistPartial;
launcherSettingsState: LauncherSettingsState & PersistPartial;
supportForm: SupportFormState; supportForm: SupportFormState;
pluginManager: PluginManagerState; pluginManager: PluginManagerState;
healthchecks: HealthcheckState; healthchecks: HealthcheckState;
@@ -92,6 +100,10 @@ const settingsStorage = new JsonFileStorage(
), ),
); );
const launcherSettingsStorage = new LauncherSettingsStorage(
resolve(launcherConfigDir(), 'flipper-launcher.toml'),
);
export default combineReducers<State, Actions>({ export default combineReducers<State, Actions>({
application, application,
connections: persistReducer<DevicesState, Actions>( connections: persistReducer<DevicesState, Actions>(
@@ -130,5 +142,15 @@ export default combineReducers<State, Actions>({
{key: 'settings', storage: settingsStorage}, {key: 'settings', storage: settingsStorage},
settings, settings,
), ),
launcherSettingsState: persistReducer(
{
key: 'launcherSettings',
storage: launcherSettingsStorage,
serialize: false,
// @ts-ignore: property is erroneously missing in redux-persist type definitions
deserialize: false,
},
launcherSettings,
),
healthchecks, healthchecks,
}); });

View File

@@ -0,0 +1,40 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @format
*/
import {Actions} from './index';
export type LauncherSettings = {
ignoreLocalPin: boolean;
};
export type Action = {
type: 'UPDATE_LAUNCHER_SETTINGS';
payload: LauncherSettings;
};
export const defaultLauncherSettings: LauncherSettings = {
ignoreLocalPin: false,
};
export default function reducer(
state: LauncherSettings = defaultLauncherSettings,
action: Actions,
): LauncherSettings {
if (action.type === 'UPDATE_LAUNCHER_SETTINGS') {
return action.payload;
}
return state;
}
export function updateLauncherSettings(settings: LauncherSettings): Action {
return {
type: 'UPDATE_LAUNCHER_SETTINGS',
payload: settings,
};
}

View File

@@ -7,9 +7,28 @@
* @format * @format
*/ */
import path from 'path';
import os from 'os';
import xdg from 'xdg-basedir';
import {ProcessConfig} from './processConfig'; import {ProcessConfig} from './processConfig';
import {Store} from '../reducers/index'; import {Store} from '../reducers/index';
// There is some disagreement among the XDG Base Directory implementations
// whether to use ~/Library/Preferences or ~/.config on MacOS. The Launcher
// expects the former, whereas `xdg-basedir` implements the latter.
const xdgConfigDir = () =>
os.platform() === 'darwin'
? path.join(os.homedir(), 'Library', 'Preferences')
: xdg.config || path.join(os.homedir(), '.config');
export const launcherConfigDir = () =>
path.join(
xdgConfigDir(),
os.platform() == 'darwin'
? 'rs.flipper-launcher.flipper-launcher'
: 'flipper-launcher',
);
export function initLauncherHooks(config: ProcessConfig, store: Store) { export function initLauncherHooks(config: ProcessConfig, store: Store) {
if (config.launcherMsg) { if (config.launcherMsg) {
store.dispatch({ store.dispatch({

View File

@@ -0,0 +1,79 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @format
*/
import fs from 'fs';
import path from 'path';
import TOML from '@iarna/toml';
import {Storage} from 'redux-persist/es/types';
import {
defaultLauncherSettings,
LauncherSettings,
} from '../reducers/launcherSettings';
export default class LauncherSettingsStorage implements Storage {
constructor(readonly filepath: string) {}
async getItem(_key: string): Promise<any> {
return await this.parseFile();
}
async setItem(_key: string, value: LauncherSettings): Promise<any> {
const originalValue = await this.parseFile();
await this.writeFile(value);
return originalValue;
}
removeItem(_key: string): Promise<void> {
return this.writeFile(defaultLauncherSettings);
}
private async parseFile(): Promise<LauncherSettings> {
try {
const content = fs.readFileSync(this.filepath).toString();
return deserialize(content);
} catch (e) {
console.warn(
`Failed to read settings file: "${this.filepath}". ${e}. Replacing file with default settings.`,
);
await this.writeFile(defaultLauncherSettings);
return defaultLauncherSettings;
}
}
private async writeFile(value: LauncherSettings): Promise<void> {
this.ensureDirExists();
const content = serialize(value);
fs.writeFileSync(this.filepath, content);
}
private ensureDirExists(): void {
const dir = path.dirname(this.filepath);
fs.existsSync(dir) || fs.mkdirSync(dir, {recursive: true});
}
}
interface FormattedSettings {
ignore_local_pin?: boolean;
}
function serialize(value: LauncherSettings): string {
const {ignoreLocalPin, ...rest} = value;
return TOML.stringify({
...rest,
ignore_local_pin: ignoreLocalPin,
});
}
function deserialize(content: string): LauncherSettings {
const {ignore_local_pin, ...rest} = TOML.parse(content) as FormattedSettings;
return {
...rest,
ignoreLocalPin: !!ignore_local_pin,
};
}

View File

@@ -859,6 +859,11 @@
resolved "https://registry.yarnpkg.com/@emotion/weak-memoize/-/weak-memoize-0.2.4.tgz#622a72bebd1e3f48d921563b4b60a762295a81fc" resolved "https://registry.yarnpkg.com/@emotion/weak-memoize/-/weak-memoize-0.2.4.tgz#622a72bebd1e3f48d921563b4b60a762295a81fc"
integrity sha512-6PYY5DVdAY1ifaQW6XYTnOMihmBVT27elqSjEoodchsGjzYlEsTQMcEhSud99kVawatyTZRTiVkJ/c6lwbQ7nA== integrity sha512-6PYY5DVdAY1ifaQW6XYTnOMihmBVT27elqSjEoodchsGjzYlEsTQMcEhSud99kVawatyTZRTiVkJ/c6lwbQ7nA==
"@iarna/toml@^2.2.3":
version "2.2.3"
resolved "https://registry.yarnpkg.com/@iarna/toml/-/toml-2.2.3.tgz#f060bf6eaafae4d56a7dac618980838b0696e2ab"
integrity sha512-FmuxfCuolpLl0AnQ2NHSzoUKWEJDFl63qXjzdoWBVyFCXzMGm1spBzk7LeHNoVCiWCF7mRVms9e6jEV9+MoPbg==
"@icons/material@^0.2.4": "@icons/material@^0.2.4":
version "0.2.4" version "0.2.4"
resolved "https://registry.yarnpkg.com/@icons/material/-/material-0.2.4.tgz#e90c9f71768b3736e76d7dd6783fc6c2afa88bc8" resolved "https://registry.yarnpkg.com/@icons/material/-/material-0.2.4.tgz#e90c9f71768b3736e76d7dd6783fc6c2afa88bc8"
@@ -1397,13 +1402,6 @@
dependencies: dependencies:
redux "^4.0.0" redux "^4.0.0"
"@types/redux-persist@^4.3.1":
version "4.3.1"
resolved "https://registry.yarnpkg.com/@types/redux-persist/-/redux-persist-4.3.1.tgz#aa4c876859e0bea5155e5f7980e5b8c4699dc2e6"
integrity sha1-qkyHaFngvqUVXl95gOW4xGmdwuY=
dependencies:
redux-persist "*"
"@types/retry@*": "@types/retry@*":
version "0.12.0" version "0.12.0"
resolved "https://registry.yarnpkg.com/@types/retry/-/retry-0.12.0.tgz#2b35eccfcee7d38cd72ad99232fbd58bffb3c84d" resolved "https://registry.yarnpkg.com/@types/retry/-/retry-0.12.0.tgz#2b35eccfcee7d38cd72ad99232fbd58bffb3c84d"
@@ -7685,7 +7683,7 @@ redux-mock-store@^1.5.3:
dependencies: dependencies:
lodash.isplainobject "^4.0.6" lodash.isplainobject "^4.0.6"
redux-persist@*, redux-persist@^6.0.0: redux-persist@^6.0.0:
version "6.0.0" version "6.0.0"
resolved "https://registry.yarnpkg.com/redux-persist/-/redux-persist-6.0.0.tgz#b4d2972f9859597c130d40d4b146fecdab51b3a8" resolved "https://registry.yarnpkg.com/redux-persist/-/redux-persist-6.0.0.tgz#b4d2972f9859597c130d40d4b146fecdab51b3a8"
integrity sha512-71LLMbUq2r02ng2We9S215LtPu3fY0KgaGE0k8WRgl6RkqxtGfl7HUozz1Dftwsb0D/5mZ8dwAaPbtnzfvbEwQ== integrity sha512-71LLMbUq2r02ng2We9S215LtPu3fY0KgaGE0k8WRgl6RkqxtGfl7HUozz1Dftwsb0D/5mZ8dwAaPbtnzfvbEwQ==