# Path: peru/async_helpers.py
# async def safe_communicate(process, input=None):
#     '''Asyncio's communicate method has a bug where `communicate(input=b"")` is
#     treated the same as `communicate(). That means that child processes can
#     hang waiting for input, when their stdin should be closed. See
#     https://bugs.python.org/issue26848. The issue is fixed upstream in
#     https://github.com/python/asyncio/commit/915b6eaa30e1e3744e6f8223f996e197c1c9b91d,
#     but we will probably always need this workaround for old versions.'''
#     if input is not None and len(input) == 0:
#         process.stdin.close()
#         return (await process.communicate())
#     else:
#         return (await process.communicate(input))
# 
# Path: peru/compat.py
# def makedirs(path):
#     '''os.makedirs() has an exist_ok param, but it still throws errors when the
#     path exists with non-default permissions. This isn't fixed until 3.4.
#     Pathlib won't be getting an exist_ok param until 3.5.'''
#     path = str(path)  # compatibility with pathlib
#     # Use isdir to avoid silently returning if the path exists but isn't a dir.
#     if not os.path.isdir(path):
#         os.makedirs(path)


import asyncio
import contextlib
import collections
import hashlib
import json
import os
import pathlib
import re
import textwrap
from .async_helpers import safe_communicate
from .compat import makedirs
from .error import PrintableError
from .keyval import KeyVal
      1) We want to be able to run multiple operations in parallel that write
         to the index file.
      2) We want to be able to save the index file corresponding to the last
         imports, and guarantee that nothing will touch it.
    A git session owns the index file it does operations on. We also use this
    class to abstract away the low level details of git command flags. (And in
    the future, this could be where we plug in libgit2.)'''

    def __init__(self, git_dir, index_file, working_copy):
        self.git_dir = git_dir
        self.index_file = index_file
        self.working_copy = working_copy

    async def git(self, *args, input=None, output_mode=TEXT_MODE, cwd=None):
        global DEBUG_GIT_COMMAND_COUNT
        DEBUG_GIT_COMMAND_COUNT += 1
        command = ['git']
        command.append('--git-dir=' + self.git_dir)
        if self.working_copy:
            command.append("--work-tree=" + self.working_copy)
        command.extend(args)
        if isinstance(input, str):
            input = input.encode()
        process = await asyncio.subprocess.create_subprocess_exec(
            *command,
            cwd=cwd,
            env=self.git_env(),
            stdin=asyncio.subprocess.PIPE,
            stdout=asyncio.subprocess.PIPE,
            stderr=asyncio.subprocess.PIPE)

# Path: peru/async_helpers.py
# async def safe_communicate(process, input=None):
#     '''Asyncio's communicate method has a bug where `communicate(input=b"")` is
#     treated the same as `communicate(). That means that child processes can
#     hang waiting for input, when their stdin should be closed. See
#     https://bugs.python.org/issue26848. The issue is fixed upstream in
#     https://github.com/python/asyncio/commit/915b6eaa30e1e3744e6f8223f996e197c1c9b91d,
#     but we will probably always need this workaround for old versions.'''
#     if input is not None and len(input) == 0:
#         process.stdin.close()
#         return (await process.communicate())
#     else:
#         return (await process.communicate(input))
# 
# Path: peru/compat.py
# def makedirs(path):
#     '''os.makedirs() has an exist_ok param, but it still throws errors when the
#     path exists with non-default permissions. This isn't fixed until 3.4.
#     Pathlib won't be getting an exist_ok param until 3.5.'''
#     path = str(path)  # compatibility with pathlib
#     # Use isdir to avoid silently returning if the path exists but isn't a dir.
#     if not os.path.isdir(path):
#         os.makedirs(path)


# Path: peru/cache.py
import asyncio
import contextlib
import collections
import hashlib
import json
import os
import pathlib
import re
import textwrap
from .async_helpers import safe_communicate
from .compat import makedirs
from .error import PrintableError
from .keyval import KeyVal

      1) We want to be able to run multiple operations in parallel that write
         to the index file.
      2) We want to be able to save the index file corresponding to the last
         imports, and guarantee that nothing will touch it.
    A git session owns the index file it does operations on. We also use this
    class to abstract away the low level details of git command flags. (And in
    the future, this could be where we plug in libgit2.)'''

    def __init__(self, git_dir, index_file, working_copy):
        self.git_dir = git_dir
        self.index_file = index_file
        self.working_copy = working_copy

    async def git(self, *args, input=None, output_mode=TEXT_MODE, cwd=None):
        global DEBUG_GIT_COMMAND_COUNT
        DEBUG_GIT_COMMAND_COUNT += 1
        command = ['git']
        command.append('--git-dir=' + self.git_dir)
        if self.working_copy:
            command.append("--work-tree=" + self.working_copy)
        command.extend(args)
        if isinstance(input, str):
            input = input.encode()
        process = await asyncio.subprocess.create_subprocess_exec(
            *command,
            cwd=cwd,
            env=self.git_env(),
            stdin=asyncio.subprocess.PIPE,
            stdout=asyncio.subprocess.PIPE,
            stderr=asyncio.subprocess.PIPE)

        stdout, stderr = await safe_communicate(process, input)