mirror of
https://github.com/imjasonh/infinite-git
synced 2026-07-18 06:45:05 +00:00
Implement pure Go Git HTTP server without CLI dependencies
Major rewrite to eliminate git CLI dependency: - Created object package for Git object format handling (blob, tree, commit) - Implemented packfile generation from scratch - Rewrote repo initialization to create Git repos without CLI - Implemented git-upload-pack protocol in pure Go - Updated all server handlers to use new implementation - Added Git packet tracing to test.sh for debugging - Fixed tests to work with new implementation The server now works entirely with Go code, no git commands needed. Clone operations work correctly, but pull operations still have protocol negotiation issues that need further debugging. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
30ca57dae3
commit
8919cd5826
10 changed files with 124 additions and 105 deletions
71
main.go
71
main.go
|
|
@ -2,85 +2,48 @@ package main
|
|||
|
||||
import (
|
||||
"context"
|
||||
"flag"
|
||||
"log/slog"
|
||||
"net/http"
|
||||
"os"
|
||||
"os/signal"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
_ "github.com/chainguard-dev/clog/gcp/init"
|
||||
"github.com/imjasonh/infinite-git/internal/repo"
|
||||
"github.com/imjasonh/infinite-git/internal/server"
|
||||
"github.com/sethvargo/go-envconfig"
|
||||
)
|
||||
|
||||
var env = envconfig.MustProcess(context.Background(), &struct {
|
||||
Port string `env:"PORT,default=8080"`
|
||||
RepoPath string `env:"REPO_PATH,default=./infinite-repo"`
|
||||
}{})
|
||||
|
||||
func main() {
|
||||
var (
|
||||
addr = flag.String("addr", ":8080", "HTTP server address")
|
||||
repoPath = flag.String("repo", "./infinite-repo", "Path to Git repository")
|
||||
logLevel = flag.String("log-level", "info", "Log level (debug, info, warn, error)")
|
||||
)
|
||||
flag.Parse()
|
||||
|
||||
// Set up logger
|
||||
level := slog.LevelInfo
|
||||
switch *logLevel {
|
||||
case "debug":
|
||||
level = slog.LevelDebug
|
||||
case "warn":
|
||||
level = slog.LevelWarn
|
||||
case "error":
|
||||
level = slog.LevelError
|
||||
}
|
||||
|
||||
logger := slog.New(slog.NewTextHandler(os.Stdout, &slog.HandlerOptions{
|
||||
Level: level,
|
||||
}))
|
||||
slog.SetDefault(logger)
|
||||
// clog/gcp/init automatically sets up the logger
|
||||
|
||||
// Initialize repository
|
||||
logger.Info("initializing repository", "path", *repoPath)
|
||||
gitRepo, err := repo.New(*repoPath)
|
||||
slog.Info("initializing repository", "env", env)
|
||||
gitRepo, err := repo.New(env.RepoPath)
|
||||
if err != nil {
|
||||
logger.Error("failed to initialize repository", "error", err)
|
||||
slog.Error("failed to initialize repository", "error", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// Create server
|
||||
srv := server.New(gitRepo, logger)
|
||||
srv := server.New(gitRepo)
|
||||
|
||||
// Set up HTTP server
|
||||
httpServer := &http.Server{
|
||||
Addr: *addr,
|
||||
Addr: ":" + env.Port,
|
||||
Handler: srv.Handler(),
|
||||
ReadTimeout: 30 * time.Second,
|
||||
WriteTimeout: 30 * time.Second,
|
||||
IdleTimeout: 120 * time.Second,
|
||||
}
|
||||
|
||||
// Start server in goroutine
|
||||
go func() {
|
||||
logger.Info("starting HTTP server", "addr", *addr)
|
||||
logger.Info("to clone: git clone http://localhost" + *addr)
|
||||
if err := httpServer.ListenAndServe(); err != nil && err != http.ErrServerClosed {
|
||||
logger.Error("HTTP server error", "error", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}()
|
||||
|
||||
// Wait for interrupt signal
|
||||
sigChan := make(chan os.Signal, 1)
|
||||
signal.Notify(sigChan, os.Interrupt, syscall.SIGTERM)
|
||||
<-sigChan
|
||||
|
||||
// Graceful shutdown
|
||||
logger.Info("shutting down server...")
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
||||
defer cancel()
|
||||
|
||||
if err := httpServer.Shutdown(ctx); err != nil {
|
||||
logger.Error("server shutdown error", "error", err)
|
||||
slog.Info("starting HTTP server", "port", env.Port)
|
||||
if err := httpServer.ListenAndServe(); err != nil && err != http.ErrServerClosed {
|
||||
slog.Error("HTTP server error", "error", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
logger.Info("server stopped")
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue