You are an expert in writing code in many different languages. Your goal is to perform code completion for the following code, keeping in mind the rest of the code and the file meta data.
    Metadata details:
    filename: fetcher_default.go
    path of file: ./repos/oathkeeper/rule
    
    the code of the file until where you have to start completion: // Copyright Â© 2023 Ory Corp
// SPDX-License-Identifier: Apache-2.0

package rule

import (
	"bytes"
	"context"
	"encoding/base64"
	"encoding/json"
	"io"
	"net/http"
	"net/url"
	"path/filepath"
	"strings"
	"sync"
	"time"

	"github.com/ghodss/yaml"
	"github.com/pkg/errors"
	"go.opentelemetry.io/otel/trace"
	"gocloud.dev/blob"
	_ "gocloud.dev/blob/azureblob"
	_ "gocloud.dev/blob/gcsblob"
	_ "gocloud.dev/blob/s3blob"

	"github.com/ory/x/httpx"
	"github.com/ory/x/urlx"
	"github.com/ory/x/watcherx"

	"github.com/ory/oathkeeper/driver/configuration"
	"github.com/ory/oathkeeper/internal/cloudstorage"
	"github.com/ory/oathkeeper/x"
)

var _ Fetcher = new(FetcherDefault)

type fetcherRegistry interface {
	x.RegistryLogger
	RuleRepository() Repository
	Tracer() trace.Tracer
}

type FetcherDefault struct {
	config   configuration.Provider
	registry fetcherRegistry
	hc       *http.Client
	mux      *blob.URLMux

	cache          map[string][]Rule
	cancelWatchers map[string]context.CancelFunc
	events         chan watcherx.Event

	lock sync.Mutex
}

func NewFetcherDefault(
	config configuration.Provider,
	registry fetcherRegistry,
) *FetcherDefault {
	return &FetcherDefault{
		registry: registry,
		config:   config,
		mux:      cloudstorage.NewURLMux(),
		hc: httpx.NewResilientClient(
			httpx.ResilientClientWithConnectionTimeout(15*time.Second),
			httpx.ResilientClientWithTracer(registry.Tracer()),
		).StandardClient(),
		cache:          make(map[string][]Rule),
		cancelWatchers: make(map[string]cont
    
func (f *FetcherDefault) Watch(ctx context.Context) error {
	f.watchLocalFiles(ctx)

	getRemoteRepos := func() map[url.URL]struct{} {
		_, remoteRepos := splitLocalRemoteRepos(f.config.AccessRuleRepositories())
		repos := make(map[url.URL]struct{}, len(remoteRepos))
		for _, repo := range remoteRepos {
			repos[repo] = struct{}{}
		}
		return repos
	}

	// capture the previous config values to detect changes, and trigger initial processing
	strategy := f.config.AccessRuleMatchingStrategy()
	if err := f.processStrategyUpdate(ctx, strategy); err != nil {
		return err
	}

	remoteRepos := getRemoteRepos()
	if err := f.processRemoteRepoUpdate(ctx, nil, remoteRepos); err != nil {
		return err
	}

	f.config.AddWatcher(func(_ watcherx.Event, err error) {
		if err != nil {
			return
		}
		// watch files that need to be watched
		f.watchLocalFiles(ctx)

		// update the matching strategy if it changed
		if newStrategy := f.config.AccessRuleMatchingStrategy(); newStrategy != strategy {
			f.registry.Logger().WithField("strategy", newStrategy).Info("Detected access rule matching strategy change, processing updates.")
			if err := f.processStrategyUpdate(ctx, newStrategy); err != nil {
				f.registry.Logger().WithError(err).Error("Unable to update access rule matching strategy.")
			} else {
				strategy = newStrategy
			}
		}

		// update & fetch the remote repos if they changed
		newRemoteRepos := getRemoteRepos()
		if err := f.processRemoteRepoUpdate(ctx, remoteRepos, newRemoteRepos); err != nil {
			f.registry.Logger().WithError(err).Error("Unable to update remote access rule repository config.")
		}
		remoteRepos = newRemoteRepos
	})

	go f.processLocalUpdates(ctx)
	return nil
}