Repository: JuliaLang/julia
File: base/file.jl (Julia)

Code before:
            end
            nothing
        finally
            Libc.free(req)
        end
    end
end


# Loaded DLLs cannot be deleted on Windows, even with posix delete mode but they can be renamed.
# delayed_delete_dll(path) does so temporarily, until later cleanup by Pkg.gc().
function delayed_delete_dll(path)
    drive = first(splitdrive(path))
    tmpdrive = first(splitdrive(tempdir()))
    # in-use DLL must be kept on the same drive
    deletedir = if drive == tmpdrive
        joinpath(tempdir(), "julia_delayed_deletes")
    else
        joinpath(drive, "julia_delayed_deletes")
    end
    mkpath(deletedir)
    temp_path = tempname(deletedir; cleanup=false, suffix=string("_", basename(path)))
    @debug "Could not delete DLL most likely because it is loaded, moving to a temporary path" path temp_path
    mkpath(delayed_delete_ref())
    io = last(mktemp(delayed_delete_ref(); cleanup=false))
    println(io, abspath(temp_path)) # record the temporary path for Pkg.gc()
    close(io)
    rename(path, temp_path) # do not call mv which could recursively call rm(path)
end

# The following use Unix command line facilities
function checkfor_mv_cp_cptree(src::AbstractString, dst::AbstractString, txt::AbstractString;
                                                          force::Bool=false)
    if ispath(dst)
        if force
            # Check for issue when: (src == dst) or when one is a link to the other
            # https://github.com/JuliaLang/julia/pull/11172#issuecomment-100391076
            if Base.samefile(src, dst)
                abs_src = islink(src) ? abspath(readlink(src)) : abspath(src)
                abs_dst = islink(dst) ? abspath(readlink(dst)) : abspath(dst)
                throw(ArgumentError(string("'src' and 'dst' refer to the same file/dir. ",
                                           "This is not supported.\n  ",
                                           "`src` refers to: $(abs_src)\n  ",
                                           "`dst` refers to: $(abs_dst)\n")))
            end
            rm(dst; recursive=true, force=true)
        else
            throw(ArgumentError(string("'$dst' exists. `force=true` ",
                                       "is required to remove '$dst' before $(txt).")))
        end
    end

Review comment (suggestion):
```suggestion
    print(io, temp_path) # record the temporary path for Pkg.gc()
```

Code after:
            end
            nothing
        finally
            Libc.free(req)
        end
    end
end


# Loaded DLLs cannot be deleted on Windows, even with posix delete mode but they can be renamed.
# delayed_delete_dll(path) does so temporarily, until later cleanup by Pkg.gc().
function delayed_delete_dll(path)
    # in-use DLL must be kept on the same drive
    temp_path = tempname(abspath(dirname(path)); cleanup=false, suffix=string("_", basename(path)))
    @debug "Could not delete DLL most likely because it is loaded, moving to a temporary path" path temp_path
    mkpath(delayed_delete_ref())
    io = last(mktemp(delayed_delete_ref(); cleanup=false))
    try
        print(io, temp_path) # record the temporary path for Pkg.gc()
    finally
        close(io)
    end
    rename(path, temp_path) # do not call mv which could recursively call rm(path)
end

# The following use Unix command line facilities
function checkfor_mv_cp_cptree(src::AbstractString, dst::AbstractString, txt::AbstractString;
                                                          force::Bool=false)
    if ispath(dst)
        if force
            # Check for issue when: (src == dst) or when one is a link to the other
            # https://github.com/JuliaLang/julia/pull/11172#issuecomment-100391076
            if Base.samefile(src, dst)
                abs_src = islink(src) ? abspath(readlink(src)) : abspath(src)
                abs_dst = islink(dst) ? abspath(readlink(dst)) : abspath(dst)
                throw(ArgumentError(string("'src' and 'dst' refer to the same file/dir. ",
                                           "This is not supported.\n  ",
                                           "`src` refers to: $(abs_src)\n  ",
                                           "`dst` refers to: $(abs_dst)\n")))
            end
            rm(dst; recursive=true, force=true)
        else
            throw(ArgumentError(string("'$dst' exists. `force=true` ",
                                       "is required to remove '$dst' before $(txt).")))
        end
    end
end

function cptree(src::String, dst::String; force::Bool=false,
                                          follow_symlinks::Bool=false)
    isdir(src) || throw(ArgumentError("'$src' is not a directory. Use `cp(src, dst)`"))