+ logger.info("Extracting updated files to %s", basePath)
+ for member in zf.namelist():
+ if not member.lower() == "nzbhydra2" and not member.lower().endswith(".exe"):
+ logger.debug("Extracting %s to %s", member, basePath)
+ try:
+ zf.extract(member, basePath)
+ except IOError as ex:
+ logger.critical("Unable to extract file %s to path %s: %s", member, basePath, ex)
+ sys.exit(-2)
+ logger.info("Removing update ZIP %s", updateZip)
+ os.remove(updateZip)
+ filesInLibFolder = [f for f in os.listdir(libFolder) if os.path.isfile(os.path.join(libFolder, f)) and f.endswith(".jar")]
+ logger.info("Found %d JAR files in lib folder", len(filesInLibFolder))
+ for file in filesInLibFolder:
+ logger.info("Found file: %s", file)
+ if len(filesInLibFolder) == 2:
+ logger.info("Deleting old JAR %s", jarFile)
+ os.remove(jarFile)
+ elif len(filesInLibFolder) == 1:
+ if filesInLibFolder[0] == os.path.basename(jarFile):
+ logger.warning("New JAR file in lib folder is the same as the old one. The update may not have found a newer version or failed for some reason")
+ else:
+ logger.warning("Expected the number of JAR files in folder %s to be 2 but it's %d. This will be fixed with the next start", libFolder, len(filesInLibFolder))
+
+ except zipfile.BadZipfile:
+ logger.critical("File is not a ZIP")
+ sys.exit(-2)
+ logger.info("Deleting folder " + updateFolder)
+ shutil.rmtree(updateFolder)
+ logger.info("Update successful, restarting Hydra main process")
+ # File "test_subprocess.py", line 58, in <module>
+ # **subprocess_args(stdout=None))
+ # File "C:\Python27\lib\subprocess.py", line 567, in check_output
+ # raise ValueError('stdout argument not allowed, it will be overridden.')
+ # ValueError: stdout argument not allowed, it will be overridden.
+ #
+ # So, add it only if it's needed.
+ if include_stdout:
+ ret = {'stdout': subprocess.PIPE}
+ else:
+ ret = {}
+
+ # On Windows, running this from the binary produced by Pyinstaller
+ # with the ``--noconsole`` option requires redirecting everything
+ # (stdin, stdout, stderr) to avoid an OSError exception
+ # "[Error 6] the handle is invalid."
+ ret.update({'stdin': subprocess.PIPE,
+ 'stderr': subprocess.STDOUT,
+ 'startupinfo': si,
+ 'env': env})
+ return ret
+
+
+def startup():
+ global jarFile, process, args, unknownArgs, consoleLines
+ basePath = getBasePath()
+
+ readme = os.path.join(basePath, "readme.md")
+ if not os.path.exists(readme):
+ logger.critical("Unable to determine base path correctly. Please make sure to run NZBHydra in the folder where its binary is located. Current base path: " + basePath)
+ logger.warning("Expected the number of JAR files in folder %s to be 1 but it's %d. Will remove all JARs except the one last changed: %s", libFolder, len(jarFiles), latestFile)
+ for file in jarFiles:
+ if file is not latestFile:
+ logger.info("Deleting file %s", file)
+ os.remove(file)
+ jarFile = latestFile
+ logger.debug("Using JAR file " + jarFile)
+
+ if args.repairdb:
+ arguments = ["--repairdb", args.repairdb]
+ elif args.version:
+ arguments = ["--version"]
+ else:
+ arguments = unknownArgs # Those arguments not "caught" by this parser
+
+ # We need to set the ones which we "pass through" separately
+ if args.restarted and "restarted" not in arguments:
+ arguments.append("restarted")
+ if (args.daemon in arguments or args.nobrowser) and "--nobrowser" not in arguments:
+ arguments.append("--nobrowser")
+ if args.datafolder and "--datafolder" not in arguments:
+ message = "Main process shut down unexpectedly. If the wrapper was started in daemon mode you might not see the error output. Start Hydra manually with the same parameters in the same environment to see it"
+ for x in consoleLines:
+ if "Unrecognized option: -Xlog" in x:
+ message = "You seem to be trying to run NZBHydra with a wrong Java version. Please make sure to use at least Java 9"
+ elif "java.lang.OutOfMemoryError" in x:
+ message = "The main process has exited because it didn't have enough memory. Please increase the XMX value in the main config"
+ logger.error(message)
+ sys.exit(-1)
+
+
+def getJavaVersion(javaExecutable):
+ if hasattr(subprocess, 'STARTUPINFO'):
+ si = subprocess.STARTUPINFO()
+ try:
+ import _subprocess
+ si.dwFlags |= _subprocess.STARTF_USESHOWWINDOW
+ except:
+ si.dwFlags |= subprocess.STARTF_USESHOWWINDOW
+ else:
+ si = None
+ # todo check shell=True/False for linux and windows
+ parser.add_argument('--java', action='store', help='Full path to java executable', default="java")
+ parser.add_argument('--debugport', action='store', help='Set debug port to enable remote debugging', default=None)
+ parser.add_argument('--daemon', '-D', action='store_true', help='Run as daemon. *nix only', default=False)
+ parser.add_argument('--pidfile', action='store', help='Path to PID file. Only relevant with daemon argument', default="nzbhydra2.pid")
+ parser.add_argument('--nopidfile', action='store_true', help='Disable writing of PID file. Only relevant with daemon argument', default=False)
+ parser.add_argument('--nocolors', action='store_true', help='Disable color coded console output (disabled on Windows by default)', default=False)
+ parser.add_argument('--listfiles', action='store', help='Lists all files in given folder and quits. For debugging docker', default=None)
+
+ # Pass to main process
+ parser.add_argument('--datafolder', action='store', help='Set the main data folder containing config, database, etc using an absolute path', default=os.path.join(getBasePath(), "data"))