blob: 1db382be7fa716c7e90940d7f691429ff557bcd5 [file]
// Copyright 2016 The LUCI Authors. All rights reserved.
// Use of this source code is governed under the Apache License, Version 2.0
// that can be found in the LICENSE file.
package main
import (
"go/build"
"io/ioutil"
"os"
"path/filepath"
"strings"
"github.com/golang/protobuf/proto"
"github.com/luci/luci-go/common/errors"
log "github.com/luci/luci-go/common/logging"
"golang.org/x/net/context"
)
func unmarshalTextProtobuf(path string, msg proto.Message) error {
data, err := ioutil.ReadFile(path)
switch {
case err == nil:
if err := proto.UnmarshalText(string(data), msg); err != nil {
return errors.Annotate(err).Reason("failed to unmarshal %(type)T from [%(path)s]").
D("type", msg).D("path", path).Err()
}
return nil
case isNotExist(err):
// Forward this so it can be tested.
return err
default:
return errors.Annotate(err).Reason("failed to read data from [%(path)s]").D("path", path).Err()
}
}
func unmarshalTextProtobufDir(base string, fis []os.FileInfo, msg proto.Message, cb func(name string) error) error {
for _, fi := range fis {
name := fi.Name()
if isHidden(name) {
continue
}
if err := unmarshalTextProtobuf(filepath.Join(base, name), msg); err != nil {
return errors.Annotate(err).Reason("failed to unmarshal file [%(name)s]").D("name", name).Err()
}
if err := cb(name); err != nil {
return errors.Annotate(err).Reason("failed to process file [%(name)s]").D("name", name).Err()
}
}
return nil
}
func logError(c context.Context, err error, f string, args ...interface{}) {
log.WithError(err).Errorf(c, f, args...)
if log.IsLogging(c, log.Debug) {
log.Debugf(c, "Error stack:\n%s", strings.Join(errors.RenderStack(err).ToLines(), "\n"))
}
}
func isNotExist(err error) bool {
return os.IsNotExist(errors.Unwrap(err))
}
func splitTitlePath(s string) (title, string) {
switch v := strings.SplitN(s, "/", 2); len(v) {
case 1:
return title(v[0]), ""
default:
return title(v[0]), v[1]
}
}
func joinPath(titles ...title) string {
comps := make([]string, len(titles))
for i, t := range titles {
comps[i] = string(t)
}
return strings.Join(comps, "/")
}
func splitSourcePath(v string) (group, source title) {
var tail string
group, tail = splitTitlePath(v)
source = title(tail)
return
}
func splitComponentPath(v string) (deployment, component title) {
var tail string
deployment, tail = splitTitlePath(v)
if tail != "" {
component = title(tail)
}
return
}
func splitGoPackage(pkg string) []string {
// Check intermediate paths to make sure there isn't a deployment
// conflict.
var (
parts []string
lastIdx = 0
)
for {
idx := strings.IndexRune(pkg[lastIdx:], '/')
if idx < 0 {
// Last component, don't check/register.
return append(parts, pkg)
}
parts = append(parts, pkg[:lastIdx+idx])
lastIdx += idx + len("/")
}
}
func findGoPackage(pkg string, goPath []string) string {
bctx := build.Default
bctx.GOPATH = strings.Join(goPath, string(os.PathListSeparator))
p, err := bctx.Import(pkg, "", build.FindOnly)
if err != nil {
return ""
}
return p.Dir
}