blob: 7f32722bd7d0c2ba5eb5833ddc2b6fe98c0c5134 [file] [log] [blame]
// Copyright (C) 2015 The Android Open Source Project
//
// 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 build
import (
"fmt"
"io"
"os"
"os/exec"
"path/filepath"
"android.googlesource.com/platform/tools/gpu/maker"
)
// File represents the path to a file or directory.
type File string
// Path returns a File formed from the joined path segments.
func Path(segments ...string) File {
return File(filepath.Join(segments...))
}
// Join returns a File formed from joining this File with ext.
func (f File) Join(ext ...string) File {
return File(filepath.Join(append([]string{string(f)}, ext...)...))
}
// RelativeTo returns the path of this File relative to base.
func (f File) RelativeTo(base File) string {
rel, err := filepath.Rel(string(base), string(f))
if err != nil {
panic(err)
}
return rel
}
// Absolute returns the absolute path of this File.
func (f File) Absolute() string {
abs, err := filepath.Abs(string(f))
if err != nil {
panic(fmt.Errorf("filepath.Abs(%s) returned error: %v", f, err))
}
return abs
}
// Exists returns true if this File exists.
func (f File) Exists() bool {
_, err := os.Stat(string(f.Absolute()))
return err == nil
}
// Contains returns true if this directory contains the file f.
func (d File) Contains(f File) bool {
a := d.Absolute()
b := f.Absolute()
if len(b) <= len(a)+1 {
return false
}
return b[:len(a)] == a && b[len(a)] == filepath.Separator
}
// Name returns the name part of the File (without directories).
func (f File) Name() string {
return filepath.Base(string(f))
}
// Dir returns the directory part of the File (without filename).
func (f File) Dir() string {
return filepath.Dir(string(f))
}
// Ext returns the extension of the file, including the '.', or an empty string
// if the file has no extension.
func (f File) Ext() string {
return filepath.Ext(string(f))
}
// ChangeExt returns a new File with the extension changed to ext.
func (f File) ChangeExt(ext string) File {
prev := filepath.Ext(string(f))
noext := f[:len(f)-len(prev)]
return noext + File(ext)
}
// Glob returns a FileSet of all files matching any of the specified patterns.
func (f File) Glob(patterns ...string) FileSet {
fs := FileSet{}
for _, patten := range patterns {
glob, err := filepath.Glob(string(f.Join(patten)))
if err != nil {
panic(err)
}
files := make(FileSet, len(glob))
for i := range glob {
files[i] = File(glob[i])
}
fs = fs.Append(files...)
}
return fs
}
// Matches returns true if the File matches any of the patterns.
func (f File) Matches(patterns ...string) bool {
abs := filepath.Base(f.Absolute())
for _, pattern := range patterns {
matched, err := filepath.Match(pattern, abs)
if err != nil {
panic(err)
}
if matched {
return true
}
}
return false
}
// MkdirAll creates the directory hierarchy to hold this File.
func (f File) MkdirAll() {
abs := f.Absolute()
dir, _ := filepath.Split(abs)
if len(dir) > 0 {
if err := os.MkdirAll(dir, os.ModePerm); err != nil {
panic(err)
}
}
}
// CopyTo copied this File to dst, replacing any existing file at dst.
func (f File) CopyTo(dst File) error {
s, err := os.Open(f.Absolute())
if err != nil {
return fmt.Errorf("Open copy source failed: %v", err)
}
defer s.Close()
fi, err := s.Stat()
if err != nil {
return fmt.Errorf("Stat copy source failed: %v", err)
}
d, err := os.OpenFile(dst.Absolute(), os.O_CREATE|os.O_TRUNC|os.O_WRONLY, fi.Mode())
if err != nil {
return fmt.Errorf("Create copy target failed: %v", err)
}
defer d.Close()
if _, err = io.Copy(d, s); err != nil {
return fmt.Errorf("Copy file data failed: %v", err)
}
return nil
}
// Exec executes this File with the specified arguments.
func (f File) Exec(env Environment, args ...string) error {
path, err := f.LookPath()
if err != nil {
return err
}
return f.ExecAt(env, File(path.Dir()), args...)
}
// ExecAt executes this File with the specified arguments with the working
// directory set to wd.
func (f File) ExecAt(env Environment, wd File, args ...string) error {
if !wd.Exists() {
return fmt.Errorf("The working directory '%s' does not exist", wd)
}
path, err := f.LookPath()
if err != nil {
return err
}
verbose := 0
if env.Verbose {
verbose = 1
}
return maker.ExecAt(wd.Absolute(), verbose, path.Absolute(), args...)
}
// LookPath returns the path to f, searching the system PATHs.
func (f File) LookPath() (File, error) {
if f.Exists() {
return f, nil
} else {
path, err := exec.LookPath(string(f))
return File(path), err
}
}