Commit 85186eb8 authored by Mark Florian's avatar Mark Florian

Fix infinite loop in truncation algorithm

This algorithm doesn't handle the case when a path, fully-ellipsised, is
still longer than the specified maxWidth.

For example, for a path with 21 segments, the string the util would
build is …/…/…/…/…/…/…/…/…/…/…/…/…/…/…/…/…/…/…/…/…, which is 41
characters long, so the `while` condition is never false, leading to the
infinite loop.

This adds a condition to handle that case, returning a truncated string
that never exceeds the maxWidth, no matter how deep the path is.
parent c2613cd6
......@@ -90,6 +90,13 @@ export const truncatePathMiddleToLength = (text, maxWidth) => {
while (returnText.length >= maxWidth) {
const textSplit = returnText.split('/').filter(s => s !== ELLIPSIS_CHAR);
if (textSplit.length === 0) {
// There are n - 1 path separators for n segments, so 2n - 1 <= maxWidth
const maxSegments = Math.floor((maxWidth + 1) / 2);
return new Array(maxSegments).fill(ELLIPSIS_CHAR).join('/');
}
const middleIndex = Math.floor(textSplit.length / 2);
returnText = textSplit
......
---
title: Fix rendering of very long paths in merge request file tree
merge_request: 34153
author:
type: fixed
......@@ -192,6 +192,20 @@ describe('text_utility', () => {
'app/…/…/diff',
);
});
describe('given a path too long for the maxWidth', () => {
it.each`
path | maxWidth | result
${'aa/bb/cc'} | ${1} | ${''}
${'aa/bb/cc'} | ${2} | ${''}
${'aa/bb/cc'} | ${3} | ${'…/…'}
${'aa/bb/cc'} | ${4} | ${'…/…'}
${'aa/bb/cc'} | ${5} | ${'…/…/…'}
`('truncates ($path, $maxWidth) to $result', ({ path, maxWidth, result }) => {
expect(result.length).toBeLessThanOrEqual(maxWidth);
expect(textUtils.truncatePathMiddleToLength(path, maxWidth)).toEqual(result);
});
});
});
describe('slugifyWithUnderscore', () => {
......
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