当前位置: 首页 > news >正文

使用go-git同步文件到gitee

go-git是golang上纯go实现的git客户端,可用来同步文件到git仓库。

为什么不用gitee官方openapi,因为我需要强制推送覆盖,官方api不支持。

下面是一个通过xml.gz文件到gitee的代码示例

package clientimport ("fmt""gin-epg/internal/app/common/util""io""os""path/filepath""strings""time""gin-epg/internal/app/store""github.com/go-git/go-git/v5""github.com/go-git/go-git/v5/config""github.com/go-git/go-git/v5/plumbing/object""github.com/go-git/go-git/v5/plumbing/transport/http"
)// SyncXmlGzToGitee 同步多个 XML.gz 文件到 Gitee,每次同步时强制覆盖历史提交记录
func SyncXmlGzToGitee() error {url := ""userName := ""password := ""// 获取配置值repoUrl, err := util.GetConfigValue("sync.repoUrl")repoUserName, err := util.GetConfigValue("sync.repoUserName")repoPassword, err := util.GetConfigValue("sync.repoPassword")if repoUrl != nil {url = repoUrl.(string)}if repoUserName != nil {userName = repoUserName.(string)}if repoPassword != nil {password = repoPassword.(string)}if url == "" || userName == "" || password == "" {return fmt.Errorf("配置错误,请检查 sync.repoUrl、sync.repoUserName 和 sync.repoPassword 是否正确")}fileNames := []interface{}{"e9.xml.gz","e7.xml.gz","e.xml.gz",}// 创建 gitee同步目录tempDirPath := filepath.Join(os.TempDir(), "gitee-sync")if err := os.MkdirAll(tempDirPath, os.ModePerm); err != nil {return fmt.Errorf("创建临时目录失败: %v", err)}fmt.Printf("临时目录路径: %s\n", tempDirPath)// 创建存储工具下载目录tempDir := filepath.Join(os.TempDir(), "xmltvsync")if err := os.MkdirAll(tempDir, os.ModePerm); err != nil {return fmt.Errorf("创建临时目录失败: %v", err)}fmt.Printf("存储工具下载目录路径: %s\n", tempDir)// 初始化 OSS 存储服务ossService := store.GlobalStoreService// 初始化或打开本地临时仓库repoPath := filepath.Join(tempDirPath, "repo")fmt.Printf("Git 仓库路径: %s\n", repoPath)// 清理旧的仓库目录(如果存在)if _, err := os.Stat(repoPath); !os.IsNotExist(err) {if err := os.RemoveAll(repoPath); err != nil {return fmt.Errorf("清理旧的仓库目录失败: %v", err)}fmt.Printf("旧的仓库目录已清理: %s\n", repoPath)}repo, err := git.PlainOpen(repoPath)if err != nil {if strings.Contains(err.Error(), "repository does not exist") {// 如果仓库不存在,则初始化一个新的仓库repo, err = git.PlainInit(repoPath, false)if err != nil {return fmt.Errorf("初始化 Git 仓库失败: %v", err)}fmt.Printf("Git 仓库初始化成功: %s\n", repoPath)} else {return fmt.Errorf("打开 Git 仓库失败: %v", err)}}// 获取工作树worktree, err := repo.Worktree()if err != nil {return fmt.Errorf("获取工作树失败: %v", err)}fmt.Printf("工作树获取成功\n")// 遍历需要同步的文件列表for _, fileInterface := range fileNames {fileName, ok := fileInterface.(string)if !ok {fmt.Printf("配置 sync.filesToSync 中包含非字符串项,跳过该项: %v\n", fileInterface)continue}localFilePath := filepath.Join(tempDir, fileName)tempFilePath := filepath.Join(repoPath, fileName)// 下载文件if err := ossService.DownloadToFile(fileName, localFilePath); err != nil {fmt.Printf("下载文件 %s 失败: %v\n", fileName, err)continue}fmt.Printf("文件下载成功: %s\n", localFilePath)// 复制文件到 Git 仓库目录if err := copyFile(localFilePath, tempFilePath); err != nil {fmt.Printf("复制文件 %s 失败: %v\n", fileName, err)continue}fmt.Printf("文件复制成功: %s\n", tempFilePath)// 添加文件到索引if _, err := worktree.Add(fileName); err != nil {fmt.Printf("添加文件 %s 到 Git 失败: %v\n", fileName, err)continue}fmt.Printf("文件 %s 添加到索引成功\n", fileName)}// 获取当前时间并格式化currentTime := time.Now().Format("2006-01-02 15:04:05")// 提交更改commitHash, err := worktree.Commit(fmt.Sprintf("同步 XML.gz 文件 - %s", currentTime), &git.CommitOptions{Author: &object.Signature{Name:  "sync",Email: "sync@example.com",When:  time.Now(),},})if err != nil {return fmt.Errorf("提交更改失败: %v", err)}fmt.Printf("提交成功,提交哈希: %s\n", commitHash)// 添加远程仓库(如果尚未添加)remoteName := "origin"if _, err := repo.Remote(remoteName); err != nil {if err == git.ErrRemoteNotFound {// 添加远程仓库_, err := repo.CreateRemote(&config.RemoteConfig{Name: remoteName,URLs: []string{url},})if err != nil {return fmt.Errorf("添加远程仓库失败: %v", err)}fmt.Printf("远程仓库添加成功\n")} else {return fmt.Errorf("检查远程仓库失败: %v", err)}}// 强制推送到远程仓库if err := repo.Push(&git.PushOptions{RemoteName: remoteName,RefSpecs: []config.RefSpec{config.RefSpec("refs/heads/master:refs/heads/master"),},Auth: &http.BasicAuth{Username: userName,Password: password,},Force: true,}); err != nil {return fmt.Errorf("强制推送失败: %v", err)}fmt.Printf("强制推送成功\n")return nil
}// copyFile 复制文件
func copyFile(src, dst string) error {in, err := os.Open(src)if err != nil {return err}defer in.Close()out, err := os.Create(dst)if err != nil {return err}defer out.Close()_, err = io.Copy(out, in)return err
}

