Stub out caching functionality
This commit is contained in:
parent
275fc8e4bc
commit
d0d192860e
4
TODO.md
4
TODO.md
|
@ -1,6 +1,10 @@
|
|||
foo#*.ext for src_filter on input side
|
||||
removes extra intermediate rules (*.css only from set)
|
||||
|
||||
Caching
|
||||
==============================================================
|
||||
|
||||
|
||||
|
||||
Stages
|
||||
==============================================================
|
||||
|
|
|
@ -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)
|
|
@ -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 = []
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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))
|
||||
|
|
Loading…
Reference in New Issue