summaryrefslogtreecommitdiff
path: root/knife/lib/chef/knife/edit.rb
diff options
context:
space:
mode:
authorChef Expeditor <chef-ci@chef.io>2021-03-11 17:45:48 +0000
committerMarc A. Paradise <marc.paradise@gmail.com>2021-03-31 13:52:49 -0400
commit01c6a9e1753bd4b2166efe747151ba8700ebc0f5 (patch)
tree55f16085d89859139211bf6d2b8fd2dbcf4633b0 /knife/lib/chef/knife/edit.rb
parent497dd4af19ea7dff9a72d704a1de8e9be36b2996 (diff)
downloadchef-01c6a9e1753bd4b2166efe747151ba8700ebc0f5.tar.gz
Move knife to its own gem
This moves knife into /knife, in the same way that chef-utils and chef-config are separated. NOTES: == File History == If you see this message as the first message in the history of an knife file, you can see the complete history by using 'git log --follow', 'git config log.follow true' to make it the default behavior in this repository, or 'git config --globa log.follow true' to make it the global default. == API Changes == At the API level, there is one breaking change: CookbookSiteStreamingUploader has been moved out of chef and into knife/core. There were a combination of reasons we chose this path: - CookbookSiteStreamingUploader (CSSU) is only used within Knife. - CookbookSiteStreamingUploader (CSSU) references the command Chef::Knife::CookbookMetadata in order to generate a metadata file for the cookbook to upload - Chef::Knife::CookbookMetadata is no longer available to Chef:: because Knife has been moved to its own gem. Knife gem depends on the Chef gem, so Chef can't depend on something in Knife. A search for usage in related projects (berks, chef-cli) and the Internet at large shows that there are no known external consumers of CSSU. For now, we'll move this class into Knife::Core, as it's going to be faster than splitting off the metadata generation and time is a concern. If we find that we need the metadata generation in chef/ proper, we should evaluate decoupling that functionality from Knife::CookbookMetadata and exposing it via something like `Chef::Cookbook::Metadata#from_cookbook_files` == spec changes == The specs are kept in their existing locations, though we have separated out a `knife_spec_helper` so that we can ensure knife is not directly accessing chef requires; and chef is relying on knife's at all. We also now clear gem paths with each test, to force gem state to reset. This works around a problem where a combination of tests is corrupting the internal Gem state, causing failures in rubygems_spec. See branch `mp/broken-gems` for many more details around findings so far. Signed-off-by: Marc A. Paradise <marc.paradise@gmail.com>
Diffstat (limited to 'knife/lib/chef/knife/edit.rb')
-rw-r--r--knife/lib/chef/knife/edit.rb88
1 files changed, 88 insertions, 0 deletions
diff --git a/knife/lib/chef/knife/edit.rb b/knife/lib/chef/knife/edit.rb
new file mode 100644
index 0000000000..45702d168b
--- /dev/null
+++ b/knife/lib/chef/knife/edit.rb
@@ -0,0 +1,88 @@
+#
+# License:: Apache License, Version 2.0
+#
+# 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.
+#
+
+require_relative "../chef_fs/knife"
+
+class Chef
+ class Knife
+ class Edit < Chef::ChefFS::Knife
+ banner "knife edit [PATTERN1 ... PATTERNn]"
+
+ category "path-based"
+
+ deps do
+ require "chef/chef_fs/file_system" unless defined?(Chef::ChefFS::FileSystem)
+ require "chef/chef_fs/file_system/exceptions" unless defined?(Chef::ChefFS::FileSystem::Exceptions)
+ end
+
+ option :local,
+ long: "--local",
+ boolean: true,
+ description: "Show local files instead of remote."
+
+ def run
+ # Get the matches (recursively)
+ error = false
+ pattern_args.each do |pattern|
+ Chef::ChefFS::FileSystem.list(config[:local] ? local_fs : chef_fs, pattern).each do |result|
+ if result.dir?
+ ui.error "#{format_path(result)}: is a directory" if pattern.exact_path
+ error = true
+ else
+ begin
+ new_value = edit_text(result.read, File.extname(result.name))
+ if new_value
+ result.write(new_value)
+ output "Updated #{format_path(result)}"
+ else
+ output "#{format_path(result)} unchanged"
+ end
+ rescue Chef::ChefFS::FileSystem::OperationNotAllowedError => e
+ ui.error "#{format_path(e.entry)}: #{e.reason}."
+ error = true
+ rescue Chef::ChefFS::FileSystem::NotFoundError => e
+ ui.error "#{format_path(e.entry)}: No such file or directory"
+ error = true
+ end
+ end
+ end
+ end
+ if error
+ exit 1
+ end
+ end
+
+ def edit_text(text, extension)
+ unless config[:disable_editing]
+ Tempfile.open([ "knife-edit-", extension ]) do |file|
+ # Write the text to a temporary file
+ file.write(text)
+ file.close
+
+ # Let the user edit the temporary file
+ unless system("#{config[:editor]} #{file.path}")
+ raise "Please set EDITOR environment variable. See https://docs.chef.io/knife_setup/ for details."
+ end
+
+ result_text = IO.read(file.path)
+
+ return result_text if result_text != text
+ end
+ end
+ end
+ end
+ end
+end