From 706f4686b8eeced9fbd9634ead9a7eef47395610 Mon Sep 17 00:00:00 2001 From: Ivan Maximov Date: Wed, 1 Feb 2023 00:42:41 +0300 Subject: [PATCH 001/434] Fix typo in storage.en-us.md (#22694) --- docs/content/doc/packages/storage.en-us.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/content/doc/packages/storage.en-us.md b/docs/content/doc/packages/storage.en-us.md index b04a7595f74bd..8b05b8a45fb4b 100644 --- a/docs/content/doc/packages/storage.en-us.md +++ b/docs/content/doc/packages/storage.en-us.md @@ -71,7 +71,7 @@ The patterns are case-insensitive which matches the behaviour of the package reg ### How the cleanup rules work -The cleanup rules are part of the [clean up job]({{< relref "doc/advanced/config-cheat-sheet.en-us.md#cron---cleanup-expired-packages-croncleanup_packages" >}}) and run periodicly. +The cleanup rules are part of the [clean up job]({{< relref "doc/advanced/config-cheat-sheet.en-us.md#cron---cleanup-expired-packages-croncleanup_packages" >}}) and run periodically. The cleanup rule: From 66877aed5439de3b26510bc0d45e434510be598b Mon Sep 17 00:00:00 2001 From: Ivan Maximov Date: Wed, 1 Feb 2023 00:43:12 +0300 Subject: [PATCH 002/434] Fix typo in guidelines-backend.en-us.md (#22690) --- docs/content/doc/developers/guidelines-backend.en-us.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/content/doc/developers/guidelines-backend.en-us.md b/docs/content/doc/developers/guidelines-backend.en-us.md index 913898be83dbb..f35111522fa63 100644 --- a/docs/content/doc/developers/guidelines-backend.en-us.md +++ b/docs/content/doc/developers/guidelines-backend.en-us.md @@ -54,7 +54,7 @@ To maintain understandable code and avoid circular dependencies it is important ### Package Dependencies -Since Golang don't support import cycles, we have to decide the package dependencies carefully. There are some levels between those packages. Below is the ideal package dependencies direction. +Since Golang doesn't support import cycles, we have to decide the package dependencies carefully. There are some levels between those packages. Below is the ideal package dependencies direction. `cmd` -> `routers` -> `services` -> `models` -> `modules` From f518b42d4c165cf52d5efdcaa362044a2507c5d2 Mon Sep 17 00:00:00 2001 From: Ivan Maximov Date: Wed, 1 Feb 2023 00:43:27 +0300 Subject: [PATCH 003/434] Fix typo in linked-references.en-us.md (#22682) --- docs/content/doc/usage/linked-references.en-us.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/content/doc/usage/linked-references.en-us.md b/docs/content/doc/usage/linked-references.en-us.md index bb40acdcd089e..df2813792868a 100644 --- a/docs/content/doc/usage/linked-references.en-us.md +++ b/docs/content/doc/usage/linked-references.en-us.md @@ -24,7 +24,7 @@ in search for references. These references will be shown as links in the Issue V and, in some cases, produce certain _actions_. Likewise, commit messages are parsed when they are listed, and _actions_ -are can be triggered when they are pushed to the main branch. +can be triggered when they are pushed to the main branch. To prevent the creation of unintended references, there are certain rules for them to be recognized. For example, they should not be included inside code From 519939fa8c325bf2112286a652fed3256051b260 Mon Sep 17 00:00:00 2001 From: Ivan Maximov Date: Wed, 1 Feb 2023 00:43:39 +0300 Subject: [PATCH 004/434] Fix typo in command-line.en-us.md (#22681) Co-authored-by: Lunny Xiao --- docs/content/doc/usage/command-line.en-us.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/content/doc/usage/command-line.en-us.md b/docs/content/doc/usage/command-line.en-us.md index 5f05bc4c3be3e..d9d397df31b3d 100644 --- a/docs/content/doc/usage/command-line.en-us.md +++ b/docs/content/doc/usage/command-line.en-us.md @@ -382,7 +382,7 @@ Currently there are a check list below: Sometimes if you moved or renamed your Gitea binary when upgrade and you haven't run `Update the '.ssh/authorized_keys' file with Gitea SSH keys. (Not needed for the built-in SSH server.)` on your Admin Panel. Then all pull/push via SSH will not be work. This check will help you to check if it works well. -For contributors, if you want to add more checks, you can wrie ad new function like `func(ctx *cli.Context) ([]string, error)` and +For contributors, if you want to add more checks, you can write a new function like `func(ctx *cli.Context) ([]string, error)` and append it to `doctor.go`. ```go From f1f0430f9fd731310713ad723bed9618bcd53cda Mon Sep 17 00:00:00 2001 From: zeripath Date: Tue, 31 Jan 2023 22:10:54 +0000 Subject: [PATCH 005/434] Add Contributed backport command (#22643) This PR provides a contributed backport command to help create backports for Gitea. It represents a significant improvement on my previously described shell-script. It can be installed using `go install contrib/backport/backport.go`. Signed-off-by: Andrew Thornton --- CONTRIBUTING.md | 20 +- contrib/backport/README | 41 ++++ contrib/backport/backport.go | 438 +++++++++++++++++++++++++++++++++++ 3 files changed, 481 insertions(+), 18 deletions(-) create mode 100644 contrib/backport/README create mode 100644 contrib/backport/backport.go diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index fbf2a331dd480..7a23448e0ab55 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -267,26 +267,10 @@ with the rest of the summary matching the original PR. Similarly for frontports --- -The below is a script that may be helpful in creating backports. YMMV. +A command to help create backports can be found in `contrib/backport` and can be installed (from inside the gitea repo root directory) using: ```bash -#!/bin/sh -PR="$1" -SHA="$2" -VERSION="$3" - -if [ -z "$SHA" ]; then - SHA=$(gh api /repos/go-gitea/gitea/pulls/$PR -q '.merge_commit_sha') -fi - -if [ -z "$VERSION" ]; then - VERSION="v1.16" -fi - -echo git checkout origin/release/"$VERSION" -b backport-$PR-$VERSION -git checkout origin/release/"$VERSION" -b backport-$PR-$VERSION -git cherry-pick $SHA && git commit --amend && git push zeripath backport-$PR-$VERSION && xdg-open https://github.com/go-gitea/gitea/compare/release/"$VERSION"...zeripath:backport-$PR-$VERSION - +go install contrib/backport/backport.go ``` ## Developer Certificate of Origin (DCO) diff --git a/contrib/backport/README b/contrib/backport/README new file mode 100644 index 0000000000000..1e84c1bb9743f --- /dev/null +++ b/contrib/backport/README @@ -0,0 +1,41 @@ +`backport` +========== + +`backport` is a command to help create backports of PRs. It backports a +provided PR from main on to a released version. + +It will create a backport branch, cherry-pick the PR's merge commit, adjust +the commit message and then push this back up to your fork's remote. + +The default version will read from `docs/config.yml`. You can override this +using the option `--version`. + +The upstream branches will be fetched, using the remote `origin`. This can +be overrided using `--upstream`, and fetching can be avoided using +`--no-fetch`. + +By default the branch created will be called `backport-$PR-$VERSION`. You +can override this using the option `--backport-branch`. This branch will +be created from `--release-branch` which is `release/$(VERSION)` +by default and will be pulled from `$(UPSTREAM)`. + +The merge-commit as determined by the github API will be used as the SHA to +cherry-pick. You can override this using `--cherry-pick`. + +The commit message will be amended to add the `Backport` header. +`--no-amend-message` can be set to stop this from happening. + +If cherry-pick is successful the backported branch will be pushed up to your +fork using your remote. These will be determined using `git remote -v`. You +can set your fork name using `--fork-user` and your remote name using +`--remote`. You can avoid pushing using `--no-push`. + +If the push is successful, `xdg-open` will be called to open a backport url. +You can stop this using `--no-xdg-open`. + +Installation +============ + +```bash +go install contrib/backport/backport.go +``` diff --git a/contrib/backport/backport.go b/contrib/backport/backport.go new file mode 100644 index 0000000000000..c35bf9e30f67e --- /dev/null +++ b/contrib/backport/backport.go @@ -0,0 +1,438 @@ +// Copyright 2023 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package main + +import ( + "context" + "fmt" + "log" + "net/http" + "os" + "os/exec" + "os/signal" + "path" + "strconv" + "strings" + "syscall" + + "github.com/google/go-github/v45/github" + "github.com/urfave/cli" + "gopkg.in/yaml.v3" +) + +const defaultVersion = "v1.18" // to backport to + +func main() { + app := cli.NewApp() + app.Name = "backport" + app.Usage = "Backport provided PR-number on to the current or previous released version" + app.Description = `Backport will look-up the PR in Gitea's git log and attempt to cherry-pick it on the current version` + app.ArgsUsage = "" + + app.Flags = []cli.Flag{ + cli.StringFlag{ + Name: "version", + Usage: "Version branch to backport on to", + }, + cli.StringFlag{ + Name: "upstream", + Value: "origin", + Usage: "Upstream remote for the Gitea upstream", + }, + cli.StringFlag{ + Name: "release-branch", + Value: "", + Usage: "Release branch to backport on. Will default to release/", + }, + cli.StringFlag{ + Name: "cherry-pick", + Usage: "SHA to cherry-pick as backport", + }, + cli.StringFlag{ + Name: "backport-branch", + Usage: "Backport branch to backport on to (default: backport--", + }, + cli.StringFlag{ + Name: "remote", + Value: "", + Usage: "Remote for your fork of the Gitea upstream", + }, + cli.StringFlag{ + Name: "fork-user", + Value: "", + Usage: "Forked user name on Github", + }, + cli.BoolFlag{ + Name: "no-fetch", + Usage: "Set this flag to prevent fetch of remote branches", + }, + cli.BoolFlag{ + Name: "no-amend-message", + Usage: "Set this flag to prevent automatic amendment of the commit message", + }, + cli.BoolFlag{ + Name: "no-push", + Usage: "Set this flag to prevent pushing the backport up to your fork", + }, + cli.BoolFlag{ + Name: "no-xdg-open", + Usage: "Set this flag to not use xdg-open to open the PR URL", + }, + } + cli.AppHelpTemplate = `NAME: + {{.Name}} - {{.Usage}} +USAGE: + {{.HelpName}} {{if .VisibleFlags}}[options]{{end}} {{if .ArgsUsage}}{{.ArgsUsage}}{{else}}[arguments...]{{end}} + {{if len .Authors}} +AUTHOR: + {{range .Authors}}{{ . }}{{end}} + {{end}}{{if .Commands}} +OPTIONS: + {{range .VisibleFlags}}{{.}} + {{end}}{{end}} +` + + app.Action = runBackport + + if err := app.Run(os.Args); err != nil { + fmt.Fprintf(os.Stderr, "Unable to backport: %v\n", err) + } +} + +func runBackport(c *cli.Context) error { + ctx, cancel := installSignals() + defer cancel() + + version := c.String("version") + if version == "" { + version = readVersion() + } + if version == "" { + version = defaultVersion + } + + upstream := c.String("upstream") + if upstream == "" { + upstream = "origin" + } + + forkUser := c.String("fork-user") + remote := c.String("remote") + if remote == "" && !c.Bool("--no-push") { + var err error + remote, forkUser, err = determineRemote(ctx, forkUser) + if err != nil { + return err + } + } + + upstreamReleaseBranch := c.String("release-branch") + if upstreamReleaseBranch == "" { + upstreamReleaseBranch = path.Join("release", version) + } + + localReleaseBranch := path.Join(upstream, upstreamReleaseBranch) + + args := c.Args() + if len(args) == 0 { + return fmt.Errorf("no PR number provided\nProvide a PR number to backport") + } else if len(args) != 1 { + return fmt.Errorf("multiple PRs provided %v\nOnly a single PR can be backported at a time", args) + } + + pr := args[0] + + backportBranch := c.String("backport-branch") + if backportBranch == "" { + backportBranch = "backport-" + pr + "-" + version + } + + fmt.Printf("* Backporting %s to %s as %s\n", pr, localReleaseBranch, backportBranch) + + sha := c.String("cherry-pick") + if sha == "" { + var err error + sha, err = determineSHAforPR(ctx, pr) + if err != nil { + return err + } + } + if sha == "" { + return fmt.Errorf("unable to determine sha for cherry-pick of %s", pr) + } + + if !c.Bool("no-fetch") { + if err := fetchRemoteAndMain(ctx, upstream, upstreamReleaseBranch); err != nil { + return err + } + } + + if err := checkoutBackportBranch(ctx, backportBranch, localReleaseBranch); err != nil { + return err + } + + if err := cherrypick(ctx, sha); err != nil { + return err + } + + if !c.Bool("no-amend-message") { + if err := amendCommit(ctx, pr); err != nil { + return err + } + } + + if !c.Bool("no-push") { + url := "https://github.com/go-gitea/gitea/compare/" + upstreamReleaseBranch + "..." + forkUser + ":" + backportBranch + + if err := gitPushUp(ctx, remote, backportBranch); err != nil { + return err + } + + if !c.Bool("no-xdg-open") { + if err := xdgOpen(ctx, url); err != nil { + return err + } + } else { + fmt.Printf("* Navigate to %s to open PR\n", url) + } + } + return nil +} + +func xdgOpen(ctx context.Context, url string) error { + fmt.Printf("* `xdg-open %s`\n", url) + out, err := exec.CommandContext(ctx, "xdg-open", url).Output() + if err != nil { + fmt.Fprintf(os.Stderr, "%s", string(out)) + return fmt.Errorf("unable to xdg-open to %s: %w", url, err) + } + return nil +} + +func gitPushUp(ctx context.Context, remote, backportBranch string) error { + fmt.Printf("* `git push -u %s %s`\n", remote, backportBranch) + out, err := exec.CommandContext(ctx, "git", "push", "-u", remote, backportBranch).Output() + if err != nil { + fmt.Fprintf(os.Stderr, "%s", string(out)) + return fmt.Errorf("unable to push up to %s: %w", remote, err) + } + return nil +} + +func amendCommit(ctx context.Context, pr string) error { + fmt.Printf("* Amending commit to prepend `Backport #%s` to body\n", pr) + out, err := exec.CommandContext(ctx, "git", "log", "-1", "--pretty=format:%B").Output() + if err != nil { + fmt.Fprintf(os.Stderr, "%s", string(out)) + return fmt.Errorf("unable to get last log message: %w", err) + } + + parts := strings.SplitN(string(out), "\n", 2) + + if len(parts) != 2 { + return fmt.Errorf("unable to interpret log message:\n%s", string(out)) + } + subject, body := parts[0], parts[1] + if !strings.HasSuffix(subject, " (#"+pr+")") { + subject = subject + " (#" + pr + ")" + } + + out, err = exec.CommandContext(ctx, "git", "commit", "--amend", "-m", subject+"\n\nBackport #"+pr+"\n"+body).Output() + if err != nil { + fmt.Fprintf(os.Stderr, "%s", string(out)) + return fmt.Errorf("unable to amend last log message: %w", err) + } + return nil +} + +func cherrypick(ctx context.Context, sha string) error { + // Check if a CHERRY_PICK_HEAD exists + if _, err := os.Stat(".git/CHERRY_PICK_HEAD"); err == nil { + // Assume that we are in the middle of cherry-pick - continue it + fmt.Println("* Attempting git cherry-pick --continue") + out, err := exec.CommandContext(ctx, "git", "cherry-pick", "--continue").Output() + if err != nil { + fmt.Fprintf(os.Stderr, "git cherry-pick --continue failed:\n%s\n", string(out)) + return fmt.Errorf("unable to continue cherry-pick: %w", err) + } + return nil + } + + fmt.Printf("* Attempting git cherry-pick %s\n", sha) + out, err := exec.CommandContext(ctx, "git", "cherry-pick", sha).Output() + if err != nil { + fmt.Fprintf(os.Stderr, "git cherry-pick %s failed:\n%s\n", sha, string(out)) + return fmt.Errorf("git cherry-pick %s failed: %w", sha, err) + } + return nil +} + +func checkoutBackportBranch(ctx context.Context, backportBranch, releaseBranch string) error { + out, err := exec.CommandContext(ctx, "git", "branch", "--show-current").Output() + if err != nil { + return fmt.Errorf("unable to check current branch %w", err) + } + + currentBranch := strings.TrimSpace(string(out)) + fmt.Printf("* Current branch is %s\n", currentBranch) + if currentBranch == backportBranch { + fmt.Printf("* Current branch is %s - not checking out\n", currentBranch) + return nil + } + + if _, err := exec.CommandContext(ctx, "git", "rev-list", "-1", backportBranch).Output(); err == nil { + fmt.Printf("* Branch %s already exists. Checking it out...\n", backportBranch) + return exec.CommandContext(ctx, "git", "checkout", "-f", backportBranch).Run() + } + + fmt.Printf("* `git checkout -b %s %s`\n", backportBranch, releaseBranch) + return exec.CommandContext(ctx, "git", "checkout", "-b", backportBranch, releaseBranch).Run() +} + +func fetchRemoteAndMain(ctx context.Context, remote, releaseBranch string) error { + fmt.Printf("* `git fetch %s main`\n", remote) + out, err := exec.CommandContext(ctx, "git", "fetch", remote, "main").Output() + if err != nil { + fmt.Println(string(out)) + return fmt.Errorf("unable to fetch %s from %s: %w", "main", remote, err) + } + fmt.Println(string(out)) + + fmt.Printf("* `git fetch %s %s`\n", remote, releaseBranch) + out, err = exec.CommandContext(ctx, "git", "fetch", remote, releaseBranch).Output() + if err != nil { + fmt.Println(string(out)) + return fmt.Errorf("unable to fetch %s from %s: %w", releaseBranch, remote, err) + } + fmt.Println(string(out)) + + return nil +} + +func determineRemote(ctx context.Context, forkUser string) (string, string, error) { + out, err := exec.CommandContext(ctx, "git", "remote", "-v").Output() + if err != nil { + fmt.Fprintf(os.Stderr, "Unable to list git remotes:\n%s\n", string(out)) + return "", "", fmt.Errorf("unable to determine forked remote: %w", err) + } + lines := strings.Split(string(out), "\n") + for _, line := range lines { + fields := strings.Split(line, "\t") + name, remote := fields[0], fields[1] + // only look at pushers + if !strings.HasSuffix(remote, " (push)") { + continue + } + // only look at github.com pushes + if !strings.Contains(remote, "github.com") { + continue + } + // ignore go-gitea/gitea + if strings.Contains(remote, "go-gitea/gitea") { + continue + } + if !strings.Contains(remote, forkUser) { + continue + } + if strings.HasPrefix(remote, "git@github.com:") { + forkUser = strings.TrimPrefix(remote, "git@github.com:") + } else if strings.HasPrefix(remote, "https://github.com/") { + forkUser = strings.TrimPrefix(remote, "https://github.com/") + } else if strings.HasPrefix(remote, "https://www.github.com/") { + forkUser = strings.TrimPrefix(remote, "https://www.github.com/") + } else if forkUser == "" { + return "", "", fmt.Errorf("unable to extract forkUser from remote %s: %s", name, remote) + } + idx := strings.Index(forkUser, "/") + if idx >= 0 { + forkUser = forkUser[:idx] + } + return name, forkUser, nil + } + return "", "", fmt.Errorf("unable to find appropriate remote in:\n%s", string(out)) +} + +func readVersion() string { + bs, err := os.ReadFile("docs/config.yaml") + if err != nil { + if err == os.ErrNotExist { + log.Println("`docs/config.yaml` not present") + return "" + } + fmt.Fprintf(os.Stderr, "Unable to read `docs/config.yaml`: %v\n", err) + return "" + } + + type params struct { + Version string + } + type docConfig struct { + Params params + } + dc := &docConfig{} + if err := yaml.Unmarshal(bs, dc); err != nil { + fmt.Fprintf(os.Stderr, "Unable to read `docs/config.yaml`: %v\n", err) + return "" + } + + if dc.Params.Version == "" { + fmt.Fprintf(os.Stderr, "No version in `docs/config.yaml`") + return "" + } + + version := dc.Params.Version + if version[0] != 'v' { + version = "v" + version + } + + split := strings.SplitN(version, ".", 3) + + return strings.Join(split[:2], ".") +} + +func determineSHAforPR(ctx context.Context, prStr string) (string, error) { + prNum, err := strconv.Atoi(prStr) + if err != nil { + return "", err + } + + client := github.NewClient(http.DefaultClient) + + pr, _, err := client.PullRequests.Get(ctx, "go-gitea", "gitea", prNum) + if err != nil { + return "", err + } + + if pr.Merged == nil || !*pr.Merged { + return "", fmt.Errorf("PR #%d is not yet merged - cannot determine sha to backport", prNum) + } + + if pr.MergeCommitSHA != nil { + return *pr.MergeCommitSHA, nil + } + + return "", nil +} + +func installSignals() (context.Context, context.CancelFunc) { + ctx, cancel := context.WithCancel(context.Background()) + go func() { + // install notify + signalChannel := make(chan os.Signal, 1) + + signal.Notify( + signalChannel, + syscall.SIGINT, + syscall.SIGTERM, + ) + select { + case <-signalChannel: + case <-ctx.Done(): + } + cancel() + signal.Reset() + }() + + return ctx, cancel +} From cc910014ab0df4d252ee61995df37b4a4cb92e06 Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Wed, 1 Feb 2023 06:11:48 +0800 Subject: [PATCH 006/434] Fix wrong hint when deleting a branch successfully from pull request UI (#22673) Fix #18785 --- routers/web/repo/pull.go | 2 +- tests/integration/pull_merge_test.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/routers/web/repo/pull.go b/routers/web/repo/pull.go index c2208120fcf24..71bc98d13d07c 100644 --- a/routers/web/repo/pull.go +++ b/routers/web/repo/pull.go @@ -1395,7 +1395,7 @@ func CleanUpPullRequest(ctx *context.Context) { } func deleteBranch(ctx *context.Context, pr *issues_model.PullRequest, gitRepo *git.Repository) { - fullBranchName := pr.HeadRepo.Owner.Name + "/" + pr.HeadBranch + fullBranchName := pr.HeadRepo.FullName() + ":" + pr.HeadBranch if err := repo_service.DeleteBranch(ctx.Doer, pr.HeadRepo, gitRepo, pr.HeadBranch); err != nil { switch { case git.IsErrBranchNotExist(err): diff --git a/tests/integration/pull_merge_test.go b/tests/integration/pull_merge_test.go index 491fc0e0aafec..e80822a7520af 100644 --- a/tests/integration/pull_merge_test.go +++ b/tests/integration/pull_merge_test.go @@ -187,7 +187,7 @@ func TestPullCleanUpAfterMerge(t *testing.T) { htmlDoc := NewHTMLParser(t, resp.Body) resultMsg := htmlDoc.doc.Find(".ui.message>p").Text() - assert.EqualValues(t, "Branch 'user1/feature/test' has been deleted.", resultMsg) + assert.EqualValues(t, "Branch 'user1/repo1:feature/test' has been deleted.", resultMsg) }) } From 1947409ef07f2dc4e0eab7482368816261510133 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Tue, 31 Jan 2023 23:40:38 +0100 Subject: [PATCH 007/434] Fix missing title and filter in issue sidebar project menu (#22557) These exist in the new issue form but were seemingly forgotten here. --- templates/repo/issue/view_content/sidebar.tmpl | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/templates/repo/issue/view_content/sidebar.tmpl b/templates/repo/issue/view_content/sidebar.tmpl index ca947e36129ea..10bb6a07f9710 100644 --- a/templates/repo/issue/view_content/sidebar.tmpl +++ b/templates/repo/issue/view_content/sidebar.tmpl @@ -212,6 +212,13 @@ {{end}}