从本地裸 git 仓库获取 ‘go get’ 项目。

huangapple go评论87阅读模式
英文:

Fetch 'go get' project from local bare git repo

问题

我正在尝试将远程存储库模拟为本地git存储库,我知道go mod edit -replace等命令,但是对于我的用例,我需要使用Go命令从本地git存储库获取依赖项。

为了用最小的可重现示例模拟它,我创建了一个裸的git存储库:

# 在 /tmp/git/repo1 目录下
git init --bare

然后克隆该存储库,创建go项目,并将其推送回去:

# 在 /tmp/projects/ 目录下
git clone file:///tmp/git/repo1
cd repo1
go mod init git.localhost/repo1
git add go.mod && git commit -m "init: go mod init localhost" && git push origin

为了确保裸存储库已成功更新:

# 在 /tmp/git/repo1 目录下
git cat-file -p $(cat refs/heads/master) | grep init
# init: go mod init localhost

然后我创建了一个名为"client"的go项目,更新了git配置,并尝试使用go get获取它:

# 在 /tmp/go-proj 目录下
go mod init example.com
git config --global url."file:///tmp/git/".insteadOf "https://git.localhost/"
go get git.localhost/repo1

但是出现了以下错误:

go: unrecognized import path "git.localhost/repo1": https fetch: Get "https://git.localhost/repo1?go-get=1": dial tcp: lookup git.localhost on 127.0.0.1:53: no such host

我还尝试更新GOPRIVATE环境变量,并为file协议设置git配置allow=always:

export GOPRIVATE="git.localhost/*"
git config --global protocol.file.allow always

并通过以下方式检查git是否可以克隆该存储库:

git clone https://git.localhost/repo1
# 成功从裸存储库克隆

是否可能使用go get从本地git裸存储库获取依赖项?


更新:
添加了GOPROXY环境变量,所以现在我的go env输出为:

GOPRIVATE="git.localhost/*"
GOPROXY="direct"

并且git config --global输出为:

url.file:///tmp/git/.insteadof=https://git.localhost/
protocol.file.allow=always

更新2:

go get命令的详细输出:

GOFLAGS="-v -x" go get git.localhost/repo1
# get https://git.localhost/?go-get=1
# get https://git.localhost/repo1?go-get=1
# get https://git.localhost/?go-get=1: Get "https://git.localhost/?go-get=1": dial tcp: lookup git.localhost on 127.0.0.1:53: no such host
# get https://git.localhost/repo1?go-get=1: Get "https://git.localhost/repo1?go-get=1": dial tcp: lookup git.localhost on 127.0.0.1:53: no such host
go: unrecognized import path "git.localhost/repo1": https fetch: Get "https://git.localhost/repo1?go-get=1": dial tcp: lookup git.localhost on 127.0.0.1:53: no such host
英文:

I'm trying to simulate remote repository for Go dependency as local git repo. I'm aware of go mod edit -replace etc., but for my use case I need Go command to fetch dependency from git repo locally.

To simulate it with minimal reproducible example, I created bare git repo:

# in /tmp/git/repo1
git init --bare

Then cloned the repo, created go project, and pushed it back:

# in /tmp/projects/
git clone file:///tmp/git/repo1
cd repo1
go mod init git.localhost/repo1
git add go.mod && git commit -m "init: go mod init localhost" && git push origin

Just in case, checked bare repo updated successfully:

# in /tmp/git/repo1
git cat-file -p $(cat refs/heads/master) | grep init
# init: go mod init localhost

Then I created "client" go project, updated git config and tried to fetch it using go get:

# in /tmp/go-proj
go mod init example.com
git config --global url."file:///tmp/git/".insteadOf "https://git.localhost/"
go get git.localhost/repo1

But got this error:

go: unrecognized import path "git.localhost/repo1": https fetch: Get "https://git.localhost/repo1?go-get=1": dial tcp: lookup git.localhost on 127.0.0.1:53: no such host

Also, I tried to update GOPRIVATE env and set git config allow=always for file protocol:

export GOPRIVATE="git.localhost/*"
git config --global protocol.file.allow always

And checked git can clone this repo by using:

git clone https://git.localhost/repo1
# successfully cloned from bare repo

Is it possible to get dependency from local git bare repo using go get?


Update:
Added GOPROXY env, so now my go env has:

GOPRIVATE="git.localhost/*"
GOPROXY="direct"

and git config --global has:

url.file:///tmp/git/.insteadof=https://git.localhost/
protocol.file.allow=always

Update2:

Verbose output for go get command:

GOFLAGS="-v -x" go get git.localhost/repo1
# get https://git.localhost/?go-get=1
# get https://git.localhost/repo1?go-get=1
# get https://git.localhost/?go-get=1: Get "https://git.localhost/?go-get=1": dial tcp: lookup git.localhost on 127.0.0.1:53: no such host
# get https://git.localhost/repo1?go-get=1: Get "https://git.localhost/repo1?go-get=1": dial tcp: lookup git.localhost on 127.0.0.1:53: no such host
go: unrecognized import path "git.localhost/repo1": https fetch: Get "https://git.localhost/repo1?go-get=1": dial tcp: lookup git.localhost on 127.0.0.1:53: no such host

