From f95aa661cb745d97c4cbe8a6eadb7b8307787e0f Mon Sep 17 00:00:00 2001 From: Michal Gorecki Date: Wed, 27 Mar 2024 10:44:31 +0100 Subject: [PATCH] newt: Add external repos patches support Now if package that adds external repository contains directory patches/*external_repo_name*, newt will try to apply patches inside this directory to the external repo. --- newt/cli/project_cmds.go | 1 + newt/downloader/downloader.go | 24 ++++++++++++++++++++++++ newt/install/install.go | 10 ++++++++++ newt/project/project.go | 32 ++++++++++++++++++++++++++++++-- newt/repo/repo.go | 18 ++++++++++++++++++ 5 files changed, 83 insertions(+), 2 deletions(-) diff --git a/newt/cli/project_cmds.go b/newt/cli/project_cmds.go index 92d40a574..9a742462e 100644 --- a/newt/cli/project_cmds.go +++ b/newt/cli/project_cmds.go @@ -131,6 +131,7 @@ func upgradeRunCmd(cmd *cobra.Command, args []string) { interfaces.SetProject(proj) proj.GetPkgRepos() + proj.SetGitEnvVariables() pred := makeRepoPredicate(args) if err := proj.UpgradeIf( diff --git a/newt/downloader/downloader.go b/newt/downloader/downloader.go index eea3249a8..2be323a14 100644 --- a/newt/downloader/downloader.go +++ b/newt/downloader/downloader.go @@ -97,6 +97,10 @@ type Downloader interface { // If such a commit exists, it is returned. Otherwise, "" is returned. LatestRc(path string, base string) (string, error) + // Applies patches provided inside "patches" directory. + // If no patch is provided function does nothing + ApplyPatches(path string, patches []string) error + // Returns the branch that contains the YAML control files; this option // allows implementers to override "master" as the main branch. MainBranch() string @@ -451,6 +455,26 @@ func (gd *GenericDownloader) Checkout(repoDir string, commit string) error { return err } +func (gd *GenericDownloader) ApplyPatches(repoDir string, patches []string) error { + cmd := []string{ + "am", + } + cmd = append(cmd, patches...) + + _, err := executeGitCommand(repoDir, cmd, true) + if err != nil { + // Abort git am if applying patches failed + cmd = []string{ + "am", + "--abort", + } + executeGitCommand(repoDir, cmd, true) + + return err + } + return nil +} + // Update one submodule tree in a repo (under path) func (gd *GenericDownloader) UpdateSubmodule(path string, submodule string) error { cmd := []string{ diff --git a/newt/install/install.go b/newt/install/install.go index 8eebff098..aa63fd657 100644 --- a/newt/install/install.go +++ b/newt/install/install.go @@ -602,6 +602,16 @@ func (inst *Installer) Upgrade(candidates []*repo.Repo, force bool, r.Name(), destVer.String()) } + for _, r := range candidates { + err = r.ApplyPatches() + if err != nil { + util.StatusMessage(util.VERBOSITY_DEFAULT, + "Applying patches in repository %s failed\n", r.Name()) + + return err + } + } + return nil } diff --git a/newt/project/project.go b/newt/project/project.go index 78651f572..b285e6644 100644 --- a/newt/project/project.go +++ b/newt/project/project.go @@ -44,6 +44,7 @@ import ( var globalProject *Project = nil const PROJECT_FILE_NAME = "project.yml" +const PATCHES_DIR = "patches" var ignoreSearchDirs []string = []string{ "bin", @@ -95,7 +96,7 @@ func initProject(dir string, download bool) error { if download { err = globalProject.UpgradeIf(newtutil.NewtForce, newtutil.NewtAsk, - func(r *repo.Repo) bool { return !r.IsExternal(r.Path()) }) + func(r *repo.Repo) bool { return !r.IsExternal(r.Path()) }) if err != nil { return err } @@ -182,7 +183,6 @@ func (proj *Project) isRepoAdded(r *repo.Repo) bool { } func (proj *Project) GetPkgRepos() error { - for _, pkgList := range proj.packages { for _, pkg := range *pkgList { if pkg.PkgConfig().HasKey("repository") { @@ -215,6 +215,21 @@ func (proj *Project) GetPkgRepos() error { } proj.rootRepoReqs[repoName] = verReq } + + if _, err := os.Stat(pkg.BasePath() + "/" + PATCHES_DIR + "/" + r.Name()); os.IsNotExist(err) { + continue + } else { + dirEntries, err := os.ReadDir(pkg.BasePath() + "/" + PATCHES_DIR + "/" + r.Name()) + if err != nil { + return err + } + + for _, e := range dirEntries { + if strings.HasSuffix(e.Name(), ".patch") { + r.AddPatch(pkg.BasePath() + "/" + PATCHES_DIR + "/" + r.Name() + "/" + e.Name()) + } + } + } } } } @@ -223,6 +238,19 @@ func (proj *Project) GetPkgRepos() error { return nil } +func (proj *Project) SetGitEnvVariables() error { + err := os.Setenv("GIT_COMMITTER_NAME", "newt") + if err != nil { + return err + } + + err = os.Setenv("GIT_COMMITTER_EMAIL", "dev@mynewt.apache.org") + if err != nil { + return err + } + return nil +} + func (proj *Project) Path() string { return proj.BasePath } diff --git a/newt/repo/repo.go b/newt/repo/repo.go index e1b5e6e04..791656714 100644 --- a/newt/repo/repo.go +++ b/newt/repo/repo.go @@ -44,6 +44,7 @@ const REPO_DEFAULT_PERMS = 0755 const REPO_FILE_NAME = "repository.yml" const REPOS_DIR = "repos" +const PATCHES_DIR = "patches" type Repo struct { name string @@ -76,6 +77,10 @@ type Repo struct { hasSubmodules bool submodules []string + + // Used with external repos. If package that adds external repository provides patches for it, + // the paths to them are going to be stored here. + patches []string } type RepoDependency struct { @@ -124,6 +129,19 @@ func (r *Repo) Downloader() downloader.Downloader { return r.downloader } +func (r *Repo) AddPatch(path string) { + r.patches = append(r.patches, path) +} + +func (r *Repo) ApplyPatches() error { + if len(r.patches) == 0 { + return nil + } + + err := r.Downloader().ApplyPatches(r.Path(), r.patches) + return err +} + func (repo *Repo) FilteredSearchList( curPath string, searchedMap map[string]struct{}) ([]string, error) {