From c8bd589e5f84d7b43eb8957b080aa73abfe45b00 Mon Sep 17 00:00:00 2001 From: Jeff Carr Date: Sun, 21 Sep 2025 21:00:50 -0500 Subject: [PATCH] forge init() --- gitTag.gui.pb.go | 257 ++++++++++++ gitTag.marshal.pb.go | 56 +++ gitTag.pb.go | 616 +++++++++++++++++++++++++++++ gitTag.sort.pb.go | 477 ++++++++++++++++++++++ go.mod | 25 ++ go.sum | 38 ++ goDep.marshal.pb.go | 11 + goDep.pb.go | 283 +++++++++++++ goDep.sort.pb.go | 380 ++++++++++++++++++ repo.gui.pb.go | 362 +++++++++++++++++ repo.http.pb.go | 56 +++ repo.marshal.pb.go | 93 +++++ repo.pb.go | 917 +++++++++++++++++++++++++++++++++++++++++++ repo.sort.pb.go | 446 +++++++++++++++++++++ 14 files changed, 4017 insertions(+) create mode 100644 gitTag.gui.pb.go create mode 100644 gitTag.marshal.pb.go create mode 100644 gitTag.pb.go create mode 100644 gitTag.sort.pb.go create mode 100644 go.mod create mode 100644 go.sum create mode 100644 goDep.marshal.pb.go create mode 100644 goDep.pb.go create mode 100644 goDep.sort.pb.go create mode 100644 repo.gui.pb.go create mode 100644 repo.http.pb.go create mode 100644 repo.marshal.pb.go create mode 100644 repo.pb.go create mode 100644 repo.sort.pb.go diff --git a/gitTag.gui.pb.go b/gitTag.gui.pb.go new file mode 100644 index 0000000..b2e3d9a --- /dev/null +++ b/gitTag.gui.pb.go @@ -0,0 +1,257 @@ +// Code generated by go.wit.com/apps/autogenpb DO NOT EDIT. +// This file was autogenerated with autogenpb v0.5.3-11-g737c5b7 2025.09.16_2337 +// 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 gitpb + +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 *GitTags) NewTable(title string) *GitTagsTable { + t := new(GitTagsTable) + 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 *GitTagsTable) AddStringFunc(title string, f func(*GitTag) string) *GitTagAnyFunc { + t.pb.Order = append(t.pb.Order, title) + + sf := new(GitTagAnyFunc) + sf.title = title + sf.f = func(x *GitTag) 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 *GitTagsTable) AddButtonFunc(title string, f func(*GitTag) string) *GitTagAnyFunc { + t.pb.Order = append(t.pb.Order, title) + + sf := new(GitTagAnyFunc) + sf.title = title + sf.f = func(x *GitTag) 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 *GitTagsTable) AddIntFunc(title string, f func(*GitTag) int) *GitTagAnyFunc { + t.pb.Order = append(t.pb.Order, title) + + sf := new(GitTagAnyFunc) + sf.title = title + sf.f = func(x *GitTag) 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 *GitTagsTable) AddTimeFunc(title string, f func(*GitTag) time.Time) *GitTagAnyFunc { + t.pb.Order = append(t.pb.Order, title) + + sf := new(GitTagAnyFunc) + sf.title = title + sf.f = func(x *GitTag) 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 *GitTagAnyFunc) SetTitle(title string) { + sf.title = title +} + +func (mt *GitTagsTable) SetParent(p *gui.Node) { + mt.parent = p +} + +func (mt *GitTagsTable) ShowTable() { + // log.Info("ShowTable() SENDING TO GUI") + mt.MakeTable() + mt.parent.ShowTable(mt.pb) +} + +type GitTagAnyFunc struct { + title string + f func(*GitTag) any + Custom func(*GitTag) + Width int + attr *guipb.ColAttr +} + +type GitTagsTable struct { + pb *guipb.Table + parent *gui.Node + x *GitTags + hostnames []string + anyFuncs []*GitTagAnyFunc + CustomFunc func(*GitTag) +} + +func (mt *GitTagsTable) doAnyFuncNew(sf *GitTagAnyFunc) 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 *GitTagsTable) MakeTable() { + for _, sf := range mt.anyFuncs { + mt.doAnyFuncNew(sf) + } +} + +func (t *GitTagsTable) AddRefname() *GitTagAnyFunc { + sf := t.AddStringFunc("Refname", func(m *GitTag) string { + return m.Refname + }) + return sf +} + +func (t *GitTagsTable) AddHash() *GitTagAnyFunc { + sf := t.AddStringFunc("Hash", func(m *GitTag) string { + return m.Hash + }) + return sf +} + +func (t *GitTagsTable) AddSubject() *GitTagAnyFunc { + sf := t.AddStringFunc("Subject", func(m *GitTag) string { + return m.Subject + }) + return sf +} +func (mt *GitTagsTable) NewUuid() { + mt.pb.Uuid = uuid.New().String() +} + +// START TABLE UPDATE (doesn't work yet) + +func (mt *GitTagsTable) 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 *GitTagsTable) Delete() { + if mt == nil { + log.Info("mt == nil table already deleted") + return + } + // log.Info("table Delete here") + mt.parent.DeleteTable(mt.pb) +} + +func (mt *GitTagsTable) gitTagsCustom(w *guipb.Widget) { + row := mt.x.GitTags[w.Location.Y-1] + // log.Info("got to gitTagsCustom() 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 *GitTagsTable) Custom(f func(*GitTag)) { + mt.pb.RegisterCustom(mt.gitTagsCustom) + mt.CustomFunc = f +} + +func (mt *GitTagsTable) GetUuid() string { + return mt.pb.Uuid +} + +// END TABLE UPDATE + +// END GUI diff --git a/gitTag.marshal.pb.go b/gitTag.marshal.pb.go new file mode 100644 index 0000000..98c9bf6 --- /dev/null +++ b/gitTag.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.3-11-g737c5b7 2025.09.16_2337 +// 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 gitpb + +import ( + "google.golang.org/protobuf/encoding/protojson" + "google.golang.org/protobuf/encoding/prototext" + "google.golang.org/protobuf/proto" +) + +// human readable JSON +func (v *GitTags) FormatJSON() string { + return protojson.Format(v) +} + +// marshal json +func (v *GitTags) MarshalJSON() ([]byte, error) { + return protojson.Marshal(v) +} + +// unmarshal json +func (v *GitTags) 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 *GitTags) FormatTEXT() string { + v.fixUuid() + return prototext.Format(v) +} + +// unmarshalTEXT. This reads the .text config file back in after the user edits it +func (v *GitTags) UnmarshalTEXT(data []byte) error { + return prototext.Unmarshal(data, v) +} + +// marshal to wire. This is called winning. +func (v *GitTags) Marshal() ([]byte, error) { + v.fixUuid() + return proto.Marshal(v) +} + +// unmarshal from wire. You have won. +func (v *GitTags) Unmarshal(data []byte) error { + return proto.Unmarshal(data, v) +} diff --git a/gitTag.pb.go b/gitTag.pb.go new file mode 100644 index 0000000..64fed72 --- /dev/null +++ b/gitTag.pb.go @@ -0,0 +1,616 @@ +// Code modified by go.wit.com/apps/autogenpb DO NOT EDIT. +// +// user defined Mutex locks were auto added +// +// autogenpb version & build time: v0.5.3-11-g737c5b7 2025.09.16_2337 +// 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: gitTag.proto + +package gitpb // 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 GitRemote struct { + // sync.RWMutex // skipped. protobuf file has `autogenpb:nomutex` + + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Url string `protobuf:"bytes,1,opt,name=url,proto3" json:"url,omitempty"` + Fetch string `protobuf:"bytes,2,opt,name=fetch,proto3" json:"fetch,omitempty"` +} + +func (x *GitRemote) Reset() { + *x = GitRemote{} + if protoimpl.UnsafeEnabled { + mi := &file_gitTag_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GitRemote) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GitRemote) ProtoMessage() {} + +func (x *GitRemote) ProtoReflect() protoreflect.Message { + mi := &file_gitTag_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 GitRemote.ProtoReflect.Descriptor instead. +func (*GitRemote) Descriptor() ([]byte, []int) { + return file_gitTag_proto_rawDescGZIP(), []int{0} +} + +func (x *GitRemote) GetUrl() string { + if x != nil { + return x.Url + } + return "" +} + +func (x *GitRemote) GetFetch() string { + if x != nil { + return x.Fetch + } + return "" +} + +type GitBranch struct { + // sync.RWMutex // skipped. protobuf file has `autogenpb:nomutex` + + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Remote string `protobuf:"bytes,1,opt,name=remote,proto3" json:"remote,omitempty"` // the name of the remote repo + Merge string `protobuf:"bytes,2,opt,name=merge,proto3" json:"merge,omitempty"` // the merge path from the config file + Name string `protobuf:"bytes,3,opt,name=name,proto3" json:"name,omitempty"` // the branch name from the config file +} + +func (x *GitBranch) Reset() { + *x = GitBranch{} + if protoimpl.UnsafeEnabled { + mi := &file_gitTag_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GitBranch) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GitBranch) ProtoMessage() {} + +func (x *GitBranch) ProtoReflect() protoreflect.Message { + mi := &file_gitTag_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 GitBranch.ProtoReflect.Descriptor instead. +func (*GitBranch) Descriptor() ([]byte, []int) { + return file_gitTag_proto_rawDescGZIP(), []int{1} +} + +func (x *GitBranch) GetRemote() string { + if x != nil { + return x.Remote + } + return "" +} + +func (x *GitBranch) GetMerge() string { + if x != nil { + return x.Merge + } + return "" +} + +func (x *GitBranch) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +type GitConfig struct { + // sync.RWMutex // skipped. protobuf file has `autogenpb:nomutex` + + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Core map[string]string `protobuf:"bytes,1,rep,name=core,proto3" json:"core,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` // map[origin] = "https:/git.wit.org/gui/gadgets" + Remotes map[string]*GitRemote `protobuf:"bytes,2,rep,name=remotes,proto3" json:"remotes,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` // map[origin] = "https:/git.wit.org/gui/gadgets" + Branches map[string]*GitBranch `protobuf:"bytes,3,rep,name=branches,proto3" json:"branches,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` // map[guimaster] = origin guimaster + Submodules map[string]string `protobuf:"bytes,4,rep,name=submodules,proto3" json:"submodules,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` + Hashes map[string]string `protobuf:"bytes,5,rep,name=hashes,proto3" json:"hashes,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` + Versions map[string]string `protobuf:"bytes,6,rep,name=versions,proto3" json:"versions,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` + Local []*GitBranch `protobuf:"bytes,7,rep,name=local,proto3" json:"local,omitempty"` // move this this and away from the map<> variables +} + +func (x *GitConfig) Reset() { + *x = GitConfig{} + if protoimpl.UnsafeEnabled { + mi := &file_gitTag_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GitConfig) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GitConfig) ProtoMessage() {} + +func (x *GitConfig) ProtoReflect() protoreflect.Message { + mi := &file_gitTag_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 GitConfig.ProtoReflect.Descriptor instead. +func (*GitConfig) Descriptor() ([]byte, []int) { + return file_gitTag_proto_rawDescGZIP(), []int{2} +} + +func (x *GitConfig) GetCore() map[string]string { + if x != nil { + return x.Core + } + return nil +} + +func (x *GitConfig) GetRemotes() map[string]*GitRemote { + if x != nil { + return x.Remotes + } + return nil +} + +func (x *GitConfig) GetBranches() map[string]*GitBranch { + if x != nil { + return x.Branches + } + return nil +} + +func (x *GitConfig) GetSubmodules() map[string]string { + if x != nil { + return x.Submodules + } + return nil +} + +func (x *GitConfig) GetHashes() map[string]string { + if x != nil { + return x.Hashes + } + return nil +} + +func (x *GitConfig) GetVersions() map[string]string { + if x != nil { + return x.Versions + } + return nil +} + +func (x *GitConfig) GetLocal() []*GitBranch { + if x != nil { + return x.Local + } + return nil +} + +type GitTag struct { + // sync.RWMutex // skipped. protobuf file has `autogenpb:nomutex` + + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Refname string `protobuf:"bytes,1,opt,name=refname,proto3" json:"refname,omitempty"` // `autogenpb:unique` `autogenpb:sort` // tag name. treated as unique + Creatordate *timestamppb.Timestamp `protobuf:"bytes,2,opt,name=creatordate,proto3" json:"creatordate,omitempty"` // git creatordate + Authordate *timestamppb.Timestamp `protobuf:"bytes,3,opt,name=authordate,proto3" json:"authordate,omitempty"` // git author date + Hash string `protobuf:"bytes,4,opt,name=hash,proto3" json:"hash,omitempty"` // `autogenpb:unique` // git hash + Subject string `protobuf:"bytes,5,opt,name=subject,proto3" json:"subject,omitempty"` // git tag subject +} + +func (x *GitTag) Reset() { + *x = GitTag{} + if protoimpl.UnsafeEnabled { + mi := &file_gitTag_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GitTag) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GitTag) ProtoMessage() {} + +func (x *GitTag) ProtoReflect() protoreflect.Message { + mi := &file_gitTag_proto_msgTypes[3] + 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 GitTag.ProtoReflect.Descriptor instead. +func (*GitTag) Descriptor() ([]byte, []int) { + return file_gitTag_proto_rawDescGZIP(), []int{3} +} + +func (x *GitTag) GetRefname() string { + if x != nil { + return x.Refname + } + return "" +} + +func (x *GitTag) GetCreatordate() *timestamppb.Timestamp { + if x != nil { + return x.Creatordate + } + return nil +} + +func (x *GitTag) GetAuthordate() *timestamppb.Timestamp { + if x != nil { + return x.Authordate + } + return nil +} + +func (x *GitTag) GetHash() string { + if x != nil { + return x.Hash + } + return "" +} + +func (x *GitTag) GetSubject() string { + if x != nil { + return x.Subject + } + return "" +} + +type GitTags 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:ffdff813-0316-4372-9e82-4c1c7d202526` + Version string `protobuf:"bytes,2,opt,name=version,proto3" json:"version,omitempty"` // `autogenpb:version:v0.0.47` + GitTags []*GitTag `protobuf:"bytes,3,rep,name=gitTags,proto3" json:"gitTags,omitempty"` +} + +func (x *GitTags) Reset() { + *x = GitTags{} + if protoimpl.UnsafeEnabled { + mi := &file_gitTag_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GitTags) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GitTags) ProtoMessage() {} + +func (x *GitTags) ProtoReflect() protoreflect.Message { + mi := &file_gitTag_proto_msgTypes[4] + 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 GitTags.ProtoReflect.Descriptor instead. +func (*GitTags) Descriptor() ([]byte, []int) { + return file_gitTag_proto_rawDescGZIP(), []int{4} +} + +func (x *GitTags) GetUuid() string { + if x != nil { + return x.Uuid + } + return "" +} + +func (x *GitTags) GetVersion() string { + if x != nil { + return x.Version + } + return "" +} + +func (x *GitTags) GetGitTags() []*GitTag { + if x != nil { + return x.GitTags + } + return nil +} + +var File_gitTag_proto protoreflect.FileDescriptor + +var file_gitTag_proto_rawDesc = []byte{ + 0x0a, 0x0c, 0x67, 0x69, 0x74, 0x54, 0x61, 0x67, 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, 0x33, 0x0a, 0x09, 0x47, 0x69, 0x74, 0x52, 0x65, 0x6d, + 0x6f, 0x74, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x72, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x03, 0x75, 0x72, 0x6c, 0x12, 0x14, 0x0a, 0x05, 0x66, 0x65, 0x74, 0x63, 0x68, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x66, 0x65, 0x74, 0x63, 0x68, 0x22, 0x4d, 0x0a, 0x09, 0x47, + 0x69, 0x74, 0x42, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x12, 0x16, 0x0a, 0x06, 0x72, 0x65, 0x6d, 0x6f, + 0x74, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, + 0x12, 0x14, 0x0a, 0x05, 0x6d, 0x65, 0x72, 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x05, 0x6d, 0x65, 0x72, 0x67, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x99, 0x06, 0x0a, 0x09, 0x47, + 0x69, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x2e, 0x0a, 0x04, 0x63, 0x6f, 0x72, 0x65, + 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x69, 0x74, 0x70, 0x62, 0x2e, 0x47, + 0x69, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x43, 0x6f, 0x72, 0x65, 0x45, 0x6e, 0x74, + 0x72, 0x79, 0x52, 0x04, 0x63, 0x6f, 0x72, 0x65, 0x12, 0x37, 0x0a, 0x07, 0x72, 0x65, 0x6d, 0x6f, + 0x74, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x67, 0x69, 0x74, 0x70, + 0x62, 0x2e, 0x47, 0x69, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x52, 0x65, 0x6d, 0x6f, + 0x74, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x07, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, + 0x73, 0x12, 0x3a, 0x0a, 0x08, 0x62, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x65, 0x73, 0x18, 0x03, 0x20, + 0x03, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x67, 0x69, 0x74, 0x70, 0x62, 0x2e, 0x47, 0x69, 0x74, 0x43, + 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x42, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x65, 0x73, 0x45, 0x6e, + 0x74, 0x72, 0x79, 0x52, 0x08, 0x62, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x65, 0x73, 0x12, 0x40, 0x0a, + 0x0a, 0x73, 0x75, 0x62, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, + 0x0b, 0x32, 0x20, 0x2e, 0x67, 0x69, 0x74, 0x70, 0x62, 0x2e, 0x47, 0x69, 0x74, 0x43, 0x6f, 0x6e, + 0x66, 0x69, 0x67, 0x2e, 0x53, 0x75, 0x62, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x73, 0x45, 0x6e, + 0x74, 0x72, 0x79, 0x52, 0x0a, 0x73, 0x75, 0x62, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x73, 0x12, + 0x34, 0x0a, 0x06, 0x68, 0x61, 0x73, 0x68, 0x65, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, + 0x1c, 0x2e, 0x67, 0x69, 0x74, 0x70, 0x62, 0x2e, 0x47, 0x69, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, + 0x67, 0x2e, 0x48, 0x61, 0x73, 0x68, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x06, 0x68, + 0x61, 0x73, 0x68, 0x65, 0x73, 0x12, 0x3a, 0x0a, 0x08, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, + 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x67, 0x69, 0x74, 0x70, 0x62, 0x2e, + 0x47, 0x69, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, + 0x6e, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x08, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, + 0x73, 0x12, 0x26, 0x0a, 0x05, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x18, 0x07, 0x20, 0x03, 0x28, 0x0b, + 0x32, 0x10, 0x2e, 0x67, 0x69, 0x74, 0x70, 0x62, 0x2e, 0x47, 0x69, 0x74, 0x42, 0x72, 0x61, 0x6e, + 0x63, 0x68, 0x52, 0x05, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x1a, 0x37, 0x0a, 0x09, 0x43, 0x6f, 0x72, + 0x65, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, + 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, + 0x38, 0x01, 0x1a, 0x4c, 0x0a, 0x0c, 0x52, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x73, 0x45, 0x6e, 0x74, + 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x03, 0x6b, 0x65, 0x79, 0x12, 0x26, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x67, 0x69, 0x74, 0x70, 0x62, 0x2e, 0x47, 0x69, 0x74, 0x52, + 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, + 0x1a, 0x4d, 0x0a, 0x0d, 0x42, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, + 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, + 0x6b, 0x65, 0x79, 0x12, 0x26, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x67, 0x69, 0x74, 0x70, 0x62, 0x2e, 0x47, 0x69, 0x74, 0x42, 0x72, + 0x61, 0x6e, 0x63, 0x68, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, + 0x3d, 0x0a, 0x0f, 0x53, 0x75, 0x62, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x73, 0x45, 0x6e, 0x74, + 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x39, + 0x0a, 0x0b, 0x48, 0x61, 0x73, 0x68, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, + 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, + 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, + 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x3b, 0x0a, 0x0d, 0x56, 0x65, 0x72, + 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, + 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, + 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, + 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0xca, 0x01, 0x0a, 0x06, 0x47, 0x69, 0x74, 0x54, 0x61, + 0x67, 0x12, 0x18, 0x0a, 0x07, 0x72, 0x65, 0x66, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x07, 0x72, 0x65, 0x66, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x3c, 0x0a, 0x0b, 0x63, + 0x72, 0x65, 0x61, 0x74, 0x6f, 0x72, 0x64, 0x61, 0x74, 0x65, 0x18, 0x02, 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, 0x0b, 0x63, 0x72, + 0x65, 0x61, 0x74, 0x6f, 0x72, 0x64, 0x61, 0x74, 0x65, 0x12, 0x3a, 0x0a, 0x0a, 0x61, 0x75, 0x74, + 0x68, 0x6f, 0x72, 0x64, 0x61, 0x74, 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, 0x0a, 0x61, 0x75, 0x74, 0x68, 0x6f, + 0x72, 0x64, 0x61, 0x74, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x68, 0x61, 0x73, 0x68, 0x18, 0x04, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x04, 0x68, 0x61, 0x73, 0x68, 0x12, 0x18, 0x0a, 0x07, 0x73, 0x75, 0x62, + 0x6a, 0x65, 0x63, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x73, 0x75, 0x62, 0x6a, + 0x65, 0x63, 0x74, 0x22, 0x60, 0x0a, 0x07, 0x47, 0x69, 0x74, 0x54, 0x61, 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, 0x27, 0x0a, 0x07, + 0x67, 0x69, 0x74, 0x54, 0x61, 0x67, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0d, 0x2e, + 0x67, 0x69, 0x74, 0x70, 0x62, 0x2e, 0x47, 0x69, 0x74, 0x54, 0x61, 0x67, 0x52, 0x07, 0x67, 0x69, + 0x74, 0x54, 0x61, 0x67, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, +} + +var ( + file_gitTag_proto_rawDescOnce sync.Once + file_gitTag_proto_rawDescData = file_gitTag_proto_rawDesc +) + +func file_gitTag_proto_rawDescGZIP() []byte { + file_gitTag_proto_rawDescOnce.Do(func() { + file_gitTag_proto_rawDescData = protoimpl.X.CompressGZIP(file_gitTag_proto_rawDescData) + }) + return file_gitTag_proto_rawDescData +} + +var file_gitTag_proto_msgTypes = make([]protoimpl.MessageInfo, 11) +var file_gitTag_proto_goTypes = []interface{}{ + (*GitRemote)(nil), // 0: gitpb.GitRemote + (*GitBranch)(nil), // 1: gitpb.GitBranch + (*GitConfig)(nil), // 2: gitpb.GitConfig + (*GitTag)(nil), // 3: gitpb.GitTag + (*GitTags)(nil), // 4: gitpb.GitTags + nil, // 5: gitpb.GitConfig.CoreEntry + nil, // 6: gitpb.GitConfig.RemotesEntry + nil, // 7: gitpb.GitConfig.BranchesEntry + nil, // 8: gitpb.GitConfig.SubmodulesEntry + nil, // 9: gitpb.GitConfig.HashesEntry + nil, // 10: gitpb.GitConfig.VersionsEntry + (*timestamppb.Timestamp)(nil), // 11: google.protobuf.Timestamp +} +var file_gitTag_proto_depIdxs = []int32{ + 5, // 0: gitpb.GitConfig.core:type_name -> gitpb.GitConfig.CoreEntry + 6, // 1: gitpb.GitConfig.remotes:type_name -> gitpb.GitConfig.RemotesEntry + 7, // 2: gitpb.GitConfig.branches:type_name -> gitpb.GitConfig.BranchesEntry + 8, // 3: gitpb.GitConfig.submodules:type_name -> gitpb.GitConfig.SubmodulesEntry + 9, // 4: gitpb.GitConfig.hashes:type_name -> gitpb.GitConfig.HashesEntry + 10, // 5: gitpb.GitConfig.versions:type_name -> gitpb.GitConfig.VersionsEntry + 1, // 6: gitpb.GitConfig.local:type_name -> gitpb.GitBranch + 11, // 7: gitpb.GitTag.creatordate:type_name -> google.protobuf.Timestamp + 11, // 8: gitpb.GitTag.authordate:type_name -> google.protobuf.Timestamp + 3, // 9: gitpb.GitTags.gitTags:type_name -> gitpb.GitTag + 0, // 10: gitpb.GitConfig.RemotesEntry.value:type_name -> gitpb.GitRemote + 1, // 11: gitpb.GitConfig.BranchesEntry.value:type_name -> gitpb.GitBranch + 12, // [12:12] is the sub-list for method output_type + 12, // [12:12] is the sub-list for method input_type + 12, // [12:12] is the sub-list for extension type_name + 12, // [12:12] is the sub-list for extension extendee + 0, // [0:12] is the sub-list for field type_name +} + +func init() { file_gitTag_proto_init() } +func file_gitTag_proto_init() { + if File_gitTag_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_gitTag_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GitRemote); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_gitTag_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GitBranch); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_gitTag_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GitConfig); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_gitTag_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GitTag); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_gitTag_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GitTags); 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_gitTag_proto_rawDesc, + NumEnums: 0, + NumMessages: 11, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_gitTag_proto_goTypes, + DependencyIndexes: file_gitTag_proto_depIdxs, + MessageInfos: file_gitTag_proto_msgTypes, + }.Build() + File_gitTag_proto = out.File + file_gitTag_proto_rawDesc = nil + file_gitTag_proto_goTypes = nil + file_gitTag_proto_depIdxs = nil +} diff --git a/gitTag.sort.pb.go b/gitTag.sort.pb.go new file mode 100644 index 0000000..13989b3 --- /dev/null +++ b/gitTag.sort.pb.go @@ -0,0 +1,477 @@ +// Code generated by go.wit.com/apps/autogenpb DO NOT EDIT. +// This file was autogenerated with autogenpb v0.5.3-11-g737c5b7 2025.09.16_2337 +// 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 gitpb + +import ( + "fmt" + "iter" + "sort" + "sync" + + "google.golang.org/protobuf/proto" +) + +// a simple global lock +var gitTagMu sync.RWMutex + +func (x *GitTags) fixUuid() { + if x == nil { + return + } + if x.Uuid == "ffdff813-0316-4372-9e82-4c1c7d202526" { + return + } + x.Uuid = "ffdff813-0316-4372-9e82-4c1c7d202526" + x.Version = "v0.0.47 go.wit.com/lib/protobuf/gitpb" +} + +func NewGitTags() *GitTags { + x := new(GitTags) + x.Uuid = "ffdff813-0316-4372-9e82-4c1c7d202526" + x.Version = "v0.0.47 go.wit.com/lib/protobuf/gitpb" + return x +} + +// START SORT + +// DEFINE THE GitTags SCANNER. +// itializes a new scanner. +func newGitTagsScanner(things []*GitTags) *GitTagsScanner { + return &GitTagsScanner{things: things} +} + +type GitTagsScanner struct { + sync.Mutex + + things []*GitTags + index int +} + +func (it *GitTagsScanner) 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 *GitTagsScanner) Next() *GitTags { + if it.things[it.index-1] == nil { + fmt.Println("Next() error in GitTagsScanner", it.index) + } + return it.things[it.index-1] +} + +// END DEFINE THE SCANNER + +// DEFINE THE GitTag SCANNER. +// itializes a new scanner. +func newGitTagScanner(things []*GitTag) *GitTagScanner { + return &GitTagScanner{things: things} +} + +type GitTagScanner struct { + sync.Mutex + + things []*GitTag + index int +} + +func (it *GitTagScanner) 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 *GitTagScanner) Next() *GitTag { + if it.things[it.index-1] == nil { + fmt.Println("Next() error in GitTagScanner", it.index) + } + return it.things[it.index-1] +} + +// END DEFINE THE SCANNER + +// DEFINE THE GitRemote SCANNER. +// itializes a new scanner. +func newGitRemoteScanner(things []*GitRemote) *GitRemoteScanner { + return &GitRemoteScanner{things: things} +} + +type GitRemoteScanner struct { + sync.Mutex + + things []*GitRemote + index int +} + +func (it *GitRemoteScanner) 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 *GitRemoteScanner) Next() *GitRemote { + if it.things[it.index-1] == nil { + fmt.Println("Next() error in GitRemoteScanner", it.index) + } + return it.things[it.index-1] +} + +// END DEFINE THE SCANNER + +// DEFINE THE GitBranch SCANNER. +// itializes a new scanner. +func newGitBranchScanner(things []*GitBranch) *GitBranchScanner { + return &GitBranchScanner{things: things} +} + +type GitBranchScanner struct { + sync.Mutex + + things []*GitBranch + index int +} + +func (it *GitBranchScanner) 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 *GitBranchScanner) Next() *GitBranch { + if it.things[it.index-1] == nil { + fmt.Println("Next() error in GitBranchScanner", it.index) + } + return it.things[it.index-1] +} + +// END DEFINE THE SCANNER + +// DEFINE THE GitConfig SCANNER. +// itializes a new scanner. +func newGitConfigScanner(things []*GitConfig) *GitConfigScanner { + return &GitConfigScanner{things: things} +} + +type GitConfigScanner struct { + sync.Mutex + + things []*GitConfig + index int +} + +func (it *GitConfigScanner) 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 *GitConfigScanner) Next() *GitConfig { + if it.things[it.index-1] == nil { + fmt.Println("Next() error in GitConfigScanner", it.index) + } + return it.things[it.index-1] +} + +// END DEFINE THE SCANNER + +// sort struct by Refname +type sortGitTagRefname []*GitTag + +func (a sortGitTagRefname) Len() int { return len(a) } +func (a sortGitTagRefname) Less(i, j int) bool { return a[i].Refname < a[j].Refname } +func (a sortGitTagRefname) Swap(i, j int) { a[i], a[j] = a[j], a[i] } + +// safely returns a slice of pointers to the FRUIT protobufs +func (x *GitTags) allGitTags() []*GitTag { + gitTagMu.RLock() + defer gitTagMu.RUnlock() + + // Create a new slice to hold pointers to each FRUIT + var tmp []*GitTag + tmp = make([]*GitTag, len(x.GitTags)) + for i, p := range x.GitTags { + tmp[i] = p // Copy pointers for safe iteration + } + + return tmp +} + +// safely returns a slice of pointers to the FRUIT protobufs +func (x *GitConfig) allLocal() []*GitBranch { + gitTagMu.RLock() + defer gitTagMu.RUnlock() + + // Create a new slice to hold pointers to each FRUIT + var tmp []*GitBranch + tmp = make([]*GitBranch, len(x.Local)) + for i, p := range x.Local { + tmp[i] = p // Copy pointers for safe iteration + } + + return tmp +} + +// safely returns a slice of pointers to the GitTag protobufs +func (x *GitTags) selectAllGitTags() []*GitTag { + gitTagMu.RLock() + defer gitTagMu.RUnlock() + + // Create a new slice to hold pointers to each GitTag + var tmp []*GitTag + tmp = make([]*GitTag, len(x.GitTags)) + for i, p := range x.GitTags { + tmp[i] = p // Copy pointers for safe iteration + } + + return tmp +} + +// safely returns a slice of pointers to the GitBranch protobufs +func (x *GitConfig) selectAllLocal() []*GitBranch { + gitTagMu.RLock() + defer gitTagMu.RUnlock() + + // Create a new slice to hold pointers to each GitBranch + var tmp []*GitBranch + tmp = make([]*GitBranch, len(x.Local)) + for i, p := range x.Local { + tmp[i] = p // Copy pointers for safe iteration + } + + return tmp +} +func (x *GitTags) SortByRefname() *GitTagScanner { + // copy the pointers as fast as possible. + things := x.selectAllGitTags() + + // todo: try slices.SortFunc() instead to see what happens + sort.Sort(sortGitTagRefname(things)) + // slices.SortFunc(things, func(a, b *GitTags) bool { + // return a.Refname < b.Refname // Sort by ??. let the compiler work it out?? + // }) + return newGitTagScanner(things) +} + +// 'for x := range' syntax using the awesome golang 1.24 'iter' +func (x *GitTags) IterByRefname() iter.Seq[*GitTag] { + items := x.selectAllGitTags() + sort.Sort(sortGitTagRefname(items)) + // log.Println("Made Iter.Seq[] with length", len(items)) + return func(yield func(*GitTag) bool) { + for _, v := range items { + if !yield(v) { + return + } + } + } +} + +// END SORT + +func (x *GitTags) Len() int { + gitTagMu.RLock() + defer gitTagMu.RUnlock() + + return len(x.GitTags) +} + +// a Append() shortcut (that does Clone() with a mutex) notsure if it really works +func (x *GitTags) Append(y *GitTag) *GitTag { + gitTagMu.Lock() + defer gitTagMu.Unlock() + + z := proto.Clone(y).(*GitTag) + x.GitTags = append(x.GitTags, z) + + return z +} + +func (x *GitTags) All() *GitTagScanner { + GitTagPointers := x.selectAllGitTags() + + scanner := newGitTagScanner(GitTagPointers) + return scanner +} + +// Iterate 'for x := range' syntax using the awesome golang 1.24 'iter' +func (x *GitTags) IterAll() iter.Seq[*GitTag] { + items := x.selectAllGitTags() + // log.Println("Made All() Iter.Seq[] with length", len(items)) + return func(yield func(*GitTag) bool) { + for _, v := range items { + if !yield(v) { + return + } + } + } +} +func (x *GitTags) Delete(y *GitTag) bool { + gitTagMu.Lock() + defer gitTagMu.Unlock() + + for i, _ := range x.GitTags { + if x.GitTags[i] == y { + x.GitTags[i] = x.GitTags[len(x.GitTags)-1] + x.GitTags = x.GitTags[:len(x.GitTags)-1] + return true + } + } + return false +} + +// lookup a GitTags by the Refname +func (x *GitTags) FindByRefname(s string) *GitTag { + if x == nil { + return nil + } + + gitTagMu.RLock() + defer gitTagMu.RUnlock() + + for i, _ := range x.GitTags { + if x.GitTags[i].Refname == s { + return x.GitTags[i] + } + } + return nil +} + +// returns a GitTag if Refname matches, otherwise create +func (x *GitTags) InsertByRefname(y string) *GitTag { + gitTagMu.Lock() + defer gitTagMu.Unlock() + + for _, z := range x.GitTags { + if z.Refname == y { + return z + } + } + + z := new(GitTag) + z.Refname = y + x.GitTags = append(x.GitTags, z) + return z +} + +// lookup a GitTags by the Hash +func (x *GitTags) FindByHash(s string) *GitTag { + if x == nil { + return nil + } + + gitTagMu.RLock() + defer gitTagMu.RUnlock() + + for i, _ := range x.GitTags { + if x.GitTags[i].Hash == s { + return x.GitTags[i] + } + } + return nil +} + +// returns a GitTag if Hash matches, otherwise create +func (x *GitTags) InsertByHash(y string) *GitTag { + gitTagMu.Lock() + defer gitTagMu.Unlock() + + for _, z := range x.GitTags { + if z.Hash == y { + return z + } + } + + z := new(GitTag) + z.Hash = y + x.GitTags = append(x.GitTags, z) + return z +} + +func (x *GitTags) DeleteByRefname(s string) bool { + gitTagMu.Lock() + defer gitTagMu.Unlock() + + for i, _ := range x.GitTags { + if x.GitTags[i].Refname == s { + x.GitTags[i] = x.GitTags[len(x.GitTags)-1] + x.GitTags = x.GitTags[:len(x.GitTags)-1] + return true + } + } + return false +} + +func (x *GitTags) DeleteByHash(s string) bool { + gitTagMu.Lock() + defer gitTagMu.Unlock() + + for i, _ := range x.GitTags { + if x.GitTags[i].Hash == s { + x.GitTags[i] = x.GitTags[len(x.GitTags)-1] + x.GitTags = x.GitTags[:len(x.GitTags)-1] + return true + } + } + return false +} + +func (x *GitTags) AppendByRefname(y *GitTag) bool { + gitTagMu.Lock() + defer gitTagMu.Unlock() + + for _, p := range x.GitTags { + if p.Refname == y.Refname { + return false + } + } + + x.GitTags = append(x.GitTags, proto.Clone(y).(*GitTag)) + return true +} + +func (x *GitTags) AppendByHash(y *GitTag) bool { + gitTagMu.Lock() + defer gitTagMu.Unlock() + + for _, p := range x.GitTags { + if p.Hash == y.Hash { + return false + } + } + + x.GitTags = append(x.GitTags, proto.Clone(y).(*GitTag)) + return true +} diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..b65ee8f --- /dev/null +++ b/go.mod @@ -0,0 +1,25 @@ +module go.wit.com/lib/protobuf/gitpb + +go 1.24.1 + +require ( + github.com/destel/rill v0.8.0 + github.com/go-cmd/cmd v1.4.3 + 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.4 + go.wit.com/lib/gui/shell v0.22.33 + go.wit.com/lib/protobuf/bugpb v0.0.6 + go.wit.com/lib/protobuf/guipb v0.0.15 + go.wit.com/lib/protobuf/httppb v0.0.9 + go.wit.com/log v0.25.1 + google.golang.org/protobuf v1.36.9 +) + +require ( + 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..610c6cd --- /dev/null +++ b/go.sum @@ -0,0 +1,38 @@ +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= +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.4 h1:kJpILEHiSXDwfYIetUvL8VyhPX8vOVCN0oTFt8emkjQ= +go.wit.com/lib/config v0.0.4/go.mod h1:dZ3Jr3sIjvCWcQX4cZxNFiUcjUAmwT85S8B140DWeS8= +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/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/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.9 h1:QyXQkoQdj5qSS8HWBV9ldRTcjBWtstAKRPy4RFpSkoM= +go.wit.com/lib/protobuf/httppb v0.0.9/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= diff --git a/goDep.marshal.pb.go b/goDep.marshal.pb.go new file mode 100644 index 0000000..7baf3a0 --- /dev/null +++ b/goDep.marshal.pb.go @@ -0,0 +1,11 @@ +// Code generated by go.wit.com/apps/autogenpb DO NOT EDIT. +// This file was autogenerated with autogenpb v0.5.3-11-g737c5b7 2025.09.16_2337 +// 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 gitpb diff --git a/goDep.pb.go b/goDep.pb.go new file mode 100644 index 0000000..efc989f --- /dev/null +++ b/goDep.pb.go @@ -0,0 +1,283 @@ +// Code modified by go.wit.com/apps/autogenpb DO NOT EDIT. +// +// user defined Mutex locks were auto added +// +// autogenpb version & build time: v0.5.3-11-g737c5b7 2025.09.16_2337 +// 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: goDep.proto + +// store go dependancies + +package gitpb // 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 GoDep struct { + // sync.RWMutex // skipped. protobuf file has `autogenpb:nomutex` + + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Hash string `protobuf:"bytes,1,opt,name=hash,proto3" json:"hash,omitempty"` // `autogenpb:unique` `autogenpb:sort` // md5sum/hash value from the go.sum file + Ctime *timestamppb.Timestamp `protobuf:"bytes,2,opt,name=ctime,proto3" json:"ctime,omitempty"` // get the go date from 'go list' ? + Version string `protobuf:"bytes,3,opt,name=version,proto3" json:"version,omitempty"` // v1.2.2 + GoPath string `protobuf:"bytes,4,opt,name=goPath,proto3" json:"goPath,omitempty"` // `autogenpb:unique` `autogenpb:sort` // "go.wit.com/lib/foo" + GoVersion string `protobuf:"bytes,5,opt,name=goVersion,proto3" json:"goVersion,omitempty"` // version of golang the developer used to make this package version +} + +func (x *GoDep) Reset() { + *x = GoDep{} + if protoimpl.UnsafeEnabled { + mi := &file_goDep_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GoDep) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GoDep) ProtoMessage() {} + +func (x *GoDep) ProtoReflect() protoreflect.Message { + mi := &file_goDep_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 GoDep.ProtoReflect.Descriptor instead. +func (*GoDep) Descriptor() ([]byte, []int) { + return file_goDep_proto_rawDescGZIP(), []int{0} +} + +func (x *GoDep) GetHash() string { + if x != nil { + return x.Hash + } + return "" +} + +func (x *GoDep) GetCtime() *timestamppb.Timestamp { + if x != nil { + return x.Ctime + } + return nil +} + +func (x *GoDep) GetVersion() string { + if x != nil { + return x.Version + } + return "" +} + +func (x *GoDep) GetGoPath() string { + if x != nil { + return x.GoPath + } + return "" +} + +func (x *GoDep) GetGoVersion() string { + if x != nil { + return x.GoVersion + } + return "" +} + +type GoDeps 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:7de62c09-b335-4d80-902d-08552c501b7c` + Version string `protobuf:"bytes,2,opt,name=version,proto3" json:"version,omitempty"` // `autogenpb:version:v0.0.51` + GoDeps []*GoDep `protobuf:"bytes,3,rep,name=goDeps,proto3" json:"goDeps,omitempty"` // `autogenpb:unique` `autogenpb:sort` +} + +func (x *GoDeps) Reset() { + *x = GoDeps{} + if protoimpl.UnsafeEnabled { + mi := &file_goDep_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GoDeps) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GoDeps) ProtoMessage() {} + +func (x *GoDeps) ProtoReflect() protoreflect.Message { + mi := &file_goDep_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 GoDeps.ProtoReflect.Descriptor instead. +func (*GoDeps) Descriptor() ([]byte, []int) { + return file_goDep_proto_rawDescGZIP(), []int{1} +} + +func (x *GoDeps) GetUuid() string { + if x != nil { + return x.Uuid + } + return "" +} + +func (x *GoDeps) GetVersion() string { + if x != nil { + return x.Version + } + return "" +} + +func (x *GoDeps) GetGoDeps() []*GoDep { + if x != nil { + return x.GoDeps + } + return nil +} + +var File_goDep_proto protoreflect.FileDescriptor + +var file_goDep_proto_rawDesc = []byte{ + 0x0a, 0x0b, 0x67, 0x6f, 0x44, 0x65, 0x70, 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, 0x9d, 0x01, 0x0a, 0x05, 0x47, 0x6f, 0x44, 0x65, 0x70, 0x12, + 0x12, 0x0a, 0x04, 0x68, 0x61, 0x73, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x68, + 0x61, 0x73, 0x68, 0x12, 0x30, 0x0a, 0x05, 0x63, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x02, 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, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, + 0x16, 0x0a, 0x06, 0x67, 0x6f, 0x50, 0x61, 0x74, 0x68, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x06, 0x67, 0x6f, 0x50, 0x61, 0x74, 0x68, 0x12, 0x1c, 0x0a, 0x09, 0x67, 0x6f, 0x56, 0x65, 0x72, + 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x67, 0x6f, 0x56, 0x65, + 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0x5c, 0x0a, 0x06, 0x47, 0x6f, 0x44, 0x65, 0x70, 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, 0x24, 0x0a, + 0x06, 0x67, 0x6f, 0x44, 0x65, 0x70, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0c, 0x2e, + 0x67, 0x69, 0x74, 0x70, 0x62, 0x2e, 0x47, 0x6f, 0x44, 0x65, 0x70, 0x52, 0x06, 0x67, 0x6f, 0x44, + 0x65, 0x70, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, +} + +var ( + file_goDep_proto_rawDescOnce sync.Once + file_goDep_proto_rawDescData = file_goDep_proto_rawDesc +) + +func file_goDep_proto_rawDescGZIP() []byte { + file_goDep_proto_rawDescOnce.Do(func() { + file_goDep_proto_rawDescData = protoimpl.X.CompressGZIP(file_goDep_proto_rawDescData) + }) + return file_goDep_proto_rawDescData +} + +var file_goDep_proto_msgTypes = make([]protoimpl.MessageInfo, 2) +var file_goDep_proto_goTypes = []interface{}{ + (*GoDep)(nil), // 0: gitpb.GoDep + (*GoDeps)(nil), // 1: gitpb.GoDeps + (*timestamppb.Timestamp)(nil), // 2: google.protobuf.Timestamp +} +var file_goDep_proto_depIdxs = []int32{ + 2, // 0: gitpb.GoDep.ctime:type_name -> google.protobuf.Timestamp + 0, // 1: gitpb.GoDeps.goDeps:type_name -> gitpb.GoDep + 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_goDep_proto_init() } +func file_goDep_proto_init() { + if File_goDep_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_goDep_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GoDep); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_goDep_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GoDeps); 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_goDep_proto_rawDesc, + NumEnums: 0, + NumMessages: 2, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_goDep_proto_goTypes, + DependencyIndexes: file_goDep_proto_depIdxs, + MessageInfos: file_goDep_proto_msgTypes, + }.Build() + File_goDep_proto = out.File + file_goDep_proto_rawDesc = nil + file_goDep_proto_goTypes = nil + file_goDep_proto_depIdxs = nil +} diff --git a/goDep.sort.pb.go b/goDep.sort.pb.go new file mode 100644 index 0000000..04a4f8c --- /dev/null +++ b/goDep.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.3-11-g737c5b7 2025.09.16_2337 +// 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 gitpb + +import ( + "fmt" + "iter" + "sort" + "sync" + + "google.golang.org/protobuf/proto" +) + +// a simple global lock +var goDepMu sync.RWMutex + +func (x *GoDeps) fixUuid() { + if x == nil { + return + } + if x.Uuid == "7de62c09-b335-4d80-902d-08552c501b7c" { + return + } + x.Uuid = "7de62c09-b335-4d80-902d-08552c501b7c" + x.Version = "v0.0.51 go.wit.com/lib/protobuf/gitpb" +} + +func NewGoDeps() *GoDeps { + x := new(GoDeps) + x.Uuid = "7de62c09-b335-4d80-902d-08552c501b7c" + x.Version = "v0.0.51 go.wit.com/lib/protobuf/gitpb" + return x +} + +// START SORT + +// DEFINE THE GoDeps SCANNER. +// itializes a new scanner. +func newGoDepsScanner(things []*GoDeps) *GoDepsScanner { + return &GoDepsScanner{things: things} +} + +type GoDepsScanner struct { + sync.Mutex + + things []*GoDeps + index int +} + +func (it *GoDepsScanner) 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 *GoDepsScanner) Next() *GoDeps { + if it.things[it.index-1] == nil { + fmt.Println("Next() error in GoDepsScanner", it.index) + } + return it.things[it.index-1] +} + +// END DEFINE THE SCANNER + +// DEFINE THE GoDep SCANNER. +// itializes a new scanner. +func newGoDepScanner(things []*GoDep) *GoDepScanner { + return &GoDepScanner{things: things} +} + +type GoDepScanner struct { + sync.Mutex + + things []*GoDep + index int +} + +func (it *GoDepScanner) 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 *GoDepScanner) Next() *GoDep { + if it.things[it.index-1] == nil { + fmt.Println("Next() error in GoDepScanner", it.index) + } + return it.things[it.index-1] +} + +// END DEFINE THE SCANNER + +// sort struct by Hash +type sortGoDepHash []*GoDep + +func (a sortGoDepHash) Len() int { return len(a) } +func (a sortGoDepHash) Less(i, j int) bool { return a[i].Hash < a[j].Hash } +func (a sortGoDepHash) Swap(i, j int) { a[i], a[j] = a[j], a[i] } + +// sort struct by GoPath +type sortGoDepGoPath []*GoDep + +func (a sortGoDepGoPath) Len() int { return len(a) } +func (a sortGoDepGoPath) Less(i, j int) bool { return a[i].GoPath < a[j].GoPath } +func (a sortGoDepGoPath) Swap(i, j int) { a[i], a[j] = a[j], a[i] } + +// safely returns a slice of pointers to the FRUIT protobufs +func (x *GoDeps) allGoDeps() []*GoDep { + goDepMu.RLock() + defer goDepMu.RUnlock() + + // Create a new slice to hold pointers to each FRUIT + var tmp []*GoDep + tmp = make([]*GoDep, len(x.GoDeps)) + for i, p := range x.GoDeps { + tmp[i] = p // Copy pointers for safe iteration + } + + return tmp +} + +// safely returns a slice of pointers to the GoDep protobufs +func (x *GoDeps) selectAllGoDeps() []*GoDep { + goDepMu.RLock() + defer goDepMu.RUnlock() + + // Create a new slice to hold pointers to each GoDep + var tmp []*GoDep + tmp = make([]*GoDep, len(x.GoDeps)) + for i, p := range x.GoDeps { + tmp[i] = p // Copy pointers for safe iteration + } + + return tmp +} +func (x *GoDeps) SortByHash() *GoDepScanner { + // copy the pointers as fast as possible. + things := x.selectAllGoDeps() + + // todo: try slices.SortFunc() instead to see what happens + sort.Sort(sortGoDepHash(things)) + // slices.SortFunc(things, func(a, b *GoDeps) bool { + // return a.Hash < b.Hash // Sort by ??. let the compiler work it out?? + // }) + return newGoDepScanner(things) +} + +// 'for x := range' syntax using the awesome golang 1.24 'iter' +func (x *GoDeps) IterByHash() iter.Seq[*GoDep] { + items := x.selectAllGoDeps() + sort.Sort(sortGoDepHash(items)) + // log.Println("Made Iter.Seq[] with length", len(items)) + return func(yield func(*GoDep) bool) { + for _, v := range items { + if !yield(v) { + return + } + } + } +} +func (x *GoDeps) SortByGoPath() *GoDepScanner { + // copy the pointers as fast as possible. + things := x.selectAllGoDeps() + + // todo: try slices.SortFunc() instead to see what happens + sort.Sort(sortGoDepGoPath(things)) + // slices.SortFunc(things, func(a, b *GoDeps) bool { + // return a.GoPath < b.GoPath // Sort by ??. let the compiler work it out?? + // }) + return newGoDepScanner(things) +} + +// 'for x := range' syntax using the awesome golang 1.24 'iter' +func (x *GoDeps) IterByGoPath() iter.Seq[*GoDep] { + items := x.selectAllGoDeps() + sort.Sort(sortGoDepGoPath(items)) + // log.Println("Made Iter.Seq[] with length", len(items)) + return func(yield func(*GoDep) bool) { + for _, v := range items { + if !yield(v) { + return + } + } + } +} + +// END SORT + +func (x *GoDeps) Len() int { + goDepMu.RLock() + defer goDepMu.RUnlock() + + return len(x.GoDeps) +} + +// a Append() shortcut (that does Clone() with a mutex) notsure if it really works +func (x *GoDeps) Append(y *GoDep) *GoDep { + goDepMu.Lock() + defer goDepMu.Unlock() + + z := proto.Clone(y).(*GoDep) + x.GoDeps = append(x.GoDeps, z) + + return z +} + +func (x *GoDeps) All() *GoDepScanner { + GoDepPointers := x.selectAllGoDeps() + + scanner := newGoDepScanner(GoDepPointers) + return scanner +} + +// Iterate 'for x := range' syntax using the awesome golang 1.24 'iter' +func (x *GoDeps) IterAll() iter.Seq[*GoDep] { + items := x.selectAllGoDeps() + // log.Println("Made All() Iter.Seq[] with length", len(items)) + return func(yield func(*GoDep) bool) { + for _, v := range items { + if !yield(v) { + return + } + } + } +} +func (x *GoDeps) Delete(y *GoDep) bool { + goDepMu.Lock() + defer goDepMu.Unlock() + + for i, _ := range x.GoDeps { + if x.GoDeps[i] == y { + x.GoDeps[i] = x.GoDeps[len(x.GoDeps)-1] + x.GoDeps = x.GoDeps[:len(x.GoDeps)-1] + return true + } + } + return false +} + +// lookup a GoDeps by the Hash +func (x *GoDeps) FindByHash(s string) *GoDep { + if x == nil { + return nil + } + + goDepMu.RLock() + defer goDepMu.RUnlock() + + for i, _ := range x.GoDeps { + if x.GoDeps[i].Hash == s { + return x.GoDeps[i] + } + } + return nil +} + +// returns a GoDep if Hash matches, otherwise create +func (x *GoDeps) InsertByHash(y string) *GoDep { + goDepMu.Lock() + defer goDepMu.Unlock() + + for _, z := range x.GoDeps { + if z.Hash == y { + return z + } + } + + z := new(GoDep) + z.Hash = y + x.GoDeps = append(x.GoDeps, z) + return z +} + +// lookup a GoDeps by the GoPath +func (x *GoDeps) FindByGoPath(s string) *GoDep { + if x == nil { + return nil + } + + goDepMu.RLock() + defer goDepMu.RUnlock() + + for i, _ := range x.GoDeps { + if x.GoDeps[i].GoPath == s { + return x.GoDeps[i] + } + } + return nil +} + +// returns a GoDep if GoPath matches, otherwise create +func (x *GoDeps) InsertByGoPath(y string) *GoDep { + goDepMu.Lock() + defer goDepMu.Unlock() + + for _, z := range x.GoDeps { + if z.GoPath == y { + return z + } + } + + z := new(GoDep) + z.GoPath = y + x.GoDeps = append(x.GoDeps, z) + return z +} + +func (x *GoDeps) DeleteByHash(s string) bool { + goDepMu.Lock() + defer goDepMu.Unlock() + + for i, _ := range x.GoDeps { + if x.GoDeps[i].Hash == s { + x.GoDeps[i] = x.GoDeps[len(x.GoDeps)-1] + x.GoDeps = x.GoDeps[:len(x.GoDeps)-1] + return true + } + } + return false +} + +func (x *GoDeps) DeleteByGoPath(s string) bool { + goDepMu.Lock() + defer goDepMu.Unlock() + + for i, _ := range x.GoDeps { + if x.GoDeps[i].GoPath == s { + x.GoDeps[i] = x.GoDeps[len(x.GoDeps)-1] + x.GoDeps = x.GoDeps[:len(x.GoDeps)-1] + return true + } + } + return false +} + +func (x *GoDeps) AppendByHash(y *GoDep) bool { + goDepMu.Lock() + defer goDepMu.Unlock() + + for _, p := range x.GoDeps { + if p.Hash == y.Hash { + return false + } + } + + x.GoDeps = append(x.GoDeps, proto.Clone(y).(*GoDep)) + return true +} + +func (x *GoDeps) AppendByGoPath(y *GoDep) bool { + goDepMu.Lock() + defer goDepMu.Unlock() + + for _, p := range x.GoDeps { + if p.GoPath == y.GoPath { + return false + } + } + + x.GoDeps = append(x.GoDeps, proto.Clone(y).(*GoDep)) + return true +} diff --git a/repo.gui.pb.go b/repo.gui.pb.go new file mode 100644 index 0000000..79d7fb1 --- /dev/null +++ b/repo.gui.pb.go @@ -0,0 +1,362 @@ +// Code generated by go.wit.com/apps/autogenpb DO NOT EDIT. +// This file was autogenerated with autogenpb v0.5.3-11-g737c5b7 2025.09.16_2337 +// 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 gitpb + +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 *Repos) NewTable(title string) *ReposTable { + t := new(ReposTable) + 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 *ReposTable) AddStringFunc(title string, f func(*Repo) string) *RepoAnyFunc { + t.pb.Order = append(t.pb.Order, title) + + sf := new(RepoAnyFunc) + sf.title = title + sf.f = func(x *Repo) 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 *ReposTable) AddButtonFunc(title string, f func(*Repo) string) *RepoAnyFunc { + t.pb.Order = append(t.pb.Order, title) + + sf := new(RepoAnyFunc) + sf.title = title + sf.f = func(x *Repo) 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 *ReposTable) AddIntFunc(title string, f func(*Repo) int) *RepoAnyFunc { + t.pb.Order = append(t.pb.Order, title) + + sf := new(RepoAnyFunc) + sf.title = title + sf.f = func(x *Repo) 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 *ReposTable) AddTimeFunc(title string, f func(*Repo) time.Time) *RepoAnyFunc { + t.pb.Order = append(t.pb.Order, title) + + sf := new(RepoAnyFunc) + sf.title = title + sf.f = func(x *Repo) 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 *RepoAnyFunc) SetTitle(title string) { + sf.title = title +} + +func (mt *ReposTable) SetParent(p *gui.Node) { + mt.parent = p +} + +func (mt *ReposTable) ShowTable() { + // log.Info("ShowTable() SENDING TO GUI") + mt.MakeTable() + mt.parent.ShowTable(mt.pb) +} + +type RepoAnyFunc struct { + title string + f func(*Repo) any + Custom func(*Repo) + Width int + attr *guipb.ColAttr +} + +type ReposTable struct { + pb *guipb.Table + parent *gui.Node + x *Repos + hostnames []string + anyFuncs []*RepoAnyFunc + CustomFunc func(*Repo) +} + +func (mt *ReposTable) doAnyFuncNew(sf *RepoAnyFunc) 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 *ReposTable) MakeTable() { + for _, sf := range mt.anyFuncs { + mt.doAnyFuncNew(sf) + } +} + +func (t *ReposTable) AddNamespace() *RepoAnyFunc { + sf := t.AddStringFunc("Namespace", func(m *Repo) string { + return m.Namespace + }) + return sf +} + +func (t *ReposTable) AddFullPath() *RepoAnyFunc { + sf := t.AddStringFunc("FullPath", func(m *Repo) string { + return m.FullPath + }) + return sf +} + +func (t *ReposTable) AddMasterBranchName() *RepoAnyFunc { + sf := t.AddStringFunc("MasterBranchName", func(m *Repo) string { + return m.MasterBranchName + }) + return sf +} + +func (t *ReposTable) AddDevelBranchName() *RepoAnyFunc { + sf := t.AddStringFunc("DevelBranchName", func(m *Repo) string { + return m.DevelBranchName + }) + return sf +} + +func (t *ReposTable) AddUserBranchName() *RepoAnyFunc { + sf := t.AddStringFunc("UserBranchName", func(m *Repo) string { + return m.UserBranchName + }) + return sf +} + +func (t *ReposTable) AddURL() *RepoAnyFunc { + sf := t.AddStringFunc("URL", func(m *Repo) string { + return m.URL + }) + return sf +} + +func (t *ReposTable) AddCurrentBranchName() *RepoAnyFunc { + sf := t.AddStringFunc("CurrentBranchName", func(m *Repo) string { + return m.CurrentBranchName + }) + return sf +} + +func (t *ReposTable) AddCurrentBranchVersion() *RepoAnyFunc { + sf := t.AddStringFunc("CurrentBranchVersion", func(m *Repo) string { + return m.CurrentBranchVersion + }) + return sf +} + +func (t *ReposTable) AddLastTag() *RepoAnyFunc { + sf := t.AddStringFunc("LastTag", func(m *Repo) string { + return m.LastTag + }) + return sf +} + +func (t *ReposTable) AddTargetVersion() *RepoAnyFunc { + sf := t.AddStringFunc("TargetVersion", func(m *Repo) string { + return m.TargetVersion + }) + return sf +} + +func (t *ReposTable) AddDesc() *RepoAnyFunc { + sf := t.AddStringFunc("Desc", func(m *Repo) string { + return m.Desc + }) + return sf +} + +func (t *ReposTable) AddStateChange() *RepoAnyFunc { + sf := t.AddStringFunc("StateChange", func(m *Repo) string { + return m.StateChange + }) + return sf +} + +func (t *ReposTable) AddMasterVersion() *RepoAnyFunc { + sf := t.AddStringFunc("MasterVersion", func(m *Repo) string { + return m.MasterVersion + }) + return sf +} + +func (t *ReposTable) AddDevelVersion() *RepoAnyFunc { + sf := t.AddStringFunc("DevelVersion", func(m *Repo) string { + return m.DevelVersion + }) + return sf +} + +func (t *ReposTable) AddUserVersion() *RepoAnyFunc { + sf := t.AddStringFunc("UserVersion", func(m *Repo) string { + return m.UserVersion + }) + return sf +} + +func (t *ReposTable) AddState() *RepoAnyFunc { + sf := t.AddStringFunc("State", func(m *Repo) string { + return m.State + }) + return sf +} + +func (t *ReposTable) AddMasterHash() *RepoAnyFunc { + sf := t.AddStringFunc("MasterHash", func(m *Repo) string { + return m.MasterHash + }) + return sf +} + +func (t *ReposTable) AddDevelHash() *RepoAnyFunc { + sf := t.AddStringFunc("DevelHash", func(m *Repo) string { + return m.DevelHash + }) + return sf +} +func (mt *ReposTable) NewUuid() { + mt.pb.Uuid = uuid.New().String() +} + +// START TABLE UPDATE (doesn't work yet) + +func (mt *ReposTable) 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 *ReposTable) Delete() { + if mt == nil { + log.Info("mt == nil table already deleted") + return + } + // log.Info("table Delete here") + mt.parent.DeleteTable(mt.pb) +} + +func (mt *ReposTable) reposCustom(w *guipb.Widget) { + row := mt.x.Repos[w.Location.Y-1] + // log.Info("got to reposCustom() 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 *ReposTable) Custom(f func(*Repo)) { + mt.pb.RegisterCustom(mt.reposCustom) + mt.CustomFunc = f +} + +func (mt *ReposTable) GetUuid() string { + return mt.pb.Uuid +} + +// END TABLE UPDATE + +// END GUI diff --git a/repo.http.pb.go b/repo.http.pb.go new file mode 100644 index 0000000..e9a90ff --- /dev/null +++ b/repo.http.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.3-11-g737c5b7 2025.09.16_2337 +// 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 gitpb + +import ( + "net/http" + "path/filepath" + + "go.wit.com/lib/protobuf/httppb" +) + +// START HTTP + +func (p *Repos) 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 *Repos) HttpPost(baseURL string, route string) (*Repos, *httppb.HttpRequest, error) { + data, err := p.Marshal() + if err != nil { + return nil, nil, err + } + + tmp := filepath.Join("repos", route) + reqPB, err := httppb.DoPost(baseURL, tmp, data) + if reqPB == nil { + return nil, nil, err + } + + newpb := new(Repos) + err = newpb.Unmarshal(reqPB.ServerData) + return newpb, reqPB, err +} + +// END HTTP diff --git a/repo.marshal.pb.go b/repo.marshal.pb.go new file mode 100644 index 0000000..9f3536d --- /dev/null +++ b/repo.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.3-11-g737c5b7 2025.09.16_2337 +// 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 gitpb + +import ( + "google.golang.org/protobuf/encoding/protojson" + "google.golang.org/protobuf/encoding/prototext" + "google.golang.org/protobuf/proto" +) + +// human readable JSON +func (v *Repos) FormatJSON() string { + return protojson.Format(v) +} + +// marshal json +func (v *Repos) MarshalJSON() ([]byte, error) { + return protojson.Marshal(v) +} + +// unmarshal json +func (v *Repos) 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 *Repos) FormatTEXT() string { + v.fixUuid() + return prototext.Format(v) +} + +// unmarshalTEXT. This reads the .text config file back in after the user edits it +func (v *Repos) UnmarshalTEXT(data []byte) error { + return prototext.Unmarshal(data, v) +} + +// marshal to wire. This is called winning. +func (v *Repos) Marshal() ([]byte, error) { + v.fixUuid() + return proto.Marshal(v) +} + +// unmarshal from wire. You have won. +func (v *Repos) Unmarshal(data []byte) error { + return proto.Unmarshal(data, v) +} + +// human readable JSON +func (v *Repo) FormatJSON() string { + return protojson.Format(v) +} + +// marshal json +func (v *Repo) MarshalJSON() ([]byte, error) { + return protojson.Marshal(v) +} + +// unmarshal json +func (v *Repo) 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 *Repo) FormatTEXT() string { + return prototext.Format(v) +} + +// unmarshalTEXT. This reads the .text config file back in after the user edits it +func (v *Repo) UnmarshalTEXT(data []byte) error { + return prototext.Unmarshal(data, v) +} + +// marshal to wire. This is called winning. +func (v *Repo) Marshal() ([]byte, error) { + return proto.Marshal(v) +} + +// unmarshal from wire. You have won. +func (v *Repo) Unmarshal(data []byte) error { + return proto.Unmarshal(data, v) +} diff --git a/repo.pb.go b/repo.pb.go new file mode 100644 index 0000000..a4130b4 --- /dev/null +++ b/repo.pb.go @@ -0,0 +1,917 @@ +// Code modified by go.wit.com/apps/autogenpb DO NOT EDIT. +// +// user defined Mutex locks were auto added +// +// autogenpb version & build time: v0.5.3-11-g737c5b7 2025.09.16_2337 +// 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: repo.proto + +package gitpb // 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 GitTimes struct { + // sync.RWMutex // skipped. protobuf file has `autogenpb:nomutex` + + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + LastPull *timestamppb.Timestamp `protobuf:"bytes,1,opt,name=lastPull,proto3" json:"lastPull,omitempty"` // last time a git pull was done + LastUpdate *timestamppb.Timestamp `protobuf:"bytes,2,opt,name=lastUpdate,proto3" json:"lastUpdate,omitempty"` // when was ReloadGit() last done + LastDirty *timestamppb.Timestamp `protobuf:"bytes,3,opt,name=lastDirty,proto3" json:"lastDirty,omitempty"` // last time CheckDirty() was run + MtimeDir *timestamppb.Timestamp `protobuf:"bytes,4,opt,name=mtimeDir,proto3" json:"mtimeDir,omitempty"` // mtime for ./git // maybe useful to track + MtimeHead *timestamppb.Timestamp `protobuf:"bytes,5,opt,name=mtimeHead,proto3" json:"mtimeHead,omitempty"` // mtime for ./git/HEAD // these two mtimes allow really fast checks to see if git has changed + MtimeIndex *timestamppb.Timestamp `protobuf:"bytes,6,opt,name=mtimeIndex,proto3" json:"mtimeIndex,omitempty"` // mtime for ./git/HEAD // probably always in sync with HEAD + MtimeFetch *timestamppb.Timestamp `protobuf:"bytes,7,opt,name=mtimeFetch,proto3" json:"mtimeFetch,omitempty"` // mtime for ./git/FETCH_HEAD // last time 'git fetch' or 'git pull' was run on current branch? + LastGoDep *timestamppb.Timestamp `protobuf:"bytes,8,opt,name=lastGoDep,proto3" json:"lastGoDep,omitempty"` // mtime for last go.sum scan + NewestCommit *timestamppb.Timestamp `protobuf:"bytes,9,opt,name=newestCommit,proto3" json:"newestCommit,omitempty"` // when the newest commit was + MtimeConfig *timestamppb.Timestamp `protobuf:"bytes,10,opt,name=mtimeConfig,proto3" json:"mtimeConfig,omitempty"` // mtime for the .git/config file +} + +func (x *GitTimes) Reset() { + *x = GitTimes{} + if protoimpl.UnsafeEnabled { + mi := &file_repo_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GitTimes) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GitTimes) ProtoMessage() {} + +func (x *GitTimes) ProtoReflect() protoreflect.Message { + mi := &file_repo_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 GitTimes.ProtoReflect.Descriptor instead. +func (*GitTimes) Descriptor() ([]byte, []int) { + return file_repo_proto_rawDescGZIP(), []int{0} +} + +func (x *GitTimes) GetLastPull() *timestamppb.Timestamp { + if x != nil { + return x.LastPull + } + return nil +} + +func (x *GitTimes) GetLastUpdate() *timestamppb.Timestamp { + if x != nil { + return x.LastUpdate + } + return nil +} + +func (x *GitTimes) GetLastDirty() *timestamppb.Timestamp { + if x != nil { + return x.LastDirty + } + return nil +} + +func (x *GitTimes) GetMtimeDir() *timestamppb.Timestamp { + if x != nil { + return x.MtimeDir + } + return nil +} + +func (x *GitTimes) GetMtimeHead() *timestamppb.Timestamp { + if x != nil { + return x.MtimeHead + } + return nil +} + +func (x *GitTimes) GetMtimeIndex() *timestamppb.Timestamp { + if x != nil { + return x.MtimeIndex + } + return nil +} + +func (x *GitTimes) GetMtimeFetch() *timestamppb.Timestamp { + if x != nil { + return x.MtimeFetch + } + return nil +} + +func (x *GitTimes) GetLastGoDep() *timestamppb.Timestamp { + if x != nil { + return x.LastGoDep + } + return nil +} + +func (x *GitTimes) GetNewestCommit() *timestamppb.Timestamp { + if x != nil { + return x.NewestCommit + } + return nil +} + +func (x *GitTimes) GetMtimeConfig() *timestamppb.Timestamp { + if x != nil { + return x.MtimeConfig + } + return nil +} + +// this is probably better. think about moving to this instead +type GoInfo 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"` // the logical path as used by golang: 'go.wit.com/apps/helloworld' + Desc string `protobuf:"bytes,2,opt,name=desc,proto3" json:"desc,omitempty"` // what is this repo? + GoLibrary bool `protobuf:"varint,3,opt,name=goLibrary,proto3" json:"goLibrary,omitempty"` // is this a golang library? + GoBinary bool `protobuf:"varint,4,opt,name=goBinary,proto3" json:"goBinary,omitempty"` // is this a golang binary? + GoPrimitive bool `protobuf:"varint,5,opt,name=goPrimitive,proto3" json:"goPrimitive,omitempty"` // if this is a golang primitive (only has go.mod) + GoPlugin bool `protobuf:"varint,6,opt,name=goPlugin,proto3" json:"goPlugin,omitempty"` // is this a golang plugin? + GoProtobuf bool `protobuf:"varint,7,opt,name=goProtobuf,proto3" json:"goProtobuf,omitempty"` // autogen go files from .proto + GoDeps *GoDeps `protobuf:"bytes,8,opt,name=goDeps,proto3" json:"goDeps,omitempty"` // what is in the go.sum file + Published *GoDeps `protobuf:"bytes,9,opt,name=published,proto3" json:"published,omitempty"` // the last published go.mod/go.sum + GoMod []byte `protobuf:"bytes,10,opt,name=goMod,proto3" json:"goMod,omitempty"` // the last go.mod file + GoSum []byte `protobuf:"bytes,11,opt,name=goSum,proto3" json:"goSum,omitempty"` // the last go.sum file + GitIgnoresGoSum bool `protobuf:"varint,12,opt,name=gitIgnoresGoSum,proto3" json:"gitIgnoresGoSum,omitempty"` // does .gitignore ignore go.mod & go.sum? +} + +func (x *GoInfo) Reset() { + *x = GoInfo{} + if protoimpl.UnsafeEnabled { + mi := &file_repo_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GoInfo) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GoInfo) ProtoMessage() {} + +func (x *GoInfo) ProtoReflect() protoreflect.Message { + mi := &file_repo_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 GoInfo.ProtoReflect.Descriptor instead. +func (*GoInfo) Descriptor() ([]byte, []int) { + return file_repo_proto_rawDescGZIP(), []int{1} +} + +func (x *GoInfo) GetGoPath() string { + if x != nil { + return x.GoPath + } + return "" +} + +func (x *GoInfo) GetDesc() string { + if x != nil { + return x.Desc + } + return "" +} + +func (x *GoInfo) GetGoLibrary() bool { + if x != nil { + return x.GoLibrary + } + return false +} + +func (x *GoInfo) GetGoBinary() bool { + if x != nil { + return x.GoBinary + } + return false +} + +func (x *GoInfo) GetGoPrimitive() bool { + if x != nil { + return x.GoPrimitive + } + return false +} + +func (x *GoInfo) GetGoPlugin() bool { + if x != nil { + return x.GoPlugin + } + return false +} + +func (x *GoInfo) GetGoProtobuf() bool { + if x != nil { + return x.GoProtobuf + } + return false +} + +func (x *GoInfo) GetGoDeps() *GoDeps { + if x != nil { + return x.GoDeps + } + return nil +} + +func (x *GoInfo) GetPublished() *GoDeps { + if x != nil { + return x.Published + } + return nil +} + +func (x *GoInfo) GetGoMod() []byte { + if x != nil { + return x.GoMod + } + return nil +} + +func (x *GoInfo) GetGoSum() []byte { + if x != nil { + return x.GoSum + } + return nil +} + +func (x *GoInfo) GetGitIgnoresGoSum() bool { + if x != nil { + return x.GitIgnoresGoSum + } + return false +} + +type Repo struct { + // sync.RWMutex // skipped. protobuf file has `autogenpb:nomutex` + + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Namespace string `protobuf:"bytes,1,opt,name=namespace,proto3" json:"namespace,omitempty"` // `autogenpb:unique` `autogenpb:sort` // this repo is 'go.wit.com/lib/protobuf/gitpb' + FullPath string `protobuf:"bytes,2,opt,name=fullPath,proto3" json:"fullPath,omitempty"` // `autogenpb:unique` `autogenpb:sort` // the OS path to the .git directory: '/home/devel/golang.org/x/tools' + MasterBranchName string `protobuf:"bytes,3,opt,name=masterBranchName,proto3" json:"masterBranchName,omitempty"` // git 'main' or 'master' branch name + DevelBranchName string `protobuf:"bytes,4,opt,name=develBranchName,proto3" json:"develBranchName,omitempty"` // whatever the git 'devel' branch name is + UserBranchName string `protobuf:"bytes,5,opt,name=userBranchName,proto3" json:"userBranchName,omitempty"` // whatever your username branch is + Dirty bool `protobuf:"varint,6,opt,name=dirty,proto3" json:"dirty,omitempty"` // if git says things have been changed + URL string `protobuf:"bytes,7,opt,name=URL,proto3" json:"URL,omitempty"` // the URL + Tags *GitTags `protobuf:"bytes,8,opt,name=tags,proto3" json:"tags,omitempty"` // known tags + Times *GitTimes `protobuf:"bytes,9,opt,name=times,proto3" json:"times,omitempty"` // store all the mtime values here. these are temporary + GoInfo *GoInfo `protobuf:"bytes,10,opt,name=goInfo,proto3" json:"goInfo,omitempty"` // put all the go specifcs here + GoDeps *GoDeps `protobuf:"bytes,11,opt,name=goDeps,proto3" json:"goDeps,omitempty"` // what is in the go.sum file + CurrentBranchName string `protobuf:"bytes,12,opt,name=currentBranchName,proto3" json:"currentBranchName,omitempty"` // the branch currently checked out + CurrentBranchVersion string `protobuf:"bytes,13,opt,name=currentBranchVersion,proto3" json:"currentBranchVersion,omitempty"` // the branch currently checked out + LastTag string `protobuf:"bytes,14,opt,name=lastTag,proto3" json:"lastTag,omitempty"` // the oldest tag + TargetVersion string `protobuf:"bytes,15,opt,name=targetVersion,proto3" json:"targetVersion,omitempty"` // useful during the package release process + ReadOnly bool `protobuf:"varint,16,opt,name=readOnly,proto3" json:"readOnly,omitempty"` // tracks access to 'git push' + Desc string `protobuf:"bytes,17,opt,name=desc,proto3" json:"desc,omitempty"` // what is this repo? + StateChange string `protobuf:"bytes,18,opt,name=stateChange,proto3" json:"stateChange,omitempty"` // used for debugging tool logic + MasterVersion string `protobuf:"bytes,19,opt,name=masterVersion,proto3" json:"masterVersion,omitempty"` // just store this for now + DevelVersion string `protobuf:"bytes,20,opt,name=develVersion,proto3" json:"develVersion,omitempty"` // + UserVersion string `protobuf:"bytes,21,opt,name=userVersion,proto3" json:"userVersion,omitempty"` // + DirtyList []string `protobuf:"bytes,22,rep,name=dirtyList,proto3" json:"dirtyList,omitempty"` // store the list from git status --porcelain + State string `protobuf:"bytes,23,opt,name=state,proto3" json:"state,omitempty"` // status or state. useful for building tooling + CurrentTag *GitTag `protobuf:"bytes,24,opt,name=currentTag,proto3" json:"currentTag,omitempty"` // used to examine repo branches + GitConfig *GitConfig `protobuf:"bytes,25,opt,name=gitConfig,proto3" json:"gitConfig,omitempty"` // protobuf of the current .git/config + MasterHash string `protobuf:"bytes,26,opt,name=MasterHash,proto3" json:"MasterHash,omitempty"` // hash of the current master branch + DevelHash string `protobuf:"bytes,27,opt,name=DevelHash,proto3" json:"DevelHash,omitempty"` // hash of the current devel branch + Control map[string]string `protobuf:"bytes,28,rep,name=control,proto3" json:"control,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` // control values. can be used to make packages (like .deb or .rpm) +} + +func (x *Repo) Reset() { + *x = Repo{} + if protoimpl.UnsafeEnabled { + mi := &file_repo_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Repo) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Repo) ProtoMessage() {} + +func (x *Repo) ProtoReflect() protoreflect.Message { + mi := &file_repo_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 Repo.ProtoReflect.Descriptor instead. +func (*Repo) Descriptor() ([]byte, []int) { + return file_repo_proto_rawDescGZIP(), []int{2} +} + +func (x *Repo) GetNamespace() string { + if x != nil { + return x.Namespace + } + return "" +} + +func (x *Repo) GetFullPath() string { + if x != nil { + return x.FullPath + } + return "" +} + +func (x *Repo) GetMasterBranchName() string { + if x != nil { + return x.MasterBranchName + } + return "" +} + +func (x *Repo) GetDevelBranchName() string { + if x != nil { + return x.DevelBranchName + } + return "" +} + +func (x *Repo) GetUserBranchName() string { + if x != nil { + return x.UserBranchName + } + return "" +} + +func (x *Repo) GetDirty() bool { + if x != nil { + return x.Dirty + } + return false +} + +func (x *Repo) GetURL() string { + if x != nil { + return x.URL + } + return "" +} + +func (x *Repo) GetTags() *GitTags { + if x != nil { + return x.Tags + } + return nil +} + +func (x *Repo) GetTimes() *GitTimes { + if x != nil { + return x.Times + } + return nil +} + +func (x *Repo) GetGoInfo() *GoInfo { + if x != nil { + return x.GoInfo + } + return nil +} + +func (x *Repo) GetGoDeps() *GoDeps { + if x != nil { + return x.GoDeps + } + return nil +} + +func (x *Repo) GetCurrentBranchName() string { + if x != nil { + return x.CurrentBranchName + } + return "" +} + +func (x *Repo) GetCurrentBranchVersion() string { + if x != nil { + return x.CurrentBranchVersion + } + return "" +} + +func (x *Repo) GetLastTag() string { + if x != nil { + return x.LastTag + } + return "" +} + +func (x *Repo) GetTargetVersion() string { + if x != nil { + return x.TargetVersion + } + return "" +} + +func (x *Repo) GetReadOnly() bool { + if x != nil { + return x.ReadOnly + } + return false +} + +func (x *Repo) GetDesc() string { + if x != nil { + return x.Desc + } + return "" +} + +func (x *Repo) GetStateChange() string { + if x != nil { + return x.StateChange + } + return "" +} + +func (x *Repo) GetMasterVersion() string { + if x != nil { + return x.MasterVersion + } + return "" +} + +func (x *Repo) GetDevelVersion() string { + if x != nil { + return x.DevelVersion + } + return "" +} + +func (x *Repo) GetUserVersion() string { + if x != nil { + return x.UserVersion + } + return "" +} + +func (x *Repo) GetDirtyList() []string { + if x != nil { + return x.DirtyList + } + return nil +} + +func (x *Repo) GetState() string { + if x != nil { + return x.State + } + return "" +} + +func (x *Repo) GetCurrentTag() *GitTag { + if x != nil { + return x.CurrentTag + } + return nil +} + +func (x *Repo) GetGitConfig() *GitConfig { + if x != nil { + return x.GitConfig + } + return nil +} + +func (x *Repo) GetMasterHash() string { + if x != nil { + return x.MasterHash + } + return "" +} + +func (x *Repo) GetDevelHash() string { + if x != nil { + return x.DevelHash + } + return "" +} + +func (x *Repo) GetControl() map[string]string { + if x != nil { + return x.Control + } + return nil +} + +type Repos 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:8daaeba1-fb1f-4762-ae6e-95a55d352673` + Version string `protobuf:"bytes,2,opt,name=version,proto3" json:"version,omitempty"` // `autogenpb:version:v4` + Repos []*Repo `protobuf:"bytes,3,rep,name=repos,proto3" json:"repos,omitempty"` // `autogenpb:append` // generate AppendUnique() function for this + HasFullScan bool `protobuf:"varint,4,opt,name=hasFullScan,proto3" json:"hasFullScan,omitempty"` // a full repo scan has been saved to disk + FullScan *timestamppb.Timestamp `protobuf:"bytes,5,opt,name=fullScan,proto3" json:"fullScan,omitempty"` // mtime of the last full scan saved to disk +} + +func (x *Repos) Reset() { + *x = Repos{} + if protoimpl.UnsafeEnabled { + mi := &file_repo_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Repos) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Repos) ProtoMessage() {} + +func (x *Repos) ProtoReflect() protoreflect.Message { + mi := &file_repo_proto_msgTypes[3] + 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 Repos.ProtoReflect.Descriptor instead. +func (*Repos) Descriptor() ([]byte, []int) { + return file_repo_proto_rawDescGZIP(), []int{3} +} + +func (x *Repos) GetUuid() string { + if x != nil { + return x.Uuid + } + return "" +} + +func (x *Repos) GetVersion() string { + if x != nil { + return x.Version + } + return "" +} + +func (x *Repos) GetRepos() []*Repo { + if x != nil { + return x.Repos + } + return nil +} + +func (x *Repos) GetHasFullScan() bool { + if x != nil { + return x.HasFullScan + } + return false +} + +func (x *Repos) GetFullScan() *timestamppb.Timestamp { + if x != nil { + return x.FullScan + } + return nil +} + +var File_repo_proto protoreflect.FileDescriptor + +var file_repo_proto_rawDesc = []byte{ + 0x0a, 0x0a, 0x72, 0x65, 0x70, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x05, 0x67, 0x69, + 0x74, 0x70, 0x62, 0x1a, 0x0c, 0x67, 0x69, 0x74, 0x54, 0x61, 0x67, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x1a, 0x0b, 0x67, 0x6f, 0x44, 0x65, 0x70, 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, + 0xda, 0x04, 0x0a, 0x08, 0x47, 0x69, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x12, 0x36, 0x0a, 0x08, + 0x6c, 0x61, 0x73, 0x74, 0x50, 0x75, 0x6c, 0x6c, 0x18, 0x01, 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, 0x6c, 0x61, 0x73, 0x74, + 0x50, 0x75, 0x6c, 0x6c, 0x12, 0x3a, 0x0a, 0x0a, 0x6c, 0x61, 0x73, 0x74, 0x55, 0x70, 0x64, 0x61, + 0x74, 0x65, 0x18, 0x02, 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, 0x0a, 0x6c, 0x61, 0x73, 0x74, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, + 0x12, 0x38, 0x0a, 0x09, 0x6c, 0x61, 0x73, 0x74, 0x44, 0x69, 0x72, 0x74, 0x79, 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, 0x44, 0x69, 0x72, 0x74, 0x79, 0x12, 0x36, 0x0a, 0x08, 0x6d, 0x74, + 0x69, 0x6d, 0x65, 0x44, 0x69, 0x72, 0x18, 0x04, 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, 0x6d, 0x74, 0x69, 0x6d, 0x65, 0x44, + 0x69, 0x72, 0x12, 0x38, 0x0a, 0x09, 0x6d, 0x74, 0x69, 0x6d, 0x65, 0x48, 0x65, 0x61, 0x64, 0x18, + 0x05, 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, 0x6d, 0x74, 0x69, 0x6d, 0x65, 0x48, 0x65, 0x61, 0x64, 0x12, 0x3a, 0x0a, 0x0a, + 0x6d, 0x74, 0x69, 0x6d, 0x65, 0x49, 0x6e, 0x64, 0x65, 0x78, 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, 0x0a, 0x6d, 0x74, + 0x69, 0x6d, 0x65, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x3a, 0x0a, 0x0a, 0x6d, 0x74, 0x69, 0x6d, + 0x65, 0x46, 0x65, 0x74, 0x63, 0x68, 0x18, 0x07, 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, 0x0a, 0x6d, 0x74, 0x69, 0x6d, 0x65, 0x46, + 0x65, 0x74, 0x63, 0x68, 0x12, 0x38, 0x0a, 0x09, 0x6c, 0x61, 0x73, 0x74, 0x47, 0x6f, 0x44, 0x65, + 0x70, 0x18, 0x08, 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, 0x47, 0x6f, 0x44, 0x65, 0x70, 0x12, 0x3e, + 0x0a, 0x0c, 0x6e, 0x65, 0x77, 0x65, 0x73, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x18, 0x09, + 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, 0x0c, 0x6e, 0x65, 0x77, 0x65, 0x73, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x12, 0x3c, + 0x0a, 0x0b, 0x6d, 0x74, 0x69, 0x6d, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x0a, 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, + 0x0b, 0x6d, 0x74, 0x69, 0x6d, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x22, 0xf6, 0x02, 0x0a, + 0x06, 0x47, 0x6f, 0x49, 0x6e, 0x66, 0x6f, 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, + 0x12, 0x0a, 0x04, 0x64, 0x65, 0x73, 0x63, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x64, + 0x65, 0x73, 0x63, 0x12, 0x1c, 0x0a, 0x09, 0x67, 0x6f, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x67, 0x6f, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, + 0x79, 0x12, 0x1a, 0x0a, 0x08, 0x67, 0x6f, 0x42, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x18, 0x04, 0x20, + 0x01, 0x28, 0x08, 0x52, 0x08, 0x67, 0x6f, 0x42, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x12, 0x20, 0x0a, + 0x0b, 0x67, 0x6f, 0x50, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x18, 0x05, 0x20, 0x01, + 0x28, 0x08, 0x52, 0x0b, 0x67, 0x6f, 0x50, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x12, + 0x1a, 0x0a, 0x08, 0x67, 0x6f, 0x50, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x18, 0x06, 0x20, 0x01, 0x28, + 0x08, 0x52, 0x08, 0x67, 0x6f, 0x50, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x12, 0x1e, 0x0a, 0x0a, 0x67, + 0x6f, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, + 0x0a, 0x67, 0x6f, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x12, 0x25, 0x0a, 0x06, 0x67, + 0x6f, 0x44, 0x65, 0x70, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x67, 0x69, + 0x74, 0x70, 0x62, 0x2e, 0x47, 0x6f, 0x44, 0x65, 0x70, 0x73, 0x52, 0x06, 0x67, 0x6f, 0x44, 0x65, + 0x70, 0x73, 0x12, 0x2b, 0x0a, 0x09, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x65, 0x64, 0x18, + 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x67, 0x69, 0x74, 0x70, 0x62, 0x2e, 0x47, 0x6f, + 0x44, 0x65, 0x70, 0x73, 0x52, 0x09, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x65, 0x64, 0x12, + 0x14, 0x0a, 0x05, 0x67, 0x6f, 0x4d, 0x6f, 0x64, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, + 0x67, 0x6f, 0x4d, 0x6f, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x67, 0x6f, 0x53, 0x75, 0x6d, 0x18, 0x0b, + 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x67, 0x6f, 0x53, 0x75, 0x6d, 0x12, 0x28, 0x0a, 0x0f, 0x67, + 0x69, 0x74, 0x49, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x73, 0x47, 0x6f, 0x53, 0x75, 0x6d, 0x18, 0x0c, + 0x20, 0x01, 0x28, 0x08, 0x52, 0x0f, 0x67, 0x69, 0x74, 0x49, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x73, + 0x47, 0x6f, 0x53, 0x75, 0x6d, 0x22, 0xa0, 0x08, 0x0a, 0x04, 0x52, 0x65, 0x70, 0x6f, 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, 0x1a, 0x0a, 0x08, + 0x66, 0x75, 0x6c, 0x6c, 0x50, 0x61, 0x74, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, + 0x66, 0x75, 0x6c, 0x6c, 0x50, 0x61, 0x74, 0x68, 0x12, 0x2a, 0x0a, 0x10, 0x6d, 0x61, 0x73, 0x74, + 0x65, 0x72, 0x42, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x03, 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, 0x04, 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, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x75, 0x73, 0x65, 0x72, 0x42, 0x72, 0x61, 0x6e, + 0x63, 0x68, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x64, 0x69, 0x72, 0x74, 0x79, 0x18, + 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, 0x64, 0x69, 0x72, 0x74, 0x79, 0x12, 0x10, 0x0a, 0x03, + 0x55, 0x52, 0x4c, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x55, 0x52, 0x4c, 0x12, 0x22, + 0x0a, 0x04, 0x74, 0x61, 0x67, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x67, + 0x69, 0x74, 0x70, 0x62, 0x2e, 0x47, 0x69, 0x74, 0x54, 0x61, 0x67, 0x73, 0x52, 0x04, 0x74, 0x61, + 0x67, 0x73, 0x12, 0x25, 0x0a, 0x05, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x18, 0x09, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x0f, 0x2e, 0x67, 0x69, 0x74, 0x70, 0x62, 0x2e, 0x47, 0x69, 0x74, 0x54, 0x69, 0x6d, + 0x65, 0x73, 0x52, 0x05, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x12, 0x25, 0x0a, 0x06, 0x67, 0x6f, 0x49, + 0x6e, 0x66, 0x6f, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x67, 0x69, 0x74, 0x70, + 0x62, 0x2e, 0x47, 0x6f, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x06, 0x67, 0x6f, 0x49, 0x6e, 0x66, 0x6f, + 0x12, 0x25, 0x0a, 0x06, 0x67, 0x6f, 0x44, 0x65, 0x70, 0x73, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x0d, 0x2e, 0x67, 0x69, 0x74, 0x70, 0x62, 0x2e, 0x47, 0x6f, 0x44, 0x65, 0x70, 0x73, 0x52, + 0x06, 0x67, 0x6f, 0x44, 0x65, 0x70, 0x73, 0x12, 0x2c, 0x0a, 0x11, 0x63, 0x75, 0x72, 0x72, 0x65, + 0x6e, 0x74, 0x42, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x0c, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x11, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x42, 0x72, 0x61, 0x6e, 0x63, + 0x68, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x32, 0x0a, 0x14, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, + 0x42, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x0d, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x14, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x42, 0x72, 0x61, 0x6e, + 0x63, 0x68, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x18, 0x0a, 0x07, 0x6c, 0x61, 0x73, + 0x74, 0x54, 0x61, 0x67, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6c, 0x61, 0x73, 0x74, + 0x54, 0x61, 0x67, 0x12, 0x24, 0x0a, 0x0d, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x56, 0x65, 0x72, + 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x74, 0x61, 0x72, 0x67, + 0x65, 0x74, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x1a, 0x0a, 0x08, 0x72, 0x65, 0x61, + 0x64, 0x4f, 0x6e, 0x6c, 0x79, 0x18, 0x10, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x72, 0x65, 0x61, + 0x64, 0x4f, 0x6e, 0x6c, 0x79, 0x12, 0x12, 0x0a, 0x04, 0x64, 0x65, 0x73, 0x63, 0x18, 0x11, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x04, 0x64, 0x65, 0x73, 0x63, 0x12, 0x20, 0x0a, 0x0b, 0x73, 0x74, 0x61, + 0x74, 0x65, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x18, 0x12, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, + 0x73, 0x74, 0x61, 0x74, 0x65, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x24, 0x0a, 0x0d, 0x6d, + 0x61, 0x73, 0x74, 0x65, 0x72, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x13, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x0d, 0x6d, 0x61, 0x73, 0x74, 0x65, 0x72, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, + 0x6e, 0x12, 0x22, 0x0a, 0x0c, 0x64, 0x65, 0x76, 0x65, 0x6c, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, + 0x6e, 0x18, 0x14, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x64, 0x65, 0x76, 0x65, 0x6c, 0x56, 0x65, + 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x20, 0x0a, 0x0b, 0x75, 0x73, 0x65, 0x72, 0x56, 0x65, 0x72, + 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x15, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x75, 0x73, 0x65, 0x72, + 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x1c, 0x0a, 0x09, 0x64, 0x69, 0x72, 0x74, 0x79, + 0x4c, 0x69, 0x73, 0x74, 0x18, 0x16, 0x20, 0x03, 0x28, 0x09, 0x52, 0x09, 0x64, 0x69, 0x72, 0x74, + 0x79, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x17, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x12, 0x2d, 0x0a, 0x0a, 0x63, + 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x54, 0x61, 0x67, 0x18, 0x18, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x0d, 0x2e, 0x67, 0x69, 0x74, 0x70, 0x62, 0x2e, 0x47, 0x69, 0x74, 0x54, 0x61, 0x67, 0x52, 0x0a, + 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x54, 0x61, 0x67, 0x12, 0x2e, 0x0a, 0x09, 0x67, 0x69, + 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x19, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, + 0x67, 0x69, 0x74, 0x70, 0x62, 0x2e, 0x47, 0x69, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, + 0x09, 0x67, 0x69, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x1e, 0x0a, 0x0a, 0x4d, 0x61, + 0x73, 0x74, 0x65, 0x72, 0x48, 0x61, 0x73, 0x68, 0x18, 0x1a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, + 0x4d, 0x61, 0x73, 0x74, 0x65, 0x72, 0x48, 0x61, 0x73, 0x68, 0x12, 0x1c, 0x0a, 0x09, 0x44, 0x65, + 0x76, 0x65, 0x6c, 0x48, 0x61, 0x73, 0x68, 0x18, 0x1b, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x44, + 0x65, 0x76, 0x65, 0x6c, 0x48, 0x61, 0x73, 0x68, 0x12, 0x32, 0x0a, 0x07, 0x63, 0x6f, 0x6e, 0x74, + 0x72, 0x6f, 0x6c, 0x18, 0x1c, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x67, 0x69, 0x74, 0x70, + 0x62, 0x2e, 0x52, 0x65, 0x70, 0x6f, 0x2e, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x45, 0x6e, + 0x74, 0x72, 0x79, 0x52, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x1a, 0x3a, 0x0a, 0x0c, + 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, + 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, + 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, + 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0xb2, 0x01, 0x0a, 0x05, 0x52, 0x65, 0x70, + 0x6f, 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, 0x21, 0x0a, 0x05, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, + 0x0b, 0x2e, 0x67, 0x69, 0x74, 0x70, 0x62, 0x2e, 0x52, 0x65, 0x70, 0x6f, 0x52, 0x05, 0x72, 0x65, + 0x70, 0x6f, 0x73, 0x12, 0x20, 0x0a, 0x0b, 0x68, 0x61, 0x73, 0x46, 0x75, 0x6c, 0x6c, 0x53, 0x63, + 0x61, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x68, 0x61, 0x73, 0x46, 0x75, 0x6c, + 0x6c, 0x53, 0x63, 0x61, 0x6e, 0x12, 0x36, 0x0a, 0x08, 0x66, 0x75, 0x6c, 0x6c, 0x53, 0x63, 0x61, + 0x6e, 0x18, 0x05, 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, 0x66, 0x75, 0x6c, 0x6c, 0x53, 0x63, 0x61, 0x6e, 0x62, 0x06, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x33, +} + +var ( + file_repo_proto_rawDescOnce sync.Once + file_repo_proto_rawDescData = file_repo_proto_rawDesc +) + +func file_repo_proto_rawDescGZIP() []byte { + file_repo_proto_rawDescOnce.Do(func() { + file_repo_proto_rawDescData = protoimpl.X.CompressGZIP(file_repo_proto_rawDescData) + }) + return file_repo_proto_rawDescData +} + +var file_repo_proto_msgTypes = make([]protoimpl.MessageInfo, 5) +var file_repo_proto_goTypes = []interface{}{ + (*GitTimes)(nil), // 0: gitpb.GitTimes + (*GoInfo)(nil), // 1: gitpb.GoInfo + (*Repo)(nil), // 2: gitpb.Repo + (*Repos)(nil), // 3: gitpb.Repos + nil, // 4: gitpb.Repo.ControlEntry + (*timestamppb.Timestamp)(nil), // 5: google.protobuf.Timestamp + (*GoDeps)(nil), // 6: gitpb.GoDeps + (*GitTags)(nil), // 7: gitpb.GitTags + (*GitTag)(nil), // 8: gitpb.GitTag + (*GitConfig)(nil), // 9: gitpb.GitConfig +} +var file_repo_proto_depIdxs = []int32{ + 5, // 0: gitpb.GitTimes.lastPull:type_name -> google.protobuf.Timestamp + 5, // 1: gitpb.GitTimes.lastUpdate:type_name -> google.protobuf.Timestamp + 5, // 2: gitpb.GitTimes.lastDirty:type_name -> google.protobuf.Timestamp + 5, // 3: gitpb.GitTimes.mtimeDir:type_name -> google.protobuf.Timestamp + 5, // 4: gitpb.GitTimes.mtimeHead:type_name -> google.protobuf.Timestamp + 5, // 5: gitpb.GitTimes.mtimeIndex:type_name -> google.protobuf.Timestamp + 5, // 6: gitpb.GitTimes.mtimeFetch:type_name -> google.protobuf.Timestamp + 5, // 7: gitpb.GitTimes.lastGoDep:type_name -> google.protobuf.Timestamp + 5, // 8: gitpb.GitTimes.newestCommit:type_name -> google.protobuf.Timestamp + 5, // 9: gitpb.GitTimes.mtimeConfig:type_name -> google.protobuf.Timestamp + 6, // 10: gitpb.GoInfo.goDeps:type_name -> gitpb.GoDeps + 6, // 11: gitpb.GoInfo.published:type_name -> gitpb.GoDeps + 7, // 12: gitpb.Repo.tags:type_name -> gitpb.GitTags + 0, // 13: gitpb.Repo.times:type_name -> gitpb.GitTimes + 1, // 14: gitpb.Repo.goInfo:type_name -> gitpb.GoInfo + 6, // 15: gitpb.Repo.goDeps:type_name -> gitpb.GoDeps + 8, // 16: gitpb.Repo.currentTag:type_name -> gitpb.GitTag + 9, // 17: gitpb.Repo.gitConfig:type_name -> gitpb.GitConfig + 4, // 18: gitpb.Repo.control:type_name -> gitpb.Repo.ControlEntry + 2, // 19: gitpb.Repos.repos:type_name -> gitpb.Repo + 5, // 20: gitpb.Repos.fullScan:type_name -> google.protobuf.Timestamp + 21, // [21:21] is the sub-list for method output_type + 21, // [21:21] is the sub-list for method input_type + 21, // [21:21] is the sub-list for extension type_name + 21, // [21:21] is the sub-list for extension extendee + 0, // [0:21] is the sub-list for field type_name +} + +func init() { file_repo_proto_init() } +func file_repo_proto_init() { + if File_repo_proto != nil { + return + } + file_gitTag_proto_init() + file_goDep_proto_init() + if !protoimpl.UnsafeEnabled { + file_repo_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GitTimes); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_repo_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GoInfo); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_repo_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Repo); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_repo_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Repos); 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_repo_proto_rawDesc, + NumEnums: 0, + NumMessages: 5, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_repo_proto_goTypes, + DependencyIndexes: file_repo_proto_depIdxs, + MessageInfos: file_repo_proto_msgTypes, + }.Build() + File_repo_proto = out.File + file_repo_proto_rawDesc = nil + file_repo_proto_goTypes = nil + file_repo_proto_depIdxs = nil +} diff --git a/repo.sort.pb.go b/repo.sort.pb.go new file mode 100644 index 0000000..a2e0fe8 --- /dev/null +++ b/repo.sort.pb.go @@ -0,0 +1,446 @@ +// Code generated by go.wit.com/apps/autogenpb DO NOT EDIT. +// This file was autogenerated with autogenpb v0.5.3-11-g737c5b7 2025.09.16_2337 +// 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 gitpb + +import ( + "fmt" + "iter" + "sort" + "sync" + + "google.golang.org/protobuf/proto" +) + +// a simple global lock +var repoMu sync.RWMutex + +func (x *Repos) fixUuid() { + if x == nil { + return + } + if x.Uuid == "8daaeba1-fb1f-4762-ae6e-95a55d352673" { + return + } + x.Uuid = "8daaeba1-fb1f-4762-ae6e-95a55d352673" + x.Version = "v4 go.wit.com/lib/protobuf/gitpb" +} + +func NewRepos() *Repos { + x := new(Repos) + x.Uuid = "8daaeba1-fb1f-4762-ae6e-95a55d352673" + x.Version = "v4 go.wit.com/lib/protobuf/gitpb" + return x +} + +// START SORT + +// DEFINE THE Repos SCANNER. +// itializes a new scanner. +func newReposScanner(things []*Repos) *ReposScanner { + return &ReposScanner{things: things} +} + +type ReposScanner struct { + sync.Mutex + + things []*Repos + index int +} + +func (it *ReposScanner) 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 *ReposScanner) Next() *Repos { + if it.things[it.index-1] == nil { + fmt.Println("Next() error in ReposScanner", it.index) + } + return it.things[it.index-1] +} + +// END DEFINE THE SCANNER + +// DEFINE THE Repo SCANNER. +// itializes a new scanner. +func newRepoScanner(things []*Repo) *RepoScanner { + return &RepoScanner{things: things} +} + +type RepoScanner struct { + sync.Mutex + + things []*Repo + index int +} + +func (it *RepoScanner) 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 *RepoScanner) Next() *Repo { + if it.things[it.index-1] == nil { + fmt.Println("Next() error in RepoScanner", it.index) + } + return it.things[it.index-1] +} + +// END DEFINE THE SCANNER + +// DEFINE THE GitTimes SCANNER. +// itializes a new scanner. +func newGitTimesScanner(things []*GitTimes) *GitTimesScanner { + return &GitTimesScanner{things: things} +} + +type GitTimesScanner struct { + sync.Mutex + + things []*GitTimes + index int +} + +func (it *GitTimesScanner) 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 *GitTimesScanner) Next() *GitTimes { + if it.things[it.index-1] == nil { + fmt.Println("Next() error in GitTimesScanner", it.index) + } + return it.things[it.index-1] +} + +// END DEFINE THE SCANNER + +// DEFINE THE GoInfo SCANNER. +// itializes a new scanner. +func newGoInfoScanner(things []*GoInfo) *GoInfoScanner { + return &GoInfoScanner{things: things} +} + +type GoInfoScanner struct { + sync.Mutex + + things []*GoInfo + index int +} + +func (it *GoInfoScanner) 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 *GoInfoScanner) Next() *GoInfo { + if it.things[it.index-1] == nil { + fmt.Println("Next() error in GoInfoScanner", it.index) + } + return it.things[it.index-1] +} + +// END DEFINE THE SCANNER + +// sort struct by Namespace +type sortRepoNamespace []*Repo + +func (a sortRepoNamespace) Len() int { return len(a) } +func (a sortRepoNamespace) Less(i, j int) bool { return a[i].Namespace < a[j].Namespace } +func (a sortRepoNamespace) Swap(i, j int) { a[i], a[j] = a[j], a[i] } + +// sort struct by FullPath +type sortRepoFullPath []*Repo + +func (a sortRepoFullPath) Len() int { return len(a) } +func (a sortRepoFullPath) Less(i, j int) bool { return a[i].FullPath < a[j].FullPath } +func (a sortRepoFullPath) Swap(i, j int) { a[i], a[j] = a[j], a[i] } + +// safely returns a slice of pointers to the FRUIT protobufs +func (x *Repos) allRepos() []*Repo { + repoMu.RLock() + defer repoMu.RUnlock() + + // Create a new slice to hold pointers to each FRUIT + var tmp []*Repo + tmp = make([]*Repo, len(x.Repos)) + for i, p := range x.Repos { + tmp[i] = p // Copy pointers for safe iteration + } + + return tmp +} + +// safely returns a slice of pointers to the Repo protobufs +func (x *Repos) selectAllRepos() []*Repo { + repoMu.RLock() + defer repoMu.RUnlock() + + // Create a new slice to hold pointers to each Repo + var tmp []*Repo + tmp = make([]*Repo, len(x.Repos)) + for i, p := range x.Repos { + tmp[i] = p // Copy pointers for safe iteration + } + + return tmp +} +func (x *Repos) SortByNamespace() *RepoScanner { + // copy the pointers as fast as possible. + things := x.selectAllRepos() + + // todo: try slices.SortFunc() instead to see what happens + sort.Sort(sortRepoNamespace(things)) + // slices.SortFunc(things, func(a, b *Repos) bool { + // return a.Namespace < b.Namespace // Sort by ??. let the compiler work it out?? + // }) + return newRepoScanner(things) +} + +// 'for x := range' syntax using the awesome golang 1.24 'iter' +func (x *Repos) IterByNamespace() iter.Seq[*Repo] { + items := x.selectAllRepos() + sort.Sort(sortRepoNamespace(items)) + // log.Println("Made Iter.Seq[] with length", len(items)) + return func(yield func(*Repo) bool) { + for _, v := range items { + if !yield(v) { + return + } + } + } +} +func (x *Repos) SortByFullPath() *RepoScanner { + // copy the pointers as fast as possible. + things := x.selectAllRepos() + + // todo: try slices.SortFunc() instead to see what happens + sort.Sort(sortRepoFullPath(things)) + // slices.SortFunc(things, func(a, b *Repos) bool { + // return a.FullPath < b.FullPath // Sort by ??. let the compiler work it out?? + // }) + return newRepoScanner(things) +} + +// 'for x := range' syntax using the awesome golang 1.24 'iter' +func (x *Repos) IterByFullPath() iter.Seq[*Repo] { + items := x.selectAllRepos() + sort.Sort(sortRepoFullPath(items)) + // log.Println("Made Iter.Seq[] with length", len(items)) + return func(yield func(*Repo) bool) { + for _, v := range items { + if !yield(v) { + return + } + } + } +} + +// END SORT + +func (x *Repos) Len() int { + repoMu.RLock() + defer repoMu.RUnlock() + + return len(x.Repos) +} + +// a Append() shortcut (that does Clone() with a mutex) notsure if it really works +func (x *Repos) Append(y *Repo) *Repo { + repoMu.Lock() + defer repoMu.Unlock() + + z := proto.Clone(y).(*Repo) + x.Repos = append(x.Repos, z) + + return z +} + +func (x *Repos) All() *RepoScanner { + RepoPointers := x.selectAllRepos() + + scanner := newRepoScanner(RepoPointers) + return scanner +} + +// Iterate 'for x := range' syntax using the awesome golang 1.24 'iter' +func (x *Repos) IterAll() iter.Seq[*Repo] { + items := x.selectAllRepos() + // log.Println("Made All() Iter.Seq[] with length", len(items)) + return func(yield func(*Repo) bool) { + for _, v := range items { + if !yield(v) { + return + } + } + } +} +func (x *Repos) Delete(y *Repo) bool { + repoMu.Lock() + defer repoMu.Unlock() + + for i, _ := range x.Repos { + if x.Repos[i] == y { + x.Repos[i] = x.Repos[len(x.Repos)-1] + x.Repos = x.Repos[:len(x.Repos)-1] + return true + } + } + return false +} + +// lookup a Repos by the Namespace +func (x *Repos) FindByNamespace(s string) *Repo { + if x == nil { + return nil + } + + repoMu.RLock() + defer repoMu.RUnlock() + + for i, _ := range x.Repos { + if x.Repos[i].Namespace == s { + return x.Repos[i] + } + } + return nil +} + +// returns a Repo if Namespace matches, otherwise create +func (x *Repos) InsertByNamespace(y string) *Repo { + repoMu.Lock() + defer repoMu.Unlock() + + for _, z := range x.Repos { + if z.Namespace == y { + return z + } + } + + z := new(Repo) + z.Namespace = y + x.Repos = append(x.Repos, z) + return z +} + +// lookup a Repos by the FullPath +func (x *Repos) FindByFullPath(s string) *Repo { + if x == nil { + return nil + } + + repoMu.RLock() + defer repoMu.RUnlock() + + for i, _ := range x.Repos { + if x.Repos[i].FullPath == s { + return x.Repos[i] + } + } + return nil +} + +// returns a Repo if FullPath matches, otherwise create +func (x *Repos) InsertByFullPath(y string) *Repo { + repoMu.Lock() + defer repoMu.Unlock() + + for _, z := range x.Repos { + if z.FullPath == y { + return z + } + } + + z := new(Repo) + z.FullPath = y + x.Repos = append(x.Repos, z) + return z +} + +func (x *Repos) DeleteByNamespace(s string) bool { + repoMu.Lock() + defer repoMu.Unlock() + + for i, _ := range x.Repos { + if x.Repos[i].Namespace == s { + x.Repos[i] = x.Repos[len(x.Repos)-1] + x.Repos = x.Repos[:len(x.Repos)-1] + return true + } + } + return false +} + +func (x *Repos) DeleteByFullPath(s string) bool { + repoMu.Lock() + defer repoMu.Unlock() + + for i, _ := range x.Repos { + if x.Repos[i].FullPath == s { + x.Repos[i] = x.Repos[len(x.Repos)-1] + x.Repos = x.Repos[:len(x.Repos)-1] + return true + } + } + return false +} + +func (x *Repos) AppendByNamespace(y *Repo) bool { + repoMu.Lock() + defer repoMu.Unlock() + + for _, p := range x.Repos { + if p.Namespace == y.Namespace { + return false + } + } + + x.Repos = append(x.Repos, proto.Clone(y).(*Repo)) + return true +} + +func (x *Repos) AppendByFullPath(y *Repo) bool { + repoMu.Lock() + defer repoMu.Unlock() + + for _, p := range x.Repos { + if p.FullPath == y.FullPath { + return false + } + } + + x.Repos = append(x.Repos, proto.Clone(y).(*Repo)) + return true +}