Skip to content

Commit db9fe56

Browse files
committed
address review comments
1 parent f5874fc commit db9fe56

3 files changed

Lines changed: 40 additions & 44 deletions

File tree

src/subcommand/checkout_subcommand.cpp

Lines changed: 32 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -56,18 +56,24 @@ namespace
5656
}
5757
}
5858

59-
void checkout_subcommand::checkout_files(
60-
const repository_wrapper& repo,
61-
const std::vector<std::string>& files,
62-
const git_checkout_options& base_options
63-
)
59+
std::vector<const char*> convert_paths_to_cstr(const std::vector<std::string>& pathspecs)
6460
{
6561
std::vector<const char*> pathspec_strings;
66-
pathspec_strings.reserve(files.size());
67-
for (const auto& f : files)
62+
pathspec_strings.reserve(pathspecs.size());
63+
for (const auto& f : pathspecs)
6864
{
6965
pathspec_strings.push_back(f.c_str());
7066
}
67+
return pathspec_strings;
68+
}
69+
70+
void checkout_subcommand::checkout_head_files(
71+
const repository_wrapper& repo,
72+
const std::vector<std::string>& pathspecs,
73+
const git_checkout_options& base_options
74+
)
75+
{
76+
std::vector<const char*> pathspec_strings = convert_paths_to_cstr(pathspecs);
7177

7278
git_checkout_options options = base_options;
7379
options.paths.strings = const_cast<char**>(pathspec_strings.data());
@@ -76,7 +82,7 @@ void checkout_subcommand::checkout_files(
7682
throw_if_error(git_checkout_head(repo, &options));
7783
}
7884

79-
void checkout_subcommand::checkout_paths(
85+
void checkout_subcommand::checkout_ref_files(
8086
const repository_wrapper& repo,
8187
const std::string_view tree_ish,
8288
const std::vector<std::string>& pathspecs,
@@ -92,12 +98,7 @@ void checkout_subcommand::checkout_paths(
9298
);
9399
}
94100

95-
std::vector<const char*> pathspec_strings;
96-
pathspec_strings.reserve(pathspecs.size());
97-
for (const auto& p : pathspecs)
98-
{
99-
pathspec_strings.push_back(p.c_str());
100-
}
101+
std::vector<const char*> pathspec_strings = convert_paths_to_cstr(pathspecs);
101102

102103
git_checkout_options options = base_options;
103104
options.paths.strings = const_cast<char**>(pathspec_strings.data());
@@ -148,15 +149,12 @@ void checkout_subcommand::run()
148149
update_head(repo, annotated_commit, target_name);
149150

150151
std::cout << "Switched to a new branch '" << target_name << "'" << std::endl;
151-
return;
152152
}
153-
154-
if (!pathspecs.empty())
153+
else if (!pathspecs.empty())
155154
{
156-
// Try tree-ish + pathspec(s)
157-
if (auto obj = repo.revparse_single(target_name))
155+
// Validate all pathspecs before checkout so we can mimic git-like errors
156+
auto lambda_validate_paths = [](repository_wrapper& repo, const std::vector<std::string> pathspecs, std::string directory)
158157
{
159-
// Validate all pathspecs before checkout so we can mimic git-like errors
160158
for (const auto& p : pathspecs)
161159
{
162160
if (!std::filesystem::exists(std::filesystem::path(directory) / p) && !repo.does_track(p))
@@ -167,27 +165,25 @@ void checkout_subcommand::run()
167165
);
168166
}
169167
}
168+
};
169+
170+
// Try tree-ish + pathspec(s)
171+
if (auto obj = repo.revparse_single(target_name))
172+
{
173+
lambda_validate_paths(repo, pathspecs, directory);
170174

171175
options.checkout_strategy = GIT_CHECKOUT_FORCE;
172-
checkout_paths(repo, target_name, pathspecs, options);
173-
return;
176+
checkout_ref_files(repo, target_name, pathspecs, options);
174177
}
175-
176178
// Else treat as files
177-
for (const auto& p : pathspecs)
179+
else
178180
{
179-
if (!std::filesystem::exists(std::filesystem::path(directory) / p) && !repo.does_track(p))
180-
{
181-
throw git_exception(
182-
"error: pathspec '" + p + "' did not match any file(s) known to git",
183-
git2cpp_error_code::BAD_ARGUMENT
184-
);
185-
}
186-
}
181+
lambda_validate_paths(repo, pathspecs, directory);
187182

