-
Notifications
You must be signed in to change notification settings - Fork 928
Expand file tree
/
Copy pathrepository_extensions.go
More file actions
130 lines (108 loc) · 3.67 KB
/
repository_extensions.go
File metadata and controls
130 lines (108 loc) · 3.67 KB
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 git
import (
"errors"
"fmt"
"strings"
"github.com/go-git/go-git/v6/config"
cfgformat "github.com/go-git/go-git/v6/plumbing/format/config"
"github.com/go-git/go-git/v6/storage"
xstorage "github.com/go-git/go-git/v6/x/storage"
)
var (
// ErrUnsupportedExtensionRepositoryFormatVersion represents when an
// extension being used is not compatible with the repository's
// core.repositoryFormatVersion.
ErrUnsupportedExtensionRepositoryFormatVersion = errors.New("core.repositoryformatversion does not support extension")
// ErrUnsupportedRepositoryFormatVersion represents when an repository
// is using a format version that is not supported.
ErrUnsupportedRepositoryFormatVersion = errors.New("core.repositoryformatversion not supported")
// ErrUnknownExtension represents when a repository has an extension
// which is unknown or unsupported by go-git.
ErrUnknownExtension = errors.New("unknown extension")
// builtinExtensions defines the Git extensions that are supported by
// the core go-git implementation.
//
// Some extensions are storage-specific, those are defined by the Storers
// themselves by implementing the ExtensionChecker interface.
builtinExtensions = map[string]struct{}{
// noop does not change git’s behavior at all.
// It is useful only for testing format-1 compatibility.
//
// This extension is respected regardless of the
// core.repositoryFormatVersion setting.
"noop": {},
// noop-v1 does not change git’s behavior at all.
// It is useful only for testing format-1 compatibility.
"noop-v1": {},
}
// Some Git extensions were supported upstream before the introduction
// of repositoryformatversion. These are the only extensions that can be
// enabled while core.repositoryformatversion is unset or set to 0.
// Keys must be lowercase to match the output of extensions(), which
// normalises extension names with strings.ToLower.
extensionsValidForV0 = map[string]struct{}{
"noop": {},
"partialclone": {},
"preciousobjects": {},
"worktreeconfig": {},
}
)
type extension struct {
name string
value string
}
func extensions(cfg *config.Config) []extension {
if cfg == nil || cfg.Raw == nil {
return nil
}
if !cfg.Raw.HasSection("extensions") {
return nil
}
section := cfg.Raw.Section("extensions")
out := make([]extension, 0, len(section.Options))
for _, opt := range section.Options {
out = append(out, extension{name: strings.ToLower(opt.Key), value: strings.ToLower(opt.Value)})
}
return out
}
func verifyExtensions(st storage.Storer, cfg *config.Config) error {
needed := extensions(cfg)
switch cfg.Core.RepositoryFormatVersion {
case "", cfgformat.Version0, cfgformat.Version1:
default:
return fmt.Errorf("%w: %q",
ErrUnsupportedRepositoryFormatVersion,
cfg.Core.RepositoryFormatVersion)
}
if len(needed) > 0 {
if cfg.Core.RepositoryFormatVersion == cfgformat.Version0 ||
cfg.Core.RepositoryFormatVersion == "" {
var unsupported []string
for _, ext := range needed {
if _, ok := extensionsValidForV0[ext.name]; !ok {
unsupported = append(unsupported, ext.name)
}
}
if len(unsupported) > 0 {
return fmt.Errorf("%w: %s",
ErrUnsupportedExtensionRepositoryFormatVersion,
strings.Join(unsupported, ", "))
}
}
storageChecker, sok := st.(xstorage.ExtensionChecker)
var missing []string
for _, ext := range needed {
if _, ok := builtinExtensions[ext.name]; ok {
continue
}
if sok && storageChecker.SupportsExtension(ext.name, ext.value) {
continue
}
missing = append(missing, ext.name)
}
if len(missing) > 0 {
return fmt.Errorf("%w: %s", ErrUnknownExtension, strings.Join(missing, ", "))
}
}
return nil
}