hunk.code_window: 			Description          string
   			RootHTML             string
   			MainCSS              string
   			ManifestJSON         string
   			Subpath              string
   			ExpectedRootHTML     string
   			ExpectedMainCSS      string
   			ExpectedManifestJSON string
   		}{
   			{
  
hunk.labels: keep keep keep keep add keep keep keep keep keep
hunk.after_edit: 			ExpectedError        error
  
hunk.file_path: utils/subpath_test.go
hunk.type: add
file: // Copyright 2012-present Oliver Eilhard. All rights reserved.
  // Use of this source code is governed by a MIT-license.
  // See http://olivere.mit-license.org/license.txt for details.
  
  package elastic
  
  import (
  	"context"
  	"encoding/json"
  	"fmt"
  	"net/url"
  	"reflect"
  	"strings"
  
  	"gopkg.in/olivere/elastic.v5/uritemplates"
  )
  
  // Search for documents in Elasticsearch.
  type SearchService struct {
  	client            *Client
  	searchSource      *SearchSource
  	source            interface{}
  	pretty            bool
  	filterPath        []string
  	searchType        string
  	index             []string
  	typ               []string
  	routing           string
  	preference        string
  	requestCache      *bool
  	ignoreUnavailable *bool
  	allowNoIndices    *bool
  	expandWildcards   string
  }
  
  // NewSearchService creates a new service for searching in Elasticsearch.
  func NewSearchService(client *Client) *SearchService {
  	builder := &SearchService{
  		client:       client,
  		searchSource: NewSearchSource(),
  	}
  	return builder
  }
  
  // SearchSource sets the search source builder to use with this service.
  func (s *SearchService) SearchSource(searchSource *SearchSource) *SearchService {
  	s.searchSource = searchSource
  	if s.searchSource == nil {
  		s.searchSource = NewSearchSource()
  	}
  	return s
  }
  
  // Source allows the user to set the request body manually without using
  // any of the structs and interfaces in Elastic.
  func (s *SearchService) Source(source interface{}) *SearchService {
  	s.source = source
  	return s
  }
  
  // FilterPath allows reducing the response, a mechanism known as
  // response filtering and described here:
  // https://www.elastic.co/guide/en/elasticsearch/reference/5.6/common-options.html#common-options-response-filtering.
  func (s *SearchService) FilterPath(filterPath ...string) *SearchService {
  	s.filterPath = append(s.filterPath, filterPath...)
  	return s
  }
  
  // Index sets the names of the indices to use for search.
  func (s *SearchService) Index(index ...string) *SearchService {
  	s.index = append(s.index, index...)
  	return s
  }
  
  // Types adds search restrictions for a list of types.
  func (s *SearchService) Type(typ ...string) *SearchService {
  	s.typ = append(s.typ, typ...)
  	return s
  }
  
  // Pretty enables the caller to indent the JSON output.
  func (s *SearchService) Pretty(pretty bool) *SearchService {
  	s.pretty = pretty
  	return s
  }
  
  // Timeout sets the timeout to use, e.g. "1s" or "1000ms".
  func (s *SearchService) Timeout(timeout string) *SearchService {
  	s.searchSource = s.searchSource.Timeout(timeout)
  	return s
  }
  
  // Profile sets the Profile API flag on the search source.
  // When enabled, a search executed by this service will return query
  // profiling data.
  func (s *SearchService) Profile(profile bool) *SearchService {
  	s.searchSource = s.searchSource.Profile(profile)
  	return s
  }
  
  // Collapse adds field collapsing.
  func (s *SearchService) Collapse(collapse *CollapseBuilder) *SearchService {
  	s.searchSource = s.searchSource.Collapse(collapse)
  	return s
  }
  
  // TimeoutInMillis sets the timeout in milliseconds.
  func (s *SearchService) TimeoutInMillis(timeoutInMillis int) *SearchService {
  	s.searchSource = s.searchSource.TimeoutInMillis(timeoutInMillis)
  	return s
  }
  
  // TerminateAfter specifies the maximum number of documents to collect for
  // each shard, upon reaching which the query execution will terminate early.
  func (s *SearchService) TerminateAfter(terminateAfter int) *SearchService {
  	s.searchSource = s.searchSource.TerminateAfter(terminateAfter)
  	return s
  }
  
  // SearchType sets the search operation type. Valid values are:
  // "dfs_query_then_fetch" and "query_then_fetch".
  // See https://www.elastic.co/guide/en/elasticsearch/reference/5.6/search-request-search-type.html
  // for details.
  func (s *SearchService) SearchType(searchType string) *SearchService {
  	s.searchType = searchType
  	return s
  }
  
  // Routing is a list of specific routing values to control the shards
  // the search will be executed on.
  func (s *SearchService) Routing(routings ...string) *SearchService {
  	s.routing = strings.Join(routings, ",")
  	return s
  }
  
  // Preference sets the preference to execute the search. Defaults to
  // randomize across shards ("random"). Can be set to "_local" to prefer
  // local shards, "_primary" to execute on primary shards only,
  // or a custom value which guarantees that the same order will be used
  // across different requests.
  func (s *SearchService) Preference(preference string) *SearchService {
  	s.preference = preference
  	return s
  }
  
  // RequestCache indicates whether the cache should be used for this
  // request or not, defaults to index level setting.
  func (s *SearchService) RequestCache(requestCache bool) *SearchService {
  	s.requestCache = &requestCache
  	return s
  }
  
  // Query sets the query to perform, e.g. MatchAllQuery.
  func (s *SearchService) Query(query Query) *SearchService {
  	s.searchSource = s.searchSource.Query(query)
  	return s
  }
  
  // PostFilter will be executed after the query has been executed and
  // only affects the search hits, not the aggregations.
  // This filter is always executed as the last filtering mechanism.
  func (s *SearchService) PostFilter(postFilter Query) *SearchService {
  	s.searchSource = s.searchSource.PostFilter(postFilter)
  	return s
  }
  
  // FetchSource indicates whether the response should contain the stored
  // _source for every hit.
  func (s *SearchService) FetchSource(fetchSource bool) *SearchService {
  	s.searchSource = s.searchSource.FetchSource(fetchSource)
  	return s
  }
  
  // FetchSourceContext indicates how the _source should be fetched.
  func (s *SearchService) FetchSourceContext(fetchSourceContext *FetchSourceContext) *SearchService {
  	s.searchSource = s.searchSource.FetchSourceContext(fetchSourceContext)
  	return s
  }
  
  // Highlight adds highlighting to the search.
  func (s *SearchService) Highlight(highlight *Highlight) *SearchService {
  	s.searchSource = s.searchSource.Highlight(highlight)
  	return s
  }
  
  // GlobalSuggestText defines the global text to use with all suggesters.
  // This avoids repetition.
  func (s *SearchService) GlobalSuggestText(globalText string) *SearchService {
  	s.searchSource = s.searchSource.GlobalSuggestText(globalText)
  	return s
  }
  
  // Suggester adds a suggester to the search.
  func (s *SearchService) Suggester(suggester Suggester) *SearchService {
  	s.searchSource = s.searchSource.Suggester(suggester)
  	return s
  }
  
  // Aggregation adds an aggreation to perform as part of the search.
  func (s *SearchService) Aggregation(name string, aggregation Aggregation) *SearchService {
  	s.searchSource = s.searchSource.Aggregation(name, aggregation)
  	return s
  }
  
  // MinScore sets the minimum score below which docs will be filtered out.
  func (s *SearchService) MinScore(minScore float64) *SearchService {
  	s.searchSource = s.searchSource.MinScore(minScore)
  	return s
  }
  
  // From index to start the search from. Defaults to 0.
  func (s *SearchService) From(from int) *SearchService {
  	s.searchSource = s.searchSource.From(from)
  	return s
  }
  
  // Size is the number of search hits to return. Defaults to 10.
  func (s *SearchService) Size(size int) *SearchService {
  	s.searchSource = s.searchSource.Size(size)
  	return s
  }
  
  // Explain indicates whether each search hit should be returned with
  // an explanation of the hit (ranking).
  func (s *SearchService) Explain(explain bool) *SearchService {
  	s.searchSource = s.searchSource.Explain(explain)
  	return s
  }
  
  // Version indicates whether each search hit should be returned with
  // a version associated to it.
  func (s *SearchService) Version(version bool) *SearchService {
  	s.searchSource = s.searchSource.Version(version)
  	return s
  }
  
  // Sort adds a sort order.
  func (s *SearchService) Sort(field string, ascending bool) *SearchService {
  	s.searchSource = s.searchSource.Sort(field, ascending)
  	return s
  }
  
  // SortWithInfo adds a sort order.
  func (s *SearchService) SortWithInfo(info SortInfo) *SearchService {
  	s.searchSource = s.searchSource.SortWithInfo(info)
  	return s
  }
  
  // SortBy	adds a sort order.
  func (s *SearchService) SortBy(sorter ...Sorter) *SearchService {
  	s.searchSource = s.searchSource.SortBy(sorter...)
  	return s
  }
  
  // NoStoredFields indicates that no stored fields should be loaded, resulting in only
  // id and type to be returned per field.
  func (s *SearchService) NoStoredFields() *SearchService {
  	s.searchSource = s.searchSource.NoStoredFields()
  	return s
  }
  
  // StoredField adds a single field to load and return (note, must be stored) as
  // part of the search request. If none are specified, the source of the
  // document will be returned.
  func (s *SearchService) StoredField(fieldName string) *SearchService {
  	s.searchSource = s.searchSource.StoredField(fieldName)
  	return s
  }
  
  // StoredFields	sets the fields to load and return as part of the search request.
  // If none are specified, the source of the document will be returned.
  func (s *SearchService) StoredFields(fields ...string) *SearchService {
  	s.searchSource = s.searchSource.StoredFields(fields...)
  	return s
  }
  
  // TrackScores is applied when sorting and controls if scores will be
  // tracked as well. Defaults to false.
  func (s *SearchService) TrackScores(trackScores bool) *SearchService {
  	s.searchSource = s.searchSource.TrackScores(trackScores)
  	return s
  }
  
  // SearchAfter allows a different form of pagination by using a live cursor,
  // using the results of the previous page to help the retrieval of the next.
  //
  // See https://www.elastic.co/guide/en/elasticsearch/reference/5.6/search-request-search-after.html
  func (s *SearchService) SearchAfter(sortValues ...interface{}) *SearchService {
  	s.searchSource = s.searchSource.SearchAfter(sortValues...)
  	return s
  }
  
  // IgnoreUnavailable indicates whether the specified concrete indices
  // should be ignored when unavailable (missing or closed).
  func (s *SearchService) IgnoreUnavailable(ignoreUnavailable bool) *SearchService {
  	s.ignoreUnavailable = &ignoreUnavailable
  	return s
  }
  
  // AllowNoIndices indicates whether to ignore if a wildcard indices
  // expression resolves into no concrete indices. (This includes `_all` string
  // or when no indices have been specified).
  func (s *SearchService) AllowNoIndices(allowNoIndices bool) *SearchService {
  	s.allowNoIndices = &allowNoIndices
  	return s
  }
  
  // ExpandWildcards indicates whether to expand wildcard expression to
  // concrete indices that are open, closed or both.
  func (s *SearchService) ExpandWildcards(expandWildcards string) *SearchService {
  	s.expandWildcards = expandWildcards
  	return s
  }
  
  // buildURL builds the URL for the operation.
  func (s *SearchService) buildURL() (string, url.Values, error) {
  	var err error
  	var path string
  
  	if len(s.index) > 0 && len(s.typ) > 0 {
  		path, err = uritemplates.Expand("/{index}/{type}/_search", map[string]string{
  			"index": strings.Join(s.index, ","),
  			"type":  strings.Join(s.typ, ","),
  		})
  	} else if len(s.index) > 0 {
  		path, err = uritemplates.Expand("/{index}/_search", map[string]string{
  			"index": strings.Join(s.index, ","),
  		})
  	} else if len(s.typ) > 0 {
  		path, err = uritemplates.Expand("/_all/{type}/_search", map[string]string{
  			"type": strings.Join(s.typ, ","),
  		})
  	} else {
  		path = "/_search"
  	}
  	if err != nil {
  		return "", url.Values{}, err
  	}
  
  	// Add query string parameters
  	params := url.Values{}
  	if s.pretty {
  		params.Set("pretty", fmt.Sprintf("%v", s.pretty))
  	}
  	if s.searchType != "" {
  		params.Set("search_type", s.searchType)
  	}
  	if s.routing != "" {
  		params.Set("routing", s.routing)
  	}
  	if s.preference != "" {
  		params.Set("preference", s.preference)
  	}
  	if s.requestCache != nil {
  		params.Set("request_cache", fmt.Sprintf("%v", *s.requestCache))
  	}
  	if s.allowNoIndices != nil {
  		params.Set("allow_no_indices", fmt.Sprintf("%v", *s.allowNoIndices))
  	}
  	if s.expandWildcards != "" {
  		params.Set("expand_wildcards", s.expandWildcards)
  	}
  	if s.ignoreUnavailable != nil {
  		params.Set("ignore_unavailable", fmt.Sprintf("%v", *s.ignoreUnavailable))
  	}
  	if len(s.filterPath) > 0 {
  		params.Set("filter_path", strings.Join(s.filterPath, ","))
  	}
  	return path, params, nil
  }
  
  // Validate checks if the operation is valid.
  func (s *SearchService) Validate() error {
  	return nil
  }
  
  // Do executes the search and returns a SearchResult.
  func (s *SearchService) Do(ctx context.Context) (*SearchResult, error) {
  	// Check pre-conditions
  	if err := s.Validate(); err != nil {
  		return nil, err
  	}
  
  	// Get URL for request
  	path, params, err := s.buildURL()
  	if err != nil {
  		return nil, err
  	}
  
  	// Perform request
  	var body interface{}
  	if s.source != nil {
  		body = s.source
  	} else {
  		src, err := s.searchSource.Source()
  		if err != nil {
  			return nil, err
  		}
  		body = src
  	}
  	res, err := s.client.PerformRequest(ctx, "POST", path, params, body)
  	if err != nil {
  		return nil, err
  	}
  
  	// Return search results
  	ret := new(SearchResult)
  	if err := s.client.decoder.Decode(res.Body, ret); err != nil {
  		return nil, err
  	}
  	return ret, nil
  }
  
  // SearchResult is the result of a search in Elasticsearch.
  type SearchResult struct {
  	TookInMillis int64          `json:"took"`              // search time in milliseconds
  	ScrollId     string         `json:"_scroll_id"`        // only used with Scroll operations
  	Hits         *SearchHits    `json:"hits"`              // the actual search hits
  	Suggest      SearchSuggest  `json:"suggest"`           // results from suggesters
  	Aggregations Aggregations   `json:"aggregations"`      // results from aggregations
  	TimedOut     bool           `json:"timed_out"`         // true if the search timed out
  	Error        *ErrorDetails  `json:"error,omitempty"`   // only used in MultiGet
  	Profile      *SearchProfile `json:"profile,omitempty"` // profiling results, if optional Profile API was active for this search
  	Shards       *shardsInfo    `json:"_shards,omitempty"` // shard information
  }
  
  // TotalHits is a convenience function to return the number of hits for
  // a search result.
  func (r *SearchResult) TotalHits() int64 {
  	if r.Hits != nil {
  		return r.Hits.TotalHits
  	}
  	return 0
  }
  
  // Each is a utility function to iterate over all hits. It saves you from
  // checking for nil values. Notice that Each will ignore errors in
  // serializing JSON.
  func (r *SearchResult) Each(typ reflect.Type) []interface{} {
  	if r.Hits == nil || r.Hits.Hits == nil || len(r.Hits.Hits) == 0 {
  		return nil
  	}
  	var slice []interface{}
  	for _, hit := range r.Hits.Hits {
  		v := reflect.New(typ).Elem()
  		if hit.Source == nil {
  			slice = append(slice, v.Interface())
  			continue
  		}
  		if err := json.Unmarshal(*hit.Source, v.Addr().Interface()); err == nil {
  			slice = append(slice, v.Interface())
  		}
  	}
  	return slice
  }
  
  // SearchHits specifies the list of search hits.
  type SearchHits struct {
  	TotalHits int64        `json:"total"`     // total number of hits found
  	MaxScore  *float64     `json:"max_score"` // maximum score of all hits
  	Hits      []*SearchHit `json:"hits"`      // the actual hits returned
  }
  
  // NestedHit is a nested innerhit
  type NestedHit struct {
  	Field  string     `json:"field"`
  	Offset int        `json:"offset,omitempty"`
  	Child  *NestedHit `json:"_nested,omitempty"`
  }
  
  // SearchHit is a single hit.
  type SearchHit struct {
  	Score          *float64                       `json:"_score"`          // computed score
  	Index          string                         `json:"_index"`          // index name
  	Type           string                         `json:"_type"`           // type meta field
  	Id             string                         `json:"_id"`             // external or internal
  	Uid            string                         `json:"_uid"`            // uid meta field (see MapperService.java for all meta fields)
  	Routing        string                         `json:"_routing"`        // routing meta field
  	Parent         string                         `json:"_parent"`         // parent meta field
  	Version        *int64                         `json:"_version"`        // version number, when Version is set to true in SearchService
  	Sort           []interface{}                  `json:"sort"`            // sort information
  	Highlight      SearchHitHighlight             `json:"highlight"`       // highlighter information
  	Source         *json.RawMessage               `json:"_source"`         // stored document source
  	Fields         map[string]interface{}         `json:"fields"`          // returned (stored) fields
  	Explanation    *SearchExplanation             `json:"_explanation"`    // explains how the score was computed
  	MatchedQueries []string                       `json:"matched_queries"` // matched queries
  	InnerHits      map[string]*SearchHitInnerHits `json:"inner_hits"`      // inner hits with ES >= 1.5.0
  	Nested         *NestedHit                     `json:"_nested"`         // for nested inner hits
  
  	// Shard
  	// HighlightFields
  	// SortValues
  	// MatchedFilters
  }
  
  type SearchHitInnerHits struct {
  	Hits *SearchHits `json:"hits"`
  }
  
  // SearchExplanation explains how the score for a hit was computed.
  // See https://www.elastic.co/guide/en/elasticsearch/reference/5.6/search-request-explain.html.
  type SearchExplanation struct {
  	Value       float64             `json:"value"`             // e.g. 1.0
  	Description string              `json:"description"`       // e.g. "boost" or "ConstantScore(*:*), product of:"
  	Details     []SearchExplanation `json:"details,omitempty"` // recursive details
  }
  
  // Suggest
  
  // SearchSuggest is a map of suggestions.
  // See https://www.elastic.co/guide/en/elasticsearch/reference/5.6/search-suggesters.html.
  type SearchSuggest map[string][]SearchSuggestion
  
  // SearchSuggestion is a single search suggestion.
  // See https://www.elastic.co/guide/en/elasticsearch/reference/5.6/search-suggesters.html.
  type SearchSuggestion struct {
  	Text    string                   `json:"text"`
  	Offset  int                      `json:"offset"`
  	Length  int                      `json:"length"`
  	Options []SearchSuggestionOption `json:"options"`
  }
  
  // SearchSuggestionOption is an option of a SearchSuggestion.
  // See https://www.elastic.co/guide/en/elasticsearch/reference/5.6/search-suggesters.html.
  type SearchSuggestionOption struct {
  	Text         string           `json:"text"`
  	Index        string           `json:"_index"`
  	Type         string           `json:"_type"`
  	Id           string           `json:"_id"`
  	Score        float64          `json:"score"`
  	Highlighted  string           `json:"highlighted"`
  	CollateMatch bool             `json:"collate_match"`
  	Freq         int              `json:"freq"` // from TermSuggestion.Option in Java API
  	Source       *json.RawMessage `json:"_source"`
  }
  
  // SearchProfile is a list of shard profiling data collected during
  // query execution in the "profile" section of a SearchResult
  type SearchProfile struct {
  	Shards []SearchProfileShardResult `json:"shards"`
  }
  
  // SearchProfileShardResult returns the profiling data for a single shard
  // accessed during the search query or aggregation.
  type SearchProfileShardResult struct {
  	ID           string                    `json:"id"`
  	Searches     []QueryProfileShardResult `json:"searches"`
  	Aggregations []ProfileResult           `json:"aggregations"`
  }
  
  // QueryProfileShardResult is a container class to hold the profile results
  // for a single shard in the request. It comtains a list of query profiles,
  // a collector tree and a total rewrite tree.
  type QueryProfileShardResult struct {
  	Query       []ProfileResult `json:"query,omitempty"`
  	RewriteTime int64           `json:"rewrite_time,omitempty"`
  	Collector   []interface{}   `json:"collector,omitempty"`
  }
  
  // CollectorResult holds the profile timings of the collectors used in the
  // search. Children's CollectorResults may be embedded inside of a parent
  // CollectorResult.
  type CollectorResult struct {
  	Name      string            `json:"name,omitempty"`
  	Reason    string            `json:"reason,omitempty"`
  	Time      string            `json:"time,omitempty"`
  	TimeNanos int64             `json:"time_in_nanos,omitempty"`
  	Children  []CollectorResult `json:"children,omitempty"`
  }
  
  // ProfileResult is the internal representation of a profiled query,
  // corresponding to a single node in the query tree.
  type ProfileResult struct {
  	Type          string           `json:"type"`
  	Description   string           `json:"description,omitempty"`
  	NodeTime      string           `json:"time,omitempty"`
  	NodeTimeNanos int64            `json:"time_in_nanos,omitempty"`
  	Breakdown     map[string]int64 `json:"breakdown,omitempty"`
  	Children      []ProfileResult  `json:"children,omitempty"`
  }
  
  // Aggregations (see search_aggs.go)
  
  // Highlighting
  
  // SearchHitHighlight is the highlight information of a search hit.
  // See https://www.elastic.co/guide/en/elasticsearch/reference/5.6/search-request-highlighting.html
  // for a general discussion of highlighting.
  type SearchHitHighlight map[string][]string
  