git

package module
v0.0.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 24, 2026 License: MIT Imports: 15 Imported by: 0

README

Git Source · Git 脚本来源

Go Version

基于 Git 仓库的脚本来源,支持 commit hash 比对热更新检测

中文 · English · 日本語


概述

Git Source 使用 go-git 从远程 Git 仓库或本地 Git 仓库读取脚本。在初始化时自动 Clone 仓库到本地临时目录,通过 commit hash 轮询检测热更新。

特性
特性 说明
底层库 github.com/go-git/go-git/v5(纯 Go,零 CGO)
热更新 commit hash 比对轮询(git pull
认证 支持 Token / 用户名密码 / SSH Key
浅克隆 支持 WithDepth 限制克隆深度
本地仓库 支持 WithLocalPath 直接打开本地仓库
Key 前缀 支持 WithPrefix 命名空间隔离
接口 实现 source.ReadWatcher

安装

go get github.com/tx7do/go-scripts/source/git

配置选项

选项 默认值 说明
WithRepoURL(url) 必填* 远程 Git 仓库 URL
WithBranch(branch) HEAD 分支 / 标签 / 引用名
WithPrefix(prefix) Key 前缀(自动去除前导 /
WithLocalPath(path) 本地仓库路径(与 RepoURL 二选一)
WithAuth(user, pass) 用户名 + 密码认证
WithToken(token) Bearer Token(GitHub PAT / GitLab Token)
WithSSHKey(path) SSH 私钥文件路径
WithDepth(n) 0(完整克隆) 浅克隆深度
WithPullInterval(d) 30s Watch 轮询间隔

* 当使用 WithLocalPath 时不需要 WithRepoURL


快速开始

从远程仓库加载
package main

import (
    "context"
    "fmt"
    gitSrc "github.com/tx7do/go-scripts/source/git"
)

func main() {
    ctx := context.Background()

    src, err := gitSrc.New(ctx,
        gitSrc.WithRepoURL("https://github.com/user/scripts.git"),
        gitSrc.WithBranch("main"),
        gitSrc.WithPrefix("scripts/lua/"),
    )
    if err != nil { panic(err) }
    defer src.Close()

    code, err := src.Load(ctx, "hello.lua")
    if err != nil { panic(err) }
    fmt.Println(code)
}
使用 Token 认证(GitHub)
src, err := gitSrc.New(ctx,
    gitSrc.WithRepoURL("https://github.com/my-org/scripts.git"),
    gitSrc.WithToken("ghp_xxxxxxxxxxxx"),
    gitSrc.WithDepth(1),  // 浅克隆
)
使用本地仓库
src, err := gitSrc.New(ctx,
    gitSrc.WithLocalPath("/path/to/local/repo"),
    gitSrc.WithPrefix("lua/"),
)
热更新监听
// 先 Load 建立基线
_, _ = src.Load(ctx, "main.lua")

// 启动监听(定期 git pull + 比较 HEAD hash)
ch, _ := src.Watch(ctx, "main.lua")

for range ch {
    // 远程仓库有新 commit
    code, _ := src.Load(ctx, "main.lua")
    fmt.Println("reloaded:", code)
}

热更新机制

每 30s(默认):
  git pull
    ↓
  获取当前 HEAD commit hash
    ↓
  与 Load 时记录的 baseline hash 比对
    ↓
  不同 → 发送变更信号
  • 每个 Watcher 独立追踪:每个 Watch() 调用维护自己的 baseline,多个 Watcher 不会互相干扰。
  • Pull 失败容错:网络异常等导致 Pull 失败时,跳过当前轮次,下次重试。
  • 无变更无信号:HEAD hash 未变时不发送信号。

错误处理

错误 说明
ErrNotFound 文件不存在;用 errors.Is(err, gitSrc.ErrNotFound)gitSrc.IsNotFound(err) 识别
其它 包装原始错误,前缀为 git source: ...

测试

cd source/git && go test -v ./...

测试覆盖(25 个用例全部通过,不依赖真实 Git 服务器):

类别 用例
接口实现 编译期断言
构造校验 WithRepoURLWithLocalPath 必填
Prefix 规范化 6 种 prefix 写法表驱动测试
Load 正常加载 / 文件不存在(ErrNotFound)/ Prefix / Context 取消
Watch 有变更触发 / 无变更不触发 / Context 取消 / 未 Load 报错 / Pull 失败容错 / 并发多 Watcher
并发安全 30 goroutine 并发 Load
Options WithRepoURL / WithBranch / WithAuth / WithToken / WithDepth / WithPullInterval
本地仓库 从本地目录加载

相关文档

License

MIT License

Documentation

Overview

Package git provides a source.Reader implementation that reads scripts from a git repository. It clones the repo to a local temp directory and reads files from the working tree. Hot-reload is supported by polling for new commits (git pull + HEAD hash comparison).

Construction:

src, err := git.New(ctx,
    git.WithRepoURL("https://github.com/user/scripts.git"),
    git.WithBranch("main"),
    git.WithPrefix("scripts/lua/"),
)

Hot-reload uses commit-hash polling: the Watcher periodically runs git pull and compares the HEAD hash with the one recorded at the last Load.

Index

Constants

This section is empty.

Variables

View Source
var ErrNotFound = errors.New("git source: key not found")

ErrNotFound is returned (wrapped) by Load when the requested key does not exist in the git repository. Detect with errors.Is(err, ErrNotFound) or the convenience helper IsNotFound.

Functions

func IsNotFound

func IsNotFound(err error) bool

IsNotFound reports whether err represents a "file not found" error.

Types

type Option

type Option func(*configOptions)

Option configures a Reader. Pass to New.

func WithAuth

func WithAuth(username, password string) Option

WithAuth sets the authentication credentials for the remote git server.

func WithBranch

func WithBranch(branch string) Option

WithBranch sets the branch, tag, or ref to checkout (default "HEAD").

func WithDepth

func WithDepth(depth int) Option

WithDepth sets the shallow clone depth (0 = full clone).

func WithLocalPath

func WithLocalPath(path string) Option

WithLocalPath sets a local repository path. When set, the Reader will open the local repo directly instead of cloning from a remote URL. This is useful for development / testing.

func WithPrefix

func WithPrefix(prefix string) Option

WithPrefix sets a path prefix that is transparently prepended to every key. Leading slashes are stripped.

WithPrefix("scripts/lua/") + key "main.lua" -> "scripts/lua/main.lua"

func WithPullInterval

func WithPullInterval(d time.Duration) Option

WithPullInterval sets the polling interval for Watch (default 30s).

func WithRepoURL

func WithRepoURL(url string) Option

WithRepoURL sets the remote git repository URL to clone from.

WithRepoURL("https://github.com/user/scripts.git")
WithRepoURL("git@github.com:user/scripts.git")

func WithSSHKey

func WithSSHKey(keyPath string) Option

WithSSHKey sets the path to an SSH private key for authentication.

func WithToken

func WithToken(token string) Option

WithToken sets a bearer token for authentication (GitHub PAT, GitLab token, etc.).

type Reader

type Reader struct {
	// contains filtered or unexported fields
}

Reader reads scripts from a git repository.

All exported methods are safe for concurrent use. Reader implements the source.ReadWatcher interface.

func New

func New(ctx context.Context, opts ...Option) (*Reader, error)

New creates a git-backed Reader.

At minimum, either WithRepoURL or WithLocalPath must be supplied. When WithRepoURL is used, the repo is cloned to a temporary directory. When WithLocalPath is used, the repo is opened directly from the local filesystem (no clone).

func (*Reader) Close

func (r *Reader) Close() error

Close releases resources. If the Reader cloned the repo to a temp directory, the directory is removed.

func (*Reader) Load

func (r *Reader) Load(ctx context.Context, key string) (string, error)

Load reads the file at the given key from the git working tree. Context cancellation propagates to the underlying read.

An absent file is reported as a wrapped ErrNotFound.

func (*Reader) Watch

func (r *Reader) Watch(ctx context.Context, key string) (<-chan struct{}, error)

Watch returns a channel that signals when the git repository receives new commits that may affect the file identified by `key`.

It works by periodically running `git pull` and comparing the HEAD commit hash with the one recorded at the last Load. If the hash has changed, a signal is sent on the channel.

The returned channel is closed when the context is cancelled. Callers should re-Load the script after receiving from the channel.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL