| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091 | 
							- /*
 
-    Copyright 2023 Docker Compose CLI authors
 
-    Licensed under the Apache License, Version 2.0 (the "License");
 
-    you may not use this file except in compliance with the License.
 
-    You may obtain a copy of the License at
 
-        http://www.apache.org/licenses/LICENSE-2.0
 
-    Unless required by applicable law or agreed to in writing, software
 
-    distributed under the License is distributed on an "AS IS" BASIS,
 
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 
-    See the License for the specific language governing permissions and
 
-    limitations under the License.
 
- */
 
- package sync
 
- import (
 
- 	"errors"
 
- 	"io"
 
- )
 
- // lossyMultiWriter attempts to tee all writes to the provided io.PipeWriter
 
- // instances.
 
- //
 
- // If a writer fails during a Write call, the write-side of the pipe is then
 
- // closed with the error and no subsequent attempts are made to write to the
 
- // pipe.
 
- //
 
- // If all writers fail during a write, an error is returned.
 
- //
 
- // On Close, any remaining writers are closed.
 
- type lossyMultiWriter struct {
 
- 	writers []*io.PipeWriter
 
- }
 
- // newLossyMultiWriter creates a new writer that *attempts* to tee all data written to it to the provided io.PipeWriter
 
- // instances. Rather than failing a write operation if any writer fails, writes only fail if there are no more valid
 
- // writers. Otherwise, errors for specific writers are propagated via CloseWithError.
 
- func newLossyMultiWriter(writers ...*io.PipeWriter) *lossyMultiWriter {
 
- 	// reverse the writers because during the write we iterate
 
- 	// backwards, so this way we'll end up writing in the same
 
- 	// order as the writers were passed to us
 
- 	writers = append([]*io.PipeWriter(nil), writers...)
 
- 	for i, j := 0, len(writers)-1; i < j; i, j = i+1, j-1 {
 
- 		writers[i], writers[j] = writers[j], writers[i]
 
- 	}
 
- 	return &lossyMultiWriter{
 
- 		writers: writers,
 
- 	}
 
- }
 
- // Write writes to each writer that is still active (i.e. has not failed/encountered an error on write).
 
- //
 
- // If a writer encounters an error during the write, the write side of the pipe is closed with the error
 
- // and no subsequent attempts will be made to write to that writer.
 
- //
 
- // An error is only returned from this function if ALL writers have failed.
 
- func (l *lossyMultiWriter) Write(p []byte) (int, error) {
 
- 	// NOTE: this function iterates backwards so that it can
 
- 	// 	safely remove elements during the loop
 
- 	for i := len(l.writers) - 1; i >= 0; i-- {
 
- 		written, err := l.writers[i].Write(p)
 
- 		if err == nil && written != len(p) {
 
- 			err = io.ErrShortWrite
 
- 		}
 
- 		if err != nil {
 
- 			// pipe writer close cannot fail
 
- 			_ = l.writers[i].CloseWithError(err)
 
- 			l.writers = append(l.writers[:i], l.writers[i+1:]...)
 
- 		}
 
- 	}
 
- 	if len(l.writers) == 0 {
 
- 		return 0, errors.New("no writers remaining")
 
- 	}
 
- 	return len(p), nil
 
- }
 
- // Close closes any still open (non-failed) writers.
 
- //
 
- // Failed writers have already been closed with an error.
 
- func (l *lossyMultiWriter) Close() {
 
- 	for i := range l.writers {
 
- 		// pipe writer close cannot fail
 
- 		_ = l.writers[i].Close()
 
- 	}
 
- }
 
 
  |