Advertisement
Guest User

Untitled

a guest
Jul 31st, 2017
63
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 5.97 KB | None | 0 0
  1. #!/usr/bin/env ruby
  2.  
  3. require 'net/ftp'
  4. require 'fileutils'
  5. require 'abbrev'
  6.  
  7. $stdout.sync = true
  8. Thread.abort_on_exception = true
  9.  
  10. class Float
  11. def mformat
  12. tmp = to_s.split('.')
  13. [tmp.first, tmp.last[0..2]].join('.')
  14. end
  15. end
  16.  
  17. class FTPSync
  18. def initialize server, user = 'anonymous', pass = 'anoymous'
  19. Net::FTP.open(server, user, pass) do |@ftp|
  20. walk '/'
  21. end
  22. end
  23.  
  24. def walk path = '/'
  25. puts @ftp.pwd
  26. fetch_listing(path).each do |node|
  27. begin
  28. walk(File.join(node.path, node.name)) if node.directory?
  29. download(node) if node.file?
  30. rescue Net::FTPPermError => ex
  31. puts "#{ex} for walking #{path}"
  32. rescue Net::FTPTempError => ex
  33. puts "#{ex} retry..."
  34. retry
  35. rescue Object => ex
  36. puts ex
  37. puts ex.backtrace
  38. end
  39. end
  40. @ftp.sendcmd('cdup')
  41. end
  42.  
  43. def fetch_listing path
  44. @ftp.sendcmd("cwd #{path}")
  45. list = @ftp.list('*')
  46. list.map do |line|
  47. FTPNode.new(line, path)
  48. end
  49. end
  50.  
  51. def download node
  52. mode = node.mode
  53. unless mode == :ignore
  54. unless node.downloaded?
  55. puts "download #{node.filename} (#{node.size} bytes | #{node.in_mb}MB) to #{node.local_file}"
  56. puts @ftp.send("get#{mode}file", node.name, node.local_file)
  57. end
  58. end
  59. end
  60. end
  61.  
  62. class FTPNode
  63. BINARY_EXTS = %w[ gz bz bz2 iso img png jpg gif exe torrent Z svg ]
  64. TEXT_EXTS = %w[ txt md5sum README MD5SUMS c ]
  65.  
  66. def initialize line, path
  67. @line = line
  68. @path = path
  69. end
  70.  
  71. def local_path
  72. local_path = File.expand_path(File.join('./', path))
  73. end
  74.  
  75. def local_file
  76. local_file = File.join(local_path, name)
  77. end
  78.  
  79. def local_size
  80. prepare_local
  81. File.size(local_file)
  82. end
  83.  
  84. def prepare_local
  85. unless File.exist?(local_file)
  86. FileUtils.mkdir_p(local_path)
  87. FileUtils.touch(local_file)
  88. end
  89. end
  90.  
  91. def downloaded?
  92. local_size == size
  93. end
  94.  
  95. def path
  96. @path
  97. end
  98.  
  99. def filename
  100. [@path, name].join('/').squeeze('/')
  101. end
  102.  
  103. def name
  104. @name ||=
  105. @line.split.last
  106. end
  107.  
  108. def mode
  109. @mode ||=
  110. if kind == :file
  111. case ext
  112. when *BINARY_EXTS
  113. :binary
  114. when *TEXT_EXTS
  115. :text
  116. when ''
  117. :text
  118. else
  119. ask_mode
  120. end
  121. else
  122. nil
  123. end
  124. end
  125.  
  126. def ext
  127. @ext ||=
  128. File.extname(name).gsub('.', '')
  129. end
  130.  
  131. def ask_mode
  132. puts "I couldn't determine the mode to use for #{name}"
  133. puts "Please choose between (b)inary and (t)ext"
  134. got = gets.strip
  135. chosen = %w[binary text].abbrev[got]
  136. if chosen == 'binary'
  137. BINARY_MODES << ext
  138. elsif chosen == 'text'
  139. TEXT_MODES << ext
  140. else
  141. puts "no valid answer, try again :)"
  142. ask_mode
  143. end
  144. chosen.to_sym
  145. end
  146.  
  147. def size
  148. @size ||=
  149. @line.split[4].to_i
  150. end
  151.  
  152. def in_mb
  153. @in_mb ||=
  154. (size / 1024.0 / 1024.0).mformat
  155. end
  156.  
  157. def kind
  158. @kind ||=
  159. case @line[0,1]
  160. when 'd' : :directory
  161. when 'l' : :link
  162. when '-' : :file
  163. end
  164. end
  165.  
  166. def directory?
  167. kind == :directory
  168. end
  169.  
  170. def file?
  171. kind == :file
  172. end
  173.  
  174. def link?
  175. kind == :link
  176. end
  177. end
  178.  
  179.  
  180. FTPSync.new('ftp.archlinux.org', 'anonymous', 'anonymous')
  181.  
  182. =begin
  183. Net::FTP.open('ftp.archlinux.org', 'anonymous', 'anonymous') do |ftp|
  184. trap('SIGINT'){ ftp.sendcmd('QUIT'); exit }
  185.  
  186. walker = lambda do |path|
  187. puts "walking #{path}"
  188. puts ftp.sendcmd("cwd #{path}")
  189. puts ftp.pwd
  190. ftp.list('*').each do |line|
  191. begin
  192. splat = line.split
  193. node = splat.last
  194. kind = line[0,1]
  195. if kind == 'd' # directory
  196. walker[node]
  197. elsif kind == 'l' # link
  198. walker[node]
  199. else # file
  200. mode =
  201. case File.extname(node)
  202. when '.gz', '.iso', '.img', '.png', '.jpg', '.gif'
  203. :binary
  204. when '.torrent'
  205. :ignore
  206. else
  207. :text
  208. end
  209. local_path = File.join('./', ftp.pwd)
  210. local_file = File.join(local_path, File.basename(node))
  211. remote_size = splat[4].to_f
  212. r_mb = (remote_size / 1024 / 1024).mformat
  213.  
  214. FileUtils.mkdir_p(local_path)
  215. FileUtils.touch(local_file) unless File.exists?(local_file)
  216.  
  217. local_size = File.size(local_file).to_f
  218.  
  219. if local_size == remote_size
  220. puts "got #{node} already"
  221. elsif mode == :ignore
  222. puts "ignoring #{node}"
  223. else
  224. puts "downloading #{node} (#{remote_size} bytes) in #{mode} Mode"
  225.  
  226. width = `stty size`.split.last.to_i - 50
  227.  
  228. t = Thread.new do
  229. this = Thread.current
  230. progress = 0.0
  231. until local_size >= remote_size
  232. local_size = File.size(local_file).to_f
  233.  
  234. l_mb = ( local_size / 1024 / 1024).mformat
  235. percentage = ((local_size / remote_size) * 100).mformat
  236. progress = ( local_size / remote_size) * width
  237.  
  238. bar = "["
  239. ("=" * progress)
  240. ("." * (width - progress))
  241. "]"
  242. "[#{l_mb.ljust(r_mb.size)}/#{r_mb}MB | #{percentage}%]"
  243.  
  244. print bar
  245. sleep 0.1
  246. print "\b" * bar.size
  247. end
  248. end
  249. ftp.send("get#{mode}file", node, local_file)
  250. t.join
  251. puts
  252. end
  253. end
  254. rescue Net::FTPPermError => ex
  255. puts "#{ex} for walking #{path}"
  256. rescue Net::FTPTempError => ex
  257. puts "#{ex} retry..."
  258. retry
  259. rescue Object => ex
  260. puts ex
  261. puts ex.backtrace
  262. end
  263. end
  264. puts ftp.sendcmd('cdup')
  265. end
  266.  
  267. walker['/']
  268. end
  269. =end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement