Skip to content

add manual conflict resolution options in merge conflicts modal!!#6777

Merged
iAmWillShepherd merged 19 commits intodevelopmentfrom
manual-resolutions-ui
Feb 8, 2019
Merged

add manual conflict resolution options in merge conflicts modal!!#6777
iAmWillShepherd merged 19 commits intodevelopmentfrom
manual-resolutions-ui

Conversation

@outofambit
Copy link
Contributor

@outofambit outofambit commented Feb 5, 2019

Overview

Closes #6062

Apologies for the slightly large and winding nature of this PR. 😞 Please reach out with questions or if anything is unclear!

screen shot 2019-02-06 at 9 02 02 am

screen shot 2019-02-06 at 9 02 09 am

screen shot 2019-02-06 at 9 02 19 am

screen shot 2019-02-06 at 9 32 34 am

Description

  • pulled out parts of merge-conflicts-dialog.tsx into their own file of stateless functions
    • tslint won't check to make sure you use all of your props, but whenever that is fixed in the tslint react plugin, we'll get start getting the warnings without having to remove "disabling tslint" comments
    • i think this made this implementation cleaner since it allowed me to focus on writing functions and not add extra bulk of class syntax, but i'm open to reconsidering that
  • added a little UI for resolving manual conflicts with the dropdown
  • ran into some issues with counting resolved and conflicted files logic, so there's a little fix for that too

Notes

Release notes

Notes: [Added] Use manual merge conflict resolution strategies from within UI

@outofambit outofambit changed the title manual conflict resolution options in ui!! [forthcoming] manual conflict resolution options in ui!! Feb 5, 2019
@outofambit outofambit added this to the 1.6.2 milestone Feb 5, 2019
Copy link
Member

@shiftkey shiftkey left a comment

Choose a reason for hiding this comment

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

I know this isn't quite ready for review but I wanted to share these small suggestions while I was reading over the code to get across what's changed...

