package forgepb import ( "fmt" "os" "path/filepath" "regexp" "strings" "github.com/google/uuid" "go.wit.com/lib/protobuf/gitpb" "go.wit.com/log" "google.golang.org/protobuf/proto" ) func (f *Forge) LoadPatchsets() error { f.Patchsets = NewPatchsets() filename := filepath.Join(f.patchDir, "all-patches.pb") data, err := os.ReadFile(filename) if err != nil { return err } err = f.Patchsets.Unmarshal(data) if err != nil { log.Infof("LoadPatchsets() proto.Marshal() error %v\n", err) return err } // log.Infof("LoadPatchsets() found %d patches.\n", f.Patchsets.Len()) return nil } func (f *Forge) InitPatchsets() error { if err := f.LoadPatchsets(); err == nil { return nil } else { log.Info("LoadPatchsets() failed", err) } // TODO: check if Unmarshal failed here f.Patchsets = NewPatchsets() f.findAutoPatchset() // adds the default values return f.SavePatchsets() } func (f *Forge) SavePatchsets() error { filename := filepath.Join(f.patchDir, "all-patches.pb") regfile, err := os.OpenFile(filename, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0666) if err != nil { log.Info("SavePatchsets() filename open error:", filename, err) // fmt.Fprintln(w, "filename open error:", filename, err) return err } defer regfile.Close() newpb := proto.Clone(f.Patchsets).(*Patchsets) if newpb == nil { for pset := range f.Patchsets.IterAll() { pset.ShowPatchsets() } return log.Errorf("SavePatchsets() Clone failed!") } data, err := newpb.Marshal() if err != nil { log.Infof("SavePatchset() proto.Marshal() error %v\n", err) return err } log.Infof("SavePatchset() worked (%d) bytes on %d patches\n", len(data), f.Patchsets.Len()) regfile.Write(data) return nil } func cleanSubject(line string) string { // Regular expression to remove "Subject:" and "[PATCH...]" patterns re := regexp.MustCompile(`(?i)^Subject:\s*(\[\s*PATCH[^\]]*\]\s*)?`) cleaned := re.ReplaceAllString(line, "") return strings.TrimSpace(cleaned) } func (pb *Patchset) ShowPatchsets() error { author := "Author: " + pb.GitAuthorName author += " <" + pb.GitAuthorEmail + ">" log.Printf("%-16s %s %s %s\n", string(pb.Uuid)[0:8], pb.Name, pb.Comment, author) for _, patch := range pb.Patches.Patches { comment := cleanSubject(patch.Comment) log.Printf("\t%-8s %-50s %-50s\n", string(patch.CommitHash)[0:8], patch.Namespace, comment) } /* for patch := range pb.IterAll() { comment := cleanSubject(patch.Comment) log.Info("\tnew patch:", patch.NewHash, "commithash:", patch.CommitHash, patch.Namespace, comment) } */ return nil } // adds a patch. returns true if patch is new func (f *Forge) AddPatch(patch *Patch) bool { if f.findPatch(patch) { // log.Info("\talready found!!!!!!!", pset.Uuid, patch.Namespace) return false } if f.AddNewPatch(patch) { log.Info("\tnew patch added:", patch.CommitHash, patch.Gs, patch.Gae, patch.Gan) return true } log.Info("\tnew patch failed:", patch.CommitHash, patch.Gs) return false } // adds a patchset or just the patches func (f *Forge) AddPatchset(pb *Patchset) bool { var changed bool // if the name of the patchset is "forge auto commit" // then just add all the patches if pb.Name == "forge auto commit" { author := "Author: " + pb.GitAuthorName author += " <" + pb.GitAuthorEmail + ">" fmt.Println(pb.Name, pb.Comment, author) for _, patch := range pb.Patches.Patches { // log.Info("\tnew patch:", i, patch.CommitHash, patch.Namespace) if f.findPatch(patch) { // log.Info("\talready found!!!!!!!", pset.Uuid, patch.Namespace) } else { if f.AddNewPatch(patch) { log.Info("\tnew patch added:", patch.CommitHash, pb.Name, pb.Comment, author) changed = true } else { log.Info("\tnew patch failed:", patch.CommitHash, pb.Name, pb.Comment, author) } } } return changed } // if you got here, this patchset was submitted with a name // Has this patchset already been submitted? for pset := range f.Patchsets.IterAll() { if pset.Uuid == pb.Uuid { log.Info("ALREADY ADDED", pset.Uuid, pset.Name) return false } else { } } // Clone() this protobuf into me.forge.Patchsets var newpb *Patchset newpb = proto.Clone(pb).(*Patchset) if newpb != nil { f.Patchsets.Patchsets = append(f.Patchsets.Patchsets, newpb) } return true } func (f *Forge) findAutoPatchset() *Patchset { for pset := range f.Patchsets.IterAll() { if pset.Name == "forge auto commit" { return pset } } var fauto *Patchset log.Warn("findAutoPatchset() had to create 'forge auto commit'") if fauto == nil { fauto = makeDefaultPatchset() f.Patchsets.Append(fauto) } return fauto } func makeDefaultPatchset() *Patchset { fauto := new(Patchset) fauto.Name = "forge auto commit" fauto.Patches = NewPatches() fauto.Uuid = uuid.New().String() return fauto } // adds submitted patches not // If the patch was actually new, return true func (f *Forge) AddNewPatch(patch *Patch) bool { // ignore patch if it's already here if f.findPatch(patch) { log.Info("already found patch", patch.CommitHash, patch.Namespace) return false } fauto := f.findAutoPatchset() if fauto == nil { // should have made the default patchset return false } fauto.Patches.Append(patch) return true } // returns true if the patch already exists in the protobuf func (f *Forge) findPatch(newpatch *Patch) bool { // log.Info("\tlook for patch:", newpatch.CommitHash, newpatch.Namespace) for pset := range f.Patchsets.IterAll() { for _, patch := range pset.Patches.Patches { if patch.CommitHash == newpatch.CommitHash { // log.Info("\tfound pset!!!!!!", pset.Uuid, patch.Namespace) return true } } } return false } func (f *Forge) IsPatchApplied(newpatch *Patch) (*gitpb.Repo, bool) { log.Info("todo: find namespace and repo for patch", newpatch.Filename) if f.findPatch(newpatch) { log.Info("\tfindPatch() patch was found") } else { log.Info("\tfindPatch() patch was not found") } return nil, false }