docs: def add(self, name: str, path_or_url: str) -> Source:
          """
          Attempts to register a source provided by a given URL or local path
          under a given name.
  
          Returns:
              a description of the registered source.
  
          Raises:
              NameInUseError: if an existing source is already registered under
                  the given name.
              IOError: if no directory exists at the given path.
              IOError: if downloading the remote source failed. (FIXME)
          """
          logger.info("adding source: %s -> %s", name, path_or_url)
          if name in self.__sources:
              logger.info("name already used by existing source: %s", name)
              raise NameInUseError(name)
  
          is_url = False
          try:
              scheme = urllib.parse.urlparse(path_or_url).scheme
              is_url = scheme in ['http', 'https']
              logger.debug("source determined to be remote: %s", path_or_url)
          except ValueError:
              logger.debug("source determined to be local: %s", path_or_url)
  
          if is_url:
              url = path_or_url
  
              # convert url to a local path
              path = url.replace('https://', '')
              path = path.replace('/', '_')
              path = path.replace('.', '_')
              path = os.path.join(self.__path, path)
  
              # download from remote to local
              shutil.rmtree(path, ignore_errors=True)
              try:
                  # TODO shallow clone
                  logger.debug("cloning repository %s to %s", url, path)
                  repo = git.Repo.clone_from(url, path)
                  logger.debug("cloned repository %s to %s", url, path)
  
                  sha = repo.head.object.hexsha
                  version = repo.git.rev_parse(sha, short=8)
              except: # TODO determine error type
                  shutil.rmtree(path, ignore_errors=True)
                  logger.error("failed to download remote source to local: %s -> %s", url, path)
                  raise IOError("failed to download remote source to local installation: '{}' -> '{}'".format(url, path))
              source = RemoteSource(name, path, url, version)
  
          else:
              path = os.path.abspath(path_or_url)
              if not os.path.isdir(path):
                  raise IOError("no directory found at path: {}".format(path))
              source = LocalSource(name, path)
  
          self.load(source)
          self.save()
          logger.info('added source: %s', name)