Skip to content

Commit 5c0cfe6

Browse files
authored
Merge pull request #14 from Coding/yangzhen/stash
Add git stash, unstash and reset.
2 parents b0e4d3e + 9f35ca6 commit 5c0cfe6

File tree

16 files changed

+717
-12
lines changed

16 files changed

+717
-12
lines changed

app/api/gitAPI.js

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,3 +30,31 @@ export function gitPushAll () {
3030
if (!res.ok) return false
3131
})
3232
}
33+
34+
export function gitCurrentBranch (){
35+
return request.get(`/git/${config.spaceKey}/branch`)
36+
}
37+
38+
export function gitCreateStash (message){
39+
return request.post(`/git/${config.spaceKey}/stash`, {message: message})
40+
}
41+
42+
export function gitStashList (){
43+
return request.get(`/git/${config.spaceKey}/stash`)
44+
}
45+
46+
export function gitDropStash (stashRef, all=false){
47+
return request.delete(`/git/${config.spaceKey}/stash`, {stashRef, all})
48+
}
49+
50+
export function gitApplyStash ({stashRef, pop, applyIndex}){
51+
return request.post(`/git/${config.spaceKey}/stash/apply`, {stashRef, pop, applyIndex})
52+
}
53+
54+
export function gitCheckoutStash ({stashRef, branch}){
55+
return request.post(`/git/${config.spaceKey}/stash/checkout`, {stashRef, branch})
56+
}
57+
58+
export function gitResetHead ({ref, resetType}) {
59+
return request.post(`/git/${config.spaceKey}/reset`, {ref, resetType})
60+
}

app/commands/commandBindings/git.js

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,16 +14,31 @@ export default {
1414
},
1515

1616
'git:pull': c => $d(Git.pull()),
17-
'git:push': c => $d(Git.push())
17+
'git:push': c => $d(Git.push()),
1818

1919
// 'git:commit_and_push':
2020
// 'git:branch':
2121
// 'git:tag':
2222
// 'git:merge':
2323
// 'git:resolve_conflicts':
24-
// 'git:stash':
25-
// 'git:unstash'<:></:>
26-
// 'git:reset_head':
24+
'git:stash': c => {
25+
$d(Git.getCurrentBranch()).then(() =>
26+
$d(Modal.showModal('GitStash'))
27+
)
28+
},
29+
'git:unstash': c => {
30+
$d(Git.getCurrentBranch()).then(() => {
31+
$d(Git.getStashList())
32+
.then(() =>
33+
$d(Modal.showModal('GitUnstash'))
34+
)
35+
})
36+
},
37+
'git:reset_head': c => {
38+
$d(Git.getCurrentBranch()).then(() =>
39+
$d(Modal.showModal('GitResetHead'))
40+
)
41+
},
2742
// 'git:rebase:start':
2843
// 'git:rebase:abort':
2944
// 'git:rebase:continue':

app/components/Git/actions.js

Lines changed: 146 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/* @flow weak */
22
import api from '../../api'
3-
import { notify } from '../Notification/actions'
4-
import { dismissModal } from '../Modal/actions'
3+
import { notify, NOTIFY_TYPE } from '../Notification/actions'
4+
import { showModal, dismissModal } from '../Modal/actions'
55

