Class: Hobix::Util::Patcher

Inherits:
Object
  • Object
show all
Defined in:
lib/hobix/util/patcher.rb

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(*paths) ⇒ Patcher

Initialize the Patcher with a list of paths to patches which must be applied in order.

patch_set = Hobix::Util::Patcher.new('1.patch', '2.patch')
patch_set.apply('/dir/to/unaltered/code')


37
38
39
40
41
42
43
44
# File 'lib/hobix/util/patcher.rb', line 37

def initialize( *paths )
    @patches = {}
    paths.each do |path|
        YAML::load_file( path ).each do |k, v|
            ( @patches[k] ||= [] ) << v
        end
    end
end

Class Method Details

.[](*paths) ⇒ Object

Alias for Patcher.new.

patch_set = Hobix::Util::Patcher['1.patch', '2.patch']
patch_set.apply('/dir/to/unaltered/code')


51
52
53
# File 'lib/hobix/util/patcher.rb', line 51

def Patcher.[]( *paths )
    Patcher.new( *paths )
end

Instance Method Details

#apply(path) ⇒ Object

Apply the patches loaded into this class against a path containing unaltered files.

patch_set = Hobix::Util::Patcher['1.patch', '2.patch']
patch_set.apply('/dir/to/unaltered/code')


61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
# File 'lib/hobix/util/patcher.rb', line 61

def apply( path )
    @patches.map do |fname, patchset|
        fname = File.join( path, fname ) # .gsub( /^.*?[\/\\]/, '' ) )
        ftarg = File.read( fname ) rescue ''
        ftarg = YAML::load( ftarg ) if fname =~ /\.yaml$/
        
        patchset.each_with_index do |(ptype, patch), patchno|
            # apply the changes
            puts "*** Applying patch ##{ patchno + 1 } for #{ fname } (#{ ptype })."
            ftarg = method( ptype.gsub( /\W/, '_' ) ).call( ftarg, patch )
        end

        [fname, ftarg]
    end.
    each do |fname, ftext|
        # save the files
        if ftext == :remove
            FileUtils.rm_rf fname
        else
            FileUtils.makedirs( File.dirname( fname ) )
            ftext = ftext.to_yaml if fname =~ /\.yaml$/
            File.open( fname, 'w+' ) { |f| f << ftext }
        end
    end
end

#file_create(target, text) ⇒ Object



91
92
93
# File 'lib/hobix/util/patcher.rb', line 91

def file_create( target, text )
    text.to_s
end

#file_ensure(target, text) ⇒ Object



95
96
97
98
# File 'lib/hobix/util/patcher.rb', line 95

def file_ensure( target, text )
    target << text unless target.include? text
    target
end

#file_remove(target, text) ⇒ Object



87
88
89
# File 'lib/hobix/util/patcher.rb', line 87

def file_remove( target, text )
    :remove
end

#yaml_merge(obj, merge) ⇒ Object



100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
# File 'lib/hobix/util/patcher.rb', line 100

def yaml_merge( obj, merge )
    obj = obj.value if obj.respond_to? :value
    if obj.class != merge.class and merge.class != Hash
        raise PatchError, "*** Patch failure since #{ obj.class } != #{ merge.class }."
    end

    case obj
    when Hash
        merge.each do |k, v|
            if obj.has_key? k
                yaml_merge obj[k], v
            else
                obj[k] = v
            end
        end
    when Array
        at = nil
        merge.each do |v|
            vat = obj.index( v )
            if vat
                at = vat if vat > at.to_i
            else
                if at
                    obj[at+=1,0] = v
                else
                    obj << v
                end
            end
        end
    when String
        obj.replace merge
    else
        merge.each do |k, v|
            ivar = obj.instance_variable_get "@#{k}"
            if ivar
                yaml_merge ivar, v
            else
                obj.instance_variable_set "@#{k}", v
            end
        end
    end

    obj
end