Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
OpenDAS
ollama
Commits
968ced2e
Unverified
Commit
968ced2e
authored
Aug 22, 2023
by
Michael Yang
Committed by
GitHub
Aug 22, 2023
Browse files
Merge pull request #393 from jmorganca/mxyng/net-url
use url.URL
parents
8f827641
2cc63468
Changes
4
Show whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
80 additions
and
55 deletions
+80
-55
server/auth.go
server/auth.go
+25
-18
server/download.go
server/download.go
+3
-2
server/images.go
server/images.go
+39
-30
server/modelpath.go
server/modelpath.go
+13
-5
No files found.
server/auth.go
View file @
968ced2e
...
@@ -12,8 +12,10 @@ import (
...
@@ -12,8 +12,10 @@ import (
"io"
"io"
"log"
"log"
"net/http"
"net/http"
"net/url"
"os"
"os"
"path"
"path"
"strconv"
"strings"
"strings"
"time"
"time"
...
@@ -43,21 +45,34 @@ func generateNonce(length int) (string, error) {
...
@@ -43,21 +45,34 @@ func generateNonce(length int) (string, error) {
return
base64
.
RawURLEncoding
.
EncodeToString
(
nonce
),
nil
return
base64
.
RawURLEncoding
.
EncodeToString
(
nonce
),
nil
}
}
func
(
r
AuthRedirect
)
URL
()
(
string
,
error
)
{
func
(
r
AuthRedirect
)
URL
()
(
*
url
.
URL
,
error
)
{
nonce
,
err
:=
generateNonce
(
16
)
redirectURL
,
err
:=
url
.
Parse
(
r
.
Realm
)
if
err
!=
nil
{
if
err
!=
nil
{
return
""
,
err
return
nil
,
err
}
}
scopes
:=
[]
string
{}
values
:=
redirectURL
.
Query
()
values
.
Add
(
"service"
,
r
.
Service
)
for
_
,
s
:=
range
strings
.
Split
(
r
.
Scope
,
" "
)
{
for
_
,
s
:=
range
strings
.
Split
(
r
.
Scope
,
" "
)
{
scopes
=
append
(
scopes
,
fmt
.
Sprintf
(
"scope=%s"
,
s
))
values
.
Add
(
"scope"
,
s
)
}
values
.
Add
(
"ts"
,
strconv
.
FormatInt
(
time
.
Now
()
.
Unix
(),
10
))
nonce
,
err
:=
generateNonce
(
16
)
if
err
!=
nil
{
return
nil
,
err
}
}
scopeStr
:=
strings
.
Join
(
scopes
,
"&"
)
values
.
Add
(
"nonce"
,
nonce
)
return
fmt
.
Sprintf
(
"%s?service=%s&%s&ts=%d&nonce=%s"
,
r
.
Realm
,
r
.
Service
,
scopeStr
,
time
.
Now
()
.
Unix
(),
nonce
),
nil
redirectURL
.
RawQuery
=
values
.
Encode
()
return
redirectURL
,
nil
}
}
func
getAuthToken
(
ctx
context
.
Context
,
redirData
AuthRedirect
,
regOpts
*
RegistryOptions
)
(
string
,
error
)
{
func
getAuthToken
(
ctx
context
.
Context
,
redirData
AuthRedirect
,
regOpts
*
RegistryOptions
)
(
string
,
error
)
{
url
,
err
:=
redirData
.
URL
()
redirectURL
,
err
:=
redirData
.
URL
()
if
err
!=
nil
{
if
err
!=
nil
{
return
""
,
err
return
""
,
err
}
}
...
@@ -77,18 +92,10 @@ func getAuthToken(ctx context.Context, redirData AuthRedirect, regOpts *Registry
...
@@ -77,18 +92,10 @@ func getAuthToken(ctx context.Context, redirData AuthRedirect, regOpts *Registry
s
:=
SignatureData
{
s
:=
SignatureData
{
Method
:
"GET"
,
Method
:
"GET"
,
Path
:
url
,
Path
:
redirectURL
.
String
()
,
Data
:
nil
,
Data
:
nil
,
}
}
if
!
strings
.
HasPrefix
(
s
.
Path
,
"http"
)
{
if
regOpts
.
Insecure
{
s
.
Path
=
"http://"
+
url
}
else
{
s
.
Path
=
"https://"
+
url
}
}
sig
,
err
:=
s
.
Sign
(
rawKey
)
sig
,
err
:=
s
.
Sign
(
rawKey
)
if
err
!=
nil
{
if
err
!=
nil
{
return
""
,
err
return
""
,
err
...
@@ -96,7 +103,7 @@ func getAuthToken(ctx context.Context, redirData AuthRedirect, regOpts *Registry
...
@@ -96,7 +103,7 @@ func getAuthToken(ctx context.Context, redirData AuthRedirect, regOpts *Registry
headers
:=
make
(
http
.
Header
)
headers
:=
make
(
http
.
Header
)
headers
.
Set
(
"Authorization"
,
sig
)
headers
.
Set
(
"Authorization"
,
sig
)
resp
,
err
:=
makeRequest
(
ctx
,
"GET"
,
url
,
headers
,
nil
,
regOpts
)
resp
,
err
:=
makeRequest
(
ctx
,
"GET"
,
redirectURL
,
headers
,
nil
,
regOpts
)
if
err
!=
nil
{
if
err
!=
nil
{
log
.
Printf
(
"couldn't get token: %q"
,
err
)
log
.
Printf
(
"couldn't get token: %q"
,
err
)
}
}
...
...
server/download.go
View file @
968ced2e
...
@@ -155,12 +155,13 @@ func doDownload(ctx context.Context, opts downloadOpts, f *FileDownload) error {
...
@@ -155,12 +155,13 @@ func doDownload(ctx context.Context, opts downloadOpts, f *FileDownload) error {
}
}
}
}
url
:=
fmt
.
Sprintf
(
"%s/v2/%s/blobs/%s"
,
opts
.
mp
.
Registry
,
opts
.
mp
.
GetNamespaceRepository
(),
f
.
Digest
)
requestURL
:=
opts
.
mp
.
BaseURL
()
requestURL
=
requestURL
.
JoinPath
(
"v2"
,
opts
.
mp
.
GetNamespaceRepository
(),
"blobs"
,
f
.
Digest
)
headers
:=
make
(
http
.
Header
)
headers
:=
make
(
http
.
Header
)
headers
.
Set
(
"Range"
,
fmt
.
Sprintf
(
"bytes=%d-"
,
size
))
headers
.
Set
(
"Range"
,
fmt
.
Sprintf
(
"bytes=%d-"
,
size
))
resp
,
err
:=
makeRequest
(
ctx
,
"GET"
,
url
,
headers
,
nil
,
opts
.
regOpts
)
resp
,
err
:=
makeRequest
(
ctx
,
"GET"
,
requestURL
,
headers
,
nil
,
opts
.
regOpts
)
if
err
!=
nil
{
if
err
!=
nil
{
log
.
Printf
(
"couldn't download blob: %v"
,
err
)
log
.
Printf
(
"couldn't download blob: %v"
,
err
)
return
fmt
.
Errorf
(
"%w: %w"
,
errDownload
,
err
)
return
fmt
.
Errorf
(
"%w: %w"
,
errDownload
,
err
)
...
...
server/images.go
View file @
968ced2e
...
@@ -12,6 +12,7 @@ import (
...
@@ -12,6 +12,7 @@ import (
"io"
"io"
"log"
"log"
"net/http"
"net/http"
"net/url"
"os"
"os"
"path"
"path"
"path/filepath"
"path/filepath"
...
@@ -961,8 +962,8 @@ func PushModel(ctx context.Context, name string, regOpts *RegistryOptions, fn fu
...
@@ -961,8 +962,8 @@ func PushModel(ctx context.Context, name string, regOpts *RegistryOptions, fn fu
return
err
return
err
}
}
if
strings
.
HasPrefix
(
path
.
Base
(
location
),
"sha256:"
)
{
if
strings
.
HasPrefix
(
path
.
Base
(
location
.
Path
),
"sha256:"
)
{
layer
.
Digest
=
path
.
Base
(
location
)
layer
.
Digest
=
path
.
Base
(
location
.
Path
)
fn
(
api
.
ProgressResponse
{
fn
(
api
.
ProgressResponse
{
Status
:
"using existing layer"
,
Status
:
"using existing layer"
,
Digest
:
layer
.
Digest
,
Digest
:
layer
.
Digest
,
...
@@ -979,7 +980,8 @@ func PushModel(ctx context.Context, name string, regOpts *RegistryOptions, fn fu
...
@@ -979,7 +980,8 @@ func PushModel(ctx context.Context, name string, regOpts *RegistryOptions, fn fu
}
}
fn
(
api
.
ProgressResponse
{
Status
:
"pushing manifest"
})
fn
(
api
.
ProgressResponse
{
Status
:
"pushing manifest"
})
url
:=
fmt
.
Sprintf
(
"%s/v2/%s/manifests/%s"
,
mp
.
Registry
,
mp
.
GetNamespaceRepository
(),
mp
.
Tag
)
requestURL
:=
mp
.
BaseURL
()
requestURL
=
requestURL
.
JoinPath
(
"v2"
,
mp
.
GetNamespaceRepository
(),
"manifests"
,
mp
.
Tag
)
manifestJSON
,
err
:=
json
.
Marshal
(
manifest
)
manifestJSON
,
err
:=
json
.
Marshal
(
manifest
)
if
err
!=
nil
{
if
err
!=
nil
{
...
@@ -988,7 +990,7 @@ func PushModel(ctx context.Context, name string, regOpts *RegistryOptions, fn fu
...
@@ -988,7 +990,7 @@ func PushModel(ctx context.Context, name string, regOpts *RegistryOptions, fn fu
headers
:=
make
(
http
.
Header
)
headers
:=
make
(
http
.
Header
)
headers
.
Set
(
"Content-Type"
,
"application/vnd.docker.distribution.manifest.v2+json"
)
headers
.
Set
(
"Content-Type"
,
"application/vnd.docker.distribution.manifest.v2+json"
)
resp
,
err
:=
makeRequestWithRetry
(
ctx
,
"PUT"
,
url
,
headers
,
bytes
.
NewReader
(
manifestJSON
),
regOpts
)
resp
,
err
:=
makeRequestWithRetry
(
ctx
,
"PUT"
,
requestURL
,
headers
,
bytes
.
NewReader
(
manifestJSON
),
regOpts
)
if
err
!=
nil
{
if
err
!=
nil
{
return
err
return
err
}
}
...
@@ -1072,11 +1074,11 @@ func PullModel(ctx context.Context, name string, regOpts *RegistryOptions, fn fu
...
@@ -1072,11 +1074,11 @@ func PullModel(ctx context.Context, name string, regOpts *RegistryOptions, fn fu
}
}
func
pullModelManifest
(
ctx
context
.
Context
,
mp
ModelPath
,
regOpts
*
RegistryOptions
)
(
*
ManifestV2
,
error
)
{
func
pullModelManifest
(
ctx
context
.
Context
,
mp
ModelPath
,
regOpts
*
RegistryOptions
)
(
*
ManifestV2
,
error
)
{
url
:=
fmt
.
Sprintf
(
"%s/v2/%s/manifests/%s"
,
mp
.
Registry
,
mp
.
GetNamespaceRepository
(),
mp
.
Tag
)
requestURL
:=
mp
.
BaseURL
()
.
JoinPath
(
"v2"
,
mp
.
GetNamespaceRepository
(),
"manifests"
,
mp
.
Tag
)
headers
:=
make
(
http
.
Header
)
headers
:=
make
(
http
.
Header
)
headers
.
Set
(
"Accept"
,
"application/vnd.docker.distribution.manifest.v2+json"
)
headers
.
Set
(
"Accept"
,
"application/vnd.docker.distribution.manifest.v2+json"
)
resp
,
err
:=
makeRequest
(
ctx
,
"GET"
,
url
,
headers
,
nil
,
regOpts
)
resp
,
err
:=
makeRequest
(
ctx
,
"GET"
,
requestURL
,
headers
,
nil
,
regOpts
)
if
err
!=
nil
{
if
err
!=
nil
{
log
.
Printf
(
"couldn't get manifest: %v"
,
err
)
log
.
Printf
(
"couldn't get manifest: %v"
,
err
)
return
nil
,
err
return
nil
,
err
...
@@ -1137,33 +1139,38 @@ func GetSHA256Digest(r io.Reader) (string, int) {
...
@@ -1137,33 +1139,38 @@ func GetSHA256Digest(r io.Reader) (string, int) {
type
requestContextKey
string
type
requestContextKey
string
func
startUpload
(
ctx
context
.
Context
,
mp
ModelPath
,
layer
*
Layer
,
regOpts
*
RegistryOptions
)
(
string
,
error
)
{
func
startUpload
(
ctx
context
.
Context
,
mp
ModelPath
,
layer
*
Layer
,
regOpts
*
RegistryOptions
)
(
*
url
.
URL
,
error
)
{
url
:=
fmt
.
Sprintf
(
"%s/v2/%s/blobs/uploads/"
,
mp
.
Registry
,
mp
.
GetNamespaceRepository
())
requestURL
:=
mp
.
BaseURL
()
requestURL
=
requestURL
.
JoinPath
(
"v2"
,
mp
.
GetNamespaceRepository
(),
"blobs/uploads/"
)
if
layer
.
From
!=
""
{
if
layer
.
From
!=
""
{
url
=
fmt
.
Sprintf
(
"%s/v2/%s/blobs/uploads/?mount=%s&from=%s"
,
mp
.
Registry
,
mp
.
GetNamespaceRepository
(),
layer
.
Digest
,
layer
.
From
)
values
:=
requestURL
.
Query
()
values
.
Add
(
"mount"
,
layer
.
Digest
)
values
.
Add
(
"from"
,
layer
.
From
)
requestURL
.
RawQuery
=
values
.
Encode
()
}
}
resp
,
err
:=
makeRequestWithRetry
(
ctx
,
"POST"
,
url
,
nil
,
nil
,
regOpts
)
resp
,
err
:=
makeRequestWithRetry
(
ctx
,
"POST"
,
requestURL
,
nil
,
nil
,
regOpts
)
if
err
!=
nil
{
if
err
!=
nil
{
log
.
Printf
(
"couldn't start upload: %v"
,
err
)
log
.
Printf
(
"couldn't start upload: %v"
,
err
)
return
""
,
err
return
nil
,
err
}
}
defer
resp
.
Body
.
Close
()
defer
resp
.
Body
.
Close
()
// Extract UUID location from header
// Extract UUID location from header
location
:=
resp
.
Header
.
Get
(
"Location"
)
location
:=
resp
.
Header
.
Get
(
"Location"
)
if
location
==
""
{
if
location
==
""
{
return
""
,
fmt
.
Errorf
(
"location header is missing in response"
)
return
nil
,
fmt
.
Errorf
(
"location header is missing in response"
)
}
}
return
location
,
nil
return
url
.
Parse
(
location
)
}
}
// Function to check if a blob already exists in the Docker registry
// Function to check if a blob already exists in the Docker registry
func
checkBlobExistence
(
ctx
context
.
Context
,
mp
ModelPath
,
digest
string
,
regOpts
*
RegistryOptions
)
(
bool
,
error
)
{
func
checkBlobExistence
(
ctx
context
.
Context
,
mp
ModelPath
,
digest
string
,
regOpts
*
RegistryOptions
)
(
bool
,
error
)
{
url
:=
fmt
.
Sprintf
(
"%s/v2/%s/blobs/%s"
,
mp
.
Registry
,
mp
.
GetNamespaceRepository
(),
digest
)
requestURL
:=
mp
.
BaseURL
()
requestURL
=
requestURL
.
JoinPath
(
"v2"
,
mp
.
GetNamespaceRepository
(),
"blobs"
,
digest
)
resp
,
err
:=
makeRequest
(
ctx
,
"HEAD"
,
url
,
nil
,
nil
,
regOpts
)
resp
,
err
:=
makeRequest
(
ctx
,
"HEAD"
,
requestURL
,
nil
,
nil
,
regOpts
)
if
err
!=
nil
{
if
err
!=
nil
{
log
.
Printf
(
"couldn't check for blob: %v"
,
err
)
log
.
Printf
(
"couldn't check for blob: %v"
,
err
)
return
false
,
err
return
false
,
err
...
@@ -1174,7 +1181,7 @@ func checkBlobExistence(ctx context.Context, mp ModelPath, digest string, regOpt
...
@@ -1174,7 +1181,7 @@ func checkBlobExistence(ctx context.Context, mp ModelPath, digest string, regOpt
return
resp
.
StatusCode
==
http
.
StatusOK
,
nil
return
resp
.
StatusCode
==
http
.
StatusOK
,
nil
}
}
func
uploadBlobChunked
(
ctx
context
.
Context
,
mp
ModelPath
,
url
string
,
layer
*
Layer
,
regOpts
*
RegistryOptions
,
fn
func
(
api
.
ProgressResponse
))
error
{
func
uploadBlobChunked
(
ctx
context
.
Context
,
mp
ModelPath
,
requestURL
*
url
.
URL
,
layer
*
Layer
,
regOpts
*
RegistryOptions
,
fn
func
(
api
.
ProgressResponse
))
error
{
// TODO allow resumability
// TODO allow resumability
// TODO allow canceling uploads via DELETE
// TODO allow canceling uploads via DELETE
...
@@ -1204,7 +1211,7 @@ func uploadBlobChunked(ctx context.Context, mp ModelPath, url string, layer *Lay
...
@@ -1204,7 +1211,7 @@ func uploadBlobChunked(ctx context.Context, mp ModelPath, url string, layer *Lay
headers
.
Set
(
"Content-Type"
,
"application/octet-stream"
)
headers
.
Set
(
"Content-Type"
,
"application/octet-stream"
)
headers
.
Set
(
"Content-Length"
,
strconv
.
Itoa
(
int
(
chunk
)))
headers
.
Set
(
"Content-Length"
,
strconv
.
Itoa
(
int
(
chunk
)))
headers
.
Set
(
"Content-Range"
,
fmt
.
Sprintf
(
"%d-%d"
,
completed
,
completed
+
sectionReader
.
Size
()
-
1
))
headers
.
Set
(
"Content-Range"
,
fmt
.
Sprintf
(
"%d-%d"
,
completed
,
completed
+
sectionReader
.
Size
()
-
1
))
resp
,
err
:=
makeRequestWithRetry
(
ctx
,
"PATCH"
,
url
,
headers
,
sectionReader
,
regOpts
)
resp
,
err
:=
makeRequestWithRetry
(
ctx
,
"PATCH"
,
requestURL
,
headers
,
sectionReader
,
regOpts
)
if
err
!=
nil
&&
!
errors
.
Is
(
err
,
io
.
EOF
)
{
if
err
!=
nil
&&
!
errors
.
Is
(
err
,
io
.
EOF
)
{
fn
(
api
.
ProgressResponse
{
fn
(
api
.
ProgressResponse
{
Status
:
fmt
.
Sprintf
(
"error uploading chunk: %v"
,
err
),
Status
:
fmt
.
Sprintf
(
"error uploading chunk: %v"
,
err
),
...
@@ -1225,20 +1232,26 @@ func uploadBlobChunked(ctx context.Context, mp ModelPath, url string, layer *Lay
...
@@ -1225,20 +1232,26 @@ func uploadBlobChunked(ctx context.Context, mp ModelPath, url string, layer *Lay
Completed
:
int
(
completed
),
Completed
:
int
(
completed
),
})
})
url
=
resp
.
Header
.
Get
(
"Location"
)
requestURL
,
err
=
url
.
Parse
(
resp
.
Header
.
Get
(
"Location"
))
if
err
!=
nil
{
return
err
}
if
completed
>=
int64
(
layer
.
Size
)
{
if
completed
>=
int64
(
layer
.
Size
)
{
break
break
}
}
}
}
url
=
fmt
.
Sprintf
(
"%s&digest=%s"
,
url
,
layer
.
Digest
)
values
:=
requestURL
.
Query
()
values
.
Add
(
"digest"
,
layer
.
Digest
)
requestURL
.
RawQuery
=
values
.
Encode
()
headers
:=
make
(
http
.
Header
)
headers
:=
make
(
http
.
Header
)
headers
.
Set
(
"Content-Type"
,
"application/octet-stream"
)
headers
.
Set
(
"Content-Type"
,
"application/octet-stream"
)
headers
.
Set
(
"Content-Length"
,
"0"
)
headers
.
Set
(
"Content-Length"
,
"0"
)
// finish the upload
// finish the upload
resp
,
err
:=
makeRequest
(
ctx
,
"PUT"
,
url
,
headers
,
nil
,
regOpts
)
resp
,
err
:=
makeRequest
(
ctx
,
"PUT"
,
requestURL
,
headers
,
nil
,
regOpts
)
if
err
!=
nil
{
if
err
!=
nil
{
log
.
Printf
(
"couldn't finish upload: %v"
,
err
)
log
.
Printf
(
"couldn't finish upload: %v"
,
err
)
return
err
return
err
...
@@ -1252,10 +1265,10 @@ func uploadBlobChunked(ctx context.Context, mp ModelPath, url string, layer *Lay
...
@@ -1252,10 +1265,10 @@ func uploadBlobChunked(ctx context.Context, mp ModelPath, url string, layer *Lay
return
nil
return
nil
}
}
func
makeRequestWithRetry
(
ctx
context
.
Context
,
method
,
url
string
,
headers
http
.
Header
,
body
io
.
ReadSeeker
,
regOpts
*
RegistryOptions
)
(
*
http
.
Response
,
error
)
{
func
makeRequestWithRetry
(
ctx
context
.
Context
,
method
string
,
requestURL
*
url
.
URL
,
headers
http
.
Header
,
body
io
.
ReadSeeker
,
regOpts
*
RegistryOptions
)
(
*
http
.
Response
,
error
)
{
var
status
string
var
status
string
for
try
:=
0
;
try
<
MaxRetries
;
try
++
{
for
try
:=
0
;
try
<
MaxRetries
;
try
++
{
resp
,
err
:=
makeRequest
(
ctx
,
method
,
url
,
headers
,
body
,
regOpts
)
resp
,
err
:=
makeRequest
(
ctx
,
method
,
requestURL
,
headers
,
body
,
regOpts
)
if
err
!=
nil
{
if
err
!=
nil
{
log
.
Printf
(
"couldn't start upload: %v"
,
err
)
log
.
Printf
(
"couldn't start upload: %v"
,
err
)
return
nil
,
err
return
nil
,
err
...
@@ -1291,16 +1304,12 @@ func makeRequestWithRetry(ctx context.Context, method, url string, headers http.
...
@@ -1291,16 +1304,12 @@ func makeRequestWithRetry(ctx context.Context, method, url string, headers http.
return
nil
,
fmt
.
Errorf
(
"max retry exceeded: %v"
,
status
)
return
nil
,
fmt
.
Errorf
(
"max retry exceeded: %v"
,
status
)
}
}
func
makeRequest
(
ctx
context
.
Context
,
method
,
url
string
,
headers
http
.
Header
,
body
io
.
Reader
,
regOpts
*
RegistryOptions
)
(
*
http
.
Response
,
error
)
{
func
makeRequest
(
ctx
context
.
Context
,
method
string
,
requestURL
*
url
.
URL
,
headers
http
.
Header
,
body
io
.
Reader
,
regOpts
*
RegistryOptions
)
(
*
http
.
Response
,
error
)
{
if
!
strings
.
HasPrefix
(
url
,
"http"
)
{
if
requestURL
.
Scheme
!=
"http"
&&
regOpts
.
Insecure
{
if
regOpts
.
Insecure
{
requestURL
.
Scheme
=
"http"
url
=
"http://"
+
url
}
else
{
url
=
"https://"
+
url
}
}
}
req
,
err
:=
http
.
NewRequestWithContext
(
ctx
,
method
,
url
,
body
)
req
,
err
:=
http
.
NewRequestWithContext
(
ctx
,
method
,
requestURL
.
String
()
,
body
)
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
err
return
nil
,
err
}
}
...
...
server/modelpath.go
View file @
968ced2e
...
@@ -3,6 +3,7 @@ package server
...
@@ -3,6 +3,7 @@ package server
import
(
import
(
"errors"
"errors"
"fmt"
"fmt"
"net/url"
"os"
"os"
"path/filepath"
"path/filepath"
"runtime"
"runtime"
...
@@ -39,13 +40,13 @@ func ParseModelPath(name string) ModelPath {
...
@@ -39,13 +40,13 @@ func ParseModelPath(name string) ModelPath {
Tag
:
DefaultTag
,
Tag
:
DefaultTag
,
}
}
parts
:=
strings
.
Spli
t
(
name
,
"://"
)
before
,
after
,
found
:=
strings
.
Cu
t
(
name
,
"://"
)
if
len
(
parts
)
>
1
{
if
found
{
mp
.
ProtocolScheme
=
parts
[
0
]
mp
.
ProtocolScheme
=
before
name
=
parts
[
1
]
name
=
after
}
}
parts
=
strings
.
Split
(
name
,
"/"
)
parts
:
=
strings
.
Split
(
name
,
"/"
)
switch
len
(
parts
)
{
switch
len
(
parts
)
{
case
3
:
case
3
:
mp
.
Registry
=
parts
[
0
]
mp
.
Registry
=
parts
[
0
]
...
@@ -100,6 +101,13 @@ func (mp ModelPath) GetManifestPath(createDir bool) (string, error) {
...
@@ -100,6 +101,13 @@ func (mp ModelPath) GetManifestPath(createDir bool) (string, error) {
return
path
,
nil
return
path
,
nil
}
}
func
(
mp
ModelPath
)
BaseURL
()
*
url
.
URL
{
return
&
url
.
URL
{
Scheme
:
mp
.
ProtocolScheme
,
Host
:
mp
.
Registry
,
}
}
func
GetManifestPath
()
(
string
,
error
)
{
func
GetManifestPath
()
(
string
,
error
)
{
home
,
err
:=
os
.
UserHomeDir
()
home
,
err
:=
os
.
UserHomeDir
()
if
err
!=
nil
{
if
err
!=
nil
{
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment