<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def inline_blob(commit_ref, root_text, base_dir='.', repo_dir=""):
 """Inline all input latex files that exist as git blobs in a tree object. The inlining is accomplished recursively. All files are opened as UTF-8 unicode files. Parameters commit_ref : str String identifying a git commit/tag. root_text : unicode Text of tex document where referenced files will be inlined. base_dir : str Directory of the master tex document, relative to the repo_dir. repo_dir : str Directory of the containing git repository. Returns ------- txt : unicode Text with referenced files included. """

    def _sub_blob(match):
        """Function to be used with re.sub to inline files for each match."""
        fname = match.group(1)
        if not fname.endswith('.tex'):
            full_fname = ".".join((fname, 'tex'))
        else:
            full_fname = fname
        git_rel_path = os.path.relpath(full_fname, base_dir)
        included_text = read_git_blob(commit_ref, git_rel_path,
                                      repo_dir=repo_dir)
        if included_text is None:
            # perhaps file is not in VC
            # FIXME need to deal with possibility
            # it does not exist there either
            with codecs.open(full_fname, 'r', encoding='utf-8') as f:
                included_text = f.read()
        # Recursively inline files
        included_text = inline_blob(commit_ref, included_text,
                                    base_dir=base_dir,
                                    repo_dir=repo_dir)
        return included_text

    def _sub_blob_ifexists(match):
        """Function to be used with re.sub for the input_ifexists_pattern."""
        fname = match.group(1)
        if not fname.endswith('.tex'):
            full_fname = ".".join((fname, 'tex'))
        else:
            full_fname = fname

        # full_fname is relative to the root_path
        # Make path relative to git repo root
        git_rel_path = os.path.relpath(
            os.path.join(repo_dir, base_dir, full_fname),
            repo_dir)

        included_text = read_git_blob(commit_ref, git_rel_path,
                                      repo_dir=repo_dir)
        if included_text is not None:
            # Append extra info after input
            included_text = "\n".join((included_text, match.group(2)))

        if included_text is None:
            # Use the fall-back clause in InputIfExists
            included_text = match.group(3)

        # Recursively inline files
        included_text = inline_blob(commit_ref, included_text,
                                    base_dir=base_dir,
                                    repo_dir=repo_dir)
        return included_text

    # Text processing pipline
    result = remove_comments(root_text)
    result = input_pattern.sub(_sub_blob, result)
    result = include_pattern.sub(_sub_blob, result)
    result = input_ifexists_pattern.sub(_sub_blob_ifexists, result)
    return result