revtree 0.1.3 → 0.1.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +24 -15
- data/lib/revtree.rb +121 -81
- metadata +62 -2
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA256:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: 38695028f770cc56588f3101b95f6dfdde959306928750c41ee7b04694b25f93
         | 
| 4 | 
            +
              data.tar.gz: 4b240bf3d9601e5cbb73592ccaa4b95de20a1164ce8a0506642c394a1d5959c0
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: 1b2db6f9de82d4b0b5adb8ea1fb0f562eec56e5242c97fddefde0240d6f0cbab0ade2f6baff811d579a139c85865d462ff27f94aed24de834d88975cb98277fd
         | 
| 7 | 
            +
              data.tar.gz: 71c0386cd9c5d64e1881c47e6ab7ac83c5e5e03ceba87ff16c4fc63be1ef07795ac5cc8629ace349cc9315db8c3e955f21a21f488dfce61c0b0e6dbf607b8461
         | 
    
        data/README.md
    CHANGED
    
    | @@ -1,5 +1,10 @@ | |
| 1 1 | 
             
            # RevTree
         | 
| 2 2 |  | 
| 3 | 
            +
            [](https://github.com/juliankahlert/revtree)
         | 
| 4 | 
            +
            [](https://rubygems.org/gems/revtree)
         | 
| 5 | 
            +
            [](https://app.codacy.com/gh/juliankahlert/revtree/dashboard?utm_source=gh&utm_medium=referral&utm_content=&utm_campaign=Badge_grade)
         | 
| 6 | 
            +
            [](https://app.codacy.com/gh/juliankahlert/revtree/dashboard?utm_source=gh&utm_medium=referral&utm_content=&utm_campaign=Badge_coverage)
         | 
| 7 | 
            +
             | 
| 3 8 | 
             
            ## Introduction
         | 
| 4 9 |  | 
| 5 10 | 
             
            `RevTree` is a Ruby library for tracking and comparing directory structures.
         | 
| @@ -20,16 +25,19 @@ It also provides methods to print and serialize the tree structure, as well as t | |
| 20 25 | 
             
            ## Install
         | 
| 21 26 |  | 
| 22 27 | 
             
            The supported tools are:
         | 
| 28 | 
            +
             | 
| 23 29 | 
             
            - gitpack
         | 
| 24 30 | 
             
            - make
         | 
| 25 31 | 
             
            - gem
         | 
| 26 32 |  | 
| 27 33 | 
             
            ### gitpack
         | 
| 34 | 
            +
             | 
| 28 35 | 
             
            ```sh
         | 
| 29 36 | 
             
            gitpack add juliankahlert/revtree
         | 
| 30 37 | 
             
            ```
         | 
| 31 38 |  | 
| 32 39 | 
             
            ### make
         | 
| 40 | 
            +
             | 
| 33 41 | 
             
            ```sh
         | 
| 34 42 | 
             
            git clone https://github.com/juliankahlert/revtree.git
         | 
| 35 43 | 
             
            cd revtree
         | 
| @@ -37,11 +45,12 @@ sudo make install | |
| 37 45 | 
             
            ```
         | 
| 38 46 |  | 
| 39 47 | 
             
            ### gem (local)
         | 
| 48 | 
            +
             | 
| 40 49 | 
             
            ```sh
         | 
| 41 50 | 
             
            git clone https://github.com/juliankahlert/revtree.git
         | 
| 42 51 | 
             
            cd revtree
         | 
| 43 52 | 
             
            gem build revtree.gemspec
         | 
| 44 | 
            -
            sudo gem install --local revtree-0.1. | 
| 53 | 
            +
            sudo gem install --local revtree-0.1.5.gem
         | 
| 45 54 | 
             
            ```
         | 
| 46 55 |  | 
| 47 56 | 
             
            ## API Documentation
         | 
| @@ -49,52 +58,52 @@ sudo gem install --local revtree-0.1.3.gem | |
| 49 58 | 
             
            ### `RevTree.new(path, whitelist = nil)`
         | 
| 50 59 |  | 
| 51 60 | 
             
            - **Parameters**:
         | 
| 52 | 
            -
              - `path` (String): The path to the file or directory.
         | 
| 53 | 
            -
              - `whitelist` (Array<String | 
| 61 | 
            +
              - `path` (`String`): The path to the file or directory.
         | 
| 62 | 
            +
              - `whitelist` (`Array<String>`): List of patterns to include in the tree.
         | 
| 54 63 |  | 
| 55 64 | 
             
            ### `#print_tree(indent = 0)`
         | 
| 56 65 |  | 
| 57 66 | 
             
            - **Parameters**:
         | 
| 58 | 
            -
              - `indent` (Integer): Number of spaces to indent each level of the tree.
         | 
| 67 | 
            +
              - `indent` (`Integer`): Number of spaces to indent each level of the tree.
         | 
| 59 68 |  | 
| 60 69 | 
             
            ### `#to_h`
         | 
| 61 70 |  | 
| 62 | 
            -
            - **Returns**: A Hash representation of the RevTree object.
         | 
| 71 | 
            +
            - **Returns**: A `Hash` representation of the `RevTree` object.
         | 
| 63 72 |  | 
| 64 73 | 
             
            ### `#to_json`
         | 
| 65 74 |  | 
| 66 | 
            -
            - **Returns**: A JSON representation of the RevTree object.
         | 
| 75 | 
            +
            - **Returns**: A `JSON` representation of the `RevTree` object.
         | 
| 67 76 |  | 
| 68 77 | 
             
            ### `#for_each(status_whitelist, &block)`
         | 
| 69 78 |  | 
| 70 79 | 
             
            - **Parameters**:
         | 
| 71 | 
            -
              - `status_whitelist` (Array<Symbol | 
| 72 | 
            -
              - `&block` (Proc): A block to execute for each file matching the given statuses.
         | 
| 80 | 
            +
              - `status_whitelist` (`Array<Symbol>`): List of statuses to include (e.g., `[:added, :removed]`).
         | 
| 81 | 
            +
              - `&block` (`Proc`): A block to execute for each file matching the given statuses.
         | 
| 73 82 | 
             
            - **Behavior**: Iterates over files in the tree, executing the block for each file whose status matches one of the statuses in the whitelist.
         | 
| 74 83 |  | 
| 75 84 | 
             
            ### `#watch(status_whitelist = [:modified, :added, :removed], &block)`
         | 
| 76 85 |  | 
| 77 86 | 
             
            - **Parameters**:
         | 
| 78 | 
            -
              - `status_whitelist` (Array<Symbol | 
| 79 | 
            -
              - `&block` (Proc): A block to execute when a file matching the given statuses is changed.
         | 
| 87 | 
            +
              - `status_whitelist` (`Array<Symbol>`): List of statuses to watch (e.g., `[:added, :removed]`).
         | 
| 88 | 
            +
              - `&block` (`Proc`): A block to execute when a file matching the given statuses is changed.
         | 
| 80 89 |  | 
| 81 90 | 
             
            ### `#with_interval(interval)`
         | 
| 82 91 |  | 
| 83 92 | 
             
            - **Parameters**:
         | 
| 84 | 
            -
              - `interval` (Integer): Interval (in seconds) between checks for changes.
         | 
| 93 | 
            +
              - `interval` (`Integer`): Interval (in seconds) between checks for changes.
         | 
| 85 94 | 
             
            - **Returns**: The `RevTree` instance, enabling method chaining.
         | 
| 86 95 |  | 
| 87 96 | 
             
            ### `RevTree.from_h(h)`
         | 
| 88 97 |  | 
| 89 98 | 
             
            - **Parameters**:
         | 
| 90 | 
            -
              - `h` (Hash): A  | 
| 91 | 
            -
            - **Returns**: A RevTree object.
         | 
| 99 | 
            +
              - `h` (`Hash`): A `Hash` representation of a `RevTree` object.
         | 
| 100 | 
            +
            - **Returns**: A `RevTree` object.
         | 
| 92 101 |  | 
| 93 102 | 
             
            ### `RevTree.from_json(json_str)`
         | 
| 94 103 |  | 
| 95 104 | 
             
            - **Parameters**:
         | 
| 96 | 
            -
              - `json_str` (String): A JSON string representing a RevTree object.
         | 
| 97 | 
            -
            - **Returns**: A RevTree object.
         | 
| 105 | 
            +
              - `json_str` (`String`): A `JSON` string representing a `RevTree` object.
         | 
| 106 | 
            +
            - **Returns**: A `RevTree` object.
         | 
| 98 107 |  | 
| 99 108 | 
             
            ## Example Usage
         | 
| 100 109 |  | 
    
        data/lib/revtree.rb
    CHANGED
    
    | @@ -51,11 +51,15 @@ class RevTree | |
| 51 51 | 
             
              #
         | 
| 52 52 | 
             
              # @param path [String, Pathname] the path to the file or directory
         | 
| 53 53 | 
             
              # @param whitelist [Array<String>, nil] a list of file patterns to include (optional)
         | 
| 54 | 
            -
              def initialize(path, whitelist =  | 
| 54 | 
            +
              def initialize(path, whitelist = ['*'])
         | 
| 55 55 | 
             
                @path = Pathname.new(path)
         | 
| 56 56 | 
             
                @name = @path.basename.to_s
         | 
| 57 | 
            -
                @whitelist = whitelist | 
| 57 | 
            +
                @whitelist = whitelist
         | 
| 58 58 | 
             
                @status = :unmodified
         | 
| 59 | 
            +
                @type = :folder
         | 
| 60 | 
            +
                @children = []
         | 
| 61 | 
            +
                @interval = 5
         | 
| 62 | 
            +
                @rev = ''
         | 
| 59 63 |  | 
| 60 64 | 
             
                if @path.directory?
         | 
| 61 65 | 
             
                  init_dir
         | 
| @@ -69,8 +73,8 @@ class RevTree | |
| 69 73 | 
             
              # @param indent [Integer] the indentation level (default: 0)
         | 
| 70 74 | 
             
              # @return [void]
         | 
| 71 75 | 
             
              def print_tree(indent = 0)
         | 
| 72 | 
            -
                 | 
| 73 | 
            -
                puts "#{ | 
| 76 | 
            +
                indent_prefix = '  ' * indent
         | 
| 77 | 
            +
                puts "#{indent_prefix}#{type_to_str()} #{@name} (rev: #{@rev}) #{status_to_str()}"
         | 
| 74 78 | 
             
                @children.each { |child| child.print_tree(indent + 1) }
         | 
| 75 79 | 
             
              end
         | 
| 76 80 |  | 
| @@ -96,10 +100,12 @@ class RevTree | |
| 96 100 |  | 
| 97 101 | 
             
              # Reconstructs a `RevTree` object from a hash.
         | 
| 98 102 | 
             
              #
         | 
| 99 | 
            -
              # @param  | 
| 103 | 
            +
              # @param hash [Hash] the hash to deserialize
         | 
| 100 104 | 
             
              # @return [RevTree] the reconstructed `RevTree` object
         | 
| 101 | 
            -
              def self.from_h( | 
| 102 | 
            -
                 | 
| 105 | 
            +
              def self.from_h(hash)
         | 
| 106 | 
            +
                hash[:status] = hash[:status].to_sym
         | 
| 107 | 
            +
                hash[:type] = hash[:type].to_sym
         | 
| 108 | 
            +
                new_tree(hash)
         | 
| 103 109 | 
             
              end
         | 
| 104 110 |  | 
| 105 111 | 
             
              # Reconstructs a `RevTree` object from a JSON string.
         | 
| @@ -123,7 +129,7 @@ class RevTree | |
| 123 129 | 
             
              def for_each(status_whitelist = [:unmodified, :modified, :added, :removed], &block)
         | 
| 124 130 | 
             
                return unless block_given?
         | 
| 125 131 |  | 
| 126 | 
            -
                RevTree.traverse_tree(self, status_whitelist, @path, &block)
         | 
| 132 | 
            +
                RevTree.traverse_tree(self, status_whitelist, @path, nil, &block)
         | 
| 127 133 | 
             
              end
         | 
| 128 134 |  | 
| 129 135 | 
             
              # Watches the tree for changes
         | 
| @@ -138,23 +144,12 @@ class RevTree | |
| 138 144 | 
             
              # @return [void]
         | 
| 139 145 | 
             
              def watch(status_whitelist = [:modified, :added, :removed], &block)
         | 
| 140 146 | 
             
                current_tree = self
         | 
| 141 | 
            -
                 | 
| 147 | 
            +
                setup_traps
         | 
| 142 148 |  | 
| 143 | 
            -
                Signal.trap('INT') { exit }
         | 
| 144 | 
            -
                Signal.trap('TERM') { exit }
         | 
| 145 149 | 
             
                loop do
         | 
| 146 150 | 
             
                  sleep @interval
         | 
| 147 151 |  | 
| 148 | 
            -
                   | 
| 149 | 
            -
                  diff_tree = RevTree.compare(current_tree, new_tree)
         | 
| 150 | 
            -
             | 
| 151 | 
            -
                  next if diff_tree.nil?
         | 
| 152 | 
            -
             | 
| 153 | 
            -
                  diff_tree.for_each(status_whitelist) do |node, full_path|
         | 
| 154 | 
            -
                    block.call(node, full_path)
         | 
| 155 | 
            -
                  end
         | 
| 156 | 
            -
             | 
| 157 | 
            -
                  current_tree = new_tree
         | 
| 152 | 
            +
                  current_tree = refresh_tree(current_tree, status_whitelist, block)
         | 
| 158 153 | 
             
                end
         | 
| 159 154 | 
             
              end
         | 
| 160 155 |  | 
| @@ -169,6 +164,45 @@ class RevTree | |
| 169 164 |  | 
| 170 165 | 
             
              private
         | 
| 171 166 |  | 
| 167 | 
            +
              # Refreshes the tree by comparing the current tree with a new version and executing a block
         | 
| 168 | 
            +
              # for each file that matches the given statuses.
         | 
| 169 | 
            +
              #
         | 
| 170 | 
            +
              # @param current_tree [RevTree] the current RevTree instance
         | 
| 171 | 
            +
              # @param status_whitelist [Array<Symbol>] the list of statuses to match (e.g., :added, :modified, :removed)
         | 
| 172 | 
            +
              # @param block [Proc] the block to execute for each file matching the statuses
         | 
| 173 | 
            +
              # @return [RevTree] the updated RevTree with changes
         | 
| 174 | 
            +
              def refresh_tree(current_tree, status_whitelist, block)
         | 
| 175 | 
            +
                new_tree = RevTree.new(@path, @whitelist)
         | 
| 176 | 
            +
                diff_tree = RevTree.compare(current_tree, new_tree)
         | 
| 177 | 
            +
                return current_tree unless diff_tree
         | 
| 178 | 
            +
             | 
| 179 | 
            +
                diff_tree.for_each(status_whitelist, &block)
         | 
| 180 | 
            +
             | 
| 181 | 
            +
                new_tree
         | 
| 182 | 
            +
              end
         | 
| 183 | 
            +
             | 
| 184 | 
            +
              # Setup traps.
         | 
| 185 | 
            +
              #
         | 
| 186 | 
            +
              # @return [void]
         | 
| 187 | 
            +
              def setup_traps
         | 
| 188 | 
            +
                Signal.trap('INT') { exit }
         | 
| 189 | 
            +
                Signal.trap('TERM') { exit }
         | 
| 190 | 
            +
              end
         | 
| 191 | 
            +
             | 
| 192 | 
            +
              # Stringify the type for pretty-printing.
         | 
| 193 | 
            +
              #
         | 
| 194 | 
            +
              # @return [String] the type string
         | 
| 195 | 
            +
              def type_to_str
         | 
| 196 | 
            +
                @type == :folder ? '[Folder]' : '[File]'
         | 
| 197 | 
            +
              end
         | 
| 198 | 
            +
             | 
| 199 | 
            +
              # Stringify the status for pretty-printing.
         | 
| 200 | 
            +
              #
         | 
| 201 | 
            +
              # @return [String] the status string
         | 
| 202 | 
            +
              def status_to_str
         | 
| 203 | 
            +
                @status ? "(status: #{@status})" : ''
         | 
| 204 | 
            +
              end
         | 
| 205 | 
            +
             | 
| 172 206 | 
             
              # Calculates the MD5 hash for the file.
         | 
| 173 207 | 
             
              #
         | 
| 174 208 | 
             
              # @return [String] the MD5 hash of the file
         | 
| @@ -187,10 +221,9 @@ class RevTree | |
| 187 221 | 
             
              #
         | 
| 188 222 | 
             
              # @return [void]
         | 
| 189 223 | 
             
              def init_dir
         | 
| 190 | 
            -
                @type = :folder
         | 
| 191 224 | 
             
                @children = @path.children
         | 
| 192 | 
            -
                  .select { | | 
| 193 | 
            -
                  .map { | | 
| 225 | 
            +
                  .select { |child| include_in_tree?(child) }
         | 
| 226 | 
            +
                  .map { |child| RevTree.new(child, @whitelist) }
         | 
| 194 227 | 
             
                @rev = calculate_directory_rev
         | 
| 195 228 | 
             
              end
         | 
| 196 229 |  | 
| @@ -199,43 +232,61 @@ class RevTree | |
| 199 232 | 
             
              # @return [void]
         | 
| 200 233 | 
             
              def init_file
         | 
| 201 234 | 
             
                @type = :file
         | 
| 202 | 
            -
                @children = []
         | 
| 203 235 | 
             
                @rev = calculate_file_rev
         | 
| 204 236 | 
             
              end
         | 
| 205 237 |  | 
| 238 | 
            +
              # Apply attributes from a `Hash` to a `RevTree`.
         | 
| 239 | 
            +
              #
         | 
| 240 | 
            +
              # @param revtree [RevTree] the tree node to be modified
         | 
| 241 | 
            +
              # @param attr_hash [Hash] the hash containing the attributes
         | 
| 242 | 
            +
              # @return [void]
         | 
| 243 | 
            +
              def self.apply_attributes(revtree, attr_hash)
         | 
| 244 | 
            +
                revtree.instance_variable_set(:@name, attr_hash[:name])
         | 
| 245 | 
            +
                revtree.instance_variable_set(:@type, attr_hash[:type])
         | 
| 246 | 
            +
                revtree.instance_variable_set(:@rev, attr_hash[:rev])
         | 
| 247 | 
            +
                revtree.instance_variable_set(:@status, attr_hash[:status])
         | 
| 248 | 
            +
                revtree.instance_variable_set(:@children, attr_hash[:children])
         | 
| 249 | 
            +
              end
         | 
| 250 | 
            +
             | 
| 251 | 
            +
              # Recurse into child nodes to deserialize `RevTree`.
         | 
| 252 | 
            +
              #
         | 
| 253 | 
            +
              # @param hash [Hash] the hash to deserialize
         | 
| 254 | 
            +
              # @return [void]
         | 
| 255 | 
            +
              def self.new_tree_recurse_children(hash)
         | 
| 256 | 
            +
                children = hash[:children] || []
         | 
| 257 | 
            +
                hash[:children] = children.map { |child| from_h(child) }
         | 
| 258 | 
            +
              end
         | 
| 259 | 
            +
             | 
| 206 260 | 
             
              # Rebuilds a `RevTree` from its serialized components.
         | 
| 207 261 | 
             
              #
         | 
| 208 | 
            -
              # @param  | 
| 209 | 
            -
              # @param type [Symbol] the type of the node (:folder or :file)
         | 
| 210 | 
            -
              # @param rev [String] the revision hash of the node
         | 
| 211 | 
            -
              # @param children [Array<Hash>] the child nodes (if any)
         | 
| 212 | 
            -
              # @param status [Symbol] the status of the node (:unmodified, :modified, etc.)
         | 
| 262 | 
            +
              # @param hash [Hash] the hash to deserialize
         | 
| 213 263 | 
             
              # @return [RevTree] the reconstructed tree
         | 
| 214 | 
            -
              def self.new_tree( | 
| 264 | 
            +
              def self.new_tree(hash)
         | 
| 215 265 | 
             
                tree = allocate
         | 
| 216 | 
            -
                 | 
| 217 | 
            -
                tree | 
| 218 | 
            -
                tree.instance_variable_set(:@rev, rev)
         | 
| 219 | 
            -
                tree.instance_variable_set(:@status, status.to_sym)
         | 
| 220 | 
            -
                if type == :folder && children
         | 
| 221 | 
            -
                  tree.instance_variable_set(:@children, children.map { |c| from_h(c) })
         | 
| 222 | 
            -
                else
         | 
| 223 | 
            -
                  tree.instance_variable_set(:@children, [])
         | 
| 224 | 
            -
                end
         | 
| 266 | 
            +
                new_tree_recurse_children(hash)
         | 
| 267 | 
            +
                apply_attributes(tree, hash)
         | 
| 225 268 | 
             
                tree
         | 
| 226 269 | 
             
              end
         | 
| 227 270 |  | 
| 271 | 
            +
              # Determines whether a path is a dot directory.
         | 
| 272 | 
            +
              #
         | 
| 273 | 
            +
              # @param path [Pathname] the path to the file or directory
         | 
| 274 | 
            +
              # @return [Boolean] `true` if path is a dot directory, `false` otherwise
         | 
| 275 | 
            +
              def self.path_is_dot_dir?(path)
         | 
| 276 | 
            +
                path.directory? && path.basename.to_s.start_with?('.')
         | 
| 277 | 
            +
              end
         | 
| 278 | 
            +
             | 
| 228 279 | 
             
              # Determines whether a file or directory should be included in the tree.
         | 
| 229 280 | 
             
              #
         | 
| 230 281 | 
             
              # @param path [Pathname] the path to the file or directory
         | 
| 231 282 | 
             
              # @return [Boolean] `true` if the path should be included, `false` otherwise
         | 
| 232 283 | 
             
              def include_in_tree?(path)
         | 
| 233 | 
            -
                return false if  | 
| 284 | 
            +
                return false if RevTree.path_is_dot_dir?(path)
         | 
| 234 285 |  | 
| 235 286 | 
             
                return true if path.directory?
         | 
| 236 287 | 
             
                return true if @whitelist.empty?
         | 
| 237 288 |  | 
| 238 | 
            -
                @whitelist.any? { | | 
| 289 | 
            +
                @whitelist.any? { |pattern| File.fnmatch?(pattern, path.basename.to_s) }
         | 
| 239 290 | 
             
              end
         | 
| 240 291 |  | 
| 241 292 | 
             
              # Compares two `RevTree` nodes (old and new) and returns a tree with appropriate status.
         | 
| @@ -244,16 +295,13 @@ class RevTree | |
| 244 295 | 
             
              # @param new [RevTree, nil] the new version of the tree
         | 
| 245 296 | 
             
              # @return [RevTree, nil] the resulting tree with status updates or `nil`
         | 
| 246 297 | 
             
              def self.compare(old, new)
         | 
| 247 | 
            -
                return nil  | 
| 298 | 
            +
                return nil unless old || new
         | 
| 248 299 |  | 
| 249 | 
            -
                return handle_addition(new)  | 
| 250 | 
            -
                return handle_removal(old)  | 
| 300 | 
            +
                return handle_addition(new) unless old
         | 
| 301 | 
            +
                return handle_removal(old) unless new
         | 
| 251 302 |  | 
| 252 | 
            -
                 | 
| 253 | 
            -
             | 
| 254 | 
            -
                else
         | 
| 255 | 
            -
                  return handle_unmodified(old, new)
         | 
| 256 | 
            -
                end
         | 
| 303 | 
            +
                status = old.rev != new.rev ? :modified : :unmodified
         | 
| 304 | 
            +
                handle_modification(old, new, status)
         | 
| 257 305 | 
             
              end
         | 
| 258 306 |  | 
| 259 307 | 
             
              # Handles the addition of a new node.
         | 
| @@ -280,13 +328,14 @@ class RevTree | |
| 280 328 | 
             
              #
         | 
| 281 329 | 
             
              # @param old [RevTree] the old node
         | 
| 282 330 | 
             
              # @param new [RevTree] the new node
         | 
| 331 | 
            +
              # @param status [Symbol] the status to apply (:modified or :unmodified)
         | 
| 283 332 | 
             
              # @return [RevTree] the node with the status set to `:modified`
         | 
| 284 | 
            -
              def self.handle_modification(old, new)
         | 
| 333 | 
            +
              def self.handle_modification(old, new, status)
         | 
| 285 334 | 
             
                if old.type == :folder && new.type == :folder
         | 
| 286 | 
            -
                  compare_folders(old, new,  | 
| 335 | 
            +
                  compare_folders(old, new, status)
         | 
| 287 336 | 
             
                else
         | 
| 288 337 | 
             
                  with_status = new.dup
         | 
| 289 | 
            -
                  with_status.instance_variable_set(:@status,  | 
| 338 | 
            +
                  with_status.instance_variable_set(:@status, status)
         | 
| 290 339 | 
             
                  with_status
         | 
| 291 340 | 
             
                end
         | 
| 292 341 | 
             
              end
         | 
| @@ -300,7 +349,9 @@ class RevTree | |
| 300 349 | 
             
              def self.compare_folders(old, new, status)
         | 
| 301 350 | 
             
                combined_children = merge_children(old.children, new.children)
         | 
| 302 351 | 
             
                with_status = new.dup
         | 
| 303 | 
            -
                merged = combined_children.map  | 
| 352 | 
            +
                merged = combined_children.map do |old_child, new_child|
         | 
| 353 | 
            +
                  compare(old_child, new_child)
         | 
| 354 | 
            +
                end
         | 
| 304 355 |  | 
| 305 356 | 
             
                folder_status = merged.any? { |child| child.status == :modified } ? :modified : status
         | 
| 306 357 |  | 
| @@ -309,53 +360,42 @@ class RevTree | |
| 309 360 | 
             
                with_status
         | 
| 310 361 | 
             
              end
         | 
| 311 362 |  | 
| 312 | 
            -
              # Handles the unmodified status of a node.
         | 
| 313 | 
            -
              #
         | 
| 314 | 
            -
              # @param old [RevTree] the old node
         | 
| 315 | 
            -
              # @param new [RevTree] the new node
         | 
| 316 | 
            -
              # @return [RevTree] the node with the status set to `:unmodified`
         | 
| 317 | 
            -
              def self.handle_unmodified(old, new)
         | 
| 318 | 
            -
                if old.type == :folder && new.type == :folder
         | 
| 319 | 
            -
                  compare_folders(old, new, :unmodified)
         | 
| 320 | 
            -
                else
         | 
| 321 | 
            -
                  with_status = new.dup
         | 
| 322 | 
            -
                  with_status.instance_variable_set(:@status, :unmodified)
         | 
| 323 | 
            -
                  with_status
         | 
| 324 | 
            -
                end
         | 
| 325 | 
            -
              end
         | 
| 326 | 
            -
             | 
| 327 363 | 
             
              # Merges the children of two nodes.
         | 
| 328 364 | 
             
              #
         | 
| 329 | 
            -
              # @param old_children [Array<RevTree>] the children of the old node
         | 
| 330 | 
            -
              # @param new_children [Array<RevTree>] the children of the new node
         | 
| 331 365 | 
             
              # @return [Array<Array<RevTree, RevTree>>] an array of paired old and new children
         | 
| 332 366 | 
             
              def self.merge_children(old_children, new_children)
         | 
| 333 367 | 
             
                all_names = (old_children.map(&:name) + new_children.map(&:name)).uniq
         | 
| 334 | 
            -
                all_names.map  | 
| 335 | 
            -
             | 
| 336 | 
            -
             | 
| 337 | 
            -
             | 
| 338 | 
            -
             | 
| 368 | 
            +
                all_names.map { |name| find_child_pair(name, old_children, new_children) }
         | 
| 369 | 
            +
              end
         | 
| 370 | 
            +
             | 
| 371 | 
            +
              # @param old_children [Array<RevTree>] the children of the old node
         | 
| 372 | 
            +
              # @param new_children [Array<RevTree>] the children of the new node
         | 
| 373 | 
            +
              def self.find_child_pair(name, old_children, new_children)
         | 
| 374 | 
            +
                old_child = old_children.find { |old| old.name == name }
         | 
| 375 | 
            +
                new_child = new_children.find { |new| new.name == name }
         | 
| 376 | 
            +
                [old_child, new_child]
         | 
| 339 377 | 
             
              end
         | 
| 340 378 |  | 
| 341 379 | 
             
              # Traverses the tree and executes a block for each file matching the provided status whitelist.
         | 
| 342 380 | 
             
              #
         | 
| 343 381 | 
             
              # @param node [RevTree] the current node being traversed
         | 
| 344 382 | 
             
              # @param status_whitelist [Array<Symbol>] the list of statuses to match
         | 
| 383 | 
            +
              # @param root [Pathname] the root path
         | 
| 345 384 | 
             
              # @param current_path [Pathname] the current path
         | 
| 346 385 | 
             
              # @yield [node, full_path] the block to be executed for each matching file
         | 
| 347 386 | 
             
              # @yieldparam node [RevTree] the current node being traversed
         | 
| 348 387 | 
             
              # @yieldparam full_path [String] the full path of the current node
         | 
| 349 388 | 
             
              # @return [void]
         | 
| 350 | 
            -
              def self.traverse_tree(node, status_whitelist, current_path, &block)
         | 
| 389 | 
            +
              def self.traverse_tree(node, status_whitelist, root, current_path, &block)
         | 
| 390 | 
            +
                current_path = current_path.to_s
         | 
| 391 | 
            +
                full_path = current_path == '' ? root : File.join(current_path, node.name.to_s)
         | 
| 392 | 
            +
             | 
| 351 393 | 
             
                if node.type == :file && status_whitelist.include?(node.status)
         | 
| 352 | 
            -
                  block.call(node, File.expand_path(current_path | 
| 394 | 
            +
                  block.call(node, File.expand_path(current_path))
         | 
| 353 395 | 
             
                end
         | 
| 354 396 |  | 
| 355 | 
            -
                full_path = File.join(current_path.to_s, node.name.to_s)
         | 
| 356 | 
            -
             | 
| 357 397 | 
             
                node.children.each do |child|
         | 
| 358 | 
            -
                  traverse_tree(child, status_whitelist, full_path, &block)
         | 
| 398 | 
            +
                  traverse_tree(child, status_whitelist, root, full_path, &block)
         | 
| 359 399 | 
             
                end
         | 
| 360 400 | 
             
              end
         | 
| 361 401 | 
             
            end
         | 
    
        metadata
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification
         | 
| 2 2 | 
             
            name: revtree
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            -
              version: 0.1. | 
| 4 | 
            +
              version: 0.1.5
         | 
| 5 5 | 
             
            platform: ruby
         | 
| 6 6 | 
             
            authors:
         | 
| 7 7 | 
             
            - Julian Kahlert
         | 
| @@ -10,6 +10,66 @@ bindir: bin | |
| 10 10 | 
             
            cert_chain: []
         | 
| 11 11 | 
             
            date: 2024-09-07 00:00:00.000000000 Z
         | 
| 12 12 | 
             
            dependencies:
         | 
| 13 | 
            +
            - !ruby/object:Gem::Dependency
         | 
| 14 | 
            +
              name: simplecov-simplecov-cobertura
         | 
| 15 | 
            +
              requirement: !ruby/object:Gem::Requirement
         | 
| 16 | 
            +
                requirements:
         | 
| 17 | 
            +
                - - "~>"
         | 
| 18 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 19 | 
            +
                    version: '2'
         | 
| 20 | 
            +
                - - ">="
         | 
| 21 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 22 | 
            +
                    version: '2.1'
         | 
| 23 | 
            +
              type: :development
         | 
| 24 | 
            +
              prerelease: false
         | 
| 25 | 
            +
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 26 | 
            +
                requirements:
         | 
| 27 | 
            +
                - - "~>"
         | 
| 28 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 29 | 
            +
                    version: '2'
         | 
| 30 | 
            +
                - - ">="
         | 
| 31 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 32 | 
            +
                    version: '2.1'
         | 
| 33 | 
            +
            - !ruby/object:Gem::Dependency
         | 
| 34 | 
            +
              name: simplecov-console
         | 
| 35 | 
            +
              requirement: !ruby/object:Gem::Requirement
         | 
| 36 | 
            +
                requirements:
         | 
| 37 | 
            +
                - - "~>"
         | 
| 38 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 39 | 
            +
                    version: '0.9'
         | 
| 40 | 
            +
                - - ">="
         | 
| 41 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 42 | 
            +
                    version: 0.9.1
         | 
| 43 | 
            +
              type: :development
         | 
| 44 | 
            +
              prerelease: false
         | 
| 45 | 
            +
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 46 | 
            +
                requirements:
         | 
| 47 | 
            +
                - - "~>"
         | 
| 48 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 49 | 
            +
                    version: '0.9'
         | 
| 50 | 
            +
                - - ">="
         | 
| 51 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 52 | 
            +
                    version: 0.9.1
         | 
| 53 | 
            +
            - !ruby/object:Gem::Dependency
         | 
| 54 | 
            +
              name: simplecov
         | 
| 55 | 
            +
              requirement: !ruby/object:Gem::Requirement
         | 
| 56 | 
            +
                requirements:
         | 
| 57 | 
            +
                - - "~>"
         | 
| 58 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 59 | 
            +
                    version: '0.22'
         | 
| 60 | 
            +
                - - ">="
         | 
| 61 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 62 | 
            +
                    version: 0.22.0
         | 
| 63 | 
            +
              type: :development
         | 
| 64 | 
            +
              prerelease: false
         | 
| 65 | 
            +
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 66 | 
            +
                requirements:
         | 
| 67 | 
            +
                - - "~>"
         | 
| 68 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 69 | 
            +
                    version: '0.22'
         | 
| 70 | 
            +
                - - ">="
         | 
| 71 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 72 | 
            +
                    version: 0.22.0
         | 
| 13 73 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 14 74 | 
             
              name: yard
         | 
| 15 75 | 
             
              requirement: !ruby/object:Gem::Requirement
         | 
| @@ -66,7 +126,7 @@ licenses: | |
| 66 126 | 
             
            - MIT
         | 
| 67 127 | 
             
            metadata:
         | 
| 68 128 | 
             
              homepage_uri: https://juliankahlert.github.io/revtree/
         | 
| 69 | 
            -
              documentation_uri: https://www.rubydoc.info/gems/revtree/0.1. | 
| 129 | 
            +
              documentation_uri: https://www.rubydoc.info/gems/revtree/0.1.5
         | 
| 70 130 | 
             
              source_code_uri: https://github.com/juliankahlert/revtree
         | 
| 71 131 | 
             
            post_install_message: 
         | 
| 72 132 | 
             
            rdoc_options: []
         |