Class: Amp::Changeset

Inherits:
Object show all
Includes:
RevlogSupport::Node, Comparable, Enumerable
Defined in:
lib/amp/revlogs/changeset.rb

Overview

A Changeset is a simple way of accessing the repository within a certain revision. For example, if the user specifies revision # 36, or revision 3adf21, then we can look those up, and work within the repository at the moment of that revision.

Direct Known Subclasses

WorkingDirectoryChangeset

Constant Summary

Constants included from RevlogSupport::Node

RevlogSupport::Node::NULL_ID, RevlogSupport::Node::NULL_REV

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from Enumerable

#inject, #select_map

Methods included from RevlogSupport::Node

#short

Constructor Details

#initialize(repo, change_id = '') ⇒ Changeset

Initializes a new changeset. We need a repository to work with, and also a change_id. this change_id could be a revision index or a node_id for the revision.

Parameters:

  • repo (Repository)

    a repository to work with.

  • change_id (Integer, String) (defaults to: '')

    an ID or index to lookup to find this changeset.



25
26
27
28
29
30
31
32
33
34
35
# File 'lib/amp/revlogs/changeset.rb', line 25

def initialize(repo, change_id='')
  change_id = '.' if change_id == ''
  @repo = repo
  if change_id.kind_of? Integer
    @revision = change_id
    @node_id  = @repo.changelog.node_id_for_index change_id
  else
    @node_id = @repo.lookup change_id
    @revision = @repo.changelog.rev @node_id
  end
end

Instance Attribute Details

#repoObject (readonly) Also known as: repository

Returns the value of attribute repo.



13
14
15
# File 'lib/amp/revlogs/changeset.rb', line 13

def repo
  @repo
end

Instance Method Details

#<=>(other) ⇒ Integer

Compares 2 changesets so we can sort them and whatnot

Parameters:

  • other (Changeset)

    a changeset we will compare against

Returns:

  • (Integer)

    -1, 0, or 1. Typical comparison.



123
124
125
126
# File 'lib/amp/revlogs/changeset.rb', line 123

def <=>(other)
  return 0 if @revision.nil? || other.revision.nil?
  @revision <=> other.revision
end

#[](file) ⇒ VersionedFile

Gets the file with the given name, as a VersionedFile.

Parameters:

  • file

    the path to the file to retrieve

Returns:



203
204
205
# File 'lib/amp/revlogs/changeset.rb', line 203

def [](file)
  get_file(file)
end

#ancestor(other_changeset) ⇒ Object



324
325
326
327
# File 'lib/amp/revlogs/changeset.rb', line 324

def ancestor(other_changeset)
  node = @repo.changelog.ancestor(self.node, other_changeset.node)
  return Changeset.new(@repo, node)
end

#ancestorsObject



329
330
331
332
# File 'lib/amp/revlogs/changeset.rb', line 329

def ancestors
  results = []
  @repo.changelog.ancestors(revision)
end

#branchObject

What branch i was committed onto



290
291
292
# File 'lib/amp/revlogs/changeset.rb', line 290

def branch 
  raw_changeset[5]["branch"] 
end

#childrenArray<Changeset>

Returns the children of this changeset as Amp::Changesets.

Returns:



177
178
179
180
181
# File 'lib/amp/revlogs/changeset.rb', line 177

def children
  @repo.changelog.children(node_id).map do |node|
    Changeset.new(@repo, node)
  end
end

#dateObject

the date i was committed!



283
# File 'lib/amp/revlogs/changeset.rb', line 283

def date; raw_changeset[2]; end

#descriptionObject

the message with this commit



288
# File 'lib/amp/revlogs/changeset.rb', line 288

def description; raw_changeset[4]; end

#each(&block) ⇒ Object

Iterates over each entry in the manifest.



185
186
187
# File 'lib/amp/revlogs/changeset.rb', line 185

def each(&block)
  manifest.sort.each(&block)
end

#easy_dateObject



284
# File 'lib/amp/revlogs/changeset.rb', line 284

def easy_date; Time.at(raw_changeset[2].first); end

#extraObject

Any extra stuff I’ve got in me



294
# File 'lib/amp/revlogs/changeset.rb', line 294

def extra; raw_changeset[5]; end

