diff --git a/pkg/repo/contents.go b/pkg/repo/contents.go index 220c6272..c0348c1e 100644 --- a/pkg/repo/contents.go +++ b/pkg/repo/contents.go @@ -23,6 +23,43 @@ import ( "google.golang.org/protobuf/proto" ) +// TODO: Diffing method + +// Take the namespace contents of `other` into `dst`. +// Namespaces and features in `other` that are not in `dst` are added. +// Conflicting features are overwritten with ones from `other`. +// Namespaces in `dst` that are not in `other` are NOT removed. +// Returns the modified `dst`. `other` should not be used after being passed. +func TakeNamespaceContents(dst *featurev1beta1.RepositoryContents, other *featurev1beta1.RepositoryContents) *featurev1beta1.RepositoryContents { + for _, otherNs := range other.Namespaces { + replaced := false + for i, dstNs := range dst.Namespaces { + if dstNs.Name == otherNs.Name { + dst.Namespaces[i] = otherNs + replaced = true + } + } + if !replaced { + dst.Namespaces = append(dst.Namespaces, otherNs) + } + } + // Need to also overwrite appropriate file descriptors + // Assumes that file descriptors corresponding to namespaces have deterministic names + for _, otherFD := range other.FileDescriptorSet.File { + replaced := false + for i, dstFD := range dst.FileDescriptorSet.File { + if dstFD.Name == otherFD.Name { + dst.FileDescriptorSet.File[i] = otherFD + replaced = true + } + } + if !replaced { + dst.FileDescriptorSet.File = append(dst.FileDescriptorSet.File, otherFD) + } + } + return dst +} + // Expects base64 encoded serialized RepositoryContents message func DecodeRepositoryContents(encoded []byte) (*featurev1beta1.RepositoryContents, error) { // Because Protobuf is not self-describing, we have to jump through some hoops here for deserialization. diff --git a/pkg/repo/feature.go b/pkg/repo/feature.go index df7aacd6..4d20dd39 100644 --- a/pkg/repo/feature.go +++ b/pkg/repo/feature.go @@ -681,9 +681,10 @@ func (r *repository) BuildDynamicTypeRegistry(ctx context.Context, protoDirPath // because we need to first ensure that buf cmd line can be executed in the // ephemeral env. func (r *repository) ReBuildDynamicTypeRegistry(ctx context.Context, protoDirPath string, useExternalTypes bool) (*protoregistry.Types, error) { - if !r.bufEnabled { - return nil, errors.New("buf cmd line not enabled") - } + // TODO: We do need a way of regenerating the buf image in ephemeral repos. Disabling this check for now. + // if !r.bufEnabled { + // return nil, errors.New("buf cmd line not enabled") + // } sTypes, err := prototypes.ReBuildDynamicTypeRegistry(ctx, protoDirPath, useExternalTypes, r) if err != nil { return nil, err diff --git a/pkg/sync/repo.go b/pkg/sync/repo.go index dfabfc24..b257dc34 100644 --- a/pkg/sync/repo.go +++ b/pkg/sync/repo.go @@ -46,11 +46,17 @@ func WriteContentsToLocalRepo(ctx context.Context, contents *featurev1beta1.Repo if err != nil { return errors.Wrap(err, "prepare repo") } + return WriteContentsToRepo(ctx, contents, r) +} + +func WriteContentsToRepo(ctx context.Context, contents *featurev1beta1.RepositoryContents, r repo.ConfigurationRepository) error { // Discard logs, mainly for silencing compilation later - // TODO: Maybe a verbose flag - r.ConfigureLogger(&repo.LoggingConfiguration{ - Writer: io.Discard, + // TODO: Allow passing in writer + clear := r.ConfigureLogger(&repo.LoggingConfiguration{ + Writer: io.Discard, + ColorsDisabled: true, }) + defer clear() rootMD, _, err := r.ParseMetadata(ctx) if err != nil { return err @@ -159,6 +165,7 @@ func WriteContentsToLocalRepo(ctx context.Context, contents *featurev1beta1.Repo if err := WriteTypesToRepo(ctx, contents.FileDescriptorSet, r); err != nil { return errors.Wrap(err, "write type files") } + // FIXME: We need this to be runnable on ephemeral repositories if _, err := r.ReBuildDynamicTypeRegistry(ctx, rootMD.ProtoDirectory, false); err != nil { return errors.Wrap(err, "final rebuild type registry") }