| 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 |
3x
1x
1x
19x
1x
3x
1x
1x
8x
8x
28x
28x
27x
28x
9x
28x
28x
28x
28x
28x
1x
1x
28x
28x
3x
1x
1x
3x
1x
1x
1x
1x
1x
1x
1x
1x
1x
1x
1x
2x
2x
2x
6x
6x
6x
6x
6x
1x
| import * as path from 'path';
import { createSelector } from 'reselect';
import { IDiff } from 'app/interfaces';
import { FilesContainerSorts } from 'app/actions/ActionTypes';
import { getFilesContainerSort, getSearch, getDiff } from './stateVars';
import { hasSearch, matchesFileSearch, fileSearchRegex } from './search';
import { getFilteredCommits } from './commits';
const getObjectValues = function(obj) {
const values = [];
for (const key in obj) {
values.push(obj[key]);
}
return values;
};
// returns an array of
// {
// fileName: string,
// commits: ICommit[],
// linesAdded: number,
// linesDeleted: number
// }
export const getFilteredFiles = createSelector(
getFilteredCommits,
getFilesContainerSort,
getSearch,
(commits, filesContainerSort) => {
const commitsByFile = {};
for (const commit of commits) {
Iif (!commit.files) {
continue;
}
for (const file of commit.files) {
const thisFile = commitsByFile[file.name] || {
fileName: file.name,
authorNames: [],
commits: [],
linesAdded: 0,
linesDeleted: 0,
firstCommitOn: commit.authorDate,
lastCommitOn: commit.authorDate,
};
if (thisFile.authorNames.indexOf(commit.authorName) === -1) {
thisFile.authorNames.push(commit.authorName);
}
if (commit.authorDate < thisFile.firstCommitOn) {
thisFile.firstCommitOn = commit.authorDate;
}
Iif (commit.authorDate > thisFile.lastCommitOn) {
thisFile.lastCommitOn = commit.authorDate;
}
thisFile.linesAdded += file.linesAdded;
thisFile.linesDeleted += file.linesDeleted;
thisFile.commits.push(commit);
commitsByFile[file.name] = thisFile;
}
}
// files are filtered by virtual of getFilteredCommits
const filteredFiles = getObjectValues(commitsByFile);
return filteredFiles.sort((a, b) => {
switch (filesContainerSort) {
case FilesContainerSorts.LINES:
return (
b.linesAdded + b.linesDeleted - (a.linesAdded + a.linesDeleted)
);
case FilesContainerSorts.TIME:
return b.lastCommitOn - a.lastCommitOn;
case FilesContainerSorts.COMMITS:
return b.commits.length - a.commits.length;
}
return 0;
});
}
);
export const getFilteredFilesForFilesContainer = createSelector(
getFilteredFiles,
getSearch,
(files, search) => {
// if the user specifically searched for files on show those in files container
// otherwise all files in any commits with this file would also show up here
Iif (hasSearch(search) && search.match(fileSearchRegex)) {
return files.filter(file => {
return matchesFileSearch(file.fileName, search);
});
}
return files;
}
);
export const getDirectoryDiff = createSelector(
getDiff,
(diff: IDiff | null) => {
Iif (!diff || !diff.isDirectory) {
return null;
}
const leftTree = {};
const rightTree = {};
Iif (!diff.modifiedFiles) {
return {};
}
let index = 0;
diff.modifiedFiles.forEach(file => {
let trees = [];
switch (file.status) {
case 'added':
trees = [rightTree];
break;
case 'deleted':
trees = [leftTree];
break;
case 'modified':
trees = [leftTree, rightTree];
break;
}
for (const tree of trees) {
let currentNode = tree;
const parsedPaths = file.path.split(path.sep);
parsedPaths.forEach((pathPart, pathPartIndex) => {
let nodeForPart = currentNode[pathPart];
Eif (!nodeForPart) {
nodeForPart = currentNode[pathPart] = {
index,
status: file.status,
delta: file.delta,
fullPath: parsedPaths.slice(0, pathPartIndex + 1).join(path.sep),
nodes: {},
};
index += 1;
} else {
nodeForPart.status =
file.status === 'modified' ? 'modified' : nodeForPart.status;
nodeForPart.delta = nodeForPart.delta + file.delta;
}
currentNode = nodeForPart.nodes;
});
}
});
return {
leftTree,
rightTree,
};
}
);
|