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.



20
21
22
23
24
# File 'lib/grit/index.rb', line 20

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

#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.



32
33
34
35
36
37
38
39
40
41
42
43
44
45
# File 'lib/grit/index.rb', line 32

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: "master").
: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.



99
100
101
102
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
# File 'lib/grit/index.rb', line 99

def commit(message, parents = nil, actor = nil, last_tree = nil, head = 'master')
  if parents.is_a?(Hash)
    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

  tree_sha1 = write_tree(self.tree, self.current_tree)

  # 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

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

  self.repo.update_ref(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.



52
53
54
# File 'lib/grit/index.rb', line 52

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.



62
63
64
# File 'lib/grit/index.rb', line 62

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.



192
193
194
# File 'lib/grit/index.rb', line 192

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

#write_tree(tree, 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.



152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
# File 'lib/grit/index.rb', line 152

def write_tree(tree, now_tree = nil)
  tree_contents = {}

  # fill in original tree
  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 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('')
  self.repo.git.put_raw_object(tr, 'tree')
end