Skip to content

Commit

Permalink
Add typespecs for Upload
Browse files Browse the repository at this point in the history
  • Loading branch information
pmeinhardt committed Dec 26, 2020
1 parent ef90bcb commit 412970c
Show file tree
Hide file tree
Showing 3 changed files with 23 additions and 13 deletions.
2 changes: 1 addition & 1 deletion examples/upload.exs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

:ok =
conn
|> SSHKit.upload!("test/fixtures", "/tmp/fixtures", recursive: true)
|> SSHKit.upload!("test/fixtures", "/tmp/fixtures")
|> Stream.run()

:ok = SSHKit.close(conn)
2 changes: 1 addition & 1 deletion lib/sshkit/transfer.ex
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ defmodule SSHKit.Transfer do
if module.done?(transfer) do
{:halt, transfer}
else
{:ok, transfer} = module.continue(transfer)
{:ok, transfer} = module.step(transfer)
{[transfer], transfer}
end
end,
Expand Down
32 changes: 21 additions & 11 deletions lib/sshkit/upload.ex
Original file line number Diff line number Diff line change
Expand Up @@ -3,38 +3,43 @@ defmodule SSHKit.Upload do
TODO
"""

alias SSHKit.Connection
alias SSHKit.SFTP.Channel

defstruct [:source, :target, :options, :cwd, :stack, :channel]

@type t() :: %__MODULE__{}

@spec init(binary(), binary(), keyword()) :: t()
def init(source, target, options \\ []) do
%__MODULE__{source: Path.expand(source), target: target, options: options}
end

@spec start(t(), Connection.t()) :: {:ok, t()} | {:error, term()}
def start(%__MODULE__{options: options} = upload, conn) do
# accepts options like timeout… http://erlang.org/doc/man/ssh_sftp.html#start_channel-1
start_options =
options
|> Keyword.get(:start, [])
|> Keyword.put_new(:timeout, Keyword.get(options, :timeout, :infinity))

with {:ok, upload} <- prepare(upload),
with {:ok, upload} <- preflight(upload),
{:ok, chan} <- Channel.start(conn, start_options) do
{:ok, %{upload | channel: chan}}
end
end

defp prepare(%__MODULE__{source: source, options: options} = upload) do
if !Keyword.get(options, :recursive, false) && File.dir?(source) do
# TODO: Better error
{:error, "Option :recursive not specified, but local file is a directory (#{source})"}
else
defp preflight(%__MODULE__{source: source, options: options} = upload) do
if File.exists?(source) do
{:ok, %{upload | cwd: Path.dirname(source), stack: [[Path.basename(source)]]}}
else
{:error, :enoent}
end
end

@spec stop(t()) :: {:ok, t()} | {:error, term()}
def stop(upload)

def stop(%__MODULE__{channel: nil} = upload), do: {:ok, upload}

def stop(%__MODULE__{channel: chan} = upload) do
Expand All @@ -45,15 +50,18 @@ defmodule SSHKit.Upload do

# TODO: Handle unstarted uploads w/o channel, cwd, stack… and provide helpful error?

def continue(%__MODULE__{stack: []} = upload) do
@spec step(t()) :: {:ok, t()} | {:error, term()}
def step(upload)

def step(%__MODULE__{stack: []} = upload) do
{:ok, upload}
end

def continue(%__MODULE__{stack: [[] | paths]} = upload) do
def step(%__MODULE__{stack: [[] | paths]} = upload) do
{:ok, %{upload | cwd: Path.dirname(upload.cwd), stack: paths}}
end

def continue(%__MODULE__{stack: [[name | rest] | paths]} = upload) do
def step(%__MODULE__{stack: [[name | rest] | paths]} = upload) do
path = Path.join(upload.cwd, name)
relpath = Path.relative_to(path, upload.source)
relpath = if relpath == path, do: ".", else: relpath
Expand Down Expand Up @@ -101,6 +109,8 @@ defmodule SSHKit.Upload do
|> Enum.find(:ok, &(&1 != :ok))
end

def done?(%{stack: []}), do: true
def done?(%{}), do: false
@spec done?(t()) :: boolean()
def done?(upload)
def done?(%__MODULE__{stack: []}), do: true
def done?(%__MODULE__{}), do: false
end

0 comments on commit 412970c

Please sign in to comment.