修正bug

This commit is contained in:
刘铭 2023-05-17 13:01:01 +08:00
parent 5c008ae23e
commit e5df80f374
9 changed files with 219 additions and 186 deletions

2
.gitignore vendored
View File

@ -1 +1 @@
bin tmp_hyperledger/

12
404.html Normal file
View File

@ -0,0 +1,12 @@
<html>
<head>
<title>404</title>
</head>
<body>
<h1>404</h1>
<p>Page not found</p>
<P>你下载的链接不存在,可能是你拿到的链接是老版本的链接,请访问软件站点获得最新版本链接再下载
点击这里访问<a href="https://gitee.com/extrame/dget">软件站点</a>
</P>
</body>
</html>

View File

@ -42,8 +42,8 @@ dget -arch linux/arm influxdb:1.8.3
## 直接下载链接 ## 直接下载链接
[windows x64版本](https://dget.oss-cn-beijing.aliyuncs.com/dget_windows_amd64_v_1_0_1.zip) [windows x64版本](./bin/windows_amd64/dget.exe)
[linux amd64版本](https://dget.oss-cn-beijing.aliyuncs.com/dget_linux_amd64_v_1_0_1.zip) [linux amd64版本](./bin/linux_amd64/dget)
[linux arm版本](https://dget.oss-cn-beijing.aliyuncs.com/dget_linux_arm_v_1_0_1.zip) [linux arm版本](./bin/linux_arm/dget)
[Mac 传统版本](https://dget.oss-cn-beijing.aliyuncs.com/dget_darwin_amd64_v1_0_1.zip) [Mac 传统版本](https://dget.oss-cn-beijing.aliyuncs.com/dget_darwin_amd64_v1_0_1.zip)
[Mac arm64版本](https://dget.oss-cn-beijing.aliyuncs.com/dget_darwin_arm64_v1_0_1.zip) [Mac arm64版本](https://dget.oss-cn-beijing.aliyuncs.com/dget_darwin_arm64_v1_0_1.zip)

BIN
bin/linux_amd64/dget Normal file

Binary file not shown.

BIN
bin/linux_arm/dget Normal file

Binary file not shown.

BIN
bin/windows_amd64/dget.exe Normal file

Binary file not shown.

1
go.mod
View File

@ -5,6 +5,7 @@ go 1.15
require ( require (
github.com/boltdb/bolt v1.3.1 github.com/boltdb/bolt v1.3.1
github.com/docker/distribution v2.8.1+incompatible // indirect github.com/docker/distribution v2.8.1+incompatible // indirect
github.com/docker/libtrust v0.0.0-20160708172513-aabc10ec26b7 // indirect
github.com/opencontainers/go-digest v1.0.0 // indirect github.com/opencontainers/go-digest v1.0.0 // indirect
github.com/opencontainers/image-spec v1.0.2 // indirect github.com/opencontainers/image-spec v1.0.2 // indirect
github.com/sirupsen/logrus v1.8.1 github.com/sirupsen/logrus v1.8.1

2
go.sum
View File

@ -3,6 +3,8 @@ github.com/boltdb/bolt v1.3.1/go.mod h1:clJnj/oiGkjum5o1McbSZDSLxVThjynRyGBgiAx2
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/docker/distribution v2.8.1+incompatible h1:Q50tZOPR6T/hjNsyc9g8/syEs6bk8XXApsHjKukMl68= github.com/docker/distribution v2.8.1+incompatible h1:Q50tZOPR6T/hjNsyc9g8/syEs6bk8XXApsHjKukMl68=
github.com/docker/distribution v2.8.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= github.com/docker/distribution v2.8.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
github.com/docker/libtrust v0.0.0-20160708172513-aabc10ec26b7 h1:UhxFibDNY/bfvqU5CAUmr9zpesgbU6SWc8/B4mflAE4=
github.com/docker/libtrust v0.0.0-20160708172513-aabc10ec26b7/go.mod h1:cyGadeNEkKy96OOhEzfZl+yxihPEzKnqJwvfuSUqbZE=
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
github.com/opencontainers/image-spec v1.0.2 h1:9yCKha/T5XdGtO0q9Q9a6T5NUCsTn/DrBg0D7ufOcFM= github.com/opencontainers/image-spec v1.0.2 h1:9yCKha/T5XdGtO0q9Q9a6T5NUCsTn/DrBg0D7ufOcFM=

View File

@ -129,40 +129,48 @@ func Install(_registry, d, tag string, arch string, printInfo bool) (err error)
os.Exit(1) os.Exit(1)
} else { } else {
var info manifestlist.ManifestList
var bts []byte var bts []byte
bts, err = io.ReadAll(resp.Body) bts, err = io.ReadAll(resp.Body)
if err == nil { if err == nil {
switch resp.Header.Get("Content-Type") {
case "application/vnd.docker.distribution.manifest.list.v2+json":
var info manifestlist.ManifestList
err = json.Unmarshal(bts, &info)
err = json.Unmarshal(bts, &info) if err == nil {
resp.Body.Close()
logrus.Infof("获得%d个架构信息:", len(info.Manifests))
var selectedManifest *manifestlist.ManifestDescriptor
for i := 0; i < len(info.Manifests); i++ {
var m = info.Manifests[i]
logrus.Infof("[%d]架构:%s,OS:%s", i+1, m.Platform.Architecture, m.Platform.OS)
if m.Platform.OS+"/"+m.Platform.Architecture == arch {
logrus.Infoln("找到匹配的架构,开始下载")
selectedManifest = &m
}
}
if printInfo {
fmt.Println(string(bts))
os.Exit(0)
}
if selectedManifest == nil {
return errors.New("未找到匹配的架构:" + arch)
}
req.Header.Set("Accept", selectedManifest.MediaType)
}
case "application/vnd.docker.distribution.manifest.v1+prettyjws":
req.Header.Set("Accept", "application/vnd.docker.distribution.manifest.v2+json")
}
resp, err = http.DefaultClient.Do(req)
if err == nil { if err == nil {
resp.Body.Close()
logrus.Infof("获得%d个架构信息:", len(info.Manifests))
var selectedManifest *manifestlist.ManifestDescriptor
for i := 0; i < len(info.Manifests); i++ {
var m = info.Manifests[i]
logrus.Infof("[%d]架构:%s,OS:%s", i+1, m.Platform.Architecture, m.Platform.OS)
if m.Platform.OS+"/"+m.Platform.Architecture == arch {
logrus.Infoln("找到匹配的架构,开始下载")
selectedManifest = &m
}
}
if printInfo {
fmt.Println(string(bts))
os.Exit(0)
}
if selectedManifest == nil {
return errors.New("未找到匹配的架构:" + arch)
}
req.Header.Set("Accept", selectedManifest.MediaType)
resp, err = http.DefaultClient.Do(req)
var info Info var info Info
err = json.NewDecoder(resp.Body).Decode(&info) err = json.NewDecoder(resp.Body).Decode(&info)
@ -170,162 +178,9 @@ func Install(_registry, d, tag string, arch string, printInfo bool) (err error)
resp.Body.Close() resp.Body.Close()
logrus.Infof("获得Manifest信息共%d层需要下载", len(info.Layers)) logrus.Infof("获得Manifest信息共%d层需要下载", len(info.Layers))
var tmpDir = fmt.Sprintf("tmp_%s_%s", d, tag) err = download(_registry, d, tag, info.Config.Digest, authHeader, info.Layers)
err = os.MkdirAll(tmpDir, 0777) if err != nil {
if err == nil { goto response
if _, e := os.Stat(filepath.Join(tmpDir, "repositories")); e == nil {
logrus.Info(tmpDir, "is downloaded,use dir as cache")
} else {
req, err = http.NewRequest("GET", fmt.Sprintf("https://%s/v2/%s/blobs/%s", _registry, d, info.Config.Digest), nil)
if err == nil {
req.Header = authHeader
resp, err = http.DefaultClient.Do(req)
if err == nil {
var dest *os.File
dest, err = os.OpenFile(filepath.Join(tmpDir, info.Config.Digest.Encoded()+".json"), os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0666)
if err == nil {
var bts []byte
bts, err = ioutil.ReadAll(resp.Body)
var lastLayerInfo LayerInfo
err = json.Unmarshal(bts, &lastLayerInfo)
resp.Body.Close()
var config []PackageConfig
config = append(config, PackageConfig{
Config: info.Config.Digest.Encoded() + ".json",
RepoTags: []string{d + ":" + tag},
})
if err == nil {
_, err = io.Copy(dest, bytes.NewReader(bts))
dest.Close()
if err == nil {
parentid := ""
var fakeLayerId string
for n, layer := range info.Layers {
namer := sha256.New()
namer.Write([]byte(parentid + "\n" + layer.Digest + "\n"))
fakeLayerId = hex.EncodeToString(namer.Sum(nil))
logrus.Infoln("handle layer", n, fakeLayerId, layer.Urls)
layerDirName := filepath.Join(tmpDir, fakeLayerId)
err = os.Mkdir(layerDirName, 0777)
if _, er := os.Stat(filepath.Join(layerDirName, "layer.tar")); er == nil {
logrus.Infoln("layer", fakeLayerId, "is existed, continue")
config[0].Layers = append(config[0].Layers, fakeLayerId+"/layer.tar")
parentid = fakeLayerId
continue
}
if err == nil || os.IsExist(err) {
err = ioutil.WriteFile(filepath.Join(layerDirName, "VERSION"), []byte("1.0"), 0666)
if err == nil {
req, err = http.NewRequest("GET", fmt.Sprintf("https://%s/v2/%s/blobs/%s", _registry, d, layer.Digest), nil)
if err == nil {
req.Header = authHeader
req.Header.Set("Accept", "application/vnd.docker.distribution.manifest.v2+json")
resp, err = http.DefaultClient.Do(req)
if err == nil {
if resp.StatusCode != 200 {
defer resp.Body.Close()
if len(layer.Urls) > 0 {
req, err = http.NewRequest("GET", layer.Urls[0], nil)
if err == nil {
req.Header = authHeader
req.Header.Set("Accept", "application/vnd.docker.distribution.manifest.v2+json")
resp, err = http.DefaultClient.Do(req)
if err == nil {
if resp.StatusCode != 200 {
err = fmt.Errorf("download from customized url fail for layer[%d]", n)
goto response
}
}
}
} else {
bts, _ := ioutil.ReadAll(resp.Body)
logrus.Fatalln("下载失败", string(bts))
}
}
}
if err != nil {
logrus.Errorf("请求第%d/%d层失败:%v", n+1, len(info.Layers), err)
} else {
logrus.Infof("请求第%d/%d层成功", n+1, len(info.Layers))
}
var dst *os.File
dst, err = os.OpenFile(filepath.Join(layerDirName, "layer.tar.part"), os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0666)
if err == nil {
var greader *gzip.Reader
greader, err = gzip.NewReader(resp.Body)
if err == nil {
_, err = io.Copy(dst, greader)
if err == nil {
dst.Close()
var layerInfo LayerInfo
if n == len(info.Layers)-1 {
layerInfo = lastLayerInfo
}
layerInfo.Id = fakeLayerId
if parentid != "" {
layerInfo.Parent = parentid
}
parentid = fakeLayerId
var jsonFile *os.File
jsonFile, err = os.OpenFile(filepath.Join(layerDirName, "json"), os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0666)
if err == nil {
err = json.NewEncoder(jsonFile).Encode(&layerInfo)
if err == nil {
jsonFile.Close()
err = os.Rename(filepath.Join(layerDirName, "layer.tar.part"), filepath.Join(layerDirName, "layer.tar"))
}
}
}
}
}
if err != nil {
logrus.Errorf("保存第%d/%d层失败,%v", n+1, len(info.Layers), err)
} else {
logrus.Infof("保存第%d/%d层成功", n+1, len(info.Layers))
}
if err != nil {
goto response
} else {
config[0].Layers = append(config[0].Layers, fakeLayerId+"/layer.tar")
}
}
}
}
}
var manifest *os.File
manifest, err = os.OpenFile(filepath.Join(tmpDir, "manifest.json"), os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0666)
if err == nil {
err = json.NewEncoder(manifest).Encode(&config)
if err == nil {
manifest.Close()
var repositories = make(map[string]interface{})
repositories[d] = map[string]string{
tag: fakeLayerId,
}
var rFile *os.File
rFile, err = os.OpenFile(filepath.Join(tmpDir, "repositories"), os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0666)
if err == nil {
err = json.NewEncoder(rFile).Encode(&repositories)
goto maketar
}
}
}
}
}
}
}
}
}
maketar:
if err == nil {
err = writeDirToTarGz(tmpDir, tmpDir+"-img.tar.gz")
if err == nil {
fmt.Println("write tar success", tmpDir+"-img.tar.gz")
}
}
} }
} }
} }
@ -338,6 +193,169 @@ response:
return return
} }
func download(_registry, d, tag string, digest digest.Digest, authHeader http.Header, layers []Layer) (err error) {
var tmpDir = fmt.Sprintf("tmp_%s_%s", d, tag)
err = os.MkdirAll(tmpDir, 0777)
if err == nil {
if _, e := os.Stat(filepath.Join(tmpDir, "repositories")); e == nil {
logrus.Info(tmpDir, "is downloaded,use dir as cache")
} else {
var req *http.Request
req, err = http.NewRequest("GET", fmt.Sprintf("https://%s/v2/%s/blobs/%s", _registry, d, digest), nil)
if err == nil {
req.Header = authHeader
var resp *http.Response
resp, err = http.DefaultClient.Do(req)
if err == nil {
var dest *os.File
dest, err = os.OpenFile(filepath.Join(tmpDir, digest.Encoded()+".json"), os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0666)
if err == nil {
var bts []byte
bts, err = ioutil.ReadAll(resp.Body)
var lastLayerInfo LayerInfo
err = json.Unmarshal(bts, &lastLayerInfo)
resp.Body.Close()
var config []PackageConfig
config = append(config, PackageConfig{
Config: digest.Encoded() + ".json",
RepoTags: []string{d + ":" + tag},
})
if err == nil {
_, err = io.Copy(dest, bytes.NewReader(bts))
dest.Close()
if err == nil {
parentid := ""
var fakeLayerId string
for n, layer := range layers {
namer := sha256.New()
namer.Write([]byte(parentid + "\n" + layer.Digest + "\n"))
fakeLayerId = hex.EncodeToString(namer.Sum(nil))
logrus.Infoln("handle layer", n, fakeLayerId, layer.Urls)
layerDirName := filepath.Join(tmpDir, fakeLayerId)
err = os.Mkdir(layerDirName, 0777)
if _, er := os.Stat(filepath.Join(layerDirName, "layer.tar")); er == nil {
logrus.Infoln("layer", fakeLayerId, "is existed, continue")
config[0].Layers = append(config[0].Layers, fakeLayerId+"/layer.tar")
parentid = fakeLayerId
continue
}
if err == nil || os.IsExist(err) {
err = ioutil.WriteFile(filepath.Join(layerDirName, "VERSION"), []byte("1.0"), 0666)
if err == nil {
req, err = http.NewRequest("GET", fmt.Sprintf("https://%s/v2/%s/blobs/%s", _registry, d, layer.Digest), nil)
if err == nil {
req.Header = authHeader
req.Header.Set("Accept", "application/vnd.docker.distribution.manifest.v2+json")
resp, err = http.DefaultClient.Do(req)
if err == nil {
if resp.StatusCode != 200 {
defer resp.Body.Close()
if len(layer.Urls) > 0 {
req, err = http.NewRequest("GET", layer.Urls[0], nil)
if err == nil {
req.Header = authHeader
req.Header.Set("Accept", "application/vnd.docker.distribution.manifest.v2+json")
resp, err = http.DefaultClient.Do(req)
if err == nil {
if resp.StatusCode != 200 {
err = fmt.Errorf("download from customized url fail for layer[%d]", n)
return err
}
}
}
} else {
bts, _ := ioutil.ReadAll(resp.Body)
logrus.Fatalln("下载失败", string(bts))
}
}
}
if err != nil {
logrus.Errorf("请求第%d/%d层失败:%v", n+1, len(layers), err)
} else {
logrus.Infof("请求第%d/%d层成功", n+1, len(layers))
}
var dst *os.File
dst, err = os.OpenFile(filepath.Join(layerDirName, "layer.tar.part"), os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0666)
if err == nil {
var greader *gzip.Reader
greader, err = gzip.NewReader(resp.Body)
if err == nil {
_, err = io.Copy(dst, greader)
if err == nil {
dst.Close()
var layerInfo LayerInfo
if n == len(layers)-1 {
layerInfo = lastLayerInfo
}
layerInfo.Id = fakeLayerId
if parentid != "" {
layerInfo.Parent = parentid
}
parentid = fakeLayerId
var jsonFile *os.File
jsonFile, err = os.OpenFile(filepath.Join(layerDirName, "json"), os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0666)
if err == nil {
err = json.NewEncoder(jsonFile).Encode(&layerInfo)
if err == nil {
jsonFile.Close()
err = os.Rename(filepath.Join(layerDirName, "layer.tar.part"), filepath.Join(layerDirName, "layer.tar"))
}
}
}
}
}
if err != nil {
logrus.Errorf("保存第%d/%d层失败,%v", n+1, len(layers), err)
} else {
logrus.Infof("保存第%d/%d层成功", n+1, len(layers))
}
if err != nil {
return err
} else {
config[0].Layers = append(config[0].Layers, fakeLayerId+"/layer.tar")
}
}
}
}
}
var manifest *os.File
manifest, err = os.OpenFile(filepath.Join(tmpDir, "manifest.json"), os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0666)
if err == nil {
err = json.NewEncoder(manifest).Encode(&config)
if err == nil {
manifest.Close()
var repositories = make(map[string]interface{})
repositories[d] = map[string]string{
tag: fakeLayerId,
}
var rFile *os.File
rFile, err = os.OpenFile(filepath.Join(tmpDir, "repositories"), os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0666)
if err == nil {
err = json.NewEncoder(rFile).Encode(&repositories)
goto maketar
}
}
}
}
}
}
}
}
}
maketar:
if err == nil {
err = writeDirToTarGz(tmpDir, tmpDir+"-img.tar.gz")
if err == nil {
fmt.Println("write tar success", tmpDir+"-img.tar.gz")
}
}
}
return
}
func getAuthHead(a, r, d string) (string, error) { func getAuthHead(a, r, d string) (string, error) {
resp, err := http.Get(fmt.Sprintf("%s?service=%s&scope=repository:%s:pull", a, r, d)) resp, err := http.Get(fmt.Sprintf("%s?service=%s&scope=repository:%s:pull", a, r, d))
if err == nil { if err == nil {