Welcome to mirror list, hosted at ThFree Co, Russian Federation.

namespace.go « namespace « service « internal - gitlab.com/gitlab-org/gitaly.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: f1682cee8d21f6781cb75c9111276ff2de7e8cc5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
package namespace

import (
	"context"
	"errors"
	"fmt"
	"os"
	"path/filepath"

	"gitlab.com/gitlab-org/gitaly-proto/go/gitalypb"
	"gitlab.com/gitlab-org/gitaly/internal/helper"
)

var noNameError = helper.ErrInvalidArgumentf("name: cannot be empty")

func (s *server) NamespaceExists(ctx context.Context, in *gitalypb.NamespaceExistsRequest) (*gitalypb.NamespaceExistsResponse, error) {
	storagePath, err := helper.GetStorageByName(in.GetStorageName())
	if err != nil {
		return nil, err
	}

	// This case should return an error, as else we'd actually say the path
	// exists as the storage exists
	if in.GetName() == "" {
		return nil, noNameError
	}

	exists, err := directoryExists(storagePath, in.GetName())

	return &gitalypb.NamespaceExistsResponse{Exists: exists}, helper.ErrInternal(err)
}

func (s *server) AddNamespace(ctx context.Context, in *gitalypb.AddNamespaceRequest) (*gitalypb.AddNamespaceResponse, error) {
	storagePath, err := helper.GetStorageByName(in.GetStorageName())
	if err != nil {
		return nil, err
	}

	name := in.GetName()
	if name == "" {
		return nil, noNameError
	}

	if err := createDirectory(storagePath, name); err != nil {
		return nil, helper.ErrInternal(err)
	}

	return &gitalypb.AddNamespaceResponse{}, nil
}

func (s *server) RenameNamespace(ctx context.Context, in *gitalypb.RenameNamespaceRequest) (*gitalypb.RenameNamespaceResponse, error) {
	if err := validateRenameNamespaceRequest(in); err != nil {
		return nil, helper.ErrInvalidArgument(err)
	}

	storagePath, err := helper.GetStorageByName(in.GetStorageName())
	if err != nil {
		return nil, err
	}

	fromPath, toPath := in.GetFrom(), in.GetTo()

	if err = createDirectory(storagePath, filepath.Dir(toPath)); err != nil {
		return nil, helper.ErrInternal(err)
	}

	if err = os.Rename(namespacePath(storagePath, fromPath), namespacePath(storagePath, toPath)); err != nil {
		return nil, helper.ErrInternal(err)
	}

	return &gitalypb.RenameNamespaceResponse{}, nil
}

func (s *server) RemoveNamespace(ctx context.Context, in *gitalypb.RemoveNamespaceRequest) (*gitalypb.RemoveNamespaceResponse, error) {
	storagePath, err := helper.GetStorageByName(in.GetStorageName())
	if err != nil {
		return nil, err
	}

	// Needed as else we might destroy the whole storage
	name := in.GetName()
	if name == "" {
		return nil, noNameError
	}

	// os.RemoveAll is idempotent by itself
	// No need to check if the directory exists, or not
	if err = os.RemoveAll(namespacePath(storagePath, name)); err != nil {
		return nil, helper.ErrInternal(err)
	}
	return &gitalypb.RemoveNamespaceResponse{}, nil
}

func namespacePath(storagePath, ns string) string {
	return filepath.Join(storagePath, ns)
}

func createDirectory(storagePath, namespace string) error {
	return os.MkdirAll(namespacePath(storagePath, namespace), 0755)
}

func directoryExists(storagePath, namespace string) (bool, error) {
	fi, err := os.Stat(namespacePath(storagePath, namespace))
	if os.IsNotExist(err) {
		return false, nil
	} else if err != nil {
		return false, err
	}

	if !fi.IsDir() {
		return false, fmt.Errorf("expected directory, found file %s", namespace)
	}

	return true, nil
}

func validateRenameNamespaceRequest(req *gitalypb.RenameNamespaceRequest) error {
	if _, err := helper.GetStorageByName(req.GetStorageName()); err != nil {
		return err
	}

	if req.GetFrom() == "" {
		return errors.New("from field cannot be empty")
	}
	if req.GetTo() == "" {
		return errors.New("to field cannot be empty")
	}

	return nil
}