@@ -58,13 +58,6 @@ type Go struct {
58
58
Syntax * Line
59
59
}
60
60
61
- // A Require is a single require statement.
62
- type Require struct {
63
- Mod module.Version
64
- Indirect bool // has "// indirect" comment
65
- Syntax * Line
66
- }
67
-
68
61
// An Exclude is a single exclude statement.
69
62
type Exclude struct {
70
63
Mod module.Version
@@ -93,6 +86,93 @@ type VersionInterval struct {
93
86
Low , High string
94
87
}
95
88
89
+ // A Require is a single require statement.
90
+ type Require struct {
91
+ Mod module.Version
92
+ Indirect bool // has "// indirect" comment
93
+ Syntax * Line
94
+ }
95
+
96
+ func (r * Require ) markRemoved () {
97
+ r .Syntax .markRemoved ()
98
+ * r = Require {}
99
+ }
100
+
101
+ func (r * Require ) setVersion (v string ) {
102
+ r .Mod .Version = v
103
+
104
+ if line := r .Syntax ; len (line .Token ) > 0 {
105
+ if line .InBlock {
106
+ // If the line is preceded by an empty line, remove it; see
107
+ // https://golang.org/issue/33779.
108
+ if len (line .Comments .Before ) == 1 && len (line .Comments .Before [0 ].Token ) == 0 {
109
+ line .Comments .Before = line .Comments .Before [:0 ]
110
+ }
111
+ if len (line .Token ) >= 2 { // example.com v1.2.3
112
+ line .Token [1 ] = v
113
+ }
114
+ } else {
115
+ if len (line .Token ) >= 3 { // require example.com v1.2.3
116
+ line .Token [2 ] = v
117
+ }
118
+ }
119
+ }
120
+ }
121
+
122
+ // setIndirect sets line to have (or not have) a "// indirect" comment.
123
+ func (r * Require ) setIndirect (indirect bool ) {
124
+ r .Indirect = indirect
125
+ line := r .Syntax
126
+ if isIndirect (line ) == indirect {
127
+ return
128
+ }
129
+ if indirect {
130
+ // Adding comment.
131
+ if len (line .Suffix ) == 0 {
132
+ // New comment.
133
+ line .Suffix = []Comment {{Token : "// indirect" , Suffix : true }}
134
+ return
135
+ }
136
+
137
+ com := & line .Suffix [0 ]
138
+ text := strings .TrimSpace (strings .TrimPrefix (com .Token , string (slashSlash )))
139
+ if text == "" {
140
+ // Empty comment.
141
+ com .Token = "// indirect"
142
+ return
143
+ }
144
+
145
+ // Insert at beginning of existing comment.
146
+ com .Token = "// indirect; " + text
147
+ return
148
+ }
149
+
150
+ // Removing comment.
151
+ f := strings .TrimSpace (strings .TrimPrefix (line .Suffix [0 ].Token , string (slashSlash )))
152
+ if f == "indirect" {
153
+ // Remove whole comment.
154
+ line .Suffix = nil
155
+ return
156
+ }
157
+
158
+ // Remove comment prefix.
159
+ com := & line .Suffix [0 ]
160
+ i := strings .Index (com .Token , "indirect;" )
161
+ com .Token = "//" + com .Token [i + len ("indirect;" ):]
162
+ }
163
+
164
+ // isIndirect reports whether line has a "// indirect" comment,
165
+ // meaning it is in go.mod only for its effect on indirect dependencies,
166
+ // so that it can be dropped entirely once the effective version of the
167
+ // indirect dependency reaches the given minimum version.
168
+ func isIndirect (line * Line ) bool {
169
+ if len (line .Suffix ) == 0 {
170
+ return false
171
+ }
172
+ f := strings .Fields (strings .TrimPrefix (line .Suffix [0 ].Token , string (slashSlash )))
173
+ return (len (f ) == 1 && f [0 ] == "indirect" || len (f ) > 1 && f [0 ] == "indirect;" )
174
+ }
175
+
96
176
func (f * File ) AddModuleStmt (path string ) error {
97
177
if f .Syntax == nil {
98
178
f .Syntax = new (FileSyntax )
@@ -476,58 +556,6 @@ func (f *File) fixRetract(fix VersionFixer, errs *ErrorList) {
476
556
}
477
557
}
478
558
479
- // isIndirect reports whether line has a "// indirect" comment,
480
- // meaning it is in go.mod only for its effect on indirect dependencies,
481
- // so that it can be dropped entirely once the effective version of the
482
- // indirect dependency reaches the given minimum version.
483
- func isIndirect (line * Line ) bool {
484
- if len (line .Suffix ) == 0 {
485
- return false
486
- }
487
- f := strings .Fields (strings .TrimPrefix (line .Suffix [0 ].Token , string (slashSlash )))
488
- return (len (f ) == 1 && f [0 ] == "indirect" || len (f ) > 1 && f [0 ] == "indirect;" )
489
- }
490
-
491
- // setIndirect sets line to have (or not have) a "// indirect" comment.
492
- func setIndirect (line * Line , indirect bool ) {
493
- if isIndirect (line ) == indirect {
494
- return
495
- }
496
- if indirect {
497
- // Adding comment.
498
- if len (line .Suffix ) == 0 {
499
- // New comment.
500
- line .Suffix = []Comment {{Token : "// indirect" , Suffix : true }}
501
- return
502
- }
503
-
504
- com := & line .Suffix [0 ]
505
- text := strings .TrimSpace (strings .TrimPrefix (com .Token , string (slashSlash )))
506
- if text == "" {
507
- // Empty comment.
508
- com .Token = "// indirect"
509
- return
510
- }
511
-
512
- // Insert at beginning of existing comment.
513
- com .Token = "// indirect; " + text
514
- return
515
- }
516
-
517
- // Removing comment.
518
- f := strings .TrimSpace (strings .TrimPrefix (line .Suffix [0 ].Token , string (slashSlash )))
519
- if f == "indirect" {
520
- // Remove whole comment.
521
- line .Suffix = nil
522
- return
523
- }
524
-
525
- // Remove comment prefix.
526
- com := & line .Suffix [0 ]
527
- i := strings .Index (com .Token , "indirect;" )
528
- com .Token = "//" + com .Token [i + len ("indirect;" ):]
529
- }
530
-
531
559
// IsDirectoryPath reports whether the given path should be interpreted
532
560
// as a directory path. Just like on the go command line, relative paths
533
561
// and rooted paths are directory paths; the rest are module paths.
@@ -866,8 +894,12 @@ func (f *File) AddRequire(path, vers string) error {
866
894
// the last require block, regardless of any existing require lines for path.
867
895
func (f * File ) AddNewRequire (path , vers string , indirect bool ) {
868
896
line := f .Syntax .addLine (nil , "require" , AutoQuote (path ), vers )
869
- setIndirect (line , indirect )
870
- f .Require = append (f .Require , & Require {module.Version {Path : path , Version : vers }, indirect , line })
897
+ r := & Require {
898
+ Mod : module.Version {Path : path , Version : vers },
899
+ Syntax : line ,
900
+ }
901
+ r .setIndirect (indirect )
902
+ f .Require = append (f .Require , r )
871
903
}
872
904
873
905
// SetRequire updates the requirements of f to contain exactly req, preserving
@@ -885,49 +917,28 @@ func (f *File) AddNewRequire(path, vers string, indirect bool) {
885
917
// If any existing requirements may be removed, the caller should call Cleanup
886
918
// after all edits are complete.
887
919
func (f * File ) SetRequire (req []* Require ) {
888
- need := make (map [string ]string )
889
- indirect := make (map [string ]bool )
920
+ type elem struct {
921
+ version string
922
+ indirect bool
923
+ }
924
+ need := make (map [string ]elem )
890
925
for _ , r := range req {
891
- if prev , dup := need [r .Mod .Path ]; dup && prev != r .Mod .Version {
892
- panic (fmt .Errorf ("SetRequire called with conflicting versions for path %s (%s and %s)" , r .Mod .Path , prev , r .Mod .Version ))
926
+ if prev , dup := need [r .Mod .Path ]; dup && prev . version != r .Mod .Version {
927
+ panic (fmt .Errorf ("SetRequire called with conflicting versions for path %s (%s and %s)" , r .Mod .Path , prev . version , r .Mod .Version ))
893
928
}
894
- need [r .Mod .Path ] = r .Mod .Version
895
- indirect [r .Mod .Path ] = r .Indirect
929
+ need [r .Mod .Path ] = elem {r .Mod .Version , r .Indirect }
896
930
}
897
931
898
932
// Update or delete the existing Require entries to preserve
899
933
// only the first for each module path in req.
900
934
for _ , r := range f .Require {
901
- v , ok := need [r .Mod .Path ]
902
- if ! ok {
903
- // This line is redundant or its path is no longer required at all.
904
- // Mark the requirement for deletion in Cleanup.
905
- r .Syntax .markRemoved ()
906
- * r = Require {}
907
- }
908
-
909
- r .Mod .Version = v
910
- r .Indirect = indirect [r .Mod .Path ]
911
-
912
- if line := r .Syntax ; line != nil && len (line .Token ) > 0 {
913
- if line .InBlock {
914
- // If the line is preceded by an empty line, remove it; see
915
- // https://golang.org/issue/33779.
916
- if len (line .Comments .Before ) == 1 && len (line .Comments .Before [0 ].Token ) == 0 {
917
- line .Comments .Before = line .Comments .Before [:0 ]
918
- }
919
- if len (line .Token ) >= 2 { // example.com v1.2.3
920
- line .Token [1 ] = v
921
- }
922
- } else {
923
- if len (line .Token ) >= 3 { // require example.com v1.2.3
924
- line .Token [2 ] = v
925
- }
926
- }
927
-
928
- setIndirect (line , r .Indirect )
935
+ e , ok := need [r .Mod .Path ]
936
+ if ok {
937
+ r .setVersion (e .version )
938
+ r .setIndirect (e .indirect )
939
+ } else {
940
+ r .markRemoved ()
929
941
}
930
-
931
942
delete (need , r .Mod .Path )
932
943
}
933
944
@@ -936,8 +947,8 @@ func (f *File) SetRequire(req []*Require) {
936
947
//
937
948
// This step is nondeterministic, but the final result will be deterministic
938
949
// because we will sort the block.
939
- for path , vers := range need {
940
- f .AddNewRequire (path , vers , indirect [ path ] )
950
+ for path , e := range need {
951
+ f .AddNewRequire (path , e . version , e . indirect )
941
952
}
942
953
943
954
f .SortBlocks ()
0 commit comments