Repository: pypa/setuptools

Issue:
commit 618312b breaks console_scripts
The current master branch is currently broken with respect to `console_scripts`, the symptom is that `setuptools` lies about installing files in `/usr/local/bin`.

My test case…
```
$ tail -n +0 Dockerfile hello/__init__.py hello/main.py setup.py 
==> Dockerfile <==
FROM debian:jessie

COPY setup.py /tmp/app/
COPY hello /tmp/app/hello/
COPY setuptools /tmp/setuptools/

RUN apt-get update
RUN apt-get install -y python git
RUN cd /tmp/setuptools && python bootstrap.py && python setup.py build && python setup.py install
RUN cd /tmp/app && python setup.py build && python setup.py install
RUN ls -l /usr/local/bin && test -x /usr/local/bin/sayhello

==> hello/__init__.py <==

==> hello/main.py <==
#!/usr/bin/env python

def main():
    print ('hello world')

==> setup.py <==
#!/usr/bin/env python
from setuptools import setup

setup (name = 'hello',
	description = 'Hello world program',
	packages = [
            'hello',
        ],
        entry_points = {
            'console_scripts': [
                'sayhello=hello.main:main',
            ],
        })
```

Also in the same directory, is a git checkout of `setuptools`.

`master` branch gives the following output:
```
stuartl@vk4msl-ws /tmp/testcase $ ( cd setuptools ; git log -1 | cat )
commit 618312bec376e5c71b0938a754106973d8889417
Author: Jason R. Coombs <jaraco@jaraco.com>
Date:   Sat Jan 20 08:41:57 2018 -0500

    Refactor to short-circuit on dry-run
stuartl@vk4msl-ws /tmp/testcase $ docker build -t testsetuptools .
Sending build context to Docker daemon  38.08MB
Step 1/9 : FROM debian:jessie
 ---> 2fe79f06fa6d
…
copying hello.egg-info/top_level.txt -> build/bdist.linux-x86_64/egg/EGG-INFO
zip_safe flag not set; analyzing archive contents...
creating dist
creating 'dist/hello-0.0.0-py2.7.egg' and adding 'build/bdist.linux-x86_64/egg' to it
removing 'build/bdist.linux-x86_64/egg' (and everything under it)
Processing hello-0.0.0-py2.7.egg
Copying hello-0.0.0-py2.7.egg to /usr/local/lib/python2.7/dist-packages
Adding hello 0.0.0 to easy-install.pth file
Installing sayhello script to /usr/local/bin

Installed /usr/local/lib/python2.7/dist-packages/hello-0.0.0-py2.7.egg
Processing dependencies for hello==0.0.0
Finished processing dependencies for hello==0.0.0
 ---> 4a9e9af2ee0d
Removing intermediate container 629b9d8184d0
Step 9/9 : RUN ls -l /usr/local/bin && test -x /usr/local/bin/sayhello
 ---> Running in ff847e785765
total 0
The command '/bin/sh -c ls -l /usr/local/bin && test -x /usr/local/bin/sayhello' returned a non-zero code: 1
```

The revision before gives the following output:
```
stuartl@vk4msl-ws /tmp/testcase $ ( cd setuptools ; git checkout HEAD^ )
Note: checking out 'HEAD^'.

You are in 'detached HEAD' state. You can look around, make experimental
changes and commit them, and you can discard any commits you make in this
state without impacting any branches by performing another checkout.

If you want to create a new branch to retain commits you create, you may
do so (now or later) by using -b with the checkout command again. Example:

  git checkout -b <new-branch-name>

HEAD is now at de000c41... On Appveyor, omit the '1.0.' prefix on all builds.
stuartl@vk4msl-ws /tmp/testcase $ docker build -t testsetuptools .
Sending build context to Docker daemon  38.08MB
Step 1/9 : FROM debian:jessie
 ---> 2fe79f06fa6d
…
copying hello.egg-info/PKG-INFO -> build/bdist.linux-x86_64/egg/EGG-INFO
copying hello.egg-info/SOURCES.txt -> build/bdist.linux-x86_64/egg/EGG-INFO
copying hello.egg-info/dependency_links.txt -> build/bdist.linux-x86_64/egg/EGG-INFO
copying hello.egg-info/entry_points.txt -> build/bdist.linux-x86_64/egg/EGG-INFO
copying hello.egg-info/top_level.txt -> build/bdist.linux-x86_64/egg/EGG-INFO
zip_safe flag not set; analyzing archive contents...
creating dist
creating 'dist/hello-0.0.0-py2.7.egg' and adding 'build/bdist.linux-x86_64/egg' to it
removing 'build/bdist.linux-x86_64/egg' (and everything under it)
Processing hello-0.0.0-py2.7.egg
Copying hello-0.0.0-py2.7.egg to /usr/local/lib/python2.7/dist-packages
Adding hello 0.0.0 to easy-install.pth file
Installing sayhello script to /usr/local/bin

Installed /usr/local/lib/python2.7/dist-packages/hello-0.0.0-py2.7.egg
Processing dependencies for hello==0.0.0
Finished processing dependencies for hello==0.0.0
 ---> bad96919d192
Removing intermediate container c74bbdf5b577
Step 9/9 : RUN ls -l /usr/local/bin && test -x /usr/local/bin/sayhello
 ---> Running in adedd76e2179
total 12
-rwxr-xr-x 1 root staff 442 Jan 25 06:59 easy_install
-rwxr-xr-x 1 root staff 450 Jan 25 06:59 easy_install-2.7
-rwxr-xr-x 1 root staff 377 Jan 25 06:59 sayhello
 ---> aef3c2190c4c
Removing intermediate container adedd76e2179
Successfully built aef3c2190c4c
Successfully tagged testsetuptools:latest
```


