diff --git a/forgeConfig.marshal.pb.go b/forgeConfig.marshal.pb.go new file mode 100644 index 0000000..dde2834 --- /dev/null +++ b/forgeConfig.marshal.pb.go @@ -0,0 +1,93 @@ +// Code generated by go.wit.com/apps/autogenpb DO NOT EDIT. +// This file was autogenerated with autogenpb v0.5.6-1-g08dc949 2025.09.23_0925 +// go install go.wit.com/apps/autogenpb@latest +// +// define which structs (messages) you want to use in the .proto file +// Then sort.pb.go and marshal.pb.go files are autogenerated +// +// autogenpb uses it and has an example .proto file with instructions +// + +package forgepb + +import ( + "google.golang.org/protobuf/encoding/protojson" + "google.golang.org/protobuf/encoding/prototext" + "google.golang.org/protobuf/proto" +) + +// human readable JSON +func (v *ForgeConfigs) FormatJSON() string { + return protojson.Format(v) +} + +// marshal json +func (v *ForgeConfigs) MarshalJSON() ([]byte, error) { + return protojson.Marshal(v) +} + +// unmarshal json +func (v *ForgeConfigs) UnmarshalJSON(data []byte) error { + return protojson.Unmarshal(data, v) +} + +// apparently this isn't stable, but it's awesomely better +// https://protobuf.dev/reference/go/faq/#unstable-text +// it's brilliant for config files! +func (v *ForgeConfigs) FormatTEXT() string { + v.fixUuid() + return prototext.Format(v) +} + +// unmarshalTEXT. This reads the .text config file back in after the user edits it +func (v *ForgeConfigs) UnmarshalTEXT(data []byte) error { + return prototext.Unmarshal(data, v) +} + +// marshal to wire. This is called winning. +func (v *ForgeConfigs) Marshal() ([]byte, error) { + v.fixUuid() + return proto.Marshal(v) +} + +// unmarshal from wire. You have won. +func (v *ForgeConfigs) Unmarshal(data []byte) error { + return proto.Unmarshal(data, v) +} + +// human readable JSON +func (v *Identify) FormatJSON() string { + return protojson.Format(v) +} + +// marshal json +func (v *Identify) MarshalJSON() ([]byte, error) { + return protojson.Marshal(v) +} + +// unmarshal json +func (v *Identify) UnmarshalJSON(data []byte) error { + return protojson.Unmarshal(data, v) +} + +// apparently this isn't stable, but it's awesomely better +// https://protobuf.dev/reference/go/faq/#unstable-text +// it's brilliant for config files! +func (v *Identify) FormatTEXT() string { + return prototext.Format(v) +} + +// unmarshalTEXT. This reads the .text config file back in after the user edits it +func (v *Identify) UnmarshalTEXT(data []byte) error { + return prototext.Unmarshal(data, v) +} + +// marshal to wire. This is called winning. +func (v *Identify) Marshal() ([]byte, error) { + return proto.Marshal(v) +} + +// unmarshal from wire. You have won. +func (v *Identify) Unmarshal(data []byte) error { + return proto.Unmarshal(data, v) +} diff --git a/forgeConfig.pb.go b/forgeConfig.pb.go new file mode 100644 index 0000000..f72f72c --- /dev/null +++ b/forgeConfig.pb.go @@ -0,0 +1,652 @@ +// Code modified by go.wit.com/apps/autogenpb DO NOT EDIT. +// +// user defined Mutex locks were auto added +// +// autogenpb version & build time: v0.5.6-1-g08dc949 2025.09.23_0925 +// autogenpb auto generates Sort(), Unique() and Marshal() functions +// go install go.wit.com/apps/autogenpb@latest + +// Copyright 2025 WIT.COM Inc Licensed GPL 3.0 + +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.33.0 +// protoc v3.21.12 +// source: forgeConfig.proto + +package forgepb // autogenpb changed the package name + +import ( + reflect "reflect" + sync "sync" + + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + timestamppb "google.golang.org/protobuf/types/known/timestamppb" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +type ForgeMode int32 + +const ( + ForgeMode_MASTER ForgeMode = 0 // "release mode" + ForgeMode_DEVEL ForgeMode = 1 // "patch mode" + ForgeMode_USER ForgeMode = 2 // "work mode" + ForgeMode_NORMAL ForgeMode = 3 // "normal mode" // use this when you are developing code + ForgeMode_CLEAN ForgeMode = 4 // indicates "clean" was run +) + +// Enum value maps for ForgeMode. +var ( + ForgeMode_name = map[int32]string{ + 0: "MASTER", + 1: "DEVEL", + 2: "USER", + 3: "NORMAL", + 4: "CLEAN", + } + ForgeMode_value = map[string]int32{ + "MASTER": 0, + "DEVEL": 1, + "USER": 2, + "NORMAL": 3, + "CLEAN": 4, + } +) + +func (x ForgeMode) Enum() *ForgeMode { + p := new(ForgeMode) + *p = x + return p +} + +func (x ForgeMode) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (ForgeMode) Descriptor() protoreflect.EnumDescriptor { + return file_forgeConfig_proto_enumTypes[0].Descriptor() +} + +func (ForgeMode) Type() protoreflect.EnumType { + return &file_forgeConfig_proto_enumTypes[0] +} + +func (x ForgeMode) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use ForgeMode.Descriptor instead. +func (ForgeMode) EnumDescriptor() ([]byte, []int) { + return file_forgeConfig_proto_rawDescGZIP(), []int{0} +} + +type ForgeConfig struct { + // sync.RWMutex // skipped. protobuf file has `autogenpb:nomutex` + + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + GoPath string `protobuf:"bytes,1,opt,name=goPath,proto3" json:"goPath,omitempty"` // `autogenpb:unique` `autogenpb:sort` // Examples: 'go.wit.com/apps/go-clone' or "~/mythings" or "/home/src/foo" + Writable bool `protobuf:"varint,2,opt,name=writable,proto3" json:"writable,omitempty"` // if you have write access to the repo + ReadOnly bool `protobuf:"varint,3,opt,name=readOnly,proto3" json:"readOnly,omitempty"` // the opposite, but needed for now because I don't know what I'm doing + Private bool `protobuf:"varint,4,opt,name=private,proto3" json:"private,omitempty"` // if the repo can be published + Directory bool `protobuf:"varint,5,opt,name=directory,proto3" json:"directory,omitempty"` // everything in this directory should use these writable & private values + Favorite bool `protobuf:"varint,6,opt,name=favorite,proto3" json:"favorite,omitempty"` // you like this. always git clone/go clone this repo + Interesting bool `protobuf:"varint,7,opt,name=interesting,proto3" json:"interesting,omitempty"` // this is something interesting you found and want to remember it + MasterBranchName string `protobuf:"bytes,8,opt,name=masterBranchName,proto3" json:"masterBranchName,omitempty"` // git 'main' or 'master' branch name + DevelBranchName string `protobuf:"bytes,9,opt,name=develBranchName,proto3" json:"develBranchName,omitempty"` // whatever the git 'devel' branch name is + UserBranchName string `protobuf:"bytes,10,opt,name=userBranchName,proto3" json:"userBranchName,omitempty"` // whatever your username branch is + DebName string `protobuf:"bytes,11,opt,name=debName,proto3" json:"debName,omitempty"` // the actual name used with 'apt install' (or distro apt equivalent. + Verstamp *timestamppb.Timestamp `protobuf:"bytes,12,opt,name=verstamp,proto3" json:"verstamp,omitempty"` // the git commit timestamp of the version + GoSrc string `protobuf:"bytes,13,opt,name=goSrc,proto3" json:"goSrc,omitempty"` // is ~/go/src unless a go.work file is found + Namespace string `protobuf:"bytes,14,opt,name=namespace,proto3" json:"namespace,omitempty"` // `autogenpb:unique` `autogenpb:sort` +} + +func (x *ForgeConfig) Reset() { + *x = ForgeConfig{} + if protoimpl.UnsafeEnabled { + mi := &file_forgeConfig_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ForgeConfig) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ForgeConfig) ProtoMessage() {} + +func (x *ForgeConfig) ProtoReflect() protoreflect.Message { + mi := &file_forgeConfig_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ForgeConfig.ProtoReflect.Descriptor instead. +func (*ForgeConfig) Descriptor() ([]byte, []int) { + return file_forgeConfig_proto_rawDescGZIP(), []int{0} +} + +func (x *ForgeConfig) GetGoPath() string { + if x != nil { + return x.GoPath + } + return "" +} + +func (x *ForgeConfig) GetWritable() bool { + if x != nil { + return x.Writable + } + return false +} + +func (x *ForgeConfig) GetReadOnly() bool { + if x != nil { + return x.ReadOnly + } + return false +} + +func (x *ForgeConfig) GetPrivate() bool { + if x != nil { + return x.Private + } + return false +} + +func (x *ForgeConfig) GetDirectory() bool { + if x != nil { + return x.Directory + } + return false +} + +func (x *ForgeConfig) GetFavorite() bool { + if x != nil { + return x.Favorite + } + return false +} + +func (x *ForgeConfig) GetInteresting() bool { + if x != nil { + return x.Interesting + } + return false +} + +func (x *ForgeConfig) GetMasterBranchName() string { + if x != nil { + return x.MasterBranchName + } + return "" +} + +func (x *ForgeConfig) GetDevelBranchName() string { + if x != nil { + return x.DevelBranchName + } + return "" +} + +func (x *ForgeConfig) GetUserBranchName() string { + if x != nil { + return x.UserBranchName + } + return "" +} + +func (x *ForgeConfig) GetDebName() string { + if x != nil { + return x.DebName + } + return "" +} + +func (x *ForgeConfig) GetVerstamp() *timestamppb.Timestamp { + if x != nil { + return x.Verstamp + } + return nil +} + +func (x *ForgeConfig) GetGoSrc() string { + if x != nil { + return x.GoSrc + } + return "" +} + +func (x *ForgeConfig) GetNamespace() string { + if x != nil { + return x.Namespace + } + return "" +} + +type ForgeConfigs struct { + // sync.RWMutex // skipped. protobuf file has `autogenpb:nomutex` + + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Uuid string `protobuf:"bytes,1,opt,name=uuid,proto3" json:"uuid,omitempty"` // `autogenpb:uuid:1941cd4f-1cfd-4bf6-aa75-c2c391907e81` + Version string `protobuf:"bytes,2,opt,name=version,proto3" json:"version,omitempty"` // `autogenpb:version:v0.0.47` + ForgeConfigs []*ForgeConfig `protobuf:"bytes,3,rep,name=ForgeConfigs,proto3" json:"ForgeConfigs,omitempty"` + Username string `protobuf:"bytes,4,opt,name=username,proto3" json:"username,omitempty"` // what to use for the user branch (default ENV{USER}) + Xterm string `protobuf:"bytes,5,opt,name=xterm,proto3" json:"xterm,omitempty"` // what xterm the user wants as the default + XtermArgv []string `protobuf:"bytes,6,rep,name=xtermArgv,proto3" json:"xtermArgv,omitempty"` // the argv line for xterm + DefaultGui string `protobuf:"bytes,7,opt,name=defaultGui,proto3" json:"defaultGui,omitempty"` // default GUI plugin to use + Mode ForgeMode `protobuf:"varint,8,opt,name=mode,proto3,enum=forgepb.ForgeMode" json:"mode,omitempty"` // what "mode" forge is in + GoWork bool `protobuf:"varint,9,opt,name=goWork,proto3" json:"goWork,omitempty"` // true if there is a go.work file + PathLock bool `protobuf:"varint,10,opt,name=pathLock,proto3" json:"pathLock,omitempty"` // the path is locked + ReposPB string `protobuf:"bytes,11,opt,name=ReposPB,proto3" json:"ReposPB,omitempty"` // where the repos.pb is + ReposDir string `protobuf:"bytes,12,opt,name=ReposDir,proto3" json:"ReposDir,omitempty"` // where the repos are + PatchDir string `protobuf:"bytes,13,opt,name=PatchDir,proto3" json:"PatchDir,omitempty"` // patch dir + ForgeURL string `protobuf:"bytes,14,opt,name=ForgeURL,proto3" json:"ForgeURL,omitempty"` // forge URL + Filename string `protobuf:"bytes,15,opt,name=Filename,proto3" json:"Filename,omitempty"` // filename of the config file + RillX int32 `protobuf:"varint,16,opt,name=rillX,proto3" json:"rillX,omitempty"` // used by rill + RillY int32 `protobuf:"varint,17,opt,name=rillY,proto3" json:"rillY,omitempty"` // used by rill +} + +func (x *ForgeConfigs) Reset() { + *x = ForgeConfigs{} + if protoimpl.UnsafeEnabled { + mi := &file_forgeConfig_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ForgeConfigs) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ForgeConfigs) ProtoMessage() {} + +func (x *ForgeConfigs) ProtoReflect() protoreflect.Message { + mi := &file_forgeConfig_proto_msgTypes[1] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ForgeConfigs.ProtoReflect.Descriptor instead. +func (*ForgeConfigs) Descriptor() ([]byte, []int) { + return file_forgeConfig_proto_rawDescGZIP(), []int{1} +} + +func (x *ForgeConfigs) GetUuid() string { + if x != nil { + return x.Uuid + } + return "" +} + +func (x *ForgeConfigs) GetVersion() string { + if x != nil { + return x.Version + } + return "" +} + +func (x *ForgeConfigs) GetForgeConfigs() []*ForgeConfig { + if x != nil { + return x.ForgeConfigs + } + return nil +} + +func (x *ForgeConfigs) GetUsername() string { + if x != nil { + return x.Username + } + return "" +} + +func (x *ForgeConfigs) GetXterm() string { + if x != nil { + return x.Xterm + } + return "" +} + +func (x *ForgeConfigs) GetXtermArgv() []string { + if x != nil { + return x.XtermArgv + } + return nil +} + +func (x *ForgeConfigs) GetDefaultGui() string { + if x != nil { + return x.DefaultGui + } + return "" +} + +func (x *ForgeConfigs) GetMode() ForgeMode { + if x != nil { + return x.Mode + } + return ForgeMode_MASTER +} + +func (x *ForgeConfigs) GetGoWork() bool { + if x != nil { + return x.GoWork + } + return false +} + +func (x *ForgeConfigs) GetPathLock() bool { + if x != nil { + return x.PathLock + } + return false +} + +func (x *ForgeConfigs) GetReposPB() string { + if x != nil { + return x.ReposPB + } + return "" +} + +func (x *ForgeConfigs) GetReposDir() string { + if x != nil { + return x.ReposDir + } + return "" +} + +func (x *ForgeConfigs) GetPatchDir() string { + if x != nil { + return x.PatchDir + } + return "" +} + +func (x *ForgeConfigs) GetForgeURL() string { + if x != nil { + return x.ForgeURL + } + return "" +} + +func (x *ForgeConfigs) GetFilename() string { + if x != nil { + return x.Filename + } + return "" +} + +func (x *ForgeConfigs) GetRillX() int32 { + if x != nil { + return x.RillX + } + return 0 +} + +func (x *ForgeConfigs) GetRillY() int32 { + if x != nil { + return x.RillY + } + return 0 +} + +// this generic message is used by autogen to identify and +// then dump the uuid and version from any arbitrary .pb file +type Identify struct { + sync.RWMutex // auto-added by go.wit.com/apps/autogenpb + + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Uuid string `protobuf:"bytes,1,opt,name=uuid,proto3" json:"uuid,omitempty"` // + Version string `protobuf:"bytes,2,opt,name=version,proto3" json:"version,omitempty"` // +} + +func (x *Identify) Reset() { + *x = Identify{} + if protoimpl.UnsafeEnabled { + mi := &file_forgeConfig_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Identify) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Identify) ProtoMessage() {} + +func (x *Identify) ProtoReflect() protoreflect.Message { + mi := &file_forgeConfig_proto_msgTypes[2] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Identify.ProtoReflect.Descriptor instead. +func (*Identify) Descriptor() ([]byte, []int) { + return file_forgeConfig_proto_rawDescGZIP(), []int{2} +} + +func (x *Identify) GetUuid() string { + if x != nil { + return x.Uuid + } + return "" +} + +func (x *Identify) GetVersion() string { + if x != nil { + return x.Version + } + return "" +} + +var File_forgeConfig_proto protoreflect.FileDescriptor + +var file_forgeConfig_proto_rawDesc = []byte{ + 0x0a, 0x11, 0x66, 0x6f, 0x72, 0x67, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x12, 0x07, 0x66, 0x6f, 0x72, 0x67, 0x65, 0x70, 0x62, 0x1a, 0x1f, 0x67, 0x6f, + 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x74, 0x69, + 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xd7, 0x03, + 0x0a, 0x0b, 0x46, 0x6f, 0x72, 0x67, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x16, 0x0a, + 0x06, 0x67, 0x6f, 0x50, 0x61, 0x74, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x67, + 0x6f, 0x50, 0x61, 0x74, 0x68, 0x12, 0x1a, 0x0a, 0x08, 0x77, 0x72, 0x69, 0x74, 0x61, 0x62, 0x6c, + 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x77, 0x72, 0x69, 0x74, 0x61, 0x62, 0x6c, + 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x72, 0x65, 0x61, 0x64, 0x4f, 0x6e, 0x6c, 0x79, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x08, 0x52, 0x08, 0x72, 0x65, 0x61, 0x64, 0x4f, 0x6e, 0x6c, 0x79, 0x12, 0x18, 0x0a, + 0x07, 0x70, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, + 0x70, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x64, 0x69, 0x72, 0x65, 0x63, + 0x74, 0x6f, 0x72, 0x79, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x64, 0x69, 0x72, 0x65, + 0x63, 0x74, 0x6f, 0x72, 0x79, 0x12, 0x1a, 0x0a, 0x08, 0x66, 0x61, 0x76, 0x6f, 0x72, 0x69, 0x74, + 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x66, 0x61, 0x76, 0x6f, 0x72, 0x69, 0x74, + 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, + 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x65, 0x73, 0x74, + 0x69, 0x6e, 0x67, 0x12, 0x2a, 0x0a, 0x10, 0x6d, 0x61, 0x73, 0x74, 0x65, 0x72, 0x42, 0x72, 0x61, + 0x6e, 0x63, 0x68, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x6d, + 0x61, 0x73, 0x74, 0x65, 0x72, 0x42, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x4e, 0x61, 0x6d, 0x65, 0x12, + 0x28, 0x0a, 0x0f, 0x64, 0x65, 0x76, 0x65, 0x6c, 0x42, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x4e, 0x61, + 0x6d, 0x65, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x64, 0x65, 0x76, 0x65, 0x6c, 0x42, + 0x72, 0x61, 0x6e, 0x63, 0x68, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x26, 0x0a, 0x0e, 0x75, 0x73, 0x65, + 0x72, 0x42, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x0a, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x0e, 0x75, 0x73, 0x65, 0x72, 0x42, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x4e, 0x61, 0x6d, + 0x65, 0x12, 0x18, 0x0a, 0x07, 0x64, 0x65, 0x62, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x0b, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x07, 0x64, 0x65, 0x62, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x36, 0x0a, 0x08, 0x76, + 0x65, 0x72, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, + 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, + 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x08, 0x76, 0x65, 0x72, 0x73, 0x74, + 0x61, 0x6d, 0x70, 0x12, 0x14, 0x0a, 0x05, 0x67, 0x6f, 0x53, 0x72, 0x63, 0x18, 0x0d, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x05, 0x67, 0x6f, 0x53, 0x72, 0x63, 0x12, 0x1c, 0x0a, 0x09, 0x6e, 0x61, 0x6d, + 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6e, 0x61, + 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x22, 0xf8, 0x03, 0x0a, 0x0c, 0x46, 0x6f, 0x72, 0x67, + 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x75, 0x75, 0x69, 0x64, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x75, 0x75, 0x69, 0x64, 0x12, 0x18, 0x0a, 0x07, + 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x76, + 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x38, 0x0a, 0x0c, 0x46, 0x6f, 0x72, 0x67, 0x65, 0x43, + 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x66, + 0x6f, 0x72, 0x67, 0x65, 0x70, 0x62, 0x2e, 0x46, 0x6f, 0x72, 0x67, 0x65, 0x43, 0x6f, 0x6e, 0x66, + 0x69, 0x67, 0x52, 0x0c, 0x46, 0x6f, 0x72, 0x67, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x73, + 0x12, 0x1a, 0x0a, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x04, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x14, 0x0a, 0x05, + 0x78, 0x74, 0x65, 0x72, 0x6d, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x78, 0x74, 0x65, + 0x72, 0x6d, 0x12, 0x1c, 0x0a, 0x09, 0x78, 0x74, 0x65, 0x72, 0x6d, 0x41, 0x72, 0x67, 0x76, 0x18, + 0x06, 0x20, 0x03, 0x28, 0x09, 0x52, 0x09, 0x78, 0x74, 0x65, 0x72, 0x6d, 0x41, 0x72, 0x67, 0x76, + 0x12, 0x1e, 0x0a, 0x0a, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x47, 0x75, 0x69, 0x18, 0x07, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x47, 0x75, 0x69, + 0x12, 0x26, 0x0a, 0x04, 0x6d, 0x6f, 0x64, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x12, + 0x2e, 0x66, 0x6f, 0x72, 0x67, 0x65, 0x70, 0x62, 0x2e, 0x46, 0x6f, 0x72, 0x67, 0x65, 0x4d, 0x6f, + 0x64, 0x65, 0x52, 0x04, 0x6d, 0x6f, 0x64, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x67, 0x6f, 0x57, 0x6f, + 0x72, 0x6b, 0x18, 0x09, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x67, 0x6f, 0x57, 0x6f, 0x72, 0x6b, + 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x61, 0x74, 0x68, 0x4c, 0x6f, 0x63, 0x6b, 0x18, 0x0a, 0x20, 0x01, + 0x28, 0x08, 0x52, 0x08, 0x70, 0x61, 0x74, 0x68, 0x4c, 0x6f, 0x63, 0x6b, 0x12, 0x18, 0x0a, 0x07, + 0x52, 0x65, 0x70, 0x6f, 0x73, 0x50, 0x42, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x52, + 0x65, 0x70, 0x6f, 0x73, 0x50, 0x42, 0x12, 0x1a, 0x0a, 0x08, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x44, + 0x69, 0x72, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x44, + 0x69, 0x72, 0x12, 0x1a, 0x0a, 0x08, 0x50, 0x61, 0x74, 0x63, 0x68, 0x44, 0x69, 0x72, 0x18, 0x0d, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x50, 0x61, 0x74, 0x63, 0x68, 0x44, 0x69, 0x72, 0x12, 0x1a, + 0x0a, 0x08, 0x46, 0x6f, 0x72, 0x67, 0x65, 0x55, 0x52, 0x4c, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x08, 0x46, 0x6f, 0x72, 0x67, 0x65, 0x55, 0x52, 0x4c, 0x12, 0x1a, 0x0a, 0x08, 0x46, 0x69, + 0x6c, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x46, 0x69, + 0x6c, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x72, 0x69, 0x6c, 0x6c, 0x58, 0x18, + 0x10, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x72, 0x69, 0x6c, 0x6c, 0x58, 0x12, 0x14, 0x0a, 0x05, + 0x72, 0x69, 0x6c, 0x6c, 0x59, 0x18, 0x11, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x72, 0x69, 0x6c, + 0x6c, 0x59, 0x22, 0x38, 0x0a, 0x08, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x79, 0x12, 0x12, + 0x0a, 0x04, 0x75, 0x75, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x75, 0x75, + 0x69, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x2a, 0x43, 0x0a, 0x09, + 0x46, 0x6f, 0x72, 0x67, 0x65, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x0a, 0x0a, 0x06, 0x4d, 0x41, 0x53, + 0x54, 0x45, 0x52, 0x10, 0x00, 0x12, 0x09, 0x0a, 0x05, 0x44, 0x45, 0x56, 0x45, 0x4c, 0x10, 0x01, + 0x12, 0x08, 0x0a, 0x04, 0x55, 0x53, 0x45, 0x52, 0x10, 0x02, 0x12, 0x0a, 0x0a, 0x06, 0x4e, 0x4f, + 0x52, 0x4d, 0x41, 0x4c, 0x10, 0x03, 0x12, 0x09, 0x0a, 0x05, 0x43, 0x4c, 0x45, 0x41, 0x4e, 0x10, + 0x04, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, +} + +var ( + file_forgeConfig_proto_rawDescOnce sync.Once + file_forgeConfig_proto_rawDescData = file_forgeConfig_proto_rawDesc +) + +func file_forgeConfig_proto_rawDescGZIP() []byte { + file_forgeConfig_proto_rawDescOnce.Do(func() { + file_forgeConfig_proto_rawDescData = protoimpl.X.CompressGZIP(file_forgeConfig_proto_rawDescData) + }) + return file_forgeConfig_proto_rawDescData +} + +var file_forgeConfig_proto_enumTypes = make([]protoimpl.EnumInfo, 1) +var file_forgeConfig_proto_msgTypes = make([]protoimpl.MessageInfo, 3) +var file_forgeConfig_proto_goTypes = []interface{}{ + (ForgeMode)(0), // 0: forgepb.ForgeMode + (*ForgeConfig)(nil), // 1: forgepb.ForgeConfig + (*ForgeConfigs)(nil), // 2: forgepb.ForgeConfigs + (*Identify)(nil), // 3: forgepb.Identify + (*timestamppb.Timestamp)(nil), // 4: google.protobuf.Timestamp +} +var file_forgeConfig_proto_depIdxs = []int32{ + 4, // 0: forgepb.ForgeConfig.verstamp:type_name -> google.protobuf.Timestamp + 1, // 1: forgepb.ForgeConfigs.ForgeConfigs:type_name -> forgepb.ForgeConfig + 0, // 2: forgepb.ForgeConfigs.mode:type_name -> forgepb.ForgeMode + 3, // [3:3] is the sub-list for method output_type + 3, // [3:3] is the sub-list for method input_type + 3, // [3:3] is the sub-list for extension type_name + 3, // [3:3] is the sub-list for extension extendee + 0, // [0:3] is the sub-list for field type_name +} + +func init() { file_forgeConfig_proto_init() } +func file_forgeConfig_proto_init() { + if File_forgeConfig_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_forgeConfig_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ForgeConfig); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_forgeConfig_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ForgeConfigs); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_forgeConfig_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Identify); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_forgeConfig_proto_rawDesc, + NumEnums: 1, + NumMessages: 3, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_forgeConfig_proto_goTypes, + DependencyIndexes: file_forgeConfig_proto_depIdxs, + EnumInfos: file_forgeConfig_proto_enumTypes, + MessageInfos: file_forgeConfig_proto_msgTypes, + }.Build() + File_forgeConfig_proto = out.File + file_forgeConfig_proto_rawDesc = nil + file_forgeConfig_proto_goTypes = nil + file_forgeConfig_proto_depIdxs = nil +} diff --git a/forgeConfig.sort.pb.go b/forgeConfig.sort.pb.go new file mode 100644 index 0000000..877bdbd --- /dev/null +++ b/forgeConfig.sort.pb.go @@ -0,0 +1,413 @@ +// Code generated by go.wit.com/apps/autogenpb DO NOT EDIT. +// This file was autogenerated with autogenpb v0.5.6-1-g08dc949 2025.09.23_0925 +// go install go.wit.com/apps/autogenpb@latest +// +// define which structs (messages) you want to use in the .proto file +// Then sort.pb.go and marshal.pb.go files are autogenerated +// +// autogenpb uses it and has an example .proto file with instructions +// + +package forgepb + +import ( + "fmt" + "iter" + "sort" + "sync" + + "google.golang.org/protobuf/proto" +) + +// a simple global lock +var forgeConfigMu sync.RWMutex + +func (x *ForgeConfigs) fixUuid() { + if x == nil { + return + } + if x.Uuid == "1941cd4f-1cfd-4bf6-aa75-c2c391907e81" { + return + } + x.Uuid = "1941cd4f-1cfd-4bf6-aa75-c2c391907e81" + x.Version = "v0.0.47 go.wit.com/lib/protobuf/forgepb" +} + +func NewForgeConfigs() *ForgeConfigs { + x := new(ForgeConfigs) + x.Uuid = "1941cd4f-1cfd-4bf6-aa75-c2c391907e81" + x.Version = "v0.0.47 go.wit.com/lib/protobuf/forgepb" + return x +} + +// START SORT + +// DEFINE THE ForgeConfigs SCANNER. +// itializes a new scanner. +func newForgeConfigsScanner(things []*ForgeConfigs) *ForgeConfigsScanner { + return &ForgeConfigsScanner{things: things} +} + +type ForgeConfigsScanner struct { + sync.Mutex + + things []*ForgeConfigs + index int +} + +func (it *ForgeConfigsScanner) Scan() bool { + if it.index >= len(it.things) { + return false + } + it.Lock() + it.index++ + it.Unlock() + return true +} + +// Next() returns the next thing in the array +func (it *ForgeConfigsScanner) Next() *ForgeConfigs { + if it.things[it.index-1] == nil { + fmt.Println("Next() error in ForgeConfigsScanner", it.index) + } + return it.things[it.index-1] +} + +// END DEFINE THE SCANNER + +// DEFINE THE ForgeConfig SCANNER. +// itializes a new scanner. +func newForgeConfigScanner(things []*ForgeConfig) *ForgeConfigScanner { + return &ForgeConfigScanner{things: things} +} + +type ForgeConfigScanner struct { + sync.Mutex + + things []*ForgeConfig + index int +} + +func (it *ForgeConfigScanner) Scan() bool { + if it.index >= len(it.things) { + return false + } + it.Lock() + it.index++ + it.Unlock() + return true +} + +// Next() returns the next thing in the array +func (it *ForgeConfigScanner) Next() *ForgeConfig { + if it.things[it.index-1] == nil { + fmt.Println("Next() error in ForgeConfigScanner", it.index) + } + return it.things[it.index-1] +} + +// END DEFINE THE SCANNER + +// DEFINE THE Identify SCANNER. +// itializes a new scanner. +func newIdentifyScanner(things []*Identify) *IdentifyScanner { + return &IdentifyScanner{things: things} +} + +type IdentifyScanner struct { + sync.Mutex + + things []*Identify + index int +} + +func (it *IdentifyScanner) Scan() bool { + if it.index >= len(it.things) { + return false + } + it.Lock() + it.index++ + it.Unlock() + return true +} + +// Next() returns the next thing in the array +func (it *IdentifyScanner) Next() *Identify { + if it.things[it.index-1] == nil { + fmt.Println("Next() error in IdentifyScanner", it.index) + } + return it.things[it.index-1] +} + +// END DEFINE THE SCANNER + +// sort struct by GoPath +type sortForgeConfigGoPath []*ForgeConfig + +func (a sortForgeConfigGoPath) Len() int { return len(a) } +func (a sortForgeConfigGoPath) Less(i, j int) bool { return a[i].GoPath < a[j].GoPath } +func (a sortForgeConfigGoPath) Swap(i, j int) { a[i], a[j] = a[j], a[i] } + +// sort struct by Namespace +type sortForgeConfigNamespace []*ForgeConfig + +func (a sortForgeConfigNamespace) Len() int { return len(a) } +func (a sortForgeConfigNamespace) Less(i, j int) bool { return a[i].Namespace < a[j].Namespace } +func (a sortForgeConfigNamespace) Swap(i, j int) { a[i], a[j] = a[j], a[i] } + +// safely returns a slice of pointers to the FRUIT protobufs +func (x *ForgeConfigs) allForgeConfigs() []*ForgeConfig { + forgeConfigMu.RLock() + defer forgeConfigMu.RUnlock() + + // Create a new slice to hold pointers to each FRUIT + var tmp []*ForgeConfig + tmp = make([]*ForgeConfig, len(x.ForgeConfigs)) + for i, p := range x.ForgeConfigs { + tmp[i] = p // Copy pointers for safe iteration + } + + return tmp +} + +// safely returns a slice of pointers to the ForgeConfig protobufs +func (x *ForgeConfigs) selectAllForgeConfigs() []*ForgeConfig { + forgeConfigMu.RLock() + defer forgeConfigMu.RUnlock() + + // Create a new slice to hold pointers to each ForgeConfig + var tmp []*ForgeConfig + tmp = make([]*ForgeConfig, len(x.ForgeConfigs)) + for i, p := range x.ForgeConfigs { + tmp[i] = p // Copy pointers for safe iteration + } + + return tmp +} +func (x *ForgeConfigs) SortByGoPath() *ForgeConfigScanner { + // copy the pointers as fast as possible. + things := x.selectAllForgeConfigs() + + // todo: try slices.SortFunc() instead to see what happens + sort.Sort(sortForgeConfigGoPath(things)) + // slices.SortFunc(things, func(a, b *ForgeConfigs) bool { + // return a.GoPath < b.GoPath // Sort by ??. let the compiler work it out?? + // }) + return newForgeConfigScanner(things) +} + +// 'for x := range' syntax using the awesome golang 1.24 'iter' +func (x *ForgeConfigs) IterByGoPath() iter.Seq[*ForgeConfig] { + items := x.selectAllForgeConfigs() + sort.Sort(sortForgeConfigGoPath(items)) + // log.Println("Made Iter.Seq[] with length", len(items)) + return func(yield func(*ForgeConfig) bool) { + for _, v := range items { + if !yield(v) { + return + } + } + } +} +func (x *ForgeConfigs) SortByNamespace() *ForgeConfigScanner { + // copy the pointers as fast as possible. + things := x.selectAllForgeConfigs() + + // todo: try slices.SortFunc() instead to see what happens + sort.Sort(sortForgeConfigNamespace(things)) + // slices.SortFunc(things, func(a, b *ForgeConfigs) bool { + // return a.Namespace < b.Namespace // Sort by ??. let the compiler work it out?? + // }) + return newForgeConfigScanner(things) +} + +// 'for x := range' syntax using the awesome golang 1.24 'iter' +func (x *ForgeConfigs) IterByNamespace() iter.Seq[*ForgeConfig] { + items := x.selectAllForgeConfigs() + sort.Sort(sortForgeConfigNamespace(items)) + // log.Println("Made Iter.Seq[] with length", len(items)) + return func(yield func(*ForgeConfig) bool) { + for _, v := range items { + if !yield(v) { + return + } + } + } +} + +// END SORT + +func (x *ForgeConfigs) Len() int { + forgeConfigMu.RLock() + defer forgeConfigMu.RUnlock() + + return len(x.ForgeConfigs) +} + +// a Append() shortcut (that does Clone() with a mutex) notsure if it really works +func (x *ForgeConfigs) Append(y *ForgeConfig) *ForgeConfig { + forgeConfigMu.Lock() + defer forgeConfigMu.Unlock() + + z := proto.Clone(y).(*ForgeConfig) + x.ForgeConfigs = append(x.ForgeConfigs, z) + + return z +} + +func (x *ForgeConfigs) All() *ForgeConfigScanner { + ForgeConfigPointers := x.selectAllForgeConfigs() + + scanner := newForgeConfigScanner(ForgeConfigPointers) + return scanner +} + +// Iterate 'for x := range' syntax using the awesome golang 1.24 'iter' +func (x *ForgeConfigs) IterAll() iter.Seq[*ForgeConfig] { + items := x.selectAllForgeConfigs() + // log.Println("Made All() Iter.Seq[] with length", len(items)) + return func(yield func(*ForgeConfig) bool) { + for _, v := range items { + if !yield(v) { + return + } + } + } +} +func (x *ForgeConfigs) Delete(y *ForgeConfig) bool { + forgeConfigMu.Lock() + defer forgeConfigMu.Unlock() + + for i, _ := range x.ForgeConfigs { + if x.ForgeConfigs[i] == y { + x.ForgeConfigs[i] = x.ForgeConfigs[len(x.ForgeConfigs)-1] + x.ForgeConfigs = x.ForgeConfigs[:len(x.ForgeConfigs)-1] + return true + } + } + return false +} + +// lookup a ForgeConfigs by the GoPath +func (x *ForgeConfigs) FindByGoPath(s string) *ForgeConfig { + if x == nil { + return nil + } + + forgeConfigMu.RLock() + defer forgeConfigMu.RUnlock() + + for i, _ := range x.ForgeConfigs { + if x.ForgeConfigs[i].GoPath == s { + return x.ForgeConfigs[i] + } + } + return nil +} + +// returns a ForgeConfig if GoPath matches, otherwise create +func (x *ForgeConfigs) InsertByGoPath(y string) *ForgeConfig { + forgeConfigMu.Lock() + defer forgeConfigMu.Unlock() + + for _, z := range x.ForgeConfigs { + if z.GoPath == y { + return z + } + } + + z := new(ForgeConfig) + z.GoPath = y + x.ForgeConfigs = append(x.ForgeConfigs, z) + return z +} + +// lookup a ForgeConfigs by the Namespace +func (x *ForgeConfigs) FindByNamespace(s string) *ForgeConfig { + if x == nil { + return nil + } + + forgeConfigMu.RLock() + defer forgeConfigMu.RUnlock() + + for i, _ := range x.ForgeConfigs { + if x.ForgeConfigs[i].Namespace == s { + return x.ForgeConfigs[i] + } + } + return nil +} + +// returns a ForgeConfig if Namespace matches, otherwise create +func (x *ForgeConfigs) InsertByNamespace(y string) *ForgeConfig { + forgeConfigMu.Lock() + defer forgeConfigMu.Unlock() + + for _, z := range x.ForgeConfigs { + if z.Namespace == y { + return z + } + } + + z := new(ForgeConfig) + z.Namespace = y + x.ForgeConfigs = append(x.ForgeConfigs, z) + return z +} + +func (x *ForgeConfigs) DeleteByGoPath(s string) bool { + forgeConfigMu.Lock() + defer forgeConfigMu.Unlock() + + for i, _ := range x.ForgeConfigs { + if x.ForgeConfigs[i].GoPath == s { + x.ForgeConfigs[i] = x.ForgeConfigs[len(x.ForgeConfigs)-1] + x.ForgeConfigs = x.ForgeConfigs[:len(x.ForgeConfigs)-1] + return true + } + } + return false +} + +func (x *ForgeConfigs) DeleteByNamespace(s string) bool { + forgeConfigMu.Lock() + defer forgeConfigMu.Unlock() + + for i, _ := range x.ForgeConfigs { + if x.ForgeConfigs[i].Namespace == s { + x.ForgeConfigs[i] = x.ForgeConfigs[len(x.ForgeConfigs)-1] + x.ForgeConfigs = x.ForgeConfigs[:len(x.ForgeConfigs)-1] + return true + } + } + return false +} + +func (x *ForgeConfigs) AppendByGoPath(y *ForgeConfig) bool { + forgeConfigMu.Lock() + defer forgeConfigMu.Unlock() + + for _, p := range x.ForgeConfigs { + if p.GoPath == y.GoPath { + return false + } + } + + x.ForgeConfigs = append(x.ForgeConfigs, proto.Clone(y).(*ForgeConfig)) + return true +} + +func (x *ForgeConfigs) AppendByNamespace(y *ForgeConfig) bool { + forgeConfigMu.Lock() + defer forgeConfigMu.Unlock() + + for _, p := range x.ForgeConfigs { + if p.Namespace == y.Namespace { + return false + } + } + + x.ForgeConfigs = append(x.ForgeConfigs, proto.Clone(y).(*ForgeConfig)) + return true +} diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..809a2b8 --- /dev/null +++ b/go.mod @@ -0,0 +1,31 @@ +module go.wit.com/lib/protobuf/forgepb + +go 1.24.1 + +require ( + github.com/destel/rill v0.8.0 + github.com/google/uuid v1.6.0 + go.wit.com/gui v0.25.3 + go.wit.com/lib/cobol v0.0.7 + go.wit.com/lib/config v0.0.5 + go.wit.com/lib/fhelp v0.0.23 + go.wit.com/lib/gui/prep v0.0.11 + go.wit.com/lib/gui/shell v0.22.33 + go.wit.com/lib/hostname v0.0.4 + go.wit.com/lib/protobuf/gitpb v0.0.132 + go.wit.com/lib/protobuf/guipb v0.0.15 + go.wit.com/lib/protobuf/httppb v0.0.10 + go.wit.com/log v0.25.1 + google.golang.org/protobuf v1.36.9 +) + +require ( + github.com/alexflint/go-scalar v1.2.0 // indirect + github.com/go-cmd/cmd v1.4.3 // indirect + go.wit.com/dev/alexflint/arg v1.6.3 // indirect + go.wit.com/lib/protobuf/bugpb v0.0.6 // indirect + go.wit.com/widget v1.1.30 // indirect + golang.org/x/sys v0.36.0 // indirect + golang.org/x/term v0.35.0 // indirect + golang.org/x/text v0.29.0 // indirect +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..15e8b01 --- /dev/null +++ b/go.sum @@ -0,0 +1,58 @@ +github.com/alexflint/go-scalar v1.2.0 h1:WR7JPKkeNpnYIOfHRa7ivM21aWAdHD0gEWHCx+WQBRw= +github.com/alexflint/go-scalar v1.2.0/go.mod h1:LoFvNMqS1CPrMVltza4LvnGKhaSpc3oyLEBUZVhhS2o= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/destel/rill v0.8.0 h1:PzWvw4Du+9SUy87riG/Ef4GHQpYX8qDtPMYzu40Lqvw= +github.com/destel/rill v0.8.0/go.mod h1:srKuXzvGqINUEGYR5b/iwvW+L9/S35RxVHWGYbXNoO4= +github.com/go-cmd/cmd v1.4.3 h1:6y3G+3UqPerXvPcXvj+5QNPHT02BUw7p6PsqRxLNA7Y= +github.com/go-cmd/cmd v1.4.3/go.mod h1:u3hxg/ry+D5kwh8WvUkHLAMe2zQCaXd00t35WfQaOFk= +github.com/go-test/deep v1.1.0 h1:WOcxcdHcvdgThNXjw0t76K42FXTU7HpNQWHpA2HHNlg= +github.com/go-test/deep v1.1.0/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncVwcsE= +github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= +github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= +go.wit.com/dev/alexflint/arg v1.6.3 h1:EduPl3oA/Sk4XcBVM7EYERlHjvbyEDysK5PqI/Wmdtw= +go.wit.com/dev/alexflint/arg v1.6.3/go.mod h1:RKOrAnxFl+856vbfvMEYcdd4qgBq2ZEO8atUcINendY= +go.wit.com/gui v0.25.3 h1:kDUzh/z52ghRlp/urVFCrDEIlkrfsKRmObN3LjbwsBU= +go.wit.com/gui v0.25.3/go.mod h1:H02phAerHwzSZMAb9mhL8rr7/zCbjASU8Cmg97tNvxY= +go.wit.com/lib/cobol v0.0.7 h1:VCU6cq0gBskkJop7IUhu9DddlCV5tYgRELp44vF+osw= +go.wit.com/lib/cobol v0.0.7/go.mod h1:F0bGWpoHVTOPUIq3bshRq/2/ViRGMnWDP3iwQIgeu/o= +go.wit.com/lib/config v0.0.5 h1:sHgY4PSpEeiNSJFDQGXOkbgmXrOGU/8+4HjqEiqo43w= +go.wit.com/lib/config v0.0.5/go.mod h1:dZ3Jr3sIjvCWcQX4cZxNFiUcjUAmwT85S8B140DWeS8= +go.wit.com/lib/fhelp v0.0.23 h1:XWQLxxS603xQwJ5IKjCKQ5vNeiivh3jfVrmDdc5piJ8= +go.wit.com/lib/fhelp v0.0.23/go.mod h1:8lRn3kJUuxkhief0JjbxL/ydw06ZJx/HLw7eMx9Xx9Y= +go.wit.com/lib/gui/prep v0.0.11 h1:8lla9pdZ3KkQVgt+F77imtqSMBkXZaFxIwXLcjBgW8E= +go.wit.com/lib/gui/prep v0.0.11/go.mod h1:6lgucjv3/RvzUV2tuo/Loh3WZNlePVRYEsEfiFIy97s= +go.wit.com/lib/gui/shell v0.22.33 h1:3MvWBQU4rOHK4Ac5MkQ62ndW7WhCBpu9F3AVeUF7YgQ= +go.wit.com/lib/gui/shell v0.22.33/go.mod h1:aRDwKXKXkZaO4y/0KPe1lhKQCXpyi8hXgUEOrHhzpAI= +go.wit.com/lib/hostname v0.0.4 h1:N8QobXDg31BaZGMDdWzX8rwENBGJNoO6xvGzPrzjsx0= +go.wit.com/lib/hostname v0.0.4/go.mod h1:6iQeqUdkbL7NHx29Ax5pw1rCrjyvRGG9NlHU/BvBlTg= +go.wit.com/lib/protobuf/bugpb v0.0.6 h1:IJNEPHphShQujSl7fP7sh5rQyCLxB5Uk/uoGzMx+/Z8= +go.wit.com/lib/protobuf/bugpb v0.0.6/go.mod h1:CIMtL7AS0Gx8K9ChgL80Omk25WWIFTG2stt1BzclySw= +go.wit.com/lib/protobuf/gitpb v0.0.132 h1:8/aNQfBtK8B3/NJV/qKhT+i2zgpCz6ZBtA0GuNn0USs= +go.wit.com/lib/protobuf/gitpb v0.0.132/go.mod h1:2zLW3GRz7vIohjRhjGP24kSSMv09R74x+nk0ounmEyc= +go.wit.com/lib/protobuf/guipb v0.0.15 h1:0MJ9FNFuUuNS8AsK+UcgGGnb3Xlw+ve7AbWLnHyIJ08= +go.wit.com/lib/protobuf/guipb v0.0.15/go.mod h1:9AzFoNKnE0161IOTfdul6SX5+GPAFNW7RPKWohenmcQ= +go.wit.com/lib/protobuf/httppb v0.0.10 h1:PwCQ16z0FcPUFOCXiZWJKXTygqj50Jw5pmCgcarvDq4= +go.wit.com/lib/protobuf/httppb v0.0.10/go.mod h1:4NdIampDfAKkFY9rdG7GcnTSTsQisyxCMWxO+b7GwCo= +go.wit.com/log v0.25.1 h1:74WVf9NSN6z5jc2oSbA1ehxdZ7V/NBXTk5t0jIoaTMg= +go.wit.com/log v0.25.1/go.mod h1:XE4lTfAibWgwBJksIk7u3IEJ8xcBvNhnlewYAQGj2Ew= +go.wit.com/widget v1.1.30 h1:O/dIG7QtDrZkR5P6f8JAMyevBiMXSun9vL6F0KFAWV8= +go.wit.com/widget v1.1.30/go.mod h1:wj7TpAr2gk7Poa+v8XQkH1aidnTdgAa/a8GxrMtcztw= +golang.org/x/sys v0.36.0 h1:KVRy2GtZBrk1cBYA7MKu5bEZFxQk4NIDV6RLVcC8o0k= +golang.org/x/sys v0.36.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= +golang.org/x/term v0.35.0 h1:bZBVKBudEyhRcajGcNc3jIfWPqV4y/Kt2XcoigOWtDQ= +golang.org/x/term v0.35.0/go.mod h1:TPGtkTLesOwf2DE8CgVYiZinHAOuy5AYUYT1lENIZnA= +golang.org/x/text v0.29.0 h1:1neNs90w9YzJ9BocxfsQNHKuAT4pkghyXc4nhZ6sJvk= +golang.org/x/text v0.29.0/go.mod h1:7MhJOA9CD2qZyOKYazxdYMF85OwPdEr9jTtBpO7ydH4= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/protobuf v1.36.9 h1:w2gp2mA27hUeUzj9Ex9FBjsBm40zfaDtEWow293U7Iw= +google.golang.org/protobuf v1.36.9/go.mod h1:fuxRtAxBytpl4zzqUh6/eyUujkJdNiuEkXntxiD/uRU= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/patch.gui.pb.go b/patch.gui.pb.go new file mode 100644 index 0000000..82fcb84 --- /dev/null +++ b/patch.gui.pb.go @@ -0,0 +1,398 @@ +// Code generated by go.wit.com/apps/autogenpb DO NOT EDIT. +// This file was autogenerated with autogenpb v0.5.6-1-g08dc949 2025.09.23_0925 +// go install go.wit.com/apps/autogenpb@latest +// +// define which structs (messages) you want to use in the .proto file +// Then sort.pb.go and marshal.pb.go files are autogenerated +// +// autogenpb uses it and has an example .proto file with instructions +// + +package forgepb + +import ( + "time" + + "github.com/google/uuid" + "go.wit.com/gui" + "go.wit.com/lib/protobuf/guipb" + "go.wit.com/log" + "google.golang.org/protobuf/proto" + anypb "google.golang.org/protobuf/types/known/anypb" + timestamppb "google.golang.org/protobuf/types/known/timestamppb" + "google.golang.org/protobuf/types/known/wrapperspb" +) + +// START GUI + +func (x *Patches) NewTable(title string) *PatchesTable { + t := new(PatchesTable) + t.x = x + pb := new(guipb.Table) + pb.Title = title + t.pb = pb + return t +} + +// force the application to choose the type of data. this allows the GUI plugin to be smarter +func (t *PatchesTable) AddStringFunc(title string, f func(*Patch) string) *PatchAnyFunc { + t.pb.Order = append(t.pb.Order, title) + + sf := new(PatchAnyFunc) + sf.title = title + sf.f = func(x *Patch) any { + return f(x) + } + sf.attr = new(guipb.ColAttr) + sf.attr.Width = int32(sf.Width) + sf.attr.Type = guipb.ColAttr_STRING + + t.anyFuncs = append(t.anyFuncs, sf) + return sf +} + +// force the application to choose the type of data. this allows the GUI plugin to be smarter +func (t *PatchesTable) AddButtonFunc(title string, f func(*Patch) string) *PatchAnyFunc { + t.pb.Order = append(t.pb.Order, title) + + sf := new(PatchAnyFunc) + sf.title = title + sf.f = func(x *Patch) any { + return f(x) + } + sf.attr = new(guipb.ColAttr) + sf.attr.Width = int32(sf.Width) + sf.attr.Type = guipb.ColAttr_STRING + sf.attr.Click = true + + t.anyFuncs = append(t.anyFuncs, sf) + return sf +} + +// force the application to choose the type of data. this allows the GUI plugin to be smarter +func (t *PatchesTable) AddIntFunc(title string, f func(*Patch) int) *PatchAnyFunc { + t.pb.Order = append(t.pb.Order, title) + + sf := new(PatchAnyFunc) + sf.title = title + sf.f = func(x *Patch) any { + return f(x) + } + sf.attr = new(guipb.ColAttr) + sf.attr.Width = int32(sf.Width) + sf.attr.Type = guipb.ColAttr_INT + + t.anyFuncs = append(t.anyFuncs, sf) + return sf +} + +// force the application to choose the type of data. this allows the GUI plugin to be smarter +func (t *PatchesTable) AddTimeFunc(title string, f func(*Patch) time.Time) *PatchAnyFunc { + t.pb.Order = append(t.pb.Order, title) + + sf := new(PatchAnyFunc) + sf.title = title + sf.f = func(x *Patch) any { + return f(x) + } + sf.attr = new(guipb.ColAttr) + sf.attr.Width = int32(sf.Width) + sf.attr.Type = guipb.ColAttr_TIME + + // t.timeFuncs = append(t.timeFuncs, sf) + t.anyFuncs = append(t.anyFuncs, sf) + return sf +} + +func (sf *PatchAnyFunc) SetTitle(title string) { + sf.title = title +} + +func (mt *PatchesTable) SetParent(p *gui.Node) { + mt.parent = p +} + +func (mt *PatchesTable) ShowTable() { + // log.Info("ShowTable() SENDING TO GUI") + mt.MakeTable() + mt.parent.ShowTable(mt.pb) +} + +type PatchAnyFunc struct { + title string + f func(*Patch) any + Custom func(*Patch) + Width int + attr *guipb.ColAttr +} + +type PatchesTable struct { + pb *guipb.Table + parent *gui.Node + x *Patches + hostnames []string + anyFuncs []*PatchAnyFunc + CustomFunc func(*Patch) +} + +func (mt *PatchesTable) doAnyFuncNew(sf *PatchAnyFunc) bool { + r := new(guipb.AnyCol) + r.Header = new(guipb.Widget) + r.Header.Name = sf.title + r.Attr = proto.Clone(sf.attr).(*guipb.ColAttr) + r.Attr.Width = int32(sf.Width) + + for m := range mt.x.IterAll() { + t := sf.f(m) + switch r.Attr.Type { + case guipb.ColAttr_STRING: + // anyProto, err := anypb.New(tsProto) + stringValue := wrapperspb.String(t.(string)) + anyProto, err := anypb.New(stringValue) + _ = err // do something with err someday (?) + r.Vals = append(r.Vals, anyProto) + // return col.Vals[row] true + case guipb.ColAttr_INT: + var finalInt int + finalInt = t.(int) + intVal := wrapperspb.Int32(int32(finalInt)) + anyProto, _ := anypb.New(intVal) + r.Vals = append(r.Vals, anyProto) + case guipb.ColAttr_DURATION: + case guipb.ColAttr_TIME: + var goTime time.Time + goTime = t.(time.Time) + tsProto := timestamppb.New(goTime) + anyProto, err := anypb.New(tsProto) + _ = err // do something with err someday (?) + r.Vals = append(r.Vals, anyProto) + default: + log.Info("cell unhandled type", r.Attr.Type) + } + // cellTime := r.Vals[row] + // s := shell.FormatDuration(time.Since(cellTime.AsTime())) + } + + mt.pb.AnyCols = append(mt.pb.AnyCols, r) + return true +} + +func (mt *PatchesTable) MakeTable() { + for _, sf := range mt.anyFuncs { + mt.doAnyFuncNew(sf) + } +} + +func (t *PatchesTable) AddNamespace() *PatchAnyFunc { + sf := t.AddStringFunc("Namespace", func(m *Patch) string { + return m.Namespace + }) + return sf +} + +func (t *PatchesTable) AddGH() *PatchAnyFunc { + sf := t.AddStringFunc("GH", func(m *Patch) string { + return m.GH + }) + return sf +} + +func (t *PatchesTable) AddGT() *PatchAnyFunc { + sf := t.AddStringFunc("GT", func(m *Patch) string { + return m.GT + }) + return sf +} + +func (t *PatchesTable) AddGP() *PatchAnyFunc { + sf := t.AddStringFunc("GP", func(m *Patch) string { + return m.GP + }) + return sf +} + +func (t *PatchesTable) AddGs() *PatchAnyFunc { + sf := t.AddStringFunc("Gs", func(m *Patch) string { + return m.Gs + }) + return sf +} + +func (t *PatchesTable) AddGaI() *PatchAnyFunc { + sf := t.AddStringFunc("GaI", func(m *Patch) string { + return m.GaI + }) + return sf +} + +func (t *PatchesTable) AddGan() *PatchAnyFunc { + sf := t.AddStringFunc("Gan", func(m *Patch) string { + return m.Gan + }) + return sf +} + +func (t *PatchesTable) AddGae() *PatchAnyFunc { + sf := t.AddStringFunc("Gae", func(m *Patch) string { + return m.Gae + }) + return sf +} + +func (t *PatchesTable) AddGcI() *PatchAnyFunc { + sf := t.AddStringFunc("GcI", func(m *Patch) string { + return m.GcI + }) + return sf +} + +func (t *PatchesTable) AddGcn() *PatchAnyFunc { + sf := t.AddStringFunc("Gcn", func(m *Patch) string { + return m.Gcn + }) + return sf +} + +func (t *PatchesTable) AddGce() *PatchAnyFunc { + sf := t.AddStringFunc("Gce", func(m *Patch) string { + return m.Gce + }) + return sf +} + +func (t *PatchesTable) AddGN() *PatchAnyFunc { + sf := t.AddStringFunc("GN", func(m *Patch) string { + return m.GN + }) + return sf +} + +func (t *PatchesTable) AddGGG() *PatchAnyFunc { + sf := t.AddStringFunc("GGG", func(m *Patch) string { + return m.GGG + }) + return sf +} + +func (t *PatchesTable) AddGGS() *PatchAnyFunc { + sf := t.AddStringFunc("GGS", func(m *Patch) string { + return m.GGS + }) + return sf +} + +func (t *PatchesTable) AddGGK() *PatchAnyFunc { + sf := t.AddStringFunc("GGK", func(m *Patch) string { + return m.GGK + }) + return sf +} + +func (t *PatchesTable) AddNewHash() *PatchAnyFunc { + sf := t.AddStringFunc("NewHash", func(m *Patch) string { + return m.NewHash + }) + return sf +} + +func (t *PatchesTable) AddState() *PatchAnyFunc { + sf := t.AddStringFunc("State", func(m *Patch) string { + return m.State + }) + return sf +} + +func (t *PatchesTable) AddFilename() *PatchAnyFunc { + sf := t.AddStringFunc("Filename", func(m *Patch) string { + return m.Filename + }) + return sf +} + +func (t *PatchesTable) AddStartHash() *PatchAnyFunc { + sf := t.AddStringFunc("StartHash", func(m *Patch) string { + return m.StartHash + }) + return sf +} + +func (t *PatchesTable) AddCommitHash() *PatchAnyFunc { + sf := t.AddStringFunc("CommitHash", func(m *Patch) string { + return m.CommitHash + }) + return sf +} + +func (t *PatchesTable) AddComment() *PatchAnyFunc { + sf := t.AddStringFunc("Comment", func(m *Patch) string { + return m.Comment + }) + return sf +} + +func (t *PatchesTable) AddPatchId() *PatchAnyFunc { + sf := t.AddStringFunc("PatchId", func(m *Patch) string { + return m.PatchId + }) + return sf +} + +func (t *PatchesTable) AddTreeHash() *PatchAnyFunc { + sf := t.AddStringFunc("TreeHash", func(m *Patch) string { + return m.TreeHash + }) + return sf +} +func (mt *PatchesTable) NewUuid() { + mt.pb.Uuid = uuid.New().String() +} + +// START TABLE UPDATE (doesn't work yet) + +func (mt *PatchesTable) dumpStringFunc(name string) { + for i, r := range mt.pb.StringCols { + // log.Info("could use", i, r.Header.Name, "for name =", name) + if r.Header.Name == name { + log.Info("dump Strings row", i, r.Header.Name, r.Vals) + break + } + } +} + +func (mt *PatchesTable) Delete() { + if mt == nil { + log.Info("mt == nil table already deleted") + return + } + // log.Info("table Delete here") + mt.parent.DeleteTable(mt.pb) +} + +func (mt *PatchesTable) patchesCustom(w *guipb.Widget) { + row := mt.x.Patches[w.Location.Y-1] + // log.Info("got to patchesCustom() with", w.Location.X, w.Location.Y-1) + + for i, sf := range mt.anyFuncs { + if i == int(w.Location.X) { + if sf.Custom != nil { + log.Info("doing Custom() func for button") + sf.Custom(row) + return + } + } + } + mt.CustomFunc(row) +} + +func (mt *PatchesTable) Custom(f func(*Patch)) { + mt.pb.RegisterCustom(mt.patchesCustom) + mt.CustomFunc = f +} + +func (mt *PatchesTable) GetUuid() string { + return mt.pb.Uuid +} + +// END TABLE UPDATE + +// END GUI diff --git a/patch.http.pb.go b/patch.http.pb.go new file mode 100644 index 0000000..1aae001 --- /dev/null +++ b/patch.http.pb.go @@ -0,0 +1,61 @@ +// Code generated by go.wit.com/apps/autogenpb DO NOT EDIT. +// This file was autogenerated with autogenpb v0.5.6-1-g08dc949 2025.09.23_0925 +// go install go.wit.com/apps/autogenpb@latest +// +// define which structs (messages) you want to use in the .proto file +// Then sort.pb.go and marshal.pb.go files are autogenerated +// +// autogenpb uses it and has an example .proto file with instructions +// + +package forgepb + +import ( + "fmt" + "net/http" + "path/filepath" + + "go.wit.com/lib/protobuf/httppb" +) + +// START HTTP + +func (p *Patches) SendReply(w http.ResponseWriter, reqPB *httppb.HttpRequest) error { + data, err := p.Marshal() + if err != nil { + // reqPB.Errors = append(reqPB.Errors, log.Sprintf(, err)) + } + if len(data) == 0 { + // reqPB.Errors = append(reqPB.Errors, "Patches PB data was nil/emtpy without Marsha() error") + return nil + } + _, err = w.Write(data) + if err != nil { + // reqPB.Errors = append(reqPB.Errors, log.Sprintf(, i, err)) + } + return err +} + +// Marshal protobuf, then http POST, then Unmarshal() to protobuf again +func (p *Patches) HttpPost(baseURL string, route string) (*Patches, *httppb.HttpRequest, error) { + data, err := p.Marshal() + if err != nil { + return nil, nil, err + } + + tmp := filepath.Join("patches", route) + reqPB, err := httppb.DoPost(baseURL, tmp, data) + if reqPB == nil { + return nil, nil, err + } + + if len(reqPB.ServerData) == 0 { + return nil, reqPB, fmt.Errorf("server returned len(data)=0") + } + + newpb := new(Patches) + err = newpb.Unmarshal(reqPB.ServerData) + return newpb, reqPB, err +} + +// END HTTP diff --git a/patch.marshal.pb.go b/patch.marshal.pb.go new file mode 100644 index 0000000..ce8a6b0 --- /dev/null +++ b/patch.marshal.pb.go @@ -0,0 +1,56 @@ +// Code generated by go.wit.com/apps/autogenpb DO NOT EDIT. +// This file was autogenerated with autogenpb v0.5.6-1-g08dc949 2025.09.23_0925 +// go install go.wit.com/apps/autogenpb@latest +// +// define which structs (messages) you want to use in the .proto file +// Then sort.pb.go and marshal.pb.go files are autogenerated +// +// autogenpb uses it and has an example .proto file with instructions +// + +package forgepb + +import ( + "google.golang.org/protobuf/encoding/protojson" + "google.golang.org/protobuf/encoding/prototext" + "google.golang.org/protobuf/proto" +) + +// human readable JSON +func (v *Patches) FormatJSON() string { + return protojson.Format(v) +} + +// marshal json +func (v *Patches) MarshalJSON() ([]byte, error) { + return protojson.Marshal(v) +} + +// unmarshal json +func (v *Patches) UnmarshalJSON(data []byte) error { + return protojson.Unmarshal(data, v) +} + +// apparently this isn't stable, but it's awesomely better +// https://protobuf.dev/reference/go/faq/#unstable-text +// it's brilliant for config files! +func (v *Patches) FormatTEXT() string { + v.fixUuid() + return prototext.Format(v) +} + +// unmarshalTEXT. This reads the .text config file back in after the user edits it +func (v *Patches) UnmarshalTEXT(data []byte) error { + return prototext.Unmarshal(data, v) +} + +// marshal to wire. This is called winning. +func (v *Patches) Marshal() ([]byte, error) { + v.fixUuid() + return proto.Marshal(v) +} + +// unmarshal from wire. You have won. +func (v *Patches) Unmarshal(data []byte) error { + return proto.Unmarshal(data, v) +} diff --git a/patch.pb.go b/patch.pb.go new file mode 100644 index 0000000..d9400eb --- /dev/null +++ b/patch.pb.go @@ -0,0 +1,508 @@ +// Code modified by go.wit.com/apps/autogenpb DO NOT EDIT. +// +// user defined Mutex locks were auto added +// +// autogenpb version & build time: v0.5.6-1-g08dc949 2025.09.23_0925 +// autogenpb auto generates Sort(), Unique() and Marshal() functions +// go install go.wit.com/apps/autogenpb@latest + +// Copyright 2025 WIT.COM Inc Licensed GPL 3.0 + +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.33.0 +// protoc v3.21.12 +// source: patch.proto + +package forgepb // autogenpb changed the package name + +import ( + reflect "reflect" + sync "sync" + + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + timestamppb "google.golang.org/protobuf/types/known/timestamppb" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +type Patch struct { + sync.RWMutex // auto-added by go.wit.com/apps/autogenpb + + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Namespace string `protobuf:"bytes,1,opt,name=namespace,proto3" json:"namespace,omitempty"` // the base repo git namespace + Data []byte `protobuf:"bytes,2,opt,name=data,proto3" json:"data,omitempty"` // the raw data of the whole patch + GH string `protobuf:"bytes,3,opt,name=gH,proto3" json:"gH,omitempty"` // Commit Hash (%H) + GT string `protobuf:"bytes,4,opt,name=gT,proto3" json:"gT,omitempty"` // Tree Hash (%T) + GP string `protobuf:"bytes,5,opt,name=gP,proto3" json:"gP,omitempty"` // Parent Hashes (%P) + Gs string `protobuf:"bytes,6,opt,name=gs,proto3" json:"gs,omitempty"` // Subject (%s) + GaI string `protobuf:"bytes,7,opt,name=gaI,proto3" json:"gaI,omitempty"` // Author Date, ISO 8601 format (%aI) + Gan string `protobuf:"bytes,8,opt,name=gan,proto3" json:"gan,omitempty"` // Author Name (%an) + Gae string `protobuf:"bytes,9,opt,name=gae,proto3" json:"gae,omitempty"` // Author Email (%ae) + GcI string `protobuf:"bytes,10,opt,name=gcI,proto3" json:"gcI,omitempty"` // Committer Date, ISO 8601 format (%cI) + Gcn string `protobuf:"bytes,11,opt,name=gcn,proto3" json:"gcn,omitempty"` // Committer Name (%cn) + Gce string `protobuf:"bytes,12,opt,name=gce,proto3" json:"gce,omitempty"` // Committer Email (%ce) + GN string `protobuf:"bytes,13,opt,name=gN,proto3" json:"gN,omitempty"` // Commit Notes (%N) + GGG string `protobuf:"bytes,14,opt,name=gGG,proto3" json:"gGG,omitempty"` // GPG Signature, raw (%GG) + GGS string `protobuf:"bytes,15,opt,name=gGS,proto3" json:"gGS,omitempty"` // GPG Signer Name (%GS) + GGK string `protobuf:"bytes,16,opt,name=gGK,proto3" json:"gGK,omitempty"` // GPG Key ID (%GK) + NewHash string `protobuf:"bytes,17,opt,name=newHash,proto3" json:"newHash,omitempty"` // new hash + State string `protobuf:"bytes,18,opt,name=state,proto3" json:"state,omitempty"` // the 'state' of the patch + Filename string `protobuf:"bytes,19,opt,name=filename,proto3" json:"filename,omitempty"` // `autogenpb:unique` `autogenpb:sort` + StartHash string `protobuf:"bytes,20,opt,name=startHash,proto3" json:"startHash,omitempty"` // the start commit hash + CommitHash string `protobuf:"bytes,21,opt,name=commitHash,proto3" json:"commitHash,omitempty"` // the git commit hash of this patch `autogenpb:sort` `autogenpb:unique` + Comment string `protobuf:"bytes,22,opt,name=comment,proto3" json:"comment,omitempty"` // the git commit message (in patch form) + Files []string `protobuf:"bytes,23,rep,name=Files,proto3" json:"Files,omitempty"` // the filenames this patch changes + Ctime *timestamppb.Timestamp `protobuf:"bytes,24,opt,name=ctime,proto3" json:"ctime,omitempty"` // create time of the patch + Applied bool `protobuf:"varint,25,opt,name=applied,proto3" json:"applied,omitempty"` // have you applied this patch? + Upstream bool `protobuf:"varint,26,opt,name=upstream,proto3" json:"upstream,omitempty"` // has this patch been applied upstream? + PatchId string `protobuf:"bytes,27,opt,name=patchId,proto3" json:"patchId,omitempty"` // patchId + TreeHash string `protobuf:"bytes,28,opt,name=treeHash,proto3" json:"treeHash,omitempty"` // final tree Hash +} + +func (x *Patch) Reset() { + *x = Patch{} + if protoimpl.UnsafeEnabled { + mi := &file_patch_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Patch) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Patch) ProtoMessage() {} + +func (x *Patch) ProtoReflect() protoreflect.Message { + mi := &file_patch_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Patch.ProtoReflect.Descriptor instead. +func (*Patch) Descriptor() ([]byte, []int) { + return file_patch_proto_rawDescGZIP(), []int{0} +} + +func (x *Patch) GetNamespace() string { + if x != nil { + return x.Namespace + } + return "" +} + +func (x *Patch) GetData() []byte { + if x != nil { + return x.Data + } + return nil +} + +func (x *Patch) GetGH() string { + if x != nil { + return x.GH + } + return "" +} + +func (x *Patch) GetGT() string { + if x != nil { + return x.GT + } + return "" +} + +func (x *Patch) GetGP() string { + if x != nil { + return x.GP + } + return "" +} + +func (x *Patch) GetGs() string { + if x != nil { + return x.Gs + } + return "" +} + +func (x *Patch) GetGaI() string { + if x != nil { + return x.GaI + } + return "" +} + +func (x *Patch) GetGan() string { + if x != nil { + return x.Gan + } + return "" +} + +func (x *Patch) GetGae() string { + if x != nil { + return x.Gae + } + return "" +} + +func (x *Patch) GetGcI() string { + if x != nil { + return x.GcI + } + return "" +} + +func (x *Patch) GetGcn() string { + if x != nil { + return x.Gcn + } + return "" +} + +func (x *Patch) GetGce() string { + if x != nil { + return x.Gce + } + return "" +} + +func (x *Patch) GetGN() string { + if x != nil { + return x.GN + } + return "" +} + +func (x *Patch) GetGGG() string { + if x != nil { + return x.GGG + } + return "" +} + +func (x *Patch) GetGGS() string { + if x != nil { + return x.GGS + } + return "" +} + +func (x *Patch) GetGGK() string { + if x != nil { + return x.GGK + } + return "" +} + +func (x *Patch) GetNewHash() string { + if x != nil { + return x.NewHash + } + return "" +} + +func (x *Patch) GetState() string { + if x != nil { + return x.State + } + return "" +} + +func (x *Patch) GetFilename() string { + if x != nil { + return x.Filename + } + return "" +} + +func (x *Patch) GetStartHash() string { + if x != nil { + return x.StartHash + } + return "" +} + +func (x *Patch) GetCommitHash() string { + if x != nil { + return x.CommitHash + } + return "" +} + +func (x *Patch) GetComment() string { + if x != nil { + return x.Comment + } + return "" +} + +func (x *Patch) GetFiles() []string { + if x != nil { + return x.Files + } + return nil +} + +func (x *Patch) GetCtime() *timestamppb.Timestamp { + if x != nil { + return x.Ctime + } + return nil +} + +func (x *Patch) GetApplied() bool { + if x != nil { + return x.Applied + } + return false +} + +func (x *Patch) GetUpstream() bool { + if x != nil { + return x.Upstream + } + return false +} + +func (x *Patch) GetPatchId() string { + if x != nil { + return x.PatchId + } + return "" +} + +func (x *Patch) GetTreeHash() string { + if x != nil { + return x.TreeHash + } + return "" +} + +// this is a "PATCH: [1/x]" series +type Patches struct { + sync.RWMutex // auto-added by go.wit.com/apps/autogenpb + + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Uuid string `protobuf:"bytes,1,opt,name=uuid,proto3" json:"uuid,omitempty"` // `autogenpb:uuid:2679065e-c81d-4a00-aca4-03c158a834fb` + Version string `protobuf:"bytes,2,opt,name=version,proto3" json:"version,omitempty"` // `autogenpb:version:v2.0.0` + Patches []*Patch `protobuf:"bytes,3,rep,name=patches,proto3" json:"patches,omitempty"` + Error string `protobuf:"bytes,4,opt,name=Error,proto3" json:"Error,omitempty"` // when passing these around, if there is an error, store it here +} + +func (x *Patches) Reset() { + *x = Patches{} + if protoimpl.UnsafeEnabled { + mi := &file_patch_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Patches) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Patches) ProtoMessage() {} + +func (x *Patches) ProtoReflect() protoreflect.Message { + mi := &file_patch_proto_msgTypes[1] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Patches.ProtoReflect.Descriptor instead. +func (*Patches) Descriptor() ([]byte, []int) { + return file_patch_proto_rawDescGZIP(), []int{1} +} + +func (x *Patches) GetUuid() string { + if x != nil { + return x.Uuid + } + return "" +} + +func (x *Patches) GetVersion() string { + if x != nil { + return x.Version + } + return "" +} + +func (x *Patches) GetPatches() []*Patch { + if x != nil { + return x.Patches + } + return nil +} + +func (x *Patches) GetError() string { + if x != nil { + return x.Error + } + return "" +} + +var File_patch_proto protoreflect.FileDescriptor + +var file_patch_proto_rawDesc = []byte{ + 0x0a, 0x0b, 0x70, 0x61, 0x74, 0x63, 0x68, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x07, 0x66, + 0x6f, 0x72, 0x67, 0x65, 0x70, 0x62, 0x1a, 0x1f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, + 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x83, 0x05, 0x0a, 0x05, 0x50, 0x61, 0x74, 0x63, + 0x68, 0x12, 0x1c, 0x0a, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, + 0x12, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x64, + 0x61, 0x74, 0x61, 0x12, 0x0e, 0x0a, 0x02, 0x67, 0x48, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x02, 0x67, 0x48, 0x12, 0x0e, 0x0a, 0x02, 0x67, 0x54, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x02, 0x67, 0x54, 0x12, 0x0e, 0x0a, 0x02, 0x67, 0x50, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x02, 0x67, 0x50, 0x12, 0x0e, 0x0a, 0x02, 0x67, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x02, 0x67, 0x73, 0x12, 0x10, 0x0a, 0x03, 0x67, 0x61, 0x49, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x03, 0x67, 0x61, 0x49, 0x12, 0x10, 0x0a, 0x03, 0x67, 0x61, 0x6e, 0x18, 0x08, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x03, 0x67, 0x61, 0x6e, 0x12, 0x10, 0x0a, 0x03, 0x67, 0x61, 0x65, 0x18, 0x09, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x67, 0x61, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x67, 0x63, 0x49, + 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x67, 0x63, 0x49, 0x12, 0x10, 0x0a, 0x03, 0x67, + 0x63, 0x6e, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x67, 0x63, 0x6e, 0x12, 0x10, 0x0a, + 0x03, 0x67, 0x63, 0x65, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x67, 0x63, 0x65, 0x12, + 0x0e, 0x0a, 0x02, 0x67, 0x4e, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x67, 0x4e, 0x12, + 0x10, 0x0a, 0x03, 0x67, 0x47, 0x47, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x67, 0x47, + 0x47, 0x12, 0x10, 0x0a, 0x03, 0x67, 0x47, 0x53, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, + 0x67, 0x47, 0x53, 0x12, 0x10, 0x0a, 0x03, 0x67, 0x47, 0x4b, 0x18, 0x10, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x03, 0x67, 0x47, 0x4b, 0x12, 0x18, 0x0a, 0x07, 0x6e, 0x65, 0x77, 0x48, 0x61, 0x73, 0x68, + 0x18, 0x11, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6e, 0x65, 0x77, 0x48, 0x61, 0x73, 0x68, 0x12, + 0x14, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x12, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, + 0x73, 0x74, 0x61, 0x74, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x66, 0x69, 0x6c, 0x65, 0x6e, 0x61, 0x6d, + 0x65, 0x18, 0x13, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x66, 0x69, 0x6c, 0x65, 0x6e, 0x61, 0x6d, + 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x73, 0x74, 0x61, 0x72, 0x74, 0x48, 0x61, 0x73, 0x68, 0x18, 0x14, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x73, 0x74, 0x61, 0x72, 0x74, 0x48, 0x61, 0x73, 0x68, 0x12, + 0x1e, 0x0a, 0x0a, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x48, 0x61, 0x73, 0x68, 0x18, 0x15, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x0a, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x48, 0x61, 0x73, 0x68, 0x12, + 0x18, 0x0a, 0x07, 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x16, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x07, 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x46, 0x69, 0x6c, + 0x65, 0x73, 0x18, 0x17, 0x20, 0x03, 0x28, 0x09, 0x52, 0x05, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x12, + 0x30, 0x0a, 0x05, 0x63, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x18, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, + 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, + 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x05, 0x63, 0x74, 0x69, 0x6d, + 0x65, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x65, 0x64, 0x18, 0x19, 0x20, 0x01, + 0x28, 0x08, 0x52, 0x07, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x65, 0x64, 0x12, 0x1a, 0x0a, 0x08, 0x75, + 0x70, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x18, 0x1a, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x75, + 0x70, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x12, 0x18, 0x0a, 0x07, 0x70, 0x61, 0x74, 0x63, 0x68, + 0x49, 0x64, 0x18, 0x1b, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x70, 0x61, 0x74, 0x63, 0x68, 0x49, + 0x64, 0x12, 0x1a, 0x0a, 0x08, 0x74, 0x72, 0x65, 0x65, 0x48, 0x61, 0x73, 0x68, 0x18, 0x1c, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x08, 0x74, 0x72, 0x65, 0x65, 0x48, 0x61, 0x73, 0x68, 0x22, 0x77, 0x0a, + 0x07, 0x50, 0x61, 0x74, 0x63, 0x68, 0x65, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x75, 0x75, 0x69, 0x64, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x75, 0x75, 0x69, 0x64, 0x12, 0x18, 0x0a, 0x07, + 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x76, + 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x28, 0x0a, 0x07, 0x70, 0x61, 0x74, 0x63, 0x68, 0x65, + 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x66, 0x6f, 0x72, 0x67, 0x65, 0x70, + 0x62, 0x2e, 0x50, 0x61, 0x74, 0x63, 0x68, 0x52, 0x07, 0x70, 0x61, 0x74, 0x63, 0x68, 0x65, 0x73, + 0x12, 0x14, 0x0a, 0x05, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x05, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, +} + +var ( + file_patch_proto_rawDescOnce sync.Once + file_patch_proto_rawDescData = file_patch_proto_rawDesc +) + +func file_patch_proto_rawDescGZIP() []byte { + file_patch_proto_rawDescOnce.Do(func() { + file_patch_proto_rawDescData = protoimpl.X.CompressGZIP(file_patch_proto_rawDescData) + }) + return file_patch_proto_rawDescData +} + +var file_patch_proto_msgTypes = make([]protoimpl.MessageInfo, 2) +var file_patch_proto_goTypes = []interface{}{ + (*Patch)(nil), // 0: forgepb.Patch + (*Patches)(nil), // 1: forgepb.Patches + (*timestamppb.Timestamp)(nil), // 2: google.protobuf.Timestamp +} +var file_patch_proto_depIdxs = []int32{ + 2, // 0: forgepb.Patch.ctime:type_name -> google.protobuf.Timestamp + 0, // 1: forgepb.Patches.patches:type_name -> forgepb.Patch + 2, // [2:2] is the sub-list for method output_type + 2, // [2:2] is the sub-list for method input_type + 2, // [2:2] is the sub-list for extension type_name + 2, // [2:2] is the sub-list for extension extendee + 0, // [0:2] is the sub-list for field type_name +} + +func init() { file_patch_proto_init() } +func file_patch_proto_init() { + if File_patch_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_patch_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Patch); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_patch_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Patches); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_patch_proto_rawDesc, + NumEnums: 0, + NumMessages: 2, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_patch_proto_goTypes, + DependencyIndexes: file_patch_proto_depIdxs, + MessageInfos: file_patch_proto_msgTypes, + }.Build() + File_patch_proto = out.File + file_patch_proto_rawDesc = nil + file_patch_proto_goTypes = nil + file_patch_proto_depIdxs = nil +} diff --git a/patch.sort.pb.go b/patch.sort.pb.go new file mode 100644 index 0000000..9cc4586 --- /dev/null +++ b/patch.sort.pb.go @@ -0,0 +1,380 @@ +// Code generated by go.wit.com/apps/autogenpb DO NOT EDIT. +// This file was autogenerated with autogenpb v0.5.6-1-g08dc949 2025.09.23_0925 +// go install go.wit.com/apps/autogenpb@latest +// +// define which structs (messages) you want to use in the .proto file +// Then sort.pb.go and marshal.pb.go files are autogenerated +// +// autogenpb uses it and has an example .proto file with instructions +// + +package forgepb + +import ( + "fmt" + "iter" + "sort" + "sync" + + "google.golang.org/protobuf/proto" +) + +// a simple global lock +var patchMu sync.RWMutex + +func (x *Patches) fixUuid() { + if x == nil { + return + } + if x.Uuid == "2679065e-c81d-4a00-aca4-03c158a834fb" { + return + } + x.Uuid = "2679065e-c81d-4a00-aca4-03c158a834fb" + x.Version = "v2.0.0 go.wit.com/lib/protobuf/forgepb" +} + +func NewPatches() *Patches { + x := new(Patches) + x.Uuid = "2679065e-c81d-4a00-aca4-03c158a834fb" + x.Version = "v2.0.0 go.wit.com/lib/protobuf/forgepb" + return x +} + +// START SORT + +// DEFINE THE Patches SCANNER. +// itializes a new scanner. +func newPatchesScanner(things []*Patches) *PatchesScanner { + return &PatchesScanner{things: things} +} + +type PatchesScanner struct { + sync.Mutex + + things []*Patches + index int +} + +func (it *PatchesScanner) Scan() bool { + if it.index >= len(it.things) { + return false + } + it.Lock() + it.index++ + it.Unlock() + return true +} + +// Next() returns the next thing in the array +func (it *PatchesScanner) Next() *Patches { + if it.things[it.index-1] == nil { + fmt.Println("Next() error in PatchesScanner", it.index) + } + return it.things[it.index-1] +} + +// END DEFINE THE SCANNER + +// DEFINE THE Patch SCANNER. +// itializes a new scanner. +func newPatchScanner(things []*Patch) *PatchScanner { + return &PatchScanner{things: things} +} + +type PatchScanner struct { + sync.Mutex + + things []*Patch + index int +} + +func (it *PatchScanner) Scan() bool { + if it.index >= len(it.things) { + return false + } + it.Lock() + it.index++ + it.Unlock() + return true +} + +// Next() returns the next thing in the array +func (it *PatchScanner) Next() *Patch { + if it.things[it.index-1] == nil { + fmt.Println("Next() error in PatchScanner", it.index) + } + return it.things[it.index-1] +} + +// END DEFINE THE SCANNER + +// sort struct by Filename +type sortPatchFilename []*Patch + +func (a sortPatchFilename) Len() int { return len(a) } +func (a sortPatchFilename) Less(i, j int) bool { return a[i].Filename < a[j].Filename } +func (a sortPatchFilename) Swap(i, j int) { a[i], a[j] = a[j], a[i] } + +// sort struct by CommitHash +type sortPatchCommitHash []*Patch + +func (a sortPatchCommitHash) Len() int { return len(a) } +func (a sortPatchCommitHash) Less(i, j int) bool { return a[i].CommitHash < a[j].CommitHash } +func (a sortPatchCommitHash) Swap(i, j int) { a[i], a[j] = a[j], a[i] } + +// safely returns a slice of pointers to the FRUIT protobufs +func (x *Patches) allPatches() []*Patch { + x.RLock() + defer x.RUnlock() + + // Create a new slice to hold pointers to each FRUIT + var tmp []*Patch + tmp = make([]*Patch, len(x.Patches)) + for i, p := range x.Patches { + tmp[i] = p // Copy pointers for safe iteration + } + + return tmp +} + +// safely returns a slice of pointers to the Patch protobufs +func (x *Patches) selectAllPatches() []*Patch { + x.RLock() + defer x.RUnlock() + + // Create a new slice to hold pointers to each Patch + var tmp []*Patch + tmp = make([]*Patch, len(x.Patches)) + for i, p := range x.Patches { + tmp[i] = p // Copy pointers for safe iteration + } + + return tmp +} +func (x *Patches) SortByFilename() *PatchScanner { + // copy the pointers as fast as possible. + things := x.selectAllPatches() + + // todo: try slices.SortFunc() instead to see what happens + sort.Sort(sortPatchFilename(things)) + // slices.SortFunc(things, func(a, b *Patches) bool { + // return a.Filename < b.Filename // Sort by ??. let the compiler work it out?? + // }) + return newPatchScanner(things) +} + +// 'for x := range' syntax using the awesome golang 1.24 'iter' +func (x *Patches) IterByFilename() iter.Seq[*Patch] { + items := x.selectAllPatches() + sort.Sort(sortPatchFilename(items)) + // log.Println("Made Iter.Seq[] with length", len(items)) + return func(yield func(*Patch) bool) { + for _, v := range items { + if !yield(v) { + return + } + } + } +} +func (x *Patches) SortByCommitHash() *PatchScanner { + // copy the pointers as fast as possible. + things := x.selectAllPatches() + + // todo: try slices.SortFunc() instead to see what happens + sort.Sort(sortPatchCommitHash(things)) + // slices.SortFunc(things, func(a, b *Patches) bool { + // return a.CommitHash < b.CommitHash // Sort by ??. let the compiler work it out?? + // }) + return newPatchScanner(things) +} + +// 'for x := range' syntax using the awesome golang 1.24 'iter' +func (x *Patches) IterByCommitHash() iter.Seq[*Patch] { + items := x.selectAllPatches() + sort.Sort(sortPatchCommitHash(items)) + // log.Println("Made Iter.Seq[] with length", len(items)) + return func(yield func(*Patch) bool) { + for _, v := range items { + if !yield(v) { + return + } + } + } +} + +// END SORT + +func (x *Patches) Len() int { + x.RLock() + defer x.RUnlock() + + return len(x.Patches) +} + +// a Append() shortcut (that does Clone() with a mutex) notsure if it really works +func (x *Patches) Append(y *Patch) *Patch { + x.Lock() + defer x.Unlock() + + z := proto.Clone(y).(*Patch) + x.Patches = append(x.Patches, z) + + return z +} + +func (x *Patches) All() *PatchScanner { + PatchPointers := x.selectAllPatches() + + scanner := newPatchScanner(PatchPointers) + return scanner +} + +// Iterate 'for x := range' syntax using the awesome golang 1.24 'iter' +func (x *Patches) IterAll() iter.Seq[*Patch] { + items := x.selectAllPatches() + // log.Println("Made All() Iter.Seq[] with length", len(items)) + return func(yield func(*Patch) bool) { + for _, v := range items { + if !yield(v) { + return + } + } + } +} +func (x *Patches) Delete(y *Patch) bool { + x.Lock() + defer x.Unlock() + + for i, _ := range x.Patches { + if x.Patches[i] == y { + x.Patches[i] = x.Patches[len(x.Patches)-1] + x.Patches = x.Patches[:len(x.Patches)-1] + return true + } + } + return false +} + +// lookup a Patches by the Filename +func (x *Patches) FindByFilename(s string) *Patch { + if x == nil { + return nil + } + + x.RLock() + defer x.RUnlock() + + for i, _ := range x.Patches { + if x.Patches[i].Filename == s { + return x.Patches[i] + } + } + return nil +} + +// returns a Patch if Filename matches, otherwise create +func (x *Patches) InsertByFilename(y string) *Patch { + x.Lock() + defer x.Unlock() + + for _, z := range x.Patches { + if z.Filename == y { + return z + } + } + + z := new(Patch) + z.Filename = y + x.Patches = append(x.Patches, z) + return z +} + +// lookup a Patches by the CommitHash +func (x *Patches) FindByCommitHash(s string) *Patch { + if x == nil { + return nil + } + + x.RLock() + defer x.RUnlock() + + for i, _ := range x.Patches { + if x.Patches[i].CommitHash == s { + return x.Patches[i] + } + } + return nil +} + +// returns a Patch if CommitHash matches, otherwise create +func (x *Patches) InsertByCommitHash(y string) *Patch { + x.Lock() + defer x.Unlock() + + for _, z := range x.Patches { + if z.CommitHash == y { + return z + } + } + + z := new(Patch) + z.CommitHash = y + x.Patches = append(x.Patches, z) + return z +} + +func (x *Patches) DeleteByFilename(s string) bool { + x.Lock() + defer x.Unlock() + + for i, _ := range x.Patches { + if x.Patches[i].Filename == s { + x.Patches[i] = x.Patches[len(x.Patches)-1] + x.Patches = x.Patches[:len(x.Patches)-1] + return true + } + } + return false +} + +func (x *Patches) DeleteByCommitHash(s string) bool { + x.Lock() + defer x.Unlock() + + for i, _ := range x.Patches { + if x.Patches[i].CommitHash == s { + x.Patches[i] = x.Patches[len(x.Patches)-1] + x.Patches = x.Patches[:len(x.Patches)-1] + return true + } + } + return false +} + +func (x *Patches) AppendByFilename(y *Patch) bool { + x.Lock() + defer x.Unlock() + + for _, p := range x.Patches { + if p.Filename == y.Filename { + return false + } + } + + x.Patches = append(x.Patches, proto.Clone(y).(*Patch)) + return true +} + +func (x *Patches) AppendByCommitHash(y *Patch) bool { + x.Lock() + defer x.Unlock() + + for _, p := range x.Patches { + if p.CommitHash == y.CommitHash { + return false + } + } + + x.Patches = append(x.Patches, proto.Clone(y).(*Patch)) + return true +} diff --git a/set.gui.pb.go b/set.gui.pb.go new file mode 100644 index 0000000..289fb4b --- /dev/null +++ b/set.gui.pb.go @@ -0,0 +1,328 @@ +// Code generated by go.wit.com/apps/autogenpb DO NOT EDIT. +// This file was autogenerated with autogenpb v0.5.6-1-g08dc949 2025.09.23_0925 +// go install go.wit.com/apps/autogenpb@latest +// +// define which structs (messages) you want to use in the .proto file +// Then sort.pb.go and marshal.pb.go files are autogenerated +// +// autogenpb uses it and has an example .proto file with instructions +// + +package forgepb + +import ( + "time" + + "github.com/google/uuid" + "go.wit.com/gui" + "go.wit.com/lib/protobuf/guipb" + "go.wit.com/log" + "google.golang.org/protobuf/proto" + anypb "google.golang.org/protobuf/types/known/anypb" + timestamppb "google.golang.org/protobuf/types/known/timestamppb" + "google.golang.org/protobuf/types/known/wrapperspb" +) + +// START GUI + +func (x *Sets) NewTable(title string) *SetsTable { + t := new(SetsTable) + t.x = x + pb := new(guipb.Table) + pb.Title = title + t.pb = pb + return t +} + +// force the application to choose the type of data. this allows the GUI plugin to be smarter +func (t *SetsTable) AddStringFunc(title string, f func(*Set) string) *SetAnyFunc { + t.pb.Order = append(t.pb.Order, title) + + sf := new(SetAnyFunc) + sf.title = title + sf.f = func(x *Set) any { + return f(x) + } + sf.attr = new(guipb.ColAttr) + sf.attr.Width = int32(sf.Width) + sf.attr.Type = guipb.ColAttr_STRING + + t.anyFuncs = append(t.anyFuncs, sf) + return sf +} + +// force the application to choose the type of data. this allows the GUI plugin to be smarter +func (t *SetsTable) AddButtonFunc(title string, f func(*Set) string) *SetAnyFunc { + t.pb.Order = append(t.pb.Order, title) + + sf := new(SetAnyFunc) + sf.title = title + sf.f = func(x *Set) any { + return f(x) + } + sf.attr = new(guipb.ColAttr) + sf.attr.Width = int32(sf.Width) + sf.attr.Type = guipb.ColAttr_STRING + sf.attr.Click = true + + t.anyFuncs = append(t.anyFuncs, sf) + return sf +} + +// force the application to choose the type of data. this allows the GUI plugin to be smarter +func (t *SetsTable) AddIntFunc(title string, f func(*Set) int) *SetAnyFunc { + t.pb.Order = append(t.pb.Order, title) + + sf := new(SetAnyFunc) + sf.title = title + sf.f = func(x *Set) any { + return f(x) + } + sf.attr = new(guipb.ColAttr) + sf.attr.Width = int32(sf.Width) + sf.attr.Type = guipb.ColAttr_INT + + t.anyFuncs = append(t.anyFuncs, sf) + return sf +} + +// force the application to choose the type of data. this allows the GUI plugin to be smarter +func (t *SetsTable) AddTimeFunc(title string, f func(*Set) time.Time) *SetAnyFunc { + t.pb.Order = append(t.pb.Order, title) + + sf := new(SetAnyFunc) + sf.title = title + sf.f = func(x *Set) any { + return f(x) + } + sf.attr = new(guipb.ColAttr) + sf.attr.Width = int32(sf.Width) + sf.attr.Type = guipb.ColAttr_TIME + + // t.timeFuncs = append(t.timeFuncs, sf) + t.anyFuncs = append(t.anyFuncs, sf) + return sf +} + +func (sf *SetAnyFunc) SetTitle(title string) { + sf.title = title +} + +func (mt *SetsTable) SetParent(p *gui.Node) { + mt.parent = p +} + +func (mt *SetsTable) ShowTable() { + // log.Info("ShowTable() SENDING TO GUI") + mt.MakeTable() + mt.parent.ShowTable(mt.pb) +} + +type SetAnyFunc struct { + title string + f func(*Set) any + Custom func(*Set) + Width int + attr *guipb.ColAttr +} + +type SetsTable struct { + pb *guipb.Table + parent *gui.Node + x *Sets + hostnames []string + anyFuncs []*SetAnyFunc + CustomFunc func(*Set) +} + +func (mt *SetsTable) doAnyFuncNew(sf *SetAnyFunc) bool { + r := new(guipb.AnyCol) + r.Header = new(guipb.Widget) + r.Header.Name = sf.title + r.Attr = proto.Clone(sf.attr).(*guipb.ColAttr) + r.Attr.Width = int32(sf.Width) + + for m := range mt.x.IterAll() { + t := sf.f(m) + switch r.Attr.Type { + case guipb.ColAttr_STRING: + // anyProto, err := anypb.New(tsProto) + stringValue := wrapperspb.String(t.(string)) + anyProto, err := anypb.New(stringValue) + _ = err // do something with err someday (?) + r.Vals = append(r.Vals, anyProto) + // return col.Vals[row] true + case guipb.ColAttr_INT: + var finalInt int + finalInt = t.(int) + intVal := wrapperspb.Int32(int32(finalInt)) + anyProto, _ := anypb.New(intVal) + r.Vals = append(r.Vals, anyProto) + case guipb.ColAttr_DURATION: + case guipb.ColAttr_TIME: + var goTime time.Time + goTime = t.(time.Time) + tsProto := timestamppb.New(goTime) + anyProto, err := anypb.New(tsProto) + _ = err // do something with err someday (?) + r.Vals = append(r.Vals, anyProto) + default: + log.Info("cell unhandled type", r.Attr.Type) + } + // cellTime := r.Vals[row] + // s := shell.FormatDuration(time.Since(cellTime.AsTime())) + } + + mt.pb.AnyCols = append(mt.pb.AnyCols, r) + return true +} + +func (mt *SetsTable) MakeTable() { + for _, sf := range mt.anyFuncs { + mt.doAnyFuncNew(sf) + } +} + +func (t *SetsTable) AddUuid() *SetAnyFunc { + sf := t.AddStringFunc("Uuid", func(m *Set) string { + return m.Uuid + }) + return sf +} + +func (t *SetsTable) AddSubmitter() *SetAnyFunc { + sf := t.AddStringFunc("Submitter", func(m *Set) string { + return m.Submitter + }) + return sf +} + +func (t *SetsTable) AddName() *SetAnyFunc { + sf := t.AddStringFunc("Name", func(m *Set) string { + return m.Name + }) + return sf +} + +func (t *SetsTable) AddGitAuthorName() *SetAnyFunc { + sf := t.AddStringFunc("GitAuthorName", func(m *Set) string { + return m.GitAuthorName + }) + return sf +} + +func (t *SetsTable) AddGitAuthorEmail() *SetAnyFunc { + sf := t.AddStringFunc("GitAuthorEmail", func(m *Set) string { + return m.GitAuthorEmail + }) + return sf +} + +func (t *SetsTable) AddHostname() *SetAnyFunc { + sf := t.AddStringFunc("Hostname", func(m *Set) string { + return m.Hostname + }) + return sf +} + +func (t *SetsTable) AddTmpDir() *SetAnyFunc { + sf := t.AddStringFunc("TmpDir", func(m *Set) string { + return m.TmpDir + }) + return sf +} + +func (t *SetsTable) AddStartBranchName() *SetAnyFunc { + sf := t.AddStringFunc("StartBranchName", func(m *Set) string { + return m.StartBranchName + }) + return sf +} + +func (t *SetsTable) AddEndBranchName() *SetAnyFunc { + sf := t.AddStringFunc("EndBranchName", func(m *Set) string { + return m.EndBranchName + }) + return sf +} + +func (t *SetsTable) AddStartBranchHash() *SetAnyFunc { + sf := t.AddStringFunc("StartBranchHash", func(m *Set) string { + return m.StartBranchHash + }) + return sf +} + +func (t *SetsTable) AddEndBranchHash() *SetAnyFunc { + sf := t.AddStringFunc("EndBranchHash", func(m *Set) string { + return m.EndBranchHash + }) + return sf +} + +func (t *SetsTable) AddComment() *SetAnyFunc { + sf := t.AddStringFunc("Comment", func(m *Set) string { + return m.Comment + }) + return sf +} + +func (t *SetsTable) AddState() *SetAnyFunc { + sf := t.AddStringFunc("State", func(m *Set) string { + return m.State + }) + return sf +} +func (mt *SetsTable) NewUuid() { + mt.pb.Uuid = uuid.New().String() +} + +// START TABLE UPDATE (doesn't work yet) + +func (mt *SetsTable) dumpStringFunc(name string) { + for i, r := range mt.pb.StringCols { + // log.Info("could use", i, r.Header.Name, "for name =", name) + if r.Header.Name == name { + log.Info("dump Strings row", i, r.Header.Name, r.Vals) + break + } + } +} + +func (mt *SetsTable) Delete() { + if mt == nil { + log.Info("mt == nil table already deleted") + return + } + // log.Info("table Delete here") + mt.parent.DeleteTable(mt.pb) +} + +func (mt *SetsTable) setsCustom(w *guipb.Widget) { + row := mt.x.Sets[w.Location.Y-1] + // log.Info("got to setsCustom() with", w.Location.X, w.Location.Y-1) + + for i, sf := range mt.anyFuncs { + if i == int(w.Location.X) { + if sf.Custom != nil { + log.Info("doing Custom() func for button") + sf.Custom(row) + return + } + } + } + mt.CustomFunc(row) +} + +func (mt *SetsTable) Custom(f func(*Set)) { + mt.pb.RegisterCustom(mt.setsCustom) + mt.CustomFunc = f +} + +func (mt *SetsTable) GetUuid() string { + return mt.pb.Uuid +} + +// END TABLE UPDATE + +// END GUI diff --git a/set.http.pb.go b/set.http.pb.go new file mode 100644 index 0000000..0291e1b --- /dev/null +++ b/set.http.pb.go @@ -0,0 +1,98 @@ +// Code generated by go.wit.com/apps/autogenpb DO NOT EDIT. +// This file was autogenerated with autogenpb v0.5.6-1-g08dc949 2025.09.23_0925 +// go install go.wit.com/apps/autogenpb@latest +// +// define which structs (messages) you want to use in the .proto file +// Then sort.pb.go and marshal.pb.go files are autogenerated +// +// autogenpb uses it and has an example .proto file with instructions +// + +package forgepb + +import ( + "fmt" + "net/http" + "path/filepath" + + "go.wit.com/lib/protobuf/httppb" +) + +// START HTTP + +func (p *Sets) SendReply(w http.ResponseWriter, reqPB *httppb.HttpRequest) error { + data, err := p.Marshal() + if err != nil { + // reqPB.Errors = append(reqPB.Errors, log.Sprintf(, err)) + } + if len(data) == 0 { + // reqPB.Errors = append(reqPB.Errors, "Patches PB data was nil/emtpy without Marsha() error") + return nil + } + _, err = w.Write(data) + if err != nil { + // reqPB.Errors = append(reqPB.Errors, log.Sprintf(, i, err)) + } + return err +} + +// Marshal protobuf, then http POST, then Unmarshal() to protobuf again +func (p *Sets) HttpPost(baseURL string, route string) (*Sets, *httppb.HttpRequest, error) { + data, err := p.Marshal() + if err != nil { + return nil, nil, err + } + + tmp := filepath.Join("sets", route) + reqPB, err := httppb.DoPost(baseURL, tmp, data) + if reqPB == nil { + return nil, nil, err + } + + if len(reqPB.ServerData) == 0 { + return nil, reqPB, fmt.Errorf("server returned len(data)=0") + } + + newpb := new(Sets) + err = newpb.Unmarshal(reqPB.ServerData) + return newpb, reqPB, err +} +func (p *Set) SendReply(w http.ResponseWriter, reqPB *httppb.HttpRequest) error { + data, err := p.Marshal() + if err != nil { + // reqPB.Errors = append(reqPB.Errors, log.Sprintf(, err)) + } + if len(data) == 0 { + // reqPB.Errors = append(reqPB.Errors, "Patches PB data was nil/emtpy without Marsha() error") + return nil + } + _, err = w.Write(data) + if err != nil { + // reqPB.Errors = append(reqPB.Errors, log.Sprintf(, i, err)) + } + return err +} + +// Marshal protobuf, then http POST, then Unmarshal() to protobuf again +func (p *Set) HttpPost(baseURL string, route string) (*Set, *httppb.HttpRequest, error) { + data, err := p.Marshal() + if err != nil { + return nil, nil, err + } + + tmp := filepath.Join("set", route) + reqPB, err := httppb.DoPost(baseURL, tmp, data) + if reqPB == nil { + return nil, nil, err + } + + if len(reqPB.ServerData) == 0 { + return nil, reqPB, fmt.Errorf("server returned len(data)=0") + } + + newpb := new(Set) + err = newpb.Unmarshal(reqPB.ServerData) + return newpb, reqPB, err +} + +// END HTTP diff --git a/set.marshal.pb.go b/set.marshal.pb.go new file mode 100644 index 0000000..c5022ba --- /dev/null +++ b/set.marshal.pb.go @@ -0,0 +1,93 @@ +// Code generated by go.wit.com/apps/autogenpb DO NOT EDIT. +// This file was autogenerated with autogenpb v0.5.6-1-g08dc949 2025.09.23_0925 +// go install go.wit.com/apps/autogenpb@latest +// +// define which structs (messages) you want to use in the .proto file +// Then sort.pb.go and marshal.pb.go files are autogenerated +// +// autogenpb uses it and has an example .proto file with instructions +// + +package forgepb + +import ( + "google.golang.org/protobuf/encoding/protojson" + "google.golang.org/protobuf/encoding/prototext" + "google.golang.org/protobuf/proto" +) + +// human readable JSON +func (v *Sets) FormatJSON() string { + return protojson.Format(v) +} + +// marshal json +func (v *Sets) MarshalJSON() ([]byte, error) { + return protojson.Marshal(v) +} + +// unmarshal json +func (v *Sets) UnmarshalJSON(data []byte) error { + return protojson.Unmarshal(data, v) +} + +// apparently this isn't stable, but it's awesomely better +// https://protobuf.dev/reference/go/faq/#unstable-text +// it's brilliant for config files! +func (v *Sets) FormatTEXT() string { + v.fixUuid() + return prototext.Format(v) +} + +// unmarshalTEXT. This reads the .text config file back in after the user edits it +func (v *Sets) UnmarshalTEXT(data []byte) error { + return prototext.Unmarshal(data, v) +} + +// marshal to wire. This is called winning. +func (v *Sets) Marshal() ([]byte, error) { + v.fixUuid() + return proto.Marshal(v) +} + +// unmarshal from wire. You have won. +func (v *Sets) Unmarshal(data []byte) error { + return proto.Unmarshal(data, v) +} + +// human readable JSON +func (v *Set) FormatJSON() string { + return protojson.Format(v) +} + +// marshal json +func (v *Set) MarshalJSON() ([]byte, error) { + return protojson.Marshal(v) +} + +// unmarshal json +func (v *Set) UnmarshalJSON(data []byte) error { + return protojson.Unmarshal(data, v) +} + +// apparently this isn't stable, but it's awesomely better +// https://protobuf.dev/reference/go/faq/#unstable-text +// it's brilliant for config files! +func (v *Set) FormatTEXT() string { + return prototext.Format(v) +} + +// unmarshalTEXT. This reads the .text config file back in after the user edits it +func (v *Set) UnmarshalTEXT(data []byte) error { + return prototext.Unmarshal(data, v) +} + +// marshal to wire. This is called winning. +func (v *Set) Marshal() ([]byte, error) { + return proto.Marshal(v) +} + +// unmarshal from wire. You have won. +func (v *Set) Unmarshal(data []byte) error { + return proto.Unmarshal(data, v) +} diff --git a/set.pb.go b/set.pb.go new file mode 100644 index 0000000..660deb5 --- /dev/null +++ b/set.pb.go @@ -0,0 +1,388 @@ +// Code modified by go.wit.com/apps/autogenpb DO NOT EDIT. +// +// user defined Mutex locks were auto added +// +// autogenpb version & build time: v0.5.6-1-g08dc949 2025.09.23_0925 +// autogenpb auto generates Sort(), Unique() and Marshal() functions +// go install go.wit.com/apps/autogenpb@latest + +// Copyright 2025 WIT.COM Inc Licensed GPL 3.0 + +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.33.0 +// protoc v3.21.12 +// source: set.proto + +package forgepb // autogenpb changed the package name + +import ( + reflect "reflect" + sync "sync" + + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + timestamppb "google.golang.org/protobuf/types/known/timestamppb" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +type Set struct { + sync.RWMutex // auto-added by go.wit.com/apps/autogenpb + + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Patches *Patches `protobuf:"bytes,1,opt,name=patches,proto3" json:"patches,omitempty"` + Uuid string `protobuf:"bytes,2,opt,name=uuid,proto3" json:"uuid,omitempty"` + Ctime *timestamppb.Timestamp `protobuf:"bytes,3,opt,name=ctime,proto3" json:"ctime,omitempty"` // when the patches were submitted + Submitter string `protobuf:"bytes,4,opt,name=submitter,proto3" json:"submitter,omitempty"` // who submitted these // deprecate this + Name string `protobuf:"bytes,5,opt,name=name,proto3" json:"name,omitempty"` // "fixes for foo" + GitAuthorName string `protobuf:"bytes,6,opt,name=gitAuthorName,proto3" json:"gitAuthorName,omitempty"` + GitAuthorEmail string `protobuf:"bytes,7,opt,name=gitAuthorEmail,proto3" json:"gitAuthorEmail,omitempty"` + Hostname string `protobuf:"bytes,8,opt,name=hostname,proto3" json:"hostname,omitempty"` + TmpDir string `protobuf:"bytes,9,opt,name=tmpDir,proto3" json:"tmpDir,omitempty"` // temp dir for 'git am' deprecate this + StartBranchName string `protobuf:"bytes,10,opt,name=startBranchName,proto3" json:"startBranchName,omitempty"` // deprecate this + EndBranchName string `protobuf:"bytes,11,opt,name=endBranchName,proto3" json:"endBranchName,omitempty"` // deprecate this + StartBranchHash string `protobuf:"bytes,12,opt,name=startBranchHash,proto3" json:"startBranchHash,omitempty"` // deprecate this + EndBranchHash string `protobuf:"bytes,13,opt,name=endBranchHash,proto3" json:"endBranchHash,omitempty"` // deprecate this + Comment string `protobuf:"bytes,14,opt,name=comment,proto3" json:"comment,omitempty"` // deprecate this + State string `protobuf:"bytes,15,opt,name=state,proto3" json:"state,omitempty"` // deprecate this +} + +func (x *Set) Reset() { + *x = Set{} + if protoimpl.UnsafeEnabled { + mi := &file_set_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Set) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Set) ProtoMessage() {} + +func (x *Set) ProtoReflect() protoreflect.Message { + mi := &file_set_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Set.ProtoReflect.Descriptor instead. +func (*Set) Descriptor() ([]byte, []int) { + return file_set_proto_rawDescGZIP(), []int{0} +} + +func (x *Set) GetPatches() *Patches { + if x != nil { + return x.Patches + } + return nil +} + +func (x *Set) GetUuid() string { + if x != nil { + return x.Uuid + } + return "" +} + +func (x *Set) GetCtime() *timestamppb.Timestamp { + if x != nil { + return x.Ctime + } + return nil +} + +func (x *Set) GetSubmitter() string { + if x != nil { + return x.Submitter + } + return "" +} + +func (x *Set) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *Set) GetGitAuthorName() string { + if x != nil { + return x.GitAuthorName + } + return "" +} + +func (x *Set) GetGitAuthorEmail() string { + if x != nil { + return x.GitAuthorEmail + } + return "" +} + +func (x *Set) GetHostname() string { + if x != nil { + return x.Hostname + } + return "" +} + +func (x *Set) GetTmpDir() string { + if x != nil { + return x.TmpDir + } + return "" +} + +func (x *Set) GetStartBranchName() string { + if x != nil { + return x.StartBranchName + } + return "" +} + +func (x *Set) GetEndBranchName() string { + if x != nil { + return x.EndBranchName + } + return "" +} + +func (x *Set) GetStartBranchHash() string { + if x != nil { + return x.StartBranchHash + } + return "" +} + +func (x *Set) GetEndBranchHash() string { + if x != nil { + return x.EndBranchHash + } + return "" +} + +func (x *Set) GetComment() string { + if x != nil { + return x.Comment + } + return "" +} + +func (x *Set) GetState() string { + if x != nil { + return x.State + } + return "" +} + +type Sets struct { + // sync.RWMutex // skipped. protobuf file has `autogenpb:nomutex` + + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Uuid string `protobuf:"bytes,1,opt,name=uuid,proto3" json:"uuid,omitempty"` // `autogenpb:uuid:be926ad9-f07f-484c-adf2-d96eeabf3079` + Version string `protobuf:"bytes,2,opt,name=version,proto3" json:"version,omitempty"` // `autogenpb:version:v0.0.45` + Sets []*Set `protobuf:"bytes,3,rep,name=sets,proto3" json:"sets,omitempty"` +} + +func (x *Sets) Reset() { + *x = Sets{} + if protoimpl.UnsafeEnabled { + mi := &file_set_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Sets) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Sets) ProtoMessage() {} + +func (x *Sets) ProtoReflect() protoreflect.Message { + mi := &file_set_proto_msgTypes[1] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Sets.ProtoReflect.Descriptor instead. +func (*Sets) Descriptor() ([]byte, []int) { + return file_set_proto_rawDescGZIP(), []int{1} +} + +func (x *Sets) GetUuid() string { + if x != nil { + return x.Uuid + } + return "" +} + +func (x *Sets) GetVersion() string { + if x != nil { + return x.Version + } + return "" +} + +func (x *Sets) GetSets() []*Set { + if x != nil { + return x.Sets + } + return nil +} + +var File_set_proto protoreflect.FileDescriptor + +var file_set_proto_rawDesc = []byte{ + 0x0a, 0x09, 0x73, 0x65, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x07, 0x66, 0x6f, 0x72, + 0x67, 0x65, 0x70, 0x62, 0x1a, 0x1f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x0b, 0x70, 0x61, 0x74, 0x63, 0x68, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x22, 0xfb, 0x03, 0x0a, 0x03, 0x53, 0x65, 0x74, 0x12, 0x2a, 0x0a, 0x07, 0x70, 0x61, + 0x74, 0x63, 0x68, 0x65, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x66, 0x6f, + 0x72, 0x67, 0x65, 0x70, 0x62, 0x2e, 0x50, 0x61, 0x74, 0x63, 0x68, 0x65, 0x73, 0x52, 0x07, 0x70, + 0x61, 0x74, 0x63, 0x68, 0x65, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x75, 0x75, 0x69, 0x64, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x75, 0x75, 0x69, 0x64, 0x12, 0x30, 0x0a, 0x05, 0x63, 0x74, + 0x69, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, + 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, + 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x05, 0x63, 0x74, 0x69, 0x6d, 0x65, 0x12, 0x1c, 0x0a, 0x09, + 0x73, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x09, 0x73, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x72, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, + 0x6d, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x24, + 0x0a, 0x0d, 0x67, 0x69, 0x74, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x18, + 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x67, 0x69, 0x74, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, + 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x26, 0x0a, 0x0e, 0x67, 0x69, 0x74, 0x41, 0x75, 0x74, 0x68, 0x6f, + 0x72, 0x45, 0x6d, 0x61, 0x69, 0x6c, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x67, 0x69, + 0x74, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x45, 0x6d, 0x61, 0x69, 0x6c, 0x12, 0x1a, 0x0a, 0x08, + 0x68, 0x6f, 0x73, 0x74, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, + 0x68, 0x6f, 0x73, 0x74, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x74, 0x6d, 0x70, 0x44, + 0x69, 0x72, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x74, 0x6d, 0x70, 0x44, 0x69, 0x72, + 0x12, 0x28, 0x0a, 0x0f, 0x73, 0x74, 0x61, 0x72, 0x74, 0x42, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x4e, + 0x61, 0x6d, 0x65, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x73, 0x74, 0x61, 0x72, 0x74, + 0x42, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x24, 0x0a, 0x0d, 0x65, 0x6e, + 0x64, 0x42, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x0b, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x0d, 0x65, 0x6e, 0x64, 0x42, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x4e, 0x61, 0x6d, 0x65, + 0x12, 0x28, 0x0a, 0x0f, 0x73, 0x74, 0x61, 0x72, 0x74, 0x42, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x48, + 0x61, 0x73, 0x68, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x73, 0x74, 0x61, 0x72, 0x74, + 0x42, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x48, 0x61, 0x73, 0x68, 0x12, 0x24, 0x0a, 0x0d, 0x65, 0x6e, + 0x64, 0x42, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x48, 0x61, 0x73, 0x68, 0x18, 0x0d, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x0d, 0x65, 0x6e, 0x64, 0x42, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x48, 0x61, 0x73, 0x68, + 0x12, 0x18, 0x0a, 0x07, 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x0e, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x07, 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x74, + 0x61, 0x74, 0x65, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, + 0x22, 0x56, 0x0a, 0x04, 0x53, 0x65, 0x74, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x75, 0x75, 0x69, 0x64, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x75, 0x75, 0x69, 0x64, 0x12, 0x18, 0x0a, 0x07, + 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x76, + 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x20, 0x0a, 0x04, 0x73, 0x65, 0x74, 0x73, 0x18, 0x03, + 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x66, 0x6f, 0x72, 0x67, 0x65, 0x70, 0x62, 0x2e, 0x53, + 0x65, 0x74, 0x52, 0x04, 0x73, 0x65, 0x74, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, +} + +var ( + file_set_proto_rawDescOnce sync.Once + file_set_proto_rawDescData = file_set_proto_rawDesc +) + +func file_set_proto_rawDescGZIP() []byte { + file_set_proto_rawDescOnce.Do(func() { + file_set_proto_rawDescData = protoimpl.X.CompressGZIP(file_set_proto_rawDescData) + }) + return file_set_proto_rawDescData +} + +var file_set_proto_msgTypes = make([]protoimpl.MessageInfo, 2) +var file_set_proto_goTypes = []interface{}{ + (*Set)(nil), // 0: forgepb.Set + (*Sets)(nil), // 1: forgepb.Sets + (*Patches)(nil), // 2: forgepb.Patches + (*timestamppb.Timestamp)(nil), // 3: google.protobuf.Timestamp +} +var file_set_proto_depIdxs = []int32{ + 2, // 0: forgepb.Set.patches:type_name -> forgepb.Patches + 3, // 1: forgepb.Set.ctime:type_name -> google.protobuf.Timestamp + 0, // 2: forgepb.Sets.sets:type_name -> forgepb.Set + 3, // [3:3] is the sub-list for method output_type + 3, // [3:3] is the sub-list for method input_type + 3, // [3:3] is the sub-list for extension type_name + 3, // [3:3] is the sub-list for extension extendee + 0, // [0:3] is the sub-list for field type_name +} + +func init() { file_set_proto_init() } +func file_set_proto_init() { + if File_set_proto != nil { + return + } + file_patch_proto_init() + if !protoimpl.UnsafeEnabled { + file_set_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Set); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_set_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Sets); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_set_proto_rawDesc, + NumEnums: 0, + NumMessages: 2, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_set_proto_goTypes, + DependencyIndexes: file_set_proto_depIdxs, + MessageInfos: file_set_proto_msgTypes, + }.Build() + File_set_proto = out.File + file_set_proto_rawDesc = nil + file_set_proto_goTypes = nil + file_set_proto_depIdxs = nil +} diff --git a/set.sort.pb.go b/set.sort.pb.go new file mode 100644 index 0000000..7b95ed0 --- /dev/null +++ b/set.sort.pb.go @@ -0,0 +1,191 @@ +// Code generated by go.wit.com/apps/autogenpb DO NOT EDIT. +// This file was autogenerated with autogenpb v0.5.6-1-g08dc949 2025.09.23_0925 +// go install go.wit.com/apps/autogenpb@latest +// +// define which structs (messages) you want to use in the .proto file +// Then sort.pb.go and marshal.pb.go files are autogenerated +// +// autogenpb uses it and has an example .proto file with instructions +// + +package forgepb + +import ( + "fmt" + "iter" + "sync" + + "google.golang.org/protobuf/proto" +) + +// a simple global lock +var setMu sync.RWMutex + +func (x *Sets) fixUuid() { + if x == nil { + return + } + if x.Uuid == "be926ad9-f07f-484c-adf2-d96eeabf3079" { + return + } + x.Uuid = "be926ad9-f07f-484c-adf2-d96eeabf3079" + x.Version = "v0.0.45 go.wit.com/lib/protobuf/forgepb" +} + +func NewSets() *Sets { + x := new(Sets) + x.Uuid = "be926ad9-f07f-484c-adf2-d96eeabf3079" + x.Version = "v0.0.45 go.wit.com/lib/protobuf/forgepb" + return x +} + +// START SORT + +// DEFINE THE Sets SCANNER. +// itializes a new scanner. +func newSetsScanner(things []*Sets) *SetsScanner { + return &SetsScanner{things: things} +} + +type SetsScanner struct { + sync.Mutex + + things []*Sets + index int +} + +func (it *SetsScanner) Scan() bool { + if it.index >= len(it.things) { + return false + } + it.Lock() + it.index++ + it.Unlock() + return true +} + +// Next() returns the next thing in the array +func (it *SetsScanner) Next() *Sets { + if it.things[it.index-1] == nil { + fmt.Println("Next() error in SetsScanner", it.index) + } + return it.things[it.index-1] +} + +// END DEFINE THE SCANNER + +// DEFINE THE Set SCANNER. +// itializes a new scanner. +func newSetScanner(things []*Set) *SetScanner { + return &SetScanner{things: things} +} + +type SetScanner struct { + sync.Mutex + + things []*Set + index int +} + +func (it *SetScanner) Scan() bool { + if it.index >= len(it.things) { + return false + } + it.Lock() + it.index++ + it.Unlock() + return true +} + +// Next() returns the next thing in the array +func (it *SetScanner) Next() *Set { + if it.things[it.index-1] == nil { + fmt.Println("Next() error in SetScanner", it.index) + } + return it.things[it.index-1] +} + +// END DEFINE THE SCANNER + +// safely returns a slice of pointers to the FRUIT protobufs +func (x *Sets) allSets() []*Set { + setMu.RLock() + defer setMu.RUnlock() + + // Create a new slice to hold pointers to each FRUIT + var tmp []*Set + tmp = make([]*Set, len(x.Sets)) + for i, p := range x.Sets { + tmp[i] = p // Copy pointers for safe iteration + } + + return tmp +} + +// safely returns a slice of pointers to the Set protobufs +func (x *Sets) selectAllSets() []*Set { + setMu.RLock() + defer setMu.RUnlock() + + // Create a new slice to hold pointers to each Set + var tmp []*Set + tmp = make([]*Set, len(x.Sets)) + for i, p := range x.Sets { + tmp[i] = p // Copy pointers for safe iteration + } + + return tmp +} + +// END SORT + +func (x *Sets) Len() int { + setMu.RLock() + defer setMu.RUnlock() + + return len(x.Sets) +} + +// a Append() shortcut (that does Clone() with a mutex) notsure if it really works +func (x *Sets) Append(y *Set) *Set { + setMu.Lock() + defer setMu.Unlock() + + z := proto.Clone(y).(*Set) + x.Sets = append(x.Sets, z) + + return z +} + +func (x *Sets) All() *SetScanner { + SetPointers := x.selectAllSets() + + scanner := newSetScanner(SetPointers) + return scanner +} + +// Iterate 'for x := range' syntax using the awesome golang 1.24 'iter' +func (x *Sets) IterAll() iter.Seq[*Set] { + items := x.selectAllSets() + // log.Println("Made All() Iter.Seq[] with length", len(items)) + return func(yield func(*Set) bool) { + for _, v := range items { + if !yield(v) { + return + } + } + } +} +func (x *Sets) Delete(y *Set) bool { + setMu.Lock() + defer setMu.Unlock() + + for i, _ := range x.Sets { + if x.Sets[i] == y { + x.Sets[i] = x.Sets[len(x.Sets)-1] + x.Sets = x.Sets[:len(x.Sets)-1] + return true + } + } + return false +}