From 1120239b699166130bc49952d3334c3d2272cb33 Mon Sep 17 00:00:00 2001 From: Wade Carpenter Date: Tue, 3 Oct 2023 17:17:49 -0700 Subject: [PATCH] Support file:// scheme for repo URLs In a repo.yaml file, instead of just the http:// or https:// scheme, the user might want to specify a local path for an repo, e.g. repositories: - arch: x86_64 baseurl: file:///RPMS name: local And then use that with fetch, e.g. % bazeldnf fetch INFO[0000] Resolving repomd.xml from file:///RPMS/repodata/repomd.xml INFO[0000] Loading primary file from file:///RPMS/repodata/-primary.xml.gz To address this, update the Getter implementation to parse the URL using net/url Parse, and the call a handler that opens a local file and returns a wrapper http.Response when the scheme is "file". --- pkg/repo/fetch.go | 28 +++++++++++++++++++++++++--- 1 file changed, 25 insertions(+), 3 deletions(-) diff --git a/pkg/repo/fetch.go b/pkg/repo/fetch.go index f78b5a2..15bac70 100644 --- a/pkg/repo/fetch.go +++ b/pkg/repo/fetch.go @@ -8,6 +8,7 @@ import ( "io" "net/http" "net/url" + "os" "path" "path/filepath" "strings" @@ -186,7 +187,7 @@ func (r *RepoFetcherImpl) fetchFile(fileType string, repo *bazeldnf.Repository, log.Infof("Loading %s file from %s", fileType, fileURL) resp, err := r.Getter.Get(fileURL) if err != nil { - return fmt.Errorf("Failed to load promary repository file from %s: %v", fileURL, err) + return fmt.Errorf("Failed to load primary repository file from %s: %v", fileURL, err) } sha := sha256.New() defer resp.Body.Close() @@ -214,8 +215,29 @@ type Getter interface { type getterImpl struct{} -func (*getterImpl) Get(url string) (resp *http.Response, err error) { - return http.Get(url) +func fileGet(filename string) (*http.Response, error) { + fp, err := os.Open(filename) + if err != nil { + return nil, err // skipped wrapping the error since the error already begins with "open: " + } + + resp := &http.Response{ + Status: "OK", + StatusCode: http.StatusOK, + Body: fp, + } + return resp, nil +} + +func (*getterImpl) Get(rawURL string) (*http.Response, error) { + u, err := url.Parse(rawURL) + if err != nil { + return nil, fmt.Errorf("Failed to parse URL: %w", err) + } + if u.Scheme == "file" { + return fileGet(u.Path) + } + return http.Get(rawURL) } func toHex(hasher hash.Hash) string {