Class: Rubyfocus::Patch
- Inherits:
-
Object
- Object
- Rubyfocus::Patch
- Defined in:
- lib/rubyfocus/patch.rb
Overview
The patch class represents a text-file patch, storing update, delete, and creation operations. It should also be able to apply itself to an existing document.
Instance Attribute Summary collapse
-
#create ⇒ Object
Operations to be performed on a document.
-
#delete ⇒ Object
Operations to be performed on a document.
-
#fetcher ⇒ Object
The fetcher this patch belongs to.
-
#file ⇒ Object
The file the patch loads from.
-
#from_ids ⇒ Object
These record the transformation in terms of patch ID values.
-
#time ⇒ Object
The time the file was submitted.
-
#to_id ⇒ Object
These record the transformation in terms of patch ID values.
-
#update ⇒ Object
Update, delete and create methods.
Class Method Summary collapse
-
.from_string(fetcher, str) ⇒ Object
Load from a string.
Instance Method Summary collapse
-
#apply_to(document) ⇒ Object
Apply this patch to a document.
-
#apply_to!(document) ⇒ Object
Apply this patch to a document.
-
#can_patch?(document) ⇒ Boolean
Can we apply this patch to a given document?.
-
#initialize(fetcher = nil, file = nil) ⇒ Patch
constructor
By default we initialize patches from a file.
-
#load_data(str = nil) ⇒ Object
Loads data from the file.
-
#to_s ⇒ Object
String representation.
Constructor Details
#initialize(fetcher = nil, file = nil) ⇒ Patch
By default we initialize patches from a file. To initialize from a string, use the .from_string method. This class will lazily load data from the file proper
21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 |
# File 'lib/rubyfocus/patch.rb', line 21 def initialize(fetcher=nil, file=nil) @fetcher = fetcher @file = file @update = [] @create = [] @delete = [] if file if File.basename(file) =~ /^(\d+)=(.*)\./ time_string = $1 self.time = if (time_string == "00000000000000") Time.at(0) else Time.parse(time_string) end ids = $2.split("+") self.to_id = ids.pop self.from_ids = ids else raise ArgumentError, "Constructed patch from a malformed patch file: #{file}." end end end |
Instance Attribute Details
#create ⇒ Object
Operations to be performed on a document
8 9 10 |
# File 'lib/rubyfocus/patch.rb', line 8 def create @create end |
#delete ⇒ Object
Operations to be performed on a document
8 9 10 |
# File 'lib/rubyfocus/patch.rb', line 8 def delete @delete end |
#fetcher ⇒ Object
The fetcher this patch belongs to. We mainly use this to work out how to fetch content for the patch proper
5 6 7 |
# File 'lib/rubyfocus/patch.rb', line 5 def fetcher @fetcher end |
#file ⇒ Object
The file the patch loads from
11 12 13 |
# File 'lib/rubyfocus/patch.rb', line 11 def file @file end |
#from_ids ⇒ Object
These record the transformation in terms of patch ID values.
14 15 16 |
# File 'lib/rubyfocus/patch.rb', line 14 def from_ids @from_ids end |
#time ⇒ Object
The time the file was submitted
17 18 19 |
# File 'lib/rubyfocus/patch.rb', line 17 def time @time end |
#to_id ⇒ Object
These record the transformation in terms of patch ID values.
14 15 16 |
# File 'lib/rubyfocus/patch.rb', line 14 def to_id @to_id end |
#update ⇒ Object
Update, delete and create methods
8 9 10 |
# File 'lib/rubyfocus/patch.rb', line 8 def update @update end |
Class Method Details
.from_string(fetcher, str) ⇒ Object
Load from a string.
47 48 49 50 51 |
# File 'lib/rubyfocus/patch.rb', line 47 def self.from_string(fetcher, str) n = new(fetcher) n.load_data(str) n end |
Instance Method Details
#apply_to(document) ⇒ Object
Apply this patch to a document. Check to make sure ids match
87 88 89 90 91 92 93 |
# File 'lib/rubyfocus/patch.rb', line 87 def apply_to(document) if can_patch?(document) apply_to!(document) else raise RuntimeError, "Patch ID mismatch (patch from_ids: [#{self.from_ids.join(", ")}], document.patch_id: #{document.patch_id}" end end |
#apply_to!(document) ⇒ Object
Apply this patch to a document. Who needs error checking amirite?
96 97 98 99 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 |
# File 'lib/rubyfocus/patch.rb', line 96 def apply_to!(document) # Updates modify elements self.update.each do |node| elem = document[node["id"]] # Tasks can become projects and v.v.: check this. if [Rubyfocus::Task, Rubyfocus::Project].include?(elem.class) should_be_project = (node.at_xpath("xmlns:project") != nil) if (elem.class == Rubyfocus::Project) && !should_be_project elem.document = nil # Remove this from current document elem = elem.to_task # Convert to task elem.document = document # Insert again! elsif (elem.class == Rubyfocus::Task) && should_be_project elem.document = nil # Remove this from current document elem = elem.to_project # Convert to task elem.document = document # Insert again! end end elem.apply_xml(node) if elem end # Deletes remove elements self.delete.each do |node| document.remove_element(node["id"]) end # Creates make new elements self.create.each do |node| if Rubyfocus::Parser.parse(document, node).nil? raise RuntimeError, "Encountered unparsable XML during patch reading: #{node}." end end # Modify current patch_id to show new value document.patch_id = self.to_id end |
#can_patch?(document) ⇒ Boolean
Can we apply this patch to a given document?
82 83 84 |
# File 'lib/rubyfocus/patch.rb', line 82 def can_patch?(document) self.from_ids.include?(document.patch_id) end |
#load_data(str = nil) ⇒ Object
Loads data from the file. Optional argument str if you want to supply your own data, otherwise will load file data
55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 |
# File 'lib/rubyfocus/patch.rb', line 55 def load_data(str=nil) return if @data_loaded @data_loaded = true str ||= fetcher.patch(self.file) doc = Nokogiri::XML(str) doc.root.children.select{ |n| !n.text?}.each do |child| case child["op"] when "update" @update << child when "delete" @delete << child when "reference" # Ignore! when nil @create << child else raise RuntimeError, "Rubyfocus::Patch encountered unknown operation type #{child["op"]}." end end end |
#to_s ⇒ Object
String representation
135 136 137 138 139 140 141 |
# File 'lib/rubyfocus/patch.rb', line 135 def to_s if from_ids.size == 1 "(#{from_ids.first} -> #{to_id})" else "([#{from_ids.join(", ")}] -> #{to_id})" end end |