".github/workflows/build_cpp.yml" did not exist on "c89bf6b77a5be85e568401ffbbda0689e9bad252"
Unverified Commit 29b897f5 authored by Michael Yang's avatar Michael Yang Committed by GitHub
Browse files

Merge pull request #253 from jmorganca/upload

use a pipe to push to registry with progress
parents 85aeb428 a71ff3f6
...@@ -906,71 +906,58 @@ func uploadBlobChunked(mp ModelPath, url string, layer *Layer, regOpts *Registry ...@@ -906,71 +906,58 @@ func uploadBlobChunked(mp ModelPath, url string, layer *Layer, regOpts *Registry
return err return err
} }
headers := make(map[string]string) totalUploaded := 0
headers["Content-Type"] = "application/octet-stream"
chunkSize := 1 << 20 r, w := io.Pipe()
buf := make([]byte, chunkSize) defer r.Close()
var totalUploaded int
for { go func() {
n, err := f.Read(buf) defer w.Close()
if err != nil { for {
return err n, err := io.CopyN(w, f, 1024*1024)
} if err != nil && !errors.Is(err, io.EOF) {
fn(api.ProgressResponse{
headers["Content-Length"] = fmt.Sprintf("%d", n) Status: fmt.Sprintf("error copying pipe: %v", err),
headers["Content-Range"] = fmt.Sprintf("%d-%d", totalUploaded, totalUploaded+n-1) Digest: layer.Digest,
Total: layer.Size,
fn(api.ProgressResponse{ Completed: totalUploaded,
Status: fmt.Sprintf("uploading %s", layer.Digest), })
Digest: layer.Digest, return
Total: int(layer.Size), }
Completed: int(totalUploaded),
})
// change the buffersize for the last chunk totalUploaded += int(n)
if n < chunkSize {
buf = buf[:n]
}
resp, err := makeRequest("PATCH", url, headers, bytes.NewReader(buf), regOpts)
if err != nil {
log.Printf("couldn't upload blob: %v", err)
return err
}
defer resp.Body.Close()
url = resp.Header.Get("Location")
// Check for success: For a successful upload, the Docker registry will respond with a 201 Created
if resp.StatusCode != http.StatusAccepted {
fn(api.ProgressResponse{ fn(api.ProgressResponse{
Status: "error uploading layer", Status: fmt.Sprintf("uploading %s", layer.Digest),
Digest: layer.Digest, Digest: layer.Digest,
Total: int(layer.Size), Total: layer.Size,
Completed: int(totalUploaded), Completed: totalUploaded,
}) })
body, _ := io.ReadAll(resp.Body)
return fmt.Errorf("on layer upload registry responded with code %d: %v", resp.StatusCode, string(body)) if totalUploaded >= layer.Size {
return
}
} }
}()
totalUploaded += n url = fmt.Sprintf("%s&digest=%s", url, layer.Digest)
if totalUploaded >= layer.Size {
url = fmt.Sprintf("%s&digest=%s", url, layer.Digest)
// finish the upload headers := make(map[string]string)
resp, err := makeRequest("PUT", url, nil, nil, regOpts) headers["Content-Type"] = "application/octet-stream"
if err != nil { headers["Content-Range"] = fmt.Sprintf("0-%d", layer.Size-1)
log.Printf("couldn't finish upload: %v", err) headers["Content-Length"] = strconv.Itoa(int(layer.Size))
return err
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusCreated { // finish the upload
body, _ := io.ReadAll(resp.Body) resp, err := makeRequest("PUT", url, headers, r, regOpts)
return fmt.Errorf("on finish upload registry responded with code %d: %v", resp.StatusCode, string(body)) if err != nil {
} log.Printf("couldn't finish upload: %v", err)
break return err
} }
defer resp.Body.Close()
if resp.StatusCode != http.StatusCreated {
body, _ := io.ReadAll(resp.Body)
return fmt.Errorf("on finish upload registry responded with code %d: %v", resp.StatusCode, string(body))
} }
return nil return nil
} }
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment