multi_git 0.0.1.alpha1
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/lib/multi_git/backend.rb +100 -0
- data/lib/multi_git/backend_set.rb +42 -0
- data/lib/multi_git/blob.rb +52 -0
- data/lib/multi_git/builder.rb +19 -0
- data/lib/multi_git/commit.rb +185 -0
- data/lib/multi_git/directory.rb +67 -0
- data/lib/multi_git/error.rb +67 -0
- data/lib/multi_git/executeable.rb +12 -0
- data/lib/multi_git/file.rb +35 -0
- data/lib/multi_git/git_backend/blob.rb +11 -0
- data/lib/multi_git/git_backend/cmd.rb +117 -0
- data/lib/multi_git/git_backend/commit.rb +75 -0
- data/lib/multi_git/git_backend/object.rb +34 -0
- data/lib/multi_git/git_backend/ref.rb +36 -0
- data/lib/multi_git/git_backend/repository.rb +162 -0
- data/lib/multi_git/git_backend/tree.rb +22 -0
- data/lib/multi_git/git_backend.rb +19 -0
- data/lib/multi_git/handle.rb +33 -0
- data/lib/multi_git/jgit_backend/blob.rb +10 -0
- data/lib/multi_git/jgit_backend/commit.rb +45 -0
- data/lib/multi_git/jgit_backend/object.rb +48 -0
- data/lib/multi_git/jgit_backend/ref.rb +117 -0
- data/lib/multi_git/jgit_backend/repository.rb +223 -0
- data/lib/multi_git/jgit_backend/rewindeable_io.rb +33 -0
- data/lib/multi_git/jgit_backend/tree.rb +28 -0
- data/lib/multi_git/jgit_backend.rb +15 -0
- data/lib/multi_git/object.rb +59 -0
- data/lib/multi_git/ref.rb +381 -0
- data/lib/multi_git/repository.rb +190 -0
- data/lib/multi_git/rugged_backend/blob.rb +8 -0
- data/lib/multi_git/rugged_backend/commit.rb +38 -0
- data/lib/multi_git/rugged_backend/object.rb +38 -0
- data/lib/multi_git/rugged_backend/ref.rb +32 -0
- data/lib/multi_git/rugged_backend/repository.rb +160 -0
- data/lib/multi_git/rugged_backend/tree.rb +18 -0
- data/lib/multi_git/rugged_backend.rb +16 -0
- data/lib/multi_git/submodule.rb +7 -0
- data/lib/multi_git/symlink.rb +42 -0
- data/lib/multi_git/tree/builder.rb +184 -0
- data/lib/multi_git/tree.rb +144 -0
- data/lib/multi_git/tree_entry.rb +86 -0
- data/lib/multi_git/utils.rb +57 -0
- data/lib/multi_git/version.rb +3 -0
- data/lib/multi_git.rb +44 -0
- metadata +138 -0
@@ -0,0 +1,75 @@
|
|
1
|
+
require 'multi_git/git_backend/object'
|
2
|
+
require 'multi_git/commit'
|
3
|
+
module MultiGit
|
4
|
+
module GitBackend
|
5
|
+
class Commit < Object
|
6
|
+
include MultiGit::Commit
|
7
|
+
|
8
|
+
def parents
|
9
|
+
read!
|
10
|
+
@parents ||= @parent_oids.map{|oid| repository.read(oid) }
|
11
|
+
end
|
12
|
+
|
13
|
+
def tree
|
14
|
+
read!
|
15
|
+
@tree ||= repository.read(@tree_oid)
|
16
|
+
end
|
17
|
+
|
18
|
+
def message
|
19
|
+
read!
|
20
|
+
@message
|
21
|
+
end
|
22
|
+
|
23
|
+
def committer
|
24
|
+
read!
|
25
|
+
@committer
|
26
|
+
end
|
27
|
+
|
28
|
+
def author
|
29
|
+
read!
|
30
|
+
@author
|
31
|
+
end
|
32
|
+
|
33
|
+
def time
|
34
|
+
read!
|
35
|
+
@time
|
36
|
+
end
|
37
|
+
|
38
|
+
def commit_time
|
39
|
+
read!
|
40
|
+
@commit_time
|
41
|
+
end
|
42
|
+
|
43
|
+
def read!
|
44
|
+
return if @read
|
45
|
+
@read = true
|
46
|
+
@header, @message = content.split("\n\n")
|
47
|
+
@parent_oids = []
|
48
|
+
@header.each_line do |line|
|
49
|
+
type, content = line.split(' ',2)
|
50
|
+
case(type)
|
51
|
+
when 'tree' then @tree_oid = content.chomp
|
52
|
+
when 'parent' then @parent_oids << content.chomp
|
53
|
+
when 'author' then
|
54
|
+
@author, @time = parse_signature(content)
|
55
|
+
when 'committer' then
|
56
|
+
@committer, @commit_time = parse_signature(content)
|
57
|
+
else
|
58
|
+
raise "Commit line type: #{type}"
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
private
|
64
|
+
|
65
|
+
SIGNATURE_RX = /\A(.+) <([^>]+)> (\d+) ([\-+]\d{2})(\d{2})\Z/
|
66
|
+
|
67
|
+
def parse_signature(content)
|
68
|
+
match = SIGNATURE_RX.match(content)
|
69
|
+
return MultiGit::Handle.new(match[1],match[2]), Time.at(match[3].to_i).localtime(match[4]+':'+match[5])
|
70
|
+
end
|
71
|
+
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'multi_git/object'
|
2
|
+
require 'forwardable'
|
3
|
+
class MultiGit::GitBackend::Object
|
4
|
+
|
5
|
+
extend Forwardable
|
6
|
+
|
7
|
+
include MultiGit::Object
|
8
|
+
|
9
|
+
def initialize(repository, oid, content = nil)
|
10
|
+
@repository = repository
|
11
|
+
@git = repository.__backend__
|
12
|
+
@oid = oid
|
13
|
+
@content = content ? content.dup.freeze : nil
|
14
|
+
end
|
15
|
+
|
16
|
+
def bytesize
|
17
|
+
@size ||= begin
|
18
|
+
if @content
|
19
|
+
@content.bytesize
|
20
|
+
else
|
21
|
+
@git['cat-file',:s,@oid].to_i
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def content
|
27
|
+
@content ||= @git['cat-file',type.to_s,@oid].freeze
|
28
|
+
end
|
29
|
+
|
30
|
+
def to_io
|
31
|
+
StringIO.new(content)
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
require 'multi_git/ref'
|
3
|
+
module MultiGit
|
4
|
+
module GitBackend
|
5
|
+
class Ref
|
6
|
+
|
7
|
+
include MultiGit::Ref
|
8
|
+
|
9
|
+
attr :target
|
10
|
+
|
11
|
+
def initialize(repository, name)
|
12
|
+
super(repository, name)
|
13
|
+
read!
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
SHOW_REF_LINE = /\A(\h{40}) ([^\n]+)\Z/.freeze
|
19
|
+
|
20
|
+
def read!
|
21
|
+
begin
|
22
|
+
if symbolic?
|
23
|
+
content = repository.__backend__['symbolic-ref', name]
|
24
|
+
@target = repository.ref(content.chomp)
|
25
|
+
else
|
26
|
+
lines = repository.__backend__['show-ref', name].lines
|
27
|
+
match = SHOW_REF_LINE.match(lines.first)
|
28
|
+
@target = repository.read(match[1])
|
29
|
+
end
|
30
|
+
rescue Cmd::Error::ExitCode1
|
31
|
+
# doesn't exists
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,162 @@
|
|
1
|
+
require 'multi_git/utils'
|
2
|
+
require 'multi_git/tree_entry'
|
3
|
+
require 'multi_git/repository'
|
4
|
+
require 'multi_git/git_backend/cmd'
|
5
|
+
require 'multi_git/git_backend/blob'
|
6
|
+
require 'multi_git/git_backend/tree'
|
7
|
+
require 'multi_git/git_backend/commit'
|
8
|
+
require 'multi_git/git_backend/ref'
|
9
|
+
module MultiGit::GitBackend
|
10
|
+
|
11
|
+
class Repository < MultiGit::Repository
|
12
|
+
|
13
|
+
# @api private
|
14
|
+
def __backend__
|
15
|
+
@git
|
16
|
+
end
|
17
|
+
|
18
|
+
Utils = MultiGit::Utils
|
19
|
+
|
20
|
+
OBJECT_CLASSES = {
|
21
|
+
:blob => Blob,
|
22
|
+
:tree => Tree,
|
23
|
+
:commit => Commit
|
24
|
+
}
|
25
|
+
|
26
|
+
def bare?
|
27
|
+
git_work_tree.nil?
|
28
|
+
end
|
29
|
+
|
30
|
+
attr :git_dir
|
31
|
+
attr :git_work_tree
|
32
|
+
attr :git_binary
|
33
|
+
|
34
|
+
def initialize(path, options = {})
|
35
|
+
@git_binary = `which git`.chomp
|
36
|
+
options = initialize_options(path, options)
|
37
|
+
git_dir = options[:repository]
|
38
|
+
@git = Cmd.new(git_binary, :git_dir => git_dir )
|
39
|
+
if !::File.exists?(git_dir) || MultiGit::Utils.empty_dir?(git_dir)
|
40
|
+
if options[:init]
|
41
|
+
if options[:bare]
|
42
|
+
@git['init', :bare, git_dir]
|
43
|
+
else
|
44
|
+
@git['init', git_dir]
|
45
|
+
end
|
46
|
+
else
|
47
|
+
raise MultiGit::Error::NotARepository, options[:repository]
|
48
|
+
end
|
49
|
+
end
|
50
|
+
@git_dir = git_dir
|
51
|
+
@git_work_tree = options[:working_directory]
|
52
|
+
@index = options[:index]
|
53
|
+
verify_bareness(path, options)
|
54
|
+
end
|
55
|
+
|
56
|
+
# {include:MultiGit::Repository#write}
|
57
|
+
# @param (see MultiGit::Repository#write)
|
58
|
+
# @raise (see MultiGit::Repository#write)
|
59
|
+
# @return (see MultiGit::Repository#write)
|
60
|
+
def write(content, type = :blob)
|
61
|
+
if content.kind_of? MultiGit::Builder
|
62
|
+
return content >> self
|
63
|
+
end
|
64
|
+
validate_type(type)
|
65
|
+
oid = nil
|
66
|
+
if content.kind_of? MultiGit::Object
|
67
|
+
if include?(content.oid)
|
68
|
+
return read(content.oid)
|
69
|
+
end
|
70
|
+
content = content.to_io
|
71
|
+
end
|
72
|
+
if content.respond_to? :path
|
73
|
+
oid = @git["hash-object",:t, type.to_s,:w,'--', content.path].chomp
|
74
|
+
else
|
75
|
+
content = content.read if content.respond_to? :read
|
76
|
+
@git.call('hash-object',:t,type.to_s, :w, :stdin) do |stdin, stdout|
|
77
|
+
stdin.write(content)
|
78
|
+
stdin.close
|
79
|
+
oid = stdout.read.chomp
|
80
|
+
end
|
81
|
+
end
|
82
|
+
return OBJECT_CLASSES[type].new(self,oid)
|
83
|
+
end
|
84
|
+
|
85
|
+
# {include:MultiGit::Repository#read}
|
86
|
+
# @param (see MultiGit::Repository#read)
|
87
|
+
# @raise (see MultiGit::Repository#read)
|
88
|
+
# @return (see MultiGit::Repository#read)
|
89
|
+
def read(oidish)
|
90
|
+
oid = parse(oidish)
|
91
|
+
type = @git['cat-file',:t, oid].chomp
|
92
|
+
return OBJECT_CLASSES[type.to_sym].new(self, oid)
|
93
|
+
end
|
94
|
+
|
95
|
+
# {include:MultiGit::Repository#parse}
|
96
|
+
# @param (see MultiGit::Repository#parse)
|
97
|
+
# @raise (see MultiGit::Repository#parse)
|
98
|
+
# @return (see MultiGit::Repository#parse)
|
99
|
+
def parse(oidish)
|
100
|
+
begin
|
101
|
+
result = @git['rev-parse', :revs_only, :validate, oidish.to_s].chomp
|
102
|
+
if result == ""
|
103
|
+
raise MultiGit::Error::InvalidReference, oidish
|
104
|
+
end
|
105
|
+
return result
|
106
|
+
rescue Cmd::Error::ExitCode128
|
107
|
+
raise MultiGit::Error::InvalidReference, oidish
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
# {include:MultiGit::Repository#include?}
|
112
|
+
# @param (see MultiGit::Repository#include?)
|
113
|
+
# @raise (see MultiGit::Repository#include?)
|
114
|
+
# @return (see MultiGit::Repository#include?)
|
115
|
+
def include?(oid)
|
116
|
+
begin
|
117
|
+
@git['cat-file', :e, oid.to_s]
|
118
|
+
return true
|
119
|
+
rescue Cmd::Error::ExitCode1
|
120
|
+
return false
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
def ref(name)
|
125
|
+
MultiGit::GitBackend::Ref.new(self, name)
|
126
|
+
end
|
127
|
+
|
128
|
+
# @visibility private
|
129
|
+
MKTREE_FORMAT = "%06o %s %s\t%s\n"
|
130
|
+
|
131
|
+
# @visibility private
|
132
|
+
# @api private
|
133
|
+
def make_tree(entries)
|
134
|
+
@git.call('mktree') do |stdin, stdout|
|
135
|
+
entries.each do |name, mode, oid|
|
136
|
+
stdin.printf(MKTREE_FORMAT, mode, Utils.type_from_mode(mode), oid, name)
|
137
|
+
end
|
138
|
+
stdin.close
|
139
|
+
read(stdout.read.chomp)
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
# @visibility private
|
144
|
+
# @api private
|
145
|
+
def make_commit(commit)
|
146
|
+
env = {
|
147
|
+
'GIT_AUTHOR_NAME'=>commit[:author].name,
|
148
|
+
'GIT_AUTHOR_EMAIL'=>commit[:author].email,
|
149
|
+
'GIT_AUTHOR_DATE' =>commit[:time].strftime('%s %z'),
|
150
|
+
'GIT_COMMITTER_NAME'=>commit[:committer].name,
|
151
|
+
'GIT_COMMITTER_EMAIL'=>commit[:committer].email,
|
152
|
+
'GIT_COMMITTER_DATE' =>commit[:commit_time].strftime('%s %z')
|
153
|
+
}
|
154
|
+
@git.call_env(env, 'commit-tree', commit[:tree], commit[:parents].map{|p| [:p, p] } ) do |stdin, stdout|
|
155
|
+
stdin << commit[:message]
|
156
|
+
stdin.close
|
157
|
+
return read(stdout.read.chomp)
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
end
|
162
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'multi_git/tree'
|
2
|
+
require 'multi_git/git_backend/object'
|
3
|
+
module MultiGit::GitBackend
|
4
|
+
class Tree < Object
|
5
|
+
|
6
|
+
LS_TREE_REGEX = /^([0-7]{6}) (?:blob|tree|commit) (\h{40})\t(.+)$/
|
7
|
+
|
8
|
+
include MultiGit::Tree
|
9
|
+
|
10
|
+
def raw_entries
|
11
|
+
@raw_entries ||= begin
|
12
|
+
@git.call('ls-tree', oid) do |stdout|
|
13
|
+
stdout.each_line.map do |line|
|
14
|
+
raise unless LS_TREE_REGEX =~ line
|
15
|
+
[$3,$1.to_i(8),$2]
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module MultiGit
|
2
|
+
module GitBackend
|
3
|
+
class << self
|
4
|
+
|
5
|
+
def load!
|
6
|
+
end
|
7
|
+
|
8
|
+
def available?
|
9
|
+
true
|
10
|
+
end
|
11
|
+
|
12
|
+
def open(directory, options = {})
|
13
|
+
Repository.new(directory, options)
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
require 'multi_git/git_backend/repository'
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module MultiGit
|
2
|
+
# Encapsulates name + email. Mostly used for commits.
|
3
|
+
class Handle < Struct.new(:name, :email)
|
4
|
+
|
5
|
+
private
|
6
|
+
EMAIL = /\A\w+@\w+\.\w+\z/ # close enough, but
|
7
|
+
NAME_WITH_EMAIL = /\A(.*) <(\S+@\S+\.\S+)>\z/
|
8
|
+
public
|
9
|
+
|
10
|
+
# Parses a handle from a string
|
11
|
+
#
|
12
|
+
# Currently two formats are recognized. Either just a mail address
|
13
|
+
# (e.g. 'user@example.com') or user + mail address in brackets ( e.g.
|
14
|
+
# 'User <user@example.com>' ).
|
15
|
+
#
|
16
|
+
# @param string [String] a string containing a handle.
|
17
|
+
# @return [Handle]
|
18
|
+
#
|
19
|
+
# @example
|
20
|
+
# MultiGit::Handle.parse('me@mydom.ain') #=> be_a MultiGit::Handle
|
21
|
+
#
|
22
|
+
def self.parse(string)
|
23
|
+
case(string)
|
24
|
+
when EMAIL then return new(string, string)
|
25
|
+
when NAME_WITH_EMAIL then return new($1,$2)
|
26
|
+
else raise ArgumentError, "Unknown handle format: #{string}. Please use either 'user@example.com' or 'User <user@example.com>'"
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
DEFAULT = parse("MultiGit #{MultiGit::VERSION} <#{MultiGit::VERSION}@multi.git>")
|
31
|
+
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require 'multi_git/commit'
|
2
|
+
require 'multi_git/jgit_backend/object'
|
3
|
+
module MultiGit
|
4
|
+
module JGitBackend
|
5
|
+
class Commit < Object
|
6
|
+
include MultiGit::Commit
|
7
|
+
|
8
|
+
import 'org.eclipse.jgit.revwalk.RevWalk'
|
9
|
+
|
10
|
+
def parents
|
11
|
+
@parents ||= java_commit.parents.map{|pr| repository.read(pr.getId()) }
|
12
|
+
end
|
13
|
+
|
14
|
+
def tree
|
15
|
+
@tree ||= repository.read(java_commit.tree.id)
|
16
|
+
end
|
17
|
+
|
18
|
+
def message
|
19
|
+
@message ||= java_commit.full_message.freeze
|
20
|
+
end
|
21
|
+
|
22
|
+
def time
|
23
|
+
@time ||= java_commit.author_ident.when
|
24
|
+
end
|
25
|
+
|
26
|
+
def commit_time
|
27
|
+
@time ||= java_commit.committer_ident.when
|
28
|
+
end
|
29
|
+
|
30
|
+
def author
|
31
|
+
@author ||= MultiGit::Handle.new(java_commit.author_ident.name,java_commit.author_ident.email_address)
|
32
|
+
end
|
33
|
+
|
34
|
+
def committer
|
35
|
+
@committer ||= MultiGit::Handle.new(java_commit.committer_ident.name,java_commit.committer_ident.email_address)
|
36
|
+
end
|
37
|
+
private
|
38
|
+
|
39
|
+
def java_commit
|
40
|
+
@java_commit ||= repository.use_reader{|rd| RevWalk.new(rd).parseCommit(java_oid) }
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
require 'multi_git/object'
|
2
|
+
require 'forwardable'
|
3
|
+
require 'multi_git/jgit_backend/rewindeable_io'
|
4
|
+
class MultiGit::JGitBackend::Object
|
5
|
+
|
6
|
+
import "org.eclipse.jgit.lib.ObjectId"
|
7
|
+
|
8
|
+
extend Forwardable
|
9
|
+
|
10
|
+
include MultiGit::Object
|
11
|
+
|
12
|
+
def initialize(repository,oid, object = nil)
|
13
|
+
@repository = repository
|
14
|
+
@java_oid = oid
|
15
|
+
@git = repository.__backend__
|
16
|
+
@oid = ObjectId.toString(oid)
|
17
|
+
@java_object = object
|
18
|
+
end
|
19
|
+
|
20
|
+
def bytesize
|
21
|
+
java_object.getSize
|
22
|
+
end
|
23
|
+
|
24
|
+
def to_io
|
25
|
+
MultiGit::JGitBackend::RewindeableIO.new( java_stream )
|
26
|
+
end
|
27
|
+
|
28
|
+
def content
|
29
|
+
@content ||= to_io.read.freeze
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
def java_stream
|
35
|
+
stream = java_object.openStream
|
36
|
+
stream.mark(bytesize)
|
37
|
+
stream
|
38
|
+
end
|
39
|
+
|
40
|
+
protected
|
41
|
+
|
42
|
+
attr :java_oid
|
43
|
+
|
44
|
+
def java_object
|
45
|
+
@java_object ||= repository.use_reader{|rdr| rdr.open(@java_oid) }
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
@@ -0,0 +1,117 @@
|
|
1
|
+
require 'multi_git/ref'
|
2
|
+
module MultiGit
|
3
|
+
module JGitBackend
|
4
|
+
class Ref
|
5
|
+
|
6
|
+
include MultiGit::Ref
|
7
|
+
|
8
|
+
# HACK!
|
9
|
+
# @api private
|
10
|
+
# @visibility private
|
11
|
+
class Java::OrgEclipseJgitStorageFile::RefDirectoryUpdate
|
12
|
+
public :tryLock, :unlock, :doUpdate, :doDelete
|
13
|
+
end
|
14
|
+
|
15
|
+
# @api developer
|
16
|
+
class Updater < MultiGit::Ref::Updater
|
17
|
+
|
18
|
+
import "org.eclipse.jgit.lib.ObjectId"
|
19
|
+
import 'org.eclipse.jgit.lib.RefUpdate'
|
20
|
+
|
21
|
+
protected
|
22
|
+
|
23
|
+
def do_update(ru, nx)
|
24
|
+
case nx
|
25
|
+
when nil then
|
26
|
+
ru.doDelete(RefUpdate::Result::FORCED)
|
27
|
+
when MultiGit::Object then
|
28
|
+
ru.new_object_id = ObjectId.fromString(nx.oid)
|
29
|
+
ru.doUpdate(RefUpdate::Result::FORCED)
|
30
|
+
when MultiGit::Ref then
|
31
|
+
ru.link( nx.name )
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
36
|
+
|
37
|
+
# @api developer
|
38
|
+
class OptimisticUpdater < Updater
|
39
|
+
def update(nx)
|
40
|
+
ru = repository.__backend__.updateRef(name)
|
41
|
+
begin
|
42
|
+
if !ru.try_lock(false)
|
43
|
+
raise
|
44
|
+
end
|
45
|
+
if ref.direct?
|
46
|
+
old_id = ObjectId.toString(ru.old_object_id)
|
47
|
+
if target.nil?
|
48
|
+
raise Error::ConcurrentRefUpdate if old_id != Utils::NULL_OID
|
49
|
+
elsif old_id != target.oid
|
50
|
+
raise Error::ConcurrentRefUpdate
|
51
|
+
end
|
52
|
+
end
|
53
|
+
nx = super
|
54
|
+
do_update(ru, nx)
|
55
|
+
return nx
|
56
|
+
ensure
|
57
|
+
ru.unlock
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
end
|
62
|
+
|
63
|
+
# @api developer
|
64
|
+
class PessimisticUpdater < Updater
|
65
|
+
|
66
|
+
def initialize(*_)
|
67
|
+
super
|
68
|
+
@ref_update = repository.__backend__.updateRef(name)
|
69
|
+
if !@ref_update.try_lock(false)
|
70
|
+
raise
|
71
|
+
end
|
72
|
+
self.ref = ref.reload
|
73
|
+
end
|
74
|
+
|
75
|
+
def update(nx)
|
76
|
+
nx = super
|
77
|
+
do_update(@ref_update, nx)
|
78
|
+
return nx
|
79
|
+
end
|
80
|
+
|
81
|
+
def destroy!
|
82
|
+
@ref_update.unlock
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
def initialize(repository, name)
|
87
|
+
super(repository, name)
|
88
|
+
@java_ref = repository.__backend__.getRef(name)
|
89
|
+
end
|
90
|
+
|
91
|
+
def target
|
92
|
+
return nil unless java_ref
|
93
|
+
@target ||= begin
|
94
|
+
if java_ref.symbolic?
|
95
|
+
repository.ref(java_ref.target.name)
|
96
|
+
else
|
97
|
+
repository.read(java_ref.getObjectId())
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
# @api private
|
103
|
+
# @visibility private
|
104
|
+
attr :java_ref
|
105
|
+
|
106
|
+
private
|
107
|
+
|
108
|
+
def optimistic_updater
|
109
|
+
OptimisticUpdater
|
110
|
+
end
|
111
|
+
|
112
|
+
def pessimistic_updater
|
113
|
+
PessimisticUpdater
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|