#95 spectool: return non-zero exit code if download fails (i.e. IOError)
Merged 7 months ago by ngompa. Opened 8 months ago by decathorpe.
Unknown source main  into  main

file modified
+42 -8
@@ -367,6 +367,7 @@

                  except IOError as e:

                      print("Download failed:")

                      print(e)

+                     raise e

  

                  except KeyboardInterrupt:

                      if os.path.isfile(path):
@@ -383,21 +384,41 @@

          if not value:

              value = self.sources[number]

  

-         self._get_file(value, directory, force, dry)

+         try:

+             self._get_file(value, directory, force, dry)

+             return True

+ 

+         except IOError:

+             return False

  

      def get_patch(self, number: int, directory: str, force: bool, dry: bool, value: str = None):

          if not value:

              value = self.patches[number]

  

-         self._get_file(value, directory, force, dry)

+         try:

+             self._get_file(value, directory, force, dry)

+             return True

+ 

+         except IOError:

+             return False

  

      def get_sources(self, directory: str, force: bool, dry: bool):

+         failure = False

+ 

          for number, value in self.sources.items():

-             self.get_source(number, directory, force, dry, value)

+             if self.get_source(number, directory, force, dry, value):

+                 failure = True

+ 

+         return failure

  

      def get_patches(self, directory: str, force: bool, dry: bool):

+         failure = False

+ 

          for number, value in self.patches.items():

-             self.get_patch(number, directory, force, dry, value)

+             if self.get_patch(number, directory, force, dry, value):

+                 failure = True

+ 

+         return failure

  

  

  def main() -> int:
@@ -496,6 +517,8 @@

          else:

              directory = os.getcwd()

  

+         tasks = []

+ 

          if args["source"]:

              numbers = split_numbers(args["source"])

  
@@ -504,10 +527,10 @@

                      print("No patch with number '{}' found.".format(number))

                      continue

  

-                 spec.get_source(number, directory, force, dry)

+                 tasks.append((spec.get_source, (number, directory, force, dry)))

  

          elif args["sources"] and not args["patch"]:

-             spec.get_sources(directory, force, dry)

+             tasks.append((spec.get_sources, (directory, force, dry)))

  

          if args["patch"]:

              numbers = split_numbers(args["patch"])
@@ -517,10 +540,21 @@

                      print("No patch with number '{}' found.".format(number))

                      continue

  

-                 spec.get_patch(number, directory, force, dry)

+                 tasks.append((spec.get_patch, (number, directory, force, dry)))

  

          elif args["patches"] and not args["source"]:

-             spec.get_patches(directory, force, dry)

+             tasks.append((spec.get_patches, (directory, force, dry)))

+ 

+         failure = False

+ 

+         for task, args in tasks:

+             fail = task(*args)

+ 

+             if fail:

+                 failure = True

+ 

+         if failure:

+             return 1

  

      return 0

  

Exceptions thrown by requests (which are subclasses of IOError) are right now caught, but ignored. This results in a zero exit code, even if the download fails (c.f. https://bugzilla.redhat.com/show_bug.cgi?id=2096624 ).

This PR changes the download() function to re-raise any IOErrors that occur.

Additionally, the main() function is slightly refactored, to collect requested tasks and execute them in a loop. This way, any error handling (i.e. catching IOError and returning a non-zero exit code in that case) can happen in one place.

Not sure if the "early exit" is desirable (i.e. with this PR, spectool will abort after the first failed download), or if it should attempt to do all the things and just return a non-zero exit code if any of the requested downloads failed.

It'd probably be better to do the latter, don't you think? That way the user knows which ones don't work all at once.

rebased onto 7b60394

8 months ago

Meh, I just realized that I put the "did any of this fail" check in the wrong place. :(

rebased onto 3524825

8 months ago

Ok, spectool should now attempt to fetch everything that was requested (be that patches, sources, or both), print all errors that occur, and return with a non-zero exit code in case any request failed, and return 0 if they were all successful.

Keeping compatibility with how the "old" spectool worked is starting to result in kinda gnarly code :(

rebased onto 7b8aec7

7 months ago

Pull-Request has been merged by ngompa

7 months ago

I built rpmdevtools from HEAD to test the new pyproject template and noticed that spectool -g now exit 1 when the sources are already downloaded, which breaks my package update script. I agree it should exit 1 if the download fails but returning an error code when the download was simply skipped seems wrong.

Uh, that's definitely not intentional ... at this point the code is pretty bad just to ensure compatibility with the original perl implementation of spectool, so it's possible this change unintentionally changed return code for "already exists" case :(

Metadata