change_agent 0.2.2 → 0.2.4
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 +5 -5
- data/.github/dependabot.yml +11 -0
- data/.github/workflows/ci.yml +21 -0
- data/.rubocop.yml +5 -0
- data/.rubocop_todo.yml +54 -0
- data/Gemfile +2 -0
- data/README.md +1 -1
- data/Rakefile +5 -3
- data/change_agent.gemspec +19 -16
- data/lib/change_agent/client.rb +9 -8
- data/lib/change_agent/document.rb +21 -20
- data/lib/change_agent/sync.rb +26 -21
- data/lib/change_agent/version.rb +3 -1
- data/lib/change_agent.rb +9 -9
- data/script/cibuild +2 -0
- data/test/helper.rb +3 -1
- data/test/test_change_agent.rb +3 -2
- data/test/test_change_agent_client.rb +30 -24
- data/test/test_change_agent_document.rb +31 -30
- data/test/test_change_agent_sync.rb +22 -21
- metadata +113 -38
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: b9e1bb76f1fdfc79b7c66cb1856b3c7ddc2ce7fc4e0d84b9c7209c8a01b85453
|
4
|
+
data.tar.gz: 69652cf94dc625148debbb9d7ad68bf763781a01d0c939eac6a9b695813f8614
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 94fbd390e06214dc7d6444873e27c24c75863b75ac10b1919f157e06356967388d9e4970d396d2a47433f10abec28d0b3017b31967804fbe69d49ee7e647f2c6
|
7
|
+
data.tar.gz: c79c86ba8a1f47b56a3caa42c5432c6d0914aee4a1584f8d88377d6fa1eb539da50ea5ee393d9244d741e6b6e971c6b7af831406f233591f10324a049514fb1e
|
@@ -0,0 +1,11 @@
|
|
1
|
+
# To get started with Dependabot version updates, you'll need to specify which
|
2
|
+
# package ecosystems to update and where the package manifests are located.
|
3
|
+
# Please see the documentation for all configuration options:
|
4
|
+
# https://docs.github.com/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file
|
5
|
+
|
6
|
+
version: 2
|
7
|
+
updates:
|
8
|
+
- package-ecosystem: "bundler" # See documentation for possible values
|
9
|
+
directory: "/" # Location of package manifests
|
10
|
+
schedule:
|
11
|
+
interval: "weekly"
|
@@ -0,0 +1,21 @@
|
|
1
|
+
name: CI
|
2
|
+
|
3
|
+
on:
|
4
|
+
push:
|
5
|
+
branches: [ main, master ]
|
6
|
+
pull_request:
|
7
|
+
branches: [ main, master ]
|
8
|
+
|
9
|
+
jobs:
|
10
|
+
build:
|
11
|
+
runs-on: ubuntu-latest
|
12
|
+
steps:
|
13
|
+
- name: Checkout code
|
14
|
+
uses: actions/checkout@v4
|
15
|
+
- name: Set up Ruby
|
16
|
+
uses: ruby/setup-ruby@v1
|
17
|
+
with:
|
18
|
+
bundler-cache: true
|
19
|
+
ruby-version: 3.2
|
20
|
+
- name: Run cibuild script
|
21
|
+
run: script/cibuild
|
data/.rubocop.yml
ADDED
data/.rubocop_todo.yml
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
# This configuration was generated by
|
2
|
+
# `rubocop --auto-gen-config`
|
3
|
+
# on 2025-05-07 20:42:05 UTC using RuboCop version 1.75.5.
|
4
|
+
# The point is for the user to remove these configuration records
|
5
|
+
# one by one as the offenses are removed from the code base.
|
6
|
+
# Note that changes in the inspected code, or installation of new
|
7
|
+
# versions of RuboCop, may require this file to be generated again.
|
8
|
+
|
9
|
+
# Offense count: 6
|
10
|
+
# Configuration parameters: EnforcedStyle, AllowedGems, Include.
|
11
|
+
# SupportedStyles: Gemfile, gems.rb, gemspec
|
12
|
+
# Include: **/*.gemspec, **/Gemfile, **/gems.rb
|
13
|
+
Gemspec/DevelopmentDependencies:
|
14
|
+
Exclude:
|
15
|
+
- 'change_agent.gemspec'
|
16
|
+
|
17
|
+
# Offense count: 1
|
18
|
+
# Configuration parameters: Severity, Include.
|
19
|
+
# Include: **/*.gemspec
|
20
|
+
Gemspec/RequiredRubyVersion:
|
21
|
+
Exclude:
|
22
|
+
- 'change_agent.gemspec'
|
23
|
+
|
24
|
+
# Offense count: 2
|
25
|
+
# Configuration parameters: AllowedMethods, AllowedPatterns, CountRepeatedAttributes.
|
26
|
+
Metrics/AbcSize:
|
27
|
+
Max: 30
|
28
|
+
|
29
|
+
# Offense count: 1
|
30
|
+
# Configuration parameters: CountComments, CountAsOne, AllowedMethods, AllowedPatterns.
|
31
|
+
Metrics/MethodLength:
|
32
|
+
Max: 15
|
33
|
+
|
34
|
+
# Offense count: 1
|
35
|
+
# Configuration parameters: NamePrefix, ForbiddenPrefixes, AllowedMethods, MethodDefinitionMacros, UseSorbetSigs.
|
36
|
+
# NamePrefix: is_, has_, have_, does_
|
37
|
+
# ForbiddenPrefixes: is_, has_, have_, does_
|
38
|
+
# AllowedMethods: is_a?
|
39
|
+
# MethodDefinitionMacros: define_method, define_singleton_method
|
40
|
+
Naming/PredicateName:
|
41
|
+
Exclude:
|
42
|
+
- 'spec/**/*'
|
43
|
+
- 'lib/change_agent/sync.rb'
|
44
|
+
|
45
|
+
# Offense count: 4
|
46
|
+
# Configuration parameters: AllowedConstants.
|
47
|
+
Style/Documentation:
|
48
|
+
Exclude:
|
49
|
+
- 'spec/**/*'
|
50
|
+
- 'test/**/*'
|
51
|
+
- 'lib/change_agent.rb'
|
52
|
+
- 'lib/change_agent/client.rb'
|
53
|
+
- 'lib/change_agent/document.rb'
|
54
|
+
- 'lib/change_agent/sync.rb'
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -16,7 +16,7 @@ Want to see it in action? Check out [this lightweight demo](https://github.com/b
|
|
16
16
|
|
17
17
|
## Okay, I'm sold. How do I use it?
|
18
18
|
|
19
|
-
ChangeAgent writes values to the
|
19
|
+
ChangeAgent writes values directly to the Git database based on a given key (path), and immediately triggers a commit, providing you with both a snapshot and a timestamp for every change.
|
20
20
|
|
21
21
|
### Basic usage
|
22
22
|
|
data/Rakefile
CHANGED
@@ -1,6 +1,8 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'rake'
|
2
4
|
require 'rake/testtask'
|
3
|
-
require
|
5
|
+
require 'bundler/gem_tasks'
|
4
6
|
|
5
7
|
Rake::TestTask.new(:test) do |test|
|
6
8
|
test.libs << 'lib' << 'test'
|
@@ -8,7 +10,7 @@ Rake::TestTask.new(:test) do |test|
|
|
8
10
|
test.verbose = true
|
9
11
|
end
|
10
12
|
|
11
|
-
desc
|
13
|
+
desc 'Open console with Change Agent loaded'
|
12
14
|
task :console do
|
13
|
-
exec
|
15
|
+
exec 'pry -r ./lib/change_agent.rb'
|
14
16
|
end
|
data/change_agent.gemspec
CHANGED
@@ -1,26 +1,29 @@
|
|
1
|
-
#
|
2
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
lib = File.expand_path('lib', __dir__)
|
3
4
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
5
|
require 'change_agent/version'
|
5
6
|
|
6
7
|
Gem::Specification.new do |spec|
|
7
|
-
spec.name =
|
8
|
+
spec.name = 'change_agent'
|
8
9
|
spec.version = ChangeAgent::VERSION
|
9
|
-
spec.authors = [
|
10
|
-
spec.email = [
|
11
|
-
spec.summary =
|
12
|
-
spec.homepage =
|
13
|
-
spec.license =
|
10
|
+
spec.authors = ['Ben Balter']
|
11
|
+
spec.email = ['ben.balter@github.com']
|
12
|
+
spec.summary = 'A Git-backed key-value store, for tracking changes to documents and other files over time.'
|
13
|
+
spec.homepage = 'https://github.com/benbalter/change-agent'
|
14
|
+
spec.license = 'MIT'
|
14
15
|
|
15
16
|
spec.files = `git ls-files -z`.split("\x0")
|
16
17
|
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
17
|
-
spec.
|
18
|
-
spec.require_paths = ["lib"]
|
18
|
+
spec.require_paths = ['lib']
|
19
19
|
|
20
|
-
spec.add_dependency
|
21
|
-
spec.add_dependency
|
22
|
-
spec.add_development_dependency
|
23
|
-
spec.add_development_dependency
|
24
|
-
spec.add_development_dependency
|
25
|
-
spec.add_development_dependency
|
20
|
+
spec.add_dependency 'dotenv', '>= 3.1', '< 4.0'
|
21
|
+
spec.add_dependency 'rugged', '>= 1.9', '< 2.0'
|
22
|
+
spec.add_development_dependency 'bundler', '>= 2.0', '< 3.0'
|
23
|
+
spec.add_development_dependency 'pry', '>= 0.15', '< 1.0'
|
24
|
+
spec.add_development_dependency 'rake', '>= 13.0', '< 14.0'
|
25
|
+
spec.add_development_dependency 'rubocop', '>= 1.0', '< 2.0'
|
26
|
+
spec.add_development_dependency 'rubocop-performance', '>= 1.0', '< 2.0'
|
27
|
+
spec.add_development_dependency 'shoulda', '>= 4.0', '< 5.0'
|
28
|
+
spec.metadata['rubygems_mfa_required'] = 'true'
|
26
29
|
end
|
data/lib/change_agent/client.rb
CHANGED
@@ -1,26 +1,28 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ChangeAgent
|
2
4
|
class Client
|
3
|
-
|
4
5
|
include ChangeAgent::Sync
|
5
6
|
attr_accessor :directory
|
6
7
|
|
7
|
-
def initialize(directory=nil, remote=nil)
|
8
|
+
def initialize(directory = nil, remote = nil)
|
8
9
|
@directory = File.expand_path(directory || Dir.pwd)
|
9
10
|
@remote = remote
|
10
11
|
end
|
11
12
|
|
12
13
|
def repo
|
13
|
-
if @remote.nil?
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
14
|
+
@repo ||= if @remote.nil?
|
15
|
+
Rugged::Repository.init_at directory
|
16
|
+
else
|
17
|
+
Rugged::Repository.clone_at @remote, directory, { credentials: credentials }
|
18
|
+
end
|
18
19
|
end
|
19
20
|
|
20
21
|
def set(key, value)
|
21
22
|
document = Document.new(key, self)
|
22
23
|
document.contents = value
|
23
24
|
return unless document.changed?
|
25
|
+
|
24
26
|
document.save
|
25
27
|
document
|
26
28
|
end
|
@@ -40,6 +42,5 @@ module ChangeAgent
|
|
40
42
|
def inspect
|
41
43
|
"#<ChangeAgent::Client repo=\"#{directory}\">"
|
42
44
|
end
|
43
|
-
|
44
45
|
end
|
45
46
|
end
|
@@ -1,17 +1,18 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ChangeAgent
|
2
4
|
class Document
|
3
|
-
|
4
5
|
attr_writer :contents
|
5
6
|
attr_accessor :path
|
6
|
-
|
7
|
+
alias key path
|
7
8
|
|
8
|
-
def initialize(path, client_or_directory=nil)
|
9
|
+
def initialize(path, client_or_directory = nil)
|
9
10
|
@path = path
|
10
|
-
if client_or_directory.
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
11
|
+
@client = if client_or_directory.instance_of?(ChangeAgent::Client)
|
12
|
+
client_or_directory
|
13
|
+
else
|
14
|
+
ChangeAgent::Client.new(client_or_directory)
|
15
|
+
end
|
15
16
|
end
|
16
17
|
|
17
18
|
def repo
|
@@ -28,24 +29,24 @@ module ChangeAgent
|
|
28
29
|
|
29
30
|
def save
|
30
31
|
oid = repo.write contents, :blob
|
31
|
-
repo.index.add(path: path, oid: oid, mode:
|
32
|
+
repo.index.add(path: path, oid: oid, mode: 0o100644)
|
32
33
|
|
33
34
|
Rugged::Commit.create repo,
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
35
|
+
message: "Updating #{path}",
|
36
|
+
parents: repo.empty? ? [] : [repo.head.target],
|
37
|
+
tree: repo.index.write_tree(repo),
|
38
|
+
update_ref: 'HEAD'
|
38
39
|
end
|
39
|
-
|
40
|
+
alias write save
|
40
41
|
|
41
|
-
def delete(file=path)
|
42
|
+
def delete(file = path)
|
42
43
|
repo.index.remove(file)
|
43
44
|
|
44
45
|
Rugged::Commit.create repo,
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
46
|
+
message: "Removing #{path}",
|
47
|
+
parents: [repo.head.target],
|
48
|
+
tree: repo.index.write_tree(repo),
|
49
|
+
update_ref: 'HEAD'
|
49
50
|
rescue Rugged::IndexError
|
50
51
|
false
|
51
52
|
end
|
@@ -59,7 +60,7 @@ module ChangeAgent
|
|
59
60
|
def blob_contents
|
60
61
|
tree = repo.head.target.tree
|
61
62
|
blob = repo.lookup tree.path(path)[:oid]
|
62
|
-
blob.content
|
63
|
+
blob.content.force_encoding('UTF-8')
|
63
64
|
rescue Rugged::ReferenceError, Rugged::TreeError
|
64
65
|
nil
|
65
66
|
end
|
data/lib/change_agent/sync.rb
CHANGED
@@ -1,23 +1,24 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ChangeAgent
|
2
4
|
module Sync
|
3
|
-
|
4
5
|
class MergeConflict < StandardError; end
|
5
6
|
class MissingRemote < ArgumentError; end
|
6
7
|
|
7
8
|
attr_writer :credentials
|
8
9
|
|
9
|
-
DEFAULT_REMOTE =
|
10
|
-
DEFAULT_REMOTE_BRANCH =
|
11
|
-
DEFAULT_LOCAL_REF =
|
10
|
+
DEFAULT_REMOTE = 'origin'
|
11
|
+
DEFAULT_REMOTE_BRANCH = 'origin/master'
|
12
|
+
DEFAULT_LOCAL_REF = 'refs/heads/master'
|
12
13
|
|
13
14
|
# Default to token-based credentials passed as GITHUB_TOKEN
|
14
15
|
# Can be over ridden by overwritting @credentials with a
|
15
16
|
# different Rugged Credentialing method
|
16
17
|
def credentials
|
17
18
|
@credentials ||= Rugged::Credentials::UserPassword.new({
|
18
|
-
|
19
|
-
|
20
|
-
|
19
|
+
username: 'x-oauth-basic',
|
20
|
+
password: ENV.fetch('GITHUB_TOKEN', nil)
|
21
|
+
})
|
21
22
|
end
|
22
23
|
|
23
24
|
# Helper method to return all remots
|
@@ -32,7 +33,7 @@ module ChangeAgent
|
|
32
33
|
|
33
34
|
# Does the current repo have at least a single remote?
|
34
35
|
def has_remotes?
|
35
|
-
remotes.count
|
36
|
+
remotes.count.positive?
|
36
37
|
end
|
37
38
|
|
38
39
|
# Push to a remote
|
@@ -40,19 +41,22 @@ module ChangeAgent
|
|
40
41
|
# Options:
|
41
42
|
# :remote - the name of the remote (default: origin)
|
42
43
|
# :ref - the ref to push (default: "refs/heads/master")
|
43
|
-
def push(options={})
|
44
|
+
def push(options = {})
|
44
45
|
raise MissingRemote unless has_remotes?
|
45
|
-
|
46
|
-
|
46
|
+
|
47
|
+
options[:remote] = DEFAULT_REMOTE
|
48
|
+
options[:ref] = DEFAULT_LOCAL_REF
|
49
|
+
remotes[options[:remote]].push([options[:ref]], { credentials: credentials })
|
47
50
|
end
|
48
51
|
|
49
52
|
# Fetch a remote
|
50
53
|
#
|
51
54
|
# Options:
|
52
55
|
# remote - the name of the remote (default: origin)
|
53
|
-
def fetch(remote=nil)
|
56
|
+
def fetch(remote = nil)
|
54
57
|
raise MissingRemote unless has_remotes?
|
55
|
-
|
58
|
+
|
59
|
+
repo.fetch(remote || DEFAULT_REMOTE, credentials: credentials)
|
56
60
|
end
|
57
61
|
|
58
62
|
# Merge two refs
|
@@ -60,8 +64,9 @@ module ChangeAgent
|
|
60
64
|
# Options:
|
61
65
|
# :from - the remote ref (default: "origin/master")
|
62
66
|
# :to - the local ref (default: "refs/heads/master")
|
63
|
-
def merge(options={})
|
64
|
-
options
|
67
|
+
def merge(options = {})
|
68
|
+
options[:from] = DEFAULT_REMOTE_BRANCH
|
69
|
+
options[:to] = DEFAULT_LOCAL_REF
|
65
70
|
theirs = repo.rev_parse options[:from]
|
66
71
|
ours = repo.rev_parse options[:to]
|
67
72
|
|
@@ -74,11 +79,11 @@ module ChangeAgent
|
|
74
79
|
raise MergeConflict if index.conflicts?
|
75
80
|
|
76
81
|
Rugged::Commit.create(repo, {
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
+
parents: [ours, theirs],
|
83
|
+
tree: index.write_tree(repo),
|
84
|
+
message: "Merged `#{options[:from]}` into `#{options[:to].sub('refs/heads/', '')}`",
|
85
|
+
update_ref: options[:to]
|
86
|
+
})
|
82
87
|
end
|
83
88
|
|
84
89
|
# Fetch a remote and merge
|
@@ -87,7 +92,7 @@ module ChangeAgent
|
|
87
92
|
# :remote - the name of the remote (default: origin)
|
88
93
|
# :from - the remote ref (default: "origin/master")
|
89
94
|
# :to - the local ref (default: "refs/heads/master")
|
90
|
-
def pull(options={})
|
95
|
+
def pull(options = {})
|
91
96
|
fetch(options[:remote])
|
92
97
|
merge(options)
|
93
98
|
end
|
data/lib/change_agent/version.rb
CHANGED
data/lib/change_agent.rb
CHANGED
@@ -1,17 +1,17 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
require_relative
|
4
|
-
require_relative
|
5
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'change_agent/version'
|
4
|
+
require_relative 'change_agent/document'
|
5
|
+
require_relative 'change_agent/sync'
|
6
|
+
require_relative 'change_agent/client'
|
7
|
+
require 'rugged'
|
6
8
|
require 'pathname'
|
7
|
-
require
|
9
|
+
require 'dotenv'
|
8
10
|
|
9
11
|
module ChangeAgent
|
10
|
-
|
11
|
-
def self.init(directory=nil, remote=nil)
|
12
|
+
def self.init(directory = nil, remote = nil)
|
12
13
|
Client.new(directory, remote)
|
13
14
|
end
|
14
|
-
|
15
15
|
end
|
16
16
|
|
17
17
|
Dotenv.load
|
data/script/cibuild
CHANGED
data/test/helper.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'rubygems'
|
2
4
|
require 'bundler'
|
3
5
|
require 'minitest/autorun'
|
@@ -6,7 +8,7 @@ require 'shoulda'
|
|
6
8
|
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
7
9
|
|
8
10
|
def tempdir
|
9
|
-
File.expand_path
|
11
|
+
File.expand_path './tmp', File.dirname(__FILE__)
|
10
12
|
end
|
11
13
|
|
12
14
|
def init_tempdir
|
data/test/test_change_agent.rb
CHANGED
@@ -1,7 +1,8 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'helper'
|
2
4
|
|
3
5
|
class TestChangeAgent < Minitest::Test
|
4
|
-
|
5
6
|
def setup
|
6
7
|
init_tempdir
|
7
8
|
end
|
@@ -10,7 +11,7 @@ class TestChangeAgent < Minitest::Test
|
|
10
11
|
FileUtils.rm_rf tempdir
|
11
12
|
end
|
12
13
|
|
13
|
-
should
|
14
|
+
should 'return a ChangeAgent::Client' do
|
14
15
|
assert_equal ChangeAgent::Client, ChangeAgent.init(tempdir).class
|
15
16
|
end
|
16
17
|
end
|
@@ -1,7 +1,8 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'helper'
|
2
4
|
|
3
5
|
class TestChangeAgentClient < Minitest::Test
|
4
|
-
|
5
6
|
def setup
|
6
7
|
init_tempdir
|
7
8
|
@client = ChangeAgent::Client.new(tempdir)
|
@@ -11,58 +12,63 @@ class TestChangeAgentClient < Minitest::Test
|
|
11
12
|
FileUtils.rm_rf tempdir
|
12
13
|
end
|
13
14
|
|
14
|
-
should
|
15
|
+
should 'set the directory on init' do
|
15
16
|
assert_equal tempdir, @client.directory
|
16
17
|
end
|
17
18
|
|
18
|
-
should
|
19
|
-
repo =
|
19
|
+
should 'clone into existing repos' do
|
20
|
+
repo = 'https://github.com/benbalter/change_agent'
|
20
21
|
agent = ChangeAgent::Client.new(tempdir, repo)
|
21
22
|
assert_equal repo, agent.repo.remotes.first.url
|
22
23
|
assert Dir.entries(tempdir).count > 5
|
23
24
|
end
|
24
25
|
|
25
|
-
should
|
26
|
+
should 'default to the pwd' do
|
26
27
|
assert_equal Dir.pwd, ChangeAgent::Client.new.directory
|
27
28
|
end
|
28
29
|
|
29
|
-
should
|
30
|
+
should 'init the git object' do
|
30
31
|
assert_equal Rugged::Repository, @client.repo.class
|
31
|
-
assert_equal tempdir
|
32
|
+
assert_equal "#{tempdir}/.git/", @client.repo.path
|
32
33
|
end
|
33
34
|
|
34
|
-
should
|
35
|
-
@client.set
|
35
|
+
should 'store a value' do
|
36
|
+
@client.set 'foo', 'bar'
|
36
37
|
tree = @client.repo.head.target.tree
|
37
|
-
blob = @client.repo.lookup tree[
|
38
|
-
assert_equal
|
38
|
+
blob = @client.repo.lookup tree['foo'][:oid]
|
39
|
+
assert_equal 'bar', blob.content
|
39
40
|
end
|
40
41
|
|
41
|
-
should
|
42
|
-
@client.set
|
42
|
+
should 'store a namespaced value' do
|
43
|
+
@client.set 'foo/bar', 'baz'
|
43
44
|
tree = @client.repo.head.target.tree
|
44
|
-
blob = @client.repo.lookup tree.path(
|
45
|
-
assert_equal
|
45
|
+
blob = @client.repo.lookup tree.path('foo/bar')[:oid]
|
46
|
+
assert_equal 'baz', blob.content
|
46
47
|
end
|
47
48
|
|
48
49
|
should "retrieve a file's value" do
|
49
|
-
@client.set
|
50
|
-
assert_equal
|
50
|
+
@client.set 'foo', 'bar'
|
51
|
+
assert_equal 'bar', @client.get('foo')
|
51
52
|
end
|
52
53
|
|
53
54
|
should "retrive a namespaced file's value" do
|
54
|
-
@client.set
|
55
|
-
assert_equal
|
55
|
+
@client.set 'foo/bar', 'baz'
|
56
|
+
assert_equal 'baz', @client.get('foo/bar')
|
56
57
|
end
|
57
58
|
|
58
|
-
should
|
59
|
-
refute @client.get
|
59
|
+
should 'not err on an unknown value' do
|
60
|
+
refute @client.get 'does/not/exist'
|
60
61
|
end
|
61
62
|
|
62
|
-
should
|
63
|
-
@client.set
|
63
|
+
should 'not double save a document' do
|
64
|
+
@client.set 'foo', 'bar'
|
64
65
|
sha = @client.repo.last_commit.oid
|
65
|
-
@client.set
|
66
|
+
@client.set 'foo', 'bar'
|
66
67
|
assert_equal sha, @client.repo.last_commit.oid
|
67
68
|
end
|
69
|
+
|
70
|
+
should 'save UTF-8 encoded values' do
|
71
|
+
@client.set 'foo', '§'
|
72
|
+
assert_equal '§', @client.get('foo')
|
73
|
+
end
|
68
74
|
end
|
@@ -1,87 +1,88 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'helper'
|
2
4
|
|
3
5
|
class TestChangeAgentDocument < Minitest::Test
|
4
|
-
|
5
6
|
def setup
|
6
7
|
init_tempdir
|
7
8
|
@client = ChangeAgent::Client.new tempdir
|
8
|
-
@document = ChangeAgent::Document.new(
|
9
|
-
@namespaced_document = ChangeAgent::Document.new(
|
9
|
+
@document = ChangeAgent::Document.new('foo', @client)
|
10
|
+
@namespaced_document = ChangeAgent::Document.new('bar/foo', @client)
|
10
11
|
end
|
11
12
|
|
12
13
|
def teardown
|
13
14
|
FileUtils.rm_rf tempdir
|
14
15
|
end
|
15
16
|
|
16
|
-
should
|
17
|
-
assert_equal
|
17
|
+
should 'store the document path on init' do
|
18
|
+
assert_equal 'foo', @document.path
|
18
19
|
end
|
19
20
|
|
20
|
-
should
|
21
|
-
doc = ChangeAgent::Document.new(
|
22
|
-
assert_equal ChangeAgent::Client, doc.instance_variable_get(
|
21
|
+
should 'accept a client if passed' do
|
22
|
+
doc = ChangeAgent::Document.new('foo', ChangeAgent::Client.new)
|
23
|
+
assert_equal ChangeAgent::Client, doc.instance_variable_get(:@client).class
|
23
24
|
end
|
24
25
|
|
25
|
-
should
|
26
|
-
assert_equal ChangeAgent::Client, @document.instance_variable_get(
|
26
|
+
should 'build a client from a directory' do
|
27
|
+
assert_equal ChangeAgent::Client, @document.instance_variable_get(:@client).class
|
27
28
|
end
|
28
29
|
|
29
|
-
should
|
30
|
+
should 'expose the git client' do
|
30
31
|
assert_equal Rugged::Repository, @document.repo.class
|
31
32
|
end
|
32
33
|
|
33
34
|
should "read a file's contents" do
|
34
|
-
@document.contents =
|
35
|
+
@document.contents = 'bar'
|
35
36
|
@document.write
|
36
37
|
@document.contents = nil # prevent caching
|
37
|
-
assert_equal
|
38
|
+
assert_equal 'bar', @document.contents
|
38
39
|
end
|
39
40
|
|
40
41
|
should "write a file's contents" do
|
41
|
-
@document.contents =
|
42
|
+
@document.contents = 'bar'
|
42
43
|
@document.write
|
43
44
|
@document.contents = nil # prevent caching
|
44
|
-
assert_equal
|
45
|
+
assert_equal 'bar', @client.get('foo')
|
45
46
|
end
|
46
47
|
|
47
|
-
should
|
48
|
-
@document.contents =
|
48
|
+
should 'commit the document to the repo' do
|
49
|
+
@document.contents = 'bar'
|
49
50
|
@document.write
|
50
51
|
@document.contents = nil # prevent caching
|
51
52
|
assert_equal "Updating #{@document.key}", @document.repo.last_commit.message
|
52
53
|
end
|
53
54
|
|
54
|
-
should
|
55
|
-
@document.contents =
|
55
|
+
should 'delete the document' do
|
56
|
+
@document.contents = 'bar'
|
56
57
|
@document.write
|
57
58
|
@document.contents = nil # prevent caching
|
58
|
-
assert @client.get
|
59
|
+
assert @client.get 'foo'
|
59
60
|
@document.delete
|
60
|
-
refute @client.get
|
61
|
+
refute @client.get 'foo'
|
61
62
|
assert_equal "Removing #{@document.key}", @document.repo.last_commit.message
|
62
63
|
end
|
63
64
|
|
64
|
-
should
|
65
|
-
doc = ChangeAgent::Document.new(
|
66
|
-
doc.contents =
|
65
|
+
should 'allow two files in the same folder' do
|
66
|
+
doc = ChangeAgent::Document.new('foo/bar', @client)
|
67
|
+
doc.contents = 'baz'
|
67
68
|
doc.write
|
68
69
|
doc.contents = nil # prevent caching
|
69
|
-
assert_equal
|
70
|
+
assert_equal 'baz', @client.get('foo/bar')
|
70
71
|
|
71
|
-
doc = ChangeAgent::Document.new(
|
72
|
-
doc.contents =
|
72
|
+
doc = ChangeAgent::Document.new('foo/bar2', @client)
|
73
|
+
doc.contents = 'baz2'
|
73
74
|
doc.write
|
74
75
|
doc.contents = nil # prevent caching
|
75
|
-
assert_equal
|
76
|
+
assert_equal 'baz2', @client.get('foo/bar2')
|
76
77
|
end
|
77
78
|
|
78
79
|
should "know if a file's changed" do
|
79
80
|
refute @document.changed?
|
80
81
|
|
81
|
-
@client.set
|
82
|
+
@client.set 'foo', 'bar'
|
82
83
|
refute @document.changed?
|
83
84
|
|
84
|
-
@document.contents =
|
85
|
+
@document.contents = 'baz'
|
85
86
|
assert @document.changed?
|
86
87
|
end
|
87
88
|
end
|
@@ -1,62 +1,63 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'helper'
|
2
4
|
|
3
5
|
class TestChangeAgentSync < Minitest::Test
|
4
|
-
|
5
6
|
def setup
|
6
7
|
init_tempdir
|
7
8
|
@client = ChangeAgent::Client.new tempdir
|
8
|
-
@demo = ChangeAgent::Client.new tempdir,
|
9
|
+
@demo = ChangeAgent::Client.new tempdir, 'http://github.com/benbalter/change_agent_demo'
|
9
10
|
end
|
10
11
|
|
11
12
|
def teardown
|
12
13
|
FileUtils.rm_rf tempdir
|
13
14
|
end
|
14
15
|
|
15
|
-
should
|
16
|
+
should 'return the remotes' do
|
16
17
|
assert_equal Rugged::RemoteCollection, @client.remotes.class
|
17
18
|
end
|
18
19
|
|
19
|
-
should
|
20
|
+
should 'add remotes' do
|
20
21
|
assert_equal 0, @client.remotes.count
|
21
|
-
@client.add_remote
|
22
|
+
@client.add_remote 'origin', 'https://github.com/benbalter/change_agent_demo'
|
22
23
|
assert_equal 1, @client.remotes.count
|
23
24
|
end
|
24
25
|
|
25
|
-
should
|
26
|
+
should 'know when the repo has remotes' do
|
26
27
|
refute @client.has_remotes?
|
27
|
-
@client.add_remote
|
28
|
+
@client.add_remote 'origin', 'https://github.com/benbalter/change_agent_demo'
|
28
29
|
assert @client.has_remotes?
|
29
30
|
end
|
30
31
|
|
31
|
-
should
|
32
|
-
@client.add_remote
|
32
|
+
should 'fetch' do
|
33
|
+
@client.add_remote 'origin', 'https://github.com/benbalter/change_agent_demo'
|
33
34
|
assert_raises Rugged::ReferenceError do
|
34
|
-
@client.repo.rev_parse
|
35
|
+
@client.repo.rev_parse 'origin/master'
|
35
36
|
end
|
36
37
|
@client.fetch
|
37
|
-
assert @client.repo.rev_parse
|
38
|
+
assert @client.repo.rev_parse 'origin/master'
|
38
39
|
end
|
39
40
|
|
40
|
-
should
|
41
|
+
should 'merge' do
|
41
42
|
head = @demo.repo.head.target.oid
|
42
|
-
@demo.repo.reset
|
43
|
+
@demo.repo.reset 'd877861', :hard
|
43
44
|
assert @demo.merge
|
44
|
-
assert_equal
|
45
|
+
assert_equal 'Merged `origin/master` into `master`', @demo.repo.last_commit.message
|
45
46
|
assert head != @demo.repo.head.target.oid
|
46
47
|
end
|
47
48
|
|
48
|
-
should
|
49
|
+
should 'pull' do
|
49
50
|
head = @demo.repo.head.target.oid
|
50
|
-
@demo.repo.reset
|
51
|
+
@demo.repo.reset 'd877861', :hard
|
51
52
|
assert @demo.pull
|
52
|
-
assert_equal
|
53
|
+
assert_equal 'Merged `origin/master` into `master`', @demo.repo.last_commit.message
|
53
54
|
assert head != @demo.repo.head.target.oid
|
54
55
|
end
|
55
56
|
|
56
|
-
should
|
57
|
-
ENV[
|
57
|
+
should 'init credentials' do
|
58
|
+
ENV['GITHUB_TOKEN'] = 'foo'
|
58
59
|
assert_equal Rugged::Credentials::UserPassword, @client.credentials.class
|
59
|
-
assert_equal
|
60
|
-
assert_equal
|
60
|
+
assert_equal 'x-oauth-basic', @client.credentials.instance_variable_get(:@username)
|
61
|
+
assert_equal 'foo', @client.credentials.instance_variable_get(:@password)
|
61
62
|
end
|
62
63
|
end
|
metadata
CHANGED
@@ -1,99 +1,175 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: change_agent
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ben Balter
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2025-05-07 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
|
-
name:
|
14
|
+
name: dotenv
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- - "
|
17
|
+
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '
|
19
|
+
version: '3.1'
|
20
|
+
- - "<"
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: '4.0'
|
20
23
|
type: :runtime
|
21
24
|
prerelease: false
|
22
25
|
version_requirements: !ruby/object:Gem::Requirement
|
23
26
|
requirements:
|
24
|
-
- - "
|
27
|
+
- - ">="
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '3.1'
|
30
|
+
- - "<"
|
25
31
|
- !ruby/object:Gem::Version
|
26
|
-
version: '0
|
32
|
+
version: '4.0'
|
27
33
|
- !ruby/object:Gem::Dependency
|
28
|
-
name:
|
34
|
+
name: rugged
|
29
35
|
requirement: !ruby/object:Gem::Requirement
|
30
36
|
requirements:
|
31
|
-
- - "
|
37
|
+
- - ">="
|
32
38
|
- !ruby/object:Gem::Version
|
33
|
-
version: '1.
|
39
|
+
version: '1.9'
|
40
|
+
- - "<"
|
41
|
+
- !ruby/object:Gem::Version
|
42
|
+
version: '2.0'
|
34
43
|
type: :runtime
|
35
44
|
prerelease: false
|
36
45
|
version_requirements: !ruby/object:Gem::Requirement
|
37
46
|
requirements:
|
38
|
-
- - "
|
47
|
+
- - ">="
|
39
48
|
- !ruby/object:Gem::Version
|
40
|
-
version: '1.
|
49
|
+
version: '1.9'
|
50
|
+
- - "<"
|
51
|
+
- !ruby/object:Gem::Version
|
52
|
+
version: '2.0'
|
41
53
|
- !ruby/object:Gem::Dependency
|
42
54
|
name: bundler
|
43
55
|
requirement: !ruby/object:Gem::Requirement
|
44
56
|
requirements:
|
45
|
-
- - "
|
57
|
+
- - ">="
|
58
|
+
- !ruby/object:Gem::Version
|
59
|
+
version: '2.0'
|
60
|
+
- - "<"
|
46
61
|
- !ruby/object:Gem::Version
|
47
|
-
version: '
|
62
|
+
version: '3.0'
|
48
63
|
type: :development
|
49
64
|
prerelease: false
|
50
65
|
version_requirements: !ruby/object:Gem::Requirement
|
51
66
|
requirements:
|
52
|
-
- - "
|
67
|
+
- - ">="
|
53
68
|
- !ruby/object:Gem::Version
|
54
|
-
version: '
|
69
|
+
version: '2.0'
|
70
|
+
- - "<"
|
71
|
+
- !ruby/object:Gem::Version
|
72
|
+
version: '3.0'
|
73
|
+
- !ruby/object:Gem::Dependency
|
74
|
+
name: pry
|
75
|
+
requirement: !ruby/object:Gem::Requirement
|
76
|
+
requirements:
|
77
|
+
- - ">="
|
78
|
+
- !ruby/object:Gem::Version
|
79
|
+
version: '0.15'
|
80
|
+
- - "<"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '1.0'
|
83
|
+
type: :development
|
84
|
+
prerelease: false
|
85
|
+
version_requirements: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0.15'
|
90
|
+
- - "<"
|
91
|
+
- !ruby/object:Gem::Version
|
92
|
+
version: '1.0'
|
55
93
|
- !ruby/object:Gem::Dependency
|
56
94
|
name: rake
|
57
95
|
requirement: !ruby/object:Gem::Requirement
|
58
96
|
requirements:
|
59
|
-
- - "
|
97
|
+
- - ">="
|
98
|
+
- !ruby/object:Gem::Version
|
99
|
+
version: '13.0'
|
100
|
+
- - "<"
|
60
101
|
- !ruby/object:Gem::Version
|
61
|
-
version: '
|
102
|
+
version: '14.0'
|
62
103
|
type: :development
|
63
104
|
prerelease: false
|
64
105
|
version_requirements: !ruby/object:Gem::Requirement
|
65
106
|
requirements:
|
66
|
-
- - "
|
107
|
+
- - ">="
|
67
108
|
- !ruby/object:Gem::Version
|
68
|
-
version: '
|
109
|
+
version: '13.0'
|
110
|
+
- - "<"
|
111
|
+
- !ruby/object:Gem::Version
|
112
|
+
version: '14.0'
|
69
113
|
- !ruby/object:Gem::Dependency
|
70
|
-
name:
|
114
|
+
name: rubocop
|
115
|
+
requirement: !ruby/object:Gem::Requirement
|
116
|
+
requirements:
|
117
|
+
- - ">="
|
118
|
+
- !ruby/object:Gem::Version
|
119
|
+
version: '1.0'
|
120
|
+
- - "<"
|
121
|
+
- !ruby/object:Gem::Version
|
122
|
+
version: '2.0'
|
123
|
+
type: :development
|
124
|
+
prerelease: false
|
125
|
+
version_requirements: !ruby/object:Gem::Requirement
|
126
|
+
requirements:
|
127
|
+
- - ">="
|
128
|
+
- !ruby/object:Gem::Version
|
129
|
+
version: '1.0'
|
130
|
+
- - "<"
|
131
|
+
- !ruby/object:Gem::Version
|
132
|
+
version: '2.0'
|
133
|
+
- !ruby/object:Gem::Dependency
|
134
|
+
name: rubocop-performance
|
71
135
|
requirement: !ruby/object:Gem::Requirement
|
72
136
|
requirements:
|
73
|
-
- - "
|
137
|
+
- - ">="
|
138
|
+
- !ruby/object:Gem::Version
|
139
|
+
version: '1.0'
|
140
|
+
- - "<"
|
74
141
|
- !ruby/object:Gem::Version
|
75
|
-
version: '0
|
142
|
+
version: '2.0'
|
76
143
|
type: :development
|
77
144
|
prerelease: false
|
78
145
|
version_requirements: !ruby/object:Gem::Requirement
|
79
146
|
requirements:
|
80
|
-
- - "
|
147
|
+
- - ">="
|
81
148
|
- !ruby/object:Gem::Version
|
82
|
-
version: '0
|
149
|
+
version: '1.0'
|
150
|
+
- - "<"
|
151
|
+
- !ruby/object:Gem::Version
|
152
|
+
version: '2.0'
|
83
153
|
- !ruby/object:Gem::Dependency
|
84
154
|
name: shoulda
|
85
155
|
requirement: !ruby/object:Gem::Requirement
|
86
156
|
requirements:
|
87
|
-
- - "
|
157
|
+
- - ">="
|
158
|
+
- !ruby/object:Gem::Version
|
159
|
+
version: '4.0'
|
160
|
+
- - "<"
|
88
161
|
- !ruby/object:Gem::Version
|
89
|
-
version: '
|
162
|
+
version: '5.0'
|
90
163
|
type: :development
|
91
164
|
prerelease: false
|
92
165
|
version_requirements: !ruby/object:Gem::Requirement
|
93
166
|
requirements:
|
94
|
-
- - "
|
167
|
+
- - ">="
|
95
168
|
- !ruby/object:Gem::Version
|
96
|
-
version: '
|
169
|
+
version: '4.0'
|
170
|
+
- - "<"
|
171
|
+
- !ruby/object:Gem::Version
|
172
|
+
version: '5.0'
|
97
173
|
description:
|
98
174
|
email:
|
99
175
|
- ben.balter@github.com
|
@@ -101,7 +177,11 @@ executables: []
|
|
101
177
|
extensions: []
|
102
178
|
extra_rdoc_files: []
|
103
179
|
files:
|
180
|
+
- ".github/dependabot.yml"
|
181
|
+
- ".github/workflows/ci.yml"
|
104
182
|
- ".gitignore"
|
183
|
+
- ".rubocop.yml"
|
184
|
+
- ".rubocop_todo.yml"
|
105
185
|
- ".travis.yml"
|
106
186
|
- Gemfile
|
107
187
|
- LICENSE.txt
|
@@ -125,7 +205,8 @@ files:
|
|
125
205
|
homepage: https://github.com/benbalter/change-agent
|
126
206
|
licenses:
|
127
207
|
- MIT
|
128
|
-
metadata:
|
208
|
+
metadata:
|
209
|
+
rubygems_mfa_required: 'true'
|
129
210
|
post_install_message:
|
130
211
|
rdoc_options: []
|
131
212
|
require_paths:
|
@@ -141,15 +222,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
141
222
|
- !ruby/object:Gem::Version
|
142
223
|
version: '0'
|
143
224
|
requirements: []
|
144
|
-
|
145
|
-
rubygems_version: 2.2.0
|
225
|
+
rubygems_version: 3.5.11
|
146
226
|
signing_key:
|
147
227
|
specification_version: 4
|
148
228
|
summary: A Git-backed key-value store, for tracking changes to documents and other
|
149
229
|
files over time.
|
150
|
-
test_files:
|
151
|
-
- test/helper.rb
|
152
|
-
- test/test_change_agent.rb
|
153
|
-
- test/test_change_agent_client.rb
|
154
|
-
- test/test_change_agent_document.rb
|
155
|
-
- test/test_change_agent_sync.rb
|
230
|
+
test_files: []
|