mirror of
				https://github.com/go-gitea/gitea.git
				synced 2025-10-31 20:21:47 +01:00 
			
		
		
		
	Allows users to specify a "force" option in API /contents routes when modifying files in a new branch. When "force" is true, and the branch already exists, a force push will occur provided the branch does not have a branch protection rule that disables force pushing. This is useful as a way to manage a branch remotely through only the API. For example in an automated release tool you can pull commits, analyze, and update a release PR branch all remotely without needing to clone or perform any local git operations. Resolve #35538 --------- Co-authored-by: Rob Gonnella <rob.gonnella@papayapay.com> Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
		
			
				
	
	
		
			153 lines
		
	
	
		
			4.1 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			153 lines
		
	
	
		
			4.1 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| // Copyright 2015 The Gogs Authors. All rights reserved.
 | |
| // SPDX-License-Identifier: MIT
 | |
| 
 | |
| package git
 | |
| 
 | |
| import (
 | |
| 	"context"
 | |
| 	"errors"
 | |
| 	"fmt"
 | |
| 	"strings"
 | |
| 
 | |
| 	"code.gitea.io/gitea/modules/util"
 | |
| )
 | |
| 
 | |
| // ErrNotExist commit not exist error
 | |
| type ErrNotExist struct {
 | |
| 	ID      string
 | |
| 	RelPath string
 | |
| }
 | |
| 
 | |
| // IsErrNotExist if some error is ErrNotExist
 | |
| func IsErrNotExist(err error) bool {
 | |
| 	_, ok := err.(ErrNotExist)
 | |
| 	return ok
 | |
| }
 | |
| 
 | |
| func (err ErrNotExist) Error() string {
 | |
| 	return fmt.Sprintf("object does not exist [id: %s, rel_path: %s]", err.ID, err.RelPath)
 | |
| }
 | |
| 
 | |
| func (err ErrNotExist) Unwrap() error {
 | |
| 	return util.ErrNotExist
 | |
| }
 | |
| 
 | |
| // ErrBranchNotExist represents a "BranchNotExist" kind of error.
 | |
| type ErrBranchNotExist struct {
 | |
| 	Name string
 | |
| }
 | |
| 
 | |
| // IsErrBranchNotExist checks if an error is a ErrBranchNotExist.
 | |
| func IsErrBranchNotExist(err error) bool {
 | |
| 	_, ok := err.(ErrBranchNotExist)
 | |
| 	return ok
 | |
| }
 | |
| 
 | |
| func (err ErrBranchNotExist) Error() string {
 | |
| 	return fmt.Sprintf("branch does not exist [name: %s]", err.Name)
 | |
| }
 | |
| 
 | |
| func (err ErrBranchNotExist) Unwrap() error {
 | |
| 	return util.ErrNotExist
 | |
| }
 | |
| 
 | |
| // ErrPushOutOfDate represents an error if merging fails due to the base branch being updated
 | |
| type ErrPushOutOfDate struct {
 | |
| 	StdOut string
 | |
| 	StdErr string
 | |
| 	Err    error
 | |
| }
 | |
| 
 | |
| // IsErrPushOutOfDate checks if an error is a ErrPushOutOfDate.
 | |
| func IsErrPushOutOfDate(err error) bool {
 | |
| 	_, ok := err.(*ErrPushOutOfDate)
 | |
| 	return ok
 | |
| }
 | |
| 
 | |
| func (err *ErrPushOutOfDate) Error() string {
 | |
| 	return fmt.Sprintf("PushOutOfDate Error: %v: %s\n%s", err.Err, err.StdErr, err.StdOut)
 | |
| }
 | |
| 
 | |
| // Unwrap unwraps the underlying error
 | |
| func (err *ErrPushOutOfDate) Unwrap() error {
 | |
| 	return fmt.Errorf("%w - %s", err.Err, err.StdErr)
 | |
| }
 | |
| 
 | |
| // ErrPushRejected represents an error if merging fails due to rejection from a hook
 | |