// get manual resolutions in case there are manual conflicts
const repositoryState = this.repositoryStateManager.get(repository)
const { conflictState } = repositoryState.changesState
if (conflictState === 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.

i have mixed feelings about this check being in Dispatcher. do folks think this would be better as a wrapper function in AppStore?

Copy link
Member

Choose a reason for hiding this comment

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

Did you mean like this?

diff --git a/app/src/lib/stores/app-store.ts b/app/src/lib/stores/app-store.ts
index ff72a3fee..71821ed17 100644
--- a/app/src/lib/stores/app-store.ts
+++ b/app/src/lib/stores/app-store.ts
@@ -3200,16 +3200,30 @@ export class AppStore extends TypedBaseStore<IAppState> {
   /** This shouldn't be called directly. See `Dispatcher`. */
   public async _finishConflictedMerge(
     repository: Repository,
-    workingDirectory: WorkingDirectoryStatus,
-    manualResolutions: Map<string, ManualConflictResolutionKind>
+    workingDirectory: WorkingDirectoryStatus
   ): Promise<string | undefined> {
+    // get manual resolutions in case there are manual conflicts
+    const repositoryState = this.repositoryStateCache.get(repository)
+    const { conflictState } = repositoryState.changesState
+    if (conflictState === null) {
+      // if this doesn't exist, something is very wrong and we shouldn't proceed 😢
+      log.error(
+        'Conflict state missing during finishConflictedMerge. No merge will be committed.'
+      )
+      return
+    }
+
     // filter out untracked files so we don't commit them
     const trackedFiles = workingDirectory.files.filter(f => {
       return f.status.kind !== AppFileStatusKind.Untracked
     })
     const gitStore = this.gitStoreCache.get(repository)
     return await gitStore.performFailableOperation(() =>
-      createMergeCommit(repository, trackedFiles, manualResolutions)
+      createMergeCommit(
+        repository,
+        trackedFiles,
+        conflictState.manualResolutions
+      )
     )
   }
 
diff --git a/app/src/ui/dispatcher/dispatcher.ts b/app/src/ui/dispatcher/dispatcher.ts
index b2cb4f2ad..106a4b7c4 100644
--- a/app/src/ui/dispatcher/dispatcher.ts
+++ b/app/src/ui/dispatcher/dispatcher.ts
@@ -647,20 +647,9 @@ export class Dispatcher {
     workingDirectory: WorkingDirectoryStatus,
     successfulMergeBannerState: SuccessfulMergeBannerState
   ) {
-    // get manual resolutions in case there are manual conflicts
-    const repositoryState = this.repositoryStateManager.get(repository)
-    const { conflictState } = repositoryState.changesState
-    if (conflictState === null) {
-      // if this doesn't exist, something is very wrong and we shouldn't proceed 😢
-      log.error(
-        'Conflict state missing during finishConflictedMerge. No merge will be committed.'
-      )
-      return
-    }
     const result = await this.appStore._finishConflictedMerge(
       repository,
-      workingDirectory,
-      conflictState.manualResolutions
+      workingDirectory
     )
     if (result !== undefined) {
       this.appStore._setSuccessfulMergeBannerState(successfulMergeBannerState)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

No, i tried that and i'd like to avoid it because it adds some side effects to _finishConflictedMerge that make it harder to test (it would then depend on state existing somewhere else in the store). I was thinking another method called something like "withConflictState" which would ensure conflict state is not null and then call _finishConflictedMerge. That way the side-effect-i-ness would be contained to a single clear function and _finishConflictedMerge could remain more functional. 🤔

export function hasUnresolvedConflicts(status: ConflictedFileStatus) {
export function hasUnresolvedConflicts(
status: ConflictedFileStatus,
manualResolution?: ManualConflictResolution
Copy link
Contributor Author

Choose a reason for hiding this comment

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

we have to take into account a (possible) manualResolution if its a manual conflict. i think this points to a larger issue with manual conflict resolution state existing as a part of conflict state and not associated with the file status. 😕 and that we need a none type in the ManualConflictMethodKind enum.

i'd like to dive into this more, but i think this gets us where we need to be for now. ⏳

Copy link
Contributor Author

Choose a reason for hiding this comment

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

i don't love this being optional ?, but again having an explicit type for "no manual resolution" would help with that... if this was ManualConflictResolution | null then when callers go to pull the value out of the Map<string, ManualConflictResolution> of resolutions in conflictState then they have to check for undefined fist and pass in null instead.

@outofambit outofambit added the ready-for-review Pull Requests that are ready to be reviewed by the maintainers label Feb 6, 2019
@outofambit outofambit changed the title [forthcoming] manual conflict resolution options in ui!! add manual conflict resolution options in merge conflicts modal!! Feb 6, 2019
@shiftkey
Copy link
Member

shiftkey commented Feb 6, 2019

I'm going to avoid reviewing this PR because I've been involved a lot with Merge Conflicts reviews, and I'd love some fresh eyes in this area to avoid siloing of things.

@outofambit
Copy link
Contributor Author

@niik or @iAmWillShepherd do you have time to take a looksee? 🙏

@shiftkey
Copy link
Member

shiftkey commented Feb 6, 2019

@outofambit I had a question about this screenshot, and the "Using our version" message we display here:

It's not clear from the current flow what "ours" or "theirs" represents here - the file could be modified or deleted (or maybe even added). Would if it'd be helpful to show that detail while we're in here (either in the context menu, after selecting or both)?

For reference, this is what we had in an iteration of the design:

And this is what I had working in an prototype of the flow (disregard the branch names, I'm pretty sure they were hard-coded then):

@outofambit
Copy link
Contributor Author

@shiftkey correct, that is not in this PR. i'm including that in

  • language using names of branches in strings is deferred to an upcoming PR (issue goes here)

to be followed up on in a subsequent PR. i'll open an issue for that now and update the description to be more clear. sorry about that.

@shiftkey
Copy link
Member

shiftkey commented Feb 6, 2019

@outofambit cool, as long as we've got it tracked somewhere. Thanks for the context.

Copy link
Member

@agisilaos agisilaos left a comment

Choose a reason for hiding this comment

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

Left some comments about the names of 2 labels. @outofambit.

}

return { type: SelectionType.CloningRepository, repository, progress }
return {
Copy link
Contributor

Choose a reason for hiding this comment

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

It's unclear why we are returning an object of this shape. A bit of documentation describing PossibleSelections and it's variants would go a long way in helping me understand it.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

this was simply a formatting change by prettier. @iAmWillShepherd do you want to file a new issue for some docs around this?

Copy link
Contributor

@iAmWillShepherd iAmWillShepherd left a comment

Choose a reason for hiding this comment

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

Just a few minor changes.

@outofambit
Copy link
Contributor Author

@iAmWillShepherd changes made! 🍎

@maxbed

This comment has been minimized.

Copy link
Member

@shiftkey shiftkey left a comment

Choose a reason for hiding this comment

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

Approving this to indicate that the Appveyor failure is being investigated in #6793, and shouldn't hold up getting this to beta.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ready-for-review Pull Requests that are ready to be reviewed by the maintainers

Projects

None yet

Development

Successfully merging this pull request may close these issues.

display manual conflict resolution options in app

6 participants