v 0.0.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.
- 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
|