#file_info(path) ⇒ [String, String]

Returns the file’s info, namely it’s node_id and flags it may have at this point in time, such as “x” for executable.

Parameters:

  • path

    the path to the file

Returns:

  • ([String, String])

    the [node_id, flags] pair for this file



213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
# File 'lib/amp/revlogs/changeset.rb', line 213

def file_info(path)
  if manifest # have we loaded our manifest yet? if so, use that sucker
    result = [manifest[path], manifest.flags[path]]
    if result[0].nil?
      return [NULL_ID, '']
    else
      return result
    end
  end
  if manifest_delta || files[path] # check if it's in the delta... i dunno
    if manifest_delta[path]
      return [manifest_delta[path], manifest_delta.flags[path]]
    end
  end
  # Give us, just look it up the long way in the manifest. not fun. slow.
  node, flag = @repo.manifest.find(raw_changeset[0], path)
  if node.nil?
    return [NULL_ID, '']
  end
  return [node, flag]
end

#file_node(path) ⇒ String

Gets the node_id in the manifest for the file at this path, for this specific revision.

Parameters:

  • path

    the path to the file

Returns:

  • (String)

    the node’s ID in the manifest, which we’ll use every where we need a node_id.



253
254
255
# File 'lib/amp/revlogs/changeset.rb', line 253

def file_node(path)
  file_info(path).first[0..19]
end

#filesObject

the files affected in this commit!



286
# File 'lib/amp/revlogs/changeset.rb', line 286

def files; raw_changeset[3]; end

#flags(path) ⇒ String

Gets the flags for the file at the given path at this revision.

Parameters:

  • path

    the path to the file in question

Returns:

  • (String)

    the flags for the file, such as “x” or “l”.



240
241
242
243
244
# File 'lib/amp/revlogs/changeset.rb', line 240

def flags(path)
  info = file_info(path)[1]
  return "" if info.nil?
  info
end

#get_file(path, file_id = nil, file_log = nil) ⇒ VersionedFile

Creates a versioned file for the file at the given path, for the frame of reference of this revision.

Parameters:

  • path

    the path to the file

  • file_id (String) (defaults to: nil)

    the node_id, to save us some computation

  • file_log (FileLog) (defaults to: nil)

    the file_log to use, again to save us computation

Returns:



265
266
267
268
269
# File 'lib/amp/revlogs/changeset.rb', line 265

def get_file(path, file_id = nil, file_log = nil)
  file_id = file_node(path) if file_id.nil?
  VersionedFile.new(@repo, path, :file_id => file_id, :changeset => self,
                                 :file_log => file_log)
end

#hashInteger

Hash function for putting these bad boys in hashes

Returns:



113
114
115
116
# File 'lib/amp/revlogs/changeset.rb', line 113

def hash
  return @revision.hash if @revision
  return object_id
end

#hexObject

our node_id in sexy hexy



279
# File 'lib/amp/revlogs/changeset.rb', line 279

def hex; @node_id.hexlify; end

#include?(file) ⇒ Boolean

Checks whether this changeset included a given file or not.

Parameters:

  • file (String)

    the file to lookup

Returns:

  • (Boolean)

    whether the file is in this changeset’s manifest



194
195
196
# File 'lib/amp/revlogs/changeset.rb', line 194

def include?(file)
  manifest[file] != nil
end

#inspectObject

Gives an easier way to digest this changeset while reminding us it’s a changeset



105
106
107
# File 'lib/amp/revlogs/changeset.rb', line 105

def inspect
  "#<Changeset #{to_s}>"
end

#manifestManifestEntry

Returns the ManifestEntry for this revision. This will give us info on any file we want, including flags such as executable or if it’s a link. Sizes and so on are also included.

Returns:



149
150
151
# File 'lib/amp/revlogs/changeset.rb', line 149

def manifest
  @manifest ||= @repo.manifest.read(raw_changeset[0])
end

#manifest_deltaObject

Returns the change in the manifest at this revision. I don’t entirely know what this is yet.



156
157
158
# File 'lib/amp/revlogs/changeset.rb', line 156

def manifest_delta
  @manifest_delta ||= @repo.manifest.read_delta(raw_changeset[0])
end

#nil?Boolean Also known as: null?

