Skip to content

Commit

Permalink
Merge pull request #30 from JuliaWeb/options
Browse files Browse the repository at this point in the history
SFTP `mkpath()` and other things
  • Loading branch information
JamesWrigley authored Dec 6, 2024
2 parents ffe521c + bb1989c commit 88a3193
Show file tree
Hide file tree
Showing 6 changed files with 63 additions and 4 deletions.
2 changes: 1 addition & 1 deletion Project.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name = "LibSSH"
uuid = "00483490-30f8-4353-8aba-35b82f51f4d0"
authors = ["James Wrigley <[email protected]> and contributors"]
version = "0.7.0"
version = "0.8.0"

[deps]
CEnum = "fa961155-64e5-5f13-b03f-caf6b980ea82"
Expand Down
10 changes: 10 additions & 0 deletions docs/src/changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,16 @@ CurrentModule = LibSSH
This documents notable changes in LibSSH.jl. The format is based on [Keep a
Changelog](https://keepachangelog.com).

## [v0.8.0] - 2024-12-06

### Added
- Implemented [`Base.mkpath(::AbstractString, ::SftpSession)`](@ref) ([#30]).
- Added support for 32-bit platforms, though only Linux is tested with that in
CI ([#29]).

### Fixed
- Fixed behaviour of the [`Session`](@ref)`.known_hosts` property ([#30]).

## [v0.7.0] - 2024-10-25

### Added
Expand Down
1 change: 1 addition & 0 deletions docs/src/sftp.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ Base.unlock(::SftpSession)
Base.readdir(::AbstractString, ::SftpSession)
Base.rm(::AbstractString, ::SftpSession)
Base.mkdir(::AbstractString, ::SftpSession)
Base.mkpath(::AbstractString, ::SftpSession)
Base.mv(::AbstractString, ::AbstractString, ::SftpSession)
Base.stat(::String, ::SftpSession)
get_extensions(::SftpSession)
Expand Down
7 changes: 4 additions & 3 deletions src/session.jl
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ mutable struct Session

log_verbosity::Int
ssh_dir::Union{String, Nothing}
known_hosts::Union{String, Nothing}
gssapi_server_identity::Union{String, Nothing}
process_config::Bool

Expand Down Expand Up @@ -69,7 +68,7 @@ mutable struct Session
lib.ssh_set_blocking(ptr, 0)

session = new(ptr, own, [], nothing,
-1, nothing, nothing, nothing, true,
-1, nothing, nothing, true,
ReentrantLock(), nothing, AuthMethod[], true,
Threads.Event(true), CloseableCondition(), false)

Expand Down Expand Up @@ -311,7 +310,7 @@ const SESSION_PROPERTY_OPTIONS = Dict(:host => (SSH_OPTIONS_HOST, Cstring),
:process_config => (SSH_OPTIONS_PROCESS_CONFIG, Bool))
# These properties cannot be retrieved from the libssh API (i.e. with
# ssh_options_get()), so we store them in the Session object instead.
const SAVED_PROPERTIES = (:log_verbosity, :gssapi_server_identity, :ssh_dir, :known_hosts, :process_config)
const SAVED_PROPERTIES = (:log_verbosity, :gssapi_server_identity, :ssh_dir, :process_config)

function Base.propertynames(::Session, private::Bool=false)
fields = fieldnames(Session)
Expand Down Expand Up @@ -869,6 +868,8 @@ function authenticate_cli(session::Session)
# We can't continue if they don't accept the key
return ret
end
elseif ret == AuthStatus_Success
# Do nothing
else
error("Unsupported return value from authenticate(): $(ret)")
end
Expand Down
31 changes: 31 additions & 0 deletions src/sftp.jl
Original file line number Diff line number Diff line change
Expand Up @@ -526,6 +526,37 @@ end
"""
$(TYPEDSIGNATURES)
Create a remote path. This behaves in exactly the same way as `Base.mkpath()`.
# Throws
- `ArgumentError`: If `sftp` is closed.
- [`SftpException`](@ref): If making the path fails for some reason, such as
part of `path` being an existing file.
"""
function Base.mkpath(path::AbstractString, sftp::SftpSession; mode=0o777)
if !isopen(sftp)
throw(ArgumentError("$(sftp) is closed, cannot use it to mkpath()"))
end

parts = splitpath(path)
for i in eachindex(parts)
part= joinpath(parts[1:i])

try
mkdir(part, sftp; mode)
catch ex
if !(ex isa SftpException && ex.error_code == SftpError_FileAlreadyExists && isdir(part, sftp))
rethrow()
end
end
end

return path
end

"""
$(TYPEDSIGNATURES)
Move `src` to `dst` remotely. Has the same behaviour as `Base.mv()`.
# Throws
Expand Down
16 changes: 16 additions & 0 deletions test/LibSSHTests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -954,6 +954,21 @@ end
@test_throws ssh.SftpException mkdir(path, sftp)
end

# Test mkpath()
mktempdir() do tmpdir
parent_dir = joinpath(tmpdir, "foo")
path = joinpath(parent_dir, "bar")

# Creating a path with no existing files in the name should work
@test mkpath(path, sftp) == path
@test isdir(path)

# But if there's a file already in there we should get an exception
rm(parent_dir; force=true, recursive=true)
touch(parent_dir)
@test_throws ssh.SftpException mkpath(path, sftp)
end

# Test mv()
mktempdir() do tmpdir
src = joinpath(tmpdir, "foo")
Expand Down Expand Up @@ -984,6 +999,7 @@ end
@test_throws ArgumentError readdir("/tmp", sftp)
@test_throws ArgumentError rm("/tmp", sftp)
@test_throws ArgumentError mkdir("/tmp", sftp)
@test_throws ArgumentError mkpath("/tmp", sftp)
@test_throws ArgumentError mv("foo", "bar", sftp)
end
end
Expand Down

0 comments on commit 88a3193

Please sign in to comment.