Skip to content
Snippets Groups Projects
Commit 5a7834e5 authored by Denys Mishunov's avatar Denys Mishunov Committed by Phil Hughes
Browse files

Allow adding new entries to existing path

If an entry has been removed from the tree and later, during the same
session, a user is trying to add a new item with the same name/path we
should allow for that as long as the original entry is marked with
`deleted`.
parent c2118657
No related branches found
No related tags found
No related merge requests found
Showing
with 173 additions and 15 deletions
Loading
Loading
@@ -62,7 +62,7 @@ export const createTempEntry = (
new Promise(resolve => {
const fullName = name.slice(-1) !== '/' && type === 'tree' ? `${name}/` : name;
 
if (state.entries[name]) {
if (state.entries[name] && !state.entries[name].deleted) {
flash(
`The name "${name.split('/').pop()}" is already taken in this directory.`,
'alert',
Loading
Loading
@@ -208,6 +208,7 @@ export const deleteEntry = ({ commit, dispatch, state }, path) => {
}
 
commit(types.DELETE_ENTRY, path);
dispatch('stageChange', path);
 
dispatch('triggerFilesChange');
};
Loading
Loading
Loading
Loading
@@ -186,6 +186,8 @@ export const commitChanges = ({ commit, state, getters, dispatch, rootState, roo
 
commit(rootTypes.CLEAR_STAGED_CHANGES, null, { root: true });
 
commit(rootTypes.CLEAR_REPLACED_FILES, null, { root: true });
setTimeout(() => {
commit(rootTypes.SET_LAST_COMMIT_MSG, '', { root: true });
}, 5000);
Loading
Loading
Loading
Loading
@@ -60,6 +60,8 @@ export const CLEAR_STAGED_CHANGES = 'CLEAR_STAGED_CHANGES';
export const STAGE_CHANGE = 'STAGE_CHANGE';
export const UNSTAGE_CHANGE = 'UNSTAGE_CHANGE';
 
export const CLEAR_REPLACED_FILES = 'CLEAR_REPLACED_FILES';
export const UPDATE_FILE_AFTER_COMMIT = 'UPDATE_FILE_AFTER_COMMIT';
export const ADD_PENDING_TAB = 'ADD_PENDING_TAB';
export const REMOVE_PENDING_TAB = 'REMOVE_PENDING_TAB';
Loading
Loading
Loading
Loading
@@ -56,6 +56,11 @@ export default {
stagedFiles: [],
});
},
[types.CLEAR_REPLACED_FILES](state) {
Object.assign(state, {
replacedFiles: [],
});
},
[types.SET_ENTRIES](state, entries) {
Object.assign(state, {
entries,
Loading
Loading
@@ -70,6 +75,13 @@ export default {
Object.assign(state.entries, {
[key]: entry,
});
} else if (foundEntry.deleted) {
Object.assign(state.entries, {
[key]: {
...entry,
replaces: true,
},
});
} else {
const tree = entry.tree.filter(
f => foundEntry.tree.find(e => e.path === f.path) === undefined,
Loading
Loading
@@ -144,6 +156,7 @@ export default {
raw: file.content,
changed: Boolean(changedFile),
staged: false,
replaces: false,
prevPath: '',
moved: false,
lastCommitSha: lastCommit.commit.id,
Loading
Loading
Loading
Loading
@@ -170,12 +170,16 @@ export default {
entries: Object.assign(state.entries, {
[path]: Object.assign(state.entries[path], {
staged: true,
changed: false,
}),
}),
});
 
if (stagedFile) {
Object.assign(state, {
replacedFiles: state.replacedFiles.concat({
...stagedFile,
}),
});
Object.assign(stagedFile, {
...state.entries[path],
});
Loading
Loading
Loading
Loading
@@ -6,6 +6,7 @@ export default () => ({
currentMergeRequestId: '',
changedFiles: [],
stagedFiles: [],
replacedFiles: [],
endpoints: {},
lastCommitMsg: '',
lastCommitPath: '',
Loading
Loading
Loading
Loading
@@ -18,6 +18,7 @@ export const dataStructure = () => ({
active: false,
changed: false,
staged: false,
replaces: false,
lastCommitPath: '',
lastCommitSha: '',
lastCommit: {
Loading
Loading
@@ -119,7 +120,7 @@ export const commitActionForFile = file => {
return commitActionTypes.move;
} else if (file.deleted) {
return commitActionTypes.delete;
} else if (file.tempFile) {
} else if (file.tempFile && !file.replaces) {
return commitActionTypes.create;
}
 
Loading
Loading
@@ -151,7 +152,8 @@ export const createCommitPayload = ({
previous_path: f.prevPath === '' ? undefined : f.prevPath,
content: f.prevPath ? null : f.content || undefined,
encoding: f.base64 ? 'base64' : 'text',
last_commit_id: newBranch || f.deleted || f.prevPath ? undefined : f.lastCommitSha,
last_commit_id:
newBranch || f.deleted || f.prevPath || f.replaces ? undefined : f.lastCommitSha,
})),
start_sha: newBranch ? rootGetters.lastCommit.short_id : undefined,
});
Loading
Loading
---
title: In WebIDE allow adding new entries of the same name as deleted entry
merge_request: 30239
author:
type: fixed
Loading
Loading
@@ -10,6 +10,7 @@ import actions, {
deleteEntry,
renameEntry,
getBranchData,
createTempEntry,
} from '~/ide/stores/actions';
import axios from '~/lib/utils/axios_utils';
import store from '~/ide/stores';
Loading
Loading
@@ -247,18 +248,30 @@ describe('Multi-file store actions', () => {
});
 
it('sets tmp file as active', done => {
store
.dispatch('createTempEntry', {
testAction(
createTempEntry,
{
name: 'test',
branchId: 'mybranch',
type: 'blob',
})
.then(f => {
expect(f.active).toBeTruthy();
done();
})
.catch(done.fail);
},
store.state,
[
{ type: types.CREATE_TMP_ENTRY, payload: jasmine.any(Object) },
{ type: types.TOGGLE_FILE_OPEN, payload: 'test' },
{ type: types.ADD_FILE_TO_CHANGED, payload: 'test' },
],
[
{
type: 'setFileActive',
payload: 'test',
},
{
type: 'triggerFilesChange',
},
],
done,
);
});
 
it('creates flash message if file already exists', done => {
Loading
Loading
@@ -488,7 +501,11 @@ describe('Multi-file store actions', () => {
'path',
store.state,
[{ type: types.DELETE_ENTRY, payload: 'path' }],
[{ type: 'burstUnusedSeal' }, { type: 'triggerFilesChange' }],
[
{ type: 'burstUnusedSeal' },
{ type: 'stageChange', payload: 'path' },
{ type: 'triggerFilesChange' },
],
done,
);
});
Loading
Loading
@@ -515,7 +532,11 @@ describe('Multi-file store actions', () => {
'testFolder/entry-to-delete',
store.state,
[{ type: types.DELETE_ENTRY, payload: 'testFolder/entry-to-delete' }],
[{ type: 'burstUnusedSeal' }, { type: 'triggerFilesChange' }],
[
{ type: 'burstUnusedSeal' },
{ type: 'stageChange', payload: 'testFolder/entry-to-delete' },
{ type: 'triggerFilesChange' },
],
done,
);
});
Loading
Loading
Loading
Loading
@@ -315,6 +315,19 @@ describe('IDE store file mutations', () => {
expect(localState.stagedFiles.length).toBe(1);
expect(localState.stagedFiles[0].raw).toEqual('testing 123');
});
it('adds already-staged file to `replacedFiles`', () => {
localFile.raw = 'already-staged';
mutations.STAGE_CHANGE(localState, localFile.path);
localFile.raw = 'testing 123';
mutations.STAGE_CHANGE(localState, localFile.path);
expect(localState.replacedFiles.length).toBe(1);
expect(localState.replacedFiles[0].raw).toEqual('already-staged');
});
});
 
describe('UNSTAGE_CHANGE', () => {
Loading
Loading
Loading
Loading
@@ -79,6 +79,16 @@ describe('Multi-file store mutations', () => {
});
});
 
describe('CLEAR_REPLACED_FILES', () => {
it('clears replacedFiles array', () => {
localState.replacedFiles.push('a');
mutations.CLEAR_REPLACED_FILES(localState);
expect(localState.replacedFiles.length).toBe(0);
});
});
describe('UPDATE_VIEWER', () => {
it('sets viewer state', () => {
mutations.UPDATE_VIEWER(localState, 'diff');
Loading
Loading
@@ -109,6 +119,62 @@ describe('Multi-file store mutations', () => {
});
});
 
describe('CREATE_TMP_ENTRY', () => {
beforeEach(() => {
localState.currentProjectId = 'gitlab-ce';
localState.currentBranchId = 'master';
localState.trees['gitlab-ce/master'] = {
tree: [],
};
});
it('creates temp entry in the tree', () => {
const tmpFile = file('test');
mutations.CREATE_TMP_ENTRY(localState, {
data: {
entries: {
test: {
...tmpFile,
tempFile: true,
changed: true,
},
},
treeList: [tmpFile],
},
projectId: 'gitlab-ce',
branchId: 'master',
});
expect(localState.trees['gitlab-ce/master'].tree.length).toEqual(1);
expect(localState.entries.test.tempFile).toEqual(true);
});
it('marks entry as replacing previous entry if the old one has been deleted', () => {
const tmpFile = file('test');
localState.entries.test = {
...tmpFile,
deleted: true,
};
mutations.CREATE_TMP_ENTRY(localState, {
data: {
entries: {
test: {
...tmpFile,
tempFile: true,
changed: true,
},
},
treeList: [tmpFile],
},
projectId: 'gitlab-ce',
branchId: 'master',
});
expect(localState.trees['gitlab-ce/master'].tree.length).toEqual(1);
expect(localState.entries.test.replaces).toEqual(true);
});
});
describe('UPDATE_TEMP_FLAG', () => {
beforeEach(() => {
localState.entries.test = {
Loading
Loading
@@ -252,6 +318,7 @@ describe('Multi-file store mutations', () => {
permalink: `${gl.TEST_HOST}/testing-123`,
commitsPath: `${gl.TEST_HOST}/testing-123`,
blamePath: `${gl.TEST_HOST}/testing-123`,
replaces: true,
};
localState.entries.test = f;
localState.changedFiles.push(f);
Loading
Loading
@@ -262,6 +329,7 @@ describe('Multi-file store mutations', () => {
expect(f.permalink).toBe(`${gl.TEST_HOST}/test`);
expect(f.commitsPath).toBe(`${gl.TEST_HOST}/test`);
expect(f.blamePath).toBe(`${gl.TEST_HOST}/test`);
expect(f.replaces).toBe(false);
});
});
 
Loading
Loading
Loading
Loading
@@ -92,6 +92,16 @@ describe('Multi-file store utils', () => {
path: 'deletedFile',
deleted: true,
},
{
...file('renamedFile'),
path: 'renamedFile',
prevPath: 'prevPath',
},
{
...file('replacingFile'),
path: 'replacingFile',
replaces: true,
},
],
currentBranchId: 'master',
};
Loading
Loading
@@ -131,6 +141,22 @@ describe('Multi-file store utils', () => {
last_commit_id: undefined,
previous_path: undefined,
},
{
action: commitActionTypes.move,
file_path: 'renamedFile',
content: null,
encoding: 'text',
last_commit_id: undefined,
previous_path: 'prevPath',
},
{
action: commitActionTypes.update,
file_path: 'replacingFile',
content: undefined,
encoding: 'text',
last_commit_id: undefined,
previous_path: undefined,
},
],
start_sha: undefined,
});
Loading
Loading
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment