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

Skip to content
This repository was archived by the owner on Dec 15, 2022. It is now read-only.

Decorate merge conflicts within TextEditors #385

Merged
merged 116 commits into from
Feb 21, 2017

Conversation

smashwilson
Copy link
Contributor

@smashwilson smashwilson commented Dec 22, 2016

Port a bunch of code from merge-conflicts to parse, mark, and resolve conflict markers within TextEditors.

  • Parse conflict markers from a corpus of text, creating a DisplayMarker on the banners, sides, and separators of each. Handle and test against weird recursive conflict cases.
  • Create a Decoration component, like the Panel and PaneItem components, that maps the lifecycle of an Atom Decoration to that of a React component.
  • RepositoryConflictController to render a subcomponent for each open TextEditor that corresponds to a merge conflict.
  • EditorConflictController to render a subcomponent for each Conflict parsed out of a specific TextEditor.
  • ConflictController to render a set of Decorations corresponding to each part of a specific Conflict.
  • Track conflict marker counts and resolution progress per conflicting file within a Repository. Reset it when the merge is aborted or committed.
  • Render a mini-progress bar within the list of merge conflicts in the GitPanelView to show the resolution progress for each file.
  • Change the CSS class of a conflict side when it's been modified by hand.
    • Display a "revert" button on modified conflict sides.
  • Use a block decoration to bracket each side of the conflict.
  • Add resolution methods to ConflictController to resolve a conflict as ours, theirs, ours then theirs, or theirs then ours.
    • Signal the resolution progress model.
    • Trigger them with github:* commands.
    • Trigger them with a "use me" button on the block decoration.
    • Trigger them with a context menu, accessible from a gear icon.
  • Backfill unit tests for the things I rushed ahead with for the demo 😉
  • Dismiss a conflict marker to handle manually
  • "Abort merge" or "Stage all" controls on the merge conflicts list

References #383.

@smashwilson smashwilson changed the title [wip] Decorate merge conflicts within TextEditors Decorate merge conflicts within TextEditors Dec 30, 2016
@smashwilson smashwilson force-pushed the merge-conflict-resolution branch from cb662e6 to 2761dd3 Compare December 30, 2016 16:44

import Portal from './portal';

export default class Decoration extends React.Component {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@BinaryMuse: here's my Decoration component, largely cargo-culted from Panel and PaneItem. I'm also not actually using it for any decorations that use a subtree yet (although that will change before this PR is ready). I'd ❤️ any early feedback you'd have 😄

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks awesome!

@smashwilson smashwilson mentioned this pull request Jan 5, 2017
render() {
const controllers = this.state.conflictingEditors.map(editor => (
<EditorConflictController
key={editor.getPath()}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it possible we'll have multiple editors open with the same path (such as when splitting)?

@@ -16,7 +16,7 @@ import ReactDom from 'react-dom';
* rendered into it. Note that this uses `unstable_renderSubtreeIntoContainer`
* to preserve context in the subtree.
*
* `getElement()` allows acccess to the React subtree container element.
* `getElement()` allows access to the React subtree container element.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

😅

@smashwilson smashwilson force-pushed the merge-conflict-resolution branch 2 times, most recently from bb8bfd0 to 757c2a3 Compare January 11, 2017 19:42
@smashwilson smashwilson mentioned this pull request Jan 23, 2017
@smashwilson smashwilson force-pushed the merge-conflict-resolution branch 2 times, most recently from 2804678 to 61b297e Compare January 30, 2017 18:48
Copy link
Contributor Author

@smashwilson smashwilson left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Feedback from a ScreenHero code review extravaganza with @kuychaco and @BinaryMuse

}

export default class Conflict {

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔥

conflict() {
return new Conflict(this.ours, this.separator, this.base, this.theirs);
}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔥

);
}

getConflictingEditors() {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@kuychaco: If you don't want to mess around with putting conflicting files in the index for your discard-undo work, you could pass in extra "conflicting" paths as a prop here ☝️


componentDidMount() {
this.subscriptions.add(
this.props.editor.onDidStopChanging(() => this.setState({})),
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Change this to .forceUpdate()

this.layer = props.editor.getDefaultMarkerLayer();

this.state = {
conflicts: Conflict.allFromEditor(props.editor, this.layer, props.isRebase),
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Make this a Set

dismissConflicts(conflicts) {
const conflictSet = new Set(conflicts);
this.setState((prevState, props) => {
const newConflicts = prevState.conflicts.filter(conflict => !conflictSet.has(conflict));
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use compare-sets

onclick={this.props.abortMerge}>
Abort Merge
</button>
) : null;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead, add a drop-down to resolve all files as ours/theirs

remainingConflicts={resolutionProgress.getRemaining(fullPath)}
registerItemElement={this.registerItemElement}
ondblclick={event => this.dblclickOnItem(event, mergeConflict)}
oncontextmenu={event => this.contextMenuOnItem(event, mergeConflict)}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add resolve as ours/resolve as theirs as context menu options

for (let i = 0; i < data.mergeConflicts.length; i++) {
const conflictPath = path.join(data.workingDirectoryPath, data.mergeConflicts[i].filePath);
if (!openPaths.has(conflictPath) && this.props.resolutionProgress.getRemaining(conflictPath) === undefined) {
const readStream = fs.createReadStream(conflictPath, {encoding: 'utf-8'});
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove the - in utf-8

@simurai
Copy link
Contributor

simurai commented Feb 21, 2017

Changed the colors from the "random" site colors to the git colors. Should add a little more meaning:

  • ours: @syntax-color-removed -> red 🍓
  • theirs: @syntax-color-renamed -> blue 🐟
  • base: desaturated mix of the above -> grey-purple-ish 🍆
  • modified: @syntax-color-modified -> orange 🍊
  • resolved: @syntax-color-added -> green 🍏

screen shot 2017-02-21 at 7 05 16 pm

That the "ours" changes are red might be a bit strong, but also makes some sense. Like picking only "your changes" and ignore the rest (remote) is somewhat dangerous and should only be done with caution.

@smashwilson
Copy link
Contributor Author

Hmm, yeah, I'm not as fond of that red, it feels too strong. I'm not sure what would be better, though - orange is blue's complement but that's already used for "modified," which feels right...

I like the others though!

@smashwilson
Copy link
Contributor Author

Hmm now that I've used it a bit, the red seems okay to me 🤔 I trust your judgement, go with whatever looks right to you 😁

@smashwilson smashwilson merged commit 7803b3e into master Feb 21, 2017
@smashwilson smashwilson deleted the merge-conflict-resolution branch February 21, 2017 20:47
@smashwilson
Copy link
Contributor Author

@Bjvanminnen
Copy link

Bjvanminnen commented Jun 26, 2017

Is there a setting I can change if I want to disable this feature?

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants