Closes #9798
@maintainers please note that this is a change to the UX. We no longer
require the -f flag on `docker tag` to move a tag from an existing image.
However, this does make us more consistent across our commands,
see https://github.com/docker/docker/issues/9798 for the history.
Signed-off-by: Doug Davis <dug@us.ibm.com>
| ... | ... |
@@ -15,7 +15,7 @@ import ( |
| 15 | 15 |
// Usage: docker tag [OPTIONS] IMAGE[:TAG] [REGISTRYHOST/][USERNAME/]NAME[:TAG] |
| 16 | 16 |
func (cli *DockerCli) CmdTag(args ...string) error {
|
| 17 | 17 |
cmd := Cli.Subcmd("tag", []string{"IMAGE[:TAG] [REGISTRYHOST/][USERNAME/]NAME[:TAG]"}, Cli.DockerCommands["tag"].Description, true)
|
| 18 |
- force := cmd.Bool([]string{"f", "-force"}, false, "Force the tagging even if there's a conflict")
|
|
| 18 |
+ force := cmd.Bool([]string{"#f", "#-force"}, false, "Force the tagging even if there's a conflict")
|
|
| 19 | 19 |
cmd.Require(flag.Exact, 2) |
| 20 | 20 |
|
| 21 | 21 |
cmd.ParseFlags(args, true) |
| ... | ... |
@@ -466,7 +466,7 @@ func (s *router) postBuild(ctx context.Context, w http.ResponseWriter, r *http.R |
| 466 | 466 |
} |
| 467 | 467 |
|
| 468 | 468 |
for _, rt := range repoAndTags {
|
| 469 |
- if err := s.daemon.TagImage(rt, imgID, true); err != nil {
|
|
| 469 |
+ if err := s.daemon.TagImage(rt, imgID); err != nil {
|
|
| 470 | 470 |
return errf(err) |
| 471 | 471 |
} |
| 472 | 472 |
} |
| ... | ... |
@@ -550,8 +550,7 @@ func (s *router) postImagesTag(ctx context.Context, w http.ResponseWriter, r *ht |
| 550 | 550 |
return err |
| 551 | 551 |
} |
| 552 | 552 |
} |
| 553 |
- force := httputils.BoolValue(r, "force") |
|
| 554 |
- if err := s.daemon.TagImage(newTag, vars["name"], force); err != nil {
|
|
| 553 |
+ if err := s.daemon.TagImage(newTag, vars["name"]); err != nil {
|
|
| 555 | 554 |
return err |
| 556 | 555 |
} |
| 557 | 556 |
w.WriteHeader(http.StatusCreated) |
| ... | ... |
@@ -136,7 +136,7 @@ func (daemon *Daemon) Commit(name string, c *ContainerCommitConfig) (string, err |
| 136 | 136 |
return "", err |
| 137 | 137 |
} |
| 138 | 138 |
} |
| 139 |
- if err := daemon.TagImage(newTag, id.String(), true); err != nil {
|
|
| 139 |
+ if err := daemon.TagImage(newTag, id.String()); err != nil {
|
|
| 140 | 140 |
return "", err |
| 141 | 141 |
} |
| 142 | 142 |
} |
| ... | ... |
@@ -1017,15 +1017,14 @@ func (daemon *Daemon) changes(container *Container) ([]archive.Change, error) {
|
| 1017 | 1017 |
} |
| 1018 | 1018 |
|
| 1019 | 1019 |
// TagImage creates a tag in the repository reponame, pointing to the image named |
| 1020 |
-// imageName. If force is true, an existing tag with the same name may be |
|
| 1021 |
-// overwritten. |
|
| 1022 |
-func (daemon *Daemon) TagImage(newTag reference.Named, imageName string, force bool) error {
|
|
| 1020 |
+// imageName. |
|
| 1021 |
+func (daemon *Daemon) TagImage(newTag reference.Named, imageName string) error {
|
|
| 1023 | 1022 |
imageID, err := daemon.GetImageID(imageName) |
| 1024 | 1023 |
if err != nil {
|
| 1025 | 1024 |
return err |
| 1026 | 1025 |
} |
| 1027 | 1026 |
newTag = registry.NormalizeLocalReference(newTag) |
| 1028 |
- if err := daemon.tagStore.AddTag(newTag, imageID, force); err != nil {
|
|
| 1027 |
+ if err := daemon.tagStore.AddTag(newTag, imageID, true); err != nil {
|
|
| 1029 | 1028 |
return err |
| 1030 | 1029 |
} |
| 1031 | 1030 |
daemon.EventsService.Log("tag", newTag.String(), "")
|
| ... | ... |
@@ -100,7 +100,7 @@ func (daemon *Daemon) ImportImage(src string, newRef reference.Named, msg string |
| 100 | 100 |
|
| 101 | 101 |
// FIXME: connect with commit code and call tagstore directly |
| 102 | 102 |
if newRef != nil {
|
| 103 |
- if err := daemon.TagImage(newRef, id.String(), true); err != nil {
|
|
| 103 |
+ if err := daemon.TagImage(newRef, id.String()); err != nil {
|
|
| 104 | 104 |
return err |
| 105 | 105 |
} |
| 106 | 106 |
} |
| ... | ... |
@@ -12,6 +12,13 @@ parent = "mn_use_docker" |
| 12 | 12 |
|
| 13 | 13 |
The following list of features are deprecated. |
| 14 | 14 |
|
| 15 |
+### `-f` flag on `docker tag` |
|
| 16 |
+**Deprecated In Release: v1.10** |
|
| 17 |
+ |
|
| 18 |
+**Target For Removal In Release: v1.12** |
|
| 19 |
+ |
|
| 20 |
+To make tagging consistent across the various `docker` commands, the `-f` flag on the `docker tag` command is deprecated. It is not longer necessary to specify `-f` to move a tag from one image to another. Nor will `docker` generate an error if the `-f` flag is missing and the specified tag is already in use. |
|
| 21 |
+ |
|
| 15 | 22 |
### HostConfig at API container start |
| 16 | 23 |
**Deprecated In Release: v1.10** |
| 17 | 24 |
|
| ... | ... |
@@ -69,7 +69,7 @@ func (s *DockerSuite) TestTagValidPrefixedRepo(c *check.C) {
|
| 69 | 69 |
} |
| 70 | 70 |
} |
| 71 | 71 |
|
| 72 |
-// tag an image with an existed tag name without -f option should fail |
|
| 72 |
+// tag an image with an existed tag name without -f option should work |
|
| 73 | 73 |
func (s *DockerSuite) TestTagExistedNameWithoutForce(c *check.C) {
|
| 74 | 74 |
testRequires(c, DaemonIsLinux) |
| 75 | 75 |
if err := pullImageIfNotExist("busybox:latest"); err != nil {
|
| ... | ... |
@@ -77,10 +77,6 @@ func (s *DockerSuite) TestTagExistedNameWithoutForce(c *check.C) {
|
| 77 | 77 |
} |
| 78 | 78 |
|
| 79 | 79 |
dockerCmd(c, "tag", "busybox:latest", "busybox:test") |
| 80 |
- out, _, err := dockerCmdWithError("tag", "busybox:latest", "busybox:test")
|
|
| 81 |
- |
|
| 82 |
- c.Assert(err, checker.NotNil, check.Commentf(out)) |
|
| 83 |
- c.Assert(out, checker.Contains, "Conflict: Tag busybox:test is already set to image", check.Commentf("tag busybox busybox:test should have failed,because busybox:test is existed"))
|
|
| 84 | 80 |
} |
| 85 | 81 |
|
| 86 | 82 |
// tag an image with an existed tag name with -f option should work |
| ... | ... |
@@ -129,7 +125,7 @@ func (s *DockerSuite) TestTagOfficialNames(c *check.C) {
|
| 129 | 129 |
} |
| 130 | 130 |
|
| 131 | 131 |
for _, name := range names {
|
| 132 |
- out, exitCode, err := dockerCmdWithError("tag", "-f", "busybox:latest", name+":latest")
|
|
| 132 |
+ out, exitCode, err := dockerCmdWithError("tag", "busybox:latest", name+":latest")
|
|
| 133 | 133 |
if err != nil || exitCode != 0 {
|
| 134 | 134 |
c.Errorf("tag busybox %v should have worked: %s, %s", name, err, out)
|
| 135 | 135 |
continue |
| ... | ... |
@@ -146,7 +142,7 @@ func (s *DockerSuite) TestTagOfficialNames(c *check.C) {
|
| 146 | 146 |
} |
| 147 | 147 |
|
| 148 | 148 |
for _, name := range names {
|
| 149 |
- _, exitCode, err := dockerCmdWithError("tag", "-f", name+":latest", "fooo/bar:latest")
|
|
| 149 |
+ _, exitCode, err := dockerCmdWithError("tag", name+":latest", "fooo/bar:latest")
|
|
| 150 | 150 |
if err != nil || exitCode != 0 {
|
| 151 | 151 |
c.Errorf("tag %v fooo/bar should have worked: %s", name, err)
|
| 152 | 152 |
continue |
| ... | ... |
@@ -163,7 +159,7 @@ func (s *DockerSuite) TestTagMatchesDigest(c *check.C) {
|
| 163 | 163 |
} |
| 164 | 164 |
digest := "busybox@sha256:abcdef76720241213f5303bda7704ec4c2ef75613173910a56fb1b6e20251507" |
| 165 | 165 |
// test setting tag fails |
| 166 |
- _, _, err := dockerCmdWithError("tag", "-f", "busybox:latest", digest)
|
|
| 166 |
+ _, _, err := dockerCmdWithError("tag", "busybox:latest", digest)
|
|
| 167 | 167 |
if err == nil {
|
| 168 | 168 |
c.Fatal("digest tag a name should have failed")
|
| 169 | 169 |
} |
| ... | ... |
@@ -181,7 +177,7 @@ func (s *DockerSuite) TestTagInvalidRepoName(c *check.C) {
|
| 181 | 181 |
} |
| 182 | 182 |
|
| 183 | 183 |
// test setting tag fails |
| 184 |
- _, _, err := dockerCmdWithError("tag", "-f", "busybox:latest", "sha256:sometag")
|
|
| 184 |
+ _, _, err := dockerCmdWithError("tag", "busybox:latest", "sha256:sometag")
|
|
| 185 | 185 |
if err == nil {
|
| 186 | 186 |
c.Fatal("tagging with image named \"sha256\" should have failed")
|
| 187 | 187 |
} |
| ... | ... |
@@ -214,7 +210,7 @@ func (s *DockerSuite) TestTagTruncationAmbiguity(c *check.C) {
|
| 214 | 214 |
c.Logf("Built image: %s", imageID)
|
| 215 | 215 |
|
| 216 | 216 |
// test setting tag fails |
| 217 |
- _, _, err = dockerCmdWithError("tag", "-f", "busybox:latest", truncatedTag)
|
|
| 217 |
+ _, _, err = dockerCmdWithError("tag", "busybox:latest", truncatedTag)
|
|
| 218 | 218 |
if err != nil {
|
| 219 | 219 |
c.Fatalf("Error tagging with an image id: %s", err)
|
| 220 | 220 |
} |
| ... | ... |
@@ -6,7 +6,6 @@ docker-tag - Tag an image into a repository |
| 6 | 6 |
|
| 7 | 7 |
# SYNOPSIS |
| 8 | 8 |
**docker tag** |
| 9 |
-[**-f**|**--force**[=*false*]] |
|
| 10 | 9 |
[**--help**] |
| 11 | 10 |
IMAGE[:TAG] [REGISTRY_HOST/][USERNAME/]NAME[:TAG] |
| 12 | 11 |
|
| ... | ... |
@@ -18,9 +17,6 @@ If you do not specify a `REGISTRY_HOST`, the command uses Docker's public |
| 18 | 18 |
registry located at `registry-1.docker.io` by default. |
| 19 | 19 |
|
| 20 | 20 |
# "OPTIONS" |
| 21 |
-**-f**, **--force**=*true*|*false* |
|
| 22 |
- When set to true, force the alias. The default is *false*. |
|
| 23 |
- |
|
| 24 | 21 |
**--help** |
| 25 | 22 |
Print usage statement. |
| 26 | 23 |
|