Commit 75bdbf25 authored by Tim Zallmann's avatar Tim Zallmann

Merge branch '48167-fix-outdated-discussions-new-datastructure' into 'master'

Resolve "Merge requests show outdated discussions on changes tab"

Closes #48167

See merge request gitlab-org/gitlab-ce!21543
parents 5949f552 04c0d12d
...@@ -3,6 +3,7 @@ import axios from '~/lib/utils/axios_utils'; ...@@ -3,6 +3,7 @@ import axios from '~/lib/utils/axios_utils';
import Cookies from 'js-cookie'; import Cookies from 'js-cookie';
import { handleLocationHash, historyPushState } from '~/lib/utils/common_utils'; import { handleLocationHash, historyPushState } from '~/lib/utils/common_utils';
import { mergeUrlParams } from '~/lib/utils/url_utility'; import { mergeUrlParams } from '~/lib/utils/url_utility';
import { getDiffPositionByLineCode } from './utils';
import * as types from './mutation_types'; import * as types from './mutation_types';
import { import {
PARALLEL_DIFF_VIEW_TYPE, PARALLEL_DIFF_VIEW_TYPE,
...@@ -31,11 +32,17 @@ export const fetchDiffFiles = ({ state, commit }) => { ...@@ -31,11 +32,17 @@ export const fetchDiffFiles = ({ state, commit }) => {
// This is adding line discussions to the actual lines in the diff tree // This is adding line discussions to the actual lines in the diff tree
// once for parallel and once for inline mode // once for parallel and once for inline mode
export const assignDiscussionsToDiff = ({ commit }, allLineDiscussions) => { export const assignDiscussionsToDiff = ({ state, commit }, allLineDiscussions) => {
const diffPositionByLineCode = getDiffPositionByLineCode(state.diffFiles);
Object.values(allLineDiscussions).forEach(discussions => { Object.values(allLineDiscussions).forEach(discussions => {
if (discussions.length > 0) { if (discussions.length > 0) {
const { fileHash } = discussions[0]; const { fileHash } = discussions[0];
commit(types.SET_LINE_DISCUSSIONS_FOR_FILE, { fileHash, discussions }); commit(types.SET_LINE_DISCUSSIONS_FOR_FILE, {
fileHash,
discussions,
diffPositionByLineCode,
});
} }
}); });
}; };
......
...@@ -6,6 +6,7 @@ import { ...@@ -6,6 +6,7 @@ import {
removeMatchLine, removeMatchLine,
addContextLines, addContextLines,
prepareDiffData, prepareDiffData,
isDiscussionApplicableToLine,
} from './utils'; } from './utils';
import * as types from './mutation_types'; import * as types from './mutation_types';
...@@ -84,10 +85,22 @@ export default { ...@@ -84,10 +85,22 @@ export default {
})); }));
}, },
[types.SET_LINE_DISCUSSIONS_FOR_FILE](state, { fileHash, discussions }) { [types.SET_LINE_DISCUSSIONS_FOR_FILE](state, { fileHash, discussions, diffPositionByLineCode }) {
const selectedFile = state.diffFiles.find(f => f.fileHash === fileHash); const selectedFile = state.diffFiles.find(f => f.fileHash === fileHash);
if (selectedFile) {
const firstDiscussion = discussions[0]; const firstDiscussion = discussions[0];
const isDiffDiscussion = firstDiscussion.diff_discussion;
const hasLineCode = firstDiscussion.line_code;
const isResolvable = firstDiscussion.resolvable;
const diffPosition = diffPositionByLineCode[firstDiscussion.line_code];
if (
selectedFile &&
isDiffDiscussion &&
hasLineCode &&
isResolvable &&
diffPosition &&
isDiscussionApplicableToLine(firstDiscussion, diffPosition)
) {
const targetLine = selectedFile.parallelDiffLines.find( const targetLine = selectedFile.parallelDiffLines.find(
line => line =>
(line.left && line.left.lineCode === firstDiscussion.line_code) || (line.left && line.left.lineCode === firstDiscussion.line_code) ||
......
...@@ -217,7 +217,7 @@ export function prepareDiffData(diffData) { ...@@ -217,7 +217,7 @@ export function prepareDiffData(diffData) {
} }
} }
export function getDiffRefsByLineCode(diffFiles) { export function getDiffPositionByLineCode(diffFiles) {
return diffFiles.reduce((acc, diffFile) => { return diffFiles.reduce((acc, diffFile) => {
const { baseSha, headSha, startSha } = diffFile.diffRefs; const { baseSha, headSha, startSha } = diffFile.diffRefs;
const { newPath, oldPath } = diffFile; const { newPath, oldPath } = diffFile;
...@@ -237,3 +237,12 @@ export function getDiffRefsByLineCode(diffFiles) { ...@@ -237,3 +237,12 @@ export function getDiffRefsByLineCode(diffFiles) {
return acc; return acc;
}, {}); }, {});
} }
// This method will check whether the discussion is still applicable
// to the diff line in question regarding different versions of the MR
export function isDiscussionApplicableToLine(discussion, diffPosition) {
const originalRefs = convertObjectPropsToCamelCase(discussion.original_position.formatter);
const refs = convertObjectPropsToCamelCase(discussion.position.formatter);
return _.isEqual(refs, diffPosition) || _.isEqual(originalRefs, diffPosition);
}
...@@ -6,6 +6,7 @@ class DiscussionEntity < Grape::Entity ...@@ -6,6 +6,7 @@ class DiscussionEntity < Grape::Entity
expose :id, :reply_id expose :id, :reply_id
expose :position, if: -> (d, _) { d.diff_discussion? && !d.legacy_diff_discussion? } expose :position, if: -> (d, _) { d.diff_discussion? && !d.legacy_diff_discussion? }
expose :original_position, if: -> (d, _) { d.diff_discussion? && !d.legacy_diff_discussion? }
expose :line_code, if: -> (d, _) { d.diff_discussion? } expose :line_code, if: -> (d, _) { d.diff_discussion? }
expose :expanded?, as: :expanded expose :expanded?, as: :expanded
expose :active?, as: :active, if: -> (d, _) { d.diff_discussion? } expose :active?, as: :active, if: -> (d, _) { d.diff_discussion? }
......
---
title: Fix outdated discussions being shown on Merge Request Changes tab
merge_request: 21543
author:
type: fixed
...@@ -95,20 +95,45 @@ describe('DiffsStoreActions', () => { ...@@ -95,20 +95,45 @@ describe('DiffsStoreActions', () => {
{ {
lineCode: 'ABC_1_1', lineCode: 'ABC_1_1',
discussions: [], discussions: [],
oldLine: 5,
newLine: null,
}, },
], ],
diffRefs: {
baseSha: 'abc',
headSha: 'def',
startSha: 'ghi',
},
newPath: 'file1',
oldPath: 'file2',
}, },
], ],
}; };
const diffPosition = {
baseSha: 'abc',
headSha: 'def',
startSha: 'ghi',
newLine: null,
newPath: 'file1',
oldLine: 5,
oldPath: 'file2',
};
const singleDiscussion = { const singleDiscussion = {
line_code: 'ABC_1_1', line_code: 'ABC_1_1',
diff_discussion: {}, diff_discussion: {},
diff_file: { diff_file: {
file_hash: 'ABC', file_hash: 'ABC',
}, },
resolvable: true,
fileHash: 'ABC', fileHash: 'ABC',
resolvable: true,
position: {
formatter: diffPosition,
},
original_position: {
formatter: diffPosition,
},
}; };
const discussions = reduceDiscussionsToLineCodes([singleDiscussion]); const discussions = reduceDiscussionsToLineCodes([singleDiscussion]);
...@@ -123,6 +148,17 @@ describe('DiffsStoreActions', () => { ...@@ -123,6 +148,17 @@ describe('DiffsStoreActions', () => {
payload: { payload: {
fileHash: 'ABC', fileHash: 'ABC',
discussions: [singleDiscussion], discussions: [singleDiscussion],
diffPositionByLineCode: {
ABC_1_1: {
baseSha: 'abc',
headSha: 'def',
startSha: 'ghi',
newLine: null,
newPath: 'file1',
oldLine: 5,
oldPath: 'file2',
},
},
}, },
}, },
], ],
......
...@@ -151,6 +151,16 @@ describe('DiffsStoreMutations', () => { ...@@ -151,6 +151,16 @@ describe('DiffsStoreMutations', () => {
describe('SET_LINE_DISCUSSIONS_FOR_FILE', () => { describe('SET_LINE_DISCUSSIONS_FOR_FILE', () => {
it('should add discussions to the given line', () => { it('should add discussions to the given line', () => {
const diffPosition = {
baseSha: 'ed13df29948c41ba367caa757ab3ec4892509910',
headSha: 'b921914f9a834ac47e6fd9420f78db0f83559130',
newLine: null,
newPath: '500-lines-4.txt',
oldLine: 5,
oldPath: '500-lines-4.txt',
startSha: 'ed13df29948c41ba367caa757ab3ec4892509910',
};
const state = { const state = {
diffFiles: [ diffFiles: [
{ {
...@@ -180,14 +190,38 @@ describe('DiffsStoreMutations', () => { ...@@ -180,14 +190,38 @@ describe('DiffsStoreMutations', () => {
{ {
id: 1, id: 1,
line_code: 'ABC_1', line_code: 'ABC_1',
diff_discussion: true,
resolvable: true,
original_position: {
formatter: diffPosition,
},
position: {
formatter: diffPosition,
},
}, },
{ {
id: 2, id: 2,
line_code: 'ABC_1', line_code: 'ABC_1',
diff_discussion: true,
resolvable: true,
original_position: {
formatter: diffPosition,
},
position: {
formatter: diffPosition,
},
}, },
]; ];
mutations[types.SET_LINE_DISCUSSIONS_FOR_FILE](state, { fileHash: 'ABC', discussions }); const diffPositionByLineCode = {
ABC_1: diffPosition,
};
mutations[types.SET_LINE_DISCUSSIONS_FOR_FILE](state, {
fileHash: 'ABC',
discussions,
diffPositionByLineCode,
});
expect(state.diffFiles[0].parallelDiffLines[0].left.discussions.length).toEqual(2); expect(state.diffFiles[0].parallelDiffLines[0].left.discussions.length).toEqual(2);
expect(state.diffFiles[0].parallelDiffLines[0].left.discussions[1].id).toEqual(2); expect(state.diffFiles[0].parallelDiffLines[0].left.discussions[1].id).toEqual(2);
......
...@@ -239,4 +239,57 @@ describe('DiffsStoreUtils', () => { ...@@ -239,4 +239,57 @@ describe('DiffsStoreUtils', () => {
expect(preparedDiff.diffFiles[0].collapsed).toBeFalsy(); expect(preparedDiff.diffFiles[0].collapsed).toBeFalsy();
}); });
}); });
describe('isDiscussionApplicableToLine', () => {
const diffPosition = {
baseSha: 'ed13df29948c41ba367caa757ab3ec4892509910',
headSha: 'b921914f9a834ac47e6fd9420f78db0f83559130',
newLine: null,
newPath: '500-lines-4.txt',
oldLine: 5,
oldPath: '500-lines-4.txt',
startSha: 'ed13df29948c41ba367caa757ab3ec4892509910',
};
const wrongDiffPosition = {
baseSha: 'wrong',
headSha: 'wrong',
newLine: null,
newPath: '500-lines-4.txt',
oldLine: 5,
oldPath: '500-lines-4.txt',
startSha: 'wrong',
};
const discussions = {
upToDateDiscussion1: {
original_position: {
formatter: diffPosition,
},
position: {
formatter: wrongDiffPosition,
},
},
outDatedDiscussion1: {
original_position: {
formatter: wrongDiffPosition,
},
position: {
formatter: wrongDiffPosition,
},
},
};
it('returns true when the discussion is up to date', () => {
expect(
utils.isDiscussionApplicableToLine(discussions.upToDateDiscussion1, diffPosition),
).toBe(true);
});
it('returns false when the discussion is not up to date', () => {
expect(
utils.isDiscussionApplicableToLine(discussions.outDatedDiscussion1, diffPosition),
).toBe(false);
});
});
}); });
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment