Stub out caching functionality

This commit is contained in:
Ben Vanik 2012-09-19 21:21:59 -07:00
parent 275fc8e4bc
commit d0d192860e
8 changed files with 136 additions and 18 deletions

View File

@ -1,6 +1,10 @@
foo#*.ext for src_filter on input side
removes extra intermediate rules (*.css only from set)
Caching
==============================================================
Stages
==============================================================

54
anvil/cache.py Normal file
View File

@ -0,0 +1,54 @@
# Copyright 2012 Google Inc. All Rights Reserved.
"""Rule cache.
"""
__author__ = 'benvanik@google.com (Ben Vanik)'
class RuleCache(object):
"""
"""
def __init__(self):
"""Initializes the rule cache.
"""
pass
def compute_delta(self, src_paths):
"""Computes a file delta for the given source paths.
Args:
src_paths: A list of fully-resolved source file paths.
Returns:
A FileDelta with the information from the given paths.
"""
file_delta = FileDelta()
file_delta.all_files.extend(src_paths)
# TODO(benvanik): work
file_delta.changed_files.extend(src_paths)
return file_delta
class FileDelta(object):
"""
"""
def __init__(self):
"""Initializes a file delta.
"""
self.all_files = []
self.added_files = []
self.removed_files = []
self.modified_files = []
self.changed_files = []
def any_changes(self):
"""
Returns:
True if any changes occurred.
"""
return len(self.changed_files)

View File

@ -17,6 +17,7 @@ import stat
from anvil import async
from anvil.async import Deferred
from anvil import cache
from anvil import graph
from anvil import project
from anvil import task
@ -120,6 +121,9 @@ class BuildContext(object):
# Dictionary that should be used to map rule paths to RuleContexts
self.rule_contexts = {}
# Cache used to generate file deltas
self.cache = cache.RuleCache()
def __enter__(self):
return self
@ -350,6 +354,8 @@ class RuleContext(object):
self.build_env = build_context.build_env
self.rule = rule
self.file_delta = None
self.deferred = Deferred()
self.status = Status.WAITING
self.start_time = None
@ -404,7 +410,6 @@ class RuleContext(object):
exclude_filter_list = []
if apply_src_filter and self.rule.src_exclude_filter:
exclude_filter_list = self.rule.src_exclude_filter.split('|')
print 'got filters %s' % (exclude_filter_list)
base_path = os.path.dirname(self.rule.parent_module.path)
input_paths = []
@ -594,6 +599,23 @@ class RuleContext(object):
return True
return False
def _check_if_cached(self):
"""Checks if all inputs and outputs match their expected values.
Returns:
True if no inputs or outputs have changed.
"""
# If any input changed...
if self.file_delta.any_changes():
return False
# If any output is changed...
output_delta = self.build_context.cache.compute_delta(self.all_output_files)
if output_delta.any_changes():
return False
return True
def begin(self):
"""Begins asynchronous rule execution.
Custom RuleContext implementations should override this method to perform
@ -617,6 +639,10 @@ class RuleContext(object):
print '... %20s ~ %s' % (self.rule.rule_name, rel_path)
# Compute file delta
# Note that this could be done async (somehow)
self.file_delta = self.build_context.cache.compute_delta(self.src_paths)
return self.deferred
def cascade_failure(self):
@ -695,19 +721,3 @@ class RuleContext(object):
break
self._fail(exception=exception)
deferred.add_errback_fn(_errback)
# class FileDelta(object):
# """
# TODO(benvanik): move to another module and setup to use cache
# """
# def __init__(self, source_paths=None):
# """
# Args:
# source_paths
# """
# self.all_files = []
# self.added_files = []
# self.removed_files = []
# self.changed_files = []

View File

