v 0.0.4
Sign up to get free protection for your applications and to get access to all the features.
- data/.document +5 -0
- data/.gitignore +23 -0
- data/.watchr +24 -0
- data/.yardoc +0 -0
- data/LICENSE +20 -0
- data/README.markdown +146 -0
- data/Rakefile +56 -0
- data/VERSION +1 -0
- data/auto_commit.rb +131 -0
- data/lib/v/adapters/git/branches.rb +115 -0
- data/lib/v/adapters/git/commits.rb +55 -0
- data/lib/v/adapters/git/environment.rb +99 -0
- data/lib/v/adapters/git/index.rb +63 -0
- data/lib/v/adapters/git/object.rb +104 -0
- data/lib/v/adapters/git/object_types/blob.rb +24 -0
- data/lib/v/adapters/git/object_types/commit.rb +124 -0
- data/lib/v/adapters/git/object_types/tag.rb +23 -0
- data/lib/v/adapters/git/object_types/tree.rb +51 -0
- data/lib/v/adapters/git/operations/add_to_index.rb +30 -0
- data/lib/v/adapters/git/operations/branch.rb +42 -0
- data/lib/v/adapters/git/operations/commit_index.rb +39 -0
- data/lib/v/adapters/git/operations/diff_index.rb +20 -0
- data/lib/v/adapters/git/operations/initialize_repository.rb +21 -0
- data/lib/v/adapters/git/operations/list_files.rb +38 -0
- data/lib/v/adapters/git/operations/list_tree.rb +30 -0
- data/lib/v/adapters/git/operations/push_references_to_remote.rb +25 -0
- data/lib/v/adapters/git/operations/remove_from_index.rb +25 -0
- data/lib/v/adapters/git/operations/reset_index.rb +25 -0
- data/lib/v/adapters/git/operations/show_log.rb +23 -0
- data/lib/v/adapters/git/operations/show_object.rb +21 -0
- data/lib/v/adapters/git/operations/tag.rb +29 -0
- data/lib/v/adapters/git/participation.rb +18 -0
- data/lib/v/adapters/git/remotes.rb +19 -0
- data/lib/v/adapters/git/status.rb +60 -0
- data/lib/v/adapters/git.rb +27 -0
- data/lib/v/adapters.rb +25 -0
- data/lib/v/arguments.rb +102 -0
- data/lib/v/errors.rb +39 -0
- data/lib/v/future.rb +46 -0
- data/lib/v/operation.rb +94 -0
- data/lib/v/worker.rb +73 -0
- data/lib/v.rb +29 -0
- data/test/teststrap.rb +4 -0
- data/test/v_test.rb +32 -0
- data/test/work_tree/file +1 -0
- data/v.gemspec +97 -0
- metadata +131 -0
@@ -0,0 +1,23 @@
|
|
1
|
+
module V::Adapters::Git
|
2
|
+
module Operations
|
3
|
+
ShowLog = operation(:log) do
|
4
|
+
# 1.6.3.2
|
5
|
+
arguments do |args|
|
6
|
+
args.pretty(:medium)
|
7
|
+
args.abbrev_commit
|
8
|
+
args.oneline
|
9
|
+
args.encoding('UTF-8')
|
10
|
+
args << '--'
|
11
|
+
# TODO: complete arguments ...
|
12
|
+
end
|
13
|
+
|
14
|
+
def run(environment)
|
15
|
+
out, err = exec environment
|
16
|
+
err.empty? or raise V::ERROR, err
|
17
|
+
|
18
|
+
out
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module V::Adapters::Git
|
2
|
+
module Operations
|
3
|
+
ShowObject = operation(:show) do
|
4
|
+
# 1.6.3.2
|
5
|
+
arguments do |args|
|
6
|
+
args.pretty(:medium)
|
7
|
+
args.abbrev_commit
|
8
|
+
args.oneline
|
9
|
+
args.encoding('UTF-8')
|
10
|
+
end
|
11
|
+
|
12
|
+
def run(environment)
|
13
|
+
out, err = exec environment
|
14
|
+
err.empty? or raise V::ERROR, err
|
15
|
+
|
16
|
+
out
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module V::Adapters::Git
|
2
|
+
module Operations
|
3
|
+
Tag = operation(:tag) do
|
4
|
+
# 1.6.3.2
|
5
|
+
arguments do |args|
|
6
|
+
args.annotated(:alias => true).a
|
7
|
+
args.signed(:alias => true).s
|
8
|
+
args.signed_as(nil, :alias => true).u
|
9
|
+
args.force(:alias => true).f
|
10
|
+
args.delete(:alias => true).d
|
11
|
+
args.verify(:alias => true).v
|
12
|
+
args.lines(1, :alias => true).n
|
13
|
+
args.list('*', :alias => true).l
|
14
|
+
args.contains.c
|
15
|
+
args.message(nil, :alias => true).m
|
16
|
+
args.file(nil, :alias => true).F
|
17
|
+
end
|
18
|
+
|
19
|
+
include WorkTreeRequirement
|
20
|
+
def run(environment)
|
21
|
+
out, err = exec environment
|
22
|
+
err.empty? or raise V::ERROR, err
|
23
|
+
|
24
|
+
out
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module V
|
2
|
+
module Adapters
|
3
|
+
module Git
|
4
|
+
Participation = Struct.new(:role, :name, :email, :unix_timestamp) do
|
5
|
+
|
6
|
+
def to_s
|
7
|
+
"#{ role } #{ name } <#{ email }> #{ unix_timestamp }"
|
8
|
+
end
|
9
|
+
|
10
|
+
# TODO: take TZ into account
|
11
|
+
def time
|
12
|
+
Time.at unix_timestamp.to_i
|
13
|
+
end
|
14
|
+
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
module V
|
2
|
+
module Adapters
|
3
|
+
module Git
|
4
|
+
Status = Struct.new :diff do
|
5
|
+
|
6
|
+
ADDED = :A
|
7
|
+
COPIED = :C
|
8
|
+
DELETED = :D
|
9
|
+
MODIFIED = :M
|
10
|
+
RENAMED = :R
|
11
|
+
TYPE_CHANGED = :T
|
12
|
+
UNMERGED = :U
|
13
|
+
UNKNOWN = :X
|
14
|
+
|
15
|
+
def added?(filename)
|
16
|
+
index[filename] == ADDED
|
17
|
+
end
|
18
|
+
def copied?(filename)
|
19
|
+
index[filename] == COPIED
|
20
|
+
end
|
21
|
+
def deleted?(filename)
|
22
|
+
index[filename] == DELETED
|
23
|
+
end
|
24
|
+
def modified?(filename)
|
25
|
+
index[filename] == MODIFIED
|
26
|
+
end
|
27
|
+
def renamed?(filename)
|
28
|
+
index[filename] == RENAMED
|
29
|
+
end
|
30
|
+
def type_changed?(filename)
|
31
|
+
index[filename] == TYPE_CHANGED
|
32
|
+
end
|
33
|
+
def unmerged?(filename)
|
34
|
+
index[filename] == UNMERGED
|
35
|
+
end
|
36
|
+
def unknown?(filename)
|
37
|
+
index[filename] == UNKNOWN
|
38
|
+
end
|
39
|
+
|
40
|
+
def [](filename)
|
41
|
+
index[filename]
|
42
|
+
end
|
43
|
+
|
44
|
+
protected
|
45
|
+
|
46
|
+
def index
|
47
|
+
build_index unless defined? @index
|
48
|
+
@index
|
49
|
+
end
|
50
|
+
def build_index
|
51
|
+
@index = diff.split($/).inject({}) do |mem, line|
|
52
|
+
state, path = line.split("\t").map { |v| v.strip }
|
53
|
+
mem.update path => state.to_sym
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module V
|
2
|
+
module Adapters
|
3
|
+
module Git
|
4
|
+
VERSION = [0,0,4]
|
5
|
+
|
6
|
+
# Builds Operations module.
|
7
|
+
Operations = Operations.new __FILE__.gsub(/\.rb$/, '')
|
8
|
+
|
9
|
+
module WorkTreeRequirement
|
10
|
+
# Ensures all calls require a git dir and a work tree.
|
11
|
+
def call(environment)
|
12
|
+
raise V::ENOTREPO unless File.directory? environment.git_dir
|
13
|
+
raise V::ENOTWTREE if environment.bare
|
14
|
+
|
15
|
+
super environment
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
begin
|
24
|
+
__dir__ = File.dirname __FILE__
|
25
|
+
%w[ environment branches commits index object participation status ].
|
26
|
+
each { |basename| require "#{ __dir__ }/git/#{ basename }" }
|
27
|
+
end
|
data/lib/v/adapters.rb
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
module V
|
2
|
+
module Adapters
|
3
|
+
autoload :Git, "#{ File.dirname __FILE__ }/adapters/git"
|
4
|
+
end
|
5
|
+
|
6
|
+
# Initialize a git environment.
|
7
|
+
#
|
8
|
+
# Attributes => Default
|
9
|
+
# :bare => false
|
10
|
+
# :work_tree => ENV || Dir.getwd
|
11
|
+
# :git_dir => ENV || bare? ? work_tree : File.join(work_tree, '.git')
|
12
|
+
# :which_git => `which git`
|
13
|
+
def self.git(attrs = {}, &block)
|
14
|
+
env = Adapters::Git::Environment.new attrs
|
15
|
+
|
16
|
+
if not block_given?
|
17
|
+
env
|
18
|
+
elsif not block.arity.between?(-1, 0)
|
19
|
+
yield env
|
20
|
+
else
|
21
|
+
env.instance_eval(&block)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
data/lib/v/arguments.rb
ADDED
@@ -0,0 +1,102 @@
|
|
1
|
+
module V
|
2
|
+
class Arguments
|
3
|
+
instance_methods.each { |meth| undef_method(meth) unless meth =~ /\A__/ }
|
4
|
+
|
5
|
+
def initialize(op, &args)
|
6
|
+
@op, @first_argument = op.to_sym, nil
|
7
|
+
|
8
|
+
@slots = []
|
9
|
+
yield self if block_given?
|
10
|
+
@slots.freeze
|
11
|
+
end
|
12
|
+
|
13
|
+
def method_missing(argument, *defaults)
|
14
|
+
options = Hash === defaults.last ? defaults.pop : {}
|
15
|
+
@first_argument = argument if options[:first]
|
16
|
+
|
17
|
+
slot = Slot.new argument, defaults, options
|
18
|
+
@slots << slot
|
19
|
+
|
20
|
+
slot
|
21
|
+
end
|
22
|
+
|
23
|
+
def <<(string)
|
24
|
+
@slots << string
|
25
|
+
end
|
26
|
+
|
27
|
+
def %(args)
|
28
|
+
opts = Hash === args.last ? args.pop : {}
|
29
|
+
opts[@first_argument] = args.shift if @first_argument
|
30
|
+
|
31
|
+
op_args = @slots.inject([@op]) { |ca, slot|
|
32
|
+
if String === slot
|
33
|
+
ca << slot
|
34
|
+
elsif key = slot.key(opts)
|
35
|
+
if slot.standalone? and opts[key]
|
36
|
+
ca << slot
|
37
|
+
else
|
38
|
+
value = opts[key]
|
39
|
+
|
40
|
+
if slot.defaults_to? value then ca
|
41
|
+
else
|
42
|
+
ca << slot.to_s % quote(value)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
else
|
46
|
+
ca
|
47
|
+
end
|
48
|
+
}.concat args.map { |arg| quote arg }
|
49
|
+
|
50
|
+
op_args * ' '
|
51
|
+
end
|
52
|
+
|
53
|
+
def inspect
|
54
|
+
@slots.inspect
|
55
|
+
end
|
56
|
+
|
57
|
+
protected
|
58
|
+
|
59
|
+
def quote(str)
|
60
|
+
str = "#{ str }"
|
61
|
+
|
62
|
+
str.gsub! "\'", "'\\\\''"
|
63
|
+
str.gsub! ";", '\\;'
|
64
|
+
|
65
|
+
"'#{ str }'"
|
66
|
+
end
|
67
|
+
|
68
|
+
class Slot
|
69
|
+
attr_reader :to_sym
|
70
|
+
def initialize(argument, defaults, options)
|
71
|
+
@to_s, @to_sym = "#{ argument }".gsub('_', '-'), argument
|
72
|
+
@captures = [argument]
|
73
|
+
@options = options
|
74
|
+
@standalone, @defaults = defaults.empty?, defaults.map { |d| d.to_s }
|
75
|
+
|
76
|
+
@fstring = if @options[:rude] then '%s'
|
77
|
+
elsif @options[:alias] and @standalone then '-$op'
|
78
|
+
elsif @options[:alias] and not @standalone then '-$op %s'
|
79
|
+
elsif not @options[:alias] and @standalone then '--$op'
|
80
|
+
else '--$op=%s'
|
81
|
+
end
|
82
|
+
end
|
83
|
+
def method_missing(sym)
|
84
|
+
@captures << sym
|
85
|
+
@to_s = sym.to_s if @options[:alias]
|
86
|
+
end
|
87
|
+
def standalone?
|
88
|
+
@standalone
|
89
|
+
end
|
90
|
+
def key(opts)
|
91
|
+
@captures.find { |cap| opts.member? cap }
|
92
|
+
end
|
93
|
+
def defaults_to?(value)
|
94
|
+
@defaults.include? value.to_s
|
95
|
+
end
|
96
|
+
def to_s
|
97
|
+
@fstring.sub '$op', @to_s
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
end
|
102
|
+
end
|
data/lib/v/errors.rb
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
module V
|
2
|
+
class ERROR < RuntimeError
|
3
|
+
# otherwise I get these stupid parenthesis warnings...
|
4
|
+
def self.raise(*args)
|
5
|
+
target = Thread === args.last ? args.pop : Kernel
|
6
|
+
target.raise new(*args)
|
7
|
+
end
|
8
|
+
end
|
9
|
+
class ENOTREPO < ERROR
|
10
|
+
def initialize
|
11
|
+
super 'repository do not exist'
|
12
|
+
end
|
13
|
+
end
|
14
|
+
class ENOTWTREE < ERROR
|
15
|
+
def initialize
|
16
|
+
super 'operation must be run in a work tree'
|
17
|
+
end
|
18
|
+
end
|
19
|
+
class ENOOP < ERROR
|
20
|
+
def initialize(op_sym)
|
21
|
+
super "undefined operation `#{ op_sym }'"
|
22
|
+
end
|
23
|
+
end
|
24
|
+
class ECMDNOFO
|
25
|
+
def initialize(command)
|
26
|
+
super "#{ command }: command not found"
|
27
|
+
end
|
28
|
+
end
|
29
|
+
class EUNREV < ERROR
|
30
|
+
def initialize
|
31
|
+
super 'unknown revision or path not in the working tree'
|
32
|
+
end
|
33
|
+
end
|
34
|
+
class ECLOSED < ERROR
|
35
|
+
def initialize
|
36
|
+
super 'worker queue was closed already'
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
data/lib/v/future.rb
ADDED
@@ -0,0 +1,46 @@
|
|
1
|
+
module V
|
2
|
+
class Future
|
3
|
+
instance_methods.each { |meth| undef_method(meth) unless meth =~ /\A__/ }
|
4
|
+
|
5
|
+
def initialize(worker)
|
6
|
+
@worker, @waiting = worker, []
|
7
|
+
end
|
8
|
+
|
9
|
+
def value
|
10
|
+
while (Thread.critical = true; not defined? @value)
|
11
|
+
Thread.current != @worker or
|
12
|
+
raise ThreadError, 'waiting for a value in worker causes deadlock'
|
13
|
+
@waiting << Thread.current
|
14
|
+
Thread.stop
|
15
|
+
end
|
16
|
+
|
17
|
+
@value
|
18
|
+
ensure
|
19
|
+
Thread.critical = false
|
20
|
+
end
|
21
|
+
|
22
|
+
def value=(value)
|
23
|
+
Thread.critical = true
|
24
|
+
@value = value
|
25
|
+
|
26
|
+
class << self
|
27
|
+
def value; @value end
|
28
|
+
end
|
29
|
+
|
30
|
+
begin
|
31
|
+
while thread = @waiting.shift
|
32
|
+
thread.wakeup
|
33
|
+
end
|
34
|
+
rescue ThreadError
|
35
|
+
retry
|
36
|
+
ensure
|
37
|
+
Thread.critical = false
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def method_missing(*params, &block)
|
42
|
+
value.send(*params, &block)
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
46
|
+
end
|
data/lib/v/operation.rb
ADDED
@@ -0,0 +1,94 @@
|
|
1
|
+
module V
|
2
|
+
|
3
|
+
class Operations < Module
|
4
|
+
|
5
|
+
def initialize(load_path)
|
6
|
+
@load_path, @operations = load_path, {}
|
7
|
+
end
|
8
|
+
|
9
|
+
def included(base)
|
10
|
+
base.const_set :Operations, self
|
11
|
+
|
12
|
+
class_path = File.join @load_path, 'operations', '**', '*'
|
13
|
+
Dir[ class_path ].each { |p| require p }
|
14
|
+
end
|
15
|
+
|
16
|
+
TO_SYM_DEFN = %q"def self.to_sym; :'%s' end"
|
17
|
+
DEF_SHORTCUT = <<-RUBY
|
18
|
+
def %s(*args, &callback)
|
19
|
+
schedule (self.class)::Operations.new(:%s, *args, &callback)
|
20
|
+
end
|
21
|
+
RUBY
|
22
|
+
def operation(op_sym, &defn)
|
23
|
+
this_module = self
|
24
|
+
op = Class.new(Operation) { const_set :Operations, this_module }
|
25
|
+
op.class_eval TO_SYM_DEFN % "#{ op_sym }".gsub('_', '-')
|
26
|
+
op.class_eval(&defn)
|
27
|
+
|
28
|
+
module_eval DEF_SHORTCUT % [ op_sym, op_sym ]
|
29
|
+
|
30
|
+
@operations[ op_sym ] = op
|
31
|
+
end
|
32
|
+
def new(op_sym, *args, &callback)
|
33
|
+
op_class = @operations[op_sym] or
|
34
|
+
V::ENOOP.raise(op_sym)
|
35
|
+
|
36
|
+
op_class.new(*args, &callback)
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
40
|
+
|
41
|
+
class Operation
|
42
|
+
attr_reader :arguments
|
43
|
+
|
44
|
+
def self.arguments(&defn)
|
45
|
+
const_set :Arguments, Arguments.new(self, &defn)
|
46
|
+
end
|
47
|
+
|
48
|
+
def initialize(*arguments, &callback)
|
49
|
+
@arguments, @callback = arguments, callback
|
50
|
+
@hooks = Hash.new { |h, k| h[k] = [] }
|
51
|
+
end
|
52
|
+
|
53
|
+
def call(environment)
|
54
|
+
@hooks[:pre].all? { |hook| hook[environment] != false } or throw :pre
|
55
|
+
value = run environment
|
56
|
+
@hooks[:post].all? { |hook| hook[environment] != false } or throw :post
|
57
|
+
|
58
|
+
@callback ? @callback[value] : value
|
59
|
+
end
|
60
|
+
|
61
|
+
def run(value)
|
62
|
+
raise NotImplementedError
|
63
|
+
end
|
64
|
+
|
65
|
+
def exec(environment)
|
66
|
+
sh = "#{ environment } #{ self }"
|
67
|
+
logger.info sh
|
68
|
+
|
69
|
+
stdout, stderr = Open3.popen3(sh) { |_, *oe| oe.map { |io| io.read } }
|
70
|
+
logger.debug stdout unless stdout.empty?
|
71
|
+
logger.error stderr unless stderr.empty?
|
72
|
+
|
73
|
+
return stdout, stderr
|
74
|
+
end
|
75
|
+
|
76
|
+
def to_s
|
77
|
+
(self.class)::Arguments % @arguments
|
78
|
+
end
|
79
|
+
|
80
|
+
# TODO: replace this stub
|
81
|
+
require 'logger'
|
82
|
+
@@logger = Logger.new STDERR
|
83
|
+
@@logger.level = Logger::INFO
|
84
|
+
|
85
|
+
def self.logger
|
86
|
+
@@logger
|
87
|
+
end
|
88
|
+
def logger
|
89
|
+
self.class.logger
|
90
|
+
end
|
91
|
+
|
92
|
+
end
|
93
|
+
|
94
|
+
end
|
data/lib/v/worker.rb
ADDED
@@ -0,0 +1,73 @@
|
|
1
|
+
module V
|
2
|
+
class Worker < Thread
|
3
|
+
class Group < ThreadGroup
|
4
|
+
include Singleton
|
5
|
+
|
6
|
+
def enclose
|
7
|
+
super
|
8
|
+
|
9
|
+
list.
|
10
|
+
each { |worker| worker.stop! }.
|
11
|
+
each { |worker| worker.join }
|
12
|
+
end
|
13
|
+
|
14
|
+
at_exit {
|
15
|
+
if defined? Test::Unit
|
16
|
+
unless $! or Test::Unit.respond_to?(:run?) && Test::Unit.run?
|
17
|
+
test_result = Test::Unit::AutoRunner.run
|
18
|
+
instance.enclose
|
19
|
+
exit test_result
|
20
|
+
end
|
21
|
+
else
|
22
|
+
instance.enclose
|
23
|
+
end
|
24
|
+
}
|
25
|
+
end
|
26
|
+
|
27
|
+
@instances = {}
|
28
|
+
def self.new(git_dir)
|
29
|
+
@instances[git_dir] ||= super()
|
30
|
+
end
|
31
|
+
|
32
|
+
def initialize
|
33
|
+
@queue = Queue.new
|
34
|
+
|
35
|
+
super do
|
36
|
+
while continue?
|
37
|
+
operation, environment, thread, future = @queue.pop
|
38
|
+
|
39
|
+
begin
|
40
|
+
future.value = operation.call environment
|
41
|
+
|
42
|
+
rescue Exception => e
|
43
|
+
thread.raise e
|
44
|
+
|
45
|
+
end if future
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
if continue?
|
50
|
+
Group.instance.add self
|
51
|
+
else
|
52
|
+
raise V::ECLOSED
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def enq(operation, environment)
|
57
|
+
raise V::ECLOSED unless continue?
|
58
|
+
|
59
|
+
thread, future = Thread.current, Future.new(self)
|
60
|
+
@queue.enq [operation, environment, thread, future]
|
61
|
+
|
62
|
+
future
|
63
|
+
end
|
64
|
+
|
65
|
+
def stop!
|
66
|
+
@queue.push nil
|
67
|
+
end
|
68
|
+
def continue?
|
69
|
+
not Group.instance.enclosed?
|
70
|
+
end
|
71
|
+
|
72
|
+
end
|
73
|
+
end
|
data/lib/v.rb
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
#
|
3
|
+
# v.rb
|
4
|
+
# v
|
5
|
+
#
|
6
|
+
# Created by Florian Aßmann on 2009-10-01.
|
7
|
+
# Copyright 2009 Oniversus Media, Fork Unstable Media. All rights reserved.
|
8
|
+
#
|
9
|
+
|
10
|
+
module V
|
11
|
+
VERSION = [0,0,4]
|
12
|
+
end
|
13
|
+
|
14
|
+
require 'enumerator'
|
15
|
+
require 'open3'
|
16
|
+
require 'singleton'
|
17
|
+
|
18
|
+
begin
|
19
|
+
require 'fastthread'
|
20
|
+
rescue
|
21
|
+
RUBY_PLATFORM =~ /java/ or warn 'Please install fastthread.'
|
22
|
+
require 'thread'
|
23
|
+
end
|
24
|
+
|
25
|
+
begin
|
26
|
+
__dir__ = File.dirname __FILE__
|
27
|
+
%w[ errors arguments operation worker future adapters ].
|
28
|
+
each { |basename| require "#{ __dir__ }/v/#{ basename }" }
|
29
|
+
end
|
data/test/teststrap.rb
ADDED
data/test/v_test.rb
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'teststrap'
|
2
|
+
|
3
|
+
context 'V' do
|
4
|
+
context 'git' do
|
5
|
+
|
6
|
+
setup do
|
7
|
+
@work_tree = Pathname.new "#{ File.dirname __FILE__ }/work_tree"
|
8
|
+
@work_tree.rmtree if @work_tree.directory?
|
9
|
+
@work_tree.mkpath
|
10
|
+
|
11
|
+
V.git :work_tree => @work_tree
|
12
|
+
end
|
13
|
+
|
14
|
+
should 'initialize repository' do
|
15
|
+
topic.init
|
16
|
+
|
17
|
+
File.directory? topic.git_dir
|
18
|
+
end
|
19
|
+
should 'add files to index' do
|
20
|
+
@work_tree.join('file').open('w') { |f| f << 0 }
|
21
|
+
|
22
|
+
topic.add('file').include? 'file'
|
23
|
+
end
|
24
|
+
asserts 'content of committed file' do
|
25
|
+
topic.index.commit 'commit file'
|
26
|
+
blob = topic.head.tree / 'file'
|
27
|
+
|
28
|
+
Integer blob.content
|
29
|
+
end.equals 0
|
30
|
+
|
31
|
+
end
|
32
|
+
end
|
data/test/work_tree/file
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0
|