mirror of
				https://gitee.com/gitea/gitea
				synced 2025-11-04 16:40:24 +08:00 
			
		
		
		
	* Make cancel from CatFileBatch and CatFileBatchCheck wait for the command to end Fix #16427 (again!) * handle sharing violation error code Signed-off-by: Andrew Thornton <art27@cantab.net>
This commit is contained in:
		@@ -7,6 +7,7 @@ package git
 | 
				
			|||||||
import (
 | 
					import (
 | 
				
			||||||
	"bufio"
 | 
						"bufio"
 | 
				
			||||||
	"bytes"
 | 
						"bytes"
 | 
				
			||||||
 | 
						"context"
 | 
				
			||||||
	"io"
 | 
						"io"
 | 
				
			||||||
	"math"
 | 
						"math"
 | 
				
			||||||
	"strconv"
 | 
						"strconv"
 | 
				
			||||||
@@ -15,20 +16,24 @@ import (
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
// CatFileBatch opens git cat-file --batch in the provided repo and returns a stdin pipe, a stdout reader and cancel function
 | 
					// CatFileBatch opens git cat-file --batch in the provided repo and returns a stdin pipe, a stdout reader and cancel function
 | 
				
			||||||
func CatFileBatch(repoPath string) (*io.PipeWriter, *bufio.Reader, func()) {
 | 
					func CatFileBatch(repoPath string) (*io.PipeWriter, *bufio.Reader, func()) {
 | 
				
			||||||
	// Next feed the commits in order into cat-file --batch, followed by their trees and sub trees as necessary.
 | 
						// We often want to feed the commits in order into cat-file --batch, followed by their trees and sub trees as necessary.
 | 
				
			||||||
	// so let's create a batch stdin and stdout
 | 
						// so let's create a batch stdin and stdout
 | 
				
			||||||
	batchStdinReader, batchStdinWriter := io.Pipe()
 | 
						batchStdinReader, batchStdinWriter := io.Pipe()
 | 
				
			||||||
	batchStdoutReader, batchStdoutWriter := io.Pipe()
 | 
						batchStdoutReader, batchStdoutWriter := io.Pipe()
 | 
				
			||||||
 | 
						ctx, ctxCancel := context.WithCancel(DefaultContext)
 | 
				
			||||||
 | 
						closed := make(chan struct{})
 | 
				
			||||||
	cancel := func() {
 | 
						cancel := func() {
 | 
				
			||||||
		_ = batchStdinReader.Close()
 | 
							_ = batchStdinReader.Close()
 | 
				
			||||||
		_ = batchStdinWriter.Close()
 | 
							_ = batchStdinWriter.Close()
 | 
				
			||||||
		_ = batchStdoutReader.Close()
 | 
							_ = batchStdoutReader.Close()
 | 
				
			||||||
		_ = batchStdoutWriter.Close()
 | 
							_ = batchStdoutWriter.Close()
 | 
				
			||||||
 | 
							ctxCancel()
 | 
				
			||||||
 | 
							<-closed
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	go func() {
 | 
						go func() {
 | 
				
			||||||
		stderr := strings.Builder{}
 | 
							stderr := strings.Builder{}
 | 
				
			||||||
		err := NewCommand("cat-file", "--batch").RunInDirFullPipeline(repoPath, batchStdoutWriter, &stderr, batchStdinReader)
 | 
							err := NewCommandContext(ctx, "cat-file", "--batch").RunInDirFullPipeline(repoPath, batchStdoutWriter, &stderr, batchStdinReader)
 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
			_ = batchStdoutWriter.CloseWithError(ConcatenateError(err, (&stderr).String()))
 | 
								_ = batchStdoutWriter.CloseWithError(ConcatenateError(err, (&stderr).String()))
 | 
				
			||||||
			_ = batchStdinReader.CloseWithError(ConcatenateError(err, (&stderr).String()))
 | 
								_ = batchStdinReader.CloseWithError(ConcatenateError(err, (&stderr).String()))
 | 
				
			||||||
@@ -36,10 +41,11 @@ func CatFileBatch(repoPath string) (*io.PipeWriter, *bufio.Reader, func()) {
 | 
				
			|||||||
			_ = batchStdoutWriter.Close()
 | 
								_ = batchStdoutWriter.Close()
 | 
				
			||||||
			_ = batchStdinReader.Close()
 | 
								_ = batchStdinReader.Close()
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
							close(closed)
 | 
				
			||||||
	}()
 | 
						}()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// For simplicities sake we'll us a buffered reader to read from the cat-file --batch
 | 
						// For simplicities sake we'll us a buffered reader to read from the cat-file --batch
 | 
				
			||||||
	batchReader := bufio.NewReader(batchStdoutReader)
 | 
						batchReader := bufio.NewReaderSize(batchStdoutReader, 32*1024)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return batchStdinWriter, batchReader, cancel
 | 
						return batchStdinWriter, batchReader, cancel
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -6,10 +6,13 @@ package util
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"os"
 | 
						"os"
 | 
				
			||||||
 | 
						"runtime"
 | 
				
			||||||
	"syscall"
 | 
						"syscall"
 | 
				
			||||||
	"time"
 | 
						"time"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const windowsSharingViolationError syscall.Errno = 32
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Remove removes the named file or (empty) directory with at most 5 attempts.
 | 
					// Remove removes the named file or (empty) directory with at most 5 attempts.
 | 
				
			||||||
func Remove(name string) error {
 | 
					func Remove(name string) error {
 | 
				
			||||||
	var err error
 | 
						var err error
 | 
				
			||||||
@@ -25,6 +28,12 @@ func Remove(name string) error {
 | 
				
			|||||||
			continue
 | 
								continue
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if unwrapped == windowsSharingViolationError && runtime.GOOS == "windows" {
 | 
				
			||||||
 | 
								// try again
 | 
				
			||||||
 | 
								<-time.After(100 * time.Millisecond)
 | 
				
			||||||
 | 
								continue
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if unwrapped == syscall.ENOENT {
 | 
							if unwrapped == syscall.ENOENT {
 | 
				
			||||||
			// it's already gone
 | 
								// it's already gone
 | 
				
			||||||
			return nil
 | 
								return nil
 | 
				
			||||||
@@ -48,6 +57,12 @@ func RemoveAll(name string) error {
 | 
				
			|||||||
			continue
 | 
								continue
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if unwrapped == windowsSharingViolationError && runtime.GOOS == "windows" {
 | 
				
			||||||
 | 
								// try again
 | 
				
			||||||
 | 
								<-time.After(100 * time.Millisecond)
 | 
				
			||||||
 | 
								continue
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if unwrapped == syscall.ENOENT {
 | 
							if unwrapped == syscall.ENOENT {
 | 
				
			||||||
			// it's already gone
 | 
								// it's already gone
 | 
				
			||||||
			return nil
 | 
								return nil
 | 
				
			||||||
@@ -71,6 +86,12 @@ func Rename(oldpath, newpath string) error {
 | 
				
			|||||||
			continue
 | 
								continue
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if unwrapped == windowsSharingViolationError && runtime.GOOS == "windows" {
 | 
				
			||||||
 | 
								// try again
 | 
				
			||||||
 | 
								<-time.After(100 * time.Millisecond)
 | 
				
			||||||
 | 
								continue
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if i == 0 && os.IsNotExist(err) {
 | 
							if i == 0 && os.IsNotExist(err) {
 | 
				
			||||||
			return err
 | 
								return err
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user