* Dump: Use mholt/archive/v3 to support tar including many compressions Signed-off-by: Philipp Homann <homann.philipp@googlemail.com> * Dump: Allow dump output to stdout Signed-off-by: Philipp Homann <homann.philipp@googlemail.com> * Dump: Fixed bug present since #6677 where SessionConfig.Provider is never "file" Signed-off-by: Philipp Homann <homann.philipp@googlemail.com> * Dump: never pack RepoRootPath, LFS.ContentPath and LogRootPath when they are below AppDataPath Signed-off-by: Philipp Homann <homann.philipp@googlemail.com> * Dump: also dump LFS (fixes #10058) Signed-off-by: Philipp Homann <homann.philipp@googlemail.com> * Dump: never dump CustomPath if CustomPath is a subdir of or equal to AppDataPath (fixes #10365) Signed-off-by: Philipp Homann <homann.philipp@googlemail.com> * Use log.Info instead of fmt.Fprintf Signed-off-by: Philipp Homann <homann.philipp@googlemail.com> * import ordering * make fmt Co-authored-by: zeripath <art27@cantab.net> Co-authored-by: techknowlogick <techknowlogick@gitea.io> Co-authored-by: Matti R <matti@mdranta.net>
		
			
				
	
	
		
			167 lines
		
	
	
		
			4.9 KiB
		
	
	
	
		
			Go
		
	
	
	
		
			Vendored
		
	
	
	
			
		
		
	
	
			167 lines
		
	
	
		
			4.9 KiB
		
	
	
	
		
			Go
		
	
	
	
		
			Vendored
		
	
	
	
| // Copyright 2015, Joe Tsai. All rights reserved.
 | |
| // Use of this source code is governed by a BSD-style
 | |
| // license that can be found in the LICENSE.md file.
 | |
| 
 | |
| package prefix
 | |
| 
 | |
| import (
 | |
| 	"encoding/binary"
 | |
| 	"io"
 | |
| 
 | |
| 	"github.com/dsnet/compress/internal/errors"
 | |
| )
 | |
| 
 | |
| // Writer implements a prefix encoder. For performance reasons, Writer will not
 | |
| // write bytes immediately to the underlying stream.
 | |
| type Writer struct {
 | |
| 	Offset int64 // Number of bytes written to the underlying io.Writer
 | |
| 
 | |
| 	wr        io.Writer
 | |
| 	bufBits   uint64 // Buffer to hold some bits
 | |
| 	numBits   uint   // Number of valid bits in bufBits
 | |
| 	bigEndian bool   // Are bits written in big-endian order?
 | |
| 
 | |
| 	buf    [512]byte
 | |
| 	cntBuf int
 | |
| }
 | |
| 
 | |
| // Init initializes the bit Writer to write to w. If bigEndian is true, then
 | |
| // bits will be written starting from the most-significant bits of a byte
 | |
| // (as done in bzip2), otherwise it will write starting from the
 | |
| // least-significant bits of a byte (such as for deflate and brotli).
 | |
| func (pw *Writer) Init(w io.Writer, bigEndian bool) {
 | |
| 	*pw = Writer{wr: w, bigEndian: bigEndian}
 | |
| 	return
 | |
| }
 | |
| 
 | |
| // BitsWritten reports the total number of bits issued to any Write method.
 | |
| func (pw *Writer) BitsWritten() int64 {
 | |
| 	return 8*pw.Offset + 8*int64(pw.cntBuf) + int64(pw.numBits)
 | |
| }
 | |
| 
 | |
| // WritePads writes 0-7 bits to the bit buffer to achieve byte-alignment.
 | |
| func (pw *Writer) WritePads(v uint) {
 | |
| 	nb := -pw.numBits & 7
 | |
| 	pw.bufBits |= uint64(v) << pw.numBits
 | |
| 	pw.numBits += nb
 | |
| }
 | |
| 
 | |
| // Write writes bytes from buf.
 | |
| // The bit-ordering mode does not affect this method.
 | |
| func (pw *Writer) Write(buf []byte) (cnt int, err error) {
 | |
| 	if pw.numBits > 0 || pw.cntBuf > 0 {
 | |
| 		if pw.numBits%8 != 0 {
 | |
| 			return 0, errorf(errors.Invalid, "non-aligned bit buffer")
 | |
| 		}
 | |
| 		if _, err := pw.Flush(); err != nil {
 | |
| 			return 0, err
 | |
| 		}
 | |
| 	}
 | |
| 	cnt, err = pw.wr.Write(buf)
 | |
| 	pw.Offset += int64(cnt)
 | |
| 	return cnt, err
 | |
| }
 | |
| 
 | |
| // WriteOffset writes ofs in a (sym, extra) fashion using the provided prefix
 | |
| // Encoder and RangeEncoder.
 | |
| func (pw *Writer) WriteOffset(ofs uint, pe *Encoder, re *RangeEncoder) {
 | |
| 	sym := re.Encode(ofs)
 | |
| 	pw.WriteSymbol(sym, pe)
 | |
| 	rc := re.rcs[sym]
 | |
| 	pw.WriteBits(ofs-uint(rc.Base), uint(rc.Len))
 | |
| }
 | |
