summaryrefslogtreecommitdiff
path: root/misc/dashboard/builder/hg.go
blob: d4310845d1b64305b09ed736cd347bb6bf4a6ea8 (plain)
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
// Copyright 2011 The Go 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 main

import (
	"fmt"
	"os"
	"regexp"
	"strconv"
	"strings"
)

type Commit struct {
	num    int    // mercurial revision number
	node   string // mercurial hash
	parent string // hash of commit's parent
	user   string // author's Name <email>
	date   string // date of commit
	desc   string // description
}

// getCommit returns details about the Commit specified by the revision hash
func getCommit(rev string) (c Commit, err os.Error) {
	defer func() {
		if err != nil {
			err = fmt.Errorf("getCommit: %s: %s", rev, err)
		}
	}()
	parts, err := getCommitParts(rev)
	if err != nil {
		return
	}
	num, err := strconv.Atoi(parts[0])
	if err != nil {
		return
	}
	parent := ""
	if num > 0 {
		prev := strconv.Itoa(num - 1)
		if pparts, err := getCommitParts(prev); err == nil {
			parent = pparts[1]
		}
	}
	user := strings.Replace(parts[2], "&lt;", "<", -1)
	user = strings.Replace(user, "&gt;", ">", -1)
	return Commit{num, parts[1], parent, user, parts[3], parts[4]}, nil
}

func getCommitParts(rev string) (parts []string, err os.Error) {
	const format = "{rev}>{node}>{author|escape}>{date}>{desc}"
	s, _, err := runLog(nil, "", goroot,
		"hg", "log",
		"--encoding", "utf-8",
		"--rev", rev,
		"--limit", "1",
		"--template", format,
	)
	if err != nil {
		return
	}
	return strings.Split(s, ">", 5), nil
}

var revisionRe = regexp.MustCompile(`([0-9]+):[0-9a-f]+$`)

// getTag fetches a Commit by finding the first hg tag that matches re.
func getTag(re *regexp.Regexp) (c Commit, tag string, err os.Error) {
	o, _, err := runLog(nil, "", goroot, "hg", "tags")
	for _, l := range strings.Split(o, "\n", -1) {
		tag = re.FindString(l)
		if tag == "" {
			continue
		}
		s := revisionRe.FindStringSubmatch(l)
		if s == nil {
			err = os.NewError("couldn't find revision number")
			return
		}
		c, err = getCommit(s[1])
		return
	}
	err = os.NewError("no matching tag found")
	return
}