// Code generated by mockery v0.0.0-dev. DO NOT EDIT.

package mocks

import (
	context "context"
	fs "io/fs"

	git "go.skia.org/infra/go/git"

	gitiles "go.skia.org/infra/go/gitiles"

	mock "github.com/stretchr/testify/mock"

	testing "testing"

	vcsinfo "go.skia.org/infra/go/vcsinfo"
)

// GitilesRepo is an autogenerated mock type for the GitilesRepo type
type GitilesRepo struct {
	mock.Mock
}

// Branches provides a mock function with given fields: ctx
func (_m *GitilesRepo) Branches(ctx context.Context) ([]*git.Branch, error) {
	ret := _m.Called(ctx)

	var r0 []*git.Branch
	if rf, ok := ret.Get(0).(func(context.Context) []*git.Branch); ok {
		r0 = rf(ctx)
	} else {
		if ret.Get(0) != nil {
			r0 = ret.Get(0).([]*git.Branch)
		}
	}

	var r1 error
	if rf, ok := ret.Get(1).(func(context.Context) error); ok {
		r1 = rf(ctx)
	} else {
		r1 = ret.Error(1)
	}

	return r0, r1
}

// Details provides a mock function with given fields: ctx, ref
func (_m *GitilesRepo) Details(ctx context.Context, ref string) (*vcsinfo.LongCommit, error) {
	ret := _m.Called(ctx, ref)

	var r0 *vcsinfo.LongCommit
	if rf, ok := ret.Get(0).(func(context.Context, string) *vcsinfo.LongCommit); ok {
		r0 = rf(ctx, ref)
	} else {
		if ret.Get(0) != nil {
			r0 = ret.Get(0).(*vcsinfo.LongCommit)
		}
	}

	var r1 error
	if rf, ok := ret.Get(1).(func(context.Context, string) error); ok {
		r1 = rf(ctx, ref)
	} else {
		r1 = ret.Error(1)
	}

	return r0, r1
}

// DownloadFile provides a mock function with given fields: ctx, srcPath, dstPath
func (_m *GitilesRepo) DownloadFile(ctx context.Context, srcPath string, dstPath string) error {
	ret := _m.Called(ctx, srcPath, dstPath)

	var r0 error
	if rf, ok := ret.Get(0).(func(context.Context, string, string) error); ok {
		r0 = rf(ctx, srcPath, dstPath)
	} else {
		r0 = ret.Error(0)
	}

	return r0
}

// DownloadFileAtRef provides a mock function with given fields: ctx, srcPath, ref, dstPath
func (_m *GitilesRepo) DownloadFileAtRef(ctx context.Context, srcPath string, ref string, dstPath string) error {
	ret := _m.Called(ctx, srcPath, ref, dstPath)

	var r0 error
	if rf, ok := ret.Get(0).(func(context.Context, string, string, string) error); ok {
		r0 = rf(ctx, srcPath, ref, dstPath)
	} else {
		r0 = ret.Error(0)
	}

	return r0
}

// ListDir provides a mock function with given fields: ctx, dir
func (_m *GitilesRepo) ListDir(ctx context.Context, dir string) ([]fs.FileInfo, error) {
	ret := _m.Called(ctx, dir)

	var r0 []fs.FileInfo
	if rf, ok := ret.Get(0).(func(context.Context, string) []fs.FileInfo); ok {
		r0 = rf(ctx, dir)
	} else {
		if ret.Get(0) != nil {
			r0 = ret.Get(0).([]fs.FileInfo)
		}
	}

	var r1 error
	if rf, ok := ret.Get(1).(func(context.Context, string) error); ok {
		r1 = rf(ctx, dir)
	} else {
		r1 = ret.Error(1)
	}

	return r0, r1
}

