Class: PatternPatch::Patch
- Inherits:
-
Object
- Object
- PatternPatch::Patch
- Defined in:
- lib/pattern_patch/patch.rb
Overview
The PatternPatch::Patch class defines a patch as an operation that may be applied to any file. Often the operation may also be reverted.
Instance Attribute Summary collapse
-
#global ⇒ true, false
Setting this to true will apply the patch to all matches in the file.
-
#mode ⇒ Symbol
Symbol specifying the patch mode: :append (default), :prepend or :replace.
-
#regexp ⇒ Regexp
Regexp defining one or more matching regions in a file.
-
#text ⇒ String
String with text to use in the patch operation.
-
#text_file ⇒ String
Path to a text file used to populate the text attribute.
Class Method Summary collapse
-
.from_yaml(path) ⇒ Patch
Load a Patch from a YAML file.
Instance Method Summary collapse
-
#apply(files, options = {}) ⇒ Object
Applies the patch to one or more files.
-
#initialize(options = {}) ⇒ Patch
constructor
Construct a new Patch from the options.
-
#inspect ⇒ String
Returns a diagnostic string representation.
-
#revert(files, options = {}) ⇒ Object
Reverse the effect of a patch on one or more files.
-
#to_s ⇒ String
Returns a string representation.
Constructor Details
#initialize(options = {}) ⇒ Patch
Construct a new Patch from the options. The following fields are mapped to the corresponding attributes: :regexp, :text, :text_file, :mode, :global. Raises ArgumentError if both :text and :text_file are specified. All values may be modified between construction and calling #apply or #revert.
97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 |
# File 'lib/pattern_patch/patch.rb', line 97 def initialize( = {}) raise ArgumentError, "text and text_file are mutually exclusive" if [:text] && [:text_file] @regexp = [:regexp] @text_file = [:text_file] if @text_file @text = File.read @text_file else @text = [:text] end @mode = [:mode] || :append @global = [:global].nil? ? false : [:global] end |
Instance Attribute Details
#global ⇒ true, false
Setting this to true will apply the patch to all matches in the file. By default (when false), the patch is only applied to the first match.
29 30 31 |
# File 'lib/pattern_patch/patch.rb', line 29 def global @global end |
#mode ⇒ Symbol
Symbol specifying the patch mode: :append (default), :prepend or :replace
23 24 25 |
# File 'lib/pattern_patch/patch.rb', line 23 def mode @mode end |
#regexp ⇒ Regexp
Regexp defining one or more matching regions in a file.
13 14 15 |
# File 'lib/pattern_patch/patch.rb', line 13 def regexp @regexp end |
#text ⇒ String
String with text to use in the patch operation. May contain ERB.
18 19 20 |
# File 'lib/pattern_patch/patch.rb', line 18 def text @text end |
#text_file ⇒ String
Path to a text file used to populate the text attribute. Setting this after construction modifies the text attribute.
35 36 37 |
# File 'lib/pattern_patch/patch.rb', line 35 def text_file @text_file end |
Class Method Details
.from_yaml(path) ⇒ Patch
Load a Patch from a YAML file. The following special processing applies: The mode field is converted to a symbol. The text_file field will be interpreted relative to the YAML file. A Regexp will be constructed from the regexp field using Regexp.new unless it is a String containing a Regexp literal using slash delimiters, e.g. /x/i. This format may be used to specify a Regexp with modifiers in YAML. Raises if the file cannot be loaded.
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 75 76 77 78 79 80 81 |
# File 'lib/pattern_patch/patch.rb', line 48 def from_yaml(path) hash = YAML.load_file(path).symbolize_keys # Adjust string fields from YAML if hash[:regexp].kind_of? String regexp_string = hash[:regexp] if (matches = %r{^/(.+)/([imx]*)$}.match regexp_string) flags = 0 if matches[2] =~ /i/ flags |= Regexp::IGNORECASE end if matches[2] =~ /x/ flags |= Regexp::EXTENDED end if matches[2] =~ /m/ flags |= Regexp::MULTILINE end hash[:regexp] = Regexp.new matches[1], flags else hash[:regexp] = /#{regexp_string}/ end end if hash[:mode].kind_of? String hash[:mode] = hash[:mode].to_sym end if hash[:text_file] hash[:text_file] = File. hash[:text_file], File.dirname(path) end new hash end |
Instance Method Details
#apply(files, options = {}) ⇒ Object
Applies the patch to one or more files. ERB is processed in the text field, whether it comes from a text_file or not. Pass a Binding to ERB using the :binding option or a Hash of locals. Pass the :offset option to specify a starting offset, in characters, from the beginning of the file.
131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 |
# File 'lib/pattern_patch/patch.rb', line 131 def apply(files, = {}) offset = [:offset] || 0 files = [files] if files.kind_of? String safe_level = [:safe_level] || PatternPatch.safe_level trim_mode = [:trim_mode] || PatternPatch.trim_mode locals = [:locals] raise ArgumentError, ':binding is incompatible with :locals' if [:binding] && locals renderer = Renderer.new text, safe_level, trim_mode if locals.nil? patch_text = renderer.render [:binding] else patch_text = renderer.render locals end files.each do |path| modified = Utilities.apply_patch File.read(path), regexp, patch_text, global, mode, offset File.write path, modified end end |
#inspect ⇒ String
Returns a diagnostic string representation
204 205 206 |
# File 'lib/pattern_patch/patch.rb', line 204 def inspect "#<PatternPatch::Patch regexp=#{regexp.inspect} text=#{text.inspect} text_file=#{text_file.inspect} mode=#{mode.inspect} global=#{global.inspect}>" end |
#revert(files, options = {}) ⇒ Object
Reverse the effect of a patch on one or more files. ERB is processed in the text field, whether it comes from a text_file or not. Pass a Binding to ERB using the :binding option or a Hash of locals. Pass the :offset option to specify a starting offset, in characters, from the beginning of the file.
173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 |
# File 'lib/pattern_patch/patch.rb', line 173 def revert(files, = {}) offset = [:offset] || 0 files = [files] if files.kind_of? String safe_level = [:safe_level] || PatternPatch.safe_level trim_mode = [:trim_mode] || PatternPatch.trim_mode locals = [:locals] raise ArgumentError, ':binding is incompatible with :locals' if [:binding] && locals renderer = Renderer.new text, safe_level, trim_mode if locals.nil? patch_text = renderer.render [:binding] else patch_text = renderer.render locals end files.each do |path| modified = Utilities.revert_patch File.read(path), regexp, patch_text, global, mode, offset File.write path, modified end end |
#to_s ⇒ String
Returns a string representation
210 211 212 |
# File 'lib/pattern_patch/patch.rb', line 210 def to_s inspect end |