Skip to content

Commit e648a18

Browse files
committed
Allow push of a single tag
Docker-DCO-1.1-Signed-off-by: Guillaume J. Charmes <[email protected]> (github: creack)
1 parent f6f059d commit e648a18

3 files changed

Lines changed: 31 additions & 12 deletions

File tree

api/client/commands.go

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1000,7 +1000,7 @@ func (cli *DockerCli) CmdImport(args ...string) error {
10001000
}
10011001

10021002
func (cli *DockerCli) CmdPush(args ...string) error {
1003-
cmd := cli.Subcmd("push", "NAME", "Push an image or a repository to the registry")
1003+
cmd := cli.Subcmd("push", "NAME[:TAG]", "Push an image or a repository to the registry")
10041004
if err := cmd.Parse(args); err != nil {
10051005
return nil
10061006
}
@@ -1013,8 +1013,10 @@ func (cli *DockerCli) CmdPush(args ...string) error {
10131013

10141014
cli.LoadConfigFile()
10151015

1016+
remote, tag := utils.ParseRepositoryTag(name)
1017+
10161018
// Resolve the Repository name from fqn to hostname + name
1017-
hostname, _, err := registry.ResolveRepositoryName(name)
1019+
hostname, _, err := registry.ResolveRepositoryName(remote)
10181020
if err != nil {
10191021
return err
10201022
}
@@ -1033,6 +1035,7 @@ func (cli *DockerCli) CmdPush(args ...string) error {
10331035
}
10341036

10351037
v := url.Values{}
1038+
v.Set("tag", tag)
10361039
push := func(authConfig registry.AuthConfig) error {
10371040
buf, err := json.Marshal(authConfig)
10381041
if err != nil {
@@ -1042,7 +1045,7 @@ func (cli *DockerCli) CmdPush(args ...string) error {
10421045
base64.URLEncoding.EncodeToString(buf),
10431046
}
10441047

1045-
return cli.stream("POST", "/images/"+name+"/push?"+v.Encode(), nil, cli.out, map[string][]string{
1048+
return cli.stream("POST", "/images/"+remote+"/push?"+v.Encode(), nil, cli.out, map[string][]string{
10461049
"X-Registry-Auth": registryAuthHeader,
10471050
})
10481051
}

api/server/server.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -517,6 +517,7 @@ func postImagesPush(eng *engine.Engine, version version.Version, w http.Response
517517
job := eng.Job("push", vars["name"])
518518
job.SetenvJson("metaHeaders", metaHeaders)
519519
job.SetenvJson("authConfig", authConfig)
520+
job.Setenv("tag", r.Form.Get("tag"))
520521
if version.GreaterThan("1.0") {
521522
job.SetenvBool("json", true)
522523
streamJSON(job, w, true)

server/server.go

Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1401,14 +1401,17 @@ func (srv *Server) ImagePull(job *engine.Job) engine.Status {
14011401
}
14021402

14031403
// Retrieve the all the images to be uploaded in the correct order
1404-
func (srv *Server) getImageList(localRepo map[string]string) ([]string, map[string][]string, error) {
1404+
func (srv *Server) getImageList(localRepo map[string]string, requestedTag string) ([]string, map[string][]string, error) {
14051405
var (
14061406
imageList []string
14071407
imagesSeen map[string]bool = make(map[string]bool)
14081408
tagsByImage map[string][]string = make(map[string][]string)
14091409
)
14101410

14111411
for tag, id := range localRepo {
1412+
if requestedTag != "" && requestedTag != tag {
1413+
continue
1414+
}
14121415
var imageListForThisTag []string
14131416

14141417
tagsByImage[id] = append(tagsByImage[id], tag)
@@ -1435,25 +1438,29 @@ func (srv *Server) getImageList(localRepo map[string]string) ([]string, map[stri
14351438
// append to main image list
14361439
imageList = append(imageList, imageListForThisTag...)
14371440
}
1438-
1441+
if len(imageList) == 0 {
1442+
return nil, nil, fmt.Errorf("No images found for the requested repository / tag")
1443+
}
14391444
utils.Debugf("Image list: %v", imageList)
14401445
utils.Debugf("Tags by image: %v", tagsByImage)
14411446

14421447
return imageList, tagsByImage, nil
14431448
}
14441449

1445-
func (srv *Server) pushRepository(r *registry.Registry, out io.Writer, localName, remoteName string, localRepo map[string]string, sf *utils.StreamFormatter) error {
1450+
func (srv *Server) pushRepository(r *registry.Registry, out io.Writer, localName, remoteName string, localRepo map[string]string, tag string, sf *utils.StreamFormatter) error {
14461451
out = utils.NewWriteFlusher(out)
14471452
utils.Debugf("Local repo: %s", localRepo)
1448-
imgList, tagsByImage, err := srv.getImageList(localRepo)
1453+
imgList, tagsByImage, err := srv.getImageList(localRepo, tag)
14491454
if err != nil {
14501455
return err
14511456
}
14521457

14531458
out.Write(sf.FormatStatus("", "Sending image list"))
14541459

1455-
var repoData *registry.RepositoryData
1456-
var imageIndex []*registry.ImgData
1460+
var (
1461+
repoData *registry.RepositoryData
1462+
imageIndex []*registry.ImgData
1463+
)
14571464

14581465
for _, imgId := range imgList {
14591466
if tags, exists := tagsByImage[imgId]; exists {
@@ -1488,8 +1495,12 @@ func (srv *Server) pushRepository(r *registry.Registry, out io.Writer, localName
14881495
return err
14891496
}
14901497

1498+
nTag := 1
1499+
if tag == "" {
1500+
nTag = len(localRepo)
1501+
}
14911502
for _, ep := range repoData.Endpoints {
1492-
out.Write(sf.FormatStatus("", "Pushing repository %s (%d tags)", localName, len(localRepo)))
1503+
out.Write(sf.FormatStatus("", "Pushing repository %s (%d tags)", localName, nTag))
14931504

14941505
for _, imgId := range imgList {
14951506
if r.LookupRemoteImage(imgId, ep, repoData.Tokens) {
@@ -1575,6 +1586,7 @@ func (srv *Server) ImagePush(job *engine.Job) engine.Status {
15751586
metaHeaders map[string][]string
15761587
)
15771588

1589+
tag := job.Getenv("tag")
15781590
job.GetenvJson("authConfig", authConfig)
15791591
job.GetenvJson("metaHeaders", metaHeaders)
15801592
if _, err := srv.poolAdd("push", localName); err != nil {
@@ -1600,11 +1612,14 @@ func (srv *Server) ImagePush(job *engine.Job) engine.Status {
16001612
}
16011613

16021614
if err != nil {
1603-
reposLen := len(srv.runtime.Repositories().Repositories[localName])
1615+
reposLen := 1
1616+
if tag == "" {
1617+
reposLen = len(srv.runtime.Repositories().Repositories[localName])
1618+
}
16041619
job.Stdout.Write(sf.FormatStatus("", "The push refers to a repository [%s] (len: %d)", localName, reposLen))
16051620
// If it fails, try to get the repository
16061621
if localRepo, exists := srv.runtime.Repositories().Repositories[localName]; exists {
1607-
if err := srv.pushRepository(r, job.Stdout, localName, remoteName, localRepo, sf); err != nil {
1622+
if err := srv.pushRepository(r, job.Stdout, localName, remoteName, localRepo, tag, sf); err != nil {
16081623
return job.Error(err)
16091624
}
16101625
return engine.StatusOK

0 commit comments

Comments
 (0)