summaryrefslogtreecommitdiffstats
path: root/lib/puppet/util/diff.rb
blob: 0e5deab82b5c2c032c740b0bed46b28b64d11133 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
# 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