@ -56,6 +56,11 @@ class ArchiveFilesRule(Rule):
self._ensure_output_exists(os.path.dirname(output_path))
self._append_output_paths([output_path])
# Skip if cache hit
if self._check_if_cached():
self._succeed()
return
# Compute the relative archive path for each file
paths = []
for src_path in self.src_paths:

View File

@ -108,6 +108,11 @@ class ClosureGssLibraryRule(Rule):
args.extend(self.src_paths)
# Skip if cache hit
if self._check_if_cached():
self._succeed()
return
jar_path = self._resolve_input_files([self.rule.compiler_jar])[0]
d = self._run_task_async(JavaExecutableTask(
self.build_env, jar_path, args))

View File

@ -60,6 +60,11 @@ class ClosureJsLintRule(Rule):
super(ClosureJsLintRule._Context, self).begin()
self._append_output_paths(self.src_paths)
# Skip if cache hit
if self._check_if_cached():
self._succeed()
return
namespaces = ','.join(self.rule.namespaces)
args = [
'--strict',
@ -69,7 +74,7 @@ class ClosureJsLintRule(Rule):
# TODO(benvanik): only changed paths
# Exclude any path containing build-*
for src_path in self.src_paths:
for src_path in self.file_delta.changed_files:
if (src_path.find('build-out%s' % os.sep) == -1 and
src_path.find('build-gen%s' % os.sep) == -1):
args.append(src_path)
@ -265,6 +270,11 @@ class ClosureJsLibraryRule(Rule):
self._ensure_output_exists(os.path.dirname(deps_js_path))
self._append_output_paths([deps_js_path])
# Skip if cache hit
if self._check_if_cached():
self._succeed()
return
# Issue dependency scanning to build the deps graph
d = self._run_task_async(_ScanJsDependenciesTask(
self.build_env, self.src_paths))

View File

@ -78,6 +78,11 @@ class ClosureSoyLibraryRule(Rule):
rel_path = os.path.relpath(src_path, self.build_env.root_path)
args.append(rel_path)
# Skip if cache hit
if self._check_if_cached():
self._succeed()
return
jar_path = self._resolve_input_files([self.rule.compiler_jar])[0]
d = self._run_task_async(JavaExecutableTask(
self.build_env, jar_path, args))

View File

@ -90,6 +90,11 @@ class CopyFilesRule(Rule):
self._append_output_paths([out_path])
file_pairs.append((src_path, out_path))
# Skip if cache hit
if self._check_if_cached():
self._succeed()
return
# Async issue copying task
d = self._run_task_async(_CopyFilesTask(
self.build_env, file_pairs))
@ -147,6 +152,11 @@ class ConcatFilesRule(Rule):
self._ensure_output_exists(os.path.dirname(output_path))
self._append_output_paths([output_path])
# Skip if cache hit
if self._check_if_cached():
self._succeed()
return
# Async issue concat task
d = self._run_task_async(_ConcatFilesTask(
self.build_env, self.src_paths, output_path))
@ -221,6 +231,11 @@ class TemplateFilesRule(Rule):
self._append_output_paths([out_path])
file_pairs.append((src_path, out_path))
# Skip if cache hit
if self._check_if_cached():
self._succeed()
return
# Async issue templating task
d = self._run_task_async(_TemplateFilesTask(
self.build_env, file_pairs, self.rule.params))
@ -289,6 +304,11 @@ class StripCommentsRule(Rule):
self._append_output_paths([out_path])
file_pairs.append((src_path, out_path))
# Skip if cache hit
if self._check_if_cached():
self._succeed()
return
# Async issue stripping task
d = self._run_task_async(_StripCommentsRuleTask(
self.build_env, file_pairs))
@ -355,6 +375,11 @@ class ShellExecuteRule(Rule):
call_args = self.rule.command[1:]
call_args.extend(self.src_paths)
# Skip if cache hit
if self._check_if_cached():
self._succeed()
return
# Async issue copying task
d = self._run_task_async(ExecutableTask(
self.build_env, executable_name, call_args))