outatime 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +9 -0
- data/.rspec +2 -0
- data/.travis.yml +5 -0
- data/Gemfile +4 -0
- data/LICENSE +21 -0
- data/README.md +42 -0
- data/Rakefile +6 -0
- data/bin/outatime +31 -0
- data/lib/outatime.rb +20 -0
- data/lib/outatime/cli.rb +35 -0
- data/lib/outatime/fetcher.rb +142 -0
- data/lib/outatime/version.rb +3 -0
- data/outatime.gemspec +35 -0
- metadata +208 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: ad66a0137663ddd2acc6eb4d723360557dd39c9b
|
4
|
+
data.tar.gz: dbf910aa8229373c9d7d305ab83abcb82c67fcad
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: d85e34909a6fd7b71555565e207519fe537c3b416ca625ea5b93b96fa38428c9ecb5eede76812525fb62a326149de5652dfebb592cfc388bedbb10f0d893cc57
|
7
|
+
data.tar.gz: 34f8bc3d299908d13c035475c1a8e21eaf8d53bd0dadc049bc9776723cf62782864b39993da1c8dce37f1e768616cff2fa690bd2d7e91b1f7d231d34e7652a86
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
MIT License
|
2
|
+
|
3
|
+
Copyright (c) 2016 Pressed.net
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
# Outatime
|
2
|
+
|
3
|
+
For users of versioned AWS S3 buckets. This command-line tool will allow you to download a snapshot of the files in that bucket from a given point in time.
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
```ruby
|
10
|
+
gem 'outatime'
|
11
|
+
```
|
12
|
+
|
13
|
+
And then execute:
|
14
|
+
|
15
|
+
$ bundle
|
16
|
+
|
17
|
+
Or install it yourself as:
|
18
|
+
|
19
|
+
$ gem install outatime
|
20
|
+
|
21
|
+
## Usage
|
22
|
+
|
23
|
+
```
|
24
|
+
outatime -r {region} -b {bucket-name} -f {date} -p {subdirectory} --profile {aws profile name}
|
25
|
+
```
|
26
|
+
|
27
|
+
Example:
|
28
|
+
```
|
29
|
+
outatime -r us-east-1 -b my-bucket -f '21 Oct 2015' -p schematics/hoverboard --profile aws-profile
|
30
|
+
```
|
31
|
+
|
32
|
+
## Development
|
33
|
+
|
34
|
+
After checking out the repo, run `bundle` to install dependencies. Then, run `rake spec` to run the tests.
|
35
|
+
|
36
|
+
## Contributing
|
37
|
+
|
38
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/pressednet/outatime.
|
39
|
+
|
40
|
+
## LICENSE
|
41
|
+
|
42
|
+
MIT License, see [LICENSE](LICENSE) for details.
|
data/Rakefile
ADDED
data/bin/outatime
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require_relative '../lib/outatime'
|
4
|
+
|
5
|
+
begin
|
6
|
+
options = Trollop::options do
|
7
|
+
opt :region, "AWS region", type: :string, default: "us-west-2"
|
8
|
+
opt :bucket, "Bucket name", type: :string, required: true
|
9
|
+
opt :from, "Time description", type: :string, required: true
|
10
|
+
opt :prefix, "Restore files from this prefix", type: :string, default: ""
|
11
|
+
opt :destination, "Destination for restored files", type: :string, required: true
|
12
|
+
opt :profile, "AWS Profile Name", type: :string, required: false, default: nil
|
13
|
+
opt :threads, "Number of download threads", type: :integer, default: 20
|
14
|
+
opt :verbose, "Verbose Mode", type: :boolean, default: false
|
15
|
+
end
|
16
|
+
|
17
|
+
if options[:profile]
|
18
|
+
Outatime.update_aws_profile(
|
19
|
+
region: options[:region],
|
20
|
+
credentials: Aws::SharedCredentials.new(profile_name: options[:profile])
|
21
|
+
)
|
22
|
+
end
|
23
|
+
|
24
|
+
Outatime::CLI.new(options).run
|
25
|
+
|
26
|
+
rescue => e
|
27
|
+
raise e if $DEBUG
|
28
|
+
STDERR.puts e.message
|
29
|
+
STDERR.puts e.backtrace.join("\n")
|
30
|
+
exit 1
|
31
|
+
end
|
data/lib/outatime.rb
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
require "aws-sdk"
|
2
|
+
require "chronic"
|
3
|
+
require "pathname"
|
4
|
+
require "ruby-progressbar"
|
5
|
+
require "thread"
|
6
|
+
require "trollop"
|
7
|
+
require_relative "outatime/version"
|
8
|
+
require_relative "outatime/fetcher"
|
9
|
+
require_relative "outatime/cli"
|
10
|
+
|
11
|
+
module Outatime
|
12
|
+
# Public: Update AWS profile
|
13
|
+
#
|
14
|
+
# params - Hash of profile settings.
|
15
|
+
#
|
16
|
+
# Returns nothing.
|
17
|
+
def self.update_aws_profile(params)
|
18
|
+
Aws.config.update(params)
|
19
|
+
end
|
20
|
+
end
|
data/lib/outatime/cli.rb
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
module Outatime
|
2
|
+
class CLI
|
3
|
+
attr_accessor :options
|
4
|
+
|
5
|
+
# Public: It will fetch the correct version of a file from S3 and shows a
|
6
|
+
# progress bar to indicate its progress.
|
7
|
+
#
|
8
|
+
# options - The Hash options used to configure how fetcher works:
|
9
|
+
# :region - The AWS region.
|
10
|
+
# :bucket - The versioned bucket name.
|
11
|
+
# :from - Time description.
|
12
|
+
# :prefix - Restore files from this prefix.
|
13
|
+
# :destination - Destination for restored files
|
14
|
+
# :threads - Number of download threads
|
15
|
+
# :verbose - Verbose Mode
|
16
|
+
#
|
17
|
+
def initialize(options)
|
18
|
+
@options = options
|
19
|
+
end
|
20
|
+
|
21
|
+
# Public: Runs the fetcher and download the correct files version.
|
22
|
+
def run
|
23
|
+
fetcher = Outatime::Fetcher.new(options)
|
24
|
+
|
25
|
+
pb = ProgressBar.create(total: fetcher.total_size,
|
26
|
+
format: "%t: |%B| %f %c/%C %R MB/sec",
|
27
|
+
rate_scale: lambda { |rate| rate / 1024 / 1024 },
|
28
|
+
throttle_rate: 0.5)
|
29
|
+
|
30
|
+
fetcher.fetch! do |file|
|
31
|
+
pb.progress += file.size
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,142 @@
|
|
1
|
+
module Outatime
|
2
|
+
class Fetcher
|
3
|
+
attr_accessor :options
|
4
|
+
|
5
|
+
# Public: Fetcher will fetch the correct version of a file from S3.
|
6
|
+
#
|
7
|
+
# options - The Hash options used to configure how fetcher works:
|
8
|
+
# :bucket - The versioned bucket name (required).
|
9
|
+
# :destination - Destination for restored files (required).
|
10
|
+
# :from - Time description (required).
|
11
|
+
# :prefix - Restore files from this prefix.
|
12
|
+
# :s3_client - An existing Aws::S3::Client.
|
13
|
+
# :threads - Number of download threads
|
14
|
+
# :verbose - Verbose Mode
|
15
|
+
#
|
16
|
+
def initialize(options = {})
|
17
|
+
@options = options
|
18
|
+
@files_mutex = Mutex.new
|
19
|
+
@fetch_block_mutex = Mutex.new
|
20
|
+
@s3_client = options[:s3_client] if options[:s3_client]
|
21
|
+
@from = ::Chronic.parse(@options[:from]) if @options[:from]
|
22
|
+
|
23
|
+
# raise if the date/time was not parsed
|
24
|
+
raise ArgumentError, "The from time was not parseable." if @from.nil?
|
25
|
+
end
|
26
|
+
|
27
|
+
# Public: Fetches the file versions from S3 bucket.
|
28
|
+
#
|
29
|
+
# block - an optional block that receives the file description after it is
|
30
|
+
# downloaded to the local.
|
31
|
+
#
|
32
|
+
# Returns nothing.
|
33
|
+
def fetch!(&block)
|
34
|
+
fetch_objects(object_versions, &block)
|
35
|
+
end
|
36
|
+
|
37
|
+
# Public: Returns the objects total size.
|
38
|
+
#
|
39
|
+
# Returns an integer.
|
40
|
+
def total_size
|
41
|
+
object_versions.inject(0) { |sum, obj| sum += obj.size }
|
42
|
+
end
|
43
|
+
|
44
|
+
# Public: Fetch the S3 object versions.
|
45
|
+
#
|
46
|
+
# Returns an Array of Aws::S3::Types::ObjectVersion.
|
47
|
+
def object_versions
|
48
|
+
puts "fetching object versions from #{@from}" if verbose?
|
49
|
+
@files ||= begin
|
50
|
+
versions = []
|
51
|
+
delete_markers = []
|
52
|
+
|
53
|
+
s3_client.list_object_versions(bucket: @options[:bucket],
|
54
|
+
prefix: @options[:prefix]).each do |response|
|
55
|
+
|
56
|
+
versions += filter_future_items(response.versions, @from)
|
57
|
+
delete_markers += filter_future_items(response.delete_markers, @from)
|
58
|
+
end
|
59
|
+
|
60
|
+
# keep only the latest versions
|
61
|
+
# AWS lists the latest versions first, so it should be OK to use uniq here.
|
62
|
+
versions.uniq! { |obj| obj.key }
|
63
|
+
delete_markers.uniq! { |obj| obj.key }
|
64
|
+
|
65
|
+
delete_marker_keys = delete_markers.map { |dm| dm.key }
|
66
|
+
|
67
|
+
# check versions to see if we have newer delete_markers
|
68
|
+
# if so, delete those versions
|
69
|
+
versions.delete_if do |version|
|
70
|
+
if dm_index = delete_marker_keys.index(version.key)
|
71
|
+
if version.last_modified <= delete_markers[dm_index].last_modified
|
72
|
+
true
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
private
|
80
|
+
|
81
|
+
# Private: Checks if it is in verbose mode.
|
82
|
+
#
|
83
|
+
# Returns a boolean.
|
84
|
+
def verbose?
|
85
|
+
@options[:verbose]
|
86
|
+
end
|
87
|
+
|
88
|
+
# Private: Fetches the objects from S3 bucket.
|
89
|
+
#
|
90
|
+
# files - an Array of Aws::S3::Types::ObjectVersion.
|
91
|
+
#
|
92
|
+
# Returns nothing.
|
93
|
+
def fetch_objects(files)
|
94
|
+
threads = []
|
95
|
+
|
96
|
+
@options[:threads].times do
|
97
|
+
threads << Thread.new do
|
98
|
+
while !(file = @files_mutex.synchronize { files.pop }).nil? do
|
99
|
+
dest = Pathname.new("#{@options[:destination]}/#{file.key}")
|
100
|
+
|
101
|
+
if file.key.end_with?("/")
|
102
|
+
puts "Creating s3 subdirectory #{file.key} - #{Time.now}" if verbose?
|
103
|
+
dest.mkpath
|
104
|
+
else
|
105
|
+
dest.dirname.mkpath
|
106
|
+
|
107
|
+
puts "Copying from s3 #{file.key} - #{Time.now}" if verbose?
|
108
|
+
s3_client.get_object(response_target: "#{dest}",
|
109
|
+
bucket: @options[:bucket],
|
110
|
+
key: file.key,
|
111
|
+
version_id: file.version_id)
|
112
|
+
end
|
113
|
+
|
114
|
+
@fetch_block_mutex.synchronize { yield file } if block_given?
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
threads.map(&:join)
|
120
|
+
end
|
121
|
+
|
122
|
+
# Private: Creates the S3 client instance.
|
123
|
+
#
|
124
|
+
# Returns an Aws::S3::Client.
|
125
|
+
def s3_client
|
126
|
+
region = @options[:region] || ENV["AWS_REGION"]
|
127
|
+
@s3_client ||= Aws::S3::Client.new(region: region)
|
128
|
+
end
|
129
|
+
|
130
|
+
# Private: Returns an Array of items modified on or before the given date/time.
|
131
|
+
#
|
132
|
+
# items - An Array of objects. Object must respond to #last_modified.
|
133
|
+
# date_time - Comparison date/time.
|
134
|
+
#
|
135
|
+
# Returns Array.
|
136
|
+
def filter_future_items(items, date_time)
|
137
|
+
items.find_all do |obj|
|
138
|
+
obj.last_modified <= @from
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|
data/outatime.gemspec
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'outatime/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "outatime"
|
8
|
+
spec.version = Outatime::VERSION
|
9
|
+
spec.authors = ["Justin Mazzi", "Rubem Nakamura", "Mike Boone"]
|
10
|
+
spec.email = ["justin@pressed.net", "rubem.nakamura@pressed.net", "mike.boone@pressed.net"]
|
11
|
+
|
12
|
+
spec.summary = %q{Choose versioned S3 files from a point in time.}
|
13
|
+
spec.description = %q{Choose file versions from a versioned S3 bucket based on a given time.}
|
14
|
+
spec.homepage = "https://github.com/pressednet/outatime/"
|
15
|
+
spec.license = "MIT"
|
16
|
+
|
17
|
+
spec.files = `git ls-files -z`.split("\x0").reject do |f|
|
18
|
+
f.match(%r{^(test|spec|features)/})
|
19
|
+
end
|
20
|
+
spec.bindir = "bin"
|
21
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
22
|
+
spec.require_paths = ["lib"]
|
23
|
+
|
24
|
+
spec.add_runtime_dependency "aws-sdk", "~> 2.6", ">= 2.6.14"
|
25
|
+
spec.add_runtime_dependency "chronic", "~> 0.10.2"
|
26
|
+
spec.add_runtime_dependency "ruby-progressbar", "~> 1.8.1"
|
27
|
+
spec.add_runtime_dependency "thread", "~> 0.2.2"
|
28
|
+
spec.add_runtime_dependency "trollop", "~> 2.1.2"
|
29
|
+
|
30
|
+
spec.add_development_dependency "bundler", "~> 1.13"
|
31
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
32
|
+
spec.add_development_dependency "rspec", "~> 3.0"
|
33
|
+
spec.add_development_dependency "activesupport", "~> 5.0.0"
|
34
|
+
spec.add_development_dependency "byebug"
|
35
|
+
end
|
metadata
ADDED
@@ -0,0 +1,208 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: outatime
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.2.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Justin Mazzi
|
8
|
+
- Rubem Nakamura
|
9
|
+
- Mike Boone
|
10
|
+
autorequire:
|
11
|
+
bindir: bin
|
12
|
+
cert_chain: []
|
13
|
+
date: 2016-12-22 00:00:00.000000000 Z
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: aws-sdk
|
17
|
+
requirement: !ruby/object:Gem::Requirement
|
18
|
+
requirements:
|
19
|
+
- - "~>"
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '2.6'
|
22
|
+
- - ">="
|
23
|
+
- !ruby/object:Gem::Version
|
24
|
+
version: 2.6.14
|
25
|
+
type: :runtime
|
26
|
+
prerelease: false
|
27
|
+
version_requirements: !ruby/object:Gem::Requirement
|
28
|
+
requirements:
|
29
|
+
- - "~>"
|
30
|
+
- !ruby/object:Gem::Version
|
31
|
+
version: '2.6'
|
32
|
+
- - ">="
|
33
|
+
- !ruby/object:Gem::Version
|
34
|
+
version: 2.6.14
|
35
|
+
- !ruby/object:Gem::Dependency
|
36
|
+
name: chronic
|
37
|
+
requirement: !ruby/object:Gem::Requirement
|
38
|
+
requirements:
|
39
|
+
- - "~>"
|
40
|
+
- !ruby/object:Gem::Version
|
41
|
+
version: 0.10.2
|
42
|
+
type: :runtime
|
43
|
+
prerelease: false
|
44
|
+
version_requirements: !ruby/object:Gem::Requirement
|
45
|
+
requirements:
|
46
|
+
- - "~>"
|
47
|
+
- !ruby/object:Gem::Version
|
48
|
+
version: 0.10.2
|
49
|
+
- !ruby/object:Gem::Dependency
|
50
|
+
name: ruby-progressbar
|
51
|
+
requirement: !ruby/object:Gem::Requirement
|
52
|
+
requirements:
|
53
|
+
- - "~>"
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
version: 1.8.1
|
56
|
+
type: :runtime
|
57
|
+
prerelease: false
|
58
|
+
version_requirements: !ruby/object:Gem::Requirement
|
59
|
+
requirements:
|
60
|
+
- - "~>"
|
61
|
+
- !ruby/object:Gem::Version
|
62
|
+
version: 1.8.1
|
63
|
+
- !ruby/object:Gem::Dependency
|
64
|
+
name: thread
|
65
|
+
requirement: !ruby/object:Gem::Requirement
|
66
|
+
requirements:
|
67
|
+
- - "~>"
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: 0.2.2
|
70
|
+
type: :runtime
|
71
|
+
prerelease: false
|
72
|
+
version_requirements: !ruby/object:Gem::Requirement
|
73
|
+
requirements:
|
74
|
+
- - "~>"
|
75
|
+
- !ruby/object:Gem::Version
|
76
|
+
version: 0.2.2
|
77
|
+
- !ruby/object:Gem::Dependency
|
78
|
+
name: trollop
|
79
|
+
requirement: !ruby/object:Gem::Requirement
|
80
|
+
requirements:
|
81
|
+
- - "~>"
|
82
|
+
- !ruby/object:Gem::Version
|
83
|
+
version: 2.1.2
|
84
|
+
type: :runtime
|
85
|
+
prerelease: false
|
86
|
+
version_requirements: !ruby/object:Gem::Requirement
|
87
|
+
requirements:
|
88
|
+
- - "~>"
|
89
|
+
- !ruby/object:Gem::Version
|
90
|
+
version: 2.1.2
|
91
|
+
- !ruby/object:Gem::Dependency
|
92
|
+
name: bundler
|
93
|
+
requirement: !ruby/object:Gem::Requirement
|
94
|
+
requirements:
|
95
|
+
- - "~>"
|
96
|
+
- !ruby/object:Gem::Version
|
97
|
+
version: '1.13'
|
98
|
+
type: :development
|
99
|
+
prerelease: false
|
100
|
+
version_requirements: !ruby/object:Gem::Requirement
|
101
|
+
requirements:
|
102
|
+
- - "~>"
|
103
|
+
- !ruby/object:Gem::Version
|
104
|
+
version: '1.13'
|
105
|
+
- !ruby/object:Gem::Dependency
|
106
|
+
name: rake
|
107
|
+
requirement: !ruby/object:Gem::Requirement
|
108
|
+
requirements:
|
109
|
+
- - "~>"
|
110
|
+
- !ruby/object:Gem::Version
|
111
|
+
version: '10.0'
|
112
|
+
type: :development
|
113
|
+
prerelease: false
|
114
|
+
version_requirements: !ruby/object:Gem::Requirement
|
115
|
+
requirements:
|
116
|
+
- - "~>"
|
117
|
+
- !ruby/object:Gem::Version
|
118
|
+
version: '10.0'
|
119
|
+
- !ruby/object:Gem::Dependency
|
120
|
+
name: rspec
|
121
|
+
requirement: !ruby/object:Gem::Requirement
|
122
|
+
requirements:
|
123
|
+
- - "~>"
|
124
|
+
- !ruby/object:Gem::Version
|
125
|
+
version: '3.0'
|
126
|
+
type: :development
|
127
|
+
prerelease: false
|
128
|
+
version_requirements: !ruby/object:Gem::Requirement
|
129
|
+
requirements:
|
130
|
+
- - "~>"
|
131
|
+
- !ruby/object:Gem::Version
|
132
|
+
version: '3.0'
|
133
|
+
- !ruby/object:Gem::Dependency
|
134
|
+
name: activesupport
|
135
|
+
requirement: !ruby/object:Gem::Requirement
|
136
|
+
requirements:
|
137
|
+
- - "~>"
|
138
|
+
- !ruby/object:Gem::Version
|
139
|
+
version: 5.0.0
|
140
|
+
type: :development
|
141
|
+
prerelease: false
|
142
|
+
version_requirements: !ruby/object:Gem::Requirement
|
143
|
+
requirements:
|
144
|
+
- - "~>"
|
145
|
+
- !ruby/object:Gem::Version
|
146
|
+
version: 5.0.0
|
147
|
+
- !ruby/object:Gem::Dependency
|
148
|
+
name: byebug
|
149
|
+
requirement: !ruby/object:Gem::Requirement
|
150
|
+
requirements:
|
151
|
+
- - ">="
|
152
|
+
- !ruby/object:Gem::Version
|
153
|
+
version: '0'
|
154
|
+
type: :development
|
155
|
+
prerelease: false
|
156
|
+
version_requirements: !ruby/object:Gem::Requirement
|
157
|
+
requirements:
|
158
|
+
- - ">="
|
159
|
+
- !ruby/object:Gem::Version
|
160
|
+
version: '0'
|
161
|
+
description: Choose file versions from a versioned S3 bucket based on a given time.
|
162
|
+
email:
|
163
|
+
- justin@pressed.net
|
164
|
+
- rubem.nakamura@pressed.net
|
165
|
+
- mike.boone@pressed.net
|
166
|
+
executables:
|
167
|
+
- outatime
|
168
|
+
extensions: []
|
169
|
+
extra_rdoc_files: []
|
170
|
+
files:
|
171
|
+
- ".gitignore"
|
172
|
+
- ".rspec"
|
173
|
+
- ".travis.yml"
|
174
|
+
- Gemfile
|
175
|
+
- LICENSE
|
176
|
+
- README.md
|
177
|
+
- Rakefile
|
178
|
+
- bin/outatime
|
179
|
+
- lib/outatime.rb
|
180
|
+
- lib/outatime/cli.rb
|
181
|
+
- lib/outatime/fetcher.rb
|
182
|
+
- lib/outatime/version.rb
|
183
|
+
- outatime.gemspec
|
184
|
+
homepage: https://github.com/pressednet/outatime/
|
185
|
+
licenses:
|
186
|
+
- MIT
|
187
|
+
metadata: {}
|
188
|
+
post_install_message:
|
189
|
+
rdoc_options: []
|
190
|
+
require_paths:
|
191
|
+
- lib
|
192
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
193
|
+
requirements:
|
194
|
+
- - ">="
|
195
|
+
- !ruby/object:Gem::Version
|
196
|
+
version: '0'
|
197
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
198
|
+
requirements:
|
199
|
+
- - ">="
|
200
|
+
- !ruby/object:Gem::Version
|
201
|
+
version: '0'
|
202
|
+
requirements: []
|
203
|
+
rubyforge_project:
|
204
|
+
rubygems_version: 2.5.2
|
205
|
+
signing_key:
|
206
|
+
specification_version: 4
|
207
|
+
summary: Choose versioned S3 files from a point in time.
|
208
|
+
test_files: []
|