aboutsummaryrefslogtreecommitdiffstats
path: root/bootstrap/cleanup.go
diff options
context:
space:
mode:
authorColin Cross <ccross@google.com>2015-01-23 13:38:48 -0800
committerColin Cross <ccross@google.com>2015-01-23 14:23:27 -0800
commit3e8e74f276eafaf709e8e4c4291431a1d4ccb7e2 (patch)
tree2599d6ac3c3810a41a87a709a004fc1fab4a7b74 /bootstrap/cleanup.go
parent6bb4af9e208ea9769ae52933e8d9f42a4e75938e (diff)
downloadandroid_build_blueprint-3e8e74f276eafaf709e8e4c4291431a1d4ccb7e2.tar.gz
android_build_blueprint-3e8e74f276eafaf709e8e4c4291431a1d4ccb7e2.tar.bz2
android_build_blueprint-3e8e74f276eafaf709e8e4c4291431a1d4ccb7e2.zip
Move blueprint/* up a directory
Make integrating with go tools easier by putting the blueprint package files in the top level directory of the git project instead of in a subdirectory called blueprint. Change-Id: I35c144c5fe7ddf34e478d0c47c50b2f6c92c2a03
Diffstat (limited to 'bootstrap/cleanup.go')
-rw-r--r--bootstrap/cleanup.go141
1 files changed, 141 insertions, 0 deletions
diff --git a/bootstrap/cleanup.go b/bootstrap/cleanup.go
new file mode 100644
index 0000000..4a44b49
--- /dev/null
+++ b/bootstrap/cleanup.go
@@ -0,0 +1,141 @@
+package bootstrap
+
+import (
+ "blueprint"
+ "bufio"
+ "errors"
+ "fmt"
+ "os"
+ "path/filepath"
+ "strings"
+ "syscall"
+)
+
+const logFileName = ".ninja_log"
+
+// removeAbandonedFiles removes any files that appear in the Ninja log that are
+// not currently build targets.
+func removeAbandonedFiles(ctx *blueprint.Context, config interface{},
+ srcDir, manifestFile string) error {
+
+ buildDir := "."
+ if generatingBootstrapper(config) {
+ buildDir = bootstrapDir
+ }
+
+ targetRules, err := ctx.AllTargets()
+ if err != nil {
+ return fmt.Errorf("error determining target list: %s", err)
+ }
+
+ replacer := strings.NewReplacer(
+ "@@SrcDir@@", srcDir,
+ "@@BootstrapManifest@@", manifestFile)
+ targets := make(map[string]bool)
+ for target := range targetRules {
+ replacedTarget := replacer.Replace(target)
+ targets[replacedTarget] = true
+ }
+
+ filePaths, err := parseNinjaLog(buildDir)
+ if err != nil {
+ return err
+ }
+
+ for _, filePath := range filePaths {
+ isTarget := targets[filePath]
+ if !isTarget {
+ err = removeFileAndEmptyDirs(filePath)
+ if err != nil {
+ return err
+ }
+ }
+ }
+
+ return nil
+}
+
+func parseNinjaLog(buildDir string) ([]string, error) {
+ logFilePath := filepath.Join(buildDir, logFileName)
+ logFile, err := os.Open(logFilePath)
+ if err != nil {
+ if os.IsNotExist(err) {
+ return nil, nil
+ }
+ return nil, err
+ }
+ defer logFile.Close()
+
+ scanner := bufio.NewScanner(logFile)
+
+ // Check that the first line indicates that this is a Ninja log version 5
+ const expectedFirstLine = "# ninja log v5"
+ if !scanner.Scan() || scanner.Text() != expectedFirstLine {
+ return nil, errors.New("unrecognized ninja log format")
+ }
+
+ var filePaths []string
+ for scanner.Scan() {
+ line := scanner.Text()
+ if strings.HasPrefix(line, "#") {
+ continue
+ }
+
+ const fieldSeperator = "\t"
+ fields := strings.Split(line, fieldSeperator)
+
+ const precedingFields = 3
+ const followingFields = 1
+
+ if len(fields) < precedingFields+followingFields+1 {
+ return nil, fmt.Errorf("log entry has too few fields: %q", line)
+ }
+
+ start := precedingFields
+ end := len(fields) - followingFields
+ filePath := strings.Join(fields[start:end], fieldSeperator)
+
+ filePaths = append(filePaths, filePath)
+ }
+ if err := scanner.Err(); err != nil {
+ return nil, err
+ }
+
+ return filePaths, nil
+}
+
+func removeFileAndEmptyDirs(path string) error {
+ err := os.Remove(path)
+ if err != nil {
+ if os.IsNotExist(err) {
+ return nil
+ }
+ return err
+ }
+
+ path, err = filepath.Abs(path)
+ if err != nil {
+ return err
+ }
+
+ cwd, err := os.Getwd()
+ if err != nil {
+ return err
+ }
+
+ for dir := filepath.Dir(path); dir != cwd; dir = filepath.Dir(dir) {
+ err = os.Remove(dir)
+ if err != nil {
+ pathErr := err.(*os.PathError)
+ switch pathErr.Err {
+ case syscall.ENOTEMPTY, syscall.EEXIST:
+ // We've come to a nonempty directory, so we're done.
+ return nil
+ default:
+ return err
+ }
+ }
+ }
+
+ return nil
+}