Path: blob/master/src/applications/diffusion/query/lowlevel/DiffusionLowLevelFilesizeQuery.php
12242 views
<?php12final class DiffusionLowLevelFilesizeQuery3extends DiffusionLowLevelQuery {45private $identifier;67public function withIdentifier($identifier) {8$this->identifier = $identifier;9return $this;10}1112protected function executeQuery() {13if (!strlen($this->identifier)) {14throw new PhutilInvalidStateException('withIdentifier');15}1617$type = $this->getRepository()->getVersionControlSystem();18switch ($type) {19case PhabricatorRepositoryType::REPOSITORY_TYPE_GIT:20$result = $this->loadGitFilesizes();21break;22default:23throw new Exception(pht('Unsupported repository type "%s"!', $type));24}2526return $result;27}2829private function loadGitFilesizes() {30$repository = $this->getRepository();31$identifier = $this->identifier;3233$paths_future = $repository->getLocalCommandFuture(34'diff-tree -z -r --no-commit-id %s --',35gitsprintf('%s', $identifier));3637// With "-z" we get "<fields>\0<filename>\0" for each line. Process the38// delimited text as "<fields>, <filename>" pairs.3940$path_lines = id(new LinesOfALargeExecFuture($paths_future))41->setDelimiter("\0");4243$paths = array();4445$path_pairs = new PhutilChunkedIterator($path_lines, 2);46foreach ($path_pairs as $path_pair) {47if (count($path_pair) != 2) {48throw new Exception(49pht(50'Unexpected number of output lines from "git diff-tree" when '.51'processing commit ("%s"): expected an even number of lines.',52$identifier));53}5455list($fields, $pathname) = array_values($path_pair);56$fields = explode(' ', $fields);5758// Fields are:59//60// :100644 100644 aaaa bbbb M61//62// [0] Old file mode.63// [1] New file mode.64// [2] Old object hash.65// [3] New object hash.66// [4] Change mode.6768$paths[] = array(69'path' => $pathname,70'newHash' => $fields[3],71);72}7374$path_sizes = array();7576if (!$paths) {77return $path_sizes;78}7980$check_paths = array();81foreach ($paths as $path) {82if ($path['newHash'] === DiffusionCommitHookEngine::EMPTY_HASH) {83$path_sizes[$path['path']] = 0;84continue;85}86$check_paths[$path['newHash']][] = $path['path'];87}8889if (!$check_paths) {90return $path_sizes;91}9293$future = $repository->getLocalCommandFuture(94'cat-file --batch-check=%s',95'%(objectsize)');9697$future->write(implode("\n", array_keys($check_paths)));9899$size_lines = id(new LinesOfALargeExecFuture($future))100->setDelimiter("\n");101foreach ($size_lines as $line) {102$object_size = (int)$line;103104$object_hash = head_key($check_paths);105$path_names = $check_paths[$object_hash];106unset($check_paths[$object_hash]);107108foreach ($path_names as $path_name) {109$path_sizes[$path_name] = $object_size;110}111}112113if ($check_paths) {114throw new Exception(115pht(116'Unexpected number of output lines from "git cat-file" when '.117'processing commit ("%s").',118$identifier));119}120121return $path_sizes;122}123124}125126127