Module: MultiGit::Tree::Base

Includes:
Enumerable, Walkable
Included in:
Directory::Base, MultiGit::Tree, Builder
Defined in:
lib/multi_git/tree.rb

Instance Method Summary collapse

Methods included from Walkable

#walk

Instance Method Details

#==(other) ⇒ Object Also known as: eql?

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



176
177
178
179
# File 'lib/multi_git/tree.rb', line 176

def ==( other )
  return false unless other.respond_to? :entries
  entries == other.entries
end

#each {|entry| ... } ⇒ Object #eachEnumerable

Overloads:



136
137
138
139
140
141
142
# File 'lib/multi_git/tree.rb', line 136

def each
  return to_enum unless block_given?
  entries.each do |_, entry|
    yield entry
  end
  return self
end

#entriesHash<String, MultiGit::TreeEntry>

Returns:



190
191
192
# File 'lib/multi_git/tree.rb', line 190

def entries
  @entries ||= Hash[ raw_entries.map{|name, mode, oid| [name, make_entry(name, mode, oid) ] } ]
end

#entry(key) ⇒ MultiGit::TreeEntry?

Parameters:

  • key (String)

Returns:



29
30
31
# File 'lib/multi_git/tree.rb', line 29

def entry(key)
  entries[key]
end

#glob(pattern, flags = 0) {|MultiGit::TreeEntry| ... } ⇒ Enumerator

Works like the builtin Dir.glob

Examples:

bld = MultiGit::Tree::Builder.new do
  file "file"
  directory "folder" do
    file "file"
  end
end
bld.glob( '**/file' ).map(&:path) #=> eq ['file','folder/file']

Parameters:

  • pattern (String)

    A glob pattern

  • flags (Integer) (defaults to: 0)

    glob flags

Yields:

Returns:

  • (Enumerator)

    if called without a block

  • self if called with a block

See Also:



111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
# File 'lib/multi_git/tree.rb', line 111

def glob( pattern, flags = 0 )
  return to_enum(:glob, pattern, flags) unless block_given?
  l = respond_to?(:path) ? path.size : 0
  flags |= ::File::FNM_PATHNAME
  if ::File.fnmatch(pattern, '.', flags)
    yield self
  end
  each do |entry|
    entry.walk_pre do |sub_entry|
      if ::File.fnmatch(pattern, sub_entry.path[l..-1], flags)
        yield sub_entry
        false
      end
    end
  end
  return self
end

#hashObject

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



185
186
187
# File 'lib/multi_git/tree.rb', line 185

def hash
  entries.hash
end

#key?(key) ⇒ Boolean

Returns:

  • (Boolean)


19
20
21
22
23
24
25
# File 'lib/multi_git/tree.rb', line 19

def key?(key)
  if key.kind_of? String
    return entries.key?(key)
  else
    raise ArgumentError, "Expected a String, got #{key.inspect}"
  end
end

#namesArray<String>

Returns names of all entries.

Returns:

  • (Array<String>)

    names of all entries



171
172
173
# File 'lib/multi_git/tree.rb', line 171

def names
  entries.keys
end

#sizeInteger

Returns number of entries.

Returns:

  • (Integer)

    number of entries



166
167
168
# File 'lib/multi_git/tree.rb', line 166

def size
  entries.size
end

#traverse(path, options = {}) ⇒ MultiGit::TreeEntry Also known as: /, []

Traverses to path

Parameters:

  • path (String)
  • options (Hash) (defaults to: {})

Options Hash (options):

  • :follow (Boolean)

    follow sylinks ( default: true )

Returns:

Raises:



40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
# File 'lib/multi_git/tree.rb', line 40

def traverse(path, options = {})
  unless path.kind_of? String
    raise ArgumentError, "Expected a String, got #{path.inspect}"
  end
  parts = path.split('/').reverse!
  current = self
  follow = options.fetch(:follow){true}
  symlinks = Set.new
  while parts.any?
    part = parts.pop
    if part == '..'
      unless current.respond_to?(:parent) && p = current.parent
        raise MultiGit::Error::InvalidTraversal, "Can't traverse to parent of #{current.inspect} since I don't know where it is."
      end
      current = p
    elsif part == '.' || part == ''
      # do nothing
    else
      if !current.respond_to? :entry
        raise MultiGit::Error::NotADirectory, "Can't traverse to #{path} from #{self.inspect}: #{current.inspect} doesn't contain an entry named #{part.inspect}"
      end
      entry = current.entry(part)
      raise MultiGit::Error::EntryDoesNotExist, "Can't traverse to #{path} from #{self.inspect}: #{current.inspect} doesn't contain an entry named #{part.inspect}" unless entry
      # may be a symlink
      if entry.respond_to? :target
        # this is a symlink
        if symlinks.include? entry
          # We have already seen this symlink
          #TODO: it's okay to see a symlink twice if requested
          raise MultiGit::Error::CyclicSymlink, "Cyclic symlink detected while traversing #{path} from #{self.inspect}."
        else
          symlinks << entry
        end
        if follow
          parts.push(*entry.target.split(SLASH))
        else
          if parts.none?
            return entry
          else
            raise ArgumentError, "Can't follow symlink #{entry.inspect} since you didn't allow me to"
          end
        end
      else
        current = entry
      end
    end
  end
  return current
end

#typeObject



15
16
17
# File 'lib/multi_git/tree.rb', line 15

def type
  :tree
end