Repository: iterative/dvc

Issue:
local variable 'old_handler' referenced before assignment
**Please provide information about your setup**
DVC version(i.e. `dvc --version`), Platform and method of installation (pip, homebrew, pkg Mac, exe (Windows), DEB(Linux), RPM(Linux))

dvc version: 0.55.0 on macos via homebrew cask

![Screen Shot 2019-08-19 at 3 31 14 AM](https://user-images.githubusercontent.com/2790092/63246986-e3a5f100-c231-11e9-8f96-0fcd9c77ba9e.png)


Discussion:

Patch:
diff --git a/dvc/scm/git/__init__.py b/dvc/scm/git/__init__.py
index 631f84744..9c18b216e 100644
--- a/dvc/scm/git/__init__.py
+++ b/dvc/scm/git/__init__.py
@@ -212,11 +212,7 @@ class Git(Base):
         return [t.name for t in self.repo.tags]
 
     def _install_hook(self, name, cmd):
-        command = (
-            '[ "$3" == "0" ]'
-            ' || [ -z "$(git ls-files .dvc)" ]'
-            " || exec dvc {}".format(cmd)
-        )
+        command = '[ -z "$(git ls-files .dvc)" ] || exec dvc {}'.format(cmd)
 
         hook = os.path.join(self.root_dir, self.GIT_DIR, "hooks", name)
 


Test patch:
diff --git a/tests/func/test_install.py b/tests/func/test_install.py
index 1ff4ca23a..140e0b5d5 100644
--- a/tests/func/test_install.py
+++ b/tests/func/test_install.py
@@ -39,9 +39,7 @@ class TestInstall(object):
         expected_script = (
             "#!/bin/sh\n"
             "echo hello\n"
-            '[ "$3" == "0" ]'
-            ' || [ -z "$(git ls-files .dvc)" ]'
-            " || exec dvc checkout\n"
+            '[ -z "$(git ls-files .dvc)" ] || exec dvc checkout\n'
         )
 
         with open(self._hook("post-checkout"), "r") as fobj:
@@ -53,9 +51,7 @@ class TestInstall(object):
 
         expected_script = (
             "#!/bin/sh\n"
-            '[ "$3" == "0" ]'
-            ' || [ -z "$(git ls-files .dvc)" ]'
-            " || exec dvc checkout\n"
+            '[ -z "$(git ls-files .dvc)" ] || exec dvc checkout\n'
         )
 
         with open(self._hook("post-checkout"), "r") as fobj:
diff --git a/tests/func/test_run.py b/tests/func/test_run.py
index 8ff535915..383a4204a 100644
--- a/tests/func/test_run.py
+++ b/tests/func/test_run.py
@@ -5,9 +5,6 @@ import logging
 import mock
 import shutil
 import filecmp
-import subprocess
-import signal
-import threading
 import pytest
 
 from dvc.main import main
@@ -272,66 +269,6 @@ class TestRunBadName(TestDvc):
             )
 
 
-@pytest.mark.skipif(
-    not isinstance(threading.current_thread(), threading._MainThread),
-    reason="Not running in the main thread.",
-)
-@mock.patch.object(subprocess.Popen, "wait", new=KeyboardInterrupt)
-def test_keyboard_interrupt(repo_dir, dvc_repo):
-    assert (
-        main(
-            [
-                "run",
-                "-d",
-                repo_dir.FOO,
-                "-d",
-                repo_dir.CODE,
-                "-o",
-                "out",
-                "-f",
-                "out.dvc",
-                "python",
-                repo_dir.CODE,
-                repo_dir.FOO,
-                "out",
-            ]
-        )
-        == 1
-    )
-
-
-@pytest.mark.skipif(
-    not isinstance(threading.current_thread(), threading._MainThread),
-    reason="Not running in the main thread.",
-)
-def test_keyboard_interrupt_after_second_signal_call(
-    mocker, repo_dir, dvc_repo
-):
-    mocker.patch.object(
-        signal, "signal", side_effect=[None, KeyboardInterrupt]
-    )
-    assert (
-        main(
-            [
-                "run",
-                "-d",
-                repo_dir.FOO,
-                "-d",
-                repo_dir.CODE,
-                "-o",
-                "out",
-                "-f",
-                "out.dvc",
-                "python",
-                repo_dir.CODE,
-                repo_dir.FOO,
-                "out",
-            ]
-        )
-        == 252
-    )
-
-
 class TestRunRemoveOuts(TestDvc):
     def test(self):
         with open(self.CODE, "w+") as fobj:
diff --git a/tests/unit/test_stage.py b/tests/unit/test_stage.py
index a477059a8..41460f9e6 100644
--- a/tests/unit/test_stage.py
+++ b/tests/unit/test_stage.py
@@ -2,6 +2,10 @@ from dvc.path_info import PathInfo
 from dvc.stage import Stage, StageUpdateError
 from dvc.dependency.repo import DependencyREPO
 
+import signal
+import threading
+import subprocess
+
 import mock
 import pytest
 from unittest import TestCase
@@ -82,3 +86,24 @@ def test_stage_update(mocker):
     is_repo_import.return_value = False
     with pytest.raises(StageUpdateError):
         stage.update()
+
+
+@pytest.mark.skipif(
+    not isinstance(threading.current_thread(), threading._MainThread),
+    reason="Not running in the main thread.",
+)
+def test_stage_run_ignore_sigint(mocker):
+    stage = Stage(None, "path")
+
+    proc = mocker.Mock()
+    communicate = mocker.Mock()
+    proc.configure_mock(returncode=0, communicate=communicate)
+    popen = mocker.patch.object(subprocess, "Popen", return_value=proc)
+    signal_mock = mocker.patch("signal.signal")
+
+    stage._run()
+
+    assert popen.called_once()
+    assert communicate.called_once_with()
+    signal_mock.assert_any_call(signal.SIGINT, signal.SIG_IGN)
+    assert signal.getsignal(signal.SIGINT) == signal.default_int_handler