diff mbox series

fetch/git: Remove the LFS worktree when git lfs fetch fails

Message ID 20261112183111.3425042-1-damianfalkowski9@gmail.com
State New
Headers show
Series fetch/git: Remove the LFS worktree when git lfs fetch fails | expand

Commit Message

Damian Falkowski Nov. 12, 2026, 6:31 p.m. UTC
Since commit d369bfd8e5b4 ("fetch2: Raise on git lfs fetch failures"), a
failing "git lfs fetch" raises before the temporary "wt" worktree is
removed. The worktree stays in the clone directory in DL_DIR, and every
later fetch of the same repository fails at "git worktree add" with
"fatal: 'wt' already exists" until someone deletes it by hand. A single
temporary error from the LFS server, such as a short outage of its
backing storage, thus breaks the download directory for good.

Remove the worktree also when "git lfs fetch" fails, and add a test
that fetches again after a failed LFS fetch.

AI-Generated: Cursor, Claude Opus 5.5
Signed-off-by: Damian Falkowski <damianfalkowski9@gmail.com>
---
 lib/bb/fetch/git.py   |  6 ++++--
 lib/bb/tests/fetch.py | 21 +++++++++++++++++++++
 2 files changed, 25 insertions(+), 2 deletions(-)
diff mbox series

Patch

diff --git a/lib/bb/fetch/git.py b/lib/bb/fetch/git.py
index dc1b31b58..75ce1eda0 100644
--- a/lib/bb/fetch/git.py
+++ b/lib/bb/fetch/git.py
@@ -509,9 +509,11 @@  class Git(FetchMethod):
             lfs_fetch_cmd = ud.basecmd + ['lfs', 'fetch']
             if fetchall:
                 lfs_fetch_cmd.append('--all')
-            runfetchcmd(lfs_fetch_cmd, d, log=progresshandler, workdir=(clonedir + "/wt"))
             worktree_rem_cmd = ud.basecmd + ['worktree', 'remove', '-f', 'wt']
-            runfetchcmd(worktree_rem_cmd, d, log=progresshandler, workdir=clonedir)
+            try:
+                runfetchcmd(lfs_fetch_cmd, d, log=progresshandler, workdir=(clonedir + "/wt"))
+            finally:
+                runfetchcmd(worktree_rem_cmd, d, log=progresshandler, workdir=clonedir)
 
 
     @contextmanager
diff --git a/lib/bb/tests/fetch.py b/lib/bb/tests/fetch.py
index 0f29cdf11..7c93a6cbe 100644
--- a/lib/bb/tests/fetch.py
+++ b/lib/bb/tests/fetch.py
@@ -2872,6 +2872,27 @@  class GitLfsTest(FetcherTest):
         with self.assertRaises(bb.fetch.FetchError):
             self.fetch()
 
+    @skipIfNoGitLFS()
+    def test_lfs_fetch_retry_after_failure(self):
+        """Test that a failed LFS fetch does not break later fetches of the same repository"""
+        self.git(["lfs", "install", "--local"], cwd=self.srcdir)
+        self.commit_file("a.mp3", "version 1")
+
+        uri = 'git://%s;protocol=file;lfs=1;branch=master' % self.srcdir
+        self.d.setVar('SRC_URI', uri)
+
+        lfs_objects = os.path.join(self.srcdir, ".git", "lfs", "objects")
+        with hide_directory(lfs_objects):
+            with self.assertRaises(bb.fetch.FetchError):
+                self.fetch()
+
+        fetcher, ud = self.fetch()
+        with hide_directory(self.srcdir):
+            workdir = self.d.getVar('WORKDIR')
+            fetcher.unpack(workdir)
+            with open(os.path.join(workdir, "git", "a.mp3")) as f:
+                self.assertEqual(f.read(), "version 1")
+
 class GitURLWithSpacesTest(FetcherTest):
     test_git_urls = {
         "git://tfs-example.org:22/tfs/example%20path/example.git;branch=master" : {