mirror of
https://github.com/desktop/desktop
synced 2024-09-18 07:32:01 +00:00
Implement GitConfig Setting section within Repository Settings
This commit is contained in:
parent
1a414d0797
commit
6516c35121
|
@ -111,6 +111,18 @@ export async function getGlobalConfigPath(env?: {
|
|||
return normalize(path[1])
|
||||
}
|
||||
|
||||
/** Set the local config value by name. */
|
||||
export async function setConfigValue(
|
||||
repository: Repository,
|
||||
name: string,
|
||||
value: string,
|
||||
env?: {
|
||||
HOME: string
|
||||
}
|
||||
): Promise<void> {
|
||||
setConfigValueInPath(name, value, repository.path, env)
|
||||
}
|
||||
|
||||
/** Set the global config value by name. */
|
||||
export async function setGlobalConfigValue(
|
||||
name: string,
|
||||
|
|
107
app/src/ui/repository-settings/git-config.tsx
Normal file
107
app/src/ui/repository-settings/git-config.tsx
Normal file
|
@ -0,0 +1,107 @@
|
|||
import * as React from 'react'
|
||||
import { DialogContent } from '../dialog'
|
||||
import { TextBox } from '../lib/text-box'
|
||||
import { Row } from '../lib/row'
|
||||
|
||||
interface IGitConfigProps {
|
||||
readonly gitConfigLocation: GitConfigLocation
|
||||
readonly name: string
|
||||
readonly email: string
|
||||
readonly globalName: string
|
||||
readonly globalEmail: string
|
||||
|
||||
readonly onGitConfigLocationChanged: (value: GitConfigLocation) => void
|
||||
readonly onNameChanged: (name: string) => void
|
||||
readonly onEmailChanged: (email: string) => void
|
||||
}
|
||||
|
||||
interface IGitConfigState {
|
||||
readonly gitConfigLocation: GitConfigLocation
|
||||
}
|
||||
|
||||
export enum GitConfigLocation {
|
||||
Global = 'Global',
|
||||
Local = 'Local',
|
||||
}
|
||||
|
||||
/** A view for creating or modifying the repository's gitignore file */
|
||||
export class GitConfig extends React.Component<
|
||||
IGitConfigProps,
|
||||
IGitConfigState
|
||||
> {
|
||||
public constructor(props: IGitConfigProps) {
|
||||
super(props)
|
||||
|
||||
this.state = {
|
||||
gitConfigLocation: this.props.gitConfigLocation,
|
||||
}
|
||||
}
|
||||
private onGitConfigLocationChanged = (
|
||||
event: React.FormEvent<HTMLInputElement>
|
||||
) => {
|
||||
const value = event.currentTarget.value as GitConfigLocation
|
||||
|
||||
this.setState({ gitConfigLocation: value })
|
||||
this.props.onGitConfigLocationChanged(value)
|
||||
}
|
||||
|
||||
public render() {
|
||||
return (
|
||||
<DialogContent>
|
||||
<div className="advanced-section">
|
||||
<h2>For this repository I wish to</h2>
|
||||
<div className="radio-component">
|
||||
<input
|
||||
type="radio"
|
||||
id={GitConfigLocation.Global}
|
||||
value={GitConfigLocation.Global}
|
||||
checked={
|
||||
this.state.gitConfigLocation === GitConfigLocation.Global
|
||||
}
|
||||
onChange={this.onGitConfigLocationChanged}
|
||||
/>
|
||||
<label htmlFor={GitConfigLocation.Global}>
|
||||
Use my global Git config
|
||||
</label>
|
||||
</div>
|
||||
<div className="radio-component">
|
||||
<input
|
||||
type="radio"
|
||||
id={GitConfigLocation.Local}
|
||||
value={GitConfigLocation.Local}
|
||||
checked={this.state.gitConfigLocation === GitConfigLocation.Local}
|
||||
onChange={this.onGitConfigLocationChanged}
|
||||
/>
|
||||
<label htmlFor={GitConfigLocation.Local}>
|
||||
Use a local Git config
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<Row>
|
||||
<TextBox
|
||||
label="Name"
|
||||
value={
|
||||
this.state.gitConfigLocation === GitConfigLocation.Global
|
||||
? this.props.globalName
|
||||
: this.props.name
|
||||
}
|
||||
onValueChanged={this.props.onNameChanged}
|
||||
disabled={this.state.gitConfigLocation === GitConfigLocation.Global}
|
||||
/>
|
||||
</Row>
|
||||
<Row>
|
||||
<TextBox
|
||||
label="Email"
|
||||
value={
|
||||
this.state.gitConfigLocation === GitConfigLocation.Global
|
||||
? this.props.globalEmail
|
||||
: this.props.email
|
||||
}
|
||||
onValueChanged={this.props.onEmailChanged}
|
||||
disabled={this.state.gitConfigLocation === GitConfigLocation.Global}
|
||||
/>
|
||||
</Row>
|
||||
</DialogContent>
|
||||
)
|
||||
}
|
||||
}
|
|
@ -18,6 +18,16 @@ import { OkCancelButtonGroup } from '../dialog/ok-cancel-button-group'
|
|||
import { ForkSettings } from './fork-settings'
|
||||
import { ForkContributionTarget } from '../../models/workflow-preferences'
|
||||
import { enableForkSettings } from '../../lib/feature-flag'
|
||||
import { GitConfigLocation, GitConfig } from './git-config'
|
||||
import {
|
||||
getConfigValue,
|
||||
getGlobalConfigValue,
|
||||
setConfigValue,
|
||||
} from '../../lib/git/config'
|
||||
import {
|
||||
gitAuthorNameIsValid,
|
||||
invalidGitAuthorNameMessage,
|
||||
} from '../lib/identifier-rules'
|
||||
|
||||
interface IRepositorySettingsProps {
|
||||
readonly dispatcher: Dispatcher
|
||||
|
@ -30,6 +40,7 @@ enum RepositorySettingsTab {
|
|||
Remote = 0,
|
||||
IgnoredFiles,
|
||||
ForkSettings,
|
||||
GitConfig,
|
||||
}
|
||||
|
||||
interface IRepositorySettingsState {
|
||||
|
@ -38,6 +49,14 @@ interface IRepositorySettingsState {
|
|||
readonly ignoreText: string | null
|
||||
readonly ignoreTextHasChanged: boolean
|
||||
readonly disabled: boolean
|
||||
readonly saveDisabled: boolean
|
||||
readonly gitConfigLocation: GitConfigLocation
|
||||
readonly committerName: string
|
||||
readonly committerEmail: string
|
||||
readonly globalCommitterName: string
|
||||
readonly globalCommitterEmail: string
|
||||
readonly initialCommitterName: string | null
|
||||
readonly initialCommitterEmail: string | null
|
||||
readonly errors?: ReadonlyArray<JSX.Element | string>
|
||||
readonly forkContributionTarget: ForkContributionTarget
|
||||
}
|
||||
|
@ -56,6 +75,14 @@ export class RepositorySettings extends React.Component<
|
|||
ignoreTextHasChanged: false,
|
||||
disabled: false,
|
||||
forkContributionTarget: getForkContributionTarget(props.repository),
|
||||
saveDisabled: false,
|
||||
gitConfigLocation: GitConfigLocation.Global,
|
||||
committerName: '',
|
||||
committerEmail: '',
|
||||
globalCommitterName: '',
|
||||
globalCommitterEmail: '',
|
||||
initialCommitterName: null,
|
||||
initialCommitterEmail: null,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -70,6 +97,38 @@ export class RepositorySettings extends React.Component<
|
|||
)
|
||||
this.setState({ errors: [`Could not read root .gitignore: ${e}`] })
|
||||
}
|
||||
|
||||
const initialCommitterName = await getConfigValue(
|
||||
this.props.repository,
|
||||
'user.name'
|
||||
)
|
||||
const initialCommitterEmail = await getConfigValue(
|
||||
this.props.repository,
|
||||
'user.email'
|
||||
)
|
||||
|
||||
const globalCommitterName = (await getGlobalConfigValue('user.name')) || ''
|
||||
const globalCommitterEmail =
|
||||
(await getGlobalConfigValue('user.email')) || ''
|
||||
|
||||
let gitConfigLocation =
|
||||
initialCommitterName === globalCommitterName &&
|
||||
initialCommitterEmail === globalCommitterEmail
|
||||
? GitConfigLocation.Global
|
||||
: GitConfigLocation.Local
|
||||
|
||||
let committerName = initialCommitterName || ''
|
||||
let committerEmail = initialCommitterEmail || ''
|
||||
|
||||
this.setState({
|
||||
gitConfigLocation,
|
||||
committerName,
|
||||
committerEmail,
|
||||
globalCommitterName,
|
||||
globalCommitterEmail,
|
||||
initialCommitterName,
|
||||
initialCommitterEmail,
|
||||
})
|
||||
}
|
||||
|
||||
private renderErrors(): JSX.Element[] | null {
|
||||
|
@ -111,6 +170,7 @@ export class RepositorySettings extends React.Component<
|
|||
{showForkSettings && (
|
||||
<span>{__DARWIN__ ? 'Fork Behavior' : 'Fork behavior'}</span>
|
||||
)}
|
||||
<span>{__DARWIN__ ? 'Git Config' : 'Git config'}</span>
|
||||
</TabBar>
|
||||
|
||||
<div className="active-tab">{this.renderActiveTab()}</div>
|
||||
|
@ -129,7 +189,10 @@ export class RepositorySettings extends React.Component<
|
|||
|
||||
return (
|
||||
<DialogFooter>
|
||||
<OkCancelButtonGroup okButtonText="Save" />
|
||||
<OkCancelButtonGroup
|
||||
okButtonText="Save"
|
||||
okButtonDisabled={this.state.saveDisabled}
|
||||
/>
|
||||
</DialogFooter>
|
||||
)
|
||||
}
|
||||
|
@ -174,6 +237,22 @@ export class RepositorySettings extends React.Component<
|
|||
/>
|
||||
)
|
||||
}
|
||||
|
||||
case RepositorySettingsTab.GitConfig: {
|
||||
return (
|
||||
<GitConfig
|
||||
gitConfigLocation={this.state.gitConfigLocation}
|
||||
onGitConfigLocationChanged={this.onGitConfigLocationChanged}
|
||||
name={this.state.committerName}
|
||||
email={this.state.committerEmail}
|
||||
globalName={this.state.globalCommitterName}
|
||||
globalEmail={this.state.globalCommitterEmail}
|
||||
onNameChanged={this.onCommitterNameChanged}
|
||||
onEmailChanged={this.onCommitterEmailChanged}
|
||||
/>
|
||||
)
|
||||
}
|
||||
}
|
||||
default:
|
||||
return assertNever(tab, `Unknown tab type: ${tab}`)
|
||||
}
|
||||
|
@ -238,6 +317,23 @@ export class RepositorySettings extends React.Component<
|
|||
...this.props.repository.workflowPreferences,
|
||||
forkContributionTarget: this.state.forkContributionTarget,
|
||||
}
|
||||
if (this.state.committerName !== this.state.initialCommitterName) {
|
||||
await setConfigValue(
|
||||
this.props.repository,
|
||||
'user.name',
|
||||
this.state.gitConfigLocation === GitConfigLocation.Global
|
||||
? this.state.globalCommitterName
|
||||
: this.state.committerName
|
||||
)
|
||||
}
|
||||
|
||||
if (this.state.committerEmail !== this.state.initialCommitterEmail) {
|
||||
await setConfigValue(
|
||||
this.props.repository,
|
||||
'user.email',
|
||||
this.state.gitConfigLocation === GitConfigLocation.Global
|
||||
? this.state.globalCommitterEmail
|
||||
: this.state.committerEmail
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -273,5 +369,25 @@ export class RepositorySettings extends React.Component<
|
|||
this.setState({
|
||||
forkContributionTarget,
|
||||
})
|
||||
|
||||
private onGitConfigLocationChanged = (value: GitConfigLocation) => {
|
||||
this.setState({ gitConfigLocation: value })
|
||||
}
|
||||
|
||||
private onCommitterNameChanged = (committerName: string) => {
|
||||
const errors = new Array<JSX.Element | string>()
|
||||
|
||||
if (gitAuthorNameIsValid(committerName)) {
|
||||
this.setState({ saveDisabled: false })
|
||||
} else {
|
||||
this.setState({ saveDisabled: true })
|
||||
errors.push(invalidGitAuthorNameMessage)
|
||||
}
|
||||
|
||||
this.setState({ committerName, errors })
|
||||
}
|
||||
|
||||
private onCommitterEmailChanged = (committerEmail: string) => {
|
||||
this.setState({ committerEmail })
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue