git-safe 0.1.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 +12 -0
- data/.rspec +3 -0
- data/.travis.yml +7 -0
- data/Gemfile +6 -0
- data/Gemfile.lock +45 -0
- data/README.md +43 -0
- data/Rakefile +6 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/git-safe.gemspec +31 -0
- data/lib/git-safe/command_error.rb +3 -0
- data/lib/git-safe/configuration.rb +46 -0
- data/lib/git-safe/git.rb +160 -0
- data/lib/git-safe/private_key_file.rb +28 -0
- data/lib/git-safe/ssh_tempfile.rb +24 -0
- data/lib/git-safe/version.rb +3 -0
- data/lib/git_safe.rb +37 -0
- metadata +131 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 2b7839df797b7a01ee24bafccc8f6086ed5142ffbe7d7cf5901899a410e895d6
|
4
|
+
data.tar.gz: 0032cd4ceed5039f1e0e3b60cb872ec8a68aa3cbfe17e745198b2842c19cb329
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 68d399eb56a55c992bcc12f7d4bf7e3f87b1a2b3a670e93bffba1d27703d70d3ee117eb28a6a66a1a90671cca2242d1f40720a4040366d951735562d8df9fa5c
|
7
|
+
data.tar.gz: 9ab7a7a5e919e57787702a2300dacdb006a35339a6a1d0fa6850d6360178ce1f23328ea4df45a5e364ac64de5f1eb1b46a9fcf8a64655ab1bdebb1d32a9ac977
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
git-safe (0.1.0)
|
5
|
+
|
6
|
+
GEM
|
7
|
+
remote: https://rubygems.org/
|
8
|
+
specs:
|
9
|
+
coderay (1.1.2)
|
10
|
+
diff-lcs (1.4.4)
|
11
|
+
method_source (1.0.0)
|
12
|
+
pry (0.13.1)
|
13
|
+
coderay (~> 1.1)
|
14
|
+
method_source (~> 1.0)
|
15
|
+
rake (10.5.0)
|
16
|
+
rspec (3.9.0)
|
17
|
+
rspec-core (~> 3.9.0)
|
18
|
+
rspec-expectations (~> 3.9.0)
|
19
|
+
rspec-mocks (~> 3.9.0)
|
20
|
+
rspec-core (3.9.3)
|
21
|
+
rspec-support (~> 3.9.3)
|
22
|
+
rspec-expectations (3.9.2)
|
23
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
24
|
+
rspec-support (~> 3.9.0)
|
25
|
+
rspec-its (1.3.0)
|
26
|
+
rspec-core (>= 3.0.0)
|
27
|
+
rspec-expectations (>= 3.0.0)
|
28
|
+
rspec-mocks (3.9.1)
|
29
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
30
|
+
rspec-support (~> 3.9.0)
|
31
|
+
rspec-support (3.9.3)
|
32
|
+
|
33
|
+
PLATFORMS
|
34
|
+
ruby
|
35
|
+
|
36
|
+
DEPENDENCIES
|
37
|
+
bundler (~> 1.17)
|
38
|
+
git-safe!
|
39
|
+
pry
|
40
|
+
rake (~> 10.0)
|
41
|
+
rspec (~> 3.0)
|
42
|
+
rspec-its (~> 1.3)
|
43
|
+
|
44
|
+
BUNDLED WITH
|
45
|
+
1.17.2
|
data/README.md
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
# Git::Safe
|
2
|
+
|
3
|
+
This ruby git gem can safely be executed in concurrent environments with multiple ssh keys
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
```ruby
|
10
|
+
gem 'git-safe'
|
11
|
+
```
|
12
|
+
|
13
|
+
And then execute:
|
14
|
+
|
15
|
+
$ bundle
|
16
|
+
|
17
|
+
Or install it yourself as:
|
18
|
+
|
19
|
+
$ gem install git-safe
|
20
|
+
|
21
|
+
## Usage
|
22
|
+
Configuration
|
23
|
+
```ruby
|
24
|
+
require 'git_safe'
|
25
|
+
GitPusher.configure do |config|
|
26
|
+
config.logger = Logger.new(STDOUT)
|
27
|
+
end
|
28
|
+
```
|
29
|
+
|
30
|
+
Initialize with work_tree and an optional ssh_private_key (string or path)
|
31
|
+
```ruby
|
32
|
+
git_safe = GitSafe.init('/my/work/tree', ssh_private_key: 'path-to-file-or-string')
|
33
|
+
```
|
34
|
+
|
35
|
+
## Development
|
36
|
+
|
37
|
+
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
38
|
+
|
39
|
+
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
40
|
+
|
41
|
+
## Contributing
|
42
|
+
|
43
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/git-safe.
|
data/Rakefile
ADDED
data/bin/console
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "bundler/setup"
|
4
|
+
require "git/safe"
|
5
|
+
|
6
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
7
|
+
# with your gem easier. You can also use a different console, if you like.
|
8
|
+
|
9
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
10
|
+
# require "pry"
|
11
|
+
# Pry.start
|
12
|
+
|
13
|
+
require "irb"
|
14
|
+
IRB.start(__FILE__)
|
data/bin/setup
ADDED
data/git-safe.gemspec
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
|
2
|
+
lib = File.expand_path("../lib", __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require "git-safe/version"
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "git-safe"
|
8
|
+
spec.version = GitSafe::VERSION
|
9
|
+
spec.authors = ["Perry Hertler"]
|
10
|
+
spec.email = ["perry@hertler.org"]
|
11
|
+
|
12
|
+
spec.summary = %q{A concurrent-safe way to perform multiple ssh configuration git operations against "origin".}
|
13
|
+
spec.description = %q{Some applications need to access git "origin" from multiple threads or processes with different security access approaches. This gem makes it possible}
|
14
|
+
spec.homepage = "https://github.com/perrqh/git-safe-ruby"
|
15
|
+
|
16
|
+
|
17
|
+
# Specify which files should be added to the gem when it is released.
|
18
|
+
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
19
|
+
spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
|
20
|
+
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
21
|
+
end
|
22
|
+
spec.bindir = "exe"
|
23
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
24
|
+
spec.require_paths = ["lib"]
|
25
|
+
|
26
|
+
spec.add_development_dependency "bundler", "~> 1.17"
|
27
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
28
|
+
spec.add_development_dependency "rspec", "~> 3.0"
|
29
|
+
spec.add_development_dependency "rspec-its", "~> 1.3"
|
30
|
+
spec.add_development_dependency "pry"
|
31
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
module GitSafe
|
2
|
+
class Configuration
|
3
|
+
OPTIONS = {
|
4
|
+
logger: ::Logger.new(STDOUT),
|
5
|
+
branch: 'master',
|
6
|
+
remote: 'origin',
|
7
|
+
clone_command_repo_dir_replace_text: '<REPO_DIR>',
|
8
|
+
ssh_private_key: nil, # path or string
|
9
|
+
}.freeze
|
10
|
+
|
11
|
+
# Defines accessors for all OPTIONS
|
12
|
+
OPTIONS.each_pair do |key, _value|
|
13
|
+
attr_accessor key
|
14
|
+
end
|
15
|
+
|
16
|
+
# Initializes defaults to be the environment varibales of the same names
|
17
|
+
def initialize
|
18
|
+
OPTIONS.each_pair do |key, value|
|
19
|
+
send("#{key}=", value)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
# Allows config options to be read like a hash
|
24
|
+
#
|
25
|
+
# @param [Symbol] option Key for a given attribute
|
26
|
+
def [](option)
|
27
|
+
send(option)
|
28
|
+
end
|
29
|
+
|
30
|
+
# Returns a hash of all configurable options
|
31
|
+
def to_hash
|
32
|
+
OPTIONS.each_with_object({}) do |option, hash|
|
33
|
+
key = option.first
|
34
|
+
hash[key] = send(key)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
# Returns a hash of all configurable options merged with +hash+
|
39
|
+
#
|
40
|
+
# @param [Hash] hash A set of configuration options that will take
|
41
|
+
# precedence over the defaults
|
42
|
+
def merge(hash)
|
43
|
+
to_hash.merge(hash)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
data/lib/git-safe/git.rb
ADDED
@@ -0,0 +1,160 @@
|
|
1
|
+
require 'open3'
|
2
|
+
|
3
|
+
module GitSafe
|
4
|
+
class Git
|
5
|
+
include PrivateKeyFile
|
6
|
+
|
7
|
+
attr_reader :options, :work_tree, :ssh_private_key, :logger
|
8
|
+
|
9
|
+
def initialize(work_tree, options)
|
10
|
+
@work_tree = work_tree
|
11
|
+
@options = options
|
12
|
+
@ssh_private_key = options[:ssh_private_key]
|
13
|
+
@logger = options[:logger]
|
14
|
+
FileUtils.mkdir_p(work_tree)
|
15
|
+
end
|
16
|
+
|
17
|
+
def init
|
18
|
+
execute_git_cmd("git #{git_locale} init")
|
19
|
+
end
|
20
|
+
|
21
|
+
def status
|
22
|
+
execute_git_cmd("git #{git_locale} status")
|
23
|
+
end
|
24
|
+
|
25
|
+
def config_set(name_values = {})
|
26
|
+
name_values.keys.each do |key|
|
27
|
+
execute_git_cmd("git #{git_locale} config #{key} #{name_values[key]}") if name_values[key]
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def config_get(name)
|
32
|
+
execute_git_cmd("git #{git_locale} config #{name}")
|
33
|
+
end
|
34
|
+
|
35
|
+
def add_and_commit(commit_msg)
|
36
|
+
execute_git_cmd("git #{git_locale} add .")
|
37
|
+
execute_git_cmd("git #{git_locale} commit -m '#{commit_msg}'")
|
38
|
+
end
|
39
|
+
|
40
|
+
def last_commit_sha
|
41
|
+
execute_git_cmd("git #{git_locale} rev-parse HEAD")
|
42
|
+
end
|
43
|
+
|
44
|
+
def last_commit_timestamp
|
45
|
+
execute_git_cmd("git #{git_locale} log -1 --format=%cd ")
|
46
|
+
end
|
47
|
+
|
48
|
+
def branch_a
|
49
|
+
execute_git_cmd("git #{git_locale} branch -a")
|
50
|
+
end
|
51
|
+
|
52
|
+
def checkout(branch: nil, create: false, sha: nil)
|
53
|
+
co = "git #{git_locale} checkout"
|
54
|
+
create_flag = create ? ' -b' : ''
|
55
|
+
if branch
|
56
|
+
co = "#{co}#{create_flag} #{branch}"
|
57
|
+
elsif sha
|
58
|
+
co = "#{co} #{sha}"
|
59
|
+
end
|
60
|
+
execute_git_cmd(co)
|
61
|
+
end
|
62
|
+
|
63
|
+
def merge(to_merge_name)
|
64
|
+
execute_git_cmd("git #{git_locale} merge #{to_merge_name}")
|
65
|
+
end
|
66
|
+
|
67
|
+
def push(remote: 'origin', branch: 'master', force: false)
|
68
|
+
force_flag = force ? '-f ' : ''
|
69
|
+
execute_git_cmd("git #{git_locale} push #{force_flag}#{remote} #{branch}")
|
70
|
+
end
|
71
|
+
|
72
|
+
def fetch
|
73
|
+
execute_git_cmd("#{ssh_cmd}git #{git_locale} fetch")
|
74
|
+
ensure
|
75
|
+
safe_unlink_private_key_tmp_file
|
76
|
+
end
|
77
|
+
|
78
|
+
def pull(branch: 'master')
|
79
|
+
execute_git_cmd("#{ssh_cmd}git #{git_locale} pull origin #{branch}")
|
80
|
+
ensure
|
81
|
+
safe_unlink_private_key_tmp_file
|
82
|
+
end
|
83
|
+
|
84
|
+
def clone(remote_uri, depth: nil)
|
85
|
+
if options[:clone_command]
|
86
|
+
execute_git_cmd(options[:clone_command].gsub(options[:clone_command_repo_dir_replace_text], work_tree))
|
87
|
+
else
|
88
|
+
depth_cmd = depth ? " --depth=#{depth}" : ''
|
89
|
+
execute_git_cmd("#{ssh_cmd}git clone #{remote_uri}#{depth_cmd} #{work_tree}")
|
90
|
+
end
|
91
|
+
ensure
|
92
|
+
safe_unlink_private_key_tmp_file
|
93
|
+
end
|
94
|
+
|
95
|
+
def git_locale
|
96
|
+
"#{work_tree_flag} --git-dir=#{work_tree}/.git"
|
97
|
+
end
|
98
|
+
|
99
|
+
def work_tree_flag
|
100
|
+
"--work-tree=#{work_tree}"
|
101
|
+
end
|
102
|
+
|
103
|
+
def add_remote(uri, name: 'origin')
|
104
|
+
execute_git_cmd("git #{git_locale} remote add #{name} #{uri}")
|
105
|
+
end
|
106
|
+
|
107
|
+
def has_remote?
|
108
|
+
git_config&.match(/\[remote/)
|
109
|
+
end
|
110
|
+
|
111
|
+
def remotes
|
112
|
+
return [] unless has_git_config? && remote_strs = execute_git_cmd("git #{git_locale} remote -v")
|
113
|
+
|
114
|
+
remote_strs.split("\n").collect do |remote_str|
|
115
|
+
name, uri, type = remote_str.split(' ')
|
116
|
+
{ name: name,
|
117
|
+
uri: uri,
|
118
|
+
type: type.gsub('(', '').gsub(')', '') }
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
def clone_or_fetch_and_merge(remote_uri, branch: 'master', remote_name: 'origin', depth: nil, force_fresh_clone: false, git_config: {})
|
123
|
+
delete_work_tree if force_fresh_clone
|
124
|
+
|
125
|
+
unless has_remote?
|
126
|
+
clone(remote_uri, depth: depth)
|
127
|
+
end
|
128
|
+
|
129
|
+
config_set(git_config)
|
130
|
+
fetch
|
131
|
+
checkout(branch: branch)
|
132
|
+
merge("#{remote_name}/#{branch}")
|
133
|
+
end
|
134
|
+
|
135
|
+
def git_config
|
136
|
+
File.read(git_config_path) if has_git_config?
|
137
|
+
end
|
138
|
+
|
139
|
+
def has_git_config?
|
140
|
+
File.exists?(git_config_path)
|
141
|
+
end
|
142
|
+
|
143
|
+
def git_config_path
|
144
|
+
"#{work_tree}/.git/config"
|
145
|
+
end
|
146
|
+
|
147
|
+
def delete_work_tree
|
148
|
+
FileUtils.rm_rf(work_tree) if Dir.exists?(work_tree)
|
149
|
+
end
|
150
|
+
|
151
|
+
alias_method :work_tree_is_git_repo?, :has_git_config?
|
152
|
+
|
153
|
+
def execute_git_cmd(git_cmd)
|
154
|
+
stdout_str, stderr_str, status = Open3.capture3(git_cmd)
|
155
|
+
raise CommandError.new("error executing '#{git_cmd}', status: #{status.exitstatus}, std_error: #{stderr_str}") unless status.exitstatus == 0
|
156
|
+
|
157
|
+
[stdout_str, stderr_str].reject { |out| out.nil? || out.strip == '' }.join(',')
|
158
|
+
end
|
159
|
+
end
|
160
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module GitSafe
|
2
|
+
module PrivateKeyFile
|
3
|
+
def ssh_cmd
|
4
|
+
return '' unless ssh_private_key_file_path
|
5
|
+
"GIT_SSH_COMMAND=\"ssh -i #{ssh_private_key_file_path} -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no\" "
|
6
|
+
end
|
7
|
+
|
8
|
+
def ssh_private_key_file_path
|
9
|
+
return unless ssh_private_key
|
10
|
+
|
11
|
+
if File.exist?(ssh_private_key)
|
12
|
+
logger.info('ssh_private_key key is a file')
|
13
|
+
ssh_private_key
|
14
|
+
else
|
15
|
+
logger.info('ssh_private_key key is a string')
|
16
|
+
ssh_tempfile.private_key_temp_file.path
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def ssh_tempfile
|
21
|
+
@ssh_tempfile ||= SshTempfile.new(ssh_private_key)
|
22
|
+
end
|
23
|
+
|
24
|
+
def safe_unlink_private_key_tmp_file
|
25
|
+
ssh_tempfile&.safe_unlink_private_key_tmp_file
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module GitSafe
|
2
|
+
class SshTempfile
|
3
|
+
attr_reader :private_key_string, :private_key_temp_file
|
4
|
+
|
5
|
+
def initialize(private_key_string)
|
6
|
+
@private_key_string = private_key_string
|
7
|
+
@private_key_temp_file = create_private_key_tmp_file
|
8
|
+
end
|
9
|
+
|
10
|
+
def safe_unlink_private_key_tmp_file
|
11
|
+
private_key_temp_file&.unlink
|
12
|
+
end
|
13
|
+
|
14
|
+
def create_private_key_tmp_file
|
15
|
+
tf = Tempfile.new('git-ssh-wrapper')
|
16
|
+
tf << private_key_string
|
17
|
+
tf.puts('') # required for openssh keys
|
18
|
+
tf.chmod(0600)
|
19
|
+
tf.flush
|
20
|
+
tf.close
|
21
|
+
tf
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
data/lib/git_safe.rb
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
require 'logger'
|
2
|
+
require 'git-safe/ssh_tempfile'
|
3
|
+
require 'git-safe/private_key_file'
|
4
|
+
require 'git-safe/command_error'
|
5
|
+
require 'git-safe/git'
|
6
|
+
require 'git-safe/configuration'
|
7
|
+
|
8
|
+
module GitSafe
|
9
|
+
class << self
|
10
|
+
def init(work_tree, options = {})
|
11
|
+
Git.new(work_tree, configuration.merge(options))
|
12
|
+
end
|
13
|
+
|
14
|
+
# A GitSafe configuration object. Must act like a hash and
|
15
|
+
# return sensible values for all GitSafe configuration options.
|
16
|
+
#
|
17
|
+
# @see GitSafe::Configuration.
|
18
|
+
attr_writer :configuration
|
19
|
+
|
20
|
+
# The configuration object.
|
21
|
+
#
|
22
|
+
# @see GitSafe.configure
|
23
|
+
def configuration
|
24
|
+
@configuration ||= Configuration.new
|
25
|
+
end
|
26
|
+
|
27
|
+
# Call this method to modify defaults in your initializers.
|
28
|
+
#
|
29
|
+
# @example
|
30
|
+
# GitSafe.configure do |config|
|
31
|
+
# config.logger = Logger.new(STDOUT)
|
32
|
+
# end
|
33
|
+
def configure
|
34
|
+
yield(configuration)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
metadata
ADDED
@@ -0,0 +1,131 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: git-safe
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Perry Hertler
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2020-10-30 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.17'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.17'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '10.0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '10.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rspec
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '3.0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '3.0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rspec-its
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '1.3'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '1.3'
|
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
|
+
description: Some applications need to access git "origin" from multiple threads or
|
84
|
+
processes with different security access approaches. This gem makes it possible
|
85
|
+
email:
|
86
|
+
- perry@hertler.org
|
87
|
+
executables: []
|
88
|
+
extensions: []
|
89
|
+
extra_rdoc_files: []
|
90
|
+
files:
|
91
|
+
- ".gitignore"
|
92
|
+
- ".rspec"
|
93
|
+
- ".travis.yml"
|
94
|
+
- Gemfile
|
95
|
+
- Gemfile.lock
|
96
|
+
- README.md
|
97
|
+
- Rakefile
|
98
|
+
- bin/console
|
99
|
+
- bin/setup
|
100
|
+
- git-safe.gemspec
|
101
|
+
- lib/git-safe/command_error.rb
|
102
|
+
- lib/git-safe/configuration.rb
|
103
|
+
- lib/git-safe/git.rb
|
104
|
+
- lib/git-safe/private_key_file.rb
|
105
|
+
- lib/git-safe/ssh_tempfile.rb
|
106
|
+
- lib/git-safe/version.rb
|
107
|
+
- lib/git_safe.rb
|
108
|
+
homepage: https://github.com/perrqh/git-safe-ruby
|
109
|
+
licenses: []
|
110
|
+
metadata: {}
|
111
|
+
post_install_message:
|
112
|
+
rdoc_options: []
|
113
|
+
require_paths:
|
114
|
+
- lib
|
115
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
116
|
+
requirements:
|
117
|
+
- - ">="
|
118
|
+
- !ruby/object:Gem::Version
|
119
|
+
version: '0'
|
120
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - ">="
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '0'
|
125
|
+
requirements: []
|
126
|
+
rubygems_version: 3.0.3
|
127
|
+
signing_key:
|
128
|
+
specification_version: 4
|
129
|
+
summary: A concurrent-safe way to perform multiple ssh configuration git operations
|
130
|
+
against "origin".
|
131
|
+
test_files: []
|