Class: Gash::Tree

Inherits:
Hash
  • Object
show all
Includes:
Helpers
Defined in:
lib/gash.rb

Overview

A Tree is a Hash which can store other instances of Tree and Blob.

Special methods

Internally, a tree is being stored like this:

{
  "README" => blob,
  "examples" => {
    "test.rb" => blob,
    "yay.rb" => blob
  }
}

So you have to do tree["examples"].delete("test.rb") instead of tree.delete("examples/test.rb"). However, there are some methods which supports the slash. All of these will work:

tree["examples/test.rb"]
tree.fetch("examples/test.rb")
tree["examples/another.rb"] = "Content"
tree.store("examples/another.rb", "Content") # Exactly the same as above.

tree["examples"]["test.rb"] # Or, you could use this

Documentation

The point of Tree is that it should be as close to Hash as possible. Therefore, methods which behaves exactly equally in Gash and Hash will not be documentated below. Please see the Ruby documentation if you wonder what you can do.

See also: Helpers, Blob

Instance Attribute Summary

Attributes included from Helpers

#mode, #parent, #sha1

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Helpers

#blob?, #changed!, #changed?, #gash, #initialize, #normalize, #tree?

Class Method Details

.[](*val) ⇒ Object



262
263
264
# File 'lib/gash.rb', line 262

def self.[](*val)
  new.merge!(Hash[*val])
end

Instance Method Details

#/Object

Retrieves the value stored as key:

tree["FILE"] == File.read("FILE")
tree["DIR/FILE"] == tree["DIR"]["FILE"] == File.read("DIR/FILE")

Lazy loading

By default, this method will automatically load the blob/tree from the repo. If you rather want to load it later, simply set lazy to true:

blob = tree["FILE", true]
# do some other stuff...
blob.load! # Load it now!


176
177
178
179
180
# File 'lib/gash.rb', line 176

def [](key, lazy = nil)
  ret = fetch(key, default)
ensure
  ret.load! if ret.respond_to?(:load!) && !lazy
end

#==(other) ⇒ Object



266
267
268
269
270
271
272
# File 'lib/gash.rb', line 266

def ==(other)
  if other.is_a?(Tree) && sha1 && other.sha1
    sha1 == other.sha1
  else
    super
  end
end

#[](key, lazy = nil) ⇒ Object

Retrieves the value stored as key:

tree["FILE"] == File.read("FILE")
tree["DIR/FILE"] == tree["DIR"]["FILE"] == File.read("DIR/FILE")

Lazy loading

By default, this method will automatically load the blob/tree from the repo. If you rather want to load it later, simply set lazy to true:

blob = tree["FILE", true]
# do some other stuff...
blob.load! # Load it now!


171
172
173
174
175
# File 'lib/gash.rb', line 171

def [](key, lazy = nil)
  ret = fetch(key, default)
ensure
  ret.load! if ret.respond_to?(:load!) && !lazy
end

#[]=(key, value, not_changed = nil) ⇒ Object Also known as: store

Stores the given value at key:

tree["FILE"] = "Content"

It uses Helpers#normalize in order convert it to a blob/tree, and will always set the parent to itself:

tree["FILE"] = "Content"
  # is the same as:
tree["FILE"] = Gash::Blob.new(:content => "Content", :parent => tree)

Mark as changed

By default, the object will be marked as changed (using Helpers#changed!). If this is not what you want, simply set not_changed to true.

However, if you give it three arguments, then the second one will act as not_changed, not the third:

       1       2        3
tree["FILE", true] = "Test"
tree["FILE"].changed? # => false


201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
# File 'lib/gash.rb', line 201

def []=(key, value, not_changed = nil)
  key, value, not_changed = if not_changed.nil?
    [key, value]
  else
    [key, not_changed, value]
  end
  
  if key.include?("/")
    keys = key.split("/")
    name = keys.pop
    keys.inject(self) do |memo, i|
      memo[i, not_changed] = Tree.new(:parent => self) unless memo.include?(i)
      memo[i, true]
    end[name, not_changed] = value
  else
    value = normalize(value)
    value.parent = self
    super(key, value)
  end
ensure
  self.changed! unless not_changed
end

#delete(key) ⇒ Object



258
259
260
# File 'lib/gash.rb', line 258

def delete(key)
  super && changed!
end

#fetch(*args) ⇒ Object

:stopdoc:



234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
# File 'lib/gash.rb', line 234

def fetch(*args)
  key = args.first.to_s
  
  case args.length
  when 1
    r = true
  when 2
    r = false
    default = args.last
  else
    raise ArgumentError, "wrong number of arguments (#{args.length} for 2)"
  end
  
  if key.include?("/")
    key, rest = key.split("/", 2)
    value = super(key)
    value.fetch(rest)
  else
    super(key)
  end
rescue IndexError => e
  (r && raise(e)) || default
end

#merge(hash) ⇒ Object



274
275
276
277
# File 'lib/gash.rb', line 274

def merge(hash)
  tree = self.dup
  tree.merge!(hash)
end

#merge!(hash) ⇒ Object Also known as: update



279
280
281
282
283
284
# File 'lib/gash.rb', line 279

def merge!(hash)
  hash.each do |key, value|
    self[key] = value
  end
  self
end

#replace(hash) ⇒ Object



287
288
289
290
291
292
293
294
# File 'lib/gash.rb', line 287

def replace(hash)
  if hash.is_a?(Gash::Tree)
    super
  else
    clear
    merge!(hash)
  end
end

#to_hashObject

Converts the tree to a Hash.



226
227
228
229
230
231
# File 'lib/gash.rb', line 226

def to_hash
  inject({}) do |memo, (key, value)|
    memo[key] = value.respond_to?(:to_hash) ? value.to_hash : value.to_s
    memo
  end
end