这里需要强制推送,没有git历史可以减少仓库体积。不能用go-git v4版,v4版不支持强制推送。

若需要兼容win7 golang1.20 需要降低go-git版本至github.com/go-git/go-git/v5 v5.9.0

可在go.mod文件中修改版本后执行 go mod tidy

相关文章:

  • 【OSG学习笔记】Day 5: 坐标系与变换节点(Transform)
  • Spark-SQL(四)
  • C++之unordered封装
  • MyBatis框架—xml映射
  • 可穿戴设备待机功耗需降至μA级但需保持实时响应(2万字长文深度解析)
  • Android Studio打开xml布局文件内存会快速增加如何设置
  • C语言复习笔记--字符函数和字符串函数(下)
  • Unity接入安卓SDK(3)厘清Gradle的版本
  • 第六章.java集合与泛型
  • UML 状态图:解锁电子图书馆管理系统的高效设计
  • android的 framework 有哪些知识点和应用场景
  • 一键部署k8s之EFK日志收集系统
  • 在 Android 中实现通话录音
  • Flask API 项目 Swagger 版本打架不兼容
  • 02_Flask是什么?
  • Hadoop+Spark 笔记 2025/4/21
  • 【python实用小脚本系列】用Python让鼠标“动起来”:光标自动移动、自动点击、自动图象识别的小技巧
  • CSS 中实现 div 居中有以下几种常用方法
  • ADB -> pull指令推送电脑文件到手机上
  • 大数据学习(109)-Impala 和 Hive 之间的 SQL 差异
  • 我们的免疫系统,是世界上最好的“医生”
  • 国家开发银行原副行长李吉平一审获刑14年
  • 商务部:服务业扩大开放试点任务多数来源于经营主体实际需要
  • 今年一季度,上海对东盟进出口总值同比增长7.1%
  • 电动自行车新国标将于9月1日落地,首批6家检测机构出炉
  • 廊坊市长:健全依法决策和决策纠错机制,把群众满意作为工作准绳