Module: UploadUtils

Defined in:
lib/proutils/icli/uploadutils.rb

Overview

Upload files to host. These means of uploading are current supported: ftp, sftp, scp and rsync.

user       Username for host.
host       Host server's domain name.
root       Document root path on host.
copy       Directory of files to publish, or
           Files to publish using from and to.

dryrun     If true only pretend to upload.
quiet      Supress all output.
verbose    Provide extra details.

The copy parameter allows you to simply specify a file or directory which will be published to host’s document root location.

If you need more control over which files to publish where, you can use the copy parameter instead. Provide an array of pattern strings in the form of “from to”. If the desitination is the host’s document root you do not need to specify the to part. For example:

copy = [ 'web/*', 'doc/api/* doc/api' ]

The first copies the files under your project’s web directory to the host’s document root. The second copies your projects doc/api files to the doc/api location on the host.

The internal template used for the outbound destination is ‘username@host:root/’.

Class Method Summary collapse

Class Method Details

.files(dir, copy) ⇒ Object

Put together the list of files to copy.



226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
# File 'lib/proutils/icli/uploadutils.rb', line 226

def files( dir, copy )
  Dir.chdir(dir) do
    del, add = copy.partition{ |f| /^[-]/ =~ f }

    # remove - and + prefixes
    del.collect!{ |f| f.sub(/^[-]/,'') }
    add.collect!{ |f| f.sub(/^[+]/,'') }

    #del.concat(must_exclude)

    files = []
    add.each{ |g| files += Dir.multiglob(g) }
    del.each{ |g| files -= Dir.multiglob(g) }

    files.collect!{ |f| f.sub(/^\//,'') }

    return files
  end
end

.ftp(keys) ⇒ Object

Use ftp to upload files.



62
63
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
93
94
# File 'lib/proutils/icli/uploadutils.rb', line 62

def ftp( keys )
  keys = upload_parameters(keys)

  # set transfer rules
  if keys.stage
    trans = stage_transfer(keys.stage)
  else
    files(keys.dir, keys.copy).each do |from|
      trans << [from,from]
    end
  end

  # append location of publication dir to from
  dir = keys.dir
  trans.collect!{ |from,to| [File.join(dir,from), to] }

  if keys.dryrun
    puts "ftp open #{keys.user}@#{keys.host}:#{keys.root}/"
    keys.trans.each do |f, t|
      puts "ftp put #{f} #{t}"
    end
  else
    require 'net/ftp'
    Net::FTP.open(keys.host) do |ftp|
      ftp.(keys.user) #password?
      ftp.chdir(keys.root)
      keys.trans.each do |f, t|
        puts "ftp #{f} #{t}" unless keys.quiet
        ftp.putbinaryfile( f, t, 1024 )
      end
    end
  end
end

.rsync(keys) ⇒ Object

Use rsync to upload files.



138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
# File 'lib/proutils/icli/uploadutils.rb', line 138

def rsync( keys )
  keys = upload_parameters(keys)

  flags = []
  flags << "-n" if keys.dryrun
  flags << "-q" if keys.quiet
  flags << "-v" if keys.verbose
  flags << "--progress" unless keys.quiet
  flags = flags.join(' ').strip
  flags = ' ' + flags unless flags.empty?

  manfile = 'Publish.txt'

  if keys.stage
    dir = stage_linkdir(keys.dir, keys.stage)
    Dir.chdir(dir) do
      cpy = files(keys.copy)
    end
    manifest = File.join(dir,manfile)
    cmd = %{rsync#{flags} -L -arz --files-from='#{manifest}' #{dir} #{keys.user}@#{keys.host}:/#{keys.root}}
  else
    dir = keys.dir
    cpy = files(dir, keys.copy)
    manifest = File.join(dir,manfile)
    cmd = %{rsync#{flags} -arz --files-from='#{manifest}' #{dir} #{keys.user}@#{keys.host}:/#{keys.root}}
  end

  #Dir.chdir(keys.dir) do
    begin
      File.open(manifest, 'w'){ |f| f << cpy.join("\n") }
      ENV['RSYNC_PASSWORD'] = keys.pass if keys.pass
      puts cmd unless keys.quiet
      system cmd
    ensure
      ENV.delete('RSYNC_PASSWORD') if keys.pass
    end
  #end

end

.sftp(keys) ⇒ Object

Use sftp to upload files.



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
125
126
127
128
129
130
131
132
# File 'lib/proutils/icli/uploadutils.rb', line 100

def sftp( keys )
  keys = upload_parameters(keys)

  # set transfer rules
  if keys.stage
    trans = stage_transfer(keys.stage)
  else
    files(keys.dir, keys.copy).each do |from|
      trans << [from,from]
    end
  end

  # append location of publication dir to from
  dir = keys.dir
  trans.collect!{ |from,to| [File.join(dir,from), to] }

  if keys.dryrun
    puts "sftp open #{keys.user}@#{keys.host}:#{keys.root}/"
    keys.trans.each do |f,t|
      puts "sftp put #{f} #{t}"
    end
  else
    require 'net/sftp'
    Net::SFTP.start(keys.host, keys.user, keys.pass) do |sftp|
      #sftp.login( user )
      sftp.chdir(keys.root)
      keys.trans.each do |f,t|
        puts "sftp #{f} #{t}" unless keys.quiet
        sftp.put_file(f,t) #, 1024 )
      end
    end
  end
end

.stage_linkdir(dir, list) ⇒ Object

When using stage options this will create temporary linked location.



272
273
274
275
276
277
278
279
280
281
282
283
284
# File 'lib/proutils/icli/uploadutils.rb', line 272

def stage_linkdir( dir, list )
  folder = File.join(Dir.tmpdir, 'ratchets', 'project', object_id.abs.to_s)
  FileUtils.mkdir_p(folder)

  Dir.chdir(dir) do
    stage_transfer(list).each do |file, to|
      link = File.join(folder,to)
      FileUtils.ln_s(link,file)
    end
  end

  return folder
end

.stage_transfer(list) ⇒ Object

Combine three part stage list into a two part from->to list.

Using the stage list of three space separated fields.

fromdir file todir

This is used to generate a from -> to list of the form:

fromdir/file todir/file


257
258
259
260
261
262
263
264
265
266
267
268
# File 'lib/proutils/icli/uploadutils.rb', line 257

def stage_transfer( list )
  trans = []
  list.each do |line|
    trans << Shellwords.shellwords(line)
  end

  trans.collect! do |from, base, to|
    file = File.join(from,base)
    to = File.join(to,base)
    [from, to]
  end
end

.upload(protocol, opts) ⇒ Object

Upload via given protocol.



54
55
56
# File 'lib/proutils/icli/uploadutils.rb', line 54

def upload( protocol, opts )
  send(protocol.to_s.downcase,opts)
end

.upload_parameters(keys) ⇒ Object

parse publishing options.

Raises:

  • (ArgumentError)


182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
# File 'lib/proutils/icli/uploadutils.rb', line 182

def upload_parameters( keys )
  keys = OpenObject.new(keys)

  keys.copy = keys.copy || '**/*'
  keys.host = keys.host || keys.domain
  keys.user = keys.user || keys.username
  keys.root = keys.root || '/'
  #keys.pass = keys.pass || keys.password

  # validate
  raise ArgumentError, "missing publish parameter -- dir" unless keys.dir
  raise ArgumentError, "missing publish parameter -- host" unless keys.host
  raise ArgumentError, "missing publish parameter -- user" unless keys.user
  #raise ArgumentError, "missing publish parameter -- copy" unless keys.copy
  #raise ArgumentError, "missing publish parameter -- root" unless keys.root

  keys.root = '' if keys.root.nil?
  keys.root.sub!(/^\//,'')

  if String===keys.copy and File.directory?(keys.copy)
    copy = File.join(keys.copy, '*')
  end
  keys.copy = [keys.copy].flatten.compact

#     trans = []
#     keys.copy.each do |from|
#       #from, to = *Shellwords.shellwords(c)
#       #to = from if to.nil?
#       #to = to[1..-1] if to[0,1] == '/'
#       from.sub('*','**/*') unless from =~ /\*\*/
#       files = Dir.glob(from)
#       files.each do |f|
#         #t = File.join(to,File.basename(f))
#         #t = t[1..-1] if t[0,1] == '/'
#         trans << [f,f]
#       end
#     end
#     keys.trans = trans

  return keys
end