Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/phabricator
Path: blob/master/src/applications/diffusion/query/lowlevel/DiffusionLowLevelFilesizeQuery.php
12242 views
1
<?php
2
3
final class DiffusionLowLevelFilesizeQuery
4
extends DiffusionLowLevelQuery {
5
6
private $identifier;
7
8
public function withIdentifier($identifier) {
9
$this->identifier = $identifier;
10
return $this;
11
}
12
13
protected function executeQuery() {
14
if (!strlen($this->identifier)) {
15
throw new PhutilInvalidStateException('withIdentifier');
16
}
17
18
$type = $this->getRepository()->getVersionControlSystem();
19
switch ($type) {
20
case PhabricatorRepositoryType::REPOSITORY_TYPE_GIT:
21
$result = $this->loadGitFilesizes();
22
break;
23
default:
24
throw new Exception(pht('Unsupported repository type "%s"!', $type));
25
}
26
27
return $result;
28
}
29
30
private function loadGitFilesizes() {
31
$repository = $this->getRepository();
32
$identifier = $this->identifier;
33
34
$paths_future = $repository->getLocalCommandFuture(
35
'diff-tree -z -r --no-commit-id %s --',
36
gitsprintf('%s', $identifier));
37
38
// With "-z" we get "<fields>\0<filename>\0" for each line. Process the
39
// delimited text as "<fields>, <filename>" pairs.
40
41
$path_lines = id(new LinesOfALargeExecFuture($paths_future))
42
->setDelimiter("\0");
43
44
$paths = array();
45
46
$path_pairs = new PhutilChunkedIterator($path_lines, 2);
47
foreach ($path_pairs as $path_pair) {
48
if (count($path_pair) != 2) {
49
throw new Exception(
50
pht(
51
'Unexpected number of output lines from "git diff-tree" when '.
52
'processing commit ("%s"): expected an even number of lines.',
53
$identifier));
54
}
55
56
list($fields, $pathname) = array_values($path_pair);
57
$fields = explode(' ', $fields);
58
59
// Fields are:
60
//
61
// :100644 100644 aaaa bbbb M
62
//
63
// [0] Old file mode.
64
// [1] New file mode.
65
// [2] Old object hash.
66
// [3] New object hash.
67
// [4] Change mode.
68
69
$paths[] = array(
70
'path' => $pathname,
71
'newHash' => $fields[3],
72
);
73
}
74
75
$path_sizes = array();
76
77
if (!$paths) {
78
return $path_sizes;
79
}
80
81
$check_paths = array();
82
foreach ($paths as $path) {
83
if ($path['newHash'] === DiffusionCommitHookEngine::EMPTY_HASH) {
84
$path_sizes[$path['path']] = 0;
85
continue;
86
}
87
$check_paths[$path['newHash']][] = $path['path'];
88
}
89
90
if (!$check_paths) {
91
return $path_sizes;
92
}
93
94
$future = $repository->getLocalCommandFuture(
95
'cat-file --batch-check=%s',
96
'%(objectsize)');
97
98
$future->write(implode("\n", array_keys($check_paths)));
99
100
$size_lines = id(new LinesOfALargeExecFuture($future))
101
->setDelimiter("\n");
102
foreach ($size_lines as $line) {
103
$object_size = (int)$line;
104
105
$object_hash = head_key($check_paths);
106
$path_names = $check_paths[$object_hash];
107
unset($check_paths[$object_hash]);
108
109
foreach ($path_names as $path_name) {
110
$path_sizes[$path_name] = $object_size;
111
}
112
}
113
114
if ($check_paths) {
115
throw new Exception(
116
pht(
117
'Unexpected number of output lines from "git cat-file" when '.
118
'processing commit ("%s").',
119
$identifier));
120
}
121
122
return $path_sizes;
123
}
124
125
}
126
127