# Buggy code
def clobber(source, dest, is_base, fixer=None, filter=None):
    ensure_dir(dest)  # common for the 'include' path

    for dir, subdirs, files in os.walk(source):
        basedir = dir[len(source) :].lstrip(os.path.sep)
        destdir = os.path.join(dest, basedir)
        if is_base and basedir.split(os.path.sep, 1)[0].endswith(".data"):
            continue
        for s in subdirs:
            destsubdir = os.path.join(dest, basedir, s)
            if is_base and basedir == "" and destsubdir.endswith(".data"):
                data_dirs.append(s)
                continue
            elif (
                is_base
                and s.endswith(".dist-info")
                and
                # is self.req.project_name case preserving?
                s.lower().startswith(req.name.replace("-", "_").lower())
            ):
                assert not info_dir, (
                    "Multiple .dist-info directories: "
                    + destsubdir
                    + ", "
                    + ", ".join(info_dir)
                )
                info_dir.append(destsubdir)
        for f in files:
            # Skip unwanted files
            if filter and filter(f):
                continue
            srcfile = os.path.join(dir, f)
            destfile = os.path.join(dest, basedir, f)
            # directory creation is lazy and after the file filtering above
            # to ensure we don't install empty dirs; empty dirs can't be
            # uninstalled.
            ensure_dir(destdir)

            # We use copyfile (not move, copy, or copy2) to be extra sure
            # that we are not moving directories over (copyfile fails for
            # directories) as well as to ensure that we are not copying
            # over any metadata because we want more control over what
            # metadata we actually copy over.
            shutil.copyfile(srcfile, destfile)

            # Copy over the metadata for the file, currently this only
            # includes the atime and mtime.
            st = os.stat(srcfile)
            if hasattr(os, "utime"):
                os.utime(destfile, (st.st_atime, st.st_mtime))

            # If our file is executable, then make our destination file
            # executable.
            if os.access(srcfile, os.X_OK):
                st = os.stat(srcfile)
                permissions = st.st_mode | stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH
                os.chmod(destfile, permissions)

            changed = False
            if fixer:
                changed = fixer(destfile)
            record_installed(srcfile, destfile, changed)


# Traceback (AssertionError)
Exception:
Traceback (most recent call last):
File "/Users/sigmavirus24/.test/lib/python2.7/site-packages/pip/basecommand.py", line 215, in main
status = self.run(options, args)
File "/Users/sigmavirus24/.test/lib/python2.7/site-packages/pip/commands/install.py", line 317, in run
prefix=options.prefix_path,
File "/Users/sigmavirus24/.test/lib/python2.7/site-packages/pip/req/req_set.py", line 742, in install
**kwargs
File "/Users/sigmavirus24/.test/lib/python2.7/site-packages/pip/req/req_install.py", line 831, in install
self.move_wheel_files(self.source_dir, root=root, prefix=prefix)
File "/Users/sigmavirus24/.test/lib/python2.7/site-packages/pip/req/req_install.py", line 1032, in move_wheel_files
isolated=self.isolated,
File "/Users/sigmavirus24/.test/lib/python2.7/site-packages/pip/wheel.py", line 348, in move_wheel_files
assert info_dir, "%s .dist-info directory not found" % req
AssertionError: github3-py .dist-info directory not found

# Fixed code
def clobber(source, dest, is_base, fixer=None, filter=None):
    ensure_dir(dest)  # common for the 'include' path

    for dir, subdirs, files in os.walk(source):
        basedir = dir[len(source) :].lstrip(os.path.sep)
        destdir = os.path.join(dest, basedir)
        if is_base and basedir.split(os.path.sep, 1)[0].endswith(".data"):
            continue
        for s in subdirs:
            destsubdir = os.path.join(dest, basedir, s)
            if is_base and basedir == "" and destsubdir.endswith(".data"):
                data_dirs.append(s)
                continue
            elif (
                is_base
                and s.endswith(".dist-info")
                and canonicalize_name(s).startswith(canonicalize_name(req.name))
            ):
                assert not info_dir, (
                    "Multiple .dist-info directories: "
                    + destsubdir
                    + ", "
                    + ", ".join(info_dir)
                )
                info_dir.append(destsubdir)
        for f in files:
            # Skip unwanted files
            if filter and filter(f):
                continue
            srcfile = os.path.join(dir, f)
            destfile = os.path.join(dest, basedir, f)
            # directory creation is lazy and after the file filtering above
            # to ensure we don't install empty dirs; empty dirs can't be
            # uninstalled.
            ensure_dir(destdir)

            # We use copyfile (not move, copy, or copy2) to be extra sure
            # that we are not moving directories over (copyfile fails for
            # directories) as well as to ensure that we are not copying
            # over any metadata because we want more control over what
            # metadata we actually copy over.
            shutil.copyfile(srcfile, destfile)

            # Copy over the metadata for the file, currently this only
            # includes the atime and mtime.
            st = os.stat(srcfile)
            if hasattr(os, "utime"):
                os.utime(destfile, (st.st_atime, st.st_mtime))

            # If our file is executable, then make our destination file
            # executable.
            if os.access(srcfile, os.X_OK):
                st = os.stat(srcfile)
                permissions = st.st_mode | stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH
                os.chmod(destfile, permissions)

            changed = False
            if fixer:
                changed = fixer(destfile)
            record_installed(srcfile, destfile, changed)