From 81b3e3d6e7f324990979a03bffdf475f09edfca4 Mon Sep 17 00:00:00 2001 From: Jason Hall Date: Tue, 8 Feb 2022 15:30:36 -0500 Subject: [PATCH] Remove --watch mode --- doc/ko_apply.md | 1 - doc/ko_create.md | 1 - doc/ko_resolve.md | 1 - go.mod | 2 - go.sum | 2 - pkg/commands/options/filestuff.go | 55 --- pkg/commands/resolver.go | 64 +--- vendor/github.com/mattmoor/dep-notify/LICENSE | 201 ---------- .../mattmoor/dep-notify/pkg/graph/doc.go | 19 - .../dep-notify/pkg/graph/interface.go | 31 -- .../mattmoor/dep-notify/pkg/graph/manager.go | 343 ------------------ .../dep-notify/pkg/graph/manager_options.go | 119 ------ .../mattmoor/dep-notify/pkg/graph/node.go | 185 ---------- .../mattmoor/dep-notify/pkg/graph/set.go | 51 --- vendor/modules.txt | 4 - 15 files changed, 1 insertion(+), 1078 deletions(-) delete mode 100644 vendor/github.com/mattmoor/dep-notify/LICENSE delete mode 100644 vendor/github.com/mattmoor/dep-notify/pkg/graph/doc.go delete mode 100644 vendor/github.com/mattmoor/dep-notify/pkg/graph/interface.go delete mode 100644 vendor/github.com/mattmoor/dep-notify/pkg/graph/manager.go delete mode 100644 vendor/github.com/mattmoor/dep-notify/pkg/graph/manager_options.go delete mode 100644 vendor/github.com/mattmoor/dep-notify/pkg/graph/node.go delete mode 100644 vendor/github.com/mattmoor/dep-notify/pkg/graph/set.go diff --git a/doc/ko_apply.md b/doc/ko_apply.md index 94eca33dc9..feeb982268 100644 --- a/doc/ko_apply.md +++ b/doc/ko_apply.md @@ -83,7 +83,6 @@ ko apply -f FILENAME [flags] --token string Bearer token for authentication to the API server (DEPRECATED) --user string The name of the kubeconfig user to use (DEPRECATED) --username string Username for basic authentication to the API server (DEPRECATED) - -W, --watch Continuously monitor the transitive dependencies of the passed yaml files, and redeploy whenever anything changes. (DEPRECATED) ``` ### Options inherited from parent commands diff --git a/doc/ko_create.md b/doc/ko_create.md index e49656b78a..06615e59b3 100644 --- a/doc/ko_create.md +++ b/doc/ko_create.md @@ -83,7 +83,6 @@ ko create -f FILENAME [flags] --token string Bearer token for authentication to the API server (DEPRECATED) --user string The name of the kubeconfig user to use (DEPRECATED) --username string Username for basic authentication to the API server (DEPRECATED) - -W, --watch Continuously monitor the transitive dependencies of the passed yaml files, and redeploy whenever anything changes. (DEPRECATED) ``` ### Options inherited from parent commands diff --git a/doc/ko_resolve.md b/doc/ko_resolve.md index 7b9e770994..2355229005 100644 --- a/doc/ko_resolve.md +++ b/doc/ko_resolve.md @@ -58,7 +58,6 @@ ko resolve -f FILENAME [flags] --tag-only Include tags but not digests in resolved image references. Useful when digests are not preserved when images are repopulated. -t, --tags strings Which tags to use for the produced image instead of the default 'latest' tag (may not work properly with --base-import-paths or --bare). (default [latest]) --tarball string File to save images tarballs - -W, --watch Continuously monitor the transitive dependencies of the passed yaml files, and redeploy whenever anything changes. (DEPRECATED) ``` ### Options inherited from parent commands diff --git a/go.mod b/go.mod index f9ce2d8475..3069493e67 100644 --- a/go.mod +++ b/go.mod @@ -11,11 +11,9 @@ require ( github.com/containerd/stargz-snapshotter/estargz v0.11.1 github.com/docker/docker v20.10.12+incompatible github.com/dprotaso/go-yit v0.0.0-20191028211022-135eb7262960 - github.com/fsnotify/fsnotify v1.5.1 github.com/go-training/helloworld v0.0.0-20200225145412-ba5f4379d78b github.com/google/go-cmp v0.5.7 github.com/google/go-containerregistry v0.8.1-0.20220209165246-a44adc326839 - github.com/mattmoor/dep-notify v0.0.0-20190205035814-a45dec370a17 github.com/opencontainers/image-spec v1.0.3-0.20220114050600-8b9d41f48198 github.com/sigstore/cosign v1.3.2-0.20211120003522-90e2dcfe7b92 github.com/spf13/cobra v1.3.0 diff --git a/go.sum b/go.sum index b30b7444f9..4d37009c33 100644 --- a/go.sum +++ b/go.sum @@ -1310,8 +1310,6 @@ github.com/markbates/safe v1.0.1/go.mod h1:nAqgmRi7cY2nqMc92/bSEeQA+R4OheNU2T1kN github.com/marstr/guid v1.1.0/go.mod h1:74gB1z2wpxxInTG6yaqA7KrtM0NZ+RbrcqDvYHefzho= github.com/matoous/godox v0.0.0-20210227103229-6504466cf951/go.mod h1:1BELzlh859Sh1c6+90blK8lbYy0kwQf1bYlBhBysy1s= github.com/matryer/is v1.4.0/go.mod h1:8I/i5uYgLzgsgEloJE1U6xx5HkBQpAZvepWuujKwMRU= -github.com/mattmoor/dep-notify v0.0.0-20190205035814-a45dec370a17 h1:P91eDVgVzvF2EmA6fmGCyR2VQFlmo2nsmS2DbHoGAco= -github.com/mattmoor/dep-notify v0.0.0-20190205035814-a45dec370a17/go.mod h1:qWnF4u+oS4UWOZMwZcBQXrt5IQIdWc6XVJLDdxGIfdQ= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ= github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= diff --git a/pkg/commands/options/filestuff.go b/pkg/commands/options/filestuff.go index 83936b0484..2820aa5468 100644 --- a/pkg/commands/options/filestuff.go +++ b/pkg/commands/options/filestuff.go @@ -19,25 +19,13 @@ import ( "os" "path/filepath" - "github.com/fsnotify/fsnotify" "github.com/spf13/cobra" ) -const deprecation412 = `NOTICE! ------------------------------------------------------------------ -Watch mode is deprecated and unsupported, and will be removed in -a future release. - -For more information see: - https://github.com/google/ko/issues/412 ------------------------------------------------------------------ -` - // FilenameOptions is from pkg/kubectl. type FilenameOptions struct { Filenames []string Recursive bool - Watch bool } func AddFileArg(cmd *cobra.Command, fo *FilenameOptions) { @@ -46,8 +34,6 @@ func AddFileArg(cmd *cobra.Command, fo *FilenameOptions) { "Filename, directory, or URL to files to use to create the resource") cmd.Flags().BoolVarP(&fo.Recursive, "recursive", "R", fo.Recursive, "Process the directory used in -f, --filename recursively. Useful when you want to manage related manifests organized within the same directory.") - cmd.Flags().BoolVarP(&fo.Watch, "watch", "W", fo.Watch, - "Continuously monitor the transitive dependencies of the passed yaml files, and redeploy whenever anything changes. (DEPRECATED)") } // Based heavily on pkg/kubectl @@ -56,19 +42,6 @@ func EnumerateFiles(fo *FilenameOptions) chan string { go func() { // When we're done enumerating files, close the channel defer close(files) - // When we are in --watch mode, we set up watches on the filesystem locations - // that we are supplied and continuously stream files, until we are sent an - // interrupt. - var watcher *fsnotify.Watcher - if fo.Watch { - log.Print(deprecation412) - var err error - watcher, err = fsnotify.NewWatcher() - if err != nil { - log.Fatalf("Unexpected error initializing fsnotify: %v", err) - } - defer watcher.Close() - } for _, paths := range fo.Filenames { // Just pass through '-' as it is indicative of stdin. if paths == "-" { @@ -90,9 +63,6 @@ func EnumerateFiles(fo *FilenameOptions) chan string { if path != paths && !fo.Recursive { return filepath.SkipDir } - if watcher != nil { - watcher.Add(path) - } // We don't stream back directories, we just decide to skip them, or not. return nil } @@ -105,14 +75,6 @@ func EnumerateFiles(fo *FilenameOptions) chan string { default: return nil } - // We weren't passed this explicitly, so elide the watch as we - // are already watching the directory. - } else { - // We were passed this directly, and so we may not be watching the - // directory, so watch this file explicitly. - if watcher != nil { - watcher.Add(path) - } } files <- path @@ -122,23 +84,6 @@ func EnumerateFiles(fo *FilenameOptions) chan string { log.Fatalf("Error enumerating files: %v", err) } } - - // We're done watching the files we were passed and setting up watches. - // Now listen for change events from the watches we set up and resend - // files that change as if we just saw them (so they can be reprocessed). - if watcher != nil { - for { - select { - case event := <-watcher.Events: - switch filepath.Ext(event.Name) { - case ".json", ".yaml": - files <- event.Name - } - case err := <-watcher.Errors: - log.Fatalf("Error watching: %v", err) - } - } - } }() return files } diff --git a/pkg/commands/resolver.go b/pkg/commands/resolver.go index 4deb201c4a..91c09fba99 100644 --- a/pkg/commands/resolver.go +++ b/pkg/commands/resolver.go @@ -23,14 +23,12 @@ import ( "fmt" "io" "io/ioutil" - "log" "os" "path" "strings" "sync" "github.com/google/go-containerregistry/pkg/name" - "github.com/mattmoor/dep-notify/pkg/graph" "golang.org/x/sync/errgroup" "gopkg.in/yaml.v3" "k8s.io/apimachinery/pkg/labels" @@ -150,9 +148,6 @@ func makeBuilder(ctx context.Context, bo *options.BuildOptions) (*build.Caching, // - if a valid Build future exists at the time of the request, // then block on it. // - if it does not, then initiate and record a Build future. - // - When import paths are "affected" by filesystem changes during a - // Watch, then invalidate their build futures *before* we put the - // affected yaml files onto the channel // // This will benefit the following key cases: // 1. When the same import path is referenced across multiple yaml files @@ -295,38 +290,6 @@ func resolveFilesToWriter( // This tracks filename -> []importpath var sm sync.Map - var g graph.Interface - var errCh chan error - var err error - if fo.Watch { - // Start a dep-notify process that on notifications scans the - // file-to-recorded-build map and for each affected file resends - // the filename along the channel. - g, errCh, err = graph.New(func(ss graph.StringSet) { - sm.Range(func(k, v interface{}) bool { - key := k.(string) - value := v.([]string) - - for _, ip := range value { - // dep-notify doesn't understand the ko:// prefix - ip := strings.TrimPrefix(ip, build.StrictScheme) - if ss.Has(ip) { - // See the comment above about how "builder" works. - // Always use ko:// for the builder. - builder.Invalidate(build.StrictScheme + ip) - fs <- key - } - } - return true - }) - }) - if err != nil { - return fmt.Errorf("creating dep-notify graph: %w", err) - } - // Cleanup the fsnotify hooks when we're done. - defer g.Shutdown() - } - // This tracks resolution errors and ensures we cancel other builds if an // individual build fails. errs, ctx := errgroup.WithContext(ctx) @@ -376,33 +339,11 @@ func resolveFilesToWriter( if err != nil { // This error is sometimes expected during watch mode, so this // isn't fatal. Just print it and keep the watch open. - err := fmt.Errorf("error processing import paths in %q: %w", f, err) - if fo.Watch { - log.Print(err) - return nil - } - return err + return fmt.Errorf("error processing import paths in %q: %w", f, err) } // Associate with this file the collection of binary import paths. sm.Store(f, recordingBuilder.ImportPaths) ch <- b - if fo.Watch { - for _, ip := range recordingBuilder.ImportPaths { - // dep-notify doesn't understand the ko:// prefix - ip := strings.TrimPrefix(ip, build.StrictScheme) - - // Technically we never remove binary targets from the graph, - // which will increase our graph's watch load, but the - // notifications that they change will result in no affected - // yamls, and no new builds or deploys. - if err := g.Add(ip); err != nil { - // If we're in watch mode, just fail. - err := fmt.Errorf("adding importpath %q to dep graph: %w", ip, err) - errCh <- err - return err - } - } - } return nil }) @@ -418,9 +359,6 @@ func resolveFilesToWriter( // be applied. out.Write(append(b, []byte("\n---\n")...)) } - - case err := <-errCh: - return fmt.Errorf("watching dependencies: %w", err) } } diff --git a/vendor/github.com/mattmoor/dep-notify/LICENSE b/vendor/github.com/mattmoor/dep-notify/LICENSE deleted file mode 100644 index 261eeb9e9f..0000000000 --- a/vendor/github.com/mattmoor/dep-notify/LICENSE +++ /dev/null @@ -1,201 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. diff --git a/vendor/github.com/mattmoor/dep-notify/pkg/graph/doc.go b/vendor/github.com/mattmoor/dep-notify/pkg/graph/doc.go deleted file mode 100644 index f7797e81c7..0000000000 --- a/vendor/github.com/mattmoor/dep-notify/pkg/graph/doc.go +++ /dev/null @@ -1,19 +0,0 @@ -/* -Copyright 2018 Matt Moore - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -// Package graph holds the utilities for building/maintaining the dependency -// graph and notifying on changes. -package graph diff --git a/vendor/github.com/mattmoor/dep-notify/pkg/graph/interface.go b/vendor/github.com/mattmoor/dep-notify/pkg/graph/interface.go deleted file mode 100644 index db1fb66c8e..0000000000 --- a/vendor/github.com/mattmoor/dep-notify/pkg/graph/interface.go +++ /dev/null @@ -1,31 +0,0 @@ -/* -Copyright 2018 Matt Moore - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package graph - -// Interface for manipulating the dependency graph. -type Interface interface { - // This adds a given importpath to the collection of roots that we are tracking. - Add(importpath string) error - - // Shutdown stops tracking all Add'ed import paths for changes. - Shutdown() error -} - -// Observer is the type for the callback that will happen on changes. -// The callback is supplied with the transitive dependents (aka "affected -// targets") of the file that has changed. -type Observer func(affected StringSet) diff --git a/vendor/github.com/mattmoor/dep-notify/pkg/graph/manager.go b/vendor/github.com/mattmoor/dep-notify/pkg/graph/manager.go deleted file mode 100644 index e24b135a1d..0000000000 --- a/vendor/github.com/mattmoor/dep-notify/pkg/graph/manager.go +++ /dev/null @@ -1,343 +0,0 @@ -/* -Copyright 2018 Matt Moore - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package graph - -import ( - "fmt" - gb "go/build" - "path/filepath" - "sort" - "strings" - "sync" - - "github.com/fsnotify/fsnotify" -) - -// New creates a new Interface for building up dependency graphs. -// It starts in the provided working directory, and will call the provided -// Observer for any changes. -// -// The returned graph is empty, but new targets may be added via the returned -// Interface. New also returns any immediate errors, and a channel through which -// errors watching for changes in the dependencies will be returned until the -// graph is Shutdown. -// // Create our empty graph -// g, errCh, err := New(...) -// if err != nil { ... } -// // Cleanup when we're done. This closes errCh. -// defer g.Shutdown() -// // Start tracking this target. -// err := g.Add("github.com/mattmoor/warm-image/cmd/controller") -// if err != nil { ... } -// select { -// case err := <- errCh: -// // Handle errors that occur while watching the above target. -// case <-stopCh: -// // When some stop signal happens, we're done. -// } -func New(obs Observer) (Interface, chan error, error) { - return NewWithOptions(obs, DefaultOptions...) -} - -var DefaultOptions = []Option{WithCurrentDirectory, WithContext(&gb.Default), WithFSNotify, - WithFileFilter(OmitTest, OmitNonGo), WithPackageFilter(OmitVendor), WithOutsideWorkDirFilter} - -func NewWithOptions(obs Observer, opts ...Option) (Interface, chan error, error) { - m := &manager{ - packages: make(map[string]*node), - } - - for _, opt := range opts { - if err := opt(m); err != nil { - if m.watcher != nil { - m.watcher.Close() - } - return nil, nil, err - } - } - - // Start listening for events via the filesystem watcher. - go func() { - for { - event, ok := <-m.eventCh - if !ok { - // When the channel has been closed, the watcher is shutting down - // and we should return to cleanup the go routine. - return - } - - // Apply our file filters to improve the signal-to-noise. - skip := false - for _, f := range m.fileFilters { - if f(event.Name) { - skip = true - } - } - if skip { - continue - } - - // Determine what package contains this file - // and signal the change. Call our Observer - // on affected targets when we're done. - if n := m.enclosingPackage(event.Name); n != nil { - m.onChange(n, func(n *node) { - obs(m.affectedTargets(n)) - }) - } - } - }() - - return m, m.errCh, nil -} - -// notification is a callback that internal consumers of manager may use to get -// a crack at a node after it has been updated. -type notification func(*node) - -// empty implements notification and does nothing. -func empty(n *node) {} - -type watcher interface { - Add(string) error - Remove(string) error - Close() error -} - -type manager struct { - m sync.Mutex - - ctx *gb.Context - - pkgFilters []PackageFilter - fileFilters []FileFilter - - packages map[string]*node - watcher watcher - - // The working directory relative to which import paths are evaluated. - workdir string - - errCh chan error - eventCh chan fsnotify.Event -} - -// manager implements Interface -var _ Interface = (*manager)(nil) - -// manager implements fmt.Stringer -var _ fmt.Stringer = (*manager)(nil) - -// Add implements Interface -func (m *manager) Add(importpath string) error { - m.m.Lock() - defer m.m.Unlock() - - _, _, err := m.add(importpath, nil) - return err -} - -// add adds the provided importpath (if it doesn't exist) and optionally -// adds the dependent node (if provided) as a dependent of the target. -// This returns the node for the provided importpath, whether the dependency -// structure has changed, and any errors that may have occurred adding the node. -func (m *manager) add(importpath string, dependent *node) (*node, bool, error) { - // INVARIANT m.m must be held to call this. - if pkg, ok := m.packages[importpath]; ok { - return pkg, pkg.addDependent(dependent), nil - } - - // New nodes always start as a simple shell, then we set up the - // fsnotify and immediate simulate a change to prompt the package - // to load its data. A good analogy would be how the "diff" in - // a code review for new files looks like everything being added; - // so too does this first simulated change pull in the rest of the - // dependency graph. - newNode := &node{ - name: importpath, - } - m.packages[importpath] = newNode - newNode.addDependent(dependent) - - // Load the package once to determine it's filesystem location, - // and set up a watch on that location. - pkg, err := m.ctx.Import(importpath, m.workdir, gb.ImportComment) - if err != nil { - newNode.removeDependent(dependent) - delete(m.packages, importpath) - return nil, false, err - } - if err := m.watcher.Add(pkg.Dir); err != nil { - newNode.removeDependent(dependent) - delete(m.packages, importpath) - return nil, false, err - } - newNode.dir = pkg.Dir - - // This is done via go routine so that it can take over the lock. - go m.onChange(newNode, empty) - - return newNode, true, nil -} - -// affectedTargets returns the set of targets that would be affected by a -// change to the target represented by the given node. This set is comprised -// of the transitive dependents of the node, including itself. -func (m *manager) affectedTargets(n *node) StringSet { - m.m.Lock() - defer m.m.Unlock() - - return n.transitiveDependents() -} - -// enclosingPackage returns the node for the package covering the -// watched path. -func (m *manager) enclosingPackage(path string) *node { - m.m.Lock() - defer m.m.Unlock() - - dir := filepath.Dir(path) - for _, v := range m.packages { - if strings.HasSuffix(dir, v.dir) { - return v - } - } - return nil -} - -// onChange updates the graph based on the current state of the package -// represented by the given node. Once the graph has been updated, the -// notification function is called on the node. -func (m *manager) onChange(changed *node, not notification) { - m.m.Lock() - defer m.m.Unlock() - - // Load the package information and update dependencies. - pkg, err := m.ctx.Import(changed.name, m.workdir, gb.ImportComment) - if err != nil { - m.errCh <- err - return - } - - // haveDepsChanged := false - seen := make(StringSet) - for _, ip := range pkg.Imports { - if ip == "C" { - // skip cgo - continue - } - subpkg, err := m.ctx.Import(ip, m.workdir, gb.ImportComment) - if err != nil { - m.errCh <- err - return - } - - skip := false - for _, f := range m.pkgFilters { - if f(subpkg) { - skip = true - break - } - } - if skip { - continue - } - n, chg, err := m.add(subpkg.ImportPath, changed) - if err != nil { - m.errCh <- err - return - } else if chg { - // haveDepsChanged = true - } - if changed.addDependency(n) { - // haveDepsChanged = true - } - seen.Add(subpkg.ImportPath) - } - - // Remove dependencies that we no longer have. - removed := changed.removeUnseenDependencies(seen) - if len(removed) > 0 { - // haveDepsChanged = true - } - for _, dependency := range removed { - d := dependency - go m.maybeGC(d) - } - - // log.Printf("Processing %s, have deps changed: %v", changed.name, haveDepsChanged) - // Done via go routine so that we can be passed a callback that - // takes the lock on manager. - go not(changed) -} - -func (m *manager) maybeGC(n *node) { - m.m.Lock() - defer m.m.Unlock() - - if len(n.dependents) > 0 { - // It has dependents, so it should not be removed. - return - } - - // If it has zero dependents, then remove it from the packages map. - delete(m.packages, n.name) - - // Lookup the package information, so that we know what directory to stop watching. - subpkg, err := m.ctx.Import(n.name, m.workdir, gb.ImportComment) - if err != nil { - m.errCh <- err - return - } - - // Remove the watch on the package's directory - if err := m.watcher.Remove(subpkg.Dir); err != nil { - m.errCh <- err - return - } - - for _, dependency := range n.dependencies { - dependency.removeDependent(n) - - d := dependency - go m.maybeGC(d) - } -} - -// Shutdown implements Interface. -func (m *manager) Shutdown() error { - return m.watcher.Close() -} - -// String implements fmt.Stringer -func (m *manager) String() string { - m.m.Lock() - defer m.m.Unlock() - - // WTB Topo sort. - order := []string{} - for k := range m.packages { - order = append(order, k) - } - sort.Strings(order) - - parts := []string{} - for _, key := range order { - parts = append(parts, m.packages[key].String()) - } - return strings.Join(parts, "\n") -} diff --git a/vendor/github.com/mattmoor/dep-notify/pkg/graph/manager_options.go b/vendor/github.com/mattmoor/dep-notify/pkg/graph/manager_options.go deleted file mode 100644 index 6d4330dc67..0000000000 --- a/vendor/github.com/mattmoor/dep-notify/pkg/graph/manager_options.go +++ /dev/null @@ -1,119 +0,0 @@ -/* -Copyright 2018 Matt Moore - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package graph - -import ( - gb "go/build" - "os" - "path/filepath" - "strings" - - "github.com/fsnotify/fsnotify" -) - -// PackageFilter is the type of functions that determine whether to omit a -// particular Go package from the dependency graph. -type PackageFilter func(*gb.Package) bool - -// OmitVendor implements PackageFilter to exclude packages in the vendor directory. -func OmitVendor(pkg *gb.Package) bool { - return strings.Contains(pkg.ImportPath, "/vendor/") -} - -// FileFilter is the type of functions that determine whether to omit a particular -// file from triggering a package-level event. -type FileFilter func(string) bool - -// OmitNonGo implements FileFilter to exclude non-Go files from triggering package -// change notifications. -func OmitNonGo(path string) bool { - return filepath.Ext(path) != ".go" -} - -// OmitTests implements FileFilter to exclude Go test files from triggering package -// change notifications. -func OmitTest(path string) bool { - return strings.HasSuffix(path, "_test.go") -} - -// Option is used to mutate the underlying graph implementation during construction. -// Since the implementation's type is private this may only be implemented from within -// this package. -type Option func(*manager) error - -// WithWorkDir configures the graph to use the provided working directory. -func WithWorkDir(workdir string) Option { - return func(m *manager) error { - m.workdir = workdir - return nil - } -} - -// WithCurrentDirectory configures the working directory to be the current directory -func WithCurrentDirectory(m *manager) error { - wd, err := os.Getwd() - if err != nil { - return err - } - return WithWorkDir(wd)(m) -} - -// WithContext configures the graph to use the provided Go build context. -func WithContext(ctx *gb.Context) Option { - return func(m *manager) error { - m.ctx = ctx - return nil - } -} - -// WithFSNotify configures the graph to use fsnotify to implement its watcher and error channel. -func WithFSNotify(m *manager) error { - watcher, err := fsnotify.NewWatcher() - if err != nil { - return err - } - - m.watcher = watcher - m.errCh = watcher.Errors - m.eventCh = watcher.Events - return nil -} - -// WithFileFilter configures the graph implementation with the provided file filters. -func WithFileFilter(ff ...FileFilter) Option { - return func(m *manager) error { - m.fileFilters = append(m.fileFilters, ff...) - return nil - } -} - -// WithPackageFilter configures the graph implementation with the provided package filters. -func WithPackageFilter(ff ...PackageFilter) Option { - return func(m *manager) error { - m.pkgFilters = append(m.pkgFilters, ff...) - return nil - } -} - -// WithOutsideWorkDirFilter configures the graph with a package filter that omits files outside -// of the configured working directory. -func WithOutsideWorkDirFilter(m *manager) error { - m.pkgFilters = append(m.pkgFilters, func(pkg *gb.Package) bool { - return !strings.HasPrefix(pkg.Dir, m.workdir) - }) - return nil -} diff --git a/vendor/github.com/mattmoor/dep-notify/pkg/graph/node.go b/vendor/github.com/mattmoor/dep-notify/pkg/graph/node.go deleted file mode 100644 index dba8b311f5..0000000000 --- a/vendor/github.com/mattmoor/dep-notify/pkg/graph/node.go +++ /dev/null @@ -1,185 +0,0 @@ -/* -Copyright 2018 Matt Moore - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package graph - -import ( - "fmt" -) - -// node holds a single node in our dependency graph and its immediately adjacent neighbors. -type node struct { - // The canonical import path for this node. - name string - - // The directory from which we pull this import path. - dir string - - // The dependency structure - dependencies []*node - dependents []*node -} - -// node implements fmt.Stringer -var _ fmt.Stringer = (*node)(nil) - -// String implements fmt.Stringer -func (n *node) String() string { - return fmt.Sprintf(`--- -name: %s -depdnt: %v -depdncy: %v`, n.name, names(n.dependents), names(n.dependencies)) -} - -// addDependent adds the given dependent to the list of dependents for -// the given dependency. Dependent may be nil. -// This returns whether the node's neighborhood changes. -// The manager's lock must be held before calling this. -func (dependency *node) addDependent(dependent *node) bool { - if dependent == nil { - return false - } - - for _, depdnt := range dependency.dependents { - if depdnt == dependent { - // Already a dependent - return false - } - } - - // log.Printf("Adding %s <- %s", dependent.name, dependency.name) - dependency.dependents = append(dependency.dependents, dependent) - return true -} - -// addDependency adds the given dependency to the list of dependencies for -// the given dependent. Neither parameter may be nil. -// This returns whether the node's neighborhood changes. -// The manager's lock must be held before calling this. -func (dependent *node) addDependency(dependency *node) bool { - for _, depdcy := range dependent.dependencies { - if depdcy == dependency { - // Already a dependency - return false - } - } - - // log.Printf("Adding %s -> %s", dependent.name, dependency.name) - dependent.dependencies = append(dependent.dependencies, dependency) - return true -} - -// removeDependent removes the given dependent to the list of dependents for -// the given dependency. Dependent may be nil. -// This returns whether the node's neighborhood changes. -// The manager's lock must be held before calling this. -func (dependency *node) removeDependent(dependent *node) bool { - for i, depdnt := range dependency.dependents { - if depdnt == dependent { - dependency.dependents = append( - dependency.dependents[:i], dependency.dependents[i+1:]...) - return true - } - } - - return false -} - -// removeDependency removes the given dependency to the list of dependencies for -// the given dependent. Neither parameter may be nil. -// This returns whether the node's neighborhood changes. -// The manager's lock must be held before calling this. -func (dependent *node) removeDependency(dependency *node) bool { - for i, depdcy := range dependent.dependencies { - if depdcy == dependency { - dependent.dependencies = append( - dependent.dependencies[:i], dependent.dependencies[i+1:]...) - return true - } - } - return false -} - -// removeUnseenDependencies removes dependencies that aren't in the list of seen -// names. Returns the list of nodes that correspond to the named dependencies removed. -func (dependent *node) removeUnseenDependencies(seen StringSet) []*node { - keep := make([]*node, 0, len(dependent.dependencies)) - toss := make([]*node, 0, len(dependent.dependencies)) - for _, dep := range dependent.dependencies { - if seen.Has(dep.name) { - keep = append(keep, dep) - } else { - toss = append(toss, dep) - dependent.removeDependency(dep) - dep.removeDependent(dependent) - } - } - dependent.dependencies = keep - return toss -} - -// transitiveDependents collects the set of node names transitively reachable -// by following the "dependents" edges. -func (n *node) transitiveDependents() StringSet { - return n.transitiveFoo(func(n *node) []*node { - return n.dependents - }) -} - -// transitiveDependencies collects the set of node names transitively reachable -// by following the "dependencies" edges. -func (n *node) transitiveDependencies() StringSet { - return n.transitiveFoo(func(n *node) []*node { - return n.dependencies - }) -} - -// neighbors defines a function for returning the neighbors of a -// particular node. -type neighbors func(*node) []*node - -// transitiveDependents collects the set of node names transitively reachable -// by following the edges determines by the "neighbors" function. -func (n *node) transitiveFoo(nbr neighbors) StringSet { - // We will use "set" as the visited group for our DFS. - set := make(StringSet) - queue := []*node{n} - - for len(queue) != 0 { - // Pop the top element off of the queue. - top := queue[len(queue)-1] - queue = queue[:len(queue)-1] - // Check/Mark visited - if set.Has(top.name) { - continue - } - set.Add(top.name) - - // Append this node's dependents to our search. - queue = append(queue, nbr(top)...) - } - - return set -} - -// names returns the deduplicated and sorted names of the provided nodes. -func names(ns []*node) []string { - ss := make(StringSet, len(ns)) - for _, n := range ns { - ss.Add(n.name) - } - return ss.InOrder() -} diff --git a/vendor/github.com/mattmoor/dep-notify/pkg/graph/set.go b/vendor/github.com/mattmoor/dep-notify/pkg/graph/set.go deleted file mode 100644 index 28a4da311a..0000000000 --- a/vendor/github.com/mattmoor/dep-notify/pkg/graph/set.go +++ /dev/null @@ -1,51 +0,0 @@ -/* -Copyright 2018 Matt Moore - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package graph - -import ( - "sort" -) - -// StringSet is a simple abstraction for holding a collection of deduplicated strings. -type StringSet map[string]struct{} - -// Add inserts a provided key into our set. -func (ss *StringSet) Add(key string) { - (*ss)[key] = struct{}{} -} - -// Remove deletes a provided key from our set. -func (ss *StringSet) Remove(key string) { - delete(*ss, key) -} - -// Has returns whether the set contains the provided key. -func (ss *StringSet) Has(key string) bool { - _, ok := (*ss)[key] - return ok -} - -// InOrder returns the keys of the set in the ordering determined by sort.Strings. -func (ss StringSet) InOrder() []string { - keys := make([]string, 0, len(ss)) - for k := range ss { - keys = append(keys, k) - } - sort.Strings(keys) - - return keys -} diff --git a/vendor/modules.txt b/vendor/modules.txt index 6ebe07bd1a..b65237707a 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -175,7 +175,6 @@ github.com/evanphx/json-patch/v5 # github.com/form3tech-oss/jwt-go v3.2.5+incompatible github.com/form3tech-oss/jwt-go # github.com/fsnotify/fsnotify v1.5.1 -## explicit github.com/fsnotify/fsnotify # github.com/go-logr/logr v1.2.0 github.com/go-logr/logr @@ -259,9 +258,6 @@ github.com/klauspost/compress/zstd github.com/klauspost/compress/zstd/internal/xxhash # github.com/magiconair/properties v1.8.5 github.com/magiconair/properties -# github.com/mattmoor/dep-notify v0.0.0-20190205035814-a45dec370a17 -## explicit -github.com/mattmoor/dep-notify/pkg/graph # github.com/mattn/go-isatty v0.0.14 github.com/mattn/go-isatty # github.com/mitchellh/go-homedir v1.1.0