change_agent 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +22 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +68 -0
- data/Rakefile +14 -0
- data/change_agent.gemspec +26 -0
- data/lib/change_agent.rb +12 -0
- data/lib/change_agent/client.rb +37 -0
- data/lib/change_agent/document.rb +63 -0
- data/lib/change_agent/version.rb +3 -0
- data/script/bootstrap +1 -0
- data/script/cibuild +1 -0
- data/script/console +1 -0
- data/script/release +38 -0
- data/test/helper.rb +17 -0
- data/test/test_change_agent.rb +12 -0
- data/test/test_change_agent_client.rb +64 -0
- data/test/test_change_agent_document.rb +79 -0
- metadata +151 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: b77277230a8527bd86be1e4caa5500834b9aef1b
|
4
|
+
data.tar.gz: 43b6adf0ecc54612020d28b9050970cd3279b4c6
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 308dc37a2ce06801aac82ee1bde0113ee23181bc40c3cf0093f72bf03b3c4c47a4f8672f53b4e032d25c596e217428b1590da20b530054ab35b36f2dbe73a3e0
|
7
|
+
data.tar.gz: 26a15963bff1938fdd7418169dfd9bdf0b7e731ba17b527032800e87a209e12340850cb96fe8bd7969071d1b53f69670c7e770344919d997db11b3ea9f3ff721
|
data/.gitignore
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
*.gem
|
2
|
+
*.rbc
|
3
|
+
.bundle
|
4
|
+
.config
|
5
|
+
.yardoc
|
6
|
+
Gemfile.lock
|
7
|
+
InstalledFiles
|
8
|
+
_yardoc
|
9
|
+
coverage
|
10
|
+
doc/
|
11
|
+
lib/bundler/man
|
12
|
+
pkg
|
13
|
+
rdoc
|
14
|
+
spec/reports
|
15
|
+
test/tmp
|
16
|
+
test/version_tmp
|
17
|
+
tmp
|
18
|
+
*.bundle
|
19
|
+
*.so
|
20
|
+
*.o
|
21
|
+
*.a
|
22
|
+
mkmf.log
|
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2014 Ben Balter
|
2
|
+
|
3
|
+
MIT License
|
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,68 @@
|
|
1
|
+
# Change Agent
|
2
|
+
|
3
|
+
*A Git-backed key-value store, for tracking changes to documents and other files over time.*
|
4
|
+
|
5
|
+
### A git-backed key value store sounds like a terrible idea. Why would you do that?
|
6
|
+
|
7
|
+
Let's say you're building a scraper to see when Members of Congress post press releases to their websites and to track how those press releases change over time. You could build a purpose-built application, store each revision in a database, and then build an interface to view all the known press releases and compare their history. Stop the insanity!
|
8
|
+
|
9
|
+
But wait. What if I told you you could just commit each press release to Git, and let Git/GitHub do the heavy lifting. Without writing a single line of HTML you can browse all the press releases, see when they were changed, diff exactly how they were changed, and you've got hosting baked in.
|
10
|
+
|
11
|
+
Having built the first app more times then I'd like to admit, I thought I'd make a Gem to facilitate building lightweight apps that use Git to track changes to scraped documents (or whatever you want, really).
|
12
|
+
|
13
|
+
## Okay, I'm sold. How do I use it?
|
14
|
+
|
15
|
+
ChangeAgent writes values to the file system based on a given key, and immediately commits the file to Git, providing you with both a snapshot and a timestamp for every change.
|
16
|
+
|
17
|
+
### Basic usage
|
18
|
+
|
19
|
+
```ruby
|
20
|
+
change_agent = ChangeAgent.init "path/to/repo"
|
21
|
+
=> #<ChangeAgent::Client repo="path/to/repo">
|
22
|
+
|
23
|
+
change_agent.set "foo", "bar"
|
24
|
+
=> #<ChangeAgent::Document key="foo">
|
25
|
+
|
26
|
+
change_agent.get "foo"
|
27
|
+
=> "bar"
|
28
|
+
```
|
29
|
+
|
30
|
+
### Namespaced usage
|
31
|
+
|
32
|
+
Keys (files) are intended to be namespaced when logically grouped. In the above example, if you were storing congressional press releases, you might store Rep. Balter's Nov 26th press release on puppies as "balter/2014/11/26/puppies.html", or just "balter/2014-11-26-puppies.txt" or even just "balter/puppies".
|
33
|
+
|
34
|
+
```ruby
|
35
|
+
change_agent.set "foo/bar", "baz"
|
36
|
+
=> #<ChangeAgent::Document key="foo">
|
37
|
+
|
38
|
+
change_agent.get "foo/bar"
|
39
|
+
=> "baz"
|
40
|
+
```
|
41
|
+
|
42
|
+
It's really up to you, but you'll get performance and usability bumps the more you namespace. I'd recommend thinking about what you want the Git repo to look like when browse, and work backwards from there.
|
43
|
+
|
44
|
+
## Project status
|
45
|
+
|
46
|
+
Initial proof of concept
|
47
|
+
|
48
|
+
## Installation
|
49
|
+
|
50
|
+
Add this line to your application's Gemfile:
|
51
|
+
|
52
|
+
gem 'change_agent'
|
53
|
+
|
54
|
+
And then execute:
|
55
|
+
|
56
|
+
$ bundle
|
57
|
+
|
58
|
+
Or install it yourself as:
|
59
|
+
|
60
|
+
$ gem install change_agent
|
61
|
+
|
62
|
+
## Contributing
|
63
|
+
|
64
|
+
1. Fork it ( https://github.com/[my-github-username]/change_agent/fork )
|
65
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
66
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
67
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
68
|
+
5. Create a new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'rake'
|
2
|
+
require 'rake/testtask'
|
3
|
+
require "bundler/gem_tasks"
|
4
|
+
|
5
|
+
Rake::TestTask.new(:test) do |test|
|
6
|
+
test.libs << 'lib' << 'test'
|
7
|
+
test.pattern = 'test/**/test_change_agent*.rb'
|
8
|
+
test.verbose = true
|
9
|
+
end
|
10
|
+
|
11
|
+
desc "Open console with Change Agent loaded"
|
12
|
+
task :console do
|
13
|
+
exec "pry -r ./lib/change_agent.rb"
|
14
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'change_agent/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "change_agent"
|
8
|
+
spec.version = ChangeAgent::VERSION
|
9
|
+
spec.authors = ["Ben Balter"]
|
10
|
+
spec.email = ["ben.balter@github.com"]
|
11
|
+
spec.summary = %q{A Git-backed key-value store, for tracking changes to documents and other files over time.}
|
12
|
+
spec.homepage = "https://github.com/benbalter/change-agent"
|
13
|
+
spec.license = "MIT"
|
14
|
+
|
15
|
+
spec.files = `git ls-files -z`.split("\x0")
|
16
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
17
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
18
|
+
spec.require_paths = ["lib"]
|
19
|
+
|
20
|
+
spec.add_dependency "git"
|
21
|
+
spec.add_dependency "rugged"
|
22
|
+
spec.add_development_dependency "bundler", "~> 1.6"
|
23
|
+
spec.add_development_dependency "rake"
|
24
|
+
spec.add_development_dependency "pry"
|
25
|
+
spec.add_development_dependency('shoulda', '~> 3.5')
|
26
|
+
end
|
data/lib/change_agent.rb
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
module ChangeAgent
|
2
|
+
class Client
|
3
|
+
|
4
|
+
attr_accessor :directory
|
5
|
+
|
6
|
+
def initialize(directory=nil)
|
7
|
+
@directory = File.expand_path(directory || Dir.pwd)
|
8
|
+
end
|
9
|
+
|
10
|
+
def git
|
11
|
+
@git ||= Git.init directory
|
12
|
+
end
|
13
|
+
|
14
|
+
def set(key, value)
|
15
|
+
document = Document.new(key, self)
|
16
|
+
document.contents = value
|
17
|
+
document.write
|
18
|
+
document
|
19
|
+
end
|
20
|
+
|
21
|
+
def get(key)
|
22
|
+
get_document(key).contents
|
23
|
+
end
|
24
|
+
|
25
|
+
def get_document(key)
|
26
|
+
Document.new(key, self)
|
27
|
+
end
|
28
|
+
|
29
|
+
def delete(key)
|
30
|
+
Document.new(key, self).delete
|
31
|
+
end
|
32
|
+
|
33
|
+
def inspect
|
34
|
+
"#<ChangeAgent::Client repo=\"#{directory}\">"
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
module ChangeAgent
|
2
|
+
class Document
|
3
|
+
|
4
|
+
attr_accessor :key
|
5
|
+
attr_writer :contents
|
6
|
+
|
7
|
+
def initialize(key, client_or_directory=nil)
|
8
|
+
@key = key
|
9
|
+
if client_or_directory.class == ChangeAgent::Client
|
10
|
+
@client = client_or_directory
|
11
|
+
else
|
12
|
+
@client = ChangeAgent::Client.new(client_or_directory)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def git
|
17
|
+
@client.git
|
18
|
+
end
|
19
|
+
|
20
|
+
# base dir for repo
|
21
|
+
def base_dir
|
22
|
+
@client.directory
|
23
|
+
end
|
24
|
+
|
25
|
+
# directory containing file
|
26
|
+
def directory
|
27
|
+
@directory ||= File.dirname(path)
|
28
|
+
end
|
29
|
+
|
30
|
+
def path
|
31
|
+
File.expand_path key, base_dir
|
32
|
+
end
|
33
|
+
|
34
|
+
def exists?
|
35
|
+
File.exists? path
|
36
|
+
end
|
37
|
+
|
38
|
+
def contents
|
39
|
+
@contents ||= File.open(path).read
|
40
|
+
rescue Errno::ENOENT
|
41
|
+
nil
|
42
|
+
end
|
43
|
+
|
44
|
+
def write
|
45
|
+
FileUtils.mkdir_p directory unless Dir.exists? directory
|
46
|
+
File.write(path, contents)
|
47
|
+
commit
|
48
|
+
end
|
49
|
+
|
50
|
+
def commit
|
51
|
+
git.add(path)
|
52
|
+
git.commit "Updating #{path}"
|
53
|
+
end
|
54
|
+
|
55
|
+
def delete
|
56
|
+
git.remove(path)
|
57
|
+
end
|
58
|
+
|
59
|
+
def inspect
|
60
|
+
"#<ChangeAgent::Document key=\"#{key}\">"
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
data/script/bootstrap
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
bundle install
|
data/script/cibuild
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
bundle exec rake test
|
data/script/console
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
bundle exec rake console
|
data/script/release
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
#!/bin/sh
|
2
|
+
# Tag and push a release.
|
3
|
+
|
4
|
+
set -e
|
5
|
+
|
6
|
+
# Make sure we're in the project root.
|
7
|
+
|
8
|
+
cd $(dirname "$0")/..
|
9
|
+
|
10
|
+
# Build a new gem archive.
|
11
|
+
|
12
|
+
rm -rf change_agent-*.gem
|
13
|
+
gem build -q change_agent.gemspec
|
14
|
+
|
15
|
+
# Make sure we're on the master branch.
|
16
|
+
|
17
|
+
(git branch | grep -q '* master') || {
|
18
|
+
echo "Only release from the master branch."
|
19
|
+
exit 1
|
20
|
+
}
|
21
|
+
|
22
|
+
# Figure out what version we're releasing.
|
23
|
+
|
24
|
+
tag=v`ls change_agent-*.gem | sed 's/^change_agent-\(.*\)\.gem$/\1/'`
|
25
|
+
|
26
|
+
# Make sure we haven't released this version before.
|
27
|
+
|
28
|
+
git fetch -t origin
|
29
|
+
|
30
|
+
(git tag -l | grep -q "$tag") && {
|
31
|
+
echo "Whoops, there's already a '${tag}' tag."
|
32
|
+
exit 1
|
33
|
+
}
|
34
|
+
|
35
|
+
# Tag it and bag it.
|
36
|
+
|
37
|
+
gem push change_agent-*.gem && git tag "$tag" &&
|
38
|
+
git push origin master && git push origin "$tag"
|
data/test/helper.rb
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'bundler'
|
3
|
+
require 'minitest/autorun'
|
4
|
+
require 'shoulda'
|
5
|
+
|
6
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
7
|
+
|
8
|
+
def tempdir
|
9
|
+
File.expand_path "../tmp", File.dirname(__FILE__)
|
10
|
+
end
|
11
|
+
|
12
|
+
def init_tempdir
|
13
|
+
FileUtils.rm_rf tempdir
|
14
|
+
FileUtils.mkdir tempdir
|
15
|
+
end
|
16
|
+
|
17
|
+
require 'change_agent'
|
@@ -0,0 +1,64 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
class TestChangeAgentClient < Minitest::Test
|
4
|
+
|
5
|
+
def setup
|
6
|
+
init_tempdir
|
7
|
+
@client = ChangeAgent::Client.new(tempdir)
|
8
|
+
end
|
9
|
+
|
10
|
+
should "set the directory on init" do
|
11
|
+
assert_equal tempdir, @client.directory
|
12
|
+
end
|
13
|
+
|
14
|
+
should "default to the pwd" do
|
15
|
+
assert_equal Dir.pwd, ChangeAgent::Client.new.directory
|
16
|
+
end
|
17
|
+
|
18
|
+
should "init the git object" do
|
19
|
+
assert_equal Git::Base, @client.git.class
|
20
|
+
expected = File.expand_path ".git", tempdir
|
21
|
+
assert_equal expected, @client.git.repo.path
|
22
|
+
end
|
23
|
+
|
24
|
+
should "store a value" do
|
25
|
+
@client.set "foo", "bar"
|
26
|
+
file = File.expand_path "foo", tempdir
|
27
|
+
assert File.exists? file
|
28
|
+
assert_equal "bar", File.open(file).read
|
29
|
+
end
|
30
|
+
|
31
|
+
should "store a namespaced value" do
|
32
|
+
@client.set "foo/bar", "baz"
|
33
|
+
file = File.expand_path "foo/bar", tempdir
|
34
|
+
assert File.exists? file
|
35
|
+
assert_equal "baz", File.open(file).read
|
36
|
+
end
|
37
|
+
|
38
|
+
should "retrieve a file's value" do
|
39
|
+
file = File.expand_path "foo", tempdir
|
40
|
+
File.write file, "bar"
|
41
|
+
assert_equal "bar", @client.get("foo")
|
42
|
+
end
|
43
|
+
|
44
|
+
should "retrive a namespaced file's value" do
|
45
|
+
file = File.expand_path "foo/bar", tempdir
|
46
|
+
FileUtils.mkdir_p File.dirname(file)
|
47
|
+
File.write file, "baz"
|
48
|
+
assert_equal "baz", @client.get("foo/bar")
|
49
|
+
end
|
50
|
+
|
51
|
+
should "round trip a value" do
|
52
|
+
@client.set "foo", "bar"
|
53
|
+
assert_equal "bar", @client.get("foo")
|
54
|
+
end
|
55
|
+
|
56
|
+
should "round trip a namespaced value" do
|
57
|
+
@client.set "foo/bar", "baz"
|
58
|
+
assert_equal "baz", @client.get("foo/bar")
|
59
|
+
end
|
60
|
+
|
61
|
+
should "not err on an unknown value" do
|
62
|
+
refute @client.get "does/not/exist"
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,79 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
class TestChangeAgentDocument < Minitest::Test
|
4
|
+
|
5
|
+
def setup
|
6
|
+
init_tempdir
|
7
|
+
@document = ChangeAgent::Document.new("foo", tempdir)
|
8
|
+
@namespaced_document = ChangeAgent::Document.new("bar/foo", tempdir)
|
9
|
+
end
|
10
|
+
|
11
|
+
should "store the document key on init" do
|
12
|
+
assert_equal "foo", @document.key
|
13
|
+
end
|
14
|
+
|
15
|
+
should "accept a client if passed" do
|
16
|
+
doc = ChangeAgent::Document.new("foo", ChangeAgent::Client.new)
|
17
|
+
assert_equal ChangeAgent::Client, doc.instance_variable_get("@client").class
|
18
|
+
end
|
19
|
+
|
20
|
+
should "build a client from a directory" do
|
21
|
+
assert_equal ChangeAgent::Client, @document.instance_variable_get("@client").class
|
22
|
+
end
|
23
|
+
|
24
|
+
should "expose the git client" do
|
25
|
+
assert_equal Git::Base, @document.git.class
|
26
|
+
end
|
27
|
+
|
28
|
+
should "calcuate the base_dir" do
|
29
|
+
assert_equal tempdir, @document.base_dir
|
30
|
+
end
|
31
|
+
|
32
|
+
should "calcuate the directory" do
|
33
|
+
assert_equal tempdir, @document.directory
|
34
|
+
|
35
|
+
expected = File.expand_path "bar", tempdir
|
36
|
+
assert_equal expected, @namespaced_document.directory
|
37
|
+
end
|
38
|
+
|
39
|
+
should "know the file path" do
|
40
|
+
expected = File.expand_path "foo", tempdir
|
41
|
+
assert_equal expected, @document.path
|
42
|
+
|
43
|
+
expected = File.expand_path "bar/foo", tempdir
|
44
|
+
assert_equal expected, @namespaced_document.path
|
45
|
+
end
|
46
|
+
|
47
|
+
should "know if a file exists" do
|
48
|
+
refute @document.exists?
|
49
|
+
FileUtils.touch @document.path
|
50
|
+
assert @document.exists?
|
51
|
+
end
|
52
|
+
|
53
|
+
should "read a file's contents" do
|
54
|
+
File.write @document.path, "bar"
|
55
|
+
assert_equal "bar", @document.contents
|
56
|
+
end
|
57
|
+
|
58
|
+
should "write a file's contents" do
|
59
|
+
@document.contents = "bar"
|
60
|
+
assert_equal "bar", @document.contents
|
61
|
+
@document.write
|
62
|
+
assert_equal "bar", File.open(@document.path).read
|
63
|
+
end
|
64
|
+
|
65
|
+
should "commit the document to the repo" do
|
66
|
+
@document.contents = "bar"
|
67
|
+
@document.write
|
68
|
+
assert_equal 1, @document.git.log.count
|
69
|
+
assert_equal "Updating #{@document.path}", @document.git.log.first.message
|
70
|
+
end
|
71
|
+
|
72
|
+
should "delete the document" do
|
73
|
+
@document.contents = "bar"
|
74
|
+
@document.write
|
75
|
+
assert File.exists? @document.path
|
76
|
+
@document.delete
|
77
|
+
refute File.exists? @document.path
|
78
|
+
end
|
79
|
+
end
|
metadata
ADDED
@@ -0,0 +1,151 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: change_agent
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Ben Balter
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-11-26 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: git
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rugged
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: bundler
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '1.6'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '1.6'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rake
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: pry
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: shoulda
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '3.5'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - "~>"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '3.5'
|
97
|
+
description:
|
98
|
+
email:
|
99
|
+
- ben.balter@github.com
|
100
|
+
executables: []
|
101
|
+
extensions: []
|
102
|
+
extra_rdoc_files: []
|
103
|
+
files:
|
104
|
+
- ".gitignore"
|
105
|
+
- Gemfile
|
106
|
+
- LICENSE.txt
|
107
|
+
- README.md
|
108
|
+
- Rakefile
|
109
|
+
- change_agent.gemspec
|
110
|
+
- lib/change_agent.rb
|
111
|
+
- lib/change_agent/client.rb
|
112
|
+
- lib/change_agent/document.rb
|
113
|
+
- lib/change_agent/version.rb
|
114
|
+
- script/bootstrap
|
115
|
+
- script/cibuild
|
116
|
+
- script/console
|
117
|
+
- script/release
|
118
|
+
- test/helper.rb
|
119
|
+
- test/test_change_agent.rb
|
120
|
+
- test/test_change_agent_client.rb
|
121
|
+
- test/test_change_agent_document.rb
|
122
|
+
homepage: https://github.com/benbalter/change-agent
|
123
|
+
licenses:
|
124
|
+
- MIT
|
125
|
+
metadata: {}
|
126
|
+
post_install_message:
|
127
|
+
rdoc_options: []
|
128
|
+
require_paths:
|
129
|
+
- lib
|
130
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
131
|
+
requirements:
|
132
|
+
- - ">="
|
133
|
+
- !ruby/object:Gem::Version
|
134
|
+
version: '0'
|
135
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
136
|
+
requirements:
|
137
|
+
- - ">="
|
138
|
+
- !ruby/object:Gem::Version
|
139
|
+
version: '0'
|
140
|
+
requirements: []
|
141
|
+
rubyforge_project:
|
142
|
+
rubygems_version: 2.2.0
|
143
|
+
signing_key:
|
144
|
+
specification_version: 4
|
145
|
+
summary: A Git-backed key-value store, for tracking changes to documents and other
|
146
|
+
files over time.
|
147
|
+
test_files:
|
148
|
+
- test/helper.rb
|
149
|
+
- test/test_change_agent.rb
|
150
|
+
- test/test_change_agent_client.rb
|
151
|
+
- test/test_change_agent_document.rb
|