返回
Featured image of post 自动同步本地笔记目录到Git

自动同步本地笔记目录到Git

之前有写过,使用Typora搭配uPic来进行自己的笔记管理,今天在家,研究了下,使用Python写了段小程序,来实现将本地的笔记文件自动同步到自己的GitLab中去,这样在手机端也可以用过Working Copy进行快速的查看。

说明

由于本人并不是程序员,纯属依葫芦画瓢,所以难免疏漏,如发现BUG,可以给我留言,至于我有没有能力改,我也说不准,嘿嘿。

至少目前本人使用正常。

设计思路

  • 需要一个配置文件,来做一些常规的配置信息

  • 使用Watchdog来监听文件和目录的变化

  • 当文件变化时,执行Git命令来推送文件到指定的远程仓库

配置文件说明

配置文件中包含了如下的基本配置:

LOCAL_REPO:本地笔记目录,用来存放自己的笔记

LOCAL_BRANCH:本地笔记目录的仓库分支,默认master

GIT_REMOTE_REPO:远程仓库的地址

ORIGIN_BRANCH:提交到远程仓库的分支

SLEEP_TIME:执行等待的时间

IGNORE:忽略的文件内容

IGNORE_DIR:是否忽略文件夹变更,默认:true

config.json代码如下:

{
  "LOCAL_REPO": "自己的本地文件目录地址",
  "LOCAL_BRANCH": "master",
  "GIT_REMOTE_REPO": "自己的GIT仓库地址",
  "ORIGIN_BRANCH": "master",
  "SLEEP_TIME": 20,
  "IGNORE": [
    "*/.git",
    "*/.git/*.*",
    "*/.git/*",
    "*/.DS_Store"
  ],
  "IGNORE_DIR": true
}

主程序说明

  • 程序启动时会将配置信息读入缓存
  • 程序启动时,先进行一次Git同步
  • 当监听到文件和目录的更新,把更新内容插入到缓存,并打印到控制台
  • 间隔特定的时间判断缓存内是否有更新信息
    • 有:进行Git同步,把更新内容作为COMMIT信息提交
    • 没有:继续等待

run.py

#coding:utf8
#author:wood

from watchdog.observers import Observer
from watchdog.events import *
from subprocess import call
from cacheout import Cache
import logging
import json
import time

config_file = "config.json"

with open(config_file, 'r') as f:
    config = json.load(f)

logging.basicConfig(format='%(asctime)s | %(levelname)s | %(message)s',
                    level=logging.DEBUG)

cache = Cache()
cache.set_many(config)
cache.set("commit", "")
cache.set("desc", "")

class FileEventHandler(PatternMatchingEventHandler):
    def __init__(self, *args, **kwargs):
        super(FileEventHandler, self).__init__(*args, **kwargs)

    def on_moved(self, event):
        if event.is_directory:
            desc = '目录移动:{0} ==> {1}'.format(event.src_path,event.dest_path)
            cache.set("commit", cache.get("commit") + "\n" + desc)
            logging.info(desc)
        else:
            desc = '文件移动:{0} ==> {1}'.format(event.src_path, event.dest_path)
            cache.set("commit", cache.get("commit") + "\n" + desc)
            logging.info(desc)

    def on_created(self, event):
        if event.is_directory:
            desc = '目录创建:{0}'.format(event.src_path)
            cache.set("commit", cache.get("commit") + "\n" + desc)
            logging.info(desc)
        else:
            desc = '文件创建:{0}'.format(event.src_path)
            cache.set("commit", cache.get("commit") + "\n" + desc)
            logging.info(desc)

    def on_deleted(self, event):
        if event.is_directory:
            desc = '目录删除:{0}'.format(event.src_path)
            cache.set("commit", cache.get("commit") + "\n" + desc)
            logging.info(desc)
        else:
            desc = '文件删除:{0}'.format(event.src_path)
            cache.set("commit", cache.get("commit") + "\n" + desc)
            logging.info(desc)

    def on_modified(self, event):
        if event.is_directory:
            cache.set('desc', '目录更新:{0}'.format(event.src_path))
            cache.set("commit", cache.get("commit") + "\n" + cache.get('desc'))
            logging.info(cache.get('desc'))
        else:
            desc = '文件更新:{0}'.format(event.src_path)
            cache.set("commit", cache.get("commit") + "\n" + desc)
            logging.info(desc)

    def add_remote_repo(self):
        git_remote_cmd = "git remote add origin " + cache.get("GIT_REMOTE_REPO")
        call(
            git_remote_cmd,
            shell=True
        )

    def set_branch(self):
        set_branch_cmd = "git checkout " + cache.get("LOCAL_BRANCH")
        call(
            set_branch_cmd,
            shell=True
        )

    def git_syn(self):
        git_add_cmd = "git add -A"
        git_commit_cmd = "git commit -m " + "\"" + "update\n" + str(cache.get("commit")) + "\""
        git_pull_cmd = "git pull origin " + cache.get("ORIGIN_BRANCH")
        git_push_cmd = "git push origin " + cache.get("ORIGIN_BRANCH")
        call(
            "cd " + cache.get("LOCAL_REPO") + "&&" +
            git_add_cmd + "&&" +
            git_commit_cmd + "&&" +
            git_pull_cmd + "&&" +
            git_push_cmd,
            shell=True
        )
        cache.set("commit", "")

if __name__ == "__main__":
    event_handler = FileEventHandler(ignore_patterns=cache.get('IGNORE'), ignore_directories=cache.get('IGNORE_DIR'))
    event_handler.add_remote_repo()
    event_handler.set_branch()
    event_handler.git_syn()
    logging.info('当前监听的目录:' + cache.get("LOCAL_REPO"))
    observer = Observer()
    observer.schedule(event_handler, cache.get("LOCAL_REPO"), True)
    observer.start()
    try:
        while True:
            time.sleep(cache.get("SLEEP_TIME"))
            if cache.get("commit") != "":
                logging.info("==================开始同步==================")
                event_handler.git_syn()
                logging.info("==================同步完成==================")
    except KeyboardInterrupt:
        observer.stop()
    observer.join()

使用的依赖

requirements.txt

astroid==2.4.1
cacheout==0.11.2
isort==4.3.21
lazy-object-proxy==1.4.3
mccabe==0.6.1
observer==0.1.0
pathtools==0.1.2
pylint==2.5.2
six==1.14.0
toml==0.10.1
typed-ast==1.4.1
watchdog==0.10.2
wrapt==1.12.1

使用

将以上三个文件放在同一个文件夹中,执行命令:

 pip3 install -r requirements.txt

完成依赖的安装。

根据自己的需要修改配置文件 config.json

执行程序,开始进入同步模式:

python3 run.py