Discussion:
Yeah, clearly the if condition should have been flipped:
```python
    def write_script(self, script_name, contents, mode="t", blockers=()):
        """Write an executable file to the scripts directory"""
        self.delete_blockers(  # clean up old .py/.pyw w/o a script
            [os.path.join(self.script_dir, x) for x in blockers]
        )
        log.info("Installing %s script to %s", script_name, self.script_dir)
        target = os.path.join(self.script_dir, script_name)
        self.add_output(target)

        if not self.dry_run:
            return

        mask = current_umask()
        ensure_directory(target)
        if os.path.exists(target):
            os.unlink(target)
        with open(target, "w" + mode) as f:
            f.write(contents)
        chmod(target, 0o777 - mask)
```

Resolving patch:
diff --git a/setuptools/command/easy_install.py b/setuptools/command/easy_install.py
--- a/setuptools/command/easy_install.py
+++ b/setuptools/command/easy_install.py
@@ -828,7 +828,7 @@ def write_script(self, script_name, contents, mode="t", blockers=()):
         target = os.path.join(self.script_dir, script_name)
         self.add_output(target)
 
-        if not self.dry_run:
+        if self.dry_run:
             return
 
         mask = current_umask()


Test patch:
diff --git a/setuptools/tests/test_easy_install.py b/setuptools/tests/test_easy_install.py
--- a/setuptools/tests/test_easy_install.py
+++ b/setuptools/tests/test_easy_install.py
@@ -183,6 +183,51 @@ def test_unicode_filename_in_sdist(self, sdist_unicode, tmpdir, monkeypatch):
         cmd.ensure_finalized()
         cmd.easy_install(sdist_unicode)
 
+    @pytest.fixture
+    def sdist_script(self, tmpdir):
+        files = [
+            (
+                'setup.py',
+                DALS("""
+                    import setuptools
+                    setuptools.setup(
+                        name="setuptools-test-script",
+                        version="1.0",
+                        scripts=["mypkg_script"],
+                    )
+                    """),
+            ),
+            (
+                u'mypkg_script',
+                DALS("""
+                     #/usr/bin/python
+                     print('mypkg_script')
+                     """),
+            ),
+        ]
+        sdist_name = 'setuptools-test-script-1.0.zip'
+        sdist = str(tmpdir / sdist_name)
+        make_sdist(sdist, files)
+        return sdist
+
+    @pytest.mark.skipif(not sys.platform.startswith('linux'),
+                        reason="Test can only be run on Linux")
+    def test_script_install(self, sdist_script, tmpdir, monkeypatch):
+        """
+        Check scripts are installed.
+        """
+        dist = Distribution({'script_args': ['easy_install']})
+        target = (tmpdir / 'target').ensure_dir()
+        cmd = ei.easy_install(
+            dist,
+            install_dir=str(target),
+            args=['x'],
+        )
+        monkeypatch.setitem(os.environ, 'PYTHONPATH', str(target))
+        cmd.ensure_finalized()
+        cmd.easy_install(sdist_script)
+        assert (target / 'mypkg_script').exists()
+
 
 class TestPTHFileWriter:
     def test_add_from_cwd_site_sets_dirty(self):