66
export const GIT_STATUS = 'GIT_STATUS'
77
export function updateStatus ({files, isClean}) {
@@ -94,3 +94,147 @@ export function push () {
9494
})
9595
}
9696
}
97+
98+
export const GIT_CURRENT_BRANCH = 'GIT_CURRENT_BRANCH'
99+
export function updateCurrentBranch ({ name }) {
100+
return {
101+
type: GIT_CURRENT_BRANCH,
102+
branch: name,
103+
}
104+
}
105+
106+
export const GIT_UPDATE_STASH_MESSAGE = 'GIT_UPDATE_STASH_MESSAGE'
107+
export function updateStashMessage (stashMessage) {
108+
return {
109+
type: GIT_UPDATE_STASH_MESSAGE,
110+
stashMessage,
111+
}
112+
}
113+
114+
export function createStash (message) {
115+
return dispatch => api.gitCreateStash(message).then(res => {
116+
dispatch(notify({
117+
message: 'Git stash success.',
118+
}))
119+
dispatch(dismissModal())
120+
}).catch(res => {
121+
dispatch(notify({
122+
notifyType: NOTIFY_TYPE.ERROR,
123+
message: res.msg,
124+
}))
125+
dispatch(dismissModal())
126+
})
127+
}
128+
129+
export const GIT_UPDATE_STASH_LIST = 'GIT_UPDATE_STASH_LIST'
130+
export function updateStashList (stashList) {
131+
return {
132+
type: GIT_UPDATE_STASH_LIST,
133+
stashList: stashList
134+
}
135+
}
136+
137+
export const GIT_UPDATE_UNSTASH_IS_POP = 'GIT_UPDATE_UNSTASH_IS_POP'
138+
export function updateUnstashIsPop (isPop) {
139+
return {
140+
type: GIT_UPDATE_UNSTASH_IS_POP,
141+
isPop
142+
}
143+
}
144+
145+
export const GIT_UPDATE_UNSTASH_IS_REINSTATE = 'GIT_UPDATE_UNSTASH_IS_REINSTATE'
146+
export function updateUnstashIsReinstate (isReinstate) {
147+
return {
148+
type: GIT_UPDATE_UNSTASH_IS_REINSTATE,
149+
isReinstate
150+
}
151+
}
152+
153+
export const GIT_UPDATE_UNSTASH_BRANCH_NAME = 'GIT_UPDATE_UNSTASH_BRANCH_NAME'
154+
export function updateUnstashBranchName (newBranchName) {
155+
return {
156+
type: GIT_UPDATE_UNSTASH_BRANCH_NAME,
157+
newBranchName
158+
}
159+
}
160+
161+
export function getStashList () {
162+
return (dispatch) => api.gitStashList().then(({ stashes }) => {
163+
dispatch(updateStashList(stashes))
164+
})
165+
}
166+
167+
export const GIT_SELECT_STASH = 'GIT_SELECT_STASH'
168+
export function selectStash (selectedStash) {
169+
return {
170+
type: GIT_SELECT_STASH,
171+
selectedStash: selectedStash
172+
}
173+
}
174+
175+
export function dropStash (stashRef, all) {
176+
return dispatch => api.gitDropStash(stashRef, all).then(res => {
177+
dispatch(notify({
178+
message: 'Drop stash success.',
179+
}))
180+
getStashList()(dispatch)
181+
}).catch(res => {
182+
dispatch(notify({
183+
notifyType: NOTIFY_TYPE.ERROR,
184+
message: 'Drop stash error.',
185+
}))
186+
})
187+
}
188+
189+
export function applyStash ({stashRef, pop, applyIndex}) {
190+
return dispatch => api.gitApplyStash({stashRef, pop, applyIndex}).then(res => {
191+
dispatch(notify({
192+
message: 'Apply stash success.',
193+
}))
194+
dispatch(dismissModal())
195+
}).catch(res => {
196+
dispatch(notify({
197+
notifyType: NOTIFY_TYPE.ERROR,
198+
message: 'Apply stash error.',
199+
}))
200+
})
201+
}
202+
203+
export function checkoutStash ({stashRef, branch}) {
204+
return dispatch => api.gitCheckoutStash({stashRef, branch}).then(res => {
205+
dispatch(notify({
206+
message: 'Checkout stash success.',
207+
}))
208+
dispatch(dismissModal())
209+
}).catch(res => {
210+
dispatch(notify({
211+
notifyType: NOTIFY_TYPE.ERROR,
212+
message: 'Checkout stash error.',
213+
}))
214+
})
215+
}
216+
217+
export function getCurrentBranch () {
218+
return dispatch => api.gitCurrentBranch().then(({ name }) => {
219+
dispatch(updateCurrentBranch({name}))
220+
}).catch(res => {
221+
dispatch(notify({
222+
notifyType: NOTIFY_TYPE.ERROR,
223+
message: 'Get current branch error.',
224+
}))
225+
})
226+
}
227+
228+
export function resetHead ({ref, resetType}) {
229+
return dispatch => api.gitResetHead({ref, resetType}).then(res => {
230+
dispatch(notify({
231+
message: 'Reset success.',
232+
}))
233+
dispatch(dismissModal())
234+
}).catch(res => {
235+
dispatch(notify({
236+
notifyType: NOTIFY_TYPE.ERROR,
237+
message: 'Reset error.',
238+
}))
239+
})
240+
}

