Convert PathListBehavior to util
Some methods from pat-list-util are used for bindings in templates and/or in computed properties. Wrappers for those methods are added to elements directly. Change-Id: I6ddeca7abf71bc3bacdd8de3f5203809ba1a9556
This commit is contained in:
@@ -32,13 +32,13 @@ import {LegacyElementMixin} from '@polymer/polymer/lib/legacy/legacy-element-mix
|
||||
import {PolymerElement} from '@polymer/polymer/polymer-element.js';
|
||||
import {htmlTemplate} from './gr-change-list-item_html.js';
|
||||
import {ChangeTableMixin} from '../../../mixins/gr-change-table-mixin/gr-change-table-mixin.js';
|
||||
import {PathListBehavior} from '../../../behaviors/gr-path-list-behavior/gr-path-list-behavior.js';
|
||||
import {RESTClientBehavior} from '../../../behaviors/rest-client-behavior/rest-client-behavior.js';
|
||||
import {GerritNav} from '../../core/gr-navigation/gr-navigation.js';
|
||||
import {getDisplayName} from '../../../utils/display-name-util.js';
|
||||
import {pluginEndpoints} from '../../shared/gr-js-api-interface/gr-plugin-endpoints.js';
|
||||
import {pluginLoader} from '../../shared/gr-js-api-interface/gr-plugin-loader.js';
|
||||
import {appContext} from '../../../services/app-context.js';
|
||||
import {truncatePath} from '../../../utils/path-list-util.js';
|
||||
|
||||
const CHANGE_SIZE = {
|
||||
XS: 10,
|
||||
@@ -55,7 +55,6 @@ const PRIMARY_REVIEWERS_COUNT = 2;
|
||||
* @extends PolymerElement
|
||||
*/
|
||||
class GrChangeListItem extends ChangeTableMixin(mixinBehaviors( [
|
||||
PathListBehavior,
|
||||
RESTClientBehavior,
|
||||
], GestureEventListeners(
|
||||
LegacyElementMixin(
|
||||
@@ -207,7 +206,7 @@ class GrChangeListItem extends ChangeTableMixin(mixinBehaviors( [
|
||||
if (!change || !change.project) { return ''; }
|
||||
let str = '';
|
||||
if (change.internalHost) { str += change.internalHost + '/'; }
|
||||
str += truncate ? this.truncatePath(change.project, 2) : change.project;
|
||||
str += truncate ? truncatePath(change.project, 2) : change.project;
|
||||
return str;
|
||||
}
|
||||
|
||||
|
||||
@@ -34,7 +34,6 @@ import {LegacyElementMixin} from '@polymer/polymer/lib/legacy/legacy-element-mix
|
||||
import {PolymerElement} from '@polymer/polymer/polymer-element.js';
|
||||
import {htmlTemplate} from './gr-file-list_html.js';
|
||||
import {asyncForeach} from '../../../utils/async-util.js';
|
||||
import {PathListBehavior} from '../../../behaviors/gr-path-list-behavior/gr-path-list-behavior.js';
|
||||
import {KeyboardShortcutBehavior} from '../../../behaviors/keyboard-shortcut-behavior/keyboard-shortcut-behavior.js';
|
||||
import {GrFileListConstants} from '../gr-file-list-constants.js';
|
||||
import {GrCountStringFormatter} from '../../shared/gr-count-string-formatter/gr-count-string-formatter.js';
|
||||
@@ -45,6 +44,13 @@ import {appContext} from '../../../services/app-context.js';
|
||||
import {SpecialFilePath} from '../../../constants/constants.js';
|
||||
import {descendedFromClass} from '../../../utils/dom-util.js';
|
||||
import {getRevisionByPatchNum} from '../../../utils/patch-set-util.js';
|
||||
import {
|
||||
addUnmodifiedFiles,
|
||||
computeDisplayPath,
|
||||
computeTruncatedPath,
|
||||
isMagicPath,
|
||||
specialFilePathCompare,
|
||||
} from '../../../utils/path-list-util.js';
|
||||
|
||||
// Maximum length for patch set descriptions.
|
||||
const PATCH_DESC_MAX_LENGTH = 500;
|
||||
@@ -92,7 +98,6 @@ const FILE_ROW_CLASS = 'file-row';
|
||||
*/
|
||||
class GrFileList extends mixinBehaviors( [
|
||||
KeyboardShortcutBehavior,
|
||||
PathListBehavior,
|
||||
], GestureEventListeners(
|
||||
LegacyElementMixin(
|
||||
PolymerElement))) {
|
||||
@@ -418,7 +423,7 @@ class GrFileList extends mixinBehaviors( [
|
||||
|
||||
_calculatePatchChange(files) {
|
||||
const magicFilesExcluded = files.filter(files =>
|
||||
!this.isMagicPath(files.__path)
|
||||
!isMagicPath(files.__path)
|
||||
);
|
||||
|
||||
return magicFilesExcluded.reduce((acc, obj) => {
|
||||
@@ -656,14 +661,12 @@ class GrFileList extends mixinBehaviors( [
|
||||
}
|
||||
|
||||
/**
|
||||
* The closure compiler doesn't realize this.specialFilePathCompare is
|
||||
* valid.
|
||||
*
|
||||
* @returns {!Array<FileInfo>}
|
||||
*/
|
||||
_normalizeChangeFilesResponse(response) {
|
||||
if (!response) { return []; }
|
||||
const paths = Object.keys(response).sort(this.specialFilePathCompare);
|
||||
const paths = Object.keys(response).sort(specialFilePathCompare);
|
||||
const files = [];
|
||||
for (let i = 0; i < paths.length; i++) {
|
||||
const info = response[paths[i]];
|
||||
@@ -1074,7 +1077,7 @@ class GrFileList extends mixinBehaviors( [
|
||||
|
||||
const commentedPaths = changeComments.getPaths(patchRange);
|
||||
const files = Object.assign({}, filesByPath);
|
||||
this.addUnmodifiedFiles(files, commentedPaths);
|
||||
addUnmodifiedFiles(files, commentedPaths);
|
||||
const reviewedSet = new Set(reviewed || []);
|
||||
for (const filePath in files) {
|
||||
if (!files.hasOwnProperty(filePath)) { continue; }
|
||||
@@ -1608,6 +1611,20 @@ class GrFileList extends mixinBehaviors( [
|
||||
this.diffPrefs = prefs;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrapper for using in the element template and computed properties
|
||||
*/
|
||||
_computeDisplayPath(path) {
|
||||
return computeDisplayPath(path);
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrapper for using in the element template and computed properties
|
||||
*/
|
||||
_computeTruncatedPath(path) {
|
||||
return computeTruncatedPath(path);
|
||||
}
|
||||
}
|
||||
|
||||
customElements.define(GrFileList.is, GrFileList);
|
||||
|
||||
@@ -409,16 +409,16 @@ export const htmlTemplate = html`
|
||||
href$="[[_computeDiffURL(change, patchRange, file.__path, editMode)]]"
|
||||
>
|
||||
<span
|
||||
title$="[[computeDisplayPath(file.__path)]]"
|
||||
title$="[[_computeDisplayPath(file.__path)]]"
|
||||
class="fullFileName"
|
||||
>
|
||||
[[computeDisplayPath(file.__path)]]
|
||||
[[_computeDisplayPath(file.__path)]]
|
||||
</span>
|
||||
<span
|
||||
title$="[[computeDisplayPath(file.__path)]]"
|
||||
title$="[[_computeDisplayPath(file.__path)]]"
|
||||
class="truncatedFileName"
|
||||
>
|
||||
[[computeTruncatedPath(file.__path)]]
|
||||
[[_computeTruncatedPath(file.__path)]]
|
||||
</span>
|
||||
<span
|
||||
class$="[[_computeStatusClass(file)]]"
|
||||
|
||||
@@ -38,7 +38,6 @@ import {GestureEventListeners} from '@polymer/polymer/lib/mixins/gesture-event-l
|
||||
import {LegacyElementMixin} from '@polymer/polymer/lib/legacy/legacy-element-mixin.js';
|
||||
import {PolymerElement} from '@polymer/polymer/polymer-element.js';
|
||||
import {htmlTemplate} from './gr-diff-view_html.js';
|
||||
import {PathListBehavior} from '../../../behaviors/gr-path-list-behavior/gr-path-list-behavior.js';
|
||||
import {KeyboardShortcutBehavior} from '../../../behaviors/keyboard-shortcut-behavior/keyboard-shortcut-behavior.js';
|
||||
import {RESTClientBehavior} from '../../../behaviors/rest-client-behavior/rest-client-behavior.js';
|
||||
import {GrCountStringFormatter} from '../../shared/gr-count-string-formatter/gr-count-string-formatter.js';
|
||||
@@ -51,6 +50,10 @@ import {
|
||||
patchNumEquals,
|
||||
SPECIAL_PATCH_SET_NUM,
|
||||
} from '../../../utils/patch-set-util.js';
|
||||
import {
|
||||
addUnmodifiedFiles, computeDisplayPath, computeTruncatedPath,
|
||||
isMagicPath, specialFilePathCompare,
|
||||
} from '../../../utils/path-list-util.js';
|
||||
|
||||
const ERR_REVIEW_STATUS = 'Couldn’t change file review status.';
|
||||
const MSG_LOADING_BLAME = 'Loading blame...';
|
||||
@@ -73,7 +76,6 @@ const DiffViewMode = {
|
||||
*/
|
||||
class GrDiffView extends mixinBehaviors( [
|
||||
KeyboardShortcutBehavior,
|
||||
PathListBehavior,
|
||||
RESTClientBehavior,
|
||||
], GestureEventListeners(
|
||||
LegacyElementMixin(
|
||||
@@ -394,9 +396,9 @@ class GrDiffView extends mixinBehaviors( [
|
||||
if (!changeFiles) return;
|
||||
const commentedPaths = changeComments.getPaths(patchRange);
|
||||
const files = Object.assign({}, changeFiles);
|
||||
this.addUnmodifiedFiles(files, commentedPaths);
|
||||
addUnmodifiedFiles(files, commentedPaths);
|
||||
this._files = {
|
||||
sortedFileList: Object.keys(files).sort(this.specialFilePathCompare),
|
||||
sortedFileList: Object.keys(files).sort(specialFilePathCompare),
|
||||
changeFilesByPath: files,
|
||||
};
|
||||
});
|
||||
@@ -768,7 +770,7 @@ class GrDiffView extends mixinBehaviors( [
|
||||
// has been queued, the event can bubble up to the handler in gr-app.
|
||||
this.async(() => {
|
||||
this.dispatchEvent(new CustomEvent('title-change', {
|
||||
detail: {title: this.computeTruncatedPath(this._path)},
|
||||
detail: {title: computeTruncatedPath(this._path)},
|
||||
composed: true, bubbles: true,
|
||||
}));
|
||||
});
|
||||
@@ -900,7 +902,7 @@ class GrDiffView extends mixinBehaviors( [
|
||||
_pathChanged(path) {
|
||||
if (path) {
|
||||
this.dispatchEvent(new CustomEvent('title-change', {
|
||||
detail: {title: this.computeTruncatedPath(path)},
|
||||
detail: {title: computeTruncatedPath(path)},
|
||||
composed: true, bubbles: true,
|
||||
}));
|
||||
}
|
||||
@@ -984,8 +986,8 @@ class GrDiffView extends mixinBehaviors( [
|
||||
const dropdownContent = [];
|
||||
for (const path of files.sortedFileList) {
|
||||
dropdownContent.push({
|
||||
text: this.computeDisplayPath(path),
|
||||
mobileText: this.computeTruncatedPath(path),
|
||||
text: computeDisplayPath(path),
|
||||
mobileText: computeTruncatedPath(path),
|
||||
value: path,
|
||||
bottomText: this._computeCommentString(changeComments, patchNum,
|
||||
path, files.changeFilesByPath[path]),
|
||||
@@ -1385,7 +1387,7 @@ class GrDiffView extends mixinBehaviors( [
|
||||
}
|
||||
|
||||
_computeBlameLoaderClass(isImageDiff, path) {
|
||||
return !this.isMagicPath(path) && !isImageDiff ? 'show' : '';
|
||||
return !isMagicPath(path) && !isImageDiff ? 'show' : '';
|
||||
}
|
||||
|
||||
_getRevisionInfo(change) {
|
||||
@@ -1455,6 +1457,13 @@ class GrDiffView extends mixinBehaviors( [
|
||||
_computeAllPatchSets(change) {
|
||||
return computeAllPatchSets(change);
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrapper for using in the element template and computed properties
|
||||
*/
|
||||
_computeDisplayPath(path) {
|
||||
return computeDisplayPath(path);
|
||||
}
|
||||
}
|
||||
|
||||
customElements.define(GrDiffView.is, GrDiffView);
|
||||
|
||||
@@ -371,7 +371,7 @@ export const htmlTemplate = html`
|
||||
>
|
||||
<</a
|
||||
>
|
||||
<div class="fullFileName mobile">[[computeDisplayPath(_path)]]</div>
|
||||
<div class="fullFileName mobile">[[_computeDisplayPath(_path)]]</div>
|
||||
<a
|
||||
class="mobileNavLink"
|
||||
href$="[[_computeNavLinkURL(_change, _path, _fileList, 1, 1)]]"
|
||||
|
||||
@@ -28,10 +28,10 @@ import {GestureEventListeners} from '@polymer/polymer/lib/mixins/gesture-event-l
|
||||
import {LegacyElementMixin} from '@polymer/polymer/lib/legacy/legacy-element-mixin.js';
|
||||
import {PolymerElement} from '@polymer/polymer/polymer-element.js';
|
||||
import {htmlTemplate} from './gr-editor-view_html.js';
|
||||
import {PathListBehavior} from '../../../behaviors/gr-path-list-behavior/gr-path-list-behavior.js';
|
||||
import {KeyboardShortcutBehavior} from '../../../behaviors/keyboard-shortcut-behavior/keyboard-shortcut-behavior.js';
|
||||
import {GerritNav} from '../../core/gr-navigation/gr-navigation.js';
|
||||
import {SPECIAL_PATCH_SET_NUM} from '../../../utils/patch-set-util.js';
|
||||
import {computeTruncatedPath} from '../../../utils/path-list-util.js';
|
||||
|
||||
const RESTORED_MESSAGE = 'Content restored from a previous edit.';
|
||||
const SAVING_MESSAGE = 'Saving changes...';
|
||||
@@ -45,7 +45,6 @@ const STORAGE_DEBOUNCE_INTERVAL_MS = 100;
|
||||
*/
|
||||
class GrEditorView extends mixinBehaviors( [
|
||||
KeyboardShortcutBehavior,
|
||||
PathListBehavior,
|
||||
], GestureEventListeners(
|
||||
LegacyElementMixin(
|
||||
PolymerElement))) {
|
||||
@@ -145,7 +144,7 @@ class GrEditorView extends mixinBehaviors( [
|
||||
// null). Fire title-change in an async so that, if attachment to the DOM
|
||||
// has been queued, the event can bubble up to the handler in gr-app.
|
||||
this.async(() => {
|
||||
const title = `Editing ${this.computeTruncatedPath(this._path)}`;
|
||||
const title = `Editing ${computeTruncatedPath(this._path)}`;
|
||||
this.dispatchEvent(new CustomEvent('title-change', {
|
||||
detail: {title},
|
||||
composed: true, bubbles: true,
|
||||
|
||||
@@ -24,12 +24,12 @@ import {GestureEventListeners} from '@polymer/polymer/lib/mixins/gesture-event-l
|
||||
import {LegacyElementMixin} from '@polymer/polymer/lib/legacy/legacy-element-mixin.js';
|
||||
import {PolymerElement} from '@polymer/polymer/polymer-element.js';
|
||||
import {htmlTemplate} from './gr-comment-thread_html.js';
|
||||
import {PathListBehavior} from '../../../behaviors/gr-path-list-behavior/gr-path-list-behavior.js';
|
||||
import {KeyboardShortcutBehavior} from '../../../behaviors/keyboard-shortcut-behavior/keyboard-shortcut-behavior.js';
|
||||
import {parseDate} from '../../../utils/date-util.js';
|
||||
import {GerritNav} from '../../core/gr-navigation/gr-navigation.js';
|
||||
import {appContext} from '../../../services/app-context.js';
|
||||
import {SpecialFilePath} from '../../../constants/constants.js';
|
||||
import {computeDisplayPath} from '../../../utils/path-list-util.js';
|
||||
|
||||
const UNRESOLVED_EXPAND_COUNT = 5;
|
||||
const NEWLINE_PATTERN = /\n/g;
|
||||
@@ -42,7 +42,6 @@ class GrCommentThread extends mixinBehaviors( [
|
||||
* Not used in this element rather other elements tests
|
||||
*/
|
||||
KeyboardShortcutBehavior,
|
||||
PathListBehavior,
|
||||
], GestureEventListeners(
|
||||
LegacyElementMixin(
|
||||
PolymerElement))) {
|
||||
@@ -245,7 +244,7 @@ class GrCommentThread extends mixinBehaviors( [
|
||||
}
|
||||
|
||||
_computeDisplayPath(path) {
|
||||
const displayPath = this.computeDisplayPath(path);
|
||||
const displayPath = computeDisplayPath(path);
|
||||
if (displayPath === SpecialFilePath.PATCHSET_LEVEL_COMMENTS) {
|
||||
return `Patchset`;
|
||||
}
|
||||
|
||||
@@ -20,7 +20,6 @@ import {mixinBehaviors} from '@polymer/polymer/lib/legacy/class.js';
|
||||
import {GestureEventListeners} from '@polymer/polymer/lib/mixins/gesture-event-listeners.js';
|
||||
import {LegacyElementMixin} from '@polymer/polymer/lib/legacy/legacy-element-mixin.js';
|
||||
import {PolymerElement} from '@polymer/polymer/polymer-element.js';
|
||||
import {PathListBehavior} from '../../../behaviors/gr-path-list-behavior/gr-path-list-behavior.js';
|
||||
import {RESTClientBehavior} from '../../../behaviors/rest-client-behavior/rest-client-behavior.js';
|
||||
import {GrEtagDecorator} from './gr-etag-decorator.js';
|
||||
import {SiteBasedCache, FetchPromisesCache, GrRestApiHelper} from './gr-rest-apis/gr-rest-api-helper.js';
|
||||
@@ -92,7 +91,6 @@ export function _testOnlyResetGrRestApiSharedObjects() {
|
||||
* @extends PolymerElement
|
||||
*/
|
||||
class GrRestApiInterface extends mixinBehaviors( [
|
||||
PathListBehavior,
|
||||
RESTClientBehavior,
|
||||
], GestureEventListeners(
|
||||
LegacyElementMixin(
|
||||
|
||||
@@ -256,59 +256,6 @@ suite('gr-rest-api-interface tests', () => {
|
||||
});
|
||||
});
|
||||
|
||||
test('special file path sorting', () => {
|
||||
assert.deepEqual(
|
||||
['.b', '/COMMIT_MSG', '.a', 'file'].sort(
|
||||
element.specialFilePathCompare),
|
||||
['/COMMIT_MSG', '.a', '.b', 'file']);
|
||||
|
||||
assert.deepEqual(
|
||||
['.b', '/COMMIT_MSG', 'foo/bar/baz.cc', 'foo/bar/baz.h'].sort(
|
||||
element.specialFilePathCompare),
|
||||
['/COMMIT_MSG', '.b', 'foo/bar/baz.h', 'foo/bar/baz.cc']);
|
||||
|
||||
assert.deepEqual(
|
||||
['.b', '/COMMIT_MSG', 'foo/bar/baz.cc', 'foo/bar/baz.hpp'].sort(
|
||||
element.specialFilePathCompare),
|
||||
['/COMMIT_MSG', '.b', 'foo/bar/baz.hpp', 'foo/bar/baz.cc']);
|
||||
|
||||
assert.deepEqual(
|
||||
['.b', '/COMMIT_MSG', 'foo/bar/baz.cc', 'foo/bar/baz.hxx'].sort(
|
||||
element.specialFilePathCompare),
|
||||
['/COMMIT_MSG', '.b', 'foo/bar/baz.hxx', 'foo/bar/baz.cc']);
|
||||
|
||||
assert.deepEqual(
|
||||
['foo/bar.h', 'foo/bar.hxx', 'foo/bar.hpp'].sort(
|
||||
element.specialFilePathCompare),
|
||||
['foo/bar.h', 'foo/bar.hpp', 'foo/bar.hxx']);
|
||||
|
||||
// Regression test for Issue 4448.
|
||||
assert.deepEqual(
|
||||
[
|
||||
'minidump/minidump_memory_writer.cc',
|
||||
'minidump/minidump_memory_writer.h',
|
||||
'minidump/minidump_thread_writer.cc',
|
||||
'minidump/minidump_thread_writer.h',
|
||||
].sort(element.specialFilePathCompare),
|
||||
[
|
||||
'minidump/minidump_memory_writer.h',
|
||||
'minidump/minidump_memory_writer.cc',
|
||||
'minidump/minidump_thread_writer.h',
|
||||
'minidump/minidump_thread_writer.cc',
|
||||
]);
|
||||
|
||||
// Regression test for Issue 4545.
|
||||
assert.deepEqual(
|
||||
[
|
||||
'task_test.go',
|
||||
'task.go',
|
||||
].sort(element.specialFilePathCompare),
|
||||
[
|
||||
'task.go',
|
||||
'task_test.go',
|
||||
]);
|
||||
});
|
||||
|
||||
test('server error', done => {
|
||||
const getResponseObjectStub = sinon.stub(element, 'getResponseObject');
|
||||
window.fetch.returns(Promise.resolve({ok: false}));
|
||||
|
||||
@@ -15,117 +15,106 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import {SpecialFilePath} from '../../constants/constants.js';
|
||||
import {SpecialFilePath} from '../constants/constants.js';
|
||||
|
||||
/** @polymerBehavior Gerrit.PathListBehavior */
|
||||
export const PathListBehavior = {
|
||||
/**
|
||||
* @param {string} a
|
||||
* @param {string} b
|
||||
* @return {number}
|
||||
*/
|
||||
export function specialFilePathCompare(a, b) {
|
||||
// The commit message always goes first.
|
||||
if (a === SpecialFilePath.COMMIT_MESSAGE) {
|
||||
return -1;
|
||||
}
|
||||
if (b === SpecialFilePath.COMMIT_MESSAGE) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} a
|
||||
* @param {string} b
|
||||
* @return {number}
|
||||
*/
|
||||
specialFilePathCompare(a, b) {
|
||||
// The commit message always goes first.
|
||||
if (a === SpecialFilePath.COMMIT_MESSAGE) {
|
||||
// The merge list always comes next.
|
||||
if (a === SpecialFilePath.MERGE_LIST) {
|
||||
return -1;
|
||||
}
|
||||
if (b === SpecialFilePath.MERGE_LIST) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
const aLastDotIndex = a.lastIndexOf('.');
|
||||
const aExt = a.substr(aLastDotIndex + 1);
|
||||
const aFile = a.substr(0, aLastDotIndex) || a;
|
||||
|
||||
const bLastDotIndex = b.lastIndexOf('.');
|
||||
const bExt = b.substr(bLastDotIndex + 1);
|
||||
const bFile = b.substr(0, bLastDotIndex) || b;
|
||||
|
||||
// Sort header files above others with the same base name.
|
||||
const headerExts = ['h', 'hxx', 'hpp'];
|
||||
if (aFile.length > 0 && aFile === bFile) {
|
||||
if (headerExts.includes(aExt) && headerExts.includes(bExt)) {
|
||||
return a.localeCompare(b);
|
||||
}
|
||||
if (headerExts.includes(aExt)) {
|
||||
return -1;
|
||||
}
|
||||
if (b === SpecialFilePath.COMMIT_MESSAGE) {
|
||||
if (headerExts.includes(bExt)) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return aFile.localeCompare(bFile) || a.localeCompare(b);
|
||||
}
|
||||
|
||||
// The merge list always comes next.
|
||||
if (a === SpecialFilePath.MERGE_LIST) {
|
||||
return -1;
|
||||
}
|
||||
if (b === SpecialFilePath.MERGE_LIST) {
|
||||
return 1;
|
||||
}
|
||||
export function shouldHideFile(file) {
|
||||
return file === SpecialFilePath.PATCHSET_LEVEL_COMMENTS;
|
||||
}
|
||||
|
||||
const aLastDotIndex = a.lastIndexOf('.');
|
||||
const aExt = a.substr(aLastDotIndex + 1);
|
||||
const aFile = a.substr(0, aLastDotIndex) || a;
|
||||
export function addUnmodifiedFiles(files, commentedPaths) {
|
||||
Object.keys(commentedPaths).forEach(commentedPath => {
|
||||
if (files.hasOwnProperty(commentedPath) ||
|
||||
shouldHideFile(commentedPath)) { return; }
|
||||
files[commentedPath] = {status: 'U'};
|
||||
});
|
||||
}
|
||||
|
||||
const bLastDotIndex = b.lastIndexOf('.');
|
||||
const bExt = b.substr(bLastDotIndex + 1);
|
||||
const bFile = b.substr(0, bLastDotIndex) || b;
|
||||
export function computeDisplayPath(path) {
|
||||
if (path === SpecialFilePath.COMMIT_MESSAGE) {
|
||||
return 'Commit message';
|
||||
} else if (path === SpecialFilePath.MERGE_LIST) {
|
||||
return 'Merge list';
|
||||
}
|
||||
return path;
|
||||
}
|
||||
|
||||
// Sort header files above others with the same base name.
|
||||
const headerExts = ['h', 'hxx', 'hpp'];
|
||||
if (aFile.length > 0 && aFile === bFile) {
|
||||
if (headerExts.includes(aExt) && headerExts.includes(bExt)) {
|
||||
return a.localeCompare(b);
|
||||
}
|
||||
if (headerExts.includes(aExt)) {
|
||||
return -1;
|
||||
}
|
||||
if (headerExts.includes(bExt)) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return aFile.localeCompare(bFile) || a.localeCompare(b);
|
||||
},
|
||||
export function isMagicPath(path) {
|
||||
return !!path &&
|
||||
(path === SpecialFilePath.COMMIT_MESSAGE || path ===
|
||||
SpecialFilePath.MERGE_LIST);
|
||||
}
|
||||
|
||||
shouldHideFile(file) {
|
||||
return file === SpecialFilePath.PATCHSET_LEVEL_COMMENTS;
|
||||
},
|
||||
export function computeTruncatedPath(path) {
|
||||
return truncatePath(
|
||||
computeDisplayPath(path));
|
||||
}
|
||||
|
||||
addUnmodifiedFiles(files, commentedPaths) {
|
||||
Object.keys(commentedPaths).forEach(commentedPath => {
|
||||
if (files.hasOwnProperty(commentedPath) ||
|
||||
this.shouldHideFile(commentedPath)) { return; }
|
||||
files[commentedPath] = {status: 'U'};
|
||||
});
|
||||
},
|
||||
/**
|
||||
* Truncates URLs to display filename only
|
||||
* Example
|
||||
* // returns '.../text.html'
|
||||
* util.truncatePath.('dir/text.html');
|
||||
* Example
|
||||
* // returns 'text.html'
|
||||
* util.truncatePath.('text.html');
|
||||
*
|
||||
* @param {string} path
|
||||
* @param {number=} opt_threshold
|
||||
* @return {string} Returns the truncated value of a URL.
|
||||
*/
|
||||
export function truncatePath(path, opt_threshold) {
|
||||
const threshold = opt_threshold || 1;
|
||||
const pathPieces = path.split('/');
|
||||
|
||||
computeDisplayPath(path) {
|
||||
if (path === SpecialFilePath.COMMIT_MESSAGE) {
|
||||
return 'Commit message';
|
||||
} else if (path === SpecialFilePath.MERGE_LIST) {
|
||||
return 'Merge list';
|
||||
}
|
||||
return path;
|
||||
},
|
||||
if (pathPieces.length <= threshold) { return path; }
|
||||
|
||||
isMagicPath(path) {
|
||||
return !!path &&
|
||||
(path === SpecialFilePath.COMMIT_MESSAGE || path ===
|
||||
SpecialFilePath.MERGE_LIST);
|
||||
},
|
||||
|
||||
computeTruncatedPath(path) {
|
||||
return PathListBehavior.truncatePath(
|
||||
PathListBehavior.computeDisplayPath(path));
|
||||
},
|
||||
|
||||
/**
|
||||
* Truncates URLs to display filename only
|
||||
* Example
|
||||
* // returns '.../text.html'
|
||||
* util.truncatePath.('dir/text.html');
|
||||
* Example
|
||||
* // returns 'text.html'
|
||||
* util.truncatePath.('text.html');
|
||||
*
|
||||
* @param {string} path
|
||||
* @param {number=} opt_threshold
|
||||
* @return {string} Returns the truncated value of a URL.
|
||||
*/
|
||||
truncatePath(path, opt_threshold) {
|
||||
const threshold = opt_threshold || 1;
|
||||
const pathPieces = path.split('/');
|
||||
|
||||
if (pathPieces.length <= threshold) { return path; }
|
||||
|
||||
const index = pathPieces.length - threshold;
|
||||
// Character is an ellipsis.
|
||||
return `\u2026/${pathPieces.slice(index).join('/')}`;
|
||||
},
|
||||
};
|
||||
|
||||
// TODO(dmfilippov) Remove the following lines with assignments
|
||||
// Plugins can use the behavior because it was accessible with
|
||||
// the global Gerrit... variable. To avoid breaking changes in plugins
|
||||
// temporary assign global variables.
|
||||
window.Gerrit = window.Gerrit || {};
|
||||
window.Gerrit.PathListBehavior = PathListBehavior;
|
||||
const index = pathPieces.length - threshold;
|
||||
// Character is an ellipsis.
|
||||
return `\u2026/${pathPieces.slice(index).join('/')}`;
|
||||
}
|
||||
|
||||
@@ -15,13 +15,17 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import '../../test/common-test-setup-karma.js';
|
||||
import {PathListBehavior} from './gr-path-list-behavior.js';
|
||||
import {SpecialFilePath} from '../../constants/constants.js';
|
||||
import '../test/common-test-setup-karma.js';
|
||||
import {SpecialFilePath} from '../constants/constants.js';
|
||||
import {
|
||||
addUnmodifiedFiles,
|
||||
computeDisplayPath,
|
||||
isMagicPath,
|
||||
specialFilePathCompare, truncatePath,
|
||||
} from './path-list-util.js';
|
||||
|
||||
suite('gr-path-list-behavior tests', () => {
|
||||
suite('path-list-utl tests', () => {
|
||||
test('special sort', () => {
|
||||
const sort = PathListBehavior.specialFilePathCompare;
|
||||
const testFiles = [
|
||||
'/a.h',
|
||||
'/MERGE_LIST',
|
||||
@@ -31,7 +35,7 @@ suite('gr-path-list-behavior tests', () => {
|
||||
'/mrPeanutbutter.py',
|
||||
];
|
||||
assert.deepEqual(
|
||||
testFiles.sort(sort),
|
||||
testFiles.sort(specialFilePathCompare),
|
||||
[
|
||||
'/COMMIT_MSG',
|
||||
'/MERGE_LIST',
|
||||
@@ -42,20 +46,71 @@ suite('gr-path-list-behavior tests', () => {
|
||||
]);
|
||||
});
|
||||
|
||||
test('special file path sorting', () => {
|
||||
assert.deepEqual(
|
||||
['.b', '/COMMIT_MSG', '.a', 'file'].sort(
|
||||
specialFilePathCompare),
|
||||
['/COMMIT_MSG', '.a', '.b', 'file']);
|
||||
|
||||
assert.deepEqual(
|
||||
['.b', '/COMMIT_MSG', 'foo/bar/baz.cc', 'foo/bar/baz.h'].sort(
|
||||
specialFilePathCompare),
|
||||
['/COMMIT_MSG', '.b', 'foo/bar/baz.h', 'foo/bar/baz.cc']);
|
||||
|
||||
assert.deepEqual(
|
||||
['.b', '/COMMIT_MSG', 'foo/bar/baz.cc', 'foo/bar/baz.hpp'].sort(
|
||||
specialFilePathCompare),
|
||||
['/COMMIT_MSG', '.b', 'foo/bar/baz.hpp', 'foo/bar/baz.cc']);
|
||||
|
||||
assert.deepEqual(
|
||||
['.b', '/COMMIT_MSG', 'foo/bar/baz.cc', 'foo/bar/baz.hxx'].sort(
|
||||
specialFilePathCompare),
|
||||
['/COMMIT_MSG', '.b', 'foo/bar/baz.hxx', 'foo/bar/baz.cc']);
|
||||
|
||||
assert.deepEqual(
|
||||
['foo/bar.h', 'foo/bar.hxx', 'foo/bar.hpp'].sort(
|
||||
specialFilePathCompare),
|
||||
['foo/bar.h', 'foo/bar.hpp', 'foo/bar.hxx']);
|
||||
|
||||
// Regression test for Issue 4448.
|
||||
assert.deepEqual(
|
||||
[
|
||||
'minidump/minidump_memory_writer.cc',
|
||||
'minidump/minidump_memory_writer.h',
|
||||
'minidump/minidump_thread_writer.cc',
|
||||
'minidump/minidump_thread_writer.h',
|
||||
].sort(specialFilePathCompare),
|
||||
[
|
||||
'minidump/minidump_memory_writer.h',
|
||||
'minidump/minidump_memory_writer.cc',
|
||||
'minidump/minidump_thread_writer.h',
|
||||
'minidump/minidump_thread_writer.cc',
|
||||
]);
|
||||
|
||||
// Regression test for Issue 4545.
|
||||
assert.deepEqual(
|
||||
[
|
||||
'task_test.go',
|
||||
'task.go',
|
||||
].sort(specialFilePathCompare),
|
||||
[
|
||||
'task.go',
|
||||
'task_test.go',
|
||||
]);
|
||||
});
|
||||
|
||||
test('file display name', () => {
|
||||
const name = PathListBehavior.computeDisplayPath;
|
||||
assert.equal(name('/foo/bar/baz'), '/foo/bar/baz');
|
||||
assert.equal(name('/foobarbaz'), '/foobarbaz');
|
||||
assert.equal(name('/COMMIT_MSG'), 'Commit message');
|
||||
assert.equal(name('/MERGE_LIST'), 'Merge list');
|
||||
assert.equal(computeDisplayPath('/foo/bar/baz'), '/foo/bar/baz');
|
||||
assert.equal(computeDisplayPath('/foobarbaz'), '/foobarbaz');
|
||||
assert.equal(computeDisplayPath('/COMMIT_MSG'), 'Commit message');
|
||||
assert.equal(computeDisplayPath('/MERGE_LIST'), 'Merge list');
|
||||
});
|
||||
|
||||
test('isMagicPath', () => {
|
||||
const isMagic = PathListBehavior.isMagicPath;
|
||||
assert.isFalse(isMagic(undefined));
|
||||
assert.isFalse(isMagic('/foo.cc'));
|
||||
assert.isTrue(isMagic('/COMMIT_MSG'));
|
||||
assert.isTrue(isMagic('/MERGE_LIST'));
|
||||
assert.isFalse(isMagicPath(undefined));
|
||||
assert.isFalse(isMagicPath('/foo.cc'));
|
||||
assert.isTrue(isMagicPath('/COMMIT_MSG'));
|
||||
assert.isTrue(isMagicPath('/MERGE_LIST'));
|
||||
});
|
||||
|
||||
test('patchset level comments are hidden', () => {
|
||||
@@ -65,7 +120,7 @@ suite('gr-path-list-behavior tests', () => {
|
||||
};
|
||||
|
||||
const files = {'file2.txt': {status: 'M'}};
|
||||
PathListBehavior.addUnmodifiedFiles(files, commentedPaths);
|
||||
addUnmodifiedFiles(files, commentedPaths);
|
||||
assert.equal(files['file1.txt'].status, 'U');
|
||||
assert.equal(files['file2.txt'].status, 'M');
|
||||
assert.isFalse(files.hasOwnProperty(
|
||||
@@ -73,7 +128,6 @@ suite('gr-path-list-behavior tests', () => {
|
||||
});
|
||||
|
||||
test('truncatePath with long path should add ellipsis', () => {
|
||||
const truncatePath = PathListBehavior.truncatePath;
|
||||
let path = 'level1/level2/level3/level4/file.js';
|
||||
let shortenedPath = truncatePath(path);
|
||||
// The expected path is truncated with an ellipsis.
|
||||
@@ -86,7 +140,6 @@ suite('gr-path-list-behavior tests', () => {
|
||||
});
|
||||
|
||||
test('truncatePath with opt_threshold', () => {
|
||||
const truncatePath = PathListBehavior.truncatePath;
|
||||
let path = 'level1/level2/level3/level4/file.js';
|
||||
let shortenedPath = truncatePath(path, 2);
|
||||
// The expected path is truncated with an ellipsis.
|
||||
@@ -99,7 +152,6 @@ suite('gr-path-list-behavior tests', () => {
|
||||
});
|
||||
|
||||
test('truncatePath with short path should not add ellipsis', () => {
|
||||
const truncatePath = PathListBehavior.truncatePath;
|
||||
const path = 'file.js';
|
||||
const expectedPath = 'file.js';
|
||||
const shortenedPath = truncatePath(path);
|
||||
|
||||
Reference in New Issue
Block a user