From 15e162dfdc8f44f8103257b13d299eefa3ad064e Mon Sep 17 00:00:00 2001 From: tbxark Date: Fri, 24 Jan 2025 16:47:19 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0=E6=9C=AC=E5=9C=B0?= =?UTF-8?q?=E5=A4=87=E4=BB=BD=E6=8F=90=E4=BE=9B=E8=80=85=E6=94=AF=E6=8C=81?= =?UTF-8?q?=EF=BC=8C=E6=9B=B4=E6=96=B0=E9=85=8D=E7=BD=AE=E7=B1=BB=E5=9E=8B?= =?UTF-8?q?=E5=B9=B6=E5=AE=9E=E7=8E=B0=E7=9B=B8=E5=85=B3=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- config/config.go | 2 +- provider/local/local.go | 117 ++++++++++++++++++++++++++++++++++++++++ task.go | 7 +++ 3 files changed, 125 insertions(+), 1 deletion(-) create mode 100644 provider/local/local.go diff --git a/config/config.go b/config/config.go index 457c4c3..8a6029e 100644 --- a/config/config.go +++ b/config/config.go @@ -8,7 +8,7 @@ type BackupProviderConfigType string const ( BackupProviderConfigTypeGitea BackupProviderConfigType = "gitea" - BackupProviderConfigTypeFile BackupProviderConfigType = "file" + BackupProviderConfigTypeLocal BackupProviderConfigType = "local" ) type UnmatchedRepoAction string diff --git a/provider/local/local.go b/provider/local/local.go new file mode 100644 index 0000000..21f7b89 --- /dev/null +++ b/provider/local/local.go @@ -0,0 +1,117 @@ +package local + +import ( + "fmt" + "github.com/TBXark/github-backup/provider/provider" + "log" + "os" + "os/exec" + "path/filepath" +) + +type Config struct { + Root string `json:"root"` + Questions bool `json:"questions"` +} + +var _ provider.Provider = &Local{} + +type Local struct { + conf *Config +} + +func NewLocal(conf *Config) *Local { + return &Local{conf: conf} +} + +func (l *Local) LoadRepos(owner *provider.Owner) ([]string, error) { + ownerPath := filepath.Join(l.conf.Root, owner.Name) + dirEntries, err := os.ReadDir(ownerPath) + if err != nil { + return nil, err + } + repos := make([]string, 0) + for _, dirEntry := range dirEntries { + if dirEntry.IsDir() && isGitRepository(filepath.Join(ownerPath, dirEntry.Name())) { + repos = append(repos, dirEntry.Name()) + } + } + return repos, nil +} + +func (l *Local) MigrateRepo(from *provider.Owner, to *provider.Owner, repo *provider.Repo) (string, error) { + if l.conf.Questions && !question(fmt.Sprintf("Are you sure you want to migrate %s/%s to %s/%s? [y/n]: ", from.Name, repo.Name, to.Name, repo.Name)) { + return "skip", nil + } + ownerPath := filepath.Join(l.conf.Root, to.Name) + _, err := os.Stat(ownerPath) + if err != nil { + if os.IsNotExist(err) { + if e := os.MkdirAll(ownerPath, os.ModePerm); e != nil { + return "", e + } + } else { + return "", err + } + } + repoPath := filepath.Join(ownerPath, repo.Name) + _, err = os.Stat(repoPath) + gitUrl := fmt.Sprintf("git@github.com:%s/%s.git", from.Name, repo.Name) + if err != nil { + if os.IsNotExist(err) { + err = gitClone(gitUrl, repoPath) + if err != nil { + return "success", err + } + } else { + return "", err + } + } + err = gitPull(repoPath) + if err != nil { + return "fail", err + } + return "success", nil +} + +func (l *Local) DeleteRepo(owner, repo string) (string, error) { + if l.conf.Questions && !question(fmt.Sprintf("Are you sure you want to delete %s/%s? [y/n]: ", owner, repo)) { + return "skip", nil + } + repoPath := filepath.Join(l.conf.Root, owner, repo) + err := os.RemoveAll(repoPath) + if err != nil { + return "fail", err + } + return "success", nil +} + +func isGitRepository(path string) bool { + cmd := exec.Command("git", "rev-parse", "--is-inside-work-tree") + cmd.Dir = path + err := cmd.Run() + return err == nil +} + +func gitClone(url, path string) error { + log.Printf("cloning %s", url) + cmd := exec.Command("git", "clone", url, path) + return cmd.Run() +} + +func gitPull(path string) error { + log.Printf("pulling %s", path) + cmd := exec.Command("git", "pull") + cmd.Dir = path + return cmd.Run() +} + +func question(message string) bool { + var response string + fmt.Print(message) + _, err := fmt.Scanln(&response) + if err != nil { + return false + } + return response == "y" +} diff --git a/task.go b/task.go index e31aa1c..536b22c 100644 --- a/task.go +++ b/task.go @@ -5,6 +5,7 @@ import ( "github.com/TBXark/github-backup/config" "github.com/TBXark/github-backup/provider/gitea" "github.com/TBXark/github-backup/provider/github" + "github.com/TBXark/github-backup/provider/local" "github.com/TBXark/github-backup/provider/provider" "github.com/TBXark/github-backup/utils/matcher" "log" @@ -18,6 +19,12 @@ func BuildBackupProvider(conf *config.BackupProviderConfig) (provider.Provider, return nil, err } return gitea.NewGitea(c), nil + case config.BackupProviderConfigTypeLocal: + c, err := config.Convert[local.Config](conf.Config) + if err != nil { + return nil, err + } + return local.NewLocal(c), nil } return nil, fmt.Errorf("unknown backup provider type: %s", conf.Type) }