diff --git a/dvc/daemon.py b/dvc/daemon.py index 3ae15147d..46cd7adf7 100644 --- a/dvc/daemon.py +++ b/dvc/daemon.py @@ -1,27 +1,42 @@ import os import sys from subprocess import Popen + from dvc.logger import logger +from dvc.utils import is_binary, fix_env class Daemon(object): # pragma: no cover def _spawn_windows(self, cmd): + from subprocess import STARTUPINFO, STARTF_USESHOWWINDOW + CREATE_NEW_PROCESS_GROUP = 0x00000200 DETACHED_PROCESS = 0x00000008 creationflags = CREATE_NEW_PROCESS_GROUP | DETACHED_PROCESS - Popen(cmd, - close_fds=True, - shell=False, - creationflags=creationflags) + + startupinfo = STARTUPINFO() + startupinfo.dwFlags |= STARTF_USESHOWWINDOW + + p = Popen(cmd, + env=fix_env(), + close_fds=True, + shell=False, + creationflags=creationflags, + startupinfo=startupinfo) + + p.communicate() def _spawn_posix(self, cmd): + # NOTE: using os._exit instead of sys.exit, because dvc built + # with PyInstaller has trouble with SystemExit exeption and throws + # errors such as "[26338] Failed to execute script __main__" try: pid = os.fork() if pid > 0: return except OSError as exc: logger.error("Failed at first fork", exc) - sys.exit(1) + os._exit(1) os.setsid() os.umask(0) @@ -29,22 +44,25 @@ class Daemon(object): # pragma: no cover try: pid = os.fork() if pid > 0: - sys.exit(0) + os._exit(0) except OSError as exc: logger.error("Failed at second fork", exc) - sys.exit(1) + os._exit(1) sys.stdin.close() sys.stdout.close() sys.stderr.close() - Popen(cmd, - close_fds=True, - shell=False) + p = Popen(cmd, + env=fix_env(), + close_fds=True, + shell=False) + + p.communicate() + + os._exit(0) def __call__(self, args): - from dvc.utils import is_binary - cmd = [sys.executable] if not is_binary(): cmd += ['-m', 'dvc'] diff --git a/dvc/utils.py b/dvc/utils.py index b43160d4d..ec07698de 100644 --- a/dvc/utils.py +++ b/dvc/utils.py @@ -177,7 +177,7 @@ def is_binary(): # NOTE: Fix env variables modified by PyInstaller # http://pyinstaller.readthedocs.io/en/stable/runtime-information.html -def fix_env(env): +def fix_env(env=None): if env is None: env = os.environ.copy() else: diff --git a/scripts/build_posix.sh b/scripts/build_posix.sh index 2b6b9dce1..ee30067cb 100755 --- a/scripts/build_posix.sh +++ b/scripts/build_posix.sh @@ -13,6 +13,7 @@ fi BUILD_DIR=build BIN_DIR=$BUILD_DIR/$INSTALL_DIR/bin +LIB_DIR=$BUILD_DIR/$INSTALL_DIR/lib print_error() { @@ -40,7 +41,7 @@ fpm_build() { print_info "Building $1..." VERSION=$(python -c "import dvc; from dvc import VERSION; print(str(VERSION))") - fpm -s dir -f -t $1 $FPM_FLAGS -n dvc -v $VERSION -C $BUILD_DIR $INSTALL_DIR + fpm -s dir -f -t $1 $FPM_FLAGS -n dvc -v $VERSION -C $BUILD_DIR usr } cleanup() @@ -78,7 +79,18 @@ install_dependencies() build_dvc() { print_info "Building dvc binary..." - pyinstaller --onefile --additional-hooks-dir $(pwd)/scripts/hooks dvc/__main__.py --name dvc --distpath $BIN_DIR --specpath $BUILD_DIR + pyinstaller \ + --additional-hooks-dir $(pwd)/scripts/hooks dvc/__main__.py \ + --name dvc \ + --distpath $LIB_DIR \ + --specpath $BUILD_DIR + + $LIB_DIR/dvc/dvc --help + + mkdir -p $BIN_DIR + pushd $BIN_DIR + ln -s ../lib/dvc/dvc dvc + popd $BIN_DIR/dvc --help } diff --git a/scripts/build_windows.cmd b/scripts/build_windows.cmd index 8b1502850..7c38380df 100644 --- a/scripts/build_windows.cmd +++ b/scripts/build_windows.cmd @@ -19,7 +19,7 @@ call pip install -r requirements.txt || goto :error call pip install pyinstaller || goto :error echo ====== Building dvc binary... ====== -call pyinstaller --onefile --additional-hooks-dir scripts\hooks dvc/__main__.py --name dvc --specpath build +call pyinstaller --additional-hooks-dir scripts\hooks dvc/__main__.py --name dvc --specpath build echo ====== Copying additional files... ====== copy scripts\innosetup\addSymLinkPermissions.ps1 dist\ || goto :error diff --git a/scripts/innosetup/setup.iss b/scripts/innosetup/setup.iss index 35b3fae1a..1bff3a246 100644 --- a/scripts/innosetup/setup.iss +++ b/scripts/innosetup/setup.iss @@ -2,7 +2,7 @@ #define MyAppVersion ReadIni(".\scripts\innosetup\config.ini", "Version", "version", "unknown") #define MyAppPublisher "Dmitry Petrov" #define MyAppURL "https://dataversioncontrol.com/" -#define MyAppDir "..\..\dist" +#define MyAppDir "..\..\dist\dvc" [Setup] AppId={{8258CE8A-110E-4E0D-AE60-FEE00B15F041}