diff options
author | Jacob Vosmaer (GitLab) <jacob@gitlab.com> | 2018-05-24 15:17:01 +0300 |
---|---|---|
committer | Jacob Vosmaer (GitLab) <jacob@gitlab.com> | 2018-05-24 15:17:01 +0300 |
commit | ce735034323f10559032ca055187e3df20799ff7 (patch) | |
tree | 1c82a94af9fa23f7612119d38c7e7e8fee7bfa29 | |
parent | 4e344ff6210e32d6e705e1ef828abcb948313a78 (diff) | |
parent | c270435bc7e328803240b2b5e031465a9152a1e6 (diff) |
Merge branch '1165-rewrite-is-rabase-in-progress' into 'master'
Rewrite Is{Squash,Rebase}InProgress in go
Closes #1165
See merge request gitlab-org/gitaly!698
5 files changed, 92 insertions, 12 deletions
diff --git a/changelogs/unreleased/1165-rewrite-is-rabase-in-progress.yml b/changelogs/unreleased/1165-rewrite-is-rabase-in-progress.yml new file mode 100644 index 000000000..08bc113f7 --- /dev/null +++ b/changelogs/unreleased/1165-rewrite-is-rabase-in-progress.yml @@ -0,0 +1,5 @@ +--- +title: Rewrite IsRebase/SquashInProgress in Go +merge_request: 698 +author: +type: performance diff --git a/internal/service/repository/rebase_in_progress.go b/internal/service/repository/rebase_in_progress.go index 2c894e198..dc7d16b6e 100644 --- a/internal/service/repository/rebase_in_progress.go +++ b/internal/service/repository/rebase_in_progress.go @@ -2,32 +2,62 @@ package repository import ( "fmt" + "os" + "path" + "strings" + "time" pb "gitlab.com/gitlab-org/gitaly-proto/go" - - "gitlab.com/gitlab-org/gitaly/internal/rubyserver" + "gitlab.com/gitlab-org/gitaly/internal/helper" + "gitlab.com/gitlab-org/gitaly/internal/helper/housekeeping" "golang.org/x/net/context" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" ) +const ( + worktreePrefix = "gitlab-worktree" + rebaseWorktreePrefix = "rebase" + freshTimeout = 15 * time.Minute +) + func (s *server) IsRebaseInProgress(ctx context.Context, req *pb.IsRebaseInProgressRequest) (*pb.IsRebaseInProgressResponse, error) { if err := validateIsRebaseInProgressRequest(req); err != nil { return nil, status.Errorf(codes.InvalidArgument, "IsRebaseInProgress: %v", err) } - client, err := s.RepositoryServiceClient(ctx) + repoPath, err := helper.GetRepoPath(req.GetRepository()) if err != nil { return nil, err } - clientCtx, err := rubyserver.SetHeaders(ctx, req.GetRepository()) + inProg, err := freshWorktree(repoPath, rebaseWorktreePrefix, req.GetRebaseId()) if err != nil { return nil, err } + return &pb.IsRebaseInProgressResponse{InProgress: inProg}, nil +} + +func freshWorktree(repoPath, prefix, id string) (bool, error) { + worktreePath := path.Join(repoPath, worktreePrefix, fmt.Sprintf("%s-%s", prefix, id)) + + fs, err := os.Stat(worktreePath) + if err != nil { + return false, nil + } + + if time.Since(fs.ModTime()) > freshTimeout { + if err = os.RemoveAll(worktreePath); err != nil { + if err = housekeeping.FixDirectoryPermissions(worktreePath); err != nil { + return false, err + } + err = os.RemoveAll(worktreePath) + } + return false, err + } - return client.IsRebaseInProgress(clientCtx, req) + return true, nil } func validateIsRebaseInProgressRequest(req *pb.IsRebaseInProgressRequest) error { @@ -39,5 +69,9 @@ func validateIsRebaseInProgressRequest(req *pb.IsRebaseInProgressRequest) error return fmt.Errorf("empty RebaseId") } + if strings.Contains(req.GetRebaseId(), "/") { + return fmt.Errorf("RebaseId contains '/'") + } + return nil } diff --git a/internal/service/repository/rebase_in_progress_test.go b/internal/service/repository/rebase_in_progress_test.go index 7037028d1..d34165951 100644 --- a/internal/service/repository/rebase_in_progress_test.go +++ b/internal/service/repository/rebase_in_progress_test.go @@ -1,8 +1,11 @@ package repository import ( + "fmt" + "os" "path" "testing" + "time" "gitlab.com/gitlab-org/gitaly/internal/testhelper" @@ -22,7 +25,20 @@ func TestSuccessfulIsRebaseInProgressRequest(t *testing.T) { testRepo1, testRepo1Path, cleanupFn := testhelper.NewTestRepo(t) defer cleanupFn() - testhelper.MustRunCommand(t, nil, "git", "-C", testRepo1Path, "worktree", "add", "--detach", path.Join(testRepo1Path, "gitlab-worktree", "rebase-1"), "master") + testhelper.MustRunCommand(t, nil, "git", "-C", testRepo1Path, "worktree", "add", "--detach", path.Join(testRepo1Path, worktreePrefix, fmt.Sprintf("%s-1", rebaseWorktreePrefix)), "master") + + brokenPath := path.Join(testRepo1Path, worktreePrefix, fmt.Sprintf("%s-2", rebaseWorktreePrefix)) + testhelper.MustRunCommand(t, nil, "git", "-C", testRepo1Path, "worktree", "add", "--detach", brokenPath, "master") + os.Chmod(brokenPath, 0) + os.Chtimes(brokenPath, time.Now(), time.Now().Add(-16*time.Minute)) + defer func() { + os.Chmod(brokenPath, 0755) + os.RemoveAll(brokenPath) + }() + + oldPath := path.Join(testRepo1Path, worktreePrefix, fmt.Sprintf("%s-3", rebaseWorktreePrefix)) + testhelper.MustRunCommand(t, nil, "git", "-C", testRepo1Path, "worktree", "add", "--detach", oldPath, "master") + os.Chtimes(oldPath, time.Now(), time.Now().Add(-16*time.Minute)) testRepo2, _, cleanupFn := testhelper.NewTestRepo(t) defer cleanupFn() @@ -41,6 +57,22 @@ func TestSuccessfulIsRebaseInProgressRequest(t *testing.T) { inProgress: true, }, { + desc: "broken rebase in progress", + request: &pb.IsRebaseInProgressRequest{ + Repository: testRepo1, + RebaseId: "2", + }, + inProgress: false, + }, + { + desc: "expired rebase in progress", + request: &pb.IsRebaseInProgressRequest{ + Repository: testRepo1, + RebaseId: "3", + }, + inProgress: false, + }, + { desc: "no rebase in progress", request: &pb.IsRebaseInProgressRequest{ Repository: testRepo2, diff --git a/internal/service/repository/squash_in_progress.go b/internal/service/repository/squash_in_progress.go index 3b0217237..2e284faa2 100644 --- a/internal/service/repository/squash_in_progress.go +++ b/internal/service/repository/squash_in_progress.go @@ -2,30 +2,35 @@ package repository import ( "fmt" + "strings" pb "gitlab.com/gitlab-org/gitaly-proto/go" - "gitlab.com/gitlab-org/gitaly/internal/rubyserver" + "gitlab.com/gitlab-org/gitaly/internal/helper" + "golang.org/x/net/context" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" ) +const ( + squashWorktreePrefix = "squash" +) + func (s *server) IsSquashInProgress(ctx context.Context, req *pb.IsSquashInProgressRequest) (*pb.IsSquashInProgressResponse, error) { if err := validateIsSquashInProgressRequest(req); err != nil { return nil, status.Errorf(codes.InvalidArgument, "IsSquashInProgress: %v", err) } - client, err := s.RepositoryServiceClient(ctx) + repoPath, err := helper.GetRepoPath(req.GetRepository()) if err != nil { return nil, err } - clientCtx, err := rubyserver.SetHeaders(ctx, req.GetRepository()) + inProg, err := freshWorktree(repoPath, squashWorktreePrefix, req.GetSquashId()) if err != nil { return nil, err } - - return client.IsSquashInProgress(clientCtx, req) + return &pb.IsSquashInProgressResponse{InProgress: inProg}, nil } func validateIsSquashInProgressRequest(req *pb.IsSquashInProgressRequest) error { @@ -37,5 +42,9 @@ func validateIsSquashInProgressRequest(req *pb.IsSquashInProgressRequest) error return fmt.Errorf("empty SquashId") } + if strings.Contains(req.GetSquashId(), "/") { + return fmt.Errorf("SquashId contains '/'") + } + return nil } diff --git a/internal/service/repository/squash_in_progress_test.go b/internal/service/repository/squash_in_progress_test.go index 248887173..5d16545aa 100644 --- a/internal/service/repository/squash_in_progress_test.go +++ b/internal/service/repository/squash_in_progress_test.go @@ -22,7 +22,7 @@ func TestSuccessfulIsSquashInProgressRequest(t *testing.T) { testRepo1, testRepo1Path, cleanupFn := testhelper.NewTestRepo(t) defer cleanupFn() - testhelper.MustRunCommand(t, nil, "git", "-C", testRepo1Path, "worktree", "add", "--detach", path.Join(testRepo1Path, "gitlab-worktree", "squash-1"), "master") + testhelper.MustRunCommand(t, nil, "git", "-C", testRepo1Path, "worktree", "add", "--detach", path.Join(testRepo1Path, worktreePrefix, "squash-1"), "master") testRepo2, _, cleanupFn := testhelper.NewTestRepo(t) defer cleanupFn() |