1package types
2
3import (
4	"os"
5	"strconv"
6	"strings"
7	"unicode"
8
9	"github.com/onsi/ginkgo/config"
10	"github.com/onsi/ginkgo/formatter"
11)
12
13type Deprecation struct {
14	Message string
15	DocLink string
16	Version string
17}
18
19type deprecations struct{}
20
21var Deprecations = deprecations{}
22
23func (d deprecations) CustomReporter() Deprecation {
24	return Deprecation{
25		Message: "You are using a custom reporter.  Support for custom reporters will likely be removed in V2.  Most users were using them to generate junit or teamcity reports and this functionality will be merged into the core reporter.  In addition, Ginkgo 2.0 will support emitting a JSON-formatted report that users can then manipulate to generate custom reports.\n\n{{red}}{{bold}}If this change will be impactful to you please leave a comment on {{cyan}}{{underline}}https://github.com/onsi/ginkgo/issues/711{{/}}",
26		DocLink: "removed-custom-reporters",
27		Version: "1.16.0",
28	}
29}
30
31func (d deprecations) V1Reporter() Deprecation {
32	return Deprecation{
33		Message: "You are using a V1 Ginkgo Reporter.  Please update your custom reporter to the new V2 Reporter interface.",
34		DocLink: "changed-reporter-interface",
35		Version: "1.16.0",
36	}
37}
38
39func (d deprecations) Async() Deprecation {
40	return Deprecation{
41		Message: "You are passing a Done channel to a test node to test asynchronous behavior.  This is deprecated in Ginkgo V2.  Your test will run synchronously and the timeout will be ignored.",
42		DocLink: "removed-async-testing",
43		Version: "1.16.0",
44	}
45}
46
47func (d deprecations) Measure() Deprecation {
48	return Deprecation{
49		Message: "Measure is deprecated and will be removed in Ginkgo V2.  Please migrate to gomega/gmeasure.",
50		DocLink: "removed-measure",
51		Version: "1.16.3",
52	}
53}
54
55func (d deprecations) ParallelNode() Deprecation {
56	return Deprecation{
57		Message: "GinkgoParallelNode is deprecated and will be removed in Ginkgo V2.  Please use GinkgoParallelProcess instead.",
58		DocLink: "renamed-ginkgoparallelnode",
59		Version: "1.16.5",
60	}
61}
62
63func (d deprecations) Convert() Deprecation {
64	return Deprecation{
65		Message: "The convert command is deprecated in Ginkgo V2",
66		DocLink: "removed-ginkgo-convert",
67		Version: "1.16.0",
68	}
69}
70
71func (d deprecations) Blur() Deprecation {
72	return Deprecation{
73		Message: "The blur command is deprecated in Ginkgo V2.  Use 'ginkgo unfocus' instead.",
74		Version: "1.16.0",
75	}
76}
77
78type DeprecationTracker struct {
79	deprecations map[Deprecation][]CodeLocation
80}
81
82func NewDeprecationTracker() *DeprecationTracker {
83	return &DeprecationTracker{
84		deprecations: map[Deprecation][]CodeLocation{},
85	}
86}
87
88func (d *DeprecationTracker) TrackDeprecation(deprecation Deprecation, cl ...CodeLocation) {
89	ackVersion := os.Getenv("ACK_GINKGO_DEPRECATIONS")
90	if deprecation.Version != "" && ackVersion != "" {
91		ack := ParseSemVer(ackVersion)
92		version := ParseSemVer(deprecation.Version)
93		if ack.GreaterThanOrEqualTo(version) {
94			return
95		}
96	}
97
98	if len(cl) == 1 {
99		d.deprecations[deprecation] = append(d.deprecations[deprecation], cl[0])
100	} else {
101		d.deprecations[deprecation] = []CodeLocation{}
102	}
103}
104
105func (d *DeprecationTracker) DidTrackDeprecations() bool {
106	return len(d.deprecations) > 0
107}
108
109func (d *DeprecationTracker) DeprecationsReport() string {
110	out := formatter.F("\n{{light-yellow}}You're using deprecated Ginkgo functionality:{{/}}\n")
111	out += formatter.F("{{light-yellow}}============================================={{/}}\n")
112	out += formatter.F("{{bold}}{{green}}Ginkgo 2.0{{/}} is under active development and will introduce several new features, improvements, and a small handful of breaking changes.\n")
113	out += formatter.F("A release candidate for 2.0 is now available and 2.0 should GA in Fall 2021.  {{bold}}Please give the RC a try and send us feedback!{{/}}\n")
114	out += formatter.F("  - To learn more, view the migration guide at {{cyan}}{{underline}}https://github.com/onsi/ginkgo/blob/ver2/docs/MIGRATING_TO_V2.md{{/}}\n")
115	out += formatter.F("  - For instructions on using the Release Candidate visit {{cyan}}{{underline}}https://github.com/onsi/ginkgo/blob/ver2/docs/MIGRATING_TO_V2.md#using-the-beta{{/}}\n")
116	out += formatter.F("  - To comment, chime in at {{cyan}}{{underline}}https://github.com/onsi/ginkgo/issues/711{{/}}\n\n")
117
118	for deprecation, locations := range d.deprecations {
119		out += formatter.Fi(1, "{{yellow}}"+deprecation.Message+"{{/}}\n")
120		if deprecation.DocLink != "" {
121			out += formatter.Fi(1, "{{bold}}Learn more at:{{/}} {{cyan}}{{underline}}https://github.com/onsi/ginkgo/blob/ver2/docs/MIGRATING_TO_V2.md#%s{{/}}\n", deprecation.DocLink)
122		}
123		for _, location := range locations {
124			out += formatter.Fi(2, "{{gray}}%s{{/}}\n", location)
125		}
126	}
127	out += formatter.F("\n{{gray}}To silence deprecations that can be silenced set the following environment variable:{{/}}\n")
128	out += formatter.Fi(1, "{{gray}}ACK_GINKGO_DEPRECATIONS=%s{{/}}\n", config.VERSION)
129	return out
130}
131
132type SemVer struct {
133	Major int
134	Minor int
135	Patch int
136}
137
138func (s SemVer) GreaterThanOrEqualTo(o SemVer) bool {
139	return (s.Major > o.Major) ||
140		(s.Major == o.Major && s.Minor > o.Minor) ||
141		(s.Major == o.Major && s.Minor == o.Minor && s.Patch >= o.Patch)
142}
143
144func ParseSemVer(semver string) SemVer {
145	out := SemVer{}
146	semver = strings.TrimFunc(semver, func(r rune) bool {
147		return !(unicode.IsNumber(r) || r == '.')
148	})
149	components := strings.Split(semver, ".")
150	if len(components) > 0 {
151		out.Major, _ = strconv.Atoi(components[0])
152	}
153	if len(components) > 1 {
154		out.Minor, _ = strconv.Atoi(components[1])
155	}
156	if len(components) > 2 {
157		out.Patch, _ = strconv.Atoi(components[2])
158	}
159	return out
160}
161