Are we a null revision?

Returns:



131
132
133
# File 'lib/amp/revlogs/changeset.rb', line 131

def nil?
 @revision != NULL_REV
end

#node_idObject Also known as: node

node_id



275
# File 'lib/amp/revlogs/changeset.rb', line 275

def node_id; @node_id; end

#parents[Changeset]

Returns the parents of this changeset as Amp::Changesets.

Returns:

  • ([Changeset])

    the parents of this changeset.



164
165
166
167
168
169
170
171
# File 'lib/amp/revlogs/changeset.rb', line 164

def parents
  return @parents if @parents
  
  p = @repo.changelog.parent_indices_for_index @revision
  p = [p[0]] if p[1] == NULL_REV
  
  @parents = p.map {|x| Changeset.new(@repo, x) }
end

#raw_changesetObject

Gets the raw changeset data for this revision. This includes the user who committed it, the description of the commit, and so on. Returns this: [manifest, user, [time, timezone], files, desc, extra]



139
140
141
# File 'lib/amp/revlogs/changeset.rb', line 139

def raw_changeset
  @repo.changelog.read(@node_id)
end

#revisionObject Also known as: rev

accessors revision index



272
# File 'lib/amp/revlogs/changeset.rb', line 272

def revision; @revision; end

#tagsObject

tags



296
# File 'lib/amp/revlogs/changeset.rb', line 296

def tags; @repo.tags_for_node node; end

#to_iObject

Converts the revision to a number



39
# File 'lib/amp/revlogs/changeset.rb', line 39

def to_i; @revision; end

#to_s(opts = {}) ⇒ Object

Converts the revision to an easy-to-digest string



43
44
45
46
47
48
49
# File 'lib/amp/revlogs/changeset.rb', line 43

def to_s(opts = {})
  if opts[:template]
    to_templated_s(opts)
  else
    @node_id[0..5].hexlify
  end
end

#to_templated_s(opts = {}) ⇒ Object



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/amp/revlogs/changeset.rb', line 53

def to_templated_s(opts={})
  
  change_node = node
  revision    = self.revision
  log         = @repo.changelog
  changes     = log.read change_node
  username    = changes[1]
  date        = Time.at changes[2].first
  files       = changes[3]
  description = changes[4]
  extra       = changes[5]
  branch      = extra["branch"]
  cs_tags     = tags
  type        = opts[:template_type].to_s || 'log'
  
  added   = opts[:added]
  removed = opts[:removed]
  updated = opts[:updated]
  config  = opts
  
  parents = useful_parents log, revision
  parents.map! {|p| [p, log.node(p)[0..5].hexlify] }
  
  p1 = useful_parents(log, revision)[0]
  p2 = useful_parents(log, revision)[1]
  
  return "" if opts[:no_output]
  
  config = opts
  
  template = opts[:template]
  template = "default-#{type}" if (template.nil? || template.to_s == "default")

  template = Support::Template[template]
  template.render({}, binding)
end

#useful_parents(log, revision) ⇒ Object



90
91
92
93
94
95
96
97
98
99
100
# File 'lib/amp/revlogs/changeset.rb', line 90

def useful_parents(log, revision)
  parents = log.parent_indices_for_index revision
  if parents[1] == -1
    if parents[0] >= revision - 1
      parents = []
    else
      parents = [parents[0]]
    end
  end
  parents
end

#userObject

the user who committed me!



281
# File 'lib/amp/revlogs/changeset.rb', line 281

def user; raw_changeset[1]; end

#walk(match) ⇒ Object

recursively walk

Parameters:

  • match (Amp::Matcher)

    this is a custom object that knows files magically. Not your grampa’s proc!



303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
# File 'lib/amp/revlogs/changeset.rb', line 303

def walk(match) # calls DirState#walk
  # just make it so the keys are there
  results = []
  
  hash = Hash.with_keys match.files
  hash.delete '.'
  
  each do |file|
    hash.each {|f, val| (hash.delete file and break) if f == file }
    
    results << file if match.call file # yield file if match.call file
  end
  
  hash.keys.sort.each do |file|
    if match.bad file, "No such file in revision #{revision}" and match[file]
      results << file # yield file
    end
  end
  results
end