...

Text file src/cmd/go/testdata/script/mod_tidy_convergence.txt

Documentation: cmd/go/testdata/script

     1# This test demonstrates a simple case in which 'go mod tidy' may resolve a
     2# missing package, only to remove that package when resolving its dependencies.
     3#
     4# If we naively iterate 'go mod tidy' until the dependency graph converges, this
     5# scenario may fail to converge.
     6
     7# The import graph used in this test looks like:
     8#
     9# m --- x
    10#       |
    11#       x_test --- y
    12#
    13# The module dependency graph of m is initially empty.
    14# Modules x and y look like:
    15#
    16# x.1 (provides package x that imports y, but does not depend on module y)
    17#
    18# x.2-pre (no dependencies, but does not provide package x)
    19#
    20# y.1 (no dependencies, but provides package y)
    21#
    22# y.2 --- x.2-pre (provides package y)
    23#
    24#
    25# When we resolve the missing import of y in x_test, we add y@latest — which is
    26# y.2, not y.1 — as a new dependency. That upgrades to x to x.2-pre, which
    27# removes package x (and also the need for module y). We can then safely remove
    28# the dependency on module y, because nothing imports package y any more!
    29#
    30# We might be tempted to remove the dependency on module x for the same reason:
    31# it no longer provides any imported package. However, that would cause 'go mod
    32# tidy -e' to become unstable: with x.2-pre out of the way, we could once again
    33# resolve the missing import of package x by re-adding x.1.
    34
    35cp go.mod go.mod.orig
    36
    37# 'go mod tidy' without -e should fail without modifying go.mod,
    38# because it cannot resolve x and y simultaneously.
    39! go mod tidy
    40
    41cmp go.mod go.mod.orig
    42
    43stderr '^go: found example\.net/y in example\.net/y v0.2.0$'
    44stderr '^go: finding module for package example\.net/x$'
    45
    46	# TODO: This error message should be clearer — it doesn't indicate why v0.2.0-pre is required.
    47stderr '^go: example\.net/m imports\n\texample\.net/x: package example\.net/x provided by example\.net/x at latest version v0\.1\.0 but not at required version v0\.2\.0-pre$'
    48
    49
    50# 'go mod tidy -e' should follow upgrades to try to resolve the modules that it
    51# can, and then stop. When we resolve example.net/y, we upgrade to example.net/x
    52# to v0.2.0-pre. At that version, package x no longer exists and no longer
    53# imports package y, so the import of x should be left unsatisfied and the
    54# existing dependency on example.net/x removed.
    55#
    56# TODO(bcmills): It would be ever better if we could keep the original
    57# dependency on example.net/x v0.1.0, but I don't see a way to do that without
    58# making the algorithm way too complicated. (We would have to detect that the
    59# new dependency on example.net/y interferes with the package that caused us to
    60# to add that dependency in the first place, and back out that part of the change
    61# without also backing out any other needed changes.)
    62
    63go mod tidy -e
    64cmp go.mod go.mod.tidye
    65stderr '^go: found example\.net/y in example\.net/y v0.2.0$'
    66
    67	# TODO: This error message should be clearer — it doesn't indicate why v0.2.0-pre is required.
    68stderr '^go: example\.net/m imports\n\texample\.net/x: package example\.net/x provided by example\.net/x at latest version v0\.1\.0 but not at required version v0\.2\.0-pre$'
    69
    70
    71# Since we attempt to resolve the dependencies of package x whenever we add x itself,
    72# this end state is stable.
    73
    74go mod tidy -e
    75cmp go.mod go.mod.tidye
    76
    77
    78# An explicit 'go get' with the correct versions should allow 'go mod tidy' to
    79# succeed and remain stable. y.1 does not upgrade x, and can therefore be used
    80# with it.
    81
    82go get example.net/x@v0.1.0 example.net/y@v0.1.0
    83go mod tidy
    84cmp go.mod go.mod.postget
    85
    86
    87# The 'tidy' logic for a lazy main module is somewhat different from that for an
    88# eager main module, but the overall behavior is the same.
    89
    90cp go.mod.orig go.mod
    91go mod edit -go=1.17 go.mod
    92go mod edit -go=1.17 go.mod.tidye
    93
    94go mod tidy -e
    95cmp go.mod go.mod.tidye
    96stderr '^go: found example\.net/y in example\.net/y v0.2.0$'
    97stderr '^go: example\.net/m imports\n\texample\.net/x: package example\.net/x provided by example\.net/x at latest version v0\.1\.0 but not at required version v0\.2\.0-pre$'
    98
    99go get example.net/x@v0.1.0 example.net/y@v0.1.0
   100go mod tidy
   101cmp go.mod go.mod.postget-117
   102
   103
   104-- go.mod --
   105module example.net/m
   106
   107go 1.16
   108
   109replace (
   110	example.net/x v0.1.0 => ./x1
   111	example.net/x v0.2.0-pre => ./x2-pre
   112	example.net/y v0.1.0 => ./y1
   113	example.net/y v0.2.0 => ./y2
   114)
   115
   116require (
   117	example.net/x v0.1.0
   118)
   119-- go.mod.tidye --
   120module example.net/m
   121
   122go 1.16
   123
   124replace (
   125	example.net/x v0.1.0 => ./x1
   126	example.net/x v0.2.0-pre => ./x2-pre
   127	example.net/y v0.1.0 => ./y1
   128	example.net/y v0.2.0 => ./y2
   129)
   130-- go.mod.postget --
   131module example.net/m
   132
   133go 1.16
   134
   135replace (
   136	example.net/x v0.1.0 => ./x1
   137	example.net/x v0.2.0-pre => ./x2-pre
   138	example.net/y v0.1.0 => ./y1
   139	example.net/y v0.2.0 => ./y2
   140)
   141
   142require (
   143	example.net/x v0.1.0
   144	example.net/y v0.1.0 // indirect
   145)
   146-- go.mod.postget-117 --
   147module example.net/m
   148
   149go 1.17
   150
   151replace (
   152	example.net/x v0.1.0 => ./x1
   153	example.net/x v0.2.0-pre => ./x2-pre
   154	example.net/y v0.1.0 => ./y1
   155	example.net/y v0.2.0 => ./y2
   156)
   157
   158require example.net/x v0.1.0
   159
   160require example.net/y v0.1.0 // indirect
   161-- m.go --
   162package m
   163
   164import _ "example.net/x"
   165
   166-- x1/go.mod --
   167module example.net/x
   168
   169go 1.16
   170-- x1/x.go --
   171package x
   172-- x1/x_test.go --
   173package x
   174
   175import _ "example.net/y"
   176
   177-- x2-pre/go.mod --
   178module example.net/x
   179
   180go 1.16
   181-- x2-pre/README.txt --
   182There is no package x here. Use example.com/x/subpkg instead.
   183-- x2-pre/subpkg/subpkg.go --
   184package subpkg  // import "example.net/x/subpkg"
   185
   186-- y1/go.mod --
   187module example.net/y
   188
   189go 1.16
   190-- y1/y.go --
   191package y
   192
   193-- y2/go.mod --
   194module example.net/y
   195
   196go 1.16
   197
   198require example.net/x v0.2.0-pre
   199-- y2/y.go --
   200package y
   201
   202import _ "example.net/x/subpkg"

View as plain text