This repository has been archived by the owner on May 2, 2024. It is now read-only.
/
tags.go
110 lines (96 loc) · 2.26 KB
/
tags.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
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
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
// Copyright 2013 The hgo Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package hgo
import (
"bytes"
"io"
"io/ioutil"
"sort"
"strings"
"github.com/knieriem/hgo/revlog"
)
// Tags contains a mapping from tag names to changeset IDs,
// and a mapping from changesetIDs to slices of tag names.
type Tags struct {
IdByName map[string]string
ById map[string][]string
}
func newTags() *Tags {
return &Tags{
ById: map[string][]string{},
IdByName: map[string]string{},
}
}
func (dest *Tags) copy(src *Tags) {
for k, v := range src.ById {
dest.ById[k] = v
}
for k, v := range src.IdByName {
dest.IdByName[k] = v
}
}
// Parse tags, and return one Tags structure containing only
// global tags, another one containing both global and local tags.
func (r *Repository) Tags() (tGlobal, tAll *Tags) {
tGlobal, tAll = newTags(), newTags()
st := r.NewStore()
index, err := st.OpenRevlog(".hgtags")
if err == nil {
fb := revlog.NewFileBuilder()
if err := fb.BuildWrite(nil, index.Tip()); err == nil {
tAll.parseFile(bytes.NewReader(fb.Bytes()))
}
}
f, err := r.open(".hg/localtags")
if err == nil {
tGlobal.copy(tAll)
err = tAll.parseFile(f)
f.Close()
} else {
tGlobal = tAll
}
return
}
func (t *Tags) parseFile(r io.Reader) (err error) {
buf, err := ioutil.ReadAll(r)
if err != nil {
return
}
lines := strings.Split(string(buf), "\n")
m := make(map[string]string, len(lines))
for _, line := range lines {
tag := strings.SplitN(strings.TrimSpace(line), " ", 2)
if len(tag) != 2 {
continue
}
m[tag[1]] = tag[0]
}
// unify
for name, id := range m {
t.ById[id] = append(t.ById[id], name)
t.IdByName[name] = id
}
return
}
// Associate a new tag with a changeset ID.
func (t *Tags) Add(name, id string) {
t.ById[id] = append(t.ById[id], name)
t.IdByName[name] = id
}
// For each changeset ID within the ById member, sort the tag names
// associated with it in increasing order. This function should be called
// if one or more tags have been inserted using Add.
func (t *Tags) Sort() {
for _, v := range t.ById {
switch len(v) {
case 1:
case 2:
if v[0] > v[1] {
v[0], v[1] = v[1], v[0]
}
default:
sort.Strings(v)
}
}
}