Class: Bard::Copy

Inherits:
Struct
  • Object
show all
Defined in:
lib/bard/copy.rb

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#fromObject

Returns the value of attribute from

Returns:

  • (Object)

    the current value of from



5
6
7
# File 'lib/bard/copy.rb', line 5

def from
  @from
end

#pathObject

Returns the value of attribute path

Returns:

  • (Object)

    the current value of path



5
6
7
# File 'lib/bard/copy.rb', line 5

def path
  @path
end

#toObject

Returns the value of attribute to

Returns:

  • (Object)

    the current value of to



5
6
7
# File 'lib/bard/copy.rb', line 5

def to
  @to
end

#verboseObject

Returns the value of attribute verbose

Returns:

  • (Object)

    the current value of verbose



5
6
7
# File 'lib/bard/copy.rb', line 5

def verbose
  @verbose
end

Class Method Details

.dir(path, from:, to:, verbose: false) ⇒ Object



10
11
12
# File 'lib/bard/copy.rb', line 10

def self.dir path, from:, to:, verbose: false
  new(path, from, to, verbose).rsync
end

.file(path, from:, to:, verbose: false) ⇒ Object



6
7
8
# File 'lib/bard/copy.rb', line 6

def self.file path, from:, to:, verbose: false
  new(path, from, to, verbose).scp
end

Instance Method Details

#rsyncObject



54
55
56
57
58
59
60
61
62
# File 'lib/bard/copy.rb', line 54

def rsync
  if from.key == :local
    rsync_using_local :to, to
  elsif to.key == :local
    rsync_using_local :from, from
  else
    rsync_as_mediator
  end
end

#rsync_as_mediatorObject

Raises:

  • (NotImplementedError)


94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
# File 'lib/bard/copy.rb', line 94

def rsync_as_mediator
  from_server = from.respond_to?(:server) ? from.server : from
  to_server = to.respond_to?(:server) ? to.server : to

  raise NotImplementedError if from_server.gateway || to_server.gateway || from_server.ssh_key || to_server.ssh_key

  # Get ssh_uri - it might be a URI object (old Server), string (new SSHServer), or mock
  from_uri_value = from_server.respond_to?(:ssh_uri) ? from_server.ssh_uri : nil
  if from_uri_value.respond_to?(:port)
    from_uri = from_uri_value
  elsif from_uri_value.is_a?(String)
    from_uri = URI("ssh://#{from_uri_value}")
  else
    from_uri = from_uri_value
  end

  to_uri_value = to_server.respond_to?(:ssh_uri) ? to_server.ssh_uri : nil
  if to_uri_value.respond_to?(:port)
    to_uri = to_uri_value
  elsif to_uri_value.is_a?(String)
    to_uri = URI("ssh://#{to_uri_value}")
  else
    to_uri = to_uri_value
  end

  from_str = "-p#{from_uri.port || 22} #{from_uri.user}@#{from_uri.host}"
  to_str = to.rsync_uri(path).sub(%r(/[^/]+$), '/')

  command = %(ssh -A #{from_str} 'rsync -e \"ssh -A -p#{to_uri.port || 22} -o StrictHostKeyChecking=no -o LogLevel=ERROR\" --delete --info=progress2 -az #{from.path}/#{path} #{to_str}')
  Bard::Command.run! command, verbose: verbose
end

#rsync_using_local(direction, target_or_server) ⇒ Object



64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
# File 'lib/bard/copy.rb', line 64

def rsync_using_local direction, target_or_server
  # Support both new Target (with server attribute) and old Server
  ssh_server = target_or_server.respond_to?(:server) ? target_or_server.server : target_or_server

  # Get ssh_uri - it might be a URI object (old Server), string (new SSHServer), or mock
  ssh_uri_value = ssh_server.respond_to?(:ssh_uri) ? ssh_server.ssh_uri : nil
  if ssh_uri_value.respond_to?(:port)
    # Already a URI-like object (old Server or mock)
    ssh_uri = ssh_uri_value
  elsif ssh_uri_value.is_a?(String)
    # String from new SSHServer
    ssh_uri = URI("ssh://#{ssh_uri_value}")
  else
    # Fallback
    ssh_uri = ssh_uri_value
  end

  gateway = ssh_server.gateway ? "-oProxyCommand=\"ssh #{ssh_server.gateway} -W %h:%p\"" : ""

  ssh_key = ssh_server.ssh_key ? "-i #{ssh_server.ssh_key}" : ""
  ssh = "-e'ssh #{gateway} -p#{ssh_uri.port || 22}'"

  from_and_to = ["./#{path}", target_or_server.rsync_uri(path)]
  from_and_to.reverse! if direction == :from
  from_and_to[-1].sub! %r(/[^/]+$), '/'

  command = "rsync #{ssh} --delete --info=progress2 -az #{from_and_to.join(" ")}"
  Bard::Command.run! command, verbose: verbose
end

#scpObject



14
15
16
17
18
19
20
21
22
# File 'lib/bard/copy.rb', line 14

def scp
  if from.key == :local
    scp_using_local :to, to
  elsif to.key == :local
    scp_using_local :from, from
  else
    scp_as_mediator
  end
end

#scp_as_mediatorObject

Raises:

  • (NotImplementedError)


45
46
47
48
49
50
51
52
# File 'lib/bard/copy.rb', line 45

def scp_as_mediator
  from_server = from.respond_to?(:server) ? from.server : from
  to_server = to.respond_to?(:server) ? to.server : to

  raise NotImplementedError if from_server.gateway || to_server.gateway || from_server.ssh_key || to_server.ssh_key
  command = "scp -o ForwardAgent=yes #{from.scp_uri(path)} #{to.scp_uri(path)}"
  Bard::Command.run! command, verbose: verbose
end

#scp_using_local(direction, target_or_server) ⇒ Object



24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
# File 'lib/bard/copy.rb', line 24

def scp_using_local direction, target_or_server
  # Support both new Target (with server attribute) and old Server
  ssh_server = target_or_server.respond_to?(:server) ? target_or_server.server : target_or_server

  gateway = ssh_server.gateway ? "-oProxyCommand='ssh #{ssh_server.gateway} -W %h:%p'" : ""

  ssh_key = ssh_server.ssh_key ? "-i #{ssh_server.ssh_key}" : ""

  ssh_opts = "-o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o LogLevel=ERROR"

  # scp uses -P for port (uppercase, unlike ssh's -p)
  port = ssh_server.port
  port_opt = port && port.to_s != "22" ? "-P #{port}" : ""

  from_and_to = [path, target_or_server.scp_uri(path)]
  from_and_to.reverse! if direction == :from

  command = ["scp", ssh_opts, gateway, ssh_key, port_opt, *from_and_to].reject(&:empty?).join(" ")
  Bard::Command.run! command, verbose: verbose
end