diff --git a/services/repository/files/pathutils.go b/services/repository/files/pathutils.go index 0adab4093b..271d496998 100644 --- a/services/repository/files/pathutils.go +++ b/services/repository/files/pathutils.go @@ -22,7 +22,7 @@ func SanitizePath(inputPath string) (string, error) { for _, component := range pathComponents { // Trim whitespace and apply regex sanitization sanitizedComponent := strings.TrimSpace(fileNameComponentSanitizeRegexp.ReplaceAllString(component, "_")) - + // Skip empty components after sanitization if sanitizedComponent != "" { sanitizedComponents = append(sanitizedComponents, sanitizedComponent) @@ -36,4 +36,3 @@ func SanitizePath(inputPath string) (string, error) { reconstructedPath := path.Join(sanitizedComponents...) return reconstructedPath, nil } - diff --git a/tests/e2e/repo-files.test.e2e.ts b/tests/e2e/repo-files.test.e2e.ts index e282e57b41..bfaad966d7 100644 --- a/tests/e2e/repo-files.test.e2e.ts +++ b/tests/e2e/repo-files.test.e2e.ts @@ -12,78 +12,77 @@ // make TAGS="sqlite sqlite_unlock_notify" build // otherwise the test fails. +import {expect} from '@playwright/test'; +import {test, dynamic_id, save_visual} from './utils_e2e.ts'; -import { expect } from '@playwright/test'; -import { test, dynamic_id, save_visual } from './utils_e2e.ts'; +test.use({user: 'user2'}); -test.use({ user: 'user2' }); - -test('drag and drop upload a', async ({ page }) => { +test('drag and drop upload a', async ({page}) => { const response = await page.goto(`/user2/file-uploads/_upload/main/`); expect(response?.status()).toBe(200); // Status OK const testID = dynamic_id(); - const dropzone = page.getByRole('button', { name: 'Drop files or click here to upload.' }); + const dropzone = page.getByRole('button', {name: 'Drop files or click here to upload.'}); // create the virtual files const dataTransferA = await page.evaluateHandle(() => { const dt = new DataTransfer(); // add items in different folders - dt.items.add(new File(['Filecontent (dir1/file1.txt)'], 'dir1/file1.txt', { type: 'text/plain' })); - dt.items.add(new File(["Another file's content(double / nested / file.txt)"], 'double / nested / file.txt', { type: 'text / plain' })); - dt.items.add(new File(['Root file (root_file.txt)'], 'root_file.txt', { type: 'text/plain' })); - dt.items.add(new File(['Umlaut test'], 'special/äüöÄÜÖß.txt', { type: 'text/plain' })); - dt.items.add(new File(['Unicode test'], 'special/Ʉ₦ł₵ØĐɆ.txt', { type: 'text/plain' })); + dt.items.add(new File(['Filecontent (dir1/file1.txt)'], 'dir1/file1.txt', {type: 'text/plain'})); + dt.items.add(new File(["Another file's content(double / nested / file.txt)"], 'double / nested / file.txt', {type: 'text / plain'})); + dt.items.add(new File(['Root file (root_file.txt)'], 'root_file.txt', {type: 'text/plain'})); + dt.items.add(new File(['Umlaut test'], 'special/äüöÄÜÖß.txt', {type: 'text/plain'})); + dt.items.add(new File(['Unicode test'], 'special/Ʉ₦ł₵ØĐɆ.txt', {type: 'text/plain'})); return dt; }); // and drop them to the upload area - await dropzone.dispatchEvent('drop', { dataTransfer: dataTransferA }); + await dropzone.dispatchEvent('drop', {dataTransfer: dataTransferA}); await page.getByText('new branch').click(); await save_visual(page); - await page.getByRole('textbox', { name: 'Name the new branch for this' }).fill(testID); - await page.getByRole('button', { name: 'Propose file change' }).click(); + await page.getByRole('textbox', {name: 'Name the new branch for this'}).fill(testID); + await page.getByRole('button', {name: 'Propose file change'}).click(); // check that nested file structure is preserved - await expect(page.getByRole('link', { name: 'dir1/file1.txt' })).toBeVisible(); - await expect(page.getByRole('link', { name: 'double/nested/file.txt' })).toBeVisible(); - await expect(page.getByRole('link', { name: 'special/äüöÄÜÖß.txt' })).toBeVisible(); - await expect(page.getByRole('link', { name: 'special/Ʉ₦ł₵ØĐɆ.txt' })).toBeVisible(); - await expect(page.locator('#diff-file-boxes').getByRole('link', { name: 'root_file.txt', exact: true })).toBeVisible(); + await expect(page.getByRole('link', {name: 'dir1/file1.txt'})).toBeVisible(); + await expect(page.getByRole('link', {name: 'double/nested/file.txt'})).toBeVisible(); + await expect(page.getByRole('link', {name: 'special/äüöÄÜÖß.txt'})).toBeVisible(); + await expect(page.getByRole('link', {name: 'special/Ʉ₦ł₵ØĐɆ.txt'})).toBeVisible(); + await expect(page.locator('#diff-file-boxes').getByRole('link', {name: 'root_file.txt', exact: true})).toBeVisible(); await save_visual(page); }); -test('drag and drop upload b', async ({ page }) => { +test('drag and drop upload b', async ({page}) => { const response = await page.goto(`/user2/file-uploads/_upload/main/`); expect(response?.status()).toBe(200); // Status OK const testID = dynamic_id(); - const dropzone = page.getByRole('button', { name: 'Drop files or click here to upload.' }); + const dropzone = page.getByRole('button', {name: 'Drop files or click here to upload.'}); // create the virtual files const dataTransferA = await page.evaluateHandle(() => { const dt = new DataTransfer(); // add items in different folders - dt.items.add(new File(['1'], '../../dots.txt', { type: 'text/plain' })); - dt.items.add(new File(['2'], 'special/../../dots_vanish.txt', { type: 'text/plain' })); - dt.items.add(new File(['3'], '\\windows\\windows_slash.txt', { type: 'text/plain' })); - dt.items.add(new File(['4'], '/special/badfirstslash.txt', { type: 'text/plain' })); - dt.items.add(new File(['5'], 'special/S P A C E !.txt', { type: 'text/plain' })); + dt.items.add(new File(['1'], '../../dots.txt', {type: 'text/plain'})); + dt.items.add(new File(['2'], 'special/../../dots_vanish.txt', {type: 'text/plain'})); + dt.items.add(new File(['3'], '\\windows\\windows_slash.txt', {type: 'text/plain'})); + dt.items.add(new File(['4'], '/special/badfirstslash.txt', {type: 'text/plain'})); + dt.items.add(new File(['5'], 'special/S P A C E !.txt', {type: 'text/plain'})); return dt; }); // and drop them to the upload area - await dropzone.dispatchEvent('drop', { dataTransfer: dataTransferA }); + await dropzone.dispatchEvent('drop', {dataTransfer: dataTransferA}); await page.getByText('new branch').click(); await save_visual(page); - await page.getByRole('textbox', { name: 'Name the new branch for this' }).fill(testID); - await page.getByRole('button', { name: 'Propose file change' }).click(); + await page.getByRole('textbox', {name: 'Name the new branch for this'}).fill(testID); + await page.getByRole('button', {name: 'Propose file change'}).click(); // check that nested file structure is preserved - await expect(page.getByRole('link', { name: 'windows/windows_slash.txt' })).toBeVisible(); - await expect(page.getByRole('link', { name: '_/dots_vanish.txt' })).toBeVisible(); - await expect(page.getByRole('link', { name: 'special/badfirstslash.txt' })).toBeVisible(); - await expect(page.getByRole('link', { name: 'special/S P A C E !.txt' })).toBeVisible(); - await expect(page.locator('#diff-file-boxes').getByRole('link', { name: '_/_/dots.txt', exact: true })).toBeVisible(); + await expect(page.getByRole('link', {name: 'windows/windows_slash.txt'})).toBeVisible(); + await expect(page.getByRole('link', {name: '_/dots_vanish.txt'})).toBeVisible(); + await expect(page.getByRole('link', {name: 'special/badfirstslash.txt'})).toBeVisible(); + await expect(page.getByRole('link', {name: 'special/S P A C E !.txt'})).toBeVisible(); + await expect(page.locator('#diff-file-boxes').getByRole('link', {name: '_/_/dots.txt', exact: true})).toBeVisible(); await save_visual(page); -}); \ No newline at end of file +});