code: func ReplaceVariables(str string, opts *ArchiveOptions) (string, error) {
  	var err error
  	subst := variableSubstitutionMatcher.ReplaceAllStringFunc(str,
  		func(match string) string {
  			varName := match[2 : len(match)-1]
  			if v, ok := opts.PathVariables[varName]; ok {
  				return v
  			}
  			if v, ok := opts.ExtraVariables[varName]; ok {
  				return v
  			}
  			if v, ok := opts.ConfigVariables[varName]; ok {
  				return v
  			}
  			if err == nil {
  				err = errors.New("no value for variable '" + varName + "'")
  			}
  			return match
  		})
  	return subst, err
  }
docs: // ReplaceVariables replaces any occurrences of '<(FOO)' in 'str' with the
  // corresponding variable from 'opts'.
  //
  // If any substitution refers to a variable that is missing, the returned error will
  // refer to the first such variable. In the case of errors, the returned string will
  // still contain a valid result for any non-missing substitutions.