github.com/blend/go-sdk@v1.20220411.3/fileutil/temp.go (about)

     1  /*
     2  
     3  Copyright (c) 2022 - Present. Blend Labs, Inc. All rights reserved
     4  Use of this source code is governed by a MIT license that can be found in the LICENSE file.
     5  
     6  */
     7  
     8  package fileutil
     9  
    10  import (
    11  	"os"
    12  	"sync"
    13  
    14  	"github.com/blend/go-sdk/ex"
    15  )
    16  
    17  // NewTemp creates a new temp file with given contents.
    18  func NewTemp(contents []byte) (*Temp, error) {
    19  	f, err := os.CreateTemp("", "")
    20  	if err != nil {
    21  		return nil, ex.New(err)
    22  	}
    23  	if _, err := f.Write(contents); err != nil {
    24  		return nil, ex.New(err)
    25  	}
    26  	return &Temp{
    27  		file: f,
    28  	}, nil
    29  }
    30  
    31  // Temp is a file that deletes itself when closed.
    32  // It does not hold a file handle open, so no
    33  // guarantees are made around the file persisting for the lifetime of the object.
    34  type Temp struct {
    35  	sync.Mutex
    36  
    37  	file *os.File
    38  }
    39  
    40  // Name returns the fully qualified file path.
    41  func (tf *Temp) Name() string {
    42  	return tf.file.Name()
    43  }
    44  
    45  // Stat returns a FileInfo describing the named file.
    46  // If there is an error, it will be of type *PathError.
    47  func (tf *Temp) Stat() (os.FileInfo, error) {
    48  	tf.Lock()
    49  	defer tf.Unlock()
    50  
    51  	return tf.file.Stat()
    52  }
    53  
    54  // Read reads up to len(b) bytes from the File.
    55  // It returns the number of bytes read and any error encountered.
    56  // At end of file, Read returns 0, io.EOF.
    57  func (tf *Temp) Read(buffer []byte) (int, error) {
    58  	tf.Lock()
    59  	defer tf.Unlock()
    60  
    61  	read, err := tf.file.Read(buffer)
    62  	return read, ex.New(err)
    63  }
    64  
    65  // ReadAt reads len(b) bytes from the File starting at byte offset off.
    66  // It returns the number of bytes read and the error, if any.
    67  // ReadAt always returns a non-nil error when n < len(b).
    68  // At end of file, that error is io.EOF.
    69  func (tf *Temp) ReadAt(buffer []byte, off int64) (int, error) {
    70  	tf.Lock()
    71  	defer tf.Unlock()
    72  
    73  	read, err := tf.file.ReadAt(buffer, off)
    74  	return read, ex.New(err)
    75  }
    76  
    77  // Write writes len(b) bytes to the File.
    78  // It returns the number of bytes written and an error, if any.
    79  // Write returns a non-nil error when n != len(b).
    80  func (tf *Temp) Write(contents []byte) (int, error) {
    81  	tf.Lock()
    82  	defer tf.Unlock()
    83  
    84  	written, err := tf.file.Write(contents)
    85  	return written, ex.New(err)
    86  }
    87  
    88  // WriteAt writes len(b) bytes to the File starting at byte offset off.
    89  // It returns the number of bytes written and an error, if any.
    90  // WriteAt returns a non-nil error when n != len(b).
    91  func (tf *Temp) WriteAt(contents []byte, off int64) (int, error) {
    92  	tf.Lock()
    93  	defer tf.Unlock()
    94  
    95  	written, err := tf.file.WriteAt(contents, off)
    96  	return written, ex.New(err)
    97  }
    98  
    99  // WriteString is like Write, but writes the contents of string s rather than
   100  // a slice of bytes.
   101  func (tf *Temp) WriteString(contents string) (int, error) {
   102  	tf.Lock()
   103  	defer tf.Unlock()
   104  
   105  	written, err := tf.file.WriteString(contents)
   106  	return written, ex.New(err)
   107  }
   108  
   109  // Close closes the file reference and deletes the file.
   110  func (tf *Temp) Close() error {
   111  	tf.Lock()
   112  	defer tf.Unlock()
   113  
   114  	if err := tf.file.Close(); err != nil {
   115  		return ex.New(err)
   116  	}
   117  	if err := os.Remove(tf.file.Name()); err != nil {
   118  		return ex.New(err)
   119  	}
   120  	return nil
   121  }