// ListDirAtRef provides a mock function with given fields: ctx, dir, ref
func (_m *GitilesRepo) ListDirAtRef(ctx context.Context, dir string, ref string) ([]fs.FileInfo, error) {
	ret := _m.Called(ctx, dir, ref)

	var r0 []fs.FileInfo
	if rf, ok := ret.Get(0).(func(context.Context, string, string) []fs.FileInfo); ok {
		r0 = rf(ctx, dir, ref)
	} else {
		if ret.Get(0) != nil {
			r0 = ret.Get(0).([]fs.FileInfo)
		}
	}

	var r1 error
	if rf, ok := ret.Get(1).(func(context.Context, string, string) error); ok {
		r1 = rf(ctx, dir, ref)
	} else {
		r1 = ret.Error(1)
	}

	return r0, r1
}

// ListFilesRecursive provides a mock function with given fields: ctx, dir
func (_m *GitilesRepo) ListFilesRecursive(ctx context.Context, dir string) ([]string, error) {
	ret := _m.Called(ctx, dir)

	var r0 []string
	if rf, ok := ret.Get(0).(func(context.Context, string) []string); ok {
		r0 = rf(ctx, dir)
	} else {
		if ret.Get(0) != nil {
			r0 = ret.Get(0).([]string)
		}
	}

	var r1 error
	if rf, ok := ret.Get(1).(func(context.Context, string) error); ok {
		r1 = rf(ctx, dir)
	} else {
		r1 = ret.Error(1)
	}

	return r0, r1
}

// ListFilesRecursiveAtRef provides a mock function with given fields: ctx, topDir, ref
func (_m *GitilesRepo) ListFilesRecursiveAtRef(ctx context.Context, topDir string, ref string) ([]string, error) {
	ret := _m.Called(ctx, topDir, ref)

	var r0 []string
	if rf, ok := ret.Get(0).(func(context.Context, string, string) []string); ok {
		r0 = rf(ctx, topDir, ref)
	} else {
		if ret.Get(0) != nil {
			r0 = ret.Get(0).([]string)
		}
	}

	var r1 error
	if rf, ok := ret.Get(1).(func(context.Context, string, string) error); ok {
		r1 = rf(ctx, topDir, ref)
	} else {
		r1 = ret.Error(1)
	}

	return r0, r1
}

// Log provides a mock function with given fields: ctx, logExpr, opts
func (_m *GitilesRepo) Log(ctx context.Context, logExpr string, opts ...gitiles.LogOption) ([]*vcsinfo.LongCommit, error) {
	_va := make([]interface{}, len(opts))
	for _i := range opts {
		_va[_i] = opts[_i]
	}
	var _ca []interface{}
	_ca = append(_ca, ctx, logExpr)
	_ca = append(_ca, _va...)
	ret := _m.Called(_ca...)

	var r0 []*vcsinfo.LongCommit
	if rf, ok := ret.Get(0).(func(context.Context, string, ...gitiles.LogOption) []*vcsinfo.LongCommit); ok {
		r0 = rf(ctx, logExpr, opts...)
	} else {
		if ret.Get(0) != nil {
			r0 = ret.Get(0).([]*vcsinfo.LongCommit)
		}
	}

	var r1 error
	if rf, ok := ret.Get(1).(func(context.Context, string, ...gitiles.LogOption) error); ok {
		r1 = rf(ctx, logExpr, opts...)
	} else {
		r1 = ret.Error(1)
	}

	return r0, r1
}

// LogFirstParent provides a mock function with given fields: ctx, from, to, opts
func (_m *GitilesRepo) LogFirstParent(ctx context.Context, from string, to string, opts ...gitiles.LogOption) ([]*vcsinfo.LongCommit, error) {
	_va := make([]interface{}, len(opts))
	for _i := range opts {
		_va[_i] = opts[_i]
	}
	var _ca []interface{}
	_ca = append(_ca, ctx, from, to)
	_ca = append(_ca, _va...)
	ret := _m.Called(_ca...)

	var r0 []*vcsinfo.LongCommit
	if rf, ok := ret.Get(0).(func(context.Context, string, string, ...gitiles.LogOption) []*vcsinfo.LongCommit); ok {
		r0 = rf(ctx, from, to, opts...)
	} else {
		if ret.Get(0) != nil {
			r0 = ret.Get(0).([]*vcsinfo.LongCommit)
		}
	}

	var r1 error
	if rf, ok := ret.Get(1).(func(context.Context, string, string, ...gitiles.LogOption) error); ok {
		r1 = rf(ctx, from, to, opts...)
	} else {
		r1 = ret.Error(1)
	}

	return r0, r1
}

