Class: Grit::Index

Inherits:
Object
  • Object
show all
Defined in:
lib/grit/index.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(repo) ⇒ Index

Initialize a new Index object.

repo - The Grit::Repo to which the index belongs.

Returns the newly initialized Grit::Index.


24
25
26
27
28
# File 'lib/grit/index.rb', line 24

def initialize(repo)
  self.repo = repo
  self.tree = {}
  self.current_tree = nil
end

Instance Attribute Details

#current_treeObject

Public: Gets/Sets the Grit::Tree object representing the tree upon which the next commit will be based.


13
14
15
# File 'lib/grit/index.rb', line 13

def current_tree
  @current_tree
end

#last_commit_sizeObject (readonly)

Returns the value of attribute last_commit_size


17
18
19
# File 'lib/grit/index.rb', line 17

def last_commit_size
  @last_commit_size
end

#last_tree_sizeObject (readonly)

Public: if a tree or commit is written, this stores the size of that object


16
17
18
# File 'lib/grit/index.rb', line 16

def last_tree_size
  @last_tree_size
end

#repoObject

Public: Gets/Sets the Grit::Repo to which this index belongs.


5
6
7
# File 'lib/grit/index.rb', line 5

def repo
  @repo
end

#treeObject

Public: Gets/Sets the Hash tree map that holds the changes to be made in the next commit.


9
10
11
# File 'lib/grit/index.rb', line 9

def tree
  @tree
end

Instance Method Details

#add(path, data) ⇒ Object

Public: Add a file to the index.

path - The String file path including filename (no slash prefix). data - The String binary contents of the file.

Returns nothing.


36
37
38
39
40
41
42
43
44
45
46
47
48
49
# File 'lib/grit/index.rb', line 36

def add(path, data)
  path = path.split('/')
  filename = path.pop

  current = self.tree

  path.each do |dir|
    current[dir] ||= {}
    node = current[dir]
    current = node
  end

  current[filename] = data
end

#commit(message, parents = nil, actor = nil, last_tree = nil, head = 'master') ⇒ Object

Public: Commit the contents of the index. This method supports two formats for arguments:

message - The String commit message. options - An optional Hash of index options.

:parents        - Array of String commit SHA1s or Grit::Commit
                  objects to attach this commit to to form a 
                  new head (default: nil).
:actor          - The Grit::Actor details of the user making
                  the commit (default: nil).
:last_tree      - The String SHA1 of a tree to compare with
                  in order to avoid making empty commits
                  (default: nil).
:head           - The String branch name to write this head to
                  (default: nil).
:committed_date - The Time that the commit was made.
                  (Default: Time.now)
:authored_date  - The Time that the commit was authored.
                  (Default: committed_date)

The legacy argument style looks like:

message - The String commit message. parents - Array of String commit SHA1s or Grit::Commit objects to

attach this commit to to form a new head (default: nil).

actor - The Grit::Actor details of the user making the commit

(default: nil).

last_tree - The String SHA1 of a tree to compare with in order to avoid

making empty commits (default: nil).

head - The String branch name to write this head to

(default: "master").

Returns a String of the SHA1 of the new commit.


103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
# File 'lib/grit/index.rb', line 103

def commit(message, parents = nil, actor = nil, last_tree = nil, head = 'master')
  commit_tree_sha = nil
  if parents.is_a?(Hash)
    commit_tree_sha = parents[:commit_tree_sha]
    actor          = parents[:actor]
    committer      = parents[:committer]
    author         = parents[:author]
    last_tree      = parents[:last_tree]
    head           = parents[:head]
    committed_date = parents[:committed_date]
    authored_date  = parents[:authored_date]
    parents        = parents[:parents]
  end

  committer ||= actor
  author    ||= committer

  if commit_tree_sha
    tree_sha1 = commit_tree_sha
  else
    tree_sha1 = write_tree(self.tree, self.current_tree)
  end

  # don't write identical commits
  return false if tree_sha1 == last_tree

  contents = []
  contents << ['tree', tree_sha1].join(' ')
  parents.each do |p|
    contents << ['parent', p].join(' ')
  end if parents

  committer      ||= begin
    config = Config.new(self.repo)
    Actor.new(config['user.name'], config['user.email'])
  end
  author         ||= committer
  committed_date ||= Time.now
  authored_date  ||= committed_date

  contents << ['author',    author.output(authored_date)].join(' ')
  contents << ['committer', committer.output(committed_date)].join(' ')
  contents << ''
  contents << message

  contents = contents.join("\n")
  @last_commit_size = contents.size
  commit_sha1 = self.repo.git.put_raw_object(contents, 'commit')

  self.repo.update_ref(head, commit_sha1) if head
  commit_sha1
end

#delete(path) ⇒ Object

Public: Delete the given file from the index.

path - The String file path including filename (no slash prefix).

Returns nothing.


56
57
58
# File 'lib/grit/index.rb', line 56

def delete(path)
  add(path, false)
end

#read_tree(tree) ⇒ Object

Public: Read the contents of the given Tree into the index to use as a starting point for the index.

tree - The String branch/tag/sha of the Git tree object.

Returns nothing.


66
67
68
# File 'lib/grit/index.rb', line 66

def read_tree(tree)
  self.current_tree = self.repo.tree(tree)
end

#write_blob(data) ⇒ Object

Write a blob to the index.

data - The String data to write.

Returns the String SHA1 of the new blob.


217
218
219
# File 'lib/grit/index.rb', line 217

def write_blob(data)
  self.repo.git.put_raw_object(data, 'blob')
end

#write_tree(tree = nil, now_tree = nil) ⇒ Object

Recursively write a tree to the index.

tree - The Hash tree map:

key - The String directory or filename.
val - The Hash submap or the String contents of the file.

now_tree - The Grit::Tree representing the a previous tree upon which

this tree will be based (default: nil).

Returns the String SHA1 String of the tree.


165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
# File 'lib/grit/index.rb', line 165

def write_tree(tree = nil, now_tree = nil)
  tree = self.tree if !tree
  tree_contents = {}

  # fill in original tree
  now_tree = read_tree(now_tree) if(now_tree && now_tree.is_a?(String))
  now_tree.contents.each do |obj|
    sha = [obj.id].pack("H*")
    k = obj.name
    k += '/' if (obj.class == Grit::Tree)
    tmode = obj.mode.to_i.to_s  ## remove zero-padding
    tree_contents[k] = "%s %s\0%s" % [tmode, obj.name, sha]
  end if now_tree

  # overwrite with new tree contents
  tree.each do |k, v|
    case v
      when Array
        sha, mode = v
        if sha.size == 40        # must be a sha
          sha = [sha].pack("H*")
          mode = mode.to_i.to_s  # leading 0s not allowed
          k = k.split('/').last  # slashes not allowed
          str = "%s %s\0%s" % [mode, k, sha]
          tree_contents[k] = str
        end
      when String
        sha = write_blob(v)
        sha = [sha].pack("H*")
        str = "%s %s\0%s" % ['100644', k, sha]
        tree_contents[k] = str
      when Hash
        ctree = now_tree/k if now_tree
        sha = write_tree(v, ctree)
        sha = [sha].pack("H*")
        str = "%s %s\0%s" % ['40000', k, sha]
        tree_contents[k + '/'] = str
      when false
        tree_contents.delete(k)
    end
  end

  tr = tree_contents.sort.map { |k, v| v }.join('')
  @last_tree_size = tr.size
  self.repo.git.put_raw_object(tr, 'tree')
end