diff options
author | Loïc Dachary | 2021-12-27 17:42:21 +0100 |
---|---|---|
committer | Loïc Dachary | 2022-03-13 09:20:45 +0100 |
commit | 466a5d85d7fc6e24a912707e040c56a864638780 (patch) | |
tree | 36f7b1118fb85d14d745bb280a0effae444fafdc | |
parent | 53bfafc8c2e94a1f0a8ec50d599e5044eba99d02 (diff) |
projectbase: implement tests for UpdateProjectBase
Fixes: forgefriends/forgefriends#2
Signed-off-by: Loïc Dachary <loic@dachary.org>
-rw-r--r-- | integrations/projectbase_test.go | 67 | ||||
-rw-r--r-- | services/projectbase/projectbase.go | 98 |
2 files changed, 163 insertions, 2 deletions
diff --git a/integrations/projectbase_test.go b/integrations/projectbase_test.go new file mode 100644 index 000000000..48d8f7b81 --- /dev/null +++ b/integrations/projectbase_test.go @@ -0,0 +1,67 @@ +// Copyright 2022 The Gitea Authors. All rights reserved. +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file. + +package integrations + +import ( + "context" + "fmt" + "net/url" + "sort" + "testing" + + repo_model "code.gitea.io/gitea/models/repo" + "code.gitea.io/gitea/models/unittest" + user_model "code.gitea.io/gitea/models/user" + "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/setting" + "code.gitea.io/gitea/services/migrations" + projectbase_service "code.gitea.io/gitea/services/projectbase" + + "github.com/stretchr/testify/assert" +) + +func TestProjectBaseUpdate(t *testing.T) { + onGiteaRun(t, func(t *testing.T, u *url.URL) { + AllowedDomains := setting.Migrations.AllowedDomains + setting.Migrations.AllowedDomains = "loopback" + AllowLocalNetworks := setting.Migrations.AllowLocalNetworks + setting.Migrations.AllowLocalNetworks = true + setting.Database.LogSQL = true + AppVer := setting.AppVer + setting.AppVer = "1.15" + defer func() { + setting.Migrations.AllowedDomains = AllowedDomains + setting.Migrations.AllowLocalNetworks = AllowLocalNetworks + setting.Database.LogSQL = false + setting.AppVer = AppVer + }() + + assert.NoError(t, migrations.Init()) + + reponame := "repo1" + repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{Name: reponame}).(*repo_model.Repository) + repoOwner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID}).(*user_model.User) + session := loginUser(t, repoOwner.Name) + token := getTokenForLoggedInUser(t, session) + assert.False(t, repo.HasProjectBase()) + ctx := context.Background() + assert.NoError(t, projectbase_service.InitProjectBase(ctx, repo)) + assert.True(t, repo.HasProjectBase()) + assert.NoError(t, projectbase_service.UpdateProjectBase(ctx, token, repo)) + + gitRepo, err := git.OpenRepository(repo.ProjectBasePath()) + fmt.Println(repo.ProjectBasePath()) + assert.NoError(t, err) + defer gitRepo.Close() + files := []string{"repo.yml", "issue.yml", "comments"} + filelist, err := gitRepo.LsTree("HEAD", files...) + assert.NoError(t, err) + sort.Strings(filelist) + expected := files + expected = append(expected, "") + sort.Strings(expected) + assert.Equal(t, expected, filelist) + }) +} diff --git a/services/projectbase/projectbase.go b/services/projectbase/projectbase.go index 28460cf48..eb86a65ef 100644 --- a/services/projectbase/projectbase.go +++ b/services/projectbase/projectbase.go @@ -5,22 +5,116 @@ package projectbase import ( + "context" "fmt" + "os" + "path/filepath" repo_model "code.gitea.io/gitea/models/repo" + user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/log" + "code.gitea.io/gitea/modules/structs" + "code.gitea.io/gitea/modules/util" + "code.gitea.io/gitea/services/migrations" + files_service "code.gitea.io/gitea/services/repository/files" ) // InitProjectBase function -func InitProjectBase(repo *repo_model.Repository) error { +func InitProjectBase(ctx context.Context, repo *repo_model.Repository) error { if repo.HasProjectBase() { return nil } - if err := git.InitRepository(repo.ProjectBasePath(), true); err != nil { + if err := git.InitRepository(ctx, repo.ProjectBasePath(), true); err != nil { return fmt.Errorf("InitRepository: %v", err) } else if _, err = git.NewCommand(ctx, "symbolic-ref", "HEAD", git.BranchPrefix+"master").RunInDir(repo.ProjectBasePath()); err != nil { return fmt.Errorf("unable to set default branch to master: %v", err) } return nil } + +// UpdateProjectBase function +func UpdateProjectBase(ctx context.Context, token string, repo *repo_model.Repository) error { + // + // Checkout repository + // + temp, err := files_service.NewTemporaryUploadRepository(ctx, repo) + if err != nil { + return err + } + basePath := temp.BasePath() + defer temp.Close() + if stdout, err := git.NewCommand(ctx, "clone", "--no-checkout", "--shared", "--depth=1", repo.ProjectBasePath(), basePath).Run(); err != nil { + log.Error("Failed to clone projectbase repository: %s %s (%v)", repo.FullName(), stdout, err) + return fmt.Errorf("Failed to clone projectbase repository: %s %s (%v)", repo.FullName(), stdout, err) + } + + // + // Create downloader & uploader + // + opts := migrations.MigrateOptions{ + GitServiceType: structs.GiteaService, + Issues: true, + Comments: true, + AuthToken: token, + CloneAddr: repo.CloneLink().HTTPS, + } + downloaderFactory := &migrations.GiteaDownloaderFactory{} + downloader, err := downloaderFactory.New(ctx, opts) + if err != nil { + return err + } + uploader, err := migrations.NewRepositoryDumper(ctx, basePath, repo.OwnerName, repo.Name, opts) + if err != nil { + return err + } + + // + // Perform the migration + // + if err := migrations.InternalMigrateRepository(downloader, uploader, opts); err != nil { + if err1 := uploader.Rollback(); err1 != nil { + log.Error("rollback failed: %v", err1) + } + return err + } + d := filepath.Join(basePath, repo.OwnerName, repo.Name) + for _, f := range []string{"repo.yml", "topic.yml", "issue.yml", "comments"} { + if err := os.Rename(filepath.Join(d, f), filepath.Join(basePath, f)); err != nil { + return err + } + } + if err := util.RemoveAll(filepath.Join(basePath, repo.OwnerName)); err != nil { + return err + } + + // + // Commit the migration to the repository & push it + // + if stdout, err := git.NewCommand(ctx, "add", ".").RunInDir(basePath); err != nil { + log.Error("Failed to git add. : %s %s (%v)", repo.FullName(), stdout, err) + return fmt.Errorf("Failed to git add .: %s %s (%v)", repo.FullName(), stdout, err) + } + owner, err := user_model.GetUserByName(repo.OwnerName) + if err != nil { + log.Error("GetUserByName(repo.OwnerName=%s) (%v)", repo.OwnerName, err) + return err + } + author := owner.NewGitSig() + env := append(os.Environ(), + "GIT_AUTHOR_NAME="+author.Name, + "GIT_AUTHOR_EMAIL="+author.Email, + "GIT_COMMITTER_NAME="+author.Name, + "GIT_COMMITTER_EMAIL="+author.Email, + ) + if stdout, err := git.NewCommand(ctx, "commit", "-m", "project info").RunInDirWithEnv(basePath, env); err != nil { + log.Error("Failed to git add . : %s %s (%v)", repo.FullName(), stdout, err) + return fmt.Errorf("Failed to git add .: %s %s (%v)", repo.FullName(), stdout, err) + } + if stdout, err := git.NewCommand(ctx, "push").RunInDir(basePath); err != nil { + log.Error("Failed to git push: %s %s (%v)", repo.FullName(), stdout, err) + return fmt.Errorf("Failed to git push: %s %s (%v)", repo.FullName(), stdout, err) + } + return nil +} |