multi_git 0.0.1.alpha2 → 0.0.1.beta1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/lib/multi_git/config/default_schema.rb +26 -0
- data/lib/multi_git/config/schema.rb +141 -0
- data/lib/multi_git/config.rb +170 -0
- data/lib/multi_git/error.rb +4 -0
- data/lib/multi_git/git_backend/cmd.rb +9 -4
- data/lib/multi_git/git_backend/commit.rb +1 -1
- data/lib/multi_git/git_backend/config.rb +47 -0
- data/lib/multi_git/git_backend/ref.rb +9 -8
- data/lib/multi_git/git_backend/remote.rb +47 -0
- data/lib/multi_git/git_backend/repository.rb +16 -1
- data/lib/multi_git/jgit_backend/config.rb +52 -0
- data/lib/multi_git/jgit_backend/remote.rb +74 -0
- data/lib/multi_git/jgit_backend/repository.rb +15 -0
- data/lib/multi_git/ref.rb +82 -38
- data/lib/multi_git/refspec.rb +118 -0
- data/lib/multi_git/remote.rb +66 -0
- data/lib/multi_git/repository.rb +17 -0
- data/lib/multi_git/rugged_backend/config.rb +43 -0
- data/lib/multi_git/rugged_backend/remote.rb +66 -0
- data/lib/multi_git/rugged_backend/repository.rb +25 -0
- data/lib/multi_git/tree.rb +28 -9
- data/lib/multi_git/tree_entry.rb +1 -1
- data/lib/multi_git/version.rb +1 -1
- data/lib/multi_git.rb +1 -0
- metadata +16 -13
@@ -4,6 +4,8 @@ require 'multi_git/jgit_backend/blob'
|
|
4
4
|
require 'multi_git/jgit_backend/tree'
|
5
5
|
require 'multi_git/jgit_backend/commit'
|
6
6
|
require 'multi_git/jgit_backend/ref'
|
7
|
+
require 'multi_git/jgit_backend/config'
|
8
|
+
require 'multi_git/jgit_backend/remote'
|
7
9
|
module MultiGit::JGitBackend
|
8
10
|
class Repository < MultiGit::Repository
|
9
11
|
|
@@ -114,6 +116,10 @@ module MultiGit::JGitBackend
|
|
114
116
|
Ref.new(self, name)
|
115
117
|
end
|
116
118
|
|
119
|
+
def config
|
120
|
+
@config ||= Config.new(@git.config)
|
121
|
+
end
|
122
|
+
|
117
123
|
private
|
118
124
|
ALL_FILTER = %r{\Arefs/(?:heads|remotes)}
|
119
125
|
LOCAL_FILTER = %r{\Arefs/heads}
|
@@ -212,6 +218,15 @@ module MultiGit::JGitBackend
|
|
212
218
|
return Java::OrgEclipseJgitLib::ObjectId.toString(parse_java(ref))
|
213
219
|
end
|
214
220
|
|
221
|
+
def remote( name_or_url )
|
222
|
+
if looks_like_remote_url? name_or_url
|
223
|
+
remote = Remote.new(self, name_or_url)
|
224
|
+
else
|
225
|
+
remote = Remote::Persistent.new(self, name_or_url)
|
226
|
+
end
|
227
|
+
return remote
|
228
|
+
end
|
229
|
+
|
215
230
|
# @visibility private
|
216
231
|
# @api private
|
217
232
|
def parse_java(oidish)
|
data/lib/multi_git/ref.rb
CHANGED
@@ -157,7 +157,6 @@ module MultiGit
|
|
157
157
|
def destroy!
|
158
158
|
release_lock(@lock)
|
159
159
|
end
|
160
|
-
|
161
160
|
end
|
162
161
|
|
163
162
|
# @api developer
|
@@ -197,9 +196,17 @@ module MultiGit
|
|
197
196
|
release_lock( lock ) if lock
|
198
197
|
end
|
199
198
|
end
|
199
|
+
end
|
200
200
|
|
201
|
-
|
202
|
-
|
201
|
+
class RecklessUpdater < Updater
|
202
|
+
def update( new )
|
203
|
+
pu = PessimisticFileUpdater.new( ref )
|
204
|
+
begin
|
205
|
+
pu.update( new )
|
206
|
+
ensure
|
207
|
+
pu.destroy!
|
208
|
+
end
|
209
|
+
end
|
203
210
|
end
|
204
211
|
|
205
212
|
extend MultiGit::Utils::AbstractMethods
|
@@ -254,12 +261,6 @@ module MultiGit
|
|
254
261
|
|
255
262
|
alias / []
|
256
263
|
|
257
|
-
def []=(path, options = {}, value)
|
258
|
-
resolve.update(options.fetch(:lock, :pessimistic) ) do |commit|
|
259
|
-
|
260
|
-
end
|
261
|
-
end
|
262
|
-
|
263
264
|
# @!endgroup
|
264
265
|
|
265
266
|
# @!group Utility methods
|
@@ -272,6 +273,10 @@ module MultiGit
|
|
272
273
|
!direct?
|
273
274
|
end
|
274
275
|
|
276
|
+
def detached?
|
277
|
+
symbolic? && !target.kind_of?(Ref)
|
278
|
+
end
|
279
|
+
|
275
280
|
def exists?
|
276
281
|
!target.nil?
|
277
282
|
end
|
@@ -285,22 +290,31 @@ module MultiGit
|
|
285
290
|
# The new target of this reference is the result of the passed block. If
|
286
291
|
# you return nil, the ref will be deleted.
|
287
292
|
#
|
288
|
-
#
|
293
|
+
# @overload update( lock = :optimistic )
|
294
|
+
# By using the lock param you can control the isolation:
|
295
|
+
#
|
296
|
+
# [:reckless] Updates the reference the hard way. Only locks enough
|
297
|
+
# to ensure the integrity of the repository and simply
|
298
|
+
# overwrites concurrent changes.
|
299
|
+
# [:optimistic] If the target is altered during the execution of the
|
300
|
+
# block, a {MultiGit::Error::ConcurrentRefUpdate} is
|
301
|
+
# raised. This is the default as it holds hard locks
|
302
|
+
# only as long as necessary while providing pointfull
|
303
|
+
# isolation.
|
304
|
+
# [:pessimistic] A lock is acquired and held during the execution of the
|
305
|
+
# block. Concurrent updates will wait or fail. This is
|
306
|
+
# good if the block is not retry-able or very small.
|
289
307
|
#
|
290
|
-
# [:optimistic]
|
291
|
-
#
|
292
|
-
#
|
293
|
-
#
|
294
|
-
#
|
295
|
-
# [:pessimistic] A lock is acquired and held during the execution of the
|
296
|
-
# block. Concurrent updates will wait or fail. This is
|
297
|
-
# good if the block is not retry-able or very small.
|
308
|
+
# @param lock [:reckless, :optimistic, :pessimistic]
|
309
|
+
# @yield [current_target] Yields the current target and expects the block to return the new target
|
310
|
+
# @yieldparam current_target [MultiGit::Ref, MultiGit::Object, nil] current target
|
311
|
+
# @yieldreturn [MultiGit::Ref, MultiGit::Object, nil] new target
|
312
|
+
# @return [MultiGit::Ref] The altered ref
|
298
313
|
#
|
299
|
-
# @
|
300
|
-
#
|
301
|
-
#
|
302
|
-
#
|
303
|
-
# @return [MultiGit::Ref] The altered ref
|
314
|
+
# @overload update( value )
|
315
|
+
#
|
316
|
+
# @param value [Commit, Ref, nil] new target for this ref
|
317
|
+
# @return [MultiGit::Ref] The altered ref
|
304
318
|
#
|
305
319
|
# @example
|
306
320
|
# # setup:
|
@@ -320,26 +334,40 @@ module MultiGit
|
|
320
334
|
# repository.ref('refs/heads/master').target #=> eql commit
|
321
335
|
# # teardown:
|
322
336
|
# `rm -rf #{dir}`
|
323
|
-
def update(
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
updater = updater_class.new(self)
|
330
|
-
updater.update( yield(updater.target) )
|
331
|
-
return reload
|
332
|
-
ensure
|
333
|
-
updater.destroy! if updater
|
334
|
-
end
|
337
|
+
def update( value_or_lock = :optimistic )
|
338
|
+
updater = updater_class(block_given?, value_or_lock).new(self)
|
339
|
+
updater.update( block_given? ? yield(updater.target) : value_or_lock )
|
340
|
+
return reload
|
341
|
+
ensure
|
342
|
+
updater.destroy! if updater
|
335
343
|
end
|
336
344
|
|
345
|
+
# Shorthand for deleting this ref.
|
346
|
+
# @return [Ref]
|
337
347
|
def delete
|
338
|
-
update(
|
348
|
+
update( nil )
|
339
349
|
end
|
340
350
|
|
341
|
-
|
342
|
-
|
351
|
+
# Shorthand method to directly create a commit and update the given ref.
|
352
|
+
#
|
353
|
+
# @example
|
354
|
+
# # setup:
|
355
|
+
# dir = `mktemp -d`
|
356
|
+
# repository = MultiGit.open(dir, init: true)
|
357
|
+
# # insert a commit:
|
358
|
+
# repository.head.commit do
|
359
|
+
# tree['a_file'] = 'some_content'
|
360
|
+
# end
|
361
|
+
# # check result:
|
362
|
+
# repository.head['a_file'].content #=> eql 'some_content'
|
363
|
+
# # teardown:
|
364
|
+
# `rm -rf #{dir}`
|
365
|
+
#
|
366
|
+
# @option options :lock [:optimistic, :pessimistic] How to lock during the commit.
|
367
|
+
# @yield
|
368
|
+
# @return [Ref]
|
369
|
+
def commit(options = {}, &block)
|
370
|
+
resolve.update(options.fetch(:lock, :optimistic)) do |current|
|
343
371
|
Commit::Builder.new(current, &block)
|
344
372
|
end
|
345
373
|
return reload
|
@@ -382,6 +410,22 @@ module MultiGit
|
|
382
410
|
PessimisticFileUpdater
|
383
411
|
end
|
384
412
|
|
413
|
+
def reckless_updater
|
414
|
+
RecklessUpdater
|
415
|
+
end
|
416
|
+
|
417
|
+
def updater_class( block_given, lock )
|
418
|
+
if block_given
|
419
|
+
case lock
|
420
|
+
when :optimistic then optimistic_updater
|
421
|
+
when :pessimistic then pessimistic_updater
|
422
|
+
when :reckless then reckless_updater
|
423
|
+
end
|
424
|
+
else
|
425
|
+
pessimistic_updater
|
426
|
+
end
|
427
|
+
end
|
428
|
+
|
385
429
|
end
|
386
430
|
|
387
431
|
end
|
@@ -0,0 +1,118 @@
|
|
1
|
+
module MultiGit
|
2
|
+
|
3
|
+
# A RefSpec describes which and how references are updated during
|
4
|
+
# push and pull.
|
5
|
+
#
|
6
|
+
# It basically says: set the "to" ref to the target of "from"
|
7
|
+
#
|
8
|
+
# @example
|
9
|
+
# refspecs = MultiGit::RefSpec.parse('master')
|
10
|
+
#
|
11
|
+
class RefSpec < Struct.new(:from,:to,:forced)
|
12
|
+
|
13
|
+
extend Utils::AbstractMethods
|
14
|
+
|
15
|
+
# @!attribute from
|
16
|
+
# @return [String]
|
17
|
+
|
18
|
+
# @!attribute to
|
19
|
+
# @return [String]
|
20
|
+
|
21
|
+
# @!attribute forced
|
22
|
+
# @return [Boolean]
|
23
|
+
|
24
|
+
alias forced? forced
|
25
|
+
|
26
|
+
# @param from [String]
|
27
|
+
# @param to [String]
|
28
|
+
# @param forced [Boolean]
|
29
|
+
def initialize(from,to,forced = false)
|
30
|
+
super
|
31
|
+
end
|
32
|
+
|
33
|
+
def inspect
|
34
|
+
['#<',self.class,' ',forced ? '+':'',from,':',to,'>'].join
|
35
|
+
end
|
36
|
+
|
37
|
+
def to_s
|
38
|
+
[forced ? '+':'',from,':',to].join
|
39
|
+
end
|
40
|
+
|
41
|
+
class Parser
|
42
|
+
|
43
|
+
REF = %r{\A(\+?)([a-zA-Z/0-9_*]+)?(?:(:)([a-zA-Z/0-9_*]+)?)?\z}
|
44
|
+
|
45
|
+
attr :from_base, :to_base
|
46
|
+
|
47
|
+
def initialize(from_base = 'refs/heads/', to_base )
|
48
|
+
@from_base = from_base
|
49
|
+
@to_base = to_base
|
50
|
+
end
|
51
|
+
|
52
|
+
#
|
53
|
+
# @param args [RefSpec, String, Hash, Range, ...]
|
54
|
+
# @return [Array<RefSpec>]
|
55
|
+
def [](*args)
|
56
|
+
args.collect_concat do |arg|
|
57
|
+
if arg.kind_of? RefSpec
|
58
|
+
[arg]
|
59
|
+
elsif arg.kind_of? String
|
60
|
+
[parse_string(arg)]
|
61
|
+
elsif arg.kind_of? Hash
|
62
|
+
arg.map{|k,v| parse_pair(k,v) }
|
63
|
+
elsif arg.kind_of? Range
|
64
|
+
[parse_pair(arg.begin, arg.end)]
|
65
|
+
else
|
66
|
+
raise ArgumentError, "Expected a String, Hash or Range. Got #{arg.inspect}"
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
private
|
72
|
+
def parse_string(string)
|
73
|
+
if ma = REF.match(string)
|
74
|
+
if ma[2]
|
75
|
+
from = normalize(from_base, ma[2])
|
76
|
+
end
|
77
|
+
if ma[3]
|
78
|
+
to = normalize(to_base, ma[4])
|
79
|
+
else
|
80
|
+
to = normalize(to_base, ma[2])
|
81
|
+
end
|
82
|
+
RefSpec.new( from, to, ma[1] == '+' )
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
def parse_pair(a,b)
|
87
|
+
RefSpec.new( normalize(from_base,a.to_s), normalize(to_base,b.to_s) )
|
88
|
+
end
|
89
|
+
|
90
|
+
def normalize(base, name)
|
91
|
+
ns = name.split(SLASH, -1)
|
92
|
+
bs = base.split(SLASH, -1)
|
93
|
+
fill_reverse(bs, ns)
|
94
|
+
return bs.join(SLASH)
|
95
|
+
end
|
96
|
+
|
97
|
+
def fill_reverse(a,b)
|
98
|
+
s = a.size - b.size
|
99
|
+
b.each_with_index do |e, i|
|
100
|
+
a[s+i] = e
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
end
|
105
|
+
|
106
|
+
DEFAULT_PARSER = Parser.new('refs/remotes/origin/')
|
107
|
+
|
108
|
+
class << self
|
109
|
+
|
110
|
+
def parse(arg)
|
111
|
+
DEFAULT_PARSER[arg].first
|
112
|
+
end
|
113
|
+
|
114
|
+
end
|
115
|
+
|
116
|
+
end
|
117
|
+
|
118
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
require 'multi_git/refspec'
|
2
|
+
module MultiGit
|
3
|
+
|
4
|
+
module Remote
|
5
|
+
|
6
|
+
extend Utils::AbstractMethods
|
7
|
+
|
8
|
+
# @!attribute repository
|
9
|
+
# @return [Repository]
|
10
|
+
abstract :repository
|
11
|
+
|
12
|
+
# @!attribute fetch_urls
|
13
|
+
# @return [Enumerable<URI>]
|
14
|
+
abstract :fetch_urls
|
15
|
+
|
16
|
+
# @!attribute push_urls
|
17
|
+
# @return [Enumerable<URI>]
|
18
|
+
abstract :push_urls
|
19
|
+
|
20
|
+
# @!method fetch( *refspecs )
|
21
|
+
# @param refspecs [RefSpec, String, Range, Hash, ...]
|
22
|
+
abstract :fetch
|
23
|
+
|
24
|
+
# @!method push( *refspecs )
|
25
|
+
# @param refspecs [RefSpec, String, Range, Hash, ...]
|
26
|
+
abstract :push
|
27
|
+
|
28
|
+
# @!method save( name )
|
29
|
+
# @param name [String]
|
30
|
+
# @return [Persistent]
|
31
|
+
abstract :save
|
32
|
+
|
33
|
+
module Persistent
|
34
|
+
include Remote
|
35
|
+
extend Utils::AbstractMethods
|
36
|
+
|
37
|
+
# @!attribute name
|
38
|
+
# @return [String, nil]
|
39
|
+
abstract :name
|
40
|
+
|
41
|
+
# @!method save( name = name )
|
42
|
+
# @param name [String]
|
43
|
+
# @return [Persistent]
|
44
|
+
abstract :save
|
45
|
+
|
46
|
+
protected
|
47
|
+
|
48
|
+
def refspec_parser
|
49
|
+
RefSpec::Parser.new("refs/remotes/#{name}/")
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|
53
|
+
|
54
|
+
protected
|
55
|
+
|
56
|
+
def parse_fetch_refspec(*refspecs)
|
57
|
+
refspec_parser[*refspecs]
|
58
|
+
end
|
59
|
+
|
60
|
+
def refspec_parser
|
61
|
+
RefSpec::Parser.new("refs/remotes//")
|
62
|
+
end
|
63
|
+
|
64
|
+
end
|
65
|
+
|
66
|
+
end
|
data/lib/multi_git/repository.rb
CHANGED
@@ -21,6 +21,12 @@ protected
|
|
21
21
|
public
|
22
22
|
extend Utils::AbstractMethods
|
23
23
|
|
24
|
+
# @!method config
|
25
|
+
# @abstract
|
26
|
+
# Returns the config
|
27
|
+
# @return [Config]
|
28
|
+
abstract :config
|
29
|
+
|
24
30
|
# @!method git_dir
|
25
31
|
# @abstract
|
26
32
|
# Return the repository base directory
|
@@ -101,6 +107,12 @@ public
|
|
101
107
|
# @return [MultiGit::Ref] ref
|
102
108
|
abstract :ref
|
103
109
|
|
110
|
+
# Gets the ref
|
111
|
+
# @return [Ref] head
|
112
|
+
def head
|
113
|
+
return ref('HEAD')
|
114
|
+
end
|
115
|
+
|
104
116
|
# Opens a branch
|
105
117
|
#
|
106
118
|
# @param name [String] branch name
|
@@ -236,4 +248,9 @@ protected
|
|
236
248
|
raise Error::InvalidObjectType, type.inspect unless VALID_TYPES.include?(type)
|
237
249
|
end
|
238
250
|
|
251
|
+
def looks_like_remote_url?(string)
|
252
|
+
# poor but efficient
|
253
|
+
string.include? '/'
|
254
|
+
end
|
255
|
+
|
239
256
|
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'forwardable'
|
2
|
+
require 'multi_git/config'
|
3
|
+
module MultiGit
|
4
|
+
module RuggedBackend
|
5
|
+
class Config
|
6
|
+
|
7
|
+
include MultiGit::Config
|
8
|
+
|
9
|
+
def initialize(rugged_config)
|
10
|
+
@rugged_config = rugged_config
|
11
|
+
@config = Hash.new([])
|
12
|
+
rugged_config.each_pair do |qk, value|
|
13
|
+
key = split_key(qk)
|
14
|
+
@config.fetch(key){ @config[key] = [] } << value
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def get(section, subsection, key)
|
19
|
+
s = schema_for(section, subsection, key)
|
20
|
+
v = @config[ [section, subsection,key] ]
|
21
|
+
if v.size == 0
|
22
|
+
s.default
|
23
|
+
elsif s.list?
|
24
|
+
s.convert(v)
|
25
|
+
else
|
26
|
+
s.convert(v.last)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def each_explicit_key
|
31
|
+
return to_enum(:each_explicit_key) unless block_given?
|
32
|
+
@config.each_key do |k|
|
33
|
+
yield *k
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
private
|
38
|
+
|
39
|
+
attr :rugged_config
|
40
|
+
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
require 'multi_git/remote'
|
2
|
+
require 'forwardable'
|
3
|
+
module MultiGit
|
4
|
+
module RuggedBackend
|
5
|
+
class Remote
|
6
|
+
|
7
|
+
include MultiGit::Remote
|
8
|
+
extend Forwardable
|
9
|
+
|
10
|
+
attr :repository
|
11
|
+
|
12
|
+
attr :rugged_remote
|
13
|
+
protected :rugged_remote
|
14
|
+
|
15
|
+
def fetch_urls
|
16
|
+
[rugged_remote.url]
|
17
|
+
end
|
18
|
+
|
19
|
+
# :nocov:
|
20
|
+
if Rugged::Remote.instance_methods.include? :push_url
|
21
|
+
def push_urls
|
22
|
+
[rugged_remote.push_url || rugged_remote.url]
|
23
|
+
end
|
24
|
+
else
|
25
|
+
def push_urls
|
26
|
+
raise Error::NotYetImplemented, 'Rugged::Remote#push_urls is only available in bleeding edge rugged'
|
27
|
+
end
|
28
|
+
end
|
29
|
+
# :nocov:
|
30
|
+
|
31
|
+
def initialize( repository, remote )
|
32
|
+
@repository = repository
|
33
|
+
@rugged_remote = remote
|
34
|
+
end
|
35
|
+
|
36
|
+
class Persistent < self
|
37
|
+
|
38
|
+
include MultiGit::Remote::Persistent
|
39
|
+
extend Forwardable
|
40
|
+
|
41
|
+
def_instance_delegator :rugged_remote, :name
|
42
|
+
|
43
|
+
end
|
44
|
+
|
45
|
+
if Rugged::Remote.instance_methods.include? :clear_refspecs
|
46
|
+
def fetch(*refspecs)
|
47
|
+
rs = parse_fetch_refspec(*refspecs)
|
48
|
+
cl = Rugged::Remote.new(repository.__backend__, fetch_urls.first)
|
49
|
+
cl.clear_refspecs
|
50
|
+
rs.each do |spec|
|
51
|
+
cl.add_fetch(spec.to_s)
|
52
|
+
end
|
53
|
+
cl.connect(:fetch) do |r|
|
54
|
+
r.download
|
55
|
+
end
|
56
|
+
cl.update_tips!
|
57
|
+
end
|
58
|
+
else
|
59
|
+
def fetch(*_)
|
60
|
+
raise Error::NotYetImplemented, 'This rugged version doesn\'t seem to support fetching. You may want to install from HEAD.'
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
@@ -4,6 +4,8 @@ require 'multi_git/rugged_backend/blob'
|
|
4
4
|
require 'multi_git/rugged_backend/tree'
|
5
5
|
require 'multi_git/rugged_backend/commit'
|
6
6
|
require 'multi_git/rugged_backend/ref'
|
7
|
+
require 'multi_git/rugged_backend/config'
|
8
|
+
require 'multi_git/rugged_backend/remote'
|
7
9
|
module MultiGit::RuggedBackend
|
8
10
|
|
9
11
|
class Repository < MultiGit::Repository
|
@@ -45,6 +47,7 @@ module MultiGit::RuggedBackend
|
|
45
47
|
raise MultiGit::Error::NotARepository, path
|
46
48
|
end
|
47
49
|
end
|
50
|
+
@git.config = Rugged::Config.new(::File.join(@git.path, 'config'))
|
48
51
|
verify_bareness(path, options)
|
49
52
|
end
|
50
53
|
|
@@ -115,6 +118,10 @@ module MultiGit::RuggedBackend
|
|
115
118
|
@git.include?(oid)
|
116
119
|
end
|
117
120
|
|
121
|
+
def config
|
122
|
+
@config ||= Config.new(@git.config)
|
123
|
+
end
|
124
|
+
|
118
125
|
TRUE_LAMBDA = proc{ true }
|
119
126
|
|
120
127
|
def each_branch(filter = :all)
|
@@ -181,6 +188,24 @@ module MultiGit::RuggedBackend
|
|
181
188
|
return read(oid)
|
182
189
|
end
|
183
190
|
|
191
|
+
#
|
192
|
+
def remote( name_or_url )
|
193
|
+
if looks_like_remote_url? name_or_url
|
194
|
+
remote = Rugged::Remote.new(__backend__, name_or_url)
|
195
|
+
else
|
196
|
+
remote = Rugged::Remote.lookup(__backend__, name_or_url)
|
197
|
+
end
|
198
|
+
if remote
|
199
|
+
if remote.name
|
200
|
+
return Remote::Persistent.new(self, remote)
|
201
|
+
else
|
202
|
+
return Remote.new(self, remote)
|
203
|
+
end
|
204
|
+
else
|
205
|
+
return nil
|
206
|
+
end
|
207
|
+
end
|
208
|
+
|
184
209
|
private
|
185
210
|
|
186
211
|
def strip_slash(path)
|
data/lib/multi_git/tree.rb
CHANGED
@@ -94,14 +94,37 @@ module MultiGit
|
|
94
94
|
alias / traverse
|
95
95
|
alias [] traverse
|
96
96
|
|
97
|
+
# Works like the builtin Dir.glob
|
98
|
+
#
|
99
|
+
# @param pattern [String] A glob pattern
|
100
|
+
# @param flags [Integer] glob flags
|
101
|
+
# @yield [MultiGit::TreeEntry]
|
102
|
+
# @return [Enumerator] if called without a block
|
103
|
+
# @return self if called with a block
|
104
|
+
#
|
105
|
+
# @example
|
106
|
+
# bld = MultiGit::Tree::Builder.new do
|
107
|
+
# file "file"
|
108
|
+
# directory "folder" do
|
109
|
+
# file "file"
|
110
|
+
# end
|
111
|
+
# end
|
112
|
+
# bld.glob( '**/file' ).map(&:path) #=> eq ['file','folder/file']
|
113
|
+
#
|
114
|
+
# @see http://ruby-doc.org/core/Dir.html#method-c-glob
|
97
115
|
def glob( pattern, flags = 0 )
|
98
116
|
return to_enum(:glob, pattern, flags) unless block_given?
|
99
|
-
l = path.size
|
117
|
+
l = respond_to?(:path) ? path.size : 0
|
100
118
|
flags |= ::File::FNM_PATHNAME
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
119
|
+
if ::File.fnmatch(pattern, '.', flags)
|
120
|
+
yield self
|
121
|
+
end
|
122
|
+
each do |entry|
|
123
|
+
entry.walk_pre do |sub_entry|
|
124
|
+
if ::File.fnmatch(pattern, sub_entry.path[l..-1], flags)
|
125
|
+
yield sub_entry
|
126
|
+
false
|
127
|
+
end
|
105
128
|
end
|
106
129
|
end
|
107
130
|
return self
|
@@ -161,10 +184,6 @@ module MultiGit
|
|
161
184
|
['#<',self.class.name,' ',oid,' repository:', repository.inspect,'>'].join
|
162
185
|
end
|
163
186
|
|
164
|
-
def path
|
165
|
-
''
|
166
|
-
end
|
167
|
-
|
168
187
|
protected
|
169
188
|
# @return [Hash<String, MultiGit::TreeEntry>]
|
170
189
|
def entries
|
data/lib/multi_git/tree_entry.rb
CHANGED
data/lib/multi_git/version.rb
CHANGED