golang.org/x/build@v0.0.0-20240506185731-218518f32b70/maintner/godata/godata.go (about) 1 // Copyright 2017 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 // Package godata loads the Go project's corpus of Git, Github, and 6 // Gerrit activity into memory to allow easy analysis without worrying 7 // about APIs and their pagination, quotas, and other nuisances and 8 // limitations. 9 package godata 10 11 import ( 12 "context" 13 "log" 14 "os" 15 "os/user" 16 "path/filepath" 17 "runtime" 18 19 "golang.org/x/build/maintner" 20 ) 21 22 // Server is the Go project's production maintner log. 23 const Server = "https://maintner.golang.org/logs" 24 25 // Get returns the Go project's corpus, containing all Git commits, 26 // Github activity, and Gerrit activity and metadata since the 27 // beginning of the project. 28 // 29 // Use Corpus.Update to keep the corpus up-to-date. If you do this, you must 30 // hold the read lock if reading and updating concurrently. 31 // 32 // The initial call to Get will download a few gigabytes of data 33 // into a directory "golang-maintner" under your operating 34 // system's user cache directory. Subsequent calls will only download 35 // what's changed since the previous call. 36 // 37 // Even with all the data already cached on local disk, a call to Get 38 // takes approximately 15 seconds per gigabyte of mutation log data 39 // to load it into memory. 40 // For daemons, use Corpus.Update to incrementally update an 41 // already-loaded Corpus. 42 // 43 // The in-memory representation is about 25% larger than its on-disk 44 // size. In April 2022, it's under 4 GB. 45 // 46 // See https://pkg.go.dev/golang.org/x/build/maintner#Corpus for how 47 // to walk the data structure. 48 func Get(ctx context.Context) (*maintner.Corpus, error) { 49 targetDir := Dir() 50 if err := os.MkdirAll(targetDir, 0700); err != nil { 51 return nil, err 52 } 53 mutSrc := maintner.NewNetworkMutationSource(Server, targetDir) 54 corpus := new(maintner.Corpus) 55 if err := corpus.Initialize(ctx, mutSrc); err != nil { 56 return nil, err 57 } 58 return corpus, nil 59 } 60 61 // Dir returns the directory containing the cached mutation logs. 62 func Dir() string { 63 return filepath.Join(XdgCacheDir(), "golang-maintner") 64 } 65 66 // XdgCacheDir returns the XDG Base Directory Specification cache 67 // directory. 68 func XdgCacheDir() string { 69 cache := os.Getenv("XDG_CACHE_HOME") 70 if cache != "" { 71 return cache 72 } 73 home := homeDir() 74 // Not XDG but standard for OS X. 75 if runtime.GOOS == "darwin" { 76 return filepath.Join(home, "Library/Caches") 77 } 78 return filepath.Join(home, ".cache") 79 } 80 81 func homeDir() string { 82 if runtime.GOOS == "windows" { 83 return os.Getenv("HOMEDRIVE") + os.Getenv("HOMEPATH") 84 } 85 home := os.Getenv("HOME") 86 if home != "" { 87 return home 88 } 89 u, err := user.Current() 90 if err != nil { 91 log.Fatalf("failed to get home directory or current user: %v", err) 92 } 93 return u.HomeDir 94 }