// LogFn provides a mock function with given fields: ctx, logExpr, fn, opts
func (_m *GitilesRepo) LogFn(ctx context.Context, logExpr string, fn func(context.Context, *vcsinfo.LongCommit) error, opts ...gitiles.LogOption) error {
	_va := make([]interface{}, len(opts))
	for _i := range opts {
		_va[_i] = opts[_i]
	}
	var _ca []interface{}
	_ca = append(_ca, ctx, logExpr, fn)
	_ca = append(_ca, _va...)
	ret := _m.Called(_ca...)

	var r0 error
	if rf, ok := ret.Get(0).(func(context.Context, string, func(context.Context, *vcsinfo.LongCommit) error, ...gitiles.LogOption) error); ok {
		r0 = rf(ctx, logExpr, fn, opts...)
	} else {
		r0 = ret.Error(0)
	}

	return r0
}

// LogFnBatch provides a mock function with given fields: ctx, logExpr, fn, opts
func (_m *GitilesRepo) LogFnBatch(ctx context.Context, logExpr string, fn func(context.Context, []*vcsinfo.LongCommit) error, opts ...gitiles.LogOption) error {
	_va := make([]interface{}, len(opts))
	for _i := range opts {
		_va[_i] = opts[_i]
	}
	var _ca []interface{}
	_ca = append(_ca, ctx, logExpr, fn)
	_ca = append(_ca, _va...)
	ret := _m.Called(_ca...)

	var r0 error
	if rf, ok := ret.Get(0).(func(context.Context, string, func(context.Context, []*vcsinfo.LongCommit) error, ...gitiles.LogOption) error); ok {
		r0 = rf(ctx, logExpr, fn, opts...)
	} else {
		r0 = ret.Error(0)
	}

	return r0
}

// LogLinear provides a mock function with given fields: ctx, from, to, opts
func (_m *GitilesRepo) LogLinear(ctx context.Context, from string, to string, opts ...gitiles.LogOption) ([]*vcsinfo.LongCommit, error) {
	_va := make([]interface{}, len(opts))
	for _i := range opts {
		_va[_i] = opts[_i]
	}
	var _ca []interface{}
	_ca = append(_ca, ctx, from, to)
	_ca = append(_ca, _va...)
	ret := _m.Called(_ca...)

	var r0 []*vcsinfo.LongCommit
	if rf, ok := ret.Get(0).(func(context.Context, string, string, ...gitiles.LogOption) []*vcsinfo.LongCommit); ok {
		r0 = rf(ctx, from, to, opts...)
	} else {
		if ret.Get(0) != nil {
			r0 = ret.Get(0).([]*vcsinfo.LongCommit)
		}
	}

	var r1 error
	if rf, ok := ret.Get(1).(func(context.Context, string, string, ...gitiles.LogOption) error); ok {
		r1 = rf(ctx, from, to, opts...)
	} else {
		r1 = ret.Error(1)
	}

	return r0, r1
}

// ReadFile provides a mock function with given fields: ctx, srcPath
func (_m *GitilesRepo) ReadFile(ctx context.Context, srcPath string) ([]byte, error) {
	ret := _m.Called(ctx, srcPath)

	var r0 []byte
	if rf, ok := ret.Get(0).(func(context.Context, string) []byte); ok {
		r0 = rf(ctx, srcPath)
	} else {
		if ret.Get(0) != nil {
			r0 = ret.Get(0).([]byte)
		}
	}

	var r1 error
	if rf, ok := ret.Get(1).(func(context.Context, string) error); ok {
		r1 = rf(ctx, srcPath)
	} else {
		r1 = ret.Error(1)
	}

	return r0, r1
}

