148 lines
		
	
	
		
			4.5 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
			
		
		
	
	
			148 lines
		
	
	
		
			4.5 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
| import { diffViewerModes as viewerModes } from '~/ide/constants';
 | |
| import { changeInPercent, numberToHumanSize } from '~/lib/utils/number_utils';
 | |
| import { truncateSha } from '~/lib/utils/text_utility';
 | |
| import { uuids } from '~/lib/utils/uuids';
 | |
| 
 | |
| import {
 | |
|   DIFF_FILE_SYMLINK_MODE,
 | |
|   DIFF_FILE_DELETED_MODE,
 | |
|   DIFF_FILE_MANUAL_COLLAPSE,
 | |
|   DIFF_FILE_AUTOMATIC_COLLAPSE,
 | |
| } from '../constants';
 | |
| import { getDerivedMergeRequestInformation } from './merge_request';
 | |
| 
 | |
| function fileSymlinkInformation(file, fileList) {
 | |
|   const duplicates = fileList.filter((iteratedFile) => iteratedFile.file_hash === file.file_hash);
 | |
|   const includesSymlink = duplicates.some((iteratedFile) => {
 | |
|     return [iteratedFile.a_mode, iteratedFile.b_mode].includes(DIFF_FILE_SYMLINK_MODE);
 | |
|   });
 | |
|   const brokenSymlinkScenario = duplicates.length > 1 && includesSymlink;
 | |
| 
 | |
|   return (
 | |
|     brokenSymlinkScenario && {
 | |
|       replaced: file.b_mode === DIFF_FILE_DELETED_MODE,
 | |
|       wasSymbolic: file.a_mode === DIFF_FILE_SYMLINK_MODE,
 | |
|       isSymbolic: file.b_mode === DIFF_FILE_SYMLINK_MODE,
 | |
|       wasReal: ![DIFF_FILE_SYMLINK_MODE, DIFF_FILE_DELETED_MODE].includes(file.a_mode),
 | |
|       isReal: ![DIFF_FILE_SYMLINK_MODE, DIFF_FILE_DELETED_MODE].includes(file.b_mode),
 | |
|     }
 | |
|   );
 | |
| }
 | |
| 
 | |
| function collapsed(file) {
 | |
|   const viewer = file.viewer || {};
 | |
| 
 | |
|   return {
 | |
|     automaticallyCollapsed: viewer.automaticallyCollapsed || viewer.collapsed || false,
 | |
|     manuallyCollapsed: null,
 | |
|   };
 | |
| }
 | |
| 
 | |
| function identifier(file) {
 | |
|   const { userOrGroup, project, id } = getDerivedMergeRequestInformation({
 | |
|     endpoint: file.load_collapsed_diff_url,
 | |
|   });
 | |
| 
 | |
|   return uuids({
 | |
|     seeds: [userOrGroup, project, id, file.file_identifier_hash, file.blob?.id],
 | |
|   })[0];
 | |
| }
 | |
| 
 | |
| export const isNotDiffable = (file) => file?.viewer?.name === viewerModes.not_diffable;
 | |
| 
 | |
| export function prepareRawDiffFile({ file, allFiles, meta = false, index = -1 }) {
 | |
|   const additionalProperties = {
 | |
|     brokenSymlink: fileSymlinkInformation(file, allFiles),
 | |
|     viewer: {
 | |
|       ...file.viewer,
 | |
|       ...collapsed(file),
 | |
|     },
 | |
|   };
 | |
| 
 | |
|   // It's possible, but not confirmed, that `blob.id` isn't available sometimes
 | |
|   // See: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/49506#note_464692057
 | |
|   // We don't want duplicate IDs if that's the case, so we just don't assign an ID
 | |
|   if (!meta && file.blob?.id && file.load_collapsed_diff_url) {
 | |
|     additionalProperties.id = identifier(file);
 | |
|   }
 | |
| 
 | |
|   if (index >= 0 && Number(index) === index) {
 | |
|     additionalProperties.order = index;
 | |
|   }
 | |
| 
 | |
|   return Object.assign(file, additionalProperties);
 | |
| }
 | |
| 
 | |
| export function collapsedType(file) {
 | |
|   const isManual = typeof file.viewer?.manuallyCollapsed === 'boolean';
 | |
| 
 | |
|   return isManual ? DIFF_FILE_MANUAL_COLLAPSE : DIFF_FILE_AUTOMATIC_COLLAPSE;
 | |
| }
 | |
| 
 | |
| export function isCollapsed(file) {
 | |
|   const type = collapsedType(file);
 | |
|   const collapsedStates = {
 | |
|     [DIFF_FILE_AUTOMATIC_COLLAPSE]: file.viewer?.automaticallyCollapsed || false,
 | |
|     [DIFF_FILE_MANUAL_COLLAPSE]: file.viewer?.manuallyCollapsed,
 | |
|   };
 | |
| 
 | |
|   return collapsedStates[type];
 | |
| }
 | |
| 
 | |
| export function getShortShaFromFile(file) {
 | |
|   return file.content_sha ? truncateSha(String(file.content_sha)) : null;
 | |
| }
 | |
| 
 | |
| export function match({ fileA, fileB, mode = 'universal' } = {}) {
 | |
|   const matching = {
 | |
|     universal: (a, b) => (a?.id && b?.id ? a.id === b.id : false),
 | |
|     /*
 | |
|      * MR mode can be wildly incorrect if there is ever the possibility of files from multiple MRs
 | |
|      *  (e.g. a browser-local merge request/file cache).
 | |
|      * That's why the default here is "universal" mode: UUIDs can't conflict, but you can opt into
 | |
|      *  the dangerous one.
 | |
|      *
 | |
|      * For reference:
 | |
|      *    file_identifier_hash === sha1( `${filePath}-${Boolean(isNew)}-${Boolean(isDeleted)}-${Boolean(isRenamed)}` )
 | |
|      */
 | |
|     mr: (a, b) =>
 | |
|       a?.file_identifier_hash && b?.file_identifier_hash
 | |
|         ? a.file_identifier_hash === b.file_identifier_hash
 | |
|         : false,
 | |
|   };
 | |
| 
 | |
|   return (matching[mode] || (() => false))(fileA, fileB);
 | |
| }
 | |
| 
 | |
| export function stats(file) {
 | |
|   let valid = false;
 | |
|   let classes = '';
 | |
|   let sign = '';
 | |
|   let text = '';
 | |
|   let percent = 0;
 | |
|   let diff = 0;
 | |
| 
 | |
|   if (file) {
 | |
|     percent = changeInPercent(file.old_size, file.new_size);
 | |
|     diff = file.new_size - file.old_size;
 | |
|     sign = diff >= 0 ? '+' : '';
 | |
|     text = `${sign}${numberToHumanSize(diff)} (${sign}${percent}%)`;
 | |
|     valid = true;
 | |
| 
 | |
|     if (diff > 0) {
 | |
|       classes = 'gl-text-green-600';
 | |
|     } else if (diff < 0) {
 | |
|       classes = 'gl-text-red-500';
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   return {
 | |
|     changed: diff,
 | |
|     text,
 | |
|     percent,
 | |
|     classes,
 | |
|     sign,
 | |
|     valid,
 | |
|   };
 | |
| }
 |