zoukankan      html  css  js  c++  java
  • Github项目备份与更新

    需求

      假如现在想对使用到的一些Github上的开源组件进行备份,采用自建Gitlab服务器的方式进行备份保存,并且组件需定时保持与Github更新。

    总体步骤

    组件备份- 整体步骤如下:
        a.搭建gitlab服务器,参考CentOS7 搭建gitlab服务器 
        b.登录账户,创建一个group,如kdv-opensource(方便统一管理,不创建也一样)
        c.在kdv-opensource组里需创建相应的repo,可设置访问权限为public。不过不手动创建,则gitlab默认创建为private。
        d.脚本执行git clone --mirror github-url,克隆镜像
           或git remote update,进行更新 e.添加要推送到远端repo 的git地址
        git remote add gitlab gitlab-url f.推送到gitlab服务器上 git push gitlab --all git push gitlab --tags g.python脚本加入crontab定期执行即可

    搭建Gitlab服务器

      如前所述,略。

    创建group

      登录账户,菜单栏选择Groups,右侧New group,填写组名即描述信息即可。如创建一个kdv-opensource组:

    创建项目repo

       需要在kdv-opensource组内创建好所有要备份组件项目,且名字需与Github上开源项目名字保持一致(为了方便),可设定访问权限为public,如下:

      如果不显示创建repo,则创建的项目repo默认为private。

    脚本功能

       我们使用python实现一个脚本从Github上镜像克隆(git clone --mirror)相应的项目和镜像更新(git remote update)。

       python可以直接调用系统命令,使用os.system(command),即可执行相应的命令。当然,操作系统需预先安装git及一些软件才能使用。

    修改配置文件

      前面一步的git clone --mirror下载好相应的github repo,需导入到我们自建的Gitlab服务器中,这样就需要修改推送的git 地址,即pushurl,仅需修改git项目下相应的配置文件。

    git remote add gitlab git@ip:kdv-opensource/repo-name.git

      ip为gitlab服务的相应ip地址,kdv-opensource为分组名,如果不分组则为用户名,粗体gitlab为分支名。

    推送到gitlab服务器上

      我们知道,如果要进行push操作是需要进行鉴权的,也即需要输入账户密码,而在脚本执行过程中无法一一手工输入密码。有两种方法可以解决这个问题:

    方法一

      在pushurl地址中指定username:password,如下:

    pushurl = 'http://username:password@ip:port/kdv-opensource/{repo}.git'

    方法二

      通过SSH登录,更为方便和安全,也是现在比较流行的方式。(推荐

       导入本机生成的ssh公钥即可,公钥可通过ssh-keygen生成(默认即可),因此需要先安装SSH。

      这样,在脚本执行过程中就能自动地向gitlab服务器上推送repo内容。

    定期更新

       在linux下可将脚本加入到crontab列表,使之定期自动执行即可。

    实现脚本 

    组件列表sample

      文件以“项目名,github地址”的格式填入list.txt文件即可。

    haproxy,https://github.com/haproxy/haproxy.git
    libevent,https://github.com/libevent/libevent.git
    openresty,https://github.com/openresty/openresty.git

    python脚本

      完整代码如下,由于实际工作需要,增加了日记记录功能,脚本执行在控制台上看不到数据,输出会保存到日志文件中,如不需要,去掉重定向到文件即可。

      应该比较清晰了。

    #!/usr/bin/env python
    # -*- encoding: utf-8 -*-
    
    import os
    import time
    
    # 以下参数可自由指定
    # 修改此处ip地址为gitlab服务器ip地址
    giturl = 'git@172.16.6.105:kdv-opensource/{}.git'     # 需修改ip为相应的gitlab服务器地址
    opensource_list = 'list.txt'            # 组件列表文件名
    log_dirname = 'sync-logs'               # 日志记录目录名
    opensource_dirname = 'opensource'       # 组件列表存放目录名
    
    # 以下参数程序自动构建
    dicts = {}                  # 存放组件列表,组件-组件链接地址
    base_path = ''              # 程序执行根目录
    log_file = ''               # 日志文件
    opensource_path = ''
    
    
    def read_file(file):
        """
        从文件中读取开源组件列表,填入到dicts中,以组件名为key,组件url为value
        :param file: 组件文件
        :return: None
        """
        with open(file, 'r') as fr:
            for line in fr:
                if line.strip():
                    line = line.strip()
                    # 逗号分隔的组件名和组件URL,存放到字典dicts中
                    name, url = line.split(',')
                    dicts[name.strip()] = url.strip()
    
    
    def initialize():
        """
        做一些初始化工作
        :return: None
        """
        global base_path, log_file, opensource_path
    
        # 获取程序当前执行路径为根路径:base_path
        base_path = os.path.dirname(os.path.realpath(__file__))
        msg = 'Program path {}'.format(base_path)
        print(msg)
    
        # 组件目录
        opensource_path = os.path.join(base_path, opensource_dirname)
    
        # 判断程序是否是初始化运行,确定组件目录是否存在
        if not os.path.exists(opensource_path):
            mkdir_command = 'mkdir {}'.format(opensource_path)
            os.system(mkdir_command)
    
        # 日志目录
        log_path = os.path.join(base_path, log_dirname)
    
        # 判断程序是否是初始化运行,确定日志文件目录是否存在
        if not os.path.exists(log_path):
            mkdir_command = 'mkdir {}'.format(log_path)
            os.system(mkdir_command)
    
        # 以当前时间构造日志文件名称,存放到log_dirname目录中
        xtime = time.strftime("%Y-%m-%d-%H.%M.%S")
        file_name = '{}.{}'.format(xtime, 'txt')
        log_file = os.path.join(log_path, file_name)
        print(log_file)
    
        # write basic info to log file
        msg = '[*]Program base path : {}'.format(base_path)
        append_2_file(log_file, msg)
        msg = '[*]Program opensource path : {}'.format(opensource_path)
        append_2_file(log_file, msg)
        msg = '[*]Program log path : {}'.format(log_path)
        append_2_file(log_file, msg)
    
    
    def append_2_file(file, msg):
        """
        append sth to file
        :param file: actually, the log file
        :param msg: sth you want to log
        :return: None
        """
        with open(file, 'a') as fw:
            fw.write(msg)
            fw.write('
    ')
            pass
    
    
    if __name__ == '__main__':
    
        # 初始化参数
        initialize()
    
        # 读取组件文件列表
        read_file(opensource_list)
    
        # 组件目录opensource下已经存在的文件列表
        num = len(dicts)                        # 总的组件个数
        files = os.listdir(opensource_path)            # 获取当前路径下的所有文件
        msg = '[*]Existing opensource-files in {} are : {}'.format(opensource_path, files)
        append_2_file(log_file, msg)
    
        index = 0
        os.chdir(opensource_path)               # 切换到组件路径下,方便操作
        print()
        for name, url in dicts.items():            # 组件名字&git repo的url地址
            # progress information
            index += 1
            msg = '
    
    [{}/{}] - {}'.format(index, num, name)
            print(msg)
            append_2_file(log_file, msg)
    
            # save github information(origin) to log file
            msg = 'github(origin): {} - {}'.format(name, url)
            print(msg)
            append_2_file(log_file, msg)
    
            # save gitlab information(new) to log file
            name_git = '{}.git'.format(name)
            gitlab_url = giturl.format(name)
            msg = 'gitlab(new): {} - {}'.format(name, gitlab_url)
            print(msg)
            append_2_file(log_file, msg)
    
            if name_git in files:                # 如果是已有的repo,update更新即可
                try:
                    print('-----------------------------------')
                    # update
                    os.chdir(name_git)
                    command = 'git remote update'
                    print(command)
                    append_2_file(log_file, command)
              os.system(command) # push all branches command_push_all
    = 'git push gitlab --all 2>>{}'.format(log_file) print(command_push_all) append_2_file(log_file, ' ') # for better presentation append_2_file(log_file, command_push_all) # log command execution os.system(command_push_all) # push all tags command_push_tags = 'git push gitlab --tags 2>>{}'.format(log_file) print(command_push_tags) append_2_file(log_file, ' ') # for better presentation append_2_file(log_file, command_push_tags) # log command execution os.system(command_push_tags) except: print('sth bad happen...') continue finally: os.chdir('..') else: try: print('-----------------------------------') # 以镜像的形式clone repo command = 'git clone --mirror {} --progress 2>> {}'.format(url, log_file) print(command) os.system(command) # 创建远端分支 os.chdir(name_git) pushurl = 'git remote add gitlab {}'.format(giturl.format(name)) print(pushurl) append_2_file(log_file, pushurl) os.system(pushurl) # push all branches command_push_all = 'git push gitlab --all 2>>{}'.format(log_file) append_2_file(log_file, ' ') # for better presentation append_2_file(log_file, command_push_all) # log command execution os.system(command_push_all) # push all tags command_push_tags = 'git push gitlab --tags 2>>{}'.format(log_file) append_2_file(log_file, ' ') # for better presentation append_2_file(log_file, command_push_tags) # log command execution os.system(command_push_tags) os.chdir('..') except: print('sth bad happen...') continue finally: pass os.chdir('..') end_line = ' ==============================================' print(end_line) append_2_file(log_file, end_line) append_2_file(log_file, "This is the End") pass

    效果图

      再补两张效果图吧,如备份的组件curl,项目页 ==> 

      分支情况 ==>

      提交记录 ==> 

    Question

    zeroPaddedFilemode

      在push过程中(push --mirror),如果有文件出现错误:"zeroPaddedFilemode: contains zero-padded file modes",可参考如下文章。

      Pushing fails if local repo has problems with zero-padded file modes

      Zero-padded file modes in repository

      remote: fatal: fsck error in packed object when pushing oh-my-zsh repo to new remote

      不过好像对我不起作用,什么.git/config和~/.gitconfig文件都改烂了,还是不行。难受...

      解决方法:修改配置文件

    # vim  /etc/gitlab/gitlab.rb
    ...
    omnibus_gitconfig['system'] = {
      'fsck' => ['zeroPaddedFilemode = ignore'],     # 这个是上面某个链接里说的方法,但不起作用,于是试了下-下面那行
      "receive" => ["fsckObjects = false"],
    }
    重新配置:
      gitlab-ctl reconfigure
    重启服务:
      gitlab-ctl restart
  • 相关阅读:
    Android开发 ViewConfiguration View的配置信息类
    Android 开发 倒计时功能 转载
    Android 开发 关于7.0 FileUriExposedException异常 详解
    Android 开发 实现文本搜索功能
    Android 开发 Activity里获取View的宽度和高度 转载
    Android 开发 存储目录的详解
    Android 开发 Fresco框架点击小图显示全屏大图实现 ZoomableDraweeView
    Android 开发 将window变暗
    Android 开发 DisplayMetrics获取Android设备的屏幕高宽与其他信息
    Android 开发 DP、PX、SP转换详解
  • 原文地址:https://www.cnblogs.com/Hi-blog/p/How-To-Backup-Github-Repo-And-Update.html
Copyright © 2011-2022 走看看