From e83b5ece50a757acc5a03e257b46383308790f79 Mon Sep 17 00:00:00 2001 From: Jeff Carr Date: Mon, 22 Sep 2025 10:22:56 -0500 Subject: [PATCH] forge patches --- go.mod | 15 ++ go.sum | 20 +++ machine.gui.pb.go | 285 ++++++++++++++++++++++++++++++++ machine.http.pb.go | 98 +++++++++++ machine.marshal.pb.go | 93 +++++++++++ machine.pb.go | 371 ++++++++++++++++++++++++++++++++++++++++++ machine.sort.pb.go | 286 ++++++++++++++++++++++++++++++++ package.marshal.pb.go | 56 +++++++ package.pb.go | 292 +++++++++++++++++++++++++++++++++ package.sort.pb.go | 286 ++++++++++++++++++++++++++++++++ 10 files changed, 1802 insertions(+) create mode 100644 go.mod create mode 100644 go.sum create mode 100644 machine.gui.pb.go create mode 100644 machine.http.pb.go create mode 100644 machine.marshal.pb.go create mode 100644 machine.pb.go create mode 100644 machine.sort.pb.go create mode 100644 package.marshal.pb.go create mode 100644 package.pb.go create mode 100644 package.sort.pb.go diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..2f66bea --- /dev/null +++ b/go.mod @@ -0,0 +1,15 @@ +module go.wit.com/lib/protobuf/zoopb + +go 1.24.1 + +require ( + github.com/google/uuid v1.6.0 + go.wit.com/gui v0.25.3 + 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 + golang.org/x/sys v0.36.0 + google.golang.org/protobuf v1.36.9 +) + +require go.wit.com/widget v1.1.30 // indirect diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..41a3b21 --- /dev/null +++ b/go.sum @@ -0,0 +1,20 @@ +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= +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/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/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= diff --git a/machine.gui.pb.go b/machine.gui.pb.go new file mode 100644 index 0000000..2c5795c --- /dev/null +++ b/machine.gui.pb.go @@ -0,0 +1,285 @@ +// Code generated by go.wit.com/apps/autogenpb DO NOT EDIT. +// This file was autogenerated with autogenpb v0.5.5-2-g6c9a3dd 2025.09.22_0851 +// 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 zoopb + +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 *Machines) NewTable(title string) *MachinesTable { + t := new(MachinesTable) + 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 *MachinesTable) AddStringFunc(title string, f func(*Machine) string) *MachineAnyFunc { + t.pb.Order = append(t.pb.Order, title) + + sf := new(MachineAnyFunc) + sf.title = title + sf.f = func(x *Machine) 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 *MachinesTable) AddButtonFunc(title string, f func(*Machine) string) *MachineAnyFunc { + t.pb.Order = append(t.pb.Order, title) + + sf := new(MachineAnyFunc) + sf.title = title + sf.f = func(x *Machine) 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 *MachinesTable) AddIntFunc(title string, f func(*Machine) int) *MachineAnyFunc { + t.pb.Order = append(t.pb.Order, title) + + sf := new(MachineAnyFunc) + sf.title = title + sf.f = func(x *Machine) 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 *MachinesTable) AddTimeFunc(title string, f func(*Machine) time.Time) *MachineAnyFunc { + t.pb.Order = append(t.pb.Order, title) + + sf := new(MachineAnyFunc) + sf.title = title + sf.f = func(x *Machine) 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 *MachineAnyFunc) SetTitle(title string) { + sf.title = title +} + +func (mt *MachinesTable) SetParent(p *gui.Node) { + mt.parent = p +} + +func (mt *MachinesTable) ShowTable() { + // log.Info("ShowTable() SENDING TO GUI") + mt.MakeTable() + mt.parent.ShowTable(mt.pb) +} + +type MachineAnyFunc struct { + title string + f func(*Machine) any + Custom func(*Machine) + Width int + attr *guipb.ColAttr +} + +type MachinesTable struct { + pb *guipb.Table + parent *gui.Node + x *Machines + hostnames []string + anyFuncs []*MachineAnyFunc + CustomFunc func(*Machine) +} + +func (mt *MachinesTable) doAnyFuncNew(sf *MachineAnyFunc) bool { + r := new(guipb.AnyCol) + r.Header = new(guipb.Widget) + r.Header.Name = sf.title + r.Attr = proto.Clone(sf.attr).(*guipb.ColAttr) + + 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 *MachinesTable) MakeTable() { + for _, sf := range mt.anyFuncs { + mt.doAnyFuncNew(sf) + } +} + +func (t *MachinesTable) AddHostname() *MachineAnyFunc { + sf := t.AddStringFunc("Hostname", func(m *Machine) string { + return m.Hostname + }) + return sf +} + +func (t *MachinesTable) AddMemory() *MachineAnyFunc { + custf := t.AddIntFunc("Memory", func(m *Machine) int { + return int(m.Memory) + }) + return custf +} + +func (t *MachinesTable) AddCpus() *MachineAnyFunc { + custf := t.AddIntFunc("Cpus", func(m *Machine) int { + return int(m.Cpus) + }) + return custf +} + +func (t *MachinesTable) AddDistro() *MachineAnyFunc { + sf := t.AddStringFunc("Distro", func(m *Machine) string { + return m.Distro + }) + return sf +} + +func (t *MachinesTable) AddUserAgent() *MachineAnyFunc { + sf := t.AddStringFunc("UserAgent", func(m *Machine) string { + return m.UserAgent + }) + return sf +} + +func (t *MachinesTable) AddUuid() *MachineAnyFunc { + sf := t.AddStringFunc("Uuid", func(m *Machine) string { + return m.Uuid + }) + return sf +} + +func (t *MachinesTable) AddUpgradeCmd() *MachineAnyFunc { + sf := t.AddStringFunc("UpgradeCmd", func(m *Machine) string { + return m.UpgradeCmd + }) + return sf +} +func (mt *MachinesTable) NewUuid() { + mt.pb.Uuid = uuid.New().String() +} + +// START TABLE UPDATE (doesn't work yet) + +func (mt *MachinesTable) 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 *MachinesTable) Delete() { + if mt == nil { + log.Info("mt == nil table already deleted") + return + } + // log.Info("table Delete here") + mt.parent.DeleteTable(mt.pb) +} + +func (mt *MachinesTable) machinesCustom(w *guipb.Widget) { + row := mt.x.Machines[w.Location.Y-1] + // log.Info("got to machinesCustom() 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 *MachinesTable) Custom(f func(*Machine)) { + mt.pb.RegisterCustom(mt.machinesCustom) + mt.CustomFunc = f +} + +func (mt *MachinesTable) GetUuid() string { + return mt.pb.Uuid +} + +// END TABLE UPDATE + +// END GUI diff --git a/machine.http.pb.go b/machine.http.pb.go new file mode 100644 index 0000000..c28ba7c --- /dev/null +++ b/machine.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.5-2-g6c9a3dd 2025.09.22_0851 +// 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 zoopb + +import ( + "fmt" + "net/http" + "path/filepath" + + "go.wit.com/lib/protobuf/httppb" +) + +// START HTTP + +func (p *Machines) 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 *Machines) HttpPost(baseURL string, route string) (*Machines, *httppb.HttpRequest, error) { + data, err := p.Marshal() + if err != nil { + return nil, nil, err + } + + tmp := filepath.Join("machines", 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(Machines) + err = newpb.Unmarshal(reqPB.ServerData) + return newpb, reqPB, err +} +func (p *Machine) 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 *Machine) HttpPost(baseURL string, route string) (*Machine, *httppb.HttpRequest, error) { + data, err := p.Marshal() + if err != nil { + return nil, nil, err + } + + tmp := filepath.Join("machine", 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(Machine) + err = newpb.Unmarshal(reqPB.ServerData) + return newpb, reqPB, err +} + +// END HTTP diff --git a/machine.marshal.pb.go b/machine.marshal.pb.go new file mode 100644 index 0000000..ea814c8 --- /dev/null +++ b/machine.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.5-2-g6c9a3dd 2025.09.22_0851 +// 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 zoopb + +import ( + "google.golang.org/protobuf/encoding/protojson" + "google.golang.org/protobuf/encoding/prototext" + "google.golang.org/protobuf/proto" +) + +// human readable JSON +func (v *Machines) FormatJSON() string { + return protojson.Format(v) +} + +// marshal json +func (v *Machines) MarshalJSON() ([]byte, error) { + return protojson.Marshal(v) +} + +// unmarshal json +func (v *Machines) 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 *Machines) FormatTEXT() string { + v.fixUuid() + return prototext.Format(v) +} + +// unmarshalTEXT. This reads the .text config file back in after the user edits it +func (v *Machines) UnmarshalTEXT(data []byte) error { + return prototext.Unmarshal(data, v) +} + +// marshal to wire. This is called winning. +func (v *Machines) Marshal() ([]byte, error) { + v.fixUuid() + return proto.Marshal(v) +} + +// unmarshal from wire. You have won. +func (v *Machines) Unmarshal(data []byte) error { + return proto.Unmarshal(data, v) +} + +// human readable JSON +func (v *Machine) FormatJSON() string { + return protojson.Format(v) +} + +// marshal json +func (v *Machine) MarshalJSON() ([]byte, error) { + return protojson.Marshal(v) +} + +// unmarshal json +func (v *Machine) 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 *Machine) FormatTEXT() string { + return prototext.Format(v) +} + +// unmarshalTEXT. This reads the .text config file back in after the user edits it +func (v *Machine) UnmarshalTEXT(data []byte) error { + return prototext.Unmarshal(data, v) +} + +// marshal to wire. This is called winning. +func (v *Machine) Marshal() ([]byte, error) { + return proto.Marshal(v) +} + +// unmarshal from wire. You have won. +func (v *Machine) Unmarshal(data []byte) error { + return proto.Unmarshal(data, v) +} diff --git a/machine.pb.go b/machine.pb.go new file mode 100644 index 0000000..b938806 --- /dev/null +++ b/machine.pb.go @@ -0,0 +1,371 @@ +// Code modified by go.wit.com/apps/autogenpb DO NOT EDIT. +// +// user defined Mutex locks were auto added +// +// autogenpb version & build time: v0.5.5-2-g6c9a3dd 2025.09.22_0851 +// autogenpb auto generates Sort(), Unique() and Marshal() functions +// go install go.wit.com/apps/autogenpb@latest + +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.33.0 +// protoc v3.21.12 +// source: machine.proto + +package zoopb // 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 Machine struct { + sync.RWMutex // auto-added by go.wit.com/apps/autogenpb + + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Hostname string `protobuf:"bytes,1,opt,name=hostname,proto3" json:"hostname,omitempty"` // `autogenpb:unique` `autogenpb:sort` + Memory int64 `protobuf:"varint,2,opt,name=memory,proto3" json:"memory,omitempty"` + Cpus int64 `protobuf:"varint,3,opt,name=cpus,proto3" json:"cpus,omitempty"` + Distro string `protobuf:"bytes,4,opt,name=distro,proto3" json:"distro,omitempty"` + Packages *Packages `protobuf:"bytes,5,opt,name=packages,proto3" json:"packages,omitempty"` + Laststamp *timestamppb.Timestamp `protobuf:"bytes,6,opt,name=laststamp,proto3" json:"laststamp,omitempty"` // the last time we heard anything from this machine + Installed *Packages `protobuf:"bytes,7,opt,name=installed,proto3" json:"installed,omitempty"` // packages that are installed + Available *Packages `protobuf:"bytes,8,opt,name=available,proto3" json:"available,omitempty"` // packages that are available + Wit *Packages `protobuf:"bytes,9,opt,name=wit,proto3" json:"wit,omitempty"` // packages that are available from mirrors.wit.com + UserAgent string `protobuf:"bytes,10,opt,name=userAgent,proto3" json:"userAgent,omitempty"` + Uuid string `protobuf:"bytes,11,opt,name=uuid,proto3" json:"uuid,omitempty"` + Upgrade bool `protobuf:"varint,12,opt,name=upgrade,proto3" json:"upgrade,omitempty"` // upgrade is needed + UpgradeCmd string `protobuf:"bytes,13,opt,name=upgradeCmd,proto3" json:"upgradeCmd,omitempty"` // upgrade cmd +} + +func (x *Machine) Reset() { + *x = Machine{} + if protoimpl.UnsafeEnabled { + mi := &file_machine_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Machine) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Machine) ProtoMessage() {} + +func (x *Machine) ProtoReflect() protoreflect.Message { + mi := &file_machine_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 Machine.ProtoReflect.Descriptor instead. +func (*Machine) Descriptor() ([]byte, []int) { + return file_machine_proto_rawDescGZIP(), []int{0} +} + +func (x *Machine) GetHostname() string { + if x != nil { + return x.Hostname + } + return "" +} + +func (x *Machine) GetMemory() int64 { + if x != nil { + return x.Memory + } + return 0 +} + +func (x *Machine) GetCpus() int64 { + if x != nil { + return x.Cpus + } + return 0 +} + +func (x *Machine) GetDistro() string { + if x != nil { + return x.Distro + } + return "" +} + +func (x *Machine) GetPackages() *Packages { + if x != nil { + return x.Packages + } + return nil +} + +func (x *Machine) GetLaststamp() *timestamppb.Timestamp { + if x != nil { + return x.Laststamp + } + return nil +} + +func (x *Machine) GetInstalled() *Packages { + if x != nil { + return x.Installed + } + return nil +} + +func (x *Machine) GetAvailable() *Packages { + if x != nil { + return x.Available + } + return nil +} + +func (x *Machine) GetWit() *Packages { + if x != nil { + return x.Wit + } + return nil +} + +func (x *Machine) GetUserAgent() string { + if x != nil { + return x.UserAgent + } + return "" +} + +func (x *Machine) GetUuid() string { + if x != nil { + return x.Uuid + } + return "" +} + +func (x *Machine) GetUpgrade() bool { + if x != nil { + return x.Upgrade + } + return false +} + +func (x *Machine) GetUpgradeCmd() string { + if x != nil { + return x.UpgradeCmd + } + return "" +} + +type Machines 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:b57e7fac-a8fc-4949-9d50-fa38312dec87` + Version string `protobuf:"bytes,2,opt,name=version,proto3" json:"version,omitempty"` // `autogenpb:version:v0.0.1` + Machines []*Machine `protobuf:"bytes,3,rep,name=machines,proto3" json:"machines,omitempty"` +} + +func (x *Machines) Reset() { + *x = Machines{} + if protoimpl.UnsafeEnabled { + mi := &file_machine_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Machines) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Machines) ProtoMessage() {} + +func (x *Machines) ProtoReflect() protoreflect.Message { + mi := &file_machine_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 Machines.ProtoReflect.Descriptor instead. +func (*Machines) Descriptor() ([]byte, []int) { + return file_machine_proto_rawDescGZIP(), []int{1} +} + +func (x *Machines) GetUuid() string { + if x != nil { + return x.Uuid + } + return "" +} + +func (x *Machines) GetVersion() string { + if x != nil { + return x.Version + } + return "" +} + +func (x *Machines) GetMachines() []*Machine { + if x != nil { + return x.Machines + } + return nil +} + +var File_machine_proto protoreflect.FileDescriptor + +var file_machine_proto_rawDesc = []byte{ + 0x0a, 0x0d, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, + 0x05, 0x67, 0x69, 0x74, 0x70, 0x62, 0x1a, 0x0d, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 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, 0xbd, 0x03, 0x0a, 0x07, 0x4d, 0x61, 0x63, 0x68, 0x69, + 0x6e, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x68, 0x6f, 0x73, 0x74, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x68, 0x6f, 0x73, 0x74, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x16, + 0x0a, 0x06, 0x6d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, + 0x6d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x12, 0x12, 0x0a, 0x04, 0x63, 0x70, 0x75, 0x73, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x03, 0x52, 0x04, 0x63, 0x70, 0x75, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x64, 0x69, + 0x73, 0x74, 0x72, 0x6f, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x64, 0x69, 0x73, 0x74, + 0x72, 0x6f, 0x12, 0x2b, 0x0a, 0x08, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x73, 0x18, 0x05, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x67, 0x69, 0x74, 0x70, 0x62, 0x2e, 0x50, 0x61, 0x63, + 0x6b, 0x61, 0x67, 0x65, 0x73, 0x52, 0x08, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x73, 0x12, + 0x38, 0x0a, 0x09, 0x6c, 0x61, 0x73, 0x74, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x06, 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, 0x09, + 0x6c, 0x61, 0x73, 0x74, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x2d, 0x0a, 0x09, 0x69, 0x6e, 0x73, + 0x74, 0x61, 0x6c, 0x6c, 0x65, 0x64, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x67, + 0x69, 0x74, 0x70, 0x62, 0x2e, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x73, 0x52, 0x09, 0x69, + 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x65, 0x64, 0x12, 0x2d, 0x0a, 0x09, 0x61, 0x76, 0x61, 0x69, + 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x67, 0x69, + 0x74, 0x70, 0x62, 0x2e, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x73, 0x52, 0x09, 0x61, 0x76, + 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x12, 0x21, 0x0a, 0x03, 0x77, 0x69, 0x74, 0x18, 0x09, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x67, 0x69, 0x74, 0x70, 0x62, 0x2e, 0x50, 0x61, 0x63, + 0x6b, 0x61, 0x67, 0x65, 0x73, 0x52, 0x03, 0x77, 0x69, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x75, 0x73, + 0x65, 0x72, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x75, + 0x73, 0x65, 0x72, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x75, 0x75, 0x69, 0x64, + 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x75, 0x75, 0x69, 0x64, 0x12, 0x18, 0x0a, 0x07, + 0x75, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x75, + 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x12, 0x1e, 0x0a, 0x0a, 0x75, 0x70, 0x67, 0x72, 0x61, 0x64, + 0x65, 0x43, 0x6d, 0x64, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x75, 0x70, 0x67, 0x72, + 0x61, 0x64, 0x65, 0x43, 0x6d, 0x64, 0x22, 0x64, 0x0a, 0x08, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, + 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, 0x2a, 0x0a, 0x08, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, + 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x67, 0x69, 0x74, 0x70, 0x62, 0x2e, 0x4d, 0x61, 0x63, 0x68, 0x69, + 0x6e, 0x65, 0x52, 0x08, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x73, 0x62, 0x06, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x33, +} + +var ( + file_machine_proto_rawDescOnce sync.Once + file_machine_proto_rawDescData = file_machine_proto_rawDesc +) + +func file_machine_proto_rawDescGZIP() []byte { + file_machine_proto_rawDescOnce.Do(func() { + file_machine_proto_rawDescData = protoimpl.X.CompressGZIP(file_machine_proto_rawDescData) + }) + return file_machine_proto_rawDescData +} + +var file_machine_proto_msgTypes = make([]protoimpl.MessageInfo, 2) +var file_machine_proto_goTypes = []interface{}{ + (*Machine)(nil), // 0: gitpb.Machine + (*Machines)(nil), // 1: gitpb.Machines + (*Packages)(nil), // 2: gitpb.Packages + (*timestamppb.Timestamp)(nil), // 3: google.protobuf.Timestamp +} +var file_machine_proto_depIdxs = []int32{ + 2, // 0: gitpb.Machine.packages:type_name -> gitpb.Packages + 3, // 1: gitpb.Machine.laststamp:type_name -> google.protobuf.Timestamp + 2, // 2: gitpb.Machine.installed:type_name -> gitpb.Packages + 2, // 3: gitpb.Machine.available:type_name -> gitpb.Packages + 2, // 4: gitpb.Machine.wit:type_name -> gitpb.Packages + 0, // 5: gitpb.Machines.machines:type_name -> gitpb.Machine + 6, // [6:6] is the sub-list for method output_type + 6, // [6:6] is the sub-list for method input_type + 6, // [6:6] is the sub-list for extension type_name + 6, // [6:6] is the sub-list for extension extendee + 0, // [0:6] is the sub-list for field type_name +} + +func init() { file_machine_proto_init() } +func file_machine_proto_init() { + if File_machine_proto != nil { + return + } + file_package_proto_init() + if !protoimpl.UnsafeEnabled { + file_machine_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Machine); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_machine_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Machines); 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_machine_proto_rawDesc, + NumEnums: 0, + NumMessages: 2, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_machine_proto_goTypes, + DependencyIndexes: file_machine_proto_depIdxs, + MessageInfos: file_machine_proto_msgTypes, + }.Build() + File_machine_proto = out.File + file_machine_proto_rawDesc = nil + file_machine_proto_goTypes = nil + file_machine_proto_depIdxs = nil +} diff --git a/machine.sort.pb.go b/machine.sort.pb.go new file mode 100644 index 0000000..ca7929c --- /dev/null +++ b/machine.sort.pb.go @@ -0,0 +1,286 @@ +// Code generated by go.wit.com/apps/autogenpb DO NOT EDIT. +// This file was autogenerated with autogenpb v0.5.5-2-g6c9a3dd 2025.09.22_0851 +// 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 zoopb + +import ( + "fmt" + "iter" + "sort" + "sync" + + "google.golang.org/protobuf/proto" +) + +// a simple global lock +var machineMu sync.RWMutex + +func (x *Machines) fixUuid() { + if x == nil { + return + } + if x.Uuid == "b57e7fac-a8fc-4949-9d50-fa38312dec87" { + return + } + x.Uuid = "b57e7fac-a8fc-4949-9d50-fa38312dec87" + x.Version = "v0.0.1 go.wit.com/lib/protobuf/zoopb" +} + +func NewMachines() *Machines { + x := new(Machines) + x.Uuid = "b57e7fac-a8fc-4949-9d50-fa38312dec87" + x.Version = "v0.0.1 go.wit.com/lib/protobuf/zoopb" + return x +} + +// START SORT + +// DEFINE THE Machines SCANNER. +// itializes a new scanner. +func newMachinesScanner(things []*Machines) *MachinesScanner { + return &MachinesScanner{things: things} +} + +type MachinesScanner struct { + sync.Mutex + + things []*Machines + index int +} + +func (it *MachinesScanner) 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 *MachinesScanner) Next() *Machines { + if it.things[it.index-1] == nil { + fmt.Println("Next() error in MachinesScanner", it.index) + } + return it.things[it.index-1] +} + +// END DEFINE THE SCANNER + +// DEFINE THE Machine SCANNER. +// itializes a new scanner. +func newMachineScanner(things []*Machine) *MachineScanner { + return &MachineScanner{things: things} +} + +type MachineScanner struct { + sync.Mutex + + things []*Machine + index int +} + +func (it *MachineScanner) 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 *MachineScanner) Next() *Machine { + if it.things[it.index-1] == nil { + fmt.Println("Next() error in MachineScanner", it.index) + } + return it.things[it.index-1] +} + +// END DEFINE THE SCANNER + +// sort struct by Hostname +type sortMachineHostname []*Machine + +func (a sortMachineHostname) Len() int { return len(a) } +func (a sortMachineHostname) Less(i, j int) bool { return a[i].Hostname < a[j].Hostname } +func (a sortMachineHostname) Swap(i, j int) { a[i], a[j] = a[j], a[i] } + +// safely returns a slice of pointers to the FRUIT protobufs +func (x *Machines) allMachines() []*Machine { + x.RLock() + defer x.RUnlock() + + // Create a new slice to hold pointers to each FRUIT + var tmp []*Machine + tmp = make([]*Machine, len(x.Machines)) + for i, p := range x.Machines { + tmp[i] = p // Copy pointers for safe iteration + } + + return tmp +} + +// safely returns a slice of pointers to the Machine protobufs +func (x *Machines) selectAllMachines() []*Machine { + x.RLock() + defer x.RUnlock() + + // Create a new slice to hold pointers to each Machine + var tmp []*Machine + tmp = make([]*Machine, len(x.Machines)) + for i, p := range x.Machines { + tmp[i] = p // Copy pointers for safe iteration + } + + return tmp +} +func (x *Machines) SortByHostname() *MachineScanner { + // copy the pointers as fast as possible. + things := x.selectAllMachines() + + // todo: try slices.SortFunc() instead to see what happens + sort.Sort(sortMachineHostname(things)) + // slices.SortFunc(things, func(a, b *Machines) bool { + // return a.Hostname < b.Hostname // Sort by ??. let the compiler work it out?? + // }) + return newMachineScanner(things) +} + +// 'for x := range' syntax using the awesome golang 1.24 'iter' +func (x *Machines) IterByHostname() iter.Seq[*Machine] { + items := x.selectAllMachines() + sort.Sort(sortMachineHostname(items)) + // log.Println("Made Iter.Seq[] with length", len(items)) + return func(yield func(*Machine) bool) { + for _, v := range items { + if !yield(v) { + return + } + } + } +} + +// END SORT + +func (x *Machines) Len() int { + x.RLock() + defer x.RUnlock() + + return len(x.Machines) +} + +// a Append() shortcut (that does Clone() with a mutex) notsure if it really works +func (x *Machines) Append(y *Machine) *Machine { + x.Lock() + defer x.Unlock() + + z := proto.Clone(y).(*Machine) + x.Machines = append(x.Machines, z) + + return z +} + +func (x *Machines) All() *MachineScanner { + MachinePointers := x.selectAllMachines() + + scanner := newMachineScanner(MachinePointers) + return scanner +} + +// Iterate 'for x := range' syntax using the awesome golang 1.24 'iter' +func (x *Machines) IterAll() iter.Seq[*Machine] { + items := x.selectAllMachines() + // log.Println("Made All() Iter.Seq[] with length", len(items)) + return func(yield func(*Machine) bool) { + for _, v := range items { + if !yield(v) { + return + } + } + } +} +func (x *Machines) Delete(y *Machine) bool { + x.Lock() + defer x.Unlock() + + for i, _ := range x.Machines { + if x.Machines[i] == y { + x.Machines[i] = x.Machines[len(x.Machines)-1] + x.Machines = x.Machines[:len(x.Machines)-1] + return true + } + } + return false +} + +// lookup a Machines by the Hostname +func (x *Machines) FindByHostname(s string) *Machine { + if x == nil { + return nil + } + + x.RLock() + defer x.RUnlock() + + for i, _ := range x.Machines { + if x.Machines[i].Hostname == s { + return x.Machines[i] + } + } + return nil +} + +// returns a Machine if Hostname matches, otherwise create +func (x *Machines) InsertByHostname(y string) *Machine { + x.Lock() + defer x.Unlock() + + for _, z := range x.Machines { + if z.Hostname == y { + return z + } + } + + z := new(Machine) + z.Hostname = y + x.Machines = append(x.Machines, z) + return z +} + +func (x *Machines) DeleteByHostname(s string) bool { + x.Lock() + defer x.Unlock() + + for i, _ := range x.Machines { + if x.Machines[i].Hostname == s { + x.Machines[i] = x.Machines[len(x.Machines)-1] + x.Machines = x.Machines[:len(x.Machines)-1] + return true + } + } + return false +} + +func (x *Machines) AppendByHostname(y *Machine) bool { + x.Lock() + defer x.Unlock() + + for _, p := range x.Machines { + if p.Hostname == y.Hostname { + return false + } + } + + x.Machines = append(x.Machines, proto.Clone(y).(*Machine)) + return true +} diff --git a/package.marshal.pb.go b/package.marshal.pb.go new file mode 100644 index 0000000..8133fcc --- /dev/null +++ b/package.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.5-2-g6c9a3dd 2025.09.22_0851 +// 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 zoopb + +import ( + "google.golang.org/protobuf/encoding/protojson" + "google.golang.org/protobuf/encoding/prototext" + "google.golang.org/protobuf/proto" +) + +// human readable JSON +func (v *Packages) FormatJSON() string { + return protojson.Format(v) +} + +// marshal json +func (v *Packages) MarshalJSON() ([]byte, error) { + return protojson.Marshal(v) +} + +// unmarshal json +func (v *Packages) 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 *Packages) FormatTEXT() string { + v.fixUuid() + return prototext.Format(v) +} + +// unmarshalTEXT. This reads the .text config file back in after the user edits it +func (v *Packages) UnmarshalTEXT(data []byte) error { + return prototext.Unmarshal(data, v) +} + +// marshal to wire. This is called winning. +func (v *Packages) Marshal() ([]byte, error) { + v.fixUuid() + return proto.Marshal(v) +} + +// unmarshal from wire. You have won. +func (v *Packages) Unmarshal(data []byte) error { + return proto.Unmarshal(data, v) +} diff --git a/package.pb.go b/package.pb.go new file mode 100644 index 0000000..14a6cae --- /dev/null +++ b/package.pb.go @@ -0,0 +1,292 @@ +// Code modified by go.wit.com/apps/autogenpb DO NOT EDIT. +// +// user defined Mutex locks were auto added +// +// autogenpb version & build time: v0.5.5-2-g6c9a3dd 2025.09.22_0851 +// autogenpb auto generates Sort(), Unique() and Marshal() functions +// go install go.wit.com/apps/autogenpb@latest + +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.33.0 +// protoc v3.21.12 +// source: package.proto + +package zoopb // 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 Package struct { + sync.RWMutex // auto-added by go.wit.com/apps/autogenpb + + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` // `autogenpb:unique` `autogenpb:sort` + Version string `protobuf:"bytes,2,opt,name=version,proto3" json:"version,omitempty"` // version: 0.0.3 + Laststamp *timestamppb.Timestamp `protobuf:"bytes,3,opt,name=laststamp,proto3" json:"laststamp,omitempty"` // the last time this package was seen (used to timeout entries) + SrcPath string `protobuf:"bytes,4,opt,name=srcPath,proto3" json:"srcPath,omitempty"` // path to the sources (go.wit.com/apps/zookeeper) + Installed bool `protobuf:"varint,5,opt,name=installed,proto3" json:"installed,omitempty"` // if installed on your machine, this should be set to true + PkgName string `protobuf:"bytes,6,opt,name=pkgName,proto3" json:"pkgName,omitempty"` // the apt filename pool/main/f/foo/foo_2.2.2_riscv64.deb +} + +func (x *Package) Reset() { + *x = Package{} + if protoimpl.UnsafeEnabled { + mi := &file_package_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Package) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Package) ProtoMessage() {} + +func (x *Package) ProtoReflect() protoreflect.Message { + mi := &file_package_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 Package.ProtoReflect.Descriptor instead. +func (*Package) Descriptor() ([]byte, []int) { + return file_package_proto_rawDescGZIP(), []int{0} +} + +func (x *Package) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *Package) GetVersion() string { + if x != nil { + return x.Version + } + return "" +} + +func (x *Package) GetLaststamp() *timestamppb.Timestamp { + if x != nil { + return x.Laststamp + } + return nil +} + +func (x *Package) GetSrcPath() string { + if x != nil { + return x.SrcPath + } + return "" +} + +func (x *Package) GetInstalled() bool { + if x != nil { + return x.Installed + } + return false +} + +func (x *Package) GetPkgName() string { + if x != nil { + return x.PkgName + } + return "" +} + +type Packages 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:2f26cc03-ea30-4481-a333-ad0acc86e1d3` + Version string `protobuf:"bytes,2,opt,name=version,proto3" json:"version,omitempty"` // `autogenpb:version:v0.0.1` + Packages []*Package `protobuf:"bytes,3,rep,name=packages,proto3" json:"packages,omitempty"` +} + +func (x *Packages) Reset() { + *x = Packages{} + if protoimpl.UnsafeEnabled { + mi := &file_package_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Packages) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Packages) ProtoMessage() {} + +func (x *Packages) ProtoReflect() protoreflect.Message { + mi := &file_package_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 Packages.ProtoReflect.Descriptor instead. +func (*Packages) Descriptor() ([]byte, []int) { + return file_package_proto_rawDescGZIP(), []int{1} +} + +func (x *Packages) GetUuid() string { + if x != nil { + return x.Uuid + } + return "" +} + +func (x *Packages) GetVersion() string { + if x != nil { + return x.Version + } + return "" +} + +func (x *Packages) GetPackages() []*Package { + if x != nil { + return x.Packages + } + return nil +} + +var File_package_proto protoreflect.FileDescriptor + +var file_package_proto_rawDesc = []byte{ + 0x0a, 0x0d, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, + 0x05, 0x67, 0x69, 0x74, 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, 0xc3, 0x01, 0x0a, 0x07, 0x50, 0x61, 0x63, 0x6b, + 0x61, 0x67, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 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, 0x09, 0x6c, 0x61, 0x73, 0x74, 0x73, 0x74, 0x61, 0x6d, 0x70, 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, 0x09, 0x6c, 0x61, 0x73, 0x74, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x18, 0x0a, 0x07, 0x73, + 0x72, 0x63, 0x50, 0x61, 0x74, 0x68, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x73, 0x72, + 0x63, 0x50, 0x61, 0x74, 0x68, 0x12, 0x1c, 0x0a, 0x09, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, + 0x65, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, + 0x6c, 0x65, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x70, 0x6b, 0x67, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x06, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x70, 0x6b, 0x67, 0x4e, 0x61, 0x6d, 0x65, 0x22, 0x64, 0x0a, + 0x08, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 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, 0x2a, 0x0a, 0x08, 0x70, 0x61, 0x63, 0x6b, 0x61, + 0x67, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x67, 0x69, 0x74, 0x70, + 0x62, 0x2e, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x52, 0x08, 0x70, 0x61, 0x63, 0x6b, 0x61, + 0x67, 0x65, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, +} + +var ( + file_package_proto_rawDescOnce sync.Once + file_package_proto_rawDescData = file_package_proto_rawDesc +) + +func file_package_proto_rawDescGZIP() []byte { + file_package_proto_rawDescOnce.Do(func() { + file_package_proto_rawDescData = protoimpl.X.CompressGZIP(file_package_proto_rawDescData) + }) + return file_package_proto_rawDescData +} + +var file_package_proto_msgTypes = make([]protoimpl.MessageInfo, 2) +var file_package_proto_goTypes = []interface{}{ + (*Package)(nil), // 0: gitpb.Package + (*Packages)(nil), // 1: gitpb.Packages + (*timestamppb.Timestamp)(nil), // 2: google.protobuf.Timestamp +} +var file_package_proto_depIdxs = []int32{ + 2, // 0: gitpb.Package.laststamp:type_name -> google.protobuf.Timestamp + 0, // 1: gitpb.Packages.packages:type_name -> gitpb.Package + 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_package_proto_init() } +func file_package_proto_init() { + if File_package_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_package_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Package); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_package_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Packages); 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_package_proto_rawDesc, + NumEnums: 0, + NumMessages: 2, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_package_proto_goTypes, + DependencyIndexes: file_package_proto_depIdxs, + MessageInfos: file_package_proto_msgTypes, + }.Build() + File_package_proto = out.File + file_package_proto_rawDesc = nil + file_package_proto_goTypes = nil + file_package_proto_depIdxs = nil +} diff --git a/package.sort.pb.go b/package.sort.pb.go new file mode 100644 index 0000000..0911c33 --- /dev/null +++ b/package.sort.pb.go @@ -0,0 +1,286 @@ +// Code generated by go.wit.com/apps/autogenpb DO NOT EDIT. +// This file was autogenerated with autogenpb v0.5.5-2-g6c9a3dd 2025.09.22_0851 +// 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 zoopb + +import ( + "fmt" + "iter" + "sort" + "sync" + + "google.golang.org/protobuf/proto" +) + +// a simple global lock +var packageMu sync.RWMutex + +func (x *Packages) fixUuid() { + if x == nil { + return + } + if x.Uuid == "2f26cc03-ea30-4481-a333-ad0acc86e1d3" { + return + } + x.Uuid = "2f26cc03-ea30-4481-a333-ad0acc86e1d3" + x.Version = "v0.0.1 go.wit.com/lib/protobuf/zoopb" +} + +func NewPackages() *Packages { + x := new(Packages) + x.Uuid = "2f26cc03-ea30-4481-a333-ad0acc86e1d3" + x.Version = "v0.0.1 go.wit.com/lib/protobuf/zoopb" + return x +} + +// START SORT + +// DEFINE THE Packages SCANNER. +// itializes a new scanner. +func newPackagesScanner(things []*Packages) *PackagesScanner { + return &PackagesScanner{things: things} +} + +type PackagesScanner struct { + sync.Mutex + + things []*Packages + index int +} + +func (it *PackagesScanner) 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 *PackagesScanner) Next() *Packages { + if it.things[it.index-1] == nil { + fmt.Println("Next() error in PackagesScanner", it.index) + } + return it.things[it.index-1] +} + +// END DEFINE THE SCANNER + +// DEFINE THE Package SCANNER. +// itializes a new scanner. +func newPackageScanner(things []*Package) *PackageScanner { + return &PackageScanner{things: things} +} + +type PackageScanner struct { + sync.Mutex + + things []*Package + index int +} + +func (it *PackageScanner) 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 *PackageScanner) Next() *Package { + if it.things[it.index-1] == nil { + fmt.Println("Next() error in PackageScanner", it.index) + } + return it.things[it.index-1] +} + +// END DEFINE THE SCANNER + +// sort struct by Name +type sortPackageName []*Package + +func (a sortPackageName) Len() int { return len(a) } +func (a sortPackageName) Less(i, j int) bool { return a[i].Name < a[j].Name } +func (a sortPackageName) Swap(i, j int) { a[i], a[j] = a[j], a[i] } + +// safely returns a slice of pointers to the FRUIT protobufs +func (x *Packages) allPackages() []*Package { + x.RLock() + defer x.RUnlock() + + // Create a new slice to hold pointers to each FRUIT + var tmp []*Package + tmp = make([]*Package, len(x.Packages)) + for i, p := range x.Packages { + tmp[i] = p // Copy pointers for safe iteration + } + + return tmp +} + +// safely returns a slice of pointers to the Package protobufs +func (x *Packages) selectAllPackages() []*Package { + x.RLock() + defer x.RUnlock() + + // Create a new slice to hold pointers to each Package + var tmp []*Package + tmp = make([]*Package, len(x.Packages)) + for i, p := range x.Packages { + tmp[i] = p // Copy pointers for safe iteration + } + + return tmp +} +func (x *Packages) SortByName() *PackageScanner { + // copy the pointers as fast as possible. + things := x.selectAllPackages() + + // todo: try slices.SortFunc() instead to see what happens + sort.Sort(sortPackageName(things)) + // slices.SortFunc(things, func(a, b *Packages) bool { + // return a.Name < b.Name // Sort by ??. let the compiler work it out?? + // }) + return newPackageScanner(things) +} + +// 'for x := range' syntax using the awesome golang 1.24 'iter' +func (x *Packages) IterByName() iter.Seq[*Package] { + items := x.selectAllPackages() + sort.Sort(sortPackageName(items)) + // log.Println("Made Iter.Seq[] with length", len(items)) + return func(yield func(*Package) bool) { + for _, v := range items { + if !yield(v) { + return + } + } + } +} + +// END SORT + +func (x *Packages) Len() int { + x.RLock() + defer x.RUnlock() + + return len(x.Packages) +} + +// a Append() shortcut (that does Clone() with a mutex) notsure if it really works +func (x *Packages) Append(y *Package) *Package { + x.Lock() + defer x.Unlock() + + z := proto.Clone(y).(*Package) + x.Packages = append(x.Packages, z) + + return z +} + +func (x *Packages) All() *PackageScanner { + PackagePointers := x.selectAllPackages() + + scanner := newPackageScanner(PackagePointers) + return scanner +} + +// Iterate 'for x := range' syntax using the awesome golang 1.24 'iter' +func (x *Packages) IterAll() iter.Seq[*Package] { + items := x.selectAllPackages() + // log.Println("Made All() Iter.Seq[] with length", len(items)) + return func(yield func(*Package) bool) { + for _, v := range items { + if !yield(v) { + return + } + } + } +} +func (x *Packages) Delete(y *Package) bool { + x.Lock() + defer x.Unlock() + + for i, _ := range x.Packages { + if x.Packages[i] == y { + x.Packages[i] = x.Packages[len(x.Packages)-1] + x.Packages = x.Packages[:len(x.Packages)-1] + return true + } + } + return false +} + +// lookup a Packages by the Name +func (x *Packages) FindByName(s string) *Package { + if x == nil { + return nil + } + + x.RLock() + defer x.RUnlock() + + for i, _ := range x.Packages { + if x.Packages[i].Name == s { + return x.Packages[i] + } + } + return nil +} + +// returns a Package if Name matches, otherwise create +func (x *Packages) InsertByName(y string) *Package { + x.Lock() + defer x.Unlock() + + for _, z := range x.Packages { + if z.Name == y { + return z + } + } + + z := new(Package) + z.Name = y + x.Packages = append(x.Packages, z) + return z +} + +func (x *Packages) DeleteByName(s string) bool { + x.Lock() + defer x.Unlock() + + for i, _ := range x.Packages { + if x.Packages[i].Name == s { + x.Packages[i] = x.Packages[len(x.Packages)-1] + x.Packages = x.Packages[:len(x.Packages)-1] + return true + } + } + return false +} + +func (x *Packages) AppendByName(y *Package) bool { + x.Lock() + defer x.Unlock() + + for _, p := range x.Packages { + if p.Name == y.Name { + return false + } + } + + x.Packages = append(x.Packages, proto.Clone(y).(*Package)) + return true +}