答案1

得分: 1

以防万一这是问题,首先使用以下命令测试您的go get命令:

export GOPROXY=direct

这样应该允许go get从本地Git仓库获取依赖项而不会出现任何问题。
这应该是除了您的其他设置之外设置的,比如您的export GOPRIVATE="git.localhost/*"和Git的insteadOf指令。


OP在评论中补充道:

> 看起来go get正在尝试通过http从依赖主机(在我的情况下是git.localhost)获取一些元数据,然后在go/pkg/mod/cache/vcs/{hash}中创建git包仓库,然后使用git获取依赖代码,其中git应用了insteadOf替换。
>
> 所以我打算创建一个简单的http服务器,以对http://git.localhost/?go-get=1 URL响应带有VCS、前缀和RepoRoot URL响应的元信息。

这确实是在“如何使go get与本地服务器上的存储库一起工作”中所说明的。

英文:

Just in case this is the issue, test your go get command with first:

export GOPROXY=direct

That should allow go get to fetch the dependency from the local Git repository without any issues.
That should be set in addition to your other settings, like your export GOPRIVATE="git.localhost/*" and your Git insteadOf directive.


The OP adds in the comments:

> Looks like go get is trying to fetch some meta data via http from dependency host (git.localhost in my case), then create package git repo in go/pkg/mod/cache/vcs/{hash} and then fetch dependency code using git, where git applies isnteadOf replace.
>
> So I'm going to try create simple http server to respond with meta information with VCS, Prefix and RepoRoot url response to http://git.localhost/?go-get=1 URL

This is indeed what is illustrated in "How can I make go get work with a repo on a local server".

答案2

得分: 1

为了解决这个问题,我启动了一个基本的HTTP Web服务器,用于处理go get请求并返回带有<meta> go-import标签的HTML页面。它指定了git仓库的位置为https://git.localhost/<repo-name>,然后go get使用git来获取这个仓库,并且insteadOf git配置将https://git.localhost替换为file:///位置。此外,需要设置GOINSECURE="git.localhost/*环境变量以使用http请求go-get请求。

这是我的服务器处理程序(带有子模块和语义版本支持):

package main

import (
	"fmt"
	"log"
	"net/http"
	"regexp"
	"strings"
)

// 仓库名称:/repo /repo/module /repo/ /repo/submodule /repo/v2
var reRepo = regexp.MustCompile(`^/([a-zA-Z0-9_-]+)/?(?:.+)?$`)

func main() {
	http.ListenAndServe(":80", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		repoParts := reRepo.FindStringSubmatch(r.URL.Path)
		if len(repoParts) == 0 {
			http.NotFound(w, r)
			return
		}
		name := repoParts[1]
		log.Printf("解析 %s => %s", r.URL.Path, name)

		var sb strings.Builder
		sb.WriteString("<html><head>")
		sb.WriteString(fmt.Sprintf(`<meta name="go-import" content="git.localhost/%s git https://git.localhost/%s" />`, name, name))
		sb.WriteString("</head></html>")
		fmt.Fprint(w, sb.String())
	}))
}
英文:

To solve this problem, I started primitive HTTP web server to return HTML page for go get requests with &lt;meta&gt; go-import tag. It specifies the location of git repository as https://git.localhost/&lt;repo-name&gt; and then go get uses git to fetch this repo and insteadOf git config replaces https://git.localhost with file:/// location. Also, GOINSECURE=&quot;git.localhost/* environment is required to request go-get requests using http.

This is my server handler (with submodule and semver support):

package main

import (
	&quot;fmt&quot;
	&quot;log&quot;
	&quot;net/http&quot;
	&quot;regexp&quot;
	&quot;strings&quot;
)

// repo names: /repo /repo/module /repo/ /repo/submodule /repo/v2
var reRepo = regexp.MustCompile(`^/([a-zA-Z0-9_-]+)/?(?:.+)?$`)

func main() {
	http.ListenAndServe(&quot;:80&quot;, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		repoParts := reRepo.FindStringSubmatch(r.URL.Path)
		if len(repoParts) == 0 {
			http.NotFound(w, r)
			return
		}
		name := repoParts[1]
		log.Printf(&quot;Resolve %s =&gt; %s&quot;, r.URL.Path, name)

		var sb strings.Builder
		sb.WriteString(&quot;&lt;html&gt;&lt;head&gt;&quot;)
		sb.WriteString(fmt.Sprintf(`&lt;meta name=&quot;go-import&quot; content=&quot;git.localhost/%s git https://git.localhost/%s&quot; /&gt;`, name, name))
		sb.WriteString(&quot;&lt;/head&gt;&lt;/html&gt;&quot;)
		fmt.Fprint(w, sb.String())
	}))
}

huangapple
  • 本文由 发表于 2023年4月22日 04:12:48
  • 转载请务必保留本文链接:https://go.coder-hub.com/76076452.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定