summaryrefslogtreecommitdiffstats
path: root/lib/puppet/util
diff options
context:
space:
mode:
authorLuke Kanies <luke@madstop.com>2007-08-27 14:26:49 -0500
committerLuke Kanies <luke@madstop.com>2007-08-27 14:26:49 -0500
commit1de5ae0da0d336f1b96ceaac5aca1dfed4169460 (patch)
tree9a302b3e786ba320c6d668bc93387044027e6092 /lib/puppet/util
parent11081ce8864dca2bc92d8c9f825c3fe7f96333f4 (diff)
downloadpuppet-1de5ae0da0d336f1b96ceaac5aca1dfed4169460.tar.gz
puppet-1de5ae0da0d336f1b96ceaac5aca1dfed4169460.tar.xz
puppet-1de5ae0da0d336f1b96ceaac5aca1dfed4169460.zip
Adding support for providing a diff when files are being changed. Currently uses a local diff binary, but could easily be changed to use the ruby diff/lcs library. Modified puppet and puppetd to automatically show file diffs when in noop mode, but can otherwise be enabled using --show_diff. This only works when running interactively, because the diffs are printed on stdout.
Diffstat (limited to 'lib/puppet/util')
-rw-r--r--lib/puppet/util/diff.rb71
1 files changed, 71 insertions, 0 deletions
diff --git a/lib/puppet/util/diff.rb b/lib/puppet/util/diff.rb
new file mode 100644
index 000000000..e6ff57108
--- /dev/null
+++ b/lib/puppet/util/diff.rb
@@ -0,0 +1,71 @@
+# Provide a diff between two strings.
+module Puppet::Util::Diff
+ include Puppet::Util
+ require 'tempfile'
+
+ def diff(old, new)
+ command = [Puppet[:diff]]
+ if args = Puppet[:diff_args] and args != ""
+ command << args
+ end
+ command << old << new
+ execute(command, :failonfail => false)
+ end
+
+ module_function :diff
+
+ # return diff string of two input strings
+ # format defaults to unified
+ # context defaults to 3 lines
+ def lcs_diff(data_old, data_new, format=:unified, context_lines=3)
+ unless Puppet.features.diff?
+ Puppet.warning "Cannot provide diff without the diff/lcs Ruby library"
+ return ""
+ end
+ data_old = data_old.split(/\n/).map! { |e| e.chomp }
+ data_new = data_new.split(/\n/).map! { |e| e.chomp }
+
+ output = ""
+
+ diffs = Diff::LCS.diff(data_old, data_new)
+ return output if diffs.empty?
+
+ oldhunk = hunk = nil
+ file_length_difference = 0
+
+ diffs.each do |piece|
+ begin
+ hunk = Diff::LCS::Hunk.new(data_old, data_new, piece,
+ context_lines,
+ file_length_difference)
+ file_length_difference = hunk.file_length_difference
+ next unless oldhunk
+ # Hunks may overlap, which is why we need to be careful when our
+ # diff includes lines of context. Otherwise, we might print
+ # redundant lines.
+ if (context_lines > 0) and hunk.overlaps?(oldhunk)
+ hunk.unshift(oldhunk)
+ else
+ output << oldhunk.diff(format)
+ end
+ ensure
+ oldhunk = hunk
+ output << "\n"
+ end
+ end
+
+ # Handle the last remaining hunk
+ output << oldhunk.diff(format) << "\n"
+ end
+
+ def string_file_diff(path, string)
+ require 'tempfile'
+ tempfile = Tempfile.new("puppet-diffing")
+ tempfile.open
+ tempfile.print string
+ tempfile.close
+ print diff(path, tempfile.path)
+ tempfile.delete
+ end
+end
+