utils: Add a git-r utility for mapping svn revisions to git revisions in the monorepo.

llvm-svn: 305598
This commit is contained in:
Peter Collingbourne 2017-06-16 22:15:18 +00:00
parent 32614fcf42
commit f6ca97284c
1 changed files with 169 additions and 0 deletions

View File

@ -0,0 +1,169 @@
//===- git-r.go - svn revisions to git revisions --------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This is a small program for mapping svn revisions to git revisions in the
// monorepo.
//
// To set up:
// 1) http://llvm.org/docs/GettingStarted.html#for-developers-to-work-with-a-git-monorepo
// and make sure to follow the instructions for fetching commit notes.
// 2) go build
// 3) cp git-r ~/bin
//
// To use:
// $ git r 1
// 09c4b68e68c4fcff64b00e1ac077c4f4a524cbcc
//
//===----------------------------------------------------------------------===//
package main
import (
"bufio"
"bytes"
"encoding/gob"
"fmt"
"log"
"os"
"os/exec"
"strconv"
"strings"
)
func git(args ...string) (*bytes.Buffer, error) {
cmd := exec.Command("git", args...)
var b bytes.Buffer
cmd.Stdout = &b
err := cmd.Run()
return &b, err
}
func mkrevmap() []string {
revs, err := git("grep", "git-svn-rev", "refs/notes/commits")
if err != nil {
panic(err)
}
var revmap []string
scanner := bufio.NewScanner(revs)
for scanner.Scan() {
// refs/notes/commits:00/0b/d4acb454290301c140a1d9c4f7a45aa2fa9c:git-svn-rev: 37235
bits := strings.Split(scanner.Text(), ":")
gitrev := strings.Replace(bits[1], "/", "", -1)
svnrev := bits[3][1:]
svnrevn, err := strconv.Atoi(svnrev)
if err != nil {
panic(err)
}
if svnrevn >= len(revmap) {
newrevmap := make([]string, svnrevn+1)
copy(newrevmap, revmap)
revmap = newrevmap
}
revmap[svnrevn] = gitrev
}
return revmap
}
type revmap struct {
Noterev string
Revs []string
}
func writerevmap(path string, rmap *revmap, svnrev int) {
noterevbuf, err := git("rev-parse", "refs/notes/commits")
if err != nil {
fmt.Fprintf(os.Stderr, "%s: could not find refs/notes/commits, see instructions:\n", os.Args[0])
fmt.Fprintln(os.Stderr, "http://llvm.org/docs/GettingStarted.html#for-developers-to-work-with-a-git-monorepo")
os.Exit(1)
}
noterev := noterevbuf.String()
noterev = noterev[:len(noterev)-1]
if rmap == nil || rmap.Noterev != noterev {
var newrmap revmap
newrmap.Revs = mkrevmap()
newrmap.Noterev = noterev
f, err := os.Create(path)
if err != nil {
panic(err)
}
enc := gob.NewEncoder(f)
err = enc.Encode(newrmap)
if err != nil {
os.Remove(path)
panic(err)
}
rmap = &newrmap
}
if svnrev >= len(rmap.Revs) || rmap.Revs[svnrev] == "" {
fmt.Fprintf(os.Stderr, "%s: %d: unknown revision\n", os.Args[0], svnrev)
os.Exit(1)
}
fmt.Println(rmap.Revs[svnrev])
}
func main() {
if len(os.Args) != 2 {
fmt.Fprintf(os.Stderr, "%s: expected a single argument\n", os.Args[0])
os.Exit(1)
}
svnrev, err := strconv.Atoi(os.Args[1])
if err != nil {
fmt.Fprintf(os.Stderr, "%s: %s: expected an integer argument\n", os.Args[0], os.Args[1])
os.Exit(1)
}
gitdirbuf, err := git("rev-parse", "--git-common-dir")
if err != nil {
fmt.Fprintf(os.Stderr, "%s: not in a git repository\n", os.Args[0])
os.Exit(1)
}
gitdir := gitdirbuf.String()
gitdir = gitdir[:len(gitdir)-1]
err = os.Chdir(gitdir)
if err != nil {
panic(err)
}
mappath := "git-svn-revmap-cache"
f, err := os.Open(mappath)
if err != nil {
writerevmap(mappath, nil, svnrev)
return
}
dec := gob.NewDecoder(f)
var rmap revmap
err = dec.Decode(&rmap)
if err != nil {
writerevmap(mappath, nil, svnrev)
return
}
if svnrev < len(rmap.Revs) && rmap.Revs[svnrev] != "" {
fmt.Println(rmap.Revs[svnrev])
return
}
writerevmap(mappath, &rmap, svnrev)
}