gash 0.1 → 0.1.1

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.
Files changed (5) hide show
  1. data/CHANGELOG +2 -0
  2. data/Rakefile +1 -0
  3. data/gash.gemspec +6 -6
  4. data/lib/gash.rb +113 -35
  5. metadata +5 -5
data/CHANGELOG CHANGED
@@ -1 +1,3 @@
1
+ v0.1.1. Tree got more Hash-methods. Better documentation.
2
+
1
3
  v0.1. First version.
data/Rakefile CHANGED
@@ -8,6 +8,7 @@ Echoe.new('gash') do |p|
8
8
  p.summary = "Git + Hash"
9
9
  p.url = "http://dojo.rubyforge.org/gash/"
10
10
  p.rdoc_options += ["--main", "Gash", "--title", "Gash"]
11
+ p.rubygems_version = nil
11
12
  end
12
13
 
13
14
  Rake::Task[:publish_docs].instance_eval do
@@ -1,18 +1,18 @@
1
1
 
2
- # Gem::Specification for Gash-0.1
2
+ # Gem::Specification for Gash-0.1.1
3
3
  # Originally generated by Echoe
4
4
 
5
5
  --- !ruby/object:Gem::Specification
6
6
  name: gash
7
7
  version: !ruby/object:Gem::Version
8
- version: "0.1"
8
+ version: 0.1.1
9
9
  platform: ruby
10
10
  authors:
11
11
  - Magnus Holm
12
12
  autorequire:
13
13
  bindir: bin
14
14
 
15
- date: 2008-09-04 00:00:00 +02:00
15
+ date: 2008-09-27 00:00:00 +02:00
16
16
  default_executable:
17
17
  dependencies:
18
18
  - !ruby/object:Gem::Dependency
@@ -66,14 +66,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
66
66
  version:
67
67
  required_rubygems_version: !ruby/object:Gem::Requirement
68
68
  requirements:
69
- - - "="
69
+ - - ">="
70
70
  - !ruby/object:Gem::Version
71
- version: "1.2"
71
+ version: "0"
72
72
  version:
73
73
  requirements: []
74
74
 
75
75
  rubyforge_project: dojo
76
- rubygems_version: 1.2.0
76
+ rubygems_version: 1.3.0
77
77
  specification_version: 2
78
78
  summary: Git + Hash
79
79
  test_files: []
@@ -3,13 +3,15 @@ require 'delegate'
3
3
  # == What is Gash?
4
4
  #
5
5
  # * Gash lets you access a Git-repo as a Hash.
6
+ # * Gash doesn't touch your working directory
6
7
  # * Gash only cares about the data, not the commits.
7
8
  # * Gash only cares about the _latest_ data.
8
9
  # * Gash can commit.
9
- # * Gash doesn't touch your working directory
10
10
  # * Gash will automatically create branches if they don't exists.
11
11
  # * Gash only loads what it needs, so it handles large repos well.
12
12
  #
13
+ # Some of these "rules" might change it the future.
14
+ #
13
15
  # == How do you use it?
14
16
  #
15
17
  # gash = Gash.new
@@ -19,16 +21,12 @@ require 'delegate'
19
21
  # It's also important to remember that a Gash is simply a Tree, so you can
20
22
  # also call those methods.
21
23
  #
22
- # <strong>See also</strong>: #new, #commit, Tree
23
- #
24
- # == Limitation
25
- #
26
- # The only Hash-like features which currently works is #[] and #[]=,
27
- # so don't try #merge or something like that.
24
+ # <b>See also</b>: #new, #commit, Tree
28
25
  class Gash < SimpleDelegator
29
26
  module Errors
30
27
  # This error is raised when the Git-command fails.
31
28
  class Git < StandardError; end
29
+ class NoGitRepo < StandardError; end
32
30
  end
33
31
 
34
32
  # Some common methods used by both Tree and Blob.
@@ -55,28 +53,63 @@ class Gash < SimpleDelegator
55
53
  # Checks if this object has been changed (since last commit).
56
54
  def changed?; !@sha1 end
57
55
  # Mark this, and all parents as changed.
58
- def changed!; @sha1 = nil;parent.changed! end
56
+ def changed!; @sha1 = nil;parent.changed! if parent end
59
57
  # Returns the Gash-object (top-parent).
