diff mbox series

[v3,02/14] fetch2: add LocalModificationsError and RebaseError exceptions

Message ID 20260329183332.1996183-3-adrian.freihofer@siemens.com
State New
Headers show
Series bitbake-setup: improvements, VSCode workspace generation | expand

Commit Message

AdrianF March 29, 2026, 6:32 p.m. UTC
From: Adrian Freihofer <adrian.freihofer@siemens.com>

When unpack_update() detects either of two blocking conditions, it now
raises a dedicated exception subclass of UnpackError instead of a
generic UnpackError:

- LocalModificationsError: for uncommitted changes in the working tree
  that prevent the update. Includes git status output and instructs
  the user to commit, stash or discard changes.

- RebaseError: for local commits that could not be rebased onto the
  new upstream revision. Includes the git rebase output and a hint
  that the 'dldir' remote points to the local download cache and may
  be used to resolve conflicts manually.

Both exceptions take (repodir, url, git_output) as arguments, build
the full user-facing message in __init__, and preserve the is-a
relationship with UnpackError so existing callers are not broken.

The fetch and rebase operations are also split into separate
try/except blocks so that a failure to fetch from dldir raises a
plain UnpackError while a failed rebase raises RebaseError.

Signed-off-by: Adrian Freihofer <adrian.freihofer@siemens.com>
---
 lib/bb/fetch2/__init__.py | 17 +++++++++++++++++
 lib/bb/fetch2/git.py      |  7 +++++--
 2 files changed, 22 insertions(+), 2 deletions(-)
diff mbox series

Patch

diff --git a/lib/bb/fetch2/__init__.py b/lib/bb/fetch2/__init__.py
index e7213dea4..d104dfaf3 100644
--- a/lib/bb/fetch2/__init__.py
+++ b/lib/bb/fetch2/__init__.py
@@ -96,6 +96,23 @@  class UnpackError(BBFetchException):
         BBFetchException.__init__(self, msg)
         self.args = (message, url)
 
+class LocalModificationsError(UnpackError):
+    """Exception raised when a checkout cannot be updated due to local modifications"""
+    def __init__(self, repodir, url, git_output):
+        message = ("Repository at %s has uncommitted changes, unable to update:\n%s\n"
+                   "Commit, stash or discard your changes and re-run the update." % (repodir, git_output))
+        UnpackError.__init__(self, message, url)
+        self.args = (repodir, url, git_output)
+
+class RebaseError(UnpackError):
+    """Exception raised when a checkout has local commits that could not be rebased onto the new upstream revision"""
+    def __init__(self, repodir, url, git_output):
+        message = ("Repository at %s has local commits that could not be rebased onto the new upstream revision:\n%s\n"
+                   "Note: the 'dldir' remote points to the local download cache and may be used to resolve the conflict manually.\n"
+                   "Once resolved, re-run the update." % (repodir, git_output))
+        UnpackError.__init__(self, message, url)
+        self.args = (repodir, url, git_output)
+
 class NoMethodError(BBFetchException):
     """Exception raised when there is no method to obtain a supplied url or set of urls"""
     def __init__(self, url):
diff --git a/lib/bb/fetch2/git.py b/lib/bb/fetch2/git.py
index 645746340..6ed14005b 100644
--- a/lib/bb/fetch2/git.py
+++ b/lib/bb/fetch2/git.py
@@ -730,7 +730,7 @@  class Git(FetchMethod):
 
             output = runfetchcmd("%s status --untracked-files=no --porcelain" % (ud.basecmd), d, workdir=destdir)
             if output:
-                raise bb.fetch2.UnpackError("Repository at %s has uncommitted changes, unable to update:\n%s" % (destdir, output), ud.url)
+                raise bb.fetch2.LocalModificationsError(destdir, ud.url, output)
 
             # Set up remote for the download location if it doesn't exist
             try:
@@ -740,6 +740,9 @@  class Git(FetchMethod):
                     runfetchcmd("%s remote add dldir file://%s" % (ud.basecmd, ud.clonedir), d, workdir=destdir)
             try:
                 runfetchcmd("%s fetch dldir" % (ud.basecmd), d, workdir=destdir)
+            except bb.fetch2.FetchError as e:
+                raise bb.fetch2.UnpackError("Failed to fetch from dldir remote: %s" % str(e), ud.url)
+            try:
                 runfetchcmd("%s rebase --no-autosquash --no-autostash %s" % (ud.basecmd, ud.revision), d, workdir=destdir)
             except bb.fetch2.FetchError as e:
                 # If rebase failed, abort it
@@ -747,7 +750,7 @@  class Git(FetchMethod):
                     runfetchcmd("%s rebase --abort" % (ud.basecmd), d, workdir=destdir)
                 except Exception:
                     pass
-                raise bb.fetch2.UnpackError("Failed to update checkout in place: %s" % str(e), ud.url)
+                raise bb.fetch2.RebaseError(destdir, ud.url, str(e))
             return True
 
         # If there is a tag parameter in the url and we also have a fixed srcrev, check the tag