188-
std::vector<std::string> files = m_positional_args;
189-
options.checkout_strategy = GIT_CHECKOUT_FORCE;
190-
checkout_files(repo, files, options);
183+
std::vector<std::string> files = m_positional_args;
184+
options.checkout_strategy = GIT_CHECKOUT_FORCE;
185+
checkout_head_files(repo, files, options);
186+
}
191187
return;
192188
}
193189

@@ -209,7 +205,7 @@ void checkout_subcommand::run()
209205
}
210206

211207
options.checkout_strategy = GIT_CHECKOUT_FORCE;
212-
checkout_files(repo, file, options);
208+
checkout_head_files(repo, file, options);
213209
return;
214210
}
215211

src/subcommand/checkout_subcommand.hpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,13 +33,13 @@ class checkout_subcommand
3333
const std::string_view target_name
3434
);
3535

36-
void checkout_files(
36+
void checkout_head_files(
3737
const repository_wrapper& repo,
3838
const std::vector<std::string>& files,
3939
const git_checkout_options& options
4040
);
4141

42-
void checkout_paths(
42+
void checkout_ref_files(
4343
const repository_wrapper& repo,
4444
const std::string_view tree_ish,
4545
const std::vector<std::string>& pathspecs,

test/test_checkout.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -129,10 +129,10 @@ def test_checkout_refuses_overwrite(
129129
initial_file.write_text("Content on newbranch")
130130

131131
add_cmd = [git2cpp_path, "add", "initial.txt"]
132-
subprocess.run(add_cmd, cwd=tmp_path, text=True)
132+
subprocess.run(add_cmd, cwd=tmp_path, text=True, check=True)
133133

134134
commit_cmd = [git2cpp_path, "commit", "-m", "Change on newbranch"]
135-
subprocess.run(commit_cmd, cwd=tmp_path, text=True)
135+
subprocess.run(commit_cmd, cwd=tmp_path, text=True, check=True)
136136

137137
# Switch back to default branch
138138
checkout_default_cmd = [git2cpp_path, "checkout", "main"]
@@ -200,9 +200,9 @@ def test_checkout_file_restores_multiple_files(repo_init_with_commit, git2cpp_pa
200200
second_file.write_text("second content")
201201

202202
add_cmd = [git2cpp_path, "add", "second.txt"]
203-
subprocess.run(add_cmd, cwd=tmp_path, text=True)
203+
subprocess.run(add_cmd, cwd=tmp_path, text=True, check=True)
204204
commit_cmd = [git2cpp_path, "commit", "-m", "Add second file"]
205-
subprocess.run(commit_cmd, cwd=tmp_path, text=True)
205+
subprocess.run(commit_cmd, cwd=tmp_path, text=True, check=True)
206206

207207
original_initial = initial_file.read_text()
208208
original_second = second_file.read_text()
@@ -229,9 +229,9 @@ def test_checkout_file_does_not_affect_other_files(repo_init_with_commit, git2cp
229229
second_file.write_text("second content")
230230

231231
add_cmd = [git2cpp_path, "add", "second.txt"]
232-
subprocess.run(add_cmd, cwd=tmp_path, text=True)
232+
subprocess.run(add_cmd, cwd=tmp_path, text=True, check=True)
233233
commit_cmd = [git2cpp_path, "commit", "-m", "Add second file"]
234-
subprocess.run(commit_cmd, cwd=tmp_path, text=True)
234+
subprocess.run(commit_cmd, cwd=tmp_path, text=True, check=True)
235235

236236
# Modify both files
237237
initial_file.write_text("dirty initial")

0 commit comments

Comments
 (0)