Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 7803b3e

Browse files
authored
Merge pull request atom#385 from atom/merge-conflict-resolution
Decorate merge conflicts within TextEditors
2 parents 579a584 + 2d456ee commit 7803b3e

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

48 files changed

+3280
-134
lines changed
Lines changed: 172 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,172 @@
1+
import React from 'react';
2+
import {remote} from 'electron';
3+
const {Menu, MenuItem} = remote;
4+
5+
import {autobind} from 'core-decorators';
6+
import {OURS, BASE, THEIRS} from '../models/conflicts/source';
7+
import Decoration from '../views/decoration';
8+
import Octicon from '../views/octicon';
9+
10+
export default class ConflictController extends React.Component {
11+
static propTypes = {
12+
editor: React.PropTypes.object.isRequired,
13+
conflict: React.PropTypes.object.isRequired,
14+
resolveAsSequence: React.PropTypes.func,
15+
dismiss: React.PropTypes.func,
16+
};
17+
18+
static defaultProps = {
19+
resolveAsSequence: sources => {},
20+
dismiss: () => {},
21+
}
22+
23+
constructor(props, context) {
24+
super(props, context);
25+
26+
this.state = {
27+
chosenSide: this.props.conflict.getChosenSide(),
28+
};
29+
}
30+
31+
resolveAsSequence(sources) {
32+
this.props.resolveAsSequence(sources);
33+
34+
this.setState({
35+
chosenSide: this.props.conflict.getChosenSide(),
36+
});
37+
}
38+
39+
revert(side) {
40+
side.isModified() && side.revert();
41+
side.isBannerModified() && side.revertBanner();
42+
}
43+
44+
@autobind
45+
showResolveMenu(event) {
46+
event.preventDefault();
47+
48+
const menu = new Menu();
49+
50+
menu.append(new MenuItem({
51+
label: 'Resolve as Ours',
52+
click: this.resolveAsSequence.bind(this, [OURS]),
53+
}));
54+
55+
if (this.props.conflict.getSide(BASE)) {
56+
menu.append(new MenuItem({
57+
label: 'Resolve as Base',
58+
click: this.resolveAsSequence.bind(this, [BASE]),
59+
}));
60+
}
61+
62+
menu.append(new MenuItem({
63+
label: 'Resolve as Theirs',
64+
click: this.resolveAsSequence.bind(this, [THEIRS]),
65+
}));
66+
67+
menu.append(new MenuItem({type: 'separator'}));
68+
69+
menu.append(new MenuItem({
70+
label: 'Resolve as Ours Then Theirs',
71+
click: this.resolveAsSequence.bind(this, [OURS, THEIRS]),
72+
}));
73+
menu.append(new MenuItem({
74+
label: 'Resolve as Theirs Then Ours',
75+
click: this.resolveAsSequence.bind(this, [THEIRS, OURS]),
76+
}));
77+
78+
menu.append(new MenuItem({type: 'separator'}));
79+
80+
menu.append(new MenuItem({
81+
label: 'Dismiss',
82+
click: this.props.dismiss,
83+
}));
84+
85+
menu.popup(remote.getCurrentWindow());
86+
}
87+
88+
render() {
89+
if (!this.state.chosenSide) {
90+
const ours = this.props.conflict.getSide(OURS);
91+
const base = this.props.conflict.getSide(BASE);
92+
const theirs = this.props.conflict.getSide(THEIRS);
93+
94+
return (
95+
<div>
96+
{this.renderSide(ours)}
97+
{base && this.renderSide(base)}
98+
<Decoration
99+
key={this.props.conflict.getSeparator().getMarker().id}
100+
editor={this.props.editor}
101+
marker={this.props.conflict.getSeparator().getMarker()}
102+
type="line"
103+
className="github-ConflictSeparator"
104+
/>
105+
{this.renderSide(theirs)}
106+
</div>
107+
);
108+
} else {
109+
return (
110+
<Decoration
111+
editor={this.props.editor}
112+
marker={this.state.chosenSide.getMarker()}
113+
type="line"
114+
className="github-ResolvedLines"
115+
/>
116+
);
117+
}
118+
}
119+
120+
renderSide(side) {
121+
const source = side.getSource();
122+
123+
return (
124+
<div>
125+
<Decoration
126+
key={side.banner.marker.id}
127+
editor={this.props.editor}
128+
marker={side.getBannerMarker()}
129+
type="line"
130+
className={side.getBannerCSSClass()}
131+
/>
132+
{side.isBannerModified() ||
133+
<Decoration
134+
key={'banner-modified-' + side.banner.marker.id}
135+
editor={this.props.editor}
136+
marker={side.getBannerMarker()}
137+
type="line"
138+
className="github-ConflictUnmodifiedBanner"
139+
/>
140+
}
141+
<Decoration
142+
key={side.marker.id}
143+
editor={this.props.editor}
144+
marker={side.getMarker()}
145+
type="line"
146+
className={side.getLineCSSClass()}
147+
/>
148+
<Decoration
149+
key={'block-' + side.marker.id}
150+
editor={this.props.editor}
151+
marker={side.getBlockMarker()}
152+
type="block"
153+
position={side.getBlockPosition()}>
154+
<div className={side.getBlockCSSClasses()}>
155+
<span className="github-ResolutionControls">
156+
<button className="btn btn-sm inline-block" onClick={() => this.resolveAsSequence([source])}>
157+
Use me
158+
</button>
159+
{(side.isModified() || side.isBannerModified()) &&
160+
<button className="btn btn-sm inline-block" onClick={() => this.revert(side)}>
161+
Revert
162+
</button>
163+
}
164+
<Octicon icon="ellipses" className="inline-block" onClick={this.showResolveMenu} />
165+
</span>
166+
<span className="github-SideDescription">{source.toUIString()}</span>
167+
</div>
168+
</Decoration>
169+
</div>
170+
);
171+
}
172+
}

0 commit comments

Comments
 (0)