Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add StorageID to Repository entity #8502

Merged
merged 16 commits into from
Jan 18, 2025
4 changes: 2 additions & 2 deletions pkg/api/controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -2010,7 +2010,7 @@ func (c *Controller) CreateRepository(w http.ResponseWriter, r *http.Request, bo
if swag.BoolValue(params.Bare) {
// create a bare repository. This is useful in conjunction with refs-restore to create a copy
// of another repository by e.g. copying the _lakefs/ directory and restoring its refs
repo, err := c.Catalog.CreateBareRepository(ctx, body.Name, body.StorageNamespace, defaultBranch, swag.BoolValue(body.ReadOnly))
repo, err := c.Catalog.CreateBareRepository(ctx, body.Name, "", body.StorageNamespace, defaultBranch, swag.BoolValue(body.ReadOnly))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since only the blockstore is aware of the current configuration (using either blockstore or blockstores), we should have a validation at the adapter level which checks whether this value is "Valid". For OSS the validation should allow empty value (or enforce it - I don't really know if we should allow providing any storage_id in that case)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Makes sense.
Removed this validation.

if c.handleAPIError(ctx, w, r, err) {
return
}
Expand All @@ -2024,7 +2024,7 @@ func (c *Controller) CreateRepository(w http.ResponseWriter, r *http.Request, bo
return
}

newRepo, err := c.Catalog.CreateRepository(ctx, body.Name, body.StorageNamespace, defaultBranch, swag.BoolValue(body.ReadOnly))
newRepo, err := c.Catalog.CreateRepository(ctx, body.Name, "", body.StorageNamespace, defaultBranch, swag.BoolValue(body.ReadOnly))
if err != nil {
c.handleAPIError(ctx, w, r, fmt.Errorf("error creating repository: %w", err))
return
Expand Down
179 changes: 90 additions & 89 deletions pkg/api/controller_test.go

Large diffs are not rendered by default.

14 changes: 10 additions & 4 deletions pkg/catalog/catalog.go
Original file line number Diff line number Diff line change
Expand Up @@ -446,8 +446,9 @@ func (c *Catalog) log(ctx context.Context) logging.Logger {
}

// CreateRepository create a new repository pointing to 'storageNamespace' (ex: s3://bucket1/repo) with default branch name 'branch'
func (c *Catalog) CreateRepository(ctx context.Context, repository string, storageNamespace string, branch string, readOnly bool) (*Repository, error) {
func (c *Catalog) CreateRepository(ctx context.Context, repository string, storageID string, storageNamespace string, branch string, readOnly bool) (*Repository, error) {
repositoryID := graveler.RepositoryID(repository)
storageIdentifier := graveler.StorageID(storageID)
storageNS := graveler.StorageNamespace(storageNamespace)
branchID := graveler.BranchID(branch)
if err := validator.Validate([]validator.ValidateArg{
Expand All @@ -456,12 +457,13 @@ func (c *Catalog) CreateRepository(ctx context.Context, repository string, stora
}); err != nil {
return nil, err
}
repo, err := c.Store.CreateRepository(ctx, repositoryID, storageNS, branchID, readOnly)
repo, err := c.Store.CreateRepository(ctx, repositoryID, storageIdentifier, storageNS, branchID, readOnly)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As mentioned in the previous comment and also discussed with @guy-har.
We should probably have someone validate the storage_id here.
Either by a dedicated method in the adapter or by getting the list of block configurations.
In the OSS this should lead to an error whenever create repository is provided with a storageID which is not empty.
We cannot merge the changes in the current state since this could lead to potential bugs in case we release a lakeFS version during development.
If we want to defer the decision of how we want to handle this, the minimum we need to do is to hardcode the current behavior so that any value other than empty will return error, and not to allow creating repositories with explicit storage IDs ATM

if err != nil {
return nil, err
}
catalogRepo := &Repository{
Name: repositoryID.String(),
StorageID: storageIdentifier.String(),
StorageNamespace: storageNS.String(),
DefaultBranch: branchID.String(),
CreationDate: repo.CreationDate,
Expand All @@ -472,8 +474,9 @@ func (c *Catalog) CreateRepository(ctx context.Context, repository string, stora

// CreateBareRepository create a new repository pointing to 'storageNamespace' (ex: s3://bucket1/repo) with no initial branch or commit
// defaultBranchID will point to a non-existent branch on creation, it is up to the caller to eventually create it.
func (c *Catalog) CreateBareRepository(ctx context.Context, repository string, storageNamespace string, defaultBranchID string, readOnly bool) (*Repository, error) {
func (c *Catalog) CreateBareRepository(ctx context.Context, repository string, storageID string, storageNamespace string, defaultBranchID string, readOnly bool) (*Repository, error) {
repositoryID := graveler.RepositoryID(repository)
storageIdentifier := graveler.StorageID(storageID)
storageNS := graveler.StorageNamespace(storageNamespace)
branchID := graveler.BranchID(defaultBranchID)
if err := validator.Validate([]validator.ValidateArg{
Expand All @@ -482,12 +485,13 @@ func (c *Catalog) CreateBareRepository(ctx context.Context, repository string, s
}); err != nil {
return nil, err
}
repo, err := c.Store.CreateBareRepository(ctx, repositoryID, storageNS, branchID, readOnly)
repo, err := c.Store.CreateBareRepository(ctx, repositoryID, storageIdentifier, storageNS, branchID, readOnly)
if err != nil {
return nil, err
}
catalogRepo := &Repository{
Name: repositoryID.String(),
StorageID: storageIdentifier.String(),
StorageNamespace: storageNS.String(),
DefaultBranch: branchID.String(),
CreationDate: repo.CreationDate,
Expand Down Expand Up @@ -516,6 +520,7 @@ func (c *Catalog) GetRepository(ctx context.Context, repository string) (*Reposi

catalogRepository := &Repository{
Name: repositoryID.String(),
StorageID: repo.StorageID.String(),
StorageNamespace: repo.StorageNamespace.String(),
DefaultBranch: repo.DefaultBranchID.String(),
CreationDate: repo.CreationDate,
Expand Down Expand Up @@ -623,6 +628,7 @@ func (c *Catalog) ListRepositories(ctx context.Context, limit int, prefix, searc
}
repos = append(repos, &Repository{
Name: record.RepositoryID.String(),
StorageID: record.StorageID.String(),
StorageNamespace: record.StorageNamespace.String(),
DefaultBranch: record.DefaultBranchID.String(),
CreationDate: record.CreationDate,
Expand Down
55 changes: 28 additions & 27 deletions pkg/catalog/catalog_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,12 +72,12 @@ func TestCatalog_ListRepositories(t *testing.T) {
// prepare data tests
now := time.Now()
gravelerData := []*graveler.RepositoryRecord{
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please make sure to have one record with no StorageID (empty) as part of our tests

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right. Added.

{RepositoryID: "re", Repository: &graveler.Repository{StorageNamespace: "storage1", CreationDate: now, DefaultBranchID: "main1"}},
{RepositoryID: "repo1", Repository: &graveler.Repository{StorageNamespace: "storage2", CreationDate: now, DefaultBranchID: "main2"}},
{RepositoryID: "repo2", Repository: &graveler.Repository{StorageNamespace: "storage3", CreationDate: now, DefaultBranchID: "main3"}},
{RepositoryID: "repo22", Repository: &graveler.Repository{StorageNamespace: "storage4", CreationDate: now, DefaultBranchID: "main4"}},
{RepositoryID: "repo23", Repository: &graveler.Repository{StorageNamespace: "storage5", CreationDate: now, DefaultBranchID: "main5"}},
{RepositoryID: "repo3", Repository: &graveler.Repository{StorageNamespace: "storage6", CreationDate: now, DefaultBranchID: "main6"}},
{RepositoryID: "re", Repository: &graveler.Repository{StorageID: "storage", StorageNamespace: "storageNS1", CreationDate: now, DefaultBranchID: "main1"}},
{RepositoryID: "repo1", Repository: &graveler.Repository{StorageID: "storage1", StorageNamespace: "storageNS2", CreationDate: now, DefaultBranchID: "main2"}},
{RepositoryID: "repo2", Repository: &graveler.Repository{StorageID: "storage1", StorageNamespace: "storageNS3", CreationDate: now, DefaultBranchID: "main3"}},
{RepositoryID: "repo22", Repository: &graveler.Repository{StorageID: "storage1", StorageNamespace: "storageNS4", CreationDate: now, DefaultBranchID: "main4"}},
{RepositoryID: "repo23", Repository: &graveler.Repository{StorageID: "storage1", StorageNamespace: "storageNS5", CreationDate: now, DefaultBranchID: "main5"}},
{RepositoryID: "repo3", Repository: &graveler.Repository{StorageID: "storage2", StorageNamespace: "storageNS6", CreationDate: now, DefaultBranchID: "main6"}},
}
type args struct {
limit int
Expand All @@ -101,12 +101,12 @@ func TestCatalog_ListRepositories(t *testing.T) {
searchString: "",
},
want: []*catalog.Repository{
{Name: "re", StorageNamespace: "storage1", DefaultBranch: "main1", CreationDate: now},
{Name: "repo1", StorageNamespace: "storage2", DefaultBranch: "main2", CreationDate: now},
{Name: "repo2", StorageNamespace: "storage3", DefaultBranch: "main3", CreationDate: now},
{Name: "repo22", StorageNamespace: "storage4", DefaultBranch: "main4", CreationDate: now},
{Name: "repo23", StorageNamespace: "storage5", DefaultBranch: "main5", CreationDate: now},
{Name: "repo3", StorageNamespace: "storage6", DefaultBranch: "main6", CreationDate: now},
{Name: "re", StorageID: "storage", StorageNamespace: "storageNS1", DefaultBranch: "main1", CreationDate: now},
{Name: "repo1", StorageID: "storage1", StorageNamespace: "storageNS2", DefaultBranch: "main2", CreationDate: now},
{Name: "repo2", StorageID: "storage1", StorageNamespace: "storageNS3", DefaultBranch: "main3", CreationDate: now},
{Name: "repo22", StorageID: "storage1", StorageNamespace: "storageNS4", DefaultBranch: "main4", CreationDate: now},
{Name: "repo23", StorageID: "storage1", StorageNamespace: "storageNS5", DefaultBranch: "main5", CreationDate: now},
{Name: "repo3", StorageID: "storage2", StorageNamespace: "storageNS6", DefaultBranch: "main6", CreationDate: now},
},
wantHasMore: false,
wantErr: false,
Expand All @@ -120,7 +120,7 @@ func TestCatalog_ListRepositories(t *testing.T) {
searchString: "",
},
want: []*catalog.Repository{
{Name: "re", StorageNamespace: "storage1", DefaultBranch: "main1", CreationDate: now},
{Name: "re", StorageID: "storage", StorageNamespace: "storageNS1", DefaultBranch: "main1", CreationDate: now},
},
wantHasMore: true,
wantErr: false,
Expand All @@ -134,7 +134,7 @@ func TestCatalog_ListRepositories(t *testing.T) {
searchString: "",
},
want: []*catalog.Repository{
{Name: "repo1", StorageNamespace: "storage2", DefaultBranch: "main2", CreationDate: now},
{Name: "repo1", StorageID: "storage1", StorageNamespace: "storageNS2", DefaultBranch: "main2", CreationDate: now},
},
wantHasMore: true,
wantErr: false,
Expand All @@ -148,8 +148,8 @@ func TestCatalog_ListRepositories(t *testing.T) {
searchString: "",
},
want: []*catalog.Repository{
{Name: "repo2", StorageNamespace: "storage3", DefaultBranch: "main3", CreationDate: now},
{Name: "repo22", StorageNamespace: "storage4", DefaultBranch: "main4", CreationDate: now},
{Name: "repo2", StorageID: "storage1", StorageNamespace: "storageNS3", DefaultBranch: "main3", CreationDate: now},
{Name: "repo22", StorageID: "storage1", StorageNamespace: "storageNS4", DefaultBranch: "main4", CreationDate: now},
},
wantHasMore: true,
wantErr: false,
Expand All @@ -163,7 +163,7 @@ func TestCatalog_ListRepositories(t *testing.T) {
searchString: "",
},
want: []*catalog.Repository{
{Name: "repo1", StorageNamespace: "storage2", DefaultBranch: "main2", CreationDate: now},
{Name: "repo1", StorageID: "storage1", StorageNamespace: "storageNS2", DefaultBranch: "main2", CreationDate: now},
},
wantHasMore: true,
wantErr: false,
Expand All @@ -177,8 +177,8 @@ func TestCatalog_ListRepositories(t *testing.T) {
searchString: "",
},
want: []*catalog.Repository{
{Name: "repo23", StorageNamespace: "storage5", DefaultBranch: "main5", CreationDate: now},
{Name: "repo3", StorageNamespace: "storage6", DefaultBranch: "main6", CreationDate: now},
{Name: "repo23", StorageID: "storage1", StorageNamespace: "storageNS5", DefaultBranch: "main5", CreationDate: now},
{Name: "repo3", StorageID: "storage2", StorageNamespace: "storageNS6", DefaultBranch: "main6", CreationDate: now},
},
wantHasMore: false,
wantErr: false,
Expand All @@ -192,9 +192,9 @@ func TestCatalog_ListRepositories(t *testing.T) {
searchString: "o2",
},
want: []*catalog.Repository{
{Name: "repo2", StorageNamespace: "storage3", DefaultBranch: "main3", CreationDate: now},
{Name: "repo22", StorageNamespace: "storage4", DefaultBranch: "main4", CreationDate: now},
{Name: "repo23", StorageNamespace: "storage5", DefaultBranch: "main5", CreationDate: now},
{Name: "repo2", StorageID: "storage1", StorageNamespace: "storageNS3", DefaultBranch: "main3", CreationDate: now},
{Name: "repo22", StorageID: "storage1", StorageNamespace: "storageNS4", DefaultBranch: "main4", CreationDate: now},
{Name: "repo23", StorageID: "storage1", StorageNamespace: "storageNS5", DefaultBranch: "main5", CreationDate: now},
},
wantHasMore: false,
wantErr: false,
Expand All @@ -208,8 +208,8 @@ func TestCatalog_ListRepositories(t *testing.T) {
searchString: "o2",
},
want: []*catalog.Repository{
{Name: "repo2", StorageNamespace: "storage3", DefaultBranch: "main3", CreationDate: now},
{Name: "repo22", StorageNamespace: "storage4", DefaultBranch: "main4", CreationDate: now},
{Name: "repo2", StorageID: "storage1", StorageNamespace: "storageNS3", DefaultBranch: "main3", CreationDate: now},
{Name: "repo22", StorageID: "storage1", StorageNamespace: "storageNS4", DefaultBranch: "main4", CreationDate: now},
},
wantHasMore: true,
wantErr: false,
Expand All @@ -223,7 +223,7 @@ func TestCatalog_ListRepositories(t *testing.T) {
searchString: "o2",
},
want: []*catalog.Repository{
{Name: "repo23", StorageNamespace: "storage5", DefaultBranch: "main5", CreationDate: now},
{Name: "repo23", StorageID: "storage1", StorageNamespace: "storageNS5", DefaultBranch: "main5", CreationDate: now},
},
wantHasMore: false,
wantErr: false,
Expand All @@ -237,8 +237,8 @@ func TestCatalog_ListRepositories(t *testing.T) {
searchString: "o2",
},
want: []*catalog.Repository{
{Name: "repo22", StorageNamespace: "storage4", DefaultBranch: "main4", CreationDate: now},
{Name: "repo23", StorageNamespace: "storage5", DefaultBranch: "main5", CreationDate: now},
{Name: "repo22", StorageID: "storage1", StorageNamespace: "storageNS4", DefaultBranch: "main4", CreationDate: now},
{Name: "repo23", StorageID: "storage1", StorageNamespace: "storageNS5", DefaultBranch: "main5", CreationDate: now},
},
wantHasMore: false,
wantErr: false,
Expand Down Expand Up @@ -871,6 +871,7 @@ func createPrepareUncommittedTestScenario(t *testing.T, repositoryID string, num
repository := &graveler.RepositoryRecord{
RepositoryID: graveler.RepositoryID(repositoryID),
Repository: &graveler.Repository{
StorageID: "storage",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this change relevant at the moment?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can remove this row and it will still work -
But I rather keep this as an extra test.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lets remove that - and address these tests in the right context (GC).
I prefer we don't modify the test without understanding what we'd want to test here

StorageNamespace: graveler.StorageNamespace("mem://" + repositoryID),
CreationDate: time.Now(),
DefaultBranchID: "main",
Expand Down
4 changes: 2 additions & 2 deletions pkg/catalog/fake_graveler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ func (g *FakeGraveler) SetGarbageCollectionRules(_ context.Context, _ *graveler.
panic("implement me")
}

func (g *FakeGraveler) CreateBareRepository(_ context.Context, _ graveler.RepositoryID, _ graveler.StorageNamespace, _ graveler.BranchID, _ bool) (*graveler.RepositoryRecord, error) {
func (g *FakeGraveler) CreateBareRepository(_ context.Context, _ graveler.RepositoryID, _ graveler.StorageID, _ graveler.StorageNamespace, _ graveler.BranchID, _ bool) (*graveler.RepositoryRecord, error) {
panic("implement me")
}

Expand Down Expand Up @@ -148,7 +148,7 @@ func (g *FakeGraveler) GetRepository(ctx context.Context, repositoryID graveler.
return &graveler.RepositoryRecord{RepositoryID: repositoryID}, nil
}

func (g *FakeGraveler) CreateRepository(ctx context.Context, repositoryID graveler.RepositoryID, storageNamespace graveler.StorageNamespace, branchID graveler.BranchID, readOnly bool) (*graveler.RepositoryRecord, error) {
func (g *FakeGraveler) CreateRepository(ctx context.Context, repositoryID graveler.RepositoryID, storageID graveler.StorageID, storageNamespace graveler.StorageNamespace, branchID graveler.BranchID, readOnly bool) (*graveler.RepositoryRecord, error) {
panic("implement me")
}

Expand Down
1 change: 1 addition & 0 deletions pkg/catalog/model.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ type CommitGeneration int64

type Repository struct {
Name string
StorageID string
StorageNamespace string
DefaultBranch string
CreationDate time.Time
Expand Down
2 changes: 1 addition & 1 deletion pkg/gateway/testutil/gateway_setup.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ func GetBasicHandler(t *testing.T, authService *FakeAuthService, repoName string
storageNamespace = "replay"
}

_, err = c.CreateRepository(ctx, repoName, storageNamespace, "main", false)
_, err = c.CreateRepository(ctx, repoName, "", storageNamespace, "main", false)
testutil.Must(t, err)

handler := gateway.NewHandler(authService.Region, c, multipartTracker, blockAdapter, authService, []string{authService.BareDomain}, &stats.NullCollector{}, upload.DefaultPathProvider, nil, config.DefaultLoggingAuditLogLevel, true, false, false)
Expand Down
23 changes: 16 additions & 7 deletions pkg/graveler/graveler.go
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,9 @@ func WithShowHidden(v bool) ListOptionsFunc {

// function/methods receiving the following basic types could assume they passed validation

// StorageID is the storage location identifier
type StorageID string

// StorageNamespace is the URI to the storage location
type StorageNamespace string

Expand Down Expand Up @@ -355,6 +358,7 @@ type Metadata map[string]string

// Repository represents repository metadata
type Repository struct {
StorageID StorageID
StorageNamespace StorageNamespace
CreationDate time.Time
DefaultBranchID BranchID
Expand All @@ -374,8 +378,9 @@ type RepositoryMetadata map[string]string

const MetadataKeyLastImportTimeStamp = ".lakefs.last.import.timestamp"

func NewRepository(storageNamespace StorageNamespace, defaultBranchID BranchID, readOnly bool) Repository {
func NewRepository(storageID StorageID, storageNamespace StorageNamespace, defaultBranchID BranchID, readOnly bool) Repository {
return Repository{
StorageID: storageID,
StorageNamespace: storageNamespace,
CreationDate: time.Now().UTC(),
DefaultBranchID: defaultBranchID,
Expand Down Expand Up @@ -600,10 +605,10 @@ type VersionController interface {
GetRepository(ctx context.Context, repositoryID RepositoryID) (*RepositoryRecord, error)

// CreateRepository stores a new Repository under RepositoryID with the given Branch as default branch
CreateRepository(ctx context.Context, repositoryID RepositoryID, storageNamespace StorageNamespace, branchID BranchID, readOnly bool) (*RepositoryRecord, error)
CreateRepository(ctx context.Context, repositoryID RepositoryID, storageID StorageID, storageNamespace StorageNamespace, branchID BranchID, readOnly bool) (*RepositoryRecord, error)

// CreateBareRepository stores a new Repository under RepositoryID with no initial branch or commit
CreateBareRepository(ctx context.Context, repositoryID RepositoryID, storageNamespace StorageNamespace, defaultBranchID BranchID, readOnly bool) (*RepositoryRecord, error)
CreateBareRepository(ctx context.Context, repositoryID RepositoryID, storageID StorageID, storageNamespace StorageNamespace, defaultBranchID BranchID, readOnly bool) (*RepositoryRecord, error)

// ListRepositories returns iterator to scan repositories
ListRepositories(ctx context.Context) (RepositoryIterator, error)
Expand Down Expand Up @@ -1095,6 +1100,10 @@ func (id RepositoryID) String() string {
return string(id)
}

func (id StorageID) String() string {
return string(id)
}

func (ns StorageNamespace) String() string {
return string(ns)
}
Expand Down Expand Up @@ -1185,27 +1194,27 @@ func (g *Graveler) GetRepository(ctx context.Context, repositoryID RepositoryID)
return g.RefManager.GetRepository(ctx, repositoryID)
}

func (g *Graveler) CreateRepository(ctx context.Context, repositoryID RepositoryID, storageNamespace StorageNamespace, branchID BranchID, readOnly bool) (*RepositoryRecord, error) {
func (g *Graveler) CreateRepository(ctx context.Context, repositoryID RepositoryID, storageID StorageID, storageNamespace StorageNamespace, branchID BranchID, readOnly bool) (*RepositoryRecord, error) {
_, err := g.RefManager.GetRepository(ctx, repositoryID)
if err != nil && !errors.Is(err, ErrRepositoryNotFound) {
return nil, err
}

repo := NewRepository(storageNamespace, branchID, readOnly)
repo := NewRepository(storageID, storageNamespace, branchID, readOnly)
repository, err := g.RefManager.CreateRepository(ctx, repositoryID, repo)
if err != nil {
return nil, err
}
return repository, nil
}

func (g *Graveler) CreateBareRepository(ctx context.Context, repositoryID RepositoryID, storageNamespace StorageNamespace, defaultBranchID BranchID, readOnly bool) (*RepositoryRecord, error) {
func (g *Graveler) CreateBareRepository(ctx context.Context, repositoryID RepositoryID, storageID StorageID, storageNamespace StorageNamespace, defaultBranchID BranchID, readOnly bool) (*RepositoryRecord, error) {
_, err := g.RefManager.GetRepository(ctx, repositoryID)
if err != nil && !errors.Is(err, ErrRepositoryNotFound) {
return nil, err
}

repo := NewRepository(storageNamespace, defaultBranchID, readOnly)
repo := NewRepository(storageID, storageNamespace, defaultBranchID, readOnly)
repository, err := g.RefManager.CreateBareRepository(ctx, repositoryID, repo)
if err != nil {
return nil, err
Expand Down
Loading
Loading