Skip to content

Add git stash, unstash and reset. #14

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Nov 2, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 28 additions & 0 deletions app/api/gitAPI.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,31 @@ export function gitPushAll () {
if (!res.ok) return false
})
}

export function gitCurrentBranch (){
return request.get(`/git/${config.spaceKey}/branch`)
}

export function gitCreateStash (message){
return request.post(`/git/${config.spaceKey}/stash`, {message: message})
}

export function gitStashList (){
return request.get(`/git/${config.spaceKey}/stash`)
}

export function gitDropStash (stashRef, all=false){
return request.delete(`/git/${config.spaceKey}/stash`, {stashRef, all})
}

export function gitApplyStash ({stashRef, pop, applyIndex}){
return request.post(`/git/${config.spaceKey}/stash/apply`, {stashRef, pop, applyIndex})
}

export function gitCheckoutStash ({stashRef, branch}){
return request.post(`/git/${config.spaceKey}/stash/checkout`, {stashRef, branch})
}

export function gitResetHead ({ref, resetType}) {
return request.post(`/git/${config.spaceKey}/reset`, {ref, resetType})
}
23 changes: 19 additions & 4 deletions app/commands/commandBindings/git.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,31 @@ export default {
},

'git:pull': c => $d(Git.pull()),
'git:push': c => $d(Git.push())
'git:push': c => $d(Git.push()),

// 'git:commit_and_push':
// 'git:branch':
// 'git:tag':
// 'git:merge':
// 'git:resolve_conflicts':
// 'git:stash':
// 'git:unstash'<:></:>
// 'git:reset_head':
'git:stash': c => {
$d(Git.getCurrentBranch()).then(() =>
$d(Modal.showModal('GitStash'))
)
},
'git:unstash': c => {
$d(Git.getCurrentBranch()).then(() => {
$d(Git.getStashList())
.then(() =>
$d(Modal.showModal('GitUnstash'))
)
})
},
'git:reset_head': c => {
$d(Git.getCurrentBranch()).then(() =>
$d(Modal.showModal('GitResetHead'))
)
},
// 'git:rebase:start':
// 'git:rebase:abort':
// 'git:rebase:continue':
Expand Down
148 changes: 146 additions & 2 deletions app/components/Git/actions.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/* @flow weak */
import api from '../../api'
import { notify } from '../Notification/actions'
import { dismissModal } from '../Modal/actions'
import { notify, NOTIFY_TYPE } from '../Notification/actions'
import { showModal, dismissModal } from '../Modal/actions'

export const GIT_STATUS = 'GIT_STATUS'
export function updateStatus ({files, isClean}) {
Expand Down Expand Up @@ -94,3 +94,147 @@ export function push () {
})
}
}

export const GIT_CURRENT_BRANCH = 'GIT_CURRENT_BRANCH'
export function updateCurrentBranch ({ name }) {
return {
type: GIT_CURRENT_BRANCH,
branch: name,
}
}

export const GIT_UPDATE_STASH_MESSAGE = 'GIT_UPDATE_STASH_MESSAGE'
export function updateStashMessage (stashMessage) {
return {
type: GIT_UPDATE_STASH_MESSAGE,
stashMessage,
}
}

export function createStash (message) {
return dispatch => api.gitCreateStash(message).then(res => {
dispatch(notify({
message: 'Git stash success.',
}))
dispatch(dismissModal())
}).catch(res => {
dispatch(notify({
notifyType: NOTIFY_TYPE.ERROR,
message: res.msg,
}))
dispatch(dismissModal())
})
}

export const GIT_UPDATE_STASH_LIST = 'GIT_UPDATE_STASH_LIST'
export function updateStashList (stashList) {
return {
type: GIT_UPDATE_STASH_LIST,
stashList: stashList
}
}

export const GIT_UPDATE_UNSTASH_IS_POP = 'GIT_UPDATE_UNSTASH_IS_POP'
export function updateUnstashIsPop (isPop) {
return {
type: GIT_UPDATE_UNSTASH_IS_POP,
isPop
}
}

export const GIT_UPDATE_UNSTASH_IS_REINSTATE = 'GIT_UPDATE_UNSTASH_IS_REINSTATE'
export function updateUnstashIsReinstate (isReinstate) {
return {
type: GIT_UPDATE_UNSTASH_IS_REINSTATE,
isReinstate
}
}

export const GIT_UPDATE_UNSTASH_BRANCH_NAME = 'GIT_UPDATE_UNSTASH_BRANCH_NAME'
export function updateUnstashBranchName (newBranchName) {
return {
type: GIT_UPDATE_UNSTASH_BRANCH_NAME,
newBranchName
}
}

export function getStashList () {
return (dispatch) => api.gitStashList().then(({ stashes }) => {
dispatch(updateStashList(stashes))
})
}

export const GIT_SELECT_STASH = 'GIT_SELECT_STASH'
export function selectStash (selectedStash) {
return {
type: GIT_SELECT_STASH,
selectedStash: selectedStash
}
}

