github.com/gitbundle/modules@v0.0.0-20231025071548-85b91c5c3b01/util/remove.go (about)

     1  // Copyright 2023 The GitBundle Inc. All rights reserved.
     2  // Copyright 2017 The Gitea Authors. All rights reserved.
     3  // Use of this source code is governed by a MIT-style
     4  // license that can be found in the LICENSE file.
     5  
     6  package util
     7  
     8  import (
     9  	"os"
    10  	"runtime"
    11  	"syscall"
    12  	"time"
    13  )
    14  
    15  const windowsSharingViolationError syscall.Errno = 32
    16  
    17  // Remove removes the named file or (empty) directory with at most 5 attempts.
    18  func Remove(name string) error {
    19  	var err error
    20  	for i := 0; i < 5; i++ {
    21  		err = os.Remove(name)
    22  		if err == nil {
    23  			break
    24  		}
    25  		unwrapped := err.(*os.PathError).Err
    26  		if unwrapped == syscall.EBUSY || unwrapped == syscall.ENOTEMPTY || unwrapped == syscall.EPERM || unwrapped == syscall.EMFILE || unwrapped == syscall.ENFILE {
    27  			// try again
    28  			<-time.After(100 * time.Millisecond)
    29  			continue
    30  		}
    31  
    32  		if unwrapped == windowsSharingViolationError && runtime.GOOS == "windows" {
    33  			// try again
    34  			<-time.After(100 * time.Millisecond)
    35  			continue
    36  		}
    37  
    38  		if unwrapped == syscall.ENOENT {
    39  			// it's already gone
    40  			return nil
    41  		}
    42  	}
    43  	return err
    44  }
    45  
    46  // RemoveAll removes the named file or (empty) directory with at most 5 attempts.
    47  func RemoveAll(name string) error {
    48  	var err error
    49  	for i := 0; i < 5; i++ {
    50  		err = os.RemoveAll(name)
    51  		if err == nil {
    52  			break
    53  		}
    54  		unwrapped := err.(*os.PathError).Err
    55  		if unwrapped == syscall.EBUSY || unwrapped == syscall.ENOTEMPTY || unwrapped == syscall.EPERM || unwrapped == syscall.EMFILE || unwrapped == syscall.ENFILE {
    56  			// try again
    57  			<-time.After(100 * time.Millisecond)
    58  			continue
    59  		}
    60  
    61  		if unwrapped == windowsSharingViolationError && runtime.GOOS == "windows" {
    62  			// try again
    63  			<-time.After(100 * time.Millisecond)
    64  			continue
    65  		}
    66  
    67  		if unwrapped == syscall.ENOENT {
    68  			// it's already gone
    69  			return nil
    70  		}
    71  	}
    72  	return err
    73  }
    74  
    75  // Rename renames (moves) oldpath to newpath with at most 5 attempts.
    76  func Rename(oldpath, newpath string) error {
    77  	var err error
    78  	for i := 0; i < 5; i++ {
    79  		err = os.Rename(oldpath, newpath)
    80  		if err == nil {
    81  			break
    82  		}
    83  		unwrapped := err.(*os.LinkError).Err
    84  		if unwrapped == syscall.EBUSY || unwrapped == syscall.ENOTEMPTY || unwrapped == syscall.EPERM || unwrapped == syscall.EMFILE || unwrapped == syscall.ENFILE {
    85  			// try again
    86  			<-time.After(100 * time.Millisecond)
    87  			continue
    88  		}
    89  
    90  		if unwrapped == windowsSharingViolationError && runtime.GOOS == "windows" {
    91  			// try again
    92  			<-time.After(100 * time.Millisecond)
    93  			continue
    94  		}
    95  
    96  		if i == 0 && os.IsNotExist(err) {
    97  			return err
    98  		}
    99  
   100  		if unwrapped == syscall.ENOENT {
   101  			// it's already gone
   102  			return nil
   103  		}
   104  	}
   105  	return err
   106  }