// ReadFileAtRef provides a mock function with given fields: ctx, srcPath, ref
func (_m *GitilesRepo) ReadFileAtRef(ctx context.Context, srcPath string, ref string) ([]byte, error) {
	ret := _m.Called(ctx, srcPath, ref)

	var r0 []byte
	if rf, ok := ret.Get(0).(func(context.Context, string, string) []byte); ok {
		r0 = rf(ctx, srcPath, ref)
	} else {
		if ret.Get(0) != nil {
			r0 = ret.Get(0).([]byte)
		}
	}

	var r1 error
	if rf, ok := ret.Get(1).(func(context.Context, string, string) error); ok {
		r1 = rf(ctx, srcPath, ref)
	} else {
		r1 = ret.Error(1)
	}

	return r0, r1
}

// ReadObject provides a mock function with given fields: ctx, path, ref
func (_m *GitilesRepo) ReadObject(ctx context.Context, path string, ref string) (fs.FileInfo, []byte, error) {
	ret := _m.Called(ctx, path, ref)

	var r0 fs.FileInfo
	if rf, ok := ret.Get(0).(func(context.Context, string, string) fs.FileInfo); ok {
		r0 = rf(ctx, path, ref)
	} else {
		if ret.Get(0) != nil {
			r0 = ret.Get(0).(fs.FileInfo)
		}
	}

	var r1 []byte
	if rf, ok := ret.Get(1).(func(context.Context, string, string) []byte); ok {
		r1 = rf(ctx, path, ref)
	} else {
		if ret.Get(1) != nil {
			r1 = ret.Get(1).([]byte)
		}
	}

	var r2 error
	if rf, ok := ret.Get(2).(func(context.Context, string, string) error); ok {
		r2 = rf(ctx, path, ref)
	} else {
		r2 = ret.Error(2)
	}

	return r0, r1, r2
}

// ResolveRef provides a mock function with given fields: ctx, ref
func (_m *GitilesRepo) ResolveRef(ctx context.Context, ref string) (string, error) {
	ret := _m.Called(ctx, ref)

	var r0 string
	if rf, ok := ret.Get(0).(func(context.Context, string) string); ok {
		r0 = rf(ctx, ref)
	} else {
		r0 = ret.Get(0).(string)
	}

	var r1 error
	if rf, ok := ret.Get(1).(func(context.Context, string) error); ok {
		r1 = rf(ctx, ref)
	} else {
		r1 = ret.Error(1)
	}

	return r0, r1
}

// Tags provides a mock function with given fields: ctx
func (_m *GitilesRepo) Tags(ctx context.Context) (map[string]string, error) {
	ret := _m.Called(ctx)

	var r0 map[string]string
	if rf, ok := ret.Get(0).(func(context.Context) map[string]string); ok {
		r0 = rf(ctx)
	} else {
		if ret.Get(0) != nil {
			r0 = ret.Get(0).(map[string]string)
		}
	}

	var r1 error
	if rf, ok := ret.Get(1).(func(context.Context) error); ok {
		r1 = rf(ctx)
	} else {
		r1 = ret.Error(1)
	}

	return r0, r1
}

// URL provides a mock function with given fields:
func (_m *GitilesRepo) URL() string {
	ret := _m.Called()

	var r0 string
	if rf, ok := ret.Get(0).(func() string); ok {
		r0 = rf()
	} else {
		r0 = ret.Get(0).(string)
	}

	return r0
}

// VFS provides a mock function with given fields: ctx, ref
func (_m *GitilesRepo) VFS(ctx context.Context, ref string) (*gitiles.FS, error) {
	ret := _m.Called(ctx, ref)

	var r0 *gitiles.FS
	if rf, ok := ret.Get(0).(func(context.Context, string) *gitiles.FS); ok {
		r0 = rf(ctx, ref)
	} else {
		if ret.Get(0) != nil {
			r0 = ret.Get(0).(*gitiles.FS)
		}
	}

	var r1 error
	if rf, ok := ret.Get(1).(func(context.Context, string) error); ok {
		r1 = rf(ctx, ref)
	} else {
		r1 = ret.Error(1)
	}

	return r0, r1
}

// NewGitilesRepo creates a new instance of GitilesRepo. It also registers a cleanup function to assert the mocks expectations.
func NewGitilesRepo(t testing.TB) *GitilesRepo {
	mock := &GitilesRepo{}

	t.Cleanup(func() { mock.AssertExpectations(t) })

	return mock
}
