Files
gitlab-to-gitea/migration/groups.go
2025-04-20 21:18:53 -04:00

148 lines
4.4 KiB
Go

// groups.go
// Package migration handles the migration of data from GitLab to Gitea
package migration
import (
"fmt"
"github.com/xanzy/go-gitlab"
"github.com/go-i2p/gitlab-to-gitea/utils"
)
// organizationCreateRequest represents the data needed to create an organization in Gitea
type organizationCreateRequest struct {
Description string `json:"description"`
FullName string `json:"full_name"`
Location string `json:"location"`
Username string `json:"username"`
Website string `json:"website"`
}
// ImportGroup imports a single GitLab group to Gitea as an organization
func (m *Manager) ImportGroup(group *gitlab.Group) error {
cleanName := utils.CleanName(group.Name)
utils.PrintInfo(fmt.Sprintf("Importing group %s...", cleanName))
// Check if organization already exists
if exists, err := m.organizationExists(cleanName); err != nil {
return fmt.Errorf("failed to check if organization exists: %w", err)
} else if exists {
utils.PrintWarning(fmt.Sprintf("Group %s already exists in Gitea, skipping!", cleanName))
return nil
}
// Get group members
members, err := m.gitlabClient.GetGroupMembers(group.ID)
if err != nil {
utils.PrintWarning(fmt.Sprintf("Error fetching members for group %s: %v", group.Name, err))
members = []*gitlab.GroupMember{}
}
utils.PrintInfo(fmt.Sprintf("Found %d GitLab members for group %s", len(members), cleanName))
// Create organization request
orgReq := organizationCreateRequest{
Description: group.Description,
FullName: group.FullName,
Location: "",
Username: cleanName,
Website: "",
}
// Call Gitea API to create organization
var result map[string]interface{}
err = m.giteaClient.Post("/orgs", orgReq, &result)
if err != nil {
return fmt.Errorf("failed to create organization %s: %w", cleanName, err)
}
utils.PrintInfo(fmt.Sprintf("Group %s imported!", cleanName))
// Import group members
if err := m.importGroupMembers(members, cleanName); err != nil {
utils.PrintWarning(fmt.Sprintf("Error importing members for group %s: %v", cleanName, err))
}
return nil
}
// importGroupMembers imports group members to the first team in an organization
func (m *Manager) importGroupMembers(members []*gitlab.GroupMember, orgName string) error {
// Get existing teams
var teams []map[string]interface{}
err := m.giteaClient.Get(fmt.Sprintf("/orgs/%s/teams", orgName), &teams)
if err != nil {
return fmt.Errorf("failed to get teams for organization %s: %w", orgName, err)
}
if len(teams) == 0 {
return fmt.Errorf("no teams found for organization %s", orgName)
}
firstTeam := teams[0]
teamID := int(firstTeam["id"].(float64))
teamName := firstTeam["name"].(string)
utils.PrintInfo(fmt.Sprintf("Organization teams fetched, importing users to first team: %s", teamName))
// Add members to the team
for _, member := range members {
cleanUsername := utils.NormalizeUsername(member.Username)
exists, err := m.memberExists(cleanUsername, teamID)
if err != nil {
utils.PrintWarning(fmt.Sprintf("Error checking if member %s exists: %v", cleanUsername, err))
continue
}
if exists {
utils.PrintWarning(fmt.Sprintf("Member %s already exists for team %s, skipping!", member.Username, teamName))
continue
}
// Add member to team
err = m.giteaClient.Put(fmt.Sprintf("/teams/%d/members/%s", teamID, cleanUsername), nil, nil)
if err != nil {
utils.PrintError(fmt.Sprintf("Failed to add member %s to team %s: %v", member.Username, teamName, err))
continue
}
utils.PrintInfo(fmt.Sprintf("Member %s added to team %s!", member.Username, teamName))
}
return nil
}
// organizationExists checks if an organization exists in Gitea
func (m *Manager) organizationExists(orgName string) (bool, error) {
var org map[string]interface{}
err := m.giteaClient.Get("/orgs/"+orgName, &org)
if err != nil {
if isNotFoundError(err) {
return false, nil
}
return false, fmt.Errorf("error checking if organization exists: %w", err)
}
return true, nil
}
// memberExists checks if a user is a member of a team
func (m *Manager) memberExists(username string, teamID int) (bool, error) {
var members []map[string]interface{}
err := m.giteaClient.Get(fmt.Sprintf("/teams/%d/members", teamID), &members)
if err != nil {
return false, fmt.Errorf("failed to get team members: %w", err)
}
for _, member := range members {
if member["username"].(string) == username {
return true, nil
}
}
return false, nil
}