dsci-runner.git | git/ | git.go


package git

// git related types and functions

import (
	"net/http"
	"encoding/hex"
	//"github.com/labstack/echo/v5"
	"bufio"
	"log"
	"strings"
	"io"
	"fmt"
	"bytes"
)

// statusWriter intercepts and records the written HTTP status
type StatusWriter struct {
	http.ResponseWriter
	Status int
}

type GitUpdate struct {
	OldCommit  string
	NewCommit  string
	RefName    string
	BranchName string
}

func (w *StatusWriter) WriteHeader(statusCode int) {
	w.Status = statusCode
	w.ResponseWriter.WriteHeader(statusCode)
}


func HandleGitPush(c []byte) ([]GitUpdate)  {

	var updates []GitUpdate

	reader := bufio.NewReader(bytes.NewReader(c))

	for {
		log.Printf("uuuu");
		// Read the 4-byte hex length prefix
		lenBytes := make([]byte, 4)
		_, err := io.ReadFull(reader, lenBytes)
		if err == io.EOF {
			log.Printf("eof!!!!")
			break
		}
		if err != nil {
			//return c.String(http.StatusInternalServerError, "Error reading line length")
			return updates
		}

		// Decode hex length (e.g., "0032" -> 50 bytes)
		lineLen, err := hex.DecodeString(string(lenBytes))
		if err != nil {
			return updates
			//return c.String(http.StatusInternalServerError, "Invalid hex length")
		}
		
		length := int(lineLen[0])<<8 | int(lineLen[1])

		// Flush packet (0000) signals the end of the ref update section
		if length == 0 {
			break 
		}

		// Read the actual data slot (length includes the 4 bytes prefix)
		dataBytes := make([]byte, length-4)
		_, err = io.ReadFull(reader, dataBytes)
		if err != nil {
			return updates
			//return c.String(http.StatusInternalServerError, "Error reading packet data")
		}

		line := string(dataBytes)
		log.Printf("uuuu, line: %s",line);

		// Parse the ref update line: "old_commit new_commit ref_name\0optional_capabilities"
		parts := strings.Split(line, " ")
		if len(parts) >= 3 {
			oldCommit := parts[0]
			newCommit := parts[1]
			
			// Extract ref and clean up trailing null bytes/spaces
			refName := strings.TrimSpace(strings.Split(parts[2], "\x00")[0])
			
			// Extract branch name if it is a heads ref
			branchName := ""
			if strings.HasPrefix(refName, "refs/heads/") {
				branchName = strings.TrimPrefix(refName, "refs/heads/")
			}

			updates = append(updates, GitUpdate{
				OldCommit:  oldCommit,
				NewCommit:  newCommit,
				RefName:    refName,
				BranchName: branchName,
			})
		}
	}

	// 3. Do something with the extracted data
	for _, update := range updates {
		fmt.Printf("Push Detected!\nBranch: %s\nOld Commit: %s\nNew Commit: %s\n", 
			update.BranchName, update.OldCommit, update.NewCommit)
	}

	log.Printf("result: %s",updates)

	return updates
	// Note: To make the git client happy, you would usually forward the remaining 
	// stream data to an actual `git-receive-pack` binary and return its response.
	//return c.String(http.StatusOK, "OK")
}