@recaptime-dev's working patches + fork for Phorge, a community fork of Phabricator. (Upstream dev and stable branches are at upstream/main and upstream/stable respectively.) hq.recaptime.dev/wiki/Phorge
phorge phabricator
at recaptime-dev/main 125 lines 3.2 kB view raw
1<?php 2 3final 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}