From 4900c0e04f035326ca90f05f0c78ab19709cd543 Mon Sep 17 00:00:00 2001 From: eyedeekay Date: Sun, 20 Apr 2025 21:44:02 -0400 Subject: [PATCH] check in the script --- LICENSE | 2 +- README.md | 73 +++++++++++++++++++++++++++++++++++++++++++++- gitea/client.go | 67 ++++++++++-------------------------------- migration/users.go | 4 +-- 4 files changed, 90 insertions(+), 56 deletions(-) diff --git a/LICENSE b/LICENSE index 1cfba70..838491a 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2025 idk +Copyright (c) 2025 idk, go-i2p Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md index fa16b8f..585bf10 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,73 @@ # gitlab-to-gitea -A port of the old gitlab-to-gitea migration script from python to Go with feature improvements + +Go-based tool for migrating GitLab repositories, users, groups, issues and related data to Gitea instances. + +## Core Functionality + +- Migrates users, groups, and their relationships from GitLab to Gitea +- Transfers repositories with labels, milestones, issues, and comments +- Preserves user relationships (collaborators) and SSH keys +- Supports resumable migrations through state tracking +- Handles username normalization and entity mapping between platforms + +## Installation + +1. Ensure Go 1.24+ is installed +2. Clone the repository: + ```bash + git clone https://github.com/go-i2p/gitlab-to-gitea.git + cd gitlab-to-gitea + ``` +3. Install dependencies: + ```bash + go mod download + ``` +4. Build the executable: + ```bash + go build -o gitlab-to-gitea ./cmd/migrate/ + ``` + +## Configuration + +1. Copy the example environment file: + ```bash + cp _env.example .env + ``` +2. Edit `.env` with your GitLab and Gitea details: + ``` + GITLAB_URL=https://your-gitlab-instance.com + GITLAB_TOKEN=your-gitlab-token + GITEA_URL=https://your-gitea-instance.com + GITEA_TOKEN=your-gitea-token + ``` + +## Usage + +Execute the migration tool after configuration: + +```bash +./gitlab-to-gitea +``` + +The tool will: +1. Connect to both GitLab and Gitea instances +2. Migrate users and groups first +3. Migrate projects with all associated data +4. Track progress in `migration_state.json` (resumable if interrupted) + +## Key Dependencies + +- github.com/xanzy/go-gitlab: GitLab API client +- github.com/joho/godotenv: Environment variable handling +- github.com/go-sql-driver/mysql: Optional database connectivity for action import + +## Optional Features + +For commit action import to Gitea's activity timeline: +1. Configure database details in `.env` +2. Generate a commit log file +3. Use the database import functionality in the `gitea` package + +## License + +MIT License \ No newline at end of file diff --git a/gitea/client.go b/gitea/client.go index 07905ce..fc96e6d 100644 --- a/gitea/client.go +++ b/gitea/client.go @@ -10,8 +10,11 @@ import ( "io" "net/http" "net/url" + "regexp" "strings" "time" + + "github.com/go-i2p/gitlab-to-gitea/utils" ) // Client handles communication with the Gitea API @@ -27,66 +30,26 @@ type VersionResponse struct { } // FetchCSRFToken retrieves a CSRF token from Gitea -func (c *Client) FetchCSRFToken() error { - // Create a request to the Gitea login page to get a CSRF token - u, err := c.baseURL.Parse("/") +// I don't think it works. +func (c *Client) FetchCSRFToken() (string, error) { + resp, err := c.request("GET", "/user/login", nil, nil) if err != nil { - return fmt.Errorf("invalid URL: %w", err) - } - - // Use a normal HTTP client without our custom transport for this request - // to avoid circular dependency (we need the token for the transport) - httpClient := &http.Client{} - - req, err := http.NewRequest("GET", u.String(), nil) - if err != nil { - return fmt.Errorf("failed to create request: %w", err) - } - - resp, err := httpClient.Do(req) - if err != nil { - return fmt.Errorf("request failed: %w", err) + return "", fmt.Errorf("failed to fetch login page: %w", err) } defer resp.Body.Close() - // Extract CSRF token from Set-Cookie header - for _, cookie := range resp.Cookies() { - if cookie.Name == "_csrf" { - // Update the transport with the CSRF token - transport, ok := c.httpClient.Transport.(*CSRFTokenTransport) - if ok { - transport.CSRFToken = cookie.Value - return nil - } - return fmt.Errorf("transport is not a CSRFTokenTransport") - } - } - - // If we couldn't find a CSRF token, try to extract it from the response body - bodyBytes, err := io.ReadAll(resp.Body) + body, err := io.ReadAll(resp.Body) if err != nil { - return fmt.Errorf("failed to read response body: %w", err) + return "", fmt.Errorf("failed to read response body: %w", err) } - // Look for in the HTML - body := string(bodyBytes) - csrfMetaStart := strings.Index(body, ` 1 { + return string(matches[1]), nil } - return fmt.Errorf("could not find CSRF token in response") + return "", fmt.Errorf("could not find CSRF token in login page") } func NewClient(baseURL, token string) (*Client, error) { @@ -178,7 +141,7 @@ func (c *Client) request(method, path string, data, result interface{}) (*http.R } // Debug output to see what endpoint is being called - fmt.Printf("Making %s request to: %s%s\n", method, c.baseURL.String(), path) + utils.PrintInfo(fmt.Sprintf("Making %s request to: %s%s\n", method, c.baseURL.String(), path)) u, err := c.baseURL.Parse(path) if err != nil { diff --git a/migration/users.go b/migration/users.go index 8165d8e..4fc2a13 100644 --- a/migration/users.go +++ b/migration/users.go @@ -59,13 +59,13 @@ func (m *Manager) ImportUser(user *gitlab.User, notify bool) error { } // Debug what endpoint we're calling and with what method - fmt.Printf("Attempting to create user via: POST /admin/users\n") + utils.PrintInfo("Attempting to create user via: POST /admin/users\n") var result map[string]interface{} err := m.giteaClient.Post("/admin/users", userReq, &result) if err != nil { // Try the alternative user creation endpoint if the first one failed - fmt.Printf("First attempt failed, trying alternative endpoint\n") + utils.PrintInfo("First attempt failed, trying alternative endpoint\n") err = m.giteaClient.Post("/api/v1/admin/users", userReq, &result) if err != nil { return fmt.Errorf("failed to create user %s: %w", user.Username, err)