blob: 85b93fe00dfb9a2333d0b351cda3a84189b72951 [file]
// Copyright 2016 The LUCI Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
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, "failed to unmarshal %T from [%s]", msg, path).Err()
}
return nil
case isNotExist(err):
// Forward this so it can be tested.
return err
default:
return errors.Annotate(err, "failed to read data from [%s]", 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, "failed to unmarshal file [%s]", name).Err()
}
if err := cb(name); err != nil {
return errors.Annotate(err, "failed to process file [%s]", 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), "\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
}