tmp-repo 1.0.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/Gemfile +13 -0
- data/History.txt +3 -0
- data/README.md +120 -0
- data/Rakefile +18 -0
- data/lib/tmp-repo.rb +117 -0
- data/lib/tmp-repo/version.rb +5 -0
- data/spec/spec_helper.rb +9 -0
- data/spec/tmp-repo_spec.rb +183 -0
- data/tmp-repo.gemspec +18 -0
- metadata +61 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 750d50105e4fe0fd086ed4c10c8bf3f4648b17c6
|
4
|
+
data.tar.gz: ebacae5e6fd5562a16c78ee84f1f262d45546620
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: d57090af6e6155920bea50f1d8fd2513bcae60ec2030c9eb5bead81e0c2f9ff740e5165c27b244edf097a130ddf8ca1bd178f0c68e37dfbd93138a72a82ef943
|
7
|
+
data.tar.gz: ab3f893e67603d9a024f8bf18c44a042e82b2bd56a68771684daa7c793efb50233c7ed527524ac53906796c91d08b097e2c1b84ef818fd001f36e355bac60833
|
data/Gemfile
ADDED
data/History.txt
ADDED
data/README.md
ADDED
@@ -0,0 +1,120 @@
|
|
1
|
+
tmp-repo
|
2
|
+
========
|
3
|
+
|
4
|
+
[](http://travis-ci.org/camertron/tmp-repo)
|
5
|
+
|
6
|
+
Creates and manages git repositories in the operating system's temporary directory. It does this by providing a thin wrapper around the git binary that's pointed at a randomly generated temporary folder.
|
7
|
+
|
8
|
+
## Installation
|
9
|
+
|
10
|
+
`gem install tmp-repo`
|
11
|
+
|
12
|
+
## Usage
|
13
|
+
|
14
|
+
```ruby
|
15
|
+
require 'tmp-repo'
|
16
|
+
```
|
17
|
+
|
18
|
+
### Basics
|
19
|
+
|
20
|
+
Creating a new `TmpRepo` will automatically create a randomly named folder in your system's temp directory and initialize a git repository in it:
|
21
|
+
|
22
|
+
```ruby
|
23
|
+
repo = TmpRepo.new
|
24
|
+
repo.working_dir # => #<Pathname:/var/folders/3x/n10r69b16bq_rlcqr3fy0rwc0000gn/T/b068487773901ffe23e66a8259711fa1>
|
25
|
+
```
|
26
|
+
|
27
|
+
Once created, you can ask your `TmpRepo` questions and perform operations on it. Don't forget to clean up after yourself when you're finished:
|
28
|
+
|
29
|
+
```ruby
|
30
|
+
repo.unlink
|
31
|
+
```
|
32
|
+
|
33
|
+
### Creating Files
|
34
|
+
|
35
|
+
```ruby
|
36
|
+
repo.create_file('foo.txt') do |f|
|
37
|
+
f.write("I'm a new file!")
|
38
|
+
end
|
39
|
+
```
|
40
|
+
|
41
|
+
OR
|
42
|
+
|
43
|
+
```ruby
|
44
|
+
file = repo.create_file('foo.txt')
|
45
|
+
file.write("I'm a new file!")
|
46
|
+
file.close
|
47
|
+
```
|
48
|
+
|
49
|
+
### Branching
|
50
|
+
|
51
|
+
To create a new branch:
|
52
|
+
|
53
|
+
```ruby
|
54
|
+
repo.create_branch('my_new_branch')
|
55
|
+
```
|
56
|
+
|
57
|
+
To check out a branch:
|
58
|
+
|
59
|
+
```ruby
|
60
|
+
repo.checkout('my_other_branch')
|
61
|
+
```
|
62
|
+
|
63
|
+
To get the current branch:
|
64
|
+
|
65
|
+
```ruby
|
66
|
+
repo.current_branch # => 'master'
|
67
|
+
```
|
68
|
+
|
69
|
+
### Staging and Committing
|
70
|
+
|
71
|
+
To add all files to the git stage:
|
72
|
+
|
73
|
+
```ruby
|
74
|
+
repo.add_all
|
75
|
+
```
|
76
|
+
|
77
|
+
To commit staged files:
|
78
|
+
|
79
|
+
```ruby
|
80
|
+
repo.commit('Commit message')
|
81
|
+
```
|
82
|
+
|
83
|
+
### Repo Status
|
84
|
+
|
85
|
+
`TmpRepo` instances provide a convenient way to retrieve the status of the repository via the `status` method. `status` return values are a simple hash of arrays:
|
86
|
+
|
87
|
+
```ruby
|
88
|
+
status = repo.status
|
89
|
+
status[:new_file] # => ['file1.txt', 'file2.txt']
|
90
|
+
status[:deleted] # => ['file3.txt']
|
91
|
+
status[:modified] # => ['file4.txt']
|
92
|
+
```
|
93
|
+
|
94
|
+
### Custom Commands
|
95
|
+
|
96
|
+
This library only provides wrapper methods around the most common git commands. To run additional git commands, use the `git` method:
|
97
|
+
|
98
|
+
```ruby
|
99
|
+
repo.git('rebase master')
|
100
|
+
```
|
101
|
+
|
102
|
+
In addition, the lower-level `in_repo` method wraps the given block in a `Dir.chdir`, meaning the block is executed in the context of the repo's working directory:
|
103
|
+
|
104
|
+
```ruby
|
105
|
+
repo.in_repo do
|
106
|
+
`ls` # list files in the repo's working directory
|
107
|
+
end
|
108
|
+
```
|
109
|
+
|
110
|
+
## Requirements
|
111
|
+
|
112
|
+
No external requirements.
|
113
|
+
|
114
|
+
## Running Tests
|
115
|
+
|
116
|
+
`bundle exec rake` should do the trick.
|
117
|
+
|
118
|
+
## Authors
|
119
|
+
|
120
|
+
* Cameron C. Dutro: http://github.com/camertron
|
data/Rakefile
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
require 'rubygems' unless ENV['NO_RUBYGEMS']
|
4
|
+
|
5
|
+
require 'bundler'
|
6
|
+
require 'rspec/core/rake_task'
|
7
|
+
require 'rubygems/package_task'
|
8
|
+
|
9
|
+
require './lib/tmp-repo'
|
10
|
+
|
11
|
+
Bundler::GemHelper.install_tasks
|
12
|
+
|
13
|
+
task :default => :spec
|
14
|
+
|
15
|
+
desc 'Run specs'
|
16
|
+
RSpec::Core::RakeTask.new do |t|
|
17
|
+
t.pattern = './spec/**/*_spec.rb'
|
18
|
+
end
|
data/lib/tmp-repo.rb
ADDED
@@ -0,0 +1,117 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
require 'tmpdir'
|
4
|
+
require 'pathname'
|
5
|
+
require 'fileutils'
|
6
|
+
require 'securerandom'
|
7
|
+
|
8
|
+
class TmpRepo
|
9
|
+
class GitError < StandardError; end
|
10
|
+
|
11
|
+
attr_reader :working_dir
|
12
|
+
|
13
|
+
def initialize
|
14
|
+
@working_dir = Pathname(
|
15
|
+
File.join(Dir.tmpdir, SecureRandom.hex(16))
|
16
|
+
)
|
17
|
+
|
18
|
+
FileUtils.mkdir_p(working_dir)
|
19
|
+
git('init')
|
20
|
+
end
|
21
|
+
|
22
|
+
def unlink
|
23
|
+
FileUtils.rm_rf(working_dir.to_s)
|
24
|
+
nil
|
25
|
+
end
|
26
|
+
|
27
|
+
def create_file(new_file)
|
28
|
+
new_path = working_dir.join(new_file).to_s
|
29
|
+
handle = File.open(new_path, 'w+')
|
30
|
+
|
31
|
+
if block_given?
|
32
|
+
yield handle
|
33
|
+
handle.close
|
34
|
+
else
|
35
|
+
handle
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def add_all
|
40
|
+
git('add -A')
|
41
|
+
end
|
42
|
+
|
43
|
+
def commit(message)
|
44
|
+
git("commit -m '#{message.gsub("'", "\\\\'")}'")
|
45
|
+
end
|
46
|
+
|
47
|
+
def checkout(ref)
|
48
|
+
git("checkout #{ref}")
|
49
|
+
end
|
50
|
+
|
51
|
+
def create_branch(branch_name)
|
52
|
+
git("checkout -b #{branch_name}")
|
53
|
+
end
|
54
|
+
|
55
|
+
def current_branch
|
56
|
+
git('rev-parse --abbrev-ref HEAD').strip
|
57
|
+
end
|
58
|
+
|
59
|
+
def status
|
60
|
+
parse_status(git('status'))
|
61
|
+
end
|
62
|
+
|
63
|
+
def git(command)
|
64
|
+
in_repo do
|
65
|
+
output = `git #{command}`
|
66
|
+
|
67
|
+
if $?.exitstatus != 0
|
68
|
+
raise GitError, output
|
69
|
+
end
|
70
|
+
|
71
|
+
output
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def in_repo
|
76
|
+
Dir.chdir(working_dir.to_s) do
|
77
|
+
yield
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
private
|
82
|
+
|
83
|
+
def parse_status(status_text)
|
84
|
+
lines = status_text.split("\n")
|
85
|
+
status_hash = create_status_hash
|
86
|
+
statuses = possible_statuses_from(status_hash)
|
87
|
+
|
88
|
+
lines.each do |line|
|
89
|
+
index = -1
|
90
|
+
|
91
|
+
status = statuses.find do |status|
|
92
|
+
index = line =~ /#{Regexp.escape(status)}: /
|
93
|
+
end
|
94
|
+
|
95
|
+
if status
|
96
|
+
status = status_to_hash_key(status)
|
97
|
+
status_hash[status] << line[(index + status.size + 2)..-1].strip
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
status_hash
|
102
|
+
end
|
103
|
+
|
104
|
+
def status_to_hash_key(status)
|
105
|
+
status.gsub(' ', '_').to_sym
|
106
|
+
end
|
107
|
+
|
108
|
+
def possible_statuses_from(status_hash)
|
109
|
+
status_hash.keys.map do |status|
|
110
|
+
status.to_s.gsub('_', ' ').downcase
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
def create_status_hash
|
115
|
+
{ modified: [], deleted: [], new_file: [] }
|
116
|
+
end
|
117
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,183 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
describe TmpRepo do
|
6
|
+
let(:repo) do
|
7
|
+
TmpRepo.new
|
8
|
+
end
|
9
|
+
|
10
|
+
before(:each) do
|
11
|
+
repo.git('config user.email tester@tester.com')
|
12
|
+
repo.git('config user.name Tester McTesterson')
|
13
|
+
end
|
14
|
+
|
15
|
+
after(:each) do
|
16
|
+
repo.unlink
|
17
|
+
end
|
18
|
+
|
19
|
+
def in_repo
|
20
|
+
Dir.chdir(repo.working_dir.to_s) do
|
21
|
+
yield
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
describe '#initialize' do
|
26
|
+
it 'should initialize the repository' do
|
27
|
+
expect(repo.working_dir.join('.git')).to exist
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
describe '#unlink' do
|
32
|
+
it 'should delete the temp directory' do
|
33
|
+
repo.unlink
|
34
|
+
expect(repo.working_dir).to_not exist
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
describe '#create_file' do
|
39
|
+
it 'yields a file handle if given a block' do
|
40
|
+
repo.create_file('foo.txt') do |f|
|
41
|
+
expect(f).to be_a(IO)
|
42
|
+
f.write('foobar')
|
43
|
+
end
|
44
|
+
|
45
|
+
contents = File.read(repo.working_dir.join('foo.txt').to_s)
|
46
|
+
expect(contents).to eq('foobar')
|
47
|
+
end
|
48
|
+
|
49
|
+
it 'returns a file handle if not given a block' do
|
50
|
+
handle = repo.create_file('foo.txt')
|
51
|
+
expect(handle).to be_a(IO)
|
52
|
+
handle.write('foobarbaz')
|
53
|
+
handle.close
|
54
|
+
|
55
|
+
contents = File.read(repo.working_dir.join('foo.txt').to_s)
|
56
|
+
expect(contents).to eq('foobarbaz')
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
describe '#add_all' do
|
61
|
+
it 'stages all files' do
|
62
|
+
repo.create_file('foo.txt') { |f| f.write('foobar') }
|
63
|
+
repo.add_all
|
64
|
+
|
65
|
+
in_repo do
|
66
|
+
expect(`git status`).to match(/new file:[\s]+foo\.txt/)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
describe '#commit' do
|
72
|
+
it 'commits the stage' do
|
73
|
+
repo.create_file('foo.txt') { |f| f.write('foobar') }
|
74
|
+
repo.add_all
|
75
|
+
repo.commit('Committing foobar')
|
76
|
+
|
77
|
+
in_repo do
|
78
|
+
expect(`git log`).to match(/Committing foobar/)
|
79
|
+
expect(`git show --name-only HEAD`).to include('foo.txt')
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
context 'with a single commit' do
|
85
|
+
before(:each) do
|
86
|
+
repo.create_file('foo.txt') do |f|
|
87
|
+
f.write('foobar')
|
88
|
+
end
|
89
|
+
|
90
|
+
repo.add_all
|
91
|
+
repo.commit('Foobar committed')
|
92
|
+
end
|
93
|
+
|
94
|
+
describe '#checkout' do
|
95
|
+
it 'checks out the given branch' do
|
96
|
+
in_repo do
|
97
|
+
`git checkout -b my_branch && git checkout master`
|
98
|
+
expect(`git rev-parse --abbrev-ref HEAD`.strip).to eq('master')
|
99
|
+
end
|
100
|
+
|
101
|
+
repo.checkout('my_branch')
|
102
|
+
|
103
|
+
in_repo do
|
104
|
+
expect(`git rev-parse --abbrev-ref HEAD`.strip).to eq('my_branch')
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
describe '#create_branch' do
|
110
|
+
it 'creates a new branch' do
|
111
|
+
repo.create_branch('new_branch')
|
112
|
+
|
113
|
+
in_repo do
|
114
|
+
expect(`git branch`).to include('new_branch')
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
describe '#current_branch' do
|
120
|
+
it 'returns the current branch name' do
|
121
|
+
in_repo { `git checkout -b cool_branch` }
|
122
|
+
expect(repo.current_branch).to eq('cool_branch')
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
describe '#status' do
|
127
|
+
it 'returns no results when there are no uncommitted changes' do
|
128
|
+
repo.status.tap do |status|
|
129
|
+
expect(status[:new_file]).to be_empty
|
130
|
+
expect(status[:modified]).to be_empty
|
131
|
+
expect(status[:deleted]).to be_empty
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
it 'shows new files' do
|
136
|
+
repo.create_file('hello.txt') do |f|
|
137
|
+
f.write('blarg blegh')
|
138
|
+
end
|
139
|
+
|
140
|
+
repo.add_all
|
141
|
+
|
142
|
+
repo.status.tap do |status|
|
143
|
+
expect(status[:new_file]).to include('hello.txt')
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
it 'shows modified files' do
|
148
|
+
in_repo do
|
149
|
+
File.open('foo.txt', 'w+') do |f|
|
150
|
+
f.write("\nI'm a change!")
|
151
|
+
end
|
152
|
+
|
153
|
+
repo.add_all
|
154
|
+
|
155
|
+
repo.status.tap do |status|
|
156
|
+
expect(status[:modified]).to include('foo.txt')
|
157
|
+
end
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
it 'shows deleted files' do
|
162
|
+
in_repo do
|
163
|
+
File.unlink('foo.txt')
|
164
|
+
repo.add_all
|
165
|
+
|
166
|
+
repo.status.tap do |status|
|
167
|
+
expect(status[:deleted]).to include('foo.txt')
|
168
|
+
end
|
169
|
+
end
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
173
|
+
describe '#git' do
|
174
|
+
it 'facilitates executing custom git commands and returning their output' do
|
175
|
+
expect(repo.git('branch')).to include('master')
|
176
|
+
end
|
177
|
+
|
178
|
+
it 'raises an error if the command fails' do
|
179
|
+
expect(lambda { repo.git('') }).to raise_error(TmpRepo::GitError)
|
180
|
+
end
|
181
|
+
end
|
182
|
+
end
|
183
|
+
end
|
data/tmp-repo.gemspec
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
$:.unshift File.join(File.dirname(__FILE__), 'lib')
|
2
|
+
require 'tmp-repo/version'
|
3
|
+
|
4
|
+
Gem::Specification.new do |s|
|
5
|
+
s.name = "tmp-repo"
|
6
|
+
s.version = ::TmpRepo::VERSION
|
7
|
+
s.authors = ["Cameron Dutro"]
|
8
|
+
s.email = ["camertron@gmail.com"]
|
9
|
+
s.homepage = "http://github.com/camertron"
|
10
|
+
|
11
|
+
s.description = s.summary = "Creates and manages a git repository in the operating system's temporary directory. Useful for running git operations in tests."
|
12
|
+
|
13
|
+
s.platform = Gem::Platform::RUBY
|
14
|
+
s.has_rdoc = true
|
15
|
+
|
16
|
+
s.require_path = 'lib'
|
17
|
+
s.files = Dir["{lib,spec}/**/*", "Gemfile", "History.txt", "README.md", "Rakefile", "tmp-repo.gemspec"]
|
18
|
+
end
|
metadata
ADDED
@@ -0,0 +1,61 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: tmp-repo
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Cameron Dutro
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2014-08-21 00:00:00 Z
|
13
|
+
dependencies: []
|
14
|
+
|
15
|
+
description: Creates and manages a git repository in the operating system's temporary directory. Useful for running git operations in tests.
|
16
|
+
email:
|
17
|
+
- camertron@gmail.com
|
18
|
+
executables: []
|
19
|
+
|
20
|
+
extensions: []
|
21
|
+
|
22
|
+
extra_rdoc_files: []
|
23
|
+
|
24
|
+
files:
|
25
|
+
- Gemfile
|
26
|
+
- History.txt
|
27
|
+
- README.md
|
28
|
+
- Rakefile
|
29
|
+
- lib/tmp-repo.rb
|
30
|
+
- lib/tmp-repo/version.rb
|
31
|
+
- spec/spec_helper.rb
|
32
|
+
- spec/tmp-repo_spec.rb
|
33
|
+
- tmp-repo.gemspec
|
34
|
+
homepage: http://github.com/camertron
|
35
|
+
licenses: []
|
36
|
+
|
37
|
+
metadata: {}
|
38
|
+
|
39
|
+
post_install_message:
|
40
|
+
rdoc_options: []
|
41
|
+
|
42
|
+
require_paths:
|
43
|
+
- lib
|
44
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
45
|
+
requirements:
|
46
|
+
- &id001
|
47
|
+
- ">="
|
48
|
+
- !ruby/object:Gem::Version
|
49
|
+
version: "0"
|
50
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- *id001
|
53
|
+
requirements: []
|
54
|
+
|
55
|
+
rubyforge_project:
|
56
|
+
rubygems_version: 2.2.2
|
57
|
+
signing_key:
|
58
|
+
specification_version: 4
|
59
|
+
summary: Creates and manages a git repository in the operating system's temporary directory. Useful for running git operations in tests.
|
60
|
+
test_files: []
|
61
|
+
|