| | |
| | public function render() { |
| | + error_log( "=== ClonePage render called ===" ); |
| | + error_log( "subPath: " . $this->subPath ); |
| | + error_log( "REQUEST_METHOD: " . $_SERVER['REQUEST_METHOD'] ); |
| | + |
| | if( $this->subPath === '' ) { |
| | + error_log( "Empty subPath - redirecting browser" ); |
| | $this->redirectBrowser(); |
| | return; |
| | } |
| | |
| | if( str_ends_with( $this->subPath, 'info/refs' ) ) { |
| | + error_log( "Handling info/refs" ); |
| | $this->renderInfoRefs(); |
| | return; |
| | } |
| | |
| | if( str_ends_with( $this->subPath, 'git-upload-pack' ) ) { |
| | + error_log( "Handling git-upload-pack" ); |
| | $this->handleUploadPack(); |
| | return; |
| | } |
| | |
| | if( str_ends_with( $this->subPath, 'git-receive-pack' ) ) { |
| | + error_log( "Handling git-receive-pack - forbidden" ); |
| | http_response_code( 403 ); |
| | echo "Read-only repository."; |
| | exit; |
| | } |
| | |
| | if( $this->subPath === 'HEAD' ) { |
| | + error_log( "Serving HEAD file" ); |
| | $this->serve( 'HEAD', 'text/plain' ); |
| | return; |
| | } |
| | |
| | if( strpos( $this->subPath, 'objects/' ) === 0 ) { |
| | + error_log( "Serving object: " . $this->subPath ); |
| | $this->serve( $this->subPath, 'application/x-git-object' ); |
| | return; |
| | } |
| | |
| | + error_log( "Path not found: " . $this->subPath ); |
| | http_response_code( 404 ); |
| | echo "Not Found"; |
 |
| | private function renderInfoRefs(): void { |
| | $service = $_GET['service'] ?? ''; |
| | + error_log( "renderInfoRefs - service: " . $service ); |
| | |
| | if( $service === 'git-upload-pack' ) { |
| | + error_log( "Smart protocol - git-upload-pack" ); |
| | header( 'Content-Type: application/x-git-upload-pack-advertisement' ); |
| | header( 'Cache-Control: no-cache' ); |
| | |
| | $this->packetWrite( "# service=git-upload-pack\n" ); |
| | $this->packetFlush(); |
| | |
| | $refs = []; |
| | $this->git->eachRef( function( $ref, $sha ) use ( &$refs ) { |
| | $refs[] = ['ref' => $ref, 'sha' => $sha]; |
| | + error_log( "Ref: $ref => $sha" ); |
| | } ); |
| | |
| | $caps = "multi_ack thin-pack side-band side-band-64k ofs-delta shallow no-progress include-tag"; |
| | |
| | if( !empty( $refs ) ) { |
| | + error_log( "Sending " . count( $refs ) . " refs with capabilities" ); |
| | $this->packetWrite( $refs[0]['sha'] . " " . $refs[0]['ref'] . "\0" . $caps . "\n" ); |
| | |
| | for( $i = 1; $i < count( $refs ); $i++ ) { |
| | $this->packetWrite( $refs[$i]['sha'] . " " . $refs[$i]['ref'] . "\n" ); |
| | } |
| | } else { |
| | + error_log( "Empty repo - sending capabilities^{}" ); |
| | $this->packetWrite( "0000000000000000000000000000000000000000 capabilities^{}\0" . $caps . "\n" ); |
| | } |
| | |
| | $this->packetFlush(); |
| | + error_log( "=== Info refs completed ===" ); |
| | exit; |
| | } |
| | |
| | + error_log( "Dumb protocol - plain text refs" ); |
| | header( 'Content-Type: text/plain' ); |
| | if( $this->git->streamRaw( 'info/refs' ) ) { |
 |
| | |
| | private function handleUploadPack(): void { |
| | + error_log( "=== handleUploadPack called ===" ); |
| | + error_log( "REQUEST_METHOD: " . $_SERVER['REQUEST_METHOD'] ); |
| | + error_log( "REQUEST_URI: " . $_SERVER['REQUEST_URI'] ); |
| | + |
| | header( 'Content-Type: application/x-git-upload-pack-result' ); |
| | header( 'Cache-Control: no-cache' ); |
| | |
| | $input = file_get_contents( 'php://input' ); |
| | + error_log( "Input length: " . strlen( $input ) ); |
| | + |
| | $wants = []; |
| | $haves = []; |
 |
| | $parts = explode( ' ', $line ); |
| | $wants[] = $parts[1]; |
| | + error_log( "WANT: " . $parts[1] ); |
| | } elseif( strpos( $line, 'have ' ) === 0 ) { |
| | $parts = explode( ' ', $line ); |
| | $haves[] = $parts[1]; |
| | + error_log( "HAVE: " . $parts[1] ); |
| | } elseif( $line === 'done' ) { |
| | + error_log( "DONE received" ); |
| | break; |
| | } |
| | } |
| | + |
| | + error_log( "Total wants: " . count( $wants ) ); |
| | + error_log( "Total haves: " . count( $haves ) ); |
| | |
| | if( empty( $wants ) ) { |
| | + error_log( "ERROR: No wants received!" ); |
| | $this->packetFlush(); |
| | exit; |
| | } |
| | |
| | $this->packetWrite( "NAK\n" ); |
| | |
| | - $objects = $this->git->collectObjects( $wants, $haves ); |
| | - $packData = $this->git->generatePackfile( $objects ); |
| | + try { |
| | + $objects = $this->git->collectObjects( $wants, $haves ); |
| | + error_log( "Collected objects: " . count( $objects ) ); |
| | |
| | - $this->sendSidebandData( 1, $packData ); |
| | - $this->packetFlush(); |
| | + $packData = $this->git->generatePackfile( $objects ); |
| | + error_log( "Generated packfile size: " . strlen( $packData ) ); |
| | + |
| | + $this->sendSidebandData( 1, $packData ); |
| | + $this->packetFlush(); |
| | + |
| | + error_log( "=== Upload pack completed successfully ===" ); |
| | + } catch( Exception $e ) { |
| | + error_log( "ERROR in handleUploadPack: " . $e->getMessage() ); |
| | + error_log( "Stack trace: " . $e->getTraceAsString() ); |
| | + } |
| | |
| | exit; |