diff options
author | Peter Collingbourne <peter@pcc.me.uk> | 2017-06-16 22:15:18 +0000 |
---|---|---|
committer | Peter Collingbourne <peter@pcc.me.uk> | 2017-06-16 22:15:18 +0000 |
commit | b8f8fa1c8c2a83165833ce5549420e22357af39d (patch) | |
tree | 52b43759f0beb0ff857c498e6365b9d8ffcd8d88 /utils/git-svn | |
parent | 3589cb5a83a8e1066d7ca7d86aa9748ae87de390 (diff) |
utils: Add a git-r utility for mapping svn revisions to git revisions in the monorepo.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@305598 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'utils/git-svn')
-rw-r--r-- | utils/git-svn/git-r/git-r.go | 169 |
1 files changed, 169 insertions, 0 deletions
diff --git a/utils/git-svn/git-r/git-r.go b/utils/git-svn/git-r/git-r.go new file mode 100644 index 00000000000..fb641c98fd2 --- /dev/null +++ b/utils/git-svn/git-r/git-r.go @@ -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) +} |