<gh_stars>1-10
# encoding: utf-8
"""
Daemon which constantly listens to repo changes from the config file (~/.codesync/config.yml)
'repos' and streams changes to server. It won't listen to changes from files in the .syncignore (which can be nested).

The daemon can store the last updated timestamp of each repo.
It keeps populating the buffer repo (~/.codesync/.diffs) with the diff files and when
there is internet access, it sends those diffs to server.
.diffs repo is also populated by Plugins.
"""
import logging

from codesync.codesyncd import handle_buffer, populate_buffer_for_missed_events
from codesync.constants import (
    CODESYNC_DIR_PATH, CONFIG_FILE_PATH, LAST_SYNCED_AT_FILE_PATH
)
from codesync.utils import write_yml

logging.basicConfig(level=logging.INFO, format='%(asctime)s-%(levelname)s %(message)s (%(filename)s,%(lineno)d)')


def run_daemon():
    """
    Populating buffer:
        For each repo in config.yml
        - Get the current branch name
            - If current branch is not in config.yml, we sync it first
        - Get already synced files from config.yml for current branch to get ID of each file in following loop
        - For each file in the repo
            - If file matches .syncignore path, skip it.
            - Get the last modified time of file
            - Compare it with last_synced_at of repo
            - Proceed only if file was modified after the last_synced_at of repo
            - Compute the diff of current file with its shadow path
            - If file_id is not found in config.yml, we upload the file
            - If file_id is present in config.yml but we we didn't iterate it in all the files, that means file has
              been deleted. So, we compute the diff to make the file empty and removes the file from config.yml
        - Add diffs to buffer
        - After populating buffer, update last_synced_at of the repo in config.yml

    Iterating Diffs:
        If internet is working/server is up
            - Pick each diff file from .diffs repo
            - Send diff to server
            - Remove diff file that have successfully been sent, Otherwise keep the diffs in the buffer and
                try again in next attempt.
    """
    # Do not continue if there is no ~/.codesync repo
    if not CODESYNC_DIR_PATH.exists():
        logging.error(f"config repo not found. Path: {CODESYNC_DIR_PATH}")
        return

    # Do not continue if there is no ~/.codesync/config.yml
    if not CONFIG_FILE_PATH.exists():
        logging.error("No config.yml found")
        return

    if not LAST_SYNCED_AT_FILE_PATH.exists():
        write_yml(LAST_SYNCED_AT_FILE_PATH, {"repos": {}})

    # Keep watching the changes that are missed by IDE plugins
    populate_buffer_for_missed_events()
    # Handle buffer, send diffs to server
    handle_buffer()
