Welcome to mirror list, hosted at ThFree Co, Russian Federation.

diff_file.js « utils « diffs « javascripts « assets « app - gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: 98e1c1cc8493d6429cea7aec253557e6ae33aa11 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
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 { namespace, project, id } = getDerivedMergeRequestInformation({
    endpoint: file.load_collapsed_diff_url,
  });

  return uuids({
    seeds: [namespace, 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),
    hasCommentForm: false,
    discussions: file.discussions || [],
    drafts: [],
    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,
  };
}