mirror of https://github.com/Xhofe/alist
feat(github_releases): concurrently request the GitHub API (#9211)
parent
2bdc5bef9e
commit
5e15a360b7
|
@ -5,6 +5,7 @@ import (
|
|||
"fmt"
|
||||
"net/http"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/alist-org/alist/v3/internal/driver"
|
||||
"github.com/alist-org/alist/v3/internal/errs"
|
||||
|
@ -36,88 +37,130 @@ func (d *GithubReleases) Drop(ctx context.Context) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// processPoint 处理单个挂载点的文件列表
|
||||
func (d *GithubReleases) processPoint(point *MountPoint, path string, args model.ListArgs) []File {
|
||||
var pointFiles []File
|
||||
|
||||
if !d.Addition.ShowAllVersion { // latest
|
||||
point.RequestLatestRelease(d.GetRequest, args.Refresh)
|
||||
pointFiles = d.processLatestVersion(point, path)
|
||||
} else { // all version
|
||||
point.RequestReleases(d.GetRequest, args.Refresh)
|
||||
pointFiles = d.processAllVersions(point, path)
|
||||
}
|
||||
|
||||
return pointFiles
|
||||
}
|
||||
|
||||
// processLatestVersion 处理最新版本的逻辑
|
||||
func (d *GithubReleases) processLatestVersion(point *MountPoint, path string) []File {
|
||||
var pointFiles []File
|
||||
|
||||
if point.Point == path { // 与仓库路径相同
|
||||
pointFiles = append(pointFiles, point.GetLatestRelease()...)
|
||||
if d.Addition.ShowReadme {
|
||||
files := point.GetOtherFile(d.GetRequest, false)
|
||||
pointFiles = append(pointFiles, files...)
|
||||
}
|
||||
} else if strings.HasPrefix(point.Point, path) { // 仓库目录的父目录
|
||||
nextDir := GetNextDir(point.Point, path)
|
||||
if nextDir != "" {
|
||||
dirFile := File{
|
||||
Path: path + "/" + nextDir,
|
||||
FileName: nextDir,
|
||||
Size: point.GetLatestSize(),
|
||||
UpdateAt: point.Release.PublishedAt,
|
||||
CreateAt: point.Release.CreatedAt,
|
||||
Type: "dir",
|
||||
Url: "",
|
||||
}
|
||||
pointFiles = append(pointFiles, dirFile)
|
||||
}
|
||||
}
|
||||
|
||||
return pointFiles
|
||||
}
|
||||
|
||||
// processAllVersions 处理所有版本的逻辑
|
||||
func (d *GithubReleases) processAllVersions(point *MountPoint, path string) []File {
|
||||
var pointFiles []File
|
||||
|
||||
if point.Point == path { // 与仓库路径相同
|
||||
pointFiles = append(pointFiles, point.GetAllVersion()...)
|
||||
if d.Addition.ShowReadme {
|
||||
files := point.GetOtherFile(d.GetRequest, false)
|
||||
pointFiles = append(pointFiles, files...)
|
||||
}
|
||||
} else if strings.HasPrefix(point.Point, path) { // 仓库目录的父目录
|
||||
nextDir := GetNextDir(point.Point, path)
|
||||
if nextDir != "" {
|
||||
dirFile := File{
|
||||
FileName: nextDir,
|
||||
Path: path + "/" + nextDir,
|
||||
Size: point.GetAllVersionSize(),
|
||||
UpdateAt: (*point.Releases)[0].PublishedAt,
|
||||
CreateAt: (*point.Releases)[0].CreatedAt,
|
||||
Type: "dir",
|
||||
Url: "",
|
||||
}
|
||||
pointFiles = append(pointFiles, dirFile)
|
||||
}
|
||||
} else if strings.HasPrefix(path, point.Point) { // 仓库目录的子目录
|
||||
tagName := GetNextDir(path, point.Point)
|
||||
if tagName != "" {
|
||||
pointFiles = append(pointFiles, point.GetReleaseByTagName(tagName)...)
|
||||
}
|
||||
}
|
||||
|
||||
return pointFiles
|
||||
}
|
||||
|
||||
// mergeFiles 合并文件列表,处理重复目录
|
||||
func (d *GithubReleases) mergeFiles(files *[]File, newFiles []File) {
|
||||
for _, newFile := range newFiles {
|
||||
if newFile.Type == "dir" {
|
||||
hasSameDir := false
|
||||
for index := range *files {
|
||||
if (*files)[index].GetName() == newFile.GetName() && (*files)[index].Type == "dir" {
|
||||
hasSameDir = true
|
||||
(*files)[index].Size += newFile.Size
|
||||
break
|
||||
}
|
||||
}
|
||||
if !hasSameDir {
|
||||
*files = append(*files, newFile)
|
||||
}
|
||||
} else {
|
||||
*files = append(*files, newFile)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (d *GithubReleases) List(ctx context.Context, dir model.Obj, args model.ListArgs) ([]model.Obj, error) {
|
||||
files := make([]File, 0)
|
||||
path := fmt.Sprintf("/%s", strings.Trim(dir.GetPath(), "/"))
|
||||
|
||||
for i := range d.points {
|
||||
point := &d.points[i]
|
||||
if d.Addition.ConcurrentRequests && d.Addition.Token != "" { // 并发处理
|
||||
var mu sync.Mutex
|
||||
var wg sync.WaitGroup
|
||||
|
||||
if !d.Addition.ShowAllVersion { // latest
|
||||
point.RequestRelease(d.GetRequest, args.Refresh)
|
||||
for i := range d.points {
|
||||
wg.Add(1)
|
||||
go func(point *MountPoint) {
|
||||
defer wg.Done()
|
||||
pointFiles := d.processPoint(point, path, args)
|
||||
|
||||
if point.Point == path { // 与仓库路径相同
|
||||
files = append(files, point.GetLatestRelease()...)
|
||||
if d.Addition.ShowReadme {
|
||||
files = append(files, point.GetOtherFile(d.GetRequest, args.Refresh)...)
|
||||
}
|
||||
} else if strings.HasPrefix(point.Point, path) { // 仓库目录的父目录
|
||||
nextDir := GetNextDir(point.Point, path)
|
||||
if nextDir == "" {
|
||||
continue
|
||||
}
|
||||
|
||||
hasSameDir := false
|
||||
for index := range files {
|
||||
if files[index].GetName() == nextDir {
|
||||
hasSameDir = true
|
||||
files[index].Size += point.GetLatestSize()
|
||||
break
|
||||
}
|
||||
}
|
||||
if !hasSameDir {
|
||||
files = append(files, File{
|
||||
Path: path + "/" + nextDir,
|
||||
FileName: nextDir,
|
||||
Size: point.GetLatestSize(),
|
||||
UpdateAt: point.Release.PublishedAt,
|
||||
CreateAt: point.Release.CreatedAt,
|
||||
Type: "dir",
|
||||
Url: "",
|
||||
})
|
||||
}
|
||||
}
|
||||
} else { // all version
|
||||
point.RequestReleases(d.GetRequest, args.Refresh)
|
||||
|
||||
if point.Point == path { // 与仓库路径相同
|
||||
files = append(files, point.GetAllVersion()...)
|
||||
if d.Addition.ShowReadme {
|
||||
files = append(files, point.GetOtherFile(d.GetRequest, args.Refresh)...)
|
||||
}
|
||||
} else if strings.HasPrefix(point.Point, path) { // 仓库目录的父目录
|
||||
nextDir := GetNextDir(point.Point, path)
|
||||
if nextDir == "" {
|
||||
continue
|
||||
}
|
||||
|
||||
hasSameDir := false
|
||||
for index := range files {
|
||||
if files[index].GetName() == nextDir {
|
||||
hasSameDir = true
|
||||
files[index].Size += point.GetAllVersionSize()
|
||||
break
|
||||
}
|
||||
}
|
||||
if !hasSameDir {
|
||||
files = append(files, File{
|
||||
FileName: nextDir,
|
||||
Path: path + "/" + nextDir,
|
||||
Size: point.GetAllVersionSize(),
|
||||
UpdateAt: (*point.Releases)[0].PublishedAt,
|
||||
CreateAt: (*point.Releases)[0].CreatedAt,
|
||||
Type: "dir",
|
||||
Url: "",
|
||||
})
|
||||
}
|
||||
} else if strings.HasPrefix(path, point.Point) { // 仓库目录的子目录
|
||||
tagName := GetNextDir(path, point.Point)
|
||||
if tagName == "" {
|
||||
continue
|
||||
}
|
||||
|
||||
files = append(files, point.GetReleaseByTagName(tagName)...)
|
||||
}
|
||||
mu.Lock()
|
||||
d.mergeFiles(&files, pointFiles)
|
||||
mu.Unlock()
|
||||
}(&d.points[i])
|
||||
}
|
||||
wg.Wait()
|
||||
} else { // 串行处理
|
||||
for i := range d.points {
|
||||
point := &d.points[i]
|
||||
pointFiles := d.processPoint(point, path, args)
|
||||
d.mergeFiles(&files, pointFiles)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -7,11 +7,12 @@ import (
|
|||
|
||||
type Addition struct {
|
||||
driver.RootID
|
||||
RepoStructure string `json:"repo_structure" type:"text" required:"true" default:"alistGo/alist" help:"structure:[path:]org/repo"`
|
||||
ShowReadme bool `json:"show_readme" type:"bool" default:"true" help:"show README、LICENSE file"`
|
||||
Token string `json:"token" type:"string" required:"false" help:"GitHub token, if you want to access private repositories or increase the rate limit"`
|
||||
ShowAllVersion bool `json:"show_all_version" type:"bool" default:"false" help:"show all versions"`
|
||||
GitHubProxy string `json:"gh_proxy" type:"string" default:"" help:"GitHub proxy, e.g. https://ghproxy.net/github.com or https://gh-proxy.com/github.com "`
|
||||
RepoStructure string `json:"repo_structure" type:"text" required:"true" default:"alistGo/alist" help:"structure:[path:]org/repo"`
|
||||
ShowReadme bool `json:"show_readme" type:"bool" default:"true" help:"show README、LICENSE file"`
|
||||
Token string `json:"token" type:"string" required:"false" help:"GitHub token, if you want to access private repositories or increase the rate limit"`
|
||||
ShowAllVersion bool `json:"show_all_version" type:"bool" default:"false" help:"show all versions"`
|
||||
ConcurrentRequests bool `json:"concurrent_requests" type:"bool" default:"false" help:"To concurrently request the GitHub API, you must enter a GitHub token"`
|
||||
GitHubProxy string `json:"gh_proxy" type:"string" default:"" help:"GitHub proxy, e.g. https://ghproxy.net/github.com or https://gh-proxy.com/github.com "`
|
||||
}
|
||||
|
||||
var config = driver.Config{
|
||||
|
|
|
@ -18,7 +18,7 @@ type MountPoint struct {
|
|||
}
|
||||
|
||||
// 请求最新版本
|
||||
func (m *MountPoint) RequestRelease(get func(url string) (*resty.Response, error), refresh bool) {
|
||||
func (m *MountPoint) RequestLatestRelease(get func(url string) (*resty.Response, error), refresh bool) {
|
||||
if m.Repo == "" {
|
||||
return
|
||||
}
|
||||
|
|
|
@ -6,8 +6,8 @@ import (
|
|||
"strings"
|
||||
|
||||
"github.com/alist-org/alist/v3/drivers/base"
|
||||
"github.com/alist-org/alist/v3/pkg/utils"
|
||||
"github.com/go-resty/resty/v2"
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
// 发送 GET 请求
|
||||
|
@ -23,7 +23,7 @@ func (d *GithubReleases) GetRequest(url string) (*resty.Response, error) {
|
|||
return nil, err
|
||||
}
|
||||
if res.StatusCode() != 200 {
|
||||
log.Warn("failed to get request: ", res.StatusCode(), res.String())
|
||||
utils.Log.Warnf("failed to get request: %s %d %s", url, res.StatusCode(), res.String())
|
||||
}
|
||||
return res, nil
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue