diff --git a/modules/structs/repo.go b/modules/structs/repo.go
index 3974c4db3a..0e4081da8e 100644
--- a/modules/structs/repo.go
+++ b/modules/structs/repo.go
@@ -287,6 +287,7 @@ const (
OneDevService // 6 onedev service
GitBucketService // 7 gitbucket service
CodebaseService // 8 codebase service
+ ForgejoService // 9 forgejo service
)
// Name represents the service type's name
@@ -312,6 +313,8 @@ func (gt GitServiceType) Title() string {
return "GitBucket"
case CodebaseService:
return "Codebase"
+ case ForgejoService:
+ return "Forgejo"
case PlainGitService:
return "Git"
}
@@ -353,7 +356,7 @@ type MigrateRepoOptions struct {
// TokenAuth represents whether a service type supports token-based auth
func (gt GitServiceType) TokenAuth() bool {
switch gt {
- case GithubService, GiteaService, GitlabService:
+ case GithubService, GiteaService, GitlabService, ForgejoService:
return true
}
return false
@@ -364,6 +367,7 @@ func (gt GitServiceType) TokenAuth() bool {
var SupportedFullGitService = []GitServiceType{
GithubService,
GitlabService,
+ ForgejoService,
GiteaService,
GogsService,
OneDevService,
diff --git a/options/locale/locale_en-US.ini b/options/locale/locale_en-US.ini
index a7a7a4f4c5..0ffa775912 100644
--- a/options/locale/locale_en-US.ini
+++ b/options/locale/locale_en-US.ini
@@ -1091,6 +1091,7 @@ migrate.migrating_failed_no_addr = Migration failed.
migrate.github.description = Migrate data from github.com or other GitHub instances.
migrate.git.description = Migrate a repository only from any Git service.
migrate.gitlab.description = Migrate data from gitlab.com or other GitLab instances.
+migrate.forgejo.description = Migrate data from codeberg.org or other Forgejo instances.
migrate.gitea.description = Migrate data from gitea.com or other Gitea instances.
migrate.gogs.description = Migrate data from notabug.org or other Gogs instances.
migrate.onedev.description = Migrate data from code.onedev.io or other OneDev instances.
diff --git a/public/assets/img/svg/gitea-forgejo.svg b/public/assets/img/svg/gitea-forgejo.svg
new file mode 100644
index 0000000000..ef617c00f3
--- /dev/null
+++ b/public/assets/img/svg/gitea-forgejo.svg
@@ -0,0 +1,9 @@
+
diff --git a/services/convert/utils.go b/services/convert/utils.go
index cdce60831c..fe35fd2dac 100644
--- a/services/convert/utils.go
+++ b/services/convert/utils.go
@@ -36,6 +36,8 @@ func ToGitServiceType(value string) structs.GitServiceType {
return structs.OneDevService
case "gitbucket":
return structs.GitBucketService
+ case "forgejo":
+ return structs.ForgejoService
default:
return structs.PlainGitService
}
diff --git a/services/convert/utils_test.go b/services/convert/utils_test.go
index 1ac03a3097..b464d8bb68 100644
--- a/services/convert/utils_test.go
+++ b/services/convert/utils_test.go
@@ -28,6 +28,8 @@ func TestToGitServiceType(t *testing.T) {
typ: "gitlab", enum: 4,
}, {
typ: "gogs", enum: 5,
+ }, {
+ typ: "forgejo", enum: 9,
}, {
typ: "trash", enum: 1,
}}
diff --git a/templates/repo/migrate/forgejo.tmpl b/templates/repo/migrate/forgejo.tmpl
new file mode 100644
index 0000000000..3caadbee15
--- /dev/null
+++ b/templates/repo/migrate/forgejo.tmpl
@@ -0,0 +1 @@
+{{template "repo/migrate/gitea" .}}
diff --git a/tests/integration/migrate_test.go b/tests/integration/migrate_test.go
index f25329f66b..c4dd431594 100644
--- a/tests/integration/migrate_test.go
+++ b/tests/integration/migrate_test.go
@@ -4,6 +4,7 @@
package integration
import (
+ "context"
"fmt"
"net/http"
"net/url"
@@ -18,6 +19,7 @@ import (
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/services/migrations"
+ "code.gitea.io/gitea/services/repository"
"github.com/stretchr/testify/assert"
)
@@ -49,7 +51,7 @@ func TestMigrateLocalPath(t *testing.T) {
setting.ImportLocalPaths = old
}
-func TestMigrateGiteaForm(t *testing.T) {
+func TestMigrate(t *testing.T) {
onGiteaRun(t, func(t *testing.T, u *url.URL) {
AllowLocalNetworks := setting.Migrations.AllowLocalNetworks
setting.Migrations.AllowLocalNetworks = true
@@ -69,33 +71,44 @@ func TestMigrateGiteaForm(t *testing.T) {
session := loginUser(t, ownerName)
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository, auth_model.AccessTokenScopeReadMisc)
- // Step 0: verify the repo is available
- req := NewRequestf(t, "GET", fmt.Sprintf("/%s/%s", ownerName, repoName))
- _ = session.MakeRequest(t, req, http.StatusOK)
- // Step 1: get the Gitea migration form
- req = NewRequestf(t, "GET", "/repo/migrate/?service_type=%d", structs.GiteaService)
- resp := session.MakeRequest(t, req, http.StatusOK)
- // Step 2: load the form
- htmlDoc := NewHTMLParser(t, resp.Body)
- link, exists := htmlDoc.doc.Find(`form.ui.form[action^="/repo/migrate"]`).Attr("action")
- assert.True(t, exists, "The template has changed")
- // Step 4: submit the migration to only migrate issues
- migratedRepoName := "otherrepo"
- req = NewRequestWithValues(t, "POST", link, map[string]string{
- "_csrf": htmlDoc.GetCSRF(),
- "service": fmt.Sprintf("%d", structs.GiteaService),
- "clone_addr": fmt.Sprintf("%s%s/%s", u, ownerName, repoName),
- "auth_token": token,
- "issues": "on",
- "repo_name": migratedRepoName,
- "description": "",
- "uid": fmt.Sprintf("%d", repoOwner.ID),
- })
- resp = session.MakeRequest(t, req, http.StatusSeeOther)
- // Step 5: a redirection displays the migrated repository
- loc := resp.Header().Get("Location")
- assert.EqualValues(t, fmt.Sprintf("/%s/%s", ownerName, migratedRepoName), loc)
- // Step 6: check the repo was created
- unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{Name: migratedRepoName})
+ for _, s := range []struct {
+ svc structs.GitServiceType
+ }{
+ {svc: structs.GiteaService},
+ {svc: structs.ForgejoService},
+ } {
+ // Step 0: verify the repo is available
+ req := NewRequestf(t, "GET", fmt.Sprintf("/%s/%s", ownerName, repoName))
+ _ = session.MakeRequest(t, req, http.StatusOK)
+ // Step 1: get the Gitea migration form
+ req = NewRequestf(t, "GET", "/repo/migrate/?service_type=%d", s.svc)
+ resp := session.MakeRequest(t, req, http.StatusOK)
+ // Step 2: load the form
+ htmlDoc := NewHTMLParser(t, resp.Body)
+ link, exists := htmlDoc.doc.Find(`form.ui.form[action^="/repo/migrate"]`).Attr("action")
+ assert.True(t, exists, "The template has changed")
+ // Step 4: submit the migration to only migrate issues
+ migratedRepoName := "otherrepo"
+ req = NewRequestWithValues(t, "POST", link, map[string]string{
+ "_csrf": htmlDoc.GetCSRF(),
+ "service": fmt.Sprintf("%d", s.svc),
+ "clone_addr": fmt.Sprintf("%s%s/%s", u, ownerName, repoName),
+ "auth_token": token,
+ "issues": "on",
+ "repo_name": migratedRepoName,
+ "description": "",
+ "uid": fmt.Sprintf("%d", repoOwner.ID),
+ })
+ resp = session.MakeRequest(t, req, http.StatusSeeOther)
+ // Step 5: a redirection displays the migrated repository
+ loc := resp.Header().Get("Location")
+ assert.EqualValues(t, fmt.Sprintf("/%s/%s", ownerName, migratedRepoName), loc)
+ // Step 6: check the repo was created
+ repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{Name: migratedRepoName})
+
+ // Step 7: delete the repository, so we can test with other services
+ err := repository.DeleteRepository(context.Background(), repoOwner, repo, false)
+ assert.NoError(t, err)
+ }
})
}
diff --git a/web_src/svg/gitea-forgejo.svg b/web_src/svg/gitea-forgejo.svg
new file mode 100644
index 0000000000..e00e5963cf
--- /dev/null
+++ b/web_src/svg/gitea-forgejo.svg
@@ -0,0 +1,9 @@
+