diff --git a/.golangci.yml b/.golangci.yml
index 3abccea826296..66d694c038fd3 100644
--- a/.golangci.yml
+++ b/.golangci.yml
@@ -5,18 +5,12 @@ run:
   skip-dirs:
     - pkg/client
     - vendor
-linter-settings:
-  goimports:
-    local-prefixes: github.com/argoproj/argo-cd
 linters:
   enable:
     - vet
-    - gofmt
-    - goimports
     - deadcode
     - varcheck
     - structcheck
     - ineffassign
     - unconvert
-    - misspell
     - unparam
diff --git a/assets/swagger.json b/assets/swagger.json
index 9f0326633898d..4413470ac6f01 100644
--- a/assets/swagger.json
+++ b/assets/swagger.json
@@ -1936,7 +1936,7 @@
     },
     "repositoryHelmAppSpec": {
       "type": "object",
-      "title": "HelmAppSpec contains helm app name and path in source repo",
+      "title": "HelmAppSpec contains helm app name  in source repo",
       "properties": {
         "name": {
           "type": "string"
@@ -1948,9 +1948,6 @@
             "$ref": "#/definitions/v1alpha1HelmParameter"
           }
         },
-        "path": {
-          "type": "string"
-        },
         "valueFiles": {
           "type": "array",
           "items": {
@@ -1989,9 +1986,6 @@
           "items": {
             "$ref": "#/definitions/v1alpha1KsonnetParameter"
           }
-        },
-        "path": {
-          "type": "string"
         }
       }
     },
@@ -2008,10 +2002,6 @@
         "name": {
           "type": "string",
           "title": "Name is the user defined name of an environment"
-        },
-        "path": {
-          "description": "Path is the relative project path containing metadata for this environment.",
-          "type": "string"
         }
       }
     },
@@ -2030,7 +2020,7 @@
     },
     "repositoryKustomizeAppSpec": {
       "type": "object",
-      "title": "KustomizeAppSpec contains kustomize app name and path in source repo",
+      "title": "KustomizeAppSpec contains kustomize images",
       "properties": {
         "images": {
           "description": "images is a list of available images.",
@@ -2038,9 +2028,6 @@
           "items": {
             "type": "string"
           }
-        },
-        "path": {
-          "type": "string"
         }
       }
     },
@@ -2713,7 +2700,7 @@
         },
         "sourceRepos": {
           "type": "array",
-          "title": "SourceRepos contains list of git repository URLs which can be used for deployment",
+          "title": "SourceRepos contains list of repository URLs which can be used for deployment",
           "items": {
             "type": "string"
           }
@@ -2806,7 +2793,7 @@
         },
         "repoURL": {
           "type": "string",
-          "title": "RepoURL is the git repository URL of the application manifests"
+          "title": "RepoURL is the repository URL of the application manifests"
         },
         "targetRevision": {
           "type": "string",
@@ -3350,7 +3337,7 @@
     },
     "v1alpha1Repository": {
       "type": "object",
-      "title": "Repository is a Git repository holding application configurations",
+      "title": "Repository is a repository holding application configurations",
       "properties": {
         "connectionState": {
           "$ref": "#/definitions/v1alpha1ConnectionState"
@@ -3368,7 +3355,11 @@
         "insecureIgnoreHostKey": {
           "type": "boolean",
           "format": "boolean",
-          "title": "InsecureIgnoreHostKey should not be used anymore, Insecure is favoured"
+          "title": "InsecureIgnoreHostKey should not be used anymore, Insecure is favoured\nonly for Git repos"
+        },
+        "name": {
+          "type": "string",
+          "title": "only for Helm repos"
         },
         "password": {
           "type": "string",
@@ -3380,7 +3371,11 @@
         },
         "sshPrivateKey": {
           "type": "string",
-          "title": "SSH private key data for authenticating at the repo server"
+          "title": "SSH private key data for authenticating at the repo server\nonly for Git repos"
+        },
+        "tlsClientCaData": {
+          "type": "string",
+          "title": "only for Helm repos"
         },
         "tlsClientCertData": {
           "type": "string",
@@ -3390,6 +3385,10 @@
           "type": "string",
           "title": "TLS client cert key for authenticating at the repo server"
         },
+        "type": {
+          "type": "string",
+          "title": "type of the repo, maybe \"git or \"helm, \"git\" is assumed if empty or absent"
+        },
         "username": {
           "type": "string",
           "title": "Username for authenticating at the repo server"
@@ -3800,7 +3799,7 @@
           }
         },
         "revision": {
-          "description": "Revision is the git revision in which to sync the application to.\nIf omitted, will use the revision specified in app spec.",
+          "description": "Revision is the revision in which to sync the application to.\nIf omitted, will use the revision specified in app spec.",
           "type": "string"
         },
         "source": {
@@ -3839,7 +3838,7 @@
         },
         "revision": {
           "type": "string",
-          "title": "Revision holds the git commit SHA of the sync"
+          "title": "Revision holds the revision of the sync"
         },
         "source": {
           "$ref": "#/definitions/v1alpha1ApplicationSource"
diff --git a/cmd/argocd-repo-server/main.go b/cmd/argocd-repo-server/main.go
index 68df86885bfa8..e9e7328122eb5 100644
--- a/cmd/argocd-repo-server/main.go
+++ b/cmd/argocd-repo-server/main.go
@@ -17,7 +17,7 @@ import (
 	"github.com/argoproj/argo-cd/reposerver"
 	"github.com/argoproj/argo-cd/util/cache"
 	"github.com/argoproj/argo-cd/util/cli"
-	"github.com/argoproj/argo-cd/util/git"
+	"github.com/argoproj/argo-cd/util/repo/factory"
 	"github.com/argoproj/argo-cd/util/stats"
 	"github.com/argoproj/argo-cd/util/tls"
 )
@@ -48,7 +48,7 @@ func newCommand() *cobra.Command {
 			cache, err := cacheSrc()
 			errors.CheckError(err)
 
-			metricsServer := metrics.NewMetricsServer(git.NewFactory())
+			metricsServer := metrics.NewMetricsServer(factory.NewFactory())
 			server, err := reposerver.NewServer(metricsServer, cache, tlsConfigCustomizer, parallelismLimit)
 			errors.CheckError(err)
 
diff --git a/cmd/argocd-util/main.go b/cmd/argocd-util/main.go
index 6aec68310eae0..38771b32a8a98 100644
--- a/cmd/argocd-util/main.go
+++ b/cmd/argocd-util/main.go
@@ -447,27 +447,8 @@ func getReferencedSecrets(un unstructured.Unstructured) map[string]bool {
 			if cred.TLSClientCertKeySecret != nil {
 				referencedSecrets[cred.TLSClientCertKeySecret.Name] = true
 			}
-		}
-	}
-	if helmReposRAW, ok := cm.Data["helm.repositories"]; ok {
-		helmRepoCreds := make([]settings.HelmRepoCredentials, 0)
-		err := yaml.Unmarshal([]byte(helmReposRAW), &helmRepoCreds)
-		errors.CheckError(err)
-		for _, cred := range helmRepoCreds {
-			if cred.CASecret != nil {
-				referencedSecrets[cred.CASecret.Name] = true
-			}
-			if cred.CertSecret != nil {
-				referencedSecrets[cred.CertSecret.Name] = true
-			}
-			if cred.KeySecret != nil {
-				referencedSecrets[cred.KeySecret.Name] = true
-			}
-			if cred.UsernameSecret != nil {
-				referencedSecrets[cred.UsernameSecret.Name] = true
-			}
-			if cred.PasswordSecret != nil {
-				referencedSecrets[cred.PasswordSecret.Name] = true
+			if cred.TLSClientCASecret != nil {
+				referencedSecrets[cred.TLSClientCASecret.Name] = true
 			}
 		}
 	}
diff --git a/cmd/argocd/commands/app.go b/cmd/argocd/commands/app.go
index 86b66ac2ffff3..85e0870d53799 100644
--- a/cmd/argocd/commands/app.go
+++ b/cmd/argocd/commands/app.go
@@ -11,7 +11,6 @@ import (
 	"os"
 	"os/exec"
 	"path"
-	"path/filepath"
 	"reflect"
 	"sort"
 	"strconv"
@@ -104,7 +103,7 @@ func NewApplicationCreateCommand(clientOpts *argocdclient.ClientOptions) *cobra.
 	)
 	var command = &cobra.Command{
 		Use:   "create APPNAME",
-		Short: "Create an application from a git location",
+		Short: "Create an application",
 		Run: func(c *cobra.Command, args []string) {
 			var app argoappv1.Application
 			argocdClient := argocdclient.NewClientOrDie(clientOpts)
@@ -592,7 +591,7 @@ func addAppFlags(command *cobra.Command, opts *appOptions) {
 	command.Flags().StringVar(&opts.repoURL, "repo", "", "Repository URL, ignored if a file is set")
 	command.Flags().StringVar(&opts.appPath, "path", "", "Path in repository to the ksonnet app directory, ignored if a file is set")
 	command.Flags().StringVar(&opts.env, "env", "", "Application environment to monitor")
-	command.Flags().StringVar(&opts.revision, "revision", "HEAD", "The tracking source branch, tag, or commit the application will sync to")
+	command.Flags().StringVar(&opts.revision, "revision", "", "The tracking source branch, tag, or commit the application will sync to")
 	command.Flags().StringVar(&opts.destServer, "dest-server", "", "K8s cluster URL (overrides the server URL specified in the ksonnet app.yaml)")
 	command.Flags().StringVar(&opts.destNamespace, "dest-namespace", "", "K8s target namespace (overrides the namespace specified in the ksonnet app.yaml)")
 	command.Flags().StringArrayVarP(&opts.parameters, "parameter", "p", []string{}, "set a parameter override (e.g. -p guestbook=image=example/guestbook:latest)")
@@ -726,7 +725,7 @@ func getLocalObjects(app *argoappv1.Application, local string, appLabelKey strin
 }
 
 func getLocalObjectsString(app *argoappv1.Application, local string, appLabelKey string, kustomizeOptions *argoappv1.KustomizeOptions) []string {
-	res, err := repository.GenerateManifests(filepath.Dir(local), filepath.Base(local), &repoapiclient.ManifestRequest{
+	res, err := repository.GenerateManifests(local, &repoapiclient.ManifestRequest{
 		ApplicationSource: &app.Spec.Source,
 		AppLabelKey:       appLabelKey,
 		AppLabelValue:     app.Name,
@@ -1214,10 +1213,6 @@ func NewApplicationSyncCommand(clientOpts *argocdclient.ClientOptions) *cobra.Co
 			if len(selectedLabels) > 0 {
 				ctx := context.Background()
 
-				if revision == "" {
-					revision = "HEAD"
-				}
-
 				q := applicationpkg.ApplicationManifestQuery{
 					Name:     &appName,
 					Revision: revision,
diff --git a/cmd/argocd/commands/project.go b/cmd/argocd/commands/project.go
index 2ee5a55cc5cce..b06c4ebc63f0c 100644
--- a/cmd/argocd/commands/project.go
+++ b/cmd/argocd/commands/project.go
@@ -92,7 +92,7 @@ func addProjFlags(command *cobra.Command, opts *projectOpts) {
 	command.Flags().StringVarP(&opts.description, "description", "", "", "Project description")
 	command.Flags().StringArrayVarP(&opts.destinations, "dest", "d", []string{},
 		"Permitted destination server and namespace (e.g. https://192.168.99.100:8443,default)")
-	command.Flags().StringArrayVarP(&opts.sources, "src", "s", []string{}, "Permitted git source repository URL")
+	command.Flags().StringArrayVarP(&opts.sources, "src", "s", []string{}, "Permitted source repository URL")
 	command.Flags().BoolVar(&opts.orphanedResourcesEnabled, "orphaned-resources", false, "Enables orphaned resources monitoring")
 	command.Flags().BoolVar(&opts.orphanedResourcesWarn, "orphaned-resources-warn", false, "Specifies if applications should be a warning condition when orphaned resources detected")
 }
diff --git a/cmd/argocd/commands/repo.go b/cmd/argocd/commands/repo.go
index c398a84109b15..e97add18d6cf0 100644
--- a/cmd/argocd/commands/repo.go
+++ b/cmd/argocd/commands/repo.go
@@ -23,7 +23,7 @@ import (
 func NewRepoCommand(clientOpts *argocdclient.ClientOptions) *cobra.Command {
 	var command = &cobra.Command{
 		Use:   "repo",
-		Short: "Manage git repository connection parameters",
+		Short: "Manage repository connection parameters",
 		Run: func(c *cobra.Command, args []string) {
 			c.HelpFunc()(c, args)
 			os.Exit(1)
@@ -127,6 +127,8 @@ Add a HTTPS repository using username/password without verifying the server's TL
 			// that were supplied, we bail out.
 			repoAccessReq := repositorypkg.RepoAccessQuery{
 				Repo:              repo.Repo,
+				Type:              repo.Type,
+				Name:              repo.Name,
 				Username:          repo.Username,
 				Password:          repo.Password,
 				SshPrivateKey:     repo.SSHPrivateKey,
@@ -146,6 +148,8 @@ Add a HTTPS repository using username/password without verifying the server's TL
 			fmt.Printf("repository '%s' added\n", createdRepo.Repo)
 		},
 	}
+	command.Flags().StringVar(&repo.Type, "type", "", "type of the repository, \"git\" or \"helm\"")
+	command.Flags().StringVar(&repo.Name, "name", "", "name of the repository")
 	command.Flags().StringVar(&repo.Username, "username", "", "username to the repository")
 	command.Flags().StringVar(&repo.Password, "password", "", "password to the repository")
 	command.Flags().StringVar(&sshPrivateKeyPath, "ssh-private-key-path", "", "path to the private ssh key (e.g. ~/.ssh/id_rsa)")
@@ -162,7 +166,7 @@ Add a HTTPS repository using username/password without verifying the server's TL
 func NewRepoRemoveCommand(clientOpts *argocdclient.ClientOptions) *cobra.Command {
 	var command = &cobra.Command{
 		Use:   "rm REPO",
-		Short: "Remove git repository credentials",
+		Short: "Remove repository credentials",
 		Run: func(c *cobra.Command, args []string) {
 			if len(args) == 0 {
 				c.HelpFunc()(c, args)
@@ -180,9 +184,9 @@ func NewRepoRemoveCommand(clientOpts *argocdclient.ClientOptions) *cobra.Command
 }
 
 // Print table of repo info
-func printRepoTable(repos []appsv1.Repository) {
+func printRepoTable(repos appsv1.Repositories) {
 	w := tabwriter.NewWriter(os.Stdout, 0, 0, 2, ' ', 0)
-	fmt.Fprintf(w, "REPO\tINSECURE\tLFS\tUSER\tSTATUS\tMESSAGE\n")
+	_, _ = fmt.Fprintf(w, "TYPE\nNAME\nREPO\tINSECURE\tLFS\tUSER\tSTATUS\tMESSAGE\n")
 	for _, r := range repos {
 		var username string
 		if r.Username == "" {
@@ -190,13 +194,13 @@ func printRepoTable(repos []appsv1.Repository) {
 		} else {
 			username = r.Username
 		}
-		fmt.Fprintf(w, "%s\t%v\t%v\t%s\t%s\t%s\n", r.Repo, r.IsInsecure(), r.EnableLFS, username, r.ConnectionState.Status, r.ConnectionState.Message)
+		_, _ = fmt.Fprintf(w, "%s\t%s\t%s\t%v\t%v\t%s\t%s\t%s\n", r.Type, r.Name, r.Repo, r.IsInsecure(), r.EnableLFS, username, r.ConnectionState.Status, r.ConnectionState.Message)
 	}
 	_ = w.Flush()
 }
 
 // Print list of repo urls
-func printRepoUrls(repos []appsv1.Repository) {
+func printRepoUrls(repos appsv1.Repositories) {
 	for _, r := range repos {
 		fmt.Println(r.Repo)
 	}
diff --git a/controller/appcontroller.go b/controller/appcontroller.go
index 7d74045ab3835..6ccfcb3a75b0c 100644
--- a/controller/appcontroller.go
+++ b/controller/appcontroller.go
@@ -774,7 +774,7 @@ func (ctrl *ApplicationController) processAppRefreshQueueItem() (processNext boo
 
 	compareResult := ctrl.appStateManager.CompareAppState(app, revision, app.Spec.Source, refreshType == appv1.RefreshTypeHard, localManifests)
 
-	ctrl.normalizeApplication(origApp, app, compareResult.appSourceType)
+	ctrl.normalizeApplication(origApp, app)
 
 	app.Status.Conditions = append(app.Status.Conditions, compareResult.conditions...)
 
@@ -872,9 +872,9 @@ func (ctrl *ApplicationController) refreshAppConditions(app *appv1.Application)
 }
 
 // normalizeApplication normalizes an application.spec and additionally persists updates if it changed
-func (ctrl *ApplicationController) normalizeApplication(orig, app *appv1.Application, sourceType appv1.ApplicationSourceType) {
+func (ctrl *ApplicationController) normalizeApplication(orig, app *appv1.Application) {
 	logCtx := log.WithFields(log.Fields{"application": app.Name})
-	app.Spec = *argo.NormalizeApplicationSpec(&app.Spec, sourceType)
+	app.Spec = *argo.NormalizeApplicationSpec(&app.Spec)
 	patch, modified, err := diff.CreateTwoWayMergePatch(orig, app, appv1.Application{})
 	if err != nil {
 		logCtx.Errorf("error constructing app spec patch: %v", err)
diff --git a/controller/state.go b/controller/state.go
index 106b599247dda..abdf925cb1ebf 100644
--- a/controller/state.go
+++ b/controller/state.go
@@ -88,7 +88,7 @@ type appStateManager struct {
 }
 
 func (m *appStateManager) getRepoObjs(app *v1alpha1.Application, source v1alpha1.ApplicationSource, appLabelKey, revision string, noCache bool) ([]*unstructured.Unstructured, []*unstructured.Unstructured, *apiclient.ManifestResponse, error) {
-	helmRepos, err := m.db.ListHelmRepos(context.Background())
+	repos, err := m.db.ListRepositories(context.Background())
 	if err != nil {
 		return nil, nil, nil, err
 	}
@@ -122,7 +122,7 @@ func (m *appStateManager) getRepoObjs(app *v1alpha1.Application, source v1alpha1
 	}
 	manifestInfo, err := repoClient.GenerateManifest(context.Background(), &apiclient.ManifestRequest{
 		Repo:              repo,
-		HelmRepos:         helmRepos,
+		Repos:             repos,
 		Revision:          revision,
 		NoCache:           noCache,
 		AppLabelKey:       appLabelKey,
diff --git a/controller/state_test.go b/controller/state_test.go
index 1213467fe23c0..9e0167479ed9e 100644
--- a/controller/state_test.go
+++ b/controller/state_test.go
@@ -38,7 +38,7 @@ func TestCompareAppStateEmpty(t *testing.T) {
 	assert.Equal(t, 0, len(compRes.conditions))
 }
 
-// TestCompareAppStateMissing tests when there is a manifest defined in git which doesn't exist in live
+// TestCompareAppStateMissing tests when there is a manifest defined in the repo which doesn't exist in live
 func TestCompareAppStateMissing(t *testing.T) {
 	app := newFakeApp()
 	data := fakeData{
diff --git a/docs/faq.md b/docs/faq.md
index 3aff2d9764f38..8efcab7777548 100644
--- a/docs/faq.md
+++ b/docs/faq.md
@@ -54,8 +54,9 @@ uses only internally available Helm repositories. Even if the chart uses only de
 
 ```yaml
 data:
-  helm.repositories: |
-    - url: http://<internal-helm-repo-host>:8080
+  repositories: |
+    - type: helm
+      url: http://<internal-helm-repo-host>:8080
       name: stable
 ```
 
diff --git a/docs/operator-manual/argocd-cm.yaml b/docs/operator-manual/argocd-cm.yaml
index b01a767aed516..933086d1dff1e 100644
--- a/docs/operator-manual/argocd-cm.yaml
+++ b/docs/operator-manual/argocd-cm.yaml
@@ -67,12 +67,11 @@ data:
       sshPrivateKeySecret:
         name: my-secret
         key: sshPrivateKey
-
-  # Non-standard and private Helm repositories (optional).
-  helm.repositories: |
-    - url: https://storage.googleapis.com/istio-prerelease/daily-build/master-latest-daily/charts
+    - type: helm
+      url: https://storage.googleapis.com/istio-prerelease/daily-build/master-latest-daily/charts
       name: istio.io
-    - url: https://my-private-chart-repo.internal
+    - type: helm
+      url: https://my-private-chart-repo.internal
       name: private-repo
       usernameSecret:
         name: my-secret
diff --git a/docs/operator-manual/declarative-setup.md b/docs/operator-manual/declarative-setup.md
index 7f71d872076cd..affa38d4f5ab6 100644
--- a/docs/operator-manual/declarative-setup.md
+++ b/docs/operator-manual/declarative-setup.md
@@ -412,8 +412,8 @@ stringData:
 
 ## Helm Chart Repositories
 
-Non standard Helm Chart repositories have to be registered under the `helm.repositories` key in the
-`argocd-cm` ConfigMap. Each repository must have `url` and `name` fields. For private Helm repos you
+Non standard Helm Chart repositories have to be registered under the `repositories` key in the
+`argocd-cm` ConfigMap. Each repository must have `url`, `type` and `name` fields. For private Helm repos you
 may need to configure access credentials and HTTPS settings using `usernameSecret`, `passwordSecret`,
 `caSecret`, `certSecret` and `keySecret` fields.
 
@@ -429,10 +429,12 @@ metadata:
     app.kubernetes.io/name: argocd-cm
     app.kubernetes.io/part-of: argocd
 data:
-  helm.repositories: |
-    - url: https://storage.googleapis.com/istio-prerelease/daily-build/master-latest-daily/charts
+  repositories: |
+    - type: helm
+      url: https://storage.googleapis.com/istio-prerelease/daily-build/master-latest-daily/charts
       name: istio.io
-    - url: https://argoproj.github.io/argo-helm
+    - type: helm
+      url: https://argoproj.github.io/argo-helm
       name: argo
       usernameSecret:
         name: my-secret
diff --git a/manifests/crds/application-crd.yaml b/manifests/crds/application-crd.yaml
index fc2a3b9cde47a..779d371722979 100644
--- a/manifests/crds/application-crd.yaml
+++ b/manifests/crds/application-crd.yaml
@@ -412,7 +412,7 @@ spec:
                     type: object
                   type: array
                 revision:
-                  description: Revision is the git revision in which to sync the application
+                  description: Revision is the revision in which to sync the application
                     to. If omitted, will use the revision specified in app spec.
                   type: string
                 source:
@@ -561,7 +561,7 @@ spec:
                           type: string
                       type: object
                     repoURL:
-                      description: RepoURL is the git repository URL of the application
+                      description: RepoURL is the repository URL of the application
                         manifests
                       type: string
                     targetRevision:
@@ -801,8 +801,7 @@ spec:
                       type: string
                   type: object
                 repoURL:
-                  description: RepoURL is the git repository URL of the application
-                    manifests
+                  description: RepoURL is the repository URL of the application manifests
                   type: string
                 targetRevision:
                   description: TargetRevision defines the commit, tag, or branch in
@@ -1012,7 +1011,7 @@ spec:
                             type: string
                         type: object
                       repoURL:
-                        description: RepoURL is the git repository URL of the application
+                        description: RepoURL is the repository URL of the application
                           manifests
                         type: string
                       targetRevision:
@@ -1078,9 +1077,9 @@ spec:
                             type: object
                           type: array
                         revision:
-                          description: Revision is the git revision in which to sync
-                            the application to. If omitted, will use the revision
-                            specified in app spec.
+                          description: Revision is the revision in which to sync the
+                            application to. If omitted, will use the revision specified
+                            in app spec.
                           type: string
                         source:
                           description: Source overrides the source definition set
@@ -1236,8 +1235,8 @@ spec:
                                   type: string
                               type: object
                             repoURL:
-                              description: RepoURL is the git repository URL of the
-                                application manifests
+                              description: RepoURL is the repository URL of the application
+                                manifests
                               type: string
                             targetRevision:
                               description: TargetRevision defines the commit, tag,
@@ -1333,7 +1332,7 @@ spec:
                         type: object
                       type: array
                     revision:
-                      description: Revision holds the git commit SHA of the sync
+                      description: Revision holds the revision of the sync
                       type: string
                     source:
                       description: Source records the application source information
@@ -1484,7 +1483,7 @@ spec:
                               type: string
                           type: object
                         repoURL:
-                          description: RepoURL is the git repository URL of the application
+                          description: RepoURL is the repository URL of the application
                             manifests
                           type: string
                         targetRevision:
@@ -1713,7 +1712,7 @@ spec:
                               type: string
                           type: object
                         repoURL:
-                          description: RepoURL is the git repository URL of the application
+                          description: RepoURL is the repository URL of the application
                             manifests
                           type: string
                         targetRevision:
diff --git a/manifests/crds/appproject-crd.yaml b/manifests/crds/appproject-crd.yaml
index 19a89fdcae586..9d4ed41c374a4 100644
--- a/manifests/crds/appproject-crd.yaml
+++ b/manifests/crds/appproject-crd.yaml
@@ -482,8 +482,8 @@ spec:
                 type: object
               type: array
             sourceRepos:
-              description: SourceRepos contains list of git repository URLs which
-                can be used for deployment
+              description: SourceRepos contains list of repository URLs which can
+                be used for deployment
               items:
                 type: string
               type: array
diff --git a/manifests/ha/install.yaml b/manifests/ha/install.yaml
index d3d344bfca3d4..30f9a7cdf1238 100644
--- a/manifests/ha/install.yaml
+++ b/manifests/ha/install.yaml
@@ -413,7 +413,7 @@ spec:
                     type: object
                   type: array
                 revision:
-                  description: Revision is the git revision in which to sync the application
+                  description: Revision is the revision in which to sync the application
                     to. If omitted, will use the revision specified in app spec.
                   type: string
                 source:
@@ -562,7 +562,7 @@ spec:
                           type: string
                       type: object
                     repoURL:
-                      description: RepoURL is the git repository URL of the application
+                      description: RepoURL is the repository URL of the application
                         manifests
                       type: string
                     targetRevision:
@@ -802,8 +802,7 @@ spec:
                       type: string
                   type: object
                 repoURL:
-                  description: RepoURL is the git repository URL of the application
-                    manifests
+                  description: RepoURL is the repository URL of the application manifests
                   type: string
                 targetRevision:
                   description: TargetRevision defines the commit, tag, or branch in
@@ -1013,7 +1012,7 @@ spec:
                             type: string
                         type: object
                       repoURL:
-                        description: RepoURL is the git repository URL of the application
+                        description: RepoURL is the repository URL of the application
                           manifests
                         type: string
                       targetRevision:
@@ -1079,9 +1078,9 @@ spec:
                             type: object
                           type: array
                         revision:
-                          description: Revision is the git revision in which to sync
-                            the application to. If omitted, will use the revision
-                            specified in app spec.
+                          description: Revision is the revision in which to sync the
+                            application to. If omitted, will use the revision specified
+                            in app spec.
                           type: string
                         source:
                           description: Source overrides the source definition set
@@ -1237,8 +1236,8 @@ spec:
                                   type: string
                               type: object
                             repoURL:
-                              description: RepoURL is the git repository URL of the
-                                application manifests
+                              description: RepoURL is the repository URL of the application
+                                manifests
                               type: string
                             targetRevision:
                               description: TargetRevision defines the commit, tag,
@@ -1334,7 +1333,7 @@ spec:
                         type: object
                       type: array
                     revision:
-                      description: Revision holds the git commit SHA of the sync
+                      description: Revision holds the revision of the sync
                       type: string
                     source:
                       description: Source records the application source information
@@ -1485,7 +1484,7 @@ spec:
                               type: string
                           type: object
                         repoURL:
-                          description: RepoURL is the git repository URL of the application
+                          description: RepoURL is the repository URL of the application
                             manifests
                           type: string
                         targetRevision:
@@ -1714,7 +1713,7 @@ spec:
                               type: string
                           type: object
                         repoURL:
-                          description: RepoURL is the git repository URL of the application
+                          description: RepoURL is the repository URL of the application
                             manifests
                           type: string
                         targetRevision:
@@ -2231,8 +2230,8 @@ spec:
                 type: object
               type: array
             sourceRepos:
-              description: SourceRepos contains list of git repository URLs which
-                can be used for deployment
+              description: SourceRepos contains list of repository URLs which can
+                be used for deployment
               items:
                 type: string
               type: array
diff --git a/manifests/ha/namespace-install.yaml b/manifests/ha/namespace-install.yaml
index 8a7b984dd4306..c4f0ce15eccce 100644
--- a/manifests/ha/namespace-install.yaml
+++ b/manifests/ha/namespace-install.yaml
@@ -413,7 +413,7 @@ spec:
                     type: object
                   type: array
                 revision:
-                  description: Revision is the git revision in which to sync the application
+                  description: Revision is the revision in which to sync the application
                     to. If omitted, will use the revision specified in app spec.
                   type: string
                 source:
@@ -562,7 +562,7 @@ spec:
                           type: string
                       type: object
                     repoURL:
-                      description: RepoURL is the git repository URL of the application
+                      description: RepoURL is the repository URL of the application
                         manifests
                       type: string
                     targetRevision:
@@ -802,8 +802,7 @@ spec:
                       type: string
                   type: object
                 repoURL:
-                  description: RepoURL is the git repository URL of the application
-                    manifests
+                  description: RepoURL is the repository URL of the application manifests
                   type: string
                 targetRevision:
                   description: TargetRevision defines the commit, tag, or branch in
@@ -1013,7 +1012,7 @@ spec:
                             type: string
                         type: object
                       repoURL:
-                        description: RepoURL is the git repository URL of the application
+                        description: RepoURL is the repository URL of the application
                           manifests
                         type: string
                       targetRevision:
@@ -1079,9 +1078,9 @@ spec:
                             type: object
                           type: array
                         revision:
-                          description: Revision is the git revision in which to sync
-                            the application to. If omitted, will use the revision
-                            specified in app spec.
+                          description: Revision is the revision in which to sync the
+                            application to. If omitted, will use the revision specified
+                            in app spec.
                           type: string
                         source:
                           description: Source overrides the source definition set
@@ -1237,8 +1236,8 @@ spec:
                                   type: string
                               type: object
                             repoURL:
-                              description: RepoURL is the git repository URL of the
-                                application manifests
+                              description: RepoURL is the repository URL of the application
+                                manifests
                               type: string
                             targetRevision:
                               description: TargetRevision defines the commit, tag,
@@ -1334,7 +1333,7 @@ spec:
                         type: object
                       type: array
                     revision:
-                      description: Revision holds the git commit SHA of the sync
+                      description: Revision holds the revision of the sync
                       type: string
                     source:
                       description: Source records the application source information
@@ -1485,7 +1484,7 @@ spec:
                               type: string
                           type: object
                         repoURL:
-                          description: RepoURL is the git repository URL of the application
+                          description: RepoURL is the repository URL of the application
                             manifests
                           type: string
                         targetRevision:
@@ -1714,7 +1713,7 @@ spec:
                               type: string
                           type: object
                         repoURL:
-                          description: RepoURL is the git repository URL of the application
+                          description: RepoURL is the repository URL of the application
                             manifests
                           type: string
                         targetRevision:
@@ -2231,8 +2230,8 @@ spec:
                 type: object
               type: array
             sourceRepos:
-              description: SourceRepos contains list of git repository URLs which
-                can be used for deployment
+              description: SourceRepos contains list of repository URLs which can
+                be used for deployment
               items:
                 type: string
               type: array
diff --git a/manifests/install.yaml b/manifests/install.yaml
index fc98ba08a3bf5..9766f68485f02 100644
--- a/manifests/install.yaml
+++ b/manifests/install.yaml
@@ -413,7 +413,7 @@ spec:
                     type: object
                   type: array
                 revision:
-                  description: Revision is the git revision in which to sync the application
+                  description: Revision is the revision in which to sync the application
                     to. If omitted, will use the revision specified in app spec.
                   type: string
                 source:
@@ -562,7 +562,7 @@ spec:
                           type: string
                       type: object
                     repoURL:
-                      description: RepoURL is the git repository URL of the application
+                      description: RepoURL is the repository URL of the application
                         manifests
                       type: string
                     targetRevision:
@@ -802,8 +802,7 @@ spec:
                       type: string
                   type: object
                 repoURL:
-                  description: RepoURL is the git repository URL of the application
-                    manifests
+                  description: RepoURL is the repository URL of the application manifests
                   type: string
                 targetRevision:
                   description: TargetRevision defines the commit, tag, or branch in
@@ -1013,7 +1012,7 @@ spec:
                             type: string
                         type: object
                       repoURL:
-                        description: RepoURL is the git repository URL of the application
+                        description: RepoURL is the repository URL of the application
                           manifests
                         type: string
                       targetRevision:
@@ -1079,9 +1078,9 @@ spec:
                             type: object
                           type: array
                         revision:
-                          description: Revision is the git revision in which to sync
-                            the application to. If omitted, will use the revision
-                            specified in app spec.
+                          description: Revision is the revision in which to sync the
+                            application to. If omitted, will use the revision specified
+                            in app spec.
                           type: string
                         source:
                           description: Source overrides the source definition set
@@ -1237,8 +1236,8 @@ spec:
                                   type: string
                               type: object
                             repoURL:
-                              description: RepoURL is the git repository URL of the
-                                application manifests
+                              description: RepoURL is the repository URL of the application
+                                manifests
                               type: string
                             targetRevision:
                               description: TargetRevision defines the commit, tag,
@@ -1334,7 +1333,7 @@ spec:
                         type: object
                       type: array
                     revision:
-                      description: Revision holds the git commit SHA of the sync
+                      description: Revision holds the revision of the sync
                       type: string
                     source:
                       description: Source records the application source information
@@ -1485,7 +1484,7 @@ spec:
                               type: string
                           type: object
                         repoURL:
-                          description: RepoURL is the git repository URL of the application
+                          description: RepoURL is the repository URL of the application
                             manifests
                           type: string
                         targetRevision:
@@ -1714,7 +1713,7 @@ spec:
                               type: string
                           type: object
                         repoURL:
-                          description: RepoURL is the git repository URL of the application
+                          description: RepoURL is the repository URL of the application
                             manifests
                           type: string
                         targetRevision:
@@ -2231,8 +2230,8 @@ spec:
                 type: object
               type: array
             sourceRepos:
-              description: SourceRepos contains list of git repository URLs which
-                can be used for deployment
+              description: SourceRepos contains list of repository URLs which can
+                be used for deployment
               items:
                 type: string
               type: array
diff --git a/manifests/namespace-install.yaml b/manifests/namespace-install.yaml
index 5742f5e889f63..5c546e26b2a68 100644
--- a/manifests/namespace-install.yaml
+++ b/manifests/namespace-install.yaml
@@ -413,7 +413,7 @@ spec:
                     type: object
                   type: array
                 revision:
-                  description: Revision is the git revision in which to sync the application
+                  description: Revision is the revision in which to sync the application
                     to. If omitted, will use the revision specified in app spec.
                   type: string
                 source:
@@ -562,7 +562,7 @@ spec:
                           type: string
                       type: object
                     repoURL:
-                      description: RepoURL is the git repository URL of the application
+                      description: RepoURL is the repository URL of the application
                         manifests
                       type: string
                     targetRevision:
@@ -802,8 +802,7 @@ spec:
                       type: string
                   type: object
                 repoURL:
-                  description: RepoURL is the git repository URL of the application
-                    manifests
+                  description: RepoURL is the repository URL of the application manifests
                   type: string
                 targetRevision:
                   description: TargetRevision defines the commit, tag, or branch in
@@ -1013,7 +1012,7 @@ spec:
                             type: string
                         type: object
                       repoURL:
-                        description: RepoURL is the git repository URL of the application
+                        description: RepoURL is the repository URL of the application
                           manifests
                         type: string
                       targetRevision:
@@ -1079,9 +1078,9 @@ spec:
                             type: object
                           type: array
                         revision:
-                          description: Revision is the git revision in which to sync
-                            the application to. If omitted, will use the revision
-                            specified in app spec.
+                          description: Revision is the revision in which to sync the
+                            application to. If omitted, will use the revision specified
+                            in app spec.
                           type: string
                         source:
                           description: Source overrides the source definition set
@@ -1237,8 +1236,8 @@ spec:
                                   type: string
                               type: object
                             repoURL:
-                              description: RepoURL is the git repository URL of the
-                                application manifests
+                              description: RepoURL is the repository URL of the application
+                                manifests
                               type: string
                             targetRevision:
                               description: TargetRevision defines the commit, tag,
@@ -1334,7 +1333,7 @@ spec:
                         type: object
                       type: array
                     revision:
-                      description: Revision holds the git commit SHA of the sync
+                      description: Revision holds the revision of the sync
                       type: string
                     source:
                       description: Source records the application source information
@@ -1485,7 +1484,7 @@ spec:
                               type: string
                           type: object
                         repoURL:
-                          description: RepoURL is the git repository URL of the application
+                          description: RepoURL is the repository URL of the application
                             manifests
                           type: string
                         targetRevision:
@@ -1714,7 +1713,7 @@ spec:
                               type: string
                           type: object
                         repoURL:
-                          description: RepoURL is the git repository URL of the application
+                          description: RepoURL is the repository URL of the application
                             manifests
                           type: string
                         targetRevision:
@@ -2231,8 +2230,8 @@ spec:
                 type: object
               type: array
             sourceRepos:
-              description: SourceRepos contains list of git repository URLs which
-                can be used for deployment
+              description: SourceRepos contains list of repository URLs which can
+                be used for deployment
               items:
                 type: string
               type: array
diff --git a/pkg/apiclient/repository/repository.pb.go b/pkg/apiclient/repository/repository.pb.go
index 4a50593f74e58..83cef2fabd96a 100644
--- a/pkg/apiclient/repository/repository.pb.go
+++ b/pkg/apiclient/repository/repository.pb.go
@@ -57,7 +57,7 @@ func (m *RepoAppsQuery) Reset()         { *m = RepoAppsQuery{} }
 func (m *RepoAppsQuery) String() string { return proto.CompactTextString(m) }
 func (*RepoAppsQuery) ProtoMessage()    {}
 func (*RepoAppsQuery) Descriptor() ([]byte, []int) {
-	return fileDescriptor_repository_3b37238e26fe0d6f, []int{0}
+	return fileDescriptor_repository_f708b278e3c45c90, []int{0}
 }
 func (m *RepoAppsQuery) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
@@ -113,7 +113,7 @@ func (m *AppInfo) Reset()         { *m = AppInfo{} }
 func (m *AppInfo) String() string { return proto.CompactTextString(m) }
 func (*AppInfo) ProtoMessage()    {}
 func (*AppInfo) Descriptor() ([]byte, []int) {
-	return fileDescriptor_repository_3b37238e26fe0d6f, []int{1}
+	return fileDescriptor_repository_f708b278e3c45c90, []int{1}
 }
 func (m *AppInfo) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
@@ -172,7 +172,7 @@ func (m *RepoAppDetailsQuery) Reset()         { *m = RepoAppDetailsQuery{} }
 func (m *RepoAppDetailsQuery) String() string { return proto.CompactTextString(m) }
 func (*RepoAppDetailsQuery) ProtoMessage()    {}
 func (*RepoAppDetailsQuery) Descriptor() ([]byte, []int) {
-	return fileDescriptor_repository_3b37238e26fe0d6f, []int{2}
+	return fileDescriptor_repository_f708b278e3c45c90, []int{2}
 }
 func (m *RepoAppDetailsQuery) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
@@ -248,7 +248,7 @@ func (m *RepoAppsResponse) Reset()         { *m = RepoAppsResponse{} }
 func (m *RepoAppsResponse) String() string { return proto.CompactTextString(m) }
 func (*RepoAppsResponse) ProtoMessage()    {}
 func (*RepoAppsResponse) Descriptor() ([]byte, []int) {
-	return fileDescriptor_repository_3b37238e26fe0d6f, []int{3}
+	return fileDescriptor_repository_f708b278e3c45c90, []int{3}
 }
 func (m *RepoAppsResponse) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
@@ -296,7 +296,7 @@ func (m *RepoQuery) Reset()         { *m = RepoQuery{} }
 func (m *RepoQuery) String() string { return proto.CompactTextString(m) }
 func (*RepoQuery) ProtoMessage()    {}
 func (*RepoQuery) Descriptor() ([]byte, []int) {
-	return fileDescriptor_repository_3b37238e26fe0d6f, []int{4}
+	return fileDescriptor_repository_f708b278e3c45c90, []int{4}
 }
 func (m *RepoQuery) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
@@ -347,7 +347,12 @@ type RepoAccessQuery struct {
 	// TLS client cert data for accessing HTTPS repository
 	TlsClientCertData string `protobuf:"bytes,6,opt,name=tlsClientCertData,proto3" json:"tlsClientCertData,omitempty"`
 	// TLS client cert key for accessing HTTPS repository
-	TlsClientCertKey     string   `protobuf:"bytes,7,opt,name=tlsClientCertKey,proto3" json:"tlsClientCertKey,omitempty"`
+	TlsClientCertKey string `protobuf:"bytes,7,opt,name=tlsClientCertKey,proto3" json:"tlsClientCertKey,omitempty"`
+	// TLS client CA data for accessing HTTPS repository
+	TlsClientCAData string `protobuf:"bytes,8,opt,name=tlsClientCAData,proto3" json:"tlsClientCAData,omitempty"`
+	Type            string `protobuf:"bytes,9,opt,name=type,proto3" json:"type,omitempty"`
+	// The name of the repo
+	Name                 string   `protobuf:"bytes,10,opt,name=name,proto3" json:"name,omitempty"`
 	XXX_NoUnkeyedLiteral struct{} `json:"-"`
 	XXX_unrecognized     []byte   `json:"-"`
 	XXX_sizecache        int32    `json:"-"`
@@ -357,7 +362,7 @@ func (m *RepoAccessQuery) Reset()         { *m = RepoAccessQuery{} }
 func (m *RepoAccessQuery) String() string { return proto.CompactTextString(m) }
 func (*RepoAccessQuery) ProtoMessage()    {}
 func (*RepoAccessQuery) Descriptor() ([]byte, []int) {
-	return fileDescriptor_repository_3b37238e26fe0d6f, []int{5}
+	return fileDescriptor_repository_f708b278e3c45c90, []int{5}
 }
 func (m *RepoAccessQuery) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
@@ -435,6 +440,27 @@ func (m *RepoAccessQuery) GetTlsClientCertKey() string {
 	return ""
 }
 
+func (m *RepoAccessQuery) GetTlsClientCAData() string {
+	if m != nil {
+		return m.TlsClientCAData
+	}
+	return ""
+}
+
+func (m *RepoAccessQuery) GetType() string {
+	if m != nil {
+		return m.Type
+	}
+	return ""
+}
+
+func (m *RepoAccessQuery) GetName() string {
+	if m != nil {
+		return m.Name
+	}
+	return ""
+}
+
 type RepoResponse struct {
 	XXX_NoUnkeyedLiteral struct{} `json:"-"`
 	XXX_unrecognized     []byte   `json:"-"`
@@ -445,7 +471,7 @@ func (m *RepoResponse) Reset()         { *m = RepoResponse{} }
 func (m *RepoResponse) String() string { return proto.CompactTextString(m) }
 func (*RepoResponse) ProtoMessage()    {}
 func (*RepoResponse) Descriptor() ([]byte, []int) {
-	return fileDescriptor_repository_3b37238e26fe0d6f, []int{6}
+	return fileDescriptor_repository_f708b278e3c45c90, []int{6}
 }
 func (m *RepoResponse) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
@@ -486,7 +512,7 @@ func (m *RepoCreateRequest) Reset()         { *m = RepoCreateRequest{} }
 func (m *RepoCreateRequest) String() string { return proto.CompactTextString(m) }
 func (*RepoCreateRequest) ProtoMessage()    {}
 func (*RepoCreateRequest) Descriptor() ([]byte, []int) {
-	return fileDescriptor_repository_3b37238e26fe0d6f, []int{7}
+	return fileDescriptor_repository_f708b278e3c45c90, []int{7}
 }
 func (m *RepoCreateRequest) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
@@ -540,7 +566,7 @@ func (m *RepoUpdateRequest) Reset()         { *m = RepoUpdateRequest{} }
 func (m *RepoUpdateRequest) String() string { return proto.CompactTextString(m) }
 func (*RepoUpdateRequest) ProtoMessage()    {}
 func (*RepoUpdateRequest) Descriptor() ([]byte, []int) {
-	return fileDescriptor_repository_3b37238e26fe0d6f, []int{8}
+	return fileDescriptor_repository_f708b278e3c45c90, []int{8}
 }
 func (m *RepoUpdateRequest) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
@@ -1118,6 +1144,24 @@ func (m *RepoAccessQuery) MarshalTo(dAtA []byte) (int, error) {
 		i = encodeVarintRepository(dAtA, i, uint64(len(m.TlsClientCertKey)))
 		i += copy(dAtA[i:], m.TlsClientCertKey)
 	}
+	if len(m.TlsClientCAData) > 0 {
+		dAtA[i] = 0x42
+		i++
+		i = encodeVarintRepository(dAtA, i, uint64(len(m.TlsClientCAData)))
+		i += copy(dAtA[i:], m.TlsClientCAData)
+	}
+	if len(m.Type) > 0 {
+		dAtA[i] = 0x4a
+		i++
+		i = encodeVarintRepository(dAtA, i, uint64(len(m.Type)))
+		i += copy(dAtA[i:], m.Type)
+	}
+	if len(m.Name) > 0 {
+		dAtA[i] = 0x52
+		i++
+		i = encodeVarintRepository(dAtA, i, uint64(len(m.Name)))
+		i += copy(dAtA[i:], m.Name)
+	}
 	if m.XXX_unrecognized != nil {
 		i += copy(dAtA[i:], m.XXX_unrecognized)
 	}
@@ -1347,6 +1391,18 @@ func (m *RepoAccessQuery) Size() (n int) {
 	if l > 0 {
 		n += 1 + l + sovRepository(uint64(l))
 	}
+	l = len(m.TlsClientCAData)
+	if l > 0 {
+		n += 1 + l + sovRepository(uint64(l))
+	}
+	l = len(m.Type)
+	if l > 0 {
+		n += 1 + l + sovRepository(uint64(l))
+	}
+	l = len(m.Name)
+	if l > 0 {
+		n += 1 + l + sovRepository(uint64(l))
+	}
 	if m.XXX_unrecognized != nil {
 		n += len(m.XXX_unrecognized)
 	}
@@ -2211,6 +2267,93 @@ func (m *RepoAccessQuery) Unmarshal(dAtA []byte) error {
 			}
 			m.TlsClientCertKey = string(dAtA[iNdEx:postIndex])
 			iNdEx = postIndex
+		case 8:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field TlsClientCAData", wireType)
+			}
+			var stringLen uint64
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowRepository
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				stringLen |= (uint64(b) & 0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			intStringLen := int(stringLen)
+			if intStringLen < 0 {
+				return ErrInvalidLengthRepository
+			}
+			postIndex := iNdEx + intStringLen
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.TlsClientCAData = string(dAtA[iNdEx:postIndex])
+			iNdEx = postIndex
+		case 9:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Type", wireType)
+			}
+			var stringLen uint64
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowRepository
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				stringLen |= (uint64(b) & 0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			intStringLen := int(stringLen)
+			if intStringLen < 0 {
+				return ErrInvalidLengthRepository
+			}
+			postIndex := iNdEx + intStringLen
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.Type = string(dAtA[iNdEx:postIndex])
+			iNdEx = postIndex
+		case 10:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Name", wireType)
+			}
+			var stringLen uint64
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowRepository
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				stringLen |= (uint64(b) & 0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			intStringLen := int(stringLen)
+			if intStringLen < 0 {
+				return ErrInvalidLengthRepository
+			}
+			postIndex := iNdEx + intStringLen
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.Name = string(dAtA[iNdEx:postIndex])
+			iNdEx = postIndex
 		default:
 			iNdEx = preIndex
 			skippy, err := skipRepository(dAtA[iNdEx:])
@@ -2578,60 +2721,62 @@ var (
 )
 
 func init() {
-	proto.RegisterFile("server/repository/repository.proto", fileDescriptor_repository_3b37238e26fe0d6f)
-}
-
-var fileDescriptor_repository_3b37238e26fe0d6f = []byte{
-	// 815 bytes of a gzipped FileDescriptorProto
-	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x55, 0xcd, 0x6e, 0x23, 0x45,
-	0x10, 0xd6, 0xec, 0x7a, 0x6d, 0xa7, 0x43, 0x96, 0xdd, 0xde, 0x65, 0x65, 0x66, 0xbd, 0x89, 0xd5,
-	0xac, 0x84, 0x77, 0x15, 0x66, 0x64, 0x87, 0x03, 0x42, 0x20, 0x94, 0x1f, 0x04, 0x51, 0x38, 0xc0,
-	0x20, 0x90, 0xe0, 0x00, 0xea, 0x8c, 0x8b, 0x71, 0xe3, 0xf1, 0x74, 0xd3, 0xdd, 0x1e, 0x64, 0x45,
-	0xb9, 0x20, 0x91, 0x07, 0x80, 0x3b, 0x47, 0x9e, 0x85, 0x03, 0x07, 0x24, 0x5e, 0x00, 0x45, 0xbc,
-	0x04, 0x37, 0xd4, 0x3d, 0x3f, 0x1e, 0xff, 0xc4, 0x41, 0x28, 0xda, 0x5b, 0x75, 0x75, 0x55, 0x7d,
-	0x5f, 0xd7, 0x5f, 0x23, 0xa2, 0x40, 0xa6, 0x20, 0x7d, 0x09, 0x82, 0x2b, 0xa6, 0xb9, 0x9c, 0x56,
-	0x44, 0x4f, 0x48, 0xae, 0x39, 0x46, 0x33, 0x8d, 0xfb, 0x30, 0xe2, 0x11, 0xb7, 0x6a, 0xdf, 0x48,
-	0x99, 0x85, 0xdb, 0x8e, 0x38, 0x8f, 0x62, 0xf0, 0xa9, 0x60, 0x3e, 0x4d, 0x12, 0xae, 0xa9, 0x66,
-	0x3c, 0x51, 0xf9, 0x2d, 0x19, 0xbd, 0xa5, 0x3c, 0xc6, 0xed, 0x6d, 0xc8, 0x25, 0xf8, 0x69, 0xcf,
-	0x8f, 0x20, 0x01, 0x49, 0x35, 0x0c, 0x72, 0x9b, 0xe3, 0x88, 0xe9, 0xe1, 0xe4, 0xd4, 0x0b, 0xf9,
-	0xd8, 0xa7, 0xd2, 0x42, 0x7c, 0x6b, 0x85, 0x37, 0xc2, 0x81, 0x2f, 0x46, 0x91, 0x71, 0x56, 0x3e,
-	0x15, 0x22, 0x66, 0xa1, 0x0d, 0xee, 0xa7, 0x3d, 0x1a, 0x8b, 0x21, 0x5d, 0x0e, 0x75, 0xb0, 0x2e,
-	0x94, 0x7d, 0xca, 0xb5, 0x4f, 0x26, 0xef, 0xa1, 0xad, 0x00, 0x04, 0xdf, 0x17, 0x42, 0x7d, 0x32,
-	0x01, 0x39, 0xc5, 0x18, 0xd5, 0x8c, 0x51, 0xcb, 0xe9, 0x38, 0xdd, 0x8d, 0xc0, 0xca, 0xd8, 0x45,
-	0x4d, 0x09, 0x29, 0x53, 0x8c, 0x27, 0xad, 0x5b, 0x56, 0x5f, 0x9e, 0x49, 0x0f, 0x35, 0xf6, 0x85,
-	0x38, 0x4e, 0xbe, 0xe1, 0xc6, 0x55, 0x4f, 0x05, 0x14, 0xae, 0x46, 0x36, 0x3a, 0x41, 0xf5, 0x30,
-	0x77, 0xb3, 0x32, 0xf9, 0xdd, 0x41, 0x0f, 0x72, 0xd0, 0x23, 0xd0, 0x94, 0xc5, 0xff, 0x0f, 0xba,
-	0x8c, 0x7d, 0x7b, 0x16, 0x1b, 0xef, 0xa1, 0xda, 0x10, 0xe2, 0x71, 0xab, 0xd6, 0x71, 0xba, 0x9b,
-	0xfd, 0x1d, 0xaf, 0xf2, 0xe0, 0x0f, 0x21, 0x1e, 0x2f, 0x40, 0x06, 0xd6, 0x18, 0xbf, 0x83, 0x1a,
-	0x23, 0xc5, 0x93, 0x04, 0x74, 0xeb, 0x8e, 0xf5, 0x23, 0x55, 0xbf, 0x93, 0xec, 0x6a, 0xd1, 0xb5,
-	0x70, 0x21, 0xef, 0xa2, 0x7b, 0x45, 0x0a, 0x03, 0x50, 0x82, 0x27, 0x0a, 0xf0, 0x33, 0x74, 0x87,
-	0x69, 0x18, 0xab, 0x96, 0xd3, 0xb9, 0xdd, 0xdd, 0xec, 0x3f, 0xa8, 0xc6, 0xcb, 0xd3, 0x15, 0x64,
-	0x16, 0x64, 0x07, 0x6d, 0x18, 0xf7, 0x2b, 0x53, 0x40, 0xfe, 0x71, 0xd0, 0xcb, 0x16, 0x20, 0x0c,
-	0x41, 0xad, 0x4f, 0xd5, 0x44, 0x81, 0x4c, 0xe8, 0x18, 0x8a, 0x54, 0x15, 0x67, 0x73, 0x27, 0xa8,
-	0x52, 0xdf, 0x73, 0x39, 0xc8, 0xd3, 0x55, 0x9e, 0xf1, 0x53, 0xb4, 0xa5, 0xd4, 0xf0, 0x63, 0xc9,
-	0x52, 0xaa, 0xe1, 0x04, 0xa6, 0x36, 0x77, 0x1b, 0xc1, 0xbc, 0xd2, 0x44, 0x60, 0x89, 0x82, 0x70,
-	0x22, 0xc1, 0x26, 0xa9, 0x19, 0x94, 0x67, 0xbc, 0x8b, 0xee, 0xeb, 0x58, 0x1d, 0xc6, 0x0c, 0x12,
-	0x7d, 0x08, 0x52, 0x1f, 0x51, 0x4d, 0x5b, 0x75, 0x1b, 0x65, 0xf9, 0x02, 0x3f, 0x47, 0xf7, 0xe6,
-	0x94, 0x06, 0xb2, 0x61, 0x8d, 0x97, 0xf4, 0xe4, 0x2e, 0x7a, 0xc9, 0x3c, 0xbd, 0xc8, 0x2b, 0xb9,
-	0x70, 0xd0, 0x7d, 0xa3, 0x38, 0x94, 0x40, 0x35, 0x04, 0xf0, 0xdd, 0x04, 0x94, 0xc6, 0x5f, 0x54,
-	0xb2, 0xb1, 0xd9, 0x7f, 0xdf, 0x9b, 0xcd, 0x85, 0x57, 0xcc, 0x85, 0x15, 0xbe, 0x0e, 0x07, 0x9e,
-	0x18, 0x45, 0x9e, 0x19, 0x31, 0xaf, 0x32, 0x62, 0x5e, 0x31, 0x62, 0x5e, 0x50, 0x96, 0x29, 0x4f,
-	0xea, 0x23, 0x54, 0x9f, 0x08, 0x05, 0x52, 0xdb, 0x94, 0x36, 0x83, 0xfc, 0x44, 0x92, 0x8c, 0xc7,
-	0x67, 0x62, 0xf0, 0x42, 0x78, 0xf4, 0x7f, 0x6d, 0x64, 0x80, 0x99, 0xf2, 0x53, 0x90, 0x29, 0x0b,
-	0x01, 0x5f, 0x38, 0xa8, 0xf6, 0x11, 0x53, 0x1a, 0xbf, 0x52, 0x6d, 0xb0, 0xb2, 0x9d, 0xdc, 0xe3,
-	0x1b, 0xa1, 0x60, 0x10, 0x48, 0xfb, 0x87, 0x3f, 0xff, 0xfe, 0xf9, 0xd6, 0x23, 0xfc, 0xd0, 0x6e,
-	0xb7, 0xb4, 0x37, 0x5b, 0x25, 0x0c, 0x14, 0x1e, 0xa3, 0xa6, 0xb1, 0x32, 0x33, 0x80, 0x5f, 0x5d,
-	0xe4, 0x52, 0x2e, 0x17, 0xb7, 0xbd, 0xea, 0xaa, 0x2c, 0x6e, 0xd7, 0x42, 0x10, 0xdc, 0x59, 0x05,
-	0xe1, 0x9f, 0x99, 0xd3, 0xb9, 0xd9, 0x8c, 0x0a, 0xff, 0xe8, 0xa0, 0xad, 0x0f, 0xaa, 0x23, 0x89,
-	0x77, 0x56, 0x44, 0xae, 0x8e, 0xab, 0x4b, 0xae, 0x36, 0x28, 0x09, 0xf8, 0x96, 0xc0, 0x33, 0xfc,
-	0xfa, 0x75, 0x04, 0xfc, 0x33, 0xb3, 0x6c, 0xce, 0xf1, 0x4f, 0x0e, 0xaa, 0x67, 0xad, 0x88, 0x9f,
-	0x2c, 0xc6, 0x9f, 0x6b, 0x51, 0xf7, 0x66, 0x9a, 0x81, 0x10, 0xcb, 0xb0, 0x4d, 0x56, 0x56, 0xe1,
-	0xed, 0xac, 0x65, 0x7f, 0x71, 0x50, 0x3d, 0xeb, 0xcb, 0x65, 0x52, 0x73, 0xfd, 0x7a, 0x53, 0xa4,
-	0x3c, 0x4b, 0xaa, 0xeb, 0xae, 0xa9, 0x9b, 0xe5, 0x71, 0x9e, 0x13, 0xfc, 0x0a, 0xd5, 0x8f, 0x20,
-	0x06, 0x0d, 0x57, 0xb5, 0x6d, 0x6b, 0x51, 0x5d, 0x56, 0xe8, 0x35, 0x0b, 0xf5, 0xe4, 0xf9, 0xe3,
-	0x35, 0x15, 0xc2, 0x67, 0xe8, 0xee, 0xe7, 0x34, 0x66, 0xe6, 0xa5, 0xd9, 0xce, 0xc4, 0x8f, 0x97,
-	0x8a, 0x3f, 0xdb, 0xa5, 0x6b, 0xd0, 0xfa, 0x16, 0x6d, 0x97, 0x3c, 0x5d, 0xd7, 0x0f, 0x69, 0x0e,
-	0x95, 0x3d, 0xee, 0xe0, 0xe0, 0xb7, 0xcb, 0x6d, 0xe7, 0x8f, 0xcb, 0x6d, 0xe7, 0xaf, 0xcb, 0x6d,
-	0xe7, 0xcb, 0x37, 0xff, 0xc3, 0x6f, 0x1f, 0xda, 0x8d, 0x57, 0xf9, 0x9a, 0x4f, 0xeb, 0xf6, 0x6f,
-	0xde, 0xfb, 0x37, 0x00, 0x00, 0xff, 0xff, 0x6c, 0xda, 0x10, 0xbf, 0xb4, 0x08, 0x00, 0x00,
+	proto.RegisterFile("server/repository/repository.proto", fileDescriptor_repository_f708b278e3c45c90)
+}
+
+var fileDescriptor_repository_f708b278e3c45c90 = []byte{
+	// 838 bytes of a gzipped FileDescriptorProto
+	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x56, 0x5b, 0x8b, 0x23, 0x45,
+	0x14, 0xa6, 0x67, 0xb3, 0xb9, 0xd4, 0x38, 0x7b, 0xa9, 0x5d, 0x97, 0xd8, 0x9b, 0x9d, 0x09, 0xe5,
+	0x82, 0xd9, 0x65, 0xed, 0x26, 0x59, 0x1f, 0x44, 0x14, 0x99, 0x8b, 0xe8, 0xb0, 0x3e, 0x68, 0x8b,
+	0x82, 0x3e, 0x28, 0x35, 0x9d, 0x63, 0xa7, 0x4c, 0xa7, 0xab, 0xac, 0xaa, 0xb4, 0x84, 0x61, 0x5e,
+	0x04, 0xe7, 0x07, 0xe8, 0xbb, 0x8f, 0xfe, 0x16, 0x41, 0x1f, 0x04, 0xff, 0x80, 0x0c, 0xfe, 0x10,
+	0xa9, 0xea, 0x4b, 0x3a, 0x97, 0xc9, 0x88, 0x0c, 0xbe, 0x9d, 0x3a, 0x75, 0xce, 0xf9, 0xbe, 0x3a,
+	0xb7, 0x6e, 0x44, 0x14, 0xc8, 0x14, 0xa4, 0x2f, 0x41, 0x70, 0xc5, 0x34, 0x97, 0xb3, 0x8a, 0xe8,
+	0x09, 0xc9, 0x35, 0xc7, 0x68, 0xae, 0x71, 0xef, 0x47, 0x3c, 0xe2, 0x56, 0xed, 0x1b, 0x29, 0xb3,
+	0x70, 0x3b, 0x11, 0xe7, 0x51, 0x0c, 0x3e, 0x15, 0xcc, 0xa7, 0x49, 0xc2, 0x35, 0xd5, 0x8c, 0x27,
+	0x2a, 0xbf, 0x25, 0xe3, 0x37, 0x95, 0xc7, 0xb8, 0xbd, 0x0d, 0xb9, 0x04, 0x3f, 0xed, 0xfb, 0x11,
+	0x24, 0x20, 0xa9, 0x86, 0x61, 0x6e, 0x73, 0x1c, 0x31, 0x3d, 0x9a, 0x9e, 0x78, 0x21, 0x9f, 0xf8,
+	0x54, 0x5a, 0x88, 0x6f, 0xac, 0xf0, 0x7a, 0x38, 0xf4, 0xc5, 0x38, 0x32, 0xce, 0xca, 0xa7, 0x42,
+	0xc4, 0x2c, 0xb4, 0xc1, 0xfd, 0xb4, 0x4f, 0x63, 0x31, 0xa2, 0xab, 0xa1, 0x0e, 0x36, 0x85, 0xb2,
+	0x4f, 0xb9, 0xf2, 0xc9, 0xe4, 0x5d, 0xb4, 0x13, 0x80, 0xe0, 0xfb, 0x42, 0xa8, 0x8f, 0xa7, 0x20,
+	0x67, 0x18, 0xa3, 0x9a, 0x31, 0x6a, 0x3b, 0x5d, 0xa7, 0xd7, 0x0a, 0xac, 0x8c, 0x5d, 0xd4, 0x94,
+	0x90, 0x32, 0xc5, 0x78, 0xd2, 0xde, 0xb2, 0xfa, 0xf2, 0x4c, 0xfa, 0xa8, 0xb1, 0x2f, 0xc4, 0x71,
+	0xf2, 0x35, 0x37, 0xae, 0x7a, 0x26, 0xa0, 0x70, 0x35, 0xb2, 0xd1, 0x09, 0xaa, 0x47, 0xb9, 0x9b,
+	0x95, 0xc9, 0xef, 0x0e, 0xba, 0x97, 0x83, 0x1e, 0x81, 0xa6, 0x2c, 0xfe, 0x6f, 0xd0, 0x65, 0xec,
+	0x1b, 0xf3, 0xd8, 0xf8, 0x39, 0xaa, 0x8d, 0x20, 0x9e, 0xb4, 0x6b, 0x5d, 0xa7, 0xb7, 0x3d, 0xd8,
+	0xf3, 0x2a, 0x0f, 0xfe, 0x00, 0xe2, 0xc9, 0x12, 0x64, 0x60, 0x8d, 0xf1, 0xdb, 0xa8, 0x31, 0x56,
+	0x3c, 0x49, 0x40, 0xb7, 0x6f, 0x5a, 0x3f, 0x52, 0xf5, 0x7b, 0x91, 0x5d, 0x2d, 0xbb, 0x16, 0x2e,
+	0xe4, 0x1d, 0x74, 0xa7, 0x48, 0x61, 0x00, 0x4a, 0xf0, 0x44, 0x01, 0x7e, 0x82, 0x6e, 0x32, 0x0d,
+	0x13, 0xd5, 0x76, 0xba, 0x37, 0x7a, 0xdb, 0x83, 0x7b, 0xd5, 0x78, 0x79, 0xba, 0x82, 0xcc, 0x82,
+	0xec, 0xa1, 0x96, 0x71, 0xbf, 0x34, 0x05, 0xe4, 0xb7, 0x2d, 0x74, 0xdb, 0x02, 0x84, 0x21, 0xa8,
+	0xcd, 0xa9, 0x9a, 0x2a, 0x90, 0x09, 0x9d, 0x40, 0x91, 0xaa, 0xe2, 0x6c, 0xee, 0x04, 0x55, 0xea,
+	0x3b, 0x2e, 0x87, 0x79, 0xba, 0xca, 0x33, 0x7e, 0x8c, 0x76, 0x94, 0x1a, 0x7d, 0x24, 0x59, 0x4a,
+	0x35, 0xbc, 0x80, 0x99, 0xcd, 0x5d, 0x2b, 0x58, 0x54, 0x9a, 0x08, 0x2c, 0x51, 0x10, 0x4e, 0x25,
+	0xd8, 0x24, 0x35, 0x83, 0xf2, 0x8c, 0x9f, 0xa1, 0xbb, 0x3a, 0x56, 0x87, 0x31, 0x83, 0x44, 0x1f,
+	0x82, 0xd4, 0x47, 0x54, 0xd3, 0x76, 0xdd, 0x46, 0x59, 0xbd, 0xc0, 0x4f, 0xd1, 0x9d, 0x05, 0xa5,
+	0x81, 0x6c, 0x58, 0xe3, 0x15, 0x3d, 0xee, 0xa1, 0xdb, 0x73, 0xdd, 0xbe, 0x8d, 0xdb, 0xb4, 0xa6,
+	0xcb, 0xea, 0xb2, 0xf9, 0x5a, 0x8b, 0xcd, 0x67, 0xb3, 0x81, 0x32, 0x9d, 0x91, 0xc9, 0x2d, 0xf4,
+	0x92, 0x49, 0x66, 0x51, 0x29, 0x72, 0xee, 0xa0, 0xbb, 0x46, 0x71, 0x28, 0x81, 0x6a, 0x08, 0xe0,
+	0xdb, 0x29, 0x28, 0x8d, 0x3f, 0xaf, 0xe4, 0x77, 0x7b, 0xf0, 0x9e, 0x37, 0x9f, 0x34, 0xaf, 0x98,
+	0x34, 0x2b, 0x7c, 0x15, 0x0e, 0x3d, 0x31, 0x8e, 0x3c, 0x33, 0xb4, 0x5e, 0x65, 0x68, 0xbd, 0x62,
+	0x68, 0xbd, 0xa0, 0x2c, 0x7c, 0x5e, 0xa6, 0x07, 0xa8, 0x3e, 0x15, 0x0a, 0xa4, 0xb6, 0x45, 0x6a,
+	0x06, 0xf9, 0x89, 0x24, 0x19, 0x8f, 0x4f, 0xc5, 0xf0, 0x7f, 0xe1, 0x31, 0xf8, 0xa5, 0x91, 0x01,
+	0x66, 0xca, 0x4f, 0x40, 0xa6, 0x2c, 0x04, 0x7c, 0xee, 0xa0, 0xda, 0x87, 0x4c, 0x69, 0xfc, 0x72,
+	0xb5, 0x65, 0xcb, 0x06, 0x75, 0x8f, 0xaf, 0x85, 0x82, 0x41, 0x20, 0x9d, 0xef, 0xff, 0xfc, 0xfb,
+	0xa7, 0xad, 0x07, 0xf8, 0xbe, 0xdd, 0x97, 0x69, 0x7f, 0xbe, 0x9c, 0x18, 0x28, 0x3c, 0x41, 0x4d,
+	0x63, 0x65, 0xa6, 0x0a, 0xbf, 0xb2, 0xcc, 0xa5, 0x5c, 0x57, 0x6e, 0x67, 0xdd, 0x55, 0x59, 0xdc,
+	0x9e, 0x85, 0x20, 0xb8, 0xbb, 0x0e, 0xc2, 0x3f, 0x35, 0xa7, 0x33, 0xb3, 0x6b, 0x15, 0xfe, 0xc1,
+	0x41, 0x3b, 0xef, 0x57, 0x87, 0x1c, 0xef, 0xad, 0x89, 0x5c, 0x5d, 0x00, 0x2e, 0xb9, 0xdc, 0xa0,
+	0x24, 0xe0, 0x5b, 0x02, 0x4f, 0xf0, 0x6b, 0x57, 0x11, 0xf0, 0x4f, 0xcd, 0xfa, 0x3a, 0xc3, 0x3f,
+	0x3a, 0xa8, 0x9e, 0xb5, 0x22, 0x7e, 0xb4, 0x1c, 0x7f, 0xa1, 0x45, 0xdd, 0xeb, 0x69, 0x06, 0x42,
+	0x2c, 0xc3, 0x0e, 0x59, 0x5b, 0x85, 0xb7, 0xb2, 0x96, 0xfd, 0xd9, 0x41, 0xf5, 0xac, 0x2f, 0x57,
+	0x49, 0x2d, 0xf4, 0xeb, 0x75, 0x91, 0xf2, 0x2c, 0xa9, 0x9e, 0xbb, 0xa1, 0x6e, 0x96, 0xc7, 0x59,
+	0x4e, 0xf0, 0x4b, 0x54, 0x3f, 0x82, 0x18, 0x34, 0x5c, 0xd6, 0xb6, 0xed, 0x65, 0x75, 0x59, 0xa1,
+	0x57, 0x2d, 0xd4, 0xa3, 0xa7, 0x0f, 0x37, 0x54, 0x08, 0x9f, 0xa2, 0x5b, 0x9f, 0xd1, 0x98, 0x99,
+	0x97, 0x66, 0x5b, 0x18, 0x3f, 0x5c, 0x29, 0xfe, 0x7c, 0x3b, 0x6f, 0x40, 0x1b, 0x58, 0xb4, 0x67,
+	0xe4, 0xf1, 0xa6, 0x7e, 0x48, 0x73, 0xa8, 0xec, 0x71, 0x07, 0x07, 0xbf, 0x5e, 0xec, 0x3a, 0x7f,
+	0x5c, 0xec, 0x3a, 0x7f, 0x5d, 0xec, 0x3a, 0x5f, 0xbc, 0xf1, 0x2f, 0xfe, 0x1f, 0x42, 0xbb, 0x18,
+	0x2b, 0x1f, 0xfb, 0x93, 0xba, 0xfd, 0xda, 0x3f, 0xff, 0x27, 0x00, 0x00, 0xff, 0xff, 0xf7, 0x29,
+	0xcd, 0xc6, 0x06, 0x09, 0x00, 0x00,
 }
diff --git a/pkg/apis/api-rules/violation_exceptions.list b/pkg/apis/api-rules/violation_exceptions.list
index 18abf317b3a64..d4cf72c92047b 100644
--- a/pkg/apis/api-rules/violation_exceptions.list
+++ b/pkg/apis/api-rules/violation_exceptions.list
@@ -4,6 +4,7 @@ API rule violation: names_match,github.com/argoproj/argo-cd/pkg/apis/application
 API rule violation: names_match,github.com/argoproj/argo-cd/pkg/apis/application/v1alpha1,JWTToken,IssuedAt
 API rule violation: names_match,github.com/argoproj/argo-cd/pkg/apis/application/v1alpha1,KustomizeOptions,BuildOptions
 API rule violation: names_match,github.com/argoproj/argo-cd/pkg/apis/application/v1alpha1,Repository,EnableLFS
+API rule violation: names_match,github.com/argoproj/argo-cd/pkg/apis/application/v1alpha1,Repository,TLSClientCAData
 API rule violation: names_match,github.com/argoproj/argo-cd/pkg/apis/application/v1alpha1,ResourceActionDefinition,ActionLua
 API rule violation: names_match,github.com/argoproj/argo-cd/pkg/apis/application/v1alpha1,ResourceActions,ActionDiscoveryLua
 API rule violation: names_match,github.com/argoproj/argo-cd/pkg/apis/application/v1alpha1,ResourceOverride,HealthLua
diff --git a/pkg/apis/application/v1alpha1/generated.pb.go b/pkg/apis/application/v1alpha1/generated.pb.go
index 7f37142259c0e..77b6f42905880 100644
--- a/pkg/apis/application/v1alpha1/generated.pb.go
+++ b/pkg/apis/application/v1alpha1/generated.pb.go
@@ -39,7 +39,7 @@ const _ = proto.GoGoProtoPackageIsVersion2 // please upgrade the proto package
 func (m *AWSAuthConfig) Reset()      { *m = AWSAuthConfig{} }
 func (*AWSAuthConfig) ProtoMessage() {}
 func (*AWSAuthConfig) Descriptor() ([]byte, []int) {
-	return fileDescriptor_generated_1d3c532c66f98f76, []int{0}
+	return fileDescriptor_generated_ee2cf7a8fb926224, []int{0}
 }
 func (m *AWSAuthConfig) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
@@ -67,7 +67,7 @@ var xxx_messageInfo_AWSAuthConfig proto.InternalMessageInfo
 func (m *AppProject) Reset()      { *m = AppProject{} }
 func (*AppProject) ProtoMessage() {}
 func (*AppProject) Descriptor() ([]byte, []int) {
-	return fileDescriptor_generated_1d3c532c66f98f76, []int{1}
+	return fileDescriptor_generated_ee2cf7a8fb926224, []int{1}
 }
 func (m *AppProject) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
@@ -95,7 +95,7 @@ var xxx_messageInfo_AppProject proto.InternalMessageInfo
 func (m *AppProjectList) Reset()      { *m = AppProjectList{} }
 func (*AppProjectList) ProtoMessage() {}
 func (*AppProjectList) Descriptor() ([]byte, []int) {
-	return fileDescriptor_generated_1d3c532c66f98f76, []int{2}
+	return fileDescriptor_generated_ee2cf7a8fb926224, []int{2}
 }
 func (m *AppProjectList) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
@@ -123,7 +123,7 @@ var xxx_messageInfo_AppProjectList proto.InternalMessageInfo
 func (m *AppProjectSpec) Reset()      { *m = AppProjectSpec{} }
 func (*AppProjectSpec) ProtoMessage() {}
 func (*AppProjectSpec) Descriptor() ([]byte, []int) {
-	return fileDescriptor_generated_1d3c532c66f98f76, []int{3}
+	return fileDescriptor_generated_ee2cf7a8fb926224, []int{3}
 }
 func (m *AppProjectSpec) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
@@ -151,7 +151,7 @@ var xxx_messageInfo_AppProjectSpec proto.InternalMessageInfo
 func (m *Application) Reset()      { *m = Application{} }
 func (*Application) ProtoMessage() {}
 func (*Application) Descriptor() ([]byte, []int) {
-	return fileDescriptor_generated_1d3c532c66f98f76, []int{4}
+	return fileDescriptor_generated_ee2cf7a8fb926224, []int{4}
 }
 func (m *Application) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
@@ -179,7 +179,7 @@ var xxx_messageInfo_Application proto.InternalMessageInfo
 func (m *ApplicationCondition) Reset()      { *m = ApplicationCondition{} }
 func (*ApplicationCondition) ProtoMessage() {}
 func (*ApplicationCondition) Descriptor() ([]byte, []int) {
-	return fileDescriptor_generated_1d3c532c66f98f76, []int{5}
+	return fileDescriptor_generated_ee2cf7a8fb926224, []int{5}
 }
 func (m *ApplicationCondition) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
@@ -207,7 +207,7 @@ var xxx_messageInfo_ApplicationCondition proto.InternalMessageInfo
 func (m *ApplicationDestination) Reset()      { *m = ApplicationDestination{} }
 func (*ApplicationDestination) ProtoMessage() {}
 func (*ApplicationDestination) Descriptor() ([]byte, []int) {
-	return fileDescriptor_generated_1d3c532c66f98f76, []int{6}
+	return fileDescriptor_generated_ee2cf7a8fb926224, []int{6}
 }
 func (m *ApplicationDestination) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
@@ -235,7 +235,7 @@ var xxx_messageInfo_ApplicationDestination proto.InternalMessageInfo
 func (m *ApplicationList) Reset()      { *m = ApplicationList{} }
 func (*ApplicationList) ProtoMessage() {}
 func (*ApplicationList) Descriptor() ([]byte, []int) {
-	return fileDescriptor_generated_1d3c532c66f98f76, []int{7}
+	return fileDescriptor_generated_ee2cf7a8fb926224, []int{7}
 }
 func (m *ApplicationList) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
@@ -263,7 +263,7 @@ var xxx_messageInfo_ApplicationList proto.InternalMessageInfo
 func (m *ApplicationSource) Reset()      { *m = ApplicationSource{} }
 func (*ApplicationSource) ProtoMessage() {}
 func (*ApplicationSource) Descriptor() ([]byte, []int) {
-	return fileDescriptor_generated_1d3c532c66f98f76, []int{8}
+	return fileDescriptor_generated_ee2cf7a8fb926224, []int{8}
 }
 func (m *ApplicationSource) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
@@ -291,7 +291,7 @@ var xxx_messageInfo_ApplicationSource proto.InternalMessageInfo
 func (m *ApplicationSourceDirectory) Reset()      { *m = ApplicationSourceDirectory{} }
 func (*ApplicationSourceDirectory) ProtoMessage() {}
 func (*ApplicationSourceDirectory) Descriptor() ([]byte, []int) {
-	return fileDescriptor_generated_1d3c532c66f98f76, []int{9}
+	return fileDescriptor_generated_ee2cf7a8fb926224, []int{9}
 }
 func (m *ApplicationSourceDirectory) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
@@ -319,7 +319,7 @@ var xxx_messageInfo_ApplicationSourceDirectory proto.InternalMessageInfo
 func (m *ApplicationSourceHelm) Reset()      { *m = ApplicationSourceHelm{} }
 func (*ApplicationSourceHelm) ProtoMessage() {}
 func (*ApplicationSourceHelm) Descriptor() ([]byte, []int) {
-	return fileDescriptor_generated_1d3c532c66f98f76, []int{10}
+	return fileDescriptor_generated_ee2cf7a8fb926224, []int{10}
 }
 func (m *ApplicationSourceHelm) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
@@ -347,7 +347,7 @@ var xxx_messageInfo_ApplicationSourceHelm proto.InternalMessageInfo
 func (m *ApplicationSourceJsonnet) Reset()      { *m = ApplicationSourceJsonnet{} }
 func (*ApplicationSourceJsonnet) ProtoMessage() {}
 func (*ApplicationSourceJsonnet) Descriptor() ([]byte, []int) {
-	return fileDescriptor_generated_1d3c532c66f98f76, []int{11}
+	return fileDescriptor_generated_ee2cf7a8fb926224, []int{11}
 }
 func (m *ApplicationSourceJsonnet) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
@@ -375,7 +375,7 @@ var xxx_messageInfo_ApplicationSourceJsonnet proto.InternalMessageInfo
 func (m *ApplicationSourceKsonnet) Reset()      { *m = ApplicationSourceKsonnet{} }
 func (*ApplicationSourceKsonnet) ProtoMessage() {}
 func (*ApplicationSourceKsonnet) Descriptor() ([]byte, []int) {
-	return fileDescriptor_generated_1d3c532c66f98f76, []int{12}
+	return fileDescriptor_generated_ee2cf7a8fb926224, []int{12}
 }
 func (m *ApplicationSourceKsonnet) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
@@ -403,7 +403,7 @@ var xxx_messageInfo_ApplicationSourceKsonnet proto.InternalMessageInfo
 func (m *ApplicationSourceKustomize) Reset()      { *m = ApplicationSourceKustomize{} }
 func (*ApplicationSourceKustomize) ProtoMessage() {}
 func (*ApplicationSourceKustomize) Descriptor() ([]byte, []int) {
-	return fileDescriptor_generated_1d3c532c66f98f76, []int{13}
+	return fileDescriptor_generated_ee2cf7a8fb926224, []int{13}
 }
 func (m *ApplicationSourceKustomize) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
@@ -431,7 +431,7 @@ var xxx_messageInfo_ApplicationSourceKustomize proto.InternalMessageInfo
 func (m *ApplicationSourcePlugin) Reset()      { *m = ApplicationSourcePlugin{} }
 func (*ApplicationSourcePlugin) ProtoMessage() {}
 func (*ApplicationSourcePlugin) Descriptor() ([]byte, []int) {
-	return fileDescriptor_generated_1d3c532c66f98f76, []int{14}
+	return fileDescriptor_generated_ee2cf7a8fb926224, []int{14}
 }
 func (m *ApplicationSourcePlugin) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
@@ -459,7 +459,7 @@ var xxx_messageInfo_ApplicationSourcePlugin proto.InternalMessageInfo
 func (m *ApplicationSpec) Reset()      { *m = ApplicationSpec{} }
 func (*ApplicationSpec) ProtoMessage() {}
 func (*ApplicationSpec) Descriptor() ([]byte, []int) {
-	return fileDescriptor_generated_1d3c532c66f98f76, []int{15}
+	return fileDescriptor_generated_ee2cf7a8fb926224, []int{15}
 }
 func (m *ApplicationSpec) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
@@ -487,7 +487,7 @@ var xxx_messageInfo_ApplicationSpec proto.InternalMessageInfo
 func (m *ApplicationStatus) Reset()      { *m = ApplicationStatus{} }
 func (*ApplicationStatus) ProtoMessage() {}
 func (*ApplicationStatus) Descriptor() ([]byte, []int) {
-	return fileDescriptor_generated_1d3c532c66f98f76, []int{16}
+	return fileDescriptor_generated_ee2cf7a8fb926224, []int{16}
 }
 func (m *ApplicationStatus) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
@@ -515,7 +515,7 @@ var xxx_messageInfo_ApplicationStatus proto.InternalMessageInfo
 func (m *ApplicationSummary) Reset()      { *m = ApplicationSummary{} }
 func (*ApplicationSummary) ProtoMessage() {}
 func (*ApplicationSummary) Descriptor() ([]byte, []int) {
-	return fileDescriptor_generated_1d3c532c66f98f76, []int{17}
+	return fileDescriptor_generated_ee2cf7a8fb926224, []int{17}
 }
 func (m *ApplicationSummary) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
@@ -543,7 +543,7 @@ var xxx_messageInfo_ApplicationSummary proto.InternalMessageInfo
 func (m *ApplicationTree) Reset()      { *m = ApplicationTree{} }
 func (*ApplicationTree) ProtoMessage() {}
 func (*ApplicationTree) Descriptor() ([]byte, []int) {
-	return fileDescriptor_generated_1d3c532c66f98f76, []int{18}
+	return fileDescriptor_generated_ee2cf7a8fb926224, []int{18}
 }
 func (m *ApplicationTree) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
@@ -571,7 +571,7 @@ var xxx_messageInfo_ApplicationTree proto.InternalMessageInfo
 func (m *ApplicationWatchEvent) Reset()      { *m = ApplicationWatchEvent{} }
 func (*ApplicationWatchEvent) ProtoMessage() {}
 func (*ApplicationWatchEvent) Descriptor() ([]byte, []int) {
-	return fileDescriptor_generated_1d3c532c66f98f76, []int{19}
+	return fileDescriptor_generated_ee2cf7a8fb926224, []int{19}
 }
 func (m *ApplicationWatchEvent) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
@@ -599,7 +599,7 @@ var xxx_messageInfo_ApplicationWatchEvent proto.InternalMessageInfo
 func (m *Cluster) Reset()      { *m = Cluster{} }
 func (*Cluster) ProtoMessage() {}
 func (*Cluster) Descriptor() ([]byte, []int) {
-	return fileDescriptor_generated_1d3c532c66f98f76, []int{20}
+	return fileDescriptor_generated_ee2cf7a8fb926224, []int{20}
 }
 func (m *Cluster) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
@@ -627,7 +627,7 @@ var xxx_messageInfo_Cluster proto.InternalMessageInfo
 func (m *ClusterConfig) Reset()      { *m = ClusterConfig{} }
 func (*ClusterConfig) ProtoMessage() {}
 func (*ClusterConfig) Descriptor() ([]byte, []int) {
-	return fileDescriptor_generated_1d3c532c66f98f76, []int{21}
+	return fileDescriptor_generated_ee2cf7a8fb926224, []int{21}
 }
 func (m *ClusterConfig) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
@@ -655,7 +655,7 @@ var xxx_messageInfo_ClusterConfig proto.InternalMessageInfo
 func (m *ClusterList) Reset()      { *m = ClusterList{} }
 func (*ClusterList) ProtoMessage() {}
 func (*ClusterList) Descriptor() ([]byte, []int) {
-	return fileDescriptor_generated_1d3c532c66f98f76, []int{22}
+	return fileDescriptor_generated_ee2cf7a8fb926224, []int{22}
 }
 func (m *ClusterList) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
@@ -683,7 +683,7 @@ var xxx_messageInfo_ClusterList proto.InternalMessageInfo
 func (m *Command) Reset()      { *m = Command{} }
 func (*Command) ProtoMessage() {}
 func (*Command) Descriptor() ([]byte, []int) {
-	return fileDescriptor_generated_1d3c532c66f98f76, []int{23}
+	return fileDescriptor_generated_ee2cf7a8fb926224, []int{23}
 }
 func (m *Command) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
@@ -711,7 +711,7 @@ var xxx_messageInfo_Command proto.InternalMessageInfo
 func (m *ComparedTo) Reset()      { *m = ComparedTo{} }
 func (*ComparedTo) ProtoMessage() {}
 func (*ComparedTo) Descriptor() ([]byte, []int) {
-	return fileDescriptor_generated_1d3c532c66f98f76, []int{24}
+	return fileDescriptor_generated_ee2cf7a8fb926224, []int{24}
 }
 func (m *ComparedTo) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
@@ -739,7 +739,7 @@ var xxx_messageInfo_ComparedTo proto.InternalMessageInfo
 func (m *ComponentParameter) Reset()      { *m = ComponentParameter{} }
 func (*ComponentParameter) ProtoMessage() {}
 func (*ComponentParameter) Descriptor() ([]byte, []int) {
-	return fileDescriptor_generated_1d3c532c66f98f76, []int{25}
+	return fileDescriptor_generated_ee2cf7a8fb926224, []int{25}
 }
 func (m *ComponentParameter) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
@@ -767,7 +767,7 @@ var xxx_messageInfo_ComponentParameter proto.InternalMessageInfo
 func (m *ConfigManagementPlugin) Reset()      { *m = ConfigManagementPlugin{} }
 func (*ConfigManagementPlugin) ProtoMessage() {}
 func (*ConfigManagementPlugin) Descriptor() ([]byte, []int) {
-	return fileDescriptor_generated_1d3c532c66f98f76, []int{26}
+	return fileDescriptor_generated_ee2cf7a8fb926224, []int{26}
 }
 func (m *ConfigManagementPlugin) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
@@ -795,7 +795,7 @@ var xxx_messageInfo_ConfigManagementPlugin proto.InternalMessageInfo
 func (m *ConnectionState) Reset()      { *m = ConnectionState{} }
 func (*ConnectionState) ProtoMessage() {}
 func (*ConnectionState) Descriptor() ([]byte, []int) {
-	return fileDescriptor_generated_1d3c532c66f98f76, []int{27}
+	return fileDescriptor_generated_ee2cf7a8fb926224, []int{27}
 }
 func (m *ConnectionState) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
@@ -823,7 +823,7 @@ var xxx_messageInfo_ConnectionState proto.InternalMessageInfo
 func (m *EnvEntry) Reset()      { *m = EnvEntry{} }
 func (*EnvEntry) ProtoMessage() {}
 func (*EnvEntry) Descriptor() ([]byte, []int) {
-	return fileDescriptor_generated_1d3c532c66f98f76, []int{28}
+	return fileDescriptor_generated_ee2cf7a8fb926224, []int{28}
 }
 func (m *EnvEntry) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
@@ -851,7 +851,7 @@ var xxx_messageInfo_EnvEntry proto.InternalMessageInfo
 func (m *HealthStatus) Reset()      { *m = HealthStatus{} }
 func (*HealthStatus) ProtoMessage() {}
 func (*HealthStatus) Descriptor() ([]byte, []int) {
-	return fileDescriptor_generated_1d3c532c66f98f76, []int{29}
+	return fileDescriptor_generated_ee2cf7a8fb926224, []int{29}
 }
 func (m *HealthStatus) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
@@ -879,7 +879,7 @@ var xxx_messageInfo_HealthStatus proto.InternalMessageInfo
 func (m *HelmParameter) Reset()      { *m = HelmParameter{} }
 func (*HelmParameter) ProtoMessage() {}
 func (*HelmParameter) Descriptor() ([]byte, []int) {
-	return fileDescriptor_generated_1d3c532c66f98f76, []int{30}
+	return fileDescriptor_generated_ee2cf7a8fb926224, []int{30}
 }
 func (m *HelmParameter) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
@@ -904,38 +904,10 @@ func (m *HelmParameter) XXX_DiscardUnknown() {
 
 var xxx_messageInfo_HelmParameter proto.InternalMessageInfo
 
-func (m *HelmRepository) Reset()      { *m = HelmRepository{} }
-func (*HelmRepository) ProtoMessage() {}
-func (*HelmRepository) Descriptor() ([]byte, []int) {
-	return fileDescriptor_generated_1d3c532c66f98f76, []int{31}
-}
-func (m *HelmRepository) XXX_Unmarshal(b []byte) error {
-	return m.Unmarshal(b)
-}
-func (m *HelmRepository) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
-	b = b[:cap(b)]
-	n, err := m.MarshalTo(b)
-	if err != nil {
-		return nil, err
-	}
-	return b[:n], nil
-}
-func (dst *HelmRepository) XXX_Merge(src proto.Message) {
-	xxx_messageInfo_HelmRepository.Merge(dst, src)
-}
-func (m *HelmRepository) XXX_Size() int {
-	return m.Size()
-}
-func (m *HelmRepository) XXX_DiscardUnknown() {
-	xxx_messageInfo_HelmRepository.DiscardUnknown(m)
-}
-
-var xxx_messageInfo_HelmRepository proto.InternalMessageInfo
-
 func (m *Info) Reset()      { *m = Info{} }
 func (*Info) ProtoMessage() {}
 func (*Info) Descriptor() ([]byte, []int) {
-	return fileDescriptor_generated_1d3c532c66f98f76, []int{32}
+	return fileDescriptor_generated_ee2cf7a8fb926224, []int{31}
 }
 func (m *Info) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
@@ -963,7 +935,7 @@ var xxx_messageInfo_Info proto.InternalMessageInfo
 func (m *InfoItem) Reset()      { *m = InfoItem{} }
 func (*InfoItem) ProtoMessage() {}
 func (*InfoItem) Descriptor() ([]byte, []int) {
-	return fileDescriptor_generated_1d3c532c66f98f76, []int{33}
+	return fileDescriptor_generated_ee2cf7a8fb926224, []int{32}
 }
 func (m *InfoItem) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
@@ -991,7 +963,7 @@ var xxx_messageInfo_InfoItem proto.InternalMessageInfo
 func (m *JWTToken) Reset()      { *m = JWTToken{} }
 func (*JWTToken) ProtoMessage() {}
 func (*JWTToken) Descriptor() ([]byte, []int) {
-	return fileDescriptor_generated_1d3c532c66f98f76, []int{34}
+	return fileDescriptor_generated_ee2cf7a8fb926224, []int{33}
 }
 func (m *JWTToken) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
@@ -1019,7 +991,7 @@ var xxx_messageInfo_JWTToken proto.InternalMessageInfo
 func (m *JsonnetVar) Reset()      { *m = JsonnetVar{} }
 func (*JsonnetVar) ProtoMessage() {}
 func (*JsonnetVar) Descriptor() ([]byte, []int) {
-	return fileDescriptor_generated_1d3c532c66f98f76, []int{35}
+	return fileDescriptor_generated_ee2cf7a8fb926224, []int{34}
 }
 func (m *JsonnetVar) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
@@ -1047,7 +1019,7 @@ var xxx_messageInfo_JsonnetVar proto.InternalMessageInfo
 func (m *KsonnetParameter) Reset()      { *m = KsonnetParameter{} }
 func (*KsonnetParameter) ProtoMessage() {}
 func (*KsonnetParameter) Descriptor() ([]byte, []int) {
-	return fileDescriptor_generated_1d3c532c66f98f76, []int{36}
+	return fileDescriptor_generated_ee2cf7a8fb926224, []int{35}
 }
 func (m *KsonnetParameter) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
@@ -1075,7 +1047,7 @@ var xxx_messageInfo_KsonnetParameter proto.InternalMessageInfo
 func (m *KustomizeOptions) Reset()      { *m = KustomizeOptions{} }
 func (*KustomizeOptions) ProtoMessage() {}
 func (*KustomizeOptions) Descriptor() ([]byte, []int) {
-	return fileDescriptor_generated_1d3c532c66f98f76, []int{37}
+	return fileDescriptor_generated_ee2cf7a8fb926224, []int{36}
 }
 func (m *KustomizeOptions) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
@@ -1103,7 +1075,7 @@ var xxx_messageInfo_KustomizeOptions proto.InternalMessageInfo
 func (m *Operation) Reset()      { *m = Operation{} }
 func (*Operation) ProtoMessage() {}
 func (*Operation) Descriptor() ([]byte, []int) {
-	return fileDescriptor_generated_1d3c532c66f98f76, []int{38}
+	return fileDescriptor_generated_ee2cf7a8fb926224, []int{37}
 }
 func (m *Operation) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
@@ -1131,7 +1103,7 @@ var xxx_messageInfo_Operation proto.InternalMessageInfo
 func (m *OperationState) Reset()      { *m = OperationState{} }
 func (*OperationState) ProtoMessage() {}
 func (*OperationState) Descriptor() ([]byte, []int) {
-	return fileDescriptor_generated_1d3c532c66f98f76, []int{39}
+	return fileDescriptor_generated_ee2cf7a8fb926224, []int{38}
 }
 func (m *OperationState) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
@@ -1159,7 +1131,7 @@ var xxx_messageInfo_OperationState proto.InternalMessageInfo
 func (m *OrphanedResourcesMonitorSettings) Reset()      { *m = OrphanedResourcesMonitorSettings{} }
 func (*OrphanedResourcesMonitorSettings) ProtoMessage() {}
 func (*OrphanedResourcesMonitorSettings) Descriptor() ([]byte, []int) {
-	return fileDescriptor_generated_1d3c532c66f98f76, []int{40}
+	return fileDescriptor_generated_ee2cf7a8fb926224, []int{39}
 }
 func (m *OrphanedResourcesMonitorSettings) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
@@ -1187,7 +1159,7 @@ var xxx_messageInfo_OrphanedResourcesMonitorSettings proto.InternalMessageInfo
 func (m *ProjectRole) Reset()      { *m = ProjectRole{} }
 func (*ProjectRole) ProtoMessage() {}
 func (*ProjectRole) Descriptor() ([]byte, []int) {
-	return fileDescriptor_generated_1d3c532c66f98f76, []int{41}
+	return fileDescriptor_generated_ee2cf7a8fb926224, []int{40}
 }
 func (m *ProjectRole) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
@@ -1215,7 +1187,7 @@ var xxx_messageInfo_ProjectRole proto.InternalMessageInfo
 func (m *Repository) Reset()      { *m = Repository{} }
 func (*Repository) ProtoMessage() {}
 func (*Repository) Descriptor() ([]byte, []int) {
-	return fileDescriptor_generated_1d3c532c66f98f76, []int{42}
+	return fileDescriptor_generated_ee2cf7a8fb926224, []int{41}
 }
 func (m *Repository) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
@@ -1243,7 +1215,7 @@ var xxx_messageInfo_Repository proto.InternalMessageInfo
 func (m *RepositoryCertificate) Reset()      { *m = RepositoryCertificate{} }
 func (*RepositoryCertificate) ProtoMessage() {}
 func (*RepositoryCertificate) Descriptor() ([]byte, []int) {
-	return fileDescriptor_generated_1d3c532c66f98f76, []int{43}
+	return fileDescriptor_generated_ee2cf7a8fb926224, []int{42}
 }
 func (m *RepositoryCertificate) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
@@ -1271,7 +1243,7 @@ var xxx_messageInfo_RepositoryCertificate proto.InternalMessageInfo
 func (m *RepositoryCertificateList) Reset()      { *m = RepositoryCertificateList{} }
 func (*RepositoryCertificateList) ProtoMessage() {}
 func (*RepositoryCertificateList) Descriptor() ([]byte, []int) {
-	return fileDescriptor_generated_1d3c532c66f98f76, []int{44}
+	return fileDescriptor_generated_ee2cf7a8fb926224, []int{43}
 }
 func (m *RepositoryCertificateList) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
@@ -1299,7 +1271,7 @@ var xxx_messageInfo_RepositoryCertificateList proto.InternalMessageInfo
 func (m *RepositoryList) Reset()      { *m = RepositoryList{} }
 func (*RepositoryList) ProtoMessage() {}
 func (*RepositoryList) Descriptor() ([]byte, []int) {
-	return fileDescriptor_generated_1d3c532c66f98f76, []int{45}
+	return fileDescriptor_generated_ee2cf7a8fb926224, []int{44}
 }
 func (m *RepositoryList) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
@@ -1327,7 +1299,7 @@ var xxx_messageInfo_RepositoryList proto.InternalMessageInfo
 func (m *ResourceAction) Reset()      { *m = ResourceAction{} }
 func (*ResourceAction) ProtoMessage() {}
 func (*ResourceAction) Descriptor() ([]byte, []int) {
-	return fileDescriptor_generated_1d3c532c66f98f76, []int{46}
+	return fileDescriptor_generated_ee2cf7a8fb926224, []int{45}
 }
 func (m *ResourceAction) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
@@ -1355,7 +1327,7 @@ var xxx_messageInfo_ResourceAction proto.InternalMessageInfo
 func (m *ResourceActionDefinition) Reset()      { *m = ResourceActionDefinition{} }
 func (*ResourceActionDefinition) ProtoMessage() {}
 func (*ResourceActionDefinition) Descriptor() ([]byte, []int) {
-	return fileDescriptor_generated_1d3c532c66f98f76, []int{47}
+	return fileDescriptor_generated_ee2cf7a8fb926224, []int{46}
 }
 func (m *ResourceActionDefinition) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
@@ -1383,7 +1355,7 @@ var xxx_messageInfo_ResourceActionDefinition proto.InternalMessageInfo
 func (m *ResourceActionParam) Reset()      { *m = ResourceActionParam{} }
 func (*ResourceActionParam) ProtoMessage() {}
 func (*ResourceActionParam) Descriptor() ([]byte, []int) {
-	return fileDescriptor_generated_1d3c532c66f98f76, []int{48}
+	return fileDescriptor_generated_ee2cf7a8fb926224, []int{47}
 }
 func (m *ResourceActionParam) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
@@ -1411,7 +1383,7 @@ var xxx_messageInfo_ResourceActionParam proto.InternalMessageInfo
 func (m *ResourceActions) Reset()      { *m = ResourceActions{} }
 func (*ResourceActions) ProtoMessage() {}
 func (*ResourceActions) Descriptor() ([]byte, []int) {
-	return fileDescriptor_generated_1d3c532c66f98f76, []int{49}
+	return fileDescriptor_generated_ee2cf7a8fb926224, []int{48}
 }
 func (m *ResourceActions) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
@@ -1439,7 +1411,7 @@ var xxx_messageInfo_ResourceActions proto.InternalMessageInfo
 func (m *ResourceDiff) Reset()      { *m = ResourceDiff{} }
 func (*ResourceDiff) ProtoMessage() {}
 func (*ResourceDiff) Descriptor() ([]byte, []int) {
-	return fileDescriptor_generated_1d3c532c66f98f76, []int{50}
+	return fileDescriptor_generated_ee2cf7a8fb926224, []int{49}
 }
 func (m *ResourceDiff) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
@@ -1467,7 +1439,7 @@ var xxx_messageInfo_ResourceDiff proto.InternalMessageInfo
 func (m *ResourceIgnoreDifferences) Reset()      { *m = ResourceIgnoreDifferences{} }
 func (*ResourceIgnoreDifferences) ProtoMessage() {}
 func (*ResourceIgnoreDifferences) Descriptor() ([]byte, []int) {
-	return fileDescriptor_generated_1d3c532c66f98f76, []int{51}
+	return fileDescriptor_generated_ee2cf7a8fb926224, []int{50}
 }
 func (m *ResourceIgnoreDifferences) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
@@ -1495,7 +1467,7 @@ var xxx_messageInfo_ResourceIgnoreDifferences proto.InternalMessageInfo
 func (m *ResourceNetworkingInfo) Reset()      { *m = ResourceNetworkingInfo{} }
 func (*ResourceNetworkingInfo) ProtoMessage() {}
 func (*ResourceNetworkingInfo) Descriptor() ([]byte, []int) {
-	return fileDescriptor_generated_1d3c532c66f98f76, []int{52}
+	return fileDescriptor_generated_ee2cf7a8fb926224, []int{51}
 }
 func (m *ResourceNetworkingInfo) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
@@ -1523,7 +1495,7 @@ var xxx_messageInfo_ResourceNetworkingInfo proto.InternalMessageInfo
 func (m *ResourceNode) Reset()      { *m = ResourceNode{} }
 func (*ResourceNode) ProtoMessage() {}
 func (*ResourceNode) Descriptor() ([]byte, []int) {
-	return fileDescriptor_generated_1d3c532c66f98f76, []int{53}
+	return fileDescriptor_generated_ee2cf7a8fb926224, []int{52}
 }
 func (m *ResourceNode) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
@@ -1551,7 +1523,7 @@ var xxx_messageInfo_ResourceNode proto.InternalMessageInfo
 func (m *ResourceOverride) Reset()      { *m = ResourceOverride{} }
 func (*ResourceOverride) ProtoMessage() {}
 func (*ResourceOverride) Descriptor() ([]byte, []int) {
-	return fileDescriptor_generated_1d3c532c66f98f76, []int{54}
+	return fileDescriptor_generated_ee2cf7a8fb926224, []int{53}
 }
 func (m *ResourceOverride) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
@@ -1579,7 +1551,7 @@ var xxx_messageInfo_ResourceOverride proto.InternalMessageInfo
 func (m *ResourceRef) Reset()      { *m = ResourceRef{} }
 func (*ResourceRef) ProtoMessage() {}
 func (*ResourceRef) Descriptor() ([]byte, []int) {
-	return fileDescriptor_generated_1d3c532c66f98f76, []int{55}
+	return fileDescriptor_generated_ee2cf7a8fb926224, []int{54}
 }
 func (m *ResourceRef) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
@@ -1607,7 +1579,7 @@ var xxx_messageInfo_ResourceRef proto.InternalMessageInfo
 func (m *ResourceResult) Reset()      { *m = ResourceResult{} }
 func (*ResourceResult) ProtoMessage() {}
 func (*ResourceResult) Descriptor() ([]byte, []int) {
-	return fileDescriptor_generated_1d3c532c66f98f76, []int{56}
+	return fileDescriptor_generated_ee2cf7a8fb926224, []int{55}
 }
 func (m *ResourceResult) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
@@ -1635,7 +1607,7 @@ var xxx_messageInfo_ResourceResult proto.InternalMessageInfo
 func (m *ResourceStatus) Reset()      { *m = ResourceStatus{} }
 func (*ResourceStatus) ProtoMessage() {}
 func (*ResourceStatus) Descriptor() ([]byte, []int) {
-	return fileDescriptor_generated_1d3c532c66f98f76, []int{57}
+	return fileDescriptor_generated_ee2cf7a8fb926224, []int{56}
 }
 func (m *ResourceStatus) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
@@ -1663,7 +1635,7 @@ var xxx_messageInfo_ResourceStatus proto.InternalMessageInfo
 func (m *RevisionHistory) Reset()      { *m = RevisionHistory{} }
 func (*RevisionHistory) ProtoMessage() {}
 func (*RevisionHistory) Descriptor() ([]byte, []int) {
-	return fileDescriptor_generated_1d3c532c66f98f76, []int{58}
+	return fileDescriptor_generated_ee2cf7a8fb926224, []int{57}
 }
 func (m *RevisionHistory) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
@@ -1691,7 +1663,7 @@ var xxx_messageInfo_RevisionHistory proto.InternalMessageInfo
 func (m *RevisionMetadata) Reset()      { *m = RevisionMetadata{} }
 func (*RevisionMetadata) ProtoMessage() {}
 func (*RevisionMetadata) Descriptor() ([]byte, []int) {
-	return fileDescriptor_generated_1d3c532c66f98f76, []int{59}
+	return fileDescriptor_generated_ee2cf7a8fb926224, []int{58}
 }
 func (m *RevisionMetadata) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
@@ -1719,7 +1691,7 @@ var xxx_messageInfo_RevisionMetadata proto.InternalMessageInfo
 func (m *SyncOperation) Reset()      { *m = SyncOperation{} }
 func (*SyncOperation) ProtoMessage() {}
 func (*SyncOperation) Descriptor() ([]byte, []int) {
-	return fileDescriptor_generated_1d3c532c66f98f76, []int{60}
+	return fileDescriptor_generated_ee2cf7a8fb926224, []int{59}
 }
 func (m *SyncOperation) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
@@ -1747,7 +1719,7 @@ var xxx_messageInfo_SyncOperation proto.InternalMessageInfo
 func (m *SyncOperationResource) Reset()      { *m = SyncOperationResource{} }
 func (*SyncOperationResource) ProtoMessage() {}
 func (*SyncOperationResource) Descriptor() ([]byte, []int) {
-	return fileDescriptor_generated_1d3c532c66f98f76, []int{61}
+	return fileDescriptor_generated_ee2cf7a8fb926224, []int{60}
 }
 func (m *SyncOperationResource) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
@@ -1775,7 +1747,7 @@ var xxx_messageInfo_SyncOperationResource proto.InternalMessageInfo
 func (m *SyncOperationResult) Reset()      { *m = SyncOperationResult{} }
 func (*SyncOperationResult) ProtoMessage() {}
 func (*SyncOperationResult) Descriptor() ([]byte, []int) {
-	return fileDescriptor_generated_1d3c532c66f98f76, []int{62}
+	return fileDescriptor_generated_ee2cf7a8fb926224, []int{61}
 }
 func (m *SyncOperationResult) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
@@ -1803,7 +1775,7 @@ var xxx_messageInfo_SyncOperationResult proto.InternalMessageInfo
 func (m *SyncPolicy) Reset()      { *m = SyncPolicy{} }
 func (*SyncPolicy) ProtoMessage() {}
 func (*SyncPolicy) Descriptor() ([]byte, []int) {
-	return fileDescriptor_generated_1d3c532c66f98f76, []int{63}
+	return fileDescriptor_generated_ee2cf7a8fb926224, []int{62}
 }
 func (m *SyncPolicy) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
@@ -1831,7 +1803,7 @@ var xxx_messageInfo_SyncPolicy proto.InternalMessageInfo
 func (m *SyncPolicyAutomated) Reset()      { *m = SyncPolicyAutomated{} }
 func (*SyncPolicyAutomated) ProtoMessage() {}
 func (*SyncPolicyAutomated) Descriptor() ([]byte, []int) {
-	return fileDescriptor_generated_1d3c532c66f98f76, []int{64}
+	return fileDescriptor_generated_ee2cf7a8fb926224, []int{63}
 }
 func (m *SyncPolicyAutomated) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
@@ -1859,7 +1831,7 @@ var xxx_messageInfo_SyncPolicyAutomated proto.InternalMessageInfo
 func (m *SyncStatus) Reset()      { *m = SyncStatus{} }
 func (*SyncStatus) ProtoMessage() {}
 func (*SyncStatus) Descriptor() ([]byte, []int) {
-	return fileDescriptor_generated_1d3c532c66f98f76, []int{65}
+	return fileDescriptor_generated_ee2cf7a8fb926224, []int{64}
 }
 func (m *SyncStatus) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
@@ -1887,7 +1859,7 @@ var xxx_messageInfo_SyncStatus proto.InternalMessageInfo
 func (m *SyncStrategy) Reset()      { *m = SyncStrategy{} }
 func (*SyncStrategy) ProtoMessage() {}
 func (*SyncStrategy) Descriptor() ([]byte, []int) {
-	return fileDescriptor_generated_1d3c532c66f98f76, []int{66}
+	return fileDescriptor_generated_ee2cf7a8fb926224, []int{65}
 }
 func (m *SyncStrategy) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
@@ -1915,7 +1887,7 @@ var xxx_messageInfo_SyncStrategy proto.InternalMessageInfo
 func (m *SyncStrategyApply) Reset()      { *m = SyncStrategyApply{} }
 func (*SyncStrategyApply) ProtoMessage() {}
 func (*SyncStrategyApply) Descriptor() ([]byte, []int) {
-	return fileDescriptor_generated_1d3c532c66f98f76, []int{67}
+	return fileDescriptor_generated_ee2cf7a8fb926224, []int{66}
 }
 func (m *SyncStrategyApply) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
@@ -1943,7 +1915,7 @@ var xxx_messageInfo_SyncStrategyApply proto.InternalMessageInfo
 func (m *SyncStrategyHook) Reset()      { *m = SyncStrategyHook{} }
 func (*SyncStrategyHook) ProtoMessage() {}
 func (*SyncStrategyHook) Descriptor() ([]byte, []int) {
-	return fileDescriptor_generated_1d3c532c66f98f76, []int{68}
+	return fileDescriptor_generated_ee2cf7a8fb926224, []int{67}
 }
 func (m *SyncStrategyHook) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
@@ -1971,7 +1943,7 @@ var xxx_messageInfo_SyncStrategyHook proto.InternalMessageInfo
 func (m *TLSClientConfig) Reset()      { *m = TLSClientConfig{} }
 func (*TLSClientConfig) ProtoMessage() {}
 func (*TLSClientConfig) Descriptor() ([]byte, []int) {
-	return fileDescriptor_generated_1d3c532c66f98f76, []int{69}
+	return fileDescriptor_generated_ee2cf7a8fb926224, []int{68}
 }
 func (m *TLSClientConfig) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
@@ -2029,7 +2001,6 @@ func init() {
 	proto.RegisterType((*EnvEntry)(nil), "github.com.argoproj.argo_cd.pkg.apis.application.v1alpha1.EnvEntry")
 	proto.RegisterType((*HealthStatus)(nil), "github.com.argoproj.argo_cd.pkg.apis.application.v1alpha1.HealthStatus")
 	proto.RegisterType((*HelmParameter)(nil), "github.com.argoproj.argo_cd.pkg.apis.application.v1alpha1.HelmParameter")
-	proto.RegisterType((*HelmRepository)(nil), "github.com.argoproj.argo_cd.pkg.apis.application.v1alpha1.HelmRepository")
 	proto.RegisterType((*Info)(nil), "github.com.argoproj.argo_cd.pkg.apis.application.v1alpha1.Info")
 	proto.RegisterType((*InfoItem)(nil), "github.com.argoproj.argo_cd.pkg.apis.application.v1alpha1.InfoItem")
 	proto.RegisterType((*JWTToken)(nil), "github.com.argoproj.argo_cd.pkg.apis.application.v1alpha1.JWTToken")
@@ -3448,58 +3419,6 @@ func (m *HelmParameter) MarshalTo(dAtA []byte) (int, error) {
 	return i, nil
 }
 
-func (m *HelmRepository) Marshal() (dAtA []byte, err error) {
-	size := m.Size()
-	dAtA = make([]byte, size)
-	n, err := m.MarshalTo(dAtA)
-	if err != nil {
-		return nil, err
-	}
-	return dAtA[:n], nil
-}
-
-func (m *HelmRepository) MarshalTo(dAtA []byte) (int, error) {
-	var i int
-	_ = i
-	var l int
-	_ = l
-	dAtA[i] = 0xa
-	i++
-	i = encodeVarintGenerated(dAtA, i, uint64(len(m.URL)))
-	i += copy(dAtA[i:], m.URL)
-	dAtA[i] = 0x12
-	i++
-	i = encodeVarintGenerated(dAtA, i, uint64(len(m.Name)))
-	i += copy(dAtA[i:], m.Name)
-	if m.CAData != nil {
-		dAtA[i] = 0x1a
-		i++
-		i = encodeVarintGenerated(dAtA, i, uint64(len(m.CAData)))
-		i += copy(dAtA[i:], m.CAData)
-	}
-	if m.CertData != nil {
-		dAtA[i] = 0x22
-		i++
-		i = encodeVarintGenerated(dAtA, i, uint64(len(m.CertData)))
-		i += copy(dAtA[i:], m.CertData)
-	}
-	if m.KeyData != nil {
-		dAtA[i] = 0x2a
-		i++
-		i = encodeVarintGenerated(dAtA, i, uint64(len(m.KeyData)))
-		i += copy(dAtA[i:], m.KeyData)
-	}
-	dAtA[i] = 0x32
-	i++
-	i = encodeVarintGenerated(dAtA, i, uint64(len(m.Username)))
-	i += copy(dAtA[i:], m.Username)
-	dAtA[i] = 0x3a
-	i++
-	i = encodeVarintGenerated(dAtA, i, uint64(len(m.Password)))
-	i += copy(dAtA[i:], m.Password)
-	return i, nil
-}
-
 func (m *Info) Marshal() (dAtA []byte, err error) {
 	size := m.Size()
 	dAtA = make([]byte, size)
@@ -3919,6 +3838,18 @@ func (m *Repository) MarshalTo(dAtA []byte) (int, error) {
 	i++
 	i = encodeVarintGenerated(dAtA, i, uint64(len(m.TLSClientCertKey)))
 	i += copy(dAtA[i:], m.TLSClientCertKey)
+	dAtA[i] = 0x5a
+	i++
+	i = encodeVarintGenerated(dAtA, i, uint64(len(m.TLSClientCAData)))
+	i += copy(dAtA[i:], m.TLSClientCAData)
+	dAtA[i] = 0x62
+	i++
+	i = encodeVarintGenerated(dAtA, i, uint64(len(m.Type)))
+	i += copy(dAtA[i:], m.Type)
+	dAtA[i] = 0x6a
+	i++
+	i = encodeVarintGenerated(dAtA, i, uint64(len(m.Name)))
+	i += copy(dAtA[i:], m.Name)
 	return i, nil
 }
 
@@ -5667,32 +5598,6 @@ func (m *HelmParameter) Size() (n int) {
 	return n
 }
 
-func (m *HelmRepository) Size() (n int) {
-	var l int
-	_ = l
-	l = len(m.URL)
-	n += 1 + l + sovGenerated(uint64(l))
-	l = len(m.Name)
-	n += 1 + l + sovGenerated(uint64(l))
-	if m.CAData != nil {
-		l = len(m.CAData)
-		n += 1 + l + sovGenerated(uint64(l))
-	}
-	if m.CertData != nil {
-		l = len(m.CertData)
-		n += 1 + l + sovGenerated(uint64(l))
-	}
-	if m.KeyData != nil {
-		l = len(m.KeyData)
-		n += 1 + l + sovGenerated(uint64(l))
-	}
-	l = len(m.Username)
-	n += 1 + l + sovGenerated(uint64(l))
-	l = len(m.Password)
-	n += 1 + l + sovGenerated(uint64(l))
-	return n
-}
-
 func (m *Info) Size() (n int) {
 	var l int
 	_ = l
@@ -5841,6 +5746,12 @@ func (m *Repository) Size() (n int) {
 	n += 1 + l + sovGenerated(uint64(l))
 	l = len(m.TLSClientCertKey)
 	n += 1 + l + sovGenerated(uint64(l))
+	l = len(m.TLSClientCAData)
+	n += 1 + l + sovGenerated(uint64(l))
+	l = len(m.Type)
+	n += 1 + l + sovGenerated(uint64(l))
+	l = len(m.Name)
+	n += 1 + l + sovGenerated(uint64(l))
 	return n
 }
 
@@ -6709,22 +6620,6 @@ func (this *HelmParameter) String() string {
 	}, "")
 	return s
 }
-func (this *HelmRepository) String() string {
-	if this == nil {
-		return "nil"
-	}
-	s := strings.Join([]string{`&HelmRepository{`,
-		`URL:` + fmt.Sprintf("%v", this.URL) + `,`,
-		`Name:` + fmt.Sprintf("%v", this.Name) + `,`,
-		`CAData:` + valueToStringGenerated(this.CAData) + `,`,
-		`CertData:` + valueToStringGenerated(this.CertData) + `,`,
-		`KeyData:` + valueToStringGenerated(this.KeyData) + `,`,
-		`Username:` + fmt.Sprintf("%v", this.Username) + `,`,
-		`Password:` + fmt.Sprintf("%v", this.Password) + `,`,
-		`}`,
-	}, "")
-	return s
-}
 func (this *Info) String() string {
 	if this == nil {
 		return "nil"
@@ -6856,6 +6751,9 @@ func (this *Repository) String() string {
 		`EnableLFS:` + fmt.Sprintf("%v", this.EnableLFS) + `,`,
 		`TLSClientCertData:` + fmt.Sprintf("%v", this.TLSClientCertData) + `,`,
 		`TLSClientCertKey:` + fmt.Sprintf("%v", this.TLSClientCertKey) + `,`,
+		`TLSClientCAData:` + fmt.Sprintf("%v", this.TLSClientCAData) + `,`,
+		`Type:` + fmt.Sprintf("%v", this.Type) + `,`,
+		`Name:` + fmt.Sprintf("%v", this.Name) + `,`,
 		`}`,
 	}, "")
 	return s
@@ -6891,7 +6789,7 @@ func (this *RepositoryList) String() string {
 	}
 	s := strings.Join([]string{`&RepositoryList{`,
 		`ListMeta:` + strings.Replace(strings.Replace(this.ListMeta.String(), "ListMeta", "v1.ListMeta", 1), `&`, ``, 1) + `,`,
-		`Items:` + strings.Replace(strings.Replace(fmt.Sprintf("%v", this.Items), "Repository", "Repository", 1), `&`, ``, 1) + `,`,
+		`Items:` + strings.Replace(fmt.Sprintf("%v", this.Items), "Repository", "Repository", 1) + `,`,
 		`}`,
 	}, "")
 	return s
@@ -11846,265 +11744,6 @@ func (m *HelmParameter) Unmarshal(dAtA []byte) error {
 	}
 	return nil
 }
-func (m *HelmRepository) Unmarshal(dAtA []byte) error {
-	l := len(dAtA)
-	iNdEx := 0
-	for iNdEx < l {
-		preIndex := iNdEx
-		var wire uint64
-		for shift := uint(0); ; shift += 7 {
-			if shift >= 64 {
-				return ErrIntOverflowGenerated
-			}
-			if iNdEx >= l {
-				return io.ErrUnexpectedEOF
-			}
-			b := dAtA[iNdEx]
-			iNdEx++
-			wire |= (uint64(b) & 0x7F) << shift
-			if b < 0x80 {
-				break
-			}
-		}
-		fieldNum := int32(wire >> 3)
-		wireType := int(wire & 0x7)
-		if wireType == 4 {
-			return fmt.Errorf("proto: HelmRepository: wiretype end group for non-group")
-		}
-		if fieldNum <= 0 {
-			return fmt.Errorf("proto: HelmRepository: illegal tag %d (wire type %d)", fieldNum, wire)
-		}
-		switch fieldNum {
-		case 1:
-			if wireType != 2 {
-				return fmt.Errorf("proto: wrong wireType = %d for field URL", wireType)
-			}
-			var stringLen uint64
-			for shift := uint(0); ; shift += 7 {
-				if shift >= 64 {
-					return ErrIntOverflowGenerated
-				}
-				if iNdEx >= l {
-					return io.ErrUnexpectedEOF
-				}
-				b := dAtA[iNdEx]
-				iNdEx++
-				stringLen |= (uint64(b) & 0x7F) << shift
-				if b < 0x80 {
-					break
-				}
-			}
-			intStringLen := int(stringLen)
-			if intStringLen < 0 {
-				return ErrInvalidLengthGenerated
-			}
-			postIndex := iNdEx + intStringLen
-			if postIndex > l {
-				return io.ErrUnexpectedEOF
-			}
-			m.URL = string(dAtA[iNdEx:postIndex])
-			iNdEx = postIndex
-		case 2:
-			if wireType != 2 {
-				return fmt.Errorf("proto: wrong wireType = %d for field Name", wireType)
-			}
-			var stringLen uint64
-			for shift := uint(0); ; shift += 7 {
-				if shift >= 64 {
-					return ErrIntOverflowGenerated
-				}
-				if iNdEx >= l {
-					return io.ErrUnexpectedEOF
-				}
-				b := dAtA[iNdEx]
-				iNdEx++
-				stringLen |= (uint64(b) & 0x7F) << shift
-				if b < 0x80 {
-					break
-				}
-			}
-			intStringLen := int(stringLen)
-			if intStringLen < 0 {
-				return ErrInvalidLengthGenerated
-			}
-			postIndex := iNdEx + intStringLen
-			if postIndex > l {
-				return io.ErrUnexpectedEOF
-			}
-			m.Name = string(dAtA[iNdEx:postIndex])
-			iNdEx = postIndex
-		case 3:
-			if wireType != 2 {
-				return fmt.Errorf("proto: wrong wireType = %d for field CAData", wireType)
-			}
-			var byteLen int
-			for shift := uint(0); ; shift += 7 {
-				if shift >= 64 {
-					return ErrIntOverflowGenerated
-				}
-				if iNdEx >= l {
-					return io.ErrUnexpectedEOF
-				}
-				b := dAtA[iNdEx]
-				iNdEx++
-				byteLen |= (int(b) & 0x7F) << shift
-				if b < 0x80 {
-					break
-				}
-			}
-			if byteLen < 0 {
-				return ErrInvalidLengthGenerated
-			}
-			postIndex := iNdEx + byteLen
-			if postIndex > l {
-				return io.ErrUnexpectedEOF
-			}
-			m.CAData = append(m.CAData[:0], dAtA[iNdEx:postIndex]...)
-			if m.CAData == nil {
-				m.CAData = []byte{}
-			}
-			iNdEx = postIndex
-		case 4:
-			if wireType != 2 {
-				return fmt.Errorf("proto: wrong wireType = %d for field CertData", wireType)
-			}
-			var byteLen int
-			for shift := uint(0); ; shift += 7 {
-				if shift >= 64 {
-					return ErrIntOverflowGenerated
-				}
-				if iNdEx >= l {
-					return io.ErrUnexpectedEOF
-				}
-				b := dAtA[iNdEx]
-				iNdEx++
-				byteLen |= (int(b) & 0x7F) << shift
-				if b < 0x80 {
-					break
-				}
-			}
-			if byteLen < 0 {
-				return ErrInvalidLengthGenerated
-			}
-			postIndex := iNdEx + byteLen
-			if postIndex > l {
-				return io.ErrUnexpectedEOF
-			}
-			m.CertData = append(m.CertData[:0], dAtA[iNdEx:postIndex]...)
-			if m.CertData == nil {
-				m.CertData = []byte{}
-			}
-			iNdEx = postIndex
-		case 5:
-			if wireType != 2 {
-				return fmt.Errorf("proto: wrong wireType = %d for field KeyData", wireType)
-			}
-			var byteLen int
-			for shift := uint(0); ; shift += 7 {
-				if shift >= 64 {
-					return ErrIntOverflowGenerated
-				}
-				if iNdEx >= l {
-					return io.ErrUnexpectedEOF
-				}
-				b := dAtA[iNdEx]
-				iNdEx++
-				byteLen |= (int(b) & 0x7F) << shift
-				if b < 0x80 {
-					break
-				}
-			}
-			if byteLen < 0 {
-				return ErrInvalidLengthGenerated
-			}
-			postIndex := iNdEx + byteLen
-			if postIndex > l {
-				return io.ErrUnexpectedEOF
-			}
-			m.KeyData = append(m.KeyData[:0], dAtA[iNdEx:postIndex]...)
-			if m.KeyData == nil {
-				m.KeyData = []byte{}
-			}
-			iNdEx = postIndex
-		case 6:
-			if wireType != 2 {
-				return fmt.Errorf("proto: wrong wireType = %d for field Username", wireType)
-			}
-			var stringLen uint64
-			for shift := uint(0); ; shift += 7 {
-				if shift >= 64 {
-					return ErrIntOverflowGenerated
-				}
-				if iNdEx >= l {
-					return io.ErrUnexpectedEOF
-				}
-				b := dAtA[iNdEx]
-				iNdEx++
-				stringLen |= (uint64(b) & 0x7F) << shift
-				if b < 0x80 {
-					break
-				}
-			}
-			intStringLen := int(stringLen)
-			if intStringLen < 0 {
-				return ErrInvalidLengthGenerated
-			}
-			postIndex := iNdEx + intStringLen
-			if postIndex > l {
-				return io.ErrUnexpectedEOF
-			}
-			m.Username = string(dAtA[iNdEx:postIndex])
-			iNdEx = postIndex
-		case 7:
-			if wireType != 2 {
-				return fmt.Errorf("proto: wrong wireType = %d for field Password", wireType)
-			}
-			var stringLen uint64
-			for shift := uint(0); ; shift += 7 {
-				if shift >= 64 {
-					return ErrIntOverflowGenerated
-				}
-				if iNdEx >= l {
-					return io.ErrUnexpectedEOF
-				}
-				b := dAtA[iNdEx]
-				iNdEx++
-				stringLen |= (uint64(b) & 0x7F) << shift
-				if b < 0x80 {
-					break
-				}
-			}
-			intStringLen := int(stringLen)
-			if intStringLen < 0 {
-				return ErrInvalidLengthGenerated
-			}
-			postIndex := iNdEx + intStringLen
-			if postIndex > l {
-				return io.ErrUnexpectedEOF
-			}
-			m.Password = string(dAtA[iNdEx:postIndex])
-			iNdEx = postIndex
-		default:
-			iNdEx = preIndex
-			skippy, err := skipGenerated(dAtA[iNdEx:])
-			if err != nil {
-				return err
-			}
-			if skippy < 0 {
-				return ErrInvalidLengthGenerated
-			}
-			if (iNdEx + skippy) > l {
-				return io.ErrUnexpectedEOF
-			}
-			iNdEx += skippy
-		}
-	}
-
-	if iNdEx > l {
-		return io.ErrUnexpectedEOF
-	}
-	return nil
-}
 func (m *Info) Unmarshal(dAtA []byte) error {
 	l := len(dAtA)
 	iNdEx := 0
@@ -13631,6 +13270,93 @@ func (m *Repository) Unmarshal(dAtA []byte) error {
 			}
 			m.TLSClientCertKey = string(dAtA[iNdEx:postIndex])
 			iNdEx = postIndex
+		case 11:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field TLSClientCAData", wireType)
+			}
+			var stringLen uint64
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowGenerated
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				stringLen |= (uint64(b) & 0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			intStringLen := int(stringLen)
+			if intStringLen < 0 {
+				return ErrInvalidLengthGenerated
+			}
+			postIndex := iNdEx + intStringLen
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.TLSClientCAData = string(dAtA[iNdEx:postIndex])
+			iNdEx = postIndex
+		case 12:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Type", wireType)
+			}
+			var stringLen uint64
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowGenerated
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				stringLen |= (uint64(b) & 0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			intStringLen := int(stringLen)
+			if intStringLen < 0 {
+				return ErrInvalidLengthGenerated
+			}
+			postIndex := iNdEx + intStringLen
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.Type = string(dAtA[iNdEx:postIndex])
+			iNdEx = postIndex
+		case 13:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Name", wireType)
+			}
+			var stringLen uint64
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowGenerated
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				stringLen |= (uint64(b) & 0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			intStringLen := int(stringLen)
+			if intStringLen < 0 {
+				return ErrInvalidLengthGenerated
+			}
+			postIndex := iNdEx + intStringLen
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.Name = string(dAtA[iNdEx:postIndex])
+			iNdEx = postIndex
 		default:
 			iNdEx = preIndex
 			skippy, err := skipGenerated(dAtA[iNdEx:])
@@ -14045,7 +13771,7 @@ func (m *RepositoryList) Unmarshal(dAtA []byte) error {
 			if postIndex > l {
 				return io.ErrUnexpectedEOF
 			}
-			m.Items = append(m.Items, Repository{})
+			m.Items = append(m.Items, &Repository{})
 			if err := m.Items[len(m.Items)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
 				return err
 			}
@@ -18396,293 +18122,292 @@ var (
 )
 
 func init() {
-	proto.RegisterFile("github.com/argoproj/argo-cd/pkg/apis/application/v1alpha1/generated.proto", fileDescriptor_generated_1d3c532c66f98f76)
-}
-
-var fileDescriptor_generated_1d3c532c66f98f76 = []byte{
-	// 4539 bytes of a gzipped FileDescriptorProto
-	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe4, 0x7c, 0x5d, 0x8c, 0x1c, 0xd9,
-	0x55, 0xf0, 0x56, 0xff, 0xcf, 0x99, 0x1f, 0x7b, 0xee, 0xae, 0x37, 0x9d, 0xd1, 0xae, 0xc7, 0x2a,
-	0xeb, 0x4b, 0x76, 0xbf, 0x6c, 0x7a, 0x58, 0xcb, 0x01, 0x07, 0x24, 0x96, 0xe9, 0x19, 0xff, 0x8c,
-	0x3d, 0x1e, 0xcf, 0xde, 0x1e, 0xaf, 0xa5, 0x4d, 0x08, 0x5b, 0xae, 0xbe, 0xdd, 0x5d, 0x9e, 0xee,
-	0xaa, 0xda, 0xaa, 0xea, 0xb1, 0x7b, 0x21, 0x21, 0x01, 0x82, 0x42, 0x60, 0x23, 0x24, 0xc4, 0x0b,
-	0x28, 0x12, 0x44, 0xbc, 0xb0, 0xe2, 0x85, 0x17, 0xf2, 0xc6, 0x43, 0x1e, 0x60, 0x1f, 0x03, 0x5a,
-	0xa4, 0x28, 0x20, 0x8b, 0x75, 0x78, 0x40, 0xe4, 0x01, 0x10, 0xe2, 0xc5, 0x4f, 0xe8, 0xfe, 0xdf,
-	0xaa, 0xee, 0xf6, 0xb4, 0xdd, 0x65, 0x47, 0x84, 0xb7, 0xa9, 0x73, 0xce, 0x3d, 0xe7, 0xdc, 0x73,
-	0x7f, 0xce, 0xcf, 0x3d, 0x3d, 0xb0, 0xd3, 0xf5, 0x92, 0xde, 0xf0, 0x76, 0xc3, 0x0d, 0x06, 0x1b,
-	0x4e, 0xd4, 0x0d, 0xc2, 0x28, 0xb8, 0xc3, 0xfe, 0xf8, 0xac, 0xdb, 0xde, 0x08, 0x0f, 0xbb, 0x1b,
-	0x4e, 0xe8, 0xc5, 0x1b, 0x4e, 0x18, 0xf6, 0x3d, 0xd7, 0x49, 0xbc, 0xc0, 0xdf, 0x38, 0x7a, 0xdd,
-	0xe9, 0x87, 0x3d, 0xe7, 0xf5, 0x8d, 0x2e, 0xf1, 0x49, 0xe4, 0x24, 0xa4, 0xdd, 0x08, 0xa3, 0x20,
-	0x09, 0xd0, 0xe7, 0x35, 0xab, 0x86, 0x64, 0xc5, 0xfe, 0xf8, 0x15, 0xb7, 0xdd, 0x08, 0x0f, 0xbb,
-	0x0d, 0xca, 0xaa, 0x61, 0xb0, 0x6a, 0x48, 0x56, 0x6b, 0x9f, 0x35, 0xb4, 0xe8, 0x06, 0xdd, 0x60,
-	0x83, 0x71, 0xbc, 0x3d, 0xec, 0xb0, 0x2f, 0xf6, 0xc1, 0xfe, 0xe2, 0x92, 0xd6, 0xec, 0xc3, 0x0b,
-	0x71, 0xc3, 0x0b, 0xa8, 0x6e, 0x1b, 0x6e, 0x10, 0x91, 0x8d, 0xa3, 0x31, 0x6d, 0xd6, 0xce, 0x6b,
-	0x9a, 0x81, 0xe3, 0xf6, 0x3c, 0x9f, 0x44, 0x23, 0x3d, 0xa1, 0x01, 0x49, 0x9c, 0x49, 0xa3, 0x36,
-	0xa6, 0x8d, 0x8a, 0x86, 0x7e, 0xe2, 0x0d, 0xc8, 0xd8, 0x80, 0x9f, 0x3d, 0x6e, 0x40, 0xec, 0xf6,
-	0xc8, 0xc0, 0xc9, 0x8e, 0xb3, 0xdf, 0x85, 0xe5, 0xcd, 0x5b, 0xad, 0xcd, 0x61, 0xd2, 0xdb, 0x0a,
-	0xfc, 0x8e, 0xd7, 0x45, 0x9f, 0x83, 0x45, 0xb7, 0x3f, 0x8c, 0x13, 0x12, 0xed, 0x39, 0x03, 0x52,
-	0xb7, 0xce, 0x58, 0xaf, 0x2c, 0x34, 0x9f, 0xff, 0xf0, 0xfe, 0xfa, 0x73, 0x0f, 0xee, 0xaf, 0x2f,
-	0x6e, 0x69, 0x14, 0x36, 0xe9, 0xd0, 0xab, 0x50, 0x8d, 0x82, 0x3e, 0xd9, 0xc4, 0x7b, 0xf5, 0x02,
-	0x1b, 0x72, 0x42, 0x0c, 0xa9, 0x62, 0x0e, 0xc6, 0x12, 0x6f, 0xff, 0xa3, 0x05, 0xb0, 0x19, 0x86,
-	0xfb, 0x51, 0x70, 0x87, 0xb8, 0x09, 0x7a, 0x07, 0x6a, 0xd4, 0x0a, 0x6d, 0x27, 0x71, 0x98, 0xb4,
-	0xc5, 0x73, 0x3f, 0xd3, 0xe0, 0x93, 0x69, 0x98, 0x93, 0xd1, 0x2b, 0x47, 0xa9, 0x1b, 0x47, 0xaf,
-	0x37, 0x6e, 0xdc, 0xa6, 0xe3, 0xaf, 0x93, 0xc4, 0x69, 0x22, 0x21, 0x0c, 0x34, 0x0c, 0x2b, 0xae,
-	0xe8, 0x10, 0x4a, 0x71, 0x48, 0x5c, 0xa6, 0xd8, 0xe2, 0xb9, 0x9d, 0xc6, 0x13, 0xef, 0x8f, 0x86,
-	0x56, 0xbb, 0x15, 0x12, 0xb7, 0xb9, 0x24, 0xc4, 0x96, 0xe8, 0x17, 0x66, 0x42, 0xec, 0x1f, 0x5a,
-	0xb0, 0xa2, 0xc9, 0x76, 0xbd, 0x38, 0x41, 0x5f, 0x1c, 0x9b, 0x61, 0x63, 0xb6, 0x19, 0xd2, 0xd1,
-	0x6c, 0x7e, 0x27, 0x85, 0xa0, 0x9a, 0x84, 0x18, 0xb3, 0xbb, 0x03, 0x65, 0x2f, 0x21, 0x83, 0xb8,
-	0x5e, 0x38, 0x53, 0x7c, 0x65, 0xf1, 0xdc, 0xc5, 0x5c, 0xa6, 0xd7, 0x5c, 0x16, 0x12, 0xcb, 0x3b,
-	0x94, 0x37, 0xe6, 0x22, 0xec, 0xbf, 0xae, 0x98, 0x93, 0xa3, 0xb3, 0x46, 0xaf, 0xc3, 0x62, 0x1c,
-	0x0c, 0x23, 0x97, 0x60, 0x12, 0x06, 0x71, 0xdd, 0x3a, 0x53, 0xa4, 0x8b, 0x4f, 0xf7, 0x4a, 0x4b,
-	0x83, 0xb1, 0x49, 0x83, 0x7e, 0xd7, 0x82, 0xa5, 0x36, 0x89, 0x13, 0xcf, 0x67, 0xf2, 0xa5, 0xe6,
-	0x6f, 0xce, 0xa7, 0xb9, 0x04, 0x6e, 0x6b, 0xce, 0xcd, 0x17, 0xc4, 0x2c, 0x96, 0x0c, 0x60, 0x8c,
-	0x53, 0xc2, 0xe9, 0x86, 0x6f, 0x93, 0xd8, 0x8d, 0xbc, 0x90, 0x7e, 0xd7, 0x8b, 0xe9, 0x0d, 0xbf,
-	0xad, 0x51, 0xd8, 0xa4, 0x43, 0x87, 0x50, 0xa6, 0x1b, 0x3a, 0xae, 0x97, 0x98, 0xf2, 0x97, 0xe6,
-	0x50, 0x5e, 0x98, 0x93, 0x1e, 0x14, 0x6d, 0x77, 0xfa, 0x15, 0x63, 0x2e, 0x03, 0xbd, 0x6f, 0x41,
-	0x5d, 0x9c, 0x36, 0x4c, 0xb8, 0x29, 0x6f, 0xf5, 0xbc, 0x84, 0xf4, 0xbd, 0x38, 0xa9, 0x97, 0x99,
-	0x02, 0x1b, 0xb3, 0x6d, 0xa9, 0xcb, 0x51, 0x30, 0x0c, 0xaf, 0x79, 0x7e, 0xbb, 0x79, 0x46, 0x48,
-	0xaa, 0x6f, 0x4d, 0x61, 0x8c, 0xa7, 0x8a, 0x44, 0x7f, 0x60, 0xc1, 0x9a, 0xef, 0x0c, 0x48, 0x1c,
-	0x3a, 0x74, 0x51, 0x39, 0xba, 0xd9, 0x77, 0xdc, 0x43, 0xa6, 0x51, 0xe5, 0xc9, 0x34, 0xb2, 0x85,
-	0x46, 0x6b, 0x7b, 0x53, 0x59, 0xe3, 0x47, 0x88, 0x45, 0x7f, 0x62, 0xc1, 0x6a, 0x10, 0x85, 0x3d,
-	0xc7, 0x27, 0x6d, 0x89, 0x8d, 0xeb, 0x55, 0x76, 0xe2, 0xbe, 0x30, 0xc7, 0xfa, 0xdc, 0xc8, 0xf2,
-	0xbc, 0x1e, 0xf8, 0x5e, 0x12, 0x44, 0x2d, 0x92, 0x24, 0x9e, 0xdf, 0x8d, 0x9b, 0xa7, 0x1e, 0xdc,
-	0x5f, 0x5f, 0x1d, 0xa3, 0xc2, 0xe3, 0xca, 0xd8, 0x7f, 0x53, 0x84, 0x45, 0x63, 0xaf, 0x3e, 0x83,
-	0xcb, 0xaf, 0x9f, 0xba, 0xfc, 0xae, 0xe6, 0x73, 0xc6, 0xa6, 0xdd, 0x7e, 0x28, 0x81, 0x4a, 0x9c,
-	0x38, 0xc9, 0x30, 0x66, 0xe7, 0x68, 0xf1, 0xdc, 0x6e, 0x4e, 0xf2, 0x18, 0xcf, 0xe6, 0x8a, 0x90,
-	0x58, 0xe1, 0xdf, 0x58, 0xc8, 0x42, 0xef, 0xc2, 0x42, 0x10, 0x52, 0xb7, 0x46, 0x0f, 0x70, 0x89,
-	0x09, 0xde, 0x9e, 0x67, 0xbd, 0x25, 0xaf, 0xe6, 0xf2, 0x83, 0xfb, 0xeb, 0x0b, 0xea, 0x13, 0x6b,
-	0x29, 0xb6, 0x0b, 0x2f, 0x18, 0xfa, 0x6d, 0x05, 0x7e, 0xdb, 0x63, 0x0b, 0x7a, 0x06, 0x4a, 0xc9,
-	0x28, 0x94, 0x7e, 0x53, 0x99, 0xe8, 0x60, 0x14, 0x12, 0xcc, 0x30, 0xd4, 0x53, 0x0e, 0x48, 0x1c,
-	0x3b, 0x5d, 0x92, 0xf5, 0x94, 0xd7, 0x39, 0x18, 0x4b, 0xbc, 0xfd, 0x2e, 0xbc, 0x38, 0xf9, 0x62,
-	0x43, 0x9f, 0x82, 0x4a, 0x4c, 0xa2, 0x23, 0x12, 0x09, 0x41, 0xda, 0x32, 0x0c, 0x8a, 0x05, 0x16,
-	0x6d, 0xc0, 0x82, 0x3a, 0x30, 0x42, 0xdc, 0xaa, 0x20, 0x5d, 0xd0, 0xa7, 0x4c, 0xd3, 0xd8, 0xff,
-	0x64, 0xc1, 0x09, 0x43, 0xe6, 0x33, 0xf0, 0x5f, 0x87, 0x69, 0xff, 0x75, 0x29, 0x9f, 0x1d, 0x33,
-	0xc5, 0x81, 0x7d, 0xab, 0x02, 0xab, 0xe6, 0xbe, 0x62, 0xc7, 0x92, 0x05, 0x2f, 0x24, 0x0c, 0x6e,
-	0xe2, 0x5d, 0x61, 0x4e, 0x1d, 0xbc, 0x70, 0x30, 0x96, 0x78, 0xba, 0xbe, 0xa1, 0x93, 0xf4, 0x84,
-	0x2d, 0xd5, 0xfa, 0xee, 0x3b, 0x49, 0x0f, 0x33, 0x0c, 0xfa, 0x45, 0x58, 0x49, 0x9c, 0xa8, 0x4b,
-	0x12, 0x4c, 0x8e, 0xbc, 0x58, 0xee, 0xc8, 0x85, 0xe6, 0x8b, 0x82, 0x76, 0xe5, 0x20, 0x85, 0xc5,
-	0x19, 0x6a, 0xe4, 0x43, 0xa9, 0x47, 0xfa, 0x03, 0x71, 0x6f, 0xed, 0xe7, 0x74, 0x80, 0xd8, 0x44,
-	0xaf, 0x90, 0xfe, 0xa0, 0x59, 0xa3, 0xfa, 0xd2, 0xbf, 0x30, 0x93, 0x83, 0x7e, 0xc3, 0x82, 0x85,
-	0xc3, 0x61, 0x9c, 0x04, 0x03, 0xef, 0x3d, 0x52, 0xaf, 0x31, 0xa9, 0x37, 0xf3, 0x94, 0x7a, 0x4d,
-	0x32, 0xe7, 0xc7, 0x49, 0x7d, 0x62, 0x2d, 0x16, 0xbd, 0x07, 0xd5, 0xc3, 0x38, 0xf0, 0x7d, 0x92,
-	0xd4, 0x17, 0x98, 0x06, 0xad, 0x5c, 0x35, 0xe0, 0xac, 0x9b, 0x8b, 0x74, 0x49, 0xc5, 0x07, 0x96,
-	0x02, 0x99, 0x01, 0xda, 0x5e, 0x44, 0xdc, 0x24, 0x88, 0x46, 0x75, 0xc8, 0xdf, 0x00, 0xdb, 0x92,
-	0x39, 0x37, 0x80, 0xfa, 0xc4, 0x5a, 0x2c, 0x3a, 0x82, 0x4a, 0xd8, 0x1f, 0x76, 0x3d, 0xbf, 0xbe,
-	0xc8, 0x14, 0xc0, 0x79, 0x2a, 0xb0, 0xcf, 0x38, 0x37, 0x81, 0x5e, 0x10, 0xfc, 0x6f, 0x2c, 0xa4,
-	0xd9, 0x7f, 0x6b, 0xc1, 0xda, 0x74, 0x85, 0xf9, 0xc9, 0x70, 0x87, 0x51, 0xcc, 0x6f, 0xb4, 0x9a,
-	0x79, 0x32, 0x18, 0x18, 0x4b, 0x3c, 0xfa, 0x0a, 0x54, 0xef, 0x88, 0x25, 0x2c, 0xe4, 0xbf, 0x84,
-	0x57, 0xc5, 0x12, 0x2a, 0xf9, 0x57, 0xe5, 0x32, 0x0a, 0xa1, 0xf6, 0x9f, 0x15, 0xe0, 0xd4, 0xc4,
-	0x1d, 0x8f, 0x1a, 0x00, 0x47, 0x4e, 0x7f, 0x48, 0x2e, 0x79, 0x34, 0x5e, 0xe3, 0x11, 0xea, 0x0a,
-	0x75, 0x98, 0x6f, 0x29, 0x28, 0x36, 0x28, 0xd0, 0xaf, 0x01, 0x84, 0x4e, 0xe4, 0x0c, 0x48, 0x42,
-	0x22, 0x79, 0x2d, 0x5d, 0x99, 0x63, 0x32, 0x54, 0x89, 0x7d, 0xc9, 0x50, 0xbb, 0x6b, 0x05, 0x8a,
-	0xb1, 0x21, 0x8f, 0xc6, 0xa3, 0x11, 0xe9, 0x13, 0x27, 0x26, 0x2c, 0x01, 0xcb, 0xc4, 0xa3, 0x58,
-	0xa3, 0xb0, 0x49, 0x47, 0x3d, 0x02, 0x9b, 0x42, 0x2c, 0xae, 0x1b, 0xe5, 0x11, 0xd8, 0x24, 0x63,
-	0x2c, 0xb0, 0xf6, 0x7f, 0x5b, 0x50, 0x9f, 0x66, 0x5d, 0x14, 0x42, 0x95, 0xdc, 0x4b, 0xde, 0x72,
-	0x22, 0x6e, 0xa6, 0xf9, 0xb2, 0x09, 0xc1, 0xf4, 0x2d, 0x27, 0xd2, 0xab, 0x76, 0x91, 0x73, 0xc7,
-	0x52, 0x0c, 0xea, 0x42, 0x29, 0xe9, 0x3b, 0x79, 0x24, 0x2f, 0x86, 0x38, 0xed, 0x76, 0x77, 0x37,
-	0x63, 0xcc, 0x04, 0xd8, 0x7f, 0x3f, 0x69, 0xde, 0xe2, 0x2e, 0xa0, 0x36, 0x27, 0xfe, 0x91, 0x17,
-	0x05, 0xfe, 0x80, 0xf8, 0x49, 0x36, 0xe9, 0xbd, 0xa8, 0x51, 0xd8, 0xa4, 0x43, 0xbf, 0x3e, 0x61,
-	0xa3, 0x5c, 0x9b, 0x63, 0x0a, 0x42, 0x9d, 0x99, 0xf7, 0x8a, 0xfd, 0xe3, 0xc2, 0x84, 0xd3, 0xab,
-	0x2e, 0x58, 0x74, 0x0e, 0x80, 0x7a, 0xf6, 0xfd, 0x88, 0x74, 0xbc, 0x7b, 0x62, 0x56, 0x8a, 0xe5,
-	0x9e, 0xc2, 0x60, 0x83, 0x0a, 0x9d, 0x87, 0x8a, 0x37, 0x70, 0xba, 0x84, 0x46, 0x70, 0xf4, 0xa0,
-	0xbc, 0x44, 0xf7, 0xd0, 0x0e, 0x83, 0x3c, 0xbc, 0xbf, 0xbe, 0xa2, 0x98, 0x33, 0x10, 0x16, 0xb4,
-	0xe8, 0x4f, 0x2d, 0x58, 0x72, 0x83, 0xc1, 0x20, 0xf0, 0x77, 0x9d, 0xdb, 0xa4, 0x2f, 0xb3, 0xa2,
-	0xee, 0x53, 0xf1, 0x23, 0x8d, 0x2d, 0x43, 0xd2, 0x45, 0x3f, 0x89, 0x46, 0x3a, 0xd1, 0x33, 0x51,
-	0x38, 0xa5, 0xd2, 0xda, 0x1b, 0xb0, 0x3a, 0x36, 0x10, 0x9d, 0x84, 0xe2, 0x21, 0x19, 0x71, 0xdb,
-	0x60, 0xfa, 0x27, 0x7a, 0x01, 0xca, 0xec, 0xa8, 0x70, 0x17, 0x8f, 0xf9, 0xc7, 0xcf, 0x17, 0x2e,
-	0x58, 0xf6, 0x1f, 0x5b, 0xf0, 0x89, 0x29, 0x77, 0x2b, 0x8d, 0x0b, 0x7c, 0x5d, 0x2f, 0x51, 0x1b,
-	0x90, 0x9d, 0x53, 0x86, 0x41, 0x5f, 0x82, 0x22, 0xf1, 0x8f, 0xc4, 0x2e, 0xd9, 0x9a, 0xc3, 0x30,
-	0x17, 0xfd, 0x23, 0x3e, 0xe9, 0xea, 0x83, 0xfb, 0xeb, 0xc5, 0x8b, 0xfe, 0x11, 0xa6, 0x8c, 0xed,
-	0xef, 0x96, 0x53, 0x91, 0x5b, 0x4b, 0x86, 0xe3, 0x4c, 0x4b, 0x11, 0xb7, 0xed, 0xe6, 0xb9, 0x1e,
-	0x46, 0xd0, 0xc9, 0x93, 0x7b, 0x21, 0x0b, 0x7d, 0xc3, 0x62, 0x29, 0xb5, 0x0c, 0x56, 0x85, 0x3b,
-	0x78, 0x0a, 0xe9, 0xbd, 0x99, 0xa5, 0x4b, 0x20, 0x36, 0x45, 0x53, 0xff, 0x15, 0xf2, 0xec, 0x5a,
-	0x5c, 0xa4, 0xea, 0x26, 0x92, 0x49, 0xb7, 0xc4, 0xa3, 0x21, 0x40, 0x3c, 0xf2, 0xdd, 0xfd, 0xa0,
-	0xef, 0xb9, 0x23, 0x91, 0x45, 0xcc, 0x73, 0x1f, 0xb5, 0x14, 0x33, 0xee, 0x6c, 0xf4, 0x37, 0x36,
-	0x04, 0xa1, 0x6f, 0x5b, 0xb0, 0xea, 0x75, 0xfd, 0x20, 0x22, 0xdb, 0x5e, 0xa7, 0x43, 0x22, 0xe2,
-	0xd3, 0xa4, 0x95, 0xe7, 0xf4, 0x07, 0x73, 0x88, 0x97, 0x39, 0xe7, 0x4e, 0x96, 0x77, 0xf3, 0x93,
-	0xc2, 0x04, 0xab, 0x63, 0x28, 0x3c, 0xae, 0x09, 0x72, 0xa0, 0xe4, 0xf9, 0x9d, 0x40, 0xe4, 0xf4,
-	0x6f, 0xcc, 0xa1, 0xd1, 0x8e, 0xdf, 0x09, 0xf4, 0xc9, 0xa0, 0x5f, 0x98, 0xb1, 0xb6, 0xff, 0xab,
-	0x96, 0x0e, 0xca, 0x79, 0x52, 0xf7, 0x1e, 0x2c, 0x44, 0x2a, 0x89, 0xe7, 0xde, 0x68, 0x27, 0x07,
-	0x7b, 0x88, 0x54, 0x52, 0x65, 0x41, 0x3a, 0x5d, 0xd7, 0xe2, 0xa8, 0x57, 0xa2, 0x4b, 0x24, 0x76,
-	0xee, 0xbc, 0xbb, 0x40, 0x88, 0xd4, 0xf9, 0xf2, 0xc8, 0xa7, 0xf9, 0xf2, 0xc8, 0x77, 0x51, 0x00,
-	0x95, 0x1e, 0x71, 0xfa, 0x49, 0x4f, 0xe4, 0xcb, 0x97, 0xe7, 0x0a, 0x33, 0x28, 0xa3, 0x6c, 0xaa,
-	0xcc, 0xa1, 0x58, 0x88, 0x41, 0x43, 0xa8, 0xf6, 0xbc, 0x98, 0x45, 0xba, 0xfc, 0x8a, 0xbe, 0x3a,
-	0x97, 0x4d, 0x79, 0xce, 0x72, 0x85, 0x73, 0xd4, 0x87, 0x4b, 0x00, 0xb0, 0x94, 0x85, 0x7e, 0xd3,
-	0x02, 0x70, 0x65, 0x92, 0x2c, 0xb7, 0xf7, 0x8d, 0x7c, 0x6e, 0x04, 0x95, 0x7c, 0x6b, 0xdf, 0xa6,
-	0x40, 0x31, 0x36, 0xc4, 0xa2, 0x77, 0x60, 0x29, 0x22, 0x6e, 0xe0, 0xbb, 0x5e, 0x9f, 0xb4, 0x37,
-	0x93, 0x7a, 0x85, 0xd9, 0xfc, 0xff, 0xcf, 0x96, 0xcc, 0x1e, 0x78, 0x03, 0xd2, 0x3c, 0x49, 0x7d,
-	0x0c, 0x36, 0x78, 0xe0, 0x14, 0x47, 0xf4, 0x75, 0x0b, 0x56, 0x54, 0x91, 0x80, 0x2e, 0x05, 0x11,
-	0x79, 0xdc, 0x4e, 0x1e, 0xf5, 0x08, 0xc6, 0xb0, 0x89, 0x68, 0x12, 0x99, 0x86, 0xe1, 0x8c, 0x50,
-	0xf4, 0x36, 0x40, 0x70, 0x9b, 0xd5, 0x00, 0xe8, 0x3c, 0x6b, 0x8f, 0x3d, 0xcf, 0x15, 0x5e, 0x4f,
-	0x92, 0x1c, 0xb0, 0xc1, 0x0d, 0x5d, 0x03, 0xe0, 0xe7, 0xe4, 0x60, 0x14, 0x12, 0x96, 0xae, 0x2d,
-	0x34, 0x3f, 0x23, 0x2d, 0xdf, 0x52, 0x98, 0x87, 0xf7, 0xd7, 0xc7, 0xe3, 0x71, 0x56, 0x07, 0x31,
-	0x86, 0xa3, 0x7b, 0x50, 0x8d, 0x87, 0x83, 0x81, 0xa3, 0x32, 0xaf, 0xeb, 0x39, 0xb9, 0x28, 0xce,
-	0x54, 0x6f, 0x49, 0x01, 0xc0, 0x52, 0x9c, 0xed, 0x03, 0x1a, 0xa7, 0x47, 0xe7, 0x61, 0x89, 0xdc,
-	0x4b, 0x48, 0xe4, 0x3b, 0xfd, 0x9b, 0x78, 0x57, 0x66, 0x0b, 0x6c, 0xd9, 0x2f, 0x1a, 0x70, 0x9c,
-	0xa2, 0x42, 0xb6, 0x0a, 0x9a, 0x0a, 0x8c, 0x1e, 0x74, 0xd0, 0x24, 0x43, 0x24, 0xfb, 0xb7, 0x0b,
-	0x29, 0xff, 0x7c, 0x10, 0x11, 0x82, 0xfa, 0x50, 0xf6, 0x83, 0xb6, 0xba, 0xdf, 0x2e, 0xe7, 0x70,
-	0xbf, 0xed, 0x05, 0x6d, 0xa3, 0x8a, 0x4c, 0xbf, 0x62, 0xcc, 0x85, 0xa0, 0xdf, 0xb2, 0x60, 0x59,
-	0x96, 0x24, 0x19, 0x42, 0x04, 0x23, 0xb9, 0x89, 0x3d, 0x25, 0xc4, 0x2e, 0xdf, 0x30, 0xa5, 0xe0,
-	0xb4, 0x50, 0xfb, 0x47, 0x56, 0x2a, 0x51, 0xbb, 0xe5, 0x24, 0x6e, 0xef, 0xe2, 0x11, 0x8d, 0xa7,
-	0xaf, 0xa5, 0x8a, 0x67, 0x3f, 0x67, 0x16, 0xcf, 0x1e, 0xde, 0x5f, 0xff, 0xf4, 0xb4, 0x27, 0xae,
-	0xbb, 0x94, 0x43, 0x83, 0xb1, 0x30, 0xea, 0x6c, 0x5f, 0x86, 0x45, 0x43, 0x63, 0x71, 0x95, 0xe7,
-	0x55, 0x5d, 0x52, 0x91, 0x87, 0x01, 0xc4, 0xa6, 0x3c, 0xfb, 0x1f, 0x0a, 0x50, 0x15, 0x95, 0xf5,
-	0x99, 0xab, 0x75, 0x32, 0x88, 0x2c, 0x4c, 0x0d, 0x22, 0x43, 0xa8, 0xb8, 0xec, 0x9d, 0x4e, 0xf8,
-	0x8b, 0x79, 0xd2, 0x52, 0xa1, 0x1d, 0x7f, 0xf7, 0xd3, 0x3a, 0xf1, 0x6f, 0x2c, 0xe4, 0xa0, 0xf7,
-	0x2d, 0x38, 0xe1, 0xd2, 0xb4, 0xc4, 0xd5, 0x57, 0x5a, 0x69, 0xee, 0x5a, 0xf2, 0x56, 0x9a, 0x63,
-	0xf3, 0x13, 0x42, 0xfa, 0x89, 0x0c, 0x02, 0x67, 0x65, 0xdb, 0x7f, 0x55, 0x84, 0xe5, 0x94, 0xe6,
-	0xe8, 0x35, 0xa8, 0x0d, 0x63, 0x7a, 0x16, 0x55, 0xf8, 0xad, 0xca, 0x8d, 0x37, 0x05, 0x1c, 0x2b,
-	0x0a, 0x4a, 0x1d, 0x3a, 0x71, 0x7c, 0x37, 0x88, 0xda, 0xc2, 0xce, 0x8a, 0x7a, 0x5f, 0xc0, 0xb1,
-	0xa2, 0xa0, 0x89, 0xe1, 0x6d, 0xe2, 0x44, 0x24, 0x3a, 0x08, 0x0e, 0xc9, 0xd8, 0xe3, 0x50, 0x53,
-	0xa3, 0xb0, 0x49, 0xc7, 0x8c, 0x96, 0xf4, 0xe3, 0xad, 0xbe, 0x47, 0xfc, 0x84, 0xab, 0x99, 0x83,
-	0xd1, 0x0e, 0x76, 0x5b, 0x26, 0x47, 0x6d, 0xb4, 0x0c, 0x02, 0x67, 0x65, 0xa3, 0xaf, 0x59, 0xb0,
-	0xec, 0xdc, 0x8d, 0xf5, 0x33, 0x6f, 0xbd, 0x3c, 0xf7, 0xf6, 0x49, 0x3d, 0x1b, 0x37, 0x57, 0xe9,
-	0xb1, 0x4f, 0x81, 0x70, 0x5a, 0xa2, 0xfd, 0x91, 0x05, 0xf2, 0xf9, 0xf8, 0x19, 0x54, 0x95, 0xbb,
-	0xe9, 0xaa, 0x72, 0x73, 0xfe, 0x73, 0x32, 0xa5, 0xa2, 0xbc, 0x07, 0x55, 0x9a, 0x55, 0x3a, 0x7e,
-	0x1b, 0xfd, 0x3f, 0xa8, 0xba, 0xfc, 0x4f, 0xe1, 0x36, 0x58, 0xbd, 0x51, 0x60, 0xb1, 0xc4, 0xa1,
-	0x97, 0xa0, 0xe4, 0x44, 0x5d, 0xe9, 0x2a, 0x58, 0x39, 0x76, 0x33, 0xea, 0xc6, 0x98, 0x41, 0xed,
-	0xf7, 0x0b, 0x00, 0x5b, 0xc1, 0x20, 0x74, 0x22, 0xd2, 0x3e, 0x08, 0xfe, 0xcf, 0x67, 0x70, 0xf6,
-	0xef, 0x59, 0x80, 0xa8, 0x3d, 0x02, 0x9f, 0xf8, 0xba, 0x32, 0x82, 0x36, 0x60, 0xc1, 0x95, 0x50,
-	0x71, 0xea, 0x55, 0x48, 0xaf, 0xc8, 0xb1, 0xa6, 0x99, 0xe1, 0x6e, 0x3d, 0x2b, 0x13, 0x7f, 0x7e,
-	0xca, 0xd5, 0x72, 0xb3, 0x02, 0x9a, 0xa8, 0x03, 0xd8, 0xdf, 0x2a, 0xc0, 0x8b, 0x7c, 0x43, 0x5f,
-	0x77, 0x7c, 0xa7, 0x4b, 0x06, 0x54, 0xab, 0x59, 0x4b, 0x00, 0xef, 0xd0, 0x5c, 0xca, 0x93, 0xf5,
-	0xd1, 0xb9, 0xf6, 0x24, 0xdf, 0x4b, 0x7c, 0xf7, 0xec, 0xf8, 0x5e, 0x82, 0x19, 0x67, 0x14, 0x42,
-	0x4d, 0x76, 0x78, 0x08, 0x0f, 0x91, 0x87, 0x14, 0x75, 0xd0, 0x2e, 0x0b, 0xde, 0x58, 0x49, 0xb1,
-	0xbf, 0x67, 0x41, 0xf6, 0xd2, 0x66, 0xfe, 0x8e, 0xbf, 0x02, 0x66, 0xfd, 0x5d, 0xfa, 0xdd, 0x6e,
-	0xf6, 0xa7, 0x30, 0xf4, 0x45, 0x58, 0x74, 0x92, 0x84, 0x0c, 0xc2, 0x84, 0x45, 0xb4, 0xc5, 0x27,
-	0x8b, 0x68, 0xaf, 0x07, 0x6d, 0xaf, 0xe3, 0xb1, 0x88, 0xd6, 0x64, 0x67, 0xbf, 0x09, 0x35, 0x59,
-	0x55, 0x99, 0x61, 0x19, 0xcf, 0xa6, 0x2a, 0x44, 0x53, 0x36, 0x8a, 0x03, 0x4b, 0x66, 0x42, 0xf6,
-	0x14, 0x6c, 0x62, 0xbf, 0x6f, 0xc1, 0x72, 0xaa, 0xb6, 0x9c, 0x93, 0xee, 0xd4, 0xeb, 0x75, 0x02,
-	0x96, 0x2b, 0x47, 0x9e, 0xcf, 0x43, 0x8d, 0x9a, 0x3e, 0xaa, 0x97, 0x34, 0x0a, 0x9b, 0x74, 0xf6,
-	0x77, 0x0a, 0xb0, 0xc2, 0x1e, 0x96, 0x48, 0x18, 0xc4, 0x1e, 0xcb, 0xfb, 0x5e, 0x86, 0xe2, 0x30,
-	0xea, 0x0b, 0x7d, 0x16, 0x05, 0x87, 0xe2, 0x4d, 0xbc, 0x8b, 0x29, 0x7c, 0x86, 0x43, 0x69, 0x43,
-	0xc5, 0x75, 0xb6, 0xa9, 0x8f, 0xa0, 0x5a, 0x2c, 0xf1, 0xc8, 0x7a, 0x6b, 0x93, 0x42, 0xb0, 0xc0,
-	0xa0, 0x57, 0xa0, 0xe6, 0x92, 0x28, 0x61, 0x54, 0x25, 0x46, 0xb5, 0x44, 0x37, 0xeb, 0x96, 0x80,
-	0x61, 0x85, 0xa5, 0x37, 0xf4, 0x21, 0x19, 0x31, 0xc2, 0x32, 0x23, 0xe4, 0x2f, 0x42, 0x1c, 0x84,
-	0x25, 0x2e, 0x15, 0x51, 0x54, 0x1e, 0x2b, 0xa2, 0xa8, 0x1e, 0x17, 0x51, 0xd8, 0xd7, 0x81, 0x95,
-	0x3e, 0xf2, 0xda, 0x66, 0x6f, 0x42, 0x8d, 0xb2, 0xa3, 0x2e, 0x29, 0x2f, 0x96, 0x2d, 0xa8, 0x5d,
-	0xbd, 0x75, 0xc0, 0x03, 0x19, 0x1b, 0x8a, 0x9e, 0xc3, 0x2f, 0xd8, 0xa2, 0x9e, 0xd6, 0x4e, 0x1c,
-	0x0f, 0xd9, 0x21, 0xa2, 0x48, 0x74, 0x16, 0x8a, 0xe4, 0x5e, 0xc8, 0x58, 0x16, 0xf5, 0x25, 0x7c,
-	0xf1, 0x5e, 0xe8, 0x45, 0x24, 0xa6, 0x44, 0xe4, 0x5e, 0x68, 0x0f, 0x01, 0x74, 0x81, 0x3e, 0xaf,
-	0x7d, 0x7a, 0x06, 0x4a, 0x6e, 0xd0, 0x26, 0x62, 0x83, 0x2a, 0x36, 0x5b, 0x41, 0x9b, 0x60, 0x86,
-	0xb1, 0xbf, 0x69, 0xc1, 0xc9, 0x6c, 0x55, 0xfd, 0x27, 0xe6, 0x3b, 0x76, 0xe1, 0xa4, 0xaa, 0x61,
-	0xdf, 0x08, 0x79, 0x49, 0xe2, 0x02, 0x2c, 0xdd, 0x1e, 0x7a, 0xfd, 0xb6, 0xf8, 0x16, 0xea, 0xa8,
-	0x72, 0x76, 0xd3, 0xc0, 0xe1, 0x14, 0xa5, 0x1d, 0x83, 0xee, 0x4c, 0x40, 0x1d, 0x51, 0xb0, 0xb2,
-	0xe6, 0x0e, 0xeb, 0x5a, 0x23, 0xdf, 0xd5, 0x0d, 0x10, 0xb5, 0x74, 0xbd, 0xca, 0xfe, 0x4e, 0x09,
-	0x32, 0xa5, 0x07, 0x34, 0x34, 0x9b, 0x2f, 0xac, 0x1c, 0x9b, 0x2f, 0xd4, 0x9a, 0x4c, 0x6a, 0xc0,
-	0x40, 0x9f, 0x83, 0x72, 0xd8, 0x73, 0x62, 0xb9, 0x28, 0xeb, 0xd2, 0xe2, 0xfb, 0x14, 0xf8, 0xd0,
-	0xac, 0x90, 0x30, 0x08, 0xe6, 0xd4, 0xe6, 0xf5, 0x5a, 0x3c, 0xc6, 0xe5, 0x7c, 0x85, 0x17, 0x84,
-	0x31, 0x89, 0x87, 0xfd, 0x44, 0x84, 0xef, 0x7b, 0x79, 0x59, 0x96, 0x73, 0xd5, 0x95, 0x61, 0xfe,
-	0x8d, 0x0d, 0x89, 0xe8, 0x0b, 0xb0, 0x10, 0x27, 0x4e, 0x94, 0x3c, 0x61, 0xa9, 0x4a, 0x99, 0xaf,
-	0x25, 0x99, 0x60, 0xcd, 0x0f, 0xbd, 0x0d, 0xd0, 0xf1, 0x7c, 0x2f, 0xee, 0x31, 0xee, 0xd5, 0x27,
-	0x73, 0xa7, 0x97, 0x14, 0x07, 0x6c, 0x70, 0xb3, 0x7f, 0x09, 0xce, 0x1c, 0xd7, 0x32, 0x45, 0x83,
-	0xe0, 0xbb, 0x4e, 0xe4, 0x8b, 0x57, 0x65, 0xb6, 0xcd, 0x6e, 0x39, 0x91, 0x8f, 0x19, 0xd4, 0xfe,
-	0xa0, 0x00, 0x8b, 0x46, 0x57, 0xdc, 0x0c, 0xf7, 0x45, 0xa6, 0x8b, 0xaf, 0x30, 0x63, 0x17, 0xdf,
-	0x2b, 0x50, 0x0b, 0x83, 0xbe, 0xe7, 0x7a, 0xea, 0xbd, 0x8b, 0xb9, 0x8e, 0x7d, 0x01, 0xc3, 0x0a,
-	0x8b, 0x12, 0x58, 0xb8, 0x73, 0x37, 0x61, 0xb7, 0xa2, 0x7c, 0xdd, 0x9a, 0xe7, 0x11, 0x47, 0xde,
-	0xb0, 0x7a, 0x99, 0x24, 0x24, 0xc6, 0x5a, 0x10, 0x75, 0x7f, 0xdd, 0x28, 0x18, 0x86, 0xbc, 0x64,
-	0x2a, 0x0a, 0x4b, 0xac, 0x63, 0x2e, 0xc6, 0x02, 0x63, 0xff, 0x51, 0x19, 0xc0, 0x70, 0xb9, 0x67,
-	0xa0, 0x14, 0x91, 0x30, 0xc8, 0xda, 0x8a, 0x52, 0x60, 0x86, 0x49, 0xb9, 0xb7, 0xc2, 0x63, 0xb9,
-	0xb7, 0xe2, 0xb1, 0x09, 0xf3, 0x2f, 0xc0, 0x72, 0x1c, 0xf7, 0xf6, 0x23, 0xef, 0xc8, 0x49, 0xc8,
-	0x35, 0x32, 0x12, 0xaf, 0xd1, 0xaa, 0x32, 0xd4, 0x6a, 0x5d, 0xd1, 0x48, 0x9c, 0xa6, 0x9d, 0x58,
-	0x6b, 0x28, 0xff, 0xe4, 0x6a, 0x0d, 0xa8, 0x05, 0xa7, 0x3c, 0x3f, 0x26, 0xee, 0x30, 0x12, 0xcf,
-	0x28, 0x57, 0x82, 0x38, 0xa1, 0x93, 0xaa, 0xb0, 0x5d, 0xfb, 0xb2, 0x60, 0x74, 0x6a, 0x67, 0x12,
-	0x11, 0x9e, 0x3c, 0x96, 0xda, 0x53, 0x22, 0xd8, 0xb9, 0xab, 0x19, 0x7e, 0x55, 0xc0, 0xb1, 0xa2,
-	0xa0, 0xbe, 0x8a, 0xf8, 0xce, 0xed, 0x3e, 0xd9, 0xed, 0xc4, 0xac, 0x8e, 0x5b, 0x33, 0x5c, 0x2c,
-	0x47, 0x5c, 0x6a, 0x61, 0x4d, 0x83, 0x2e, 0xc3, 0xaa, 0xce, 0xfe, 0x65, 0x54, 0xc4, 0x8b, 0xb4,
-	0xea, 0xe1, 0x47, 0xd7, 0x0b, 0x64, 0x88, 0x34, 0x3e, 0x06, 0x6d, 0xc3, 0xc9, 0x14, 0x90, 0xce,
-	0x1b, 0x18, 0x9f, 0xba, 0xe0, 0x73, 0x32, 0xc5, 0x87, 0x4e, 0x79, 0x6c, 0x84, 0xfd, 0x8d, 0x02,
-	0x9c, 0xd2, 0x9b, 0x93, 0x42, 0xbd, 0x0e, 0x5d, 0x21, 0xf6, 0x38, 0xcd, 0xcb, 0x5e, 0x46, 0x9f,
-	0xb9, 0x2a, 0xe0, 0xb7, 0x14, 0x06, 0x1b, 0x54, 0xd4, 0x76, 0x34, 0x96, 0x63, 0x85, 0xe7, 0xcc,
-	0xce, 0xdd, 0x12, 0x70, 0xac, 0x28, 0x58, 0x2b, 0x3b, 0x89, 0x92, 0xd6, 0xf0, 0x36, 0x1b, 0x90,
-	0x29, 0xde, 0x6c, 0x69, 0x14, 0x36, 0xe9, 0x1e, 0x23, 0x9c, 0x14, 0xea, 0xd0, 0x00, 0x8c, 0xed,
-	0xd3, 0x8c, 0x3a, 0xec, 0x89, 0x4b, 0x51, 0xd8, 0xff, 0x61, 0xc1, 0x27, 0x27, 0x9a, 0xe2, 0x19,
-	0x94, 0x43, 0x86, 0xe9, 0x72, 0xc8, 0xfe, 0x5c, 0x15, 0xdf, 0x09, 0x53, 0x98, 0x52, 0x1c, 0xf9,
-	0xa1, 0x05, 0x2b, 0x9a, 0xfe, 0x7f, 0x57, 0x33, 0xbc, 0xd6, 0x7b, 0xca, 0xe4, 0x3e, 0x60, 0x93,
-	0xe3, 0xfe, 0x6d, 0xd3, 0x95, 0xdd, 0x9f, 0xc7, 0xf8, 0xa9, 0x23, 0xa8, 0xb0, 0xfe, 0x0d, 0xa9,
-	0xe1, 0x5e, 0x0e, 0xb5, 0x77, 0x2e, 0x9c, 0xc5, 0xb7, 0x3a, 0xad, 0x64, 0x9f, 0x31, 0x16, 0xd2,
-	0xec, 0x01, 0xd4, 0xd3, 0xe4, 0xdb, 0x84, 0x7a, 0xec, 0x19, 0xb5, 0xde, 0x80, 0x05, 0x87, 0x8d,
-	0xda, 0x1d, 0x3a, 0xd9, 0x36, 0xd2, 0x4d, 0x89, 0xc0, 0x9a, 0xc6, 0xfe, 0x73, 0x0b, 0x9e, 0x9f,
-	0xa0, 0x5e, 0x8e, 0x81, 0x7f, 0xa2, 0x8f, 0xf4, 0x94, 0x2e, 0xdb, 0x36, 0xe9, 0x38, 0x32, 0x72,
-	0x33, 0xe2, 0xbc, 0x6d, 0x0e, 0xc6, 0x12, 0x6f, 0xff, 0x9b, 0x05, 0x27, 0xd2, 0xba, 0xc6, 0xe8,
-	0x2a, 0x20, 0x3e, 0x99, 0x6d, 0x2f, 0x76, 0x83, 0x23, 0x12, 0x8d, 0xe8, 0xcc, 0xb9, 0xd6, 0x6b,
-	0x82, 0x13, 0xda, 0x1c, 0xa3, 0xc0, 0x13, 0x46, 0xa1, 0x6f, 0xb2, 0x62, 0x9a, 0xb4, 0xb6, 0x5c,
-	0xf8, 0x56, 0x6e, 0x0b, 0xaf, 0x57, 0xd2, 0x0c, 0x78, 0x94, 0x3c, 0x6c, 0x0a, 0xb7, 0x3f, 0x2a,
-	0xc0, 0x92, 0x1c, 0xbe, 0xed, 0x75, 0x3a, 0xd4, 0xde, 0x2c, 0x8e, 0x10, 0x93, 0x53, 0xf6, 0x66,
-	0x41, 0x06, 0xe6, 0x38, 0x6a, 0xef, 0x43, 0xcf, 0x6f, 0x67, 0x13, 0xa0, 0x6b, 0x9e, 0xdf, 0xc6,
-	0x0c, 0x93, 0x6e, 0x34, 0x2e, 0x1e, 0xdf, 0x68, 0xac, 0x76, 0x42, 0xe9, 0x51, 0x21, 0x1d, 0x6f,
-	0x8d, 0xd5, 0x81, 0x80, 0x71, 0x7d, 0x1f, 0x68, 0x14, 0x36, 0xe9, 0xa8, 0x26, 0x7d, 0xef, 0x88,
-	0xf0, 0x41, 0x95, 0xb4, 0x26, 0xbb, 0x12, 0x81, 0x35, 0x0d, 0xd5, 0xa4, 0xed, 0x75, 0x3a, 0x22,
-	0x77, 0x57, 0x9a, 0x50, 0xeb, 0x60, 0x86, 0xa1, 0x14, 0xbd, 0x20, 0x38, 0x14, 0xfe, 0x57, 0x51,
-	0x5c, 0x09, 0x82, 0x43, 0xcc, 0x30, 0xf6, 0x8f, 0xd9, 0xdd, 0x3e, 0xa5, 0xe3, 0x22, 0x2f, 0x1b,
-	0x4b, 0x93, 0x15, 0x1f, 0x75, 0x4e, 0xf5, 0x2a, 0x94, 0x66, 0x58, 0x85, 0xf3, 0xb0, 0x74, 0x27,
-	0x0e, 0xfc, 0xfd, 0xc0, 0xf3, 0x59, 0x0f, 0x5b, 0x59, 0x3f, 0x77, 0x5e, 0x6d, 0xdd, 0xd8, 0x93,
-	0x70, 0x9c, 0xa2, 0xb2, 0xbf, 0x57, 0x86, 0x17, 0xd5, 0xc3, 0x1f, 0x49, 0xee, 0x06, 0xd1, 0xa1,
-	0xe7, 0x77, 0x59, 0x59, 0xe3, 0xdb, 0x16, 0x2c, 0xf1, 0xd5, 0x10, 0x8d, 0x60, 0xfc, 0x65, 0xd3,
-	0xcd, 0xe3, 0x89, 0x31, 0x25, 0xa9, 0x71, 0x60, 0x48, 0xc9, 0x34, 0x81, 0x99, 0x28, 0x9c, 0x52,
-	0x07, 0xbd, 0x07, 0x20, 0xfb, 0xad, 0x3b, 0x79, 0xb4, 0x9c, 0x4b, 0xe5, 0x30, 0xe9, 0xe8, 0xe8,
-	0xe5, 0x40, 0x49, 0xc0, 0x86, 0x34, 0xf4, 0x75, 0x0b, 0x2a, 0x7d, 0x6e, 0x95, 0x22, 0x13, 0xfc,
-	0xcb, 0xf9, 0x5b, 0xc5, 0xb4, 0x87, 0xf2, 0x05, 0xc2, 0x12, 0x42, 0x38, 0xc2, 0x50, 0xf5, 0xfc,
-	0x6e, 0x44, 0x62, 0x99, 0xc8, 0x7c, 0xda, 0xf0, 0xc0, 0x0d, 0x37, 0x88, 0x08, 0xf3, 0xb7, 0x81,
-	0xd3, 0x6e, 0x3a, 0x7d, 0xc7, 0x77, 0x49, 0xb4, 0xc3, 0xc9, 0xf5, 0x25, 0x2a, 0x00, 0x58, 0x32,
-	0x1a, 0x7b, 0x37, 0x2f, 0xcf, 0xf2, 0x6e, 0xbe, 0xf6, 0x06, 0xac, 0x8e, 0x2d, 0xe3, 0xe3, 0xb4,
-	0xe4, 0xad, 0x7d, 0x1e, 0x16, 0x9f, 0xb4, 0x9b, 0xef, 0xa3, 0xb2, 0xbe, 0x09, 0xf7, 0x82, 0x36,
-	0x7b, 0x30, 0x8e, 0xf4, 0x6a, 0x8a, 0xe0, 0x24, 0xaf, 0xbd, 0x61, 0x34, 0xf0, 0x2a, 0x20, 0x36,
-	0xe5, 0xd1, 0x9d, 0x19, 0x3a, 0x11, 0xf1, 0x9f, 0xea, 0xce, 0xdc, 0x57, 0x12, 0xb0, 0x21, 0x0d,
-	0x11, 0xd1, 0xe4, 0x55, 0x9c, 0x3b, 0xaf, 0x95, 0xc5, 0xc8, 0x49, 0x8d, 0x5e, 0x34, 0xbf, 0x5b,
-	0xf1, 0x53, 0xfb, 0x55, 0x94, 0x55, 0xde, 0xcc, 0xfd, 0x20, 0xf0, 0x2e, 0x99, 0x34, 0x0c, 0x67,
-	0x84, 0xa3, 0x4d, 0x38, 0x21, 0x57, 0xe0, 0x2d, 0x12, 0xb1, 0xdf, 0x6a, 0x70, 0x2f, 0xa3, 0x52,
-	0x44, 0x9c, 0x46, 0xe3, 0x2c, 0xbd, 0xd1, 0xf9, 0x51, 0x99, 0xd6, 0xf9, 0x81, 0x0e, 0x55, 0x93,
-	0x57, 0x35, 0xdf, 0x26, 0x2f, 0x18, 0x6f, 0xf0, 0xb2, 0xbf, 0x6b, 0xc1, 0x49, 0xa9, 0xf5, 0x8d,
-	0x23, 0x12, 0x45, 0x5e, 0x9b, 0xf9, 0x05, 0x8e, 0xd6, 0x51, 0x8c, 0xf2, 0x0b, 0x57, 0x24, 0x02,
-	0x6b, 0x1a, 0x9a, 0x45, 0x8e, 0x37, 0x25, 0x16, 0xd2, 0x59, 0xe4, 0x4c, 0xed, 0x83, 0xaf, 0x42,
-	0x95, 0x87, 0x44, 0x71, 0xb6, 0xde, 0x26, 0x42, 0x2d, 0x2c, 0xf1, 0xf6, 0x7f, 0x5a, 0x60, 0x9e,
-	0x8e, 0xd9, 0xbc, 0xe6, 0xab, 0x50, 0x3d, 0x12, 0x4b, 0x97, 0x79, 0x2e, 0x91, 0x4b, 0x26, 0xf1,
-	0xca, 0xc1, 0x16, 0x67, 0x0b, 0x62, 0x4a, 0x8f, 0x11, 0xc4, 0x94, 0xa7, 0x7a, 0xe4, 0x97, 0xa1,
-	0x38, 0xf4, 0xda, 0x22, 0x0e, 0xd1, 0x0f, 0x20, 0x3b, 0xdb, 0x98, 0xc2, 0xed, 0x7f, 0x29, 0xea,
-	0x1c, 0x42, 0x94, 0xfd, 0x7e, 0x2a, 0xa6, 0x7d, 0x5e, 0xbd, 0x76, 0xf1, 0x99, 0xbf, 0x94, 0x7e,
-	0xed, 0x7a, 0x78, 0x7f, 0x1d, 0xf8, 0x74, 0x59, 0xad, 0x7e, 0xc2, 0xdb, 0x57, 0xf5, 0x98, 0xe2,
-	0xec, 0x05, 0xa8, 0xd1, 0xc0, 0x8b, 0x25, 0xf6, 0xb5, 0x94, 0x88, 0xda, 0x15, 0x01, 0x7f, 0x68,
-	0xfc, 0x8d, 0x15, 0x35, 0xda, 0x84, 0x05, 0xfa, 0x37, 0xab, 0x0a, 0x8b, 0xc2, 0xc8, 0x59, 0x75,
-	0x16, 0x24, 0x62, 0x42, 0x01, 0x59, 0x8f, 0xa2, 0x06, 0x63, 0x1d, 0xbc, 0x8c, 0x05, 0xa4, 0x0d,
-	0xd6, 0x92, 0x08, 0xac, 0x69, 0xec, 0x8f, 0x8d, 0x65, 0x16, 0xef, 0x81, 0x3f, 0x15, 0xcb, 0x7c,
-	0x21, 0xb3, 0xcc, 0x67, 0xc6, 0x96, 0x79, 0x45, 0x37, 0xc0, 0xa6, 0x96, 0xfa, 0x59, 0xde, 0x89,
-	0xc7, 0xc7, 0xef, 0xdc, 0x13, 0xbc, 0x3b, 0xf4, 0x22, 0x12, 0xef, 0x47, 0x43, 0xdf, 0xf3, 0xbb,
-	0x6c, 0x6b, 0xd4, 0x4c, 0x4f, 0x90, 0x42, 0xe3, 0x2c, 0xbd, 0xfd, 0x97, 0x05, 0x9a, 0x46, 0xa6,
-	0x1a, 0x62, 0xd1, 0x6b, 0x50, 0x8b, 0xe4, 0xaf, 0x00, 0x33, 0xf5, 0x2a, 0xf5, 0xfb, 0x3f, 0x45,
-	0x81, 0xbe, 0x04, 0xd0, 0x26, 0x61, 0x3f, 0x18, 0xb1, 0x9a, 0x7c, 0xe9, 0xb1, 0x6b, 0xf2, 0xca,
-	0xcb, 0x6f, 0x2b, 0x2e, 0xd8, 0xe0, 0x88, 0xd6, 0xa0, 0xe0, 0xb5, 0xd9, 0x6a, 0x16, 0x9b, 0x20,
-	0x68, 0x0b, 0x3b, 0xdb, 0xb8, 0xe0, 0xb5, 0x8d, 0x3e, 0x93, 0xca, 0xb3, 0xeb, 0x33, 0xb1, 0xff,
-	0x8e, 0x39, 0x2b, 0x3e, 0xfd, 0xeb, 0xb2, 0x86, 0xf3, 0x29, 0xa8, 0x38, 0xc3, 0xa4, 0x17, 0x8c,
-	0x75, 0xcb, 0x6d, 0x32, 0x28, 0x16, 0x58, 0xb4, 0x0b, 0xa5, 0x36, 0xcd, 0xf1, 0x0a, 0x8f, 0x6d,
-	0x28, 0x9d, 0xe3, 0xd1, 0x54, 0x90, 0x71, 0x41, 0x2f, 0x41, 0x29, 0x71, 0xba, 0xf2, 0x15, 0x80,
-	0x3d, 0x48, 0x1c, 0x38, 0xdd, 0x18, 0x33, 0xa8, 0x79, 0x33, 0x95, 0x8e, 0x79, 0x95, 0xff, 0x8b,
-	0x12, 0x2c, 0xa7, 0x9e, 0x7a, 0x52, 0xbb, 0xc0, 0x3a, 0x76, 0x17, 0x9c, 0x85, 0x72, 0x18, 0x0d,
-	0x7d, 0x3e, 0xaf, 0x9a, 0xbe, 0x18, 0xe8, 0x3e, 0x23, 0x98, 0xe3, 0xa8, 0x8d, 0xda, 0xd1, 0x08,
-	0x0f, 0x7d, 0xf1, 0xf6, 0xa9, 0x6c, 0xb4, 0xcd, 0xa0, 0x58, 0x60, 0xd1, 0x97, 0x61, 0x29, 0x66,
-	0x07, 0x30, 0x72, 0x12, 0xd2, 0x95, 0x3f, 0x6b, 0xb8, 0x3c, 0x77, 0x43, 0x3b, 0x67, 0xc7, 0xe3,
-	0x7b, 0x13, 0x82, 0x53, 0xe2, 0xd0, 0xd7, 0x2c, 0xb3, 0x89, 0xbf, 0x32, 0x77, 0xed, 0x31, 0xfb,
-	0x84, 0xc6, 0x77, 0xd7, 0xa3, 0x7b, 0xf9, 0x43, 0xb5, 0xb3, 0xab, 0x4f, 0x61, 0x67, 0xc3, 0x84,
-	0xee, 0xa9, 0xcf, 0xc0, 0xc2, 0xc0, 0xf1, 0xbd, 0x0e, 0x89, 0x93, 0xb8, 0x5e, 0x63, 0xfb, 0x89,
-	0xfd, 0xf0, 0xf3, 0xba, 0x04, 0x62, 0x8d, 0xb7, 0xbf, 0x6a, 0xc1, 0xa9, 0x89, 0xd3, 0x7a, 0x66,
-	0x55, 0x03, 0x7a, 0x73, 0x3d, 0x3f, 0xe1, 0x71, 0x12, 0x1d, 0x3d, 0x9d, 0x5f, 0x60, 0x88, 0xa7,
-	0xcf, 0xe5, 0xa9, 0x2b, 0xf6, 0x78, 0xb7, 0xa6, 0xbe, 0xb9, 0x8a, 0xcf, 0xf0, 0xe6, 0xfa, 0x1d,
-	0x0b, 0x8c, 0x5f, 0xf4, 0xa0, 0x5f, 0x85, 0x05, 0x67, 0x98, 0x04, 0x03, 0x27, 0x21, 0x6d, 0x91,
-	0x39, 0xee, 0xe5, 0xf2, 0xdb, 0xa1, 0x4d, 0xc9, 0x95, 0xdb, 0x4b, 0x7d, 0x62, 0x2d, 0xcf, 0xee,
-	0xf1, 0xe5, 0xcb, 0x0c, 0xd0, 0x17, 0x89, 0xf5, 0x88, 0x8b, 0xe4, 0x35, 0xa8, 0xc5, 0xa4, 0xdf,
-	0xa1, 0x0e, 0x53, 0x5c, 0x38, 0xca, 0xd6, 0x2d, 0x01, 0xc7, 0x8a, 0xc2, 0xfe, 0x77, 0x31, 0x6b,
-	0x11, 0xc3, 0x5c, 0xc8, 0xf4, 0x34, 0xcd, 0xee, 0xfe, 0x47, 0x00, 0xae, 0x6a, 0x72, 0xcc, 0xe1,
-	0x67, 0x36, 0xba, 0x63, 0xd2, 0xfc, 0x11, 0x88, 0x84, 0x61, 0x43, 0x58, 0x6a, 0x77, 0x15, 0x8f,
-	0xdb, 0x5d, 0xf6, 0xbf, 0x5a, 0x90, 0xba, 0xe0, 0xd0, 0x00, 0xca, 0x54, 0x83, 0x51, 0x0e, 0xfd,
-	0x98, 0x26, 0x5f, 0xba, 0xf3, 0x46, 0xcd, 0x05, 0xba, 0x3e, 0xec, 0x4f, 0xcc, 0xa5, 0x20, 0x4f,
-	0x84, 0x2e, 0xdc, 0x44, 0xd7, 0x72, 0x92, 0x46, 0x23, 0x1f, 0xf1, 0x8f, 0x00, 0x74, 0x0d, 0xf3,
-	0x02, 0xac, 0x8e, 0x69, 0x44, 0x37, 0x11, 0x6b, 0xf1, 0xca, 0x6e, 0x22, 0xd6, 0x04, 0x86, 0x39,
-	0xce, 0xfe, 0xc0, 0x82, 0x93, 0x59, 0xf6, 0xe8, 0x0f, 0x2d, 0x58, 0x8d, 0xb3, 0xfc, 0x9e, 0x8a,
-	0xd5, 0x54, 0x46, 0x3a, 0x86, 0xc2, 0xe3, 0x1a, 0xd0, 0x15, 0xcd, 0x36, 0x4c, 0xa7, 0xde, 0x64,
-	0xad, 0x63, 0xdf, 0x64, 0xd3, 0x2f, 0x97, 0x85, 0x99, 0x5e, 0x2e, 0xcd, 0x47, 0xc5, 0xe2, 0xac,
-	0x3d, 0x6a, 0xa5, 0x47, 0xf4, 0xa8, 0xe9, 0xc6, 0xb8, 0xf2, 0xb4, 0xc6, 0xb8, 0x66, 0xe3, 0xc3,
-	0x8f, 0x4f, 0x3f, 0xf7, 0xfd, 0x8f, 0x4f, 0x3f, 0xf7, 0x83, 0x8f, 0x4f, 0x3f, 0xf7, 0xd5, 0x07,
-	0xa7, 0xad, 0x0f, 0x1f, 0x9c, 0xb6, 0xbe, 0xff, 0xe0, 0xb4, 0xf5, 0x83, 0x07, 0xa7, 0xad, 0x7f,
-	0x7e, 0x70, 0xda, 0xfa, 0xfd, 0x1f, 0x9d, 0x7e, 0xee, 0xed, 0x9a, 0x34, 0xed, 0xff, 0x04, 0x00,
-	0x00, 0xff, 0xff, 0x5e, 0x36, 0x95, 0x05, 0x85, 0x4d, 0x00, 0x00,
+	proto.RegisterFile("github.com/argoproj/argo-cd/pkg/apis/application/v1alpha1/generated.proto", fileDescriptor_generated_ee2cf7a8fb926224)
+}
+
+var fileDescriptor_generated_ee2cf7a8fb926224 = []byte{
+	// 4513 bytes of a gzipped FileDescriptorProto
+	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe4, 0x3c, 0x4d, 0x8c, 0x1c, 0xd9,
+	0x59, 0xae, 0xee, 0x9e, 0xee, 0x9e, 0x6f, 0x7e, 0xec, 0x79, 0x59, 0x6f, 0x3a, 0xa3, 0x8d, 0xc7,
+	0x2a, 0x2b, 0xc9, 0x2e, 0xd9, 0xf4, 0xb0, 0x96, 0x03, 0x0e, 0x48, 0x2c, 0xd3, 0x33, 0xfe, 0x19,
+	0x7b, 0x3c, 0x9e, 0x7d, 0x3d, 0x5e, 0x4b, 0x9b, 0x10, 0xb6, 0x5c, 0xfd, 0xba, 0xbb, 0x3c, 0xdd,
+	0x55, 0xb5, 0x55, 0xd5, 0x6d, 0xf7, 0x42, 0x42, 0x02, 0x04, 0x85, 0xc0, 0x46, 0x48, 0x88, 0x13,
+	0x8a, 0x44, 0x10, 0x17, 0x56, 0x5c, 0xb8, 0x90, 0x1b, 0x87, 0x1c, 0x60, 0x8f, 0x01, 0x2d, 0x28,
+	0x02, 0x64, 0xb1, 0x0e, 0x07, 0x44, 0x0e, 0x80, 0x10, 0x17, 0x9f, 0xd0, 0xfb, 0x7f, 0x55, 0xdd,
+	0xed, 0x69, 0xbb, 0xcb, 0x8e, 0x14, 0x6e, 0x5d, 0xef, 0xfb, 0xea, 0xfb, 0xbe, 0xf7, 0xbd, 0x9f,
+	0xef, 0xb7, 0x1a, 0x76, 0x3b, 0x5e, 0xd2, 0x1d, 0xdc, 0xa9, 0xbb, 0x41, 0x7f, 0xd3, 0x89, 0x3a,
+	0x41, 0x18, 0x05, 0x77, 0xd9, 0x8f, 0xcf, 0xb9, 0xad, 0xcd, 0xf0, 0xa8, 0xb3, 0xe9, 0x84, 0x5e,
+	0xbc, 0xe9, 0x84, 0x61, 0xcf, 0x73, 0x9d, 0xc4, 0x0b, 0xfc, 0xcd, 0xe1, 0x6b, 0x4e, 0x2f, 0xec,
+	0x3a, 0xaf, 0x6d, 0x76, 0x88, 0x4f, 0x22, 0x27, 0x21, 0xad, 0x7a, 0x18, 0x05, 0x49, 0x80, 0xbe,
+	0xa0, 0x49, 0xd5, 0x25, 0x29, 0xf6, 0xe3, 0x57, 0xdd, 0x56, 0x3d, 0x3c, 0xea, 0xd4, 0x29, 0xa9,
+	0xba, 0x41, 0xaa, 0x2e, 0x49, 0xad, 0x7f, 0xce, 0x90, 0xa2, 0x13, 0x74, 0x82, 0x4d, 0x46, 0xf1,
+	0xce, 0xa0, 0xcd, 0x9e, 0xd8, 0x03, 0xfb, 0xc5, 0x39, 0xad, 0xdb, 0x47, 0x17, 0xe3, 0xba, 0x17,
+	0x50, 0xd9, 0x36, 0xdd, 0x20, 0x22, 0x9b, 0xc3, 0x31, 0x69, 0xd6, 0x2f, 0x68, 0x9c, 0xbe, 0xe3,
+	0x76, 0x3d, 0x9f, 0x44, 0x23, 0x3d, 0xa1, 0x3e, 0x49, 0x9c, 0x49, 0x6f, 0x6d, 0x4e, 0x7b, 0x2b,
+	0x1a, 0xf8, 0x89, 0xd7, 0x27, 0x63, 0x2f, 0xfc, 0xdc, 0x71, 0x2f, 0xc4, 0x6e, 0x97, 0xf4, 0x9d,
+	0xec, 0x7b, 0xf6, 0x3b, 0xb0, 0xb2, 0x75, 0xbb, 0xb9, 0x35, 0x48, 0xba, 0xdb, 0x81, 0xdf, 0xf6,
+	0x3a, 0xe8, 0xf3, 0xb0, 0xe4, 0xf6, 0x06, 0x71, 0x42, 0xa2, 0x7d, 0xa7, 0x4f, 0x6a, 0xd6, 0x59,
+	0xeb, 0xe5, 0xc5, 0xc6, 0xc7, 0x3e, 0x78, 0xb0, 0x71, 0xe2, 0xe1, 0x83, 0x8d, 0xa5, 0x6d, 0x0d,
+	0xc2, 0x26, 0x1e, 0x7a, 0x05, 0x2a, 0x51, 0xd0, 0x23, 0x5b, 0x78, 0xbf, 0x56, 0x60, 0xaf, 0x9c,
+	0x14, 0xaf, 0x54, 0x30, 0x1f, 0xc6, 0x12, 0x6e, 0xff, 0xb3, 0x05, 0xb0, 0x15, 0x86, 0x07, 0x51,
+	0x70, 0x97, 0xb8, 0x09, 0x7a, 0x1b, 0xaa, 0x54, 0x0b, 0x2d, 0x27, 0x71, 0x18, 0xb7, 0xa5, 0xf3,
+	0x3f, 0x5b, 0xe7, 0x93, 0xa9, 0x9b, 0x93, 0xd1, 0x2b, 0x47, 0xb1, 0xeb, 0xc3, 0xd7, 0xea, 0x37,
+	0xef, 0xd0, 0xf7, 0x6f, 0x90, 0xc4, 0x69, 0x20, 0xc1, 0x0c, 0xf4, 0x18, 0x56, 0x54, 0xd1, 0x11,
+	0x94, 0xe2, 0x90, 0xb8, 0x4c, 0xb0, 0xa5, 0xf3, 0xbb, 0xf5, 0xa7, 0xde, 0x1f, 0x75, 0x2d, 0x76,
+	0x33, 0x24, 0x6e, 0x63, 0x59, 0xb0, 0x2d, 0xd1, 0x27, 0xcc, 0x98, 0xd8, 0xff, 0x64, 0xc1, 0xaa,
+	0x46, 0xdb, 0xf3, 0xe2, 0x04, 0x7d, 0x69, 0x6c, 0x86, 0xf5, 0xd9, 0x66, 0x48, 0xdf, 0x66, 0xf3,
+	0x3b, 0x25, 0x18, 0x55, 0xe5, 0x88, 0x31, 0xbb, 0xbb, 0xb0, 0xe0, 0x25, 0xa4, 0x1f, 0xd7, 0x0a,
+	0x67, 0x8b, 0x2f, 0x2f, 0x9d, 0xbf, 0x94, 0xcb, 0xf4, 0x1a, 0x2b, 0x82, 0xe3, 0xc2, 0x2e, 0xa5,
+	0x8d, 0x39, 0x0b, 0xfb, 0xaf, 0xcb, 0xe6, 0xe4, 0xe8, 0xac, 0xd1, 0x6b, 0xb0, 0x14, 0x07, 0x83,
+	0xc8, 0x25, 0x98, 0x84, 0x41, 0x5c, 0xb3, 0xce, 0x16, 0xe9, 0xe2, 0xd3, 0xbd, 0xd2, 0xd4, 0xc3,
+	0xd8, 0xc4, 0x41, 0xbf, 0x67, 0xc1, 0x72, 0x8b, 0xc4, 0x89, 0xe7, 0x33, 0xfe, 0x52, 0xf2, 0x37,
+	0xe6, 0x93, 0x5c, 0x0e, 0xee, 0x68, 0xca, 0x8d, 0x17, 0xc4, 0x2c, 0x96, 0x8d, 0xc1, 0x18, 0xa7,
+	0x98, 0xd3, 0x0d, 0xdf, 0x22, 0xb1, 0x1b, 0x79, 0x21, 0x7d, 0xae, 0x15, 0xd3, 0x1b, 0x7e, 0x47,
+	0x83, 0xb0, 0x89, 0x87, 0x8e, 0x60, 0x81, 0x6e, 0xe8, 0xb8, 0x56, 0x62, 0xc2, 0x5f, 0x9e, 0x43,
+	0x78, 0xa1, 0x4e, 0x7a, 0x50, 0xb4, 0xde, 0xe9, 0x53, 0x8c, 0x39, 0x0f, 0xf4, 0x9e, 0x05, 0x35,
+	0x71, 0xda, 0x30, 0xe1, 0xaa, 0xbc, 0xdd, 0xf5, 0x12, 0xd2, 0xf3, 0xe2, 0xa4, 0xb6, 0xc0, 0x04,
+	0xd8, 0x9c, 0x6d, 0x4b, 0x5d, 0x89, 0x82, 0x41, 0x78, 0xdd, 0xf3, 0x5b, 0x8d, 0xb3, 0x82, 0x53,
+	0x6d, 0x7b, 0x0a, 0x61, 0x3c, 0x95, 0x25, 0xfa, 0x43, 0x0b, 0xd6, 0x7d, 0xa7, 0x4f, 0xe2, 0xd0,
+	0xa1, 0x8b, 0xca, 0xc1, 0x8d, 0x9e, 0xe3, 0x1e, 0x31, 0x89, 0xca, 0x4f, 0x27, 0x91, 0x2d, 0x24,
+	0x5a, 0xdf, 0x9f, 0x4a, 0x1a, 0x3f, 0x86, 0x2d, 0xfa, 0x13, 0x0b, 0xd6, 0x82, 0x28, 0xec, 0x3a,
+	0x3e, 0x69, 0x49, 0x68, 0x5c, 0xab, 0xb0, 0x13, 0xf7, 0xc5, 0x39, 0xd6, 0xe7, 0x66, 0x96, 0xe6,
+	0x8d, 0xc0, 0xf7, 0x92, 0x20, 0x6a, 0x92, 0x24, 0xf1, 0xfc, 0x4e, 0xdc, 0x38, 0xfd, 0xf0, 0xc1,
+	0xc6, 0xda, 0x18, 0x16, 0x1e, 0x17, 0xc6, 0xfe, 0x9b, 0x22, 0x2c, 0x19, 0x7b, 0xf5, 0x39, 0x5c,
+	0x7e, 0xbd, 0xd4, 0xe5, 0x77, 0x2d, 0x9f, 0x33, 0x36, 0xed, 0xf6, 0x43, 0x09, 0x94, 0xe3, 0xc4,
+	0x49, 0x06, 0x31, 0x3b, 0x47, 0x4b, 0xe7, 0xf7, 0x72, 0xe2, 0xc7, 0x68, 0x36, 0x56, 0x05, 0xc7,
+	0x32, 0x7f, 0xc6, 0x82, 0x17, 0x7a, 0x07, 0x16, 0x83, 0x90, 0x9a, 0x35, 0x7a, 0x80, 0x4b, 0x8c,
+	0xf1, 0xce, 0x3c, 0xeb, 0x2d, 0x69, 0x35, 0x56, 0x1e, 0x3e, 0xd8, 0x58, 0x54, 0x8f, 0x58, 0x73,
+	0xb1, 0x5d, 0x78, 0xc1, 0x90, 0x6f, 0x3b, 0xf0, 0x5b, 0x1e, 0x5b, 0xd0, 0xb3, 0x50, 0x4a, 0x46,
+	0xa1, 0xb4, 0x9b, 0x4a, 0x45, 0x87, 0xa3, 0x90, 0x60, 0x06, 0xa1, 0x96, 0xb2, 0x4f, 0xe2, 0xd8,
+	0xe9, 0x90, 0xac, 0xa5, 0xbc, 0xc1, 0x87, 0xb1, 0x84, 0xdb, 0xef, 0xc0, 0x8b, 0x93, 0x2f, 0x36,
+	0xf4, 0x69, 0x28, 0xc7, 0x24, 0x1a, 0x92, 0x48, 0x30, 0xd2, 0x9a, 0x61, 0xa3, 0x58, 0x40, 0xd1,
+	0x26, 0x2c, 0xaa, 0x03, 0x23, 0xd8, 0xad, 0x09, 0xd4, 0x45, 0x7d, 0xca, 0x34, 0x8e, 0xfd, 0x2f,
+	0x16, 0x9c, 0x34, 0x78, 0x3e, 0x07, 0xfb, 0x75, 0x94, 0xb6, 0x5f, 0x97, 0xf3, 0xd9, 0x31, 0x53,
+	0x0c, 0xd8, 0xb7, 0xcb, 0xb0, 0x66, 0xee, 0x2b, 0x76, 0x2c, 0x99, 0xf3, 0x42, 0xc2, 0xe0, 0x16,
+	0xde, 0x13, 0xea, 0xd4, 0xce, 0x0b, 0x1f, 0xc6, 0x12, 0x4e, 0xd7, 0x37, 0x74, 0x92, 0xae, 0xd0,
+	0xa5, 0x5a, 0xdf, 0x03, 0x27, 0xe9, 0x62, 0x06, 0x41, 0xbf, 0x04, 0xab, 0x89, 0x13, 0x75, 0x48,
+	0x82, 0xc9, 0xd0, 0x8b, 0xe5, 0x8e, 0x5c, 0x6c, 0xbc, 0x28, 0x70, 0x57, 0x0f, 0x53, 0x50, 0x9c,
+	0xc1, 0x46, 0x3e, 0x94, 0xba, 0xa4, 0xd7, 0x17, 0xf7, 0xd6, 0x41, 0x4e, 0x07, 0x88, 0x4d, 0xf4,
+	0x2a, 0xe9, 0xf5, 0x1b, 0x55, 0x2a, 0x2f, 0xfd, 0x85, 0x19, 0x1f, 0xf4, 0x9b, 0x16, 0x2c, 0x1e,
+	0x0d, 0xe2, 0x24, 0xe8, 0x7b, 0xef, 0x92, 0x5a, 0x95, 0x71, 0xbd, 0x95, 0x27, 0xd7, 0xeb, 0x92,
+	0x38, 0x3f, 0x4e, 0xea, 0x11, 0x6b, 0xb6, 0xe8, 0x5d, 0xa8, 0x1c, 0xc5, 0x81, 0xef, 0x93, 0xa4,
+	0xb6, 0xc8, 0x24, 0x68, 0xe6, 0x2a, 0x01, 0x27, 0xdd, 0x58, 0xa2, 0x4b, 0x2a, 0x1e, 0xb0, 0x64,
+	0xc8, 0x14, 0xd0, 0xf2, 0x22, 0xe2, 0x26, 0x41, 0x34, 0xaa, 0x41, 0xfe, 0x0a, 0xd8, 0x91, 0xc4,
+	0xb9, 0x02, 0xd4, 0x23, 0xd6, 0x6c, 0xd1, 0x10, 0xca, 0x61, 0x6f, 0xd0, 0xf1, 0xfc, 0xda, 0x12,
+	0x13, 0x00, 0xe7, 0x29, 0xc0, 0x01, 0xa3, 0xdc, 0x00, 0x7a, 0x41, 0xf0, 0xdf, 0x58, 0x70, 0xb3,
+	0xff, 0xd6, 0x82, 0xf5, 0xe9, 0x02, 0xf3, 0x93, 0xe1, 0x0e, 0xa2, 0x98, 0xdf, 0x68, 0x55, 0xf3,
+	0x64, 0xb0, 0x61, 0x2c, 0xe1, 0xe8, 0xab, 0x50, 0xb9, 0x2b, 0x96, 0xb0, 0x90, 0xff, 0x12, 0x5e,
+	0x13, 0x4b, 0xa8, 0xf8, 0x5f, 0x93, 0xcb, 0x28, 0x98, 0xda, 0x7f, 0x56, 0x80, 0xd3, 0x13, 0x77,
+	0x3c, 0xaa, 0x03, 0x0c, 0x9d, 0xde, 0x80, 0x5c, 0xf6, 0xa8, 0xbf, 0xc6, 0x3d, 0xd4, 0x55, 0x6a,
+	0x30, 0xdf, 0x54, 0xa3, 0xd8, 0xc0, 0x40, 0xbf, 0x0e, 0x10, 0x3a, 0x91, 0xd3, 0x27, 0x09, 0x89,
+	0xe4, 0xb5, 0x74, 0x75, 0x8e, 0xc9, 0x50, 0x21, 0x0e, 0x24, 0x41, 0x6d, 0xae, 0xd5, 0x50, 0x8c,
+	0x0d, 0x7e, 0xd4, 0x1f, 0x8d, 0x48, 0x8f, 0x38, 0x31, 0x61, 0x01, 0x58, 0xc6, 0x1f, 0xc5, 0x1a,
+	0x84, 0x4d, 0x3c, 0x6a, 0x11, 0xd8, 0x14, 0x62, 0x71, 0xdd, 0x28, 0x8b, 0xc0, 0x26, 0x19, 0x63,
+	0x01, 0xb5, 0xff, 0xd7, 0x82, 0xda, 0x34, 0xed, 0xa2, 0x10, 0x2a, 0xe4, 0x7e, 0xf2, 0xa6, 0x13,
+	0x71, 0x35, 0xcd, 0x17, 0x4d, 0x08, 0xa2, 0x6f, 0x3a, 0x91, 0x5e, 0xb5, 0x4b, 0x9c, 0x3a, 0x96,
+	0x6c, 0x50, 0x07, 0x4a, 0x49, 0xcf, 0xc9, 0x23, 0x78, 0x31, 0xd8, 0x69, 0xb3, 0xbb, 0xb7, 0x15,
+	0x63, 0xc6, 0xc0, 0xfe, 0xfb, 0x49, 0xf3, 0x16, 0x77, 0x01, 0xd5, 0x39, 0xf1, 0x87, 0x5e, 0x14,
+	0xf8, 0x7d, 0xe2, 0x27, 0xd9, 0xa0, 0xf7, 0x92, 0x06, 0x61, 0x13, 0x0f, 0xfd, 0xc6, 0x84, 0x8d,
+	0x72, 0x7d, 0x8e, 0x29, 0x08, 0x71, 0x66, 0xde, 0x2b, 0xf6, 0x8f, 0x0b, 0x13, 0x4e, 0xaf, 0xba,
+	0x60, 0xd1, 0x79, 0x00, 0x6a, 0xd9, 0x0f, 0x22, 0xd2, 0xf6, 0xee, 0x8b, 0x59, 0x29, 0x92, 0xfb,
+	0x0a, 0x82, 0x0d, 0x2c, 0x74, 0x01, 0xca, 0x5e, 0xdf, 0xe9, 0x10, 0xea, 0xc1, 0xd1, 0x83, 0xf2,
+	0x12, 0xdd, 0x43, 0xbb, 0x6c, 0xe4, 0xd1, 0x83, 0x8d, 0x55, 0x45, 0x9c, 0x0d, 0x61, 0x81, 0x8b,
+	0xbe, 0x6b, 0xc1, 0xb2, 0x1b, 0xf4, 0xfb, 0x81, 0xbf, 0xe7, 0xdc, 0x21, 0x3d, 0x19, 0x15, 0x75,
+	0x9e, 0x89, 0x1d, 0xa9, 0x6f, 0x1b, 0x9c, 0x2e, 0xf9, 0x49, 0x34, 0xd2, 0x81, 0x9e, 0x09, 0xc2,
+	0x29, 0x91, 0xd6, 0x5f, 0x87, 0xb5, 0xb1, 0x17, 0xd1, 0x29, 0x28, 0x1e, 0x91, 0x11, 0xd7, 0x0d,
+	0xa6, 0x3f, 0xd1, 0x0b, 0xb0, 0xc0, 0x8e, 0x0a, 0x37, 0xf1, 0x98, 0x3f, 0xfc, 0x42, 0xe1, 0xa2,
+	0x65, 0xff, 0xb1, 0x05, 0x1f, 0x9f, 0x72, 0xb7, 0x52, 0xbf, 0xc0, 0xd7, 0xf9, 0x12, 0xb5, 0x01,
+	0xd9, 0x39, 0x65, 0x10, 0xf4, 0x65, 0x28, 0x12, 0x7f, 0x28, 0x76, 0xc9, 0xf6, 0x1c, 0x8a, 0xb9,
+	0xe4, 0x0f, 0xf9, 0xa4, 0x2b, 0x0f, 0x1f, 0x6c, 0x14, 0x2f, 0xf9, 0x43, 0x4c, 0x09, 0xdb, 0xdf,
+	0x5b, 0x48, 0x79, 0x6e, 0x4d, 0xe9, 0x8e, 0x33, 0x29, 0x85, 0xdf, 0xb6, 0x97, 0xe7, 0x7a, 0x18,
+	0x4e, 0x27, 0x0f, 0xee, 0x05, 0x2f, 0xf4, 0x4d, 0x8b, 0x85, 0xd4, 0xd2, 0x59, 0x15, 0xe6, 0xe0,
+	0x19, 0x84, 0xf7, 0x66, 0x94, 0x2e, 0x07, 0xb1, 0xc9, 0x9a, 0xda, 0xaf, 0x90, 0x47, 0xd7, 0xe2,
+	0x22, 0x55, 0x37, 0x91, 0x0c, 0xba, 0x25, 0x1c, 0x0d, 0x00, 0xe2, 0x91, 0xef, 0x1e, 0x04, 0x3d,
+	0xcf, 0x1d, 0x89, 0x28, 0x62, 0x9e, 0xfb, 0xa8, 0xa9, 0x88, 0x71, 0x63, 0xa3, 0x9f, 0xb1, 0xc1,
+	0x08, 0x7d, 0xc7, 0x82, 0x35, 0xaf, 0xe3, 0x07, 0x11, 0xd9, 0xf1, 0xda, 0x6d, 0x12, 0x11, 0x9f,
+	0x06, 0xad, 0x3c, 0xa6, 0x3f, 0x9c, 0x83, 0xbd, 0x8c, 0x39, 0x77, 0xb3, 0xb4, 0x1b, 0x9f, 0x10,
+	0x2a, 0x58, 0x1b, 0x03, 0xe1, 0x71, 0x49, 0x90, 0x03, 0x25, 0xcf, 0x6f, 0x07, 0x22, 0xa6, 0x7f,
+	0x7d, 0x0e, 0x89, 0x76, 0xfd, 0x76, 0xa0, 0x4f, 0x06, 0x7d, 0xc2, 0x8c, 0xb4, 0xfd, 0x3f, 0xd5,
+	0xb4, 0x53, 0xce, 0x83, 0xba, 0x77, 0x61, 0x31, 0x52, 0x41, 0x3c, 0xb7, 0x46, 0xbb, 0x39, 0xe8,
+	0x43, 0x84, 0x92, 0x2a, 0x0a, 0xd2, 0xe1, 0xba, 0x66, 0x47, 0xad, 0x12, 0x5d, 0x22, 0xb1, 0x73,
+	0xe7, 0xdd, 0x05, 0x82, 0xa5, 0x8e, 0x97, 0x47, 0x3e, 0x8d, 0x97, 0x47, 0xbe, 0x8b, 0x02, 0x28,
+	0x77, 0x89, 0xd3, 0x4b, 0xba, 0x22, 0x5e, 0xbe, 0x32, 0x97, 0x9b, 0x41, 0x09, 0x65, 0x43, 0x65,
+	0x3e, 0x8a, 0x05, 0x1b, 0x34, 0x80, 0x4a, 0xd7, 0x8b, 0x99, 0xa7, 0xcb, 0xaf, 0xe8, 0x6b, 0x73,
+	0xe9, 0x94, 0xc7, 0x2c, 0x57, 0x39, 0x45, 0x7d, 0xb8, 0xc4, 0x00, 0x96, 0xbc, 0xd0, 0x6f, 0x59,
+	0x00, 0xae, 0x0c, 0x92, 0xe5, 0xf6, 0xbe, 0x99, 0xcf, 0x8d, 0xa0, 0x82, 0x6f, 0x6d, 0xdb, 0xd4,
+	0x50, 0x8c, 0x0d, 0xb6, 0xe8, 0x6d, 0x58, 0x8e, 0x88, 0x1b, 0xf8, 0xae, 0xd7, 0x23, 0xad, 0xad,
+	0xa4, 0x56, 0x66, 0x3a, 0xff, 0x99, 0xd9, 0x82, 0xd9, 0x43, 0xaf, 0x4f, 0x1a, 0xa7, 0xa8, 0x8d,
+	0xc1, 0x06, 0x0d, 0x9c, 0xa2, 0x88, 0xbe, 0x61, 0xc1, 0xaa, 0x4a, 0x12, 0xd0, 0xa5, 0x20, 0x22,
+	0x8e, 0xdb, 0xcd, 0x23, 0x1f, 0xc1, 0x08, 0x36, 0x10, 0x0d, 0x22, 0xd3, 0x63, 0x38, 0xc3, 0x14,
+	0xbd, 0x05, 0x10, 0xdc, 0x61, 0x39, 0x00, 0x3a, 0xcf, 0xea, 0x13, 0xcf, 0x73, 0x95, 0xe7, 0x93,
+	0x24, 0x05, 0x6c, 0x50, 0x43, 0xd7, 0x01, 0xf8, 0x39, 0x39, 0x1c, 0x85, 0x84, 0x85, 0x6b, 0x8b,
+	0x8d, 0xcf, 0x4a, 0xcd, 0x37, 0x15, 0xe4, 0xd1, 0x83, 0x8d, 0x71, 0x7f, 0x9c, 0xe5, 0x41, 0x8c,
+	0xd7, 0xd1, 0x7d, 0xa8, 0xc4, 0x83, 0x7e, 0xdf, 0x51, 0x91, 0xd7, 0x8d, 0x9c, 0x4c, 0x14, 0x27,
+	0xaa, 0xb7, 0xa4, 0x18, 0xc0, 0x92, 0x9d, 0xed, 0x03, 0x1a, 0xc7, 0x47, 0x17, 0x60, 0x99, 0xdc,
+	0x4f, 0x48, 0xe4, 0x3b, 0xbd, 0x5b, 0x78, 0x4f, 0x46, 0x0b, 0x6c, 0xd9, 0x2f, 0x19, 0xe3, 0x38,
+	0x85, 0x85, 0x6c, 0xe5, 0x34, 0x15, 0x18, 0x3e, 0x68, 0xa7, 0x49, 0xba, 0x48, 0xf6, 0xef, 0x14,
+	0x52, 0xf6, 0xf9, 0x30, 0x22, 0x04, 0xf5, 0x60, 0xc1, 0x0f, 0x5a, 0xea, 0x7e, 0xbb, 0x92, 0xc3,
+	0xfd, 0xb6, 0x1f, 0xb4, 0x8c, 0x2c, 0x32, 0x7d, 0x8a, 0x31, 0x67, 0x82, 0x7e, 0xdb, 0x82, 0x15,
+	0x99, 0x92, 0x64, 0x00, 0xe1, 0x8c, 0xe4, 0xc6, 0xf6, 0xb4, 0x60, 0xbb, 0x72, 0xd3, 0xe4, 0x82,
+	0xd3, 0x4c, 0xed, 0x1f, 0x59, 0xa9, 0x40, 0xed, 0xb6, 0x93, 0xb8, 0xdd, 0x4b, 0x43, 0xea, 0x4f,
+	0x5f, 0x4f, 0x25, 0xcf, 0x7e, 0xde, 0x4c, 0x9e, 0x3d, 0x7a, 0xb0, 0xf1, 0x99, 0x69, 0x25, 0xae,
+	0x7b, 0x94, 0x42, 0x9d, 0x91, 0x30, 0xf2, 0x6c, 0x5f, 0x81, 0x25, 0x43, 0x62, 0x71, 0x95, 0xe7,
+	0x95, 0x5d, 0x52, 0x9e, 0x87, 0x31, 0x88, 0x4d, 0x7e, 0xf6, 0x3f, 0x14, 0xa0, 0x22, 0x32, 0xeb,
+	0x33, 0x67, 0xeb, 0xa4, 0x13, 0x59, 0x98, 0xea, 0x44, 0x86, 0x50, 0x76, 0x59, 0x9d, 0x4e, 0xd8,
+	0x8b, 0x79, 0xc2, 0x52, 0x21, 0x1d, 0xaf, 0xfb, 0x69, 0x99, 0xf8, 0x33, 0x16, 0x7c, 0xd0, 0x7b,
+	0x16, 0x9c, 0x74, 0x69, 0x58, 0xe2, 0xea, 0x2b, 0xad, 0x34, 0x77, 0x2e, 0x79, 0x3b, 0x4d, 0xb1,
+	0xf1, 0x71, 0xc1, 0xfd, 0x64, 0x06, 0x80, 0xb3, 0xbc, 0xed, 0xbf, 0x2a, 0xc2, 0x4a, 0x4a, 0x72,
+	0xf4, 0x2a, 0x54, 0x07, 0x31, 0x3d, 0x8b, 0xca, 0xfd, 0x56, 0xe9, 0xc6, 0x5b, 0x62, 0x1c, 0x2b,
+	0x0c, 0x8a, 0x1d, 0x3a, 0x71, 0x7c, 0x2f, 0x88, 0x5a, 0x42, 0xcf, 0x0a, 0xfb, 0x40, 0x8c, 0x63,
+	0x85, 0x41, 0x03, 0xc3, 0x3b, 0xc4, 0x89, 0x48, 0x74, 0x18, 0x1c, 0x91, 0xb1, 0xe2, 0x50, 0x43,
+	0x83, 0xb0, 0x89, 0xc7, 0x94, 0x96, 0xf4, 0xe2, 0xed, 0x9e, 0x47, 0xfc, 0x84, 0x8b, 0x99, 0x83,
+	0xd2, 0x0e, 0xf7, 0x9a, 0x26, 0x45, 0xad, 0xb4, 0x0c, 0x00, 0x67, 0x79, 0xa3, 0xaf, 0x5b, 0xb0,
+	0xe2, 0xdc, 0x8b, 0x75, 0x99, 0xb7, 0xb6, 0x30, 0xf7, 0xf6, 0x49, 0x95, 0x8d, 0x1b, 0x6b, 0xf4,
+	0xd8, 0xa7, 0x86, 0x70, 0x9a, 0xa3, 0xfd, 0xa1, 0x05, 0xb2, 0x7c, 0xfc, 0x1c, 0xb2, 0xca, 0x9d,
+	0x74, 0x56, 0xb9, 0x31, 0xff, 0x39, 0x99, 0x92, 0x51, 0xde, 0x87, 0x0a, 0x8d, 0x2a, 0x1d, 0xbf,
+	0x85, 0x3e, 0x05, 0x15, 0x97, 0xff, 0x14, 0x66, 0x83, 0xe5, 0x1b, 0x05, 0x14, 0x4b, 0x18, 0x7a,
+	0x09, 0x4a, 0x4e, 0xd4, 0x91, 0xa6, 0x82, 0xa5, 0x63, 0xb7, 0xa2, 0x4e, 0x8c, 0xd9, 0xa8, 0xfd,
+	0x5e, 0x01, 0x60, 0x3b, 0xe8, 0x87, 0x4e, 0x44, 0x5a, 0x87, 0xc1, 0xff, 0xfb, 0x08, 0xce, 0xfe,
+	0x7d, 0x0b, 0x10, 0xd5, 0x47, 0xe0, 0x13, 0x5f, 0x67, 0x46, 0xd0, 0x26, 0x2c, 0xba, 0x72, 0x54,
+	0x9c, 0x7a, 0xe5, 0xd2, 0x2b, 0x74, 0xac, 0x71, 0x66, 0xb8, 0x5b, 0xcf, 0xc9, 0xc0, 0x9f, 0x9f,
+	0x72, 0xb5, 0xdc, 0x2c, 0x81, 0x26, 0xf2, 0x00, 0xf6, 0xb7, 0x0b, 0xf0, 0x22, 0xdf, 0xd0, 0x37,
+	0x1c, 0xdf, 0xe9, 0x90, 0x3e, 0x95, 0x6a, 0xd6, 0x14, 0xc0, 0xdb, 0x34, 0x96, 0xf2, 0x64, 0x7e,
+	0x74, 0xae, 0x3d, 0xc9, 0xf7, 0x12, 0xdf, 0x3d, 0xbb, 0xbe, 0x97, 0x60, 0x46, 0x19, 0x85, 0x50,
+	0x95, 0x1d, 0x1e, 0xc2, 0x42, 0xe4, 0xc1, 0x45, 0x1d, 0xb4, 0x2b, 0x82, 0x36, 0x56, 0x5c, 0xec,
+	0xef, 0x5b, 0x90, 0xbd, 0xb4, 0x99, 0xbd, 0xe3, 0x55, 0xc0, 0xac, 0xbd, 0x4b, 0xd7, 0xed, 0x66,
+	0x2f, 0x85, 0xa1, 0x2f, 0xc1, 0x92, 0x93, 0x24, 0xa4, 0x1f, 0x26, 0xcc, 0xa3, 0x2d, 0x3e, 0x9d,
+	0x47, 0x7b, 0x23, 0x68, 0x79, 0x6d, 0x8f, 0x79, 0xb4, 0x26, 0x39, 0xfb, 0x0d, 0xa8, 0xca, 0xac,
+	0xca, 0x0c, 0xcb, 0x78, 0x2e, 0x95, 0x21, 0x9a, 0xb2, 0x51, 0x1c, 0x58, 0x36, 0x03, 0xb2, 0x67,
+	0xa0, 0x13, 0xfb, 0x3d, 0x0b, 0x56, 0x52, 0xb9, 0xe5, 0x9c, 0x64, 0xa7, 0x56, 0xaf, 0x1d, 0xb0,
+	0x58, 0x39, 0xf2, 0x7c, 0xee, 0x6a, 0x54, 0xf5, 0x51, 0xbd, 0xac, 0x41, 0xd8, 0xc4, 0xb3, 0x6f,
+	0x00, 0x8b, 0xea, 0xf3, 0xd2, 0xe0, 0x1b, 0x50, 0xa5, 0xe4, 0xe8, 0x6d, 0x9b, 0x17, 0xc9, 0x26,
+	0x54, 0xaf, 0xdd, 0x3e, 0xe4, 0x36, 0xda, 0x86, 0xa2, 0xe7, 0xf0, 0xbb, 0xa3, 0xa8, 0x77, 0xf8,
+	0x6e, 0x1c, 0x0f, 0xd8, 0xfe, 0xa0, 0x40, 0x74, 0x0e, 0x8a, 0xe4, 0x7e, 0xc8, 0x48, 0x16, 0xf5,
+	0xfd, 0x72, 0xe9, 0x7e, 0xe8, 0x45, 0x24, 0xa6, 0x48, 0xe4, 0x7e, 0x68, 0x0f, 0x00, 0x74, 0xee,
+	0x39, 0xaf, 0x25, 0x38, 0x0b, 0x25, 0x37, 0x68, 0x11, 0xa1, 0x7b, 0x45, 0x66, 0x3b, 0x68, 0x11,
+	0xcc, 0x20, 0xf6, 0xb7, 0x2c, 0x38, 0x95, 0x4d, 0x18, 0xff, 0xc4, 0xae, 0xc5, 0x3d, 0x38, 0xa5,
+	0xd2, 0xb3, 0x37, 0x43, 0x1e, 0x6d, 0x5f, 0x84, 0xe5, 0x3b, 0x03, 0xaf, 0xd7, 0x12, 0xcf, 0x42,
+	0x1c, 0x95, 0xa9, 0x6d, 0x18, 0x30, 0x9c, 0xc2, 0xb4, 0x63, 0xd0, 0x45, 0x77, 0xd4, 0x16, 0xb9,
+	0x18, 0x6b, 0x6e, 0x8f, 0xa5, 0x39, 0xf2, 0x5d, 0x5d, 0xdb, 0xaf, 0xa6, 0x53, 0x31, 0xf6, 0x9f,
+	0x96, 0x20, 0x13, 0x55, 0xa3, 0x81, 0xd9, 0x57, 0x60, 0xe5, 0xd8, 0x57, 0xa0, 0xd6, 0x64, 0x52,
+	0x6f, 0x01, 0xfa, 0x3c, 0x2c, 0x84, 0x5d, 0x27, 0x96, 0x8b, 0xb2, 0x21, 0x35, 0x7e, 0x40, 0x07,
+	0x1f, 0x99, 0xc1, 0x3f, 0x1b, 0xc1, 0x1c, 0xdb, 0xbc, 0x39, 0x8a, 0xc7, 0xdc, 0xa6, 0x5f, 0xe5,
+	0xb9, 0x4e, 0x4c, 0xe2, 0x41, 0x2f, 0x11, 0x9e, 0xe9, 0x7e, 0x5e, 0x9a, 0xe5, 0x54, 0x75, 0xd2,
+	0x93, 0x3f, 0x63, 0x83, 0x23, 0xfa, 0x22, 0x2c, 0xc6, 0x89, 0x13, 0x25, 0x4f, 0x99, 0x85, 0x51,
+	0xea, 0x6b, 0x4a, 0x22, 0x58, 0xd3, 0x43, 0x6f, 0x01, 0xb4, 0x3d, 0xdf, 0x8b, 0xbb, 0x8c, 0x7a,
+	0xe5, 0xe9, 0x2c, 0xc5, 0x65, 0x45, 0x01, 0x1b, 0xd4, 0xec, 0x5f, 0x86, 0xb3, 0xc7, 0x75, 0x03,
+	0x51, 0xff, 0xee, 0x9e, 0x13, 0xf9, 0xa2, 0x60, 0xca, 0xb6, 0xd9, 0x6d, 0x27, 0xf2, 0x31, 0x1b,
+	0xb5, 0xdf, 0x2f, 0xc0, 0x92, 0xd1, 0xf0, 0x35, 0xc3, 0x7d, 0x91, 0x69, 0x50, 0x2b, 0xcc, 0xd8,
+	0xa0, 0xf6, 0x32, 0x54, 0xc3, 0xa0, 0xe7, 0xb9, 0x9e, 0x2a, 0xe5, 0x2c, 0xb3, 0x20, 0x47, 0x8c,
+	0x61, 0x05, 0x45, 0x09, 0x2c, 0xde, 0xbd, 0x97, 0xb0, 0x5b, 0x51, 0x16, 0x6e, 0xe6, 0xa9, 0x4f,
+	0xc8, 0x1b, 0x56, 0x2f, 0x93, 0x1c, 0x89, 0xb1, 0x66, 0x84, 0x6c, 0x28, 0x77, 0xa2, 0x60, 0x10,
+	0xf2, 0x6c, 0xa0, 0xc8, 0x99, 0xb0, 0x66, 0xb0, 0x18, 0x0b, 0x88, 0xfd, 0xdd, 0x32, 0x00, 0xeb,
+	0x19, 0xf4, 0x58, 0x16, 0xf1, 0x2c, 0x94, 0x22, 0x12, 0x06, 0x59, 0x5d, 0x51, 0x0c, 0xcc, 0x20,
+	0xa9, 0x58, 0xb0, 0xf0, 0x44, 0xb1, 0x60, 0xf1, 0xd8, 0x58, 0xf0, 0x17, 0x61, 0x25, 0x8e, 0xbb,
+	0x07, 0x91, 0x37, 0x74, 0x12, 0x72, 0x9d, 0x8c, 0x44, 0xa1, 0x55, 0x25, 0x3d, 0x9a, 0xcd, 0xab,
+	0x1a, 0x88, 0xd3, 0xb8, 0x13, 0xc3, 0xe8, 0x85, 0x9f, 0x5c, 0x18, 0x8d, 0x9a, 0x70, 0xda, 0xf3,
+	0x63, 0xe2, 0x0e, 0x22, 0x51, 0x21, 0xb8, 0x1a, 0xc4, 0x09, 0x9d, 0x54, 0x99, 0xed, 0xda, 0x4f,
+	0x0a, 0x42, 0xa7, 0x77, 0x27, 0x21, 0xe1, 0xc9, 0xef, 0x52, 0x7d, 0x4a, 0x00, 0x3b, 0x77, 0x55,
+	0xc3, 0xae, 0x8a, 0x71, 0xac, 0x30, 0xa8, 0xad, 0x22, 0xbe, 0x73, 0xa7, 0x47, 0xf6, 0xda, 0x31,
+	0x4b, 0x51, 0x56, 0x0d, 0x13, 0xcb, 0x01, 0x97, 0x9b, 0x58, 0xe3, 0xa0, 0x2b, 0xb0, 0xa6, 0x03,
+	0x5b, 0x12, 0x25, 0x3b, 0x34, 0x74, 0xe4, 0xf9, 0x47, 0x55, 0xd3, 0xd0, 0xa1, 0xb0, 0x40, 0xc0,
+	0xe3, 0xef, 0xa0, 0x1d, 0x38, 0x95, 0x1a, 0xa4, 0xf3, 0x06, 0x46, 0xa7, 0x26, 0xe8, 0x9c, 0x4a,
+	0xd1, 0xa1, 0x53, 0x1e, 0x7b, 0x03, 0x6d, 0x99, 0x31, 0xbe, 0xc3, 0x84, 0x59, 0x62, 0x44, 0x26,
+	0xc4, 0xe5, 0x5b, 0x4c, 0x94, 0x2c, 0xbe, 0xea, 0x16, 0x5b, 0x9e, 0xda, 0x2d, 0x26, 0xaf, 0x87,
+	0x95, 0x69, 0xd7, 0x83, 0xfd, 0xcd, 0x02, 0x9c, 0xd6, 0x67, 0x84, 0x0a, 0xe7, 0xb5, 0xe9, 0x46,
+	0x61, 0xe5, 0x5f, 0x9e, 0x58, 0x32, 0x3a, 0xb9, 0x55, 0x8a, 0xbc, 0xa9, 0x20, 0xd8, 0xc0, 0xa2,
+	0x4b, 0xe8, 0x92, 0x88, 0xe5, 0xd1, 0xb2, 0x07, 0x68, 0x5b, 0x8c, 0x63, 0x85, 0xc1, 0x9a, 0xc5,
+	0x49, 0x94, 0x34, 0x07, 0x77, 0xd8, 0x0b, 0x99, 0xf4, 0xc8, 0xb6, 0x06, 0x61, 0x13, 0x8f, 0x5e,
+	0x4d, 0xae, 0x5c, 0x3f, 0x7a, 0x88, 0x96, 0xf9, 0xd5, 0xa4, 0x96, 0x4c, 0x41, 0xa5, 0x38, 0xd4,
+	0x0f, 0x64, 0xc7, 0x25, 0x23, 0x0e, 0x2b, 0x22, 0x29, 0x0c, 0xfb, 0xbf, 0x2c, 0xf8, 0xc4, 0x44,
+	0x55, 0x3c, 0x87, 0x84, 0xc3, 0x20, 0x9d, 0x70, 0x38, 0x98, 0x2b, 0xa7, 0x3a, 0x61, 0x0a, 0x53,
+	0xd2, 0x0f, 0xff, 0x68, 0xc1, 0xaa, 0xc6, 0x7f, 0x0e, 0xf3, 0x6c, 0xe7, 0xd7, 0x6e, 0xae, 0xe5,
+	0x6e, 0x2c, 0x8e, 0x4d, 0xec, 0x7d, 0x36, 0x31, 0x6e, 0x62, 0xb7, 0x5c, 0xd9, 0x5b, 0x79, 0x8c,
+	0xa9, 0x1c, 0x42, 0x99, 0x75, 0x47, 0x48, 0xe9, 0xf6, 0x73, 0xc8, 0x6c, 0x73, 0xe6, 0xcc, 0xc5,
+	0xd6, 0x41, 0x1b, 0x7b, 0x8c, 0xb1, 0xe0, 0x66, 0xf7, 0xa1, 0x96, 0x46, 0xdf, 0x21, 0xd4, 0x69,
+	0x98, 0x51, 0xea, 0x4d, 0x58, 0x74, 0xd8, 0x5b, 0x7b, 0x03, 0x27, 0xdb, 0xa4, 0xb9, 0x25, 0x01,
+	0x58, 0xe3, 0xd8, 0x7f, 0x6e, 0xc1, 0xc7, 0x26, 0x88, 0x97, 0x63, 0xec, 0x91, 0xe8, 0xe3, 0x3c,
+	0xa5, 0x87, 0xb5, 0x45, 0xda, 0x8e, 0x74, 0x1e, 0x0d, 0x57, 0x73, 0x87, 0x0f, 0x63, 0x09, 0xb7,
+	0xff, 0xc3, 0x82, 0x93, 0x69, 0x59, 0x63, 0x74, 0x0d, 0x10, 0x9f, 0xcc, 0x8e, 0x17, 0xbb, 0xc1,
+	0x90, 0x44, 0x23, 0x3a, 0x73, 0x2e, 0xf5, 0xba, 0xa0, 0x84, 0xb6, 0xc6, 0x30, 0xf0, 0x84, 0xb7,
+	0xd0, 0xb7, 0x58, 0xaa, 0x4a, 0x6a, 0x5b, 0x2e, 0x7c, 0x33, 0xb7, 0x85, 0xd7, 0x2b, 0x69, 0xfa,
+	0x5c, 0x8a, 0x1f, 0x36, 0x99, 0xdb, 0x1f, 0x16, 0x60, 0x59, 0xbe, 0xbe, 0xe3, 0xb5, 0xdb, 0x54,
+	0xdf, 0xcc, 0x95, 0x11, 0x93, 0x53, 0xfa, 0x66, 0x7e, 0x0e, 0xe6, 0x30, 0xaa, 0xef, 0x23, 0xcf,
+	0x6f, 0x65, 0x63, 0xb0, 0xeb, 0x9e, 0xdf, 0xc2, 0x0c, 0x92, 0x6e, 0xe3, 0x2d, 0x1e, 0xdf, 0xc6,
+	0xab, 0x76, 0x42, 0xe9, 0x71, 0x5e, 0x25, 0x6f, 0x3c, 0xd5, 0xbe, 0x88, 0x71, 0x75, 0x1f, 0x6a,
+	0x10, 0x36, 0xf1, 0xa8, 0x24, 0x3d, 0x6f, 0x48, 0xf8, 0x4b, 0xe5, 0xb4, 0x24, 0x7b, 0x12, 0x80,
+	0x35, 0x0e, 0x95, 0xa4, 0xe5, 0xb5, 0xdb, 0xcc, 0x1f, 0x30, 0x24, 0xa1, 0xda, 0xc1, 0x0c, 0x42,
+	0x31, 0xba, 0x41, 0x70, 0x24, 0x5c, 0x00, 0x85, 0x71, 0x35, 0x08, 0x8e, 0x30, 0x83, 0xd8, 0x3f,
+	0x66, 0xf7, 0xfa, 0x94, 0x7e, 0x86, 0xbc, 0x74, 0x2c, 0x55, 0x56, 0x7c, 0xdc, 0x39, 0xd5, 0xab,
+	0x50, 0x9a, 0x61, 0x15, 0x2e, 0xc0, 0xf2, 0xdd, 0x38, 0xf0, 0x0f, 0x02, 0xcf, 0x67, 0x1d, 0x62,
+	0x0b, 0xba, 0x98, 0x78, 0xad, 0x79, 0x73, 0x5f, 0x8e, 0xe3, 0x14, 0x96, 0xfd, 0xfd, 0x05, 0x78,
+	0x51, 0x95, 0xd5, 0x48, 0x72, 0x2f, 0x88, 0x8e, 0x3c, 0xbf, 0xc3, 0x32, 0x2b, 0xdf, 0xb1, 0x60,
+	0x99, 0xaf, 0x86, 0x68, 0xb3, 0xe2, 0x75, 0x43, 0x37, 0x8f, 0x02, 0x5e, 0x8a, 0x53, 0xfd, 0xd0,
+	0xe0, 0x92, 0x69, 0xb1, 0x32, 0x41, 0x38, 0x25, 0x0e, 0x7a, 0x17, 0x40, 0x76, 0x33, 0xb7, 0xf3,
+	0x68, 0xe8, 0x96, 0xc2, 0x61, 0xd2, 0xd6, 0x9e, 0xcb, 0xa1, 0xe2, 0x80, 0x0d, 0x6e, 0xe8, 0x1b,
+	0x16, 0x94, 0x7b, 0x5c, 0x2b, 0x45, 0xc6, 0xf8, 0x57, 0xf2, 0xd7, 0x8a, 0xa9, 0x0f, 0x65, 0x0b,
+	0x84, 0x26, 0x04, 0x73, 0x84, 0xa1, 0xe2, 0xf9, 0x9d, 0x88, 0xc4, 0x32, 0x96, 0xfa, 0x8c, 0x61,
+	0x7d, 0xeb, 0x6e, 0x10, 0x11, 0x66, 0x6b, 0x03, 0xa7, 0xd5, 0x70, 0x7a, 0x8e, 0xef, 0x92, 0x68,
+	0x97, 0xa3, 0xeb, 0x4b, 0x54, 0x0c, 0x60, 0x49, 0x68, 0xac, 0x2a, 0xbd, 0x30, 0x4b, 0x55, 0x7a,
+	0xfd, 0x75, 0x58, 0x1b, 0x5b, 0xc6, 0x27, 0x69, 0x78, 0x5b, 0xff, 0x02, 0x2c, 0x3d, 0x6d, 0xaf,
+	0xdc, 0x87, 0x0b, 0xfa, 0x26, 0xdc, 0x0f, 0x5a, 0xac, 0x1c, 0x1b, 0xe9, 0xd5, 0x14, 0x8e, 0x49,
+	0x5e, 0x7b, 0xc3, 0x68, 0x8f, 0x55, 0x83, 0xd8, 0xe4, 0x47, 0x77, 0x66, 0xe8, 0x44, 0xc4, 0x7f,
+	0xa6, 0x3b, 0xf3, 0x40, 0x71, 0xc0, 0x06, 0x37, 0x44, 0x44, 0x0b, 0x55, 0x71, 0xee, 0xd0, 0x5a,
+	0xe6, 0x43, 0x27, 0xb5, 0x51, 0xd1, 0x10, 0x73, 0xd5, 0x4f, 0xed, 0x57, 0x91, 0xd9, 0x79, 0x23,
+	0xf7, 0x83, 0xc0, 0x7b, 0x50, 0xd2, 0x63, 0x38, 0xc3, 0x9c, 0xc6, 0x47, 0x72, 0x05, 0xde, 0x24,
+	0x11, 0xfb, 0x12, 0x62, 0x21, 0x1d, 0x1f, 0xe1, 0x34, 0x18, 0x67, 0xf1, 0x8d, 0xbe, 0x8a, 0xf2,
+	0xb4, 0xbe, 0x0a, 0x74, 0xa4, 0x5a, 0xa8, 0x2a, 0xf9, 0xb6, 0x50, 0xc1, 0x78, 0xfb, 0x94, 0xfd,
+	0x3d, 0x0b, 0x4e, 0x49, 0xa9, 0x6f, 0x0e, 0x49, 0x14, 0x79, 0x2d, 0x66, 0x17, 0x38, 0x58, 0x7b,
+	0x31, 0xca, 0x2e, 0x5c, 0x95, 0x00, 0xac, 0x71, 0x68, 0x20, 0x3b, 0xde, 0xf2, 0x57, 0x48, 0x07,
+	0xb2, 0x33, 0x35, 0xe7, 0xbd, 0x02, 0x15, 0xee, 0x12, 0xc5, 0xd9, 0x94, 0x9f, 0x70, 0xb5, 0xb0,
+	0x84, 0xdb, 0xff, 0x6d, 0x81, 0x79, 0x3a, 0x66, 0xb3, 0x9a, 0xaf, 0x40, 0x65, 0x28, 0x96, 0x2e,
+	0x53, 0x8c, 0x90, 0x4b, 0x26, 0xe1, 0xca, 0xc0, 0x16, 0x67, 0x73, 0x62, 0x4a, 0x4f, 0xe0, 0xc4,
+	0x2c, 0x4c, 0xb5, 0xc8, 0x9f, 0x84, 0xe2, 0xc0, 0x6b, 0x09, 0x3f, 0x64, 0x49, 0x20, 0x14, 0x6f,
+	0xed, 0xee, 0x60, 0x3a, 0x6e, 0xff, 0x5b, 0x51, 0xc7, 0x10, 0x22, 0xf3, 0xf8, 0x53, 0x31, 0xed,
+	0x0b, 0xaa, 0x96, 0xc4, 0x67, 0xfe, 0x52, 0xba, 0x96, 0xf4, 0xe8, 0xc1, 0x06, 0xf0, 0xe9, 0xb2,
+	0x72, 0xc1, 0x84, 0xca, 0x52, 0xe5, 0x98, 0xfc, 0xf0, 0x45, 0xa8, 0x52, 0xc7, 0x8b, 0x05, 0xf5,
+	0xd5, 0x14, 0x8b, 0xea, 0x55, 0x31, 0xfe, 0xc8, 0xf8, 0x8d, 0x15, 0x36, 0xda, 0x82, 0x45, 0xfa,
+	0x9b, 0x25, 0xa6, 0x45, 0x6e, 0xe6, 0x9c, 0x3a, 0x0b, 0x12, 0x30, 0x21, 0x87, 0xad, 0xdf, 0xa2,
+	0x0a, 0x63, 0xfd, 0xb1, 0x8c, 0x04, 0xa4, 0x15, 0xd6, 0x94, 0x00, 0xac, 0x71, 0xec, 0x8f, 0x8c,
+	0x65, 0x16, 0xd5, 0xb6, 0x9f, 0x8a, 0x65, 0xbe, 0x98, 0x59, 0xe6, 0xb3, 0x63, 0xcb, 0xbc, 0xaa,
+	0xdb, 0x4b, 0x53, 0x4b, 0xfd, 0x3c, 0xef, 0xc4, 0xe3, 0xfd, 0x77, 0x6e, 0x09, 0xde, 0x19, 0x78,
+	0x11, 0x89, 0x0f, 0xa2, 0x81, 0xef, 0xf9, 0x1d, 0xb6, 0x35, 0xaa, 0xa6, 0x25, 0x48, 0x81, 0x71,
+	0x16, 0xdf, 0xfe, 0xcb, 0x02, 0x0d, 0x23, 0x53, 0xed, 0xa6, 0xe8, 0x55, 0xa8, 0x46, 0xf2, 0x1b,
+	0xbb, 0x4c, 0xae, 0x4a, 0x7d, 0x5d, 0xa7, 0x30, 0xd0, 0x97, 0x01, 0x5a, 0x24, 0xec, 0x05, 0x23,
+	0x56, 0x16, 0x28, 0x3d, 0x71, 0x59, 0x40, 0x59, 0xf9, 0x1d, 0x45, 0x05, 0x1b, 0x14, 0xd1, 0x3a,
+	0x14, 0xbc, 0x16, 0x5b, 0xcd, 0x62, 0x03, 0x04, 0x6e, 0x61, 0x77, 0x07, 0x17, 0xbc, 0x96, 0xd1,
+	0xc5, 0x51, 0x7e, 0x7e, 0x5d, 0x1c, 0xf6, 0xdf, 0x31, 0x63, 0xc5, 0xa7, 0x7f, 0x43, 0xe6, 0x6f,
+	0x3e, 0x0d, 0x65, 0x67, 0x90, 0x74, 0x83, 0xb1, 0x5e, 0xb4, 0x2d, 0x36, 0x8a, 0x05, 0x14, 0xed,
+	0x41, 0xa9, 0x45, 0x63, 0xbc, 0xc2, 0x13, 0x2b, 0x4a, 0xc7, 0x78, 0x34, 0x14, 0x64, 0x54, 0xd0,
+	0x4b, 0x50, 0x4a, 0x9c, 0x8e, 0x2c, 0x44, 0xb0, 0x9a, 0xc8, 0xa1, 0xd3, 0x89, 0x31, 0x1b, 0x35,
+	0x6f, 0xa6, 0xd2, 0x31, 0x35, 0xef, 0xbf, 0x28, 0xc1, 0x4a, 0xaa, 0xda, 0x94, 0xda, 0x05, 0xd6,
+	0xb1, 0xbb, 0xe0, 0x1c, 0x2c, 0x84, 0xd1, 0xc0, 0xe7, 0xf3, 0xaa, 0xea, 0x8b, 0x81, 0xee, 0x33,
+	0x82, 0x39, 0x8c, 0xea, 0xa8, 0x15, 0x8d, 0xf0, 0xc0, 0x17, 0xe5, 0x57, 0xa5, 0xa3, 0x1d, 0x36,
+	0x8a, 0x05, 0x14, 0x7d, 0x05, 0x96, 0x63, 0x76, 0x00, 0x23, 0x27, 0x21, 0x1d, 0xf9, 0xd1, 0xc0,
+	0x95, 0xb9, 0xdb, 0xc5, 0x39, 0x39, 0xee, 0xdf, 0x9b, 0x23, 0x38, 0xc5, 0x0e, 0x7d, 0xdd, 0x32,
+	0x5b, 0xe4, 0xcb, 0x73, 0xe7, 0x1d, 0xb3, 0x55, 0x3c, 0xbe, 0xbb, 0x1e, 0xdf, 0x29, 0x1f, 0xaa,
+	0x9d, 0x5d, 0x79, 0x06, 0x3b, 0x1b, 0x26, 0xf4, 0x26, 0x7d, 0x16, 0x16, 0xfb, 0x8e, 0xef, 0xb5,
+	0x49, 0x9c, 0xc4, 0xb5, 0x2a, 0xdb, 0x4f, 0xec, 0xb3, 0xca, 0x1b, 0x72, 0x10, 0x6b, 0xb8, 0xfd,
+	0x35, 0x0b, 0x4e, 0x4f, 0x9c, 0xd6, 0x73, 0xcb, 0x1a, 0xd0, 0x9b, 0xeb, 0x63, 0x13, 0xea, 0xa3,
+	0x68, 0xf8, 0x6c, 0xbe, 0x6f, 0x10, 0xd5, 0xd7, 0x95, 0xa9, 0x2b, 0xf6, 0x64, 0xb7, 0xa6, 0xbe,
+	0xb9, 0x8a, 0xcf, 0xf1, 0xe6, 0xfa, 0x5d, 0x0b, 0x8c, 0xef, 0x65, 0xd0, 0xaf, 0xc1, 0xa2, 0x33,
+	0x48, 0x82, 0xbe, 0x93, 0x90, 0x96, 0x88, 0x1c, 0xf7, 0x73, 0xf9, 0x32, 0x67, 0x4b, 0x52, 0xe5,
+	0xfa, 0x52, 0x8f, 0x58, 0xf3, 0xb3, 0xbb, 0x7c, 0xf9, 0x32, 0x2f, 0xe8, 0x8b, 0xc4, 0x7a, 0xcc,
+	0x45, 0xf2, 0x2a, 0x54, 0x63, 0xd2, 0x6b, 0x53, 0x83, 0x29, 0x2e, 0x1c, 0xa5, 0xeb, 0xa6, 0x18,
+	0xc7, 0x0a, 0xc3, 0xfe, 0x4f, 0x31, 0x6b, 0xe1, 0xc3, 0x5c, 0xcc, 0x74, 0x0c, 0xcd, 0x6e, 0xfe,
+	0x47, 0x00, 0xae, 0x6a, 0x21, 0xcc, 0xe1, 0x23, 0x16, 0xdd, 0x8f, 0x68, 0x7e, 0x62, 0x21, 0xc7,
+	0xb0, 0xc1, 0x2c, 0xb5, 0xbb, 0x8a, 0xc7, 0xed, 0x2e, 0xfb, 0xdf, 0x2d, 0x48, 0x5d, 0x70, 0xa8,
+	0x0f, 0x0b, 0x54, 0x82, 0x51, 0x0e, 0xdd, 0x8e, 0x26, 0x5d, 0xba, 0xf3, 0x44, 0x91, 0x81, 0xfd,
+	0xc4, 0x9c, 0x0b, 0xf2, 0x84, 0xeb, 0xc2, 0x55, 0x74, 0x3d, 0x27, 0x6e, 0xd4, 0xf3, 0x11, 0x9f,
+	0xd9, 0xeb, 0x1c, 0xe6, 0x45, 0x58, 0x1b, 0x93, 0x88, 0x6e, 0x22, 0xd6, 0x40, 0x95, 0xdd, 0x44,
+	0xac, 0xc5, 0x0a, 0x73, 0x98, 0xfd, 0xbe, 0x05, 0xa7, 0xb2, 0xe4, 0xd1, 0x1f, 0x59, 0xb0, 0x16,
+	0x67, 0xe9, 0x3d, 0x13, 0xad, 0xa9, 0x88, 0x74, 0x0c, 0x84, 0xc7, 0x25, 0xa0, 0x2b, 0x9a, 0x6d,
+	0x47, 0x4e, 0x95, 0x85, 0xad, 0x63, 0xcb, 0xc2, 0xe9, 0xaa, 0x65, 0x61, 0xa6, 0xaa, 0xa5, 0x59,
+	0x50, 0x2c, 0x3e, 0xb6, 0xa0, 0xf8, 0x29, 0xa8, 0x1c, 0x91, 0x91, 0x51, 0x79, 0xe4, 0xff, 0x09,
+	0xc0, 0x87, 0xb0, 0x84, 0x21, 0x1b, 0xca, 0x2e, 0x2f, 0xe9, 0x2e, 0x30, 0x2c, 0x66, 0x88, 0x44,
+	0x15, 0x57, 0x40, 0x1a, 0xf5, 0x0f, 0x3e, 0x3a, 0x73, 0xe2, 0x07, 0x1f, 0x9d, 0x39, 0xf1, 0xc3,
+	0x8f, 0xce, 0x9c, 0xf8, 0xda, 0xc3, 0x33, 0xd6, 0x07, 0x0f, 0xcf, 0x58, 0x3f, 0x78, 0x78, 0xc6,
+	0xfa, 0xe1, 0xc3, 0x33, 0xd6, 0xbf, 0x3e, 0x3c, 0x63, 0xfd, 0xc1, 0x8f, 0xce, 0x9c, 0x78, 0xab,
+	0x2a, 0x55, 0xfb, 0x7f, 0x01, 0x00, 0x00, 0xff, 0xff, 0x97, 0x47, 0x13, 0xa8, 0xe3, 0x4c, 0x00,
+	0x00,
 }
diff --git a/pkg/apis/application/v1alpha1/generated.proto b/pkg/apis/application/v1alpha1/generated.proto
index 7333b41630014..2db9f624ab4fe 100644
--- a/pkg/apis/application/v1alpha1/generated.proto
+++ b/pkg/apis/application/v1alpha1/generated.proto
@@ -48,7 +48,7 @@ message AppProjectList {
 
 // AppProjectSpec is the specification of an AppProject
 message AppProjectSpec {
-  // SourceRepos contains list of git repository URLs which can be used for deployment
+  // SourceRepos contains list of repository URLs which can be used for deployment
   repeated string sourceRepos = 1;
 
   // Destinations contains list of destinations available for deployment
@@ -113,7 +113,7 @@ message ApplicationList {
 
 // ApplicationSource contains information about github repository, path within repository and target application environment.
 message ApplicationSource {
-  // RepoURL is the git repository URL of the application manifests
+  // RepoURL is the repository URL of the application manifests
   optional string repoURL = 1;
 
   // Path is a directory path within the repository containing a
@@ -379,22 +379,6 @@ message HelmParameter {
   optional bool forceString = 3;
 }
 
-message HelmRepository {
-  optional string url = 1;
-
-  optional string name = 2;
-
-  optional bytes caData = 3;
-
-  optional bytes certData = 4;
-
-  optional bytes keyData = 5;
-
-  optional string username = 6;
-
-  optional string password = 7;
-}
-
 message Info {
   optional string name = 1;
 
@@ -491,7 +475,7 @@ message ProjectRole {
   repeated string groups = 5;
 }
 
-// Repository is a Git repository holding application configurations
+// Repository is a repository holding application configurations
 message Repository {
   // URL of the repo
   optional string repo = 1;
@@ -503,12 +487,14 @@ message Repository {
   optional string password = 3;
 
   // SSH private key data for authenticating at the repo server
+  // only for Git repos
   optional string sshPrivateKey = 4;
 
   // Current state of repository server connecting
   optional ConnectionState connectionState = 5;
 
   // InsecureIgnoreHostKey should not be used anymore, Insecure is favoured
+  // only for Git repos
   optional bool insecureIgnoreHostKey = 6;
 
   // Whether the repo is insecure
@@ -522,6 +508,15 @@ message Repository {
 
   // TLS client cert key for authenticating at the repo server
   optional string tlsClientCertKey = 10;
+
+  // only for Helm repos
+  optional string tlsClientCaData = 11;
+
+  // type of the repo, maybe "git or "helm, "git" is assumed if empty or absent
+  optional string type = 12;
+
+  // only for Helm repos
+  optional string name = 13;
 }
 
 // A RepositoryCertificate is either SSH known hosts entry or TLS certificate
@@ -755,7 +750,7 @@ message RevisionMetadata {
 
 // SyncOperation contains sync operation details.
 message SyncOperation {
-  // Revision is the git revision in which to sync the application to.
+  // Revision is the revision in which to sync the application to.
   // If omitted, will use the revision specified in app spec.
   optional string revision = 1;
 
@@ -793,7 +788,7 @@ message SyncOperationResult {
   // Resources holds the sync result of each individual resource
   repeated ResourceResult resources = 1;
 
-  // Revision holds the git commit SHA of the sync
+  // Revision holds the revision of the sync
   optional string revision = 2;
 
   // Source records the application source information of the sync, used for comparing auto-sync
diff --git a/pkg/apis/application/v1alpha1/openapi_generated.go b/pkg/apis/application/v1alpha1/openapi_generated.go
index f598a5be18afc..415b3a9f88986 100644
--- a/pkg/apis/application/v1alpha1/openapi_generated.go
+++ b/pkg/apis/application/v1alpha1/openapi_generated.go
@@ -44,7 +44,6 @@ func GetOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenA
 		"github.com/argoproj/argo-cd/pkg/apis/application/v1alpha1.EnvEntry":                         schema_pkg_apis_application_v1alpha1_EnvEntry(ref),
 		"github.com/argoproj/argo-cd/pkg/apis/application/v1alpha1.HealthStatus":                     schema_pkg_apis_application_v1alpha1_HealthStatus(ref),
 		"github.com/argoproj/argo-cd/pkg/apis/application/v1alpha1.HelmParameter":                    schema_pkg_apis_application_v1alpha1_HelmParameter(ref),
-		"github.com/argoproj/argo-cd/pkg/apis/application/v1alpha1.HelmRepository":                   schema_pkg_apis_application_v1alpha1_HelmRepository(ref),
 		"github.com/argoproj/argo-cd/pkg/apis/application/v1alpha1.Info":                             schema_pkg_apis_application_v1alpha1_Info(ref),
 		"github.com/argoproj/argo-cd/pkg/apis/application/v1alpha1.InfoItem":                         schema_pkg_apis_application_v1alpha1_InfoItem(ref),
 		"github.com/argoproj/argo-cd/pkg/apis/application/v1alpha1.JWTToken":                         schema_pkg_apis_application_v1alpha1_JWTToken(ref),
@@ -210,7 +209,7 @@ func schema_pkg_apis_application_v1alpha1_AppProjectSpec(ref common.ReferenceCal
 				Properties: map[string]spec.Schema{
 					"sourceRepos": {
 						SchemaProps: spec.SchemaProps{
-							Description: "SourceRepos contains list of git repository URLs which can be used for deployment",
+							Description: "SourceRepos contains list of repository URLs which can be used for deployment",
 							Type:        []string{"array"},
 							Items: &spec.SchemaOrArray{
 								Schema: &spec.Schema{
@@ -456,7 +455,7 @@ func schema_pkg_apis_application_v1alpha1_ApplicationSource(ref common.Reference
 				Properties: map[string]spec.Schema{
 					"repoURL": {
 						SchemaProps: spec.SchemaProps{
-							Description: "RepoURL is the git repository URL of the application manifests",
+							Description: "RepoURL is the repository URL of the application manifests",
 							Type:        []string{"string"},
 							Format:      "",
 						},
@@ -1386,61 +1385,6 @@ func schema_pkg_apis_application_v1alpha1_HelmParameter(ref common.ReferenceCall
 	}
 }
 
-func schema_pkg_apis_application_v1alpha1_HelmRepository(ref common.ReferenceCallback) common.OpenAPIDefinition {
-	return common.OpenAPIDefinition{
-		Schema: spec.Schema{
-			SchemaProps: spec.SchemaProps{
-				Type: []string{"object"},
-				Properties: map[string]spec.Schema{
-					"url": {
-						SchemaProps: spec.SchemaProps{
-							Type:   []string{"string"},
-							Format: "",
-						},
-					},
-					"name": {
-						SchemaProps: spec.SchemaProps{
-							Type:   []string{"string"},
-							Format: "",
-						},
-					},
-					"caData": {
-						SchemaProps: spec.SchemaProps{
-							Type:   []string{"string"},
-							Format: "byte",
-						},
-					},
-					"certData": {
-						SchemaProps: spec.SchemaProps{
-							Type:   []string{"string"},
-							Format: "byte",
-						},
-					},
-					"keyData": {
-						SchemaProps: spec.SchemaProps{
-							Type:   []string{"string"},
-							Format: "byte",
-						},
-					},
-					"username": {
-						SchemaProps: spec.SchemaProps{
-							Type:   []string{"string"},
-							Format: "",
-						},
-					},
-					"password": {
-						SchemaProps: spec.SchemaProps{
-							Type:   []string{"string"},
-							Format: "",
-						},
-					},
-				},
-				Required: []string{"url", "name"},
-			},
-		},
-	}
-}
-
 func schema_pkg_apis_application_v1alpha1_Info(ref common.ReferenceCallback) common.OpenAPIDefinition {
 	return common.OpenAPIDefinition{
 		Schema: spec.Schema{
@@ -1773,7 +1717,7 @@ func schema_pkg_apis_application_v1alpha1_Repository(ref common.ReferenceCallbac
 	return common.OpenAPIDefinition{
 		Schema: spec.Schema{
 			SchemaProps: spec.SchemaProps{
-				Description: "Repository is a Git repository holding application configurations",
+				Description: "Repository is a repository holding application configurations",
 				Type:        []string{"object"},
 				Properties: map[string]spec.Schema{
 					"repo": {
@@ -1799,7 +1743,7 @@ func schema_pkg_apis_application_v1alpha1_Repository(ref common.ReferenceCallbac
 					},
 					"sshPrivateKey": {
 						SchemaProps: spec.SchemaProps{
-							Description: "SSH private key data for authenticating at the repo server",
+							Description: "SSH private key data for authenticating at the repo server only for Git repos",
 							Type:        []string{"string"},
 							Format:      "",
 						},
@@ -1812,7 +1756,7 @@ func schema_pkg_apis_application_v1alpha1_Repository(ref common.ReferenceCallbac
 					},
 					"insecureIgnoreHostKey": {
 						SchemaProps: spec.SchemaProps{
-							Description: "InsecureIgnoreHostKey should not be used anymore, Insecure is favoured",
+							Description: "InsecureIgnoreHostKey should not be used anymore, Insecure is favoured only for Git repos",
 							Type:        []string{"boolean"},
 							Format:      "",
 						},
@@ -1845,6 +1789,27 @@ func schema_pkg_apis_application_v1alpha1_Repository(ref common.ReferenceCallbac
 							Format:      "",
 						},
 					},
+					"tlsClientCaData": {
+						SchemaProps: spec.SchemaProps{
+							Description: "only for Helm repos",
+							Type:        []string{"string"},
+							Format:      "",
+						},
+					},
+					"type": {
+						SchemaProps: spec.SchemaProps{
+							Description: "type of the repo, maybe \"git or \"helm, \"git\" is assumed if empty or absent",
+							Type:        []string{"string"},
+							Format:      "",
+						},
+					},
+					"name": {
+						SchemaProps: spec.SchemaProps{
+							Description: "only for Helm repos",
+							Type:        []string{"string"},
+							Format:      "",
+						},
+					},
 				},
 				Required: []string{"repo"},
 			},
@@ -2700,7 +2665,7 @@ func schema_pkg_apis_application_v1alpha1_RevisionMetadata(ref common.ReferenceC
 						},
 					},
 				},
-				Required: []string{"author", "date", "tags", "message"},
+				Required: []string{"date"},
 			},
 		},
 		Dependencies: []string{
@@ -2717,7 +2682,7 @@ func schema_pkg_apis_application_v1alpha1_SyncOperation(ref common.ReferenceCall
 				Properties: map[string]spec.Schema{
 					"revision": {
 						SchemaProps: spec.SchemaProps{
-							Description: "Revision is the git revision in which to sync the application to. If omitted, will use the revision specified in app spec.",
+							Description: "Revision is the revision in which to sync the application to. If omitted, will use the revision specified in app spec.",
 							Type:        []string{"string"},
 							Format:      "",
 						},
@@ -2837,7 +2802,7 @@ func schema_pkg_apis_application_v1alpha1_SyncOperationResult(ref common.Referen
 					},
 					"revision": {
 						SchemaProps: spec.SchemaProps{
-							Description: "Revision holds the git commit SHA of the sync",
+							Description: "Revision holds the revision of the sync",
 							Type:        []string{"string"},
 							Format:      "",
 						},
diff --git a/pkg/apis/application/v1alpha1/types.go b/pkg/apis/application/v1alpha1/types.go
index cadceefceeb18..faa495270bac3 100644
--- a/pkg/apis/application/v1alpha1/types.go
+++ b/pkg/apis/application/v1alpha1/types.go
@@ -93,7 +93,7 @@ func (e Env) Environ() []string {
 
 // ApplicationSource contains information about github repository, path within repository and target application environment.
 type ApplicationSource struct {
-	// RepoURL is the git repository URL of the application manifests
+	// RepoURL is the repository URL of the application manifests
 	RepoURL string `json:"repoURL" protobuf:"bytes,1,opt,name=repoURL"`
 	// Path is a directory path within the repository containing a
 	Path string `json:"path" protobuf:"bytes,2,opt,name=path"`
@@ -352,7 +352,7 @@ func (r SyncOperationResource) HasIdentity(name string, gvk schema.GroupVersionK
 
 // SyncOperation contains sync operation details.
 type SyncOperation struct {
-	// Revision is the git revision in which to sync the application to.
+	// Revision is the revision in which to sync the application to.
 	// If omitted, will use the revision specified in app spec.
 	Revision string `json:"revision,omitempty" protobuf:"bytes,1,opt,name=revision"`
 	// Prune deletes resources that are no longer tracked in git
@@ -515,23 +515,23 @@ type RevisionMetadata struct {
 	// who authored this revision,
 	// typically their name and email, e.g. "John Doe <john_doe@my-company.com>",
 	// but might not match this example
-	Author string `json:"author" protobuf:"bytes,1,opt,name=author"`
+	Author string `json:"author,omitempty" protobuf:"bytes,1,opt,name=author"`
 	// when the revision was authored
 	Date metav1.Time `json:"date" protobuf:"bytes,2,opt,name=date"`
 	// tags on the revision,
 	// note - tags can move from one revision to another
-	Tags []string `json:"tags" protobuf:"bytes,3,opt,name=tags"`
+	Tags []string `json:"tags,omitempty" protobuf:"bytes,3,opt,name=tags"`
 	// the message associated with the revision,
 	// probably the commit message,
 	// this is truncated to the first newline or 64 characters (which ever comes first)
-	Message string `json:"message" protobuf:"bytes,4,opt,name=message"`
+	Message string `json:"message,omitempty" protobuf:"bytes,4,opt,name=message"`
 }
 
 // SyncOperationResult represent result of sync operation
 type SyncOperationResult struct {
 	// Resources holds the sync result of each individual resource
 	Resources ResourceResults `json:"resources,omitempty" protobuf:"bytes,1,opt,name=resources"`
-	// Revision holds the git commit SHA of the sync
+	// Revision holds the revision of the sync
 	Revision string `json:"revision" protobuf:"bytes,2,opt,name=revision"`
 	// Source records the application source information of the sync, used for comparing auto-sync
 	Source ApplicationSource `json:"source,omitempty" protobuf:"bytes,3,opt,name=source"`
@@ -925,16 +925,6 @@ type TLSClientConfig struct {
 	CAData []byte `json:"caData,omitempty" protobuf:"bytes,5,opt,name=caData"`
 }
 
-type HelmRepository struct {
-	URL      string `json:"url" protobuf:"bytes,1,opt,name=url"`
-	Name     string `json:"name" protobuf:"bytes,2,opt,name=name"`
-	CAData   []byte `json:"caData,omitempty" protobuf:"bytes,3,opt,name=caData"`
-	CertData []byte `json:"certData,omitempty" protobuf:"bytes,4,opt,name=certData"`
-	KeyData  []byte `json:"keyData,omitempty" protobuf:"bytes,5,opt,name=keyData"`
-	Username string `json:"username,omitempty" protobuf:"bytes,6,opt,name=username"`
-	Password string `json:"password,omitempty" protobuf:"bytes,7,opt,name=password"`
-}
-
 // ResourceOverride holds configuration to customize resource diffing and health assessment
 type ResourceOverride struct {
 	HealthLua         string `json:"health.lua,omitempty" protobuf:"bytes,1,opt,name=healthLua"`
@@ -973,7 +963,7 @@ type ResourceActionParam struct {
 	Default string `json:"default,omitempty" protobuf:"bytes,4,opt,name=default"`
 }
 
-// Repository is a Git repository holding application configurations
+// Repository is a repository holding application configurations
 type Repository struct {
 	// URL of the repo
 	Repo string `json:"repo" protobuf:"bytes,1,opt,name=repo"`
@@ -982,10 +972,12 @@ type Repository struct {
 	// Password for authenticating at the repo server
 	Password string `json:"password,omitempty" protobuf:"bytes,3,opt,name=password"`
 	// SSH private key data for authenticating at the repo server
+	// only for Git repos
 	SSHPrivateKey string `json:"sshPrivateKey,omitempty" protobuf:"bytes,4,opt,name=sshPrivateKey"`
 	// Current state of repository server connecting
 	ConnectionState ConnectionState `json:"connectionState,omitempty" protobuf:"bytes,5,opt,name=connectionState"`
 	// InsecureIgnoreHostKey should not be used anymore, Insecure is favoured
+	// only for Git repos
 	InsecureIgnoreHostKey bool `json:"insecureIgnoreHostKey,omitempty" protobuf:"bytes,6,opt,name=insecureIgnoreHostKey"`
 	// Whether the repo is insecure
 	Insecure bool `json:"insecure,omitempty" protobuf:"bytes,7,opt,name=insecure"`
@@ -995,6 +987,12 @@ type Repository struct {
 	TLSClientCertData string `json:"tlsClientCertData,omitempty" protobuf:"bytes,9,opt,name=tlsClientCertData"`
 	// TLS client cert key for authenticating at the repo server
 	TLSClientCertKey string `json:"tlsClientCertKey,omitempty" protobuf:"bytes,10,opt,name=tlsClientCertKey"`
+	// only for Helm repos
+	TLSClientCAData string `json:"tlsClientCaData,omitempty" protobuf:"bytes,11,opt,name=tlsClientCaData"`
+	// type of the repo, maybe "git or "helm, "git" is assumed if empty or absent
+	Type string `json:"type,omitempty" protobuf:"bytes,12,opt,name=type"`
+	// only for Helm repos
+	Name string `json:"name,omitempty" protobuf:"bytes,13,opt,name=name"`
 }
 
 func (repo *Repository) IsInsecure() bool {
@@ -1022,10 +1020,22 @@ func (m *Repository) CopyCredentialsFrom(source *Repository) {
 	}
 }
 
+type Repositories []*Repository
+
+func (r Repositories) Filter(predicate func(r *Repository) bool) Repositories {
+	var res Repositories
+	for _, repo := range r {
+		if predicate(repo) {
+			res = append(res, repo)
+		}
+	}
+	return res
+}
+
 // RepositoryList is a collection of Repositories.
 type RepositoryList struct {
 	metav1.ListMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"`
-	Items           []Repository `json:"items" protobuf:"bytes,2,rep,name=items"`
+	Items           Repositories `json:"items" protobuf:"bytes,2,rep,name=items"`
 }
 
 // A RepositoryCertificate is either SSH known hosts entry or TLS certificate
@@ -1298,7 +1308,7 @@ func (s *OrphanedResourcesMonitorSettings) IsWarn() bool {
 
 // AppProjectSpec is the specification of an AppProject
 type AppProjectSpec struct {
-	// SourceRepos contains list of git repository URLs which can be used for deployment
+	// SourceRepos contains list of repository URLs which can be used for deployment
 	SourceRepos []string `json:"sourceRepos,omitempty" protobuf:"bytes,1,name=sourceRepos"`
 	// Destinations contains list of destinations available for deployment
 	Destinations []ApplicationDestination `json:"destinations,omitempty" protobuf:"bytes,2,name=destination"`
diff --git a/pkg/apis/application/v1alpha1/zz_generated.deepcopy.go b/pkg/apis/application/v1alpha1/zz_generated.deepcopy.go
index f2a8188716083..4b09302539700 100644
--- a/pkg/apis/application/v1alpha1/zz_generated.deepcopy.go
+++ b/pkg/apis/application/v1alpha1/zz_generated.deepcopy.go
@@ -817,37 +817,6 @@ func (in *HelmParameter) DeepCopy() *HelmParameter {
 	return out
 }
 
-// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
-func (in *HelmRepository) DeepCopyInto(out *HelmRepository) {
-	*out = *in
-	if in.CAData != nil {
-		in, out := &in.CAData, &out.CAData
-		*out = make([]byte, len(*in))
-		copy(*out, *in)
-	}
-	if in.CertData != nil {
-		in, out := &in.CertData, &out.CertData
-		*out = make([]byte, len(*in))
-		copy(*out, *in)
-	}
-	if in.KeyData != nil {
-		in, out := &in.KeyData, &out.KeyData
-		*out = make([]byte, len(*in))
-		copy(*out, *in)
-	}
-	return
-}
-
-// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HelmRepository.
-func (in *HelmRepository) DeepCopy() *HelmRepository {
-	if in == nil {
-		return nil
-	}
-	out := new(HelmRepository)
-	in.DeepCopyInto(out)
-	return out
-}
-
 // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
 func (in *Info) DeepCopyInto(out *Info) {
 	*out = *in
@@ -1064,6 +1033,32 @@ func (in *ProjectRole) DeepCopy() *ProjectRole {
 	return out
 }
 
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in Repositories) DeepCopyInto(out *Repositories) {
+	{
+		in := &in
+		*out = make(Repositories, len(*in))
+		for i := range *in {
+			if (*in)[i] != nil {
+				in, out := &(*in)[i], &(*out)[i]
+				*out = new(Repository)
+				(*in).DeepCopyInto(*out)
+			}
+		}
+		return
+	}
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Repositories.
+func (in Repositories) DeepCopy() Repositories {
+	if in == nil {
+		return nil
+	}
+	out := new(Repositories)
+	in.DeepCopyInto(out)
+	return *out
+}
+
 // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
 func (in *Repository) DeepCopyInto(out *Repository) {
 	*out = *in
@@ -1132,9 +1127,13 @@ func (in *RepositoryList) DeepCopyInto(out *RepositoryList) {
 	out.ListMeta = in.ListMeta
 	if in.Items != nil {
 		in, out := &in.Items, &out.Items
-		*out = make([]Repository, len(*in))
+		*out = make(Repositories, len(*in))
 		for i := range *in {
-			(*in)[i].DeepCopyInto(&(*out)[i])
+			if (*in)[i] != nil {
+				in, out := &(*in)[i], &(*out)[i]
+				*out = new(Repository)
+				(*in).DeepCopyInto(*out)
+			}
 		}
 	}
 	return
diff --git a/reposerver/apiclient/mocks/RepoServerServiceClient.go b/reposerver/apiclient/mocks/RepoServerServiceClient.go
index 32aa0043cb1c8..8ee6d7ea706fb 100644
--- a/reposerver/apiclient/mocks/RepoServerServiceClient.go
+++ b/reposerver/apiclient/mocks/RepoServerServiceClient.go
@@ -79,36 +79,6 @@ func (_m *RepoServerServiceClient) GetAppDetails(ctx context.Context, in *apicli
 	return r0, r1
 }
 
-// GetFile provides a mock function with given fields: ctx, in, opts
-func (_m *RepoServerServiceClient) GetFile(ctx context.Context, in *apiclient.GetFileRequest, opts ...grpc.CallOption) (*apiclient.GetFileResponse, error) {
-	_va := make([]interface{}, len(opts))
-	for _i := range opts {
-		_va[_i] = opts[_i]
-	}
-	var _ca []interface{}
-	_ca = append(_ca, ctx, in)
-	_ca = append(_ca, _va...)
-	ret := _m.Called(_ca...)
-
-	var r0 *apiclient.GetFileResponse
-	if rf, ok := ret.Get(0).(func(context.Context, *apiclient.GetFileRequest, ...grpc.CallOption) *apiclient.GetFileResponse); ok {
-		r0 = rf(ctx, in, opts...)
-	} else {
-		if ret.Get(0) != nil {
-			r0 = ret.Get(0).(*apiclient.GetFileResponse)
-		}
-	}
-
-	var r1 error
-	if rf, ok := ret.Get(1).(func(context.Context, *apiclient.GetFileRequest, ...grpc.CallOption) error); ok {
-		r1 = rf(ctx, in, opts...)
-	} else {
-		r1 = ret.Error(1)
-	}
-
-	return r0, r1
-}
-
 // GetRevisionMetadata provides a mock function with given fields: ctx, in, opts
 func (_m *RepoServerServiceClient) GetRevisionMetadata(ctx context.Context, in *apiclient.RepoServerRevisionMetadataRequest, opts ...grpc.CallOption) (*v1alpha1.RevisionMetadata, error) {
 	_va := make([]interface{}, len(opts))
@@ -139,8 +109,8 @@ func (_m *RepoServerServiceClient) GetRevisionMetadata(ctx context.Context, in *
 	return r0, r1
 }
 
-// ListDir provides a mock function with given fields: ctx, in, opts
-func (_m *RepoServerServiceClient) ListDir(ctx context.Context, in *apiclient.ListDirRequest, opts ...grpc.CallOption) (*apiclient.FileList, error) {
+// ListApps provides a mock function with given fields: ctx, in, opts
+func (_m *RepoServerServiceClient) ListApps(ctx context.Context, in *apiclient.ListAppsRequest, opts ...grpc.CallOption) (*apiclient.AppList, error) {
 	_va := make([]interface{}, len(opts))
 	for _i := range opts {
 		_va[_i] = opts[_i]
@@ -150,17 +120,17 @@ func (_m *RepoServerServiceClient) ListDir(ctx context.Context, in *apiclient.Li
 	_ca = append(_ca, _va...)
 	ret := _m.Called(_ca...)
 
-	var r0 *apiclient.FileList
-	if rf, ok := ret.Get(0).(func(context.Context, *apiclient.ListDirRequest, ...grpc.CallOption) *apiclient.FileList); ok {
+	var r0 *apiclient.AppList
+	if rf, ok := ret.Get(0).(func(context.Context, *apiclient.ListAppsRequest, ...grpc.CallOption) *apiclient.AppList); ok {
 		r0 = rf(ctx, in, opts...)
 	} else {
 		if ret.Get(0) != nil {
-			r0 = ret.Get(0).(*apiclient.FileList)
+			r0 = ret.Get(0).(*apiclient.AppList)
 		}
 	}
 
 	var r1 error
-	if rf, ok := ret.Get(1).(func(context.Context, *apiclient.ListDirRequest, ...grpc.CallOption) error); ok {
+	if rf, ok := ret.Get(1).(func(context.Context, *apiclient.ListAppsRequest, ...grpc.CallOption) error); ok {
 		r1 = rf(ctx, in, opts...)
 	} else {
 		r1 = ret.Error(1)
diff --git a/reposerver/apiclient/repository.pb.go b/reposerver/apiclient/repository.pb.go
index 4c99691bd9fba..f1ec34cfebb5d 100644
--- a/reposerver/apiclient/repository.pb.go
+++ b/reposerver/apiclient/repository.pb.go
@@ -45,7 +45,7 @@ type ManifestRequest struct {
 	AppLabelValue        string                             `protobuf:"bytes,5,opt,name=appLabelValue,proto3" json:"appLabelValue,omitempty"`
 	Namespace            string                             `protobuf:"bytes,8,opt,name=namespace,proto3" json:"namespace,omitempty"`
 	ApplicationSource    *v1alpha1.ApplicationSource        `protobuf:"bytes,10,opt,name=applicationSource" json:"applicationSource,omitempty"`
-	HelmRepos            []*v1alpha1.HelmRepository         `protobuf:"bytes,11,rep,name=helmRepos" json:"helmRepos,omitempty"`
+	Repos                []*v1alpha1.Repository             `protobuf:"bytes,11,rep,name=repos" json:"repos,omitempty"`
 	Plugins              []*v1alpha1.ConfigManagementPlugin `protobuf:"bytes,12,rep,name=plugins" json:"plugins,omitempty"`
 	KustomizeOptions     *v1alpha1.KustomizeOptions         `protobuf:"bytes,13,opt,name=kustomizeOptions" json:"kustomizeOptions,omitempty"`
 	XXX_NoUnkeyedLiteral struct{}                           `json:"-"`
@@ -57,7 +57,7 @@ func (m *ManifestRequest) Reset()         { *m = ManifestRequest{} }
 func (m *ManifestRequest) String() string { return proto.CompactTextString(m) }
 func (*ManifestRequest) ProtoMessage()    {}
 func (*ManifestRequest) Descriptor() ([]byte, []int) {
-	return fileDescriptor_repository_a040dcfbd17da920, []int{0}
+	return fileDescriptor_repository_3f0884c8b644d045, []int{0}
 }
 func (m *ManifestRequest) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
@@ -135,9 +135,9 @@ func (m *ManifestRequest) GetApplicationSource() *v1alpha1.ApplicationSource {
 	return nil
 }
 
-func (m *ManifestRequest) GetHelmRepos() []*v1alpha1.HelmRepository {
+func (m *ManifestRequest) GetRepos() []*v1alpha1.Repository {
 	if m != nil {
-		return m.HelmRepos
+		return m.Repos
 	}
 	return nil
 }
@@ -171,7 +171,7 @@ func (m *ManifestResponse) Reset()         { *m = ManifestResponse{} }
 func (m *ManifestResponse) String() string { return proto.CompactTextString(m) }
 func (*ManifestResponse) ProtoMessage()    {}
 func (*ManifestResponse) Descriptor() ([]byte, []int) {
-	return fileDescriptor_repository_a040dcfbd17da920, []int{1}
+	return fileDescriptor_repository_3f0884c8b644d045, []int{1}
 }
 func (m *ManifestResponse) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
@@ -235,28 +235,27 @@ func (m *ManifestResponse) GetSourceType() string {
 	return ""
 }
 
-// ListDirRequest requests a repository directory structure
-type ListDirRequest struct {
+// ListAppsRequest requests a repository directory structure
+type ListAppsRequest struct {
 	Repo                 *v1alpha1.Repository `protobuf:"bytes,1,opt,name=repo" json:"repo,omitempty"`
 	Revision             string               `protobuf:"bytes,2,opt,name=revision,proto3" json:"revision,omitempty"`
-	Path                 string               `protobuf:"bytes,3,opt,name=path,proto3" json:"path,omitempty"`
 	XXX_NoUnkeyedLiteral struct{}             `json:"-"`
 	XXX_unrecognized     []byte               `json:"-"`
 	XXX_sizecache        int32                `json:"-"`
 }
 
-func (m *ListDirRequest) Reset()         { *m = ListDirRequest{} }
-func (m *ListDirRequest) String() string { return proto.CompactTextString(m) }
-func (*ListDirRequest) ProtoMessage()    {}
-func (*ListDirRequest) Descriptor() ([]byte, []int) {
-	return fileDescriptor_repository_a040dcfbd17da920, []int{2}
+func (m *ListAppsRequest) Reset()         { *m = ListAppsRequest{} }
+func (m *ListAppsRequest) String() string { return proto.CompactTextString(m) }
+func (*ListAppsRequest) ProtoMessage()    {}
+func (*ListAppsRequest) Descriptor() ([]byte, []int) {
+	return fileDescriptor_repository_3f0884c8b644d045, []int{2}
 }
-func (m *ListDirRequest) XXX_Unmarshal(b []byte) error {
+func (m *ListAppsRequest) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
 }
-func (m *ListDirRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+func (m *ListAppsRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
 	if deterministic {
-		return xxx_messageInfo_ListDirRequest.Marshal(b, m, deterministic)
+		return xxx_messageInfo_ListAppsRequest.Marshal(b, m, deterministic)
 	} else {
 		b = b[:cap(b)]
 		n, err := m.MarshalTo(b)
@@ -266,171 +265,52 @@ func (m *ListDirRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, erro
 		return b[:n], nil
 	}
 }
-func (dst *ListDirRequest) XXX_Merge(src proto.Message) {
-	xxx_messageInfo_ListDirRequest.Merge(dst, src)
+func (dst *ListAppsRequest) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_ListAppsRequest.Merge(dst, src)
 }
-func (m *ListDirRequest) XXX_Size() int {
+func (m *ListAppsRequest) XXX_Size() int {
 	return m.Size()
 }
-func (m *ListDirRequest) XXX_DiscardUnknown() {
-	xxx_messageInfo_ListDirRequest.DiscardUnknown(m)
+func (m *ListAppsRequest) XXX_DiscardUnknown() {
+	xxx_messageInfo_ListAppsRequest.DiscardUnknown(m)
 }
 
-var xxx_messageInfo_ListDirRequest proto.InternalMessageInfo
+var xxx_messageInfo_ListAppsRequest proto.InternalMessageInfo
 
-func (m *ListDirRequest) GetRepo() *v1alpha1.Repository {
+func (m *ListAppsRequest) GetRepo() *v1alpha1.Repository {
 	if m != nil {
 		return m.Repo
 	}
 	return nil
 }
 
-func (m *ListDirRequest) GetRevision() string {
+func (m *ListAppsRequest) GetRevision() string {
 	if m != nil {
 		return m.Revision
 	}
 	return ""
 }
 
-func (m *ListDirRequest) GetPath() string {
-	if m != nil {
-		return m.Path
-	}
-	return ""
-}
-
-// FileList returns the contents of the repo of a ListDir request
-type FileList struct {
-	Items                []string `protobuf:"bytes,1,rep,name=items" json:"items,omitempty"`
-	XXX_NoUnkeyedLiteral struct{} `json:"-"`
-	XXX_unrecognized     []byte   `json:"-"`
-	XXX_sizecache        int32    `json:"-"`
-}
-
-func (m *FileList) Reset()         { *m = FileList{} }
-func (m *FileList) String() string { return proto.CompactTextString(m) }
-func (*FileList) ProtoMessage()    {}
-func (*FileList) Descriptor() ([]byte, []int) {
-	return fileDescriptor_repository_a040dcfbd17da920, []int{3}
-}
-func (m *FileList) XXX_Unmarshal(b []byte) error {
-	return m.Unmarshal(b)
-}
-func (m *FileList) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
-	if deterministic {
-		return xxx_messageInfo_FileList.Marshal(b, m, deterministic)
-	} else {
-		b = b[:cap(b)]
-		n, err := m.MarshalTo(b)
-		if err != nil {
-			return nil, err
-		}
-		return b[:n], nil
-	}
-}
-func (dst *FileList) XXX_Merge(src proto.Message) {
-	xxx_messageInfo_FileList.Merge(dst, src)
-}
-func (m *FileList) XXX_Size() int {
-	return m.Size()
-}
-func (m *FileList) XXX_DiscardUnknown() {
-	xxx_messageInfo_FileList.DiscardUnknown(m)
-}
-
-var xxx_messageInfo_FileList proto.InternalMessageInfo
-
-func (m *FileList) GetItems() []string {
-	if m != nil {
-		return m.Items
-	}
-	return nil
-}
-
-// GetFileRequest return
-type GetFileRequest struct {
-	Repo                 *v1alpha1.Repository `protobuf:"bytes,1,opt,name=repo" json:"repo,omitempty"`
-	Revision             string               `protobuf:"bytes,2,opt,name=revision,proto3" json:"revision,omitempty"`
-	Path                 string               `protobuf:"bytes,3,opt,name=path,proto3" json:"path,omitempty"`
-	XXX_NoUnkeyedLiteral struct{}             `json:"-"`
-	XXX_unrecognized     []byte               `json:"-"`
-	XXX_sizecache        int32                `json:"-"`
-}
-
-func (m *GetFileRequest) Reset()         { *m = GetFileRequest{} }
-func (m *GetFileRequest) String() string { return proto.CompactTextString(m) }
-func (*GetFileRequest) ProtoMessage()    {}
-func (*GetFileRequest) Descriptor() ([]byte, []int) {
-	return fileDescriptor_repository_a040dcfbd17da920, []int{4}
-}
-func (m *GetFileRequest) XXX_Unmarshal(b []byte) error {
-	return m.Unmarshal(b)
-}
-func (m *GetFileRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
-	if deterministic {
-		return xxx_messageInfo_GetFileRequest.Marshal(b, m, deterministic)
-	} else {
-		b = b[:cap(b)]
-		n, err := m.MarshalTo(b)
-		if err != nil {
-			return nil, err
-		}
-		return b[:n], nil
-	}
-}
-func (dst *GetFileRequest) XXX_Merge(src proto.Message) {
-	xxx_messageInfo_GetFileRequest.Merge(dst, src)
-}
-func (m *GetFileRequest) XXX_Size() int {
-	return m.Size()
-}
-func (m *GetFileRequest) XXX_DiscardUnknown() {
-	xxx_messageInfo_GetFileRequest.DiscardUnknown(m)
-}
-
-var xxx_messageInfo_GetFileRequest proto.InternalMessageInfo
-
-func (m *GetFileRequest) GetRepo() *v1alpha1.Repository {
-	if m != nil {
-		return m.Repo
-	}
-	return nil
-}
-
-func (m *GetFileRequest) GetRevision() string {
-	if m != nil {
-		return m.Revision
-	}
-	return ""
-}
-
-func (m *GetFileRequest) GetPath() string {
-	if m != nil {
-		return m.Path
-	}
-	return ""
-}
-
-// GetFileResponse returns the contents of the file of a GetFile request
-type GetFileResponse struct {
-	Data                 []byte   `protobuf:"bytes,1,opt,name=data,proto3" json:"data,omitempty"`
-	XXX_NoUnkeyedLiteral struct{} `json:"-"`
-	XXX_unrecognized     []byte   `json:"-"`
-	XXX_sizecache        int32    `json:"-"`
+// AppList returns the contents of the repo of a ListApps request
+type AppList struct {
+	Apps                 map[string]string `protobuf:"bytes,1,rep,name=apps" json:"apps,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
+	XXX_NoUnkeyedLiteral struct{}          `json:"-"`
+	XXX_unrecognized     []byte            `json:"-"`
+	XXX_sizecache        int32             `json:"-"`
 }
 
-func (m *GetFileResponse) Reset()         { *m = GetFileResponse{} }
-func (m *GetFileResponse) String() string { return proto.CompactTextString(m) }
-func (*GetFileResponse) ProtoMessage()    {}
-func (*GetFileResponse) Descriptor() ([]byte, []int) {
-	return fileDescriptor_repository_a040dcfbd17da920, []int{5}
+func (m *AppList) Reset()         { *m = AppList{} }
+func (m *AppList) String() string { return proto.CompactTextString(m) }
+func (*AppList) ProtoMessage()    {}
+func (*AppList) Descriptor() ([]byte, []int) {
+	return fileDescriptor_repository_3f0884c8b644d045, []int{3}
 }
-func (m *GetFileResponse) XXX_Unmarshal(b []byte) error {
+func (m *AppList) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
 }
-func (m *GetFileResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+func (m *AppList) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
 	if deterministic {
-		return xxx_messageInfo_GetFileResponse.Marshal(b, m, deterministic)
+		return xxx_messageInfo_AppList.Marshal(b, m, deterministic)
 	} else {
 		b = b[:cap(b)]
 		n, err := m.MarshalTo(b)
@@ -440,21 +320,21 @@ func (m *GetFileResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, err
 		return b[:n], nil
 	}
 }
-func (dst *GetFileResponse) XXX_Merge(src proto.Message) {
-	xxx_messageInfo_GetFileResponse.Merge(dst, src)
+func (dst *AppList) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_AppList.Merge(dst, src)
 }
-func (m *GetFileResponse) XXX_Size() int {
+func (m *AppList) XXX_Size() int {
 	return m.Size()
 }
-func (m *GetFileResponse) XXX_DiscardUnknown() {
-	xxx_messageInfo_GetFileResponse.DiscardUnknown(m)
+func (m *AppList) XXX_DiscardUnknown() {
+	xxx_messageInfo_AppList.DiscardUnknown(m)
 }
 
-var xxx_messageInfo_GetFileResponse proto.InternalMessageInfo
+var xxx_messageInfo_AppList proto.InternalMessageInfo
 
-func (m *GetFileResponse) GetData() []byte {
+func (m *AppList) GetApps() map[string]string {
 	if m != nil {
-		return m.Data
+		return m.Apps
 	}
 	return nil
 }
@@ -463,8 +343,8 @@ func (m *GetFileResponse) GetData() []byte {
 type RepoServerAppDetailsQuery struct {
 	Repo                 *v1alpha1.Repository               `protobuf:"bytes,1,opt,name=repo" json:"repo,omitempty"`
 	Revision             string                             `protobuf:"bytes,2,opt,name=revision,proto3" json:"revision,omitempty"`
-	Path                 string                             `protobuf:"bytes,3,opt,name=path,proto3" json:"path,omitempty"`
-	HelmRepos            []*v1alpha1.HelmRepository         `protobuf:"bytes,4,rep,name=helmRepos" json:"helmRepos,omitempty"`
+	App                  string                             `protobuf:"bytes,3,opt,name=app,proto3" json:"app,omitempty"`
+	Repos                []*v1alpha1.Repository             `protobuf:"bytes,4,rep,name=repos" json:"repos,omitempty"`
 	Plugins              []*v1alpha1.ConfigManagementPlugin `protobuf:"bytes,5,rep,name=plugins" json:"plugins,omitempty"`
 	Helm                 *HelmAppDetailsQuery               `protobuf:"bytes,6,opt,name=helm" json:"helm,omitempty"`
 	Ksonnet              *KsonnetAppDetailsQuery            `protobuf:"bytes,7,opt,name=ksonnet" json:"ksonnet,omitempty"`
@@ -478,7 +358,7 @@ func (m *RepoServerAppDetailsQuery) Reset()         { *m = RepoServerAppDetailsQ
 func (m *RepoServerAppDetailsQuery) String() string { return proto.CompactTextString(m) }
 func (*RepoServerAppDetailsQuery) ProtoMessage()    {}
 func (*RepoServerAppDetailsQuery) Descriptor() ([]byte, []int) {
-	return fileDescriptor_repository_a040dcfbd17da920, []int{6}
+	return fileDescriptor_repository_3f0884c8b644d045, []int{4}
 }
 func (m *RepoServerAppDetailsQuery) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
@@ -521,16 +401,16 @@ func (m *RepoServerAppDetailsQuery) GetRevision() string {
 	return ""
 }
 
-func (m *RepoServerAppDetailsQuery) GetPath() string {
+func (m *RepoServerAppDetailsQuery) GetApp() string {
 	if m != nil {
-		return m.Path
+		return m.App
 	}
 	return ""
 }
 
-func (m *RepoServerAppDetailsQuery) GetHelmRepos() []*v1alpha1.HelmRepository {
+func (m *RepoServerAppDetailsQuery) GetRepos() []*v1alpha1.Repository {
 	if m != nil {
-		return m.HelmRepos
+		return m.Repos
 	}
 	return nil
 }
@@ -574,7 +454,7 @@ func (m *HelmAppDetailsQuery) Reset()         { *m = HelmAppDetailsQuery{} }
 func (m *HelmAppDetailsQuery) String() string { return proto.CompactTextString(m) }
 func (*HelmAppDetailsQuery) ProtoMessage()    {}
 func (*HelmAppDetailsQuery) Descriptor() ([]byte, []int) {
-	return fileDescriptor_repository_a040dcfbd17da920, []int{7}
+	return fileDescriptor_repository_3f0884c8b644d045, []int{5}
 }
 func (m *HelmAppDetailsQuery) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
@@ -621,7 +501,7 @@ func (m *KsonnetAppDetailsQuery) Reset()         { *m = KsonnetAppDetailsQuery{}
 func (m *KsonnetAppDetailsQuery) String() string { return proto.CompactTextString(m) }
 func (*KsonnetAppDetailsQuery) ProtoMessage()    {}
 func (*KsonnetAppDetailsQuery) Descriptor() ([]byte, []int) {
-	return fileDescriptor_repository_a040dcfbd17da920, []int{8}
+	return fileDescriptor_repository_3f0884c8b644d045, []int{6}
 }
 func (m *KsonnetAppDetailsQuery) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
@@ -673,7 +553,7 @@ func (m *RepoAppDetailsResponse) Reset()         { *m = RepoAppDetailsResponse{}
 func (m *RepoAppDetailsResponse) String() string { return proto.CompactTextString(m) }
 func (*RepoAppDetailsResponse) ProtoMessage()    {}
 func (*RepoAppDetailsResponse) Descriptor() ([]byte, []int) {
-	return fileDescriptor_repository_a040dcfbd17da920, []int{9}
+	return fileDescriptor_repository_3f0884c8b644d045, []int{7}
 }
 func (m *RepoAppDetailsResponse) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
@@ -740,8 +620,10 @@ func (m *RepoAppDetailsResponse) GetDirectory() *DirectoryAppSpec {
 type RepoServerRevisionMetadataRequest struct {
 	// the repo
 	Repo *v1alpha1.Repository `protobuf:"bytes,1,opt,name=repo" json:"repo,omitempty"`
+	// the app name
+	App string `protobuf:"bytes,2,opt,name=app,proto3" json:"app,omitempty"`
 	// the revision within the repo
-	Revision             string   `protobuf:"bytes,2,opt,name=revision,proto3" json:"revision,omitempty"`
+	Revision             string   `protobuf:"bytes,3,opt,name=revision,proto3" json:"revision,omitempty"`
 	XXX_NoUnkeyedLiteral struct{} `json:"-"`
 	XXX_unrecognized     []byte   `json:"-"`
 	XXX_sizecache        int32    `json:"-"`
@@ -751,7 +633,7 @@ func (m *RepoServerRevisionMetadataRequest) Reset()         { *m = RepoServerRev
 func (m *RepoServerRevisionMetadataRequest) String() string { return proto.CompactTextString(m) }
 func (*RepoServerRevisionMetadataRequest) ProtoMessage()    {}
 func (*RepoServerRevisionMetadataRequest) Descriptor() ([]byte, []int) {
-	return fileDescriptor_repository_a040dcfbd17da920, []int{10}
+	return fileDescriptor_repository_3f0884c8b644d045, []int{8}
 }
 func (m *RepoServerRevisionMetadataRequest) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
@@ -787,6 +669,13 @@ func (m *RepoServerRevisionMetadataRequest) GetRepo() *v1alpha1.Repository {
 	return nil
 }
 
+func (m *RepoServerRevisionMetadataRequest) GetApp() string {
+	if m != nil {
+		return m.App
+	}
+	return ""
+}
+
 func (m *RepoServerRevisionMetadataRequest) GetRevision() string {
 	if m != nil {
 		return m.Revision
@@ -798,7 +687,6 @@ func (m *RepoServerRevisionMetadataRequest) GetRevision() string {
 // This roughly reflects: ksonnet/ksonnet/metadata/app/schema.go
 type KsonnetAppSpec struct {
 	Name                 string                         `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
-	Path                 string                         `protobuf:"bytes,2,opt,name=path,proto3" json:"path,omitempty"`
 	Environments         map[string]*KsonnetEnvironment `protobuf:"bytes,3,rep,name=environments" json:"environments,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value"`
 	Parameters           []*v1alpha1.KsonnetParameter   `protobuf:"bytes,4,rep,name=parameters" json:"parameters,omitempty"`
 	XXX_NoUnkeyedLiteral struct{}                       `json:"-"`
@@ -810,7 +698,7 @@ func (m *KsonnetAppSpec) Reset()         { *m = KsonnetAppSpec{} }
 func (m *KsonnetAppSpec) String() string { return proto.CompactTextString(m) }
 func (*KsonnetAppSpec) ProtoMessage()    {}
 func (*KsonnetAppSpec) Descriptor() ([]byte, []int) {
-	return fileDescriptor_repository_a040dcfbd17da920, []int{11}
+	return fileDescriptor_repository_3f0884c8b644d045, []int{9}
 }
 func (m *KsonnetAppSpec) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
@@ -846,13 +734,6 @@ func (m *KsonnetAppSpec) GetName() string {
 	return ""
 }
 
-func (m *KsonnetAppSpec) GetPath() string {
-	if m != nil {
-		return m.Path
-	}
-	return ""
-}
-
 func (m *KsonnetAppSpec) GetEnvironments() map[string]*KsonnetEnvironment {
 	if m != nil {
 		return m.Environments
@@ -867,10 +748,9 @@ func (m *KsonnetAppSpec) GetParameters() []*v1alpha1.KsonnetParameter {
 	return nil
 }
 
-// HelmAppSpec contains helm app name and path in source repo
+// HelmAppSpec contains helm app name  in source repo
 type HelmAppSpec struct {
 	Name       string   `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
-	Path       string   `protobuf:"bytes,2,opt,name=path,proto3" json:"path,omitempty"`
 	ValueFiles []string `protobuf:"bytes,3,rep,name=valueFiles" json:"valueFiles,omitempty"`
 	// the output of `helm inspect values`
 	Parameters []*v1alpha1.HelmParameter `protobuf:"bytes,4,rep,name=parameters" json:"parameters,omitempty"`
@@ -885,7 +765,7 @@ func (m *HelmAppSpec) Reset()         { *m = HelmAppSpec{} }
 func (m *HelmAppSpec) String() string { return proto.CompactTextString(m) }
 func (*HelmAppSpec) ProtoMessage()    {}
 func (*HelmAppSpec) Descriptor() ([]byte, []int) {
-	return fileDescriptor_repository_a040dcfbd17da920, []int{12}
+	return fileDescriptor_repository_3f0884c8b644d045, []int{10}
 }
 func (m *HelmAppSpec) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
@@ -921,13 +801,6 @@ func (m *HelmAppSpec) GetName() string {
 	return ""
 }
 
-func (m *HelmAppSpec) GetPath() string {
-	if m != nil {
-		return m.Path
-	}
-	return ""
-}
-
 func (m *HelmAppSpec) GetValueFiles() []string {
 	if m != nil {
 		return m.ValueFiles
@@ -949,9 +822,8 @@ func (m *HelmAppSpec) GetValues() string {
 	return ""
 }
 
-// KustomizeAppSpec contains kustomize app name and path in source repo
+// KustomizeAppSpec contains kustomize images
 type KustomizeAppSpec struct {
-	Path string `protobuf:"bytes,1,opt,name=path,proto3" json:"path,omitempty"`
 	// images is a list of available images.
 	Images               []string `protobuf:"bytes,3,rep,name=images" json:"images,omitempty"`
 	XXX_NoUnkeyedLiteral struct{} `json:"-"`
@@ -963,7 +835,7 @@ func (m *KustomizeAppSpec) Reset()         { *m = KustomizeAppSpec{} }
 func (m *KustomizeAppSpec) String() string { return proto.CompactTextString(m) }
 func (*KustomizeAppSpec) ProtoMessage()    {}
 func (*KustomizeAppSpec) Descriptor() ([]byte, []int) {
-	return fileDescriptor_repository_a040dcfbd17da920, []int{13}
+	return fileDescriptor_repository_3f0884c8b644d045, []int{11}
 }
 func (m *KustomizeAppSpec) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
@@ -992,13 +864,6 @@ func (m *KustomizeAppSpec) XXX_DiscardUnknown() {
 
 var xxx_messageInfo_KustomizeAppSpec proto.InternalMessageInfo
 
-func (m *KustomizeAppSpec) GetPath() string {
-	if m != nil {
-		return m.Path
-	}
-	return ""
-}
-
 func (m *KustomizeAppSpec) GetImages() []string {
 	if m != nil {
 		return m.Images
@@ -1011,8 +876,6 @@ type KsonnetEnvironment struct {
 	Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
 	// KubernetesVersion is the kubernetes version the targetted cluster is running on.
 	K8SVersion string `protobuf:"bytes,2,opt,name=k8sVersion,proto3" json:"k8sVersion,omitempty"`
-	// Path is the relative project path containing metadata for this environment.
-	Path string `protobuf:"bytes,3,opt,name=path,proto3" json:"path,omitempty"`
 	// Destination stores the cluster address that this environment points to.
 	Destination          *KsonnetEnvironmentDestination `protobuf:"bytes,4,opt,name=destination" json:"destination,omitempty"`
 	XXX_NoUnkeyedLiteral struct{}                       `json:"-"`
@@ -1024,7 +887,7 @@ func (m *KsonnetEnvironment) Reset()         { *m = KsonnetEnvironment{} }
 func (m *KsonnetEnvironment) String() string { return proto.CompactTextString(m) }
 func (*KsonnetEnvironment) ProtoMessage()    {}
 func (*KsonnetEnvironment) Descriptor() ([]byte, []int) {
-	return fileDescriptor_repository_a040dcfbd17da920, []int{14}
+	return fileDescriptor_repository_3f0884c8b644d045, []int{12}
 }
 func (m *KsonnetEnvironment) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
@@ -1067,13 +930,6 @@ func (m *KsonnetEnvironment) GetK8SVersion() string {
 	return ""
 }
 
-func (m *KsonnetEnvironment) GetPath() string {
-	if m != nil {
-		return m.Path
-	}
-	return ""
-}
-
 func (m *KsonnetEnvironment) GetDestination() *KsonnetEnvironmentDestination {
 	if m != nil {
 		return m.Destination
@@ -1095,7 +951,7 @@ func (m *KsonnetEnvironmentDestination) Reset()         { *m = KsonnetEnvironmen
 func (m *KsonnetEnvironmentDestination) String() string { return proto.CompactTextString(m) }
 func (*KsonnetEnvironmentDestination) ProtoMessage()    {}
 func (*KsonnetEnvironmentDestination) Descriptor() ([]byte, []int) {
-	return fileDescriptor_repository_a040dcfbd17da920, []int{15}
+	return fileDescriptor_repository_3f0884c8b644d045, []int{13}
 }
 func (m *KsonnetEnvironmentDestination) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
@@ -1149,7 +1005,7 @@ func (m *DirectoryAppSpec) Reset()         { *m = DirectoryAppSpec{} }
 func (m *DirectoryAppSpec) String() string { return proto.CompactTextString(m) }
 func (*DirectoryAppSpec) ProtoMessage()    {}
 func (*DirectoryAppSpec) Descriptor() ([]byte, []int) {
-	return fileDescriptor_repository_a040dcfbd17da920, []int{16}
+	return fileDescriptor_repository_3f0884c8b644d045, []int{14}
 }
 func (m *DirectoryAppSpec) XXX_Unmarshal(b []byte) error {
 	return m.Unmarshal(b)
@@ -1181,10 +1037,9 @@ var xxx_messageInfo_DirectoryAppSpec proto.InternalMessageInfo
 func init() {
 	proto.RegisterType((*ManifestRequest)(nil), "repository.ManifestRequest")
 	proto.RegisterType((*ManifestResponse)(nil), "repository.ManifestResponse")
-	proto.RegisterType((*ListDirRequest)(nil), "repository.ListDirRequest")
-	proto.RegisterType((*FileList)(nil), "repository.FileList")
-	proto.RegisterType((*GetFileRequest)(nil), "repository.GetFileRequest")
-	proto.RegisterType((*GetFileResponse)(nil), "repository.GetFileResponse")
+	proto.RegisterType((*ListAppsRequest)(nil), "repository.ListAppsRequest")
+	proto.RegisterType((*AppList)(nil), "repository.AppList")
+	proto.RegisterMapType((map[string]string)(nil), "repository.AppList.AppsEntry")
 	proto.RegisterType((*RepoServerAppDetailsQuery)(nil), "repository.RepoServerAppDetailsQuery")
 	proto.RegisterType((*HelmAppDetailsQuery)(nil), "repository.HelmAppDetailsQuery")
 	proto.RegisterType((*KsonnetAppDetailsQuery)(nil), "repository.KsonnetAppDetailsQuery")
@@ -1212,10 +1067,8 @@ const _ = grpc.SupportPackageIsVersion4
 type RepoServerServiceClient interface {
 	// GenerateManifest generates manifest for application in specified repo name and revision
 	GenerateManifest(ctx context.Context, in *ManifestRequest, opts ...grpc.CallOption) (*ManifestResponse, error)
-	// ListDir returns the file contents at the specified repo and path
-	ListDir(ctx context.Context, in *ListDirRequest, opts ...grpc.CallOption) (*FileList, error)
-	// GetFile returns the file contents at the specified repo and path
-	GetFile(ctx context.Context, in *GetFileRequest, opts ...grpc.CallOption) (*GetFileResponse, error)
+	// ListApps returns a list of apps in the repo
+	ListApps(ctx context.Context, in *ListAppsRequest, opts ...grpc.CallOption) (*AppList, error)
 	// Generate manifest for application in specified repo name and revision
 	GetAppDetails(ctx context.Context, in *RepoServerAppDetailsQuery, opts ...grpc.CallOption) (*RepoAppDetailsResponse, error)
 	// Get the meta-data (author, date, tags, message) for a specific revision of the repo
@@ -1239,18 +1092,9 @@ func (c *repoServerServiceClient) GenerateManifest(ctx context.Context, in *Mani
 	return out, nil
 }
 
-func (c *repoServerServiceClient) ListDir(ctx context.Context, in *ListDirRequest, opts ...grpc.CallOption) (*FileList, error) {
-	out := new(FileList)
-	err := c.cc.Invoke(ctx, "/repository.RepoServerService/ListDir", in, out, opts...)
-	if err != nil {
-		return nil, err
-	}
-	return out, nil
-}
-
-func (c *repoServerServiceClient) GetFile(ctx context.Context, in *GetFileRequest, opts ...grpc.CallOption) (*GetFileResponse, error) {
-	out := new(GetFileResponse)
-	err := c.cc.Invoke(ctx, "/repository.RepoServerService/GetFile", in, out, opts...)
+func (c *repoServerServiceClient) ListApps(ctx context.Context, in *ListAppsRequest, opts ...grpc.CallOption) (*AppList, error) {
+	out := new(AppList)
+	err := c.cc.Invoke(ctx, "/repository.RepoServerService/ListApps", in, out, opts...)
 	if err != nil {
 		return nil, err
 	}
@@ -1280,10 +1124,8 @@ func (c *repoServerServiceClient) GetRevisionMetadata(ctx context.Context, in *R
 type RepoServerServiceServer interface {
 	// GenerateManifest generates manifest for application in specified repo name and revision
 	GenerateManifest(context.Context, *ManifestRequest) (*ManifestResponse, error)
-	// ListDir returns the file contents at the specified repo and path
-	ListDir(context.Context, *ListDirRequest) (*FileList, error)
-	// GetFile returns the file contents at the specified repo and path
-	GetFile(context.Context, *GetFileRequest) (*GetFileResponse, error)
+	// ListApps returns a list of apps in the repo
+	ListApps(context.Context, *ListAppsRequest) (*AppList, error)
 	// Generate manifest for application in specified repo name and revision
 	GetAppDetails(context.Context, *RepoServerAppDetailsQuery) (*RepoAppDetailsResponse, error)
 	// Get the meta-data (author, date, tags, message) for a specific revision of the repo
@@ -1312,38 +1154,20 @@ func _RepoServerService_GenerateManifest_Handler(srv interface{}, ctx context.Co
 	return interceptor(ctx, in, info, handler)
 }
 
-func _RepoServerService_ListDir_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
-	in := new(ListDirRequest)
-	if err := dec(in); err != nil {
-		return nil, err
-	}
-	if interceptor == nil {
-		return srv.(RepoServerServiceServer).ListDir(ctx, in)
-	}
-	info := &grpc.UnaryServerInfo{
-		Server:     srv,
-		FullMethod: "/repository.RepoServerService/ListDir",
-	}
-	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
-		return srv.(RepoServerServiceServer).ListDir(ctx, req.(*ListDirRequest))
-	}
-	return interceptor(ctx, in, info, handler)
-}
-
-func _RepoServerService_GetFile_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
-	in := new(GetFileRequest)
+func _RepoServerService_ListApps_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+	in := new(ListAppsRequest)
 	if err := dec(in); err != nil {
 		return nil, err
 	}
 	if interceptor == nil {
-		return srv.(RepoServerServiceServer).GetFile(ctx, in)
+		return srv.(RepoServerServiceServer).ListApps(ctx, in)
 	}
 	info := &grpc.UnaryServerInfo{
 		Server:     srv,
-		FullMethod: "/repository.RepoServerService/GetFile",
+		FullMethod: "/repository.RepoServerService/ListApps",
 	}
 	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
-		return srv.(RepoServerServiceServer).GetFile(ctx, req.(*GetFileRequest))
+		return srv.(RepoServerServiceServer).ListApps(ctx, req.(*ListAppsRequest))
 	}
 	return interceptor(ctx, in, info, handler)
 }
@@ -1393,12 +1217,8 @@ var _RepoServerService_serviceDesc = grpc.ServiceDesc{
 			Handler:    _RepoServerService_GenerateManifest_Handler,
 		},
 		{
-			MethodName: "ListDir",
-			Handler:    _RepoServerService_ListDir_Handler,
-		},
-		{
-			MethodName: "GetFile",
-			Handler:    _RepoServerService_GetFile_Handler,
+			MethodName: "ListApps",
+			Handler:    _RepoServerService_ListApps_Handler,
 		},
 		{
 			MethodName: "GetAppDetails",
@@ -1482,8 +1302,8 @@ func (m *ManifestRequest) MarshalTo(dAtA []byte) (int, error) {
 		}
 		i += n2
 	}
-	if len(m.HelmRepos) > 0 {
-		for _, msg := range m.HelmRepos {
+	if len(m.Repos) > 0 {
+		for _, msg := range m.Repos {
 			dAtA[i] = 0x5a
 			i++
 			i = encodeVarintRepository(dAtA, i, uint64(msg.Size()))
@@ -1582,7 +1402,7 @@ func (m *ManifestResponse) MarshalTo(dAtA []byte) (int, error) {
 	return i, nil
 }
 
-func (m *ListDirRequest) Marshal() (dAtA []byte, err error) {
+func (m *ListAppsRequest) Marshal() (dAtA []byte, err error) {
 	size := m.Size()
 	dAtA = make([]byte, size)
 	n, err := m.MarshalTo(dAtA)
@@ -1592,7 +1412,7 @@ func (m *ListDirRequest) Marshal() (dAtA []byte, err error) {
 	return dAtA[:n], nil
 }
 
-func (m *ListDirRequest) MarshalTo(dAtA []byte) (int, error) {
+func (m *ListAppsRequest) MarshalTo(dAtA []byte) (int, error) {
 	var i int
 	_ = i
 	var l int
@@ -1613,19 +1433,13 @@ func (m *ListDirRequest) MarshalTo(dAtA []byte) (int, error) {
 		i = encodeVarintRepository(dAtA, i, uint64(len(m.Revision)))
 		i += copy(dAtA[i:], m.Revision)
 	}
-	if len(m.Path) > 0 {
-		dAtA[i] = 0x1a
-		i++
-		i = encodeVarintRepository(dAtA, i, uint64(len(m.Path)))
-		i += copy(dAtA[i:], m.Path)
-	}
 	if m.XXX_unrecognized != nil {
 		i += copy(dAtA[i:], m.XXX_unrecognized)
 	}
 	return i, nil
 }
 
-func (m *FileList) Marshal() (dAtA []byte, err error) {
+func (m *AppList) Marshal() (dAtA []byte, err error) {
 	size := m.Size()
 	dAtA = make([]byte, size)
 	n, err := m.MarshalTo(dAtA)
@@ -1635,95 +1449,27 @@ func (m *FileList) Marshal() (dAtA []byte, err error) {
 	return dAtA[:n], nil
 }
 
-func (m *FileList) MarshalTo(dAtA []byte) (int, error) {
+func (m *AppList) MarshalTo(dAtA []byte) (int, error) {
 	var i int
 	_ = i
 	var l int
 	_ = l
-	if len(m.Items) > 0 {
-		for _, s := range m.Items {
+	if len(m.Apps) > 0 {
+		for k, _ := range m.Apps {
 			dAtA[i] = 0xa
 			i++
-			l = len(s)
-			for l >= 1<<7 {
-				dAtA[i] = uint8(uint64(l)&0x7f | 0x80)
-				l >>= 7
-				i++
-			}
-			dAtA[i] = uint8(l)
+			v := m.Apps[k]
+			mapSize := 1 + len(k) + sovRepository(uint64(len(k))) + 1 + len(v) + sovRepository(uint64(len(v)))
+			i = encodeVarintRepository(dAtA, i, uint64(mapSize))
+			dAtA[i] = 0xa
 			i++
-			i += copy(dAtA[i:], s)
-		}
-	}
-	if m.XXX_unrecognized != nil {
-		i += copy(dAtA[i:], m.XXX_unrecognized)
-	}
-	return i, nil
-}
-
-func (m *GetFileRequest) Marshal() (dAtA []byte, err error) {
-	size := m.Size()
-	dAtA = make([]byte, size)
-	n, err := m.MarshalTo(dAtA)
-	if err != nil {
-		return nil, err
-	}
-	return dAtA[:n], nil
-}
-
-func (m *GetFileRequest) MarshalTo(dAtA []byte) (int, error) {
-	var i int
-	_ = i
-	var l int
-	_ = l
-	if m.Repo != nil {
-		dAtA[i] = 0xa
-		i++
-		i = encodeVarintRepository(dAtA, i, uint64(m.Repo.Size()))
-		n5, err := m.Repo.MarshalTo(dAtA[i:])
-		if err != nil {
-			return 0, err
+			i = encodeVarintRepository(dAtA, i, uint64(len(k)))
+			i += copy(dAtA[i:], k)
+			dAtA[i] = 0x12
+			i++
+			i = encodeVarintRepository(dAtA, i, uint64(len(v)))
+			i += copy(dAtA[i:], v)
 		}
-		i += n5
-	}
-	if len(m.Revision) > 0 {
-		dAtA[i] = 0x12
-		i++
-		i = encodeVarintRepository(dAtA, i, uint64(len(m.Revision)))
-		i += copy(dAtA[i:], m.Revision)
-	}
-	if len(m.Path) > 0 {
-		dAtA[i] = 0x1a
-		i++
-		i = encodeVarintRepository(dAtA, i, uint64(len(m.Path)))
-		i += copy(dAtA[i:], m.Path)
-	}
-	if m.XXX_unrecognized != nil {
-		i += copy(dAtA[i:], m.XXX_unrecognized)
-	}
-	return i, nil
-}
-
-func (m *GetFileResponse) Marshal() (dAtA []byte, err error) {
-	size := m.Size()
-	dAtA = make([]byte, size)
-	n, err := m.MarshalTo(dAtA)
-	if err != nil {
-		return nil, err
-	}
-	return dAtA[:n], nil
-}
-
-func (m *GetFileResponse) MarshalTo(dAtA []byte) (int, error) {
-	var i int
-	_ = i
-	var l int
-	_ = l
-	if len(m.Data) > 0 {
-		dAtA[i] = 0xa
-		i++
-		i = encodeVarintRepository(dAtA, i, uint64(len(m.Data)))
-		i += copy(dAtA[i:], m.Data)
 	}
 	if m.XXX_unrecognized != nil {
 		i += copy(dAtA[i:], m.XXX_unrecognized)
@@ -1750,11 +1496,11 @@ func (m *RepoServerAppDetailsQuery) MarshalTo(dAtA []byte) (int, error) {
 		dAtA[i] = 0xa
 		i++
 		i = encodeVarintRepository(dAtA, i, uint64(m.Repo.Size()))
-		n6, err := m.Repo.MarshalTo(dAtA[i:])
+		n5, err := m.Repo.MarshalTo(dAtA[i:])
 		if err != nil {
 			return 0, err
 		}
-		i += n6
+		i += n5
 	}
 	if len(m.Revision) > 0 {
 		dAtA[i] = 0x12
@@ -1762,14 +1508,14 @@ func (m *RepoServerAppDetailsQuery) MarshalTo(dAtA []byte) (int, error) {
 		i = encodeVarintRepository(dAtA, i, uint64(len(m.Revision)))
 		i += copy(dAtA[i:], m.Revision)
 	}
-	if len(m.Path) > 0 {
+	if len(m.App) > 0 {
 		dAtA[i] = 0x1a
 		i++
-		i = encodeVarintRepository(dAtA, i, uint64(len(m.Path)))
-		i += copy(dAtA[i:], m.Path)
+		i = encodeVarintRepository(dAtA, i, uint64(len(m.App)))
+		i += copy(dAtA[i:], m.App)
 	}
-	if len(m.HelmRepos) > 0 {
-		for _, msg := range m.HelmRepos {
+	if len(m.Repos) > 0 {
+		for _, msg := range m.Repos {
 			dAtA[i] = 0x22
 			i++
 			i = encodeVarintRepository(dAtA, i, uint64(msg.Size()))
@@ -1796,31 +1542,31 @@ func (m *RepoServerAppDetailsQuery) MarshalTo(dAtA []byte) (int, error) {
 		dAtA[i] = 0x32
 		i++
 		i = encodeVarintRepository(dAtA, i, uint64(m.Helm.Size()))
-		n7, err := m.Helm.MarshalTo(dAtA[i:])
+		n6, err := m.Helm.MarshalTo(dAtA[i:])
 		if err != nil {
 			return 0, err
 		}
-		i += n7
+		i += n6
 	}
 	if m.Ksonnet != nil {
 		dAtA[i] = 0x3a
 		i++
 		i = encodeVarintRepository(dAtA, i, uint64(m.Ksonnet.Size()))
-		n8, err := m.Ksonnet.MarshalTo(dAtA[i:])
+		n7, err := m.Ksonnet.MarshalTo(dAtA[i:])
 		if err != nil {
 			return 0, err
 		}
-		i += n8
+		i += n7
 	}
 	if m.KustomizeOptions != nil {
 		dAtA[i] = 0x42
 		i++
 		i = encodeVarintRepository(dAtA, i, uint64(m.KustomizeOptions.Size()))
-		n9, err := m.KustomizeOptions.MarshalTo(dAtA[i:])
+		n8, err := m.KustomizeOptions.MarshalTo(dAtA[i:])
 		if err != nil {
 			return 0, err
 		}
-		i += n9
+		i += n8
 	}
 	if m.XXX_unrecognized != nil {
 		i += copy(dAtA[i:], m.XXX_unrecognized)
@@ -1916,41 +1662,41 @@ func (m *RepoAppDetailsResponse) MarshalTo(dAtA []byte) (int, error) {
 		dAtA[i] = 0x12
 		i++
 		i = encodeVarintRepository(dAtA, i, uint64(m.Ksonnet.Size()))
-		n10, err := m.Ksonnet.MarshalTo(dAtA[i:])
+		n9, err := m.Ksonnet.MarshalTo(dAtA[i:])
 		if err != nil {
 			return 0, err
 		}
-		i += n10
+		i += n9
 	}
 	if m.Helm != nil {
 		dAtA[i] = 0x1a
 		i++
 		i = encodeVarintRepository(dAtA, i, uint64(m.Helm.Size()))
-		n11, err := m.Helm.MarshalTo(dAtA[i:])
+		n10, err := m.Helm.MarshalTo(dAtA[i:])
 		if err != nil {
 			return 0, err
 		}
-		i += n11
+		i += n10
 	}
 	if m.Kustomize != nil {
 		dAtA[i] = 0x22
 		i++
 		i = encodeVarintRepository(dAtA, i, uint64(m.Kustomize.Size()))
-		n12, err := m.Kustomize.MarshalTo(dAtA[i:])
+		n11, err := m.Kustomize.MarshalTo(dAtA[i:])
 		if err != nil {
 			return 0, err
 		}
-		i += n12
+		i += n11
 	}
 	if m.Directory != nil {
 		dAtA[i] = 0x2a
 		i++
 		i = encodeVarintRepository(dAtA, i, uint64(m.Directory.Size()))
-		n13, err := m.Directory.MarshalTo(dAtA[i:])
+		n12, err := m.Directory.MarshalTo(dAtA[i:])
 		if err != nil {
 			return 0, err
 		}
-		i += n13
+		i += n12
 	}
 	if m.XXX_unrecognized != nil {
 		i += copy(dAtA[i:], m.XXX_unrecognized)
@@ -1977,15 +1723,21 @@ func (m *RepoServerRevisionMetadataRequest) MarshalTo(dAtA []byte) (int, error)
 		dAtA[i] = 0xa
 		i++
 		i = encodeVarintRepository(dAtA, i, uint64(m.Repo.Size()))
-		n14, err := m.Repo.MarshalTo(dAtA[i:])
+		n13, err := m.Repo.MarshalTo(dAtA[i:])
 		if err != nil {
 			return 0, err
 		}
-		i += n14
+		i += n13
 	}
-	if len(m.Revision) > 0 {
+	if len(m.App) > 0 {
 		dAtA[i] = 0x12
 		i++
+		i = encodeVarintRepository(dAtA, i, uint64(len(m.App)))
+		i += copy(dAtA[i:], m.App)
+	}
+	if len(m.Revision) > 0 {
+		dAtA[i] = 0x1a
+		i++
 		i = encodeVarintRepository(dAtA, i, uint64(len(m.Revision)))
 		i += copy(dAtA[i:], m.Revision)
 	}
@@ -2016,12 +1768,6 @@ func (m *KsonnetAppSpec) MarshalTo(dAtA []byte) (int, error) {
 		i = encodeVarintRepository(dAtA, i, uint64(len(m.Name)))
 		i += copy(dAtA[i:], m.Name)
 	}
-	if len(m.Path) > 0 {
-		dAtA[i] = 0x12
-		i++
-		i = encodeVarintRepository(dAtA, i, uint64(len(m.Path)))
-		i += copy(dAtA[i:], m.Path)
-	}
 	if len(m.Environments) > 0 {
 		for k, _ := range m.Environments {
 			dAtA[i] = 0x1a
@@ -2042,11 +1788,11 @@ func (m *KsonnetAppSpec) MarshalTo(dAtA []byte) (int, error) {
 				dAtA[i] = 0x12
 				i++
 				i = encodeVarintRepository(dAtA, i, uint64(v.Size()))
-				n15, err := v.MarshalTo(dAtA[i:])
+				n14, err := v.MarshalTo(dAtA[i:])
 				if err != nil {
 					return 0, err
 				}
-				i += n15
+				i += n14
 			}
 		}
 	}
@@ -2089,12 +1835,6 @@ func (m *HelmAppSpec) MarshalTo(dAtA []byte) (int, error) {
 		i = encodeVarintRepository(dAtA, i, uint64(len(m.Name)))
 		i += copy(dAtA[i:], m.Name)
 	}
-	if len(m.Path) > 0 {
-		dAtA[i] = 0x12
-		i++
-		i = encodeVarintRepository(dAtA, i, uint64(len(m.Path)))
-		i += copy(dAtA[i:], m.Path)
-	}
 	if len(m.ValueFiles) > 0 {
 		for _, s := range m.ValueFiles {
 			dAtA[i] = 0x1a
@@ -2149,12 +1889,6 @@ func (m *KustomizeAppSpec) MarshalTo(dAtA []byte) (int, error) {
 	_ = i
 	var l int
 	_ = l
-	if len(m.Path) > 0 {
-		dAtA[i] = 0xa
-		i++
-		i = encodeVarintRepository(dAtA, i, uint64(len(m.Path)))
-		i += copy(dAtA[i:], m.Path)
-	}
 	if len(m.Images) > 0 {
 		for _, s := range m.Images {
 			dAtA[i] = 0x1a
@@ -2203,21 +1937,15 @@ func (m *KsonnetEnvironment) MarshalTo(dAtA []byte) (int, error) {
 		i = encodeVarintRepository(dAtA, i, uint64(len(m.K8SVersion)))
 		i += copy(dAtA[i:], m.K8SVersion)
 	}
-	if len(m.Path) > 0 {
-		dAtA[i] = 0x1a
-		i++
-		i = encodeVarintRepository(dAtA, i, uint64(len(m.Path)))
-		i += copy(dAtA[i:], m.Path)
-	}
 	if m.Destination != nil {
 		dAtA[i] = 0x22
 		i++
 		i = encodeVarintRepository(dAtA, i, uint64(m.Destination.Size()))
-		n16, err := m.Destination.MarshalTo(dAtA[i:])
+		n15, err := m.Destination.MarshalTo(dAtA[i:])
 		if err != nil {
 			return 0, err
 		}
-		i += n16
+		i += n15
 	}
 	if m.XXX_unrecognized != nil {
 		i += copy(dAtA[i:], m.XXX_unrecognized)
@@ -2318,8 +2046,8 @@ func (m *ManifestRequest) Size() (n int) {
 		l = m.ApplicationSource.Size()
 		n += 1 + l + sovRepository(uint64(l))
 	}
-	if len(m.HelmRepos) > 0 {
-		for _, e := range m.HelmRepos {
+	if len(m.Repos) > 0 {
+		for _, e := range m.Repos {
 			l = e.Size()
 			n += 1 + l + sovRepository(uint64(l))
 		}
@@ -2371,7 +2099,7 @@ func (m *ManifestResponse) Size() (n int) {
 	return n
 }
 
-func (m *ListDirRequest) Size() (n int) {
+func (m *ListAppsRequest) Size() (n int) {
 	var l int
 	_ = l
 	if m.Repo != nil {
@@ -2382,23 +2110,21 @@ func (m *ListDirRequest) Size() (n int) {
 	if l > 0 {
 		n += 1 + l + sovRepository(uint64(l))
 	}
-	l = len(m.Path)
-	if l > 0 {
-		n += 1 + l + sovRepository(uint64(l))
-	}
 	if m.XXX_unrecognized != nil {
 		n += len(m.XXX_unrecognized)
 	}
 	return n
 }
 
-func (m *FileList) Size() (n int) {
+func (m *AppList) Size() (n int) {
 	var l int
 	_ = l
-	if len(m.Items) > 0 {
-		for _, s := range m.Items {
-			l = len(s)
-			n += 1 + l + sovRepository(uint64(l))
+	if len(m.Apps) > 0 {
+		for k, v := range m.Apps {
+			_ = k
+			_ = v
+			mapEntrySize := 1 + len(k) + sovRepository(uint64(len(k))) + 1 + len(v) + sovRepository(uint64(len(v)))
+			n += mapEntrySize + 1 + sovRepository(uint64(mapEntrySize))
 		}
 	}
 	if m.XXX_unrecognized != nil {
@@ -2407,7 +2133,7 @@ func (m *FileList) Size() (n int) {
 	return n
 }
 
-func (m *GetFileRequest) Size() (n int) {
+func (m *RepoServerAppDetailsQuery) Size() (n int) {
 	var l int
 	_ = l
 	if m.Repo != nil {
@@ -2418,49 +2144,15 @@ func (m *GetFileRequest) Size() (n int) {
 	if l > 0 {
 		n += 1 + l + sovRepository(uint64(l))
 	}
-	l = len(m.Path)
+	l = len(m.App)
 	if l > 0 {
 		n += 1 + l + sovRepository(uint64(l))
 	}
-	if m.XXX_unrecognized != nil {
-		n += len(m.XXX_unrecognized)
-	}
-	return n
-}
-
-func (m *GetFileResponse) Size() (n int) {
-	var l int
-	_ = l
-	l = len(m.Data)
-	if l > 0 {
-		n += 1 + l + sovRepository(uint64(l))
-	}
-	if m.XXX_unrecognized != nil {
-		n += len(m.XXX_unrecognized)
-	}
-	return n
-}
-
-func (m *RepoServerAppDetailsQuery) Size() (n int) {
-	var l int
-	_ = l
-	if m.Repo != nil {
-		l = m.Repo.Size()
-		n += 1 + l + sovRepository(uint64(l))
-	}
-	l = len(m.Revision)
-	if l > 0 {
-		n += 1 + l + sovRepository(uint64(l))
-	}
-	l = len(m.Path)
-	if l > 0 {
-		n += 1 + l + sovRepository(uint64(l))
-	}
-	if len(m.HelmRepos) > 0 {
-		for _, e := range m.HelmRepos {
-			l = e.Size()
-			n += 1 + l + sovRepository(uint64(l))
-		}
+	if len(m.Repos) > 0 {
+		for _, e := range m.Repos {
+			l = e.Size()
+			n += 1 + l + sovRepository(uint64(l))
+		}
 	}
 	if len(m.Plugins) > 0 {
 		for _, e := range m.Plugins {
@@ -2550,6 +2242,10 @@ func (m *RepoServerRevisionMetadataRequest) Size() (n int) {
 		l = m.Repo.Size()
 		n += 1 + l + sovRepository(uint64(l))
 	}
+	l = len(m.App)
+	if l > 0 {
+		n += 1 + l + sovRepository(uint64(l))
+	}
 	l = len(m.Revision)
 	if l > 0 {
 		n += 1 + l + sovRepository(uint64(l))
@@ -2567,10 +2263,6 @@ func (m *KsonnetAppSpec) Size() (n int) {
 	if l > 0 {
 		n += 1 + l + sovRepository(uint64(l))
 	}
-	l = len(m.Path)
-	if l > 0 {
-		n += 1 + l + sovRepository(uint64(l))
-	}
 	if len(m.Environments) > 0 {
 		for k, v := range m.Environments {
 			_ = k
@@ -2603,10 +2295,6 @@ func (m *HelmAppSpec) Size() (n int) {
 	if l > 0 {
 		n += 1 + l + sovRepository(uint64(l))
 	}
-	l = len(m.Path)
-	if l > 0 {
-		n += 1 + l + sovRepository(uint64(l))
-	}
 	if len(m.ValueFiles) > 0 {
 		for _, s := range m.ValueFiles {
 			l = len(s)
@@ -2632,10 +2320,6 @@ func (m *HelmAppSpec) Size() (n int) {
 func (m *KustomizeAppSpec) Size() (n int) {
 	var l int
 	_ = l
-	l = len(m.Path)
-	if l > 0 {
-		n += 1 + l + sovRepository(uint64(l))
-	}
 	if len(m.Images) > 0 {
 		for _, s := range m.Images {
 			l = len(s)
@@ -2659,10 +2343,6 @@ func (m *KsonnetEnvironment) Size() (n int) {
 	if l > 0 {
 		n += 1 + l + sovRepository(uint64(l))
 	}
-	l = len(m.Path)
-	if l > 0 {
-		n += 1 + l + sovRepository(uint64(l))
-	}
 	if m.Destination != nil {
 		l = m.Destination.Size()
 		n += 1 + l + sovRepository(uint64(l))
@@ -2945,7 +2625,7 @@ func (m *ManifestRequest) Unmarshal(dAtA []byte) error {
 			iNdEx = postIndex
 		case 11:
 			if wireType != 2 {
-				return fmt.Errorf("proto: wrong wireType = %d for field HelmRepos", wireType)
+				return fmt.Errorf("proto: wrong wireType = %d for field Repos", wireType)
 			}
 			var msglen int
 			for shift := uint(0); ; shift += 7 {
@@ -2969,8 +2649,8 @@ func (m *ManifestRequest) Unmarshal(dAtA []byte) error {
 			if postIndex > l {
 				return io.ErrUnexpectedEOF
 			}
-			m.HelmRepos = append(m.HelmRepos, &v1alpha1.HelmRepository{})
-			if err := m.HelmRepos[len(m.HelmRepos)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+			m.Repos = append(m.Repos, &v1alpha1.Repository{})
+			if err := m.Repos[len(m.Repos)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
 				return err
 			}
 			iNdEx = postIndex
@@ -3256,7 +2936,7 @@ func (m *ManifestResponse) Unmarshal(dAtA []byte) error {
 	}
 	return nil
 }
-func (m *ListDirRequest) Unmarshal(dAtA []byte) error {
+func (m *ListAppsRequest) Unmarshal(dAtA []byte) error {
 	l := len(dAtA)
 	iNdEx := 0
 	for iNdEx < l {
@@ -3279,10 +2959,10 @@ func (m *ListDirRequest) Unmarshal(dAtA []byte) error {
 		fieldNum := int32(wire >> 3)
 		wireType := int(wire & 0x7)
 		if wireType == 4 {
-			return fmt.Errorf("proto: ListDirRequest: wiretype end group for non-group")
+			return fmt.Errorf("proto: ListAppsRequest: wiretype end group for non-group")
 		}
 		if fieldNum <= 0 {
-			return fmt.Errorf("proto: ListDirRequest: illegal tag %d (wire type %d)", fieldNum, wire)
+			return fmt.Errorf("proto: ListAppsRequest: illegal tag %d (wire type %d)", fieldNum, wire)
 		}
 		switch fieldNum {
 		case 1:
@@ -3347,115 +3027,6 @@ func (m *ListDirRequest) Unmarshal(dAtA []byte) error {
 			}
 			m.Revision = string(dAtA[iNdEx:postIndex])
 			iNdEx = postIndex
-		case 3:
-			if wireType != 2 {
-				return fmt.Errorf("proto: wrong wireType = %d for field Path", wireType)
-			}
-			var stringLen uint64
-			for shift := uint(0); ; shift += 7 {
-				if shift >= 64 {
-					return ErrIntOverflowRepository
-				}
-				if iNdEx >= l {
-					return io.ErrUnexpectedEOF
-				}
-				b := dAtA[iNdEx]
-				iNdEx++
-				stringLen |= (uint64(b) & 0x7F) << shift
-				if b < 0x80 {
-					break
-				}
-			}
-			intStringLen := int(stringLen)
-			if intStringLen < 0 {
-				return ErrInvalidLengthRepository
-			}
-			postIndex := iNdEx + intStringLen
-			if postIndex > l {
-				return io.ErrUnexpectedEOF
-			}
-			m.Path = string(dAtA[iNdEx:postIndex])
-			iNdEx = postIndex
-		default:
-			iNdEx = preIndex
-			skippy, err := skipRepository(dAtA[iNdEx:])
-			if err != nil {
-				return err
-			}
-			if skippy < 0 {
-				return ErrInvalidLengthRepository
-			}
-			if (iNdEx + skippy) > l {
-				return io.ErrUnexpectedEOF
-			}
-			m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
-			iNdEx += skippy
-		}
-	}
-
-	if iNdEx > l {
-		return io.ErrUnexpectedEOF
-	}
-	return nil
-}
-func (m *FileList) Unmarshal(dAtA []byte) error {
-	l := len(dAtA)
-	iNdEx := 0
-	for iNdEx < l {
-		preIndex := iNdEx
-		var wire uint64
-		for shift := uint(0); ; shift += 7 {
-			if shift >= 64 {
-				return ErrIntOverflowRepository
-			}
-			if iNdEx >= l {
-				return io.ErrUnexpectedEOF
-			}
-			b := dAtA[iNdEx]
-			iNdEx++
-			wire |= (uint64(b) & 0x7F) << shift
-			if b < 0x80 {
-				break
-			}
-		}
-		fieldNum := int32(wire >> 3)
-		wireType := int(wire & 0x7)
-		if wireType == 4 {
-			return fmt.Errorf("proto: FileList: wiretype end group for non-group")
-		}
-		if fieldNum <= 0 {
-			return fmt.Errorf("proto: FileList: illegal tag %d (wire type %d)", fieldNum, wire)
-		}
-		switch fieldNum {
-		case 1:
-			if wireType != 2 {
-				return fmt.Errorf("proto: wrong wireType = %d for field Items", wireType)
-			}
-			var stringLen uint64
-			for shift := uint(0); ; shift += 7 {
-				if shift >= 64 {
-					return ErrIntOverflowRepository
-				}
-				if iNdEx >= l {
-					return io.ErrUnexpectedEOF
-				}
-				b := dAtA[iNdEx]
-				iNdEx++
-				stringLen |= (uint64(b) & 0x7F) << shift
-				if b < 0x80 {
-					break
-				}
-			}
-			intStringLen := int(stringLen)
-			if intStringLen < 0 {
-				return ErrInvalidLengthRepository
-			}
-			postIndex := iNdEx + intStringLen
-			if postIndex > l {
-				return io.ErrUnexpectedEOF
-			}
-			m.Items = append(m.Items, string(dAtA[iNdEx:postIndex]))
-			iNdEx = postIndex
 		default:
 			iNdEx = preIndex
 			skippy, err := skipRepository(dAtA[iNdEx:])
@@ -3478,7 +3049,7 @@ func (m *FileList) Unmarshal(dAtA []byte) error {
 	}
 	return nil
 }
-func (m *GetFileRequest) Unmarshal(dAtA []byte) error {
+func (m *AppList) Unmarshal(dAtA []byte) error {
 	l := len(dAtA)
 	iNdEx := 0
 	for iNdEx < l {
@@ -3501,15 +3072,15 @@ func (m *GetFileRequest) Unmarshal(dAtA []byte) error {
 		fieldNum := int32(wire >> 3)
 		wireType := int(wire & 0x7)
 		if wireType == 4 {
-			return fmt.Errorf("proto: GetFileRequest: wiretype end group for non-group")
+			return fmt.Errorf("proto: AppList: wiretype end group for non-group")
 		}
 		if fieldNum <= 0 {
-			return fmt.Errorf("proto: GetFileRequest: illegal tag %d (wire type %d)", fieldNum, wire)
+			return fmt.Errorf("proto: AppList: illegal tag %d (wire type %d)", fieldNum, wire)
 		}
 		switch fieldNum {
 		case 1:
 			if wireType != 2 {
-				return fmt.Errorf("proto: wrong wireType = %d for field Repo", wireType)
+				return fmt.Errorf("proto: wrong wireType = %d for field Apps", wireType)
 			}
 			var msglen int
 			for shift := uint(0); ; shift += 7 {
@@ -3533,152 +3104,97 @@ func (m *GetFileRequest) Unmarshal(dAtA []byte) error {
 			if postIndex > l {
 				return io.ErrUnexpectedEOF
 			}
-			if m.Repo == nil {
-				m.Repo = &v1alpha1.Repository{}
-			}
-			if err := m.Repo.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
-				return err
-			}
-			iNdEx = postIndex
-		case 2:
-			if wireType != 2 {
-				return fmt.Errorf("proto: wrong wireType = %d for field Revision", wireType)
-			}
-			var stringLen uint64
-			for shift := uint(0); ; shift += 7 {
-				if shift >= 64 {
-					return ErrIntOverflowRepository
-				}
-				if iNdEx >= l {
-					return io.ErrUnexpectedEOF
-				}
-				b := dAtA[iNdEx]
-				iNdEx++
-				stringLen |= (uint64(b) & 0x7F) << shift
-				if b < 0x80 {
-					break
-				}
-			}
-			intStringLen := int(stringLen)
-			if intStringLen < 0 {
-				return ErrInvalidLengthRepository
-			}
-			postIndex := iNdEx + intStringLen
-			if postIndex > l {
-				return io.ErrUnexpectedEOF
-			}
-			m.Revision = string(dAtA[iNdEx:postIndex])
-			iNdEx = postIndex
-		case 3:
-			if wireType != 2 {
-				return fmt.Errorf("proto: wrong wireType = %d for field Path", wireType)
-			}
-			var stringLen uint64
-			for shift := uint(0); ; shift += 7 {
-				if shift >= 64 {
-					return ErrIntOverflowRepository
-				}
-				if iNdEx >= l {
-					return io.ErrUnexpectedEOF
-				}
-				b := dAtA[iNdEx]
-				iNdEx++
-				stringLen |= (uint64(b) & 0x7F) << shift
-				if b < 0x80 {
-					break
-				}
-			}
-			intStringLen := int(stringLen)
-			if intStringLen < 0 {
-				return ErrInvalidLengthRepository
-			}
-			postIndex := iNdEx + intStringLen
-			if postIndex > l {
-				return io.ErrUnexpectedEOF
-			}
-			m.Path = string(dAtA[iNdEx:postIndex])
-			iNdEx = postIndex
-		default:
-			iNdEx = preIndex
-			skippy, err := skipRepository(dAtA[iNdEx:])
-			if err != nil {
-				return err
-			}
-			if skippy < 0 {
-				return ErrInvalidLengthRepository
-			}
-			if (iNdEx + skippy) > l {
-				return io.ErrUnexpectedEOF
-			}
-			m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
-			iNdEx += skippy
-		}
-	}
-
-	if iNdEx > l {
-		return io.ErrUnexpectedEOF
-	}
-	return nil
-}
-func (m *GetFileResponse) Unmarshal(dAtA []byte) error {
-	l := len(dAtA)
-	iNdEx := 0
-	for iNdEx < l {
-		preIndex := iNdEx
-		var wire uint64
-		for shift := uint(0); ; shift += 7 {
-			if shift >= 64 {
-				return ErrIntOverflowRepository
-			}
-			if iNdEx >= l {
-				return io.ErrUnexpectedEOF
+			if m.Apps == nil {
+				m.Apps = make(map[string]string)
 			}
-			b := dAtA[iNdEx]
-			iNdEx++
-			wire |= (uint64(b) & 0x7F) << shift
-			if b < 0x80 {
-				break
-			}
-		}
-		fieldNum := int32(wire >> 3)
-		wireType := int(wire & 0x7)
-		if wireType == 4 {
-			return fmt.Errorf("proto: GetFileResponse: wiretype end group for non-group")
-		}
-		if fieldNum <= 0 {
-			return fmt.Errorf("proto: GetFileResponse: illegal tag %d (wire type %d)", fieldNum, wire)
-		}
-		switch fieldNum {
-		case 1:
-			if wireType != 2 {
-				return fmt.Errorf("proto: wrong wireType = %d for field Data", wireType)
-			}
-			var byteLen int
-			for shift := uint(0); ; shift += 7 {
-				if shift >= 64 {
-					return ErrIntOverflowRepository
-				}
-				if iNdEx >= l {
-					return io.ErrUnexpectedEOF
+			var mapkey string
+			var mapvalue string
+			for iNdEx < postIndex {
+				entryPreIndex := iNdEx
+				var wire uint64
+				for shift := uint(0); ; shift += 7 {
+					if shift >= 64 {
+						return ErrIntOverflowRepository
+					}
+					if iNdEx >= l {
+						return io.ErrUnexpectedEOF
+					}
+					b := dAtA[iNdEx]
+					iNdEx++
+					wire |= (uint64(b) & 0x7F) << shift
+					if b < 0x80 {
+						break
+					}
 				}
-				b := dAtA[iNdEx]
-				iNdEx++
-				byteLen |= (int(b) & 0x7F) << shift
-				if b < 0x80 {
-					break
+				fieldNum := int32(wire >> 3)
+				if fieldNum == 1 {
+					var stringLenmapkey uint64
+					for shift := uint(0); ; shift += 7 {
+						if shift >= 64 {
+							return ErrIntOverflowRepository
+						}
+						if iNdEx >= l {
+							return io.ErrUnexpectedEOF
+						}
+						b := dAtA[iNdEx]
+						iNdEx++
+						stringLenmapkey |= (uint64(b) & 0x7F) << shift
+						if b < 0x80 {
+							break
+						}
+					}
+					intStringLenmapkey := int(stringLenmapkey)
+					if intStringLenmapkey < 0 {
+						return ErrInvalidLengthRepository
+					}
+					postStringIndexmapkey := iNdEx + intStringLenmapkey
+					if postStringIndexmapkey > l {
+						return io.ErrUnexpectedEOF
+					}
+					mapkey = string(dAtA[iNdEx:postStringIndexmapkey])
+					iNdEx = postStringIndexmapkey
+				} else if fieldNum == 2 {
+					var stringLenmapvalue uint64
+					for shift := uint(0); ; shift += 7 {
+						if shift >= 64 {
+							return ErrIntOverflowRepository
+						}
+						if iNdEx >= l {
+							return io.ErrUnexpectedEOF
+						}
+						b := dAtA[iNdEx]
+						iNdEx++
+						stringLenmapvalue |= (uint64(b) & 0x7F) << shift
+						if b < 0x80 {
+							break
+						}
+					}
+					intStringLenmapvalue := int(stringLenmapvalue)
+					if intStringLenmapvalue < 0 {
+						return ErrInvalidLengthRepository
+					}
+					postStringIndexmapvalue := iNdEx + intStringLenmapvalue
+					if postStringIndexmapvalue > l {
+						return io.ErrUnexpectedEOF
+					}
+					mapvalue = string(dAtA[iNdEx:postStringIndexmapvalue])
+					iNdEx = postStringIndexmapvalue
+				} else {
+					iNdEx = entryPreIndex
+					skippy, err := skipRepository(dAtA[iNdEx:])
+					if err != nil {
+						return err
+					}
+					if skippy < 0 {
+						return ErrInvalidLengthRepository
+					}
+					if (iNdEx + skippy) > postIndex {
+						return io.ErrUnexpectedEOF
+					}
+					iNdEx += skippy
 				}
 			}
-			if byteLen < 0 {
-				return ErrInvalidLengthRepository
-			}
-			postIndex := iNdEx + byteLen
-			if postIndex > l {
-				return io.ErrUnexpectedEOF
-			}
-			m.Data = append(m.Data[:0], dAtA[iNdEx:postIndex]...)
-			if m.Data == nil {
-				m.Data = []byte{}
-			}
+			m.Apps[mapkey] = mapvalue
 			iNdEx = postIndex
 		default:
 			iNdEx = preIndex
@@ -3795,7 +3311,7 @@ func (m *RepoServerAppDetailsQuery) Unmarshal(dAtA []byte) error {
 			iNdEx = postIndex
 		case 3:
 			if wireType != 2 {
-				return fmt.Errorf("proto: wrong wireType = %d for field Path", wireType)
+				return fmt.Errorf("proto: wrong wireType = %d for field App", wireType)
 			}
 			var stringLen uint64
 			for shift := uint(0); ; shift += 7 {
@@ -3820,11 +3336,11 @@ func (m *RepoServerAppDetailsQuery) Unmarshal(dAtA []byte) error {
 			if postIndex > l {
 				return io.ErrUnexpectedEOF
 			}
-			m.Path = string(dAtA[iNdEx:postIndex])
+			m.App = string(dAtA[iNdEx:postIndex])
 			iNdEx = postIndex
 		case 4:
 			if wireType != 2 {
-				return fmt.Errorf("proto: wrong wireType = %d for field HelmRepos", wireType)
+				return fmt.Errorf("proto: wrong wireType = %d for field Repos", wireType)
 			}
 			var msglen int
 			for shift := uint(0); ; shift += 7 {
@@ -3848,8 +3364,8 @@ func (m *RepoServerAppDetailsQuery) Unmarshal(dAtA []byte) error {
 			if postIndex > l {
 				return io.ErrUnexpectedEOF
 			}
-			m.HelmRepos = append(m.HelmRepos, &v1alpha1.HelmRepository{})
-			if err := m.HelmRepos[len(m.HelmRepos)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+			m.Repos = append(m.Repos, &v1alpha1.Repository{})
+			if err := m.Repos[len(m.Repos)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
 				return err
 			}
 			iNdEx = postIndex
@@ -4440,6 +3956,35 @@ func (m *RepoServerRevisionMetadataRequest) Unmarshal(dAtA []byte) error {
 			}
 			iNdEx = postIndex
 		case 2:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field App", wireType)
+			}
+			var stringLen uint64
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowRepository
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				stringLen |= (uint64(b) & 0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			intStringLen := int(stringLen)
+			if intStringLen < 0 {
+				return ErrInvalidLengthRepository
+			}
+			postIndex := iNdEx + intStringLen
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.App = string(dAtA[iNdEx:postIndex])
+			iNdEx = postIndex
+		case 3:
 			if wireType != 2 {
 				return fmt.Errorf("proto: wrong wireType = %d for field Revision", wireType)
 			}
@@ -4548,35 +4093,6 @@ func (m *KsonnetAppSpec) Unmarshal(dAtA []byte) error {
 			}
 			m.Name = string(dAtA[iNdEx:postIndex])
 			iNdEx = postIndex
-		case 2:
-			if wireType != 2 {
-				return fmt.Errorf("proto: wrong wireType = %d for field Path", wireType)
-			}
-			var stringLen uint64
-			for shift := uint(0); ; shift += 7 {
-				if shift >= 64 {
-					return ErrIntOverflowRepository
-				}
-				if iNdEx >= l {
-					return io.ErrUnexpectedEOF
-				}
-				b := dAtA[iNdEx]
-				iNdEx++
-				stringLen |= (uint64(b) & 0x7F) << shift
-				if b < 0x80 {
-					break
-				}
-			}
-			intStringLen := int(stringLen)
-			if intStringLen < 0 {
-				return ErrInvalidLengthRepository
-			}
-			postIndex := iNdEx + intStringLen
-			if postIndex > l {
-				return io.ErrUnexpectedEOF
-			}
-			m.Path = string(dAtA[iNdEx:postIndex])
-			iNdEx = postIndex
 		case 3:
 			if wireType != 2 {
 				return fmt.Errorf("proto: wrong wireType = %d for field Environments", wireType)
@@ -4811,35 +4327,6 @@ func (m *HelmAppSpec) Unmarshal(dAtA []byte) error {
 			}
 			m.Name = string(dAtA[iNdEx:postIndex])
 			iNdEx = postIndex
-		case 2:
-			if wireType != 2 {
-				return fmt.Errorf("proto: wrong wireType = %d for field Path", wireType)
-			}
-			var stringLen uint64
-			for shift := uint(0); ; shift += 7 {
-				if shift >= 64 {
-					return ErrIntOverflowRepository
-				}
-				if iNdEx >= l {
-					return io.ErrUnexpectedEOF
-				}
-				b := dAtA[iNdEx]
-				iNdEx++
-				stringLen |= (uint64(b) & 0x7F) << shift
-				if b < 0x80 {
-					break
-				}
-			}
-			intStringLen := int(stringLen)
-			if intStringLen < 0 {
-				return ErrInvalidLengthRepository
-			}
-			postIndex := iNdEx + intStringLen
-			if postIndex > l {
-				return io.ErrUnexpectedEOF
-			}
-			m.Path = string(dAtA[iNdEx:postIndex])
-			iNdEx = postIndex
 		case 3:
 			if wireType != 2 {
 				return fmt.Errorf("proto: wrong wireType = %d for field ValueFiles", wireType)
@@ -4980,35 +4467,6 @@ func (m *KustomizeAppSpec) Unmarshal(dAtA []byte) error {
 			return fmt.Errorf("proto: KustomizeAppSpec: illegal tag %d (wire type %d)", fieldNum, wire)
 		}
 		switch fieldNum {
-		case 1:
-			if wireType != 2 {
-				return fmt.Errorf("proto: wrong wireType = %d for field Path", wireType)
-			}
-			var stringLen uint64
-			for shift := uint(0); ; shift += 7 {
-				if shift >= 64 {
-					return ErrIntOverflowRepository
-				}
-				if iNdEx >= l {
-					return io.ErrUnexpectedEOF
-				}
-				b := dAtA[iNdEx]
-				iNdEx++
-				stringLen |= (uint64(b) & 0x7F) << shift
-				if b < 0x80 {
-					break
-				}
-			}
-			intStringLen := int(stringLen)
-			if intStringLen < 0 {
-				return ErrInvalidLengthRepository
-			}
-			postIndex := iNdEx + intStringLen
-			if postIndex > l {
-				return io.ErrUnexpectedEOF
-			}
-			m.Path = string(dAtA[iNdEx:postIndex])
-			iNdEx = postIndex
 		case 3:
 			if wireType != 2 {
 				return fmt.Errorf("proto: wrong wireType = %d for field Images", wireType)
@@ -5147,35 +4605,6 @@ func (m *KsonnetEnvironment) Unmarshal(dAtA []byte) error {
 			}
 			m.K8SVersion = string(dAtA[iNdEx:postIndex])
 			iNdEx = postIndex
-		case 3:
-			if wireType != 2 {
-				return fmt.Errorf("proto: wrong wireType = %d for field Path", wireType)
-			}
-			var stringLen uint64
-			for shift := uint(0); ; shift += 7 {
-				if shift >= 64 {
-					return ErrIntOverflowRepository
-				}
-				if iNdEx >= l {
-					return io.ErrUnexpectedEOF
-				}
-				b := dAtA[iNdEx]
-				iNdEx++
-				stringLen |= (uint64(b) & 0x7F) << shift
-				if b < 0x80 {
-					break
-				}
-			}
-			intStringLen := int(stringLen)
-			if intStringLen < 0 {
-				return ErrInvalidLengthRepository
-			}
-			postIndex := iNdEx + intStringLen
-			if postIndex > l {
-				return io.ErrUnexpectedEOF
-			}
-			m.Path = string(dAtA[iNdEx:postIndex])
-			iNdEx = postIndex
 		case 4:
 			if wireType != 2 {
 				return fmt.Errorf("proto: wrong wireType = %d for field Destination", wireType)
@@ -5497,83 +4926,80 @@ var (
 )
 
 func init() {
-	proto.RegisterFile("reposerver/repository/repository.proto", fileDescriptor_repository_a040dcfbd17da920)
-}
-
-var fileDescriptor_repository_a040dcfbd17da920 = []byte{
-	// 1169 bytes of a gzipped FileDescriptorProto
-	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xcc, 0x57, 0xdd, 0x6e, 0x1b, 0xc5,
-	0x17, 0xcf, 0xda, 0x4e, 0x1c, 0x1f, 0x37, 0xad, 0x33, 0x8d, 0xf2, 0xdf, 0xbf, 0x1b, 0x8c, 0x59,
-	0x51, 0x14, 0x04, 0x5d, 0xd3, 0xb4, 0x48, 0x51, 0x04, 0x95, 0x4a, 0x13, 0xd2, 0xca, 0x89, 0x9a,
-	0x6e, 0xa0, 0x12, 0x08, 0xa9, 0x9a, 0xac, 0x4f, 0xd7, 0x83, 0xed, 0xdd, 0x65, 0x77, 0x6c, 0xe4,
-	0xbe, 0x00, 0x0f, 0xc0, 0x1d, 0xdc, 0x71, 0xc7, 0x9b, 0x70, 0x89, 0xc4, 0x05, 0xdc, 0x20, 0xa1,
-	0x5c, 0xf1, 0x18, 0x68, 0xc6, 0xfb, 0x31, 0xbb, 0xde, 0x44, 0x48, 0x16, 0x6d, 0x6f, 0x56, 0x33,
-	0x67, 0xce, 0xc7, 0x9c, 0xaf, 0xdf, 0x9c, 0x85, 0x77, 0x02, 0xf4, 0xbd, 0x10, 0x83, 0x09, 0x06,
-	0x1d, 0xb9, 0x64, 0xdc, 0x0b, 0xa6, 0xca, 0xd2, 0xf4, 0x03, 0x8f, 0x7b, 0x04, 0x52, 0x4a, 0x73,
-	0xc3, 0xf1, 0x1c, 0x4f, 0x92, 0x3b, 0x62, 0x35, 0xe3, 0x68, 0x6e, 0x39, 0x9e, 0xe7, 0x0c, 0xb1,
-	0x43, 0x7d, 0xd6, 0xa1, 0xae, 0xeb, 0x71, 0xca, 0x99, 0xe7, 0x86, 0xd1, 0xa9, 0x31, 0xd8, 0x0d,
-	0x4d, 0xe6, 0xc9, 0x53, 0xdb, 0x0b, 0xb0, 0x33, 0xb9, 0xdd, 0x71, 0xd0, 0xc5, 0x80, 0x72, 0xec,
-	0x45, 0x3c, 0x8f, 0x1c, 0xc6, 0xfb, 0xe3, 0x33, 0xd3, 0xf6, 0x46, 0x1d, 0x1a, 0x48, 0x13, 0x5f,
-	0xcb, 0xc5, 0x2d, 0xbb, 0xd7, 0xf1, 0x07, 0x8e, 0x10, 0x0e, 0x3b, 0xd4, 0xf7, 0x87, 0xcc, 0x96,
-	0xca, 0x3b, 0x93, 0xdb, 0x74, 0xe8, 0xf7, 0xe9, 0x9c, 0x2a, 0xe3, 0xb7, 0x65, 0xb8, 0x76, 0x4c,
-	0x5d, 0xf6, 0x1c, 0x43, 0x6e, 0xe1, 0x37, 0x63, 0x0c, 0x39, 0xf9, 0x02, 0x2a, 0xc2, 0x09, 0x5d,
-	0x6b, 0x6b, 0xdb, 0xf5, 0x9d, 0x03, 0x33, 0xb5, 0x66, 0xc6, 0xd6, 0xe4, 0xe2, 0x99, 0xdd, 0x33,
-	0xfd, 0x81, 0x63, 0x0a, 0x6b, 0xa6, 0x62, 0xcd, 0x8c, 0xad, 0x99, 0x56, 0x12, 0x0b, 0x4b, 0xaa,
-	0x24, 0x4d, 0x58, 0x0d, 0x70, 0xc2, 0x42, 0xe6, 0xb9, 0x7a, 0xa9, 0xad, 0x6d, 0xd7, 0xac, 0x64,
-	0x4f, 0x74, 0xa8, 0xba, 0xde, 0x03, 0x6a, 0xf7, 0x51, 0x2f, 0xb7, 0xb5, 0xed, 0x55, 0x2b, 0xde,
-	0x92, 0x36, 0xd4, 0xa9, 0xef, 0x1f, 0xd1, 0x33, 0x1c, 0x76, 0x71, 0xaa, 0x57, 0xa4, 0xa0, 0x4a,
-	0x22, 0x6f, 0xc3, 0x5a, 0xbc, 0x7d, 0x4a, 0x87, 0x63, 0xd4, 0x97, 0x25, 0x4f, 0x96, 0x48, 0xb6,
-	0xa0, 0xe6, 0xd2, 0x11, 0x86, 0x3e, 0xb5, 0x51, 0x5f, 0x95, 0x1c, 0x29, 0x81, 0xbc, 0x80, 0x75,
-	0xc5, 0x89, 0x53, 0x6f, 0x1c, 0xd8, 0xa8, 0x83, 0x8c, 0xc1, 0xd1, 0x02, 0x31, 0xb8, 0x9f, 0xd7,
-	0x69, 0xcd, 0x9b, 0x21, 0x0e, 0xd4, 0xfa, 0x38, 0x1c, 0xc9, 0x78, 0xe9, 0xf5, 0x76, 0x79, 0xbb,
-	0xbe, 0xf3, 0x68, 0x01, 0x9b, 0x0f, 0x63, 0x5d, 0xb3, 0xd8, 0xa7, 0xba, 0xc9, 0x00, 0xaa, 0xfe,
-	0x70, 0xec, 0x30, 0x37, 0xd4, 0xaf, 0x48, 0x33, 0x4f, 0x16, 0x30, 0xf3, 0xc0, 0x73, 0x9f, 0x33,
-	0xe7, 0x98, 0xba, 0xd4, 0xc1, 0x11, 0xba, 0xfc, 0x44, 0x6a, 0xb6, 0x62, 0x0b, 0xe4, 0x5b, 0x68,
-	0x0c, 0xc6, 0x21, 0xf7, 0x46, 0xec, 0x05, 0x3e, 0xf6, 0x65, 0x95, 0xeb, 0x6b, 0x32, 0xa0, 0xdd,
-	0x05, 0xac, 0x76, 0x73, 0x2a, 0xad, 0x39, 0x23, 0xc6, 0x4f, 0x1a, 0x34, 0xd2, 0xaa, 0x0e, 0x7d,
-	0xcf, 0x0d, 0x65, 0xf6, 0x47, 0x11, 0x2d, 0xd4, 0xb5, 0x76, 0x59, 0x64, 0x3f, 0x21, 0x64, 0x6b,
-	0xa3, 0x94, 0xaf, 0x8d, 0x4d, 0x58, 0x99, 0xf5, 0xbe, 0x2c, 0xcd, 0x9a, 0x15, 0xed, 0x32, 0xf5,
-	0x5c, 0xc9, 0xd5, 0x73, 0x0b, 0x20, 0x94, 0xd9, 0xfd, 0x6c, 0xea, 0xa3, 0xbe, 0x22, 0x4f, 0x15,
-	0x8a, 0xf1, 0xa3, 0x06, 0x57, 0x8f, 0x58, 0xc8, 0xf7, 0x59, 0xf0, 0x8a, 0x3b, 0x8f, 0x40, 0xc5,
-	0xa7, 0xbc, 0x1f, 0xf9, 0x26, 0xd7, 0x46, 0x1b, 0x56, 0x3f, 0x65, 0x43, 0x14, 0x17, 0x24, 0x1b,
-	0xb0, 0xcc, 0x38, 0x8e, 0xe2, 0xa8, 0xcd, 0x36, 0xf2, 0xfe, 0x87, 0xc8, 0x05, 0xd7, 0x6b, 0x78,
-	0xff, 0x9b, 0x70, 0x2d, 0xb9, 0x5c, 0x54, 0x00, 0x04, 0x2a, 0x3d, 0xca, 0xa9, 0xbc, 0xdd, 0x15,
-	0x4b, 0xae, 0x8d, 0xbf, 0x2b, 0xf0, 0x7f, 0x61, 0xeb, 0x54, 0xe6, 0xf3, 0xbe, 0xef, 0xef, 0x23,
-	0xa7, 0x6c, 0x18, 0x3e, 0x19, 0x63, 0x30, 0x7d, 0x8d, 0xfc, 0xc9, 0x22, 0x44, 0xe5, 0xe5, 0x20,
-	0xc4, 0xf2, 0x7f, 0x8e, 0x10, 0x77, 0xa0, 0x22, 0x2c, 0xcb, 0xee, 0xa8, 0xef, 0xbc, 0x69, 0x2a,
-	0xcf, 0xa9, 0xb8, 0x61, 0x2e, 0x1f, 0x96, 0x64, 0x26, 0x1f, 0x41, 0x75, 0x10, 0x7a, 0xae, 0x8b,
-	0x5c, 0xaf, 0x4a, 0x39, 0x43, 0x95, 0xeb, 0xce, 0x8e, 0xf2, 0xa2, 0xb1, 0x48, 0x21, 0x28, 0xad,
-	0xbe, 0x0c, 0x50, 0xfa, 0x10, 0xae, 0x17, 0xf8, 0x24, 0x60, 0x62, 0x22, 0x5e, 0x27, 0x51, 0xaa,
-	0x71, 0x87, 0x29, 0x14, 0x63, 0x0f, 0x36, 0x8b, 0x5d, 0x12, 0xcf, 0x22, 0xba, 0x13, 0x16, 0x78,
-	0xae, 0x08, 0xad, 0x2c, 0xd2, 0x9a, 0xa5, 0x92, 0x8c, 0xef, 0x4a, 0xb0, 0x29, 0xb2, 0x9a, 0x4a,
-	0xaa, 0xcd, 0xc0, 0x05, 0x2e, 0xcd, 0xa4, 0xe4, 0x9a, 0xdc, 0x4d, 0x03, 0x5b, 0x92, 0x11, 0x69,
-	0x16, 0x07, 0xf6, 0xd4, 0x47, 0x3b, 0x0d, 0xe8, 0x7b, 0x51, 0x0e, 0xcb, 0x52, 0xe4, 0x7f, 0x05,
-	0x39, 0x94, 0xfc, 0xb3, 0xdc, 0xed, 0x41, 0x2d, 0x09, 0x8c, 0x44, 0xcc, 0xfa, 0xce, 0x56, 0xc6,
-	0x48, 0x7c, 0x18, 0x8b, 0xa5, 0xec, 0x42, 0xb6, 0xc7, 0x02, 0xb4, 0x05, 0xa3, 0x7c, 0xe0, 0x73,
-	0xb2, 0xfb, 0xf1, 0x61, 0x22, 0x9b, 0xb0, 0x1b, 0x3f, 0x68, 0xf0, 0x56, 0xda, 0xe7, 0x56, 0xd4,
-	0x69, 0xc7, 0xc8, 0xa9, 0x80, 0x81, 0x57, 0x8b, 0x5f, 0xc6, 0x1f, 0x25, 0xb8, 0x9a, 0x8d, 0xae,
-	0x48, 0x8f, 0x78, 0x7d, 0xe2, 0xf4, 0x88, 0x75, 0x02, 0x0b, 0x25, 0x05, 0x16, 0x4e, 0xe0, 0x8a,
-	0x92, 0xf0, 0x50, 0x2f, 0xcb, 0x96, 0x7d, 0xff, 0xe2, 0xbc, 0x99, 0x07, 0x0a, 0xfb, 0x81, 0xcb,
-	0x83, 0xa9, 0x95, 0xd1, 0x40, 0x06, 0x00, 0x3e, 0x0d, 0xe8, 0x08, 0x39, 0x06, 0x31, 0xd2, 0x2c,
-	0xd4, 0x19, 0x33, 0xf3, 0x27, 0xb1, 0x4e, 0x4b, 0x51, 0xdf, 0x7c, 0x06, 0xeb, 0x73, 0xf7, 0x21,
-	0x0d, 0x28, 0x0f, 0x70, 0x1a, 0xb9, 0x2e, 0x96, 0xe4, 0x2e, 0x2c, 0xcb, 0x8e, 0x88, 0xca, 0xb2,
-	0x55, 0xe0, 0x9e, 0xa2, 0xc6, 0x9a, 0x31, 0xef, 0x95, 0x76, 0x35, 0xe3, 0x77, 0x0d, 0xea, 0x4a,
-	0x15, 0xfe, 0xeb, 0xb8, 0x66, 0xbb, 0xb2, 0x9c, 0xef, 0x4a, 0xd2, 0x2f, 0x88, 0xd2, 0xc3, 0x05,
-	0xf1, 0xb8, 0x30, 0x44, 0x62, 0xf4, 0x90, 0x76, 0xc3, 0x68, 0xa6, 0x8d, 0x76, 0xc6, 0x3d, 0x68,
-	0xe4, 0x9b, 0x25, 0xf1, 0x44, 0x53, 0x3c, 0xd9, 0x84, 0x15, 0x36, 0xa2, 0x4e, 0xe2, 0x45, 0xb4,
-	0x33, 0x7e, 0xd6, 0x80, 0xcc, 0xc7, 0xae, 0x30, 0x40, 0x2d, 0x80, 0xc1, 0x6e, 0xf8, 0x14, 0x03,
-	0xa5, 0x7a, 0x15, 0x4a, 0xe1, 0x7b, 0xd5, 0x85, 0x7a, 0x0f, 0x43, 0xce, 0x5c, 0xe9, 0x68, 0xd4,
-	0xea, 0xef, 0x5e, 0x9e, 0xb8, 0xfd, 0x54, 0xc0, 0x52, 0xa5, 0x8d, 0xcf, 0xe1, 0x8d, 0x4b, 0xb9,
-	0x95, 0xf9, 0x4c, 0xcb, 0xcc, 0x67, 0x97, 0x4e, 0x75, 0x06, 0x81, 0x46, 0x1e, 0x33, 0x76, 0xfe,
-	0x2c, 0xc3, 0x7a, 0x0a, 0x14, 0xe2, 0xcb, 0x6c, 0x24, 0x8f, 0xa1, 0x71, 0x18, 0xfd, 0x39, 0xc5,
-	0x73, 0x25, 0xb9, 0xa1, 0x3a, 0x93, 0xfb, 0x87, 0x6a, 0x6e, 0x15, 0x1f, 0xce, 0xc0, 0xd7, 0x58,
-	0x22, 0x1f, 0x43, 0x35, 0x9a, 0xfd, 0x48, 0x06, 0x64, 0xb3, 0x03, 0x61, 0x73, 0x43, 0x3d, 0x8b,
-	0xe7, 0x31, 0x63, 0x89, 0xec, 0x43, 0x35, 0x9a, 0x6e, 0xb2, 0xe2, 0xd9, 0x79, 0xac, 0x79, 0xa3,
-	0xf0, 0x2c, 0xb9, 0xc4, 0x57, 0xb0, 0x76, 0xa8, 0x3e, 0x2b, 0xe4, 0xa6, 0xca, 0x7f, 0xe1, 0x58,
-	0xd4, 0x34, 0xf2, 0x6c, 0xf3, 0xef, 0x8b, 0xb1, 0x44, 0xbe, 0xd7, 0xe0, 0xfa, 0x21, 0xf2, 0x3c,
-	0xd6, 0x92, 0x5b, 0xc5, 0x46, 0x2e, 0xc0, 0xe4, 0x66, 0x77, 0x21, 0x14, 0xce, 0xea, 0x34, 0x96,
-	0x3e, 0xb9, 0xf7, 0xcb, 0x79, 0x4b, 0xfb, 0xf5, 0xbc, 0xa5, 0xfd, 0x75, 0xde, 0xd2, 0xbe, 0xfc,
-	0xe0, 0xb2, 0x3f, 0x69, 0xe5, 0x8f, 0x9f, 0xfa, 0xcc, 0x1e, 0x32, 0x74, 0xf9, 0xd9, 0x8a, 0xfc,
-	0x6f, 0xbe, 0xf3, 0x4f, 0x00, 0x00, 0x00, 0xff, 0xff, 0x08, 0x6a, 0xff, 0x4a, 0x10, 0x10, 0x00,
-	0x00,
+	proto.RegisterFile("reposerver/repository/repository.proto", fileDescriptor_repository_3f0884c8b644d045)
+}
+
+var fileDescriptor_repository_3f0884c8b644d045 = []byte{
+	// 1134 bytes of a gzipped FileDescriptorProto
+	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xc4, 0x57, 0x5b, 0x6f, 0x23, 0x35,
+	0x14, 0xee, 0x24, 0xe9, 0x25, 0x27, 0x5b, 0x36, 0x75, 0x57, 0x65, 0x08, 0xdd, 0x12, 0x46, 0x80,
+	0xca, 0x65, 0x27, 0x34, 0xbb, 0x88, 0xaa, 0x42, 0x2b, 0x95, 0x6d, 0xe9, 0xa2, 0xb4, 0xda, 0xee,
+	0x14, 0x56, 0xe2, 0x22, 0xad, 0xdc, 0x89, 0x77, 0x6a, 0x92, 0x8c, 0xcd, 0xd8, 0x09, 0xea, 0xfe,
+	0x01, 0x78, 0x47, 0x48, 0x3c, 0xf3, 0xcc, 0xbf, 0x00, 0x09, 0x1e, 0x79, 0xe6, 0x09, 0xf5, 0x97,
+	0x20, 0x7b, 0x66, 0x32, 0xce, 0x64, 0xda, 0x97, 0xec, 0xe5, 0x25, 0xb1, 0x8f, 0xcf, 0xc5, 0x3e,
+	0xe7, 0x7c, 0xdf, 0xd8, 0xf0, 0x4e, 0x44, 0x38, 0x13, 0x24, 0x1a, 0x91, 0xa8, 0xa5, 0x87, 0x54,
+	0xb2, 0xe8, 0xdc, 0x18, 0xba, 0x3c, 0x62, 0x92, 0x21, 0xc8, 0x24, 0x8d, 0x1b, 0x01, 0x0b, 0x98,
+	0x16, 0xb7, 0xd4, 0x28, 0xd6, 0x68, 0xac, 0x07, 0x8c, 0x05, 0x7d, 0xd2, 0xc2, 0x9c, 0xb6, 0x70,
+	0x18, 0x32, 0x89, 0x25, 0x65, 0xa1, 0x48, 0x56, 0x9d, 0xde, 0xb6, 0x70, 0x29, 0xd3, 0xab, 0x3e,
+	0x8b, 0x48, 0x6b, 0xb4, 0xd5, 0x0a, 0x48, 0x48, 0x22, 0x2c, 0x49, 0x37, 0xd1, 0xf9, 0x3c, 0xa0,
+	0xf2, 0x6c, 0x78, 0xea, 0xfa, 0x6c, 0xd0, 0xc2, 0x91, 0x0e, 0xf1, 0x9d, 0x1e, 0xdc, 0xf2, 0xbb,
+	0x2d, 0xde, 0x0b, 0x94, 0xb1, 0x68, 0x61, 0xce, 0xfb, 0xd4, 0xd7, 0xce, 0x5b, 0xa3, 0x2d, 0xdc,
+	0xe7, 0x67, 0x78, 0xca, 0x95, 0xf3, 0xd7, 0x3c, 0x5c, 0x3f, 0xc2, 0x21, 0x7d, 0x42, 0x84, 0xf4,
+	0xc8, 0xf7, 0x43, 0x22, 0x24, 0xfa, 0x0a, 0x2a, 0xea, 0x10, 0xb6, 0xd5, 0xb4, 0x36, 0x6b, 0xed,
+	0x7d, 0x37, 0x8b, 0xe6, 0xa6, 0xd1, 0xf4, 0xe0, 0xb1, 0xdf, 0x75, 0x79, 0x2f, 0x70, 0x55, 0x34,
+	0xd7, 0x88, 0xe6, 0xa6, 0xd1, 0x5c, 0x6f, 0x9c, 0x0b, 0x4f, 0xbb, 0x44, 0x0d, 0x58, 0x8a, 0xc8,
+	0x88, 0x0a, 0xca, 0x42, 0xbb, 0xd4, 0xb4, 0x36, 0xab, 0xde, 0x78, 0x8e, 0x6c, 0x58, 0x0c, 0xd9,
+	0x3d, 0xec, 0x9f, 0x11, 0xbb, 0xdc, 0xb4, 0x36, 0x97, 0xbc, 0x74, 0x8a, 0x9a, 0x50, 0xc3, 0x9c,
+	0x1f, 0xe2, 0x53, 0xd2, 0xef, 0x90, 0x73, 0xbb, 0xa2, 0x0d, 0x4d, 0x11, 0x7a, 0x0b, 0x96, 0xd3,
+	0xe9, 0x23, 0xdc, 0x1f, 0x12, 0x7b, 0x5e, 0xeb, 0x4c, 0x0a, 0xd1, 0x3a, 0x54, 0x43, 0x3c, 0x20,
+	0x82, 0x63, 0x9f, 0xd8, 0x4b, 0x5a, 0x23, 0x13, 0xa0, 0xa7, 0xb0, 0x62, 0x1c, 0xe2, 0x84, 0x0d,
+	0x23, 0x9f, 0xd8, 0xa0, 0x73, 0x70, 0x38, 0x43, 0x0e, 0x76, 0xf3, 0x3e, 0xbd, 0xe9, 0x30, 0xe8,
+	0x1b, 0x98, 0xd7, 0x7d, 0x63, 0xd7, 0x9a, 0xe5, 0x67, 0x97, 0xf3, 0xd8, 0x27, 0xea, 0xc1, 0x22,
+	0xef, 0x0f, 0x03, 0x1a, 0x0a, 0xfb, 0x9a, 0x76, 0xff, 0x70, 0x06, 0xf7, 0xf7, 0x58, 0xf8, 0x84,
+	0x06, 0x47, 0x38, 0xc4, 0x01, 0x19, 0x90, 0x50, 0x1e, 0x6b, 0xcf, 0x5e, 0x1a, 0x01, 0xfd, 0x00,
+	0xf5, 0xde, 0x50, 0x48, 0x36, 0xa0, 0x4f, 0xc9, 0x03, 0xae, 0x3b, 0xdb, 0x5e, 0xd6, 0x49, 0xec,
+	0xcc, 0x10, 0xb5, 0x93, 0x73, 0xe9, 0x4d, 0x05, 0x71, 0x7e, 0xb3, 0xa0, 0x9e, 0x75, 0xb2, 0xe0,
+	0x2c, 0x14, 0xba, 0xe2, 0x83, 0x44, 0x26, 0x6c, 0xab, 0x59, 0x56, 0x15, 0x1f, 0x0b, 0x26, 0xfb,
+	0xa1, 0x94, 0xef, 0x87, 0x35, 0x58, 0x88, 0xf1, 0xae, 0xdb, 0xb1, 0xea, 0x25, 0xb3, 0x89, 0x1e,
+	0xae, 0xe4, 0x7a, 0x78, 0x03, 0x40, 0xe8, 0x8a, 0x7e, 0x71, 0xce, 0x89, 0xbd, 0xa0, 0x57, 0x0d,
+	0x89, 0xf3, 0x93, 0x05, 0xd7, 0x0f, 0xa9, 0x90, 0xbb, 0x9c, 0x8b, 0x97, 0x0b, 0x37, 0x67, 0x08,
+	0x8b, 0xbb, 0x9c, 0xab, 0xcd, 0xa0, 0x2d, 0xa8, 0x60, 0xce, 0xe3, 0x04, 0xd5, 0xda, 0x37, 0x5d,
+	0x83, 0xd4, 0x12, 0x15, 0xf5, 0x2f, 0xf6, 0x43, 0xa9, 0x3c, 0x2b, 0xd5, 0xc6, 0xc7, 0x50, 0x1d,
+	0x8b, 0x50, 0x1d, 0xca, 0x3d, 0x72, 0xae, 0x0f, 0x50, 0xf5, 0xd4, 0x10, 0xdd, 0x80, 0xf9, 0x91,
+	0xc6, 0x61, 0x1c, 0x35, 0x9e, 0xec, 0x94, 0xb6, 0x2d, 0xe7, 0xdf, 0x0a, 0xbc, 0xa6, 0xf6, 0x79,
+	0xa2, 0x93, 0xb9, 0xcb, 0xf9, 0x1e, 0x91, 0x98, 0xf6, 0xc5, 0xc3, 0x21, 0x89, 0xce, 0x5f, 0x16,
+	0xf5, 0xd4, 0xa1, 0x8c, 0x39, 0x4f, 0xea, 0xac, 0x86, 0x19, 0x20, 0x2b, 0xcf, 0x17, 0x90, 0xf3,
+	0xcf, 0x1d, 0x90, 0xb7, 0xa1, 0x72, 0x46, 0xfa, 0x03, 0xdd, 0x8c, 0xb5, 0xf6, 0x1b, 0x66, 0x71,
+	0xef, 0x93, 0xfe, 0x20, 0x57, 0x01, 0x4f, 0x2b, 0xa3, 0x4f, 0x60, 0xb1, 0x27, 0x58, 0x18, 0x12,
+	0x69, 0x2f, 0x6a, 0x3b, 0xc7, 0xb4, 0xeb, 0xc4, 0x4b, 0x79, 0xd3, 0xd4, 0xa4, 0x90, 0x03, 0x96,
+	0x5e, 0x04, 0x07, 0x7c, 0x04, 0xab, 0x05, 0x67, 0x52, 0xa8, 0xd4, 0x0d, 0xf8, 0x19, 0xed, 0x93,
+	0x94, 0x06, 0x0c, 0x89, 0xb3, 0x03, 0x6b, 0xc5, 0x47, 0x52, 0x5f, 0x1e, 0x12, 0x8e, 0x68, 0xc4,
+	0x42, 0x95, 0xda, 0xa4, 0xc3, 0x4d, 0x91, 0xf3, 0x63, 0x09, 0xd6, 0x54, 0x85, 0x33, 0xcb, 0x31,
+	0xf9, 0x20, 0xa8, 0x48, 0x45, 0x03, 0xb1, 0x95, 0x1e, 0xa3, 0x3b, 0x59, 0x62, 0x4b, 0x3a, 0x23,
+	0x8d, 0xe2, 0xc4, 0x9e, 0x70, 0xe2, 0x67, 0x09, 0x7d, 0x3f, 0xa9, 0x61, 0x59, 0x9b, 0xbc, 0x5a,
+	0x50, 0x43, 0xad, 0x1f, 0xd7, 0x6e, 0x07, 0xaa, 0xe3, 0xc4, 0x68, 0x82, 0xaa, 0xb5, 0xd7, 0x27,
+	0x82, 0xa4, 0x8b, 0xa9, 0x59, 0xa6, 0xae, 0x6c, 0xbb, 0x34, 0x22, 0xbe, 0x52, 0xd4, 0xdf, 0xd0,
+	0x9c, 0xed, 0x5e, 0xba, 0x38, 0xb6, 0x1d, 0xab, 0x3b, 0xbf, 0x5b, 0xf0, 0x66, 0x86, 0x6c, 0x2f,
+	0xc1, 0xd6, 0x11, 0x91, 0xb8, 0x8b, 0x25, 0x7e, 0x01, 0x6c, 0x97, 0xa0, 0xb8, 0x94, 0xa1, 0xd8,
+	0xc4, 0x7c, 0x39, 0xc7, 0x7f, 0x7f, 0x96, 0xe0, 0x95, 0xc9, 0x7c, 0xab, 0x82, 0x29, 0xfa, 0x4f,
+	0x0b, 0xa6, 0xc6, 0xe8, 0x18, 0xae, 0x19, 0xe5, 0x16, 0x76, 0x59, 0x03, 0xf6, 0x83, 0xcb, 0xab,
+	0xe6, 0xee, 0x1b, 0xea, 0x31, 0x65, 0x4e, 0x78, 0x40, 0x3d, 0x00, 0x8e, 0x23, 0x3c, 0x20, 0x92,
+	0x44, 0x29, 0xbf, 0xcc, 0x84, 0x8b, 0x38, 0xfc, 0x71, 0xea, 0xd3, 0x33, 0xdc, 0x37, 0x1e, 0xc3,
+	0xca, 0xd4, 0x7e, 0x0a, 0xf8, 0xfa, 0x8e, 0xc9, 0xd7, 0xb5, 0xf6, 0x46, 0xc1, 0xf1, 0x0c, 0x37,
+	0x26, 0x9f, 0xff, 0x61, 0x41, 0xcd, 0xe8, 0xc1, 0xc2, 0x1c, 0x4e, 0xe2, 0xaf, 0x9c, 0xc7, 0x1f,
+	0x3a, 0x2b, 0xc8, 0xc8, 0xfd, 0x19, 0x32, 0xa2, 0xf6, 0x53, 0x98, 0x0e, 0xf5, 0x4d, 0xd7, 0x71,
+	0x45, 0x72, 0x41, 0x4c, 0x66, 0xce, 0x7b, 0x50, 0xcf, 0xc3, 0x42, 0xe9, 0xd2, 0x01, 0x0e, 0xc6,
+	0x3b, 0x4e, 0x66, 0xce, 0x2f, 0x16, 0xa0, 0xe9, 0x9c, 0x5c, 0x76, 0xf0, 0xde, 0xb6, 0x78, 0x44,
+	0x22, 0xe3, 0xab, 0x63, 0x48, 0x50, 0x07, 0x6a, 0x5d, 0x22, 0x24, 0x0d, 0xf5, 0x01, 0x12, 0xb0,
+	0xbe, 0x7b, 0x75, 0xf2, 0xf7, 0x32, 0x03, 0xcf, 0xb4, 0x76, 0xbe, 0x84, 0x9b, 0x57, 0x6a, 0x1b,
+	0x17, 0x1a, 0x6b, 0xe2, 0x42, 0x73, 0xe5, 0x35, 0xc8, 0x41, 0x50, 0xcf, 0xa3, 0xbe, 0xfd, 0x6b,
+	0x19, 0x56, 0x32, 0xa8, 0xab, 0x5f, 0xea, 0x13, 0xf4, 0x00, 0xea, 0x07, 0xc9, 0xf3, 0x22, 0xbd,
+	0x88, 0xa1, 0xd7, 0xcd, 0xc3, 0xe4, 0x1e, 0x1a, 0x8d, 0xf5, 0xe2, 0xc5, 0x98, 0x3e, 0x9d, 0x39,
+	0x74, 0x17, 0x96, 0xd2, 0xcb, 0xd2, 0xa4, 0xa3, 0xdc, 0x15, 0xaa, 0xb1, 0x5a, 0x70, 0x65, 0x71,
+	0xe6, 0xd0, 0xb7, 0xb0, 0x7c, 0x60, 0x72, 0x3a, 0x7a, 0xdb, 0xd4, 0xbb, 0xf4, 0x16, 0xd2, 0x70,
+	0xf2, 0x6a, 0xd3, 0xe4, 0xee, 0xcc, 0xa1, 0x9f, 0x2d, 0x58, 0x3d, 0x20, 0x32, 0x4f, 0x74, 0xe8,
+	0x56, 0x71, 0x90, 0x4b, 0x08, 0xb1, 0xd1, 0x99, 0x89, 0x02, 0x27, 0x7d, 0x3a, 0x73, 0x9f, 0xde,
+	0xfd, 0xfb, 0x62, 0xc3, 0xfa, 0xe7, 0x62, 0xc3, 0xfa, 0xef, 0x62, 0xc3, 0xfa, 0xfa, 0xc3, 0xab,
+	0x5e, 0x8a, 0xc6, 0x8b, 0x16, 0x73, 0xea, 0xf7, 0x29, 0x09, 0xe5, 0xe9, 0x82, 0x7e, 0x17, 0xde,
+	0xfe, 0x3f, 0x00, 0x00, 0xff, 0xff, 0xc7, 0xb3, 0x21, 0x7a, 0xf0, 0x0e, 0x00, 0x00,
 }
diff --git a/reposerver/metrics/gitwrapper.go b/reposerver/metrics/gitwrapper.go
deleted file mode 100644
index f83593f58d855..0000000000000
--- a/reposerver/metrics/gitwrapper.go
+++ /dev/null
@@ -1,55 +0,0 @@
-package metrics
-
-import "github.com/argoproj/argo-cd/util/git"
-
-type gitClientWrapper struct {
-	repo          string
-	client        git.Client
-	metricsServer *MetricsServer
-}
-
-func wrapGitClient(repo string, metricsServer *MetricsServer, client git.Client) git.Client {
-	return &gitClientWrapper{repo: repo, client: client, metricsServer: metricsServer}
-}
-
-func (w *gitClientWrapper) Fetch() error {
-	w.metricsServer.IncGitRequest(w.repo, GitRequestTypeFetch)
-	return w.client.Fetch()
-}
-
-func (w *gitClientWrapper) LsRemote(revision string) (string, error) {
-	sha, err := w.client.LsRemote(revision)
-	if sha != revision {
-		// This is true only if specified revision is a tag, branch or HEAD and client had to use 'ls-remote'
-		w.metricsServer.IncGitRequest(w.repo, GitRequestTypeLsRemote)
-	}
-	return sha, err
-}
-
-func (w *gitClientWrapper) LsFiles(path string) ([]string, error) {
-	return w.client.LsFiles(path)
-}
-
-func (w *gitClientWrapper) LsLargeFiles() ([]string, error) {
-	return w.client.LsLargeFiles()
-}
-
-func (w *gitClientWrapper) Checkout(revision string) error {
-	return w.client.Checkout(revision)
-}
-
-func (w *gitClientWrapper) CommitSHA() (string, error) {
-	return w.client.CommitSHA()
-}
-
-func (w *gitClientWrapper) Root() string {
-	return w.client.Root()
-}
-
-func (w *gitClientWrapper) Init() error {
-	return w.client.Init()
-}
-
-func (w *gitClientWrapper) RevisionMetadata(revision string) (*git.RevisionMetadata, error) {
-	return w.client.RevisionMetadata(revision)
-}
diff --git a/reposerver/metrics/metrics.go b/reposerver/metrics/metrics.go
index 8269f71b99d96..ec02849a80bf2 100644
--- a/reposerver/metrics/metrics.go
+++ b/reposerver/metrics/metrics.go
@@ -3,16 +3,19 @@ package metrics
 import (
 	"net/http"
 
-	"github.com/argoproj/argo-cd/util/git"
-
 	"github.com/prometheus/client_golang/prometheus"
 	"github.com/prometheus/client_golang/prometheus/promhttp"
+
+	"github.com/argoproj/argo-cd/pkg/apis/application/v1alpha1"
+	"github.com/argoproj/argo-cd/util/repo"
+	"github.com/argoproj/argo-cd/util/repo/factory"
+	"github.com/argoproj/argo-cd/util/repo/metrics"
 )
 
 type MetricsServer struct {
 	handler           http.Handler
 	gitRequestCounter *prometheus.CounterVec
-	gitClientFactory  git.ClientFactory
+	factory           factory.Factory
 }
 
 type GitRequestType string
@@ -23,7 +26,7 @@ const (
 )
 
 // NewMetricsServer returns a new prometheus server which collects application metrics
-func NewMetricsServer(gitClientFactory git.ClientFactory) *MetricsServer {
+func NewMetricsServer(factory factory.Factory) *MetricsServer {
 	registry := prometheus.NewRegistry()
 	registry.MustRegister(prometheus.NewProcessCollector(prometheus.ProcessCollectorOpts{}))
 	registry.MustRegister(prometheus.NewGoCollector())
@@ -38,7 +41,7 @@ func NewMetricsServer(gitClientFactory git.ClientFactory) *MetricsServer {
 	registry.MustRegister(gitRequestCounter)
 
 	return &MetricsServer{
-		gitClientFactory:  gitClientFactory,
+		factory:           factory,
 		handler:           promhttp.HandlerFor(registry, promhttp.HandlerOpts{}),
 		gitRequestCounter: gitRequestCounter,
 	}
@@ -53,10 +56,15 @@ func (m *MetricsServer) IncGitRequest(repo string, requestType GitRequestType) {
 	m.gitRequestCounter.WithLabelValues(repo, string(requestType)).Inc()
 }
 
-func (m *MetricsServer) NewClient(repoURL string, path string, creds git.Creds, insecureIgnoreHostKey bool, lfsEnabled bool) (git.Client, error) {
-	client, err := m.gitClientFactory.NewClient(repoURL, path, creds, insecureIgnoreHostKey, lfsEnabled)
-	if err != nil {
-		return nil, err
+func (m *MetricsServer) Event(repo string, requestType string) {
+	switch requestType {
+	case "GitRequestTypeLsRemote":
+		m.IncGitRequest(repo, GitRequestTypeLsRemote)
+	case "GitRequestTypeFetch":
+		m.IncGitRequest(repo, GitRequestTypeFetch)
 	}
-	return wrapGitClient(repoURL, m, client), nil
+}
+
+func (m *MetricsServer) NewRepo(repo *v1alpha1.Repository, _ metrics.Reporter) (repo.Repo, error) {
+	return m.factory.NewRepo(repo, m)
 }
diff --git a/reposerver/metrics/metrics_test.go b/reposerver/metrics/metrics_test.go
new file mode 100644
index 0000000000000..243709b4c1697
--- /dev/null
+++ b/reposerver/metrics/metrics_test.go
@@ -0,0 +1,28 @@
+package metrics
+
+import (
+	"testing"
+
+	"github.com/stretchr/testify/assert"
+	"github.com/stretchr/testify/mock"
+
+	factorymocks "github.com/argoproj/argo-cd/util/repo/factory/mocks"
+	repomocks "github.com/argoproj/argo-cd/util/repo/mocks"
+)
+
+func TestNewMetricsServer(t *testing.T) {
+	factory := &factorymocks.Factory{}
+	repo := &repomocks.Repo{}
+	factory.On("NewRepo", mock.Anything, mock.Anything).Return(repo, nil)
+	server := NewMetricsServer(factory)
+	_, err := server.NewRepo(nil, nil)
+	assert.NoError(t, err)
+	server.Event("foo", "GitRequestTypeFetch")
+	counter, err := server.gitRequestCounter.GetMetricWithLabelValues("foo", "fetch")
+	assert.NoError(t, err)
+	assert.NotNil(t, counter)
+	server.Event("bar", "GitRequestTypeLsRemote")
+	counter, err = server.gitRequestCounter.GetMetricWithLabelValues("foo", "ls-remote")
+	assert.NoError(t, err)
+	assert.NotNil(t, counter)
+}
diff --git a/reposerver/repository/repository.go b/reposerver/repository/repository.go
index fae066b97d87d..ae35ef7be92e8 100644
--- a/reposerver/repository/repository.go
+++ b/reposerver/repository/repository.go
@@ -27,14 +27,18 @@ import (
 	"github.com/argoproj/argo-cd/pkg/apis/application/v1alpha1"
 	"github.com/argoproj/argo-cd/reposerver/apiclient"
 	"github.com/argoproj/argo-cd/util"
-	"github.com/argoproj/argo-cd/util/argo"
+	"github.com/argoproj/argo-cd/util/app/discovery"
 	"github.com/argoproj/argo-cd/util/cache"
 	"github.com/argoproj/argo-cd/util/config"
+	"github.com/argoproj/argo-cd/util/creds"
 	"github.com/argoproj/argo-cd/util/git"
 	"github.com/argoproj/argo-cd/util/helm"
 	"github.com/argoproj/argo-cd/util/ksonnet"
 	"github.com/argoproj/argo-cd/util/kube"
 	"github.com/argoproj/argo-cd/util/kustomize"
+	"github.com/argoproj/argo-cd/util/repo"
+	"github.com/argoproj/argo-cd/util/repo/factory"
+	"github.com/argoproj/argo-cd/util/repo/metrics"
 	"github.com/argoproj/argo-cd/util/text"
 )
 
@@ -46,105 +50,78 @@ const (
 // Service implements ManifestService interface
 type Service struct {
 	repoLock                  *util.KeyLock
-	gitFactory                git.ClientFactory
+	repoFactory               factory.Factory
 	cache                     *cache.Cache
 	parallelismLimitSemaphore *semaphore.Weighted
 }
 
 // NewService returns a new instance of the Manifest service
-func NewService(gitFactory git.ClientFactory, cache *cache.Cache, parallelismLimit int64) *Service {
+func NewService(repoFactory factory.Factory, cache *cache.Cache, parallelismLimit int64) *Service {
 	var parallelismLimitSemaphore *semaphore.Weighted
 	if parallelismLimit > 0 {
 		parallelismLimitSemaphore = semaphore.NewWeighted(parallelismLimit)
 	}
 	return &Service{
 		parallelismLimitSemaphore: parallelismLimitSemaphore,
-
-		repoLock:   util.NewKeyLock(),
-		gitFactory: gitFactory,
-		cache:      cache,
+		repoLock:                  util.NewKeyLock(),
+		repoFactory:               repoFactory,
+		cache:                     cache,
 	}
 }
 
 // ListDir lists the contents of a GitHub repo
-func (s *Service) ListDir(ctx context.Context, q *apiclient.ListDirRequest) (*apiclient.FileList, error) {
-	gitClient, commitSHA, err := s.newClientResolveRevision(q.Repo, q.Revision)
+func (s *Service) ListApps(ctx context.Context, q *apiclient.ListAppsRequest) (*apiclient.AppList, error) {
+	r, err := s.repoFactory.NewRepo(q.Repo, metrics.NopReporter)
 	if err != nil {
 		return nil, err
 	}
-	if files, err := s.cache.GetGitListDir(commitSHA, q.Path); err == nil {
-		log.Infof("listdir cache hit: %s/%s", commitSHA, q.Path)
-		return &apiclient.FileList{Items: files}, nil
-	}
-
-	s.repoLock.Lock(gitClient.Root())
-	defer s.repoLock.Unlock(gitClient.Root())
-	commitSHA, err = checkoutRevision(gitClient, commitSHA)
+	s.repoLock.Lock(r.LockKey())
+	defer s.repoLock.Unlock(r.LockKey())
+	err = r.Init()
 	if err != nil {
 		return nil, err
 	}
-
-	lsFiles, err := gitClient.LsFiles(q.Path)
+	if apps, err := s.cache.ListApps(q.Repo.Repo, q.Revision); err == nil {
+		log.Infof("cache hit: %s/%s", q.Repo.Repo, q.Revision)
+		return &apiclient.AppList{Apps: apps}, nil
+	}
+	apps, resolvedRevision, err := r.ListApps(q.Revision)
 	if err != nil {
 		return nil, err
 	}
 
-	res := apiclient.FileList{Items: lsFiles}
-	err = s.cache.SetListDir(commitSHA, q.Path, res.Items)
+	res := apiclient.AppList{Apps: apps}
+	err = s.cache.SetApps(q.Repo.Repo, q.Revision, apps)
 	if err != nil {
-		log.Warnf("listdir cache set error %s/%s: %v", commitSHA, q.Path, err)
+		log.Warnf("cache set error %s/%s: %v", q.Repo.Repo, resolvedRevision, err)
 	}
 	return &res, nil
 }
 
-func (s *Service) GetFile(ctx context.Context, q *apiclient.GetFileRequest) (*apiclient.GetFileResponse, error) {
-	gitClient, commitSHA, err := s.newClientResolveRevision(q.Repo, q.Revision)
-	if err != nil {
-		return nil, err
-	}
-
-	if data, err := s.cache.GetGitFile(commitSHA, q.Path); err == nil {
-		log.Infof("getfile cache hit: %s/%s", commitSHA, q.Path)
-		return &apiclient.GetFileResponse{Data: data}, nil
-	}
-
-	s.repoLock.Lock(gitClient.Root())
-	defer s.repoLock.Unlock(gitClient.Root())
-	commitSHA, err = checkoutRevision(gitClient, commitSHA)
+func (s *Service) GenerateManifest(c context.Context, q *apiclient.ManifestRequest) (*apiclient.ManifestResponse, error) {
+	r, err := s.repoFactory.NewRepo(q.Repo, metrics.NopReporter)
 	if err != nil {
 		return nil, err
 	}
-	data, err := ioutil.ReadFile(filepath.Join(gitClient.Root(), q.Path))
-	if err != nil {
-		return nil, err
-	}
-	res := apiclient.GetFileResponse{
-		Data: data,
-	}
-	err = s.cache.SetGitFile(commitSHA, q.Path, data)
-	if err != nil {
-		log.Warnf("getfile cache set error %s/%s: %v", commitSHA, q.Path, err)
-	}
-	return &res, nil
-}
-
-func (s *Service) GenerateManifest(c context.Context, q *apiclient.ManifestRequest) (*apiclient.ManifestResponse, error) {
-	gitClient, commitSHA, err := s.newClientResolveRevision(q.Repo, q.Revision)
+	s.repoLock.Lock(r.LockKey())
+	defer s.repoLock.Unlock(r.LockKey())
+	err = r.Init()
 	if err != nil {
 		return nil, err
 	}
+	resolvedRevision, err := r.ResolveRevision(q.ApplicationSource.Path, q.Revision)
 	getCached := func() *apiclient.ManifestResponse {
 		var res apiclient.ManifestResponse
 		if !q.NoCache {
-			err = s.cache.GetManifests(commitSHA, q.ApplicationSource, q.Namespace, q.AppLabelKey, q.AppLabelValue, &res)
+			err = s.cache.GetManifests(resolvedRevision, q.ApplicationSource, q.Namespace, q.AppLabelKey, q.AppLabelValue, &res)
 			if err == nil {
-				log.Infof("manifest cache hit: %s/%s", q.ApplicationSource.String(), commitSHA)
+				log.Infof("manifest cache hit: %s/%s", q.ApplicationSource.String(), resolvedRevision)
 				return &res
 			}
 			if err != cache.ErrCacheMiss {
 				log.Warnf("manifest cache error %s: %v", q.ApplicationSource.String(), err)
 			} else {
-				log.Infof("manifest cache miss: %s/%s", q.ApplicationSource.String(), commitSHA)
+				log.Infof("manifest cache miss: %s/%s", q.ApplicationSource.String(), resolvedRevision)
 			}
 		}
 		return nil
@@ -155,9 +132,6 @@ func (s *Service) GenerateManifest(c context.Context, q *apiclient.ManifestReque
 		return cached, nil
 	}
 
-	s.repoLock.Lock(gitClient.Root())
-	defer s.repoLock.Unlock(gitClient.Root())
-
 	cached = getCached()
 	if cached != nil {
 		return cached, nil
@@ -171,56 +145,30 @@ func (s *Service) GenerateManifest(c context.Context, q *apiclient.ManifestReque
 		defer s.parallelismLimitSemaphore.Release(1)
 	}
 
-	commitSHA, err = checkoutRevision(gitClient, commitSHA)
+	appPath, err := r.GetApp(q.ApplicationSource.Path, resolvedRevision)
 	if err != nil {
 		return nil, err
 	}
-
-	genRes, err := GenerateManifests(gitClient.Root(), q.ApplicationSource.Path, q)
+	genRes, err := GenerateManifests(appPath, q)
 	if err != nil {
 		return nil, err
 	}
 	res := *genRes
-	res.Revision = commitSHA
-	err = s.cache.SetManifests(commitSHA, q.ApplicationSource, q.Namespace, q.AppLabelKey, q.AppLabelValue, &res)
+	res.Revision = resolvedRevision
+	err = s.cache.SetManifests(resolvedRevision, q.ApplicationSource, q.Namespace, q.AppLabelKey, q.AppLabelValue, &res)
 	if err != nil {
-		log.Warnf("manifest cache set error %s/%s: %v", q.ApplicationSource.String(), commitSHA, err)
+		log.Warnf("manifest cache set error %s/%s: %v", q.ApplicationSource.String(), resolvedRevision, err)
 	}
 	return &res, nil
 }
 
-func appPath(root, path string) (string, error) {
-	if filepath.IsAbs(path) {
-		return "", fmt.Errorf("%s: app path is absolute", path)
-	}
-	appPath := filepath.Join(root, path)
-	if !strings.HasPrefix(appPath, filepath.Clean(root)) {
-		return "", fmt.Errorf("%s: app path outside repo", path)
-	}
-	info, err := os.Stat(appPath)
-	if os.IsNotExist(err) {
-		return "", fmt.Errorf("%s: app path does not exist", path)
-	}
-	if err != nil {
-		return "", err
-	}
-	if !info.IsDir() {
-		return "", fmt.Errorf("%s: app path is not a directory", path)
-	}
-	return appPath, nil
-}
-
 // GenerateManifests generates manifests from a path
-func GenerateManifests(root, path string, q *apiclient.ManifestRequest) (*apiclient.ManifestResponse, error) {
-	appPath, err := appPath(root, path)
-	if err != nil {
-		return nil, err
-	}
+func GenerateManifests(appPath string, q *apiclient.ManifestRequest) (*apiclient.ManifestResponse, error) {
 	var targetObjs []*unstructured.Unstructured
 	var dest *v1alpha1.ApplicationDestination
 
 	appSourceType, err := GetAppSourceType(q.ApplicationSource, appPath)
-	creds := argo.GetRepoCreds(q.Repo)
+	creds := creds.GetRepoCreds(q.Repo)
 	repoURL := ""
 	if q.Repo != nil {
 		repoURL = q.Repo.Repo
@@ -229,12 +177,15 @@ func GenerateManifests(root, path string, q *apiclient.ManifestRequest) (*apicli
 	case v1alpha1.ApplicationSourceTypeKsonnet:
 		targetObjs, dest, err = ksShow(q.AppLabelKey, appPath, q.ApplicationSource.Ksonnet)
 	case v1alpha1.ApplicationSourceTypeHelm:
-		h := helm.NewHelmApp(appPath, q.HelmRepos)
-		err := h.Init()
+		h, err := helm.NewHelmApp(appPath, q.Repos)
 		if err != nil {
 			return nil, err
 		}
 		defer h.Dispose()
+		err = h.Init()
+		if err != nil {
+			return nil, err
+		}
 		targetObjs, err = h.Template(q.AppLabelValue, q.Namespace, q.ApplicationSource.Helm)
 		if err != nil {
 			if !helm.IsMissingDependencyErr(err) {
@@ -312,13 +263,8 @@ func GenerateManifests(root, path string, q *apiclient.ManifestRequest) (*apicli
 	return &res, nil
 }
 
-// tempRepoPath returns a formulated temporary directory location to clone a repository
-func tempRepoPath(repo string) string {
-	return filepath.Join(os.TempDir(), strings.Replace(repo, "/", "_", -1))
-}
-
 // GetAppSourceType returns explicit application source type or examines a directory and determines its application source type
-func GetAppSourceType(source *v1alpha1.ApplicationSource, appDirPath string) (v1alpha1.ApplicationSourceType, error) {
+func GetAppSourceType(source *v1alpha1.ApplicationSource, path string) (v1alpha1.ApplicationSourceType, error) {
 	appSourceType, err := source.ExplicitType()
 	if err != nil {
 		return "", err
@@ -326,19 +272,11 @@ func GetAppSourceType(source *v1alpha1.ApplicationSource, appDirPath string) (v1
 	if appSourceType != nil {
 		return *appSourceType, nil
 	}
-
-	if pathExists(appDirPath, "app.yaml") {
-		return v1alpha1.ApplicationSourceTypeKsonnet, nil
-	}
-	if pathExists(appDirPath, "Chart.yaml") {
-		return v1alpha1.ApplicationSourceTypeHelm, nil
-	}
-	for _, kustomization := range kustomize.KustomizationNames {
-		if pathExists(appDirPath, kustomization) {
-			return v1alpha1.ApplicationSourceTypeKustomize, nil
-		}
+	appType, err := discovery.AppType(path)
+	if err != nil {
+		return "", err
 	}
-	return v1alpha1.ApplicationSourceTypeDirectory, nil
+	return v1alpha1.ApplicationSourceType(appType), nil
 }
 
 // isNullList checks if the object is a "List" type where items is null instead of an empty list.
@@ -361,24 +299,6 @@ func isNullList(obj *unstructured.Unstructured) bool {
 	return field == nil
 }
 
-// checkoutRevision is a convenience function to initialize a repo, fetch, and checkout a revision
-// Returns the 40 character commit SHA after the checkout has been performed
-func checkoutRevision(gitClient git.Client, commitSHA string) (string, error) {
-	err := gitClient.Init()
-	if err != nil {
-		return "", status.Errorf(codes.Internal, "Failed to initialize git repo: %v", err)
-	}
-	err = gitClient.Fetch()
-	if err != nil {
-		return "", status.Errorf(codes.Internal, "Failed to fetch git repo: %v", err)
-	}
-	err = gitClient.Checkout(commitSHA)
-	if err != nil {
-		return "", status.Errorf(codes.Internal, "Failed to checkout %s: %v", commitSHA, err)
-	}
-	return gitClient.CommitSHA()
-}
-
 // ksShow runs `ks show` in an app directory after setting any component parameter overrides
 func ksShow(appLabelKey, appPath string, ksonnetOpts *v1alpha1.ApplicationSourceKsonnet) ([]*unstructured.Unstructured, *v1alpha1.ApplicationDestination, error) {
 	ksApp, err := ksonnet.NewKsonnetApp(appPath)
@@ -508,36 +428,6 @@ func makeJsonnetVm(sourceJsonnet v1alpha1.ApplicationSourceJsonnet) *jsonnet.VM
 	return vm
 }
 
-// pathExists reports whether the file or directory at the named concatenation of paths exists.
-func pathExists(ss ...string) bool {
-	name := filepath.Join(ss...)
-	if _, err := os.Stat(name); err != nil {
-		if os.IsNotExist(err) {
-			return false
-		}
-	}
-	return true
-}
-
-// newClientResolveRevision is a helper to perform the common task of instantiating a git client
-// and resolving a revision to a commit SHA
-func (s *Service) newClientResolveRevision(repo *v1alpha1.Repository, revision string) (git.Client, string, error) {
-	gitClient, err := s.newClient(repo)
-	if err != nil {
-		return nil, "", err
-	}
-	commitSHA, err := gitClient.LsRemote(revision)
-	if err != nil {
-		return nil, "", err
-	}
-	return gitClient, commitSHA, nil
-}
-
-func (s *Service) newClient(repo *v1alpha1.Repository) (git.Client, error) {
-	appPath := tempRepoPath(git.NormalizeGitURL(repo.Repo))
-	return s.gitFactory.NewClient(repo.Repo, appPath, argo.GetRepoCreds(repo), repo.IsInsecure(), repo.EnableLFS)
-}
-
 func runCommand(command v1alpha1.Command, path string, env []string) (string, error) {
 	if len(command.Command) == 0 {
 		return "", fmt.Errorf("Command is empty")
@@ -586,25 +476,31 @@ func runConfigManagementPlugin(appPath string, q *apiclient.ManifestRequest, cre
 }
 
 func (s *Service) GetAppDetails(ctx context.Context, q *apiclient.RepoServerAppDetailsQuery) (*apiclient.RepoAppDetailsResponse, error) {
-	revision := q.Revision
-	if revision == "" {
-		revision = "HEAD"
+	r, err := s.repoFactory.NewRepo(q.Repo, metrics.NopReporter)
+	if err != nil {
+		return nil, err
+	}
+	s.repoLock.Lock(r.LockKey())
+	defer s.repoLock.Unlock(r.LockKey())
+	err = r.Init()
+	if err != nil {
+		return nil, err
 	}
-	gitClient, commitSHA, err := s.newClientResolveRevision(q.Repo, revision)
+	resolvedRevision, err := r.ResolveRevision(q.App, q.Revision)
 	if err != nil {
 		return nil, err
 	}
 	getCached := func() *apiclient.RepoAppDetailsResponse {
 		var res apiclient.RepoAppDetailsResponse
-		err = s.cache.GetAppDetails(commitSHA, q.Path, valueFiles(q), &res)
+		err = s.cache.GetAppDetails(resolvedRevision, q.App, valueFiles(q), &res)
 		if err == nil {
-			log.Infof("manifest cache hit: %s/%s", commitSHA, q.Path)
+			log.Infof("manifest cache hit: %s/%s", resolvedRevision, q.App)
 			return &res
 		}
 		if err != cache.ErrCacheMiss {
-			log.Warnf("manifest cache error %s: %v", commitSHA, q.Path)
+			log.Warnf("manifest cache error %s: %v", resolvedRevision, q.App)
 		} else {
-			log.Infof("manifest cache miss: %s/%s", commitSHA, q.Path)
+			log.Infof("manifest cache miss: %s/%s", resolvedRevision, q.App)
 		}
 		return nil
 	}
@@ -612,20 +508,16 @@ func (s *Service) GetAppDetails(ctx context.Context, q *apiclient.RepoServerAppD
 	if cached != nil {
 		return cached, nil
 	}
-	s.repoLock.Lock(gitClient.Root())
-	defer s.repoLock.Unlock(gitClient.Root())
 	cached = getCached()
 	if cached != nil {
 		return cached, nil
 	}
 
-	commitSHA, err = checkoutRevision(gitClient, commitSHA)
+	appPath, err := r.GetApp(q.App, resolvedRevision)
 	if err != nil {
 		return nil, err
 	}
 
-	appPath := filepath.Join(gitClient.Root(), q.Path)
-
 	appSourceType, err := GetAppSourceType(&v1alpha1.ApplicationSource{}, appPath)
 	if err != nil {
 		return nil, err
@@ -662,7 +554,6 @@ func (s *Service) GetAppDetails(ctx context.Context, q *apiclient.RepoServerAppD
 		res.Ksonnet = &ksonnetAppSpec
 	case v1alpha1.ApplicationSourceTypeHelm:
 		res.Helm = &apiclient.HelmAppSpec{}
-		res.Helm.Path = q.Path
 		files, err := ioutil.ReadDir(appPath)
 		if err != nil {
 			return nil, err
@@ -676,12 +567,15 @@ func (s *Service) GetAppDetails(ctx context.Context, q *apiclient.RepoServerAppD
 				res.Helm.ValueFiles = append(res.Helm.ValueFiles, fName)
 			}
 		}
-		h := helm.NewHelmApp(appPath, q.HelmRepos)
-		err = h.Init()
+		h, err := helm.NewHelmApp(appPath, q.Repos)
 		if err != nil {
 			return nil, err
 		}
 		defer h.Dispose()
+		err = h.Init()
+		if err != nil {
+			return nil, err
+		}
 		valuesPath := filepath.Join(appPath, "values.yaml")
 		info, err := os.Stat(valuesPath)
 		if err == nil && !info.IsDir() {
@@ -698,8 +592,7 @@ func (s *Service) GetAppDetails(ctx context.Context, q *apiclient.RepoServerAppD
 		res.Helm.Parameters = params
 	case v1alpha1.ApplicationSourceTypeKustomize:
 		res.Kustomize = &apiclient.KustomizeAppSpec{}
-		res.Kustomize.Path = q.Path
-		k := kustomize.NewKustomizeApp(appPath, argo.GetRepoCreds(q.Repo), q.Repo.Repo)
+		k := kustomize.NewKustomizeApp(appPath, creds.GetRepoCreds(q.Repo), q.Repo.Repo)
 		_, images, err := k.Build(nil, q.KustomizeOptions)
 		if err != nil {
 			return nil, err
@@ -709,43 +602,39 @@ func (s *Service) GetAppDetails(ctx context.Context, q *apiclient.RepoServerAppD
 	return &res, nil
 }
 
-func (s *Service) getRevisionMetadata(repoURL *v1alpha1.Repository, revision string) (*git.RevisionMetadata, error) {
-	client, commitSHA, err := s.newClientResolveRevision(repoURL, revision)
-	if err != nil {
-		return nil, err
-	}
-	s.repoLock.Lock(client.Root())
-	defer s.repoLock.Unlock(client.Root())
-	err = client.Init()
+func (s *Service) getRevisionMetadata(repo *v1alpha1.Repository, app, revision string) (*repo.RevisionMetadata, error) {
+	r, err := s.repoFactory.NewRepo(repo, metrics.NopReporter)
 	if err != nil {
 		return nil, err
 	}
-	err = client.Fetch()
+	s.repoLock.Lock(r.LockKey())
+	defer s.repoLock.Unlock(r.LockKey())
+	err = r.Init()
 	if err != nil {
 		return nil, err
 	}
-	return client.RevisionMetadata(commitSHA)
+	return r.RevisionMetadata(app, revision)
 }
 
 func (s *Service) GetRevisionMetadata(ctx context.Context, q *apiclient.RepoServerRevisionMetadataRequest) (*v1alpha1.RevisionMetadata, error) {
-	metadata, err := s.cache.GetRevisionMetadata(q.Repo.Repo, q.Revision)
+	metadata, err := s.cache.GetRevisionMetadata(q.Repo.Repo, q.App, q.Revision)
 	if err == nil {
-		log.WithFields(log.Fields{"repoURL": q.Repo.Repo, "revision": q.Revision}).Debug("cache hit")
+		log.WithFields(log.Fields{"repoURL": q.Repo.Repo, "app": q.App, "revision": q.Revision}).Debug("cache hit")
 		return metadata, nil
 	}
 	if err == cache.ErrCacheMiss {
-		log.WithFields(log.Fields{"repoURL": q.Repo.Repo, "revision": q.Revision}).Debug("cache miss")
-		gitMetadata, err := s.getRevisionMetadata(q.Repo, q.Revision)
+		log.WithFields(log.Fields{"repoURL": q.Repo.Repo, "app": q.App, "revision": q.Revision}).Debug("cache miss")
+		m, err := s.getRevisionMetadata(q.Repo, q.App, q.Revision)
 		if err != nil {
 			return nil, err
 		}
 		// discard anything after the first new line and then truncate to 64 chars
-		message := text.Trunc(strings.SplitN(gitMetadata.Message, "\n", 2)[0], 64)
-		metadata = &v1alpha1.RevisionMetadata{Author: gitMetadata.Author, Date: metav1.Time{Time: gitMetadata.Date}, Tags: gitMetadata.Tags, Message: message}
-		_ = s.cache.SetRevisionMetadata(q.Repo.Repo, q.Revision, metadata)
+		message := text.Trunc(strings.SplitN(m.Message, "\n", 2)[0], 64)
+		metadata = &v1alpha1.RevisionMetadata{Author: m.Author, Date: metav1.Time{Time: m.Date}, Tags: m.Tags, Message: message}
+		_ = s.cache.SetRevisionMetadata(q.Repo.Repo, q.App, q.Revision, metadata)
 		return metadata, nil
 	}
-	log.WithFields(log.Fields{"repoURL": q.Repo.Repo, "revision": q.Revision, "err": err}).Debug("cache error")
+	log.WithFields(log.Fields{"repoURL": q.Repo.Repo, "app": q.App, "revision": q.Revision, "err": err}).Debug("cache error")
 	return nil, err
 }
 
diff --git a/reposerver/repository/repository.proto b/reposerver/repository/repository.proto
index d5718e8621362..5fb9dcee64e1b 100644
--- a/reposerver/repository/repository.proto
+++ b/reposerver/repository/repository.proto
@@ -17,7 +17,7 @@ message ManifestRequest {
     string appLabelValue = 5;
     string namespace = 8;
     github.com.argoproj.argo_cd.pkg.apis.application.v1alpha1.ApplicationSource applicationSource = 10;
-    repeated github.com.argoproj.argo_cd.pkg.apis.application.v1alpha1.HelmRepository helmRepos = 11;
+    repeated github.com.argoproj.argo_cd.pkg.apis.application.v1alpha1.Repository repos = 11;
     repeated github.com.argoproj.argo_cd.pkg.apis.application.v1alpha1.ConfigManagementPlugin plugins = 12;
     github.com.argoproj.argo_cd.pkg.apis.application.v1alpha1.KustomizeOptions kustomizeOptions = 13;
 }
@@ -30,37 +30,23 @@ message ManifestResponse {
     string sourceType = 6;
 }
 
-// ListDirRequest requests a repository directory structure
-message ListDirRequest {
+// ListAppsRequest requests a repository directory structure
+message ListAppsRequest {
     github.com.argoproj.argo_cd.pkg.apis.application.v1alpha1.Repository repo = 1;
     string revision = 2;
-    string path = 3;
 }
 
-// FileList returns the contents of the repo of a ListDir request
-message FileList {
-    repeated string items = 1;
-}
-
-// GetFileRequest return
-message GetFileRequest {
-    github.com.argoproj.argo_cd.pkg.apis.application.v1alpha1.Repository repo = 1;
-    string revision = 2;
-    string path = 3;
-}
-
-
-// GetFileResponse returns the contents of the file of a GetFile request
-message GetFileResponse {
-    bytes data = 1;
+// AppList returns the contents of the repo of a ListApps request
+message AppList {
+    map<string, string> apps = 1;
 }
 
 // RepoServerAppDetailsQuery contains query information for app details request
 message RepoServerAppDetailsQuery {
     github.com.argoproj.argo_cd.pkg.apis.application.v1alpha1.Repository repo = 1;
 	string revision = 2;
-	string path = 3;
-    repeated github.com.argoproj.argo_cd.pkg.apis.application.v1alpha1.HelmRepository helmRepos = 4;
+	string app = 3;
+    repeated github.com.argoproj.argo_cd.pkg.apis.application.v1alpha1.Repository repos = 4;
     repeated github.com.argoproj.argo_cd.pkg.apis.application.v1alpha1.ConfigManagementPlugin plugins = 5;
     HelmAppDetailsQuery helm = 6;
     KsonnetAppDetailsQuery ksonnet = 7;
@@ -87,23 +73,23 @@ message RepoAppDetailsResponse {
 message RepoServerRevisionMetadataRequest {
     // the repo
     github.com.argoproj.argo_cd.pkg.apis.application.v1alpha1.Repository repo = 1;
+    // the app name
+    string app = 2;
     // the revision within the repo
-    string revision = 2;
+    string revision = 3;
 }
 
 // KsonnetAppSpec contains Ksonnet app response
 // This roughly reflects: ksonnet/ksonnet/metadata/app/schema.go
 message KsonnetAppSpec {
 	string name = 1;
-	string path = 2;
 	map<string, KsonnetEnvironment> environments = 3;
 	repeated github.com.argoproj.argo_cd.pkg.apis.application.v1alpha1.KsonnetParameter parameters = 4;
 }
 
-// HelmAppSpec contains helm app name and path in source repo
+// HelmAppSpec contains helm app name  in source repo
 message HelmAppSpec {
 	string name = 1;
-	string path = 2;
 	repeated string valueFiles = 3;
 	// the output of `helm inspect values`
 	repeated github.com.argoproj.argo_cd.pkg.apis.application.v1alpha1.HelmParameter parameters = 4;
@@ -111,9 +97,8 @@ message HelmAppSpec {
 	string values = 5;
 }
 
-// KustomizeAppSpec contains kustomize app name and path in source repo
+// KustomizeAppSpec contains kustomize images
 message KustomizeAppSpec {
-	string path = 1;
 	// images is a list of available images.
 	repeated string images = 3;
 }
@@ -123,8 +108,6 @@ message KsonnetEnvironment {
     string name = 1;
     // KubernetesVersion is the kubernetes version the targetted cluster is running on.
     string k8sVersion = 2;
-    // Path is the relative project path containing metadata for this environment.
-    string path = 3;
     // Destination stores the cluster address that this environment points to.
     KsonnetEnvironmentDestination destination = 4;
 }
@@ -148,12 +131,8 @@ service RepoServerService {
     rpc GenerateManifest(ManifestRequest) returns (ManifestResponse) {
     }
 
-    // ListDir returns the file contents at the specified repo and path
-    rpc ListDir(ListDirRequest) returns (FileList) {
-    }
-
-    // GetFile returns the file contents at the specified repo and path
-    rpc GetFile(GetFileRequest) returns (GetFileResponse) {
+    // ListApps returns a list of apps in the repo
+    rpc ListApps(ListAppsRequest) returns (AppList) {
     }
 
     // Generate manifest for application in specified repo name and revision
diff --git a/reposerver/repository/repository_test.go b/reposerver/repository/repository_test.go
index 09b754ffbd6ba..15f1c4d1486ff 100644
--- a/reposerver/repository/repository_test.go
+++ b/reposerver/repository/repository_test.go
@@ -5,6 +5,7 @@ import (
 	"encoding/json"
 	"io/ioutil"
 	"os"
+	"path/filepath"
 	"reflect"
 	"strings"
 	"testing"
@@ -20,47 +21,48 @@ import (
 	"github.com/argoproj/argo-cd/reposerver/apiclient"
 	"github.com/argoproj/argo-cd/util"
 	"github.com/argoproj/argo-cd/util/cache"
-	"github.com/argoproj/argo-cd/util/git"
-	gitmocks "github.com/argoproj/argo-cd/util/git/mocks"
+	"github.com/argoproj/argo-cd/util/repo"
+	"github.com/argoproj/argo-cd/util/repo/metrics"
+	gitmocks "github.com/argoproj/argo-cd/util/repo/mocks"
 )
 
-func newMockRepoServerService(root string) *Service {
+func newMockRepoServerService(root, path string) *Service {
 	return &Service{
-		repoLock:   util.NewKeyLock(),
-		gitFactory: newFakeGitClientFactory(root),
-		cache:      cache.NewCache(cache.NewInMemoryCache(time.Hour)),
+		repoLock:    util.NewKeyLock(),
+		repoFactory: newFakeFactory(root, path),
+		cache:       cache.NewCache(cache.NewInMemoryCache(time.Hour)),
 	}
 }
 
-func newFakeGitClientFactory(root string) *fakeGitClientFactory {
-	return &fakeGitClientFactory{
+func newFakeFactory(root, path string) *fakeFactory {
+	return &fakeFactory{
 		root:             root,
+		path:             path,
 		revision:         "aaaaaaaaaabbbbbbbbbbccccccccccdddddddddd",
-		revisionMetadata: &git.RevisionMetadata{Author: "foo", Message: strings.Repeat("x", 99), Tags: []string{"bar"}},
+		revisionMetadata: &repo.RevisionMetadata{Author: "foo", Message: strings.Repeat("x", 99), Tags: []string{"bar"}},
 	}
 }
 
-type fakeGitClientFactory struct {
+type fakeFactory struct {
 	root             string
+	path             string
 	revision         string
-	revisionMetadata *git.RevisionMetadata
+	revisionMetadata *repo.RevisionMetadata
 }
 
-func (f *fakeGitClientFactory) NewClient(repoURL string, path string, creds git.Creds, insecureIgnoreHostKey bool, enableLfs bool) (git.Client, error) {
-	mockClient := gitmocks.Client{}
+func (f *fakeFactory) NewRepo(repo *v1alpha1.Repository, reporter metrics.Reporter) (repo.Repo, error) {
+	r := gitmocks.Repo{}
 	root := "./testdata"
 	if f.root != "" {
 		root = f.root
 	}
-	mockClient.On("Root").Return(root)
-	mockClient.On("Init").Return(nil)
-	mockClient.On("Fetch", mock.Anything).Return(nil)
-	mockClient.On("Checkout", mock.Anything).Return(nil)
-	mockClient.On("LsRemote", mock.Anything).Return(f.revision, nil)
-	mockClient.On("LsFiles", mock.Anything).Return([]string{}, nil)
-	mockClient.On("CommitSHA", mock.Anything).Return(f.revision, nil)
-	mockClient.On("RevisionMetadata", f.revision).Return(f.revisionMetadata, nil)
-	return &mockClient, nil
+	r.On("LockKey").Return(root)
+	r.On("Init").Return(nil)
+	r.On("GetApp", mock.Anything, mock.Anything).Return(filepath.Join(root, f.path), nil)
+	r.On("ResolveRevision", mock.Anything, mock.Anything).Return(f.revision, nil)
+	r.On("ListApps", mock.Anything).Return(map[string]string{}, "", nil)
+	r.On("RevisionMetadata", mock.Anything, f.revision).Return(f.revisionMetadata, nil)
+	return &r, nil
 }
 
 func TestGenerateYamlManifestInDir(t *testing.T) {
@@ -70,12 +72,12 @@ func TestGenerateYamlManifestInDir(t *testing.T) {
 	q := apiclient.ManifestRequest{
 		ApplicationSource: &argoappv1.ApplicationSource{},
 	}
-	res1, err := GenerateManifests("../../manifests", "base", &q)
+	res1, err := GenerateManifests("../../manifests/base", &q)
 	assert.Nil(t, err)
 	assert.Equal(t, countOfManifests, len(res1.Manifests))
 
 	// this will test concatenated manifests to verify we split YAMLs correctly
-	res2, err := GenerateManifests("./testdata", "concatenated", &q)
+	res2, err := GenerateManifests("./testdata/concatenated", &q)
 	assert.Nil(t, err)
 	assert.Equal(t, 3, len(res2.Manifests))
 }
@@ -85,56 +87,11 @@ func TestRecurseManifestsInDir(t *testing.T) {
 		ApplicationSource: &argoappv1.ApplicationSource{},
 	}
 	q.ApplicationSource.Directory = &argoappv1.ApplicationSourceDirectory{Recurse: true}
-	res1, err := GenerateManifests("./testdata", "recurse", &q)
+	res1, err := GenerateManifests("./testdata/recurse", &q)
 	assert.Nil(t, err)
 	assert.Equal(t, 2, len(res1.Manifests))
 }
 
-func TestPathRoot(t *testing.T) {
-	_, err := appPath("./testdata", "/")
-	assert.EqualError(t, err, "/: app path is absolute")
-}
-
-func TestPathAbsolute(t *testing.T) {
-	_, err := appPath("./testdata", "/etc/passwd")
-	assert.EqualError(t, err, "/etc/passwd: app path is absolute")
-}
-
-func TestPathDotDot(t *testing.T) {
-	_, err := appPath("./testdata", "..")
-	assert.EqualError(t, err, "..: app path outside repo")
-}
-
-func TestPathDotDotSlash(t *testing.T) {
-	_, err := appPath("./testdata", "../")
-	assert.EqualError(t, err, "../: app path outside repo")
-}
-
-func TestPathDot(t *testing.T) {
-	_, err := appPath("./testdata", ".")
-	assert.NoError(t, err)
-}
-
-func TestPathDotSlash(t *testing.T) {
-	_, err := appPath("./testdata", "./")
-	assert.NoError(t, err)
-}
-
-func TestNonExistentPath(t *testing.T) {
-	_, err := appPath("./testdata", "does-not-exist")
-	assert.EqualError(t, err, "does-not-exist: app path does not exist")
-}
-
-func TestPathNotDir(t *testing.T) {
-	_, err := appPath("./testdata", "file.txt")
-	assert.EqualError(t, err, "file.txt: app path is not a directory")
-}
-
-func TestGenerateManifests_NonExistentPath(t *testing.T) {
-	_, err := GenerateManifests("./testdata", "does-not-exist", nil)
-	assert.EqualError(t, err, "does-not-exist: app path does not exist")
-}
-
 func TestGenerateJsonnetManifestInDir(t *testing.T) {
 	q := apiclient.ManifestRequest{
 		ApplicationSource: &argoappv1.ApplicationSource{
@@ -146,7 +103,7 @@ func TestGenerateJsonnetManifestInDir(t *testing.T) {
 			},
 		},
 	}
-	res1, err := GenerateManifests("./testdata", "jsonnet", &q)
+	res1, err := GenerateManifests("./testdata/jsonnet", &q)
 	assert.Nil(t, err)
 	assert.Equal(t, 2, len(res1.Manifests))
 }
@@ -165,26 +122,26 @@ func TestGenerateHelmChartWithDependencies(t *testing.T) {
 	q := apiclient.ManifestRequest{
 		ApplicationSource: &argoappv1.ApplicationSource{},
 	}
-	res1, err := GenerateManifests("../../util/helm/testdata", "wordpress", &q)
+	res1, err := GenerateManifests("../../util/helm/testdata/wordpress", &q)
 	assert.Nil(t, err)
-	assert.Equal(t, 12, len(res1.Manifests))
+	assert.Len(t, res1.Manifests, 12)
 }
 
 func TestGenerateNullList(t *testing.T) {
 	q := apiclient.ManifestRequest{
 		ApplicationSource: &argoappv1.ApplicationSource{},
 	}
-	res1, err := GenerateManifests("./testdata", "null-list", &q)
+	res1, err := GenerateManifests("./testdata/null-list", &q)
 	assert.Nil(t, err)
 	assert.Equal(t, len(res1.Manifests), 1)
 	assert.Contains(t, res1.Manifests[0], "prometheus-operator-operator")
 
-	res1, err = GenerateManifests("./testdata", "empty-list", &q)
+	res1, err = GenerateManifests("./testdata/empty-list", &q)
 	assert.Nil(t, err)
 	assert.Equal(t, len(res1.Manifests), 1)
 	assert.Contains(t, res1.Manifests[0], "prometheus-operator-operator")
 
-	res2, err := GenerateManifests("./testdata", "weird-list", &q)
+	res2, err := GenerateManifests("./testdata/weird-list", &q)
 	assert.Nil(t, err)
 	assert.Equal(t, 2, len(res2.Manifests))
 }
@@ -204,7 +161,7 @@ func TestIdentifyAppSourceTypeByAppDirWithKustomizations(t *testing.T) {
 }
 
 func TestRunCustomTool(t *testing.T) {
-	res, err := GenerateManifests(".", ".", &apiclient.ManifestRequest{
+	res, err := GenerateManifests(".", &apiclient.ManifestRequest{
 		AppLabelValue: "test-app",
 		Namespace:     "test-namespace",
 		ApplicationSource: &argoappv1.ApplicationSource{
@@ -241,22 +198,24 @@ func TestGenerateFromUTF16(t *testing.T) {
 	q := apiclient.ManifestRequest{
 		ApplicationSource: &argoappv1.ApplicationSource{},
 	}
-	res1, err := GenerateManifests("./testdata", "utf-16", &q)
+	res1, err := GenerateManifests("./testdata/utf-16", &q)
 	assert.Nil(t, err)
 	assert.Equal(t, 2, len(res1.Manifests))
 }
 
 func TestGetAppDetailsHelm(t *testing.T) {
-	serve := newMockRepoServerService("../../util/helm/testdata")
+	serve := newMockRepoServerService("../../util/helm/testdata", "redis")
 	ctx := context.Background()
 
 	// verify default parameters are returned when not supplying values
 	t.Run("DefaultParameters", func(t *testing.T) {
 		res, err := serve.GetAppDetails(ctx, &apiclient.RepoServerAppDetailsQuery{
 			Repo: &argoappv1.Repository{Repo: "https://github.com/fakeorg/fakerepo.git"},
-			Path: "redis",
+			App:  "redis",
 		})
 		assert.NoError(t, err)
+		assert.Equal(t, "Helm", res.Type)
+		assert.NotNil(t, res.Helm)
 		assert.Equal(t, []string{"values-production.yaml", "values.yaml"}, res.Helm.ValueFiles)
 		assert.Contains(t, res.Helm.Values, "registry: docker.io")
 		assert.Equal(t, argoappv1.HelmParameter{Name: "image.pullPolicy", Value: "Always"}, getHelmParameter("image.pullPolicy", res.Helm.Parameters))
@@ -267,12 +226,14 @@ func TestGetAppDetailsHelm(t *testing.T) {
 	t.Run("SpecificParameters", func(t *testing.T) {
 		res, err := serve.GetAppDetails(ctx, &apiclient.RepoServerAppDetailsQuery{
 			Repo: &argoappv1.Repository{Repo: "https://github.com/fakeorg/fakerepo.git"},
-			Path: "redis",
+			App:  "redis",
 			Helm: &apiclient.HelmAppDetailsQuery{
 				ValueFiles: []string{"values-production.yaml"},
 			},
 		})
 		assert.NoError(t, err)
+		assert.Equal(t, "Helm", res.Type)
+		assert.NotNil(t, res.Helm)
 		assert.Equal(t, []string{"values-production.yaml", "values.yaml"}, res.Helm.ValueFiles)
 		assert.Contains(t, res.Helm.Values, "registry: docker.io")
 		assert.Equal(t, argoappv1.HelmParameter{Name: "image.pullPolicy", Value: "IfNotPresent"}, getHelmParameter("image.pullPolicy", res.Helm.Parameters))
@@ -290,45 +251,44 @@ func getHelmParameter(name string, params []*argoappv1.HelmParameter) argoappv1.
 }
 
 func TestGetAppDetailsKsonnet(t *testing.T) {
-	serve := newMockRepoServerService("../../test/e2e/testdata")
+	serve := newMockRepoServerService("../../test/e2e/testdata", "ksonnet")
 	ctx := context.Background()
 
 	res, err := serve.GetAppDetails(ctx, &apiclient.RepoServerAppDetailsQuery{
 		Repo: &argoappv1.Repository{Repo: "https://github.com/fakeorg/fakerepo.git"},
-		Path: "ksonnet",
+		App:  "ksonnet",
 	})
 	assert.NoError(t, err)
 	assert.Equal(t, "https://kubernetes.default.svc", res.Ksonnet.Environments["prod"].Destination.Server)
 	assert.Equal(t, "prod", res.Ksonnet.Environments["prod"].Destination.Namespace)
 	assert.Equal(t, "v1.10.0", res.Ksonnet.Environments["prod"].K8SVersion)
-	assert.Equal(t, "prod", res.Ksonnet.Environments["prod"].Path)
 	assert.Equal(t, argoappv1.KsonnetParameter{Component: "guestbook-ui", Name: "command", Value: "null"}, *res.Ksonnet.Parameters[0])
 	assert.Equal(t, 7, len(res.Ksonnet.Parameters))
 }
 
 func TestGetAppDetailsKustomize(t *testing.T) {
-	serve := newMockRepoServerService("../../util/kustomize/testdata")
+	serve := newMockRepoServerService("../../util/kustomize/testdata", "kustomization_yaml")
 	ctx := context.Background()
 
 	res, err := serve.GetAppDetails(ctx, &apiclient.RepoServerAppDetailsQuery{
 		Repo: &argoappv1.Repository{Repo: "https://github.com/fakeorg/fakerepo.git"},
-		Path: "kustomization_yaml",
+		App:  "kustomization_yaml",
 	})
 	assert.NoError(t, err)
 	assert.Equal(t, []string{"nginx:1.15.4", "k8s.gcr.io/nginx-slim:0.8"}, res.Kustomize.Images)
 }
 
 func TestService_GetRevisionMetadata(t *testing.T) {
-	factory := newFakeGitClientFactory(".")
+	factory := newFakeFactory(".", "empty-list")
 	service := &Service{
-		repoLock:   util.NewKeyLock(),
-		gitFactory: factory,
-		cache:      cache.NewCache(cache.NewInMemoryCache(1 * time.Hour)),
+		repoLock:    util.NewKeyLock(),
+		repoFactory: factory,
+		cache:       cache.NewCache(cache.NewInMemoryCache(1 * time.Hour)),
 	}
 	type args struct {
 		q *apiclient.RepoServerRevisionMetadataRequest
 	}
-	q := &apiclient.RepoServerRevisionMetadataRequest{Repo: &argoappv1.Repository{}, Revision: factory.revision}
+	q := &apiclient.RepoServerRevisionMetadataRequest{Repo: &argoappv1.Repository{}, App: "empty-list", Revision: factory.revision}
 	metadata := &v1alpha1.RevisionMetadata{
 		Author:  factory.revisionMetadata.Author,
 		Message: strings.Repeat("x", 61) + "...",
diff --git a/reposerver/server.go b/reposerver/server.go
index b18089f977c5c..17eba22bbd583 100644
--- a/reposerver/server.go
+++ b/reposerver/server.go
@@ -8,8 +8,8 @@ import (
 	"github.com/argoproj/argo-cd/reposerver/repository"
 	"github.com/argoproj/argo-cd/server/version"
 	"github.com/argoproj/argo-cd/util/cache"
-	"github.com/argoproj/argo-cd/util/git"
 	grpc_util "github.com/argoproj/argo-cd/util/grpc"
+	"github.com/argoproj/argo-cd/util/repo/factory"
 	tlsutil "github.com/argoproj/argo-cd/util/tls"
 
 	grpc_middleware "github.com/grpc-ecosystem/go-grpc-middleware"
@@ -23,14 +23,14 @@ import (
 // ArgoCDRepoServer is the repo server implementation
 type ArgoCDRepoServer struct {
 	log              *log.Entry
-	gitFactory       git.ClientFactory
+	clientFactory    factory.Factory
 	cache            *cache.Cache
 	opts             []grpc.ServerOption
 	parallelismLimit int64
 }
 
 // NewServer returns a new instance of the Argo CD Repo server
-func NewServer(gitFactory git.ClientFactory, cache *cache.Cache, tlsConfCustomizer tlsutil.ConfigCustomizer, parallelismLimit int64) (*ArgoCDRepoServer, error) {
+func NewServer(clientFactory factory.Factory, cache *cache.Cache, tlsConfCustomizer tlsutil.ConfigCustomizer, parallelismLimit int64) (*ArgoCDRepoServer, error) {
 	// generate TLS cert
 	hosts := []string{
 		"localhost",
@@ -55,7 +55,7 @@ func NewServer(gitFactory git.ClientFactory, cache *cache.Cache, tlsConfCustomiz
 
 	return &ArgoCDRepoServer{
 		log:              serverLog,
-		gitFactory:       gitFactory,
+		clientFactory:    clientFactory,
 		cache:            cache,
 		parallelismLimit: parallelismLimit,
 		opts: []grpc.ServerOption{
@@ -70,7 +70,7 @@ func NewServer(gitFactory git.ClientFactory, cache *cache.Cache, tlsConfCustomiz
 func (a *ArgoCDRepoServer) CreateGRPC() *grpc.Server {
 	server := grpc.NewServer(a.opts...)
 	versionpkg.RegisterVersionServiceServer(server, &version.Server{})
-	manifestService := repository.NewService(a.gitFactory, a.cache, a.parallelismLimit)
+	manifestService := repository.NewService(a.clientFactory, a.cache, a.parallelismLimit)
 	apiclient.RegisterRepoServerServiceServer(server, manifestService)
 
 	// Register reflection service on gRPC server.
diff --git a/server/application/application.go b/server/application/application.go
index df692e5511ac5..457f21b859236 100644
--- a/server/application/application.go
+++ b/server/application/application.go
@@ -39,6 +39,8 @@ import (
 	"github.com/argoproj/argo-cd/util/kube"
 	"github.com/argoproj/argo-cd/util/lua"
 	"github.com/argoproj/argo-cd/util/rbac"
+	"github.com/argoproj/argo-cd/util/repo/factory"
+	"github.com/argoproj/argo-cd/util/repo/metrics"
 	"github.com/argoproj/argo-cd/util/session"
 	"github.com/argoproj/argo-cd/util/settings"
 )
@@ -54,7 +56,7 @@ type Server struct {
 	enf           *rbac.Enforcer
 	projectLock   *util.KeyLock
 	auditLogger   *argo.AuditLogger
-	gitFactory    git.ClientFactory
+	clientFactory factory.Factory
 	settingsMgr   *settings.SettingsManager
 	cache         *cache.Cache
 }
@@ -84,7 +86,7 @@ func NewServer(
 		enf:           enf,
 		projectLock:   projectLock,
 		auditLogger:   argo.NewAuditLogger(namespace, kubeclientset, "argocd-server"),
-		gitFactory:    git.NewFactory(),
+		clientFactory: factory.NewFactory(),
 		settingsMgr:   settingsMgr,
 	}
 }
@@ -182,20 +184,15 @@ func (s *Server) GetManifests(ctx context.Context, q *application.ApplicationMan
 	if err != nil {
 		return nil, err
 	}
-	helmRepos, err := s.db.ListHelmRepos(ctx)
+	repos, err := s.db.ListRepositories(ctx)
 	if err != nil {
 		return nil, err
 	}
 
-	plugins, err := s.settingsMgr.GetConfigManagementPlugins()
+	plugins, err := s.plugins()
 	if err != nil {
 		return nil, err
 	}
-
-	tools := make([]*appv1.ConfigManagementPlugin, len(plugins))
-	for i := range plugins {
-		tools[i] = &plugins[i]
-	}
 	// If source is Kustomize add build options
 	buildOptions, err := s.settingsMgr.GetKustomizeBuildOptions()
 	if err != nil {
@@ -212,8 +209,8 @@ func (s *Server) GetManifests(ctx context.Context, q *application.ApplicationMan
 		AppLabelValue:     a.Name,
 		Namespace:         a.Spec.Destination.Namespace,
 		ApplicationSource: &a.Spec.Source,
-		HelmRepos:         helmRepos,
-		Plugins:           tools,
+		Repos:             repos,
+		Plugins:           plugins,
 		KustomizeOptions:  &kustomizeOptions,
 	})
 	if err != nil {
@@ -572,7 +569,12 @@ func (s *Server) validateAndNormalizeApp(ctx context.Context, app *appv1.Applica
 	kustomizeOptions := appv1.KustomizeOptions{
 		BuildOptions: buildOptions,
 	}
-	conditions, appSourceType, err := argo.ValidateRepo(ctx, &app.Spec, s.repoClientset, s.db, &kustomizeOptions)
+	plugins, err := s.plugins()
+	if err != nil {
+		return err
+	}
+
+	conditions, err := argo.ValidateRepo(ctx, &app.Spec, s.repoClientset, s.db, &kustomizeOptions, plugins)
 	if err != nil {
 		return err
 	}
@@ -588,7 +590,7 @@ func (s *Server) validateAndNormalizeApp(ctx context.Context, app *appv1.Applica
 		return status.Errorf(codes.InvalidArgument, "application spec is invalid: %s", argo.FormatAppConditions(conditions))
 	}
 
-	app.Spec = *argo.NormalizeApplicationSpec(&app.Spec, appSourceType)
+	app.Spec = *argo.NormalizeApplicationSpec(&app.Spec)
 	return nil
 }
 
@@ -759,7 +761,7 @@ func (s *Server) RevisionMetadata(ctx context.Context, q *application.RevisionMe
 		return nil, err
 	}
 	defer util.Close(conn)
-	return repoClient.GetRevisionMetadata(ctx, &apiclient.RepoServerRevisionMetadataRequest{Repo: repo, Revision: q.GetRevision()})
+	return repoClient.GetRevisionMetadata(ctx, &apiclient.RepoServerRevisionMetadataRequest{Repo: repo, App: a.Spec.Source.Path, Revision: q.GetRevision()})
 }
 
 func (s *Server) ManagedResources(ctx context.Context, q *application.ResourcesQuery) (*application.ManagedResourcesResponse, error) {
@@ -969,8 +971,8 @@ func (s *Server) Rollback(ctx context.Context, rollbackReq *application.Applicat
 	return a, err
 }
 
-// resolveRevision resolves the git revision specified either in the sync request, or the
-// application source, into a concrete commit SHA that will be used for a sync operation.
+// resolveRevision resolves the revision specified either in the sync request, or the
+// application source, into a concrete revision that will be used for a sync operation.
 func (s *Server) resolveRevision(ctx context.Context, app *appv1.Application, syncReq *application.ApplicationSyncRequest) (string, string, error) {
 	ambiguousRevision := syncReq.Revision
 	if ambiguousRevision == "" {
@@ -984,11 +986,11 @@ func (s *Server) resolveRevision(ctx context.Context, app *appv1.Application, sy
 	if err != nil {
 		return "", "", err
 	}
-	gitClient, err := s.gitFactory.NewClient(repo.Repo, "", argoutil.GetRepoCreds(repo), repo.IsInsecure(), repo.IsLFSEnabled())
+	client, err := s.clientFactory.NewRepo(repo, metrics.NopReporter)
 	if err != nil {
 		return "", "", err
 	}
-	commitSHA, err := gitClient.LsRemote(ambiguousRevision)
+	commitSHA, err := client.ResolveRevision(app.Spec.Source.Path, ambiguousRevision)
 	if err != nil {
 		return "", "", err
 	}
@@ -1151,3 +1153,15 @@ func (s *Server) RunResourceAction(ctx context.Context, q *application.ResourceA
 	}
 	return &application.ApplicationResponse{}, nil
 }
+
+func (s *Server) plugins() ([]*v1alpha1.ConfigManagementPlugin, error) {
+	plugins, err := s.settingsMgr.GetConfigManagementPlugins()
+	if err != nil {
+		return nil, err
+	}
+	tools := make([]*v1alpha1.ConfigManagementPlugin, len(plugins))
+	for i, plugin := range plugins {
+		tools[i] = &plugin
+	}
+	return tools, nil
+}
diff --git a/server/application/application_test.go b/server/application/application_test.go
index d2948b0ca0fbf..d560ddb0393a8 100644
--- a/server/application/application_test.go
+++ b/server/application/application_test.go
@@ -61,28 +61,10 @@ func fakeCluster() *appsv1.Cluster {
 	}
 }
 
-func fakeFileResponse() *apiclient.GetFileResponse {
-	return &apiclient.GetFileResponse{
-		Data: []byte(`
-apiVersion: 0.1.0
-environments:
-  default:
-    destination:
-      namespace: default
-      server: https://cluster-api.com
-    k8sVersion: v1.10.0
-    path: minikube
-kind: ksonnet.io/app
-name: test-app
-version: 0.0.1
-`),
-	}
-}
-
-func fakeListDirResponse() *apiclient.FileList {
-	return &apiclient.FileList{
-		Items: []string{
-			"some/path/app.yaml",
+func fakeAppList() *apiclient.AppList {
+	return &apiclient.AppList{
+		Apps: map[string]string{
+			"some/path": "Ksonnet",
 		},
 	}
 }
@@ -115,9 +97,9 @@ func newTestAppServer(objects ...runtime.Object) *Server {
 	errors.CheckError(err)
 
 	mockRepoServiceClient := mocks.RepoServerServiceClient{}
-	mockRepoServiceClient.On("GetFile", mock.Anything, mock.Anything).Return(fakeFileResponse(), nil)
-	mockRepoServiceClient.On("ListDir", mock.Anything, mock.Anything).Return(fakeListDirResponse(), nil)
+	mockRepoServiceClient.On("ListApps", mock.Anything, mock.Anything).Return(fakeAppList(), nil)
 	mockRepoServiceClient.On("GenerateManifest", mock.Anything, mock.Anything).Return(&apiclient.ManifestResponse{}, nil)
+	mockRepoServiceClient.On("GetAppDetails", mock.Anything, mock.Anything).Return(&apiclient.RepoAppDetailsResponse{}, nil)
 
 	mockRepoClient := &mockrepo.Clientset{}
 	mockRepoClient.On("NewRepoServerClient").Return(&fakeCloser{}, &mockRepoServiceClient, nil)
diff --git a/server/repository/repository.go b/server/repository/repository.go
index 5519661db0c3d..32efb612e422f 100644
--- a/server/repository/repository.go
+++ b/server/repository/repository.go
@@ -1,14 +1,9 @@
 package repository
 
 import (
-	"errors"
 	"fmt"
-	"path"
-	"path/filepath"
 	"reflect"
 
-	"github.com/argoproj/argo-cd/util/settings"
-
 	log "github.com/sirupsen/logrus"
 	"golang.org/x/net/context"
 	"google.golang.org/grpc/codes"
@@ -20,12 +15,12 @@ import (
 	"github.com/argoproj/argo-cd/reposerver/apiclient"
 	"github.com/argoproj/argo-cd/server/rbacpolicy"
 	"github.com/argoproj/argo-cd/util"
-	"github.com/argoproj/argo-cd/util/argo"
 	"github.com/argoproj/argo-cd/util/cache"
 	"github.com/argoproj/argo-cd/util/db"
-	"github.com/argoproj/argo-cd/util/git"
-	"github.com/argoproj/argo-cd/util/kustomize"
 	"github.com/argoproj/argo-cd/util/rbac"
+	"github.com/argoproj/argo-cd/util/repo/factory"
+	"github.com/argoproj/argo-cd/util/repo/metrics"
+	"github.com/argoproj/argo-cd/util/settings"
 )
 
 // Server provides a Repository service
@@ -63,9 +58,10 @@ func (s *Server) getConnectionState(ctx context.Context, url string) appsv1.Conn
 		Status:     appsv1.ConnectionStatusSuccessful,
 		ModifiedAt: &now,
 	}
+	var err error
 	repo, err := s.db.GetRepository(ctx, url)
 	if err == nil {
-		err = git.TestRepo(repo.Repo, argo.GetRepoCreds(repo), repo.IsInsecure(), repo.EnableLFS)
+		_, err = factory.NewFactory().NewRepo(repo, metrics.NopReporter)
 	}
 	if err != nil {
 		connectionState.Status = appsv1.ConnectionStatusFailed
@@ -80,19 +76,18 @@ func (s *Server) getConnectionState(ctx context.Context, url string) appsv1.Conn
 
 // List returns list of repositories
 func (s *Server) List(ctx context.Context, q *repositorypkg.RepoQuery) (*appsv1.RepositoryList, error) {
-	urls, err := s.db.ListRepoURLs(ctx)
+	repos, err := s.db.ListRepositories(ctx)
 	if err != nil {
 		return nil, err
 	}
-	items := make([]appsv1.Repository, 0)
-	for _, url := range urls {
-		if s.enf.Enforce(ctx.Value("claims"), rbacpolicy.ResourceRepositories, rbacpolicy.ActionGet, url) {
-			repo, err := s.db.GetRepository(ctx, url)
-			if err != nil {
-				return nil, err
-			}
-			items = append(items, appsv1.Repository{
-				Repo:      url,
+	items := appsv1.Repositories{}
+	for _, repo := range repos {
+		if s.enf.Enforce(ctx.Value("claims"), rbacpolicy.ResourceRepositories, rbacpolicy.ActionGet, repo.Repo) {
+			// remove secrets
+			items = append(items, &appsv1.Repository{
+				Repo:      repo.Repo,
+				Type:      repo.Type,
+				Name:      repo.Name,
 				Username:  repo.Username,
 				Insecure:  repo.IsInsecure(),
 				EnableLFS: repo.EnableLFS,
@@ -109,69 +104,6 @@ func (s *Server) List(ctx context.Context, q *repositorypkg.RepoQuery) (*appsv1.
 	return &appsv1.RepositoryList{Items: items}, nil
 }
 
-func (s *Server) listAppsPaths(
-	ctx context.Context, repoClient apiclient.RepoServerServiceClient, repo *appsv1.Repository, revision string, subPath string) (map[string]appsv1.ApplicationSourceType, error) {
-
-	if revision == "" {
-		revision = "HEAD"
-	}
-
-	ksonnetRes, err := repoClient.ListDir(ctx, &apiclient.ListDirRequest{Repo: repo, Revision: revision, Path: path.Join(subPath, "*app.yaml")})
-	if err != nil {
-		return nil, err
-	}
-	componentRes, err := repoClient.ListDir(ctx, &apiclient.ListDirRequest{Repo: repo, Revision: revision, Path: path.Join(subPath, "*components/params.libsonnet")})
-	if err != nil {
-		return nil, err
-	}
-
-	helmRes, err := repoClient.ListDir(ctx, &apiclient.ListDirRequest{Repo: repo, Revision: revision, Path: path.Join(subPath, "*Chart.yaml")})
-	if err != nil {
-		return nil, err
-	}
-
-	kustomizationRes, err := getKustomizationRes(ctx, repoClient, repo, revision, subPath)
-	if err != nil {
-		return nil, err
-	}
-
-	componentDirs := make(map[string]interface{})
-	for _, i := range componentRes.Items {
-		d := filepath.Dir(filepath.Dir(i))
-		componentDirs[d] = struct{}{}
-	}
-
-	pathToType := make(map[string]appsv1.ApplicationSourceType)
-	for _, i := range ksonnetRes.Items {
-		d := filepath.Dir(i)
-		if _, ok := componentDirs[d]; ok {
-			pathToType[i] = appsv1.ApplicationSourceTypeKsonnet
-		}
-	}
-
-	for i := range helmRes.Items {
-		pathToType[helmRes.Items[i]] = appsv1.ApplicationSourceTypeHelm
-	}
-
-	for i := range kustomizationRes.Items {
-		pathToType[kustomizationRes.Items[i]] = appsv1.ApplicationSourceTypeKustomize
-	}
-	return pathToType, nil
-}
-
-func getKustomizationRes(ctx context.Context, repoClient apiclient.RepoServerServiceClient, repo *appsv1.Repository, revision string, subPath string) (*apiclient.FileList, error) {
-	for _, kustomization := range kustomize.KustomizationNames {
-		request := apiclient.ListDirRequest{Repo: repo, Revision: revision, Path: path.Join(subPath, "*"+kustomization)}
-		kustomizationRes, err := repoClient.ListDir(ctx, &request)
-		if err != nil {
-			return nil, err
-		} else {
-			return kustomizationRes, nil
-		}
-	}
-	return nil, errors.New("could not find kustomization")
-}
-
 // ListApps returns list of apps in the repo
 func (s *Server) ListApps(ctx context.Context, q *repositorypkg.RepoAppsQuery) (*repositorypkg.RepoAppsResponse, error) {
 	if err := s.enf.EnforceErr(ctx.Value("claims"), rbacpolicy.ResourceRepositories, rbacpolicy.ActionGet, q.Repo); err != nil {
@@ -189,18 +121,16 @@ func (s *Server) ListApps(ctx context.Context, q *repositorypkg.RepoAppsQuery) (
 	}
 	defer util.Close(conn)
 
-	revision := q.Revision
-	if revision == "" {
-		revision = "HEAD"
-	}
-
-	paths, err := s.listAppsPaths(ctx, repoClient, repo, revision, "")
+	apps, err := repoClient.ListApps(ctx, &apiclient.ListAppsRequest{
+		Repo:     repo,
+		Revision: q.Revision,
+	})
 	if err != nil {
 		return nil, err
 	}
 	items := make([]*repositorypkg.AppInfo, 0)
-	for appFilePath, appType := range paths {
-		items = append(items, &repositorypkg.AppInfo{Path: path.Dir(appFilePath), Type: string(appType)})
+	for app, appType := range apps.Apps {
+		items = append(items, &repositorypkg.AppInfo{Path: app, Type: appType})
 	}
 	return &repositorypkg.RepoAppsResponse{Items: items}, nil
 }
@@ -218,7 +148,7 @@ func (s *Server) GetAppDetails(ctx context.Context, q *repositorypkg.RepoAppDeta
 		return nil, err
 	}
 	defer util.Close(conn)
-	helmRepos, err := s.db.ListHelmRepos(ctx)
+	repos, err := s.db.ListRepositories(ctx)
 	if err != nil {
 		return nil, err
 	}
@@ -227,12 +157,12 @@ func (s *Server) GetAppDetails(ctx context.Context, q *repositorypkg.RepoAppDeta
 		return nil, err
 	}
 	return repoClient.GetAppDetails(ctx, &apiclient.RepoServerAppDetailsQuery{
-		Repo:      repo,
-		Revision:  q.Revision,
-		Path:      q.Path,
-		HelmRepos: helmRepos,
-		Helm:      q.Helm,
-		Ksonnet:   q.Ksonnet,
+		Repo:     repo,
+		Revision: q.Revision,
+		App:      q.Path,
+		Repos:    repos,
+		Helm:     q.Helm,
+		Ksonnet:  q.Ksonnet,
 		KustomizeOptions: &appsv1.KustomizeOptions{
 			BuildOptions: buildOptions,
 		},
@@ -241,11 +171,12 @@ func (s *Server) GetAppDetails(ctx context.Context, q *repositorypkg.RepoAppDeta
 
 // Create creates a repository
 func (s *Server) Create(ctx context.Context, q *repositorypkg.RepoCreateRequest) (*appsv1.Repository, error) {
-	if err := s.enf.EnforceErr(ctx.Value("claims"), rbacpolicy.ResourceRepositories, rbacpolicy.ActionCreate, q.Repo.Repo); err != nil {
+	err := s.enf.EnforceErr(ctx.Value("claims"), rbacpolicy.ResourceRepositories, rbacpolicy.ActionCreate, q.Repo.Repo)
+	if err != nil {
 		return nil, err
 	}
 	r := q.Repo
-	err := git.TestRepo(r.Repo, argo.GetRepoCreds(r), r.IsInsecure(), r.EnableLFS)
+	_, err = factory.NewFactory().NewRepo(q.Repo, metrics.NopReporter)
 	if err != nil {
 		return nil, err
 	}
@@ -269,7 +200,7 @@ func (s *Server) Create(ctx context.Context, q *repositorypkg.RepoCreateRequest)
 			return nil, status.Errorf(codes.InvalidArgument, "existing repository spec is different; use upsert flag to force update")
 		}
 	}
-	return &appsv1.Repository{Repo: repo.Repo}, err
+	return &appsv1.Repository{Repo: repo.Repo, Type: repo.Type, Name: repo.Name}, err
 }
 
 // Update updates a repository
@@ -278,7 +209,7 @@ func (s *Server) Update(ctx context.Context, q *repositorypkg.RepoUpdateRequest)
 		return nil, err
 	}
 	_, err := s.db.UpdateRepository(ctx, q.Repo)
-	return &appsv1.Repository{Repo: q.Repo.Repo}, err
+	return &appsv1.Repository{Repo: q.Repo.Repo, Type: q.Repo.Type, Name: q.Repo.Name}, err
 }
 
 // Delete updates a repository
@@ -304,17 +235,20 @@ func (s *Server) ValidateAccess(ctx context.Context, q *repositorypkg.RepoAccess
 	}
 
 	repo := &appsv1.Repository{
+		Repo:              q.Repo,
+		Type:              q.Type,
+		Name:              q.Name,
 		Username:          q.Username,
 		Password:          q.Password,
 		SSHPrivateKey:     q.SshPrivateKey,
 		Insecure:          q.Insecure,
 		TLSClientCertData: q.TlsClientCertData,
 		TLSClientCertKey:  q.TlsClientCertKey,
+		TLSClientCAData:   q.TlsClientCAData,
 	}
-	err := git.TestRepo(q.Repo, argo.GetRepoCreds(repo), q.Insecure, false)
+	_, err := factory.NewFactory().NewRepo(repo, metrics.NopReporter)
 	if err != nil {
 		return nil, err
 	}
-
-	return &repositorypkg.RepoResponse{}, err
+	return &repositorypkg.RepoResponse{}, nil
 }
diff --git a/server/repository/repository.proto b/server/repository/repository.proto
index 4b7a026c606b6..d3738e839faa2 100644
--- a/server/repository/repository.proto
+++ b/server/repository/repository.proto
@@ -60,6 +60,11 @@ message RepoAccessQuery {
 	string tlsClientCertData = 6;
 	// TLS client cert key for accessing HTTPS repository
 	string tlsClientCertKey = 7;
+	// TLS client CA data for accessing HTTPS repository
+	string tlsClientCAData = 8;
+	string type = 9;
+	// The name of the repo
+	string name = 10;
 }
 
 message RepoResponse {}
diff --git a/test/e2e/delarative_test.go b/test/e2e/delarative_test.go
index 402878d797c27..6e4aa0072d868 100644
--- a/test/e2e/delarative_test.go
+++ b/test/e2e/delarative_test.go
@@ -68,7 +68,7 @@ func TestDeclarativeInvalidRepoURL(t *testing.T) {
 		Expect(Success("")).
 		Expect(HealthIs(HealthStatusHealthy)).
 		Expect(SyncStatusIs(SyncStatusCodeUnknown)).
-		Expect(Condition(ApplicationConditionComparisonError, "repository not found")).
+		Expect(Condition(ApplicationConditionComparisonError, "repository 'http://github.com/' not found")).
 		When().
 		Delete(false).
 		Then().
diff --git a/test/e2e/fixture/app/actions.go b/test/e2e/fixture/app/actions.go
index e3d94e3f814c5..01f62a602331d 100644
--- a/test/e2e/fixture/app/actions.go
+++ b/test/e2e/fixture/app/actions.go
@@ -137,6 +137,10 @@ func (a *Actions) Create() *Actions {
 		args = append(args, "--config-management-plugin", a.context.configManagementPlugin)
 	}
 
+	if a.context.revision != "" {
+		args = append(args, "--revision", a.context.revision)
+	}
+
 	a.runCli(args...)
 
 	return a
diff --git a/test/e2e/fixture/app/context.go b/test/e2e/fixture/app/context.go
index 62f58fcaff743..e2be32d1bcb3f 100644
--- a/test/e2e/fixture/app/context.go
+++ b/test/e2e/fixture/app/context.go
@@ -2,6 +2,7 @@ package app
 
 import (
 	"testing"
+	"time"
 
 	. "github.com/argoproj/argo-cd/common"
 	"github.com/argoproj/argo-cd/pkg/apis/application/v1alpha1"
@@ -31,6 +32,7 @@ type Context struct {
 	async                  bool
 	localPath              string
 	project                string
+	revision               string
 	force                  bool
 }
 
@@ -94,6 +96,11 @@ func (c *Context) Path(path string) *Context {
 	return c
 }
 
+func (c *Context) Revision(revision string) *Context {
+	c.revision = revision
+	return c
+}
+
 func (c *Context) Timeout(timeout int) *Context {
 	c.timeout = timeout
 	return c
@@ -152,8 +159,8 @@ func (c *Context) ConfigManagementPlugin(plugin v1alpha1.ConfigManagementPlugin)
 	return c
 }
 
-func (c *Context) HelmRepoCredential(name, url string) *Context {
-	fixture.SetHelmRepoCredential(settings.HelmRepoCredentials{Name: name, URL: url})
+func (c *Context) Repos(repos ...settings.RepoCredentials) *Context {
+	fixture.SetRepos(repos...)
 	return c
 }
 
@@ -163,6 +170,8 @@ func (c *Context) And(block func()) *Context {
 }
 
 func (c *Context) When() *Actions {
+	// in case any settings have changed, pause for 1s, not great, but fine
+	time.Sleep(1 * time.Second)
 	return &Actions{context: c}
 }
 
diff --git a/test/e2e/fixture/fixture.go b/test/e2e/fixture/fixture.go
index 657bc8727cb9b..1cc4273a4f43d 100644
--- a/test/e2e/fixture/fixture.go
+++ b/test/e2e/fixture/fixture.go
@@ -27,6 +27,7 @@ import (
 	sessionpkg "github.com/argoproj/argo-cd/pkg/apiclient/session"
 	"github.com/argoproj/argo-cd/pkg/apis/application/v1alpha1"
 	appclientset "github.com/argoproj/argo-cd/pkg/client/clientset/versioned"
+	"github.com/argoproj/argo-cd/test/fixture/testrepos"
 	"github.com/argoproj/argo-cd/util"
 	grpcutil "github.com/argoproj/argo-cd/util/grpc"
 	"github.com/argoproj/argo-cd/util/rand"
@@ -65,6 +66,7 @@ const (
 	RepoURLTypeHTTPS           = "https"
 	RepoURLTypeHTTPSClientCert = "https-cc"
 	RepoURLTypeSSH             = "ssh"
+	RepoURLTypeHelm            = "helm"
 	GitUsername                = "admin"
 	GitPassword                = "password"
 )
@@ -142,6 +144,8 @@ func RepoURL(urlType RepoURLType) string {
 	case RepoURLTypeHTTPSClientCert:
 		return "https://localhost:9444/argo-e2e/testdata.git"
 	// Default - file based Git repository
+	case RepoURLTypeHelm:
+		return testrepos.HelmTestRepo
 	default:
 		return fmt.Sprintf("file://%s", repoDirectory())
 	}
@@ -280,17 +284,6 @@ func SetSSHKnownHosts() {
 	})
 }
 
-func SetHelmRepoCredential(creds settings.HelmRepoCredentials) {
-	updateSettingConfigMap(func(cm *corev1.ConfigMap) error {
-		yamlBytes, err := yaml.Marshal(creds)
-		if err != nil {
-			return err
-		}
-		cm.Data["helm.repositories"] = string(yamlBytes)
-		return nil
-	})
-}
-
 func SetProjectSpec(project string, spec v1alpha1.AppProjectSpec) {
 	proj, err := AppClientset.ArgoprojV1alpha1().AppProjects(ArgoCDNamespace).Get(project, v1.GetOptions{})
 	errors.CheckError(err)
diff --git a/test/e2e/helm_test.go b/test/e2e/helm_test.go
index 83052be5e6c7a..b724d1d3ec06d 100644
--- a/test/e2e/helm_test.go
+++ b/test/e2e/helm_test.go
@@ -7,8 +7,11 @@ import (
 	v1 "k8s.io/api/core/v1"
 
 	. "github.com/argoproj/argo-cd/pkg/apis/application/v1alpha1"
+	"github.com/argoproj/argo-cd/test/e2e/fixture"
 	. "github.com/argoproj/argo-cd/test/e2e/fixture"
 	. "github.com/argoproj/argo-cd/test/e2e/fixture/app"
+	"github.com/argoproj/argo-cd/test/fixture/testrepos"
+	"github.com/argoproj/argo-cd/util/settings"
 )
 
 func TestHelmHooksAreCreated(t *testing.T) {
@@ -94,15 +97,37 @@ func TestDeclarativeHelmInvalidValuesFile(t *testing.T) {
 		Expect(Condition(ApplicationConditionComparisonError, "open does-not-exist-values.yaml: no such file or directory"))
 }
 
+func TestHelmRepo(t *testing.T) {
+	Given(t).
+		Repos(settings.RepoCredentials{
+			Type: "helm",
+			Name: "testrepo",
+			URL:  testrepos.HelmTestRepo,
+		}).
+		RepoURLType(fixture.RepoURLTypeHelm).
+		Path("helm").
+		Revision("1.0.0").
+		When().
+		Create().
+		Then().
+		When().
+		Sync().
+		Then().
+		Expect(OperationPhaseIs(OperationSucceeded)).
+		Expect(HealthIs(HealthStatusHealthy)).
+		Expect(SyncStatusIs(SyncStatusCodeSynced))
+}
+
 func TestHelmValues(t *testing.T) {
 	Given(t).
 		Path("helm").
 		When().
+		AddFile("foo.yml", "").
 		Create().
-		AppSet("--values", "foo").
+		AppSet("--values", "foo.yml").
 		Then().
 		And(func(app *Application) {
-			assert.Equal(t, []string{"foo"}, app.Spec.Source.Helm.ValueFiles)
+			assert.Equal(t, []string{"foo.yml"}, app.Spec.Source.Helm.ValueFiles)
 		})
 }
 
diff --git a/test/e2e/repo_creds_test.go b/test/e2e/repo_creds_test.go
index d3c8c8f4b30b6..00379a1594df6 100644
--- a/test/e2e/repo_creds_test.go
+++ b/test/e2e/repo_creds_test.go
@@ -18,7 +18,7 @@ func TestCannotAddAppFromPrivateRepoWithoutCfg(t *testing.T) {
 		IgnoreErrors().
 		Create().
 		Then().
-		Expect(Error("", "repository not accessible"))
+		Expect(Error("", "unable to access"))
 }
 
 // make sure you cannot create an app from a private repo without set-up
@@ -31,7 +31,7 @@ func TestCannotAddAppFromClientCertRepoWithoutCfg(t *testing.T) {
 		IgnoreErrors().
 		Create().
 		Then().
-		Expect(Error("", "repository not accessible"))
+		Expect(Error("", "unable to access"))
 }
 
 // make sure you can create an app from a private repo, if the repo is set-up in the CM
diff --git a/test/e2e/repo_management_test.go b/test/e2e/repo_management_test.go
index 0e77f28cc366e..7585f953ca437 100644
--- a/test/e2e/repo_management_test.go
+++ b/test/e2e/repo_management_test.go
@@ -8,6 +8,7 @@ import (
 
 	repositorypkg "github.com/argoproj/argo-cd/pkg/apiclient/repository"
 	"github.com/argoproj/argo-cd/test/e2e/fixture"
+	"github.com/argoproj/argo-cd/test/fixture/testrepos"
 	"github.com/argoproj/argo-cd/util"
 )
 
@@ -17,7 +18,7 @@ func TestAddRemovePublicRepo(t *testing.T) {
 	assert.NoError(t, err)
 
 	conn, repoClient, err := fixture.ArgoCDClientset.NewRepoClient()
-	assert.Nil(t, err)
+	assert.NoError(t, err)
 	defer util.Close(conn)
 
 	repo, err := repoClient.List(context.Background(), &repositorypkg.RepoQuery{})
@@ -33,10 +34,10 @@ func TestAddRemovePublicRepo(t *testing.T) {
 	assert.True(t, exists)
 
 	_, err = fixture.RunCli("repo", "rm", repoUrl)
-	assert.Nil(t, err)
+	assert.NoError(t, err)
 
 	repo, err = repoClient.List(context.Background(), &repositorypkg.RepoQuery{})
-	assert.Nil(t, err)
+	assert.NoError(t, err)
 	exists = false
 	for i := range repo.Items {
 		if repo.Items[i].Repo == repoUrl {
@@ -46,3 +47,38 @@ func TestAddRemovePublicRepo(t *testing.T) {
 	}
 	assert.False(t, exists)
 }
+
+func TestAddRemoveHelmRepo(t *testing.T) {
+	_, err := fixture.RunCli("repo", "add", testrepos.HelmTestRepo, "--name", "testrepo", "--type", "helm")
+	assert.NoError(t, err)
+
+	conn, repoClient, err := fixture.ArgoCDClientset.NewRepoClient()
+	assert.NoError(t, err)
+	defer util.Close(conn)
+
+	repo, err := repoClient.List(context.Background(), &repositorypkg.RepoQuery{})
+
+	assert.NoError(t, err)
+	exists := false
+	for i := range repo.Items {
+		if repo.Items[i].Repo == testrepos.HelmTestRepo {
+			exists = true
+			break
+		}
+	}
+	assert.True(t, exists)
+
+	_, err = fixture.RunCli("repo", "rm", testrepos.HelmTestRepo)
+	assert.NoError(t, err)
+
+	repo, err = repoClient.List(context.Background(), &repositorypkg.RepoQuery{})
+	assert.NoError(t, err)
+	exists = false
+	for i := range repo.Items {
+		if repo.Items[i].Repo == testrepos.HelmTestRepo {
+			exists = true
+			break
+		}
+	}
+	assert.False(t, exists)
+}
diff --git a/test/e2e/testdata/helm-1.0.0.tgz b/test/e2e/testdata/helm-1.0.0.tgz
new file mode 100644
index 0000000000000..4b750d0206ad7
Binary files /dev/null and b/test/e2e/testdata/helm-1.0.0.tgz differ
diff --git a/test/e2e/testdata/index.yaml b/test/e2e/testdata/index.yaml
new file mode 100644
index 0000000000000..a88292d5c1647
--- /dev/null
+++ b/test/e2e/testdata/index.yaml
@@ -0,0 +1,7 @@
+apiVersion: v1
+entries:
+  helm:
+    - created: 2019-07-08T23:26:50.723856689Z
+      urls:
+        - https://github.com/alexec/argo-cd/blob/helm-1st-class/test/e2e/testdata/helm-1.0.0.tgz?raw=true
+      version: 1.0.0
\ No newline at end of file
diff --git a/test/fixture/testrepos/helm_test_repo.go b/test/fixture/testrepos/helm_test_repo.go
new file mode 100644
index 0000000000000..3019786173a74
--- /dev/null
+++ b/test/fixture/testrepos/helm_test_repo.go
@@ -0,0 +1,3 @@
+package testrepos
+
+const HelmTestRepo = "https://raw.githubusercontent.com/alexec/argo-cd/helm-1st-class/test/e2e/testdata"
diff --git a/ui/src/app/applications/components/application-create-panel/application-create-panel.tsx b/ui/src/app/applications/components/application-create-panel/application-create-panel.tsx
index 17d88aa59db6d..db538611d51af 100644
--- a/ui/src/app/applications/components/application-create-panel/application-create-panel.tsx
+++ b/ui/src/app/applications/components/application-create-panel/application-create-panel.tsx
@@ -32,7 +32,7 @@ const DEFAULT_APP: Partial<models.Application> = {
         source: {
             path: '',
             repoURL: '',
-            targetRevision: 'HEAD',
+            targetRevision: '',
         },
         project: '',
     },
@@ -109,7 +109,6 @@ export const ApplicationCreatePanel = (props: {
                                 'metadata.name': !a.metadata.name && 'Application name is required',
                                 'spec.project': !a.spec.project && 'Project name is required',
                                 'spec.source.repoURL': !a.spec.source.repoURL && 'Repository URL is required',
-                                'spec.source.targetRevision': !a.spec.source.targetRevision && 'Revision is required',
                                 'spec.source.path': !a.spec.source.path && 'Path is required',
                                 'spec.destination.server': !a.spec.destination.server && 'Cluster is required',
                                 'spec.destination.namespace': !a.spec.destination.namespace && 'Namespace is required',
diff --git a/ui/src/app/applications/components/application-deployment-history/revision-metadata-rows.tsx b/ui/src/app/applications/components/application-deployment-history/revision-metadata-rows.tsx
index f95a57964aaba..795b4c3273edb 100644
--- a/ui/src/app/applications/components/application-deployment-history/revision-metadata-rows.tsx
+++ b/ui/src/app/applications/components/application-deployment-history/revision-metadata-rows.tsx
@@ -10,14 +10,15 @@ export const RevisionMetadataRows = (props: {
 }) => {
     return (
         <DataLoader input={props}
-                    load={(input) => services.applications.revisionMetadata(input.applicationName, input.revision || 'HEAD')}
+                    load={(input) => services.applications.revisionMetadata(input.applicationName, input.revision || '')}
         >{(m: RevisionMetadata) => (
             <div>
+
                 <div className='row'>
                     <div className='columns small-3'>Authored by</div>
                     <div className='columns small-9'>
-                        {m.author}<br/>
-                        <Timestamp date={m.date}/>
+                        {m.author || 'unknown'}<br/>
+                        {m.date && <Timestamp date={m.date}/>}
                     </div>
                 </div>
                 {m.tags && (
@@ -26,10 +27,12 @@ export const RevisionMetadataRows = (props: {
                         <div className='columns small-9'>{m.tags.join(', ')}</div>
                     </div>
                 )}
-                <div className='row'>
-                    <div className='columns small-3'/>
-                    <div className='columns small-9'>{m.message}</div>
-                </div>
+                {m.message && (
+                    <div className='row'>
+                        <div className='columns small-3'/>
+                        <div className='columns small-9'>{m.message}</div>
+                    </div>
+                )}
             </div>
         )}</DataLoader>
     );
diff --git a/ui/src/app/applications/components/application-status-panel/revision-metadata-panel.tsx b/ui/src/app/applications/components/application-status-panel/revision-metadata-panel.tsx
index 296e79e4e9d2c..450884631bb3d 100644
--- a/ui/src/app/applications/components/application-status-panel/revision-metadata-panel.tsx
+++ b/ui/src/app/applications/components/application-status-panel/revision-metadata-panel.tsx
@@ -10,17 +10,18 @@ export const RevisionMetadataPanel = (props: {
 }) => {
     return (
         <DataLoader input={props}
-                    load={(input) => services.applications.revisionMetadata(input.applicationName, input.revision || 'HEAD')}
+                    load={(input) => services.applications.revisionMetadata(input.applicationName, input.revision || '')}
         >{(m: RevisionMetadata) => (
             <Tooltip content={(
                 <span>
-            <span>Authored by {m.author} <Timestamp date={m.date}/></span><br/>
+                    {m.author && <React.Fragment>Authored by {m.author}</React.Fragment>}
+                    {m.date && <Timestamp date={m.date}/>}<br/>
                     {m.tags && (<span>Tags: {m.tags}<br/></span>)}
-                    <span>{m.message}</span>
-        </span>
+                    (m.message}
+                </span>
             )} placement='bottom' allowHTML={true}>
                 <div className='application-status-panel__item-name'>
-                    Authored by {m.author}<br/>
+                    {m.author && <React.Fragment>Authored by {m.author}<br/></React.Fragment>}
                     {m.tags && <span>Tagged {m.tags.join(', ')}<br/></span>}
                     {m.message}
                 </div>
diff --git a/ui/src/app/applications/components/application-sync-panel/application-sync-panel.tsx b/ui/src/app/applications/components/application-sync-panel/application-sync-panel.tsx
index 519e03035a3b1..711ee0d64bf96 100644
--- a/ui/src/app/applications/components/application-sync-panel/application-sync-panel.tsx
+++ b/ui/src/app/applications/components/application-sync-panel/application-sync-panel.tsx
@@ -35,7 +35,7 @@ export const ApplicationSyncPanel = ({application, selectedResource, hide}: {
             {isVisible && (
                 <Form
                     defaultValues={{
-                        revision: application.spec.source.targetRevision || 'HEAD',
+                        revision: application.spec.source.targetRevision,
                         resources: appResources.filter((item) => !item.hook).map((_, i) => i === syncResIndex || syncResIndex === -1),
                     }}
                     validateError={(values) => ({
diff --git a/ui/src/app/applications/components/applications-list/applications-tiles.tsx b/ui/src/app/applications/components/applications-list/applications-tiles.tsx
index 79e9508c29584..3fbfe5e9907db 100644
--- a/ui/src/app/applications/components/applications-list/applications-tiles.tsx
+++ b/ui/src/app/applications/components/applications-list/applications-tiles.tsx
@@ -55,7 +55,7 @@ export const ApplicationTiles = ({applications, syncApplication, refreshApplicat
                             </div>
                             <div className='row'>
                                 <div className='columns small-3'>Target Revision:</div>
-                                <div className='columns small-9'>{app.spec.source.targetRevision || 'HEAD'}</div>
+                                <div className='columns small-9'>{app.spec.source.targetRevision || 'latest'}</div>
                             </div>
                             <div className='row'>
                                 <div className='columns small-3'>Path:</div>
diff --git a/ui/src/app/applications/components/utils.tsx b/ui/src/app/applications/components/utils.tsx
index 1af491c1a1d3d..5c90095586978 100644
--- a/ui/src/app/applications/components/utils.tsx
+++ b/ui/src/app/applications/components/utils.tsx
@@ -130,7 +130,7 @@ export const ComparisonStatusIcon = ({status, resource, label}: { status: appMod
 };
 
 export function syncStatusMessage(app: appModels.Application) {
-    let rev = app.spec.source.targetRevision || 'HEAD';
+    let rev = app.spec.source.targetRevision || 'latest';
     if (app.status.sync.revision && (app.status.sync.revision.length >= 7 && !app.status.sync.revision.startsWith(app.spec.source.targetRevision))) {
         rev += ' (' + app.status.sync.revision.substr(0, 7) + ')';
     }
@@ -138,12 +138,12 @@ export function syncStatusMessage(app: appModels.Application) {
         case appModels.SyncStatuses.Synced:
             return (
                 <span>To <Revision repoUrl={app.spec.source.repoURL}
-                                   revision={app.spec.source.targetRevision || 'HEAD'}>{rev}</Revision> </span>
+                                   revision={app.spec.source.targetRevision || 'latest'}>{rev}</Revision> </span>
             );
         case appModels.SyncStatuses.OutOfSync:
             return (
                 <span>From <Revision repoUrl={app.spec.source.repoURL}
-                                     revision={app.spec.source.targetRevision || 'HEAD'}>{rev}</Revision> </span>
+                                     revision={app.spec.source.targetRevision || 'latest'}>{rev}</Revision> </span>
             );
         default:
             return <span>{rev}</span>;
diff --git a/ui/src/app/settings/components/project-edit-panel/project-edit-panel.tsx b/ui/src/app/settings/components/project-edit-panel/project-edit-panel.tsx
index e1c4cc9ec3005..38f610b2b819c 100644
--- a/ui/src/app/settings/components/project-edit-panel/project-edit-panel.tsx
+++ b/ui/src/app/settings/components/project-edit-panel/project-edit-panel.tsx
@@ -48,7 +48,7 @@ export const ProjectEditPanel = (props: {
                     {(repos) => (
                         <React.Fragment>
                         <h4>Sources</h4>
-                        <div>Git repositories where application manifests are permitted to be retrieved from</div>
+                            <div>Repositories where application manifests are permitted to be retrieved from</div>
                         {(api.values.sourceRepos as Array<string>).map((_, i) => (
                             <div key={i} className='row project-edit-panel__form-row'>
                                 <div className='columns small-12'>
diff --git a/ui/src/app/settings/components/repos-list/repos-list.tsx b/ui/src/app/settings/components/repos-list/repos-list.tsx
index 2d359fc0e7803..f3669060b8e2c 100644
--- a/ui/src/app/settings/components/repos-list/repos-list.tsx
+++ b/ui/src/app/settings/components/repos-list/repos-list.tsx
@@ -12,6 +12,8 @@ import {services} from '../../../shared/services';
 require('./repos-list.scss');
 
 interface NewSSHRepoParams {
+    type: string;
+    name: string;
     url: string;
     sshPrivateKey: string;
     insecure: boolean;
@@ -19,6 +21,8 @@ interface NewSSHRepoParams {
 }
 
 interface NewHTTPSRepoParams {
+    type: string;
+    name: string;
     url: string;
     username: string;
     password: string;
@@ -62,16 +66,20 @@ export class ReposList extends React.Component<RouteComponentProps<any>> {
                                     <div className='argo-table-list'>
                                         <div className='argo-table-list__head'>
                                             <div className='row'>
-                                                <div className='columns small-9'>REPOSITORY</div>
+                                                <div className='columns small-5'>REPOSITORY</div>
+                                                <div className='columns small-2'>TYPE</div>
+                                                <div className='columns small-2'>NAME</div>
                                                 <div className='columns small-3'>CONNECTION STATUS</div>
                                             </div>
                                         </div>
                                         {repos.map((repo) => (
                                             <div className='argo-table-list__row' key={repo.repo}>
                                                 <div className='row'>
-                                                    <div className='columns small-9'>
-                                                        <i className='icon argo-icon-git'/> <Repo url={repo.repo}/>
+                                                    <div className='columns small-5'>
+                                                        <i className={'icon argo-icon-' + repo.type}/> <Repo url={repo.repo}/>
                                                     </div>
+                                                    <div className='columns small-2'>{repo.type}</div>
+                                                    <div className='columns small-2'>{repo.name}</div>
                                                     <div className='columns small-3'>
                                                         <ConnectionStateIcon
                                                             state={repo.connectionState}/> {repo.connectionState.status}
@@ -116,7 +124,7 @@ export class ReposList extends React.Component<RouteComponentProps<any>> {
                         </button>
                     </div>
                 )}>
-                    <h4>Connect Git repo using HTTPS</h4>
+                    <h4>Connect repo using HTTPS</h4>
                     <Form onSubmit={(params) => this.connectHTTPSRepo(params as NewHTTPSRepoParams)}
                           getApi={(api) => this.formApiHTTPS = api}
                           validateError={(params: NewHTTPSRepoParams) => ({
@@ -126,6 +134,13 @@ export class ReposList extends React.Component<RouteComponentProps<any>> {
                           })}>
                         {(formApi) => (
                             <form onSubmit={formApi.submitForm} role='form' className='repos-list width-control'>
+                                <div className='argo-form-row'>
+                                    <FormField formApi={formApi} label='Type' field='type' component={Text}/>
+                                    Either empty, "git" or "helm".
+                                </div>
+                                <div className='argo-form-row'>
+                                    <FormField formApi={formApi} label='Name' field='name' component={Text}/>
+                                </div>
                                 <div className='argo-form-row'>
                                     <FormField formApi={formApi} label='Repository URL' field='url' component={Text}/>
                                 </div>
@@ -162,7 +177,7 @@ export class ReposList extends React.Component<RouteComponentProps<any>> {
                         </button>
                     </div>
                 )}>
-                    <h4>Connect Git repo using SSH</h4>
+                    <h4>Connect repo using SSH</h4>
                     <Form onSubmit={(params) => this.connectSSHRepo(params as NewSSHRepoParams)}
                           getApi={(api) => this.formApiSSH = api}
                           validateError={(params: NewSSHRepoParams) => ({
@@ -171,6 +186,13 @@ export class ReposList extends React.Component<RouteComponentProps<any>> {
                           })}>
                         {(formApi) => (
                             <form onSubmit={formApi.submitForm} role='form' className='repos-list width-control'>
+                                <div className='argo-form-row'>
+                                    <FormField formApi={formApi} label='Type' field='type' component={Text}/>
+                                    Either empty, "git" or "helm".
+                                </div>
+                                <div className='argo-form-row'>
+                                    <FormField formApi={formApi} label='Name' field='name' component={Text}/>
+                                </div>
                                 <div className='argo-form-row'>
                                     <FormField formApi={formApi} label='Repository URL' field='url' component={Text}/>
                                 </div>
diff --git a/ui/src/app/settings/components/settings-overview/settings-overview.tsx b/ui/src/app/settings/components/settings-overview/settings-overview.tsx
index a750405906567..187c7c99c686f 100644
--- a/ui/src/app/settings/components/settings-overview/settings-overview.tsx
+++ b/ui/src/app/settings/components/settings-overview/settings-overview.tsx
@@ -7,7 +7,7 @@ import { AppContext } from '../../../shared/context';
 require('./settings-overview.scss');
 
 const settings = [{
-    title: 'Repositories', description: 'Configure connected Git repositories', path: './repos',
+    title: 'Repositories', description: 'Configure connected repositories', path: './repos',
 }, {
     title: 'Certificates', description: 'Configure certificates for connecting Git repositories', path: './certs',
 }, {
diff --git a/ui/src/app/shared/components/revision.tsx b/ui/src/app/shared/components/revision.tsx
index 95094a78f17b8..be2a0883890f7 100644
--- a/ui/src/app/shared/components/revision.tsx
+++ b/ui/src/app/shared/components/revision.tsx
@@ -2,7 +2,7 @@ import * as React from 'react';
 import {revisionUrl} from './urls';
 
 export const Revision = ({repoUrl, revision, children}: { repoUrl: string, revision: string, children?: React.ReactNode }) => {
-    revision = revision || 'HEAD';
+    revision = revision || '';
     const url = revisionUrl(repoUrl, revision);
     const content = children || revision.substr(0, 7);
     return url !== null ? <a href={url}>{content}</a> : <span>{content}</span>;
diff --git a/ui/src/app/shared/components/urls.ts b/ui/src/app/shared/components/urls.ts
index 384062e35c548..1954153368c04 100644
--- a/ui/src/app/shared/components/urls.ts
+++ b/ui/src/app/shared/components/urls.ts
@@ -26,5 +26,5 @@ export function revisionUrl(url: string, revision: string): string {
         return null;
     }
 
-    return `${protocol(parsed.protocol)}://${parsed.resource}/${parsed.owner}/${parsed.name}/${(url.indexOf('bitbucket') >= 0 ? 'commits' : 'commit')}/${revision}`;
+    return `${protocol(parsed.protocol)}://${parsed.resource}/${parsed.owner}/${parsed.name}/${(url.indexOf('bitbucket') >= 0 ? 'commits' : 'commit')}/${revision || 'HEAD'}`;
 }
diff --git a/ui/src/app/shared/models.ts b/ui/src/app/shared/models.ts
index e6a216b1721bd..95a8f7761aec8 100644
--- a/ui/src/app/shared/models.ts
+++ b/ui/src/app/shared/models.ts
@@ -67,10 +67,10 @@ export interface OperationState {
 export type HookType = 'PreSync' | 'Sync' | 'PostSync' | 'SyncFail' | 'Skip';
 
 export interface RevisionMetadata {
-    author: string;
+    author?: string;
     date: models.Time;
-    tags: string[];
-    message: string;
+    tags?: string[];
+    message?: string;
 }
 
 export interface SyncOperationResult {
@@ -373,6 +373,8 @@ export interface RepoCertList extends ItemsList<RepoCert> { }
 
 export interface Repository {
     repo: string;
+    type?: string;
+    name?: string;
     connectionState: ConnectionState;
 }
 
diff --git a/ui/src/app/shared/services/repo-service.ts b/ui/src/app/shared/services/repo-service.ts
index 7a24c92949b76..356755642d5ab 100644
--- a/ui/src/app/shared/services/repo-service.ts
+++ b/ui/src/app/shared/services/repo-service.ts
@@ -6,16 +6,16 @@ export class RepositoriesService {
         return requests.get('/repositories').then((res) => res.body as models.RepositoryList).then((list) => list.items || []);
     }
 
-    public createHTTPS({url, username, password, tlsClientCertData, tlsClientCertKey, insecure, enableLfs}:
-        {url: string, username: string, password: string, tlsClientCertData: string, tlsClientCertKey: string,
+    public createHTTPS({type, name, url, username, password, tlsClientCertData, tlsClientCertKey, insecure, enableLfs}:
+        {type: string, name: string, url: string, username: string, password: string, tlsClientCertData: string, tlsClientCertKey: string,
             insecure: boolean, enableLfs: boolean}): Promise<models.Repository> {
-        return requests.post('/repositories').send({ repo: url, username, password, tlsClientCertData, tlsClientCertKey, insecure, enableLfs })
+        return requests.post('/repositories').send({type, name, repo: url, username, password, tlsClientCertData, tlsClientCertKey, insecure, enableLfs })
             .then((res) => res.body as models.Repository);
     }
 
-    public createSSH({url, sshPrivateKey, insecure, enableLfs}:
-        {url: string, sshPrivateKey: string, insecure: boolean, enableLfs: boolean}): Promise<models.Repository> {
-        return requests.post('/repositories').send({ repo: url, sshPrivateKey, insecure, enableLfs }).then((res) => res.body as models.Repository);
+    public createSSH({type, name, url, sshPrivateKey, insecure, enableLfs}:
+        {type: string, name: string, url: string, sshPrivateKey: string, insecure: boolean, enableLfs: boolean}): Promise<models.Repository> {
+        return requests.post('/repositories').send({ type, name, repo: url, sshPrivateKey, insecure, enableLfs }).then((res) => res.body as models.Repository);
     }
 
     public delete(url: string): Promise<models.Repository> {
diff --git a/util/app/discovery/discovery.go b/util/app/discovery/discovery.go
new file mode 100644
index 0000000000000..227330c9ec01f
--- /dev/null
+++ b/util/app/discovery/discovery.go
@@ -0,0 +1,49 @@
+package discovery
+
+import (
+	"os"
+	"path/filepath"
+	"strings"
+
+	"github.com/argoproj/argo-cd/util/kustomize"
+)
+
+func Discover(root string) (map[string]string, error) {
+	apps := make(map[string]string)
+	err := filepath.Walk(root, func(path string, info os.FileInfo, err error) error {
+		if err != nil {
+			return err
+		}
+		if info.IsDir() {
+			return nil
+		}
+		dir, err := filepath.Rel(root, filepath.Dir(path))
+		if err != nil {
+			return err
+		}
+		base := filepath.Base(path)
+		if base == "params.libsonnet" && strings.HasSuffix(dir, "components") {
+			apps[filepath.Dir(dir)] = "Ksonnet"
+		}
+		if strings.HasSuffix(base, "Chart.yaml") {
+			apps[dir] = "Helm"
+		}
+		if kustomize.IsKustomization(base) {
+			apps[dir] = "Kustomize"
+		}
+		return nil
+	})
+	return apps, err
+}
+
+func AppType(path string) (string, error) {
+	apps, err := Discover(path)
+	if err != nil {
+		return "", err
+	}
+	appType, ok := apps["."]
+	if ok {
+		return appType, nil
+	}
+	return "Directory", nil
+}
diff --git a/util/app/discovery/discovery_test.go b/util/app/discovery/discovery_test.go
new file mode 100644
index 0000000000000..9d4bb057bf4a2
--- /dev/null
+++ b/util/app/discovery/discovery_test.go
@@ -0,0 +1,35 @@
+package discovery
+
+import (
+	"testing"
+
+	"github.com/stretchr/testify/assert"
+)
+
+func TestDiscover(t *testing.T) {
+	apps, err := Discover("./testdata")
+	assert.NoError(t, err)
+	assert.Equal(t, map[string]string{
+		"foo": "Kustomize",
+		"bar": "Ksonnet",
+		"baz": "Helm",
+	}, apps)
+}
+
+func TestAppType(t *testing.T) {
+	appType, err := AppType("./testdata/foo")
+	assert.NoError(t, err)
+	assert.Equal(t, "Kustomize", appType)
+
+	appType, err = AppType("./testdata/bar")
+	assert.NoError(t, err)
+	assert.Equal(t, "Ksonnet", appType)
+
+	appType, err = AppType("./testdata/baz")
+	assert.NoError(t, err)
+	assert.Equal(t, "Helm", appType)
+
+	appType, err = AppType("./testdata")
+	assert.NoError(t, err)
+	assert.Equal(t, "Directory", appType)
+}
diff --git a/reposerver/repository/testdata/file.txt b/util/app/discovery/testdata/bar/bar-components/params.libsonnet
similarity index 100%
rename from reposerver/repository/testdata/file.txt
rename to util/app/discovery/testdata/bar/bar-components/params.libsonnet
diff --git a/util/app/discovery/testdata/baz/Chart.yaml b/util/app/discovery/testdata/baz/Chart.yaml
new file mode 100644
index 0000000000000..e69de29bb2d1d
diff --git a/util/app/discovery/testdata/foo/Kustomization b/util/app/discovery/testdata/foo/Kustomization
new file mode 100644
index 0000000000000..e69de29bb2d1d
diff --git a/util/app/path/path.go b/util/app/path/path.go
new file mode 100644
index 0000000000000..dab84c3431bd9
--- /dev/null
+++ b/util/app/path/path.go
@@ -0,0 +1,29 @@
+package path
+
+import (
+	"fmt"
+	"os"
+	"path/filepath"
+	"strings"
+)
+
+func Path(root, path string) (string, error) {
+	if filepath.IsAbs(path) {
+		return "", fmt.Errorf("%s: app path is absolute", path)
+	}
+	appPath := filepath.Join(root, path)
+	if !strings.HasPrefix(appPath, filepath.Clean(root)) {
+		return "", fmt.Errorf("%s: app path outside root", path)
+	}
+	info, err := os.Stat(appPath)
+	if os.IsNotExist(err) {
+		return "", fmt.Errorf("%s: app path does not exist", path)
+	}
+	if err != nil {
+		return "", err
+	}
+	if !info.IsDir() {
+		return "", fmt.Errorf("%s: app path is not a directory", path)
+	}
+	return appPath, nil
+}
diff --git a/util/app/path/path_test.go b/util/app/path/path_test.go
new file mode 100644
index 0000000000000..1b6e14085f55c
--- /dev/null
+++ b/util/app/path/path_test.go
@@ -0,0 +1,47 @@
+package path
+
+import (
+	"testing"
+
+	"github.com/stretchr/testify/assert"
+)
+
+func TestPathRoot(t *testing.T) {
+	_, err := Path("./testdata", "/")
+	assert.EqualError(t, err, "/: app path is absolute")
+}
+
+func TestPathAbsolute(t *testing.T) {
+	_, err := Path("./testdata", "/etc/passwd")
+	assert.EqualError(t, err, "/etc/passwd: app path is absolute")
+}
+
+func TestPathDotDot(t *testing.T) {
+	_, err := Path("./testdata", "..")
+	assert.EqualError(t, err, "..: app path outside root")
+}
+
+func TestPathDotDotSlash(t *testing.T) {
+	_, err := Path("./testdata", "../")
+	assert.EqualError(t, err, "../: app path outside root")
+}
+
+func TestPathDot(t *testing.T) {
+	_, err := Path("./testdata", ".")
+	assert.NoError(t, err)
+}
+
+func TestPathDotSlash(t *testing.T) {
+	_, err := Path("./testdata", "./")
+	assert.NoError(t, err)
+}
+
+func TestNonExistentPath(t *testing.T) {
+	_, err := Path("./testdata", "does-not-exist")
+	assert.EqualError(t, err, "does-not-exist: app path does not exist")
+}
+
+func TestPathNotDir(t *testing.T) {
+	_, err := Path("./testdata", "file.txt")
+	assert.EqualError(t, err, "file.txt: app path is not a directory")
+}
diff --git a/util/app/path/testdata/file.txt b/util/app/path/testdata/file.txt
new file mode 100644
index 0000000000000..e69de29bb2d1d
diff --git a/util/argo/argo.go b/util/argo/argo.go
index e50078b8fb68d..ace3ba65bc6a3 100644
--- a/util/argo/argo.go
+++ b/util/argo/argo.go
@@ -4,9 +4,6 @@ import (
 	"context"
 	"encoding/json"
 	"fmt"
-	"net/url"
-	"path"
-	"path/filepath"
 	"strings"
 	"time"
 
@@ -25,14 +22,11 @@ import (
 	"github.com/argoproj/argo-cd/pkg/client/clientset/versioned/typed/application/v1alpha1"
 	applicationsv1 "github.com/argoproj/argo-cd/pkg/client/listers/application/v1alpha1"
 	"github.com/argoproj/argo-cd/reposerver/apiclient"
-
 	"github.com/argoproj/argo-cd/util"
-	"github.com/argoproj/argo-cd/util/cert"
 	"github.com/argoproj/argo-cd/util/db"
-	"github.com/argoproj/argo-cd/util/git"
-	"github.com/argoproj/argo-cd/util/ksonnet"
 	"github.com/argoproj/argo-cd/util/kube"
-	"github.com/argoproj/argo-cd/util/kustomize"
+	"github.com/argoproj/argo-cd/util/repo/factory"
+	"github.com/argoproj/argo-cd/util/repo/metrics"
 )
 
 const (
@@ -129,113 +123,107 @@ func WaitForRefresh(ctx context.Context, appIf v1alpha1.ApplicationInterface, na
 	return nil, fmt.Errorf("application refresh deadline exceeded")
 }
 
-func getCAPath(repoURL string) string {
-	if git.IsHTTPSURL(repoURL) {
-		if parsedURL, err := url.Parse(repoURL); err == nil {
-			if caPath, err := cert.GetCertBundlePathForRepository(parsedURL.Host); err != nil {
-				return caPath
-			} else {
-				log.Warnf("Could not get cert bundle path for host '%s'", parsedURL.Host)
-			}
-		} else {
-			// We don't fail if we cannot parse the URL, but log a warning in that
-			// case. And we execute the command in a verbatim way.
-			log.Warnf("Could not parse repo URL '%s'", repoURL)
-		}
-	}
-	return ""
-}
-
-// TODO: Figure out the correct way to distinguish between SSH and HTTPS repos
-func GetRepoCreds(repo *argoappv1.Repository) git.Creds {
-	if repo == nil {
-		return git.NopCreds{}
-	}
-	if (repo.Username != "" && repo.Password != "") || (repo.TLSClientCertData != "" && repo.TLSClientCertKey != "") {
-		return git.NewHTTPSCreds(repo.Username, repo.Password, repo.TLSClientCertData, repo.TLSClientCertKey, repo.IsInsecure())
-	}
-	if repo.SSHPrivateKey != "" {
-		return git.NewSSHCreds(repo.SSHPrivateKey, getCAPath(repo.Repo), repo.IsInsecure())
-	}
-	return git.NopCreds{}
-}
-
 // ValidateRepo validates the repository specified in application spec. Following is checked:
-// * the git repository is accessible
-// * the git path contains valid manifests
+// * the repository is accessible
+// * the path contains valid manifests
 // * there are parameters of only one app source type
 // * ksonnet: the specified environment exists
-func ValidateRepo(ctx context.Context, spec *argoappv1.ApplicationSpec, repoClientset apiclient.Clientset, db db.ArgoDB, kustomizeOptions *argoappv1.KustomizeOptions) ([]argoappv1.ApplicationCondition, argoappv1.ApplicationSourceType, error) {
+func ValidateRepo(
+	ctx context.Context,
+	spec *argoappv1.ApplicationSpec,
+	repoClientset apiclient.Clientset,
+	db db.ArgoDB,
+	kustomizeOptions *argoappv1.KustomizeOptions,
+	plugins []*argoappv1.ConfigManagementPlugin,
+) ([]argoappv1.ApplicationCondition, error) {
 	conditions := make([]argoappv1.ApplicationCondition, 0)
 
 	// Test the repo
 	conn, repoClient, err := repoClientset.NewRepoServerClient()
 	if err != nil {
-		return nil, "", err
+		return nil, err
 	}
 	defer util.Close(conn)
-	repoAccessable := false
-	repoRes, err := db.GetRepository(ctx, spec.Source.RepoURL)
+	repo, err := db.GetRepository(ctx, spec.Source.RepoURL)
 	if err != nil {
-		return nil, "", err
+		return nil, err
 	}
 
-	err = git.TestRepo(repoRes.Repo, GetRepoCreds(repoRes), repoRes.IsInsecure(), repoRes.EnableLFS)
+	repoAccessible := false
+	_, err = factory.NewFactory().NewRepo(repo, metrics.NopReporter)
 	if err != nil {
 		conditions = append(conditions, argoappv1.ApplicationCondition{
 			Type:    argoappv1.ApplicationConditionInvalidSpecError,
 			Message: fmt.Sprintf("repository not accessible: %v", err),
 		})
 	} else {
-		repoAccessable = true
+		repoAccessible = true
 	}
 
-	var appSourceType argoappv1.ApplicationSourceType
 	// Verify only one source type is defined
-	explicitSourceType, err := spec.Source.ExplicitType()
+	_, err = spec.Source.ExplicitType()
+	if err != nil {
+		return nil, err
+	}
+
+	// is the repo inaccessible - abort now
+	if !repoAccessible {
+		return conditions, nil
+	}
+
+	// get the app details, and populate the Ksonnet stuff from it
+	repos, err := db.ListRepositories(ctx)
+	if err != nil {
+		return nil, err
+	}
+
+	// can we actually read the app from the repo
+	var helm *apiclient.HelmAppDetailsQuery
+	if spec.Source.Helm != nil {
+		helm = &apiclient.HelmAppDetailsQuery{ValueFiles: spec.Source.Helm.ValueFiles}
+	}
+	var ksonnet *apiclient.KsonnetAppDetailsQuery
+	if spec.Source.Ksonnet != nil {
+		ksonnet = &apiclient.KsonnetAppDetailsQuery{Environment: spec.Source.Ksonnet.Environment}
+	}
+	appDetails, err := repoClient.GetAppDetails(ctx, &apiclient.RepoServerAppDetailsQuery{
+		Repo:             repo,
+		Revision:         spec.Source.TargetRevision,
+		App:              spec.Source.Path,
+		Repos:            repos,
+		Plugins:          plugins,
+		Helm:             helm,
+		Ksonnet:          ksonnet,
+		KustomizeOptions: kustomizeOptions,
+	})
 	if err != nil {
 		conditions = append(conditions, argoappv1.ApplicationCondition{
 			Type:    argoappv1.ApplicationConditionInvalidSpecError,
-			Message: fmt.Sprintf("Unable to determine app source type: %v", err),
+			Message: fmt.Sprintf("Unable to get app details: %v", err),
 		})
+		return conditions, nil
 	}
 
-	if repoAccessable {
-		if explicitSourceType != nil {
-			appSourceType = *explicitSourceType
-		} else {
-			appSourceType, err = queryAppSourceType(ctx, spec, repoRes, repoClient)
-		}
+	enrichSpec(spec, appDetails)
 
-		if err != nil {
-			conditions = append(conditions, argoappv1.ApplicationCondition{
-				Type:    argoappv1.ApplicationConditionInvalidSpecError,
-				Message: fmt.Sprintf("Unable to determine app source type: %v", err),
-			})
-		} else {
-			switch appSourceType {
-			case argoappv1.ApplicationSourceTypeKsonnet:
-				err := verifyAppYAML(ctx, repoRes, spec, repoClient)
-				if err != nil {
-					conditions = append(conditions, argoappv1.ApplicationCondition{
-						Type:    argoappv1.ApplicationConditionInvalidSpecError,
-						Message: err.Error(),
-					})
-				}
-			case argoappv1.ApplicationSourceTypeHelm:
-				helmConditions := verifyHelmChart(ctx, repoRes, spec, repoClient)
-				if len(helmConditions) > 0 {
-					conditions = append(conditions, helmConditions...)
-				}
-			case argoappv1.ApplicationSourceTypeDirectory, argoappv1.ApplicationSourceTypeKustomize:
-				mainDirConditions := verifyGenerateManifests(ctx, repoRes, []*argoappv1.HelmRepository{}, spec, repoClient, kustomizeOptions)
-				if len(mainDirConditions) > 0 {
-					conditions = append(conditions, mainDirConditions...)
-				}
+	conditions = append(conditions, verifyGenerateManifests(ctx, repo, repos, spec, repoClient, kustomizeOptions, plugins)...)
+
+	return conditions, nil
+}
+
+func enrichSpec(spec *argoappv1.ApplicationSpec, appDetails *apiclient.RepoAppDetailsResponse) {
+	if spec.Source.Ksonnet != nil && appDetails.Ksonnet != nil {
+		env, ok := appDetails.Ksonnet.Environments[spec.Source.Ksonnet.Environment]
+		if ok {
+			// If server and namespace are not supplied, pull it from the app.yaml
+			if spec.Destination.Server == "" {
+				spec.Destination.Server = env.Destination.Server
+			}
+			if spec.Destination.Namespace == "" {
+				spec.Destination.Namespace = env.Destination.Namespace
 			}
 		}
 	}
-	return conditions, appSourceType, nil
 }
 
 // ValidatePermissions ensures that the referenced cluster has been added to Argo CD and the app source repo and destination namespace/cluster are permitted in app project
@@ -286,108 +274,16 @@ func GetAppProject(spec *argoappv1.ApplicationSpec, projLister applicationsv1.Ap
 	return projLister.AppProjects(ns).Get(spec.GetProject())
 }
 
-func queryAppSourceType(ctx context.Context, spec *argoappv1.ApplicationSpec, repoRes *argoappv1.Repository, repoClient apiclient.RepoServerServiceClient) (argoappv1.ApplicationSourceType, error) {
-	req := apiclient.ListDirRequest{
-		Repo: &argoappv1.Repository{
-			Repo: spec.Source.RepoURL,
-		},
-		Revision: spec.Source.TargetRevision,
-		Path:     fmt.Sprintf("%s/*.yaml", spec.Source.Path),
-	}
-	req.Repo.CopyCredentialsFrom(repoRes)
-	getRes, err := repoClient.ListDir(ctx, &req)
-	if err != nil {
-		return "", err
-	}
-	for _, gitPath := range getRes.Items {
-		// gitPath may look like: app.yaml, or some/subpath/app.yaml
-		trimmedPath := strings.TrimPrefix(gitPath, filepath.Clean(spec.Source.Path))
-		trimmedPath = strings.TrimPrefix(trimmedPath, "/")
-		if trimmedPath == "app.yaml" {
-			return argoappv1.ApplicationSourceTypeKsonnet, nil
-		}
-		if trimmedPath == "Chart.yaml" {
-			return argoappv1.ApplicationSourceTypeHelm, nil
-		}
-		if kustomize.IsKustomization(trimmedPath) {
-			return argoappv1.ApplicationSourceTypeKustomize, nil
-		}
-	}
-	return argoappv1.ApplicationSourceTypeDirectory, nil
-}
-
-// verifyAppYAML verifies that a ksonnet app.yaml is functional
-func verifyAppYAML(ctx context.Context, repoRes *argoappv1.Repository, spec *argoappv1.ApplicationSpec, repoClient apiclient.RepoServerServiceClient) error {
-	// Default revision to HEAD if unspecified
-	if spec.Source.TargetRevision == "" {
-		spec.Source.TargetRevision = "HEAD"
-	}
-
-	req := apiclient.GetFileRequest{
-		Repo: &argoappv1.Repository{
-			Repo: spec.Source.RepoURL,
-		},
-		Revision: spec.Source.TargetRevision,
-		Path:     path.Join(spec.Source.Path, "app.yaml"),
-	}
-	req.Repo.CopyCredentialsFrom(repoRes)
-	getRes, err := repoClient.GetFile(ctx, &req)
-	if err != nil {
-		return fmt.Errorf("Unable to load app.yaml: %v", err)
-	}
-
-	// Verify the specified environment is defined in the app spec
-	if spec.Source.Ksonnet == nil {
-		return fmt.Errorf("Ksonnet environment not specified")
-	}
-
-	dest, err := ksonnet.Destination(getRes.Data, spec.Source.Ksonnet.Environment)
-	if err != nil {
-		return err
-	}
-
-	// If server and namespace are not supplied, pull it from the app.yaml
-	if spec.Destination.Server == "" {
-		spec.Destination.Server = dest.Server
-	}
-	if spec.Destination.Namespace == "" {
-		spec.Destination.Namespace = dest.Namespace
-	}
-
-	return nil
-}
-
-// verifyHelmChart verifies a helm chart is functional
-// verifyHelmChart verifies a helm chart is functional
-func verifyHelmChart(ctx context.Context, repoRes *argoappv1.Repository, spec *argoappv1.ApplicationSpec, repoClient apiclient.RepoServerServiceClient) []argoappv1.ApplicationCondition {
-	var conditions []argoappv1.ApplicationCondition
-	if spec.Destination.Server == "" || spec.Destination.Namespace == "" {
-		conditions = append(conditions, argoappv1.ApplicationCondition{
-			Type:    argoappv1.ApplicationConditionInvalidSpecError,
-			Message: errDestinationMissing,
-		})
-	}
-	req := apiclient.GetFileRequest{
-		Repo: &argoappv1.Repository{
-			Repo: spec.Source.RepoURL,
-		},
-		Revision: spec.Source.TargetRevision,
-		Path:     path.Join(spec.Source.Path, "Chart.yaml"),
-	}
-	req.Repo.CopyCredentialsFrom(repoRes)
-	_, err := repoClient.GetFile(ctx, &req)
-	if err != nil {
-		conditions = append(conditions, argoappv1.ApplicationCondition{
-			Type:    argoappv1.ApplicationConditionInvalidSpecError,
-			Message: fmt.Sprintf("Unable to load Chart.yaml: %v", err),
-		})
-	}
-	return conditions
-}
-
 // verifyGenerateManifests verifies a repo path can generate manifests
 func verifyGenerateManifests(
-	ctx context.Context, repoRes *argoappv1.Repository, helmRepos []*argoappv1.HelmRepository, spec *argoappv1.ApplicationSpec, repoClient apiclient.RepoServerServiceClient, kustomizeOptions *argoappv1.KustomizeOptions) []argoappv1.ApplicationCondition {
+	ctx context.Context,
+	repoRes *argoappv1.Repository,
+	repos argoappv1.Repositories,
+	spec *argoappv1.ApplicationSpec,
+	repoClient apiclient.RepoServerServiceClient,
+	kustomizeOptions *argoappv1.KustomizeOptions,
+	plugins []*argoappv1.ConfigManagementPlugin,
+) []argoappv1.ApplicationCondition {
 
 	var conditions []argoappv1.ApplicationCondition
 	if spec.Destination.Server == "" || spec.Destination.Namespace == "" {
@@ -396,14 +292,18 @@ func verifyGenerateManifests(
 			Message: errDestinationMissing,
 		})
 	}
+
 	req := apiclient.ManifestRequest{
 		Repo: &argoappv1.Repository{
 			Repo: spec.Source.RepoURL,
+			Type: repoRes.Type,
+			Name: repoRes.Name,
 		},
-		HelmRepos:         helmRepos,
+		Repos:             repos,
 		Revision:          spec.Source.TargetRevision,
 		Namespace:         spec.Destination.Namespace,
 		ApplicationSource: &spec.Source,
+		Plugins:           plugins,
 		KustomizeOptions:  kustomizeOptions,
 	}
 	req.Repo.CopyCredentialsFrom(repoRes)
@@ -460,7 +360,7 @@ func ContainsSyncResource(name string, gvk schema.GroupVersionKind, rr []argoapp
 // NormalizeApplicationSpec will normalize an application spec to a preferred state. This is used
 // for migrating application objects which are using deprecated legacy fields into the new fields,
 // and defaulting fields in the spec (e.g. spec.project)
-func NormalizeApplicationSpec(spec *argoappv1.ApplicationSpec, sourceType argoappv1.ApplicationSourceType) *argoappv1.ApplicationSpec {
+func NormalizeApplicationSpec(spec *argoappv1.ApplicationSpec) *argoappv1.ApplicationSpec {
 	spec = spec.DeepCopy()
 	if spec.Project == "" {
 		spec.Project = common.DefaultAppProjectName
diff --git a/util/argo/argo_test.go b/util/argo/argo_test.go
index b3d5b86a03f46..fc07449e666f3 100644
--- a/util/argo/argo_test.go
+++ b/util/argo/argo_test.go
@@ -17,6 +17,7 @@ import (
 	appclientset "github.com/argoproj/argo-cd/pkg/client/clientset/versioned/fake"
 	"github.com/argoproj/argo-cd/pkg/client/informers/externalversions/application/v1alpha1"
 	applisters "github.com/argoproj/argo-cd/pkg/client/listers/application/v1alpha1"
+	"github.com/argoproj/argo-cd/reposerver/apiclient"
 )
 
 func TestRefreshApp(t *testing.T) {
@@ -109,27 +110,27 @@ func TestContainsSyncResource(t *testing.T) {
 func TestNilOutZerValueAppSources(t *testing.T) {
 	var spec *argoappv1.ApplicationSpec
 	{
-		spec = NormalizeApplicationSpec(&argoappv1.ApplicationSpec{Source: argoappv1.ApplicationSource{Kustomize: &argoappv1.ApplicationSourceKustomize{NamePrefix: "foo"}}}, argoappv1.ApplicationSourceTypeKustomize)
+		spec = NormalizeApplicationSpec(&argoappv1.ApplicationSpec{Source: argoappv1.ApplicationSource{Kustomize: &argoappv1.ApplicationSourceKustomize{NamePrefix: "foo"}}})
 		assert.NotNil(t, spec.Source.Kustomize)
-		spec = NormalizeApplicationSpec(&argoappv1.ApplicationSpec{Source: argoappv1.ApplicationSource{Kustomize: &argoappv1.ApplicationSourceKustomize{NamePrefix: ""}}}, argoappv1.ApplicationSourceTypeKustomize)
+		spec = NormalizeApplicationSpec(&argoappv1.ApplicationSpec{Source: argoappv1.ApplicationSource{Kustomize: &argoappv1.ApplicationSourceKustomize{NamePrefix: ""}}})
 		assert.Nil(t, spec.Source.Kustomize)
 	}
 	{
-		spec = NormalizeApplicationSpec(&argoappv1.ApplicationSpec{Source: argoappv1.ApplicationSource{Helm: &argoappv1.ApplicationSourceHelm{ValueFiles: []string{"values.yaml"}}}}, argoappv1.ApplicationSourceTypeHelm)
+		spec = NormalizeApplicationSpec(&argoappv1.ApplicationSpec{Source: argoappv1.ApplicationSource{Helm: &argoappv1.ApplicationSourceHelm{ValueFiles: []string{"values.yaml"}}}})
 		assert.NotNil(t, spec.Source.Helm)
-		spec = NormalizeApplicationSpec(&argoappv1.ApplicationSpec{Source: argoappv1.ApplicationSource{Helm: &argoappv1.ApplicationSourceHelm{ValueFiles: []string{}}}}, argoappv1.ApplicationSourceTypeHelm)
+		spec = NormalizeApplicationSpec(&argoappv1.ApplicationSpec{Source: argoappv1.ApplicationSource{Helm: &argoappv1.ApplicationSourceHelm{ValueFiles: []string{}}}})
 		assert.Nil(t, spec.Source.Helm)
 	}
 	{
-		spec = NormalizeApplicationSpec(&argoappv1.ApplicationSpec{Source: argoappv1.ApplicationSource{Ksonnet: &argoappv1.ApplicationSourceKsonnet{Environment: "foo"}}}, argoappv1.ApplicationSourceTypeKsonnet)
+		spec = NormalizeApplicationSpec(&argoappv1.ApplicationSpec{Source: argoappv1.ApplicationSource{Ksonnet: &argoappv1.ApplicationSourceKsonnet{Environment: "foo"}}})
 		assert.NotNil(t, spec.Source.Ksonnet)
-		spec = NormalizeApplicationSpec(&argoappv1.ApplicationSpec{Source: argoappv1.ApplicationSource{Ksonnet: &argoappv1.ApplicationSourceKsonnet{Environment: ""}}}, argoappv1.ApplicationSourceTypeKsonnet)
+		spec = NormalizeApplicationSpec(&argoappv1.ApplicationSpec{Source: argoappv1.ApplicationSource{Ksonnet: &argoappv1.ApplicationSourceKsonnet{Environment: ""}}})
 		assert.Nil(t, spec.Source.Ksonnet)
 	}
 	{
-		spec = NormalizeApplicationSpec(&argoappv1.ApplicationSpec{Source: argoappv1.ApplicationSource{Directory: &argoappv1.ApplicationSourceDirectory{Recurse: true}}}, argoappv1.ApplicationSourceTypeDirectory)
+		spec = NormalizeApplicationSpec(&argoappv1.ApplicationSpec{Source: argoappv1.ApplicationSource{Directory: &argoappv1.ApplicationSourceDirectory{Recurse: true}}})
 		assert.NotNil(t, spec.Source.Directory)
-		spec = NormalizeApplicationSpec(&argoappv1.ApplicationSpec{Source: argoappv1.ApplicationSource{Directory: &argoappv1.ApplicationSourceDirectory{Recurse: false}}}, argoappv1.ApplicationSourceTypeDirectory)
+		spec = NormalizeApplicationSpec(&argoappv1.ApplicationSpec{Source: argoappv1.ApplicationSource{Directory: &argoappv1.ApplicationSourceDirectory{Recurse: false}}})
 		assert.Nil(t, spec.Source.Directory)
 	}
 }
@@ -146,3 +147,41 @@ func TestValidatePermissionsEmptyDestination(t *testing.T) {
 	assert.NoError(t, err)
 	assert.ElementsMatch(t, conditions, []argoappv1.ApplicationCondition{{Type: argoappv1.ApplicationConditionInvalidSpecError, Message: "Destination server and/or namespace missing from app spec"}})
 }
+
+func Test_enrichSpec(t *testing.T) {
+	t.Run("Empty", func(t *testing.T) {
+		spec := &argoappv1.ApplicationSpec{}
+		enrichSpec(spec, &apiclient.RepoAppDetailsResponse{})
+		assert.Empty(t, spec.Destination.Server)
+		assert.Empty(t, spec.Destination.Namespace)
+	})
+	t.Run("Ksonnet", func(t *testing.T) {
+		spec := &argoappv1.ApplicationSpec{
+			Source: argoappv1.ApplicationSource{
+				Ksonnet: &argoappv1.ApplicationSourceKsonnet{
+					Environment: "qa",
+				},
+			},
+		}
+		response := &apiclient.RepoAppDetailsResponse{
+			Ksonnet: &apiclient.KsonnetAppSpec{
+				Environments: map[string]*apiclient.KsonnetEnvironment{
+					"prod": {
+						Destination: &apiclient.KsonnetEnvironmentDestination{
+							Server:    "my-server",
+							Namespace: "my-namespace",
+						},
+					},
+				},
+			},
+		}
+		enrichSpec(spec, response)
+		assert.Empty(t, spec.Destination.Server)
+		assert.Empty(t, spec.Destination.Namespace)
+
+		spec.Source.Ksonnet.Environment = "prod"
+		enrichSpec(spec, response)
+		assert.Equal(t, "my-server", spec.Destination.Server)
+		assert.Equal(t, "my-namespace", spec.Destination.Namespace)
+	})
+}
diff --git a/util/cache/cache.go b/util/cache/cache.go
index 9310d3c3dcecd..4e1ce97a0c8db 100644
--- a/util/cache/cache.go
+++ b/util/cache/cache.go
@@ -92,12 +92,8 @@ func repoConnectionStateKey(repo string) string {
 	return fmt.Sprintf("repo|%s|connection-state", repo)
 }
 
-func listDirKey(commitSHA string, path string) string {
-	return fmt.Sprintf("ldir|%s|%s", path, commitSHA)
-}
-
-func gitFileKey(commitSHA string, path string) string {
-	return fmt.Sprintf("gfile|%s|%s", path, commitSHA)
+func listApps(revision, path string) string {
+	return fmt.Sprintf("ldir|%s|%s", path, revision)
 }
 
 func oidcStateKey(key string) string {
@@ -118,8 +114,8 @@ func appDetailsCacheKey(commitSHA, path string, valueFiles []string) string {
 	return fmt.Sprintf("appdetails|%s|%s|%s", commitSHA, path, valuesStr)
 }
 
-func revisionMetadataKey(repoURL, revision string) string {
-	return fmt.Sprintf("revisionmetadata|%s|%s", repoURL, revision)
+func revisionMetadataKey(repoURL, path, revision string) string {
+	return fmt.Sprintf("revisionmetadata|%s|%s|%s", repoURL, path, revision)
 }
 
 func (c *Cache) setItem(key string, item interface{}, expiration time.Duration, delete bool) error {
@@ -175,24 +171,14 @@ func (c *Cache) GetRepoConnectionState(repo string) (appv1.ConnectionState, erro
 func (c *Cache) SetRepoConnectionState(repo string, state *appv1.ConnectionState) error {
 	return c.setItem(repoConnectionStateKey(repo), &state, connectionStatusCacheExpiration, state == nil)
 }
-func (c *Cache) GetGitListDir(commitSha string, path string) ([]string, error) {
-	res := make([]string, 0)
-	err := c.getItem(listDirKey(commitSha, path), &res)
-	return res, err
-}
-
-func (c *Cache) SetListDir(commitSha string, path string, files []string) error {
-	return c.setItem(listDirKey(commitSha, path), files, repoCacheExpiration, files == nil)
-}
-
-func (c *Cache) GetGitFile(commitSha string, path string) ([]byte, error) {
-	res := make([]byte, 0)
-	err := c.getItem(gitFileKey(commitSha, path), &res)
+func (c *Cache) ListApps(revision, path string) (map[string]string, error) {
+	res := make(map[string]string)
+	err := c.getItem(listApps(revision, path), &res)
 	return res, err
 }
 
-func (c *Cache) SetGitFile(commitSha string, path string, data []byte) error {
-	return c.setItem(gitFileKey(commitSha, path), data, repoCacheExpiration, data == nil)
+func (c *Cache) SetApps(revision, path string, apps map[string]string) error {
+	return c.setItem(listApps(revision, path), apps, repoCacheExpiration, apps == nil)
 }
 
 func (c *Cache) GetManifests(commitSHA string, appSrc *appv1.ApplicationSource, namespace string, appLabelKey string, appLabelValue string, res interface{}) error {
@@ -211,13 +197,13 @@ func (c *Cache) SetAppDetails(commitSHA, path string, valueFiles []string, res i
 	return c.setItem(appDetailsCacheKey(commitSHA, path, valueFiles), res, repoCacheExpiration, res == nil)
 }
 
-func (c *Cache) GetRevisionMetadata(repoURL, revision string) (*appv1.RevisionMetadata, error) {
+func (c *Cache) GetRevisionMetadata(repoURL, path, revision string) (*appv1.RevisionMetadata, error) {
 	item := &appv1.RevisionMetadata{}
-	return item, c.getItem(revisionMetadataKey(repoURL, revision), item)
+	return item, c.getItem(revisionMetadataKey(repoURL, path, revision), item)
 }
 
-func (c *Cache) SetRevisionMetadata(repoURL, revision string, item *appv1.RevisionMetadata) error {
-	return c.setItem(revisionMetadataKey(repoURL, revision), item, repoCacheExpiration, false)
+func (c *Cache) SetRevisionMetadata(repoURL, path, revision string, item *appv1.RevisionMetadata) error {
+	return c.setItem(revisionMetadataKey(repoURL, path, revision), item, repoCacheExpiration, false)
 }
 
 func (c *Cache) GetOIDCState(key string) (*OIDCState, error) {
diff --git a/util/cache/cache_test.go b/util/cache/cache_test.go
index 5ff0d0e7f9136..96eceacc03c07 100644
--- a/util/cache/cache_test.go
+++ b/util/cache/cache_test.go
@@ -12,12 +12,12 @@ import (
 func TestCacheRevisionMetadata(t *testing.T) {
 	cache := NewCache(NewInMemoryCache(1 * time.Hour))
 	// cache miss
-	_, err := cache.GetRevisionMetadata("", "")
+	_, err := cache.GetRevisionMetadata("", "", "")
 	assert.Equal(t, ErrCacheMiss, err)
 	// cache hit
-	err = cache.SetRevisionMetadata("foo", "bar", &v1alpha1.RevisionMetadata{Message: "foo"})
+	err = cache.SetRevisionMetadata("foo", "bar", "baz", &v1alpha1.RevisionMetadata{Message: "foo"})
 	assert.NoError(t, err)
-	metadata, err := cache.GetRevisionMetadata("foo", "bar")
+	metadata, err := cache.GetRevisionMetadata("foo", "bar", "baz")
 	assert.NoError(t, err)
 	assert.Equal(t, &v1alpha1.RevisionMetadata{Message: "foo"}, metadata)
 }
diff --git a/util/creds/factory.go b/util/creds/factory.go
new file mode 100644
index 0000000000000..8b32c9266b102
--- /dev/null
+++ b/util/creds/factory.go
@@ -0,0 +1,41 @@
+package creds
+
+import (
+	"net/url"
+
+	log "github.com/sirupsen/logrus"
+
+	"github.com/argoproj/argo-cd/pkg/apis/application/v1alpha1"
+	"github.com/argoproj/argo-cd/util/cert"
+	"github.com/argoproj/argo-cd/util/git"
+)
+
+func GetRepoCreds(repo *v1alpha1.Repository) git.Creds {
+	if repo == nil {
+		return git.NopCreds{}
+	}
+	if repo.Username != "" && repo.Password != "" {
+		return git.NewHTTPSCreds(repo.Username, repo.Password, repo.TLSClientCertData, repo.TLSClientCertKey, repo.TLSClientCAData, repo.IsInsecure())
+	}
+	if repo.SSHPrivateKey != "" {
+		return git.NewSSHCreds(repo.SSHPrivateKey, getCAPath(repo.Repo), repo.IsInsecure())
+	}
+	return git.NopCreds{}
+}
+
+func getCAPath(repoURL string) string {
+	if git.IsHTTPSURL(repoURL) {
+		if parsedURL, err := url.Parse(repoURL); err == nil {
+			if caPath, err := cert.GetCertBundlePathForRepository(parsedURL.Host); err != nil {
+				return caPath
+			} else {
+				log.Warnf("Could not get cert bundle path for host '%s'", parsedURL.Host)
+			}
+		} else {
+			// We don't fail if we cannot parse the URL, but log a warning in that
+			// case. And we execute the command in a verbatim way.
+			log.Warnf("Could not parse repo URL '%s'", repoURL)
+		}
+	}
+	return ""
+}
diff --git a/util/db/db.go b/util/db/db.go
index c1e453c1eaf69..4d7fd19b63136 100644
--- a/util/db/db.go
+++ b/util/db/db.go
@@ -24,21 +24,18 @@ type ArgoDB interface {
 	// DeleteCluster deletes a cluster by name
 	DeleteCluster(ctx context.Context, name string) error
 
-	// ListRepoURLs lists repositories
-	ListRepoURLs(ctx context.Context) ([]string, error)
+	// ListRepositories lists repositories
+	ListRepositories(ctx context.Context) ([]*appv1.Repository, error)
 	// CreateRepository creates a repository
 	CreateRepository(ctx context.Context, r *appv1.Repository) (*appv1.Repository, error)
 	// GetRepository returns a repository by URL
-	GetRepository(ctx context.Context, name string) (*appv1.Repository, error)
+	GetRepository(ctx context.Context, url string) (*appv1.Repository, error)
 	// UpdateRepository updates a repository
 	UpdateRepository(ctx context.Context, r *appv1.Repository) (*appv1.Repository, error)
 	// DeleteRepository updates a repository
-	DeleteRepository(ctx context.Context, name string) error
+	DeleteRepository(ctx context.Context, url string) error
 
-	// ListHelmRepoURLs lists configured helm repositories
-	ListHelmRepos(ctx context.Context) ([]*appv1.HelmRepository, error)
-
-	// ListRepoCerticifates lists all configured certificates
+	// ListRepoCertificates lists all configured certificates
 	ListRepoCertificates(ctx context.Context, selector *CertificateListSelector) (*appv1.RepositoryCertificateList, error)
 	// CreateRepoCertificate creates a new certificate entry
 	CreateRepoCertificate(ctx context.Context, certificate *appv1.RepositoryCertificateList, upsert bool) (*appv1.RepositoryCertificateList, error)
@@ -92,16 +89,3 @@ func (db *db) unmarshalFromSecretsStr(secrets map[*string]*v1.SecretKeySelector,
 	}
 	return nil
 }
-
-func (db *db) unmarshalFromSecretsBytes(secrets map[*[]byte]*v1.SecretKeySelector, cache map[string]*v1.Secret) error {
-	for dst, src := range secrets {
-		if src != nil {
-			secret, err := db.getSecret(src.Name, cache)
-			if err != nil {
-				return err
-			}
-			*dst = secret.Data[src.Key]
-		}
-	}
-	return nil
-}
diff --git a/util/db/db_test.go b/util/db/db_test.go
index a4283e6926b6c..ba3f90680e4c5 100644
--- a/util/db/db_test.go
+++ b/util/db/db_test.go
@@ -398,22 +398,23 @@ func TestFuzzyEquivalence(t *testing.T) {
 
 func TestListHelmRepositories(t *testing.T) {
 	config := map[string]string{
-		"helm.repositories": `
+		"repositories": `
 - url: https://argoproj.github.io/argo-helm
   name: argo
+  type: helm
   usernameSecret:
     name: test-secret
     key: username
   passwordSecret:
     name: test-secret
     key: password
-  caSecret:
+  tlsClientCertCaSecret:
     name: test-secret
     key: ca
-  certSecret:
+  tlsClientCertDataSecret:
     name: test-secret
     key: cert
-  keySecret:
+  tlsClientCertKeySecret:
     name: test-secret
     key: key
 `}
@@ -432,13 +433,16 @@ func TestListHelmRepositories(t *testing.T) {
 	})
 	db := NewDB(testNamespace, settings.NewSettingsManager(context.Background(), clientset, testNamespace), clientset)
 
-	repos, err := db.ListHelmRepos(context.Background())
+	repos, err := db.ListRepositories(context.Background())
 	assert.Nil(t, err)
-	assert.Equal(t, 1, len(repos))
+	assert.Len(t, repos, 1)
 	repo := repos[0]
+	assert.Equal(t, "https://argoproj.github.io/argo-helm", repo.Repo)
+	assert.Equal(t, "helm", repo.Type)
+	assert.Equal(t, "argo", repo.Name)
 	assert.Equal(t, "test-username", repo.Username)
 	assert.Equal(t, "test-password", repo.Password)
-	assert.Equal(t, []byte("test-ca"), repo.CAData)
-	assert.Equal(t, []byte("test-cert"), repo.CertData)
-	assert.Equal(t, []byte("test-key"), repo.KeyData)
+	assert.Equal(t, "test-ca", repo.TLSClientCAData)
+	assert.Equal(t, "test-cert", repo.TLSClientCertData)
+	assert.Equal(t, "test-key", repo.TLSClientCertKey)
 }
diff --git a/util/db/helmrepository.go b/util/db/helmrepository.go
deleted file mode 100644
index 3df13fb7d9757..0000000000000
--- a/util/db/helmrepository.go
+++ /dev/null
@@ -1,68 +0,0 @@
-package db
-
-import (
-	"context"
-	"strings"
-
-	apiv1 "k8s.io/api/core/v1"
-
-	"google.golang.org/grpc/codes"
-	"google.golang.org/grpc/status"
-
-	appv1 "github.com/argoproj/argo-cd/pkg/apis/application/v1alpha1"
-	"github.com/argoproj/argo-cd/util/settings"
-)
-
-func getHelmRepoCredIndex(helmRepositories []settings.HelmRepoCredentials, repoURL string) int {
-	for i, cred := range helmRepositories {
-		if strings.EqualFold(cred.URL, repoURL) {
-			return i
-		}
-	}
-	return -1
-}
-
-func (db *db) getHelmRepo(repoURL string, helmRepositories []settings.HelmRepoCredentials) (*appv1.HelmRepository, error) {
-	index := getHelmRepoCredIndex(helmRepositories, repoURL)
-	if index < 0 {
-		return nil, status.Errorf(codes.NotFound, "repo '%s' not found", repoURL)
-	}
-
-	helmRepoInfo := helmRepositories[index]
-	helmRepo := &appv1.HelmRepository{URL: repoURL, Name: helmRepoInfo.Name}
-	cache := make(map[string]*apiv1.Secret)
-	err := db.unmarshalFromSecretsBytes(map[*[]byte]*apiv1.SecretKeySelector{
-		&helmRepo.CAData:   helmRepoInfo.CASecret,
-		&helmRepo.CertData: helmRepoInfo.CertSecret,
-		&helmRepo.KeyData:  helmRepoInfo.KeySecret,
-	}, cache)
-	if err != nil {
-		return nil, err
-	}
-	err = db.unmarshalFromSecretsStr(map[*string]*apiv1.SecretKeySelector{
-		&helmRepo.Username: helmRepoInfo.UsernameSecret,
-		&helmRepo.Password: helmRepoInfo.PasswordSecret,
-	}, cache)
-	if err != nil {
-		return nil, err
-	}
-	return helmRepo, nil
-}
-
-// ListHelmRepoURLs lists configured helm repositories
-func (db *db) ListHelmRepos(ctx context.Context) ([]*appv1.HelmRepository, error) {
-	helmRepositories, err := db.settingsMgr.GetHelmRepositories()
-	if err != nil {
-		return nil, err
-	}
-
-	repos := make([]*appv1.HelmRepository, len(helmRepositories))
-	for i, helmRepoInfo := range helmRepositories {
-		repo, err := db.getHelmRepo(helmRepoInfo.URL, helmRepositories)
-		if err != nil {
-			return nil, err
-		}
-		repos[i] = repo
-	}
-	return repos, nil
-}
diff --git a/util/db/mocks/ArgoDB.go b/util/db/mocks/ArgoDB.go
index 47618d46df00a..53e3e83282620 100644
--- a/util/db/mocks/ArgoDB.go
+++ b/util/db/mocks/ArgoDB.go
@@ -114,13 +114,13 @@ func (_m *ArgoDB) GetCluster(ctx context.Context, name string) (*v1alpha1.Cluste
 	return r0, r1
 }
 
-// GetRepository provides a mock function with given fields: ctx, repoURL
-func (_m *ArgoDB) GetRepository(ctx context.Context, repoURL string) (*v1alpha1.Repository, error) {
-	ret := _m.Called(ctx, repoURL)
+// GetRepository provides a mock function with given fields: ctx, name
+func (_m *ArgoDB) GetRepository(ctx context.Context, name string) (*v1alpha1.Repository, error) {
+	ret := _m.Called(ctx, name)
 
 	var r0 *v1alpha1.Repository
 	if rf, ok := ret.Get(0).(func(context.Context, string) *v1alpha1.Repository); ok {
-		r0 = rf(ctx, repoURL)
+		r0 = rf(ctx, name)
 	} else {
 		if ret.Get(0) != nil {
 			r0 = ret.Get(0).(*v1alpha1.Repository)
@@ -129,7 +129,7 @@ func (_m *ArgoDB) GetRepository(ctx context.Context, repoURL string) (*v1alpha1.
 
 	var r1 error
 	if rf, ok := ret.Get(1).(func(context.Context, string) error); ok {
-		r1 = rf(ctx, repoURL)
+		r1 = rf(ctx, name)
 	} else {
 		r1 = ret.Error(1)
 	}
@@ -160,39 +160,16 @@ func (_m *ArgoDB) ListClusters(ctx context.Context) (*v1alpha1.ClusterList, erro
 	return r0, r1
 }
 
-// ListHelmRepos provides a mock function with given fields: ctx
-func (_m *ArgoDB) ListHelmRepos(ctx context.Context) ([]*v1alpha1.HelmRepository, error) {
-	ret := _m.Called(ctx)
-
-	var r0 []*v1alpha1.HelmRepository
-	if rf, ok := ret.Get(0).(func(context.Context) []*v1alpha1.HelmRepository); ok {
-		r0 = rf(ctx)
-	} else {
-		if ret.Get(0) != nil {
-			r0 = ret.Get(0).([]*v1alpha1.HelmRepository)
-		}
-	}
-
-	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
-}
-
-// ListRepoURLs provides a mock function with given fields: ctx
-func (_m *ArgoDB) ListRepoURLs(ctx context.Context) ([]string, error) {
+// ListRepositories provides a mock function with given fields: ctx
+func (_m *ArgoDB) ListRepositories(ctx context.Context) ([]*v1alpha1.Repository, error) {
 	ret := _m.Called(ctx)
 
-	var r0 []string
-	if rf, ok := ret.Get(0).(func(context.Context) []string); ok {
+	var r0 []*v1alpha1.Repository
+	if rf, ok := ret.Get(0).(func(context.Context) []*v1alpha1.Repository); ok {
 		r0 = rf(ctx)
 	} else {
 		if ret.Get(0) != nil {
-			r0 = ret.Get(0).([]string)
+			r0 = ret.Get(0).([]*v1alpha1.Repository)
 		}
 	}
 
diff --git a/util/db/repository.go b/util/db/repository.go
index cb50e011e1c25..7dd99a463eced 100644
--- a/util/db/repository.go
+++ b/util/db/repository.go
@@ -32,21 +32,6 @@ const (
 	tlsClientCertKey = "tlsClientCertKey"
 )
 
-// ListRepoURLs returns list of repositories
-func (db *db) ListRepoURLs(ctx context.Context) ([]string, error) {
-	repos, err := db.settingsMgr.GetRepositories()
-	if err != nil {
-		return nil, err
-	}
-
-	urls := make([]string, len(repos))
-	for i := range repos {
-		urls[i] = repos[i].URL
-	}
-	return urls, nil
-}
-
-// CreateRepository creates a repository
 func (db *db) CreateRepository(ctx context.Context, r *appsv1.Repository) (*appsv1.Repository, error) {
 	repos, err := db.settingsMgr.GetRepositories()
 	if err != nil {
@@ -71,6 +56,8 @@ func (db *db) CreateRepository(ctx context.Context, r *appsv1.Repository) (*apps
 
 	repoInfo := settings.RepoCredentials{
 		URL:                   r.Repo,
+		Type:                  r.Type,
+		Name:                  r.Name,
 		InsecureIgnoreHostKey: r.IsInsecure(),
 		Insecure:              r.IsInsecure(),
 		EnableLFS:             r.EnableLFS,
@@ -126,9 +113,29 @@ func (db *db) GetRepository(ctx context.Context, repoURL string) (*appsv1.Reposi
 	return repo, err
 }
 
+func (db *db) ListRepositories(ctx context.Context) ([]*appsv1.Repository, error) {
+	inRepos, err := db.settingsMgr.GetRepositories()
+	if err != nil {
+		return nil, err
+	}
+
+	var repos []*appsv1.Repository
+	for _, inRepo := range inRepos {
+		r, err := db.GetRepository(ctx, inRepo.URL)
+		if err != nil {
+			return nil, err
+		}
+		repos = append(repos, r)
+
+	}
+	return repos, nil
+}
+
 func (db *db) credentialsToRepository(repoInfo settings.RepoCredentials) (*appsv1.Repository, error) {
 	repo := &appsv1.Repository{
 		Repo:                  repoInfo.URL,
+		Type:                  repoInfo.Type,
+		Name:                  repoInfo.Name,
 		InsecureIgnoreHostKey: repoInfo.InsecureIgnoreHostKey,
 		Insecure:              repoInfo.Insecure,
 		EnableLFS:             repoInfo.EnableLFS,
@@ -139,8 +146,8 @@ func (db *db) credentialsToRepository(repoInfo settings.RepoCredentials) (*appsv
 		&repo.SSHPrivateKey:     repoInfo.SSHPrivateKeySecret,
 		&repo.TLSClientCertData: repoInfo.TLSClientCertDataSecret,
 		&repo.TLSClientCertKey:  repoInfo.TLSClientCertKeySecret,
+		&repo.TLSClientCAData:   repoInfo.TLSClientCASecret,
 	}, make(map[string]*apiv1.Secret))
-
 	return repo, err
 }
 
diff --git a/util/git/client.go b/util/git/client.go
index 7ba42c1be2fe5..377d3be4d5957 100644
--- a/util/git/client.go
+++ b/util/git/client.go
@@ -25,6 +25,7 @@ import (
 
 	certutil "github.com/argoproj/argo-cd/util/cert"
 	argoconfig "github.com/argoproj/argo-cd/util/config"
+	"github.com/argoproj/argo-cd/util/repo/metrics"
 )
 
 type RevisionMetadata struct {
@@ -50,7 +51,7 @@ type Client interface {
 // ClientFactory is a factory of Git Clients
 // Primarily used to support creation of mock git clients during unit testing
 type ClientFactory interface {
-	NewClient(rawRepoURL string, path string, creds Creds, insecure bool, enableLfs bool) (Client, error)
+	NewClient(rawRepoURL string, path string, creds Creds, insecure bool, enableLfs bool, eventReporter metrics.Reporter) (Client, error)
 }
 
 // nativeGitClient implements Client interface using git CLI
@@ -65,6 +66,8 @@ type nativeGitClient struct {
 	insecure bool
 	// Whether the repository is LFS enabled
 	enableLfs bool
+	// metrics reporter
+	reporter metrics.Reporter
 }
 
 type factory struct{}
@@ -73,13 +76,14 @@ func NewFactory() ClientFactory {
 	return &factory{}
 }
 
-func (f *factory) NewClient(rawRepoURL string, path string, creds Creds, insecure bool, enableLfs bool) (Client, error) {
+func (f *factory) NewClient(rawRepoURL string, path string, creds Creds, insecure bool, enableLfs bool, reporter metrics.Reporter) (Client, error) {
 	client := nativeGitClient{
 		repoURL:   rawRepoURL,
 		root:      path,
 		creds:     creds,
 		insecure:  insecure,
 		enableLfs: enableLfs,
+		reporter:  reporter,
 	}
 	return &client, nil
 }
@@ -237,6 +241,7 @@ func (m *nativeGitClient) IsLFSEnabled() bool {
 
 // Fetch fetches latest updates from origin
 func (m *nativeGitClient) Fetch() error {
+	m.reporter.Event(m.repoURL, "GitRequestTypeFetch")
 	_, err := m.runCredentialedCmd("git", "fetch", "origin", "--tags", "--force")
 	// When we have LFS support enabled, check for large files and fetch them too.
 	if err == nil && m.IsLFSEnabled() {
@@ -323,6 +328,7 @@ func (m *nativeGitClient) LsRemote(revision string) (string, error) {
 	if err != nil {
 		return "", err
 	}
+	m.reporter.Event(m.repoURL, "GitRequestTypeLsRemote")
 	//refs, err := remote.List(&git.ListOptions{Auth: auth})
 	refs, err := listRemote(remote, &git.ListOptions{Auth: auth}, m.insecure, m.creds)
 	if err != nil {
diff --git a/util/git/creds.go b/util/git/creds.go
index dd3a399b76bc0..ede4cbf40b01c 100644
--- a/util/git/creds.go
+++ b/util/git/creds.go
@@ -44,15 +44,17 @@ type HTTPSCreds struct {
 	clientCertData string
 	// Client certificate key to use
 	clientCertKey string
+	clientCAData  string
 }
 
-func NewHTTPSCreds(username, password, clientCertData, clientCertKey string, insecure bool) HTTPSCreds {
+func NewHTTPSCreds(username, password, clientCertData, clientCertKey, clientCAData string, insecure bool) HTTPSCreds {
 	return HTTPSCreds{
 		username,
 		password,
 		insecure,
 		clientCertData,
 		clientCertKey,
+		clientCAData,
 	}
 }
 
@@ -113,6 +115,19 @@ func (c HTTPSCreds) Environ() (io.Closer, []string, error) {
 		env = append(env, fmt.Sprintf("GIT_SSL_KEY=%s", keyFile.Name()))
 
 	}
+	if c.clientCAData != "" {
+		caFile, err := ioutil.TempFile(util.TempDir, "")
+		if err != nil {
+			return NopCloser{}, nil, err
+		}
+		defer func() { _ = caFile.Close() }()
+		_, err = caFile.WriteString(c.clientCAData)
+		if err != nil {
+			_ = httpCloser.Close()
+			return NopCloser{}, nil, err
+		}
+		env = append(env, fmt.Sprintf("GIT_SSL_CAPATH=%s", caFile.Name()))
+	}
 	return httpCloser, env, nil
 }
 
diff --git a/util/git/git.go b/util/git/git.go
index a1d65fad129c6..f9dfd22be0b4d 100644
--- a/util/git/git.go
+++ b/util/git/git.go
@@ -76,13 +76,3 @@ func IsSSHURL(url string) (bool, string) {
 func IsHTTPSURL(url string) bool {
 	return httpsURLRegex.MatchString(url)
 }
-
-// TestRepo tests if a repo exists and is accessible with the given credentials
-func TestRepo(repo string, creds Creds, insecure bool, enableLfs bool) error {
-	clnt, err := NewFactory().NewClient(repo, "", creds, insecure, enableLfs)
-	if err != nil {
-		return err
-	}
-	_, err = clnt.LsRemote("HEAD")
-	return err
-}
diff --git a/util/git/git_test.go b/util/git/git_test.go
index 88c1881743ffa..c0e0e2fe40d4f 100644
--- a/util/git/git_test.go
+++ b/util/git/git_test.go
@@ -13,6 +13,7 @@ import (
 	"github.com/argoproj/argo-cd/test/fixture/log"
 	"github.com/argoproj/argo-cd/test/fixture/path"
 	"github.com/argoproj/argo-cd/test/fixture/test"
+	"github.com/argoproj/argo-cd/util/repo/metrics/mocks"
 )
 
 func TestIsCommitSHA(t *testing.T) {
@@ -127,7 +128,7 @@ func TestCustomHTTPClient(t *testing.T) {
 	assert.NotEqual(t, "", string(keyData))
 
 	// Get HTTPSCreds with client cert creds specified, and insecure connection
-	creds := NewHTTPSCreds("test", "test", string(certData), string(keyData), false)
+	creds := NewHTTPSCreds("test", "test", string(certData), string(keyData), "", false)
 	client := GetRepoHTTPClient("https://localhost:9443/foo/bar", false, creds)
 	assert.NotNil(t, client)
 	assert.NotNil(t, client.Transport)
@@ -150,7 +151,7 @@ func TestCustomHTTPClient(t *testing.T) {
 	}
 
 	// Get HTTPSCreds without client cert creds, but insecure connection
-	creds = NewHTTPSCreds("test", "test", "", "", true)
+	creds = NewHTTPSCreds("test", "test", "", "", "", true)
 	client = GetRepoHTTPClient("https://localhost:9443/foo/bar", true, creds)
 	assert.NotNil(t, client)
 	assert.NotNil(t, client.Transport)
@@ -174,7 +175,9 @@ func TestCustomHTTPClient(t *testing.T) {
 }
 
 func TestLsRemote(t *testing.T) {
-	clnt, err := NewFactory().NewClient("https://github.com/argoproj/argo-cd.git", "/tmp", NopCreds{}, false, false)
+	eventReporter := &mocks.EventReporter{}
+	eventReporter.On("Event", "https://github.com/argoproj/argo-cd.git", "GitRequestTypeLsRemote").Return()
+	clnt, err := NewFactory().NewClient("https://github.com/argoproj/argo-cd.git", "/tmp", NopCreds{}, false, false, eventReporter)
 	assert.NoError(t, err)
 	xpass := []string{
 		"HEAD",
@@ -219,7 +222,7 @@ func TestLFSClient(t *testing.T) {
 		defer func() { _ = os.RemoveAll(tempDir) }()
 	}
 
-	client, err := NewFactory().NewClient("https://github.com/argoproj-labs/argocd-testrepo-lfs", tempDir, NopCreds{}, false, true)
+	client, err := NewFactory().NewClient("https://github.com/argoproj-labs/argocd-testrepo-lfs", tempDir, NopCreds{}, false, true, &mocks.EventReporter{})
 	assert.NoError(t, err)
 
 	commitSHA, err := client.LsRemote("HEAD")
@@ -278,7 +281,10 @@ func TestNewFactory(t *testing.T) {
 		assert.NoError(t, err)
 		defer func() { _ = os.RemoveAll(dirName) }()
 
-		client, err := NewFactory().NewClient(tt.args.url, dirName, NopCreds{}, tt.args.insecureIgnoreHostKey, false)
+		metrics := &mocks.EventReporter{}
+		metrics.On("Event", tt.args.url, "GitRequestTypeLsRemote").Return()
+		metrics.On("Event", tt.args.url, "GitRequestTypeFetch").Return()
+		client, err := NewFactory().NewClient(tt.args.url, dirName, NopCreds{}, tt.args.insecureIgnoreHostKey, false, metrics)
 		assert.NoError(t, err)
 		commitSHA, err := client.LsRemote("HEAD")
 		assert.NoError(t, err)
diff --git a/util/git/repo/repo.go b/util/git/repo/repo.go
new file mode 100644
index 0000000000000..5f5dea26ffb4b
--- /dev/null
+++ b/util/git/repo/repo.go
@@ -0,0 +1,76 @@
+package repo
+
+import (
+	"github.com/argoproj/argo-cd/util/app/path"
+	"github.com/argoproj/argo-cd/util/git"
+	"github.com/argoproj/argo-cd/util/repo"
+	"github.com/argoproj/argo-cd/util/repo/metrics"
+)
+
+type gitRepo struct {
+	client git.Client
+	disco  func(root string) (map[string]string, error)
+}
+
+func (g gitRepo) Init() error {
+	err := g.client.Init()
+	if err != nil {
+		return err
+	}
+	return g.client.Fetch()
+}
+
+func (g gitRepo) LockKey() string {
+	return g.client.Root()
+}
+
+func (g gitRepo) GetApp(app, resolvedRevision string) (string, error) {
+	err := g.client.Checkout(resolvedRevision)
+	if err != nil {
+		return "", err
+	}
+	appPath, err := path.Path(g.client.Root(), app)
+	if err != nil {
+		return "", err
+	}
+	return appPath, nil
+}
+
+func (g gitRepo) ListApps(revision string) (map[string]string, string, error) {
+	resolvedRevision, err := g.client.LsRemote(revision)
+	if err != nil {
+		return nil, "", err
+	}
+	apps, err := g.disco(g.client.Root())
+	return apps, resolvedRevision, err
+}
+
+func (g gitRepo) ResolveRevision(path, revision string) (string, error) {
+	return g.client.LsRemote(revision)
+}
+
+func (g gitRepo) RevisionMetadata(_, resolvedRevision string) (*repo.RevisionMetadata, error) {
+	metadata, err := g.client.RevisionMetadata(resolvedRevision)
+	if err != nil {
+		return nil, err
+	}
+	out := &repo.RevisionMetadata{
+		Author:  metadata.Author,
+		Date:    metadata.Date,
+		Tags:    metadata.Tags,
+		Message: metadata.Message,
+	}
+	return out, err
+}
+
+func NewRepo(url string, creds git.Creds, insecure, enableLfs bool, disco func(root string) (map[string]string, error), reporter metrics.Reporter) (repo.Repo, error) {
+	workDir, err := repo.WorkDir(url)
+	if err != nil {
+		return nil, err
+	}
+	client, err := git.NewFactory().NewClient(url, workDir, creds, insecure, enableLfs, reporter)
+	if err != nil {
+		return nil, err
+	}
+	return &gitRepo{client, disco}, nil
+}
diff --git a/util/git/repo/repo_test.go b/util/git/repo/repo_test.go
new file mode 100644
index 0000000000000..f4e6e2d6c66ed
--- /dev/null
+++ b/util/git/repo/repo_test.go
@@ -0,0 +1,60 @@
+package repo
+
+import (
+	"testing"
+
+	"github.com/stretchr/testify/assert"
+	"github.com/stretchr/testify/mock"
+
+	"github.com/argoproj/argo-cd/util/git"
+	"github.com/argoproj/argo-cd/util/git/mocks"
+	"github.com/argoproj/argo-cd/util/repo"
+)
+
+func fixtures() (*gitRepo, git.Client, map[string]string) {
+	client := &mocks.Client{}
+	client.On("Checkout", mock.Anything, mock.Anything).Return(nil)
+	client.On("Root").Return("./testdata")
+	client.On("LsRemote", mock.Anything).Return("1.0.0", nil)
+	m := &git.RevisionMetadata{}
+	client.On("RevisionMetadata", mock.Anything).Return(m, nil)
+	apps := make(map[string]string)
+	r := &gitRepo{client, func(root string) (map[string]string, error) {
+		return apps, nil
+	}}
+	return r, client, apps
+}
+
+func Test_gitRepo_LockKey(t *testing.T) {
+	r, c, _ := fixtures()
+	assert.Equal(t, c.Root(), r.LockKey())
+}
+
+func Test_gitRepo_GetApp(t *testing.T) {
+	r, _, _ := fixtures()
+	_, err := r.GetApp("/", "")
+	assert.EqualError(t, err, "/: app path is absolute")
+}
+
+func Test_gitRepo_ListApps(t *testing.T) {
+	r, _, apps := fixtures()
+	listedApps, resolvedRevision, err := r.ListApps("")
+	assert.NoError(t, err)
+	assert.Equal(t, "1.0.0", resolvedRevision)
+	assert.Equal(t, apps, listedApps)
+}
+
+func Test_gitRepo_ResolveRevision(t *testing.T) {
+	r, _, _ := fixtures()
+	resolvedRevision, err := r.ResolveRevision(".", "")
+	assert.NoError(t, err)
+	assert.Equal(t, "1.0.0", resolvedRevision)
+}
+
+func Test_gitRepo_RevisionMetadata(t *testing.T) {
+	r, _, _ := fixtures()
+	m, err := r.RevisionMetadata(".", "")
+	assert.NoError(t, err)
+	assert.Equal(t, repo.RevisionMetadata{}, *m)
+
+}
diff --git a/util/git/repo/testdata/foo/Chart.yaml b/util/git/repo/testdata/foo/Chart.yaml
new file mode 100644
index 0000000000000..e69de29bb2d1d
diff --git a/util/helm/cmd.go b/util/helm/cmd.go
new file mode 100644
index 0000000000000..172f39a2e0d66
--- /dev/null
+++ b/util/helm/cmd.go
@@ -0,0 +1,165 @@
+package helm
+
+import (
+	"fmt"
+	"io/ioutil"
+	"os"
+	"os/exec"
+	"regexp"
+
+	argoexec "github.com/argoproj/pkg/exec"
+)
+
+// A thin wrapper around the "helm" command, adding logging and error translation.
+type Cmd struct {
+	helmHome string
+	WorkDir  string
+}
+
+func NewCmd(workDir string) (*Cmd, error) {
+	tmpDir, err := ioutil.TempDir("", "helm")
+	if err != nil {
+		return nil, err
+	}
+	return &Cmd{WorkDir: workDir, helmHome: tmpDir}, err
+}
+
+var redactor = func(text string) string {
+	return regexp.MustCompile("(--username|--password) [^ ]*").ReplaceAllString(text, "$1 ******")
+}
+
+func (c Cmd) run(args ...string) (string, error) {
+	cmd := exec.Command("helm", args...)
+	cmd.Dir = c.WorkDir
+	cmd.Env = os.Environ()
+	cmd.Env = append(cmd.Env, fmt.Sprintf("HELM_HOME=%s", c.helmHome))
+	return argoexec.RunCommandExt(cmd, argoexec.CmdOpts{
+		Redactor: redactor,
+	})
+}
+
+func (c *Cmd) Init() (string, error) {
+	return c.run("init", "--client-only", "--skip-refresh")
+}
+
+type RepoAddOpts struct {
+	Username, Password        string
+	CAData, CertData, KeyData []byte
+}
+
+func (c *Cmd) RepoAdd(name, url string, opts RepoAddOpts) (string, error) {
+
+	tmp, err := ioutil.TempDir("", "helm")
+	if err != nil {
+		return "", err
+	}
+	defer func() { _ = os.RemoveAll(tmp) }()
+
+	args := []string{"repo", "add"}
+
+	if opts.Username != "" {
+		args = append([]string{"--username", opts.Username}, args...)
+	}
+
+	if opts.Password != "" {
+		args = append([]string{"--password", opts.Password}, args...)
+	}
+
+	if len(opts.CAData) > 0 {
+		caFile, err := ioutil.TempFile("", "helm")
+		if err != nil {
+			return "", err
+		}
+		_, err = caFile.Write(opts.CAData)
+		if err != nil {
+			return "", err
+		}
+		args = append([]string{"--ca-file", caFile.Name()}, args...)
+	}
+
+	if len(opts.CertData) > 0 {
+		certFile, err := ioutil.TempFile("", "helm")
+		if err != nil {
+			return "", err
+		}
+		_, err = certFile.Write(opts.CertData)
+		if err != nil {
+			return "", err
+		}
+		args = append([]string{"--cert-file", certFile.Name()}, args...)
+	}
+
+	if len(opts.KeyData) > 0 {
+		keyFile, err := ioutil.TempFile("", "helm")
+		if err != nil {
+			return "", err
+		}
+		_, err = keyFile.Write(opts.KeyData)
+		if err != nil {
+			return "", err
+		}
+		args = append([]string{"--key-file", keyFile.Name()}, args...)
+	}
+
+	args = append(args, name, url)
+
+	return c.run(args...)
+}
+
+func (c *Cmd) RepoUpdate() (string, error) {
+	return c.run("repo", "update")
+}
+
+type FetchOpts struct {
+	Version, Destination string
+}
+
+func (c *Cmd) Fetch(repo, chartName string, opts FetchOpts) (string, error) {
+	args := []string{"fetch", "--untar", "--untardir", opts.Destination}
+
+	if opts.Version != "" {
+		args = append(args, "--version", opts.Version)
+	}
+
+	args = append(args, repo+"/"+chartName)
+	return c.run(args...)
+}
+
+func (c *Cmd) dependencyBuild() (string, error) {
+	return c.run("dependency", "build")
+}
+
+func (c *Cmd) inspectValues(values string) (string, error) {
+	return c.run("inspect", "values", values)
+}
+
+type templateOpts struct {
+	name      string
+	namespace string
+	set       map[string]string
+	setString map[string]string
+	values    []string
+}
+
+func (c *Cmd) template(chart string, opts templateOpts) (string, error) {
+	args := []string{"template", chart, "--name", opts.name}
+
+	if opts.namespace != "" {
+		args = append(args, "--namespace", opts.namespace)
+	}
+	for key, val := range opts.set {
+		args = append(args, "--set", key+"="+val)
+	}
+	for key, val := range opts.setString {
+		args = append(args, "--set-string", key+"="+val)
+	}
+	for _, val := range opts.values {
+		args = append(args, "--values", val)
+	}
+
+	return c.run(args...)
+}
+
+func (c *Cmd) Close() {
+	_ = os.RemoveAll(c.helmHome)
+}
diff --git a/util/helm/cmd_test.go b/util/helm/cmd_test.go
new file mode 100644
index 0000000000000..98208914d90c0
--- /dev/null
+++ b/util/helm/cmd_test.go
@@ -0,0 +1,13 @@
+package helm
+
+import (
+	"testing"
+
+	"github.com/stretchr/testify/assert"
+)
+
+func Test_cmd_redactor(t *testing.T) {
+	assert.Equal(t, "--foo bar", redactor("--foo bar"))
+	assert.Equal(t, "--username ******", redactor("--username bar"))
+	assert.Equal(t, "--password ******", redactor("--password bar"))
+}
diff --git a/util/helm/helm.go b/util/helm/helm.go
index be11c7193659a..27949a81b2316 100644
--- a/util/helm/helm.go
+++ b/util/helm/helm.go
@@ -5,19 +5,15 @@ import (
 	"io/ioutil"
 	"net/url"
 	"os"
-	"os/exec"
 	"path"
 	"regexp"
 	"sort"
 	"strings"
 
-	argoexec "github.com/argoproj/pkg/exec"
 	"github.com/ghodss/yaml"
-	log "github.com/sirupsen/logrus"
 	"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
 
 	argoappv1 "github.com/argoproj/argo-cd/pkg/apis/application/v1alpha1"
-	"github.com/argoproj/argo-cd/util"
 	"github.com/argoproj/argo-cd/util/config"
 	"github.com/argoproj/argo-cd/util/kube"
 )
@@ -30,8 +26,6 @@ type Helm interface {
 	GetParameters(valuesFiles []string) ([]*argoappv1.HelmParameter, error)
 	// DependencyBuild runs `helm dependency build` to download a chart's dependencies
 	DependencyBuild() error
-	// SetHome sets the helm home location (default "~/.helm")
-	SetHome(path string)
 	// Init runs `helm init --client-only`
 	Init() error
 	// Dispose deletes temp resources
@@ -39,16 +33,17 @@ type Helm interface {
 }
 
 // NewHelmApp create a new wrapper to run commands on the `helm` command-line tool.
-func NewHelmApp(path string, helmRepos []*argoappv1.HelmRepository) Helm {
-	return &helm{path: path, helmRepos: helmRepos}
+func NewHelmApp(workDir string, repos argoappv1.Repositories) (Helm, error) {
+	cmd, err := NewCmd(workDir)
+	if err != nil {
+		return nil, err
+	}
+	return &helm{repos: &repos, cmd: *cmd}, nil
 }
 
 type helm struct {
-	path             string
-	home             string
-	helmRepos        []*argoappv1.HelmRepository
-	reposInitialized bool
-	tempDirs         []string
+	cmd   Cmd
+	repos *argoappv1.Repositories
 }
 
 // IsMissingDependencyErr tests if the error is related to a missing chart dependency
@@ -57,23 +52,17 @@ func IsMissingDependencyErr(err error) bool {
 }
 
 func (h *helm) Template(appName string, namespace string, opts *argoappv1.ApplicationSourceHelm) ([]*unstructured.Unstructured, error) {
-	args := []string{
-		"template", ".",
-	}
-
-	setReleaseName := true
-
-	if namespace != "" {
-		args = append(args, "--namespace", namespace)
+	templateOpts := templateOpts{
+		name:      appName,
+		namespace: namespace,
+		set:       map[string]string{},
+		setString: map[string]string{},
 	}
 	if opts != nil {
 		if opts.ReleaseName != "" {
-			args = append(args, "--name", opts.ReleaseName)
-			setReleaseName = false
-		}
-		for _, valuesFile := range opts.ValueFiles {
-			args = append(args, "-f", valuesFile)
+			templateOpts.name = opts.ReleaseName
 		}
+		templateOpts.values = opts.ValueFiles
 		if opts.Values != "" {
 			file, err := ioutil.TempFile("", "values-*.yaml")
 			if err != nil {
@@ -85,109 +74,63 @@ func (h *helm) Template(appName string, namespace string, opts *argoappv1.Applic
 			if err != nil {
 				return nil, err
 			}
-			args = append(args, "-f", p)
+			templateOpts.values = append(templateOpts.values, p)
 		}
 		for _, p := range opts.Parameters {
 			if p.ForceString {
-				args = append(args, "--set-string", fmt.Sprintf("%s=%s", p.Name, p.Value))
+				templateOpts.setString[p.Name] = p.Value
 			} else {
-				args = append(args, "--set", fmt.Sprintf("%s=%s", p.Name, p.Value))
+				templateOpts.set[p.Name] = p.Value
 			}
 		}
 	}
-
-	if setReleaseName {
-		args = append(args, "--name", appName)
+	if templateOpts.name == "" {
+		templateOpts.name = appName
 	}
 
-	out, err := h.helmCmd(args...)
+	out, err := h.cmd.template(".", templateOpts)
 	if err != nil {
 		return nil, err
 	}
 	return kube.SplitYAML(out)
 }
 
-func (h *helm) DependencyBuild() error {
-	if !h.reposInitialized {
-		var files []*os.File
-		defer func() {
-			for i := range files {
-				util.DeleteFile(files[i].Name())
-			}
-		}()
-
-		for _, repo := range h.helmRepos {
-			args := []string{"repo", "add"}
-
-			for flag, data := range map[string][]byte{"--ca-file": repo.CAData, "--cert-file": repo.CertData, "--key-file": repo.KeyData} {
-				if repo.KeyData != nil {
-					f, err := ioutil.TempFile(util.TempDir, "")
-					if err != nil {
-						return fmt.Errorf("failed to generate temp file for %s: %v", flag, err)
-					}
-					files = append(files, f)
-					_, err = f.Write(data)
-					if err != nil {
-						return fmt.Errorf("failed to write temp file for %s: %v", flag, err)
-					}
-					_ = f.Close()
-					args = append(args, flag, f.Name())
-				}
-			}
-			if repo.Username != "" {
-				args = append(args, "--username", repo.Username)
-			}
-			if repo.Password != "" {
-				args = append(args, "--password", repo.Password)
-			}
+func (h *helm) reposInitialized() bool {
+	return h.repos != nil
+}
 
-			_, err := h.helmCmdExt(append(args, repo.Name, repo.URL), func(log string) string {
-				if repo.Username != "" {
-					log = strings.Replace(log, fmt.Sprintf("--username %s", repo.Username), "--username ***", 1)
-				}
-				if repo.Password != "" {
-					log = strings.Replace(log, fmt.Sprintf("--password %s", repo.Password), "--password ***", 1)
-				}
-				return log
+func (h *helm) DependencyBuild() error {
+	if !h.reposInitialized() {
+		for _, repo := range h.repos.Filter(func(r *argoappv1.Repository) bool { return r.Type == "helm" }) {
+			_, err := h.cmd.RepoAdd(repo.Name, repo.Repo, RepoAddOpts{
+				Username: repo.Username,
+				Password: repo.Password,
+				CAData:   []byte(repo.TLSClientCAData),
+				CertData: []byte(repo.TLSClientCertData),
+				KeyData:  []byte(repo.TLSClientCertKey),
 			})
+
 			if err != nil {
 				return err
 			}
 		}
+		h.repos = nil
 	}
-	_, err := h.helmCmd("dependency", "build")
+	_, err := h.cmd.dependencyBuild()
 	return err
 }
 
-func (h *helm) SetHome(home string) {
-	h.home = home
-}
-
 func (h *helm) Init() error {
-	if h.home == "" {
-		home, err := ioutil.TempDir("", "helm")
-		if err != nil {
-			return err
-		}
-		h.home = home
-		h.tempDirs = append(h.tempDirs, home)
-	}
-	_, err := h.helmCmd("init", "--client-only", "--skip-refresh")
+	_, err := h.cmd.Init()
 	return err
 }
 
 func (h *helm) Dispose() {
-	for i := range h.tempDirs {
-		err := os.RemoveAll(h.tempDirs[i])
-		if err != nil {
-			log.Warnf("Failed to delete temp directory %s", h.tempDirs[i])
-		}
-	}
-	h.tempDirs = []string{}
+	h.cmd.Close()
 }
 
 func (h *helm) GetParameters(valuesFiles []string) ([]*argoappv1.HelmParameter, error) {
-	out, err := h.helmCmd("inspect", "values", ".")
+	out, err := h.cmd.inspectValues(".")
 	if err != nil {
 		return nil, err
 	}
@@ -198,7 +141,7 @@ func (h *helm) GetParameters(valuesFiles []string) ([]*argoappv1.HelmParameter,
 		if err == nil && (parsedURL.Scheme == "http" || parsedURL.Scheme == "https") {
 			fileValues, err = config.ReadRemoteFile(file)
 		} else {
-			fileValues, err = ioutil.ReadFile(path.Join(h.path, file))
+			fileValues, err = ioutil.ReadFile(path.Join(h.cmd.WorkDir, file))
 		}
 		if err != nil {
 			return nil, fmt.Errorf("failed to read value file %s: %s", file, err)
@@ -228,25 +171,6 @@ func (h *helm) GetParameters(valuesFiles []string) ([]*argoappv1.HelmParameter,
 	return params, nil
 }
 
-func (h *helm) helmCmd(args ...string) (string, error) {
-	return h.helmCmdExt(args, argoexec.Unredacted)
-}
-
-func (h *helm) helmCmdExt(args []string, redactor func(string) string) (string, error) {
-	cleanHelmParameters(args)
-	cmd := exec.Command("helm", args...)
-	cmd.Env = os.Environ()
-	cmd.Dir = h.path
-	if h.home != "" {
-		cmd.Env = append(cmd.Env, fmt.Sprintf("HELM_HOME=%s", h.home))
-	}
-
-	return argoexec.RunCommandExt(cmd, argoexec.CmdOpts{
-		Timeout:  config.CmdOpts().Timeout,
-		Redactor: redactor,
-	})
-}
-
 func flatVals(input map[string]interface{}, output map[string]string, prefixes ...string) {
 	for key, val := range input {
 		if subMap, ok := val.(map[string]interface{}); ok {
diff --git a/util/helm/helm_test.go b/util/helm/helm_test.go
index 38d16e553df7b..810cf5fde7c59 100644
--- a/util/helm/helm_test.go
+++ b/util/helm/helm_test.go
@@ -1,7 +1,6 @@
 package helm
 
 import (
-	"io/ioutil"
 	"os"
 	"testing"
 
@@ -23,7 +22,8 @@ func findParameter(params []*argoappv1.HelmParameter, name string) *argoappv1.He
 }
 
 func TestHelmTemplateParams(t *testing.T) {
-	h := NewHelmApp("./testdata/minio", []*argoappv1.HelmRepository{})
+	h, err := NewHelmApp("./testdata/minio", argoappv1.Repositories{})
+	assert.NoError(t, err)
 	opts := argoappv1.ApplicationSourceHelm{
 		Parameters: []argoappv1.HelmParameter{
 			{
@@ -58,7 +58,8 @@ func TestHelmTemplateParams(t *testing.T) {
 }
 
 func TestHelmTemplateValues(t *testing.T) {
-	h := NewHelmApp("./testdata/redis", []*argoappv1.HelmRepository{})
+	h, err := NewHelmApp("./testdata/redis", argoappv1.Repositories{})
+	assert.NoError(t, err)
 	opts := argoappv1.ApplicationSourceHelm{
 		ValueFiles: []string{"values-production.yaml"},
 	}
@@ -77,7 +78,8 @@ func TestHelmTemplateValues(t *testing.T) {
 }
 
 func TestHelmTemplateValuesURL(t *testing.T) {
-	h := NewHelmApp("./testdata/redis", []*argoappv1.HelmRepository{})
+	h, err := NewHelmApp("./testdata/redis", argoappv1.Repositories{})
+	assert.NoError(t, err)
 	opts := argoappv1.ApplicationSourceHelm{
 		ValueFiles: []string{"https://raw.githubusercontent.com/argoproj/argo-cd/master/util/helm/testdata/redis/values-production.yaml"},
 	}
@@ -90,7 +92,8 @@ func TestHelmTemplateValuesURL(t *testing.T) {
 }
 
 func TestHelmGetParams(t *testing.T) {
-	h := NewHelmApp("./testdata/redis", []*argoappv1.HelmRepository{})
+	h, err := NewHelmApp("./testdata/redis", argoappv1.Repositories{})
+	assert.NoError(t, err)
 	params, err := h.GetParameters([]string{})
 	assert.Nil(t, err)
 
@@ -100,7 +103,8 @@ func TestHelmGetParams(t *testing.T) {
 }
 
 func TestHelmGetParamsValueFiles(t *testing.T) {
-	h := NewHelmApp("./testdata/redis", []*argoappv1.HelmRepository{})
+	h, err := NewHelmApp("./testdata/redis", argoappv1.Repositories{})
+	assert.NoError(t, err)
 	params, err := h.GetParameters([]string{"values-production.yaml"})
 	assert.Nil(t, err)
 
@@ -115,11 +119,8 @@ func TestHelmDependencyBuild(t *testing.T) {
 	}
 	clean()
 	defer clean()
-	h := NewHelmApp("./testdata/wordpress", []*argoappv1.HelmRepository{})
-	helmHome, err := ioutil.TempDir("", "")
+	h, err := NewHelmApp("./testdata/wordpress", argoappv1.Repositories{})
 	assert.NoError(t, err)
-	defer func() { _ = os.RemoveAll(helmHome) }()
-	h.SetHome(helmHome)
 	err = h.Init()
 	assert.NoError(t, err)
 	_, err = h.Template("wordpress", "", nil)
@@ -131,7 +132,8 @@ func TestHelmDependencyBuild(t *testing.T) {
 }
 
 func TestHelmTemplateReleaseNameOverwrite(t *testing.T) {
-	h := NewHelmApp("./testdata/redis", []*argoappv1.HelmRepository{})
+	h, err := NewHelmApp("./testdata/redis", argoappv1.Repositories{})
+	assert.NoError(t, err)
 	opts := argoappv1.ApplicationSourceHelm{
 		ReleaseName: "my-release",
 	}
@@ -150,7 +152,8 @@ func TestHelmTemplateReleaseNameOverwrite(t *testing.T) {
 }
 
 func TestHelmTemplateReleaseName(t *testing.T) {
-	h := NewHelmApp("./testdata/redis", []*argoappv1.HelmRepository{})
+	h, err := NewHelmApp("./testdata/redis", argoappv1.Repositories{})
+	assert.NoError(t, err)
 	opts := argoappv1.ApplicationSourceHelm{}
 	objs, err := h.Template("test", "", &opts)
 	assert.Nil(t, err)
@@ -186,7 +189,8 @@ func TestHelmArgCleaner(t *testing.T) {
 }
 
 func TestHelmValues(t *testing.T) {
-	h := NewHelmApp("./testdata/redis", []*argoappv1.HelmRepository{})
+	h, err := NewHelmApp("./testdata/redis", argoappv1.Repositories{})
+	assert.NoError(t, err)
 	opts := argoappv1.ApplicationSourceHelm{
 		ValueFiles: []string{"values-production.yaml"},
 		Values: `cluster:
diff --git a/util/helm/repo/repo.go b/util/helm/repo/repo.go
new file mode 100644
index 0000000000000..06167628781ac
--- /dev/null
+++ b/util/helm/repo/repo.go
@@ -0,0 +1,174 @@
+package repo
+
+import (
+	"errors"
+	"fmt"
+	"net/http"
+	"path/filepath"
+	"strings"
+	"time"
+
+	"github.com/patrickmn/go-cache"
+	log "github.com/sirupsen/logrus"
+	"gopkg.in/yaml.v2"
+
+	"github.com/argoproj/argo-cd/util/helm"
+	"github.com/argoproj/argo-cd/util/repo"
+)
+
+var indexCache = cache.New(5*time.Minute, 5*time.Minute)
+
+type helmRepo struct {
+	cmd                           *helm.Cmd
+	url, name, username, password string
+	caData, certData, keyData     []byte
+}
+
+func (c helmRepo) Init() error {
+	_, err := c.getIndex()
+	if err != nil {
+		return err
+	}
+	_, err = c.repoAdd()
+	if err != nil {
+		return err
+	}
+	_, err = c.cmd.RepoUpdate()
+	return err
+}
+
+func (c helmRepo) LockKey() string {
+	return c.cmd.WorkDir
+}
+
+func (c helmRepo) ResolveRevision(app, revision string) (string, error) {
+	if revision != "" {
+		return revision, nil
+	}
+
+	index, err := c.getIndex()
+	if err != nil {
+		return "", err
+	}
+
+	for chartName := range index.Entries {
+		if chartName == app {
+			return index.Entries[chartName][0].Version, nil
+		}
+	}
+
+	return "", errors.New("failed to find chart " + app)
+}
+
+func (c helmRepo) RevisionMetadata(app, resolvedRevision string) (*repo.RevisionMetadata, error) {
+
+	index, err := c.getIndex()
+	if err != nil {
+		return nil, err
+	}
+
+	for _, entry := range index.Entries[app] {
+		if entry.Version == resolvedRevision {
+			return &repo.RevisionMetadata{Date: entry.Created}, nil
+		}
+	}
+
+	return nil, fmt.Errorf("unknown chart \"%s/%s\"", app, resolvedRevision)
+}
+
+type entry struct {
+	Version string
+	Created time.Time
+}
+
+type index struct {
+	Entries map[string][]entry
+}
+
+func (c helmRepo) getIndex() (*index, error) {
+
+	cachedIndex, found := indexCache.Get(c.url)
+	if found {
+		log.WithFields(log.Fields{"url": c.url}).Debug("index cache hit")
+		i := cachedIndex.(index)
+		return &i, nil
+	}
+
+	start := time.Now()
+
+	resp, err := http.Get(strings.TrimSuffix(c.url, "/") + "/index.yaml")
+	if err != nil {
+		return nil, err
+	}
+	defer func() { _ = resp.Body.Close() }()
+
+	if resp.StatusCode != 200 {
+		return nil, errors.New("failed to get index: " + resp.Status)
+	}
+
+	index := &index{}
+	err = yaml.NewDecoder(resp.Body).Decode(index)
+
+	log.WithFields(log.Fields{"seconds": time.Since(start).Seconds()}).Info("took to get index")
+
+	indexCache.Set(c.url, *index, cache.DefaultExpiration)
+
+	return index, err
+}
+
+func (c helmRepo) ListApps(revision string) (map[string]string, string, error) {
+	index, err := c.getIndex()
+	if err != nil {
+		return nil, "", err
+	}
+	apps := make(map[string]string, len(index.Entries))
+	for chartName := range index.Entries {
+		apps[chartName] = "Helm"
+	}
+	return apps, revision, nil
+}
+
+func (c helmRepo) repoAdd() (string, error) {
+	return c.cmd.RepoAdd(c.name, c.url, helm.RepoAddOpts{
+		Username: c.username, Password: c.password,
+		CertData: c.certData, KeyData: c.keyData, CAData: c.caData,
+	})
+}
+
+func (c helmRepo) GetApp(app string, resolvedRevision string) (string, error) {
+	if resolvedRevision == "" {
+		return "", fmt.Errorf("invalid resolved revision \"%s\", must be resolved", resolvedRevision)
+	}
+
+	err := c.checkKnownChart(app)
+	if err != nil {
+		return "", err
+	}
+
+	_, err = c.cmd.Fetch(c.name, app, helm.FetchOpts{Version: resolvedRevision, Destination: "."})
+
+	return filepath.Join(c.cmd.WorkDir, app), err
+}
+
+func (c helmRepo) checkKnownChart(chartName string) error {
+	knownChart, err := c.isKnownChart(chartName)
+	if err != nil {
+		return err
+	}
+	if !knownChart {
+		return fmt.Errorf("unknown chart \"%s\"", chartName)
+	}
+	return nil
+}
+
+func (c helmRepo) isKnownChart(chartName string) (bool, error) {
+
+	index, err := c.getIndex()
+	if err != nil {
+		return false, err
+	}
+
+	_, ok := index.Entries[chartName]
+
+	return ok, nil
+}
diff --git a/util/helm/repo/repo_factory.go b/util/helm/repo/repo_factory.go
new file mode 100644
index 0000000000000..01b0e48627a1c
--- /dev/null
+++ b/util/helm/repo/repo_factory.go
@@ -0,0 +1,60 @@
+package repo
+
+import (
+	"errors"
+	"time"
+
+	"github.com/patrickmn/go-cache"
+	log "github.com/sirupsen/logrus"
+
+	"github.com/argoproj/argo-cd/util/helm"
+	"github.com/argoproj/argo-cd/util/repo"
+)
+
+var repoCache = cache.New(5*time.Minute, 5*time.Minute)
+
+func NewRepo(url, name, username, password string, caData, certData, keyData []byte) (repo.Repo, error) {
+
+	if name == "" {
+		return nil, errors.New("must name repo")
+	}
+
+	cached, found := repoCache.Get(url)
+	if found {
+		log.WithFields(log.Fields{"url": url}).Debug("helm repo cache hit")
+		return cached.(repo.Repo), nil
+	}
+	log.WithFields(log.Fields{"url": url}).Debug("helm repo cache miss")
+
+	workDir, err := repo.WorkDir(url)
+	if err != nil {
+		return nil, err
+	}
+	cmd, err := helm.NewCmd(workDir)
+	if err != nil {
+		return nil, err
+	}
+	_, err = cmd.Init()
+	if err != nil {
+		cmd.Close()
+		return nil, err
+	}
+
+	r := helmRepo{
+		cmd:      cmd,
+		url:      url,
+		name:     name,
+		username: username,
+		password: password,
+		caData:   caData,
+		certData: certData,
+		keyData:  keyData,
+	}
+	err = r.Init()
+	if err != nil {
+		cmd.Close()
+		return nil, err
+	}
+	repoCache.Set(url, r, cache.DefaultExpiration)
+	return r, nil
+}
diff --git a/util/helm/repo/repo_factory_test.go b/util/helm/repo/repo_factory_test.go
new file mode 100644
index 0000000000000..26bee14c5b761
--- /dev/null
+++ b/util/helm/repo/repo_factory_test.go
@@ -0,0 +1,24 @@
+package repo
+
+import (
+	"testing"
+
+	"github.com/stretchr/testify/assert"
+)
+
+func TestRepoFactory(t *testing.T) {
+	t.Run("Unnamed", func(t *testing.T) {
+		_, err := NewRepo("http://0.0.0.0", "", "", "", nil, nil, nil)
+		assert.EqualError(t, err, "must name repo")
+	})
+
+	t.Run("GarbageRepo", func(t *testing.T) {
+		_, err := NewRepo("http://0.0.0.0", "test", "", "", nil, nil, nil)
+		assert.Error(t, err)
+	})
+
+	t.Run("Valid", func(t *testing.T) {
+		_, err := NewRepo("https://kubernetes-charts.storage.googleapis.com", "test", "", "", nil, nil, nil)
+		assert.NoError(t, err)
+	})
+}
diff --git a/util/helm/repo/repo_test.go b/util/helm/repo/repo_test.go
new file mode 100644
index 0000000000000..2381e9f039bb9
--- /dev/null
+++ b/util/helm/repo/repo_test.go
@@ -0,0 +1,61 @@
+package repo
+
+import (
+	"testing"
+
+	"github.com/stretchr/testify/assert"
+)
+
+func TestRepo(t *testing.T) {
+	repo, err := NewRepo("https://kubernetes-charts.storage.googleapis.com", "test", "", "", nil, nil, nil)
+	assert.NoError(t, err)
+
+	// TODO - this changes regularly
+	const latestWordpressVersion = "5.8.0"
+
+	t.Run("List", func(t *testing.T) {
+		apps, _, err := repo.ListApps("")
+		assert.NoError(t, err)
+		assert.Contains(t, apps, "wordpress")
+	})
+
+	t.Run("ResolveRevision", func(t *testing.T) {
+		unresolvedRevision := ""
+		resolvedRevision, err := repo.ResolveRevision("wordpress", unresolvedRevision)
+		assert.NoError(t, err)
+		assert.NotEqual(t, unresolvedRevision, resolvedRevision)
+	})
+
+	t.Run("ResolveRevision/Latest", func(t *testing.T) {
+		resolvedRevision, err := repo.ResolveRevision("wordpress", latestWordpressVersion)
+		assert.NoError(t, err)
+		assert.Equal(t, latestWordpressVersion, resolvedRevision)
+	})
+
+	t.Run("Checkout", func(t *testing.T) {
+		appPath, err := repo.GetApp("wordpress", latestWordpressVersion)
+		assert.NoError(t, err)
+		assert.NotEmpty(t, appPath)
+	})
+
+	t.Run("Checkout/UnresolvedRevision", func(t *testing.T) {
+		_, err := repo.GetApp("wordpress", "")
+		assert.EqualError(t, err, "invalid resolved revision \"\", must be resolved")
+	})
+
+	t.Run("Checkout/UnknownChart", func(t *testing.T) {
+		_, err := repo.GetApp("garbage", latestWordpressVersion)
+		assert.EqualError(t, err, "unknown chart \"garbage\"")
+	})
+
+	t.Run("RevisionMetadata/UnknownChart", func(t *testing.T) {
+		_, err = repo.RevisionMetadata("garbage", latestWordpressVersion)
+		assert.EqualError(t, err, "unknown chart \"garbage/5.8.0\"")
+	})
+
+	t.Run("RevisionMetadata/KnownChart", func(t *testing.T) {
+		metaData, err := repo.RevisionMetadata("wordpress", latestWordpressVersion)
+		assert.NoError(t, err)
+		assert.NotEmpty(t, metaData.Date)
+	})
+}
diff --git a/util/repo/factory/factory.go b/util/repo/factory/factory.go
new file mode 100644
index 0000000000000..4b0dd64a70a5b
--- /dev/null
+++ b/util/repo/factory/factory.go
@@ -0,0 +1,31 @@
+package factory
+
+import (
+	"github.com/argoproj/argo-cd/pkg/apis/application/v1alpha1"
+	"github.com/argoproj/argo-cd/util/app/discovery"
+	"github.com/argoproj/argo-cd/util/creds"
+	gitrepo "github.com/argoproj/argo-cd/util/git/repo"
+	helmrepo "github.com/argoproj/argo-cd/util/helm/repo"
+	"github.com/argoproj/argo-cd/util/repo"
+	"github.com/argoproj/argo-cd/util/repo/metrics"
+)
+
+type Factory interface {
+	NewRepo(r *v1alpha1.Repository, reporter metrics.Reporter) (repo.Repo, error)
+}
+
+func NewFactory() Factory {
+	return &factory{}
+}
+
+type factory struct {
+}
+
+func (f *factory) NewRepo(r *v1alpha1.Repository, reporter metrics.Reporter) (repo.Repo, error) {
+	switch r.Type {
+	case "helm":
+		return helmrepo.NewRepo(r.Repo, r.Name, r.Username, r.Password, []byte(r.TLSClientCAData), []byte(r.TLSClientCertData), []byte(r.TLSClientCertKey))
+	default:
+		return gitrepo.NewRepo(r.Repo, creds.GetRepoCreds(r), r.IsInsecure(), r.EnableLFS, discovery.Discover, reporter)
+	}
+}
diff --git a/util/repo/factory/mocks/Factory.go b/util/repo/factory/mocks/Factory.go
new file mode 100644
index 0000000000000..2d78565fdf86d
--- /dev/null
+++ b/util/repo/factory/mocks/Factory.go
@@ -0,0 +1,41 @@
+// Code generated by mockery v1.0.0. DO NOT EDIT.
+
+package mocks
+
+import (
+	mock "github.com/stretchr/testify/mock"
+
+	metrics "github.com/argoproj/argo-cd/util/repo/metrics"
+
+	repo "github.com/argoproj/argo-cd/util/repo"
+
+	v1alpha1 "github.com/argoproj/argo-cd/pkg/apis/application/v1alpha1"
+)
+
+// Factory is an autogenerated mock type for the Factory type
+type Factory struct {
+	mock.Mock
+}
+
+// NewRepo provides a mock function with given fields: r, reporter
+func (_m *Factory) NewRepo(r *v1alpha1.Repository, reporter metrics.Reporter) (repo.Repo, error) {
+	ret := _m.Called(r, reporter)
+
+	var r0 repo.Repo
+	if rf, ok := ret.Get(0).(func(*v1alpha1.Repository, metrics.Reporter) repo.Repo); ok {
+		r0 = rf(r, reporter)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(repo.Repo)
+		}
+	}
+
+	var r1 error
+	if rf, ok := ret.Get(1).(func(*v1alpha1.Repository, metrics.Reporter) error); ok {
+		r1 = rf(r, reporter)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
diff --git a/util/repo/metrics/event_reporter.go b/util/repo/metrics/event_reporter.go
new file mode 100644
index 0000000000000..4e92696eb5584
--- /dev/null
+++ b/util/repo/metrics/event_reporter.go
@@ -0,0 +1,13 @@
+package metrics
+
+type Reporter interface {
+	Event(repoURL, event string)
+}
+
+var NopReporter = nopReporter{}
+
+type nopReporter struct {
+}
+
+func (n nopReporter) Event(repoURL, event string) {
+}
diff --git a/util/repo/metrics/mocks/EventReporter.go b/util/repo/metrics/mocks/EventReporter.go
new file mode 100644
index 0000000000000..c30097d9c092d
--- /dev/null
+++ b/util/repo/metrics/mocks/EventReporter.go
@@ -0,0 +1,15 @@
+// Code generated by mockery v1.0.0. DO NOT EDIT.
+
+package mocks
+
+import mock "github.com/stretchr/testify/mock"
+
+// Reporter is an autogenerated mock type for the Reporter type
+type EventReporter struct {
+	mock.Mock
+}
+
+// Event provides a mock function with given fields: repoURL, event
+func (_m *EventReporter) Event(repoURL string, event string) {
+	_m.Called(repoURL, event)
+}
diff --git a/util/repo/mocks/Repo.go b/util/repo/mocks/Repo.go
new file mode 100644
index 0000000000000..9d9cc4704f57e
--- /dev/null
+++ b/util/repo/mocks/Repo.go
@@ -0,0 +1,137 @@
+// Code generated by mockery v1.0.0. DO NOT EDIT.
+
+package mocks
+
+import (
+	mock "github.com/stretchr/testify/mock"
+
+	repo "github.com/argoproj/argo-cd/util/repo"
+)
+
+// Repo is an autogenerated mock type for the Repo type
+type Repo struct {
+	mock.Mock
+}
+
+// GetApp provides a mock function with given fields: app, resolvedRevision
+func (_m *Repo) GetApp(app string, resolvedRevision string) (string, error) {
+	ret := _m.Called(app, resolvedRevision)
+
+	var r0 string
+	if rf, ok := ret.Get(0).(func(string, string) string); ok {
+		r0 = rf(app, resolvedRevision)
+	} else {
+		r0 = ret.Get(0).(string)
+	}
+
+	var r1 error
+	if rf, ok := ret.Get(1).(func(string, string) error); ok {
+		r1 = rf(app, resolvedRevision)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// Init provides a mock function with given fields:
+func (_m *Repo) Init() error {
+	ret := _m.Called()
+
+	var r0 error
+	if rf, ok := ret.Get(0).(func() error); ok {
+		r0 = rf()
+	} else {
+		r0 = ret.Error(0)
+	}
+
+	return r0
+}
+
+// ListApps provides a mock function with given fields: revision
+func (_m *Repo) ListApps(revision string) (map[string]string, string, error) {
+	ret := _m.Called(revision)
+
+	var r0 map[string]string
+	if rf, ok := ret.Get(0).(func(string) map[string]string); ok {
+		r0 = rf(revision)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(map[string]string)
+		}
+	}
+
+	var r1 string
+	if rf, ok := ret.Get(1).(func(string) string); ok {
+		r1 = rf(revision)
+	} else {
+		r1 = ret.Get(1).(string)
+	}
+
+	var r2 error
+	if rf, ok := ret.Get(2).(func(string) error); ok {
+		r2 = rf(revision)
+	} else {
+		r2 = ret.Error(2)
+	}
+
+	return r0, r1, r2
+}
+
+// LockKey provides a mock function with given fields:
+func (_m *Repo) LockKey() 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
+}
+
+// ResolveRevision provides a mock function with given fields: app, revision
+func (_m *Repo) ResolveRevision(app string, revision string) (string, error) {
+	ret := _m.Called(app, revision)
+
+	var r0 string
+	if rf, ok := ret.Get(0).(func(string, string) string); ok {
+		r0 = rf(app, revision)
+	} else {
+		r0 = ret.Get(0).(string)
+	}
+
+	var r1 error
+	if rf, ok := ret.Get(1).(func(string, string) error); ok {
+		r1 = rf(app, revision)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// RevisionMetadata provides a mock function with given fields: app, resolvedRevision
+func (_m *Repo) RevisionMetadata(app string, resolvedRevision string) (*repo.RevisionMetadata, error) {
+	ret := _m.Called(app, resolvedRevision)
+
+	var r0 *repo.RevisionMetadata
+	if rf, ok := ret.Get(0).(func(string, string) *repo.RevisionMetadata); ok {
+		r0 = rf(app, resolvedRevision)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*repo.RevisionMetadata)
+		}
+	}
+
+	var r1 error
+	if rf, ok := ret.Get(1).(func(string, string) error); ok {
+		r1 = rf(app, resolvedRevision)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
diff --git a/util/repo/repo.go b/util/repo/repo.go
new file mode 100644
index 0000000000000..a3e9b86794c15
--- /dev/null
+++ b/util/repo/repo.go
@@ -0,0 +1,28 @@
+package repo
+
+import (
+	"time"
+)
+
+type RevisionMetadata struct {
+	Author  string
+	Date    time.Time
+	Tags    []string
+	Message string
+}
+
+// Repo is a generic repo client interface
+type Repo interface {
+	// return a key suitable for use for locking this object
+	LockKey() string
+	// init
+	Init() error
+	// list apps for an ambiguous revision,
+	ListApps(revision string) (apps map[string]string, resolvedRevision string, err error)
+	// convert an ambiguous revision (e.g. "", "master" or "HEAD") into a specific revision (e.g. "231345034boc" or "5.8.0")
+	ResolveRevision(app, revision string) (resolvedRevision string, err error)
+	// checkout an app
+	GetApp(app, resolvedRevision string) (path string, err error)
+	// return the revision meta-data for the checked out code
+	RevisionMetadata(app, resolvedRevision string) (*RevisionMetadata, error)
+}
diff --git a/util/repo/work_dir.go b/util/repo/work_dir.go
new file mode 100644
index 0000000000000..028fcb579aa9b
--- /dev/null
+++ b/util/repo/work_dir.go
@@ -0,0 +1,17 @@
+package repo
+
+import (
+	"os"
+	"path/filepath"
+	"strings"
+)
+
+// returns a formulated temporary directory location to clone a repository
+func WorkDir(url string) (string, error) {
+	path := filepath.Join(os.TempDir(), strings.Replace(url, "/", "_", -1))
+	err := os.Mkdir(path, 0700)
+	if err != nil && !os.IsExist(err) {
+		return "", err
+	}
+	return path, nil
+}
diff --git a/util/repo/work_dir_test.go b/util/repo/work_dir_test.go
new file mode 100644
index 0000000000000..b31e221e47aad
--- /dev/null
+++ b/util/repo/work_dir_test.go
@@ -0,0 +1,18 @@
+package repo
+
+import (
+	"os"
+	"testing"
+
+	"github.com/stretchr/testify/assert"
+)
+
+func TestWorkDir(t *testing.T) {
+	workDir, err := WorkDir("foo")
+	assert.NoError(t, err)
+	info, err := os.Stat(workDir)
+	assert.NoError(t, err)
+	assert.True(t, info.IsDir())
+	_, err = WorkDir("foo")
+	assert.NoError(t, err)
+}
diff --git a/util/settings/settings.go b/util/settings/settings.go
index 3ede499682bcc..499aa59abff66 100644
--- a/util/settings/settings.go
+++ b/util/settings/settings.go
@@ -98,32 +98,28 @@ type OIDCConfig struct {
 type RepoCredentials struct {
 	// The URL to the repository
 	URL string `json:"url,omitempty"`
+	// the type of the repo, "git" or "helm", assumed to be "git" if empty or absent
+	Type string `json:"type,omitempty"`
+	// helm only
+	Name string `json:"name,omitempty"`
 	// Name of the secret storing the username used to access the repo
 	UsernameSecret *apiv1.SecretKeySelector `json:"usernameSecret,omitempty"`
 	// Name of the secret storing the password used to access the repo
 	PasswordSecret *apiv1.SecretKeySelector `json:"passwordSecret,omitempty"`
-	// Name of the secret storing the SSH private key used to access the repo
+	// Name of the secret storing the SSH private key used to access the repo. Git only
 	SSHPrivateKeySecret *apiv1.SecretKeySelector `json:"sshPrivateKeySecret,omitempty"`
 	// Whether to connect the repository in an insecure way (deprecated)
 	InsecureIgnoreHostKey bool `json:"insecureIgnoreHostKey,omitempty"`
 	// Whether to connect the repository in an insecure way
 	Insecure bool `json:"insecure,omitempty"`
-	// Whether the repo is git-lfs enabled
+	// Whether the repo is git-lfs enabled. Git only.
 	EnableLFS bool `json:"enableLfs,omitempty"`
 	// Name of the secret storing the TLS client cert data
 	TLSClientCertDataSecret *apiv1.SecretKeySelector `json:"tlsClientCertDataSecret,omitempty"`
 	// Name of the secret storing the TLS client cert's key data
 	TLSClientCertKeySecret *apiv1.SecretKeySelector `json:"tlsClientCertKeySecret,omitempty"`
-}
-
-type HelmRepoCredentials struct {
-	URL            string                   `json:"url,omitempty"`
-	Name           string                   `json:"name,omitempty"`
-	UsernameSecret *apiv1.SecretKeySelector `json:"usernameSecret,omitempty"`
-	PasswordSecret *apiv1.SecretKeySelector `json:"passwordSecret,omitempty"`
-	CASecret       *apiv1.SecretKeySelector `json:"caSecret,omitempty"`
-	CertSecret     *apiv1.SecretKeySelector `json:"certSecret,omitempty"`
-	KeySecret      *apiv1.SecretKeySelector `json:"keySecret,omitempty"`
+	// The CA secret for TLS client cert. Helm only
+	TLSClientCASecret *apiv1.SecretKeySelector `json:"tlsClientCertCaSecret,omitempty"`
 }
 
 const (
@@ -151,8 +147,6 @@ const (
 	repositoriesKey = "repositories"
 	// repositoryCredentialsKey designates the key where ArgoCDs repositories credentials list is set
 	repositoryCredentialsKey = "repository.credentials"
-	// helmRepositoriesKey designates the key where list of helm repositories is set
-	helmRepositoriesKey = "helm.repositories"
 	// settingDexConfigKey designates the key for the dex config
 	settingDexConfigKey = "dex.config"
 	// settingsOIDCConfigKey designates the key for OIDC config
@@ -324,22 +318,6 @@ func (mgr *SettingsManager) GetKustomizeBuildOptions() (string, error) {
 	return argoCDCM.Data[kustomizeBuildOptions], nil
 }
 
-func (mgr *SettingsManager) GetHelmRepositories() ([]HelmRepoCredentials, error) {
-	argoCDCM, err := mgr.getConfigMap()
-	if err != nil {
-		return nil, err
-	}
-	helmRepositories := make([]HelmRepoCredentials, 0)
-	helmRepositoriesStr := argoCDCM.Data[helmRepositoriesKey]
-	if helmRepositoriesStr != "" {
-		err := yaml.Unmarshal([]byte(helmRepositoriesStr), &helmRepositories)
-		if err != nil {
-			return nil, err
-		}
-	}
-	return helmRepositories, nil
-}
-
 func (mgr *SettingsManager) GetRepositories() ([]RepoCredentials, error) {
 	argoCDCM, err := mgr.getConfigMap()
 	if err != nil {
diff --git a/util/settings/settings_test.go b/util/settings/settings_test.go
index 47acbd72008ef..e0180e3d79c74 100644
--- a/util/settings/settings_test.go
+++ b/util/settings/settings_test.go
@@ -135,16 +135,6 @@ func TestSettingsManager_GetKustomizeBuildOptions(t *testing.T) {
 	})
 }
 
-func TestGetHelmRepositories(t *testing.T) {
-	_, settingsManager := fixtures(map[string]string{
-		"helm.repositories": "\n  - url: http://foo\n",
-	})
-	helmRepositories, err := settingsManager.GetHelmRepositories()
-	assert.NoError(t, err)
-
-	assert.ElementsMatch(t, helmRepositories, []HelmRepoCredentials{{URL: "http://foo"}})
-}
-
 func TestGetGoogleAnalytics(t *testing.T) {
 	_, settingsManager := fixtures(map[string]string{
 		"ga.trackingid": "123",