From ae5eea8acddc601af72134a3071a959a531b3014 Mon Sep 17 00:00:00 2001 From: "john.mortlock" Date: Fri, 26 Nov 2021 08:00:55 +1030 Subject: [PATCH 01/24] Remove non-required files --- .gemtest | 0 .ruby-gemset | 1 - 2 files changed, 1 deletion(-) delete mode 100644 .gemtest delete mode 100644 .ruby-gemset diff --git a/.gemtest b/.gemtest deleted file mode 100644 index e69de29..0000000 diff --git a/.ruby-gemset b/.ruby-gemset deleted file mode 100644 index 002089b..0000000 --- a/.ruby-gemset +++ /dev/null @@ -1 +0,0 @@ -rubytree From 200f7088903ec7b5d1138e57be189972fce3f79b Mon Sep 17 00:00:00 2001 From: "john.mortlock" Date: Fri, 26 Nov 2021 08:01:31 +1030 Subject: [PATCH 02/24] Ignore gemfile.lock --- .gitignore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index c7f9167..b53cca5 100644 --- a/.gitignore +++ b/.gitignore @@ -9,4 +9,4 @@ tmp/ .bundle/ vendor/ .idea/ - +Gemfile.lock From 636dd4fa28a69710bef356aecc58f85047f9f4a5 Mon Sep 17 00:00:00 2001 From: "john.mortlock" Date: Fri, 26 Nov 2021 08:01:50 +1030 Subject: [PATCH 03/24] Use gemspec for the gemfile --- Gemfile | 16 ++-------------- rubytree.gemspec | 15 +++++++++------ 2 files changed, 11 insertions(+), 20 deletions(-) diff --git a/Gemfile b/Gemfile index 5875332..bb94df8 100644 --- a/Gemfile +++ b/Gemfile @@ -1,16 +1,4 @@ -source 'https://rubygems.org' +# frozen_string_literal: true -# Specify your gem's dependencies in rubytree.gemspec +source "https://rubygems.org" gemspec - -group :development, :test do - gem 'rake', '>= 13.0.1' - gem 'test-unit', '~> 3.3.6' - gem 'coveralls', '>= 0.8.23', :require => false, :platforms => :mri_21 - gem 'rspec', '>= 3.9.0' - gem 'rubocop' -end - -# Local Variables: -# mode: ruby -# End: diff --git a/rubytree.gemspec b/rubytree.gemspec index a63854f..538e8f0 100644 --- a/rubytree.gemspec +++ b/rubytree.gemspec @@ -20,7 +20,7 @@ Gem::Specification.new do |s| s.email = 'anupamsg@gmail.com' s.homepage = 'http://rubytree.anupamsg.me' - s.required_ruby_version = '>=2.4' + s.required_ruby_version = '>=2.6' s.summary = %q{A generic tree data structure.} s.description = <<-EOF @@ -69,11 +69,14 @@ Gem::Specification.new do |s| s.add_runtime_dependency 'json' , '~> 2.3.1' # Note: Rake is added as a development and test dependency in the Gemfile. - s.add_development_dependency 'bundler' , '~> 2.1.4' - s.add_development_dependency 'rdoc' , '~> 6.2.1' - s.add_development_dependency 'yard' , '~> 0.9.25' - s.add_development_dependency 'rtagstask' , '~> 0.0.4' - s.add_development_dependency 'rspec' , '~> 3.9.0' + s.add_development_dependency 'bundler' + s.add_development_dependency 'rdoc' + s.add_development_dependency 'yard' + s.add_development_dependency 'rtagstask' + s.add_development_dependency 'rspec' + s.add_development_dependency "rake" + s.add_development_dependency "test-unit" + s.post_install_message = <<-EOF ======================================================================== From 451c8e910a46bb391ae8bae1d7a4add93fbce829 Mon Sep 17 00:00:00 2001 From: "john.mortlock" Date: Fri, 26 Nov 2021 08:02:02 +1030 Subject: [PATCH 04/24] Bump dev to ruby 3.0.3 --- .ruby-version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.ruby-version b/.ruby-version index 35cee72..75a22a2 100644 --- a/.ruby-version +++ b/.ruby-version @@ -1 +1 @@ -2.4.3 +3.0.3 From da52a246a53fb28bcbacccf2ce3013e4df544326 Mon Sep 17 00:00:00 2001 From: "john.mortlock" Date: Fri, 26 Nov 2021 08:03:18 +1030 Subject: [PATCH 05/24] Switch build to github actions --- .github/workflows/ruby.yml | 16 ++++++++++++++++ .travis.yml | 31 ------------------------------- 2 files changed, 16 insertions(+), 31 deletions(-) create mode 100644 .github/workflows/ruby.yml delete mode 100644 .travis.yml diff --git a/.github/workflows/ruby.yml b/.github/workflows/ruby.yml new file mode 100644 index 0000000..809c8e5 --- /dev/null +++ b/.github/workflows/ruby.yml @@ -0,0 +1,16 @@ +name: Build and Test +on: [push, pull_request] +jobs: + test: + strategy: + fail-fast: false + matrix: + ruby: ["2.6", "2.7", "3.0"] + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: ruby/setup-ruby@v1 + with: + ruby-version: ${{ matrix.ruby }} + bundler-cache: true + - run: bundle exec rake diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 99dd131..0000000 --- a/.travis.yml +++ /dev/null @@ -1,31 +0,0 @@ -language: ruby -before_install: - - gem install bundler - - 'echo "gem: --no-ri --no-rdoc" > ~/.gemrc' - - bundle --version - - gem --version -bundler_args: --without development - -rvm: - - 2.4 - - 2.5 - - 2.6 - -matrix: - allow_failures: - - rvm: rbx # rbx is still troublesome. - include: - - rvm: rbx - gemfile: gemfiles/Gemfile.rbx - # - rvm: 2.4.3 # - # env: COVERAGE=true # - exclude: - - rvm: rbx - gemfile: Gemfile - -# blacklist -branches: - except: - - develop - - rt-site - - gh-pages From c1dd05823e6e088fc3ea0593ecd01c91f55cc8a3 Mon Sep 17 00:00:00 2001 From: "john.mortlock" Date: Fri, 26 Nov 2021 08:04:37 +1030 Subject: [PATCH 06/24] Remove committed lockfile --- Gemfile.lock | 91 ---------------------------------------------------- 1 file changed, 91 deletions(-) delete mode 100644 Gemfile.lock diff --git a/Gemfile.lock b/Gemfile.lock deleted file mode 100644 index 34cc82f..0000000 --- a/Gemfile.lock +++ /dev/null @@ -1,91 +0,0 @@ -PATH - remote: . - specs: - rubytree (1.0.1) - json (~> 2.3.1) - structured_warnings (~> 0.4.0) - -GEM - remote: https://rubygems.org/ - specs: - ast (2.4.1) - coveralls (0.8.23) - json (>= 1.8, < 3) - simplecov (~> 0.16.1) - term-ansicolor (~> 1.3) - thor (>= 0.19.4, < 2.0) - tins (~> 1.6) - diff-lcs (1.4.4) - docile (1.3.2) - json (2.3.1) - parallel (1.19.2) - parser (2.7.1.4) - ast (~> 2.4.1) - power_assert (1.2.0) - rainbow (3.0.0) - rake (13.0.1) - rdoc (6.2.1) - regexp_parser (1.7.1) - rexml (3.2.4) - rspec (3.9.0) - rspec-core (~> 3.9.0) - rspec-expectations (~> 3.9.0) - rspec-mocks (~> 3.9.0) - rspec-core (3.9.2) - rspec-support (~> 3.9.3) - rspec-expectations (3.9.2) - diff-lcs (>= 1.2.0, < 2.0) - rspec-support (~> 3.9.0) - rspec-mocks (3.9.1) - diff-lcs (>= 1.2.0, < 2.0) - rspec-support (~> 3.9.0) - rspec-support (3.9.3) - rtags (0.97) - rtagstask (0.0.4) - rtags (> 0.0.0) - rubocop (0.90.0) - parallel (~> 1.10) - parser (>= 2.7.1.1) - rainbow (>= 2.2.2, < 4.0) - regexp_parser (>= 1.7) - rexml - rubocop-ast (>= 0.3.0, < 1.0) - ruby-progressbar (~> 1.7) - unicode-display_width (>= 1.4.0, < 2.0) - rubocop-ast (0.3.0) - parser (>= 2.7.1.4) - ruby-progressbar (1.10.1) - simplecov (0.16.1) - docile (~> 1.1) - json (>= 1.8, < 3) - simplecov-html (~> 0.10.0) - simplecov-html (0.10.2) - structured_warnings (0.4.0) - sync (0.5.0) - term-ansicolor (1.7.1) - tins (~> 1.0) - test-unit (3.3.6) - power_assert - thor (1.0.1) - tins (1.25.0) - sync - unicode-display_width (1.7.0) - yard (0.9.25) - -PLATFORMS - ruby - -DEPENDENCIES - bundler (~> 2.1.4) - coveralls (>= 0.8.23) - rake (>= 13.0.1) - rdoc (~> 6.2.1) - rspec (>= 3.9.0) - rtagstask (~> 0.0.4) - rubocop - rubytree! - test-unit (~> 3.3.6) - yard (~> 0.9.25) - -BUNDLED WITH - 2.1.4 From 6d493fd216093b16fa79bf22b26253561d740e10 Mon Sep 17 00:00:00 2001 From: "john.mortlock" Date: Fri, 26 Nov 2021 08:08:34 +1030 Subject: [PATCH 07/24] Remove Rbx gemfile --- gemfiles/Gemfile.rbx | 17 ----------------- 1 file changed, 17 deletions(-) delete mode 100644 gemfiles/Gemfile.rbx diff --git a/gemfiles/Gemfile.rbx b/gemfiles/Gemfile.rbx deleted file mode 100644 index 942bf38..0000000 --- a/gemfiles/Gemfile.rbx +++ /dev/null @@ -1,17 +0,0 @@ -source 'https://rubygems.org' - -# Specify your gem's dependencies in rubytree.gemspec -gemspec :path => '..' - -platforms :rbx do - gem "rubysl" - gem "rubysl-test-unit" -end - -group :development, :test do - gem "rake", "~> 10.1" -end - -# Local Variables: -# mode: ruby -# End: From 4c4d1e9c89f19f0b60228c970ee2ff6c35af0687 Mon Sep 17 00:00:00 2001 From: "john.mortlock" Date: Fri, 26 Nov 2021 08:08:54 +1030 Subject: [PATCH 08/24] Remove deprecated CamelCaseMethodHandler support --- lib/tree.rb | 1 - lib/tree/tree_deps.rb | 1 - lib/tree/utils/camel_case_method_handler.rb | 79 --------------------- test/test_binarytree.rb | 22 ------ test/test_subclassed_node.rb | 20 ------ test/test_tree.rb | 32 --------- 6 files changed, 155 deletions(-) delete mode 100644 lib/tree/utils/camel_case_method_handler.rb diff --git a/lib/tree.rb b/lib/tree.rb index de36905..7b7ac20 100644 --- a/lib/tree.rb +++ b/lib/tree.rb @@ -89,7 +89,6 @@ class TreeNode include Comparable include Tree::Utils::TreeMetricsHandler include Tree::Utils::TreePathHandler - include Tree::Utils::CamelCaseMethodHandler include Tree::Utils::JSONConverter include Tree::Utils::TreeMergeHandler include Tree::Utils::HashConverter diff --git a/lib/tree/tree_deps.rb b/lib/tree/tree_deps.rb index 8f05d8e..4388969 100644 --- a/lib/tree/tree_deps.rb +++ b/lib/tree/tree_deps.rb @@ -43,7 +43,6 @@ require_relative '../tree/version' require_relative '../tree/utils/metrics_methods' require_relative '../tree/utils/path_methods' -require_relative '../tree/utils/camel_case_method_handler' require_relative '../tree/utils/json_converter' require_relative '../tree/utils/tree_merge_handler' require_relative '../tree/utils/hash_converter' diff --git a/lib/tree/utils/camel_case_method_handler.rb b/lib/tree/utils/camel_case_method_handler.rb deleted file mode 100644 index 1f06472..0000000 --- a/lib/tree/utils/camel_case_method_handler.rb +++ /dev/null @@ -1,79 +0,0 @@ -# camel_case_methods.rb - This file is part of the RubyTree package. -# -# = camel_case_methods.rb - Provides conversion from CamelCase to snake_case. -# -# Author:: Anupam Sengupta (anupamsg@gmail.com) -# -# Time-stamp: <2017-12-21 13:42:15 anupam> -# -# Copyright (C) 2012, 2013, 2015, 2017 Anupam Sengupta -# -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are met: -# -# - Redistributions of source code must retain the above copyright notice, this -# list of conditions and the following disclaimer. -# -# - Redistributions in binary form must reproduce the above copyright notice, -# this list of conditions and the following disclaimer in the documentation -# and/or other materials provided with the distribution. -# -# - Neither the name of the organization nor the names of its contributors may -# be used to endorse or promote products derived from this software without -# specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE -# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -# - -require_relative '../../../lib/tree' -require 'structured_warnings' - -module Tree::Utils - # Provides utility functions to handle CamelCase methods, and redirect - # invocation of such methods to the snake_case equivalents. - module CamelCaseMethodHandler - def self.included(base) - # @!visibility private - # Allow the deprecated CamelCase method names. Display a warning. - # :nodoc: - def method_missing(meth, *args, &blk) - if self.respond_to?((new_method_name = to_snake_case(meth))) - warn StructuredWarnings::DeprecatedMethodWarning, - 'The camelCased methods are deprecated. ' + - "Please use #{new_method_name} instead of #{meth}" - send(new_method_name, *args, &blk) - else - super - end - end - - # @!visibility private - # Convert a CamelCasedWord to a underscore separated camel_cased_word. - # - # @param [String] camel_cased_word The word to be converted to snake_case. - # @return [String] the snake_cased_word. - def to_snake_case(camel_cased_word) - word = camel_cased_word.to_s - word.gsub!(/::/, '/') - word.gsub!(/([A-Z]+)([A-Z][a-z])/,'\1_\2') - word.gsub!(/([a-z\d])([A-Z])/,'\1_\2') - word.tr!('-', '_') - word.downcase! - word - end - protected :to_snake_case - - end # self.included - end -end diff --git a/test/test_binarytree.rb b/test/test_binarytree.rb index f5fb9de..aa48632 100755 --- a/test/test_binarytree.rb +++ b/test/test_binarytree.rb @@ -296,27 +296,5 @@ def test_swap_children assert_equal(@right_child1, @root[0], 'right_child1 should now be the first child') assert_equal(@left_child1, @root[1], 'left_child1 should now be the last child') end - - # Test the old CamelCase method names - def test_old_camel_case_names - @left_child2 = Tree::BinaryTreeNode.new('A Child at Left', 'Child Node @ left') - @right_child2 = Tree::BinaryTreeNode.new('B Child at Right', 'Child Node @ right') - - require 'structured_warnings' - - meth_names_for_test = %w{leftChild isLeftChild? rightChild isRightChild?} - - meth_names_for_test.each do |meth_name| - assert_warn(StructuredWarnings::DeprecatedMethodWarning) {@root.send(meth_name)} - end - - # noinspection RubyResolve - assert_warn(StructuredWarnings::DeprecatedMethodWarning) {@root.leftChild = @left_child2} - # noinspection RubyResolve - assert_warn(StructuredWarnings::DeprecatedMethodWarning) {@root.rightChild = @right_child2} - assert_raise(NoMethodError) {@root.DummyMethodDoesNotExist} # Make sure the right method is visible - - end - end end diff --git a/test/test_subclassed_node.rb b/test/test_subclassed_node.rb index 3245d43..f81270e 100755 --- a/test/test_subclassed_node.rb +++ b/test/test_subclassed_node.rb @@ -43,26 +43,6 @@ class TestSubclassedTreeNode < Test::Unit::TestCase # A subclassed node to test various inheritance related features. class MyNode < Tree::TreeNode - # A dummy method to test the camelCasedMethod resolution - def my_dummy_method - 'Hello' - end - end - - def test_camelcase_methods - root = MyNode.new('Root') - - assert_equal('Hello', root.my_dummy_method) - - # We should get a warning as we are invoking the camelCase version of the dummy method. - assert_warn(StructuredWarnings::DeprecatedMethodWarning) { root.send('MyDummyMethod') } - - # Test if the structured_warnings can be disabled to call the CamelCase methods. - StructuredWarnings::DeprecatedMethodWarning.disable do - # noinspection RubyResolve - assert_equal('Hello', root.myDummyMethod) - end - end def test_detached_copy_same_clz diff --git a/test/test_tree.rb b/test/test_tree.rb index 52bbf34..15945a5 100755 --- a/test/test_tree.rb +++ b/test/test_tree.rb @@ -1413,38 +1413,6 @@ def test_json_round_trip assert_equal(k[1].name, root_node[1].name, 'Child 2 should be returned') end - # Test the old CamelCase method names - def test_old_camel_case_names - setup_test_tree - - meth_names_to_test = %w{isRoot? isLeaf? hasContent? - hasChildren? firstChild lastChild - firstSibling isFirstSibling? lastSibling isLastSibling? - isOnlyChild? nextSibling previousSibling nodeHeight nodeDepth - removeFromParent! removeAll! freezeTree! } - - require 'structured_warnings' - - StructuredWarnings::DeprecatedMethodWarning.disable do - # noinspection RubyResolve - assert(@root.isRoot?) # Test if the original method is really called - end - - meth_names_to_test.each do |meth_name| - assert_warn(StructuredWarnings::DeprecatedMethodWarning) {@root.send(meth_name)} - end - - # Special Case for printTree to avoid putting stuff on the STDOUT during the unit test. - begin - require 'stringio' - $stdout = StringIO.new - assert_warn(StructuredWarnings::DeprecatedMethodWarning) { @root.send('printTree') } - ensure - $stdout = STDOUT - end - - end - # Test usage of integers as node names def test_integer_node_names From ff9e1e0adc0b14c21043c21f0ba745c3049a4408 Mon Sep 17 00:00:00 2001 From: "john.mortlock" Date: Fri, 26 Nov 2021 08:10:27 +1030 Subject: [PATCH 09/24] Remove circular includes --- lib/tree/utils/hash_converter.rb | 2 -- lib/tree/utils/json_converter.rb | 1 - lib/tree/utils/metrics_methods.rb | 1 - lib/tree/utils/path_methods.rb | 2 -- lib/tree/utils/tree_merge_handler.rb | 2 -- lib/tree/utils/utils.rb | 2 -- 6 files changed, 10 deletions(-) diff --git a/lib/tree/utils/hash_converter.rb b/lib/tree/utils/hash_converter.rb index 4b0b750..b36248c 100644 --- a/lib/tree/utils/hash_converter.rb +++ b/lib/tree/utils/hash_converter.rb @@ -37,8 +37,6 @@ # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -require_relative '../../../lib/tree/utils/utils' - module Tree::Utils::HashConverter def self.included(base) diff --git a/lib/tree/utils/json_converter.rb b/lib/tree/utils/json_converter.rb index 8ff173a..58f0e6f 100644 --- a/lib/tree/utils/json_converter.rb +++ b/lib/tree/utils/json_converter.rb @@ -35,7 +35,6 @@ # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -require_relative '../utils/utils' require 'json' # Provides utility methods to convert a {Tree::TreeNode} to and from diff --git a/lib/tree/utils/metrics_methods.rb b/lib/tree/utils/metrics_methods.rb index f246e4f..a18d5b5 100644 --- a/lib/tree/utils/metrics_methods.rb +++ b/lib/tree/utils/metrics_methods.rb @@ -36,7 +36,6 @@ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # -require_relative '../../../lib/tree' require 'structured_warnings' module Tree::Utils diff --git a/lib/tree/utils/path_methods.rb b/lib/tree/utils/path_methods.rb index b050221..de2ff27 100644 --- a/lib/tree/utils/path_methods.rb +++ b/lib/tree/utils/path_methods.rb @@ -36,8 +36,6 @@ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # -require_relative '../../../lib/tree' - module Tree::Utils # Provides utility methods for path extraction module TreePathHandler diff --git a/lib/tree/utils/tree_merge_handler.rb b/lib/tree/utils/tree_merge_handler.rb index 04a0eb3..9cdbb96 100755 --- a/lib/tree/utils/tree_merge_handler.rb +++ b/lib/tree/utils/tree_merge_handler.rb @@ -35,8 +35,6 @@ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # -require_relative '../../../lib/tree/utils/utils' - # Provides utility methods to merge two {Tree::TreeNode} based trees. # @since 0.9.0 module Tree::Utils::TreeMergeHandler diff --git a/lib/tree/utils/utils.rb b/lib/tree/utils/utils.rb index 71ae433..c247240 100644 --- a/lib/tree/utils/utils.rb +++ b/lib/tree/utils/utils.rb @@ -37,8 +37,6 @@ # Provides utilities and mixin modules for RubyTree. -require_relative '../../../lib/tree' - module Tree::Utils # Empty module. Being used as a namespace. end From 9773c0fe98cf9228790bbd6fb9daea8be47f4058 Mon Sep 17 00:00:00 2001 From: "john.mortlock" Date: Fri, 26 Nov 2021 08:15:19 +1030 Subject: [PATCH 10/24] Remove deprecated depth method --- lib/tree/utils/metrics_methods.rb | 26 -------------------------- test/test_tree.rb | 30 ------------------------------ 2 files changed, 56 deletions(-) diff --git a/lib/tree/utils/metrics_methods.rb b/lib/tree/utils/metrics_methods.rb index a18d5b5..55be6e9 100644 --- a/lib/tree/utils/metrics_methods.rb +++ b/lib/tree/utils/metrics_methods.rb @@ -110,32 +110,6 @@ def level node_depth end - # @!attribute [r] depth - # Depth of the tree from this node. A single leaf node has a depth of 1. - # - # This method is *DEPRECATED* and may be removed in the subsequent - # releases. Note that the value returned by this method is actually the: - # - # _height_ + 1 of the node, *NOT* the _depth_. - # - # For correct and conventional behavior, please use {#node_depth} and - # {#node_height} methods instead. - # - # @return [Integer] depth of the node. - # - # @deprecated This method returns an incorrect value. Use the - # {#node_depth} method instead. - # - # @see #node_depth - def depth - warn StructuredWarnings::DeprecatedMethodWarning, - 'This method is deprecated. '\ - 'Please use node_depth() or node_height() instead (bug # 22535)' - - return 1 if is_leaf? - 1 + @children.collect { |child| child.depth }.max - end - # @!attribute [r] breadth # Breadth of the tree at this node's level. # A single node without siblings has a breadth of 1. diff --git a/test/test_tree.rb b/test/test_tree.rb index 15945a5..a1674a6 100755 --- a/test/test_tree.rb +++ b/test/test_tree.rb @@ -962,36 +962,6 @@ def test_content assert_same(person, @root.content, 'Content should be the same') end - # Test the depth computation algorithm. Note that this is an incorrect computation and actually returns height+1 - # instead of depth. This method has been deprecated in this release and may be removed in the future. - def test_depth - begin - require 'structured_warnings' - assert_warn(StructuredWarnings::DeprecatedMethodWarning) { do_deprecated_depth } - rescue LoadError - # Since the structured_warnings package is not present, we revert to good old Kernel#warn behavior. - do_deprecated_depth - end - end - - # Run the assertions for the deprecated depth method. - def do_deprecated_depth - assert_equal(1, @root.depth, "A single node's depth is 1") - - @root << @child1 - assert_equal(2, @root.depth, 'This should be of depth 2') - - @root << @child2 - assert_equal(2, @root.depth, 'This should be of depth 2') - - @child2 << @child3 - assert_equal(3, @root.depth, 'This should be of depth 3') - assert_equal(2, @child2.depth, 'This should be of depth 2') - - @child3 << @child4 - assert_equal(4, @root.depth, 'This should be of depth 4') - end - # Test the height computation algorithm def test_node_height assert_equal(0, @root.node_height, "A single node's height is 0") From 193e1048553bbcc5e07a254eb9655d106beea59f Mon Sep 17 00:00:00 2001 From: "john.mortlock" Date: Fri, 26 Nov 2021 08:26:32 +1030 Subject: [PATCH 11/24] Auto coerce integer names into string --- lib/tree.rb | 20 ++++---------------- 1 file changed, 4 insertions(+), 16 deletions(-) diff --git a/lib/tree.rb b/lib/tree.rb index 7b7ac20..7c38f1a 100644 --- a/lib/tree.rb +++ b/lib/tree.rb @@ -216,14 +216,9 @@ def has_children? # @see #[] def initialize(name, content = nil) raise ArgumentError, 'Node name HAS to be provided!' if name == nil - @name, @content = name, content - if name.kind_of?(Integer) - warn StructuredWarnings::StandardWarning, - 'Using integer as node name.'\ - ' Semantics of TreeNode[] may not be what you expect!'\ - " #{name} #{content}" - end + name = name.to_s if name.kind_of?(Integer) + @name, @content = name, content self.set_as_root! @children_hash = Hash.new @@ -592,24 +587,17 @@ def freeze_tree! # in not in range, or the name is not present, then a +nil+ # is returned. # - # @note The use of +Integer+ names is allowed by using the optional - # +num_as_name+ flag. - # # @raise [ArgumentError] Raised if the +name_or_index+ argument is +nil+. # # @see #add # @see #initialize - def [](name_or_index, num_as_name=false) + def [](name_or_index) raise ArgumentError, 'Name_or_index needs to be provided!' if name_or_index == nil - if name_or_index.kind_of?(Integer) and not num_as_name + if name_or_index.kind_of?(Integer) @children[name_or_index] else - if num_as_name and not name_or_index.kind_of?(Integer) - warn StructuredWarnings::StandardWarning, - 'Redundant use of the `num_as_name` flag for non-integer node name' - end @children_hash[name_or_index] end end From d8e4b4d04da382092d2196056d24c3aca977a94e Mon Sep 17 00:00:00 2001 From: "john.mortlock" Date: Fri, 26 Nov 2021 08:26:51 +1030 Subject: [PATCH 12/24] Remove structured warnings dependency and bump json --- lib/tree/tree_deps.rb | 1 - lib/tree/utils/metrics_methods.rb | 2 -- rubytree.gemspec | 3 +-- test/test_tree.rb | 36 ++++++------------------------- 4 files changed, 8 insertions(+), 34 deletions(-) diff --git a/lib/tree/tree_deps.rb b/lib/tree/tree_deps.rb index 4388969..385df56 100644 --- a/lib/tree/tree_deps.rb +++ b/lib/tree/tree_deps.rb @@ -37,7 +37,6 @@ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # -require 'structured_warnings' require 'json' require_relative '../tree/version' diff --git a/lib/tree/utils/metrics_methods.rb b/lib/tree/utils/metrics_methods.rb index 55be6e9..02ecd65 100644 --- a/lib/tree/utils/metrics_methods.rb +++ b/lib/tree/utils/metrics_methods.rb @@ -36,8 +36,6 @@ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # -require 'structured_warnings' - module Tree::Utils # Provides utility functions to measure various tree metrics. module TreeMetricsHandler diff --git a/rubytree.gemspec b/rubytree.gemspec index 538e8f0..8f6f0b6 100644 --- a/rubytree.gemspec +++ b/rubytree.gemspec @@ -65,8 +65,7 @@ Gem::Specification.new do |s| s.extra_rdoc_files = %w(README.md LICENSE.md API-CHANGES.rdoc History.rdoc) s.rdoc_options = ['--title', 'Rubytree Documentation', '--quiet'] - s.add_runtime_dependency 'structured_warnings' , '~> 0.4.0' - s.add_runtime_dependency 'json' , '~> 2.3.1' + s.add_runtime_dependency 'json' , '> 2.3.1' # Note: Rake is added as a development and test dependency in the Gemfile. s.add_development_dependency 'bundler' diff --git a/test/test_tree.rb b/test/test_tree.rb index a1674a6..548ed25 100755 --- a/test/test_tree.rb +++ b/test/test_tree.rb @@ -33,7 +33,6 @@ # require 'test/unit' -require 'structured_warnings' require 'json' require_relative '../lib/tree/tree_deps' @@ -304,17 +303,8 @@ def test_has_content_eh assert(a_node.has_content?, 'The node should now have content') end - # Test the equivalence of size and length methods. - def test_length_is_size - setup_test_tree - assert_equal(@root.size, @root.length, 'Length and size methods should return the same result') - end - # Test the <=> operator. def test_spaceship - require 'structured_warnings' - StructuredWarnings::StandardWarning.disable # Disable the warnings for using integers as node names - first_node = Tree::TreeNode.new(1) second_node = Tree::TreeNode.new(2) @@ -332,8 +322,6 @@ def test_spaceship second_node = Tree::TreeNode.new('ABC') assert_equal(0, first_node <=> second_node) - - StructuredWarnings::StandardWarning.enable end # Test the inclusion of Comparable @@ -1386,13 +1374,10 @@ def test_json_round_trip # Test usage of integers as node names def test_integer_node_names - require 'structured_warnings' - assert_warn(StructuredWarnings::StandardWarning) do - @n_root = Tree::TreeNode.new(0, 'Root Node') - @n_child1 = Tree::TreeNode.new(1, 'Child Node 1') - @n_child2 = Tree::TreeNode.new(2, 'Child Node 2') - @n_child3 = Tree::TreeNode.new('three', 'Child Node 3') - end + @n_root = Tree::TreeNode.new(0, 'Root Node') + @n_child1 = Tree::TreeNode.new(1, 'Child Node 1') + @n_child2 = Tree::TreeNode.new(2, 'Child Node 2') + @n_child3 = Tree::TreeNode.new('three', 'Child Node 3') @n_root << @n_child1 @n_root << @n_child2 @@ -1400,18 +1385,11 @@ def test_integer_node_names # Node[n] is really accessing the nth child with a zero-base assert_not_equal(@n_root[1].name, 1) # This is really the second child - assert_equal(@n_root[0].name, 1) # This will work, as it is the first child - assert_equal(@n_root[1, true].name, 1) # This will work, as the flag is now enabled + assert_equal(@n_root[0].name, "1") # This will work, as it is the first child + assert_equal(@n_root[1].name, "2") # This will work, as the flag is now enabled # Sanity check for the "normal" string name cases. Both cases should work. - assert_equal(@n_root['three', false].name, 'three') - - StructuredWarnings::StandardWarning.disable - assert_equal(@n_root['three', true].name, 'three') - - # Also ensure that the warning is actually being thrown - StructuredWarnings::StandardWarning.enable - assert_warn(StructuredWarnings::StandardWarning) {assert_equal(@n_root['three', true].name, 'three') } + assert_equal(@n_root['three'].name, 'three') end # Test the addition of a node to itself as a child From 63a8de61fb92433344db98e42ed36d2727eb0677 Mon Sep 17 00:00:00 2001 From: "john.mortlock" Date: Fri, 26 Nov 2021 08:34:35 +1030 Subject: [PATCH 13/24] Remove setup.rb --- setup.rb | 1584 ------------------------------------------------------ 1 file changed, 1584 deletions(-) delete mode 100644 setup.rb diff --git a/setup.rb b/setup.rb deleted file mode 100644 index 6531fd9..0000000 --- a/setup.rb +++ /dev/null @@ -1,1584 +0,0 @@ -# -# setup.rb -# -# Copyright (c) 2000-2005 Minero Aoki -# -# This program is free software. -# You can distribute/modify this program under the terms of -# the GNU LGPL, Lesser General Public License version 2.1. -# - -unless Enumerable.method_defined?(:map) # Ruby 1.4.6 - module Enumerable - alias map collect - end -end - -unless File.respond_to?(:read) # Ruby 1.6 - def File.read(fname) - open(fname) {|f| - return f.read - } - end -end - -unless Errno.const_defined?(:ENOTEMPTY) # Windows? - module Errno - class ENOTEMPTY - # We do not raise this exception, implementation is not needed. - end - end -end - -def File.binread(fname) - open(fname, 'rb') {|f| - return f.read - } -end - -# for corrupted Windows' stat(2) -def File.dir?(path) - File.directory?((path[-1,1] == '/') ? path : path + '/') -end - - -class ConfigTable - - include Enumerable - - def initialize(rbconfig) - @rbconfig = rbconfig - @items = [] - @table = {} - # options - @install_prefix = nil - @config_opt = nil - @verbose = true - @no_harm = false - end - - attr_accessor :install_prefix - attr_accessor :config_opt - - attr_writer :verbose - - def verbose? - @verbose - end - - attr_writer :no_harm - - def no_harm? - @no_harm - end - - def [](key) - lookup(key).resolve(self) - end - - def []=(key, val) - lookup(key).set val - end - - def names - @items.map {|i| i.name } - end - - def each(&block) - @items.each(&block) - end - - def key?(name) - @table.key?(name) - end - - def lookup(name) - @table[name] or setup_rb_error "no such config item: #{name}" - end - - def add(item) - @items.push item - @table[item.name] = item - end - - def remove(name) - item = lookup(name) - @items.delete_if {|i| i.name == name } - @table.delete_if {|name, i| i.name == name } - item - end - - def load_script(path, inst = nil) - if File.file?(path) - MetaConfigEnvironment.new(self, inst).instance_eval File.read(path), path - end - end - - def savefile - '.config' - end - - def load_savefile - begin - File.foreach(savefile()) do |line| - k, v = *line.split(/=/, 2) - self[k] = v.strip - end - rescue Errno::ENOENT - setup_rb_error $!.message + "\n#{File.basename($0)} config first" - end - end - - def save - @items.each {|i| i.value } - File.open(savefile(), 'w') {|f| - @items.each do |i| - f.printf "%s=%s\n", i.name, i.value if i.value? and i.value - end - } - end - - def load_standard_entries - standard_entries(@rbconfig).each do |ent| - add ent - end - end - - def standard_entries(rbconfig) - c = rbconfig - - rubypath = File.join(c['bindir'], c['ruby_install_name'] + c['EXEEXT']) - - major = c['MAJOR'].to_i - minor = c['MINOR'].to_i - teeny = c['TEENY'].to_i - version = "#{major}.#{minor}" - - # ruby ver. >= 1.4.4? - newpath_p = ((major >= 2) or - ((major == 1) and - ((minor >= 5) or - ((minor == 4) and (teeny >= 4))))) - - if c['rubylibdir'] - # V > 1.6.3 - libruby = "#{c['prefix']}/lib/ruby" - librubyver = c['rubylibdir'] - librubyverarch = c['archdir'] - siteruby = c['sitedir'] - siterubyver = c['sitelibdir'] - siterubyverarch = c['sitearchdir'] - elsif newpath_p - # 1.4.4 <= V <= 1.6.3 - libruby = "#{c['prefix']}/lib/ruby" - librubyver = "#{c['prefix']}/lib/ruby/#{version}" - librubyverarch = "#{c['prefix']}/lib/ruby/#{version}/#{c['arch']}" - siteruby = c['sitedir'] - siterubyver = "$siteruby/#{version}" - siterubyverarch = "$siterubyver/#{c['arch']}" - else - # V < 1.4.4 - libruby = "#{c['prefix']}/lib/ruby" - librubyver = "#{c['prefix']}/lib/ruby/#{version}" - librubyverarch = "#{c['prefix']}/lib/ruby/#{version}/#{c['arch']}" - siteruby = "#{c['prefix']}/lib/ruby/#{version}/site_ruby" - siterubyver = siteruby - siterubyverarch = "$siterubyver/#{c['arch']}" - end - parameterize = lambda {|path| - path.sub(/\A#{Regexp.quote(c['prefix'])}/, '$prefix') - } - - if arg = c['configure_args'].split.detect {|arg| /--with-make-prog=/ =~ arg } - makeprog = arg.sub(/'/, '').split(/=/, 2)[1] - else - makeprog = 'make' - end - - [ - ExecItem.new('installdirs', 'std/site/home', - 'std: install under libruby; site: install under site_ruby; home: install under $HOME')\ - {|val, table| - case val - when 'std' - table['rbdir'] = '$librubyver' - table['sodir'] = '$librubyverarch' - when 'site' - table['rbdir'] = '$siterubyver' - table['sodir'] = '$siterubyverarch' - when 'home' - setup_rb_error '$HOME was not set' unless ENV['HOME'] - table['prefix'] = ENV['HOME'] - table['rbdir'] = '$libdir/ruby' - table['sodir'] = '$libdir/ruby' - end - }, - PathItem.new('prefix', 'path', c['prefix'], - 'path prefix of target environment'), - PathItem.new('bindir', 'path', parameterize.call(c['bindir']), - 'the directory for commands'), - PathItem.new('libdir', 'path', parameterize.call(c['libdir']), - 'the directory for libraries'), - PathItem.new('datadir', 'path', parameterize.call(c['datadir']), - 'the directory for shared data'), - PathItem.new('mandir', 'path', parameterize.call(c['mandir']), - 'the directory for man pages'), - PathItem.new('sysconfdir', 'path', parameterize.call(c['sysconfdir']), - 'the directory for system configuration files'), - PathItem.new('localstatedir', 'path', parameterize.call(c['localstatedir']), - 'the directory for local state data'), - PathItem.new('libruby', 'path', libruby, - 'the directory for ruby libraries'), - PathItem.new('librubyver', 'path', librubyver, - 'the directory for standard ruby libraries'), - PathItem.new('librubyverarch', 'path', librubyverarch, - 'the directory for standard ruby extensions'), - PathItem.new('siteruby', 'path', siteruby, - 'the directory for version-independent aux ruby libraries'), - PathItem.new('siterubyver', 'path', siterubyver, - 'the directory for aux ruby libraries'), - PathItem.new('siterubyverarch', 'path', siterubyverarch, - 'the directory for aux ruby binaries'), - PathItem.new('rbdir', 'path', '$siterubyver', - 'the directory for ruby scripts'), - PathItem.new('sodir', 'path', '$siterubyverarch', - 'the directory for ruby extentions'), - PathItem.new('rubypath', 'path', rubypath, - 'the path to set to #! line'), - ProgramItem.new('rubyprog', 'name', rubypath, - 'the ruby program using for installation'), - ProgramItem.new('makeprog', 'name', makeprog, - 'the make program to compile ruby extentions'), - SelectItem.new('shebang', 'all/ruby/never', 'ruby', - 'shebang line (#!) editing mode'), - BoolItem.new('without-ext', 'yes/no', 'no', - 'does not compile/install ruby extentions') - ] - end - private :standard_entries - - def load_multipackage_entries - multipackage_entries().each do |ent| - add ent - end - end - - def multipackage_entries - [ - PackageSelectionItem.new('with', 'name,name...', '', 'ALL', - 'package names that you want to install'), - PackageSelectionItem.new('without', 'name,name...', '', 'NONE', - 'package names that you do not want to install') - ] - end - private :multipackage_entries - - ALIASES = { - 'std-ruby' => 'librubyver', - 'stdruby' => 'librubyver', - 'rubylibdir' => 'librubyver', - 'archdir' => 'librubyverarch', - 'site-ruby-common' => 'siteruby', # For backward compatibility - 'site-ruby' => 'siterubyver', # For backward compatibility - 'bin-dir' => 'bindir', - 'rb-dir' => 'rbdir', - 'so-dir' => 'sodir', - 'data-dir' => 'datadir', - 'ruby-path' => 'rubypath', - 'ruby-prog' => 'rubyprog', - 'ruby' => 'rubyprog', - 'make-prog' => 'makeprog', - 'make' => 'makeprog' - } - - def fixup - ALIASES.each do |ali, name| - @table[ali] = @table[name] - end - @items.freeze - @table.freeze - @options_re = /\A--(#{@table.keys.join('|')})(?:=(.*))?\z/ - end - - def parse_opt(opt) - m = @options_re.match(opt) or setup_rb_error "config: unknown option #{opt}" - m.to_a[1,2] - end - - def dllext - @rbconfig['DLEXT'] - end - - def value_config?(name) - lookup(name).value? - end - - class Item - def initialize(name, template, default, desc) - @name = name.freeze - @template = template - @value = default - @default = default - @description = desc - end - - attr_reader :name - attr_reader :description - - attr_accessor :default - alias help_default default - - def help_opt - "--#{@name}=#{@template}" - end - - def value? - true - end - - def value - @value - end - - def resolve(table) - @value.gsub(%r<\$([^/]+)>) { table[$1] } - end - - def set(val) - @value = check(val) - end - - private - - def check(val) - setup_rb_error "config: --#{name} requires argument" unless val - val - end - end - - class BoolItem < Item - def config_type - 'bool' - end - - def help_opt - "--#{@name}" - end - - private - - def check(val) - return 'yes' unless val - case val - when /\Ay(es)?\z/i, /\At(rue)?\z/i then 'yes' - when /\An(o)?\z/i, /\Af(alse)\z/i then 'no' - else - setup_rb_error "config: --#{@name} accepts only yes/no for argument" - end - end - end - - class PathItem < Item - def config_type - 'path' - end - - private - - def check(path) - setup_rb_error "config: --#{@name} requires argument" unless path - path[0,1] == '$' ? path : File.expand_path(path) - end - end - - class ProgramItem < Item - def config_type - 'program' - end - end - - class SelectItem < Item - def initialize(name, selection, default, desc) - super - @ok = selection.split('/') - end - - def config_type - 'select' - end - - private - - def check(val) - unless @ok.include?(val.strip) - setup_rb_error "config: use --#{@name}=#{@template} (#{val})" - end - val.strip - end - end - - class ExecItem < Item - def initialize(name, selection, desc, &block) - super name, selection, nil, desc - @ok = selection.split('/') - @action = block - end - - def config_type - 'exec' - end - - def value? - false - end - - def resolve(table) - setup_rb_error "$#{name()} wrongly used as option value" - end - - undef set - - def evaluate(val, table) - v = val.strip.downcase - unless @ok.include?(v) - setup_rb_error "invalid option --#{@name}=#{val} (use #{@template})" - end - @action.call v, table - end - end - - class PackageSelectionItem < Item - def initialize(name, template, default, help_default, desc) - super name, template, default, desc - @help_default = help_default - end - - attr_reader :help_default - - def config_type - 'package' - end - - private - - def check(val) - unless File.dir?("packages/#{val}") - setup_rb_error "config: no such package: #{val}" - end - val - end - end - - class MetaConfigEnvironment - def initialize(config, installer) - @config = config - @installer = installer - end - - def config_names - @config.names - end - - def config?(name) - @config.key?(name) - end - - def bool_config?(name) - @config.lookup(name).config_type == 'bool' - end - - def path_config?(name) - @config.lookup(name).config_type == 'path' - end - - def value_config?(name) - @config.lookup(name).config_type != 'exec' - end - - def add_config(item) - @config.add item - end - - def add_bool_config(name, default, desc) - @config.add BoolItem.new(name, 'yes/no', default ? 'yes' : 'no', desc) - end - - def add_path_config(name, default, desc) - @config.add PathItem.new(name, 'path', default, desc) - end - - def set_config_default(name, default) - @config.lookup(name).default = default - end - - def remove_config(name) - @config.remove(name) - end - - # For only multipackage - def packages - raise '[setup.rb fatal] multi-package metaconfig API packages() called for single-package; contact application package vendor' unless @installer - @installer.packages - end - - # For only multipackage - def declare_packages(list) - raise '[setup.rb fatal] multi-package metaconfig API declare_packages() called for single-package; contact application package vendor' unless @installer - @installer.packages = list - end - end - -end # class ConfigTable - - -# This module requires: #verbose?, #no_harm? -module FileOperations - - def mkdir_p(dirname, prefix = nil) - dirname = prefix + File.expand_path(dirname) if prefix - $stderr.puts "mkdir -p #{dirname}" if verbose? - return if no_harm? - - # Does not check '/', it's too abnormal. - dirs = File.expand_path(dirname).split(%r<(?=/)>) - if /\A[a-z]:\z/i =~ dirs[0] - disk = dirs.shift - dirs[0] = disk + dirs[0] - end - dirs.each_index do |idx| - path = dirs[0..idx].join('') - Dir.mkdir path unless File.dir?(path) - end - end - - def rm_f(path) - $stderr.puts "rm -f #{path}" if verbose? - return if no_harm? - force_remove_file path - end - - def rm_rf(path) - $stderr.puts "rm -rf #{path}" if verbose? - return if no_harm? - remove_tree path - end - - def remove_tree(path) - if File.symlink?(path) - remove_file path - elsif File.dir?(path) - remove_tree0 path - else - force_remove_file path - end - end - - def remove_tree0(path) - Dir.foreach(path) do |ent| - next if ent == '.' - next if ent == '..' - entpath = "#{path}/#{ent}" - if File.symlink?(entpath) - remove_file entpath - elsif File.dir?(entpath) - remove_tree0 entpath - else - force_remove_file entpath - end - end - begin - Dir.rmdir path - rescue Errno::ENOTEMPTY - # directory may not be empty - end - end - - def move_file(src, dest) - force_remove_file dest - begin - File.rename src, dest - rescue - File.open(dest, 'wb') {|f| - f.write File.binread(src) - } - File.chmod File.stat(src).mode, dest - File.unlink src - end - end - - def force_remove_file(path) - begin - remove_file path - rescue - end - end - - def remove_file(path) - File.chmod 0777, path - File.unlink path - end - - def install(from, dest, mode, prefix = nil) - $stderr.puts "install #{from} #{dest}" if verbose? - return if no_harm? - - realdest = prefix ? prefix + File.expand_path(dest) : dest - realdest = File.join(realdest, File.basename(from)) if File.dir?(realdest) - str = File.binread(from) - if diff?(str, realdest) - verbose_off { - rm_f realdest if File.exist?(realdest) - } - File.open(realdest, 'wb') {|f| - f.write str - } - File.chmod mode, realdest - - File.open("#{objdir_root()}/InstalledFiles", 'a') {|f| - if prefix - f.puts realdest.sub(prefix, '') - else - f.puts realdest - end - } - end - end - - def diff?(new_content, path) - return true unless File.exist?(path) - new_content != File.binread(path) - end - - def command(*args) - $stderr.puts args.join(' ') if verbose? - system(*args) or raise RuntimeError, - "system(#{args.map{|a| a.inspect }.join(' ')}) failed" - end - - def ruby(*args) - command config('rubyprog'), *args - end - - def make(task = nil) - command(*[config('makeprog'), task].compact) - end - - def extdir?(dir) - File.exist?("#{dir}/MANIFEST") or File.exist?("#{dir}/extconf.rb") - end - - def files_of(dir) - Dir.open(dir) {|d| - return d.select {|ent| File.file?("#{dir}/#{ent}") } - } - end - - DIR_REJECT = %w( . .. CVS SCCS RCS CVS.adm .svn ) - - def directories_of(dir) - Dir.open(dir) {|d| - return d.select {|ent| File.dir?("#{dir}/#{ent}") } - DIR_REJECT - } - end - -end - - -# This module requires: #srcdir_root, #objdir_root, #relpath -module HookScriptAPI - - def get_config(key) - @config[key] - end - - alias config get_config - - # obsolete: use metaconfig to change configuration - def set_config(key, val) - @config[key] = val - end - - # - # srcdir/objdir (works only in the package directory) - # - - def curr_srcdir - "#{srcdir_root()}/#{relpath()}" - end - - def curr_objdir - "#{objdir_root()}/#{relpath()}" - end - - def srcfile(path) - "#{curr_srcdir()}/#{path}" - end - - def srcexist?(path) - File.exist?(srcfile(path)) - end - - def srcdirectory?(path) - File.dir?(srcfile(path)) - end - - def srcfile?(path) - File.file?(srcfile(path)) - end - - def srcentries(path = '.') - Dir.open("#{curr_srcdir()}/#{path}") {|d| - return d.to_a - %w(. ..) - } - end - - def srcfiles(path = '.') - srcentries(path).select {|fname| - File.file?(File.join(curr_srcdir(), path, fname)) - } - end - - def srcdirectories(path = '.') - srcentries(path).select {|fname| - File.dir?(File.join(curr_srcdir(), path, fname)) - } - end - -end - - -class ToplevelInstaller - - Version = '3.4.1' - Copyright = 'Copyright (c) 2000-2005 Minero Aoki' - - TASKS = [ - [ 'all', 'do config, setup, then install' ], - [ 'config', 'saves your configurations' ], - [ 'show', 'shows current configuration' ], - [ 'setup', 'compiles ruby extentions and others' ], - [ 'install', 'installs files' ], - [ 'test', 'run all tests in test/' ], - [ 'clean', "does `make clean' for each extention" ], - [ 'distclean',"does `make distclean' for each extention" ] - ] - - def ToplevelInstaller.invoke - config = ConfigTable.new(load_rbconfig()) - config.load_standard_entries - config.load_multipackage_entries if multipackage? - config.fixup - klass = (multipackage?() ? ToplevelInstallerMulti : ToplevelInstaller) - klass.new(File.dirname($0), config).invoke - end - - def ToplevelInstaller.multipackage? - File.dir?(File.dirname($0) + '/packages') - end - - def ToplevelInstaller.load_rbconfig - if arg = ARGV.detect {|arg| /\A--rbconfig=/ =~ arg } - ARGV.delete(arg) - load File.expand_path(arg.split(/=/, 2)[1]) - $".push 'rbconfig.rb' - else - require 'rbconfig' - end - ::Config::CONFIG - end - - def initialize(ardir_root, config) - @ardir = File.expand_path(ardir_root) - @config = config - # cache - @valid_task_re = nil - end - - def config(key) - @config[key] - end - - def inspect - "#<#{self.class} #{__id__()}>" - end - - def invoke - run_metaconfigs - case task = parsearg_global() - when nil, 'all' - parsearg_config - init_installers - exec_config - exec_setup - exec_install - else - case task - when 'config', 'test' - ; - when 'clean', 'distclean' - @config.load_savefile if File.exist?(@config.savefile) - else - @config.load_savefile - end - __send__ "parsearg_#{task}" - init_installers - __send__ "exec_#{task}" - end - end - - def run_metaconfigs - @config.load_script "#{@ardir}/metaconfig" - end - - def init_installers - @installer = Installer.new(@config, @ardir, File.expand_path('.')) - end - - # - # Hook Script API bases - # - - def srcdir_root - @ardir - end - - def objdir_root - '.' - end - - def relpath - '.' - end - - # - # Option Parsing - # - - def parsearg_global - while arg = ARGV.shift - case arg - when /\A\w+\z/ - setup_rb_error "invalid task: #{arg}" unless valid_task?(arg) - return arg - when '-q', '--quiet' - @config.verbose = false - when '--verbose' - @config.verbose = true - when '--help' - print_usage $stdout - exit 0 - when '--version' - puts "#{File.basename($0)} version #{Version}" - exit 0 - when '--copyright' - puts Copyright - exit 0 - else - setup_rb_error "unknown global option '#{arg}'" - end - end - nil - end - - def valid_task?(t) - valid_task_re() =~ t - end - - def valid_task_re - @valid_task_re ||= /\A(?:#{TASKS.map {|task,desc| task }.join('|')})\z/ - end - - def parsearg_no_options - unless ARGV.empty? - task = caller(0).first.slice(%r<`parsearg_(\w+)'>, 1) - setup_rb_error "#{task}: unknown options: #{ARGV.join(' ')}" - end - end - - alias parsearg_show parsearg_no_options - alias parsearg_setup parsearg_no_options - alias parsearg_test parsearg_no_options - alias parsearg_clean parsearg_no_options - alias parsearg_distclean parsearg_no_options - - def parsearg_config - evalopt = [] - set = [] - @config.config_opt = [] - while i = ARGV.shift - if /\A--?\z/ =~ i - @config.config_opt = ARGV.dup - break - end - name, value = *@config.parse_opt(i) - if @config.value_config?(name) - @config[name] = value - else - evalopt.push [name, value] - end - set.push name - end - evalopt.each do |name, value| - @config.lookup(name).evaluate value, @config - end - # Check if configuration is valid - set.each do |n| - @config[n] if @config.value_config?(n) - end - end - - def parsearg_install - @config.no_harm = false - @config.install_prefix = '' - while a = ARGV.shift - case a - when '--no-harm' - @config.no_harm = true - when /\A--prefix=/ - path = a.split(/=/, 2)[1] - path = File.expand_path(path) unless path[0,1] == '/' - @config.install_prefix = path - else - setup_rb_error "install: unknown option #{a}" - end - end - end - - def print_usage(out) - out.puts 'Typical Installation Procedure:' - out.puts " $ ruby #{File.basename $0} config" - out.puts " $ ruby #{File.basename $0} setup" - out.puts " # ruby #{File.basename $0} install (may require root privilege)" - out.puts - out.puts 'Detailed Usage:' - out.puts " ruby #{File.basename $0} " - out.puts " ruby #{File.basename $0} [] []" - - fmt = " %-24s %s\n" - out.puts - out.puts 'Global options:' - out.printf fmt, '-q,--quiet', 'suppress message outputs' - out.printf fmt, ' --verbose', 'output messages verbosely' - out.printf fmt, ' --help', 'print this message' - out.printf fmt, ' --version', 'print version and quit' - out.printf fmt, ' --copyright', 'print copyright and quit' - out.puts - out.puts 'Tasks:' - TASKS.each do |name, desc| - out.printf fmt, name, desc - end - - fmt = " %-24s %s [%s]\n" - out.puts - out.puts 'Options for CONFIG or ALL:' - @config.each do |item| - out.printf fmt, item.help_opt, item.description, item.help_default - end - out.printf fmt, '--rbconfig=path', 'rbconfig.rb to load',"running ruby's" - out.puts - out.puts 'Options for INSTALL:' - out.printf fmt, '--no-harm', 'only display what to do if given', 'off' - out.printf fmt, '--prefix=path', 'install path prefix', '' - out.puts - end - - # - # Task Handlers - # - - def exec_config - @installer.exec_config - @config.save # must be final - end - - def exec_setup - @installer.exec_setup - end - - def exec_install - @installer.exec_install - end - - def exec_test - @installer.exec_test - end - - def exec_show - @config.each do |i| - printf "%-20s %s\n", i.name, i.value if i.value? - end - end - - def exec_clean - @installer.exec_clean - end - - def exec_distclean - @installer.exec_distclean - end - -end # class ToplevelInstaller - - -class ToplevelInstallerMulti < ToplevelInstaller - - include FileOperations - - def initialize(ardir_root, config) - super - @packages = directories_of("#{@ardir}/packages") - raise 'no package exists' if @packages.empty? - @root_installer = Installer.new(@config, @ardir, File.expand_path('.')) - end - - def run_metaconfigs - @config.load_script "#{@ardir}/metaconfig", self - @packages.each do |name| - @config.load_script "#{@ardir}/packages/#{name}/metaconfig" - end - end - - attr_reader :packages - - def packages=(list) - raise 'package list is empty' if list.empty? - list.each do |name| - raise "directory packages/#{name} does not exist"\ - unless File.dir?("#{@ardir}/packages/#{name}") - end - @packages = list - end - - def init_installers - @installers = {} - @packages.each do |pack| - @installers[pack] = Installer.new(@config, - "#{@ardir}/packages/#{pack}", - "packages/#{pack}") - end - with = extract_selection(config('with')) - without = extract_selection(config('without')) - @selected = @installers.keys.select {|name| - (with.empty? or with.include?(name)) \ - and not without.include?(name) - } - end - - def extract_selection(list) - a = list.split(/,/) - a.each do |name| - setup_rb_error "no such package: #{name}" unless @installers.key?(name) - end - a - end - - def print_usage(f) - super - f.puts 'Inluded packages:' - f.puts ' ' + @packages.sort.join(' ') - f.puts - end - - # - # Task Handlers - # - - def exec_config - run_hook 'pre-config' - each_selected_installers {|inst| inst.exec_config } - run_hook 'post-config' - @config.save # must be final - end - - def exec_setup - run_hook 'pre-setup' - each_selected_installers {|inst| inst.exec_setup } - run_hook 'post-setup' - end - - def exec_install - run_hook 'pre-install' - each_selected_installers {|inst| inst.exec_install } - run_hook 'post-install' - end - - def exec_test - run_hook 'pre-test' - each_selected_installers {|inst| inst.exec_test } - run_hook 'post-test' - end - - def exec_clean - rm_f @config.savefile - run_hook 'pre-clean' - each_selected_installers {|inst| inst.exec_clean } - run_hook 'post-clean' - end - - def exec_distclean - rm_f @config.savefile - run_hook 'pre-distclean' - each_selected_installers {|inst| inst.exec_distclean } - run_hook 'post-distclean' - end - - # - # lib - # - - def each_selected_installers - Dir.mkdir 'packages' unless File.dir?('packages') - @selected.each do |pack| - $stderr.puts "Processing the package `#{pack}' ..." if verbose? - Dir.mkdir "packages/#{pack}" unless File.dir?("packages/#{pack}") - Dir.chdir "packages/#{pack}" - yield @installers[pack] - Dir.chdir '../..' - end - end - - def run_hook(id) - @root_installer.run_hook id - end - - # module FileOperations requires this - def verbose? - @config.verbose? - end - - # module FileOperations requires this - def no_harm? - @config.no_harm? - end - -end # class ToplevelInstallerMulti - - -class Installer - - FILETYPES = %w( bin lib ext data conf man ) - - include FileOperations - include HookScriptAPI - - def initialize(config, srcroot, objroot) - @config = config - @srcdir = File.expand_path(srcroot) - @objdir = File.expand_path(objroot) - @currdir = '.' - end - - def inspect - "#<#{self.class} #{File.basename(@srcdir)}>" - end - - def noop(rel) - end - - # - # Hook Script API base methods - # - - def srcdir_root - @srcdir - end - - def objdir_root - @objdir - end - - def relpath - @currdir - end - - # - # Config Access - # - - # module FileOperations requires this - def verbose? - @config.verbose? - end - - # module FileOperations requires this - def no_harm? - @config.no_harm? - end - - def verbose_off - begin - save, @config.verbose = @config.verbose?, false - yield - ensure - @config.verbose = save - end - end - - # - # TASK config - # - - def exec_config - exec_task_traverse 'config' - end - - alias config_dir_bin noop - alias config_dir_lib noop - - def config_dir_ext(rel) - extconf if extdir?(curr_srcdir()) - end - - alias config_dir_data noop - alias config_dir_conf noop - alias config_dir_man noop - - def extconf - ruby "#{curr_srcdir()}/extconf.rb", *@config.config_opt - end - - # - # TASK setup - # - - def exec_setup - exec_task_traverse 'setup' - end - - def setup_dir_bin(rel) - files_of(curr_srcdir()).each do |fname| - update_shebang_line "#{curr_srcdir()}/#{fname}" - end - end - - alias setup_dir_lib noop - - def setup_dir_ext(rel) - make if extdir?(curr_srcdir()) - end - - alias setup_dir_data noop - alias setup_dir_conf noop - alias setup_dir_man noop - - def update_shebang_line(path) - return if no_harm? - return if config('shebang') == 'never' - old = Shebang.load(path) - if old - $stderr.puts "warning: #{path}: Shebang line includes too many args. It is not portable and your program may not work." if old.args.size > 1 - new = new_shebang(old) - return if new.to_s == old.to_s - else - return unless config('shebang') == 'all' - new = Shebang.new(config('rubypath')) - end - $stderr.puts "updating shebang: #{File.basename(path)}" if verbose? - open_atomic_writer(path) {|output| - File.open(path, 'rb') {|f| - f.gets if old # discard - output.puts new.to_s - output.print f.read - } - } - end - - def new_shebang(old) - if /\Aruby/ =~ File.basename(old.cmd) - Shebang.new(config('rubypath'), old.args) - elsif File.basename(old.cmd) == 'env' and old.args.first == 'ruby' - Shebang.new(config('rubypath'), old.args[1..-1]) - else - return old unless config('shebang') == 'all' - Shebang.new(config('rubypath')) - end - end - - def open_atomic_writer(path, &block) - tmpfile = File.basename(path) + '.tmp' - begin - File.open(tmpfile, 'wb', &block) - File.rename tmpfile, File.basename(path) - ensure - File.unlink tmpfile if File.exist?(tmpfile) - end - end - - class Shebang - def Shebang.load(path) - line = nil - File.open(path) {|f| - line = f.gets - } - return nil unless /\A#!/ =~ line - parse(line) - end - - def Shebang.parse(line) - cmd, *args = *line.strip.sub(/\A\#!/, '').split(' ') - new(cmd, args) - end - - def initialize(cmd, args = []) - @cmd = cmd - @args = args - end - - attr_reader :cmd - attr_reader :args - - def to_s - "#! #{@cmd}" + (@args.empty? ? '' : " #{@args.join(' ')}") - end - end - - # - # TASK install - # - - def exec_install - rm_f 'InstalledFiles' - exec_task_traverse 'install' - end - - def install_dir_bin(rel) - install_files targetfiles(), "#{config('bindir')}/#{rel}", 0755 - end - - def install_dir_lib(rel) - install_files libfiles(), "#{config('rbdir')}/#{rel}", 0644 - end - - def install_dir_ext(rel) - return unless extdir?(curr_srcdir()) - install_files rubyextentions('.'), - "#{config('sodir')}/#{File.dirname(rel)}", - 0555 - end - - def install_dir_data(rel) - install_files targetfiles(), "#{config('datadir')}/#{rel}", 0644 - end - - def install_dir_conf(rel) - # FIXME: should not remove current config files - # (rename previous file to .old/.org) - install_files targetfiles(), "#{config('sysconfdir')}/#{rel}", 0644 - end - - def install_dir_man(rel) - install_files targetfiles(), "#{config('mandir')}/#{rel}", 0644 - end - - def install_files(list, dest, mode) - mkdir_p dest, @config.install_prefix - list.each do |fname| - install fname, dest, mode, @config.install_prefix - end - end - - def libfiles - glob_reject(%w(*.y *.output), targetfiles()) - end - - def rubyextentions(dir) - ents = glob_select("*.#{@config.dllext}", targetfiles()) - if ents.empty? - setup_rb_error "no ruby extention exists: 'ruby #{$0} setup' first" - end - ents - end - - def targetfiles - mapdir(existfiles() - hookfiles()) - end - - def mapdir(ents) - ents.map {|ent| - if File.exist?(ent) - then ent # objdir - else "#{curr_srcdir()}/#{ent}" # srcdir - end - } - end - - # picked up many entries from cvs-1.11.1/src/ignore.c - JUNK_FILES = %w( - core RCSLOG tags TAGS .make.state - .nse_depinfo #* .#* cvslog.* ,* .del-* *.olb - *~ *.old *.bak *.BAK *.orig *.rej _$* *$ - - *.org *.in .* - ) - - def existfiles - glob_reject(JUNK_FILES, (files_of(curr_srcdir()) | files_of('.'))) - end - - def hookfiles - %w( pre-%s post-%s pre-%s.rb post-%s.rb ).map {|fmt| - %w( config setup install clean ).map {|t| sprintf(fmt, t) } - }.flatten - end - - def glob_select(pat, ents) - re = globs2re([pat]) - ents.select {|ent| re =~ ent } - end - - def glob_reject(pats, ents) - re = globs2re(pats) - ents.reject {|ent| re =~ ent } - end - - GLOB2REGEX = { - '.' => '\.', - '$' => '\$', - '#' => '\#', - '*' => '.*' - } - - def globs2re(pats) - /\A(?:#{ - pats.map {|pat| pat.gsub(/[\.\$\#\*]/) {|ch| GLOB2REGEX[ch] } }.join('|') - })\z/ - end - - # - # TASK test - # - - TESTDIR = 'test' - - def exec_test - unless File.directory?('test') - $stderr.puts 'no test in this package' if verbose? - return - end - $stderr.puts 'Running tests...' if verbose? - begin - require 'test/unit' - rescue LoadError - setup_rb_error 'test/unit cannot loaded. You need Ruby 1.8 or later to invoke this task.' - end - runner = Test::Unit::AutoRunner.new(true) - runner.to_run << TESTDIR - runner.run - end - - # - # TASK clean - # - - def exec_clean - exec_task_traverse 'clean' - rm_f @config.savefile - rm_f 'InstalledFiles' - end - - alias clean_dir_bin noop - alias clean_dir_lib noop - alias clean_dir_data noop - alias clean_dir_conf noop - alias clean_dir_man noop - - def clean_dir_ext(rel) - return unless extdir?(curr_srcdir()) - make 'clean' if File.file?('Makefile') - end - - # - # TASK distclean - # - - def exec_distclean - exec_task_traverse 'distclean' - rm_f @config.savefile - rm_f 'InstalledFiles' - end - - alias distclean_dir_bin noop - alias distclean_dir_lib noop - - def distclean_dir_ext(rel) - return unless extdir?(curr_srcdir()) - make 'distclean' if File.file?('Makefile') - end - - alias distclean_dir_data noop - alias distclean_dir_conf noop - alias distclean_dir_man noop - - # - # Traversing - # - - def exec_task_traverse(task) - run_hook "pre-#{task}" - FILETYPES.each do |type| - if type == 'ext' and config('without-ext') == 'yes' - $stderr.puts 'skipping ext/* by user option' if verbose? - next - end - traverse task, type, "#{task}_dir_#{type}" - end - run_hook "post-#{task}" - end - - def traverse(task, rel, mid) - dive_into(rel) { - run_hook "pre-#{task}" - __send__ mid, rel.sub(%r[\A.*?(?:/|\z)], '') - directories_of(curr_srcdir()).each do |d| - traverse task, "#{rel}/#{d}", mid - end - run_hook "post-#{task}" - } - end - - def dive_into(rel) - return unless File.dir?("#{@srcdir}/#{rel}") - - dir = File.basename(rel) - Dir.mkdir dir unless File.dir?(dir) - prevdir = Dir.pwd - Dir.chdir dir - $stderr.puts '---> ' + rel if verbose? - @currdir = rel - yield - Dir.chdir prevdir - $stderr.puts '<--- ' + rel if verbose? - @currdir = File.dirname(rel) - end - - def run_hook(id) - path = [ "#{curr_srcdir()}/#{id}", - "#{curr_srcdir()}/#{id}.rb" ].detect {|cand| File.file?(cand) } - return unless path - begin - instance_eval File.read(path), path, 1 - rescue - raise if $DEBUG - setup_rb_error "hook #{path} failed:\n" + $!.message - end - end - -end # class Installer - - -class SetupError < StandardError; end - -def setup_rb_error(msg) - raise SetupError, msg -end - -if $0 == __FILE__ - begin - ToplevelInstaller.invoke - rescue SetupError - raise if $DEBUG - $stderr.puts $!.message - $stderr.puts "Try 'ruby #{$0} --help' for detailed usage." - exit 1 - end -end From 118d48bfde4ba718def88016bf9ec64bdd6d3d91 Mon Sep 17 00:00:00 2001 From: "john.mortlock" Date: Fri, 26 Nov 2021 08:35:30 +1030 Subject: [PATCH 14/24] Add dependabot config --- .github/workflows/dependabot.yml | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 .github/workflows/dependabot.yml diff --git a/.github/workflows/dependabot.yml b/.github/workflows/dependabot.yml new file mode 100644 index 0000000..4695914 --- /dev/null +++ b/.github/workflows/dependabot.yml @@ -0,0 +1,6 @@ +version: 2 +updates: + - package-ecosystem: "bundler" + directory: "/" + schedule: + interval: "daily" From e65134ba8fcb37154fc24c8b6b833020390cf797 Mon Sep 17 00:00:00 2001 From: Anupam Sengupta Date: Mon, 13 Jun 2022 21:49:19 -0400 Subject: [PATCH 15/24] Reverted development Ruby version to 2.7.2. We need to keep supporting the 2.7.x version for sometime. The tests will be now performed against multiple Ruby versions. Added the `RVM` gemset support for RubyTree. This should have been added quite some time ago. --- .ruby-gemset | 1 + .ruby-version | 2 +- Gemfile.lock | 30 +++++++++++++++--------------- 3 files changed, 17 insertions(+), 16 deletions(-) create mode 100644 .ruby-gemset diff --git a/.ruby-gemset b/.ruby-gemset new file mode 100644 index 0000000..002089b --- /dev/null +++ b/.ruby-gemset @@ -0,0 +1 @@ +rubytree diff --git a/.ruby-version b/.ruby-version index 75a22a2..2eb2fe9 100644 --- a/.ruby-version +++ b/.ruby-version @@ -1 +1 @@ -3.0.3 +ruby-2.7.2 diff --git a/Gemfile.lock b/Gemfile.lock index bb53da3..f664305 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -8,34 +8,34 @@ GEM remote: https://rubygems.org/ specs: diff-lcs (1.5.0) - json (2.6.1) + json (2.6.2) power_assert (2.0.1) - psych (4.0.3) + psych (4.0.4) stringio rake (13.0.6) rdoc (6.4.0) psych (>= 4.0.0) - rspec (3.10.0) - rspec-core (~> 3.10.0) - rspec-expectations (~> 3.10.0) - rspec-mocks (~> 3.10.0) - rspec-core (3.10.1) - rspec-support (~> 3.10.0) - rspec-expectations (3.10.1) + rspec (3.11.0) + rspec-core (~> 3.11.0) + rspec-expectations (~> 3.11.0) + rspec-mocks (~> 3.11.0) + rspec-core (3.11.0) + rspec-support (~> 3.11.0) + rspec-expectations (3.11.0) diff-lcs (>= 1.2.0, < 2.0) - rspec-support (~> 3.10.0) - rspec-mocks (3.10.2) + rspec-support (~> 3.11.0) + rspec-mocks (3.11.1) diff-lcs (>= 1.2.0, < 2.0) - rspec-support (~> 3.10.0) - rspec-support (3.10.3) + rspec-support (~> 3.11.0) + rspec-support (3.11.0) rtags (0.97) rtagstask (0.0.4) rtags (> 0.0.0) - stringio (3.0.1) + stringio (3.0.2) test-unit (3.5.3) power_assert webrick (1.7.0) - yard (0.9.27) + yard (0.9.28) webrick (~> 1.7.0) PLATFORMS From 7420941abacd9940d33251d4a0bae12b7ab139cd Mon Sep 17 00:00:00 2001 From: Anupam Sengupta Date: Sun, 19 Jun 2022 12:38:49 -0400 Subject: [PATCH 16/24] Added the empty `.gemtest` file to support testing the packaged gem. --- .gemtest | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 .gemtest diff --git a/.gemtest b/.gemtest new file mode 100644 index 0000000..e69de29 From ff65eb31d777b305e3e1eed11dd20db861cfd6cb Mon Sep 17 00:00:00 2001 From: Anupam Sengupta Date: Sun, 19 Jun 2022 12:39:30 -0400 Subject: [PATCH 17/24] Updated the version to `2.0.0.pre`. --- lib/tree/version.rb | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/lib/tree/version.rb b/lib/tree/version.rb index 6c8ac29..a8d2937 100644 --- a/lib/tree/version.rb +++ b/lib/tree/version.rb @@ -4,9 +4,7 @@ # # Author:: Anupam Sengupta (anupamsg@gmail.com) # -# Copyright (c) 2012, 2013, 2014, 2015, 2017, 2020, 2021 Anupam Sengupta -# -# All rights reserved. +# Copyright (c) 2012-2022 Anupam Sengupta. All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: @@ -36,5 +34,5 @@ module Tree # Rubytree Package Version - VERSION = '1.0.2'.freeze + VERSION = '2.0.0.pre'.freeze end From e1aabdbe148e632f24688b48bd403aebb695439f Mon Sep 17 00:00:00 2001 From: Anupam Sengupta Date: Sun, 19 Jun 2022 12:40:44 -0400 Subject: [PATCH 18/24] Updated the Gemspec and Rakefile to include the optional rubocop linter. Also made minor refactoring of the gem's metadata and other cleanup in the Rakefile. --- Rakefile | 39 +++++++++++++++++++++++++-------------- rubytree.gemspec | 23 ++++++++++++++--------- 2 files changed, 39 insertions(+), 23 deletions(-) diff --git a/Rakefile b/Rakefile index d49bbd2..b54e3d6 100644 --- a/Rakefile +++ b/Rakefile @@ -2,7 +2,7 @@ # # Rakefile - This file is part of the RubyTree package. # -# Copyright (c) 2006-2021 Anupam Sengupta +# Copyright (c) 2006-2022 Anupam Sengupta # # All rights reserved. # @@ -95,10 +95,13 @@ namespace :doc do # ................................ Documentation end end -desc 'Run the test cases' -task test: 'test:unit' +desc 'Run the unit tests' +task test: %w[test:unit] namespace :test do # ................................ Test related + desc 'Run all the tests' + task all: %w[test:unit test:spec test:examples] + require 'rake/testtask' Rake::TestTask.new(:unit) do |test| test.libs << 'lib' << 'test' @@ -106,6 +109,17 @@ namespace :test do # ................................ Test related test.verbose = false end + begin # ................................ rspec tests + require 'rspec/core/rake_task' + + RSpec::Core::RakeTask.new(:spec) do |t| + t.fail_on_error = false + t.rspec_opts = ['--color', '--format doc'] + end + rescue LoadError + # Cannot load rspec. + end + desc 'Run the examples' Rake::TestTask.new(:examples) do |example| example.libs << 'lib' << 'examples' @@ -132,17 +146,6 @@ namespace :test do # ................................ Test related end end -begin # ................................ rspec tests - require 'rspec/core/rake_task' - - RSpec::Core::RakeTask.new(:spec) do |t| - t.fail_on_error = false - t.rspec_opts = ['--color', '--format doc'] - end -rescue LoadError - # Cannot load rspec. -end - namespace :tag do # ................................ Emacs Tags require 'rtagstask' RTagsTask.new(:tags) do |rd| @@ -165,3 +168,11 @@ namespace :gem do # ................................ Gem related sh "gem push pkg/#{GEM_NAME}" end end + +require 'rubocop/rake_task' # ................................ Ruby linting + +RuboCop::RakeTask.new(:rubocop) do |t| + t.options = ['--display-cop-names'] + t.requires << 'rubocop-rake' + t.requires << 'rubocop-rspec' +end diff --git a/rubytree.gemspec b/rubytree.gemspec index 816d210..afbb464 100644 --- a/rubytree.gemspec +++ b/rubytree.gemspec @@ -3,14 +3,13 @@ # # Author:: Anupam Sengupta (anupamsg@gmail.com) # -# Copyright (c) 2012, 2013, 2014, 2015, 2017, 2020, 2021, 2022 Anupam Sengupta -# All rights reserved. +# Copyright (c) 2012-2022 Anupam Sengupta. All rights reserved. require './lib/tree/version' Gem::Specification.new do |s| s.name = 'rubytree' - s.date = '2021-12-29' + s.date = '2022-06-21' s.version = Tree::VERSION s.license = 'BSD-3-Clause-Clear' @@ -22,7 +21,8 @@ Gem::Specification.new do |s| s.required_ruby_version = '>=2.6' s.summary = 'A generic tree data structure.' - s.description = <<-END_OF_TEXT + # TODO: Check if this can be formatted in Markdown or RD. + s.description = <<-EOF RubyTree is a pure Ruby implementation of the generic tree data structure. It provides a node-based model to store named nodes in the tree, and provides @@ -47,7 +47,7 @@ Gem::Specification.new do |s| The home page for RubyTree is at http://rubytree.anupamsg.me. - END_OF_TEXT + EOF s.files = Dir['lib/**/*.rb'] # The actual code s.files += Dir['[A-Z]*'] # Various documentation files @@ -55,6 +55,7 @@ Gem::Specification.new do |s| s.files += Dir['spec/**/*.rb'] # Rspec Test cases s.files += Dir['examples/**/*.rb'] # Examples + # TODO: Check if this is really needed. s.files += ['.gemtest'] # Support for gem-test s.require_paths = ['lib'] @@ -64,7 +65,7 @@ Gem::Specification.new do |s| s.extra_rdoc_files = %w[README.md LICENSE.md API-CHANGES.rdoc History.rdoc] s.rdoc_options = ['--title', 'Rubytree Documentation', '--quiet'] - s.add_runtime_dependency 'json' , '> 2.3.1' + s.add_runtime_dependency 'json', '> 2.3.1' # Note: Rake is added as a development and test dependency in the Gemfile. s.add_development_dependency 'bundler' @@ -74,15 +75,19 @@ Gem::Specification.new do |s| s.add_development_dependency 'rspec' s.add_development_dependency "rake" s.add_development_dependency "test-unit" - + s.add_development_dependency "rubocop" + s.add_development_dependency "rubocop-rake" + s.add_development_dependency "rubocop-rspec" s.post_install_message = <<-EOF ======================================================================== Thank you for installing RubyTree. - Note:: As of 1.0.1, RubyTree can only support MRI Ruby >= 2.7.x + Note:: + + - 2.0.0 is a major release with BREAKING API changes. + See `API-CHANGES.rdoc` for details. - Details of the API changes are documented in the API-CHANGES file. ======================================================================== EOF end From d25f47388a3f69cab68af3f179aef85e3435c8ce Mon Sep 17 00:00:00 2001 From: Anupam Sengupta Date: Sun, 19 Jun 2022 12:42:08 -0400 Subject: [PATCH 19/24] Attributed the modernization changes to @jmortlock. Updated the copyright year. --- LICENSE.md | 2 +- README.md | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/LICENSE.md b/LICENSE.md index 8fcac8e..0a872aa 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -1,6 +1,6 @@ [RubyTree][] is licensed under the [BSD][] license. -Copyright (c) 2006-2021 Anupam Sengupta (). +Copyright (c) 2006-2022 Anupam Sengupta (). All rights reserved. diff --git a/README.md b/README.md index 2ec0fe0..604e019 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # **RubyTree** # @@ -121,7 +121,6 @@ This example can also be found at * Run-time Dependencies: - * [structured_warnings][] * [JSON][] for converting to/from the JSON format @@ -223,6 +222,8 @@ A big thanks to the following contributors for helping improve **RubyTree**: to `is_root?` and `node_depth`. 10. [Marco Ziccadi](https://github.com/MZic) for adding the `path_as_string` and `path_as_array` methods. +11. [John Mortlock](https://github.com/jmortlock) for significant modernization + of the library code and addition of Github `workflows`. ## LICENSE: ## From d993c84e479a4b2cd1814eca4b61a0ddaa24c2f3 Mon Sep 17 00:00:00 2001 From: Anupam Sengupta Date: Sun, 19 Jun 2022 12:43:00 -0400 Subject: [PATCH 20/24] Updated the dependencies. --- Gemfile.lock | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/Gemfile.lock b/Gemfile.lock index f664305..b9d16be 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,20 +1,27 @@ PATH remote: . specs: - rubytree (1.0.2) + rubytree (2.0.0.pre) json (> 2.3.1) GEM remote: https://rubygems.org/ specs: + ast (2.4.2) diff-lcs (1.5.0) json (2.6.2) + parallel (1.21.0) + parser (3.0.3.2) + ast (~> 2.4.1) power_assert (2.0.1) psych (4.0.4) stringio + rainbow (3.0.0) rake (13.0.6) rdoc (6.4.0) psych (>= 4.0.0) + regexp_parser (2.2.0) + rexml (3.2.5) rspec (3.11.0) rspec-core (~> 3.11.0) rspec-expectations (~> 3.11.0) @@ -31,9 +38,26 @@ GEM rtags (0.97) rtagstask (0.0.4) rtags (> 0.0.0) + rubocop (1.24.0) + parallel (~> 1.10) + parser (>= 3.0.0.0) + rainbow (>= 2.2.2, < 4.0) + regexp_parser (>= 1.8, < 3.0) + rexml + rubocop-ast (>= 1.15.0, < 2.0) + ruby-progressbar (~> 1.7) + unicode-display_width (>= 1.4.0, < 3.0) + rubocop-ast (1.15.1) + parser (>= 3.0.1.1) + rubocop-rake (0.6.0) + rubocop (~> 1.0) + rubocop-rspec (2.11.1) + rubocop (~> 1.19) + ruby-progressbar (1.11.0) stringio (3.0.2) test-unit (3.5.3) power_assert + unicode-display_width (2.1.0) webrick (1.7.0) yard (0.9.28) webrick (~> 1.7.0) @@ -47,6 +71,9 @@ DEPENDENCIES rdoc rspec rtagstask + rubocop + rubocop-rake + rubocop-rspec rubytree! test-unit yard From c5cad4ea8486f8c86b106bda9da0098550d84695 Mon Sep 17 00:00:00 2001 From: Anupam Sengupta Date: Sun, 19 Jun 2022 12:43:16 -0400 Subject: [PATCH 21/24] Updated the TODOs for the project and restructured the content. This file will eventually be ported over to Github issues. --- TODO.org | 27 ++++++++++----------------- 1 file changed, 10 insertions(+), 17 deletions(-) diff --git a/TODO.org b/TODO.org index 1f039c4..9eb3dc7 100644 --- a/TODO.org +++ b/TODO.org @@ -183,10 +183,7 @@ This proposed change does make sense at one level (since the root node does not have any parent), but returning root as root's root (no pun intended) makes accessing the root from anywhere in the tree much easier. - - - -* R0.9.5 +* R0.9.5 :ARCHIVE: ** DONE Add the `#get_path_as_string` method from feature request #48 :ARCHIVE: CLOSED: [2015-05-30 Sat 15:55] ** DONE Fix [[Issue:32][Issue #32]] and enable move semantics on the TreeNode#add method. :ARCHIVE: @@ -202,11 +199,9 @@ CLOSED: [2014-11-01 Sat 20:11] - - -* Next Release - DEADLINE: <2014-12-01 Mon> -** STARTED [#A] Resolve the infinite loop bug if a node is added to itself as a child :Partial: +* Unplanned / Not assigned to any release +*** STARTED Convert all documentation to markdown mode. +*** STARTED [#A] Resolve the infinite loop bug if a node is added to itself as a child :Partial: [[Issue:5][Issue #5.]] This is a subtle problem to resolve. The specific case of a node @@ -237,15 +232,8 @@ duplicates). This needs to be a hash (to allow O(1) access), and will sacrifice memory. There might be a need to restructure the internals to make better use of memory. -** STARTED Convert all documentation to markdown mode. -** TODO Expand the examples section, and add supporting documentation +*** TODO Expand the examples section, and add supporting documentation -* Unplanned / Not assigned to any release -*** DONE [#A] Migrate the website and references from http://rubyforge.org/ :ARCHIVE: - CLOSED: [2014-07-04 Fri 22:18] -*** DONE Revert the forced install of rubygem 2.1.11 from [[file:.travis.yml][.travis.yml]] :ARCHIVE: - CLOSED: [2014-01-12 Sun 19:06] - The issue seems to have been resolved with the 2.2.1 release of Rubygems. *** TODO Create a cycle-detection/validation mechanism to prevent cyclic graphs of nodes. *** TODO Create a generic validation method to check for various issues in the created tree. *** TODO Add a FAQ document to the project. @@ -258,6 +246,11 @@ *** TODO Add a YAML export method to the TreeNode class. *** TODO marshal_load method probably should be a class method. It currently clobbers self. +*** DONE Revert the forced install of rubygem 2.1.11 from [[file:.travis.yml][.travis.yml]] :ARCHIVE: + CLOSED: [2014-01-12 Sun 19:06] + The issue seems to have been resolved with the 2.2.1 release of Rubygems. +*** DONE [#A] Migrate the website and references from http://rubyforge.org/ :ARCHIVE: + CLOSED: [2014-07-04 Fri 22:18] *** DONE Fix bug # [[http://rubyforge.org/tracker/index.php%3Ffunc%3Ddetail&aid%3D22535&group_id%3D1215&atid%3D4793][22535]]: The method Tree::TreeNode#depth is a misnomer. The current definition actually provides the height function. :ARCHIVE: DEADLINE: <2010-01-09 Sat> CLOSED: [2010-01-03 Sun 22:15] From 17082a2fcb06bff2c6b84d0cc1e2a6e6b2a7a931 Mon Sep 17 00:00:00 2001 From: Anupam Sengupta Date: Sun, 19 Jun 2022 14:15:09 -0400 Subject: [PATCH 22/24] Updated the documentation for release 2.0.0.pre. --- API-CHANGES.rdoc | 17 ++++++++++++++++- History.rdoc | 18 +++++++++++++++++- README.md | 13 +++++++------ TODO.org | 11 +++++++++++ lib/tree.rb | 13 +++---------- rubytree.gemspec | 15 +++++++++++++-- test/test_tree.rb | 7 +++---- 7 files changed, 70 insertions(+), 24 deletions(-) diff --git a/API-CHANGES.rdoc b/API-CHANGES.rdoc index b63932c..49df347 100644 --- a/API-CHANGES.rdoc +++ b/API-CHANGES.rdoc @@ -9,6 +9,22 @@ Note: API level changes are expected to reduce dramatically after the 1.x release. In most cases, an alternative will be provided to ensure relatively smooth transition to the new APIs. +== Release 2.0.0 Changes + +- The minimum required Ruby version is now '2.6.x' (and higher). + +- The long-broken 'Tree::TreeNode#depth' method has been finally removed. Use + {Tree::TreeNode#node_depth}[rdoc-ref:Tree::Utils::TreeMetricsHandler#node_depth] instead. + +- Support for 'CamelCase' methods has been removed. This was a legacy shim that + has hopefully outlived its usefulness. + +- Use of integers as node-names now no longer requires the optional + 'num_as_name' flag. + +- 'structured_warnings' has been removed from the code-base and is no longer a + dependency. This was a long-standing point of friction for many users. + == Release 0.9.5 Changes - The {Tree::TreeNode#add} method now provides 'move' semantics, if a child @@ -95,5 +111,4 @@ smooth transition to the new APIs. # Local Variables: # mode: rdoc -# coding: utf-8-unix # End: diff --git a/History.rdoc b/History.rdoc index e9e0f68..a0cb18a 100644 --- a/History.rdoc +++ b/History.rdoc @@ -1,9 +1,25 @@ = History of Changes +=== 2.0.0 / 2022-06-21 + +* A major release with significant modernization to the code base and removal of + legacy cruft, thanks to {https://github.com/jmortlock jmortlock}. + +* The long deprecated {Tree::TreeNode#depth} method has finally been removed. + Use {Tree::TreeNode#node_depth} instead. + +* Support for CamelCase methods has been dropped. + +* RubyTree now supports MRI Ruby versions 2.6.x, 2,7,x, and 3.0,x. + +* Explicit support for rbx Ruby has been removed. + +* RubyTree now uses Github Actions for its CI pipeline. + === 1.0.2 / 2021-12-29 * A minor maintenance version to address a minor but annoying warning for -circular dependencies. + circular dependencies. === 1.0.1 / 2021-12-29 diff --git a/README.md b/README.md index 604e019..ce5ab75 100644 --- a/README.md +++ b/README.md @@ -54,7 +54,7 @@ See the [API][rt_doc] documentation for more details. # # example_basic.rb:: Basic usage of the tree library. # -# Copyright (C) 2013-2021 Anupam Sengupta +# Copyright (C) 2013-2022 Anupam Sengupta # # The following example implements this tree structure: # @@ -117,7 +117,7 @@ This example can also be found at ## REQUIREMENTS: ## -* [Ruby][] 2.7.x+ +* [Ruby][] 2.6.x and above. * Run-time Dependencies: @@ -129,6 +129,7 @@ This example can also be found at * [Rake][] for building the package * [Yard][] for the documentation * [RSpec][] for additional Ruby Spec test files + * [Rubocop][] for linting the code. ## INSTALL: ## @@ -192,9 +193,9 @@ After checking out the source, run: $ gem install bundler $ bundle install - $ rake test - $ rake doc:yard - $ rake gem:package + $ bundle exec rake test:all + $ bundle exec rake doc:yard + $ bundle exec rake gem:package These steps will install any missing dependencies, run the tests/specs, generate the documentation, and finally generate the gem file. @@ -260,8 +261,8 @@ A big thanks to the following contributors for helping improve **RubyTree**: [rt_doc]: http://rubytree.anupamsg.me/rdoc "RubyTree Documentation" [rt_gem]: http://rubygems.org/gems/rubytree "RubyTree Gem" [rt_site]: http://rubytree.anupamsg.me "RubyTree Site" -[structured_warnings]: http://github.com/schmidt/structured_warnings "structured_warnings" [tree_data_structure]: http://en.wikipedia.org/wiki/Tree_data_structure "Tree Data Structure" [RSpec]: https://relishapp.com/rspec/ +[Rubocop]: https://rubocop.org [![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/evolve75/rubytree/trend.png)](https://bitdeli.com/free "Bitdeli Badge") diff --git a/TODO.org b/TODO.org index 9eb3dc7..938f3dc 100644 --- a/TODO.org +++ b/TODO.org @@ -199,6 +199,17 @@ CLOSED: [2014-11-01 Sat 20:11] +* R2.0.0 + + This is primarily a *modernization* of the library, with removal of deprecated methods, the much-hated dependency on + ~structured_warnings~, and cleanup of other cruft. + + In addition, the CI pipeline has been moved from to ~Github Actions~. + +- [X] Merge the modernization PR from @jmortlock (multiple changes). +- [X] Update the documentation to reflect the modernization changes. + + * Unplanned / Not assigned to any release *** STARTED Convert all documentation to markdown mode. *** STARTED [#A] Resolve the infinite loop bug if a node is added to itself as a child :Partial: diff --git a/lib/tree.rb b/lib/tree.rb index 26dd883..923e089 100644 --- a/lib/tree.rb +++ b/lib/tree.rb @@ -552,24 +552,17 @@ def freeze_tree! # # - If the +name+ argument is an _Integer_, then the in-sequence # array of children is accessed using the argument as the - # *index* (zero-based). However, if the second _optional_ - # +num_as_name+ argument is +true+, then the +name+ is used - # literally as a name, and *NOT* as an *index* + # *index* (zero-based). # # - If the +name+ argument is *NOT* an _Integer_, then it is taken to # be the *name* of the child node to be returned. # - # If a non-+Integer+ +name+ is passed, and the +num_as_name+ - # parameter is also +true+, then a warning is thrown (as this is a - # redundant use of the +num_as_name+ flag.) + # - To use an _Integer_ as the name, convert it to a _String_ first using + # +.to_s+. # # @param [String|Number] name_or_index Name of the child, or its # positional index in the array of child nodes. # - # @param [Boolean] num_as_name Whether to treat the +Integer+ - # +name+ argument as an actual name, and *NOT* as an _index_ to - # the children array. - # # @return [Tree::TreeNode] the requested child node. If the index # in not in range, or the name is not present, then a +nil+ # is returned. diff --git a/rubytree.gemspec b/rubytree.gemspec index afbb464..d54a743 100644 --- a/rubytree.gemspec +++ b/rubytree.gemspec @@ -21,7 +21,7 @@ Gem::Specification.new do |s| s.required_ruby_version = '>=2.6' s.summary = 'A generic tree data structure.' - # TODO: Check if this can be formatted in Markdown or RD. + # @todo: Check if this can be formatted in Markdown or RD. s.description = <<-EOF RubyTree is a pure Ruby implementation of the generic tree data structure. It @@ -55,7 +55,7 @@ Gem::Specification.new do |s| s.files += Dir['spec/**/*.rb'] # Rspec Test cases s.files += Dir['examples/**/*.rb'] # Examples - # TODO: Check if this is really needed. + # @todo: Check if this is really needed. s.files += ['.gemtest'] # Support for gem-test s.require_paths = ['lib'] @@ -88,6 +88,17 @@ Gem::Specification.new do |s| - 2.0.0 is a major release with BREAKING API changes. See `API-CHANGES.rdoc` for details. + - `Tree::TreeNode#depth` method has been removed (it was broken). + + - Support for `CamelCase` methods names has bee removed. + + - Use of integers as node names does not require the optional + `num_as_name` flag. + + - `structured_warnings` is no longer a dependency. + + - Explicit support for rbx Ruby has been removed. + ======================================================================== EOF end diff --git a/test/test_tree.rb b/test/test_tree.rb index 2fc8632..bb2ea63 100755 --- a/test/test_tree.rb +++ b/test/test_tree.rb @@ -109,7 +109,7 @@ def test_root_setup def test_root setup_test_tree - # TODO: Should probably change this logic. Root's root should + # @todo: Should probably change this logic. Root's root should # return nil so that the possibility of a recursive error does not exist # at all. assert_same(@root, @root.root, "Root's root is self") @@ -370,7 +370,7 @@ def test_to_s def test_first_sibling setup_test_tree - # TODO: Need to fix the first_sibling method to return nil for nodes with no siblings. + # @todo: Need to fix the first_sibling method to return nil for nodes with no siblings. assert_same(@root, @root.first_sibling, "Root's first sibling is itself") assert_same(@child1, @child1.first_sibling, "Child1's first sibling is itself") assert_same(@child1, @child2.first_sibling, "Child2's first sibling should be child1") @@ -960,8 +960,7 @@ def test_node_height assert_equal(0, @child4.node_height, 'This should be of height 0') end - # Test the depth computation algorithm. Note that this is the correct depth computation. The original - # Tree::TreeNode#depth was incorrectly computing the height of the node - instead of its depth. + # Test the depth computation algorithm. def test_node_depth assert_equal(0, @root.node_depth, "A root node's depth is 0") From 9b8b0dc2610bc328701e09245b70ab1a43ae1e7e Mon Sep 17 00:00:00 2001 From: Anupam Sengupta Date: Sun, 19 Jun 2022 14:37:14 -0400 Subject: [PATCH 23/24] Updated the Github Actions. --- .github/workflows/dependabot.yml | 4 ++++ .github/workflows/ruby.yml | 6 +++++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/.github/workflows/dependabot.yml b/.github/workflows/dependabot.yml index 4695914..695f25b 100644 --- a/.github/workflows/dependabot.yml +++ b/.github/workflows/dependabot.yml @@ -1,3 +1,7 @@ +# Check the dependencies for vulnerabilities. +# +# This runs as a Github Action + version: 2 updates: - package-ecosystem: "bundler" diff --git a/.github/workflows/ruby.yml b/.github/workflows/ruby.yml index 809c8e5..327ba5d 100644 --- a/.github/workflows/ruby.yml +++ b/.github/workflows/ruby.yml @@ -1,3 +1,7 @@ +# Build and test the RubyTree library. +# +# This runs as a Github Action. + name: Build and Test on: [push, pull_request] jobs: @@ -13,4 +17,4 @@ jobs: with: ruby-version: ${{ matrix.ruby }} bundler-cache: true - - run: bundle exec rake + - run: bundle exec rake clobber test:all gem:package From 4bdf7cee0612eb1d527887a0ac2625588994eacd Mon Sep 17 00:00:00 2001 From: Anupam Sengupta Date: Sun, 19 Jun 2022 14:41:02 -0400 Subject: [PATCH 24/24] Removed the dependabot.yml file. This will be setup separately via the Github UI. --- .github/workflows/dependabot.yml | 10 ---------- 1 file changed, 10 deletions(-) delete mode 100644 .github/workflows/dependabot.yml diff --git a/.github/workflows/dependabot.yml b/.github/workflows/dependabot.yml deleted file mode 100644 index 695f25b..0000000 --- a/.github/workflows/dependabot.yml +++ /dev/null @@ -1,10 +0,0 @@ -# Check the dependencies for vulnerabilities. -# -# This runs as a Github Action - -version: 2 -updates: - - package-ecosystem: "bundler" - directory: "/" - schedule: - interval: "daily"