Module: Amp::Repositories::TagManager

Includes:
Amp::RevlogSupport::Node
Included in:
LocalRepository
Defined in:
lib/amp/repository/tag_manager.rb

Overview

TagManager

This module handles all tag-related (but not branch tag) functionality of the repository.

Constant Summary collapse

TAG_FORBIDDEN_LETTERS =
":\r\n"

Constants included from Amp::RevlogSupport::Node

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

Instance Method Summary collapse

Methods included from Amp::RevlogSupport::Node

#short

Instance Method Details

#apply_tag(names, node, opts = {}) ⇒ Object

Adds the given tag to a given changeset, and commits to preserve it.

Parameters:

  • names (String, Array)

    a list of tags (or just 1 tag) to apply to the changeset

  • node (String, Integer)

    the node to apply the tag to

  • opts (Hash) (defaults to: {})

    the opts for tagging

  • [String] (Hash)

    a customizable set of options

  • [Boolean] (Hash)

    a customizable set of options

  • [Time] (Hash)

    a customizable set of options

  • [Hash] (Hash)

    a customizable set of options



132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
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
# File 'lib/amp/repository/tag_manager.rb', line 132

def apply_tag(names, node, opts={})
  use_dirstate = opts[:parent].nil?
  all_letters  = names.kind_of?(Array) ? names.join : names
  (TAG_FORBIDDEN_LETTERS.size-1).downto 0 do |i|
    if all_letters.include? TAG_FORBIDDEN_LETTERS[i, 1]
      raise abort("#{TAG_FORBIDDEN_LETTERS[i,1]} not allowed in a tag name!")
    end
  end
  
  prev_tags = ""
  # If it's a local tag, we just write the file and bounce. mad easy yo.
  if opts[:local]
    @hg_opener.open("localtags","r+") do |fp|
      prev_tags = fp.read
      write_tags(fp,names, nil, prev_tags)
    end
    return
  end
  
  # ok, it's a global tag. now we have to handle versioning and shit.
  if use_dirstate
    prev_tags = working_read(".hgtags") rescue ""
    file = @file_opener.open(".hgtags","a")
  else
    prev_tags = versioned_file(".hgtags", :change_id => parent).data
    file = @file_opener.open(".hgtags","w")
    
    file.write prev_tags if prev_tags && prev_tags.any?
  end
  
  write_tags(file, node, names, prev_tags)
  file.close
  if use_dirstate && dirstate[".hgtags"].status == :untracked
    self.add([".hgtags"])
  end
  
  tag_node = commit :files => [".hgtags"], 
                    :message => opts[:message], 
                    :user => opts[:user],
                    :date => opts[:date], 
                    :p1 => opts[:parent], 
                    :extra => opts[:extra]
  
  tag_node
end

#invalidate_tag_cache!Object

Invalidates the tag cache. Removes all ivars relating to tags.



61
62
63
64
65
# File 'lib/amp/repository/tag_manager.rb', line 61

def invalidate_tag_cache!
  @tags_for_node_cache = nil
  @tags_cache = nil
  @tags_type_cache = nil
end

#tag_listHash

Returns a list of all the tags as a hash, mapping each tag to the tip-most changeset it applies to.

Returns:

  • (Hash)

    a hash, sorted by revision index (i.e. its order in the commit history), with the keys: :revision => the revision index of the changeset, :tag => the name of the tag, :node => the node-id of the changeset



20
21
22
23
24
25
26
27
28
29
30
31
# File 'lib/amp/repository/tag_manager.rb', line 20

def tag_list
  list = []
  tags.each do |tag, node|
    begin
      r = changelog.revision(node)
    rescue
      r = -2
    end
    list << {:revision => r, :tag => tag, :node => node}
  end
  list.sort {|i1, i2| i1[:revision] <=> i2[:revision] }
end

#tag_type(tag_name) ⇒ String

Returns the tag-type of the given tag. This could be “local”, which means it is not shared among repositories.

Parameters:

  • tag_name (String)

    the name of the tag to lookup, such as “tip”

Returns:

  • (String)

    the type of the requested tag, such as “local”.



39
40
41
42
# File 'lib/amp/repository/tag_manager.rb', line 39

def tag_type(tag_name)
  tags #load the tags
  @tags_type_cache[tag_name]
end

#tagsHash

Loads all of the tags from the tag-cache file stored as .hgtags. Returns a hash, mapping tag names to node-IDs.

Returns:

  • (Hash)

    a hash mapping tags to node-IDs.



72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
# File 'lib/amp/repository/tag_manager.rb', line 72

def tags
  return @tags_cache if @tags_cache
  
  global_tags, tag_types = {}, {}
  
  file = nil
  # For each current .hgtags file in our history (including multi-heads), read in
  # the tags
  hg_tags_nodes.each do |rev, node, file_node|
    # get the file
    f = (f && f.file(file_node)) || self.versioned_file(".hgtags", :file_id => file_node.file_node)
    # read the tags, as global, because they're versioned.
    read_tags(f.data.split("\n"), f, "global", global_tags, tag_types)
  end
  
  # Now do locally stored tags, that aren't committed/versioned
  begin
    # get the local file, stored in .hg/
    data = @hg_opener.read("localtags")
    # Read the tags as local, because they are not versioned
    read_tags(data.split_newlines,"local_tags","local",global_tags, tag_types)
  rescue Errno::ENOENT
    # do nothing. most people don't have this file.
  end
  # Save our tags for use later. Use ivars.
  @tags_cache = {}
  @tags_type_cache = {}
  # Go through the global tags to store them in the cache
  global_tags.each do |k, nh|
    # the node ID is the first part of the stored data
    n = nh.first
    
    # update the cache
    @tags_cache[k] = n unless n == NULL_ID
    @tags_type_cache[k] = tag_types[k]
  end
  
  # tip = special tag
  @tags_cache["tip"] = self.changelog.tip
  
  # return our tags
  @tags_cache
end

#tags_for_node(node) ⇒ Array<String>

Returns the tags for a given revision (by ID).

Parameters:

  • node (String)

    the node-ID, in binary form.

Returns:

  • (Array<String>)

    a list of tags for the given node.



49
50
51
52
53
54
55
56
57
# File 'lib/amp/repository/tag_manager.rb', line 49

def tags_for_node(node)
  return (@tags_for_node_cache[node] || []) if @tags_for_node_cache
  @tags_for_node_cache = {}
  tags.each do |tag, tag_node|
    @tags_for_node_cache[tag_node] ||= [] # make sure there's an array
    @tags_for_node_cache[tag_node] << tag # add the tag to it
  end
  @tags_for_node_cache[node] || []
end