siba-destination-ftp 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,5 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/*
5
+ *.swp
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in siba-destination-ftp.gemspec
4
+ gemspec
data/Guardfile ADDED
@@ -0,0 +1,9 @@
1
+ # A sample Guardfile
2
+ # More info at https://github.com/guard/guard#readme
3
+
4
+ guard 'minitest', :notify=>false do
5
+ watch(%r|^test/unit/(.*\/)*test_(.*)\.rb|)
6
+ watch(%r|^lib/siba-destination-ftp/(.*\/)*([^/]+)\.rb|) do |m|
7
+ "test/unit/#{m[1]}test_#{m[2]}.rb" unless m[2][0] == '.'
8
+ end
9
+ end
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2012 Evgeny Neumerzhitskiy
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,11 @@
1
+ # Overview
2
+
3
+ This is an extension for [SIBA backup and restore utility](https://github.com/evgenyneu/siba). It allows to use FTP as backup destination.
4
+
5
+ ## Installation
6
+
7
+ $ gem install siba-destination-ftp
8
+
9
+ ## Usage
10
+
11
+ Run `siba generate FILE` command to generate options file and select ftp as a destination plugin. Edit the generated file and set backup options.
data/Rakefile ADDED
@@ -0,0 +1,28 @@
1
+ require "bundler/gem_tasks"
2
+ require 'rake/testtask'
3
+
4
+ namespace "test" do
5
+ desc "Run all unit tests"
6
+ Rake::TestTask.new("unit") do |t|
7
+ t.pattern = "test/unit/**/test*.rb"
8
+ t.libs << 'test'
9
+ end
10
+
11
+ desc "Run all integration tests"
12
+ Rake::TestTask.new("integration") do |t|
13
+ t.pattern = "test/integration/**/i9n_*.rb"
14
+ t.libs << 'test'
15
+ end
16
+
17
+ desc "Run all integration tests"
18
+ task :i9n => ["test:integration"] do
19
+ end
20
+ end
21
+
22
+ desc "Run all unit tests"
23
+ task :test => ["test:unit"] do
24
+ end
25
+
26
+ desc "Run tests"
27
+ task :default => "test:unit"
28
+
@@ -0,0 +1,11 @@
1
+ # encoding: UTF-8
2
+
3
+ require "siba-destination-ftp/version"
4
+ require "siba-destination-ftp/init"
5
+
6
+ module Siba
7
+ module Destination
8
+ module Ftp
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,48 @@
1
+ # encoding: UTF-8
2
+
3
+ require 'siba-destination-ftp/worker'
4
+
5
+ module Siba::Destination
6
+ module Ftp
7
+ class Init
8
+ include Siba::LoggerPlug
9
+ attr_accessor :worker
10
+
11
+ DEFAULT_FTP_HOST_ENV_NAME = "SIBA_FTP_HOST"
12
+ DEFAULT_FTP_USER_ENV_NAME = "SIBA_FTP_USER"
13
+ DEFAULT_FTP_PASSWORD_ENV_NAME = "SIBA_FTP_PASSWORD"
14
+
15
+ def initialize(options)
16
+ host = Siba::SibaCheck.options_string options, "host"
17
+ user = Siba::SibaCheck.options_string options, "user", true, ENV[DEFAULT_FTP_USER_ENV_NAME]
18
+ password = Siba::SibaCheck.options_string options, "password", true, ENV[DEFAULT_FTP_PASSWORD_ENV_NAME]
19
+ directory = Siba::SibaCheck.options_string options, "dir", true, "/"
20
+ passive = Siba::SibaCheck.options_bool options, "passive", true, false
21
+ @worker = Siba::Destination::Ftp::Worker.new host, user, password, directory, passive
22
+ end
23
+
24
+ # Put backup file (path_to_backup_file) to destination
25
+ # No return value is expected
26
+ def backup(path_to_backup_file)
27
+ logger.info "Uploading backup to FTP: #{worker.user_host_and_dir}"
28
+ @worker.connect_and_put_file path_to_backup_file
29
+ end
30
+
31
+ # Shows the list of files stored currently at destination
32
+ # with file names starting with 'backup_name'
33
+ #
34
+ # Returns an array of two-element arrays:
35
+ # [backup_file_name, modification_time]
36
+ def get_backups_list(backup_name)
37
+ logger.info "Getting the list of backups from FTP: #{worker.user_host_and_dir}"
38
+ @worker.get_files_list backup_name
39
+ end
40
+
41
+ # Restoring: put backup file into dir
42
+ def restore(backup_name, dir)
43
+ logger.info "Downloading backup from FTP: #{worker.user_host_and_dir}"
44
+ @worker.connect_and_get_file backup_name, File.join(dir, backup_name)
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,6 @@
1
+ host: yourserver.com
2
+ user:
3
+ password:
4
+ dir: /sub/dir
5
+ passive: No # When 'Yes' the connection is in 'passive' mode
6
+ # Note: all fields except "host" are optional
@@ -0,0 +1,9 @@
1
+ # encoding: UTF-8
2
+
3
+ module Siba
4
+ module Destination
5
+ module Ftp
6
+ VERSION = "0.0.2"
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,133 @@
1
+ # encoding: UTF-8
2
+
3
+ require 'net/ftp'
4
+ require 'net/ftp/list'
5
+
6
+ module Siba::Destination
7
+ module Ftp
8
+ class Worker
9
+ include Siba::LoggerPlug
10
+ include Siba::FilePlug
11
+
12
+ attr_accessor :host, :user, :password, :directory, :passive
13
+
14
+ def initialize(host, user, password, directory, passive)
15
+ @host = host
16
+ @host = ENV[Siba::Destination::Ftp::Init::DEFAULT_FTP_HOST_ENV_NAME] if host.nil?
17
+
18
+ @user = user
19
+ @password = password
20
+ @directory = directory || "/"
21
+ @passive = passive
22
+
23
+ logger.info "Connecting to FTP server: #{host}"
24
+ check_connection
25
+ end
26
+
27
+ def check_connection
28
+ begin
29
+ connect do |ftp|
30
+ test_file ftp
31
+ logger.debug("FTP connection verified")
32
+ end
33
+ rescue
34
+ logger.error "Failed to connect to FTP server: #{user_host_and_dir}.
35
+ Please ensure your username/password are correct and you have read/write access to your FTP directory."
36
+ raise
37
+ end
38
+ end
39
+
40
+ def user_host_and_dir
41
+ str = "#{user.nil? ? "" : user + "@"}#{host}"
42
+ str += ", dir: '#{directory}'" unless directory.nil? || directory == "/"
43
+ str
44
+ end
45
+
46
+ def get_files_list(prefix)
47
+ connect do |ftp|
48
+ list = []
49
+ ftp.list do |e|
50
+ entry = Net::FTP::List.parse(e)
51
+
52
+ # Ignore everything that's not a file (so symlinks, directories and devices etc.)
53
+ next unless entry.file?
54
+ next unless entry.basename =~ /^#{prefix}/
55
+
56
+ list << [entry.basename, entry.mtime]
57
+ end
58
+ list
59
+ end
60
+ end
61
+
62
+ def connect_and_put_file(path_to_file)
63
+ connect do |ftp|
64
+ put_file ftp, path_to_file
65
+ end
66
+ end
67
+
68
+ def put_file(ftp, path_to_file)
69
+ ftp.putbinaryfile path_to_file
70
+ end
71
+
72
+ def connect_and_get_file(remote_file_name, path_to_destination_file)
73
+ connect do |ftp|
74
+ get_file ftp, remote_file_name, path_to_destination_file
75
+ end
76
+ end
77
+
78
+ def get_file(ftp, remote_file_name, path_to_destination_file)
79
+ ftp.getbinaryfile remote_file_name, path_to_destination_file
80
+ end
81
+
82
+ def connect_and_delete_file(remote_file_name)
83
+ connect do |ftp|
84
+ delete_file ftp, remote_file_name
85
+ end
86
+ end
87
+
88
+ def delete_file(ftp, remote_file_name)
89
+ ftp.delete(remote_file_name)
90
+ end
91
+
92
+ def cd(ftp)
93
+ directory.gsub! "\\","/"
94
+ begin
95
+ ftp.chdir(subdir) # try to change to full subdir first
96
+ rescue
97
+ directories = directory.split("/")
98
+ directories.each do |subdir|
99
+ ftp.mkdir(subdir) rescue nil
100
+ ftp.chdir(subdir)
101
+ end
102
+ end
103
+ end
104
+
105
+ def test_file(ftp)
106
+ src_file = Siba::TestFiles.prepare_test_file "test_ftp"
107
+ put_file ftp, src_file
108
+ src_to_check = Siba::TestFiles.generate_path "test_ftp_check"
109
+ remote_file_name = File.basename(src_file)
110
+ get_file ftp, remote_file_name, src_to_check
111
+ raise Siba::Error, "Failed to get test file" unless File.file? src_to_check
112
+ raise Siba::Error, "Error getting test files" unless FileUtils.compare_file(src_file, src_to_check)
113
+ delete_file ftp, remote_file_name
114
+ end
115
+
116
+ def connect(&block)
117
+ siba_file.run_this do
118
+ ftp = nil
119
+ begin
120
+ ftp = Net::FTP.open(host, user, password)
121
+ ftp.passive = passive
122
+ cd ftp
123
+ block.call(ftp)
124
+ ensure
125
+ unless ftp.nil?
126
+ ftp.close rescue nil
127
+ end
128
+ end
129
+ end
130
+ end
131
+ end
132
+ end
133
+ end
@@ -0,0 +1,26 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "siba-destination-ftp/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "siba-destination-ftp"
7
+ s.version = Siba::Destination::Ftp::VERSION
8
+ s.authors = ["Evgeny Neumerzhitskiy"]
9
+ s.email = ["sausageskin@gmail.com"]
10
+ s.homepage = "https://github.com/evgenyneu/siba-destination-ftp"
11
+ s.license = "MIT"
12
+ s.summary = %q{An FTP extension to SIBA backup and restore utility}
13
+ s.description = %q{An extension to SIBA backup and restore utility. Adds FTP as a backup destination.}
14
+
15
+ s.files = `git ls-files`.split("\n")
16
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
17
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
18
+ s.require_paths = ["lib"]
19
+
20
+ s.add_runtime_dependency 'siba', '~>0.5'
21
+ s.add_runtime_dependency 'net-ftp-list', '~>3.2'
22
+
23
+ s.add_development_dependency 'minitest', '~>2.10'
24
+ s.add_development_dependency 'rake', '~>0.9'
25
+ s.add_development_dependency 'guard-minitest', '~>0.4'
26
+ end
@@ -0,0 +1,5 @@
1
+ # encoding: UTF-8
2
+
3
+ require 'siba/helpers/test/require'
4
+ SibaTest.init_integration
5
+
@@ -0,0 +1,4 @@
1
+ # encoding: UTF-8
2
+
3
+ require 'siba/helpers/test/require'
4
+ SibaTest.init_unit
@@ -0,0 +1,54 @@
1
+ # encoding: UTF-8
2
+
3
+ require 'helper/require_integration'
4
+ require 'siba-destination-ftp/init'
5
+
6
+ # Integration test example
7
+ # 'rake test:i9n' command runs integration tests
8
+ describe Siba::Destination::Ftp::Init do
9
+ before do
10
+ @test_dir = "siba_ftp_test/subdir"
11
+ @cls = Siba::Destination::Ftp::Init
12
+
13
+ host_env = @cls::DEFAULT_FTP_HOST_ENV_NAME
14
+ user_env = @cls::DEFAULT_FTP_USER_ENV_NAME
15
+ password_env = @cls::DEFAULT_FTP_PASSWORD_ENV_NAME
16
+
17
+ @host = ENV[host_env]
18
+ @user = ENV[user_env]
19
+ @password = ENV[password_env]
20
+
21
+ msg = "environment variable needs to be set in order to run integration tests"
22
+ flunk "#{host_env} #{msg}" unless @host
23
+ flunk "#{user_env} #{msg}" unless @user
24
+ flunk "#{password_env} #{msg}" unless @password
25
+ end
26
+
27
+ it "should backup and restore" do
28
+ ftp = @cls.new({"host" => @host, "directory"=>@test_dir})
29
+ src_backup = prepare_test_file "ftp_test"
30
+
31
+ # backup
32
+ ftp.backup src_backup
33
+ file_name = File.basename src_backup
34
+
35
+ # get list
36
+ list = ftp.get_backups_list file_name
37
+ list.size.must_equal 1
38
+ item = list[0]
39
+ item[0].must_equal file_name
40
+ item[1].must_be_instance_of Time
41
+
42
+ # restore
43
+ dest_backup_dir = mkdir_in_tmp_dir "restored_backup_dir"
44
+ dest_backup = File.join dest_backup_dir, file_name
45
+ ftp.restore file_name, dest_backup_dir
46
+
47
+ dest_backup.wont_equal src_backup
48
+ FileUtils.compare_file(src_backup, dest_backup).must_equal true
49
+
50
+ # remove test file
51
+ ftp.worker.connect_and_delete_file file_name
52
+ end
53
+
54
+ end
@@ -0,0 +1,73 @@
1
+ # encoding: UTF-8
2
+
3
+ require 'helper/require_unit'
4
+ require 'siba-destination-ftp/init'
5
+
6
+ # Unit test example
7
+ # 'rake' command runs unit tests
8
+ # 'guard' command will run unit tests automatically
9
+ describe Siba::Destination::Ftp do
10
+ before do
11
+ @cls = Siba::Destination::Ftp::Init
12
+ @yml_path = File.expand_path('../yml', __FILE__)
13
+ end
14
+
15
+ it "siba should load plugin" do
16
+ options_hash = load_options "valid"
17
+ plugin = @cls.new options_hash
18
+ plugin.must_be_instance_of Siba::Destination::Ftp::Init
19
+ plugin.worker.must_be_instance_of Siba::Destination::Ftp::Worker
20
+
21
+ plugin.worker.host.wont_be_nil
22
+ plugin.worker.host.must_equal options_hash["host"]
23
+ plugin.worker.user.wont_be_nil
24
+ plugin.worker.user.must_equal options_hash["user"]
25
+ plugin.worker.password.wont_be_nil
26
+ plugin.worker.password.must_equal options_hash["password"]
27
+ plugin.worker.directory.wont_be_nil
28
+ plugin.worker.directory.must_equal options_hash["dir"]
29
+ plugin.worker.passive.must_equal false
30
+ end
31
+
32
+ it "siba should load plugin with just host" do
33
+ @cls.new({"host" => "myhost"})
34
+ end
35
+
36
+ it "init should set passive mode" do
37
+ plugin = @cls.new({"host" => "myhost", "passive" => true})
38
+ plugin.worker.passive.must_equal true
39
+ end
40
+
41
+ it "siba should get user and password from environment variables" do
42
+ begin
43
+ env_user_prev = ENV[Siba::Destination::Ftp::Init::DEFAULT_FTP_USER_ENV_NAME]
44
+ env_password_prev = ENV[Siba::Destination::Ftp::Init::DEFAULT_FTP_PASSWORD_ENV_NAME]
45
+ user = "def user"
46
+ password = "def password"
47
+ ENV[Siba::Destination::Ftp::Init::DEFAULT_FTP_USER_ENV_NAME] = user
48
+ ENV[Siba::Destination::Ftp::Init::DEFAULT_FTP_PASSWORD_ENV_NAME] = password
49
+ plugin = @cls.new({"host" => "myhost"})
50
+ plugin.worker.user.must_equal user
51
+ plugin.worker.password.must_equal password
52
+ ensure
53
+ ENV[Siba::Destination::Ftp::Init::DEFAULT_FTP_USER_ENV_NAME] = env_user_prev
54
+ ENV[Siba::Destination::Ftp::Init::DEFAULT_FTP_PASSWORD_ENV_NAME] = env_password_prev
55
+ end
56
+ end
57
+
58
+ it "load should fail if no host" do
59
+ ->{@cls.new({})}.must_raise Siba::CheckError
60
+ end
61
+
62
+ it "should call backup" do
63
+ @cls.new({"host"=>"testhost"}).backup "path_to_backup"
64
+ end
65
+
66
+ it "should call get_backups_list" do
67
+ @cls.new({"host"=>"testhost"}).get_backups_list "backup_name"
68
+ end
69
+
70
+ it "should call restore" do
71
+ @cls.new({"host"=>"testhost"}).restore "backup_name", "/dir"
72
+ end
73
+ end
@@ -0,0 +1,70 @@
1
+ # encoding: UTF-8
2
+
3
+ require 'helper/require_unit'
4
+ require 'siba-destination-ftp/init'
5
+
6
+ describe Siba::Destination::Ftp::Worker do
7
+ before do
8
+ @cls = Siba::Destination::Ftp::Worker
9
+ @obj = @cls.new "host", nil, nil, nil, false
10
+ end
11
+
12
+ it "should init" do
13
+ host = "host"
14
+ user = "testuser"
15
+ password = "testpassword"
16
+ directory = "testdirectory"
17
+
18
+ worker = @cls.new host, user, password, directory, false
19
+ worker.host.must_equal host
20
+ worker.user.must_equal user
21
+ worker.password.must_equal password
22
+ worker.directory.must_equal directory
23
+ worker.passive.must_equal false
24
+ end
25
+
26
+ it "should call check_connection" do
27
+ @obj.check_connection
28
+ end
29
+
30
+ it "should set passive mode" do
31
+ @obj = @cls.new "host", nil, nil, nil, true
32
+ @obj.passive.must_equal true
33
+ end
34
+
35
+ it "should call user_host_and_dir" do
36
+ host = "myhost"
37
+ user = "myuser"
38
+ dir = "mydir"
39
+ @obj = @cls.new host, nil, nil, nil, false
40
+ str = @obj.user_host_and_dir
41
+ str.must_include host
42
+ str.wont_include "dir"
43
+
44
+ @obj = @cls.new host, user, nil, nil, false
45
+ @obj.user_host_and_dir.must_include user
46
+
47
+ @obj = @cls.new host, user, nil, dir, false
48
+ @obj.user_host_and_dir.must_include dir
49
+ end
50
+
51
+ it "should call connect_and_put_file" do
52
+ @obj.connect_and_put_file "file"
53
+ end
54
+
55
+ it "should call connect" do
56
+ @obj.connect
57
+ end
58
+
59
+ it "should call get_files_list" do
60
+ @obj.get_files_list "prefix"
61
+ end
62
+
63
+ it "should call connect_and_get_file" do
64
+ @obj.connect_and_get_file "file_name", "path_to_dest_file"
65
+ end
66
+
67
+ it "should call connect_and_delete_file" do
68
+ @obj.connect_and_delete_file "file_name"
69
+ end
70
+ end
@@ -0,0 +1,4 @@
1
+ host: myhost
2
+ user: myuser
3
+ password: mypassword
4
+ dir: mydir
metadata ADDED
@@ -0,0 +1,120 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: siba-destination-ftp
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.2
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Evgeny Neumerzhitskiy
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-02-12 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: siba
16
+ requirement: &76981360 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ~>
20
+ - !ruby/object:Gem::Version
21
+ version: '0.5'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: *76981360
25
+ - !ruby/object:Gem::Dependency
26
+ name: net-ftp-list
27
+ requirement: &76981120 !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
30
+ - - ~>
31
+ - !ruby/object:Gem::Version
32
+ version: '3.2'
33
+ type: :runtime
34
+ prerelease: false
35
+ version_requirements: *76981120
36
+ - !ruby/object:Gem::Dependency
37
+ name: minitest
38
+ requirement: &76980890 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ~>
42
+ - !ruby/object:Gem::Version
43
+ version: '2.10'
44
+ type: :development
45
+ prerelease: false
46
+ version_requirements: *76980890
47
+ - !ruby/object:Gem::Dependency
48
+ name: rake
49
+ requirement: &76980660 !ruby/object:Gem::Requirement
50
+ none: false
51
+ requirements:
52
+ - - ~>
53
+ - !ruby/object:Gem::Version
54
+ version: '0.9'
55
+ type: :development
56
+ prerelease: false
57
+ version_requirements: *76980660
58
+ - !ruby/object:Gem::Dependency
59
+ name: guard-minitest
60
+ requirement: &76980430 !ruby/object:Gem::Requirement
61
+ none: false
62
+ requirements:
63
+ - - ~>
64
+ - !ruby/object:Gem::Version
65
+ version: '0.4'
66
+ type: :development
67
+ prerelease: false
68
+ version_requirements: *76980430
69
+ description: An extension to SIBA backup and restore utility. Adds FTP as a backup
70
+ destination.
71
+ email:
72
+ - sausageskin@gmail.com
73
+ executables: []
74
+ extensions: []
75
+ extra_rdoc_files: []
76
+ files:
77
+ - .gitignore
78
+ - Gemfile
79
+ - Guardfile
80
+ - LICENSE
81
+ - README.md
82
+ - Rakefile
83
+ - lib/siba-destination-ftp.rb
84
+ - lib/siba-destination-ftp/init.rb
85
+ - lib/siba-destination-ftp/options.yml
86
+ - lib/siba-destination-ftp/version.rb
87
+ - lib/siba-destination-ftp/worker.rb
88
+ - siba-destination-ftp.gemspec
89
+ - test/helper/require_integration.rb
90
+ - test/helper/require_unit.rb
91
+ - test/integration/i9n_init.rb
92
+ - test/unit/test_init.rb
93
+ - test/unit/test_worker.rb
94
+ - test/unit/yml/valid.yml
95
+ homepage: https://github.com/evgenyneu/siba-destination-ftp
96
+ licenses:
97
+ - MIT
98
+ post_install_message:
99
+ rdoc_options: []
100
+ require_paths:
101
+ - lib
102
+ required_ruby_version: !ruby/object:Gem::Requirement
103
+ none: false
104
+ requirements:
105
+ - - ! '>='
106
+ - !ruby/object:Gem::Version
107
+ version: '0'
108
+ required_rubygems_version: !ruby/object:Gem::Requirement
109
+ none: false
110
+ requirements:
111
+ - - ! '>='
112
+ - !ruby/object:Gem::Version
113
+ version: '0'
114
+ requirements: []
115
+ rubyforge_project:
116
+ rubygems_version: 1.8.11
117
+ signing_key:
118
+ specification_version: 3
119
+ summary: An FTP extension to SIBA backup and restore utility
120
+ test_files: []