multi_git 0.0.1.alpha1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|