1065dfacbf0c6e46c80f53d9207fac17afcb1fca7Josiah Gaskin/*
2065dfacbf0c6e46c80f53d9207fac17afcb1fca7Josiah Gaskin * Copyright (C) 2011 The Android Open Source Project
3065dfacbf0c6e46c80f53d9207fac17afcb1fca7Josiah Gaskin *
4065dfacbf0c6e46c80f53d9207fac17afcb1fca7Josiah Gaskin * Licensed under the Apache License, Version 2.0 (the "License");
5065dfacbf0c6e46c80f53d9207fac17afcb1fca7Josiah Gaskin * you may not use this file except in compliance with the License.
6065dfacbf0c6e46c80f53d9207fac17afcb1fca7Josiah Gaskin * You may obtain a copy of the License at
7065dfacbf0c6e46c80f53d9207fac17afcb1fca7Josiah Gaskin *
8065dfacbf0c6e46c80f53d9207fac17afcb1fca7Josiah Gaskin *      http://www.apache.org/licenses/LICENSE-2.0
9065dfacbf0c6e46c80f53d9207fac17afcb1fca7Josiah Gaskin *
10065dfacbf0c6e46c80f53d9207fac17afcb1fca7Josiah Gaskin * Unless required by applicable law or agreed to in writing, software
11065dfacbf0c6e46c80f53d9207fac17afcb1fca7Josiah Gaskin * distributed under the License is distributed on an "AS IS" BASIS,
12065dfacbf0c6e46c80f53d9207fac17afcb1fca7Josiah Gaskin * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13065dfacbf0c6e46c80f53d9207fac17afcb1fca7Josiah Gaskin * See the License for the specific language governing permissions and
14065dfacbf0c6e46c80f53d9207fac17afcb1fca7Josiah Gaskin * limitations under the License.
15065dfacbf0c6e46c80f53d9207fac17afcb1fca7Josiah Gaskin */
16065dfacbf0c6e46c80f53d9207fac17afcb1fca7Josiah Gaskin
17065dfacbf0c6e46c80f53d9207fac17afcb1fca7Josiah Gaskinpackage com.android.ant;
18065dfacbf0c6e46c80f53d9207fac17afcb1fca7Josiah Gaskin
19f92c116240bc645a89b12975dd438a46645abe88Xavier Ducrohetimport com.google.common.base.Charsets;
20f92c116240bc645a89b12975dd438a46645abe88Xavier Ducrohetimport com.google.common.io.Files;
21f92c116240bc645a89b12975dd438a46645abe88Xavier Ducrohet
22891cbf7552f98af2f0baaed069b5eb64de50c556Xavier Ducrohetimport org.apache.tools.ant.BuildException;
23891cbf7552f98af2f0baaed069b5eb64de50c556Xavier Ducrohet
24065dfacbf0c6e46c80f53d9207fac17afcb1fca7Josiah Gaskinimport java.io.File;
25065dfacbf0c6e46c80f53d9207fac17afcb1fca7Josiah Gaskinimport java.io.IOException;
26065dfacbf0c6e46c80f53d9207fac17afcb1fca7Josiah Gaskinimport java.util.Collections;
27891cbf7552f98af2f0baaed069b5eb64de50c556Xavier Ducrohetimport java.util.HashSet;
2850b3e57fa887dc7182facfb178ef842103aeeaf3Xavier Ducrohetimport java.util.List;
29065dfacbf0c6e46c80f53d9207fac17afcb1fca7Josiah Gaskinimport java.util.Set;
30065dfacbf0c6e46c80f53d9207fac17afcb1fca7Josiah Gaskin
31065dfacbf0c6e46c80f53d9207fac17afcb1fca7Josiah Gaskin/**
32065dfacbf0c6e46c80f53d9207fac17afcb1fca7Josiah Gaskin *  This class takes care of dependency tracking for all targets and prerequisites listed in
33065dfacbf0c6e46c80f53d9207fac17afcb1fca7Josiah Gaskin *  a single dependency file. A dependency graph always has a dependency file associated with it
34065dfacbf0c6e46c80f53d9207fac17afcb1fca7Josiah Gaskin *  for the duration of its lifetime
35065dfacbf0c6e46c80f53d9207fac17afcb1fca7Josiah Gaskin */
36065dfacbf0c6e46c80f53d9207fac17afcb1fca7Josiah Gaskinpublic class DependencyGraph {
37065dfacbf0c6e46c80f53d9207fac17afcb1fca7Josiah Gaskin
38e162064a7b5db1eecec34271bc7e2a4296181ea6Xavier Ducrohet    private final static boolean DEBUG = false;
39e162064a7b5db1eecec34271bc7e2a4296181ea6Xavier Ducrohet
40891cbf7552f98af2f0baaed069b5eb64de50c556Xavier Ducrohet    private static enum DependencyStatus {
41891cbf7552f98af2f0baaed069b5eb64de50c556Xavier Ducrohet        NONE, NEW_FILE, UPDATED_FILE, MISSING_FILE, ERROR;
42891cbf7552f98af2f0baaed069b5eb64de50c556Xavier Ducrohet    }
43891cbf7552f98af2f0baaed069b5eb64de50c556Xavier Ducrohet
44065dfacbf0c6e46c80f53d9207fac17afcb1fca7Josiah Gaskin    // Files that we know about from the dependency file
45891cbf7552f98af2f0baaed069b5eb64de50c556Xavier Ducrohet    private Set<File> mTargets = Collections.emptySet();
46891cbf7552f98af2f0baaed069b5eb64de50c556Xavier Ducrohet    private Set<File> mPrereqs = mTargets;
47891cbf7552f98af2f0baaed069b5eb64de50c556Xavier Ducrohet    private File mFirstPrereq = null;
4850b3e57fa887dc7182facfb178ef842103aeeaf3Xavier Ducrohet    private boolean mMissingDepFile = false;
4950b3e57fa887dc7182facfb178ef842103aeeaf3Xavier Ducrohet    private long mDepFileLastModified;
500fd7983848915b9424501afee8d8f0ea6f08f858Xavier Ducrohet    private final List<InputPath> mNewInputs;
510fd7983848915b9424501afee8d8f0ea6f08f858Xavier Ducrohet
520fd7983848915b9424501afee8d8f0ea6f08f858Xavier Ducrohet    public DependencyGraph(String dependencyFilePath, List<InputPath> newInputPaths) {
53891cbf7552f98af2f0baaed069b5eb64de50c556Xavier Ducrohet        mNewInputs = newInputPaths;
54065dfacbf0c6e46c80f53d9207fac17afcb1fca7Josiah Gaskin        parseDependencyFile(dependencyFilePath);
55065dfacbf0c6e46c80f53d9207fac17afcb1fca7Josiah Gaskin    }
56065dfacbf0c6e46c80f53d9207fac17afcb1fca7Josiah Gaskin
57065dfacbf0c6e46c80f53d9207fac17afcb1fca7Josiah Gaskin    /**
58065dfacbf0c6e46c80f53d9207fac17afcb1fca7Josiah Gaskin     * Check all the dependencies to see if anything has changed.
590fd7983848915b9424501afee8d8f0ea6f08f858Xavier Ducrohet     *
6050b3e57fa887dc7182facfb178ef842103aeeaf3Xavier Ducrohet     * @param printStatus will print to {@link System#out} the dependencies status.
61065dfacbf0c6e46c80f53d9207fac17afcb1fca7Josiah Gaskin     * @return true if new prerequisites have appeared, target files are missing or if
62065dfacbf0c6e46c80f53d9207fac17afcb1fca7Josiah Gaskin     *         prerequisite files have been modified since the last target generation.
63065dfacbf0c6e46c80f53d9207fac17afcb1fca7Josiah Gaskin     */
640fd7983848915b9424501afee8d8f0ea6f08f858Xavier Ducrohet    public boolean dependenciesHaveChanged(boolean printStatus) {
65891cbf7552f98af2f0baaed069b5eb64de50c556Xavier Ducrohet        // If no dependency file has been set up, then we'll just return true
66891cbf7552f98af2f0baaed069b5eb64de50c556Xavier Ducrohet        // if we have a dependency file, we'll check to see what's been changed
67891cbf7552f98af2f0baaed069b5eb64de50c556Xavier Ducrohet        if (mMissingDepFile) {
68891cbf7552f98af2f0baaed069b5eb64de50c556Xavier Ducrohet            System.out.println("No Dependency File Found");
69891cbf7552f98af2f0baaed069b5eb64de50c556Xavier Ducrohet            return true;
70891cbf7552f98af2f0baaed069b5eb64de50c556Xavier Ducrohet        }
71891cbf7552f98af2f0baaed069b5eb64de50c556Xavier Ducrohet
72891cbf7552f98af2f0baaed069b5eb64de50c556Xavier Ducrohet        // check for missing output first
73891cbf7552f98af2f0baaed069b5eb64de50c556Xavier Ducrohet        if (missingTargetFile()) {
74891cbf7552f98af2f0baaed069b5eb64de50c556Xavier Ducrohet            if (printStatus) {
7550b3e57fa887dc7182facfb178ef842103aeeaf3Xavier Ducrohet                System.out.println("Found Deleted Target File");
7650b3e57fa887dc7182facfb178ef842103aeeaf3Xavier Ducrohet            }
77891cbf7552f98af2f0baaed069b5eb64de50c556Xavier Ducrohet            return true;
78065dfacbf0c6e46c80f53d9207fac17afcb1fca7Josiah Gaskin        }
7950b3e57fa887dc7182facfb178ef842103aeeaf3Xavier Ducrohet
800fd7983848915b9424501afee8d8f0ea6f08f858Xavier Ducrohet        // get the time stamp of the oldest target.
81891cbf7552f98af2f0baaed069b5eb64de50c556Xavier Ducrohet        long oldestTarget = getOutputLastModified();
82891cbf7552f98af2f0baaed069b5eb64de50c556Xavier Ducrohet
83891cbf7552f98af2f0baaed069b5eb64de50c556Xavier Ducrohet        // first look through the input folders and look for new files or modified files.
840fd7983848915b9424501afee8d8f0ea6f08f858Xavier Ducrohet        DependencyStatus status = checkInputs(oldestTarget);
85891cbf7552f98af2f0baaed069b5eb64de50c556Xavier Ducrohet
86891cbf7552f98af2f0baaed069b5eb64de50c556Xavier Ducrohet        // this can't find missing files. This is done later.
87891cbf7552f98af2f0baaed069b5eb64de50c556Xavier Ducrohet        switch (status) {
88891cbf7552f98af2f0baaed069b5eb64de50c556Xavier Ducrohet            case ERROR:
89891cbf7552f98af2f0baaed069b5eb64de50c556Xavier Ducrohet                throw new BuildException();
90891cbf7552f98af2f0baaed069b5eb64de50c556Xavier Ducrohet            case NEW_FILE:
91891cbf7552f98af2f0baaed069b5eb64de50c556Xavier Ducrohet                if (printStatus) {
92891cbf7552f98af2f0baaed069b5eb64de50c556Xavier Ducrohet                    System.out.println("Found new input file");
93891cbf7552f98af2f0baaed069b5eb64de50c556Xavier Ducrohet                }
94891cbf7552f98af2f0baaed069b5eb64de50c556Xavier Ducrohet                return true;
95891cbf7552f98af2f0baaed069b5eb64de50c556Xavier Ducrohet            case UPDATED_FILE:
96891cbf7552f98af2f0baaed069b5eb64de50c556Xavier Ducrohet                if (printStatus) {
97891cbf7552f98af2f0baaed069b5eb64de50c556Xavier Ducrohet                    System.out.println("Found modified input file");
98891cbf7552f98af2f0baaed069b5eb64de50c556Xavier Ducrohet                }
99891cbf7552f98af2f0baaed069b5eb64de50c556Xavier Ducrohet                return true;
100891cbf7552f98af2f0baaed069b5eb64de50c556Xavier Ducrohet        }
101891cbf7552f98af2f0baaed069b5eb64de50c556Xavier Ducrohet
102891cbf7552f98af2f0baaed069b5eb64de50c556Xavier Ducrohet        // now do a full check on the remaining files.
1030fd7983848915b9424501afee8d8f0ea6f08f858Xavier Ducrohet        status = checkPrereqFiles(oldestTarget);
104891cbf7552f98af2f0baaed069b5eb64de50c556Xavier Ducrohet        // this can't find new input files. This is done above.
105891cbf7552f98af2f0baaed069b5eb64de50c556Xavier Ducrohet        switch (status) {
106891cbf7552f98af2f0baaed069b5eb64de50c556Xavier Ducrohet            case ERROR:
107891cbf7552f98af2f0baaed069b5eb64de50c556Xavier Ducrohet                throw new BuildException();
108891cbf7552f98af2f0baaed069b5eb64de50c556Xavier Ducrohet            case MISSING_FILE:
109891cbf7552f98af2f0baaed069b5eb64de50c556Xavier Ducrohet                if (printStatus) {
110891cbf7552f98af2f0baaed069b5eb64de50c556Xavier Ducrohet                    System.out.println("Found deleted input file");
111891cbf7552f98af2f0baaed069b5eb64de50c556Xavier Ducrohet                }
112891cbf7552f98af2f0baaed069b5eb64de50c556Xavier Ducrohet                return true;
113891cbf7552f98af2f0baaed069b5eb64de50c556Xavier Ducrohet            case UPDATED_FILE:
114891cbf7552f98af2f0baaed069b5eb64de50c556Xavier Ducrohet                if (printStatus) {
115891cbf7552f98af2f0baaed069b5eb64de50c556Xavier Ducrohet                    System.out.println("Found modified input file");
116891cbf7552f98af2f0baaed069b5eb64de50c556Xavier Ducrohet                }
117891cbf7552f98af2f0baaed069b5eb64de50c556Xavier Ducrohet                return true;
118891cbf7552f98af2f0baaed069b5eb64de50c556Xavier Ducrohet        }
119891cbf7552f98af2f0baaed069b5eb64de50c556Xavier Ducrohet
120891cbf7552f98af2f0baaed069b5eb64de50c556Xavier Ducrohet        return false;
12150b3e57fa887dc7182facfb178ef842103aeeaf3Xavier Ducrohet    }
12250b3e57fa887dc7182facfb178ef842103aeeaf3Xavier Ducrohet
123891cbf7552f98af2f0baaed069b5eb64de50c556Xavier Ducrohet    public Set<File> getTargets() {
124891cbf7552f98af2f0baaed069b5eb64de50c556Xavier Ducrohet        return Collections.unmodifiableSet(mTargets);
12550b3e57fa887dc7182facfb178ef842103aeeaf3Xavier Ducrohet    }
12650b3e57fa887dc7182facfb178ef842103aeeaf3Xavier Ducrohet
127891cbf7552f98af2f0baaed069b5eb64de50c556Xavier Ducrohet    public File getFirstPrereq() {
128891cbf7552f98af2f0baaed069b5eb64de50c556Xavier Ducrohet        return mFirstPrereq;
129065dfacbf0c6e46c80f53d9207fac17afcb1fca7Josiah Gaskin    }
130065dfacbf0c6e46c80f53d9207fac17afcb1fca7Josiah Gaskin
131065dfacbf0c6e46c80f53d9207fac17afcb1fca7Josiah Gaskin    /**
132065dfacbf0c6e46c80f53d9207fac17afcb1fca7Josiah Gaskin     * Parses the given dependency file and stores the file paths
133065dfacbf0c6e46c80f53d9207fac17afcb1fca7Josiah Gaskin     *
134065dfacbf0c6e46c80f53d9207fac17afcb1fca7Josiah Gaskin     * @param dependencyFilePath the dependency file
135065dfacbf0c6e46c80f53d9207fac17afcb1fca7Josiah Gaskin     */
136065dfacbf0c6e46c80f53d9207fac17afcb1fca7Josiah Gaskin    private void parseDependencyFile(String dependencyFilePath) {
13750b3e57fa887dc7182facfb178ef842103aeeaf3Xavier Ducrohet        // first check if the dependency file is here.
13850b3e57fa887dc7182facfb178ef842103aeeaf3Xavier Ducrohet        File depFile = new File(dependencyFilePath);
13950b3e57fa887dc7182facfb178ef842103aeeaf3Xavier Ducrohet        if (depFile.isFile() == false) {
14050b3e57fa887dc7182facfb178ef842103aeeaf3Xavier Ducrohet            mMissingDepFile = true;
14150b3e57fa887dc7182facfb178ef842103aeeaf3Xavier Ducrohet            return;
14250b3e57fa887dc7182facfb178ef842103aeeaf3Xavier Ducrohet        }
14350b3e57fa887dc7182facfb178ef842103aeeaf3Xavier Ducrohet
14450b3e57fa887dc7182facfb178ef842103aeeaf3Xavier Ducrohet        // get the modification time of the dep file as we may need it later
14550b3e57fa887dc7182facfb178ef842103aeeaf3Xavier Ducrohet        mDepFileLastModified = depFile.lastModified();
14650b3e57fa887dc7182facfb178ef842103aeeaf3Xavier Ducrohet
147065dfacbf0c6e46c80f53d9207fac17afcb1fca7Josiah Gaskin        // Read in our dependency file
148f92c116240bc645a89b12975dd438a46645abe88Xavier Ducrohet        List<String> content = readFile(depFile);
149065dfacbf0c6e46c80f53d9207fac17afcb1fca7Josiah Gaskin        if (content == null) {
150065dfacbf0c6e46c80f53d9207fac17afcb1fca7Josiah Gaskin            System.err.println("ERROR: Couldn't read " + dependencyFilePath);
151065dfacbf0c6e46c80f53d9207fac17afcb1fca7Josiah Gaskin            return;
152065dfacbf0c6e46c80f53d9207fac17afcb1fca7Josiah Gaskin        }
153065dfacbf0c6e46c80f53d9207fac17afcb1fca7Josiah Gaskin
154065dfacbf0c6e46c80f53d9207fac17afcb1fca7Josiah Gaskin        // The format is something like:
155065dfacbf0c6e46c80f53d9207fac17afcb1fca7Josiah Gaskin        // output1 output2 [...]: dep1 dep2 [...]
156065dfacbf0c6e46c80f53d9207fac17afcb1fca7Josiah Gaskin        // expect it's likely split on several lines. So let's move it back on a single line
157065dfacbf0c6e46c80f53d9207fac17afcb1fca7Josiah Gaskin        // first
158f92c116240bc645a89b12975dd438a46645abe88Xavier Ducrohet        StringBuilder sb = new StringBuilder();
159f92c116240bc645a89b12975dd438a46645abe88Xavier Ducrohet        for (String line : content) {
160065dfacbf0c6e46c80f53d9207fac17afcb1fca7Josiah Gaskin            line = line.trim();
161065dfacbf0c6e46c80f53d9207fac17afcb1fca7Josiah Gaskin            if (line.endsWith("\\")) {
162065dfacbf0c6e46c80f53d9207fac17afcb1fca7Josiah Gaskin                line = line.substring(0, line.length() - 1);
163065dfacbf0c6e46c80f53d9207fac17afcb1fca7Josiah Gaskin            }
164065dfacbf0c6e46c80f53d9207fac17afcb1fca7Josiah Gaskin            sb.append(line);
165065dfacbf0c6e46c80f53d9207fac17afcb1fca7Josiah Gaskin        }
166065dfacbf0c6e46c80f53d9207fac17afcb1fca7Josiah Gaskin
167065dfacbf0c6e46c80f53d9207fac17afcb1fca7Josiah Gaskin        // split the left and right part
168065dfacbf0c6e46c80f53d9207fac17afcb1fca7Josiah Gaskin        String[] files = sb.toString().split(":");
169065dfacbf0c6e46c80f53d9207fac17afcb1fca7Josiah Gaskin
170065dfacbf0c6e46c80f53d9207fac17afcb1fca7Josiah Gaskin        // get the target files:
171065dfacbf0c6e46c80f53d9207fac17afcb1fca7Josiah Gaskin        String[] targets = files[0].trim().split(" ");
172065dfacbf0c6e46c80f53d9207fac17afcb1fca7Josiah Gaskin
173065dfacbf0c6e46c80f53d9207fac17afcb1fca7Josiah Gaskin        String[] prereqs = {};
174065dfacbf0c6e46c80f53d9207fac17afcb1fca7Josiah Gaskin        // Check to make sure our dependency file is okay
175065dfacbf0c6e46c80f53d9207fac17afcb1fca7Josiah Gaskin        if (files.length < 1) {
176065dfacbf0c6e46c80f53d9207fac17afcb1fca7Josiah Gaskin            System.err.println(
177065dfacbf0c6e46c80f53d9207fac17afcb1fca7Josiah Gaskin                    "Warning! Dependency file does not list any prerequisites after ':' ");
178065dfacbf0c6e46c80f53d9207fac17afcb1fca7Josiah Gaskin        } else {
179065dfacbf0c6e46c80f53d9207fac17afcb1fca7Josiah Gaskin            // and the prerequisite files:
180065dfacbf0c6e46c80f53d9207fac17afcb1fca7Josiah Gaskin            prereqs = files[1].trim().split(" ");
181065dfacbf0c6e46c80f53d9207fac17afcb1fca7Josiah Gaskin        }
182065dfacbf0c6e46c80f53d9207fac17afcb1fca7Josiah Gaskin
183891cbf7552f98af2f0baaed069b5eb64de50c556Xavier Ducrohet        mTargets = new HashSet<File>(targets.length);
184065dfacbf0c6e46c80f53d9207fac17afcb1fca7Josiah Gaskin        for (String path : targets) {
18550b3e57fa887dc7182facfb178ef842103aeeaf3Xavier Ducrohet            if (path.length() > 0) {
18650b3e57fa887dc7182facfb178ef842103aeeaf3Xavier Ducrohet                mTargets.add(new File(path));
18750b3e57fa887dc7182facfb178ef842103aeeaf3Xavier Ducrohet            }
188065dfacbf0c6e46c80f53d9207fac17afcb1fca7Josiah Gaskin        }
189891cbf7552f98af2f0baaed069b5eb64de50c556Xavier Ducrohet
190891cbf7552f98af2f0baaed069b5eb64de50c556Xavier Ducrohet        mPrereqs = new HashSet<File>(prereqs.length);
191065dfacbf0c6e46c80f53d9207fac17afcb1fca7Josiah Gaskin        for (String path : prereqs) {
19250b3e57fa887dc7182facfb178ef842103aeeaf3Xavier Ducrohet            if (path.length() > 0) {
193e162064a7b5db1eecec34271bc7e2a4296181ea6Xavier Ducrohet                if (DEBUG) {
194e162064a7b5db1eecec34271bc7e2a4296181ea6Xavier Ducrohet                    System.out.println("PREREQ: " + path);
195e162064a7b5db1eecec34271bc7e2a4296181ea6Xavier Ducrohet                }
196891cbf7552f98af2f0baaed069b5eb64de50c556Xavier Ducrohet                File f = new File(path);
197891cbf7552f98af2f0baaed069b5eb64de50c556Xavier Ducrohet                if (mFirstPrereq == null) {
198891cbf7552f98af2f0baaed069b5eb64de50c556Xavier Ducrohet                    mFirstPrereq = f;
199891cbf7552f98af2f0baaed069b5eb64de50c556Xavier Ducrohet                }
200891cbf7552f98af2f0baaed069b5eb64de50c556Xavier Ducrohet                mPrereqs.add(f);
20150b3e57fa887dc7182facfb178ef842103aeeaf3Xavier Ducrohet            }
202065dfacbf0c6e46c80f53d9207fac17afcb1fca7Josiah Gaskin        }
203065dfacbf0c6e46c80f53d9207fac17afcb1fca7Josiah Gaskin    }
204065dfacbf0c6e46c80f53d9207fac17afcb1fca7Josiah Gaskin
205065dfacbf0c6e46c80f53d9207fac17afcb1fca7Josiah Gaskin    /**
206891cbf7552f98af2f0baaed069b5eb64de50c556Xavier Ducrohet     * Check all the input files and folders to see if there have been new
207891cbf7552f98af2f0baaed069b5eb64de50c556Xavier Ducrohet     * files added to them or if any of the existing files have been modified.
208891cbf7552f98af2f0baaed069b5eb64de50c556Xavier Ducrohet     *
209891cbf7552f98af2f0baaed069b5eb64de50c556Xavier Ducrohet     * This looks at the input paths, not at the list of known prereq. Therefore this
210891cbf7552f98af2f0baaed069b5eb64de50c556Xavier Ducrohet     * will not find missing files. It will however remove processed files from the
211891cbf7552f98af2f0baaed069b5eb64de50c556Xavier Ducrohet     * prereq file list so that we can process those in a 2nd step.
212891cbf7552f98af2f0baaed069b5eb64de50c556Xavier Ducrohet     *
213891cbf7552f98af2f0baaed069b5eb64de50c556Xavier Ducrohet     * This should be followed by a call to {@link #checkPrereqFiles(long)} which
214891cbf7552f98af2f0baaed069b5eb64de50c556Xavier Ducrohet     * will process the remaining files in the prereq list.
215891cbf7552f98af2f0baaed069b5eb64de50c556Xavier Ducrohet     *
216a9a28238f7b20d7c0a05c95afad02fcdb34e0d0eXavier Ducrohet     * If a change is found, this will return immediately with either
217891cbf7552f98af2f0baaed069b5eb64de50c556Xavier Ducrohet     * {@link DependencyStatus#NEW_FILE} or {@link DependencyStatus#UPDATED_FILE}.
218891cbf7552f98af2f0baaed069b5eb64de50c556Xavier Ducrohet     *
219891cbf7552f98af2f0baaed069b5eb64de50c556Xavier Ducrohet     * @param oldestTarget the timestamp of the oldest output file to compare against.
220891cbf7552f98af2f0baaed069b5eb64de50c556Xavier Ducrohet     *
221891cbf7552f98af2f0baaed069b5eb64de50c556Xavier Ducrohet     * @return the status of the file in the watched folders.
222891cbf7552f98af2f0baaed069b5eb64de50c556Xavier Ducrohet     *
223065dfacbf0c6e46c80f53d9207fac17afcb1fca7Josiah Gaskin     */
2240fd7983848915b9424501afee8d8f0ea6f08f858Xavier Ducrohet    private DependencyStatus checkInputs(long oldestTarget) {
225891cbf7552f98af2f0baaed069b5eb64de50c556Xavier Ducrohet        if (mNewInputs != null) {
2260fd7983848915b9424501afee8d8f0ea6f08f858Xavier Ducrohet            for (InputPath input : mNewInputs) {
227a9a28238f7b20d7c0a05c95afad02fcdb34e0d0eXavier Ducrohet                File file = input.getFile();
228a9a28238f7b20d7c0a05c95afad02fcdb34e0d0eXavier Ducrohet                if (file.isDirectory()) {
229a9a28238f7b20d7c0a05c95afad02fcdb34e0d0eXavier Ducrohet                    DependencyStatus status = checkInputFolder(file, input, oldestTarget);
230891cbf7552f98af2f0baaed069b5eb64de50c556Xavier Ducrohet                    if (status != DependencyStatus.NONE) {
231891cbf7552f98af2f0baaed069b5eb64de50c556Xavier Ducrohet                        return status;
232891cbf7552f98af2f0baaed069b5eb64de50c556Xavier Ducrohet                    }
233a9a28238f7b20d7c0a05c95afad02fcdb34e0d0eXavier Ducrohet                } else if (file.isFile()) {
234a9a28238f7b20d7c0a05c95afad02fcdb34e0d0eXavier Ducrohet                    DependencyStatus status = checkInputFile(file, input, oldestTarget);
235891cbf7552f98af2f0baaed069b5eb64de50c556Xavier Ducrohet                    if (status != DependencyStatus.NONE) {
236891cbf7552f98af2f0baaed069b5eb64de50c556Xavier Ducrohet                        return status;
237891cbf7552f98af2f0baaed069b5eb64de50c556Xavier Ducrohet                    }
23850b3e57fa887dc7182facfb178ef842103aeeaf3Xavier Ducrohet                }
239065dfacbf0c6e46c80f53d9207fac17afcb1fca7Josiah Gaskin            }
240065dfacbf0c6e46c80f53d9207fac17afcb1fca7Josiah Gaskin        }
241891cbf7552f98af2f0baaed069b5eb64de50c556Xavier Ducrohet
242065dfacbf0c6e46c80f53d9207fac17afcb1fca7Josiah Gaskin        // If we make it all the way through our directories we're good.
243891cbf7552f98af2f0baaed069b5eb64de50c556Xavier Ducrohet        return DependencyStatus.NONE;
244065dfacbf0c6e46c80f53d9207fac17afcb1fca7Josiah Gaskin    }
245065dfacbf0c6e46c80f53d9207fac17afcb1fca7Josiah Gaskin
246065dfacbf0c6e46c80f53d9207fac17afcb1fca7Josiah Gaskin    /**
247065dfacbf0c6e46c80f53d9207fac17afcb1fca7Josiah Gaskin     * Check all the files in the tree under root and check to see if the files are
248891cbf7552f98af2f0baaed069b5eb64de50c556Xavier Ducrohet     * listed under the dependencies, or if they have been modified. Recurses into subdirs.
249891cbf7552f98af2f0baaed069b5eb64de50c556Xavier Ducrohet     *
250a9a28238f7b20d7c0a05c95afad02fcdb34e0d0eXavier Ducrohet     * @param folder the folder to search through.
251a9a28238f7b20d7c0a05c95afad02fcdb34e0d0eXavier Ducrohet     * @param inputFolder the root level inputFolder
2520fd7983848915b9424501afee8d8f0ea6f08f858Xavier Ducrohet     * @param oldestTarget the time stamp of the oldest output file to compare against.
253891cbf7552f98af2f0baaed069b5eb64de50c556Xavier Ducrohet     *
254891cbf7552f98af2f0baaed069b5eb64de50c556Xavier Ducrohet     * @return the status of the file in the folder.
255065dfacbf0c6e46c80f53d9207fac17afcb1fca7Josiah Gaskin     */
256a9a28238f7b20d7c0a05c95afad02fcdb34e0d0eXavier Ducrohet    private DependencyStatus checkInputFolder(File folder, InputPath inputFolder,
257891cbf7552f98af2f0baaed069b5eb64de50c556Xavier Ducrohet            long oldestTarget) {
258a9a28238f7b20d7c0a05c95afad02fcdb34e0d0eXavier Ducrohet        if (inputFolder.ignores(folder)) {
259a9a28238f7b20d7c0a05c95afad02fcdb34e0d0eXavier Ducrohet            return DependencyStatus.NONE;
260a9a28238f7b20d7c0a05c95afad02fcdb34e0d0eXavier Ducrohet        }
261a9a28238f7b20d7c0a05c95afad02fcdb34e0d0eXavier Ducrohet
262a9a28238f7b20d7c0a05c95afad02fcdb34e0d0eXavier Ducrohet        File[] files = folder.listFiles();
263065dfacbf0c6e46c80f53d9207fac17afcb1fca7Josiah Gaskin        if (files == null) {
264a9a28238f7b20d7c0a05c95afad02fcdb34e0d0eXavier Ducrohet            System.err.println("ERROR " + folder.toString() + " is not a dir or can't be read");
265891cbf7552f98af2f0baaed069b5eb64de50c556Xavier Ducrohet            return DependencyStatus.ERROR;
266065dfacbf0c6e46c80f53d9207fac17afcb1fca7Josiah Gaskin        }
267065dfacbf0c6e46c80f53d9207fac17afcb1fca7Josiah Gaskin        // Loop through files in this folder
268065dfacbf0c6e46c80f53d9207fac17afcb1fca7Josiah Gaskin        for (File file : files) {
269065dfacbf0c6e46c80f53d9207fac17afcb1fca7Josiah Gaskin            // If this is a directory, recurse into it
270065dfacbf0c6e46c80f53d9207fac17afcb1fca7Josiah Gaskin            if (file.isDirectory()) {
271a9a28238f7b20d7c0a05c95afad02fcdb34e0d0eXavier Ducrohet                DependencyStatus status = checkInputFolder(file, inputFolder, oldestTarget);
272891cbf7552f98af2f0baaed069b5eb64de50c556Xavier Ducrohet                if (status != DependencyStatus.NONE) {
273891cbf7552f98af2f0baaed069b5eb64de50c556Xavier Ducrohet                    return status;
274891cbf7552f98af2f0baaed069b5eb64de50c556Xavier Ducrohet                }
275891cbf7552f98af2f0baaed069b5eb64de50c556Xavier Ducrohet            } else if (file.isFile()) {
276a9a28238f7b20d7c0a05c95afad02fcdb34e0d0eXavier Ducrohet                DependencyStatus status = checkInputFile(file, inputFolder, oldestTarget);
277891cbf7552f98af2f0baaed069b5eb64de50c556Xavier Ducrohet                if (status != DependencyStatus.NONE) {
278891cbf7552f98af2f0baaed069b5eb64de50c556Xavier Ducrohet                    return status;
279065dfacbf0c6e46c80f53d9207fac17afcb1fca7Josiah Gaskin                }
280065dfacbf0c6e46c80f53d9207fac17afcb1fca7Josiah Gaskin            }
281065dfacbf0c6e46c80f53d9207fac17afcb1fca7Josiah Gaskin        }
282065dfacbf0c6e46c80f53d9207fac17afcb1fca7Josiah Gaskin        // If we got to here then we didn't find anything interesting
283891cbf7552f98af2f0baaed069b5eb64de50c556Xavier Ducrohet        return DependencyStatus.NONE;
284891cbf7552f98af2f0baaed069b5eb64de50c556Xavier Ducrohet    }
285891cbf7552f98af2f0baaed069b5eb64de50c556Xavier Ducrohet
286a9a28238f7b20d7c0a05c95afad02fcdb34e0d0eXavier Ducrohet    private DependencyStatus checkInputFile(File file, InputPath inputFolder,
287891cbf7552f98af2f0baaed069b5eb64de50c556Xavier Ducrohet            long oldestTarget) {
288a9a28238f7b20d7c0a05c95afad02fcdb34e0d0eXavier Ducrohet        if (inputFolder.ignores(file)) {
289a9a28238f7b20d7c0a05c95afad02fcdb34e0d0eXavier Ducrohet            return DependencyStatus.NONE;
290a9a28238f7b20d7c0a05c95afad02fcdb34e0d0eXavier Ducrohet        }
291a9a28238f7b20d7c0a05c95afad02fcdb34e0d0eXavier Ducrohet
292891cbf7552f98af2f0baaed069b5eb64de50c556Xavier Ducrohet        // if it's a file, remove it from the list of prereqs.
293891cbf7552f98af2f0baaed069b5eb64de50c556Xavier Ducrohet        // This way if files in this folder don't trigger a build we'll have less
294891cbf7552f98af2f0baaed069b5eb64de50c556Xavier Ducrohet        // files to go through manually
295891cbf7552f98af2f0baaed069b5eb64de50c556Xavier Ducrohet        if (mPrereqs.remove(file) == false) {
296891cbf7552f98af2f0baaed069b5eb64de50c556Xavier Ducrohet            // turns out this is a new file!
297e162064a7b5db1eecec34271bc7e2a4296181ea6Xavier Ducrohet
298e162064a7b5db1eecec34271bc7e2a4296181ea6Xavier Ducrohet            if (DEBUG) {
299e162064a7b5db1eecec34271bc7e2a4296181ea6Xavier Ducrohet                System.out.println("NEW FILE: " + file.getAbsolutePath());
300e162064a7b5db1eecec34271bc7e2a4296181ea6Xavier Ducrohet            }
301891cbf7552f98af2f0baaed069b5eb64de50c556Xavier Ducrohet            return DependencyStatus.NEW_FILE;
302891cbf7552f98af2f0baaed069b5eb64de50c556Xavier Ducrohet        } else {
303a9a28238f7b20d7c0a05c95afad02fcdb34e0d0eXavier Ducrohet            // check the time stamp on this file if it's a file we care about based what the
304a9a28238f7b20d7c0a05c95afad02fcdb34e0d0eXavier Ducrohet            // input folder decides.
305a9a28238f7b20d7c0a05c95afad02fcdb34e0d0eXavier Ducrohet            if (inputFolder.checksForModification(file)) {
306891cbf7552f98af2f0baaed069b5eb64de50c556Xavier Ducrohet                if (file.lastModified() > oldestTarget) {
307e162064a7b5db1eecec34271bc7e2a4296181ea6Xavier Ducrohet                    if (DEBUG) {
308e162064a7b5db1eecec34271bc7e2a4296181ea6Xavier Ducrohet                        System.out.println("UPDATED FILE: " + file.getAbsolutePath());
309e162064a7b5db1eecec34271bc7e2a4296181ea6Xavier Ducrohet                    }
310891cbf7552f98af2f0baaed069b5eb64de50c556Xavier Ducrohet                    return DependencyStatus.UPDATED_FILE;
311891cbf7552f98af2f0baaed069b5eb64de50c556Xavier Ducrohet                }
312891cbf7552f98af2f0baaed069b5eb64de50c556Xavier Ducrohet            }
313891cbf7552f98af2f0baaed069b5eb64de50c556Xavier Ducrohet        }
314891cbf7552f98af2f0baaed069b5eb64de50c556Xavier Ducrohet
315891cbf7552f98af2f0baaed069b5eb64de50c556Xavier Ducrohet        return DependencyStatus.NONE;
316065dfacbf0c6e46c80f53d9207fac17afcb1fca7Josiah Gaskin    }
317065dfacbf0c6e46c80f53d9207fac17afcb1fca7Josiah Gaskin
318065dfacbf0c6e46c80f53d9207fac17afcb1fca7Josiah Gaskin    /**
319891cbf7552f98af2f0baaed069b5eb64de50c556Xavier Ducrohet     * Check all the prereq files we know about to make sure they're still there, or that they
320891cbf7552f98af2f0baaed069b5eb64de50c556Xavier Ducrohet     * haven't been modified since the last build.
321891cbf7552f98af2f0baaed069b5eb64de50c556Xavier Ducrohet     *
3220fd7983848915b9424501afee8d8f0ea6f08f858Xavier Ducrohet     * @param oldestTarget the time stamp of the oldest output file to compare against.
323891cbf7552f98af2f0baaed069b5eb64de50c556Xavier Ducrohet     *
324891cbf7552f98af2f0baaed069b5eb64de50c556Xavier Ducrohet     * @return the status of the files
325065dfacbf0c6e46c80f53d9207fac17afcb1fca7Josiah Gaskin     */
3260fd7983848915b9424501afee8d8f0ea6f08f858Xavier Ducrohet    private DependencyStatus checkPrereqFiles(long oldestTarget) {
327a9a28238f7b20d7c0a05c95afad02fcdb34e0d0eXavier Ducrohet        // TODO: Optimize for the case of a specific file as inputPath.
328a9a28238f7b20d7c0a05c95afad02fcdb34e0d0eXavier Ducrohet        //       We should have a map of filepath to inputpath to quickly search through them?
329a9a28238f7b20d7c0a05c95afad02fcdb34e0d0eXavier Ducrohet
330065dfacbf0c6e46c80f53d9207fac17afcb1fca7Josiah Gaskin        // Loop through our prereq files and make sure they still exist
331065dfacbf0c6e46c80f53d9207fac17afcb1fca7Josiah Gaskin        for (File prereq : mPrereqs) {
332065dfacbf0c6e46c80f53d9207fac17afcb1fca7Josiah Gaskin            if (prereq.exists() == false) {
333e162064a7b5db1eecec34271bc7e2a4296181ea6Xavier Ducrohet                if (DEBUG) {
334e162064a7b5db1eecec34271bc7e2a4296181ea6Xavier Ducrohet                    System.out.println("MISSING FILE: " + prereq.getAbsolutePath());
335e162064a7b5db1eecec34271bc7e2a4296181ea6Xavier Ducrohet                }
336891cbf7552f98af2f0baaed069b5eb64de50c556Xavier Ducrohet                return DependencyStatus.MISSING_FILE;
337891cbf7552f98af2f0baaed069b5eb64de50c556Xavier Ducrohet            }
338891cbf7552f98af2f0baaed069b5eb64de50c556Xavier Ducrohet
339a9a28238f7b20d7c0a05c95afad02fcdb34e0d0eXavier Ducrohet            // check the time stamp on this file if it's a file we care about.
340a9a28238f7b20d7c0a05c95afad02fcdb34e0d0eXavier Ducrohet            // To know if we care about the file we have to find the matching input.
3410fd7983848915b9424501afee8d8f0ea6f08f858Xavier Ducrohet            if (mNewInputs != null) {
3420fd7983848915b9424501afee8d8f0ea6f08f858Xavier Ducrohet                String filePath = prereq.getAbsolutePath();
3430fd7983848915b9424501afee8d8f0ea6f08f858Xavier Ducrohet                for (InputPath input : mNewInputs) {
344a9a28238f7b20d7c0a05c95afad02fcdb34e0d0eXavier Ducrohet                    File inputFile = input.getFile();
345a9a28238f7b20d7c0a05c95afad02fcdb34e0d0eXavier Ducrohet                    // if the input path is a directory, check if the prereq file is in it,
346a9a28238f7b20d7c0a05c95afad02fcdb34e0d0eXavier Ducrohet                    // otherwise check if the prereq file match exactly the input path.
347a9a28238f7b20d7c0a05c95afad02fcdb34e0d0eXavier Ducrohet                    if (inputFile.isDirectory()) {
348a9a28238f7b20d7c0a05c95afad02fcdb34e0d0eXavier Ducrohet                        if (filePath.startsWith(inputFile.getAbsolutePath())) {
349a9a28238f7b20d7c0a05c95afad02fcdb34e0d0eXavier Ducrohet                            // ok file is inside a directory type input folder.
350a9a28238f7b20d7c0a05c95afad02fcdb34e0d0eXavier Ducrohet                            // check if we need to check this type of file, and if yes, check it.
351a9a28238f7b20d7c0a05c95afad02fcdb34e0d0eXavier Ducrohet                            if (input.checksForModification(prereq)) {
352a9a28238f7b20d7c0a05c95afad02fcdb34e0d0eXavier Ducrohet                                if (prereq.lastModified() > oldestTarget) {
353e162064a7b5db1eecec34271bc7e2a4296181ea6Xavier Ducrohet                                    if (DEBUG) {
354e162064a7b5db1eecec34271bc7e2a4296181ea6Xavier Ducrohet                                        System.out.println(
355e162064a7b5db1eecec34271bc7e2a4296181ea6Xavier Ducrohet                                                "UPDATED FILE: " + prereq.getAbsolutePath());
356e162064a7b5db1eecec34271bc7e2a4296181ea6Xavier Ducrohet                                    }
357a9a28238f7b20d7c0a05c95afad02fcdb34e0d0eXavier Ducrohet                                    return DependencyStatus.UPDATED_FILE;
358a9a28238f7b20d7c0a05c95afad02fcdb34e0d0eXavier Ducrohet                                }
359a9a28238f7b20d7c0a05c95afad02fcdb34e0d0eXavier Ducrohet                            }
360a9a28238f7b20d7c0a05c95afad02fcdb34e0d0eXavier Ducrohet                        }
361a9a28238f7b20d7c0a05c95afad02fcdb34e0d0eXavier Ducrohet                    } else {
362a9a28238f7b20d7c0a05c95afad02fcdb34e0d0eXavier Ducrohet                        // this is a file input path, we must check if the match is exact.
363a9a28238f7b20d7c0a05c95afad02fcdb34e0d0eXavier Ducrohet                        if (prereq.equals(inputFile)) {
364a9a28238f7b20d7c0a05c95afad02fcdb34e0d0eXavier Ducrohet                            if (input.checksForModification(prereq)) {
365a9a28238f7b20d7c0a05c95afad02fcdb34e0d0eXavier Ducrohet                                if (prereq.lastModified() > oldestTarget) {
366e162064a7b5db1eecec34271bc7e2a4296181ea6Xavier Ducrohet                                    if (DEBUG) {
367e162064a7b5db1eecec34271bc7e2a4296181ea6Xavier Ducrohet                                        System.out.println(
368e162064a7b5db1eecec34271bc7e2a4296181ea6Xavier Ducrohet                                                "UPDATED FILE: " + prereq.getAbsolutePath());
369e162064a7b5db1eecec34271bc7e2a4296181ea6Xavier Ducrohet                                    }
370a9a28238f7b20d7c0a05c95afad02fcdb34e0d0eXavier Ducrohet                                    return DependencyStatus.UPDATED_FILE;
371a9a28238f7b20d7c0a05c95afad02fcdb34e0d0eXavier Ducrohet                                }
372a9a28238f7b20d7c0a05c95afad02fcdb34e0d0eXavier Ducrohet                            }
373a9a28238f7b20d7c0a05c95afad02fcdb34e0d0eXavier Ducrohet                        }
3740fd7983848915b9424501afee8d8f0ea6f08f858Xavier Ducrohet                    }
3750fd7983848915b9424501afee8d8f0ea6f08f858Xavier Ducrohet                }
3762c8cced2d84e8e93214a976be7afd6f5913fc74fXavier Ducrohet            } else {
3772c8cced2d84e8e93214a976be7afd6f5913fc74fXavier Ducrohet                // no input? we consider all files.
3782c8cced2d84e8e93214a976be7afd6f5913fc74fXavier Ducrohet                if (prereq.lastModified() > oldestTarget) {
379e162064a7b5db1eecec34271bc7e2a4296181ea6Xavier Ducrohet                    if (DEBUG) {
380e162064a7b5db1eecec34271bc7e2a4296181ea6Xavier Ducrohet                        System.out.println("UPDATED FILE: " + prereq.getAbsolutePath());
381e162064a7b5db1eecec34271bc7e2a4296181ea6Xavier Ducrohet                    }
3822c8cced2d84e8e93214a976be7afd6f5913fc74fXavier Ducrohet                    return DependencyStatus.UPDATED_FILE;
3832c8cced2d84e8e93214a976be7afd6f5913fc74fXavier Ducrohet                }
3840fd7983848915b9424501afee8d8f0ea6f08f858Xavier Ducrohet            }
385065dfacbf0c6e46c80f53d9207fac17afcb1fca7Josiah Gaskin        }
386891cbf7552f98af2f0baaed069b5eb64de50c556Xavier Ducrohet
387891cbf7552f98af2f0baaed069b5eb64de50c556Xavier Ducrohet        // If we get this far, then all our prereq are okay
388891cbf7552f98af2f0baaed069b5eb64de50c556Xavier Ducrohet        return DependencyStatus.NONE;
389065dfacbf0c6e46c80f53d9207fac17afcb1fca7Josiah Gaskin    }
390065dfacbf0c6e46c80f53d9207fac17afcb1fca7Josiah Gaskin
391065dfacbf0c6e46c80f53d9207fac17afcb1fca7Josiah Gaskin    /**
392065dfacbf0c6e46c80f53d9207fac17afcb1fca7Josiah Gaskin     * Check all the target files we know about to make sure they're still there
393065dfacbf0c6e46c80f53d9207fac17afcb1fca7Josiah Gaskin     * @return true if any of the target files are missing.
394065dfacbf0c6e46c80f53d9207fac17afcb1fca7Josiah Gaskin     */
395065dfacbf0c6e46c80f53d9207fac17afcb1fca7Josiah Gaskin    private boolean missingTargetFile() {
396065dfacbf0c6e46c80f53d9207fac17afcb1fca7Josiah Gaskin        // Loop through our target files and make sure they still exist
397065dfacbf0c6e46c80f53d9207fac17afcb1fca7Josiah Gaskin        for (File target : mTargets) {
398065dfacbf0c6e46c80f53d9207fac17afcb1fca7Josiah Gaskin            if (target.exists() == false) {
399065dfacbf0c6e46c80f53d9207fac17afcb1fca7Josiah Gaskin                return true;
400065dfacbf0c6e46c80f53d9207fac17afcb1fca7Josiah Gaskin            }
401065dfacbf0c6e46c80f53d9207fac17afcb1fca7Josiah Gaskin        }
402065dfacbf0c6e46c80f53d9207fac17afcb1fca7Josiah Gaskin        // If we get this far, then all our targets are okay
403065dfacbf0c6e46c80f53d9207fac17afcb1fca7Josiah Gaskin        return false;
404065dfacbf0c6e46c80f53d9207fac17afcb1fca7Josiah Gaskin    }
405065dfacbf0c6e46c80f53d9207fac17afcb1fca7Josiah Gaskin
406065dfacbf0c6e46c80f53d9207fac17afcb1fca7Josiah Gaskin    /**
407891cbf7552f98af2f0baaed069b5eb64de50c556Xavier Ducrohet     * Returns the earliest modification time stamp from all the output targets. If there
408891cbf7552f98af2f0baaed069b5eb64de50c556Xavier Ducrohet     * are no known target, the dependency file time stamp is returned.
409065dfacbf0c6e46c80f53d9207fac17afcb1fca7Josiah Gaskin     */
410891cbf7552f98af2f0baaed069b5eb64de50c556Xavier Ducrohet    private long getOutputLastModified() {
411065dfacbf0c6e46c80f53d9207fac17afcb1fca7Josiah Gaskin        // Find the oldest target
412065dfacbf0c6e46c80f53d9207fac17afcb1fca7Josiah Gaskin        long oldestTarget = Long.MAX_VALUE;
41350b3e57fa887dc7182facfb178ef842103aeeaf3Xavier Ducrohet        // if there's no output, then compare to the time of the dependency file.
41450b3e57fa887dc7182facfb178ef842103aeeaf3Xavier Ducrohet        if (mTargets.size() == 0) {
41550b3e57fa887dc7182facfb178ef842103aeeaf3Xavier Ducrohet            oldestTarget = mDepFileLastModified;
41650b3e57fa887dc7182facfb178ef842103aeeaf3Xavier Ducrohet        } else {
41750b3e57fa887dc7182facfb178ef842103aeeaf3Xavier Ducrohet            for (File target : mTargets) {
41850b3e57fa887dc7182facfb178ef842103aeeaf3Xavier Ducrohet                if (target.lastModified() < oldestTarget) {
41950b3e57fa887dc7182facfb178ef842103aeeaf3Xavier Ducrohet                    oldestTarget = target.lastModified();
42050b3e57fa887dc7182facfb178ef842103aeeaf3Xavier Ducrohet                }
421065dfacbf0c6e46c80f53d9207fac17afcb1fca7Josiah Gaskin            }
422065dfacbf0c6e46c80f53d9207fac17afcb1fca7Josiah Gaskin        }
423065dfacbf0c6e46c80f53d9207fac17afcb1fca7Josiah Gaskin
424891cbf7552f98af2f0baaed069b5eb64de50c556Xavier Ducrohet        return oldestTarget;
425065dfacbf0c6e46c80f53d9207fac17afcb1fca7Josiah Gaskin    }
426065dfacbf0c6e46c80f53d9207fac17afcb1fca7Josiah Gaskin
427065dfacbf0c6e46c80f53d9207fac17afcb1fca7Josiah Gaskin    /**
428065dfacbf0c6e46c80f53d9207fac17afcb1fca7Josiah Gaskin     * Reads and returns the content of a text file.
429aea408b68a6f833327b6e0954a28f414f58133acXavier Ducrohet     * @param file the file to read
430065dfacbf0c6e46c80f53d9207fac17afcb1fca7Josiah Gaskin     * @return null if the file could not be read
431065dfacbf0c6e46c80f53d9207fac17afcb1fca7Josiah Gaskin     */
432f92c116240bc645a89b12975dd438a46645abe88Xavier Ducrohet    private static List<String> readFile(File file) {
433065dfacbf0c6e46c80f53d9207fac17afcb1fca7Josiah Gaskin        try {
434f92c116240bc645a89b12975dd438a46645abe88Xavier Ducrohet            return Files.readLines(file, Charsets.UTF_8);
4355f2b9cd07a6f3c409971218ee34d3f7b36bd4725Siva Velusamy        } catch (IOException e) {
436f92c116240bc645a89b12975dd438a46645abe88Xavier Ducrohet            // return null below
437065dfacbf0c6e46c80f53d9207fac17afcb1fca7Josiah Gaskin        }
438f92c116240bc645a89b12975dd438a46645abe88Xavier Ducrohet
439065dfacbf0c6e46c80f53d9207fac17afcb1fca7Josiah Gaskin        return null;
440065dfacbf0c6e46c80f53d9207fac17afcb1fca7Josiah Gaskin    }
441065dfacbf0c6e46c80f53d9207fac17afcb1fca7Josiah Gaskin}
442