60
- def gash; parent.gash end
58
+ def gash; parent.gash if parent end
59
+
60
+ # Converts the +value+ to a Tree or a Blob, using some rules:
61
+ #
62
+ # == If +value+ is already a Tree or a Blob:
63
+ #
64
+ # * If +value+ comes from another repo, we load it and return a deep copy.
65
+ # * If +value+ got no parent, we simply return the same tree.
66
+ # * If +value+'s parent is +self+, we also return the same tree.
67
+ # * If +value+'s parent is something else, we return a duplicated tree.
68
+ #
69
+ # == If it's something else:
70
+ #
71
+ # * If +value+ is a Hash, we create a Tree from it.
72
+ # * If it's not any of the former rules, we turn it into a string and create a Blob from it.
73
+ def normalize(value)
74
+ case value
75
+ when Tree, Blob, Gash
76
+ if value.parent && value.parent != self
77
+ if (g = value.gash) && self.gash == g
78
+ value.dup
79
+ else
80
+ normalize(value.tree? ? value.to_hash : value.to_s)
81
+ end
82
+ else
83
+ value
84
+ end
85
+ when Hash
86
+ Tree[value]
87
+ else
88
+ Blob.new(:content => value.to_s)
89
+ end
90
+ end
61
91
  end
62
92
 
63
93
  # A Tree is a Hash which can store other instances of Tree and Blob.
64
94
  #
65
- # <strong>See also</strong>: Helpers, Blob
95
+ # <b>See also</b>: Helpers, Blob
66
96
  class Tree < Hash
67
97
  include Helpers
68
98
 
69
99
  # Retrieves the _value_ stored as +key+:
70
100
  #
71
- # tree["FILE"] == the file
72
- # tree["DIR/FILE"] == tree["DIR"]["FILE"] = another file
101
+ # tree["FILE"] == File.read("FILE")
102
+ # tree["DIR/FILE"] == tree["DIR"]["FILE"] == File.read("DIR/FILE")
103
+ #
104
+ # ==== Lazy loading
73
105
  #
74
- # It will automatically call the +load!+-method in order to load
75
- # it from the repo. Set +lazy+ to +true+ if this is not what you want:
106
+ # By default, this method will automatically load the blob/tree from
107
+ # the repo. If you rather want to load it later, simply set +lazy+ to
108
+ # +true+:
76
109
  #
77
- # blob = tree["FILE", true] == #<Blob:1234...>
110
+ # blob = tree["FILE", true]
78
111
  # # do some other stuff...
79
- # blob.laod! # Load it now!
112
+ # blob.load! # Load it now!
80
113
  def [](key, lazy = nil)
81
114
  ret = if key.include?("/")
82
115
  key, rest = key.split("/", 2)
@@ -91,23 +124,27 @@ class Gash < SimpleDelegator
91
124
  end
92
125
  alias / []
93
126
 
94
- # Stores the given _value_:
127
+ # Stores the given _value_ at +key+:
95
128
  #
96
129
  # tree["FILE"] = "Content"
97
130
  #
98
- # Unless it's already a Tree or a Blob, it will be converted to a Blob,
99
- # and the parent will _always_ be set to +self+.
131
+ # It uses Helpers#normalize in order convert it to a blob/tree, and will
132
+ # always set the parent to itself:
100
133
  #
101
134
  # tree["FILE"] = "Content"
102
135
  # # is the same as:
103
136
  # tree["FILE"] = Gash::Blob.new(:content => "Content", :parent => tree)
104
137
  #
105
- # It will also mark the object as changed (using <code>Helpers#changed!</code>).
106
- # Set +not_changed+ to +true+ if this is not what you want.
107
- #
108
- # (If you give it three arguments, then the second one will act as
109
- # +not_changed+, not the third):
138
+ # ==== Mark as changed
139
+ #
140
+ # By default, the object will be marked as changed (using
141
+ # <code>Helpers#changed!</code>). If this is not what you want, simply set
142
+ # +not_changed+ to +true+.
143
+ #
144
+ # However, if you give it three arguments, then the second one will act as
145
+ # +not_changed+, not the third:
110
146
  #
147
+ # 1 2 3
111
148
  # tree["FILE", true] = "Test"
112
149
  # tree["FILE"].changed? # => false
113
150
  def []=(key, value, not_changed = nil)
@@ -125,18 +162,47 @@ class Gash < SimpleDelegator
125
162
  memo[i, true]
126
163
  end[name, not_changed] = value
127
164
  else
128
- value = case value
129
- when Tree, Blob
130
- value
131
- else
132
- Blob.new(:content => value.to_s)
133
- end
165
+ value = normalize(value)
134
166
  value.parent = self
