blob: ca5f58e298af67d1aed62690ded31b847046e29f [file] [log] [blame]
// Copyright 2018 The Goma Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package remoteexec
import (
"context"
"fmt"
"io"
rpb "go.chromium.org/goma/server/proto/remote-apis/build/bazel/remote/execution/v2"
pb "go.chromium.org/goma/server/proto/command"
"go.chromium.org/goma/server/remoteexec/digest"
"go.chromium.org/goma/server/remoteexec/merkletree"
)
// CmdStorage is an interface to retrieve cmd file contents.
type CmdStorage interface {
Open(ctx context.Context, hash string) (io.ReadCloser, error)
}
// fileSpecToEntry converts filespec to merkletree entry.
func fileSpecToEntry(ctx context.Context, fs *pb.FileSpec, cmdStorage CmdStorage) (merkletree.Entry, error) {
if fs.HashKey != "" || fs.Blob != nil {
return merkletree.Entry{}, fmt.Errorf("%s: fileSpecToEntry used for goma input? %s %s", fs.Path, fs.HashKey, fs.Blob.GetBlobType())
}
if fs.Hash != "" && fs.Symlink != "" {
return merkletree.Entry{}, fmt.Errorf("%s: FileSpec has both `Hash` and `Symlink` fields", fs.Path)
}
if fs.Hash == "" {
if fs.Symlink != "" {
// Symlink
return merkletree.Entry{
Name: fs.Path,
Target: fs.Symlink,
}, nil
}
// dir
return merkletree.Entry{
Name: fs.Path,
}, nil
}
d := &rpb.Digest{
Hash: fs.Hash,
SizeBytes: fs.Size,
}
src := cmdFileObj{
storage: cmdStorage,
hash: fs.Hash,
}
return merkletree.Entry{
Name: fs.Path,
Data: digest.New(src, d),
IsExecutable: fs.IsExecutable,
}, nil
}
type cmdFileObj struct {
storage CmdStorage
hash string
}
func (o cmdFileObj) Open(ctx context.Context) (io.ReadCloser, error) {
r, err := o.storage.Open(ctx, o.hash)
return r, err
}
func (o cmdFileObj) String() string {
return fmt.Sprintf("cmd-file:%s", o.hash)
}