protected function executeQuery()
 {
     $drequest = $this->getRequest();
     $repository = $drequest->getRepository();
     $path = $drequest->getPath();
     $commit = $drequest->getCommit();
     $local_path = $repository->getDetail('local-path');
     if ($path == '') {
         // Fast path to improve the performance of the repository view; we know
         // the root is always a tree at any commit and always exists.
         $stdout = 'tree';
     } else {
         try {
             list($stdout) = execx("(cd %s && git cat-file -t %s:%s)", $local_path, $commit, $path);
         } catch (CommandException $e) {
             $stderr = $e->getStdErr();
             if (preg_match('/^fatal: Not a valid object name/', $stderr)) {
                 // Grab two logs, since the first one is when the object was deleted.
                 list($stdout) = execx('(cd %s && git log -n2 --format="%%H" %s -- %s)', $local_path, $commit, $path);
                 $stdout = trim($stdout);
                 if ($stdout) {
                     $commits = explode("\n", $stdout);
                     $this->reason = self::REASON_IS_DELETED;
                     $this->deletedAtCommit = idx($commits, 0);
                     $this->existedAtCommit = idx($commits, 1);
                     return array();
                 }
                 $this->reason = self::REASON_IS_NONEXISTENT;
                 return array();
             } else {
                 throw $e;
             }
         }
     }
     if (trim($stdout) == 'blob') {
         $this->reason = self::REASON_IS_FILE;
         return array();
     }
     if ($this->shouldOnlyTestValidity()) {
         return true;
     }
     list($stdout) = execx("(cd %s && git ls-tree -l %s:%s)", $local_path, $commit, $path);
     $results = array();
     foreach (explode("\n", rtrim($stdout)) as $line) {
         list($mode, $type, $hash, $size, $name) = preg_split('/\\s+/', $line);
         if ($type == 'tree') {
             $file_type = DifferentialChangeType::FILE_DIRECTORY;
         } else {
             $file_type = DifferentialChangeType::FILE_NORMAL;
         }
         $result = new DiffusionRepositoryPath();
         $result->setPath($name);
         $result->setHash($hash);
         $result->setFileType($file_type);
         $result->setFileSize($size);
         $results[] = $result;
     }
     return $results;
 }
 protected function getGitResult(ConduitAPIRequest $request)
 {
     $drequest = $this->getDiffusionRequest();
     $repository = $drequest->getRepository();
     $path = $request->getValue('path');
     $commit = $request->getValue('commit');
     $offset = (int) $request->getValue('offset');
     $limit = (int) $request->getValue('limit');
     $result = $this->getEmptyResultSet();
     if ($path == '') {
         // Fast path to improve the performance of the repository view; we know
         // the root is always a tree at any commit and always exists.
         $stdout = 'tree';
     } else {
         try {
             list($stdout) = $repository->execxLocalCommand('cat-file -t %s:%s', $commit, $path);
         } catch (CommandException $e) {
             $stderr = $e->getStdErr();
             if (preg_match('/^fatal: Not a valid object name/', $stderr)) {
                 // Grab two logs, since the first one is when the object was deleted.
                 list($stdout) = $repository->execxLocalCommand('log -n2 --format="%%H" %s -- %s', $commit, $path);
                 $stdout = trim($stdout);
                 if ($stdout) {
                     $commits = explode("\n", $stdout);
                     $result->setReasonForEmptyResultSet(DiffusionBrowseResultSet::REASON_IS_DELETED)->setDeletedAtCommit(idx($commits, 0))->setExistedAtCommit(idx($commits, 1));
                     return $result;
                 }
                 $result->setReasonForEmptyResultSet(DiffusionBrowseResultSet::REASON_IS_NONEXISTENT);
                 return $result;
             } else {
                 throw $e;
             }
         }
     }
     if (trim($stdout) == 'blob') {
         $result->setReasonForEmptyResultSet(DiffusionBrowseResultSet::REASON_IS_FILE);
         return $result;
     }
     $result->setIsValidResults(true);
     if ($this->shouldOnlyTestValidity($request)) {
         return $result;
     }
     list($stdout) = $repository->execxLocalCommand('ls-tree -z -l %s:%s', $commit, $path);
     $submodules = array();
     if (strlen($path)) {
         $prefix = rtrim($path, '/') . '/';
     } else {
         $prefix = '';
     }
     $count = 0;
     $results = array();
     $lines = empty($stdout) ? array() : explode("", rtrim($stdout));
     foreach ($lines as $line) {
         // NOTE: Limit to 5 components so we parse filenames with spaces in them
         // correctly.
         // NOTE: The output uses a mixture of tabs and one-or-more spaces to
         // delimit fields.
         $parts = preg_split('/\\s+/', $line, 5);
         if (count($parts) < 5) {
             throw new Exception(pht('Expected "<mode> <type> <hash> <size>\\t<name>", for ls-tree of ' . '"%s:%s", got: %s', $commit, $path, $line));
         }
         list($mode, $type, $hash, $size, $name) = $parts;
         $path_result = new DiffusionRepositoryPath();
         if ($type == 'tree') {
             $file_type = DifferentialChangeType::FILE_DIRECTORY;
         } else {
             if ($type == 'commit') {
                 $file_type = DifferentialChangeType::FILE_SUBMODULE;
                 $submodules[] = $path_result;
             } else {
                 $mode = intval($mode, 8);
                 if (($mode & 0120000) == 0120000) {
                     $file_type = DifferentialChangeType::FILE_SYMLINK;
                 } else {
                     $file_type = DifferentialChangeType::FILE_NORMAL;
                 }
             }
         }
         $path_result->setFullPath($prefix . $name);
         $path_result->setPath($name);
         $path_result->setHash($hash);
         $path_result->setFileType($file_type);
         $path_result->setFileSize($size);
         if ($count >= $offset) {
             $results[] = $path_result;
         }
         $count++;
         if ($limit && $count >= $offset + $limit) {
             break;
         }
     }
     // If we identified submodules, lookup the module info at this commit to
     // find their source URIs.
     if ($submodules) {
         // NOTE: We need to read the file out of git and write it to a temporary
         // location because "git config -f" doesn't accept a "commit:path"-style
         // argument.
         // NOTE: This file may not exist, e.g. because the commit author removed
         // it when they added the submodule. See T1448. If it's not present, just
         // show the submodule without enriching it. If ".gitmodules" was removed
         // it seems to partially break submodules, but the repository as a whole
         // continues to work fine and we've seen at least two cases of this in
         // the wild.
         list($err, $contents) = $repository->execLocalCommand('cat-file blob %s:.gitmodules', $commit);
         if (!$err) {
             $tmp = new TempFile();
             Filesystem::writeFile($tmp, $contents);
             list($module_info) = $repository->execxLocalCommand('config -l -f %s', $tmp);
             $dict = array();
             $lines = explode("\n", trim($module_info));
             foreach ($lines as $line) {
                 list($key, $value) = explode('=', $line, 2);
                 $parts = explode('.', $key);
                 $dict[$key] = $value;
             }
             foreach ($submodules as $path) {
                 $full_path = $path->getFullPath();
                 $key = 'submodule.' . $full_path . '.url';
                 if (isset($dict[$key])) {
                     $path->setExternalURI($dict[$key]);
                 }
             }
         }
     }
     return $result->setPaths($results);
 }
 protected function executeQuery()
 {
     $drequest = $this->getRequest();
     $repository = $drequest->getRepository();
     $path = $drequest->getPath();
     $commit = $drequest->getCommit();
     if ($path == '') {
         // Fast path to improve the performance of the repository view; we know
         // the root is always a tree at any commit and always exists.
         $stdout = 'tree';
     } else {
         try {
             list($stdout) = $repository->execxLocalCommand('cat-file -t %s:%s', $commit, $path);
         } catch (CommandException $e) {
             $stderr = $e->getStdErr();
             if (preg_match('/^fatal: Not a valid object name/', $stderr)) {
                 // Grab two logs, since the first one is when the object was deleted.
                 list($stdout) = $repository->execxLocalCommand('log -n2 --format="%%H" %s -- %s', $commit, $path);
                 $stdout = trim($stdout);
                 if ($stdout) {
                     $commits = explode("\n", $stdout);
                     $this->reason = self::REASON_IS_DELETED;
                     $this->deletedAtCommit = idx($commits, 0);
                     $this->existedAtCommit = idx($commits, 1);
                     return array();
                 }
                 $this->reason = self::REASON_IS_NONEXISTENT;
                 return array();
             } else {
                 throw $e;
             }
         }
     }
     if (trim($stdout) == 'blob') {
         $this->reason = self::REASON_IS_FILE;
         return array();
     }
     if ($this->shouldOnlyTestValidity()) {
         return true;
     }
     list($stdout) = $repository->execxLocalCommand('ls-tree -z -l %s:%s', $commit, $path);
     $submodules = array();
     $results = array();
     foreach (explode("", rtrim($stdout)) as $line) {
         // NOTE: Limit to 5 components so we parse filenames with spaces in them
         // correctly.
         list($mode, $type, $hash, $size, $name) = preg_split('/\\s+/', $line, 5);
         $result = new DiffusionRepositoryPath();
         if ($type == 'tree') {
             $file_type = DifferentialChangeType::FILE_DIRECTORY;
         } else {
             if ($type == 'commit') {
                 $file_type = DifferentialChangeType::FILE_SUBMODULE;
                 $submodules[] = $result;
             } else {
                 $mode = intval($mode, 8);
                 if (($mode & 0120000) == 0120000) {
                     $file_type = DifferentialChangeType::FILE_SYMLINK;
                 } else {
                     $file_type = DifferentialChangeType::FILE_NORMAL;
                 }
             }
         }
         $result->setFullPath($path . $name);
         $result->setPath($name);
         $result->setHash($hash);
         $result->setFileType($file_type);
         $result->setFileSize($size);
         $results[] = $result;
     }
     // If we identified submodules, lookup the module info at this commit to
     // find their source URIs.
     if ($submodules) {
         list($module_info) = $repository->execxLocalCommand('show %s:.gitmodules', $commit);
         $module_info = parse_ini_string($module_info, $process_sections = true, $scanner_mode = INI_SCANNER_RAW);
         foreach ($submodules as $path) {
             foreach ($module_info as $section) {
                 if (empty($section['path']) || empty($section['url'])) {
                     continue;
                 }
                 if ($section['path'] == $path->getFullPath()) {
                     $path->setExternalURI($section['url']);
                 }
             }
         }
     }
     return $results;
 }