github.com/westcoastroms/westcoastroms-build@v0.0.0-20190928114312-2350e5a73030/build/blueprint/live_tracker.go (about)

     1  // Copyright 2014 Google Inc. All rights reserved.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package blueprint
    16  
    17  import "sync"
    18  
    19  // A liveTracker tracks the values of live variables, rules, and pools.  An
    20  // entity is made "live" when it is referenced directly or indirectly by a build
    21  // definition.  When an entity is made live its value is computed based on the
    22  // configuration.
    23  type liveTracker struct {
    24  	sync.Mutex
    25  	config interface{} // Used to evaluate variable, rule, and pool values.
    26  
    27  	variables map[Variable]*ninjaString
    28  	pools     map[Pool]*poolDef
    29  	rules     map[Rule]*ruleDef
    30  }
    31  
    32  func newLiveTracker(config interface{}) *liveTracker {
    33  	return &liveTracker{
    34  		config:    config,
    35  		variables: make(map[Variable]*ninjaString),
    36  		pools:     make(map[Pool]*poolDef),
    37  		rules:     make(map[Rule]*ruleDef),
    38  	}
    39  }
    40  
    41  func (l *liveTracker) AddBuildDefDeps(def *buildDef) error {
    42  	l.Lock()
    43  	defer l.Unlock()
    44  
    45  	ruleDef, err := l.addRule(def.Rule)
    46  	if err != nil {
    47  		return err
    48  	}
    49  	def.RuleDef = ruleDef
    50  
    51  	err = l.addNinjaStringListDeps(def.Outputs)
    52  	if err != nil {
    53  		return err
    54  	}
    55  
    56  	err = l.addNinjaStringListDeps(def.Inputs)
    57  	if err != nil {
    58  		return err
    59  	}
    60  
    61  	err = l.addNinjaStringListDeps(def.Implicits)
    62  	if err != nil {
    63  		return err
    64  	}
    65  
    66  	err = l.addNinjaStringListDeps(def.OrderOnly)
    67  	if err != nil {
    68  		return err
    69  	}
    70  
    71  	for _, value := range def.Variables {
    72  		err = l.addNinjaStringDeps(value)
    73  		if err != nil {
    74  			return err
    75  		}
    76  	}
    77  
    78  	for _, value := range def.Args {
    79  		err = l.addNinjaStringDeps(value)
    80  		if err != nil {
    81  			return err
    82  		}
    83  	}
    84  
    85  	return nil
    86  }
    87  
    88  func (l *liveTracker) addRule(r Rule) (def *ruleDef, err error) {
    89  	def, ok := l.rules[r]
    90  	if !ok {
    91  		def, err = r.def(l.config)
    92  		if err == errRuleIsBuiltin {
    93  			// No need to do anything for built-in rules.
    94  			return nil, nil
    95  		}
    96  		if err != nil {
    97  			return nil, err
    98  		}
    99  
   100  		if def.Pool != nil {
   101  			err = l.addPool(def.Pool)
   102  			if err != nil {
   103  				return nil, err
   104  			}
   105  		}
   106  
   107  		err = l.addNinjaStringListDeps(def.CommandDeps)
   108  		if err != nil {
   109  			return nil, err
   110  		}
   111  
   112  		err = l.addNinjaStringListDeps(def.CommandOrderOnly)
   113  		if err != nil {
   114  			return nil, err
   115  		}
   116  
   117  		for _, value := range def.Variables {
   118  			err = l.addNinjaStringDeps(value)
   119  			if err != nil {
   120  				return nil, err
   121  			}
   122  		}
   123  
   124  		l.rules[r] = def
   125  	}
   126  
   127  	return
   128  }
   129  
   130  func (l *liveTracker) addPool(p Pool) error {
   131  	_, ok := l.pools[p]
   132  	if !ok {
   133  		def, err := p.def(l.config)
   134  		if err == errPoolIsBuiltin {
   135  			// No need to do anything for built-in rules.
   136  			return nil
   137  		}
   138  		if err != nil {
   139  			return err
   140  		}
   141  
   142  		l.pools[p] = def
   143  	}
   144  
   145  	return nil
   146  }
   147  
   148  func (l *liveTracker) addVariable(v Variable) error {
   149  	_, ok := l.variables[v]
   150  	if !ok {
   151  		value, err := v.value(l.config)
   152  		if err == errVariableIsArg {
   153  			// This variable is a placeholder for an argument that can be passed
   154  			// to a rule.  It has no value and thus doesn't reference any other
   155  			// variables.
   156  			return nil
   157  		}
   158  		if err != nil {
   159  			return err
   160  		}
   161  
   162  		l.variables[v] = value
   163  
   164  		err = l.addNinjaStringDeps(value)
   165  		if err != nil {
   166  			return err
   167  		}
   168  	}
   169  
   170  	return nil
   171  }
   172  
   173  func (l *liveTracker) addNinjaStringListDeps(list []*ninjaString) error {
   174  	for _, str := range list {
   175  		err := l.addNinjaStringDeps(str)
   176  		if err != nil {
   177  			return err
   178  		}
   179  	}
   180  	return nil
   181  }
   182  
   183  func (l *liveTracker) addNinjaStringDeps(str *ninjaString) error {
   184  	for _, v := range str.variables {
   185  		err := l.addVariable(v)
   186  		if err != nil {
   187  			return err
   188  		}
   189  	}
   190  	return nil
   191  }
   192  
   193  func (l *liveTracker) RemoveVariableIfLive(v Variable) bool {
   194  	l.Lock()
   195  	defer l.Unlock()
   196  
   197  	_, isLive := l.variables[v]
   198  	if isLive {
   199  		delete(l.variables, v)
   200  	}
   201  	return isLive
   202  }
   203  
   204  func (l *liveTracker) RemoveRuleIfLive(r Rule) bool {
   205  	l.Lock()
   206  	defer l.Unlock()
   207  
   208  	_, isLive := l.rules[r]
   209  	if isLive {
   210  		delete(l.rules, r)
   211  	}
   212  	return isLive
   213  }