Skip to content

Commit ab81dff

Browse files
committed
fix(git): Fix update_repo when there are untracked files
1 parent dcf97f8 commit ab81dff

File tree

3 files changed

+68
-2
lines changed

3 files changed

+68
-2
lines changed

CHANGES

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ URL renamings (#417):
3535
- `URLProtocol`: Fix `is_valid` to use `classmethod`
3636
- All: Fix `is_valid` to use default of `None` to avoid implicitly filtering
3737
- Reduce duplicated code in methods by using `super()`
38+
- `git`: Fix `update_repo` when there are only untracked files
3839

3940
### Packaging
4041

src/libvcs/sync/git.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -408,7 +408,7 @@ def update_repo(self, set_remotes: bool = False, *args: Any, **kwargs: Any) -> N
408408
if is_remote_ref:
409409
# Check if stash is needed
410410
try:
411-
process = self.run(["status", "--porcelain"])
411+
process = self.run(["status", "--porcelain", "--untracked-files=no"])
412412
except exc.CommandError:
413413
self.log.error("Failed to get the status")
414414
return
@@ -435,7 +435,7 @@ def update_repo(self, set_remotes: bool = False, *args: Any, **kwargs: Any) -> N
435435
try:
436436
process = self.run(["rebase", git_remote_name + "/" + git_tag])
437437
except exc.CommandError as e:
438-
if "invalid_upstream" in str(e):
438+
if any(msg in str(e) for msg in ["invalid_upstream", "Aborting"]):
439439
self.log.error(e)
440440
else:
441441
# Rebase failed: Restore previous state.

tests/sync/test_git.py

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
import datetime
33
import os
44
import pathlib
5+
import random
56
import shutil
67
import textwrap
78
from typing import Callable, TypedDict
@@ -141,6 +142,7 @@ def test_repo_update_handle_cases(
141142
) -> None:
142143
git_repo: GitSync = constructor(**lazy_constructor_options(**locals()))
143144
git_repo.obtain() # clone initial repo
145+
144146
mocka = mocker.spy(git_repo, "run")
145147
git_repo.update_repo()
146148

@@ -154,6 +156,69 @@ def test_repo_update_handle_cases(
154156
assert mocker.call(["symbolic-ref", "--short", "HEAD"]) not in mocka.mock_calls
155157

156158

159+
@pytest.mark.parametrize(
160+
"has_untracked_files,needs_stash,has_remote_changes",
161+
[
162+
[True, True, True],
163+
[True, True, False],
164+
[True, False, True],
165+
[True, False, False],
166+
[False, True, True],
167+
[False, True, False],
168+
[False, False, True],
169+
[False, False, False],
170+
],
171+
)
172+
def test_repo_update_stash_cases(
173+
tmp_path: pathlib.Path,
174+
create_git_remote_repo: CreateProjectCallbackFixtureProtocol,
175+
mocker: MockerFixture,
176+
has_untracked_files: bool,
177+
needs_stash: bool,
178+
has_remote_changes: bool,
179+
) -> None:
180+
git_remote_repo = create_git_remote_repo()
181+
182+
git_repo: GitSync = GitSync(
183+
url=f"file://{git_remote_repo}",
184+
dir=tmp_path / "myrepo",
185+
vcs="git",
186+
)
187+
git_repo.obtain() # clone initial repo
188+
189+
def make_file(filename: str) -> pathlib.Path:
190+
some_file = git_repo.dir.joinpath(filename)
191+
with open(some_file, "w") as file:
192+
file.write("some content: " + str(random.random()))
193+
194+
return some_file
195+
196+
# Make an initial commit so we can reset
197+
some_file = make_file("initial_file")
198+
git_repo.run(["add", some_file])
199+
git_repo.run(["commit", "-m", "a commit"])
200+
git_repo.run(["push"])
201+
202+
if has_remote_changes:
203+
some_file = make_file("some_file")
204+
git_repo.run(["add", some_file])
205+
git_repo.run(["commit", "-m", "a commit"])
206+
git_repo.run(["push"])
207+
git_repo.run(["reset", "--hard", "HEAD^"])
208+
209+
if has_untracked_files:
210+
make_file("some_file")
211+
212+
if needs_stash:
213+
some_file = make_file("some_stashed_file")
214+
git_repo.run(["add", some_file])
215+
216+
mocka = mocker.spy(git_repo, "run")
217+
git_repo.update_repo()
218+
219+
mocka.assert_any_call(["symbolic-ref", "--short", "HEAD"])
220+
221+
157222
@pytest.mark.parametrize(
158223
# Postpone evaluation of options so fixture variables can interpolate
159224
"constructor,lazy_constructor_options",

0 commit comments

Comments
 (0)