| 
 | |
| // TryWriteBits attempts to write nb bits using the contents of the bit buffer
 | |
| // alone. It reports whether it succeeded.
 | |
| //
 | |
| // This method is designed to be inlined for performance reasons.
 | |
| func (pw *Writer) TryWriteBits(v, nb uint) bool {
 | |
| 	if 64-pw.numBits < nb {
 | |
| 		return false
 | |
| 	}
 | |
| 	pw.bufBits |= uint64(v) << pw.numBits
 | |
| 	pw.numBits += nb
 | |
| 	return true
 | |
| }
 | |
| 
 | |
| // WriteBits writes nb bits of v to the underlying writer.
 | |
| func (pw *Writer) WriteBits(v, nb uint) {
 | |
| 	if _, err := pw.PushBits(); err != nil {
 | |
| 		errors.Panic(err)
 | |
| 	}
 | |
| 	pw.bufBits |= uint64(v) << pw.numBits
 | |
| 	pw.numBits += nb
 | |
| }
 | |
| 
 | |
| // TryWriteSymbol attempts to encode the next symbol using the contents of the
 | |
| // bit buffer alone. It reports whether it succeeded.
 | |
| //
 | |
| // This method is designed to be inlined for performance reasons.
 | |
| func (pw *Writer) TryWriteSymbol(sym uint, pe *Encoder) bool {
 | |
| 	chunk := pe.chunks[uint32(sym)&pe.chunkMask]
 | |
| 	nb := uint(chunk & countMask)
 | |
| 	if 64-pw.numBits < nb {
 | |
| 		return false
 | |
| 	}
 | |
| 	pw.bufBits |= uint64(chunk>>countBits) << pw.numBits
 | |
| 	pw.numBits += nb
 | |
| 	return true
 | |
| }
 | |
| 
 | |
| // WriteSymbol writes the symbol using the provided prefix Encoder.
 | |
| func (pw *Writer) WriteSymbol(sym uint, pe *Encoder) {
 | |
| 	if _, err := pw.PushBits(); err != nil {
 | |
| 		errors.Panic(err)
 | |
| 	}
 | |
| 	chunk := pe.chunks[uint32(sym)&pe.chunkMask]
 | |
| 	nb := uint(chunk & countMask)
 | |
| 	pw.bufBits |= uint64(chunk>>countBits) << pw.numBits
 | |
| 	pw.numBits += nb
 | |
| }
 | |
| 
 | |
| // Flush flushes all complete bytes from the bit buffer to the byte buffer, and
 | |
| // then flushes all bytes in the byte buffer to the underlying writer.
 | |
| // After this call, the bit Writer is will only withhold 7 bits at most.
 | |
| func (pw *Writer) Flush() (int64, error) {
 | |
| 	if pw.numBits < 8 && pw.cntBuf == 0 {
 | |
| 		return pw.Offset, nil
 | |
| 	}
 | |
| 	if _, err := pw.PushBits(); err != nil {
 | |
| 		return pw.Offset, err
 | |
| 	}
 | |
| 	cnt, err := pw.wr.Write(pw.buf[:pw.cntBuf])
 | |
| 	pw.cntBuf -= cnt
 | |
| 	pw.Offset += int64(cnt)
 | |
| 	return pw.Offset, err
 | |
| }
 | |
| 
 | |
| // PushBits pushes as many bytes as possible from the bit buffer to the byte
 | |
| // buffer, reporting the number of bits pushed.
 | |
| func (pw *Writer) PushBits() (uint, error) {
 | |
| 	if pw.cntBuf >= len(pw.buf)-8 {
 | |
| 		cnt, err := pw.wr.Write(pw.buf[:pw.cntBuf])
 | |
| 		pw.cntBuf -= cnt
 | |
| 		pw.Offset += int64(cnt)
 | |
| 		if err != nil {
 | |
| 			return 0, err
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	u := pw.bufBits
 | |
| 	if pw.bigEndian {
 | |
| 		// Swap all the bits within each byte.
 | |
| 		u = (u&0xaaaaaaaaaaaaaaaa)>>1 | (u&0x5555555555555555)<<1
 | |
| 		u = (u&0xcccccccccccccccc)>>2 | (u&0x3333333333333333)<<2
 | |
| 		u = (u&0xf0f0f0f0f0f0f0f0)>>4 | (u&0x0f0f0f0f0f0f0f0f)<<4
 | |
| 	}
 | |
| 	// Starting with Go 1.7, the compiler should use a wide integer
 | |
| 	// store here if the architecture supports it.
 | |
| 	binary.LittleEndian.PutUint64(pw.buf[pw.cntBuf:], u)
 | |
| 
 | |
| 	nb := pw.numBits / 8 // Number of bytes to copy from bit buffer
 | |
| 	pw.cntBuf += int(nb)
 | |
| 	pw.bufBits >>= 8 * nb
 | |
| 	pw.numBits -= 8 * nb
 | |
| 	return 8 * nb, nil
 | |
| }
 |