app/components/Git/index.jsx

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ var GitCommitView = ({workingDir, stagingArea, ...actionProps}) => {
3838
onChange={e => updateCommitMessage(e.target.value)} />
3939
</div>
4040
<hr />
41-
<div className='git-commit-ops'>
41+
<div className='modal-ops'>
4242
<button className='btn btn-default' onClick={e => dispatchCommand('modal:dismiss')}>Cancel</button>
4343
<button className='btn btn-primary' onClick={e => commit(stagingArea)}>Commit</button>
4444
</div>
@@ -59,6 +59,10 @@ class _GitBranchWidget extends Component {
5959
}
6060
}
6161

62+
componentWillMount () {
63+
this.props.getCurrentBranch()
64+
}
65+
6266
render () {
6367
const {current: currentBranch, local: localBranches, remote: remoteBranches} = this.props
6468
return (

app/components/Git/modals/reset.jsx

Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
/* @flow weak */
2+
import React, { Component, PropTypes } from 'react'
3+
import { bindActionCreators } from 'redux'
4+
import { dispatchCommand } from '../../../commands'
5+
import cx from 'classnames'
6+
import { connect } from 'react-redux'
7+
8+
import * as GitActions from '../actions'
9+
10+
const actionOptions = [
11+
'SOFT',
12+
'MIXED',
13+
'HARD',
14+
]
15+
16+
class GitResetView extends Component {
17+
constructor (props) {
18+
super(props)
19+
this.state = {
20+
resetType: 'MIXED',
21+
commit: 'HEAD',
22+
}
23+
this.handleChangeOption = this.handleChangeOption.bind(this)
24+
this.handleCommitChange = this.handleCommitChange.bind(this)
25+
this.handleConfirm = this.handleConfirm.bind(this)
26+
}
27+
render () {
28+
const { branches } = this.props
29+
const { current: currentBranch} = branches
30+
return (
31+
<div>
32+
<div className='git-reset-container'>
33+
<h1>
34+
Reset Head
35+
</h1>
36+
<hr />
37+
<form className="form-horizontal">
38+
<div className="form-group">
39+
<label className="col-sm-3 control-label">Current Branch</label>
40+
<label className="col-sm-9 checkbox-inline">
41+
{currentBranch}
42+
</label>
43+
</div>
44+
<div className="form-group">
45+
<label className="col-sm-3 control-label">Reset Type</label>
46+
<label className="col-sm-3">
47+
{this.renderOptions()}
48+
</label>
49+
</div>
50+
<div className="form-group">
51+
<label className="col-sm-3 control-label">To Commit</label>
52+
<label className="col-sm-9">
53+
<input type="text"
54+
className="form-control"
55+
value={this.state.commit}
56+
onChange={this.handleCommitChange}/>
57+
</label>
58+
</div>
59+
</form>
60+
<hr />
61+
<div className='modal-ops'>
62+
<button className='btn btn-default' onClick={e => dispatchCommand('modal:dismiss')}>Cancel</button>
63+
<button className='btn btn-primary' onClick={this.handleConfirm} disabled={!this.state.commit}>OK</button>
64+
</div>
65+
</div>
66+
</div>
67+
)
68+
}
69+
70+
renderOptions () {
71+
return (
72+
<select
73+
className="form-control"
74+
onChange={this.handleChangeOption}
75+
value={this.state.resetType}
76+
>
77+
{
78+
actionOptions.map( (item, i) => {
79+
return (
80+
<option
81+
key={i}
82+
value={item}>
83+
{item}
84+
</option>
85+
)
86+
})
87+
}
88+
</select>
89+
)
90+
}
91+
92+
handleChangeOption (e) {
93+
this.setState({resetType: e.target.value})
94+
e.stopPropagation()
95+
e.nativeEvent.stopImmediatePropagation()
96+
}
97+
98+
handleCommitChange (e) {
99+
this.setState({commit: e.target.value})
100+
e.stopPropagation()
101+
e.nativeEvent.stopImmediatePropagation()
102+
}
103+
104+
handleConfirm (e) {
105+
this.props.resetHead({
106+
ref: this.state.commit,
107+
resetType: this.state.resetType,
108+
})
109+
e.stopPropagation()
110+
e.nativeEvent.stopImmediatePropagation()
111+
}
112+
}
113+
114+
export default GitResetView = connect(
115+
state => state.GitState,
116+
dispatch => bindActionCreators(GitActions, dispatch)
117+
)(GitResetView)

0 commit comments

Comments
 (0)