// Copyright 2017-2025 WIT.COM Inc. All rights reserved. // Use of this source code is governed by the GPL 3.0 package main import ( "path/filepath" "go.wit.com/lib/fhelp" "go.wit.com/lib/protobuf/forgepb" "go.wit.com/log" ) func doPatchInit() { if me.forge.Patchsets != nil { if me.forge.Patchsets.Len() == 0 { // log.Info("IGNORE: patches are empty") } else { log.Info("IGNORE: patches already initalized len =", me.forge.Patchsets.Len()) } } if err := me.forge.LoadPatchsets(); err != nil { log.Info("patches failed to open", err) if err := me.forge.SavePatchsets(); err != nil { log.Warn("savePatchsets() failed", err) } } } func isPatchingSafe() bool { if me.forge.Config.Mode == forgepb.ForgeMode_NORMAL { return true } log.Info("forge requres a 'normal' state to work with patches") log.Info("you must run:") log.Info("") log.Info("forge normal") log.Info("") return false } func doPatch() error { if argv.Patch.Repos != nil { dumpDirtyRepos() return nil } if !isPatchingSafe() { return log.Errorf("not safe to work on patches") } if argv.Patch.Submit != nil { pset, err := me.forge.MakeDevelPatchSet("testing") if err != nil { return err } pset.Patches.HttpPostVerbose(myServer(), "new") return nil } if argv.Patch.Get != nil { psets := forgepb.NewPatchsets() newpb, _, _ := psets.HttpPostVerbose(myServer(), "get") newpb.PrintTable() me.forge.Patchsets = newpb me.forge.SavePatchsets() return nil } if argv.Patch.Check != nil { /* old := findExpired() // old.PrintTable() for p := range old.IterAll() { log.Info("patch", p.Filename, p.Namespace) } newpb, err := old.HttpPostVerbose(myServer(), "check") if err != nil { return err } newpb.PrintTable() */ log.Info("do something here to find patches merged to devel") doMergeReport() return nil } if argv.Patch.List != nil { var changed bool newpatches := forgepb.NewPatches() for pset := range me.forge.Patchsets.IterAll() { log.Info(pset.Uuid) for patch := range pset.Patches.IterAll() { if setNewCommitHash(patch) { changed = true } if patch.NewHash == "na" { newpatches.Append(patch) log.Info("apply this patch?") } } /* for patch := range pset.Patches.IterAll() { if repo, ok := me.forge.IsPatchApplied(patch); ok { log.Info("\tfound patch in repo", repo.Namespace, patch.Filename) } else { log.Info("\tdid not find patch", patch.CommitHash, patch.NewHash, patch.Filename) } } */ } if changed { if err := me.forge.SavePatchsets(); err != nil { log.Warn("savePatchsets() failed", err) } } me.forge.Patchsets.PrintTable() if newpatches.Len() != 0 { for patch := range newpatches.IterAll() { log.Info("new patch:", patch.CommitHash, patch.NewHash, patch.Filename) repo := me.forge.FindByGoPath(patch.Namespace) if repo == nil { log.Info("\tCould not find namespace:", patch.Namespace) continue } if fhelp.QuestionUser("apply this patch?") { newhash, err := applyAndTrackPatch(repo, patch) log.Info("apply results:", newhash, err) } } return log.Errorf("patches need to be applied") } // return doPatchList() applied := findApplied() if applied.Len() == 0 { log.Info("no patches have been appled to the devel branch yet") return nil } // for patch := range applied.IterAll() { // log.Info("SEND APPLIED: newhash:", patch.NewHash, "commithash:", patch.CommitHash, "patch", patch.Namespace) // } newpb, _, err := applied.HttpPostVerbose(myServer(), "applied") if err != nil { return err } newpb.PrintTable() return nil } // if nothing, show patches & dirty repos me.forge.Patchsets.PrintTable() dumpDirtyRepos() return nil } func dumpDirtyRepos() { // always run dirty first me.forge.CheckDirtyQuiet() // if no option is given to patch, list out the // repos that have patches ready in them found := findReposWithPatches() if found.Len() == 0 { log.Info("you currently have no repos with patches") } else { me.forge.PrintHumanTable(found) } } // returns bad if patches can not be applied // logic is not great here but it was a first pass func dumpPatchset(pset *forgepb.Patchset) bool { // don't even bother to continue if we already know it's broken if pset.State == "BROKEN" { log.Printf("Patchset Name: %-24s Author: %s <%s> IS BAD\n", pset.Name, pset.GetGitAuthorName(), pset.GetGitAuthorEmail()) return false } else { log.Printf("Patchset Name: %-24s Author: %s <%s> IS GOOD\n", pset.Name, pset.GetGitAuthorName(), pset.GetGitAuthorEmail()) } var count int var bad int all := pset.Patches.SortByFilename() for all.Scan() { p := all.Next() if IsValidPatch(p) { // ok } else { pset.State = "BROKEN" bad += 1 } count += 1 } log.Info("pset has", count, "total patches, ", bad, "bad patches") if bad == 0 { return true } return false } func IsValidPatch(p *forgepb.Patch) bool { basepath, filename := filepath.Split(p.Filename) repo := me.forge.FindByGoPath(basepath) if argv.Verbose { log.Info("start:", p.StartHash, "end:", p.CommitHash, "file:", basepath, filename, "devel version", repo.GetDevelVersion()) } if repo == nil { log.Info("can not apply patch! repo not found", basepath, filename) return false } if repo.ActualDevelHash() != p.StartHash { log.Info("can not apply patch! devel hash mismatch", basepath, filename) return false } if repo.ActualDevelHash() == p.StartHash { log.Info("local devel hash:", repo.ActualDevelHash(), "matches patch hash", p.StartHash, "and can be applied") } log.Info("start:", p.StartHash, "end:", p.CommitHash, "file:", basepath, filename, "devel version", repo.GetDevelVersion()) for _, line := range p.Files { log.Info("\t", line) } return true }