export function dropStash (stashRef, all) {
return dispatch => api.gitDropStash(stashRef, all).then(res => {
dispatch(notify({
message: 'Drop stash success.',
}))
getStashList()(dispatch)
}).catch(res => {
dispatch(notify({
notifyType: NOTIFY_TYPE.ERROR,
message: 'Drop stash error.',
}))
})
}

export function applyStash ({stashRef, pop, applyIndex}) {
return dispatch => api.gitApplyStash({stashRef, pop, applyIndex}).then(res => {
dispatch(notify({
message: 'Apply stash success.',
}))
dispatch(dismissModal())
}).catch(res => {
dispatch(notify({
notifyType: NOTIFY_TYPE.ERROR,
message: 'Apply stash error.',
}))
})
}

export function checkoutStash ({stashRef, branch}) {
return dispatch => api.gitCheckoutStash({stashRef, branch}).then(res => {
dispatch(notify({
message: 'Checkout stash success.',
}))
dispatch(dismissModal())
}).catch(res => {
dispatch(notify({
notifyType: NOTIFY_TYPE.ERROR,
message: 'Checkout stash error.',
}))
})
}

export function getCurrentBranch () {
return dispatch => api.gitCurrentBranch().then(({ name }) => {
dispatch(updateCurrentBranch({name}))
}).catch(res => {
dispatch(notify({
notifyType: NOTIFY_TYPE.ERROR,
message: 'Get current branch error.',
}))
})
}

export function resetHead ({ref, resetType}) {
return dispatch => api.gitResetHead({ref, resetType}).then(res => {
dispatch(notify({
message: 'Reset success.',
}))
dispatch(dismissModal())
}).catch(res => {
dispatch(notify({
notifyType: NOTIFY_TYPE.ERROR,
message: 'Reset error.',
}))
})
}
6 changes: 5 additions & 1 deletion app/components/Git/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ var GitCommitView = ({workingDir, stagingArea, ...actionProps}) => {
onChange={e => updateCommitMessage(e.target.value)} />
</div>
<hr />
<div className='git-commit-ops'>
<div className='modal-ops'>
<button className='btn btn-default' onClick={e => dispatchCommand('modal:dismiss')}>Cancel</button>
<button className='btn btn-primary' onClick={e => commit(stagingArea)}>Commit</button>
</div>
Expand All @@ -59,6 +59,10 @@ class _GitBranchWidget extends Component {
}
}

componentWillMount () {
this.props.getCurrentBranch()
}

render () {
const {current: currentBranch, local: localBranches, remote: remoteBranches} = this.props
return (
Expand Down
117 changes: 117 additions & 0 deletions app/components/Git/modals/reset.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
/* @flow weak */
import React, { Component, PropTypes } from 'react'
import { bindActionCreators } from 'redux'
import { dispatchCommand } from '../../../commands'
import cx from 'classnames'
import { connect } from 'react-redux'

import * as GitActions from '../actions'

const actionOptions = [
'SOFT',
'MIXED',
'HARD',
]

class GitResetView extends Component {
constructor (props) {
super(props)
this.state = {
resetType: 'MIXED',
commit: 'HEAD',
}
this.handleChangeOption = this.handleChangeOption.bind(this)
this.handleCommitChange = this.handleCommitChange.bind(this)
this.handleConfirm = this.handleConfirm.bind(this)
}
render () {
const { branches } = this.props
const { current: currentBranch} = branches
return (
<div>
<div className='git-reset-container'>
<h1>
Reset Head
</h1>
<hr />
<form className="form-horizontal">
<div className="form-group">
<label className="col-sm-3 control-label">Current Branch</label>
<label className="col-sm-9 checkbox-inline">
{currentBranch}
</label>
</div>
<div className="form-group">
<label className="col-sm-3 control-label">Reset Type</label>
<label className="col-sm-3">
{this.renderOptions()}
</label>
</div>
<div className="form-group">
<label className="col-sm-3 control-label">To Commit</label>
<label className="col-sm-9">
<input type="text"
className="form-control"
value={this.state.commit}
onChange={this.handleCommitChange}/>
</label>
</div>
</form>
<hr />
<div className='modal-ops'>
<button className='btn btn-default' onClick={e => dispatchCommand('modal:dismiss')}>Cancel</button>
<button className='btn btn-primary' onClick={this.handleConfirm} disabled={!this.state.commit}>OK</button>
</div>
</div>
</div>
)
}

renderOptions () {
return (
<select
className="form-control"
onChange={this.handleChangeOption}
value={this.state.resetType}
>
{
actionOptions.map( (item, i) => {
return (
<option
key={i}
value={item}>
{item}
</option>
)
})
}
</select>
)
}

handleChangeOption (e) {
this.setState({resetType: e.target.value})
e.stopPropagation()
e.nativeEvent.stopImmediatePropagation()
}

handleCommitChange (e) {
this.setState({commit: e.target.value})
e.stopPropagation()
e.nativeEvent.stopImmediatePropagation()
}

handleConfirm (e) {
this.props.resetHead({
ref: this.state.commit,
resetType: this.state.resetType,
})
e.stopPropagation()
e.nativeEvent.stopImmediatePropagation()
}
}

export default GitResetView = connect(
state => state.GitState,
dispatch => bindActionCreators(GitActions, dispatch)
)(GitResetView)
Loading