Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SFTP mkpath() and other things #30

Merged
merged 4 commits into from
Dec 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 @@

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 @@
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 @@
: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 @@
# We can't continue if they don't accept the key
return ret
end
elseif ret == AuthStatus_Success

Check warning on line 871 in src/session.jl

View check run for this annotation

Codecov / codecov/patch

src/session.jl#L871

Added line #L871 was not covered by tests
# 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
Loading