code.gitea.io/gitea@v1.19.3/modules/util/remove.go (about)

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