| type ErrPushRejected struct {
 | |
| 	Message string
 | |
| 	StdOut  string
 | |
| 	StdErr  string
 | |
| 	Err     error
 | |
| }
 | |
| 
 | |
| // IsErrPushRejected checks if an error is a ErrPushRejected.
 | |
| func IsErrPushRejected(err error) bool {
 | |
| 	_, ok := err.(*ErrPushRejected)
 | |
| 	return ok
 | |
| }
 | |
| 
 | |
| func (err *ErrPushRejected) Error() string {
 | |
| 	return fmt.Sprintf("PushRejected Error: %v: %s\n%s", err.Err, err.StdErr, err.StdOut)
 | |
| }
 | |
| 
 | |
| // Unwrap unwraps the underlying error
 | |
| func (err *ErrPushRejected) Unwrap() error {
 | |
| 	return fmt.Errorf("%w - %s", err.Err, err.StdErr)
 | |
| }
 | |
| 
 | |
| // GenerateMessage generates the remote message from the stderr
 | |
| func (err *ErrPushRejected) GenerateMessage() {
 | |
| 	// The stderr is like this:
 | |
| 	//
 | |
| 	// > remote: error: push is rejected .....
 | |
| 	// > To /work/gitea/tests/integration/gitea-integration-sqlite/gitea-repositories/user2/repo1.git
 | |
| 	// >  ! [remote rejected] 44e67c77559211d21b630b902cdcc6ab9d4a4f51 -> develop (pre-receive hook declined)
 | |
| 	// > error: failed to push some refs to '/work/gitea/tests/integration/gitea-integration-sqlite/gitea-repositories/user2/repo1.git'
 | |
| 	//
 | |
| 	// The local message contains sensitive information, so we only need the remote message
 | |
| 	const prefixRemote = "remote: "
 | |
| 	const prefixError = "error: "
 | |
| 	pos := strings.Index(err.StdErr, prefixRemote)
 | |
| 	if pos < 0 {
 | |
| 		err.Message = "push is rejected"
 | |
| 		return
 | |
| 	}
 | |
| 
 | |
| 	messageBuilder := &strings.Builder{}
 | |
| 	lines := strings.SplitSeq(err.StdErr, "\n")
 | |
| 	for line := range lines {
 | |
| 		line, ok := strings.CutPrefix(line, prefixRemote)
 | |
| 		if !ok {
 | |
| 			continue
 | |
| 		}
 | |
| 		line = strings.TrimPrefix(line, prefixError)
 | |
| 		messageBuilder.WriteString(strings.TrimSpace(line) + "\n")
 | |
| 	}
 | |
| 	err.Message = strings.TrimSpace(messageBuilder.String())
 | |
| }
 | |
| 
 | |
| // ErrMoreThanOne represents an error if pull request fails when there are more than one sources (branch, tag) with the same name
 | |
| type ErrMoreThanOne struct {
 | |
| 	StdOut string
 | |
| 	StdErr string
 | |
| 	Err    error
 | |
| }
 | |
| 
 | |
| // IsErrMoreThanOne checks if an error is a ErrMoreThanOne
 | |
| func IsErrMoreThanOne(err error) bool {
 | |
| 	_, ok := err.(*ErrMoreThanOne)
 | |
| 	return ok
 | |
| }
 | |
| 
 | |
| func (err *ErrMoreThanOne) Error() string {
 | |
| 	return fmt.Sprintf("ErrMoreThanOne Error: %v: %s\n%s", err.Err, err.StdErr, err.StdOut)
 | |
| }
 | |
| 
 | |
| func IsErrCanceledOrKilled(err error) bool {
 | |
| 	// When "cancel()" a git command's context, the returned error of "Run()" could be one of them:
 | |
| 	// - context.Canceled
 | |
| 	// - *exec.ExitError: "signal: killed"
 | |
| 	return err != nil && (errors.Is(err, context.Canceled) || err.Error() == "signal: killed")
 | |
| }
 |