Skip to content

Commit e6ccb11

Browse files
committed
test: add tests for Git::Base#set_index including deprecation
1 parent ab17621 commit e6ccb11

File tree

1 file changed

+167
-0
lines changed

1 file changed

+167
-0
lines changed

tests/units/test_set_index.rb

Lines changed: 167 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,167 @@
1+
# frozen_string_literal: true
2+
3+
require 'test_helper'
4+
require 'git'
5+
require 'fileutils'
6+
require 'tmpdir'
7+
8+
# A test case to demonstrate the use of Git::Base#set_index
9+
#
10+
# This test case will to programmatically create a new commit without affecting the
11+
# main working directory or index.
12+
#
13+
class SetIndexTest < Test::Unit::TestCase
14+
# Set up a temporary Git repository before each test.
15+
def setup
16+
# Create a temporary directory for the repository
17+
@repo_path = Dir.mktmpdir('git_test')
18+
19+
# Initialize a new Git repository in the temporary directory
20+
@repo = Git.init(@repo_path)
21+
22+
# Change into the repo directory to perform file operations
23+
Dir.chdir(@repo_path) do
24+
# Create and commit an initial file to establish a HEAD and a root tree.
25+
# This gives us a base state to work from.
26+
File.write('file1.txt', 'This is the first file.')
27+
@repo.add('file1.txt')
28+
@repo.commit('Initial commit')
29+
end
30+
end
31+
32+
attr_reader :repo_path, :repo
33+
34+
# Clean up the temporary repository after each test.
35+
def teardown
36+
FileUtils.rm_rf(repo_path)
37+
end
38+
39+
# Tests that `set_index` can point to a new, non-existent index file
40+
# when `must_exist: false` is specified.
41+
def test_set_index_with_must_exist_false_for_new_path
42+
custom_index_path = File.join(repo_path, 'custom_index')
43+
assert(!File.exist?(custom_index_path), 'Precondition: Custom index file should not exist.')
44+
45+
# Action: Set the index to a new path, allowing it to not exist.
46+
repo.set_index(custom_index_path, must_exist: false)
47+
48+
# Verification: The repo object should now point to the new index path.
49+
assert_equal(custom_index_path, repo.index.path, 'Index path should be updated to the custom path.')
50+
end
51+
52+
# Tests that `set_index` successfully points to an existing index file
53+
# when `must_exist: true` is specified.
54+
def test_set_index_with_must_exist_true_for_existing_path
55+
original_index_path = repo.index.path
56+
assert(File.exist?(original_index_path), 'Precondition: Original index file should exist.')
57+
58+
# Action: Set the index to the same, existing path, explicitly requiring it to exist.
59+
repo.set_index(original_index_path, must_exist: true)
60+
61+
# Verification: The index path should remain unchanged.
62+
assert_equal(original_index_path, repo.index.path, 'Index path should still be the original path.')
63+
end
64+
65+
# Tests that `set_index` raises an ArgumentError when trying to point to a
66+
# non-existent index file with the default behavior (`must_exist: true`).
67+
def test_set_index_with_must_exist_true_raises_error_for_new_path
68+
non_existent_path = File.join(repo_path, 'no_such_file')
69+
assert(!File.exist?(non_existent_path), 'Precondition: The target index path should not exist.')
70+
71+
# Action & Verification: Assert that an ArgumentError is raised.
72+
assert_raise(ArgumentError, 'Should raise ArgumentError for a non-existent index path.') do
73+
repo.set_index(non_existent_path) # must_exist defaults to true
74+
end
75+
end
76+
77+
# Tests that using the deprecated `check` argument issues a warning via mocking.
78+
def test_set_index_with_deprecated_check_argument
79+
custom_index_path = File.join(repo_path, 'custom_index')
80+
assert(!File.exist?(custom_index_path), 'Precondition: Custom index file should not exist.')
81+
82+
# Set up the mock expectation.
83+
# We expect Git::Deprecation.warn to be called once with a message
84+
# matching the expected deprecation warning.
85+
Git::Deprecation.expects(:warn).with(
86+
regexp_matches(/The "check" argument is deprecated/)
87+
)
88+
89+
# Action: Use the deprecated positional argument `check = false`
90+
repo.set_index(custom_index_path, false)
91+
92+
# Verification: The repo object should still point to the new index path.
93+
assert_equal(custom_index_path, repo.index.path, 'Index path should be updated even with deprecated argument.')
94+
# Mocha automatically verifies the expectation at the end of the test.
95+
end
96+
97+
# This test demonstrates creating a new commit on a new branch by
98+
# manipulating a custom, temporary index file. This allows for building
99+
# commits programmatically without touching the working directory or the
100+
# default .git/index.
101+
def test_programmatic_commit_with_set_index
102+
# 1. Get the initial commit object to use as a parent for our new commit.
103+
main_commit = repo.gcommit('main')
104+
assert(!main_commit.nil?, 'Initial commit should exist.')
105+
106+
# 2. Define a path for a new, temporary index file within the repo directory.
107+
custom_index_path = File.join(repo_path, 'custom_index')
108+
assert(!File.exist?(custom_index_path), 'Custom index file should not exist yet.')
109+
110+
# 3. Point the git object to use our custom index file.
111+
# Since the file doesn't exist yet, we must pass `must_exist: false`.
112+
repo.set_index(custom_index_path, must_exist: false)
113+
assert_equal(custom_index_path, repo.index.path, 'The git object should now be using the custom index.')
114+
115+
# 4. Populate the new index by reading the tree from our initial commit into it.
116+
# This stages all the files from the 'main' commit in our custom index.
117+
repo.read_tree(main_commit.gtree.sha)
118+
119+
# 5. Programmatically create a new file blob and add it to our custom index.
120+
# This simulates `git add` for a new file, but operates directly on the index.
121+
new_content = 'This is a brand new file.'
122+
blob_sha = Tempfile.create('new_blob_content') do |file|
123+
file.write(new_content)
124+
file.rewind
125+
# Use `git hash-object -w` to write the blob to the object database and get its SHA
126+
repo.lib.send(:command, 'hash-object', '-w', file.path)
127+
end
128+
repo.lib.send(:command, 'update-index', '--add', '--cacheinfo', "100644,#{blob_sha},new_file.txt")
129+
130+
# 6. Write the state of the custom index to a new tree object in the Git database.
131+
new_tree_sha = repo.write_tree
132+
assert_match(/^[0-9a-f]{40}$/, new_tree_sha, 'A new tree SHA should be created.')
133+
134+
# 7. Create a new commit object from the new tree.
135+
# This commit will have the initial commit as its parent.
136+
new_commit = repo.commit_tree(
137+
new_tree_sha,
138+
parents: [main_commit.sha],
139+
message: 'Commit created programmatically via custom index'
140+
)
141+
assert(new_commit.commit?, 'A new commit object should be created.')
142+
143+
# 8. Create a new branch pointing to our new commit.
144+
repo.branch('feature-branch').update_ref(new_commit)
145+
assert(repo.branch('feature-branch').gcommit.sha == new_commit.sha, 'feature-branch should point to the new commit.')
146+
147+
# --- Verification ---
148+
# Verify the history of the new branch
149+
feature_log = repo.log.object('feature-branch').execute
150+
main_commit_sha = repo.rev_parse('main') # Get SHA directly for reliable comparison
151+
152+
assert_equal(2, feature_log.size, 'Feature branch should have two commits.')
153+
assert_equal(new_commit.sha, feature_log.first.sha, 'HEAD of feature-branch should be our new commit.')
154+
assert_equal(main_commit_sha, feature_log.last.sha, 'Parent of new commit should be the initial commit.')
155+
156+
# Verify that the main branch is unchanged
157+
main_log = repo.log.object('main').execute
158+
assert_equal(1, main_log.size, 'Main branch should still have one commit.')
159+
assert_equal(main_commit_sha, main_log.first.sha, 'Main branch should still point to the initial commit.')
160+
161+
# Verify the contents of the new commit's tree
162+
new_commit_tree = new_commit.gtree
163+
assert(new_commit_tree.blobs.key?('file1.txt'), 'Original file should exist in the new tree.')
164+
assert(new_commit_tree.blobs.key?('new_file.txt'), 'New file should exist in the new tree.')
165+
assert_equal(new_content, new_commit_tree.blobs['new_file.txt'].contents, 'Content of new file should match.')
166+
end
167+
end

0 commit comments

Comments
 (0)