ed 0.7.0 → 0.8.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.travis.yml +0 -8
- data/.yardopts +1 -0
- data/README.md +10 -24
- data/ed.gemspec +4 -1
- data/lib/ed.rb +8 -1
- data/lib/ed/config.rb +18 -0
- data/lib/ed/repository.rb +66 -83
- data/lib/ed/repository_copy.rb +96 -0
- data/lib/ed/version.rb +1 -1
- data/test/test_ed.rb +2 -2
- metadata +24 -14
data/.travis.yml
CHANGED
data/.yardopts
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
-m markdown
|
data/README.md
CHANGED
@@ -11,40 +11,28 @@ __OVERVIEW__
|
|
11
11
|
|
12
12
|
__DESCRIPTION__
|
13
13
|
|
14
|
-
|
15
|
-
It
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
__USE CASES__
|
20
|
-
|
21
|
-
* Run test suites against different tags, commits, and branches inside Ruby.
|
22
|
-
* Profile different tags, commits, and branches against one another inside Ruby.
|
23
|
-
* Explore code in different tags, commits, and branches using a REPL
|
24
|
-
like [Pry](https://github.com/pry/pry).
|
25
|
-
|
14
|
+
Ed is a library that you can use to talk to Git from Ruby.
|
15
|
+
It is useful when you'd like to run Ruby code in the context of multiple
|
16
|
+
commits, tags, or branchs.
|
17
|
+
|
26
18
|
__EXAMPLE__
|
27
19
|
|
28
|
-
The example below shows how you can run
|
20
|
+
The example below shows how you can run the test suite of two different
|
29
21
|
tags from a remote repository.
|
30
22
|
The [examples](https://github.com/robgleeson/ed/tree/master/examples) directory
|
31
23
|
has a few other examples you might want to check out.
|
32
24
|
|
33
25
|
__1.__
|
34
26
|
|
35
|
-
|
27
|
+
Run the tests for tag 'v0.1.0' and tag 'v0.2.0'.
|
36
28
|
|
37
29
|
Ed.new "git://github.com/robgleeson/observe.git" do
|
38
30
|
tag "v0.1.0" do |path|
|
39
|
-
|
40
|
-
system "rake test"
|
41
|
-
end
|
31
|
+
system "cd '#{path}' && rake test"
|
42
32
|
end
|
43
33
|
|
44
34
|
tag "v0.2.0" do |path|
|
45
|
-
|
46
|
-
system "rake test"
|
47
|
-
end
|
35
|
+
system "cd '#{path}' && rake test"
|
48
36
|
end
|
49
37
|
end
|
50
38
|
|
@@ -52,10 +40,8 @@ __PLATFORM SUPPORT__
|
|
52
40
|
|
53
41
|
_supported_
|
54
42
|
|
55
|
-
*
|
56
|
-
|
57
|
-
* JRuby
|
58
|
-
* MacRuby
|
43
|
+
* CRuby 1.9
|
44
|
+
|
59
45
|
|
60
46
|
__INSTALL__
|
61
47
|
|
data/ed.gemspec
CHANGED
@@ -20,7 +20,10 @@ Gem::Specification.new do |s|
|
|
20
20
|
|
21
21
|
|
22
22
|
#s.add_runtime_dependency "scm" , "~> 0.1.0.pre1"
|
23
|
-
|
23
|
+
|
24
|
+
s.required_ruby_version = "~> 1.9.1"
|
25
|
+
|
26
|
+
s.add_runtime_dependency "shell_command", "~> 0.1.0"
|
24
27
|
s.add_runtime_dependency "observe" , "~> 0.2.0"
|
25
28
|
s.add_development_dependency "rake" , "~> 0.9.2"
|
26
29
|
s.add_development_dependency "minitest", "~> 2.6"
|
data/lib/ed.rb
CHANGED
@@ -1,8 +1,11 @@
|
|
1
1
|
require 'observe'
|
2
|
+
require 'shell_command'
|
3
|
+
require 'fileutils'
|
2
4
|
require 'ed/version'
|
3
5
|
require 'ed/env'
|
4
6
|
require 'ed/config'
|
5
7
|
require 'ed/repository'
|
8
|
+
require 'ed/repository_copy'
|
6
9
|
require 'ed/delegator'
|
7
10
|
require 'ed/core_ext/object'
|
8
11
|
|
@@ -37,7 +40,11 @@ class Ed
|
|
37
40
|
# @return [Ed]
|
38
41
|
#
|
39
42
|
def initialize path, &block
|
40
|
-
|
43
|
+
if Ed::Repository.remote?(path) || Ed::Config.copy_repository?
|
44
|
+
@repo = Ed::RepositoryCopy.new(path)
|
45
|
+
else
|
46
|
+
@repo = Ed::Repository.new(path)
|
47
|
+
end
|
41
48
|
|
42
49
|
if block_given?
|
43
50
|
if block.arity == 1
|
data/lib/ed/config.rb
CHANGED
@@ -37,6 +37,23 @@ module Ed::Config
|
|
37
37
|
@repo_dir
|
38
38
|
end
|
39
39
|
|
40
|
+
#
|
41
|
+
# @param [Boolean]
|
42
|
+
# If true, a copy of a repository is created to work off.
|
43
|
+
#
|
44
|
+
def copy_repository= value
|
45
|
+
@copy_repository = value
|
46
|
+
end
|
47
|
+
|
48
|
+
#
|
49
|
+
# @return [Boolean]
|
50
|
+
# When true, a copy of a repository is created to work off.
|
51
|
+
#
|
52
|
+
def copy_repository
|
53
|
+
@copy_repository
|
54
|
+
end
|
55
|
+
alias_method :copy_repository?, :copy_repository
|
56
|
+
|
40
57
|
#
|
41
58
|
# @param [Boolean] value
|
42
59
|
# If true is given, a subprocess is created to check out a commit.
|
@@ -64,6 +81,7 @@ module Ed::Config
|
|
64
81
|
|
65
82
|
change do |config|
|
66
83
|
config.should_fork = false
|
84
|
+
config.copy_repository = true
|
67
85
|
|
68
86
|
if Ed::Env.windows?
|
69
87
|
config.repo_dir = ::ENV["TEMP"]
|
data/lib/ed/repository.rb
CHANGED
@@ -1,46 +1,68 @@
|
|
1
|
-
|
1
|
+
#
|
2
|
+
# The {Ed::Repository} class provides a interface to talk to a Git repository.
|
3
|
+
# It does _not_ make a copy of the repository but works off the path it is
|
4
|
+
# given.
|
5
|
+
#
|
6
|
+
# The {Ed::RepositoryCopy} class provides the same interface as this class but
|
7
|
+
# it creates a working copy of the repository to allow for parallel access.
|
8
|
+
#
|
9
|
+
# The default behavior is to use {Ed::RepositoryCopy} when talking to a
|
10
|
+
# repository but if you would like to disable copying you can use the
|
11
|
+
# {Ed::Config#copy_repository=} config option. You should be aware of its
|
12
|
+
# implications, though.
|
13
|
+
#
|
2
14
|
|
3
15
|
class Ed::Repository
|
4
16
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
# The reference (e.g: HEAD, tag, or branch)
|
16
|
-
#
|
17
|
-
# @return [Enumerator]
|
18
|
-
# Returns a Enumerator if no block is given.
|
19
|
-
#
|
20
|
-
def ls_remote *args
|
21
|
-
unless block_given?
|
22
|
-
return enum_for(:ls_remote, *args)
|
23
|
-
end
|
17
|
+
#
|
18
|
+
# @param [String] path
|
19
|
+
# The URI to a git a repository.
|
20
|
+
#
|
21
|
+
# @return [Boolean]
|
22
|
+
# Returns true if the path is considered to be remote.
|
23
|
+
#
|
24
|
+
def self.remote? path
|
25
|
+
!local?(path)
|
26
|
+
end
|
24
27
|
|
25
|
-
|
28
|
+
#
|
29
|
+
# @param [String] path
|
30
|
+
# The URI to a git a repository.
|
31
|
+
#
|
32
|
+
# @return [Boolean]
|
33
|
+
# Returns true if the path is considered to be local.
|
34
|
+
#
|
35
|
+
def self.local? path
|
36
|
+
URI.parse(path).scheme == "file" || !to_s.include?(':')
|
37
|
+
end
|
26
38
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
39
|
+
#
|
40
|
+
# @param [String] *args
|
41
|
+
# The same commands given to 'git ls-remote'.
|
42
|
+
#
|
43
|
+
# @yieldparam [String] sha
|
44
|
+
# The commit SHA.
|
45
|
+
#
|
46
|
+
# @yieldparam [String] ref
|
47
|
+
# The reference (e.g: HEAD, tag, or branch)
|
48
|
+
#
|
49
|
+
# @raise
|
50
|
+
# (see Ed::Repository#git)
|
51
|
+
#
|
52
|
+
# @return [Enumerator]
|
53
|
+
# Returns a Enumerator if no block is given.
|
54
|
+
#
|
55
|
+
def self.ls_remote *args
|
56
|
+
unless block_given?
|
57
|
+
return enum_for(:ls_remote, *args)
|
31
58
|
end
|
32
59
|
|
33
|
-
#
|
34
|
-
# @param [String] path
|
35
|
-
# The URI to a git a repository.
|
36
|
-
#
|
37
|
-
# @return [Boolean]
|
38
|
-
# Returns true if the repository is considered to exist on filesystem.
|
39
|
-
#
|
40
|
-
def is_local? path
|
41
|
-
path[0..6] == "file://" || !path.include?(":")
|
42
|
-
end
|
60
|
+
output = ShellCommand.run!("git ls-remote #{args.join(' ')}").stdout
|
43
61
|
|
62
|
+
output.each_line do |line|
|
63
|
+
sha, ref = line.split(/\s+/, 2)
|
64
|
+
yield sha, ref.chomp
|
65
|
+
end
|
44
66
|
end
|
45
67
|
|
46
68
|
#
|
@@ -57,15 +79,7 @@ class Ed::Repository
|
|
57
79
|
# Returns a instance of {Ed::Repository}.
|
58
80
|
#
|
59
81
|
def initialize path
|
60
|
-
@path =
|
61
|
-
|
62
|
-
parent = Process.pid
|
63
|
-
|
64
|
-
at_exit do
|
65
|
-
if parent == Process.pid
|
66
|
-
FileUtils.rm_rf(@path)
|
67
|
-
end
|
68
|
-
end
|
82
|
+
@path = path
|
69
83
|
end
|
70
84
|
|
71
85
|
#
|
@@ -79,49 +93,18 @@ class Ed::Repository
|
|
79
93
|
end
|
80
94
|
|
81
95
|
#
|
82
|
-
#
|
83
|
-
# The URI to copy from.
|
84
|
-
#
|
85
|
-
# @return [String]
|
86
|
-
# The path to the copied repository.
|
96
|
+
# Provides low-level access to the git binary in the context of {#path}.
|
87
97
|
#
|
88
|
-
|
89
|
-
|
90
|
-
sha = system("git", "--git-dir=#{path}/.git", "rev-parse", "HEAD")
|
91
|
-
else
|
92
|
-
remotes = Ed::Repository.ls_remote(path)
|
93
|
-
|
94
|
-
sha, _ =
|
95
|
-
remotes.find do |_, ref|
|
96
|
-
ref == 'HEAD'
|
97
|
-
end
|
98
|
-
end
|
99
|
-
|
100
|
-
#
|
101
|
-
# Directory layout:
|
102
|
-
# <REPO_DIR>/ed/<REPO_NAME>/<PROCESS ID>/<THREAD ID>/<COMMIT SHA>
|
103
|
-
#
|
104
|
-
repo_name = File.basename(path)
|
105
|
-
process_id = Process.pid
|
106
|
-
thread_id = Thread.current.object_id
|
107
|
-
namespace = "ed/#{repo_name}/#{process_id}/#{thread_id}/#{sha}"
|
108
|
-
destination = File.join(Ed::Config.repo_dir, namespace)
|
109
|
-
|
110
|
-
unless File.exists? destination
|
111
|
-
FileUtils.mkdir_p(destination)
|
112
|
-
system 'git', 'clone', '-q', path, destination
|
113
|
-
end
|
114
|
-
|
115
|
-
destination
|
116
|
-
end
|
117
|
-
private :copy!
|
118
|
-
|
98
|
+
# @raise [ShellCommand::Exception]
|
99
|
+
# If git exits with a status code that is non-zero.
|
119
100
|
#
|
120
|
-
#
|
121
|
-
# @return [void]
|
101
|
+
# @return [ShellCommand::Command]
|
122
102
|
#
|
123
103
|
def git *args
|
124
|
-
|
104
|
+
ShellCommand.run! "git",
|
105
|
+
"--git-dir=#{@path}/.git",
|
106
|
+
"--work-tree=#{@path}",
|
107
|
+
*args
|
125
108
|
end
|
126
109
|
private :git
|
127
110
|
|
@@ -0,0 +1,96 @@
|
|
1
|
+
#
|
2
|
+
# A {Ed::RepositoryCopy} is a subclass of {Ed::Repository} but with a distinct
|
3
|
+
# difference: it creates a copy of the repository it provides a interface to.
|
4
|
+
#
|
5
|
+
# By creating copies, it can allow parallel access to the same repository
|
6
|
+
# because every instance of {Ed::RepositoryCopy} has its own copy of the
|
7
|
+
# repository to work off.
|
8
|
+
#
|
9
|
+
# All remote repositories are _always_ instances of {Ed::RepositoryCopy}, and
|
10
|
+
# local repositories can be copied, too. It is recommended to create copies if
|
11
|
+
# you plan to access the same repository in parallel (either from Ed, or
|
12
|
+
# outside Ed).
|
13
|
+
#
|
14
|
+
# The default behavior is to create a copy all the time, but it can be
|
15
|
+
# configured from {Ed::Config.copy_repository=}. A {RepositoryCopy} is cached
|
16
|
+
# per-thread, and lives for the life of a process but for no longer, it is
|
17
|
+
# destroyed when the process exits.
|
18
|
+
#
|
19
|
+
|
20
|
+
class Ed::RepositoryCopy < Ed::Repository
|
21
|
+
|
22
|
+
#
|
23
|
+
# @param
|
24
|
+
# (see Ed::Repository#initialize)
|
25
|
+
#
|
26
|
+
# @return [Ed::RepositoryCopy]
|
27
|
+
# Returns a instance of {Ed::RepositoryCopy}.
|
28
|
+
#
|
29
|
+
def initialize path
|
30
|
+
@source = path
|
31
|
+
@path = copy!
|
32
|
+
@copy_dir = nil
|
33
|
+
|
34
|
+
parent = Process.pid
|
35
|
+
|
36
|
+
at_exit do
|
37
|
+
if parent == Process.pid
|
38
|
+
FileUtils.rm_rf(@path.to_s)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
#
|
44
|
+
# @param [String] from
|
45
|
+
# The URI to copy from.
|
46
|
+
#
|
47
|
+
# @raise
|
48
|
+
# (see Ed::Repository#git)
|
49
|
+
#
|
50
|
+
# @return [String]
|
51
|
+
# The path to the copied repository.
|
52
|
+
#
|
53
|
+
def copy!
|
54
|
+
unless File.exists? copy_dir
|
55
|
+
FileUtils.mkdir_p copy_dir
|
56
|
+
ShellCommand.run! 'git', 'clone', '-q', @source, copy_dir
|
57
|
+
end
|
58
|
+
|
59
|
+
copy_dir
|
60
|
+
end
|
61
|
+
private :copy!
|
62
|
+
|
63
|
+
#
|
64
|
+
# @raise
|
65
|
+
# (see Ed::Repository#git)
|
66
|
+
#
|
67
|
+
# @return [String]
|
68
|
+
# Returns the directory path a repository can be copied into.
|
69
|
+
#
|
70
|
+
def copy_dir
|
71
|
+
if @copy_dir
|
72
|
+
return @copy_dir
|
73
|
+
end
|
74
|
+
|
75
|
+
commit = nil
|
76
|
+
repo = File.basename(@source)
|
77
|
+
pid = Process.pid
|
78
|
+
thread_id = Thread.current.object_id
|
79
|
+
|
80
|
+
if Ed::Repository.local?(@source)
|
81
|
+
commit = ShellCommand.run!("git --git-dir=#{@source}/.git HEAD").stdout
|
82
|
+
else
|
83
|
+
remotes = Ed::Repository.ls_remote(@source)
|
84
|
+
|
85
|
+
commit, _ =
|
86
|
+
remotes.find do |_, ref|
|
87
|
+
ref == 'HEAD'
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
@copy_dir =
|
92
|
+
File.join Ed::Config.repo_dir, "ed/#{repo}/#{pid}/#{thread_id}/#{commit}"
|
93
|
+
end
|
94
|
+
private :copy_dir
|
95
|
+
|
96
|
+
end
|
data/lib/ed/version.rb
CHANGED
data/test/test_ed.rb
CHANGED
@@ -43,13 +43,13 @@ context Ed do
|
|
43
43
|
end
|
44
44
|
|
45
45
|
it 'must clone and store the repository locally.' do
|
46
|
-
File.exists?(@repo.path).must_equal(true)
|
46
|
+
File.exists?(@repo.path.to_s).must_equal(true)
|
47
47
|
end
|
48
48
|
|
49
49
|
it 'must checkout the "0.1.0" tag.' do
|
50
50
|
Tempfile.open "assertion" do |tmpfile|
|
51
51
|
@ed.setup do |path|
|
52
|
-
$: << File.join(path, "lib")
|
52
|
+
$: << File.join(path.to_s, "lib")
|
53
53
|
require 'thread'
|
54
54
|
require 'barney'
|
55
55
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ed
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.8.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,11 +9,22 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-
|
12
|
+
date: 2012-02-05 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: shell_command
|
16
|
+
requirement: &70357890439740 !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ~>
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: 0.1.0
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: *70357890439740
|
14
25
|
- !ruby/object:Gem::Dependency
|
15
26
|
name: observe
|
16
|
-
requirement: &
|
27
|
+
requirement: &70357890439280 !ruby/object:Gem::Requirement
|
17
28
|
none: false
|
18
29
|
requirements:
|
19
30
|
- - ~>
|
@@ -21,10 +32,10 @@ dependencies:
|
|
21
32
|
version: 0.2.0
|
22
33
|
type: :runtime
|
23
34
|
prerelease: false
|
24
|
-
version_requirements: *
|
35
|
+
version_requirements: *70357890439280
|
25
36
|
- !ruby/object:Gem::Dependency
|
26
37
|
name: rake
|
27
|
-
requirement: &
|
38
|
+
requirement: &70357890438800 !ruby/object:Gem::Requirement
|
28
39
|
none: false
|
29
40
|
requirements:
|
30
41
|
- - ~>
|
@@ -32,10 +43,10 @@ dependencies:
|
|
32
43
|
version: 0.9.2
|
33
44
|
type: :development
|
34
45
|
prerelease: false
|
35
|
-
version_requirements: *
|
46
|
+
version_requirements: *70357890438800
|
36
47
|
- !ruby/object:Gem::Dependency
|
37
48
|
name: minitest
|
38
|
-
requirement: &
|
49
|
+
requirement: &70357890438320 !ruby/object:Gem::Requirement
|
39
50
|
none: false
|
40
51
|
requirements:
|
41
52
|
- - ~>
|
@@ -43,7 +54,7 @@ dependencies:
|
|
43
54
|
version: '2.6'
|
44
55
|
type: :development
|
45
56
|
prerelease: false
|
46
|
-
version_requirements: *
|
57
|
+
version_requirements: *70357890438320
|
47
58
|
description: A Domain Specific Language(DSL) that you can use to talk to Git from
|
48
59
|
Ruby.
|
49
60
|
email:
|
@@ -54,6 +65,7 @@ extra_rdoc_files: []
|
|
54
65
|
files:
|
55
66
|
- .gitignore
|
56
67
|
- .travis.yml
|
68
|
+
- .yardopts
|
57
69
|
- Gemfile
|
58
70
|
- LICENSE.txt
|
59
71
|
- README.md
|
@@ -68,6 +80,7 @@ files:
|
|
68
80
|
- lib/ed/delegator.rb
|
69
81
|
- lib/ed/env.rb
|
70
82
|
- lib/ed/repository.rb
|
83
|
+
- lib/ed/repository_copy.rb
|
71
84
|
- lib/ed/version.rb
|
72
85
|
- test/setup.rb
|
73
86
|
- test/test_ed.rb
|
@@ -80,12 +93,9 @@ require_paths:
|
|
80
93
|
required_ruby_version: !ruby/object:Gem::Requirement
|
81
94
|
none: false
|
82
95
|
requirements:
|
83
|
-
- -
|
96
|
+
- - ~>
|
84
97
|
- !ruby/object:Gem::Version
|
85
|
-
version:
|
86
|
-
segments:
|
87
|
-
- 0
|
88
|
-
hash: 1406613959917538667
|
98
|
+
version: 1.9.1
|
89
99
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
90
100
|
none: false
|
91
101
|
requirements:
|
@@ -94,7 +104,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
94
104
|
version: '0'
|
95
105
|
segments:
|
96
106
|
- 0
|
97
|
-
hash:
|
107
|
+
hash: -3106733997781854880
|
98
108
|
requirements: []
|
99
109
|
rubyforge_project: Ed
|
100
110
|
rubygems_version: 1.8.15
|