135
167
  super(key, value)
136
168
  end
137
169
  ensure
138
170
  self.changed! unless not_changed
139
171
  end
172
+
173
+ # Converts the tree to a Hash.
174
+ def to_hash
175
+ inject({}) do |memo, (key, value)|
176
+ memo[key] = value.respond_to?(:to_hash) ? value.to_hash : value.to_s
177
+ memo
178
+ end
179
+ end
180
+
181
+ def self.[](*val) # :nodoc:
182
+ new.merge!(Hash[*val])
183
+ end
184
+
185
+ def merge(hash) # :nodoc:
186
+ tree = self.dup
187
+ tree.merge!(hash)
188
+ end
189
+
190
+ def merge!(hash) # :nodoc:
191
+ hash.each do |key, value|
192
+ self[key] = value
193
+ end
194
+ self
195
+ end
196
+ alias update merge!
197
+
198
+ def replace(hash) # :nodoc:
199
+ if hash.is_a?(Gash::Tree)
200
+ super
201
+ else
202
+ clear
203
+ merge!(hash)
204
+ end
205
+ end
140
206
  end
141
207
 
142
208
  # A Blob represent a string:
@@ -160,9 +226,9 @@ class Gash < SimpleDelegator
160
226
  #
161
227
  # tree["FILE"] = Gash::Blob.new(:sha1 => a_sha1)
162
228
  #
163
- # <strong>See also</strong>: Helpers, Tree
229
+ # <b>See also</b>: Helpers, Tree
164
230
  class Blob < Delegator
165
- include Helpers
231
+ include Helpers, Comparable
166
232
  attr_accessor :content
167
233
 
168
234
  # Loads the file from Git, unless it's already been loaded.
@@ -174,6 +240,14 @@ class Gash < SimpleDelegator
174
240
  @content ? @content.inspect : (@sha1 ? "#<Blob:#{@sha1}>" : to_s.inspect)
175
241
  end
176
242
 
243
+ def <=>(other) #:nodoc:
244
+ if other.is_a?(Blob) && sha1 && other.sha1
245
+ sha1 <=> other.sha1
246
+ else
247
+ __getobj__ <=> other
248
+ end
249
+ end
250
+
177
251
  def __getobj__ #:nodoc:
178
252
  @content ||= @sha1 ? load! : ''
179
253
  end
@@ -184,9 +258,9 @@ class Gash < SimpleDelegator
184
258
 
185
259
  # Opens the +repo+ with the specified +branch+.
186
260
  #
187
- # <strong>Please note:</strong> The +repo+ must link to the actual repo,
261
+ # <b>Please note:</b> The +repo+ must link to the actual repo,
188
262
  # not the working directory!
189
- def initialize(branch = "master", repo = ".git")
263
+ def initialize(repo = ".git", branch = "master")
190
264
  @branch = branch
191
265
  @repository = File.expand_path(repo)
192
266
  __setobj__(Tree.new(:parent => self))
@@ -330,7 +404,11 @@ class Gash < SimpleDelegator
330
404
  result, status = run_git(cmd, *rest, &block)
331
405
 
332
406
  if status != 0
333
- raise Errors::Git.new("Error: #{cmd} returned #{status}. Result: #{result}")
407
+ if result =~ /Not a git repository/
408
+ raise Errors::NoGitRepo.new("No Git repository at: " + @repository)
409
+ else
410
+ raise Errors::Git.new("Error: #{cmd} returned #{status}. Result: #{result}")
411
+ end
334
412
  end
335
413
  result
336
414
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: gash
3
3
  version: !ruby/object:Gem::Version
4
- version: "0.1"
4
+ version: 0.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Magnus Holm
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2008-09-04 00:00:00 +02:00
12
+ date: 2008-09-27 00:00:00 +02:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -63,14 +63,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
63
63
  version:
64
64
  required_rubygems_version: !ruby/object:Gem::Requirement
65
65
  requirements:
66
- - - "="
66
+ - - ">="
67
67
  - !ruby/object:Gem::Version
68
- version: "1.2"
68
+ version: "0"
69
69
  version:
70
70
  requirements: []
71
71
 
72
72
  rubyforge_project: dojo
73
- rubygems_version: 1.2.0
73
+ rubygems_version: 1.3.0
74
74
  signing_key:
75
75
  specification_version: 2
76
76
  summary: Git + Hash