mirror of
				https://github.com/go-gitea/gitea.git
				synced 2025-10-31 21:28:11 +09:00 
			
		
		
		
	Make cancel from CatFileBatch and CatFileBatchCheck wait for the command to end (#16479)
Fix #16427 (again!) * handle sharing violation error code Signed-off-by: Andrew Thornton <art27@cantab.net> Co-authored-by: Lauris BH <lauris@nix.lv>
This commit is contained in:
		| @@ -7,6 +7,7 @@ package git | |||||||
| import ( | import ( | ||||||
| 	"bufio" | 	"bufio" | ||||||
| 	"bytes" | 	"bytes" | ||||||
|  | 	"context" | ||||||
| 	"io" | 	"io" | ||||||
| 	"math" | 	"math" | ||||||
| 	"strconv" | 	"strconv" | ||||||
| @@ -28,16 +29,20 @@ type WriteCloserError interface { | |||||||
| func CatFileBatchCheck(repoPath string) (WriteCloserError, *bufio.Reader, func()) { | func CatFileBatchCheck(repoPath string) (WriteCloserError, *bufio.Reader, func()) { | ||||||
| 	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-check").RunInDirFullPipeline(repoPath, batchStdoutWriter, &stderr, batchStdinReader) | 		err := NewCommandContext(ctx, "cat-file", "--batch-check").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())) | ||||||
| @@ -45,6 +50,7 @@ func CatFileBatchCheck(repoPath string) (WriteCloserError, *bufio.Reader, func() | |||||||
| 			_ = batchStdoutWriter.Close() | 			_ = batchStdoutWriter.Close() | ||||||
| 			_ = batchStdinReader.Close() | 			_ = batchStdinReader.Close() | ||||||
| 		} | 		} | ||||||
|  | 		close(closed) | ||||||
| 	}() | 	}() | ||||||
|  |  | ||||||
| 	// For simplicities sake we'll use a buffered reader to read from the cat-file --batch-check | 	// For simplicities sake we'll use a buffered reader to read from the cat-file --batch-check | ||||||
| @@ -59,16 +65,20 @@ func CatFileBatch(repoPath string) (WriteCloserError, *bufio.Reader, func()) { | |||||||
| 	// 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 := nio.Pipe(buffer.New(32 * 1024)) | 	batchStdoutReader, batchStdoutWriter := nio.Pipe(buffer.New(32 * 1024)) | ||||||
|  | 	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())) | ||||||
| @@ -76,6 +86,7 @@ func CatFileBatch(repoPath string) (WriteCloserError, *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 | ||||||
|   | |||||||
| @@ -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