Add ReplaceDependencies

ReplaceDependencies allows a module to replace dependencies on a
matching variant of a target module with itself.

Change-Id: I22946dec23c38ed5e1ad23b87121d72668268c01
diff --git a/context.go b/context.go
index e38d1ec..7f5a69f 100644
--- a/context.go
+++ b/context.go
@@ -101,7 +101,9 @@
 	// set lazily by sortedModuleNames
 	cachedSortedModuleNames []string
 
-	renames []rename // List of pending renames to apply after the mutator pass
+	// List of pending renames and replacements to apply after the mutator pass
+	renames      []rename
+	replacements []replace
 
 	fs fileSystem
 }
@@ -1753,6 +1755,7 @@
 
 	c.depsModified = 0
 	c.renames = nil
+	c.replacements = nil
 
 	visit := func(module *moduleInfo) bool {
 		if module.splitModules != nil {
@@ -1858,7 +1861,7 @@
 		c.depsModified++
 	}
 
-	errs = c.handleRenames()
+	errs = c.handleRenamesAndReplacements()
 	if len(errs) > 0 {
 		return errs
 	}
@@ -2152,6 +2155,10 @@
 	walk(topModule)
 }
 
+type replace struct {
+	from, to *moduleInfo
+}
+
 type rename struct {
 	group *moduleGroup
 	name  string
@@ -2161,7 +2168,30 @@
 	c.renames = append(c.renames, rename{group, name})
 }
 
-func (c *Context) handleRenames() []error {
+func (c *Context) replaceDependencies(module *moduleInfo, name string) {
+	targets := c.modulesFromName(name)
+
+	if targets == nil {
+		panic(fmt.Errorf("ReplaceDependencies called with non-existant name %q", name))
+	}
+
+	var target *moduleInfo
+	for _, m := range targets {
+		if module.variantName == m.variantName {
+			target = m
+			break
+		}
+	}
+
+	if target == nil {
+		panic(fmt.Errorf("ReplaceDependencies could not find identical variant %q for module %q",
+			module.variantName, name))
+	}
+
+	c.replacements = append(c.replacements, replace{target, module})
+}
+
+func (c *Context) handleRenamesAndReplacements() []error {
 	var errs []error
 	for _, rename := range c.renames {
 		group, name := rename.group, rename.name
@@ -2190,6 +2220,17 @@
 		group.name = name
 	}
 
+	for _, replace := range c.replacements {
+		for _, m := range replace.from.reverseDeps {
+			for i, d := range m.directDeps {
+				if d.module == replace.from {
+					m.directDeps[i].module = replace.to
+				}
+			}
+		}
+
+		atomic.AddUint32(&c.depsModified, 1)
+	}
 	return errs
 }
 
diff --git a/module_ctx.go b/module_ctx.go
index 87eb4f1..cfbb2db 100644
--- a/module_ctx.go
+++ b/module_ctx.go
@@ -493,6 +493,7 @@
 	AddVariationDependencies([]Variation, DependencyTag, ...string)
 	AddFarVariationDependencies([]Variation, DependencyTag, ...string)
 	AddInterVariantDependency(tag DependencyTag, from, to Module)
+	ReplaceDependencies(string)
 }
 
 // A Mutator function is called for each Module, and can use
@@ -653,6 +654,13 @@
 	mctx.context.addInterVariantDependency(mctx.module, tag, from, to)
 }
 
+// ReplaceDependencies replaces all dependencies on the identical variant of the module with the
+// specified name with the current variant of this module.  Replacements don't take effect until
+// after the mutator pass is finished.
+func (mctx *mutatorContext) ReplaceDependencies(name string) {
+	mctx.context.replaceDependencies(mctx.module, name)
+}
+
 func (mctx *mutatorContext) OtherModuleExists(name string) bool {
 	return mctx.context.moduleNames[name] != nil
 }