@@ -576,9 +576,16 @@ func (s *sqlLoader) addPackageChannels(tx *sql.Tx, manifest registry.PackageMani
576576 return fmt .Errorf ("failed to add package %q: %s" , manifest .PackageName , err .Error ())
577577 }
578578
579- var errs []error
580- hasDefault := false
579+ var (
580+ errs []error
581+ channels []registry.PackageChannel
582+ hasDefault bool
583+ )
581584 for _ , c := range manifest .Channels {
585+ if deprecated , err := s .deprecated (tx , c .CurrentCSVName ); err != nil || deprecated {
586+ // Elide channels that start with a deprecated bundle
587+ continue
588+ }
582589 if _ , err := addChannel .Exec (c .Name , manifest .PackageName , c .CurrentCSVName ); err != nil {
583590 errs = append (errs , fmt .Errorf ("failed to add channel %q in package %q: %s" , c .Name , manifest .PackageName , err .Error ()))
584591 continue
@@ -590,12 +597,13 @@ func (s *sqlLoader) addPackageChannels(tx *sql.Tx, manifest registry.PackageMani
590597 continue
591598 }
592599 }
600+ channels = append (channels , c )
593601 }
594602 if ! hasDefault {
595603 errs = append (errs , fmt .Errorf ("no default channel specified for %s" , manifest .PackageName ))
596604 }
597605
598- for _ , c := range manifest . Channels {
606+ for _ , c := range channels {
599607 res , err := addChannelEntry .Exec (c .Name , manifest .PackageName , c .CurrentCSVName , 0 )
600608 if err != nil {
601609 errs = append (errs , fmt .Errorf ("failed to add channel %q in package %q: %s" , c .Name , manifest .PackageName , err .Error ()))
@@ -1268,19 +1276,18 @@ func (s *sqlLoader) addBundleProperties(tx *sql.Tx, bundle *registry.Bundle) err
12681276}
12691277
12701278func (s * sqlLoader ) rmChannelEntry (tx * sql.Tx , csvName string ) error {
1271- getEntryID := `SELECT entry_id FROM channel_entry WHERE operatorbundle_name=?`
1272- rows , err := tx .QueryContext (context .TODO (), getEntryID , csvName )
1279+ rows , err := tx .Query (`SELECT entry_id FROM channel_entry WHERE operatorbundle_name=?` , csvName )
12731280 if err != nil {
12741281 return err
12751282 }
1283+
12761284 var entryIDs []int64
12771285 for rows .Next () {
12781286 var entryID sql.NullInt64
12791287 rows .Scan (& entryID )
12801288 entryIDs = append (entryIDs , entryID .Int64 )
12811289 }
1282- err = rows .Close ()
1283- if err != nil {
1290+ if err := rows .Close (); err != nil {
12841291 return err
12851292 }
12861293
@@ -1299,35 +1306,50 @@ func (s *sqlLoader) rmChannelEntry(tx *sql.Tx, csvName string) error {
12991306 return err
13001307 }
13011308
1302- stmt , err : = tx .Prepare ( " DELETE FROM channel_entry WHERE operatorbundle_name=?" )
1309+ _ , err = tx .Exec ( ` DELETE FROM channel WHERE head_operatorbundle_name=?` , csvName )
13031310 if err != nil {
13041311 return err
13051312 }
1306- defer stmt .Close ()
1307-
1308- if _ , err := stmt .Exec (csvName ); err != nil {
1309- return err
1310- }
13111313
13121314 return nil
13131315}
13141316
1315- func getTailFromBundle (tx * sql.Tx , name string ) (bundles []string , err error ) {
1317+ func getTailFromBundle (tx * sql.Tx , head string ) (bundles []string , err error ) {
13161318 getReplacesSkips := `SELECT replaces, skips FROM operatorbundle WHERE name=?`
13171319 isDefaultChannelHead := `SELECT head_operatorbundle_name FROM channel
13181320 INNER JOIN package ON channel.name = package.default_channel
13191321 WHERE channel.head_operatorbundle_name = ?`
13201322
1321- tail := make (map [string ]struct {})
1322- next := name
1323+ visited := map [string ]struct {}{}
1324+ next := []string {head }
1325+
1326+ for len (next ) > 0 {
1327+ // Pop the next bundle off of the queue
1328+ bundle := next [0 ]
1329+ next = next [1 :] // Potentially inefficient queue implementation, but this function is only used when deprecate is called
13231330
1324- for next != "" {
1325- rows , err := tx .QueryContext (context .TODO (), getReplacesSkips , next )
1331+ // Check if next is the head of the defaultChannel
1332+ // If it is, the defaultChannel would be removed -- this is not allowed because we cannot know which channel to promote as the new default
1333+ var err error
1334+ if row := tx .QueryRow (isDefaultChannelHead , bundle ); row != nil {
1335+ err = row .Scan (& sql.NullString {})
1336+ }
1337+ if err == nil {
1338+ // A nil error indicates that next is the default channel head
1339+ return nil , registry .ErrRemovingDefaultChannelDuringDeprecation
1340+ } else if err != sql .ErrNoRows {
1341+ return nil , err
1342+ }
1343+
1344+ rows , err := tx .QueryContext (context .TODO (), getReplacesSkips , bundle )
13261345 if err != nil {
13271346 return nil , err
13281347 }
1329- var replaces sql.NullString
1330- var skips sql.NullString
1348+
1349+ var (
1350+ replaces sql.NullString
1351+ skips sql.NullString
1352+ )
13311353 if rows .Next () {
13321354 if err := rows .Scan (& replaces , & skips ); err != nil {
13331355 if nerr := rows .Close (); nerr != nil {
@@ -1341,49 +1363,32 @@ func getTailFromBundle(tx *sql.Tx, name string) (bundles []string, err error) {
13411363 }
13421364 if skips .Valid && skips .String != "" {
13431365 for _ , skip := range strings .Split (skips .String , "," ) {
1344- tail [skip ] = struct {}{}
1366+ if _ , ok := visited [skip ]; ok {
1367+ // We've already visited this bundle's subgraph
1368+ continue
1369+ }
1370+ visited [skip ] = struct {}{}
1371+ next = append (next , skip )
13451372 }
13461373 }
13471374 if replaces .Valid && replaces .String != "" {
1348- // check if replaces is the head of the defaultChannel
1349- // if it is, the defaultChannel will be removed
1350- // this is not allowed because we cannot know which channel to promote as the new default
1351- rows , err := tx .QueryContext (context .TODO (), isDefaultChannelHead , replaces .String )
1352- if err != nil {
1353- return nil , err
1354- }
1355- if rows .Next () {
1356- var defaultChannelHead sql.NullString
1357- err := rows .Scan (& defaultChannelHead )
1358- if err != nil {
1359- if nerr := rows .Close (); nerr != nil {
1360- return nil , nerr
1361- }
1362- return nil , err
1363- }
1364- if defaultChannelHead .Valid {
1365- if nerr := rows .Close (); nerr != nil {
1366- return nil , nerr
1367- }
1368- return nil , registry .ErrRemovingDefaultChannelDuringDeprecation
1369- }
1370- }
1371- if err := rows .Close (); err != nil {
1372- return nil , err
1375+ r := replaces .String
1376+ if _ , ok := visited [r ]; ok {
1377+ // We've already visited this bundle's subgraph
1378+ continue
13731379 }
1374- next = replaces .String
1375- tail [replaces .String ] = struct {}{}
1376- } else {
1377- next = ""
1380+ visited [r ] = struct {}{}
1381+ next = append (next , r )
13781382 }
13791383 }
1380- var allTails []string
13811384
1382- for k := range tail {
1383- allTails = append (allTails , k )
1385+ // The tail is exactly the set of bundles we visited while traversing the graph from head
1386+ var tail []string
1387+ for v := range visited {
1388+ tail = append (tail , v )
13841389 }
13851390
1386- return allTails , nil
1391+ return tail , nil
13871392
13881393}
13891394
@@ -1427,16 +1432,20 @@ func (s *sqlLoader) DeprecateBundle(path string) error {
14271432 }
14281433
14291434 for _ , bundle := range tailBundles {
1430- err = s .rmChannelEntry (tx , bundle )
1431- if err != nil {
1435+ if err := s .rmChannelEntry (tx , bundle ); err != nil {
14321436 return err
14331437 }
1434- err := s .rmBundle (tx , bundle )
1435- if err != nil {
1438+ if err := s .rmBundle (tx , bundle ); err != nil {
14361439 return err
14371440 }
14381441 }
14391442
1443+ // Remove any channels that start with the deprecated bundle
1444+ _ , err = tx .Exec (fmt .Sprintf (`DELETE FROM channel WHERE head_operatorbundle_name="%s"` , name ))
1445+ if err != nil {
1446+ return err
1447+ }
1448+
14401449 deprecatedValue , err := json .Marshal (registry.DeprecatedProperty {})
14411450 if err != nil {
14421451 return err
0 commit comments