# Buggy code
def get_hash(self, path_info, tree=None, **kwargs):
    assert isinstance(path_info, str) or path_info.scheme == self.scheme

    if not tree:
        tree = self

    if not tree.exists(path_info):
        return None

    if tree == self:
        # pylint: disable=assignment-from-none
        hash_ = self.state.get(path_info)
    else:
        hash_ = None
    # If we have dir hash in state db, but dir cache file is lost,
    # then we need to recollect the dir via .get_dir_hash() call below,
    # see https://github.com/iterative/dvc/issues/2219 for context
    if (
        hash_
        and self.is_dir_hash(hash_)
        and not tree.exists(self.cache.tree.hash_to_path_info(hash_))
    ):
        hash_ = None

    if hash_:
        return hash_

    if tree.isdir(path_info):
        hash_ = self.get_dir_hash(path_info, tree, **kwargs)
    else:
        hash_ = tree.get_file_hash(path_info)

    if hash_ and self.exists(path_info):
        self.state.save(path_info, hash_)

    return hash_


# Traceback (AttributeError)
2020-07-14 18:50:54,511 ERROR: unexpected error - 'NoneType' object has no attribute 'scheme'
------------------------------------------------------------
Traceback (most recent call last):
File "/usr/local/Cellar/dvc/1.1.10/libexec/lib/python3.8/site-packages/dvc/main.py", line 53, in main
ret = cmd.run()
File "/usr/local/Cellar/dvc/1.1.10/libexec/lib/python3.8/site-packages/dvc/command/commit.py", line 18, in run
self.repo.commit(
File "/usr/local/Cellar/dvc/1.1.10/libexec/lib/python3.8/site-packages/dvc/repo/__init__.py", line 36, in wrapper
ret = f(repo, *args, **kwargs)
File "/usr/local/Cellar/dvc/1.1.10/libexec/lib/python3.8/site-packages/dvc/repo/commit.py", line 42, in commit
changes = stage.changed_entries()
File "/usr/local/Cellar/dvc/1.1.10/libexec/lib/python3.8/site-packages/dvc/stage/__init__.py", line 405, in changed_entries
changed_deps = self._changed_entries(self.deps)
File "/usr/local/Cellar/dvc/1.1.10/libexec/lib/python3.8/site-packages/dvc/stage/__init__.py", line 399, in _changed_entries
return [str(entry) for entry in entries if entry.changed_checksum()]
File "/usr/local/Cellar/dvc/1.1.10/libexec/lib/python3.8/site-packages/dvc/stage/__init__.py", line 399, in <listcomp>
return [str(entry) for entry in entries if entry.changed_checksum()]
File "/usr/local/Cellar/dvc/1.1.10/libexec/lib/python3.8/site-packages/dvc/output/base.py", line 195, in changed_checksum
return self.checksum != self.get_checksum()
File "/usr/local/Cellar/dvc/1.1.10/libexec/lib/python3.8/site-packages/dvc/output/base.py", line 181, in get_checksum
return self.remote.get_hash(self.path_info)
File "/usr/local/Cellar/dvc/1.1.10/libexec/lib/python3.8/site-packages/dvc/remote/base.py", line 735, in get_hash
return self.tree.get_hash(path_info, **kwargs)
File "/usr/local/Cellar/dvc/1.1.10/libexec/lib/python3.8/site-packages/dvc/remote/base.py", line 276, in get_hash
assert isinstance(path_info, str) or path_info.scheme == self.scheme
AttributeError: 'NoneType' object has no attribute 'scheme'
------------------------------------------------------------

# Fixed code
def get_hash(self, path_info, tree=None, **kwargs):
    assert path_info and (isinstance(path_info, str) or path_info.scheme == self.scheme)

    if not tree:
        tree = self

    if not tree.exists(path_info):
        return None

    if tree == self:
        # pylint: disable=assignment-from-none
        hash_ = self.state.get(path_info)
    else:
        hash_ = None
    # If we have dir hash in state db, but dir cache file is lost,
    # then we need to recollect the dir via .get_dir_hash() call below,
    # see https://github.com/iterative/dvc/issues/2219 for context
    if (
        hash_
        and self.is_dir_hash(hash_)
        and not tree.exists(self.cache.tree.hash_to_path_info(hash_))
    ):
        hash_ = None

    if hash_:
        return hash_

    if tree.isdir(path_info):
        hash_ = self.get_dir_hash(path_info, tree, **kwargs)
    else:
        hash_ = tree.get_file_hash(path_info)

    if hash_ and self.exists(path_info):
        self.state.save(path_info, hash_)

    return hash_