# Path: catkin_tools/common.py
# def mkdir_p(path):
#     """Equivalent to UNIX mkdir -p"""
#     if os.path.exists(path):
#         return
#     try:
#         return os.makedirs(path)
#     except OSError as exc:  # Python >2.5
#         if exc.errno == errno.EEXIST and os.path.isdir(path):
#             pass
#         else:
#             raise
# 
# Path: catkin_tools/terminal_color.py
# def fmt(msg, reset=True):
#     """Replaces color annotations with ansi escape sequences"""
#     global _ansi
#     msg = msg.replace('@!', '@{boldon}')
#     msg = msg.replace('@/', '@{italicson}')
#     msg = msg.replace('@_', '@{ulon}')
#     msg = msg.replace('@|', '@{reset}')
#     t = ColorTemplate(msg)
#     return t.substitute(_ansi) + (ansi('reset') if reset else '')
# 
# Path: catkin_tools/execution/events.py
# class ExecutionEvent(object):
# 
#     """Structure for events generated by the Executor.
# 
#     Events can be jobs starting/finishing, commands starting/failing/finishing,
#     commands producing output (each line is an event), or when the executor
#     quits or fails.
#     """
# 
#     # TODO: Make this a map of ID -> fields
#     EVENT_IDS = [
#         'JOB_STATUS',  # A report of running job states
#         'QUEUED_JOB',  # A job has been queued to be executed
#         'STARTED_JOB',  # A job has started to be executed
#         'FINISHED_JOB',  # A job has finished executing (succeeded or failed)
#         'ABANDONED_JOB',  # A job has been abandoned for some reason
#         'STARTED_STAGE',  # A job stage has started to be executed
#         'FINISHED_STAGE',  # A job stage has finished executing (succeeded or failed)
#         'STAGE_PROGRESS',  # A job stage has executed partially
#         'STDOUT',  # A status message from a job
#         'STDERR',  # A warning or error message from a job
#         'SUBPROCESS',  # A subprocess has been created
#         'MESSAGE'
#     ]
# 
#     def __init__(self, event_id, **kwargs):
#         """Create a new event.
# 
#         :param event_id: One of the valid EVENT_IDS
#         :param **kwargs: The additional data to be passed along with this event.
#         """
#         # Store the time this event was generated
#         self.time = time.time()
# 
#         # Make sure the event ID is valid
#         if event_id not in ExecutionEvent.EVENT_IDS:
#             print(ExecutionEvent.EVENT_IDS)
#             raise ValueError("The event ID %s is not a valid executor event." % event_id)
# 
#         # Store the event data
#         self.event_id = event_id
#         self.data = kwargs


import os
import re
import shutil
from glob import glob
from osrf_pycommon.process_utils import AsyncSubprocessProtocol
from catkin_tools.common import mkdir_p
from catkin_tools.terminal_color import fmt
from .events import ExecutionEvent
    def __init__(self, label, job_id, stage_label, event_queue, log_path, *args, **kwargs):
        IOBufferContainer.__init__(self, label, job_id, stage_label, event_queue, log_path)
        AsyncSubprocessProtocol.__init__(self, *args, **kwargs)

        self.intermediate_stdout_buffer = b''
        self.intermediate_stderr_buffer = b''

    @staticmethod
    def _split(data):
        try:
            last_break = data.rindex(b'\n') + 1
            return data[0:last_break], data[last_break:]
        except ValueError:
            return b'', data

    def on_stdout_received(self, data):
        """
        :type data: encoded bytes
        """

        data, self.intermediate_stdout_buffer = self._split(self.intermediate_stdout_buffer + data)

        self.stdout_buffer += data
        self.interleaved_buffer += data
        self.log_file.write(data)

        # Get the decoded Python str
        decoded_data = self._decode(data)

        # Emit event with decoded Python str

# Path: catkin_tools/common.py
# def mkdir_p(path):
#     """Equivalent to UNIX mkdir -p"""
#     if os.path.exists(path):
#         return
#     try:
#         return os.makedirs(path)
#     except OSError as exc:  # Python >2.5
#         if exc.errno == errno.EEXIST and os.path.isdir(path):
#             pass
#         else:
#             raise
# 
# Path: catkin_tools/terminal_color.py
# def fmt(msg, reset=True):
#     """Replaces color annotations with ansi escape sequences"""
#     global _ansi
#     msg = msg.replace('@!', '@{boldon}')
#     msg = msg.replace('@/', '@{italicson}')
#     msg = msg.replace('@_', '@{ulon}')
#     msg = msg.replace('@|', '@{reset}')
#     t = ColorTemplate(msg)
#     return t.substitute(_ansi) + (ansi('reset') if reset else '')
# 
# Path: catkin_tools/execution/events.py
# class ExecutionEvent(object):
# 
#     """Structure for events generated by the Executor.
# 
#     Events can be jobs starting/finishing, commands starting/failing/finishing,
#     commands producing output (each line is an event), or when the executor
#     quits or fails.
#     """
# 
#     # TODO: Make this a map of ID -> fields
#     EVENT_IDS = [
#         'JOB_STATUS',  # A report of running job states
#         'QUEUED_JOB',  # A job has been queued to be executed
#         'STARTED_JOB',  # A job has started to be executed
#         'FINISHED_JOB',  # A job has finished executing (succeeded or failed)
#         'ABANDONED_JOB',  # A job has been abandoned for some reason
#         'STARTED_STAGE',  # A job stage has started to be executed
#         'FINISHED_STAGE',  # A job stage has finished executing (succeeded or failed)
#         'STAGE_PROGRESS',  # A job stage has executed partially
#         'STDOUT',  # A status message from a job
#         'STDERR',  # A warning or error message from a job
#         'SUBPROCESS',  # A subprocess has been created
#         'MESSAGE'
#     ]
# 
#     def __init__(self, event_id, **kwargs):
#         """Create a new event.
# 
#         :param event_id: One of the valid EVENT_IDS
#         :param **kwargs: The additional data to be passed along with this event.
#         """
#         # Store the time this event was generated
#         self.time = time.time()
# 
#         # Make sure the event ID is valid
#         if event_id not in ExecutionEvent.EVENT_IDS:
#             print(ExecutionEvent.EVENT_IDS)
#             raise ValueError("The event ID %s is not a valid executor event." % event_id)
# 
#         # Store the event data
#         self.event_id = event_id
#         self.data = kwargs


# Path: catkin_tools/execution/io.py
import os
import re
import shutil
from glob import glob
from osrf_pycommon.process_utils import AsyncSubprocessProtocol
from catkin_tools.common import mkdir_p
from catkin_tools.terminal_color import fmt
from .events import ExecutionEvent

    def __init__(self, label, job_id, stage_label, event_queue, log_path, *args, **kwargs):
        IOBufferContainer.__init__(self, label, job_id, stage_label, event_queue, log_path)
        AsyncSubprocessProtocol.__init__(self, *args, **kwargs)

        self.intermediate_stdout_buffer = b''
        self.intermediate_stderr_buffer = b''

    @staticmethod
    def _split(data):
        try:
            last_break = data.rindex(b'\n') + 1
            return data[0:last_break], data[last_break:]
        except ValueError:
            return b'', data

    def on_stdout_received(self, data):
        """
        :type data: encoded bytes
        """

        data, self.intermediate_stdout_buffer = self._split(self.intermediate_stdout_buffer + data)

        self.stdout_buffer += data
        self.interleaved_buffer += data
        self.log_file.write(data)

        # Get the decoded Python str
        decoded_data = self._decode(data)

        # Emit event with decoded Python str

        self.event_queue.put(ExecutionEvent(