diff --git a/lib/git/path.rb b/lib/git/path.rb index 32b3baa4..066f39db 100644 --- a/lib/git/path.rb +++ b/lib/git/path.rb @@ -9,17 +9,7 @@ module Git class Path attr_accessor :path - def initialize(path, check_path = nil, must_exist: nil) - unless check_path.nil? - Git::Deprecation.warn( - 'The "check_path" argument is deprecated and ' \ - 'will be removed in a future version. Use "must_exist:" instead.' - ) - end - - # default is true - must_exist = must_exist.nil? && check_path.nil? ? true : must_exist || check_path - + def initialize(path, must_exist: true) path = File.expand_path(path) raise ArgumentError, 'path does not exist', [path] if must_exist && !File.exist?(path) diff --git a/lib/git/stash.rb b/lib/git/stash.rb index 2e9af43b..4762fe2a 100644 --- a/lib/git/stash.rb +++ b/lib/git/stash.rb @@ -3,16 +3,7 @@ module Git # A stash in a Git repository class Stash - def initialize(base, message, existing = nil, save: nil) - unless existing.nil? - Git::Deprecation.warn( - 'The "existing" argument is deprecated and will be removed in a future version. Use "save:" instead.' - ) - end - - # default is false - save = existing.nil? && save.nil? ? false : save | existing - + def initialize(base, message, save: false) @base = base @message = message self.save unless save diff --git a/tests/test_helper.rb b/tests/test_helper.rb index aa42eedd..0e6ac89f 100644 --- a/tests/test_helper.rb +++ b/tests/test_helper.rb @@ -13,14 +13,14 @@ $stderr.sync = true # Make tests that emit a deprecation warning fail - +# # Deprecation warnings should not be ignored. - +# # This is important so that: # * when a user sees a deprecation warning, they can be confident it is coming from # their code and not this gem # * test output is clean and does not contain noisey deprecation warnings - +# # Tests whose purpose is to test that a deprecation warning is issued in the right # circumstance should mock Git::Deprecation#warn to avoid raising an error. # diff --git a/tests/units/test_log_deprecations.rb b/tests/units/test_log_deprecations.rb new file mode 100644 index 00000000..ed945a99 --- /dev/null +++ b/tests/units/test_log_deprecations.rb @@ -0,0 +1,82 @@ +# frozen_string_literal: true + +require 'test_helper' +require 'git' +require 'fileutils' +require 'tmpdir' + +# A test case to verify the deprecation warnings for methods on the Git::Log class. +class LogDeprecationsTest < Test::Unit::TestCase + # Set up a temporary Git repository with a single commit before each test. + def setup + @repo_path = Dir.mktmpdir('git_test') + @repo = Git.init(@repo_path) + + # Create a commit so the log has an entry to work with. + Dir.chdir(@repo_path) do + File.write('file.txt', 'content') + @repo.add('file.txt') + @repo.commit('Initial commit') + end + + @log = @repo.log + @first_commit = @repo.gcommit('HEAD') + end + + # Clean up the temporary repository after each test. + def teardown + FileUtils.rm_rf(@repo_path) + end + + # Test the deprecation warning and functionality of Git::Log#each + def test_each_deprecation + Git::Deprecation.expects(:warn).with( + 'Calling Git::Log#each is deprecated. Call #execute and then #each on the result object.' + ) + + commits = @log.map { |c| c } + + assert_equal(1, commits.size, 'The #each method should still yield the correct number of commits.') + assert_equal(@first_commit.sha, commits.first.sha, 'The yielded commit should have the correct SHA.') + end + + # Test the deprecation warning and functionality of Git::Log#size + def test_size_deprecation + Git::Deprecation.expects(:warn).with( + 'Calling Git::Log#size is deprecated. Call #execute and then #size on the result object.' + ) + assert_equal(1, @log.size, 'The #size method should still return the correct number of commits.') + end + + # Test the deprecation warning and functionality of Git::Log#to_s + def test_to_s_deprecation + Git::Deprecation.expects(:warn).with( + 'Calling Git::Log#to_s is deprecated. Call #execute and then #to_s on the result object.' + ) + assert_equal(@first_commit.sha, @log.to_s, 'The #to_s method should return the commit SHA.') + end + + # Test the deprecation warning and functionality of Git::Log#first + def test_first_deprecation + Git::Deprecation.expects(:warn).with( + 'Calling Git::Log#first is deprecated. Call #execute and then #first on the result object.' + ) + assert_equal(@first_commit.sha, @log.first.sha, 'The #first method should return the correct commit.') + end + + # Test the deprecation warning and functionality of Git::Log#last + def test_last_deprecation + Git::Deprecation.expects(:warn).with( + 'Calling Git::Log#last is deprecated. Call #execute and then #last on the result object.' + ) + assert_equal(@first_commit.sha, @log.last.sha, 'The #last method should return the correct commit.') + end + + # Test the deprecation warning and functionality of Git::Log#[] + def test_indexer_deprecation + Git::Deprecation.expects(:warn).with( + 'Calling Git::Log#[] is deprecated. Call #execute and then #[] on the result object.' + ) + assert_equal(@first_commit.sha, @log[0].sha, 'The #[] method should return the correct commit at the specified index.') + end +end diff --git a/tests/units/test_object_new.rb b/tests/units/test_object_new.rb new file mode 100644 index 00000000..052bf728 --- /dev/null +++ b/tests/units/test_object_new.rb @@ -0,0 +1,72 @@ +# frozen_string_literal: true + +require 'test_helper' +require 'git' +require 'fileutils' +require 'tmpdir' + +# A test case to verify the functionality of the Git::Object.new factory method. +class ObjectNewTest < Test::Unit::TestCase + # Set up a temporary Git repository with objects of different types. + def setup + @repo_path = Dir.mktmpdir('git_test') + @repo = Git.init(@repo_path) + + Dir.chdir(@repo_path) do + File.write('file.txt', 'This is a test file.') + @repo.add('file.txt') + @repo.commit('Initial commit') + @repo.add_tag('v1.0', message: 'Version 1.0', annotate: true) + end + + @commit = @repo.gcommit('HEAD') + @tree = @commit.gtree + @blob = @tree.blobs['file.txt'] + @tag = @repo.tag('v1.0') + end + + # Clean up the temporary repository after each test. + def teardown + FileUtils.rm_rf(@repo_path) + end + + # Test that the factory method creates a Git::Object::Commit for a commit SHA. + def test_new_creates_commit_object + object = Git::Object.new(@repo, @commit.sha) + assert_instance_of(Git::Object::Commit, object, 'Should create a Commit object.') + assert(object.commit?, 'Object#commit? should be true.') + end + + # Test that the factory method creates a Git::Object::Tree for a tree SHA. + def test_new_creates_tree_object + object = Git::Object.new(@repo, @tree.sha) + assert_instance_of(Git::Object::Tree, object, 'Should create a Tree object.') + assert(object.tree?, 'Object#tree? should be true.') + end + + # Test that the factory method creates a Git::Object::Blob for a blob SHA. + def test_new_creates_blob_object + object = Git::Object.new(@repo, @blob.sha) + assert_instance_of(Git::Object::Blob, object, 'Should create a Blob object.') + assert(object.blob?, 'Object#blob? should be true.') + end + + # Test that using the deprecated `is_tag` argument creates a Tag object + # and issues a deprecation warning. + def test_new_with_is_tag_deprecation + # Set up the mock expectation for the deprecation warning. + Git::Deprecation.expects(:warn).with( + 'Git::Object.new with is_tag argument is deprecated. Use Git::Object::Tag.new instead.' + ) + + # Action: Call the factory method with the deprecated argument. + # The `objectish` here is the tag name, as was the old pattern. + tag_object = Git::Object.new(@repo, 'v1.0', nil, true) + + # Verification + assert_instance_of(Git::Object::Tag, tag_object, 'Should create a Tag object.') + assert(tag_object.tag?, 'Object#tag? should be true.') + assert_equal('v1.0', tag_object.name, 'Tag object should have the correct name.') + # Mocha automatically verifies the expectation at the end of the test. + end +end diff --git a/tests/units/test_set_index.rb b/tests/units/test_set_index.rb new file mode 100644 index 00000000..e8721bfa --- /dev/null +++ b/tests/units/test_set_index.rb @@ -0,0 +1,167 @@ +# frozen_string_literal: true + +require 'test_helper' +require 'git' +require 'fileutils' +require 'tmpdir' + +# A test case to demonstrate the use of Git::Base#set_index +# +# This test case will to programmatically create a new commit without affecting the +# main working directory or index. +# +class SetIndexTest < Test::Unit::TestCase + # Set up a temporary Git repository before each test. + def setup + # Create a temporary directory for the repository + @repo_path = Dir.mktmpdir('git_test') + + # Initialize a new Git repository in the temporary directory + @repo = Git.init(@repo_path) + + # Change into the repo directory to perform file operations + Dir.chdir(@repo_path) do + # Create and commit an initial file to establish a HEAD and a root tree. + # This gives us a base state to work from. + File.write('file1.txt', 'This is the first file.') + @repo.add('file1.txt') + @repo.commit('Initial commit') + end + end + + attr_reader :repo_path, :repo + + # Clean up the temporary repository after each test. + def teardown + FileUtils.rm_rf(repo_path) + end + + # Tests that `set_index` can point to a new, non-existent index file + # when `must_exist: false` is specified. + def test_set_index_with_must_exist_false_for_new_path + custom_index_path = File.join(repo_path, 'custom_index') + assert(!File.exist?(custom_index_path), 'Precondition: Custom index file should not exist.') + + # Action: Set the index to a new path, allowing it to not exist. + repo.set_index(custom_index_path, must_exist: false) + + # Verification: The repo object should now point to the new index path. + assert_equal(custom_index_path, repo.index.path, 'Index path should be updated to the custom path.') + end + + # Tests that `set_index` successfully points to an existing index file + # when `must_exist: true` is specified. + def test_set_index_with_must_exist_true_for_existing_path + original_index_path = repo.index.path + assert(File.exist?(original_index_path), 'Precondition: Original index file should exist.') + + # Action: Set the index to the same, existing path, explicitly requiring it to exist. + repo.set_index(original_index_path, must_exist: true) + + # Verification: The index path should remain unchanged. + assert_equal(original_index_path, repo.index.path, 'Index path should still be the original path.') + end + + # Tests that `set_index` raises an ArgumentError when trying to point to a + # non-existent index file with the default behavior (`must_exist: true`). + def test_set_index_with_must_exist_true_raises_error_for_new_path + non_existent_path = File.join(repo_path, 'no_such_file') + assert(!File.exist?(non_existent_path), 'Precondition: The target index path should not exist.') + + # Action & Verification: Assert that an ArgumentError is raised. + assert_raise(ArgumentError, 'Should raise ArgumentError for a non-existent index path.') do + repo.set_index(non_existent_path) # must_exist defaults to true + end + end + + # Tests that using the deprecated `check` argument issues a warning via mocking. + def test_set_index_with_deprecated_check_argument + custom_index_path = File.join(repo_path, 'custom_index') + assert(!File.exist?(custom_index_path), 'Precondition: Custom index file should not exist.') + + # Set up the mock expectation. + # We expect Git::Deprecation.warn to be called once with a message + # matching the expected deprecation warning. + Git::Deprecation.expects(:warn).with( + regexp_matches(/The "check" argument is deprecated/) + ) + + # Action: Use the deprecated positional argument `check = false` + repo.set_index(custom_index_path, false) + + # Verification: The repo object should still point to the new index path. + assert_equal(custom_index_path, repo.index.path, 'Index path should be updated even with deprecated argument.') + # Mocha automatically verifies the expectation at the end of the test. + end + + # This test demonstrates creating a new commit on a new branch by + # manipulating a custom, temporary index file. This allows for building + # commits programmatically without touching the working directory or the + # default .git/index. + def test_programmatic_commit_with_set_index + # 1. Get the initial commit object to use as a parent for our new commit. + main_commit = repo.gcommit('main') + assert(!main_commit.nil?, 'Initial commit should exist.') + + # 2. Define a path for a new, temporary index file within the repo directory. + custom_index_path = File.join(repo_path, 'custom_index') + assert(!File.exist?(custom_index_path), 'Custom index file should not exist yet.') + + # 3. Point the git object to use our custom index file. + # Since the file doesn't exist yet, we must pass `must_exist: false`. + repo.set_index(custom_index_path, must_exist: false) + assert_equal(custom_index_path, repo.index.path, 'The git object should now be using the custom index.') + + # 4. Populate the new index by reading the tree from our initial commit into it. + # This stages all the files from the 'main' commit in our custom index. + repo.read_tree(main_commit.gtree.sha) + + # 5. Programmatically create a new file blob and add it to our custom index. + # This simulates `git add` for a new file, but operates directly on the index. + new_content = 'This is a brand new file.' + blob_sha = Tempfile.create('new_blob_content') do |file| + file.write(new_content) + file.rewind + # Use `git hash-object -w` to write the blob to the object database and get its SHA + repo.lib.send(:command, 'hash-object', '-w', file.path) + end + repo.lib.send(:command, 'update-index', '--add', '--cacheinfo', "100644,#{blob_sha},new_file.txt") + + # 6. Write the state of the custom index to a new tree object in the Git database. + new_tree_sha = repo.write_tree + assert_match(/^[0-9a-f]{40}$/, new_tree_sha, 'A new tree SHA should be created.') + + # 7. Create a new commit object from the new tree. + # This commit will have the initial commit as its parent. + new_commit = repo.commit_tree( + new_tree_sha, + parents: [main_commit.sha], + message: 'Commit created programmatically via custom index' + ) + assert(new_commit.commit?, 'A new commit object should be created.') + + # 8. Create a new branch pointing to our new commit. + repo.branch('feature-branch').update_ref(new_commit) + assert(repo.branch('feature-branch').gcommit.sha == new_commit.sha, 'feature-branch should point to the new commit.') + + # --- Verification --- + # Verify the history of the new branch + feature_log = repo.log.object('feature-branch').execute + main_commit_sha = repo.rev_parse('main') # Get SHA directly for reliable comparison + + assert_equal(2, feature_log.size, 'Feature branch should have two commits.') + assert_equal(new_commit.sha, feature_log.first.sha, 'HEAD of feature-branch should be our new commit.') + assert_equal(main_commit_sha, feature_log.last.sha, 'Parent of new commit should be the initial commit.') + + # Verify that the main branch is unchanged + main_log = repo.log.object('main').execute + assert_equal(1, main_log.size, 'Main branch should still have one commit.') + assert_equal(main_commit_sha, main_log.first.sha, 'Main branch should still point to the initial commit.') + + # Verify the contents of the new commit's tree + new_commit_tree = new_commit.gtree + assert(new_commit_tree.blobs.key?('file1.txt'), 'Original file should exist in the new tree.') + assert(new_commit_tree.blobs.key?('new_file.txt'), 'New file should exist in the new tree.') + assert_equal(new_content, new_commit_tree.blobs['new_file.txt'].contents, 'Content of new file should match.') + end +end diff --git a/tests/units/test_set_working.rb b/tests/units/test_set_working.rb new file mode 100644 index 00000000..dfe781e1 --- /dev/null +++ b/tests/units/test_set_working.rb @@ -0,0 +1,83 @@ +# frozen_string_literal: true + +require 'test_helper' +require 'git' +require 'fileutils' +require 'tmpdir' + +# A test case to demonstrate the use of Git::Base#set_working +class SetWorkingTest < Test::Unit::TestCase + # Set up a temporary Git repository before each test. + def setup + # Create a temporary directory for the repository + @repo_path = Dir.mktmpdir('git_test') + + # Initialize a new Git repository in the temporary directory + @repo = Git.init(@repo_path) + end + + attr_reader :repo_path, :repo + + # Clean up the temporary repository after each test. + def teardown + FileUtils.rm_rf(repo_path) + end + + # Tests that `set_working` can point to a new, non-existent directory + # when `must_exist: false` is specified. + def test_set_working_with_must_exist_false_for_new_path + custom_working_path = File.join(repo_path, 'custom_work_dir') + assert(!File.exist?(custom_working_path), 'Precondition: Custom working directory should not exist.') + + # Action: Set the working directory to a new path, allowing it to not exist. + repo.set_working(custom_working_path, must_exist: false) + + # Verification: The repo object should now point to the new working directory path. + assert_equal(custom_working_path, repo.dir.path, 'Working directory path should be updated to the custom path.') + end + + # Tests that `set_working` successfully points to an existing directory + # when `must_exist: true` is specified. + def test_set_working_with_must_exist_true_for_existing_path + original_working_path = repo.dir.path + assert(File.exist?(original_working_path), 'Precondition: Original working directory should exist.') + + # Action: Set the working directory to the same, existing path, explicitly requiring it to exist. + repo.set_working(original_working_path, must_exist: true) + + # Verification: The working directory path should remain unchanged. + assert_equal(original_working_path, repo.dir.path, 'Working directory path should still be the original path.') + end + + # Tests that `set_working` raises an ArgumentError when trying to point to a + # non-existent directory with the default behavior (`must_exist: true`). + def test_set_working_with_must_exist_true_raises_error_for_new_path + non_existent_path = File.join(repo_path, 'no_such_dir') + assert(!File.exist?(non_existent_path), 'Precondition: The target working directory path should not exist.') + + # Action & Verification: Assert that an ArgumentError is raised. + assert_raise(ArgumentError, 'Should raise ArgumentError for a non-existent working directory path.') do + repo.set_working(non_existent_path) # must_exist defaults to true + end + end + + # Tests that using the deprecated `check` argument issues a warning via mocking. + def test_set_working_with_deprecated_check_argument + custom_working_path = File.join(repo_path, 'custom_work_dir') + assert(!File.exist?(custom_working_path), 'Precondition: Custom working directory should not exist.') + + # Set up the mock expectation. + # We expect Git::Deprecation.warn to be called once with a message + # matching the expected deprecation warning. + Git::Deprecation.expects(:warn).with( + regexp_matches(/The "check" argument is deprecated/) + ) + + # Action: Use the deprecated positional argument `check = false` + repo.set_working(custom_working_path, false) + + # Verification: The repo object should still point to the new working directory path. + assert_equal(custom_working_path, repo.dir.path, 'Working directory path should be updated even with deprecated argument.') + # Mocha automatically verifies the expectation at the end of the test. + end +end
Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.
Alternative Proxies: