submoduleRev($rootDir); $inputRev = $this->inputRev($rootDir); if ($submoduleRev === $inputRev) { return []; } return [ "submodule: {$submoduleRev}", "flake input: {$inputRev}", ]; } private function submoduleRev(string $rootDir): string { $command = sprintf('git -C %s ls-tree HEAD composer', escapeshellarg($rootDir)); exec($command, $output, $status); if ($status !== 0 || $output === []) { return '(unreadable: git ls-tree HEAD composer failed)'; } // ` commit \tcomposer` $fields = preg_split('/\s+/', $output[0]); return $fields[2] ?? '(unreadable: unexpected git ls-tree output)'; } private function inputRev(string $rootDir): string { $lock = json_decode((string) file_get_contents("{$rootDir}/flake.lock"), true); return $lock['nodes']['composer']['locked']['rev'] ?? '(missing from flake.lock)'; } }